11package com .powsybl .openrao .data .raoresult .nc ;
22
33import 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 ;
104import com .powsybl .openrao .commons .OpenRaoException ;
115import com .powsybl .openrao .data .cracapi .Crac ;
126import 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 ;
197import com .powsybl .openrao .data .cracio .csaprofiles .craccreator .CsaProfileCracCreationContext ;
208import com .powsybl .openrao .data .raoresultapi .RaoResult ;
219import com .powsybl .openrao .data .raoresultapi .io .Exporter ;
3321import javax .xml .transform .dom .DOMSource ;
3422import javax .xml .transform .stream .StreamResult ;
3523import java .io .OutputStream ;
36- import java .nio .charset .StandardCharsets ;
3724import java .time .OffsetDateTime ;
3825import java .time .format .DateTimeFormatter ;
3926import java .util .Arrays ;
40- import java .util .Map ;
4127import java .util .Properties ;
42- import java .util .UUID ;
4328
4429@ AutoService (Exporter .class )
4530public 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 ();
0 commit comments