com.powsybl.cgmes.conversion.CgmesImport Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of powsybl-cgmes-conversion Show documentation
Show all versions of powsybl-cgmes-conversion Show documentation
Conversion between CGMES and IIDM Network definitions
/**
* Copyright (c) 2017-2018, 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.cgmes.conversion;
import com.google.auto.service.AutoService;
import com.google.common.io.ByteStreams;
import com.powsybl.cgmes.conversion.export.CgmesExportContext;
import com.powsybl.cgmes.conversion.naming.NamingStrategyFactory;
import com.powsybl.cgmes.model.*;
import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.config.PlatformConfig;
import com.powsybl.commons.datasource.DataSource;
import com.powsybl.commons.datasource.DataSourceUtil;
import com.powsybl.commons.datasource.GenericReadOnlyDataSource;
import com.powsybl.commons.datasource.ReadOnlyDataSource;
import com.powsybl.commons.parameters.Parameter;
import com.powsybl.commons.parameters.ParameterDefaultValueConfig;
import com.powsybl.commons.parameters.ParameterScope;
import com.powsybl.commons.parameters.ParameterType;
import com.powsybl.commons.reporter.Reporter;
import com.powsybl.commons.util.ServiceLoaderCache;
import com.powsybl.iidm.network.Importer;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.NetworkFactory;
import com.powsybl.triplestore.api.TripleStoreFactory;
import com.powsybl.triplestore.api.TripleStoreOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static java.util.function.Predicate.not;
/**
* @author Luma Zamarreño {@literal }
*/
@AutoService(Importer.class)
public class CgmesImport implements Importer {
public enum FictitiousSwitchesCreationMode {
ALWAYS,
ALWAYS_EXCEPT_SWITCHES,
NEVER
}
public enum SubnetworkDefinedBy {
FILENAME,
MODELING_AUTHORITY
}
public CgmesImport(PlatformConfig platformConfig, List preProcessors, List postProcessors) {
this.platformConfig = platformConfig;
this.defaultValueConfig = new ParameterDefaultValueConfig(platformConfig);
this.preProcessors = Objects.requireNonNull(preProcessors).stream()
.collect(Collectors.toMap(CgmesImportPreProcessor::getName, e -> e));
this.postProcessors = Objects.requireNonNull(postProcessors).stream()
.collect(Collectors.toMap(CgmesImportPostProcessor::getName, e -> e));
String boundaryPath = platformConfig.getConfigDir()
.map(dir -> dir.resolve(FORMAT).resolve("boundary"))
.map(Path::toString)
.orElse(null);
// Boundary location parameter can not be static
// because we want its default value
// to depend on the received platformConfig
boundaryLocationParameter = new Parameter(
BOUNDARY_LOCATION,
ParameterType.STRING,
"The location of boundary files",
boundaryPath,
null,
ParameterScope.TECHNICAL);
preProcessorsParameter = new Parameter(
PRE_PROCESSORS,
ParameterType.STRING_LIST,
"Pre processors",
Collections.emptyList(),
preProcessors.stream().map(CgmesImportPreProcessor::getName).collect(Collectors.toList()));
postProcessorsParameter = new Parameter(
POST_PROCESSORS,
ParameterType.STRING_LIST,
"Post processors",
Collections.emptyList(),
postProcessors.stream().map(CgmesImportPostProcessor::getName).collect(Collectors.toList()));
}
public CgmesImport(PlatformConfig platformConfig) {
this(platformConfig,
new ServiceLoaderCache<>(CgmesImportPreProcessor.class).getServices(),
new ServiceLoaderCache<>(CgmesImportPostProcessor.class).getServices());
}
public CgmesImport(List preProcessors, List postProcessors) {
this(PlatformConfig.defaultConfig(), preProcessors, postProcessors);
}
public CgmesImport() {
this(PlatformConfig.defaultConfig());
}
@Override
public List getParameters() {
List allParams = new ArrayList<>(STATIC_PARAMETERS);
allParams.add(boundaryLocationParameter);
allParams.add(postProcessorsParameter);
return Collections.unmodifiableList(allParams);
}
@Override
public boolean exists(ReadOnlyDataSource ds) {
CgmesOnDataSource cds = new CgmesOnDataSource(ds);
if (cds.exists()) {
return true;
}
// If we are configured to support CIM14,
// check if there is this CIM14 data
return importCim14 && cds.existsCim14();
}
@Override
public String getComment() {
return "ENTSO-E CGMES version 2.4.15";
}
@Override
public String getFormat() {
return FORMAT;
}
@Override
public Network importData(ReadOnlyDataSource ds, NetworkFactory networkFactory, Properties p, Reporter reporter) {
Objects.requireNonNull(ds);
Objects.requireNonNull(networkFactory);
Objects.requireNonNull(reporter);
if (Parameter.readBoolean(getFormat(), p, IMPORT_CGM_WITH_SUBNETWORKS_PARAMETER, defaultValueConfig)) {
SubnetworkDefinedBy separatingBy = SubnetworkDefinedBy.valueOf(Parameter.readString(getFormat(),
p, IMPORT_CGM_WITH_SUBNETWORKS_DEFINED_BY_PARAMETER, defaultValueConfig));
Set dss = new MultipleGridModelChecker(ds).separate(separatingBy);
if (dss.size() > 1) {
return Network.merge(dss.stream()
.map(ds1 -> importData1(ds1, networkFactory, p, reporter))
.toArray(Network[]::new));
}
}
return importData1(ds, networkFactory, p, reporter);
}
private Network importData1(ReadOnlyDataSource ds, NetworkFactory networkFactory, Properties p, Reporter reporter) {
CgmesModel cgmes = readCgmes(ds, p, reporter);
Reporter conversionReporter = reporter.createSubReporter("CGMESConversion", "Importing CGMES file(s)");
return new Conversion(cgmes, config(p), activatedPreProcessors(p), activatedPostProcessors(p), networkFactory).convert(conversionReporter);
}
static class FilteredReadOnlyDataSource implements ReadOnlyDataSource {
private final ReadOnlyDataSource ds;
private final Predicate filter;
FilteredReadOnlyDataSource(ReadOnlyDataSource ds, Predicate filter) {
this.ds = ds;
this.filter = filter;
}
@Override
public String getBaseName() {
return ds.getBaseName();
}
@Override
public boolean exists(String suffix, String ext) throws IOException {
return ds.exists(suffix, ext) && filter.test(DataSourceUtil.getFileName(getBaseName(), suffix, ext));
}
@Override
public boolean exists(String fileName) throws IOException {
return ds.exists(fileName) && filter.test(fileName);
}
@Override
public InputStream newInputStream(String suffix, String ext) throws IOException {
if (filter.test(DataSourceUtil.getFileName(getBaseName(), suffix, ext))) {
return ds.newInputStream(suffix, ext);
}
throw new IOException(DataSourceUtil.getFileName(getBaseName(), suffix, ext) + " not found");
}
@Override
public InputStream newInputStream(String fileName) throws IOException {
if (filter.test(fileName)) {
return ds.newInputStream(fileName);
}
throw new IOException(fileName + " not found");
}
@Override
public Set listNames(String regex) throws IOException {
return ds.listNames(regex).stream().filter(filter).collect(Collectors.toSet());
}
}
static class MultipleGridModelChecker {
private final ReadOnlyDataSource dataSource;
private XMLInputFactory xmlInputFactory;
MultipleGridModelChecker(ReadOnlyDataSource dataSource) {
this.dataSource = dataSource;
}
Set separate(SubnetworkDefinedBy separatingBy) {
// If it is a CGM, create a filtered dataset for each IGM.
// In the dataset for each IGM we must include:
// - Its own files.
// - The boundaries (we will read the boundaries multiple times, one for each IGM).
// - Any other shared instance files (files that do not contain the name of any IGMs identified).
// An example of shared file is the unique SV from a CGM solved case
// Shared files will be also loaded multiple times, one for each IGM
return switch (separatingBy) {
case MODELING_AUTHORITY -> separateByModelingAuthority();
case FILENAME -> separateByIgmName();
};
}
private Set separateByModelingAuthority() {
xmlInputFactory = XMLInputFactory.newInstance();
Map> igmNames = new CgmesOnDataSource(dataSource).names().stream()
// We consider IGMs only the modeling authorities that have an EQ file
// The CGM SV should have the MA of the merging agent
.filter(CgmesSubset.EQUIPMENT::isValidName)
.map(name -> readModelingAuthority(name).map(ma -> Map.entry(ma, name)))
.flatMap(Optional::stream)
.collect(Collectors.toMap(Map.Entry::getKey, e -> new ArrayList<>(List.of(e.getValue()))));
if (!igmNames.isEmpty()) {
LOGGER.info("IGM EQ files identified by Modeling Authority:");
igmNames.forEach((k, v) -> LOGGER.info(" {} {}", k, v.get(0)));
}
// If we only have found one IGM there is no need to partition
if (igmNames.size() == 1) {
return Set.of(dataSource);
}
Set shared = new HashSet<>();
new CgmesOnDataSource(dataSource).names().stream()
// We read the modeling authorities present in the rest of instance files
// and mark the instance name as linked to an IGM or as shared
.filter(not(CgmesSubset.EQUIPMENT::isValidName))
.filter(not(MultipleGridModelChecker::isBoundary))
.forEach(name -> {
Optional ma = readModelingAuthority(name);
if (ma.isPresent() && igmNames.containsKey(ma.get())) {
igmNames.get(ma.get()).add(name);
} else {
shared.add(name);
}
});
// Build one data source for each IGM found
if (!igmNames.isEmpty()) {
LOGGER.info("IGM files identified by Modeling Authority:");
igmNames.forEach((k, v) -> LOGGER.info(" {} {}", k, String.join(",", v)));
if (!shared.isEmpty()) {
LOGGER.info("Shared files:");
shared.forEach(name -> LOGGER.info(" {}", name));
}
LOGGER.info("Boundaries:");
try {
dataSource.listNames(".*").stream().filter(MultipleGridModelChecker::isBoundary).forEach(name -> LOGGER.info(" {}", name));
} catch (IOException e) {
throw new PowsyblException(e);
}
}
return igmNames.keySet().stream()
.map(ma -> new FilteredReadOnlyDataSource(dataSource,
name -> isBoundary(name) || igmNames.get(ma).contains(name) || shared.contains(name)))
.collect(Collectors.toSet());
}
private Optional readModelingAuthority(String name) {
String modellingAuthority = null;
try (InputStream is = dataSource.newInputStream(name)) {
XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(is);
boolean stopReading = false;
while (reader.hasNext() && !stopReading) {
int token = reader.next();
if (token == XMLStreamConstants.START_ELEMENT && reader.getLocalName().equals(CgmesNames.MODELING_AUTHORITY_SET)) {
modellingAuthority = reader.getElementText();
stopReading = true;
} else if (token == XMLStreamConstants.END_ELEMENT && reader.getLocalName().equals(CgmesNames.FULL_MODEL)) {
// Try to finish parsing the input file as soon as we can
// If we do not have found a modelling authority set inside the FullModel object, exit with unknown
stopReading = true;
}
}
reader.close();
} catch (IOException | XMLStreamException e) {
throw new PowsyblException(e);
}
return Optional.ofNullable(modellingAuthority);
}
private Set separateByIgmName() {
// Here we obtain the IGM name from the EQ filenames,
// and rely on it to find related SSH, TP files,
Set igmNames = new CgmesOnDataSource(dataSource).names().stream()
.filter(CgmesSubset.EQUIPMENT::isValidName)
// We rely on the CIMXML pattern:
// ____
// we define igmName := sourcingActor
.map(name -> name.split("_")[2])
.collect(Collectors.toSet());
return igmNames.stream()
.map(igmName -> new FilteredReadOnlyDataSource(dataSource, name -> name.contains(igmName)
|| isBoundary(name)
|| isShared(name, igmNames)))
.collect(Collectors.toSet());
}
private static boolean isBoundary(String name) {
return CgmesSubset.EQUIPMENT_BOUNDARY.isValidName(name) || CgmesSubset.TOPOLOGY_BOUNDARY.isValidName(name);
}
private static boolean isShared(String name, Set allIgmNames) {
// The name does not contain the name of one the IGMs
return allIgmNames.stream()
.filter(name::contains)
.findAny()
.isEmpty();
}
}
public CgmesModel readCgmes(ReadOnlyDataSource ds, Properties p, Reporter reporter) {
TripleStoreOptions options = new TripleStoreOptions();
String sourceForIidmIds = Parameter.readString(getFormat(), p, SOURCE_FOR_IIDM_ID_PARAMETER, defaultValueConfig);
if (sourceForIidmIds.equalsIgnoreCase(SOURCE_FOR_IIDM_ID_MRID)) {
options.setRemoveInitialUnderscoreForIdentifiers(true);
} else if (sourceForIidmIds.equalsIgnoreCase(SOURCE_FOR_IIDM_ID_RDFID)) {
options.setRemoveInitialUnderscoreForIdentifiers(false);
}
options.decodeEscapedIdentifiers(Parameter.readBoolean(getFormat(), p, DECODE_ESCAPED_IDENTIFIERS_PARAMETER, defaultValueConfig));
Reporter tripleStoreReporter = reporter.createSubReporter("CGMESTriplestore", "Reading CGMES Triplestore");
return CgmesModelFactory.create(ds, boundary(p), tripleStore(p), tripleStoreReporter, options);
}
@Override
public void copy(ReadOnlyDataSource from, DataSource to) {
Objects.requireNonNull(from);
Objects.requireNonNull(to);
try {
CgmesOnDataSource fromCgmes = new CgmesOnDataSource(from);
for (String name : fromCgmes.names()) {
copyStream(from, to, name, name);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private ReadOnlyDataSource boundary(Properties p) {
String location = Parameter.readString(
getFormat(),
p,
boundaryLocationParameter,
defaultValueConfig);
if (location == null) {
return null;
}
Path path = boundaryPath(location);
if (path == null) {
return null;
}
// Check that the Data Source has valid CGMES names
ReadOnlyDataSource ds = new GenericReadOnlyDataSource(path);
if ((new CgmesOnDataSource(ds)).names().isEmpty()) {
return null;
}
return ds;
}
Path boundaryPath(String location) {
Path path = null;
// Check first if the location is present in the file system defined from the platform configuration
Optional configDir = this.platformConfig.getConfigDir();
if (configDir.isPresent()) {
FileSystem configFileSystem = configDir.get().getFileSystem();
if (configFileSystem != FileSystems.getDefault()) {
path = configFileSystem.getPath(location);
if (!Files.exists(path)) {
LOGGER.warn("Location of boundaries ({}) not found in config file system. An attempt to load boundaries from the default file system will be made", location);
path = null;
}
}
}
if (path == null) {
path = Path.of(location);
if (!Files.exists(path)) {
LOGGER.warn("Location of boundaries ({}) not found in default file system. No attempt to load boundaries will be made", location);
}
}
return path;
}
private String tripleStore(Properties p) {
return Parameter.readString(
getFormat(),
p,
POWSYBL_TRIPLESTORE_PARAMETER,
defaultValueConfig);
}
private Conversion.Config config(Properties p) {
Conversion.Config config = new Conversion.Config()
.setAllowUnsupportedTapChangers(
Parameter.readBoolean(
getFormat(),
p,
ALLOW_UNSUPPORTED_TAP_CHANGERS_PARAMETER,
defaultValueConfig))
.setChangeSignForShuntReactivePowerFlowInitialState(
Parameter.readBoolean(
getFormat(),
p,
CHANGE_SIGN_FOR_SHUNT_REACTIVE_POWER_FLOW_INITIAL_STATE_PARAMETER,
defaultValueConfig))
.setConvertBoundary(
Parameter.readBoolean(
getFormat(),
p,
CONVERT_BOUNDARY_PARAMETER,
defaultValueConfig))
.setConvertSvInjections(
Parameter.readBoolean(
getFormat(),
p,
CONVERT_SV_INJECTIONS_PARAMETER,
defaultValueConfig))
.setCreateBusbarSectionForEveryConnectivityNode(
Parameter.readBoolean(
getFormat(),
p,
CREATE_BUSBAR_SECTION_FOR_EVERY_CONNECTIVITY_NODE_PARAMETER,
defaultValueConfig))
.setEnsureIdAliasUnicity(
Parameter.readBoolean(
getFormat(),
p,
ENSURE_ID_ALIAS_UNICITY_PARAMETER,
defaultValueConfig))
.setImportControlAreas(
Parameter.readBoolean(
getFormat(),
p,
IMPORT_CONTROL_AREAS_PARAMETER,
defaultValueConfig))
.setProfileForInitialValuesShuntSectionsTapPositions(
Parameter.readString(
getFormat(),
p,
PROFILE_FOR_INITIAL_VALUES_SHUNT_SECTIONS_TAP_POSITIONS_PARAMETER,
defaultValueConfig))
.setStoreCgmesModelAsNetworkExtension(
Parameter.readBoolean(
getFormat(),
p,
STORE_CGMES_MODEL_AS_NETWORK_EXTENSION_PARAMETER,
defaultValueConfig))
.setStoreCgmesConversionContextAsNetworkExtension(
Parameter.readBoolean(
getFormat(),
p,
STORE_CGMES_CONVERSION_CONTEXT_AS_NETWORK_EXTENSION_PARAMETER,
defaultValueConfig))
.setCreateActivePowerControlExtension(
Parameter.readBoolean(
getFormat(),
p,
CREATE_ACTIVE_POWER_CONTROL_EXTENSION_PARAMETER,
defaultValueConfig))
.createFictitiousSwitchesForDisconnectedTerminalsMode(FictitiousSwitchesCreationMode.valueOf(
Parameter.readString(
getFormat(),
p,
CREATE_FICTITIOUS_SWITCHES_FOR_DISCONNECTED_TERMINALS_MODE_PARAMETER,
defaultValueConfig)))
.setImportNodeBreakerAsBusBreaker(
Parameter.readBoolean(
getFormat(),
p,
IMPORT_NODE_BREAKER_AS_BUS_BREAKER_PARAMETER,
defaultValueConfig))
.setDisconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected(
Parameter.readBoolean(
getFormat(),
p,
DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED_PARAMETER,
defaultValueConfig))
.setMissingPermanentLimitPercentage(
Parameter.readDouble(
getFormat(),
p,
MISSING_PERMANENT_LIMIT_PERCENTAGE_PARAMETER,
defaultValueConfig));
String namingStrategy = Parameter.readString(getFormat(), p, NAMING_STRATEGY_PARAMETER, defaultValueConfig);
// Build the naming strategy with the default uuid namespace for creating name-based uuids
// In fact, when using a naming strategy for CGMES import we should not need an uuid namespace,
// because we won't be creating new UUIDs
UUID uuidNamespace = CgmesExportContext.DEFAULT_UUID_NAMESPACE;
config.setNamingStrategy(NamingStrategyFactory.create(namingStrategy, uuidNamespace));
return config;
}
private List activatedPreProcessors(Properties p) {
return Parameter
.readStringList(getFormat(), p, preProcessorsParameter, defaultValueConfig)
.stream()
.filter(name -> {
boolean found = preProcessors.containsKey(name);
if (!found) {
LOGGER.warn("CGMES pre processor {} not found", name);
}
return found;
})
.map(preProcessors::get)
.collect(Collectors.toList());
}
private List activatedPostProcessors(Properties p) {
return Parameter
.readStringList(getFormat(), p, postProcessorsParameter, defaultValueConfig)
.stream()
.filter(name -> {
boolean found = postProcessors.containsKey(name);
if (!found) {
LOGGER.warn("CGMES post processor {} not found", name);
}
return found;
})
.map(postProcessors::get)
.collect(Collectors.toList());
}
private void copyStream(ReadOnlyDataSource from, DataSource to, String fromName, String toName) throws IOException {
if (from.exists(fromName)) {
try (InputStream is = from.newInputStream(fromName);
OutputStream os = to.newOutputStream(toName, false)) {
ByteStreams.copy(is, os);
}
}
}
private static final String FORMAT = "CGMES";
public static final String ALLOW_UNSUPPORTED_TAP_CHANGERS = "iidm.import.cgmes.allow-unsupported-tap-changers";
public static final String BOUNDARY_LOCATION = "iidm.import.cgmes.boundary-location";
public static final String CHANGE_SIGN_FOR_SHUNT_REACTIVE_POWER_FLOW_INITIAL_STATE = "iidm.import.cgmes.change-sign-for-shunt-reactive-power-flow-initial-state";
public static final String CONVERT_BOUNDARY = "iidm.import.cgmes.convert-boundary";
public static final String CONVERT_SV_INJECTIONS = "iidm.import.cgmes.convert-sv-injections";
public static final String CREATE_ACTIVE_POWER_CONTROL_EXTENSION = "iidm.import.cgmes.create-active-power-control-extension";
public static final String CREATE_BUSBAR_SECTION_FOR_EVERY_CONNECTIVITY_NODE = "iidm.import.cgmes.create-busbar-section-for-every-connectivity-node";
public static final String CREATE_FICTITIOUS_SWITCHES_FOR_DISCONNECTED_TERMINALS_MODE = "iidm.import.cgmes.create-fictitious-switches-for-disconnected-terminals-mode";
public static final String DECODE_ESCAPED_IDENTIFIERS = "iidm.import.cgmes.decode-escaped-identifiers";
public static final String ENSURE_ID_ALIAS_UNICITY = "iidm.import.cgmes.ensure-id-alias-unicity";
public static final String IMPORT_CONTROL_AREAS = "iidm.import.cgmes.import-control-areas";
public static final String NAMING_STRATEGY = "iidm.import.cgmes.naming-strategy";
public static final String PRE_PROCESSORS = "iidm.import.cgmes.pre-processors";
public static final String POST_PROCESSORS = "iidm.import.cgmes.post-processors";
public static final String POWSYBL_TRIPLESTORE = "iidm.import.cgmes.powsybl-triplestore";
public static final String PROFILE_FOR_INITIAL_VALUES_SHUNT_SECTIONS_TAP_POSITIONS = "iidm.import.cgmes.profile-for-initial-values-shunt-sections-tap-positions";
public static final String SOURCE_FOR_IIDM_ID = "iidm.import.cgmes.source-for-iidm-id";
public static final String STORE_CGMES_MODEL_AS_NETWORK_EXTENSION = "iidm.import.cgmes.store-cgmes-model-as-network-extension";
public static final String STORE_CGMES_CONVERSION_CONTEXT_AS_NETWORK_EXTENSION = "iidm.import.cgmes.store-cgmes-conversion-context-as-network-extension";
public static final String IMPORT_NODE_BREAKER_AS_BUS_BREAKER = "iidm.import.cgmes.import-node-breaker-as-bus-breaker";
public static final String DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED = "iidm.import.cgmes.disconnect-dangling-line-if-boundary-side-is-disconnected";
public static final String MISSING_PERMANENT_LIMIT_PERCENTAGE = "iidm.import.cgmes.missing-permanent-limit-percentage";
public static final String IMPORT_CGM_WITH_SUBNETWORKS = "iidm.import.cgmes.cgm-with-subnetworks";
public static final String IMPORT_CGM_WITH_SUBNETWORKS_DEFINED_BY = "iidm.import.cgmes.cgm-with-subnetworks-defined-by";
public static final String SOURCE_FOR_IIDM_ID_MRID = "mRID";
public static final String SOURCE_FOR_IIDM_ID_RDFID = "rdfID";
private static final Parameter ALLOW_UNSUPPORTED_TAP_CHANGERS_PARAMETER = new Parameter(
ALLOW_UNSUPPORTED_TAP_CHANGERS,
ParameterType.BOOLEAN,
"Allow import of potentially unsupported tap changers",
Boolean.TRUE);
private static final Parameter CHANGE_SIGN_FOR_SHUNT_REACTIVE_POWER_FLOW_INITIAL_STATE_PARAMETER = new Parameter(
CHANGE_SIGN_FOR_SHUNT_REACTIVE_POWER_FLOW_INITIAL_STATE,
ParameterType.BOOLEAN,
"Change the sign of the reactive power flow for shunt in initial state",
Boolean.FALSE)
.addAdditionalNames("changeSignForShuntReactivePowerFlowInitialState");
private static final Parameter CONVERT_BOUNDARY_PARAMETER = new Parameter(
CONVERT_BOUNDARY,
ParameterType.BOOLEAN,
"Convert boundary during import",
Boolean.FALSE)
.addAdditionalNames("convertBoundary");
private static final Parameter CONVERT_SV_INJECTIONS_PARAMETER = new Parameter(
CONVERT_SV_INJECTIONS,
ParameterType.BOOLEAN,
"Convert SV injections during import",
Boolean.TRUE);
private static final Parameter CREATE_BUSBAR_SECTION_FOR_EVERY_CONNECTIVITY_NODE_PARAMETER = new Parameter(
CREATE_BUSBAR_SECTION_FOR_EVERY_CONNECTIVITY_NODE,
ParameterType.BOOLEAN,
"Create busbar section for every connectivity node",
Boolean.FALSE)
.addAdditionalNames("createBusbarSectionForEveryConnectivityNode");
private static final Parameter ENSURE_ID_ALIAS_UNICITY_PARAMETER = new Parameter(
ENSURE_ID_ALIAS_UNICITY,
ParameterType.BOOLEAN,
"Ensure IDs and aliases are unique",
Boolean.FALSE);
private static final Parameter NAMING_STRATEGY_PARAMETER = new Parameter(
NAMING_STRATEGY,
ParameterType.STRING,
"Configure what type of naming strategy you want to use",
NamingStrategyFactory.IDENTITY,
new ArrayList<>(NamingStrategyFactory.LIST));
private static final Parameter IMPORT_CONTROL_AREAS_PARAMETER = new Parameter(
IMPORT_CONTROL_AREAS,
ParameterType.BOOLEAN,
"Import control areas",
Boolean.TRUE);
private static final Parameter POWSYBL_TRIPLESTORE_PARAMETER = new Parameter(
POWSYBL_TRIPLESTORE,
ParameterType.STRING,
"The triplestore used during the import",
TripleStoreFactory.defaultImplementation(),
null,
ParameterScope.TECHNICAL)
.addAdditionalNames("powsyblTripleStore");
private static final Parameter PROFILE_FOR_INITIAL_VALUES_SHUNT_SECTIONS_TAP_POSITIONS_PARAMETER = new Parameter(
PROFILE_FOR_INITIAL_VALUES_SHUNT_SECTIONS_TAP_POSITIONS,
ParameterType.STRING,
"Profile used for initial state values",
"SSH",
List.of("SSH", "SV"))
.addAdditionalNames("iidm.import.cgmes.profile-used-for-initial-state-values");
private static final Parameter STORE_CGMES_CONVERSION_CONTEXT_AS_NETWORK_EXTENSION_PARAMETER = new Parameter(
STORE_CGMES_CONVERSION_CONTEXT_AS_NETWORK_EXTENSION,
ParameterType.BOOLEAN,
"Store the CGMES-IIDM terminal mapping as a network extension",
Boolean.FALSE);
private static final Parameter CREATE_ACTIVE_POWER_CONTROL_EXTENSION_PARAMETER = new Parameter(
CREATE_ACTIVE_POWER_CONTROL_EXTENSION,
ParameterType.BOOLEAN,
"Create active power control extension during import",
Boolean.FALSE);
private static final Parameter CREATE_FICTITIOUS_SWITCHES_FOR_DISCONNECTED_TERMINALS_MODE_PARAMETER = new Parameter(
CREATE_FICTITIOUS_SWITCHES_FOR_DISCONNECTED_TERMINALS_MODE,
ParameterType.STRING,
"Defines in which case fictitious switches for disconnected terminals are created (relevant for node-breaker models only): always, always except for switches or never",
FictitiousSwitchesCreationMode.ALWAYS.name(),
Arrays.stream(FictitiousSwitchesCreationMode.values()).map(Enum::name).collect(Collectors.toList()));
private static final Parameter STORE_CGMES_MODEL_AS_NETWORK_EXTENSION_PARAMETER = new Parameter(
STORE_CGMES_MODEL_AS_NETWORK_EXTENSION,
ParameterType.BOOLEAN,
"Store the initial CGMES model as a network extension",
Boolean.TRUE)
.addAdditionalNames("storeCgmesModelAsNetworkExtension");
private static final Parameter SOURCE_FOR_IIDM_ID_PARAMETER = new Parameter(
SOURCE_FOR_IIDM_ID,
ParameterType.STRING,
"Source for IIDM identifiers",
SOURCE_FOR_IIDM_ID_MRID,
List.of(SOURCE_FOR_IIDM_ID_MRID, SOURCE_FOR_IIDM_ID_RDFID));
private static final Parameter DECODE_ESCAPED_IDENTIFIERS_PARAMETER = new Parameter(
DECODE_ESCAPED_IDENTIFIERS,
ParameterType.BOOLEAN,
"Decode escaped special characters in IDs",
Boolean.TRUE);
public static final Parameter IMPORT_NODE_BREAKER_AS_BUS_BREAKER_PARAMETER = new Parameter(
IMPORT_NODE_BREAKER_AS_BUS_BREAKER,
ParameterType.BOOLEAN,
"Force import of CGMES node/breaker models as bus/breaker",
Boolean.FALSE);
public static final Parameter DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED_PARAMETER = new Parameter(
DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED,
ParameterType.BOOLEAN,
"Force disconnection of dangling line network side if boundary side is disconnected",
Boolean.TRUE);
private static final Parameter IMPORT_CGM_WITH_SUBNETWORKS_PARAMETER = new Parameter(
IMPORT_CGM_WITH_SUBNETWORKS,
ParameterType.BOOLEAN,
"Import CGM with subnetworks",
Boolean.TRUE);
private static final Parameter IMPORT_CGM_WITH_SUBNETWORKS_DEFINED_BY_PARAMETER = new Parameter(
IMPORT_CGM_WITH_SUBNETWORKS_DEFINED_BY,
ParameterType.STRING,
"Choose how subnetworks from CGM must be imported: defined by filenames or by modeling authority",
SubnetworkDefinedBy.MODELING_AUTHORITY.name(),
Arrays.stream(SubnetworkDefinedBy.values()).map(Enum::name).collect(Collectors.toList()));
public static final Parameter MISSING_PERMANENT_LIMIT_PERCENTAGE_PARAMETER = new Parameter(
MISSING_PERMANENT_LIMIT_PERCENTAGE,
ParameterType.DOUBLE,
"Percentage applied to lowest TATL limit to use as PATL when PATL is missing",
100.);
private static final List STATIC_PARAMETERS = List.of(
ALLOW_UNSUPPORTED_TAP_CHANGERS_PARAMETER,
CHANGE_SIGN_FOR_SHUNT_REACTIVE_POWER_FLOW_INITIAL_STATE_PARAMETER,
CONVERT_BOUNDARY_PARAMETER,
CONVERT_SV_INJECTIONS_PARAMETER,
CREATE_BUSBAR_SECTION_FOR_EVERY_CONNECTIVITY_NODE_PARAMETER,
ENSURE_ID_ALIAS_UNICITY_PARAMETER,
NAMING_STRATEGY_PARAMETER,
IMPORT_CONTROL_AREAS_PARAMETER,
POWSYBL_TRIPLESTORE_PARAMETER,
PROFILE_FOR_INITIAL_VALUES_SHUNT_SECTIONS_TAP_POSITIONS_PARAMETER,
SOURCE_FOR_IIDM_ID_PARAMETER,
STORE_CGMES_CONVERSION_CONTEXT_AS_NETWORK_EXTENSION_PARAMETER,
STORE_CGMES_MODEL_AS_NETWORK_EXTENSION_PARAMETER,
CREATE_ACTIVE_POWER_CONTROL_EXTENSION_PARAMETER,
DECODE_ESCAPED_IDENTIFIERS_PARAMETER,
CREATE_FICTITIOUS_SWITCHES_FOR_DISCONNECTED_TERMINALS_MODE_PARAMETER,
IMPORT_NODE_BREAKER_AS_BUS_BREAKER_PARAMETER,
DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED_PARAMETER,
IMPORT_CGM_WITH_SUBNETWORKS_PARAMETER,
IMPORT_CGM_WITH_SUBNETWORKS_DEFINED_BY_PARAMETER,
MISSING_PERMANENT_LIMIT_PERCENTAGE_PARAMETER);
private final Parameter boundaryLocationParameter;
private final Parameter preProcessorsParameter;
private final Parameter postProcessorsParameter;
private final Map postProcessors;
private final Map preProcessors;
private final ParameterDefaultValueConfig defaultValueConfig;
private final PlatformConfig platformConfig;
private static final Logger LOGGER = LoggerFactory.getLogger(CgmesImport.class);
// TODO Allow this property to be configurable
// Parameters of importers are only passed to importData method,
// but to decide if we are importers also for CIM 14 files
// we must implement the exists method, that has not access to parameters
private boolean importCim14 = false;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy