Skip to content

Commit

Permalink
Implementation-specific loadflow parameters managed by Loadflow provi…
Browse files Browse the repository at this point in the history
…der (#1987)


Signed-off-by: Etienne LESOT <etienne.lesot@rte-france.com>
  • Loading branch information
EtienneLt authored Mar 16, 2022
1 parent fab1432 commit 32075af
Show file tree
Hide file tree
Showing 14 changed files with 203 additions and 222 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
package com.powsybl.action.simulator;

import com.google.auto.service.AutoService;
import com.powsybl.commons.config.PlatformConfig;
import com.powsybl.commons.extensions.Extension;
import com.powsybl.commons.extensions.ExtensionJsonSerializer;
import com.powsybl.computation.ComputationManager;
import com.powsybl.iidm.network.Network;
import com.powsybl.loadflow.LoadFlowParameters;
Expand All @@ -17,6 +20,7 @@
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
Expand All @@ -42,4 +46,14 @@ public CompletableFuture<LoadFlowResult> run(Network network, ComputationManager
LOGGER.warn("Running loadflow mock");
return CompletableFuture.completedFuture(new LoadFlowResultImpl(true, Collections.emptyMap(), ""));
}

@Override
public Optional<ExtensionJsonSerializer> getSpecificParametersSerializer() {
return Optional.empty();
}

@Override
public Optional<Extension<LoadFlowParameters>> loadSpecificParameters(PlatformConfig config) {
return Optional.empty();
}
}
43 changes: 34 additions & 9 deletions commons/src/main/java/com/powsybl/commons/json/JsonUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,25 @@ public static <T> Set<String> writeExtensions(Extendable<T> extendable, JsonGene
return writeExtensions(extendable, jsonGenerator, true, serializerProvider, supplier);
}

public static <T> Set<String> writeExtensions(Extendable<T> extendable, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider,
SerializerSupplier supplier) throws IOException {
return writeExtensions(extendable, jsonGenerator, true, serializerProvider, supplier);
}

public static <T> Set<String> writeExtensions(Extendable<T> extendable, JsonGenerator jsonGenerator,
boolean headerWanted, SerializerProvider serializerProvider,
ExtensionProviders<? extends ExtensionJsonSerializer> supplier) throws IOException {
return writeExtensions(extendable, jsonGenerator, headerWanted, serializerProvider, supplier::findProvider);
}

public interface SerializerSupplier {
ExtensionJsonSerializer getSerializer(String name);
}

public static <T> Set<String> writeExtensions(Extendable<T> extendable, JsonGenerator jsonGenerator,
boolean headerWanted, SerializerProvider serializerProvider,
SerializerSupplier supplier) throws IOException {
Objects.requireNonNull(extendable);
Objects.requireNonNull(jsonGenerator);
Objects.requireNonNull(serializerProvider);
Expand All @@ -243,7 +259,7 @@ public static <T> Set<String> writeExtensions(Extendable<T> extendable, JsonGene

if (!extendable.getExtensions().isEmpty()) {
for (Extension<T> extension : extendable.getExtensions()) {
ExtensionJsonSerializer serializer = supplier.findProvider(extension.getName());
ExtensionJsonSerializer serializer = supplier.getSerializer(extension.getName());
if (serializer != null) {
if (!headerDone && headerWanted) {
jsonGenerator.writeFieldName("extensions");
Expand Down Expand Up @@ -282,13 +298,22 @@ public static <T extends Extendable> List<Extension<T>> updateExtensions(JsonPar
return updateExtensions(parser, context, supplier, null, extendable);
}

/**
* Updates the extensions of the provided extendable with possibly partial definition read from JSON.
*
* <p>Note that in order for this to work correctly, extension providers need to implement {@link ExtensionJsonSerializer#deserializeAndUpdate}.
*/
public static <T extends Extendable> List<Extension<T>> updateExtensions(JsonParser parser, DeserializationContext context,
SerializerSupplier supplier, T extendable) throws IOException {
return updateExtensions(parser, context, supplier, null, extendable);
}

public static <T extends Extendable> List<Extension<T>> updateExtensions(JsonParser parser, DeserializationContext context,
ExtensionProviders<? extends ExtensionJsonSerializer> supplier, Set<String> extensionsNotFound, T extendable) throws IOException {
return updateExtensions(parser, context, supplier::findProvider, extensionsNotFound, extendable);
}

/**
* Updates the extensions of the provided extendable with possibly partial definition read from JSON.
*
* <p>Note that in order for this to work correctly, extension providers need to implement {@link ExtensionJsonSerializer#deserializeAndUpdate}.
*/
public static <T extends Extendable> List<Extension<T>> updateExtensions(JsonParser parser, DeserializationContext context, SerializerSupplier supplier, Set<String> extensionsNotFound, T extendable) throws IOException {
Objects.requireNonNull(parser);
Objects.requireNonNull(context);
Objects.requireNonNull(supplier);
Expand All @@ -308,9 +333,9 @@ public static <T extends Extendable> List<Extension<T>> updateExtensions(JsonPar
}

private static <T extends Extendable, E extends Extension<T>> E updateExtension(JsonParser parser, DeserializationContext context,
ExtensionProviders<? extends ExtensionJsonSerializer> supplier, Set<String> extensionsNotFound, T extendable) throws IOException {
SerializerSupplier supplier, Set<String> extensionsNotFound, T extendable) throws IOException {
String extensionName = parser.getCurrentName();
ExtensionJsonSerializer<T, E> extensionJsonSerializer = supplier.findProvider(extensionName);
ExtensionJsonSerializer<T, E> extensionJsonSerializer = supplier.getSerializer(extensionName);
if (extensionJsonSerializer != null) {
parser.nextToken();
if (extendable != null && extendable.getExtensionByName(extensionName) != null) {
Expand Down Expand Up @@ -360,7 +385,7 @@ public static <T extends Extendable> Extension<T> readExtension(JsonParser parse
Objects.requireNonNull(parser);
Objects.requireNonNull(context);
Objects.requireNonNull(supplier);
return updateExtension(parser, context, supplier, extensionsNotFound, null);
return updateExtension(parser, context, supplier::findProvider, extensionsNotFound, null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,10 @@
package com.powsybl.loadflow;

import com.fasterxml.jackson.core.util.ByteArrayBuilder;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.powsybl.commons.config.PlatformConfig;
import com.powsybl.commons.extensions.AbstractExtendable;
import com.powsybl.commons.extensions.Extension;
import com.powsybl.commons.extensions.ExtensionConfigLoader;
import com.powsybl.commons.extensions.ExtensionProviders;
import com.powsybl.commons.util.ServiceLoaderCache;
import com.powsybl.iidm.network.Country;
import com.powsybl.loadflow.json.JsonLoadFlowParameters;

Expand All @@ -31,13 +27,6 @@
*/
public class LoadFlowParameters extends AbstractExtendable<LoadFlowParameters> {

/**
* A configuration loader interface for the LoadFlowParameters extensions loaded from the platform configuration
* @param <E> The extension class
*/
public interface ConfigLoader<E extends Extension<LoadFlowParameters>> extends ExtensionConfigLoader<LoadFlowParameters, E> {
}

public enum VoltageInitMode {
UNIFORM_VALUES, // v=1pu, theta=0
PREVIOUS_VALUES,
Expand Down Expand Up @@ -82,9 +71,6 @@ public enum ConnectedComponentMode {
public static final ConnectedComponentMode DEFAULT_CONNECTED_COMPONENT_MODE = ConnectedComponentMode.MAIN;
public static final boolean DEFAULT_HVDC_AC_EMULATION_ON = true;

private static final Supplier<ExtensionProviders<ConfigLoader>> SUPPLIER =
Suppliers.memoize(() -> ExtensionProviders.createProvider(ConfigLoader.class, "loadflow-parameters"));

/**
* Loads parameters from the default platform configuration.
*/
Expand Down Expand Up @@ -113,25 +99,24 @@ protected static void load(LoadFlowParameters parameters, PlatformConfig platfor
Objects.requireNonNull(platformConfig);

platformConfig.getOptionalModuleConfig("load-flow-default-parameters")
.ifPresent(config -> {
parameters.setVoltageInitMode(config.getEnumProperty("voltageInitMode", VoltageInitMode.class, DEFAULT_VOLTAGE_INIT_MODE));
parameters.setTransformerVoltageControlOn(config.getBooleanProperty("transformerVoltageControlOn", DEFAULT_TRANSFORMER_VOLTAGE_CONTROL_ON));
parameters.setNoGeneratorReactiveLimits(config.getBooleanProperty("noGeneratorReactiveLimits", DEFAULT_NO_GENERATOR_REACTIVE_LIMITS));
parameters.setPhaseShifterRegulationOn(config.getBooleanProperty("phaseShifterRegulationOn", DEFAULT_PHASE_SHIFTER_REGULATION_ON));
// keep old tag name "specificCompatibility" for compatibility
parameters.setTwtSplitShuntAdmittance(config.getBooleanProperty("twtSplitShuntAdmittance", config.getBooleanProperty("specificCompatibility", DEFAULT_TWT_SPLIT_SHUNT_ADMITTANCE)));
parameters.setShuntCompensatorVoltageControlOn(config.getBooleanProperty("shuntCompensatorVoltageControlOn",
config.getOptionalBooleanProperty("simulShunt").orElse(DEFAULT_SHUNT_COMPENSATOR_VOLTAGE_CONTROL_ON)));
parameters.setReadSlackBus(config.getBooleanProperty("readSlackBus", DEFAULT_READ_SLACK_BUS));
parameters.setWriteSlackBus(config.getBooleanProperty("writeSlackBus", DEFAULT_WRITE_SLACK_BUS));
parameters.setDc(config.getBooleanProperty("dc", DEFAULT_DC));
parameters.setDistributedSlack(config.getBooleanProperty("distributedSlack", DEFAULT_DISTRIBUTED_SLACK));
parameters.setBalanceType(config.getEnumProperty("balanceType", BalanceType.class, DEFAULT_BALANCE_TYPE));
parameters.setDcUseTransformerRatio(config.getBooleanProperty("dcUseTransformerRatio", DEFAULT_DC_USE_TRANSFORMER_RATIO_DEFAULT));
parameters.setCountriesToBalance(config.getEnumSetProperty("countriesToBalance", Country.class, DEFAULT_COUNTRIES_TO_BALANCE));
parameters.setConnectedComponentMode(config.getEnumProperty("connectedComponentMode", ConnectedComponentMode.class, DEFAULT_CONNECTED_COMPONENT_MODE));
parameters.setHvdcAcEmulation(config.getBooleanProperty("hvdcAcEmulation", DEFAULT_HVDC_AC_EMULATION_ON));
});
.ifPresent(config -> {
parameters.setVoltageInitMode(config.getEnumProperty("voltageInitMode", VoltageInitMode.class, DEFAULT_VOLTAGE_INIT_MODE));
parameters.setTransformerVoltageControlOn(config.getBooleanProperty("transformerVoltageControlOn", DEFAULT_TRANSFORMER_VOLTAGE_CONTROL_ON));
parameters.setNoGeneratorReactiveLimits(config.getBooleanProperty("noGeneratorReactiveLimits", DEFAULT_NO_GENERATOR_REACTIVE_LIMITS));
parameters.setPhaseShifterRegulationOn(config.getBooleanProperty("phaseShifterRegulationOn", DEFAULT_PHASE_SHIFTER_REGULATION_ON));
// keep old tag name "specificCompatibility" for compatibility
parameters.setTwtSplitShuntAdmittance(config.getBooleanProperty("twtSplitShuntAdmittance", config.getBooleanProperty("specificCompatibility", DEFAULT_TWT_SPLIT_SHUNT_ADMITTANCE)));
parameters.setShuntCompensatorVoltageControlOn(config.getBooleanProperty("shuntCompensatorVoltageControlOn",
config.getOptionalBooleanProperty("simulShunt").orElse(DEFAULT_SHUNT_COMPENSATOR_VOLTAGE_CONTROL_ON)));
parameters.setReadSlackBus(config.getBooleanProperty("readSlackBus", DEFAULT_READ_SLACK_BUS));
parameters.setWriteSlackBus(config.getBooleanProperty("writeSlackBus", DEFAULT_WRITE_SLACK_BUS));
parameters.setDc(config.getBooleanProperty("dc", DEFAULT_DC));
parameters.setDistributedSlack(config.getBooleanProperty("distributedSlack", DEFAULT_DISTRIBUTED_SLACK));
parameters.setBalanceType(config.getEnumProperty("balanceType", BalanceType.class, DEFAULT_BALANCE_TYPE));
parameters.setDcUseTransformerRatio(config.getBooleanProperty("dcUseTransformerRatio", DEFAULT_DC_USE_TRANSFORMER_RATIO_DEFAULT));
parameters.setCountriesToBalance(config.getEnumSetProperty("countriesToBalance", Country.class, DEFAULT_COUNTRIES_TO_BALANCE));
parameters.setConnectedComponentMode(config.getEnumProperty("connectedComponentMode", ConnectedComponentMode.class, DEFAULT_CONNECTED_COMPONENT_MODE));
});
}

private VoltageInitMode voltageInitMode;
Expand Down Expand Up @@ -187,8 +172,8 @@ public LoadFlowParameters(VoltageInitMode voltageInitMode, boolean transformerVo
}

public LoadFlowParameters(VoltageInitMode voltageInitMode, boolean transformerVoltageControlOn,
boolean noGeneratorReactiveLimits, boolean phaseShifterRegulationOn,
boolean twtSplitShuntAdmittance) {
boolean noGeneratorReactiveLimits, boolean phaseShifterRegulationOn,
boolean twtSplitShuntAdmittance) {
this(voltageInitMode, transformerVoltageControlOn, noGeneratorReactiveLimits, phaseShifterRegulationOn, twtSplitShuntAdmittance, DEFAULT_SHUNT_COMPENSATOR_VOLTAGE_CONTROL_ON, DEFAULT_READ_SLACK_BUS, DEFAULT_WRITE_SLACK_BUS,
DEFAULT_DC, DEFAULT_DISTRIBUTED_SLACK, DEFAULT_BALANCE_TYPE, DEFAULT_DC_USE_TRANSFORMER_RATIO_DEFAULT, DEFAULT_COUNTRIES_TO_BALANCE, DEFAULT_CONNECTED_COMPONENT_MODE, DEFAULT_HVDC_AC_EMULATION_ON);
}
Expand Down Expand Up @@ -431,6 +416,7 @@ public LoadFlowParameters setHvdcAcEmulation(boolean hvdcAcEmulation) {
/**
* This copy methods uses json serializer mechanism to rebuild all extensions in the this parameters.
* If an extension's serializer not found via {@code @AutoService}, the extension would be lost in copied.
*
* @return a new copied instance and with original's extensions found based-on json serializer.
*/
public LoadFlowParameters copy() {
Expand All @@ -455,8 +441,9 @@ public String toString() {
}

private void loadExtensions(PlatformConfig platformConfig) {
for (ExtensionConfigLoader provider : SUPPLIER.get().getProviders()) {
addExtension(provider.getExtensionClass(), provider.load(platformConfig));
for (LoadFlowProvider provider : new ServiceLoaderCache<>(LoadFlowProvider.class).getServices()) {
provider.loadSpecificParameters(platformConfig).ifPresent(loadFlowParametersExtension ->
addExtension((Class) loadFlowParametersExtension.getClass(), loadFlowParametersExtension));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,32 @@
package com.powsybl.loadflow;

import com.powsybl.commons.Versionable;
import com.powsybl.commons.config.PlatformConfig;
import com.powsybl.commons.config.PlatformConfigNamedProvider;
import com.powsybl.commons.extensions.Extension;
import com.powsybl.commons.extensions.ExtensionJsonSerializer;
import com.powsybl.commons.reporter.Reporter;
import com.powsybl.computation.ComputationManager;
import com.powsybl.iidm.network.Network;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
* SPI for load implementations.
* Service Provider Interface for loadflow implementations.
*
* <p>A loadflow provider is required to implement the main method {@link #run}, in charge of actually
* running a loadflow and updating the network variant with computed physical values.
*
* <p>It may, additionally, provide methods to support implementation-specific parameters.
* Specific parameters should be implemented as an implementation of {@link Extension<LoadFlowParameters>}.
*
* <ul>
* <li>In order to support JSON serialization for those specific parameters,
* implementing {@link #getSpecificParametersSerializer()} is required.</li>
* <li>In order to support loading specific parameters from platform configuration,
* implementing {@link #loadSpecificParameters(PlatformConfig)} is required.</li>
* </ul>
*
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
Expand All @@ -27,10 +44,10 @@ public interface LoadFlowProvider extends Versionable, PlatformConfigNamedProvid
* to be stateless so that it can be call simultaneously with different arguments (a different network for instance)
* without any concurrency issue.
*
* @param network the network
* @param network the network
* @param computationManager a computation manager to external program execution
* @param workingVariantId variant id of the network
* @param parameters load flow execution parameters
* @param workingVariantId variant id of the network
* @param parameters load flow execution parameters
* @return a {@link CompletableFuture} on {@link LoadFlowResult]
*/
default CompletableFuture<LoadFlowResult> run(Network network, ComputationManager computationManager, String workingVariantId, LoadFlowParameters parameters) {
Expand All @@ -43,15 +60,37 @@ default CompletableFuture<LoadFlowResult> run(Network network, ComputationManage
* to be stateless so that it can be call simultaneously with different arguments (a different network for instance)
* without any concurrency issue.
*
* @param network the network
* @param network the network
* @param computationManager a computation manager to external program execution
* @param workingVariantId variant id of the network
* @param parameters load flow execution parameters
* @param reporter the reporter used for functional logs
* @param workingVariantId variant id of the network
* @param parameters load flow execution parameters
* @param reporter the reporter used for functional logs
* @return a {@link CompletableFuture} on {@link LoadFlowResult]
*/
default CompletableFuture<LoadFlowResult> run(Network network, ComputationManager computationManager, String workingVariantId, LoadFlowParameters parameters, Reporter reporter) {
return run(network, computationManager, workingVariantId, parameters);
}

/**
* The serializer for implementation-specific parameters, or {@link Optional#empty()} if the implementation
* does not have any specific parameters, or does not support JSON serialization.
*
* <p>Note that the actual serializer type should be {@code ExtensionJsonSerializer<LoadFlowParameters, MyParametersExtension>}
* where {@code MyParametersExtension} is the specific parameters class.
*
* @return The serializer for implementation-specific parameters.
*/
default Optional<ExtensionJsonSerializer> getSpecificParametersSerializer() {
return Optional.empty();
}

/**
* Reads implementation-specific parameters from platform config, or return {@link Optional#empty()}
* if the implementation does not have any specific parameters, or does not support loading from config.
*
* @return The specific parameters read from platform config.
*/
default Optional<Extension<LoadFlowParameters>> loadSpecificParameters(PlatformConfig config) {
return Optional.empty();
}
}
Loading

0 comments on commit 32075af

Please sign in to comment.