Skip to content

Commit

Permalink
Curve builder (#362)
Browse files Browse the repository at this point in the history
* Rename DynaWaltzCurve to DynawoCurve
* Add DynawoCurveBuilder
* Use SupplierJsonDeserializer
* Update documentation
* Replace 'curves' with 'curve' in DSL

Signed-off-by: lisrte <[email protected]>
  • Loading branch information
Lisrte authored Jul 3, 2024
1 parent 0531353 commit 286a2d2
Show file tree
Hide file tree
Showing 26 changed files with 410 additions and 210 deletions.
8 changes: 4 additions & 4 deletions docs/dynamic_simulation/curves-dsl.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Curves DSL
The curves domain specific language allow a user to configure the curves Dynawo will export at the end of the simulation. This DSL defines the `curve` and the `curves` keywords.
The curves domain specific language allow a user to configure the curves Dynawo will export at the end of the simulation. This DSL defines the `curve` keywords.

The `curve` keyword create a single curve for a dynamic model. One identifies a dynamic model by its ID, the same as the one used in the [Dynamic Models DSL](dynamic-models-dsl). The variable to plot is identified by its name.
The `curve` keyword combined with the `variable` field create a single curve for a dynamic model. One identifies a dynamic model by its ID, the same as the one used in the [Dynamic Models DSL](dynamic-models-dsl). The variable to plot is identified by its name.
```groovy
curve {
dynamicModelId load.id
Expand All @@ -17,7 +17,7 @@ curve {
}
```

If you want to plot several variables of the same dynamic model, you can use the `curves` keyword that permit limiting boilerplate code in the script.
If you want to plot several variables of the same dynamic model, you can use the `variables` field that permit limiting boilerplate code in the script.
```
// This:
curve {
Expand All @@ -30,7 +30,7 @@ curve {
}
// is equivalent to:
curves {
curve {
dynamicModelId load.id
variables "load_PPu", "load_QPu"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ package com.powsybl.dynawaltz.dsl

import com.google.auto.service.AutoService
import com.powsybl.commons.report.ReportNode
import com.powsybl.dsl.DslException
import com.powsybl.dynamicsimulation.Curve
import com.powsybl.dynamicsimulation.groovy.CurveGroovyExtension

import com.powsybl.dynawaltz.DynaWaltzCurve
import com.powsybl.dynawaltz.DynaWaltzProvider
import com.powsybl.dynawaltz.curves.DynawoCurvesBuilder

import java.util.function.Consumer

/**
* An implementation of {@link CurveGroovyExtension} that adds the <pre>curve</pre> keyword to the DSL
*
Expand All @@ -25,80 +22,20 @@ import java.util.function.Consumer
@AutoService(CurveGroovyExtension.class)
class DynaWaltzCurveGroovyExtension implements CurveGroovyExtension {

/**
* A curve for <pre>DynaWaltz</pre> can be defined in DSL using {@code staticId} and {@code variable} or {@code dynamicModelId} and {@code variable}.
* Definition with {@code staticId} and {@code variable} are used when no explicit dynamic component exists (buses).
* <pre>DynaWaltz</pre> expects {@code dynamicModelId} = “NETWORK” for these variables.
*/
static class CurvesSpec {
String dynamicModelId
String staticId
String[] variables

void dynamicModelId(String dynamicModelId) {
this.dynamicModelId = dynamicModelId
}

void staticId(String staticId) {
this.staticId = staticId
}

void variables(String[] variables) {
this.variables = variables
}

void variable(String variable) {
this.variables = [variable]
}
}

@Override
String getName() {
DynaWaltzProvider.NAME
}

DynaWaltzCurve dynawoCurve(CurvesSpec curveSpec, Consumer<Curve> consumer) {

if (curveSpec.staticId && curveSpec.dynamicModelId) {
throw new DslException("Both staticId and dynamicModelId are defined")
}
if (!curveSpec.variables) {
throw new DslException("'variables' field is not set")
}
if (curveSpec.variables.length == 0) {
throw new DslException("'variables' field is empty")
}

for (String variable : curveSpec.variables) {
if (curveSpec.staticId) {
consumer.accept(new DynaWaltzCurve("NETWORK", curveSpec.staticId + "_" + variable))
} else {
consumer.accept(new DynaWaltzCurve(curveSpec.dynamicModelId, variable))
}
}
}

@Override
void load(Binding binding, Consumer<Curve> consumer, ReportNode reportNode) {
binding.curve = { Closure<Void> closure ->
def cloned = closure.clone()
CurvesSpec curveSpec = new CurvesSpec()

cloned.delegate = curveSpec
cloned()

dynawoCurve(curveSpec, consumer)
}

binding.curves = { Closure<Void> closure ->
Closure<Void> closure = { Closure<Void> closure ->
def cloned = closure.clone()
CurvesSpec curvesSpec = new CurvesSpec()

cloned.delegate = curvesSpec
DynawoCurvesBuilder curvesBuilder = new DynawoCurvesBuilder(reportNode)
cloned.delegate = curvesBuilder
cloned()

dynawoCurve(curvesSpec, consumer)
curvesBuilder.add(consumer)
}
binding.curve = closure
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@

import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import com.powsybl.dsl.DslException;
import com.powsybl.dynamicsimulation.Curve;
import com.powsybl.dynamicsimulation.CurvesSupplier;
import com.powsybl.dynamicsimulation.groovy.CurveGroovyExtension;
import com.powsybl.dynamicsimulation.groovy.GroovyCurvesSupplier;
import com.powsybl.dynamicsimulation.groovy.GroovyExtension;
import com.powsybl.dynawaltz.DynaWaltzCurve;
import com.powsybl.dynawaltz.curves.DynawoCurve;
import com.powsybl.dynawaltz.DynaWaltzProvider;
import com.powsybl.iidm.network.Generator;
import com.powsybl.iidm.network.Load;
Expand All @@ -23,24 +22,20 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.*;

/**
* @author Marcos de Miguel {@literal <demiguelm at aia.es>}
*/
class DynaWaltzGroovyCurvesSupplierTest {
class DynaWaltzGroovyCurvesSupplierTest extends AbstractModelSupplierTest {

private FileSystem fileSystem;
private Network network;
Expand All @@ -51,9 +46,6 @@ void setup() throws IOException {
network = EurostagTutorialExample1Factory.create();

Files.copy(Objects.requireNonNull(getClass().getResourceAsStream("/curves.groovy")), fileSystem.getPath("/curves.groovy"));
Files.copy(Objects.requireNonNull(getClass().getResourceAsStream("/curves_dynamicModelId_staticId.groovy")), fileSystem.getPath("/curves_dynamicModelId_staticId.groovy"));
Files.copy(Objects.requireNonNull(getClass().getResourceAsStream("/curves_variable.groovy")), fileSystem.getPath("/curves_variable.groovy"));
Files.copy(Objects.requireNonNull(getClass().getResourceAsStream("/curves_variables.groovy")), fileSystem.getPath("/curves_variables.groovy"));
}

@AfterEach
Expand All @@ -70,23 +62,6 @@ void test() {
curves.forEach(this::validateCurve);
}

@ParameterizedTest(name = "{1}")
@MethodSource("provideFileError")
void testScriptError(String fileName, String error) {
List<CurveGroovyExtension> extensions = validateGroovyExtension();
CurvesSupplier supplier = new GroovyCurvesSupplier(fileSystem.getPath(fileName), extensions);
DslException exception = assertThrows(DslException.class, () -> supplier.get(network));
assertEquals(error, exception.getMessage());
}

private static Stream<Arguments> provideFileError() {
return Stream.of(
Arguments.of("/curves_dynamicModelId_staticId.groovy", "Both staticId and dynamicModelId are defined"),
Arguments.of("/curves_variable.groovy", "'variables' field is not set"),
Arguments.of("/curves_variables.groovy", "'variables' field is not set")
);
}

private List<CurveGroovyExtension> validateGroovyExtension() {
List<CurveGroovyExtension> extensions = GroovyExtension.find(CurveGroovyExtension.class, DynaWaltzProvider.NAME);
assertEquals(1, extensions.size());
Expand All @@ -95,8 +70,8 @@ private List<CurveGroovyExtension> validateGroovyExtension() {
}

private void validateCurve(Curve curve) {
assertEquals(DynaWaltzCurve.class, curve.getClass());
DynaWaltzCurve curveImpl = (DynaWaltzCurve) curve;
assertEquals(DynawoCurve.class, curve.getClass());
DynawoCurve curveImpl = (DynawoCurve) curve;
if (curveImpl.getModelId().equals("NETWORK")) {
assertTrue(Arrays.asList("NGEN_Upu_value", "NHV1_Upu_value", "NHV2_Upu_value", "NLOAD_Upu_value").contains(curveImpl.getVariable()));
} else if (network.getIdentifiable(curveImpl.getModelId()) instanceof Generator) {
Expand Down
2 changes: 1 addition & 1 deletion dynawaltz-dsl/src/test/resources/curves.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ for (Bus bus : network.busBreakerView.buses) {
}

for (Generator gen : network.generators) {
curves {
curve {
dynamicModelId gen.id
variables "generator_omegaPu", "generator_PGen", "generator_UStatorPU", "voltageRegulator_UcEfdP", "voltageRegulator_EfdPu"
}
Expand Down

This file was deleted.

14 changes: 0 additions & 14 deletions dynawaltz-dsl/src/test/resources/curves_variable.groovy

This file was deleted.

14 changes: 0 additions & 14 deletions dynawaltz-dsl/src/test/resources/curves_variables.groovy

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ for (Bus bus : network.busBreakerView.buses) {
}

for (Generator gen : network.generators) {
curves {
curve {
dynamicModelId gen.id
variables "generator_omegaPu", "generator_PGen", "generator_QGen", "generator_UStatorPu", "voltageRegulator_EfdPu"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ for (Bus bus : network.busBreakerView.buses) {
}

for (Generator gen : network.generators) {
curves {
curve {
dynamicModelId gen.id
variables "generator_omegaPu", "generator_PGen", "generator_QGen", "generator_UStatorPu", "voltageRegulator_EfdPu"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,38 @@ for (Bus bus : network.busBreakerView.buses) {
}

for (Generator gen : network.generators) {
curves {
curve {
dynamicModelId gen.id
variables "generator_omegaPu", "generator_PGen", "generator_QGen", "generator_UStatorPu", "voltageRegulator_EfdPu"
}
}

curves {
curve {
dynamicModelId "_LOAD___2_EC"
variables "load_PPu", "load_QPu"
}

curves {
curve {
staticId "_BUS____2-BUS____4-1_AC"
variables "iSide2", "state"
}

curves {
curve {
dynamicModelId "CLA_2_4"
variables "currentLimitAutomaton_order", "currentLimitAutomaton_IMax"
}

curves {
curve {
staticId "_BUS____1-BUS____5-1_AC"
variables "iSide2", "state"
}

curves {
curve {
staticId "_BUS____2-BUS____5-1_AC"
variables "iSide2", "state"
}

curves {
curve {
dynamicModelId "CLA_2_5"
variables "currentLimitAutomaton_order", "currentLimitAutomaton_IMax"
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ for (Bus bus : network.busBreakerView.buses) {
}

for (Generator gen : network.generators) {
curves {
curve {
dynamicModelId gen.id
variables "generator_omegaPu", "generator_PGen", "generator_QGen", "generator_UStatorPu"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.powsybl.commons.report.ReportNode;
import com.powsybl.dynamicsimulation.Curve;
import com.powsybl.dynamicsimulation.DynamicSimulationParameters;
import com.powsybl.dynawaltz.curves.DynawoCurve;
import com.powsybl.dynawaltz.models.AbstractPureDynamicBlackBoxModel;
import com.powsybl.dynawaltz.models.BlackBoxModel;
import com.powsybl.dynawaltz.models.EquipmentBlackBoxModel;
Expand Down Expand Up @@ -54,7 +55,7 @@ public class DynaWaltzContext {
private final List<BlackBoxModel> dynamicModels;
private final List<BlackBoxModel> eventModels;
private final Map<String, EquipmentBlackBoxModel> staticIdBlackBoxModelMap;
private final List<Curve> curves;
private final List<DynawoCurve> curves;
private final Map<String, MacroStaticReference> macroStaticReferences = new LinkedHashMap<>();
private final List<MacroConnect> macroConnectList = new ArrayList<>();
private final Map<String, MacroConnector> macroConnectorsMap = new LinkedHashMap<>();
Expand Down Expand Up @@ -97,7 +98,10 @@ public DynaWaltzContext(Network network, String workingVariantId, List<BlackBoxM
.map(ContextDependentEvent.class::cast)
.forEach(e -> e.setEquipmentHasDynamicModel(this));

this.curves = Objects.requireNonNull(curves);
this.curves = Objects.requireNonNull(curves).stream()
.filter(DynawoCurve.class::isInstance)
.map(DynawoCurve.class::cast)
.toList();
this.frequencySynchronizer = setupFrequencySynchronizer(dynamicModels.stream().anyMatch(AbstractBus.class::isInstance) ? SetPoint::new : OmegaRef::new);
this.macroConnectionsAdder = new MacroConnectionsAdder(this::getDynamicModel,
this::getPureDynamicModel,
Expand Down Expand Up @@ -256,8 +260,8 @@ public List<BlackBoxModel> getBlackBoxEventModels() {
return eventModels;
}

public List<Curve> getCurves() {
return Collections.unmodifiableList(curves);
public List<DynawoCurve> getCurves() {
return curves;
}

public boolean withCurves() {
Expand Down
Loading

0 comments on commit 286a2d2

Please sign in to comment.