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

Loads Margin calculation #420

Draft
wants to merge 31 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c884e56
Add model documentation in models.json
Lisrte Jun 19, 2024
93e86f0
Add event models documentation
Lisrte Jun 20, 2024
52843cf
Move ModelConfigsHandler::eventBuilderConfigs in ModelConfigLoader
Lisrte Jun 20, 2024
e83f775
Merge branch 'main' into models_documentation
Lisrte Jul 1, 2024
efde11b
Rename lib to modelName
Lisrte Jul 4, 2024
2cbd3dd
Remove ModelInfos.java interface
Lisrte Jul 4, 2024
61724d4
Merge branch 'refs/heads/main' into models_documentation
Lisrte Jul 4, 2024
2aa8922
Fix merge
Lisrte Jul 4, 2024
8610109
Rename remaining lib to model
Lisrte Jul 4, 2024
019319b
Rename tag to modelName/name
Lisrte Jul 5, 2024
df3274d
Rename dynawaltz to dynawo
Lisrte Jul 5, 2024
eb5d3b6
Update documentation
Lisrte Jul 8, 2024
248b80a
Update documentation 2
Lisrte Jul 8, 2024
91b6b42
Fix code smells
Lisrte Jul 8, 2024
302bc63
Handle load variation area in margin calculation
Lisrte Jul 11, 2024
1720373
Phase 2 in DynawoSimulationContext
Lisrte Jul 12, 2024
fa97b48
Add MarginCalculationParameters and LoadVariationAreaXmlTest
Lisrte Jul 16, 2024
8dd3058
Add LoadIncreaseResult with XML parsing
Lisrte Sep 4, 2024
aee669c
Add provider, handler, multiple jobs
Lisrte Sep 4, 2024
e0caacb
Add LoadsVariationSupplier, fix todo
Lisrte Sep 6, 2024
1b5879a
Merge main
Lisrte Dec 19, 2024
c1960c1
Fix merge
Lisrte Dec 19, 2024
dcdebd5
Remove unused class
Lisrte Dec 19, 2024
1e8faf2
Remove duplicate code
Lisrte Dec 19, 2024
d073157
Remove LoadsVariation::VariationMode
Lisrte Jan 6, 2025
bda6a0b
Fix maven.yml
Lisrte Jan 7, 2025
4cb15fe
Add test coverage
Lisrte Jan 7, 2025
a0f15c4
Phase2 MC predicate
Lisrte Jan 8, 2025
82237be
Handle MC dynawo parameters
Lisrte Jan 13, 2025
e1f78d5
Fix tests
Lisrte Jan 15, 2025
0adfded
Add itools support and MC API
Lisrte Jan 16, 2025
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
20 changes: 16 additions & 4 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,37 @@ jobs:

steps:
- name: Checkout sources
uses: actions/checkout@v1
uses: actions/checkout@v4
with:
path: main

- name: Checkout powsybl-core branch
uses: actions/checkout@v4
with:
repository: powsybl/powsybl-core
ref: refs/heads/scalable_access
path: powsybl-core

- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 17

- name: Build and install powsybl-core with Maven
run: mvn --batch-mode -DskipTests=true --file ./powsybl-core/pom.xml install

- name: Build with Maven
if: matrix.os == 'ubuntu-latest'
run: mvn --batch-mode -Pintegration-tests,jacoco install
run: mvn --batch-mode -Pintegration-tests,jacoco --file ./main/pom.xml install

- name: Build with Maven
if: matrix.os != 'ubuntu-latest'
run: mvn --batch-mode install
run: mvn --batch-mode --file ./main/pom.xml install

- name: Run SonarCloud analysis
if: matrix.os == 'ubuntu-latest'
run: >
mvn --batch-mode -DskipTests sonar:sonar
mvn --batch-mode -DskipTests --file ./main/pom.xml sonar:sonar
-Dsonar.host.url=https://sonarcloud.io
-Dsonar.organization=powsybl-ci-github
-Dsonar.projectKey=com.powsybl:powsybl-dynawo
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* Copyright (c) 2025, 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/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.dynaflow.results;

import com.powsybl.commons.exceptions.UncheckedXmlStreamException;
import com.powsybl.commons.xml.XmlUtil;
import com.powsybl.dynawo.commons.AbstractXmlParser;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
* @author Laurent Issertial {@literal <laurent.issertial at rte-france.com>}
*/
public abstract class AbstractXmlAggregatedResultParser<T> extends AbstractXmlParser<T> {

protected static final String STATUS = "status";
private static final String ID = "id";
private static final String TIME = "time";

protected static boolean readScenarioResult(String elementName, XMLStreamReader xmlReader, Consumer<ScenarioResult> scenarioConsumer) {
if (elementName.equals("scenarioResults")) {
String id = xmlReader.getAttributeValue(null, ID);
String status = xmlReader.getAttributeValue(null, STATUS);
List<FailedCriterion> failedCriteria = new ArrayList<>();
XmlUtil.readSubElements(xmlReader, subElementName -> readFailedCriterion(subElementName, xmlReader, failedCriteria::add));
ResultsUtil.createScenarioResult(id, status, failedCriteria).ifPresent(scenarioConsumer);
return true;
}
return false;
}

protected static void readFailedCriterion(String elementName, XMLStreamReader xmlReader, Consumer<FailedCriterion> resultConsumer) {
try {
if (elementName.equals("criterionNonRespected")) {
String description = xmlReader.getAttributeValue(null, ID);
String time = xmlReader.getAttributeValue(null, TIME);
XmlUtil.readEndElementOrThrow(xmlReader);
ResultsUtil.createFailedCriterion(description, time).ifPresent(resultConsumer);
}
} catch (XMLStreamException e) {
throw new UncheckedXmlStreamException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static PostContingencyComputationStatus convertToPostStatus(Status status
};
}

static Optional<ScenarioResult> createScenarioResult(String id, String status, List<FailedCriterion> failedCriteria) {
public static Optional<ScenarioResult> createScenarioResult(String id, String status, List<FailedCriterion> failedCriteria) {
if (id == null || status == null || failedCriteria == null) {
LOGGER.warn("Inconsistent scenario result entry (id: '{}', status: '{}', failedCriteria: '{}')", id, status, failedCriteria);
} else {
Expand All @@ -56,7 +56,7 @@ static Optional<ScenarioResult> createScenarioResult(String id, String status, L
return Optional.empty();
}

static Optional<FailedCriterion> createFailedCriterion(String description, String time) {
public static Optional<FailedCriterion> createFailedCriterion(String description, String time) {
if (description == null || time == null) {
LOGGER.warn("Inconsistent failed criterion entry (description: '{}', time: '{}')", description, time);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,17 @@
*/
package com.powsybl.dynaflow.results;

import com.powsybl.commons.exceptions.UncheckedXmlStreamException;
import com.powsybl.commons.xml.XmlUtil;
import com.powsybl.dynawo.commons.AbstractXmlParser;

import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
* @author Laurent Issertial {@literal <laurent.issertial at rte-france.com>}
*/
public final class XmlScenarioResultParser extends AbstractXmlParser<ScenarioResult> {

private static final String STATUS = "status";
private static final String ID = "id";
private static final String TIME = "time";
public final class XmlScenarioResultParser extends AbstractXmlAggregatedResultParser<ScenarioResult> {

@Override
protected void read(XMLStreamReader xmlReader, Consumer<ScenarioResult> consumer) throws XMLStreamException {
Expand All @@ -35,27 +27,4 @@ protected void read(XMLStreamReader xmlReader, Consumer<ScenarioResult> consumer
}
XmlUtil.readSubElements(xmlReader, elementName -> readScenarioResult(elementName, xmlReader, consumer));
}

public static void readScenarioResult(String elementName, XMLStreamReader xmlReader, Consumer<ScenarioResult> scenarioConsumer) {
if (elementName.equals("scenarioResults")) {
String id = xmlReader.getAttributeValue(null, ID);
String status = xmlReader.getAttributeValue(null, STATUS);
List<FailedCriterion> failedCriteria = new ArrayList<>();
XmlUtil.readSubElements(xmlReader, subElementName -> readFailedCriterion(subElementName, xmlReader, failedCriteria::add));
ResultsUtil.createScenarioResult(id, status, failedCriteria).ifPresent(scenarioConsumer);
}
}

public static void readFailedCriterion(String elementName, XMLStreamReader xmlReader, Consumer<FailedCriterion> resultConsumer) {
try {
if (elementName.equals("criterionNonRespected")) {
String description = xmlReader.getAttributeValue(null, ID);
String time = xmlReader.getAttributeValue(null, TIME);
XmlUtil.readEndElementOrThrow(xmlReader);
ResultsUtil.createFailedCriterion(description, time).ifPresent(resultConsumer);
}
} catch (XMLStreamException e) {
throw new UncheckedXmlStreamException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
import com.powsybl.dynamicsimulation.groovy.GroovyExtension;
import com.powsybl.dynawo.DynawoSimulationParameters;
import com.powsybl.dynawo.DynawoSimulationProvider;
import com.powsybl.dynawo.algorithms.DynawoAlgorithmsConfig;
import com.powsybl.dynawo.parameters.ParametersSet;
import com.powsybl.dynawo.xml.ParametersXml;

import com.powsybl.dynawo.security.DynawoAlgorithmsConfig;
import com.powsybl.dynawo.security.DynawoSecurityAnalysisProvider;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.VariantManagerConstants;
Expand Down Expand Up @@ -71,7 +71,7 @@ void testIeee14DSA(String criteriaPath, List<Contingency> contingencies, String
Network network = Network.read(new ResourceDataSource("IEEE14", new ResourceSet("/ieee14", "IEEE14.iidm")));

GroovyDynamicModelsSupplier dynamicModelsSupplier = new GroovyDynamicModelsSupplier(
getResourceAsStream("/ieee14/dynamic-security-analysis/dynamicModels.groovy"),
getResourceAsStream("/ieee14/dynamicModels.groovy"),
GroovyExtension.find(DynamicModelGroovyExtension.class, DynawoSimulationProvider.NAME));

List<ParametersSet> modelsParameters = ParametersXml.load(getResourceAsStream("/ieee14/models.par"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void testIeee14() {
assertEquals(27, result.getCurves().size());
DoubleTimeSeries ts1 = result.getCurve("_GEN____1_SM_generator_UStatorPu");
assertEquals("_GEN____1_SM_generator_UStatorPu", ts1.getMetadata().getName());
assertEquals(192, ts1.toArray().length);
assertEquals(258, ts1.toArray().length);
assertEquals(14, result.getFinalStateValues().size());
assertEquals(1.046227, result.getFinalStateValues().get("NETWORK__BUS___10_TN_Upu_value"));
List<TimelineEvent> timeLine = result.getTimeLine();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/**
* Copyright (c) 2022, 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.it;

import com.powsybl.commons.datasource.ResourceDataSource;
import com.powsybl.commons.datasource.ResourceSet;
import com.powsybl.commons.report.ReportNode;
import com.powsybl.contingency.Contingency;
import com.powsybl.dynaflow.results.ScenarioResult;
import com.powsybl.dynaflow.results.Status;
import com.powsybl.dynamicsimulation.groovy.DynamicModelGroovyExtension;
import com.powsybl.dynamicsimulation.groovy.GroovyDynamicModelsSupplier;
import com.powsybl.dynamicsimulation.groovy.GroovyExtension;
import com.powsybl.dynawo.DynawoSimulationParameters;
import com.powsybl.dynawo.DynawoSimulationProvider;
import com.powsybl.dynawo.algorithms.DynawoAlgorithmsConfig;
import com.powsybl.dynawo.margincalculation.MarginCalculationParameters;
import com.powsybl.dynawo.margincalculation.MarginCalculationProvider;
import com.powsybl.dynawo.margincalculation.MarginCalculationRunParameters;
import com.powsybl.dynawo.margincalculation.loadsvariation.LoadsVariationBuilder;
import com.powsybl.dynawo.margincalculation.loadsvariation.supplier.LoadsVariationSupplier;
import com.powsybl.dynawo.margincalculation.results.LoadIncreaseResult;
import com.powsybl.dynawo.parameters.ParametersSet;
import com.powsybl.dynawo.xml.ParametersXml;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.VariantManagerConstants;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Laurent Issertial <laurent.issertial at rte-france.com>
*/
class MarginCalculationTest extends AbstractDynawoTest {

private MarginCalculationProvider provider;

private MarginCalculationParameters parameters;

private DynawoSimulationParameters dynawoSimulationParameters;

@Override
@BeforeEach
void setUp() throws Exception {
super.setUp();
provider = new MarginCalculationProvider(new DynawoAlgorithmsConfig(Path.of("/dynaflow-launcher"), true));
dynawoSimulationParameters = new DynawoSimulationParameters();
parameters = MarginCalculationParameters.builder()
.setStartTime(0)
.setLoadIncreaseStartTime(10)
.setLoadIncreaseStopTime(70)
.setMarginCalculationStartTime(100)
.setContingenciesStartTime(110)
.setStopTime(200)
.setDynawoParameters(dynawoSimulationParameters)
.build();
}

@ParameterizedTest
@MethodSource("provideSimulationParameter")
void testIeee14MC(String criteriaPath, List<Contingency> contingencies) {
Network network = Network.read(new ResourceDataSource("IEEE14", new ResourceSet("/ieee14", "IEEE14.iidm")));

GroovyDynamicModelsSupplier dynamicModelsSupplier = new GroovyDynamicModelsSupplier(
getResourceAsStream("/ieee14/dynamicModels.groovy"),
GroovyExtension.find(DynamicModelGroovyExtension.class, DynawoSimulationProvider.NAME));

List<ParametersSet> modelsParameters = ParametersXml.load(getResourceAsStream("/ieee14/models.par"));
ParametersSet networkParameters = ParametersXml.load(getResourceAsStream("/ieee14/network.par"), "8");
ParametersSet solverParameters = ParametersXml.load(getResourceAsStream("/ieee14/solvers.par"), "2");
dynawoSimulationParameters.setModelsParameters(modelsParameters)
.setNetworkParameters(networkParameters)
.setSolverParameters(solverParameters)
.setSolverType(DynawoSimulationParameters.SolverType.IDA)
.setCriteriaFilePath(Path.of(Objects.requireNonNull(getClass()
.getResource(criteriaPath)).getPath()));

ReportNode reportNode = ReportNode.newRootReportNode()
.withMessageTemplate("mc_test", "Margin calculation integration test")
.build();

MarginCalculationRunParameters runParameters = new MarginCalculationRunParameters()
.setComputationManager(computationManager)
.setMarginCalculationParameters(parameters)
.setReportNode(reportNode);

LoadsVariationSupplier loadsVariationSupplier = (n, r) -> List.of(
new LoadsVariationBuilder(n, r)
.loads("_LOAD___3_EC", "_LOAD___6_EC", "_LOAD___9_EC")
.variationValue(10)
.build());

List<LoadIncreaseResult> results = provider.run(network, VariantManagerConstants.INITIAL_VARIANT_ID,
dynamicModelsSupplier, n -> contingencies, loadsVariationSupplier, runParameters)
.join()
.getResults();

List<ScenarioResult> expectedResults = contingencies.stream()
.map(c -> new ScenarioResult(c.getId(), Status.CONVERGENCE))
.toList();
assertThat(results).containsExactly(
new LoadIncreaseResult(0, Status.CONVERGENCE, expectedResults),
new LoadIncreaseResult(50, Status.CONVERGENCE, expectedResults),
new LoadIncreaseResult(75, Status.CONVERGENCE, expectedResults),
new LoadIncreaseResult(88, Status.CONVERGENCE, expectedResults),
new LoadIncreaseResult(94, Status.CONVERGENCE, expectedResults),
new LoadIncreaseResult(97, Status.CONVERGENCE, expectedResults),
new LoadIncreaseResult(99, Status.CONVERGENCE, expectedResults));
}

private static Stream<Arguments> provideSimulationParameter() {
return Stream.of(
Arguments.of("/ieee14/dynamic-security-analysis/convergence/criteria.crt",
List.of(Contingency.line("_BUS____1-BUS____5-1_AC", "_BUS____5_VL"),
Contingency.generator("_GEN____2_SM")))
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ieee14
/**
* Copyright (c) 2024, 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/.
* SPDX-License-Identifier: MPL-2.0
*/

import com.powsybl.iidm.network.Load

for (Load load : network.loads) {
LoadAlphaBeta {
staticId load.id
parameterSetId "LAB"
}
}

for (gen in ["_GEN____1_SM", "_GEN____2_SM", "_GEN____3_SM"]) {
GeneratorSynchronousFourWindingsProportionalRegulations {
staticId gen
parameterSetId "GSFWPR" + gen
}
}

for (gen in ["_GEN____6_SM", "_GEN____8_SM"]) {
GeneratorSynchronousThreeWindingsProportionalRegulations {
staticId gen
parameterSetId "GSTWPR" + gen
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"variations": [
{
"loadsIds": ["_LOAD___3_EC_", "_LOAD___6_EC_", "_LOAD___9_EC_"],
"variationValue": 20
},
{
"loadsIds": ["LOAD3"],
"variationValue": 10.2
}
]
}
4 changes: 4 additions & 0 deletions dynawo-security-analysis/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
<groupId>${project.groupId}</groupId>
<artifactId>powsybl-dynaflow</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-contingency-dsl</artifactId>
</dependency>

<!-- Test dependencies -->
<dependency>
Expand Down
Loading
Loading