@@ -24,15 +24,19 @@ public final class IcsImporter {
2424 private static final int OFFSET = 2 ;
2525 private static final double COST_UP = 10 ;
2626 private static final double COST_DOWN = 10 ;
27- private static final double ACTIVATION_COST = 50 ;
27+ private static final String MAX_GRADIENT = "1000" ;
2828
29- //TODO:QUALITY CHECK: do PO respect constraints?
29+ // TODO:QUALITY CHECK: do PO respect constraints?
30+ // TODO:QUALITY CHECK: consistency between gsks defined in static file + gsk file
31+
32+ // INFOS
33+ // Gradient constraints are defined for gsks à la maille parade, et pas par générateur : on applique donc le shift key au Pmax/Pmin
3034
3135 private IcsImporter () {
3236 //should only be used statically
3337 }
3438
35- public static void populateInputWithICS (InterTemporalRaoInputWithNetworkPaths interTemporalRaoInput , InputStream staticInputStream , InputStream seriesInputStream ) throws IOException {
39+ public static void populateInputWithICS (InterTemporalRaoInputWithNetworkPaths interTemporalRaoInput , InputStream staticInputStream , InputStream seriesInputStream , InputStream gskInputStream ) throws IOException {
3640 TemporalData <Network > initialNetworks = new TemporalDataImpl <>();
3741 interTemporalRaoInput .getRaoInputs ().getDataPerTimestamp ().forEach ((dateTime , raoInput ) ->
3842 initialNetworks .add (dateTime , Network .read (raoInput .getInitialNetworkPath ()))
@@ -51,54 +55,25 @@ public static void populateInputWithICS(InterTemporalRaoInputWithNetworkPaths in
5155 seriesPerIdAndType .get (record .get ("RA RD ID" )).put (record .get ("Type of timeseries" ), record );
5256 });
5357
58+ Map <String , Map <String , Double >> weightPerNodePerGsk = new HashMap <>();
59+ if (gskInputStream != null ) {
60+ Iterable <CSVRecord > gskCsvRecords = csvFormat .parse (new InputStreamReader (gskInputStream ));
61+ gskCsvRecords .forEach (record -> {
62+ weightPerNodePerGsk .putIfAbsent (record .get ("GSK ID" ), new HashMap <>());
63+ weightPerNodePerGsk .get (record .get ("GSK ID" )).put (record .get ("Node" ), Double .parseDouble (record .get ("Weight" )));
64+ });
65+ }
66+
5467 staticCsvRecords .forEach (staticRecord -> {
55- if (shouldBeImported (staticRecord )) {
68+ if (shouldBeImported (staticRecord , weightPerNodePerGsk )) {
5669 String raId = staticRecord .get ("RA RD ID" );
5770 Map <String , CSVRecord > seriesPerType = seriesPerIdAndType .get (raId );
5871 if (seriesPerType != null && seriesPerType .containsKey ("P0" ) && seriesPerType .containsKey ("RDP-" ) && seriesPerType .containsKey ("RDP+" ) && p0RespectsGradients (staticRecord , seriesPerType .get ("P0" ), interTemporalRaoInput .getTimestampsToRun ())) {
59- String networkElement = processNetworks (staticRecord .get ("UCT Node or GSK ID" ), initialNetworks , seriesPerType );
60- if (networkElement == null ) {
61- return ;
72+ if (staticRecord .get ("RD description mode" ).equalsIgnoreCase ("NODE" )) {
73+ importNodeRedispatchingAction (interTemporalRaoInput , staticRecord , initialNetworks , seriesPerType , raId );
74+ } else {
75+ importGskRedispatchingAction (interTemporalRaoInput , staticRecord , initialNetworks , seriesPerType , raId , weightPerNodePerGsk .get (staticRecord .get ("UCT Node or GSK ID" )));
6276 }
63- interTemporalRaoInput .getRaoInputs ().getDataPerTimestamp ().forEach ((dateTime , raoInput ) -> {
64- Crac crac = raoInput .getCrac ();
65- double p0 = Double .parseDouble (seriesPerType .get ("P0" ).get (dateTime .getHour () + OFFSET ));
66- InjectionRangeActionAdder injectionRangeActionAdder = crac .newInjectionRangeAction ()
67- .withId (raId + "_RD" )
68- .withName (staticRecord .get ("Generator Name" ))
69- .withNetworkElement (networkElement )
70- .withInitialSetpoint (p0 )
71- .withVariationCost (COST_UP , VariationDirection .UP )
72- .withVariationCost (COST_DOWN , VariationDirection .DOWN )
73- //.withActivationCost(ACTIVATION_COST)
74- .newRange ()
75- .withMin (p0 - Double .parseDouble (seriesPerType .get ("RDP-" ).get (dateTime .getHour () + OFFSET )))
76- .withMax (p0 + Double .parseDouble (seriesPerType .get ("RDP+" ).get (dateTime .getHour () + OFFSET )))
77- .add ();
78- if (staticRecord .get ("Preventive" ).equals ("TRUE" )) {
79- injectionRangeActionAdder .newOnInstantUsageRule ()
80- .withInstant (crac .getPreventiveInstant ().getId ())
81- .withUsageMethod (UsageMethod .AVAILABLE )
82- .add ();
83- }
84- /*if (staticRecord.get("Curative").equals("TRUE")) {
85- injectionRangeActionAdder.newOnInstantUsageRule()
86- .withInstant(crac.getLastInstant().getId())
87- .withUsageMethod(UsageMethod.AVAILABLE)
88- .add();
89- }*/
90- injectionRangeActionAdder .add ();
91-
92- });
93-
94- PowerGradient powerGradient = PowerGradient .builder ()
95- .withNetworkElementId (networkElement )
96- .withMaxValue (Double .parseDouble (
97- staticRecord .get ("Maximum positive power gradient [MW/h]" ).isEmpty () ? "1000" : staticRecord .get ("Maximum positive power gradient [MW/h]" )
98- )).withMinValue (-Double .parseDouble (
99- staticRecord .get ("Maximum negative power gradient [MW/h]" ).isEmpty () ? "1000" : staticRecord .get ("Maximum negative power gradient [MW/h]" )
100- )).build ();
101- interTemporalRaoInput .getPowerGradients ().add (powerGradient );
10277 }
10378 }
10479 });
@@ -107,14 +82,117 @@ public static void populateInputWithICS(InterTemporalRaoInputWithNetworkPaths in
10782 initialNetwork .write ("JIIDM" , new Properties (), Path .of (interTemporalRaoInput .getRaoInputs ().getData (dateTime ).orElseThrow ().getPostIcsImportNetworkPath ())));
10883 }
10984
110- private static String processNetworks (String uctNodeOrGskId , TemporalData <Network > initialNetworks , Map <String , CSVRecord > seriesPerType ) {
111- String generatorId = seriesPerType .get ("P0" ).get ("RA RD ID" ) + "_GENERATOR" ;
85+ private static void importGskRedispatchingAction (InterTemporalRaoInputWithNetworkPaths interTemporalRaoInput , CSVRecord staticRecord , TemporalData <Network > initialNetworks , Map <String , CSVRecord > seriesPerType , String raId , Map <String , Double > weightPerNode ) {
86+ Map <String , String > networkElementPerGskElement = new HashMap <>();
87+ for (String nodeId : weightPerNode .keySet ()) {
88+ String networkElementId = processNetworks (nodeId , initialNetworks , seriesPerType , weightPerNode .get (nodeId ));
89+ if (networkElementId == null ) {
90+ return ;
91+ }
92+ networkElementPerGskElement .put (nodeId , networkElementId );
93+ }
94+
95+ interTemporalRaoInput .getRaoInputs ().getDataPerTimestamp ().forEach ((dateTime , raoInput ) -> {
96+ Crac crac = raoInput .getCrac ();
97+ double p0 = Double .parseDouble (seriesPerType .get ("P0" ).get (dateTime .getHour () + OFFSET ));
98+ InjectionRangeActionAdder injectionRangeActionAdder = crac .newInjectionRangeAction ()
99+ .withId (raId + "_RD" )
100+ .withName (staticRecord .get ("Generator Name" ))
101+ .withInitialSetpoint (p0 )
102+ .withVariationCost (COST_UP , VariationDirection .UP )
103+ .withVariationCost (COST_DOWN , VariationDirection .DOWN )
104+ //.withActivationCost(ACTIVATION_COST)
105+ .newRange ()
106+ .withMin (p0 - Double .parseDouble (seriesPerType .get ("RDP-" ).get (dateTime .getHour () + OFFSET )))
107+ .withMax (p0 + Double .parseDouble (seriesPerType .get ("RDP+" ).get (dateTime .getHour () + OFFSET )))
108+ .add ();
109+
110+ weightPerNode .forEach ((nodeId , shiftKey ) -> {
111+ injectionRangeActionAdder .withNetworkElementAndKey (shiftKey , networkElementPerGskElement .get (nodeId ));
112+ });
113+
114+ if (staticRecord .get ("Preventive" ).equals ("TRUE" )) {
115+ injectionRangeActionAdder .newOnInstantUsageRule ()
116+ .withInstant (crac .getPreventiveInstant ().getId ())
117+ .withUsageMethod (UsageMethod .AVAILABLE )
118+ .add ();
119+ }
120+ /*if (staticRecord.get("Curative").equals("TRUE")) {
121+ injectionRangeActionAdder.newOnInstantUsageRule()
122+ .withInstant(crac.getLastInstant().getId())
123+ .withUsageMethod(UsageMethod.AVAILABLE)
124+ .add();
125+ }*/
126+ injectionRangeActionAdder .add ();
127+
128+ });
129+
130+ weightPerNode .forEach ((nodeId , shiftKey ) -> {
131+ PowerGradient powerGradient = PowerGradient .builder ()
132+ .withNetworkElementId (networkElementPerGskElement .get (nodeId ))
133+ .withMaxValue (shiftKey * Double .parseDouble (
134+ staticRecord .get ("Maximum positive power gradient [MW/h]" ).isEmpty () ? MAX_GRADIENT : staticRecord .get ("Maximum positive power gradient [MW/h]" )
135+ )).withMinValue (-shiftKey * Double .parseDouble (
136+ staticRecord .get ("Maximum negative power gradient [MW/h]" ).isEmpty () ? MAX_GRADIENT : staticRecord .get ("Maximum negative power gradient [MW/h]" )
137+ )).build ();
138+ interTemporalRaoInput .getPowerGradients ().add (powerGradient );
139+ });
140+ }
141+
142+ private static void importNodeRedispatchingAction (InterTemporalRaoInputWithNetworkPaths interTemporalRaoInput , CSVRecord staticRecord , TemporalData <Network > initialNetworks , Map <String , CSVRecord > seriesPerType , String raId ) {
143+ String networkElementId = processNetworks (staticRecord .get ("UCT Node or GSK ID" ), initialNetworks , seriesPerType , 1. );
144+ if (networkElementId == null ) {
145+ return ;
146+ }
147+ interTemporalRaoInput .getRaoInputs ().getDataPerTimestamp ().forEach ((dateTime , raoInput ) -> {
148+ Crac crac = raoInput .getCrac ();
149+ double p0 = Double .parseDouble (seriesPerType .get ("P0" ).get (dateTime .getHour () + OFFSET ));
150+ InjectionRangeActionAdder injectionRangeActionAdder = crac .newInjectionRangeAction ()
151+ .withId (raId + "_RD" )
152+ .withName (staticRecord .get ("Generator Name" ))
153+ .withNetworkElement (networkElementId )
154+ .withInitialSetpoint (p0 )
155+ .withVariationCost (COST_UP , VariationDirection .UP )
156+ .withVariationCost (COST_DOWN , VariationDirection .DOWN )
157+ //.withActivationCost(ACTIVATION_COST)
158+ .newRange ()
159+ .withMin (p0 - Double .parseDouble (seriesPerType .get ("RDP-" ).get (dateTime .getHour () + OFFSET )))
160+ .withMax (p0 + Double .parseDouble (seriesPerType .get ("RDP+" ).get (dateTime .getHour () + OFFSET )))
161+ .add ();
162+ if (staticRecord .get ("Preventive" ).equals ("TRUE" )) {
163+ injectionRangeActionAdder .newOnInstantUsageRule ()
164+ .withInstant (crac .getPreventiveInstant ().getId ())
165+ .withUsageMethod (UsageMethod .AVAILABLE )
166+ .add ();
167+ }
168+ /*if (staticRecord.get("Curative").equals("TRUE")) {
169+ injectionRangeActionAdder.newOnInstantUsageRule()
170+ .withInstant(crac.getLastInstant().getId())
171+ .withUsageMethod(UsageMethod.AVAILABLE)
172+ .add();
173+ }*/
174+ injectionRangeActionAdder .add ();
175+
176+ });
177+
178+ PowerGradient powerGradient = PowerGradient .builder ()
179+ .withNetworkElementId (networkElementId )
180+ .withMaxValue (Double .parseDouble (
181+ staticRecord .get ("Maximum positive power gradient [MW/h]" ).isEmpty () ? MAX_GRADIENT : staticRecord .get ("Maximum positive power gradient [MW/h]" )
182+ )).withMinValue (-Double .parseDouble (
183+ staticRecord .get ("Maximum negative power gradient [MW/h]" ).isEmpty () ? MAX_GRADIENT : staticRecord .get ("Maximum negative power gradient [MW/h]" )
184+ )).build ();
185+ interTemporalRaoInput .getPowerGradients ().add (powerGradient );
186+ }
187+
188+ private static String processNetworks (String nodeId , TemporalData <Network > initialNetworks , Map <String , CSVRecord > seriesPerType , double shiftKey ) {
189+ String generatorId = seriesPerType .get ("P0" ).get ("RA RD ID" ) + "_" + nodeId + "_GENERATOR" ;
112190 for (Map .Entry <OffsetDateTime , Network > entry : initialNetworks .getDataPerTimestamp ().entrySet ()) {
113- Bus bus = entry .getValue ().getBusBreakerView ().getBus (uctNodeOrGskId );
191+ Bus bus = entry .getValue ().getBusBreakerView ().getBus (nodeId );
114192 if (bus == null ) {
115193 return null ;
116194 }
117- Double p0 = Double .parseDouble (seriesPerType .get ("P0" ).get (entry .getKey ().getHour () + OFFSET ));
195+ Double p0 = Double .parseDouble (seriesPerType .get ("P0" ).get (entry .getKey ().getHour () + OFFSET )) * shiftKey ;
118196 processBus (bus , generatorId , p0 );
119197 }
120198 return generatorId ;
@@ -144,16 +222,16 @@ private static void processBus(Bus bus, String generatorId, Double p0) {
144222 .add ();
145223 }
146224
147- private static boolean shouldBeImported (CSVRecord staticRecord ) {
148- return staticRecord .get ("RD description mode" ).equals ("NODE" ) &&
225+ private static boolean shouldBeImported (CSVRecord staticRecord , Map < String , Map < String , Double >> weightPerNodePerGsk ) {
226+ return ( staticRecord .get ("RD description mode" ).equalsIgnoreCase ("NODE" ) || weightPerNodePerGsk . containsKey ( staticRecord . get ( "UCT Node or GSK ID" )) ) &&
149227 (staticRecord .get ("Preventive" ).equals ("TRUE" ) /*|| staticRecord.get("Curative").equals("TRUE")*/ );
150228 }
151229
152230 private static boolean p0RespectsGradients (CSVRecord staticRecord , CSVRecord p0record , Set <OffsetDateTime > dateTimes ) {
153231 double maxGradient = Double .parseDouble (staticRecord .get ("Maximum positive power gradient [MW/h]" ).isEmpty () ?
154- "1000" : staticRecord .get ("Maximum positive power gradient [MW/h]" ));
232+ MAX_GRADIENT : staticRecord .get ("Maximum positive power gradient [MW/h]" ));
155233 double minGradient = -Double .parseDouble (staticRecord .get ("Maximum negative power gradient [MW/h]" ).isEmpty () ?
156- "1000" : staticRecord .get ("Maximum negative power gradient [MW/h]" ));
234+ MAX_GRADIENT : staticRecord .get ("Maximum negative power gradient [MW/h]" ));
157235
158236 Iterator <OffsetDateTime > dateTimeIterator = dateTimes .iterator ();
159237 OffsetDateTime currentDateTime = dateTimeIterator .next ();
0 commit comments