-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* inter-tempoal RAO API Signed-off-by: Thomas Bouquet <[email protected]> * move to right module Signed-off-by: Thomas Bouquet <[email protected]> * fix InterTemporalRaoInput creation Signed-off-by: Godelaine de Montmorillon <[email protected]> --------- Signed-off-by: Thomas Bouquet <[email protected]> Signed-off-by: Godelaine de Montmorillon <[email protected]> Co-authored-by: Godelaine <[email protected]> Co-authored-by: Godelaine de Montmorillon <[email protected]>
- Loading branch information
1 parent
da19936
commit f23fd92
Showing
6 changed files
with
400 additions
and
1 deletion.
There are no files selected for viewing
148 changes: 148 additions & 0 deletions
148
ra-optimisation/rao-api/src/main/java/com/powsybl/openrao/raoapi/InterTemporalRao.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
/* | ||
* 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/. | ||
*/ | ||
|
||
package com.powsybl.openrao.raoapi; | ||
|
||
import com.google.common.base.Supplier; | ||
import com.google.common.base.Suppliers; | ||
import com.powsybl.commons.Versionable; | ||
import com.powsybl.commons.config.PlatformConfig; | ||
import com.powsybl.commons.util.ServiceLoaderCache; | ||
import com.powsybl.openrao.commons.OpenRaoException; | ||
import com.powsybl.openrao.commons.TemporalData; | ||
import com.powsybl.openrao.data.raoresult.api.RaoResult; | ||
import com.powsybl.openrao.raoapi.parameters.RaoParameters; | ||
import com.powsybl.tools.Version; | ||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.ServiceLoader; | ||
|
||
import static com.powsybl.openrao.commons.logs.OpenRaoLoggerProvider.BUSINESS_WARNS; | ||
|
||
/** | ||
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>} | ||
*/ | ||
public final class InterTemporalRao { | ||
private InterTemporalRao() { | ||
throw new AssertionError("Utility class should not been instantiated"); | ||
} | ||
|
||
private static final Supplier<List<InterTemporalRaoProvider>> RAO_PROVIDERS | ||
= Suppliers.memoize(() -> new ServiceLoaderCache<>(InterTemporalRaoProvider.class).getServices()); | ||
|
||
/** | ||
* An inter-temporal RA optimisation runner is responsible for providing convenient methods on top of | ||
* {@link InterTemporalRaoProvider}: several variants of synchronous and asynchronous run with default parameters. | ||
*/ | ||
public static class Runner implements Versionable { | ||
|
||
private final InterTemporalRaoProvider provider; | ||
|
||
public Runner(InterTemporalRaoProvider provider) { | ||
this.provider = Objects.requireNonNull(provider); | ||
} | ||
|
||
public TemporalData<RaoResult> run(InterTemporalRaoInput raoInput, RaoParameters parameters) { | ||
Objects.requireNonNull(raoInput, "RAO input should not be null"); | ||
Objects.requireNonNull(parameters, "parameters should not be null"); | ||
|
||
Version openRaoVersion = ServiceLoader.load(Version.class).findFirst().orElseThrow(); | ||
BUSINESS_WARNS.warn("Running RAO using Open RAO version {} from git commit {}.", openRaoVersion.getMavenProjectVersion(), openRaoVersion.getGitVersion()); | ||
|
||
return provider.run(raoInput, parameters).join(); | ||
} | ||
|
||
public TemporalData<RaoResult> run(InterTemporalRaoInput raoInput) { | ||
return run(raoInput, RaoParameters.load()); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return provider.getName(); | ||
} | ||
|
||
@Override | ||
public String getVersion() { | ||
return provider.getVersion(); | ||
} | ||
} | ||
|
||
/** | ||
* Get a runner for an inter-temporal RAO named {@code name}. In the case of a null {@code name}, default | ||
* implementation is used. | ||
* | ||
* @param name name of the RAO implementation, null if we want to use default one | ||
* @return a runner for RAO implementation named {@code name} | ||
*/ | ||
public static InterTemporalRao.Runner find(String name) { | ||
return find(name, RAO_PROVIDERS.get(), PlatformConfig.defaultConfig()); | ||
} | ||
|
||
/** | ||
* Get a runner for default inter-temporal RAO implementation. | ||
* | ||
* @throws OpenRaoException in case we cannot find a default implementation | ||
* @return a runner for default RAO implementation | ||
*/ | ||
public static InterTemporalRao.Runner find() { | ||
return find(null); | ||
} | ||
|
||
/** | ||
* A variant of {@link Rao#find(String)} intended to be used for unit testing that allow passing | ||
* an explicit provider list instead of relying on service loader and an explicit {@link PlatformConfig} | ||
* instead of global one. | ||
* | ||
* @param name name of the RAO implementation, null if we want to use default one | ||
* @param providers flowbased provider list | ||
* @param platformConfig platform config to look for default flowbased implementation name | ||
* @return a runner for flowbased implementation named {@code name} | ||
*/ | ||
public static InterTemporalRao.Runner find(String name, List<InterTemporalRaoProvider> providers, PlatformConfig platformConfig) { | ||
Objects.requireNonNull(providers); | ||
Objects.requireNonNull(platformConfig); | ||
|
||
if (providers.isEmpty()) { | ||
throw new OpenRaoException("No inter-temporal RAO providers found"); | ||
} | ||
|
||
// if no RAO implementation name is provided through the API we look for information | ||
// in platform configuration | ||
String raOptimizerName = name != null ? name : platformConfig.getOptionalModuleConfig("rao") | ||
.flatMap(mc -> mc.getOptionalStringProperty("default")) | ||
.orElse(null); | ||
InterTemporalRaoProvider provider; | ||
if (providers.size() == 1 && raOptimizerName == null) { | ||
// no information to select the implementation but only one provider, so we can use it by default | ||
// (that is the most common use case) | ||
provider = providers.get(0); | ||
} else { | ||
if (providers.size() > 1 && raOptimizerName == null) { | ||
// several providers and no information to select which one to choose, we can only throw | ||
// an exception | ||
List<String> raOptimizerNames = providers.stream().map(InterTemporalRaoProvider::getName).toList(); | ||
throw new OpenRaoException("Several RAO implementations found (" + raOptimizerNames | ||
+ "), you must add configuration to select the implementation"); | ||
} | ||
provider = providers.stream() | ||
.filter(p -> p.getName().equals(raOptimizerName)) | ||
.findFirst() | ||
.orElseThrow(() -> new OpenRaoException("RA optimizer provider '" + raOptimizerName + "' not found")); | ||
} | ||
|
||
return new InterTemporalRao.Runner(provider); | ||
} | ||
|
||
public static TemporalData<RaoResult> run(InterTemporalRaoInput raoInput, RaoParameters parameters) { | ||
return find().run(raoInput, parameters); | ||
} | ||
|
||
public static TemporalData<RaoResult> run(InterTemporalRaoInput raoInput) { | ||
return find().run(raoInput); | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
...timisation/rao-api/src/main/java/com/powsybl/openrao/raoapi/InterTemporalRaoProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* 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/. | ||
*/ | ||
|
||
package com.powsybl.openrao.raoapi; | ||
|
||
import com.powsybl.commons.Versionable; | ||
import com.powsybl.openrao.commons.TemporalData; | ||
import com.powsybl.openrao.data.raoresult.api.RaoResult; | ||
import com.powsybl.openrao.raoapi.parameters.RaoParameters; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
|
||
/** | ||
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>} | ||
*/ | ||
public interface InterTemporalRaoProvider extends Versionable { | ||
|
||
/** | ||
* @param raoInput: Data to optimize. Contains Cracs and Networks for each timestamp and gradient constraints | ||
* @param parameters: RAO parameters. | ||
* @return A completable future of a RaoComputationResult for each timestamp. | ||
*/ | ||
CompletableFuture<TemporalData<RaoResult>> run(InterTemporalRaoInput raoInput, RaoParameters parameters); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
ra-optimisation/rao-api/src/test/java/com/powsybl/openrao/raoapi/InterTemporalRaoTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* | ||
* 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/. | ||
*/ | ||
|
||
package com.powsybl.openrao.raoapi; | ||
|
||
import com.google.common.jimfs.Configuration; | ||
import com.google.common.jimfs.Jimfs; | ||
import com.powsybl.commons.config.InMemoryPlatformConfig; | ||
import com.powsybl.iidm.network.Network; | ||
import com.powsybl.iidm.network.VariantManager; | ||
import com.powsybl.openrao.commons.OpenRaoException; | ||
import com.powsybl.openrao.commons.TemporalData; | ||
import com.powsybl.openrao.commons.TemporalDataImpl; | ||
import com.powsybl.openrao.data.crac.api.Crac; | ||
import com.powsybl.openrao.data.raoresult.api.ComputationStatus; | ||
import com.powsybl.openrao.data.raoresult.api.RaoResult; | ||
import com.powsybl.openrao.raoapi.parameters.RaoParameters; | ||
import com.powsybl.openrao.raoapi.raomock.AnotherInterTemporalRaoProviderMock; | ||
import com.powsybl.openrao.raoapi.raomock.InterTemporalRaoProviderMock; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.mockito.Mockito; | ||
|
||
import java.nio.file.FileSystem; | ||
import java.time.OffsetDateTime; | ||
import java.time.ZoneOffset; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
/** | ||
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>} | ||
*/ | ||
class InterTemporalRaoTest { | ||
|
||
private FileSystem fileSystem; | ||
private InMemoryPlatformConfig platformConfig; | ||
private InterTemporalRaoInput raoInput; | ||
|
||
@BeforeEach | ||
public void setUp() { | ||
fileSystem = Jimfs.newFileSystem(Configuration.unix()); | ||
platformConfig = new InMemoryPlatformConfig(fileSystem); | ||
Network network = Mockito.mock(Network.class); | ||
Crac crac = Mockito.mock(Crac.class); | ||
VariantManager variantManager = Mockito.mock(VariantManager.class); | ||
Mockito.when(network.getVariantManager()).thenReturn(variantManager); | ||
Mockito.when(variantManager.getWorkingVariantId()).thenReturn("v"); | ||
raoInput = new InterTemporalRaoInput(new TemporalDataImpl<>(Map.of(OffsetDateTime.of(2024, 12, 13, 16, 17, 0, 0, ZoneOffset.UTC), RaoInput.build(network, crac).build())), new HashSet<>()); | ||
} | ||
|
||
@AfterEach | ||
public void tearDown() throws Exception { | ||
fileSystem.close(); | ||
} | ||
|
||
@Test | ||
void testDefaultOneProvider() { | ||
// case with only one provider, no need for config | ||
// find rao | ||
InterTemporalRao.Runner defaultRao = InterTemporalRao.find(null, List.of(new InterTemporalRaoProviderMock()), platformConfig); | ||
assertEquals("RandomInterTemporalRAO", defaultRao.getName()); | ||
assertEquals("1.0", defaultRao.getVersion()); | ||
|
||
// run rao | ||
OffsetDateTime timestamp = OffsetDateTime.of(2024, 12, 13, 16, 17, 0, 0, ZoneOffset.UTC); | ||
TemporalData<RaoResult> result = defaultRao.run(raoInput, new RaoParameters()); | ||
assertNotNull(result); | ||
assertEquals(List.of(timestamp), result.getTimestamps()); | ||
assertTrue(result.getData(timestamp).isPresent()); | ||
assertEquals(ComputationStatus.DEFAULT, result.getData(timestamp).get().getComputationStatus()); | ||
} | ||
|
||
@Test | ||
void testDefaultTwoProviders() { | ||
// case with two providers : should throw as no config defines which provider must be selected | ||
List<InterTemporalRaoProvider> raoProviders = List.of(new InterTemporalRaoProviderMock(), new AnotherInterTemporalRaoProviderMock()); | ||
assertThrows(OpenRaoException.class, () -> InterTemporalRao.find(null, raoProviders, platformConfig)); | ||
} | ||
|
||
@Test | ||
void testDefinedAmongTwoProviders() { | ||
// case with two providers where one the two RAOs is specifically selected | ||
InterTemporalRao.Runner definedRao = InterTemporalRao.find("GlobalRAOptimizer", List.of(new InterTemporalRaoProviderMock(), new AnotherInterTemporalRaoProviderMock()), platformConfig); | ||
assertEquals("GlobalRAOptimizer", definedRao.getName()); | ||
assertEquals("2.3", definedRao.getVersion()); | ||
} | ||
|
||
@Test | ||
void testDefaultNoProvider() { | ||
// case with no provider | ||
List<InterTemporalRaoProvider> raoProviders = List.of(); | ||
assertThrows(OpenRaoException.class, () -> InterTemporalRao.find(null, raoProviders, platformConfig)); | ||
} | ||
|
||
@Test | ||
void testDefaultTwoProvidersPlatformConfig() { | ||
// case with 2 providers without any config but specifying which one to use in platform config | ||
platformConfig.createModuleConfig("rao").setStringProperty("default", "GlobalRAOptimizer"); | ||
InterTemporalRao.Runner globalRaOptimizer = InterTemporalRao.find(null, List.of(new InterTemporalRaoProviderMock(), new AnotherInterTemporalRaoProviderMock()), platformConfig); | ||
assertEquals("GlobalRAOptimizer", globalRaOptimizer.getName()); | ||
assertEquals("2.3", globalRaOptimizer.getVersion()); | ||
} | ||
|
||
@Test | ||
void testOneProviderAndMistakeInPlatformConfig() { | ||
// case with 1 provider with config but with a name that is not the one of provider. | ||
platformConfig.createModuleConfig("rao").setStringProperty("default", "UnknownRao"); | ||
List<InterTemporalRaoProvider> raoProviders = List.of(new InterTemporalRaoProviderMock()); | ||
assertThrows(OpenRaoException.class, () -> InterTemporalRao.find(null, raoProviders, platformConfig)); | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
...src/test/java/com/powsybl/openrao/raoapi/raomock/AnotherInterTemporalRaoProviderMock.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* 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/. | ||
*/ | ||
|
||
package com.powsybl.openrao.raoapi.raomock; | ||
|
||
import com.google.auto.service.AutoService; | ||
import com.powsybl.openrao.commons.TemporalData; | ||
import com.powsybl.openrao.commons.TemporalDataImpl; | ||
import com.powsybl.openrao.data.raoresult.api.ComputationStatus; | ||
import com.powsybl.openrao.data.raoresult.api.RaoResult; | ||
import com.powsybl.openrao.data.raoresult.impl.RaoResultImpl; | ||
import com.powsybl.openrao.raoapi.InterTemporalRaoInput; | ||
import com.powsybl.openrao.raoapi.InterTemporalRaoProvider; | ||
import com.powsybl.openrao.raoapi.parameters.RaoParameters; | ||
|
||
import java.time.OffsetDateTime; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.concurrent.CompletableFuture; | ||
|
||
/** | ||
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>} | ||
*/ | ||
@AutoService(InterTemporalRaoProvider.class) | ||
public class AnotherInterTemporalRaoProviderMock implements InterTemporalRaoProvider { | ||
@Override | ||
public CompletableFuture<TemporalData<RaoResult>> run(InterTemporalRaoInput raoInput, RaoParameters parameters) { | ||
Map<OffsetDateTime, RaoResult> raoResultPerTimestamp = new HashMap<>(); | ||
for (OffsetDateTime timestamp : raoInput.getTimestampsToRun()) { | ||
RaoResultImpl raoResult = new RaoResultImpl(raoInput.getRaoInputs().getData(timestamp).orElseThrow().getCrac()); | ||
raoResult.setComputationStatus(ComputationStatus.FAILURE); | ||
raoResultPerTimestamp.put(timestamp, raoResult); | ||
} | ||
return CompletableFuture.completedFuture(new TemporalDataImpl<>(raoResultPerTimestamp)); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return "GlobalRAOptimizer"; | ||
} | ||
|
||
@Override | ||
public String getVersion() { | ||
return "2.3"; | ||
} | ||
} |
Oops, something went wrong.