Skip to content

Commit

Permalink
Dynawo final state values (#381)
Browse files Browse the repository at this point in the history
* Add FSV input
* Rename curve to outputVariable
* Parse Fsv CSV file
* Add Fsv handling in integration test

Signed-off-by: lisrte <[email protected]>
  • Loading branch information
Lisrte authored Oct 1, 2024
1 parent bb8ac28 commit 2b6a07f
Show file tree
Hide file tree
Showing 53 changed files with 777 additions and 485 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ To run a dynamic simulation, you need:
- a case file
- a `DynamicModelsSupplier` to associate dynamic models to the equipment of the network
- an `EventModelsSuppler` to configure events simulated during the simulation (optional)
- a `CurvesSupplier` to follow the evolution of dynamic variables during the simulation (optional)
- an `OutputVariablesSupplier` to follow the evolution of dynamic variables during the simulation (optional)
- a set of parameters to configure the simulation (optional)

Thanks to `powsybl-dynawo-dsl`, the inputs can be easily configured using Groovy scripts.
Expand All @@ -38,25 +38,25 @@ The simulation parameters can be configured either in the `config.yml` file or u
Network network = Network.read("/path/to/the/casefile.xiidm");

// Load the dynamic models mapping
GroovyDynamicModelsSupplier dynamicModelsSupplier = new GroovyDynamicModelsSupplier(
DynamicModelsSupplier dynamicModelsSupplier = new GroovyDynamicModelsSupplier(
Paths.get("/path/to/dynamicModelsMapping.groovy"),
GroovyExtension.find(DynamicModelGroovyExtension.class, DynawoSimulationProvider.NAME));

// Load the events
GroovyEventModelsSupplier eventModelsSupplier = new GroovyEventModelsSupplier(
EventModelsSupplier eventModelsSupplier = new GroovyEventModelsSupplier(
Paths.get("/path/to/event.groovy"),
GroovyExtension.find(EventModelGroovyExtension.class, DynawoSimulationProvider.NAME));

// Configure the curves
GroovyCurvesSupplier curvesSupplier = new GroovyCurvesSupplier(
Paths.get("/path/to/curves.groovy"),
GroovyExtension.find(CurveGroovyExtension.class, DynawoSimulationProvider.NAME));
// Configure the output variables
OutputVariablesSupplier outputVariablesSupplier = new GroovyOutputVariablesSupplier(
Paths.get("/path/to/outputVariables.groovy"),
GroovyExtension.find(OutputVariableGroovyExtension.class, DynawoSimulationProvider.NAME));

// Load the parameters
DynamicSimulationParameters parameters = DynamicSimulationParameters.load();

// Run the simulation and display the results
DynamicSimulationResult result = DynamicSimulation.run(network, dynamicModelsSupplier, eventModelsSupplier, curvesSupplier, parameters);
DynamicSimulationResult result = DynamicSimulation.run(network, dynamicModelsSupplier, eventModelsSupplier, outputVariablesSupplier, parameters);
System.out.println(result.getStatus());
System.out.println("Timeline:");
result.getTimeLine().forEach(tl -> System.out.printf("[%.8f] %s (on %s)%n", tl.time(), tl.message(), tl.modelName()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,30 @@ public abstract class AbstractCsvParser<T> {

protected static final char DEFAULT_SEPARATOR = '|';

private final char separator;
private final CsvParser csvParser;

protected AbstractCsvParser(char separator) {
this.separator = separator;
protected AbstractCsvParser(char separator, boolean skipHeader) {
CsvParserSettings settings = new CsvParserSettings();
settings.getFormat().setDelimiter(separator);
settings.getFormat().setQuoteEscape('"');
settings.getFormat().setLineSeparator(System.lineSeparator());
settings.setMaxColumns(getNbColumns());
settings.setHeaderExtractionEnabled(skipHeader);
csvParser = new CsvParser(settings);
}

public List<T> parse(Path file) {
if (!Files.exists(file)) {
return Collections.emptyList();
}

try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
return parse(reader);
Objects.requireNonNull(reader);
return read(csvParser.iterate(reader).iterator());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

private List<T> parse(BufferedReader reader) {
Objects.requireNonNull(reader);
CsvParserSettings settings = new CsvParserSettings();
settings.getFormat().setDelimiter(separator);
settings.getFormat().setQuoteEscape('"');
settings.getFormat().setLineSeparator(System.lineSeparator());
settings.setMaxColumns(getNbColumns());
CsvParser csvParser = new CsvParser(settings);
ResultIterator<String[], ParsingContext> iterator = csvParser.iterate(reader).iterator();
return read(iterator);
}

protected List<T> read(ResultIterator<String[], ParsingContext> iterator) {
List<T> logs = new ArrayList<>();
int iLine = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public CsvLogParser() {
}

public CsvLogParser(char separator) {
super(separator);
super(separator, false);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public CsvTimeLineParser() {
}

public CsvTimeLineParser(char separator) {
super(separator);
super(separator, false);
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion docs/dynamic_simulation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
configuration.md
dynamic-models-dsl.md
event-models-dsl.md
curves-dsl.md
output-variables-dsl.md
```

PowSyBl provides an implementation of the [DynamicSimulation API from powsybl-core](inv:powsyblcore:*:*#simulation/dynamic/index) with [Dynaωo](https://dynawo.github.io), a tool for long-term stability simulation.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
# 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` keywords.
# Output Variables DSL
The output variables domain specific language allow a user to configure the curves or final state values Dynawo will export at the end of the simulation.
This DSL defines the `curve` and `fsv`keywords.

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
dynamicModelId "dynamicId"
variable "load_PPu"
}
```

If the only information needed is the variable final value, the `curve` keyword can be replaced by `fsv` keyword:
```groovy
fsv {
dynamicModelId "dynamicId"
variable "load_PPu"
}
```
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (c) 2020, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.powsybl.dynawo.dsl

import com.google.auto.service.AutoService
import com.powsybl.commons.report.ReportNode
import com.powsybl.dynamicsimulation.OutputVariable
import com.powsybl.dynamicsimulation.groovy.OutputVariableGroovyExtension
import com.powsybl.dynawo.DynawoSimulationProvider
import com.powsybl.dynawo.outputvariables.DynawoOutputVariablesBuilder

import java.util.function.Consumer
/**
* An implementation of {@link OutputVariableGroovyExtension} that adds the <pre>curve</pre> and <pre>fsv</pre> keywords to the DSL
*
* @author Mathieu Bague {@literal <[email protected]>}
*/
@AutoService(OutputVariableGroovyExtension.class)
class DynawoOutputVariableGroovyExtension implements OutputVariableGroovyExtension {

@Override
String getName() {
DynawoSimulationProvider.NAME
}

@Override
void load(Binding binding, Consumer<OutputVariable> consumer, ReportNode reportNode) {
Closure<Void> closure = { Closure<Void> closure, OutputVariable.OutputType type ->
def cloned = closure.clone()
DynawoOutputVariablesBuilder variablesBuilder = new DynawoOutputVariablesBuilder(reportNode).outputType(type)
cloned.delegate = variablesBuilder
cloned()
variablesBuilder.add(consumer)
}
binding.curve = c -> closure(c, OutputVariable.OutputType.CURVE)
binding.fsv = c -> closure(c, OutputVariable.OutputType.FINAL_STATE)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* Copyright (c) 2020, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.powsybl.dynawo.dsl;

import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import com.powsybl.dynamicsimulation.OutputVariable;
import com.powsybl.dynamicsimulation.OutputVariablesSupplier;
import com.powsybl.dynamicsimulation.groovy.GroovyExtension;
import com.powsybl.dynamicsimulation.groovy.GroovyOutputVariablesSupplier;
import com.powsybl.dynamicsimulation.groovy.OutputVariableGroovyExtension;
import com.powsybl.dynawo.outputvariables.DynawoOutputVariable;
import com.powsybl.dynawo.DynawoSimulationProvider;
import com.powsybl.iidm.network.Generator;
import com.powsybl.iidm.network.Load;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

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 static org.junit.jupiter.api.Assertions.*;

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

private FileSystem fileSystem;
private Network network;

@BeforeEach
void setup() throws IOException {
fileSystem = Jimfs.newFileSystem(Configuration.unix());
network = EurostagTutorialExample1Factory.create();

Files.copy(Objects.requireNonNull(getClass().getResourceAsStream("/outputVariables.groovy")), fileSystem.getPath("/outputVariables.groovy"));
}

@AfterEach
void tearDown() throws IOException {
fileSystem.close();
}

@Test
void test() {
List<OutputVariableGroovyExtension> extensions = validateGroovyExtension();
OutputVariablesSupplier supplier = new GroovyOutputVariablesSupplier(fileSystem.getPath("/outputVariables.groovy"), extensions);
List<OutputVariable> outputVariables = supplier.get(network);
assertEquals(11, outputVariables.size());
outputVariables.forEach(this::validateOutputVariable);
}

private List<OutputVariableGroovyExtension> validateGroovyExtension() {
List<OutputVariableGroovyExtension> extensions = GroovyExtension.find(OutputVariableGroovyExtension.class, DynawoSimulationProvider.NAME);
assertEquals(1, extensions.size());
assertInstanceOf(DynawoOutputVariableGroovyExtension.class, extensions.get(0));
return extensions;
}

private void validateOutputVariable(OutputVariable outputVariable) {
assertEquals(DynawoOutputVariable.class, outputVariable.getClass());
if (outputVariable.getModelId().equals("NETWORK")) {
assertEquals(OutputVariable.OutputType.CURVE, outputVariable.getOutputType());
assertTrue(Arrays.asList("NGEN_Upu_value", "NHV1_Upu_value", "NHV2_Upu_value", "NLOAD_Upu_value").contains(outputVariable.getVariableName()));
} else if (network.getIdentifiable(outputVariable.getModelId()) instanceof Generator) {
assertEquals(OutputVariable.OutputType.FINAL_STATE, outputVariable.getOutputType());
assertTrue(Arrays.asList("generator_omegaPu", "generator_PGen", "generator_UStatorPU", "voltageRegulator_UcEfdP", "voltageRegulator_EfdPu").contains(outputVariable.getVariableName()));
} else if (network.getIdentifiable(outputVariable.getModelId()) instanceof Load) {
assertEquals(OutputVariable.OutputType.CURVE, outputVariable.getOutputType());
assertTrue(Arrays.asList("load_PPu", "load_QPu").contains(outputVariable.getVariableName()));
}
}
}
Loading

0 comments on commit 2b6a07f

Please sign in to comment.