Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Curve builder #362

Merged
merged 17 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Lisrte marked this conversation as resolved.
Show resolved Hide resolved
.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
Loading