Skip to content

Commit c6319d1

Browse files
committed
Create NcProfileWriter interface
Signed-off-by: Thomas Bouquet <thomas.bouquet@rte-france.com>
1 parent 42d5dd7 commit c6319d1

4 files changed

Lines changed: 210 additions & 163 deletions

File tree

data/result-exporter/nc-exporter/src/main/java/com/powsybl/openrao/data/raoresult/nc/NcExporter.java

Lines changed: 3 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
11
package com.powsybl.openrao.data.raoresult.nc;
22

33
import com.google.auto.service.AutoService;
4-
import com.powsybl.action.Action;
5-
import com.powsybl.action.GeneratorAction;
6-
import com.powsybl.action.LoadAction;
7-
import com.powsybl.action.PhaseTapChangerTapPositionAction;
8-
import com.powsybl.action.ShuntCompensatorPositionAction;
9-
import com.powsybl.action.SwitchAction;
104
import com.powsybl.openrao.commons.OpenRaoException;
115
import com.powsybl.openrao.data.cracapi.Crac;
126
import com.powsybl.openrao.data.cracapi.CracCreationContext;
13-
import com.powsybl.openrao.data.cracapi.Instant;
14-
import com.powsybl.openrao.data.cracapi.RemedialAction;
15-
import com.powsybl.openrao.data.cracapi.State;
16-
import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction;
17-
import com.powsybl.openrao.data.cracapi.rangeaction.PstRangeAction;
18-
import com.powsybl.openrao.data.cracapi.rangeaction.RangeAction;
197
import com.powsybl.openrao.data.cracio.csaprofiles.craccreator.CsaProfileCracCreationContext;
208
import com.powsybl.openrao.data.raoresultapi.RaoResult;
219
import com.powsybl.openrao.data.raoresultapi.io.Exporter;
@@ -33,13 +21,10 @@
3321
import javax.xml.transform.dom.DOMSource;
3422
import javax.xml.transform.stream.StreamResult;
3523
import java.io.OutputStream;
36-
import java.nio.charset.StandardCharsets;
3724
import java.time.OffsetDateTime;
3825
import java.time.format.DateTimeFormatter;
3926
import java.util.Arrays;
40-
import java.util.Map;
4127
import java.util.Properties;
42-
import java.util.UUID;
4328

4429
@AutoService(Exporter.class)
4530
public class NcExporter implements Exporter {
@@ -55,9 +40,10 @@ public void exportData(RaoResult raoResult, CracCreationContext cracCreationCont
5540
OffsetDateTime timeStamp = ncCracCreationContext.getTimeStamp();
5641

5742
Element rootRdfElement = createRootRdfElement(document);
58-
rootRdfElement.appendChild(writeProfileHeader(document, timeStamp));
43+
Element header = writeProfileHeader(document, timeStamp);
44+
rootRdfElement.appendChild(header);
5945

60-
writeRemedialActionScheduleProfileContent(raoResult, ncCracCreationContext, document, timeStamp, rootRdfElement, ncCracCreationContext.getInstantApplicationTimeMap());
46+
new RemedialActionScheduleProfileExporter().addWholeProfile(document, rootRdfElement, header, raoResult, ncCracCreationContext);
6147

6248
writeOutputXmlFile(document, outputStream);
6349
} else {
@@ -103,154 +89,9 @@ private static Element writeProfileHeader(Document document, OffsetDateTime time
10389
endDate.setTextContent(formatOffsetDateTime(timeStamp.plusHours(1)));
10490
header.appendChild(endDate);
10591

106-
Element keyword = document.createElement("dcat:keyword");
107-
keyword.setTextContent("RAS");
108-
header.appendChild(keyword);
109-
11092
return header;
11193
}
11294

113-
private static void writeRemedialActionScheduleProfileContent(RaoResult raoResult, CsaProfileCracCreationContext ncCracCreationContext, Document document, OffsetDateTime timeStamp, Element rootRdfElement, Map<Instant, Integer> instantApplicationTimeMap) {
114-
ncCracCreationContext.getCrac().getStates().forEach(
115-
state -> {
116-
raoResult.getActivatedRangeActionsDuringState(state).forEach(rangeAction -> writeRemedialActionResult(document, rootRdfElement, rangeAction, state, raoResult, timeStamp.plusSeconds(instantApplicationTimeMap.get(state.getInstant()))));
117-
raoResult.getActivatedNetworkActionsDuringState(state).forEach(networkAction -> writeRemedialActionResult(document, rootRdfElement, networkAction, state, raoResult, timeStamp.plusSeconds(instantApplicationTimeMap.get(state.getInstant()))));
118-
}
119-
);
120-
}
121-
122-
private static void writeRemedialActionResult(Document document, Element rootRdfElement, RemedialAction<?> remedialAction, State state, RaoResult raoResult, OffsetDateTime timeStamp) {
123-
// Step 1: Create RemedialActionSchedule to indicate the application state of the remedial action
124-
String remedialActionScheduleMRid = generateRemedialActionScheduleMRid(remedialAction, state);
125-
Element remedialActionScheduleElement = writeRemedialActionScheduleElement(document, remedialActionScheduleMRid, remedialAction, state);
126-
rootRdfElement.appendChild(remedialActionScheduleElement);
127-
128-
// Step 2: For each elementary action, create a GridStateIntensitySchedule and a GenericValueTimePoint to indicate the optimal set-point
129-
if (remedialAction instanceof RangeAction<?> rangeAction) {
130-
// no elementary action -> use remedial action directly
131-
String gridStateIntensityScheduleMRid = generateGridStateIntensityScheduleMRid(rangeAction.getId(), state);
132-
rootRdfElement.appendChild(writeGridStateIntensitySchedule(document, gridStateIntensityScheduleMRid, remedialActionScheduleMRid, rangeAction.getId()));
133-
rootRdfElement.appendChild(writeGenericValueTimePoint(document, gridStateIntensityScheduleMRid, getRangeActionSetPoint(rangeAction, state, raoResult), timeStamp));
134-
} else if (remedialAction instanceof NetworkAction networkAction) {
135-
for (Action elementaryAction : networkAction.getElementaryActions()) {
136-
String gridStateIntensityScheduleMRid = generateGridStateIntensityScheduleMRid(elementaryAction.getId(), state);
137-
rootRdfElement.appendChild(writeGridStateIntensitySchedule(document, gridStateIntensityScheduleMRid, remedialActionScheduleMRid, elementaryAction.getId()));
138-
rootRdfElement.appendChild(writeGenericValueTimePoint(document, gridStateIntensityScheduleMRid, getActionSetPoint(elementaryAction), timeStamp));
139-
}
140-
}
141-
}
142-
143-
private static Number getRangeActionSetPoint(RangeAction<?> rangeAction, State state, RaoResult raoResult) {
144-
if (rangeAction instanceof PstRangeAction pstRangeAction) {
145-
return raoResult.getOptimizedTapOnState(state, pstRangeAction);
146-
}
147-
return raoResult.getOptimizedSetPointOnState(state, rangeAction);
148-
}
149-
150-
private static Number getActionSetPoint(Action elementaryAction) {
151-
if (elementaryAction instanceof SwitchAction switchAction) {
152-
return switchAction.isOpen() ? 1 : 0;
153-
} else if (elementaryAction instanceof ShuntCompensatorPositionAction shuntCompensatorPositionAction) {
154-
return shuntCompensatorPositionAction.getSectionCount();
155-
} else if (elementaryAction instanceof GeneratorAction generatorAction) {
156-
return generatorAction.getActivePowerValue().orElseThrow();
157-
} else if (elementaryAction instanceof LoadAction loadAction) {
158-
return loadAction.getActivePowerValue().orElseThrow();
159-
} else if (elementaryAction instanceof PhaseTapChangerTapPositionAction tapPositionAction) {
160-
return tapPositionAction.getTapPosition();
161-
} else {
162-
throw new OpenRaoException("Unsupported elementary action type %s".formatted(elementaryAction.getClass().getSimpleName()));
163-
}
164-
}
165-
166-
private static Element writeRemedialActionScheduleElement(Document document, String remedialActionScheduleMRid, RemedialAction<?> remedialAction, State state) {
167-
Element remedialActionScheduleElement = document.createElement("nc:RemedialActionSchedule");
168-
remedialActionScheduleElement.setAttribute("rdf:ID", getMRidReference(remedialActionScheduleMRid));
169-
170-
Element mRidElement = document.createElement("cim:IdentifiedObject.mRID");
171-
mRidElement.setTextContent(remedialActionScheduleMRid);
172-
remedialActionScheduleElement.appendChild(mRidElement);
173-
174-
Element statusKindElement = document.createElement("nc:RemedialActionSchedule.statusKind");
175-
setRdfResourceReference(statusKindElement, Namespace.NC.getUri() + "RemedialActionScheduleStatusKind.proposed");
176-
remedialActionScheduleElement.appendChild(statusKindElement);
177-
178-
Element remedialActionElement = document.createElement("nc:RemedialActionSchedule.RemedialAction");
179-
setRdfResourceReference(remedialActionElement, getMRidReference(remedialAction.getId()));
180-
remedialActionScheduleElement.appendChild(remedialActionElement);
181-
182-
state.getContingency().ifPresent(contingency -> {
183-
Element contingencyElement = document.createElement("nc:RemedialActionSchedule.Contingency");
184-
setRdfResourceReference(contingencyElement, getMRidReference(contingency.getId()));
185-
remedialActionScheduleElement.appendChild(contingencyElement);
186-
});
187-
188-
return remedialActionScheduleElement;
189-
}
190-
191-
private static Element writeGridStateIntensitySchedule(Document document, String gridStateIntensityScheduleMRid, String remedialActionScheduleMRid, String elementaryActionId) {
192-
Element gridStateIntensityScheduleElement = document.createElement("nc:GridStateIntensitySchedule");
193-
gridStateIntensityScheduleElement.setAttribute("rdf:ID", getMRidReference(gridStateIntensityScheduleMRid));
194-
195-
Element valueKindElement = document.createElement("nc:GridStateIntensitySchedule.valueKind");
196-
setRdfResourceReference(valueKindElement, Namespace.NC.getUri() + "ValueOffsetKind.absolute");
197-
gridStateIntensityScheduleElement.appendChild(valueKindElement);
198-
199-
Element interpolationKindElement = document.createElement("nc:BaseTimeSeries.interpolationKind");
200-
setRdfResourceReference(interpolationKindElement, Namespace.NC.getUri() + "TimeSeriesInterpolationKind.none");
201-
gridStateIntensityScheduleElement.appendChild(interpolationKindElement);
202-
203-
Element mRidElement = document.createElement("cim:IdentifiedObject.mRID");
204-
mRidElement.setTextContent(gridStateIntensityScheduleMRid);
205-
gridStateIntensityScheduleElement.appendChild(mRidElement);
206-
207-
Element gridStateAlterationElement = document.createElement("nc:GridStateIntensitySchedule.GridStateAlteration");
208-
setRdfResourceReference(gridStateAlterationElement, getMRidReference(elementaryActionId));
209-
gridStateIntensityScheduleElement.appendChild(gridStateAlterationElement);
210-
211-
Element remedialActionScheduleElement = document.createElement("nc:GenericValueSchedule.RemedialActionSchedule");
212-
setRdfResourceReference(remedialActionScheduleElement, getMRidReference(remedialActionScheduleMRid));
213-
gridStateIntensityScheduleElement.appendChild(remedialActionScheduleElement);
214-
215-
return gridStateIntensityScheduleElement;
216-
}
217-
218-
private static Element writeGenericValueTimePoint(Document document, String genericValueScheduleMRid, Number setPoint, OffsetDateTime timeStamp) {
219-
Element genericValueTimePointElement = document.createElement("nc:GenericValueTimePoint");
220-
221-
// TODO: for CRAs, use curative instant post-outage time as an offset to identify curative batch
222-
// TODO: add curative instants post-outage time in CRAC Creation Context
223-
Element atTimeElement = document.createElement("nc:GenericValueTimePoint.atTime");
224-
atTimeElement.setTextContent(formatOffsetDateTime(timeStamp));
225-
genericValueTimePointElement.appendChild(atTimeElement);
226-
227-
Element valueElement = document.createElement("nc:GenericValueTimePoint.value");
228-
valueElement.setTextContent(String.valueOf(setPoint));
229-
genericValueTimePointElement.appendChild(valueElement);
230-
231-
Element genericValueSchedule = document.createElement("nc:GenericValueTimePoint.GenericValueSchedule");
232-
setRdfResourceReference(genericValueSchedule, getMRidReference(genericValueScheduleMRid));
233-
genericValueTimePointElement.appendChild(genericValueSchedule);
234-
235-
return genericValueTimePointElement;
236-
}
237-
238-
private static String generateRemedialActionScheduleMRid(RemedialAction<?> remedialAction, State state) {
239-
return UUID.nameUUIDFromBytes("%s@%s".formatted(remedialAction.getId(), state.getId()).getBytes(StandardCharsets.UTF_8)).toString();
240-
}
241-
242-
private static String generateGridStateIntensityScheduleMRid(String elementaryActionId, State state) {
243-
return UUID.nameUUIDFromBytes("%s@%s::set-point".formatted(elementaryActionId, state.getId()).getBytes(StandardCharsets.UTF_8)).toString();
244-
}
245-
246-
private static void setRdfResourceReference(Element element, String reference) {
247-
element.setAttribute("rdf:resource", reference);
248-
}
249-
250-
private static String getMRidReference(String mRid) {
251-
return "#_%s".formatted(mRid);
252-
}
253-
25495
private static void writeOutputXmlFile(Document document, OutputStream outputStream) {
25596
try {
25697
TransformerFactory tf = TransformerFactory.newInstance();
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.powsybl.openrao.data.raoresult.nc;
2+
3+
import com.powsybl.openrao.data.cracio.csaprofiles.craccreator.CsaProfileCracCreationContext;
4+
import com.powsybl.openrao.data.raoresultapi.RaoResult;
5+
import org.w3c.dom.Document;
6+
import org.w3c.dom.Element;
7+
8+
import java.time.OffsetDateTime;
9+
import java.time.format.DateTimeFormatter;
10+
11+
public interface NcProfileWriter {
12+
String getKeyword();
13+
14+
default void addProfileKeywordToHeader(Document document, Element header) {
15+
Element keywordElement = document.createElement("dcat:keyword");
16+
keywordElement.setTextContent(getKeyword());
17+
header.appendChild(keywordElement);
18+
}
19+
20+
void addProfileContent(Document document, Element rootRdfElement, RaoResult raoResult, CsaProfileCracCreationContext ncCracCreationContext);
21+
22+
default void addWholeProfile(Document document, Element rootRdfElement, Element header, RaoResult raoResult, CsaProfileCracCreationContext ncCracCreationContext) {
23+
addProfileKeywordToHeader(document, header);
24+
addProfileContent(document, rootRdfElement, raoResult, ncCracCreationContext);
25+
}
26+
27+
static String formatOffsetDateTime(OffsetDateTime offsetDateTime) {
28+
return offsetDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
29+
}
30+
31+
static void setRdfResourceReference(Element element, String reference) {
32+
element.setAttribute("rdf:resource", reference);
33+
}
34+
35+
static String getMRidReference(String mRid) {
36+
return "#_%s".formatted(mRid);
37+
}
38+
}

0 commit comments

Comments
 (0)