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

Contingency Load Flow parameters extension #1139

Open
wants to merge 10 commits into
base: feature/refactor-outer-loops
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 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
11 changes: 11 additions & 0 deletions docs/security/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,14 @@ open-security-analysis-default-parameters:
```

At the moment, overriding the parameters by a JSON file is not supported by Open Load Flow.

## Contingency Parameters

Some load flow related parameters can be configured per contingency. This can be done by adding to the `Contingency` object an extension of the `ContingencyLoadFlowParameters` class.
Those parameters correspond to parameters present in [`LoadFlowParameters`](inv:powsyblcore:*:*#simulation/loadflow/configuration) and [`OpenLoadFlowParameters`](../loadflow/parameters.md#specific-parameters) :

- `distributedSlack` (see [distributedSlack](inv:powsyblcore:*:*#simulation/loadflow/configuration))
- `areaInterchangeControl` (see [areaInterchangeControl](../loadflow/parameters.md#specific-parameters))
- `balanceType` (see [balanceType](inv:powsyblcore:*:*#simulation/loadflow/configuration))

If the extension is added to a contingency, the values of these parameters will override their equivalent of the SA input parameters for post contingency and post remedial actions states calculations.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright (c) 2024, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/)
* 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.openloadflow.sa.extensions;

import com.powsybl.commons.extensions.AbstractExtension;
import com.powsybl.contingency.Contingency;
import com.powsybl.loadflow.LoadFlowParameters;

/**
* @author Valentin Mouradian {@literal <valentin.mouradian at artelys.com>}
*/
public class ContingencyLoadFlowParameters extends AbstractExtension<Contingency> {

private boolean distributedSlack;

private boolean areaInterchangeControl;

private LoadFlowParameters.BalanceType balanceType;

public ContingencyLoadFlowParameters(boolean distributedSlack, boolean areaInterchangeControl, LoadFlowParameters.BalanceType balanceType) {
this.distributedSlack = distributedSlack;
this.areaInterchangeControl = areaInterchangeControl;
this.balanceType = balanceType;
}

@Override
public String getName() {
return "contingency-parameters";
m-guibert marked this conversation as resolved.
Show resolved Hide resolved
}

public boolean isDistributedSlack() {
return distributedSlack;
}

public boolean isAreaInterchangeControl() {
return areaInterchangeControl;
}

public LoadFlowParameters.BalanceType getBalanceType() {
return balanceType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.powsybl.openloadflow.sa.extensions;
m-guibert marked this conversation as resolved.
Show resolved Hide resolved

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.google.auto.service.AutoService;
import com.powsybl.commons.extensions.ExtensionJsonSerializer;
import com.powsybl.commons.json.JsonUtil;
import com.powsybl.contingency.Contingency;

import java.io.IOException;

@AutoService(ExtensionJsonSerializer.class)
public class ContingencyLoadFlowParametersJsonSerializer implements ExtensionJsonSerializer<Contingency, ContingencyLoadFlowParameters> {
m-guibert marked this conversation as resolved.
Show resolved Hide resolved

@Override
public String getExtensionName() {
return "contingency-parameters";
m-guibert marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public String getCategoryName() {
return "contingency";
}

@Override
public Class<? super ContingencyLoadFlowParameters> getExtensionClass() {
return ContingencyLoadFlowParameters.class;
}

/**
* Specifies serialization for our extension: ignore name and extendable
*/
private interface SerializationSpec {

@JsonIgnore
String getName();

@JsonIgnore
Contingency getExtendable();
}

private static ObjectMapper createMapper() {
return JsonUtil.createObjectMapper()
.addMixIn(ContingencyLoadFlowParameters.class, SerializationSpec.class);
}

@Override
public void serialize(ContingencyLoadFlowParameters extension, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
createMapper().writeValue(jsonGenerator, extension);
}

@Override
public ContingencyLoadFlowParameters deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
return createMapper().readValue(jsonParser, ContingencyLoadFlowParameters.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Copyright (c) 2024, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/)
* 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.openloadflow.sa.extensions;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.powsybl.commons.json.JsonUtil;
import com.powsybl.commons.test.AbstractSerDeTest;
import com.powsybl.contingency.BranchContingency;
import com.powsybl.contingency.Contingency;
import com.powsybl.contingency.json.ContingencyJsonModule;
import com.powsybl.loadflow.LoadFlowParameters;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* @author Valentin Mouradian {@literal <valentin.mouradian at artelys.com>}
*/
class OpenSecurityAnalysisExtensionsTest extends AbstractSerDeTest {

@Test
void testContingencyLoadFlowParametersExtension() {
Contingency contingency = new Contingency("L2", new BranchContingency("L2"));
contingency.addExtension(ContingencyLoadFlowParameters.class, new ContingencyLoadFlowParameters(false, true, LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD));

ContingencyLoadFlowParameters contingencyLoadFlowParameters = contingency.getExtension(ContingencyLoadFlowParameters.class);

assertEquals(contingencyLoadFlowParameters, contingency.getExtensionByName("contingency-parameters"));
assertFalse(contingencyLoadFlowParameters.isDistributedSlack());
assertTrue(contingencyLoadFlowParameters.isAreaInterchangeControl());
assertEquals(LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD, contingencyLoadFlowParameters.getBalanceType());
}

@Test
void testContingencyLoadFlowParametersExtensionJson() throws IOException {
Contingency contingency = new Contingency("L2", new BranchContingency("L2"));
contingency.addExtension(ContingencyLoadFlowParameters.class, new ContingencyLoadFlowParameters(false, true, LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD));
assertEquals(ContingencyLoadFlowParameters.class, new ContingencyLoadFlowParametersJsonSerializer().getExtensionClass());
roundTripTest(contingency, OpenSecurityAnalysisExtensionsTest::writeContingency, OpenSecurityAnalysisExtensionsTest::readContingency, "/contingencies.json");
}

public static Contingency readContingency(Path jsonFile) {
Objects.requireNonNull(jsonFile);

try (InputStream is = Files.newInputStream(jsonFile)) {
ObjectMapper objectMapper = JsonUtil.createObjectMapper();
ContingencyJsonModule module = new ContingencyJsonModule();
objectMapper.registerModule(module);

return objectMapper.readValue(is, Contingency.class);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

public static void writeContingency(Contingency contingency, Path jsonFile) {
Objects.requireNonNull(contingency);
Objects.requireNonNull(jsonFile);

try (OutputStream os = Files.newOutputStream(jsonFile)) {
ObjectMapper mapper = JsonUtil.createObjectMapper();
ContingencyJsonModule module = new ContingencyJsonModule();
mapper.registerModule(module);

ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
writer.writeValue(os, contingency);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

}
14 changes: 14 additions & 0 deletions src/test/resources/contingencies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id" : "L2",
"elements" : [ {
"id" : "L2",
"type" : "BRANCH"
} ],
"extensions" : {
"contingency-parameters" : {
"distributedSlack" : false,
"areaInterchangeControl" : true,
"balanceType" : "PROPORTIONAL_TO_LOAD"
}
}
}
Loading