psr-factory 4.1.0b5__py3-none-win_amd64.whl → 4.1.0b10__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
psr/factory/__init__.py CHANGED
@@ -2,6 +2,6 @@
2
2
  # Unauthorized copying of this file, via any medium is strictly prohibited
3
3
  # Proprietary and confidential
4
4
 
5
- __version__ = "4.1.0b5"
5
+ __version__ = "4.1.0b10"
6
6
 
7
7
  from .api import *
psr/factory/api.py CHANGED
@@ -5,6 +5,7 @@
5
5
  import locale
6
6
  from typing import Dict, List, Optional, Tuple, Union
7
7
  from types import ModuleType
8
+ import copy
8
9
  import ctypes
9
10
  import datetime as dt
10
11
  import enum
@@ -945,6 +946,9 @@ class DataObject(_BaseObject):
945
946
  def help(self) -> str:
946
947
  return help(self.type)
947
948
 
949
+ def clone(self) -> "DataObject":
950
+ return copy.copy(self)
951
+
948
952
  @property
949
953
  def context(self) -> "Context":
950
954
  _check_initialized()
@@ -1234,7 +1238,6 @@ class Context(DataObject):
1234
1238
  class Study(_BaseObject):
1235
1239
  def __init__(self):
1236
1240
  super().__init__()
1237
- self.find_by_name = self.find
1238
1241
 
1239
1242
  def __del__(self):
1240
1243
  if self._hdr is not None:
@@ -1269,10 +1272,18 @@ class Study(_BaseObject):
1269
1272
  dest._hdr = ref
1270
1273
  return dest
1271
1274
 
1275
+ def create(self, object_type: str) -> DataObject:
1276
+ _check_initialized()
1277
+ return create(object_type, self.context)
1278
+
1279
+
1272
1280
  @staticmethod
1273
1281
  def help():
1274
1282
  return help("Study")
1275
1283
 
1284
+ def clone(self) -> "Study":
1285
+ return copy.deepcopy(self)
1286
+
1276
1287
  @staticmethod
1277
1288
  def create_object(profile_or_context: Union[str, Context, dict, None],
1278
1289
  blocks: Optional[int] = None):
@@ -1431,7 +1442,14 @@ class Study(_BaseObject):
1431
1442
  object_list._hdr = ref
1432
1443
  return object_list.to_list()
1433
1444
 
1434
- def find_by_name(self, type_name: str, name: str) -> List[DataObject]:
1445
+ def find_by_name(self, type_name: str, name: Optional[str] = None) -> List[DataObject]:
1446
+ if name is None:
1447
+ warnings.warn(DeprecationWarning("Starting from Factory 4.0.28 "
1448
+ "the second argument 'name' must be provided.\n"
1449
+ "Use find_by_name(type_name, name)"))
1450
+
1451
+ type_name, name_str = type_name.split(".", 1)
1452
+ name = name_str
1435
1453
  object_list = ValueList(False)
1436
1454
  _err = Error()
1437
1455
  if name.strip() == "":
@@ -1765,7 +1783,7 @@ class _DataFrameBuilder:
1765
1783
  if self._err.code != 0:
1766
1784
  raise FactoryException(self._err.what)
1767
1785
  # convert array values to python datetime
1768
- self.indices[index].values = [dt.datetime.utcfromtimestamp(value - _date_transform) for value in array_values]
1786
+ self.indices[index].values = [dt.datetime.fromtimestamp(value - _date_transform, dt.UTC) for value in array_values]
1769
1787
  else:
1770
1788
  array_values = (ctypes.c_int * rows_count)()
1771
1789
  factorylib.lib.psrd_table_index_get_int32_values(df.handler(),
psr/factory/factory.dll CHANGED
Binary file
psr/factory/factory.pmd CHANGED
@@ -2516,11 +2516,11 @@ DEFINE_MODEL MODL:Optgen_RestricaoGenerica
2516
2516
  PARM DATE DataMin
2517
2517
  PARM DATE DataMax
2518
2518
  PARM REAL RHS
2519
- PARM STRING Type
2520
2519
  VECTOR REAL Coefficients
2521
2520
  PARM INTEGER LimitType
2522
2521
  PARM REAL Penalty
2523
2522
  PARM INTEGER Selected
2523
+ PARM INTEGER FlagIncremental
2524
2524
  VECTOR REFERENCE AgentElement PSRElement
2525
2525
  END_MODEL
2526
2526
  //--------------------------------------------------------------------------------------------------
@@ -2739,6 +2739,7 @@ DEFINE_MODEL MODL:Optgen_Configuration_Keywords
2739
2739
  PARM INTEGER RXGM
2740
2740
  PARM INTEGER FSCN
2741
2741
  PARM INTEGER RMET
2742
+ PARM REAL MXPF
2742
2743
  END_MODEL
2743
2744
 
2744
2745
 
@@ -4450,8 +4451,8 @@ END_MODEL
4450
4451
  //--------------------------------------------------------------------------------------------------
4451
4452
  DEFINE_MODEL MODL:SDDP_V10.2_Combustivel
4452
4453
  VETOR DATE Data @addyear_chronological
4453
- PARM STRING UComb
4454
- PARM STRING UE
4454
+ PARM STRING UComb
4455
+ PARM STRING UE
4455
4456
  PARM REAL EmiCO2
4456
4457
  VETOR REAL Custo INDEX Data
4457
4458
 
@@ -4460,7 +4461,7 @@ DEFINE_MODEL MODL:SDDP_V10.2_Combustivel
4460
4461
  VETOR DATE DataAvailability @addyear_chronological
4461
4462
  VETOR REAL Availability INDEX DataAvailability
4462
4463
 
4463
- PARM INTEGER FlagScenario
4464
+ PARM INTEGER FlagScenario
4464
4465
  VETOR REAL ScenarioCost
4465
4466
  END_MODEL
4466
4467
 
@@ -4864,7 +4865,7 @@ END_MODEL
4864
4865
  // Supply chain Node
4865
4866
  //--------------------------------------------------------------------------------------------------
4866
4867
  DEFINE_MODEL MODL:SDDP_ElectrificationNode
4867
- // nada aqui
4868
+ MERGE_MODEL Sddp_Georeference
4868
4869
  END_MODEL
4869
4870
  //--------------------------------------------------------------------------------------------------
4870
4871
  // Supply chain Transport
psr/factory/factory.pmk CHANGED
@@ -6865,6 +6865,7 @@ CONTEXT_READ optmain
6865
6865
  CONTEXT_WRITE optmain
6866
6866
  CLASSNAME PSRPlant
6867
6867
  MODEL StageCstr
6868
+ MERGE_OBJECTS TRUE
6868
6869
  END_AUTOMATIC_INFO
6869
6870
 
6870
6871
  DEFINE_DATA
@@ -6888,6 +6889,7 @@ CONTEXT_READ optmain
6888
6889
  CONTEXT_WRITE optmain
6889
6890
  CLASSNAME PSRSystem
6890
6891
  MODEL MinRes
6892
+ MERGE_OBJECTS TRUE
6891
6893
  END_AUTOMATIC_INFO
6892
6894
 
6893
6895
  DEFINE_DATA
@@ -6912,6 +6914,7 @@ CONTEXT_READ optmain
6912
6914
  CONTEXT_WRITE optmain
6913
6915
  CLASSNAME PSRSystem
6914
6916
  MODEL InstDem
6917
+ MERGE_OBJECTS TRUE
6915
6918
  END_AUTOMATIC_INFO
6916
6919
 
6917
6920
  DEFINE_DATA
@@ -6984,6 +6987,7 @@ CONTEXT_READ optmain
6984
6987
  CONTEXT_WRITE optmain
6985
6988
  CLASSNAME PSRPlant
6986
6989
  MODEL UnitFactors
6990
+ MERGE_OBJECTS TRUE
6987
6991
  END_AUTOMATIC_INFO
6988
6992
 
6989
6993
  DEFINE_DATA
@@ -7007,6 +7011,7 @@ CONTEXT_READ optmain
7007
7011
  CONTEXT_WRITE optmain
7008
7012
  CLASSNAME PSRPlant
7009
7013
  MODEL UnitCodes
7014
+ MERGE_OBJECTS TRUE
7010
7015
  END_AUTOMATIC_INFO
7011
7016
 
7012
7017
  DEFINE_DATA
@@ -14721,7 +14726,7 @@ MonitoringList REFERENCE,2 AUTOSET(model.parm("MonitoringList"))
14721
14726
  END_DATA
14722
14727
  DEFINE_HEADER
14723
14728
  $version=1
14724
- !name,Serie,MonitoringList
14729
+ !Serie,MonitoringList
14725
14730
  END_HEADER
14726
14731
  END_MASK
14727
14732
  //--------------------------------------------------------------------------------------------------
@@ -16806,7 +16811,7 @@ END_AUTOMATIC_INFO
16806
16811
 
16807
16812
  DEFINE_DATA
16808
16813
  code REFERENCE 1
16809
- DateStatus DATE 2 YYYY/MM/DD AUTOSET
16814
+ DateBypass DATE 2 YYYY/MM/DD AUTOSET
16810
16815
  block INTEGER 3
16811
16816
  Bypass INTEGER 4
16812
16817
  END_DATA
@@ -17390,8 +17395,8 @@ DEFINE_MASK CSVDATA SDDP_genesysweights
17390
17395
  DEFINE_AUTOMATIC_INFO
17391
17396
  FILENAME genesys_weights.dat
17392
17397
  VERSION 1
17393
- CONTEXT_READ sddp
17394
- CONTEXT_WRITE sddp
17398
+ CONTEXT_READ genesys
17399
+ CONTEXT_WRITE genesys
17395
17400
  CLASSNAME PSRStudy
17396
17401
  MODEL GenesysWeights
17397
17402
  CREATE_OBJECTS TRUE
@@ -17682,7 +17687,8 @@ ElementType INTEGER 3
17682
17687
  Coefficient REAL 4
17683
17688
  END_DATA
17684
17689
  END_MASK
17685
-
17690
+ //---------------------------------------------------------------------
17691
+ //---------------------------------------------------------------------
17686
17692
  DEFINE_MASK CSVDATA SDDP_mip_dyn_conv
17687
17693
 
17688
17694
  DEFINE_DATA
@@ -17694,7 +17700,24 @@ DEFINE_HEADER
17694
17700
  !Step,MaxTime,Tolerance
17695
17701
  END_HEADER
17696
17702
  END_MASK
17703
+ //---------------------------------------------------------------------
17704
+ //---------------------------------------------------------------------
17705
+ DEFINE_MASK CSVDATA SDDP_ccombu
17706
+ DEFINE_HEADER
17707
+ $version=2
17708
+ !Code,Name,FuelUnit,Cost,EmissionFactor,CostType
17709
+ END_HEADER
17697
17710
 
17711
+ DEFINE_DATA
17712
+ Code INTEGER 1
17713
+ Name STRING 2
17714
+ UComb STRING 3 AUTOSET(model.parm("UComb"))
17715
+ Custo REAL 4 AUTOSET
17716
+ EmiCO2 REAL 5 AUTOSET(model.parm("EmiCO2"))
17717
+ FlagScenario INTEGER 6 AUTOSET(model.parm("FlagScenario"))
17718
+ END_DATA
17719
+
17720
+ END_MASK
17698
17721
  //---------------------------------------------------------------------
17699
17722
  //---------------------------------------------------------------------
17700
17723
  DEFINE_MASK ROWDATA SDDP_v10.3_cloads
Binary file
File without changes
@@ -0,0 +1,169 @@
1
+ """Creates SDDP 1 stage Case01 example."""
2
+ import copy
3
+ import os
4
+
5
+ import psr.factory
6
+
7
+
8
+ def get_case_path() -> str:
9
+ return os.path.join(os.path.splitext(os.path.basename(__file__))[0], "")
10
+
11
+
12
+ def create_sddp_sample_case01() -> psr.factory.Study:
13
+ blocks = 1
14
+ # Create a study object and define its basic settings.
15
+ study = psr.factory.create_study({
16
+ "Models": ["SDDP", ], # Default model: SDDP
17
+ "Blocks": blocks, # Default number of blocks: 1
18
+ "StageType": 2, # Weekly: 1 (default), Monthly: 2
19
+ })
20
+ study.from_dict({
21
+ "Description": "Caso ejemplo - DT - 1 etapa - 1 bloque",
22
+ "InitialYear": 2013,
23
+ "InitialStage": 1,
24
+ "NumberOfStages": 1,
25
+ "NumberOfSeries": 1,
26
+ })
27
+
28
+ # Study options
29
+ study.from_dict({
30
+ "Type": 2,
31
+ "InitialYearOfHydrology": 1996,
32
+ "NumberOfSystems": 1,
33
+ "AggregateInTheOperationPolicy": 0,
34
+ "UMON": "$",
35
+ "LoadSheddingInBuses": 0,
36
+ "MonitoringOfCircuitLimits": 0,
37
+ "HourlyRepresentation": 0,
38
+ "MaximumNumberOfIterations": 10,
39
+ "MinimumOutflowPenaltyHm3": 5000.0,
40
+ "DeficitSegment": [100.0, 0.0, 0.0, 0.0],
41
+ "DeficitCost": [500.0, 0.0, 0.0, 0.0],
42
+ "FutureCostStage": 4,
43
+ "FutureCostYear": 1998,
44
+ })
45
+
46
+ # Study duration
47
+ study.set("FixedDurationOfBlocks(1)", 100.0)
48
+
49
+ # By default, a study comes with one system.
50
+ system = study.get("System")[0]
51
+ system.code = 1
52
+ system.id = "s1"
53
+ system.name = "System 1"
54
+ # System's currency
55
+ system.set("SystemCurrency", "$")
56
+ # It's not required to add an existing object to the study.
57
+
58
+ # Set study to run with this unique system
59
+ study.set("CodesOfPowerSystems", [1, ])
60
+
61
+ # Create a demand segment - it's required to add at least
62
+ # an inelastic segment to a demand object.
63
+ segment = psr.factory.create("DemandSegment", study.context)
64
+ # Set demand and cost data.
65
+ segment.set_at("EnergyPerBlock(:)", "01/2013", 8.928)
66
+ # Add segment to the study.
67
+ study.add(segment)
68
+
69
+ # Create a system demand.
70
+ demand = psr.factory.create("Demand", study.context)
71
+ demand.code = 1
72
+ demand.name = "System 1"
73
+ # Associate it with the only system in the case.
74
+ demand.set("RefSystem", system)
75
+ # Associate the demand with its segments.
76
+ demand.set("RefSegments", [segment, ])
77
+ # Add demand to the study.
78
+ study.add(demand)
79
+
80
+ # Create all fuels - Thermal plants requires then.
81
+ fuel1 = psr.factory.create("Fuel", study.context)
82
+ fuel1.code = 1
83
+ fuel1.name = "Fuel 1"
84
+ fuel1.from_dict({
85
+ "Unit": "UC",
86
+ "UE": "MWh",
87
+ "Price": 0.8,
88
+ "EmissionFactor": 0.0,
89
+ "RefSystem": system,
90
+ })
91
+ study.add(fuel1)
92
+
93
+ fuel2 = psr.factory.create("Fuel", study.context)
94
+ fuel2.code = 2
95
+ fuel2.name = "Fuel 2"
96
+ fuel2.from_dict({
97
+ "Unit": "UC",
98
+ "UE": "MWh",
99
+ "Price": 1.2,
100
+ "EmissionFactor": 0.0,
101
+ "RefSystem": system,
102
+ })
103
+ study.add(fuel2)
104
+
105
+ # Create all thermal plants.
106
+ plant1 = psr.factory.create("ThermalPlant", study.context)
107
+ plant1.code = 1
108
+ plant1.name = "Thermal 1"
109
+ # Set plant's properties
110
+ t_params = {
111
+ "MaximumGenerationCapacity": 10.0,
112
+ "InstalledCapacity": 10.0,
113
+ "ThermalType": 0,
114
+ "Type": 0,
115
+ "NumberOfGeneratingUnits": 1,
116
+ "NumberOfAlternativeFuels": 0,
117
+ "CodeOfAlternativeFuels(:)": 0,
118
+ "O&MCost": 0.0,
119
+ "FuelTransportationCost": 0.0,
120
+ "SpecificConsumptionSegment(1)": 100.0,
121
+ "SpecificConsumptionSegment(2:3)": 0.0,
122
+ "SpecificConsumption(1:3,1)": 10.0,
123
+ "RefFuels": [fuel1, ],
124
+ "RefSystem": system,
125
+ }
126
+ plant1.from_dict(t_params)
127
+ for i in range(5):
128
+ pcopy = copy.copy(plant1)
129
+ pcopy.code = i + 1
130
+ study.add(pcopy)
131
+
132
+
133
+ # Use Python copy's module copy function to create
134
+ # a copy of an object.
135
+ plant2 = copy.copy(plant1)
136
+ plant2.code = 2
137
+ plant2.name = "Thermal 2"
138
+ plant2.set("MaximumGenerationCapacity", 5.0)
139
+ plant2.set("InstalledCapacity", 5.0)
140
+ plant2.set("SpecificConsumption(1:3,1)", 15.0)
141
+ plant2.set("RefFuels", [fuel1, ])
142
+ plant2.set("RefSystem", system)
143
+ study.add(plant2)
144
+
145
+ plant3 = plant2.clone()
146
+ plant3.code = 3
147
+ plant3.name = "Thermal 3"
148
+ plant3.from_dict({
149
+ "MaximumGenerationCapacity": 20.0,
150
+ "InstalledCapacity": 20.0,
151
+ "SpecificConsumption(1:3,1)": 12.5,
152
+ "RefFuels": [fuel2, ],
153
+ "RefSystem": system,
154
+ })
155
+ study.add(plant3)
156
+
157
+ return study
158
+
159
+
160
+ if __name__ == "__main__":
161
+
162
+ case_path = get_case_path()
163
+ os.makedirs(case_path, exist_ok=True)
164
+ print("Creating example case... ", end="")
165
+ study = create_sddp_sample_case01()
166
+ print(" OK.")
167
+ print("Saving example case in \"{}\"... ".format(case_path), end="")
168
+ study.save(case_path)
169
+ print(" OK.")
@@ -0,0 +1,164 @@
1
+ """Creates SDDP 1 stage Case01 example."""
2
+ import copy
3
+ import os
4
+
5
+ import psr.factory
6
+
7
+
8
+ def get_case_path() -> str:
9
+ return os.path.join(os.path.splitext(os.path.basename(__file__))[0], "")
10
+
11
+
12
+ def create_sddp_sample_case01() -> psr.factory.Study:
13
+ blocks = 1
14
+ # Create a study object and define its basic settings.
15
+ study = psr.factory.create_study({
16
+ "Models": ["SDDP", ], # Default model: SDDP
17
+ "Blocks": blocks, # Default number of blocks: 1
18
+ "StageType": 2, # Weekly: 1 (default), Monthly: 2
19
+ })
20
+ study.from_dict({
21
+ "Description": "Caso ejemplo - DT - 1 etapa - 1 bloque",
22
+ "InitialYear": 2013,
23
+ "InitialStage": 1,
24
+ "NumberOfStages": 1,
25
+ "NumberOfSeries": 1,
26
+ })
27
+
28
+ # Study options
29
+ study.from_dict({
30
+ "Type": 2,
31
+ "InitialYearOfHydrology": 1996,
32
+ "NumberOfSystems": 1,
33
+ "AggregateInTheOperationPolicy": 0,
34
+ "UMON": "$",
35
+ "LoadSheddingInBuses": 0,
36
+ "MonitoringOfCircuitLimits": 0,
37
+ "HourlyRepresentation": 0,
38
+ "MaximumNumberOfIterations": 10,
39
+ "MinimumOutflowPenaltyHm3": 5000.0,
40
+ "DeficitSegment": [100.0, 0.0, 0.0, 0.0],
41
+ "DeficitCost": [500.0, 0.0, 0.0, 0.0],
42
+ "FutureCostStage": 4,
43
+ "FutureCostYear": 1998,
44
+ })
45
+
46
+ # Study duration
47
+ study.set("FixedDurationOfBlocks(1)", 100.0)
48
+
49
+ # By default, a study comes with one system.
50
+ system = study.get("System")[0]
51
+ system.code = 1
52
+ system.id = "s1"
53
+ system.name = "System 1"
54
+ # System's currency
55
+ system.set("SystemCurrency", "$")
56
+ # It's not required to add an existing object to the study.
57
+
58
+ # Set study to run with this unique system
59
+ study.set("CodesOfPowerSystems", [1, ])
60
+
61
+ # Create a demand segment - it's required to add at least
62
+ # an inelastic segment to a demand object.
63
+ segment = psr.factory.create("DemandSegment", study.context)
64
+ # Set demand and cost data.
65
+ segment.set_at("EnergyPerBlock(:)", "01/2013", 8.928)
66
+ # Add segment to the study.
67
+ study.add(segment)
68
+
69
+ # Create a system demand.
70
+ demand = psr.factory.create("Demand", study.context)
71
+ demand.code = 1
72
+ demand.name = "System 1"
73
+ # Associate it with the only system in the case.
74
+ demand.set("RefSystem", system)
75
+ # Associate the demand with its segments.
76
+ demand.set("RefSegments", [segment, ])
77
+ # Add demand to the study.
78
+ study.add(demand)
79
+
80
+ # Create all fuels - Thermal plants requires then.
81
+ fuel1 = psr.factory.create("Fuel", study.context)
82
+ fuel1.code = 1
83
+ fuel1.name = "Fuel 1"
84
+ fuel1.from_dict({
85
+ "Unit": "UC",
86
+ "UE": "MWh",
87
+ "Price": 0.8,
88
+ "EmissionFactor": 0.0,
89
+ "RefSystem": system,
90
+ })
91
+ study.add(fuel1)
92
+
93
+ fuel2 = psr.factory.create("Fuel", study.context)
94
+ fuel2.code = 2
95
+ fuel2.name = "Fuel 2"
96
+ fuel2.from_dict({
97
+ "Unit": "UC",
98
+ "UE": "MWh",
99
+ "Price": 1.2,
100
+ "EmissionFactor": 0.0,
101
+ "RefSystem": system,
102
+ })
103
+ study.add(fuel2)
104
+
105
+ # Create all thermal plants.
106
+ plant1 = psr.factory.create("ThermalPlant", study.context)
107
+ plant1.code = 1
108
+ plant1.name = "Thermal 1"
109
+ # Set plant's properties
110
+ t_params = {
111
+ "MaximumGenerationCapacity": 10.0,
112
+ "InstalledCapacity": 10.0,
113
+ "ThermalType": 0,
114
+ "Type": 0,
115
+ "NumberOfGeneratingUnits": 1,
116
+ "NumberOfAlternativeFuels": 0,
117
+ "CodeOfAlternativeFuels(:)": 0,
118
+ "O&MCost": 0.0,
119
+ "FuelTransportationCost": 0.0,
120
+ "SpecificConsumptionSegment(1)": 100.0,
121
+ "SpecificConsumptionSegment(2:3)": 0.0,
122
+ "SpecificConsumption(1:3,1)": 10.0,
123
+ "RefFuels": [fuel1, ],
124
+ "RefSystem": system,
125
+ }
126
+ plant1.from_dict(t_params)
127
+
128
+ # Use Python copy's module copy function to create
129
+ # a copy of an object.
130
+ plant2 = copy.copy(plant1)
131
+ plant2.code = 2
132
+ plant2.name = "Thermal 2"
133
+ plant2.set("MaximumGenerationCapacity", 5.0)
134
+ plant2.set("InstalledCapacity", 5.0)
135
+ plant2.set("SpecificConsumption(1:3,1)", 15.0)
136
+ plant2.set("RefFuels", [fuel1, ])
137
+ plant2.set("RefSystem", system)
138
+ study.add(plant2)
139
+
140
+ plant3 = plant2.clone()
141
+ plant3.code = 3
142
+ plant3.name = "Thermal 3"
143
+ plant3.from_dict({
144
+ "MaximumGenerationCapacity": 20.0,
145
+ "InstalledCapacity": 20.0,
146
+ "SpecificConsumption(1:3,1)": 12.5,
147
+ "RefFuels": [fuel2, ],
148
+ "RefSystem": system,
149
+ })
150
+ study.add(plant3)
151
+
152
+ return study
153
+
154
+
155
+ if __name__ == "__main__":
156
+
157
+ case_path = get_case_path()
158
+ os.makedirs(case_path, exist_ok=True)
159
+ print("Creating example case... ", end="")
160
+ study = create_sddp_sample_case01()
161
+ print(" OK.")
162
+ print("Saving example case in \"{}\"... ".format(case_path), end="")
163
+ study.save(case_path)
164
+ print(" OK.")
@@ -0,0 +1,241 @@
1
+ """Creates SDDP 12 stages Case21 example."""
2
+ import copy
3
+ import os
4
+
5
+ import psr.factory
6
+
7
+
8
+ def get_case_path() -> str:
9
+ return os.path.join(os.path.splitext(os.path.basename(__file__))[0], "")
10
+
11
+
12
+ def create_sddp_sample_case21() -> psr.factory.Study:
13
+ # Create a study object and define its basic settings.
14
+ blocks = 1
15
+ # A context defines the dimensions of the study and the meaning of
16
+ # its stages. You can only share or copy data from one study to another
17
+ # if they share the same context.
18
+ context = psr.factory.get_new_context()
19
+ context.set("Models", ["SDDP", ]) # Default model: Sddp
20
+ context.set("Blocks", blocks) # Default number of blocks: 3
21
+ context.set("StageType", 2) # Weekly: 1, Monthly: 2 (default)
22
+
23
+ study = psr.factory.create_study(context)
24
+ study.set("Description", "SDDP")
25
+ study.set("InitialYear", 2016)
26
+ study.set("InitialStage", 1)
27
+ study.set("NumberOfStages", 12)
28
+ study.set("NumberOfSeries", 1)
29
+
30
+ # Study options
31
+ study.set("Type", 2)
32
+ study.set("InitialYearOfHydrology", 2016)
33
+ study.set("NumberOfSystems", 1)
34
+ study.set("AggregateInTheOperationPolicy", 1)
35
+ study.set("DeficitSegment", [100.0, 0.0, 0.0, 0.0])
36
+ study.set("DeficitCost", [1000.0, 0.0, 0.0, 0.0])
37
+ study.set("UMON", "$")
38
+
39
+ # Study duration
40
+ study.set("FixedDurationOfBlocks(1)", 100.0)
41
+
42
+ # By default, a study comes with one system.
43
+ system = study.get("System")[0]
44
+ system.code = 1
45
+ system.id = "s1"
46
+ system.name = "S1"
47
+ # System's currency
48
+ system.set("SystemCurrency", "$")
49
+ # It's not required to add an existing object to the study.
50
+
51
+ # Set study to run with this unique system
52
+ study.set("CodesOfPowerSystems", [1, ])
53
+
54
+ # Create a demand segment - it's required to add at least
55
+ # inelastic segment to a demand object.
56
+ segment = psr.factory.create("DemandSegment", context)
57
+ # Set demand and cost data.
58
+ segment.set_at("EnergyPerBlock(:)", "01/2016", 11.7)
59
+ segment.set_at("EnergyPerBlock(:)", "02/2016", 10.8)
60
+ segment.set_at("EnergyPerBlock(:)", "03/2016", 12.5)
61
+ segment.set_at("EnergyPerBlock(:)", "04/2016", 13.7)
62
+ segment.set_at("EnergyPerBlock(:)", "05/2016", 14.6)
63
+ segment.set_at("EnergyPerBlock(:)", "06/2016", 14.8)
64
+ segment.set_at("EnergyPerBlock(:)", "07/2016", 15.8)
65
+ segment.set_at("EnergyPerBlock(:)", "08/2016", 16.2)
66
+ segment.set_at("EnergyPerBlock(:)", "09/2016", 15.3)
67
+ segment.set_at("EnergyPerBlock(:)", "10/2016", 14.5)
68
+ segment.set_at("EnergyPerBlock(:)", "11/2016", 12.9)
69
+ segment.set_at("EnergyPerBlock(:)", "12/2016", 12.5)
70
+
71
+ segment.set_at("PricePerBlock(:)", "01/2016", 0.0)
72
+ # Add segment to the study.
73
+ study.add(segment)
74
+
75
+ # Create a system demand.
76
+ demand = psr.factory.create("Demand", context)
77
+ demand.code = 1
78
+ demand.name = "S1"
79
+ # Associate it with the only system in the case.
80
+ demand.set("RefSystem", system)
81
+ # Add segment to the demand.
82
+ demand.set("RefSegments", [segment, ])
83
+ # Add demand to the study.
84
+ study.add(demand)
85
+
86
+ # Create all fuels - Thermal plants requires them.
87
+ fuel1 = psr.factory.create("Fuel", context)
88
+ fuel1.code = 1
89
+ fuel1.name = "C1"
90
+ fuel1.set("Unit", "MWh")
91
+ fuel1.set("Price", 8.0)
92
+ fuel1.set("RefSystem", system)
93
+ study.add(fuel1)
94
+
95
+ fuel2 = psr.factory.create("Fuel", context)
96
+ fuel2.code = 2
97
+ fuel2.name = "C2"
98
+ fuel2.set("Unit", "MWh")
99
+ fuel2.set("Price", 12.0)
100
+ fuel2.set("RefSystem", system)
101
+ study.add(fuel2)
102
+
103
+ fuel3 = psr.factory.create("Fuel", context)
104
+ fuel3.code = 3
105
+ fuel3.name = "C3"
106
+ fuel3.set("Unit", "MWh")
107
+ fuel3.set("Price", 14.4)
108
+ fuel3.set("RefSystem", system)
109
+ study.add(fuel3)
110
+
111
+ # Create all thermal plants.
112
+ plant1 = psr.factory.create("ThermalPlant", context)
113
+ plant1.code = 1
114
+ plant1.name = "T1"
115
+ # Set plant's properties
116
+ plant1.set("MaximumGenerationCapacity", 12.0)
117
+ plant1.set("InstalledCapacity", 12.0)
118
+ plant1.set("ThermalType", 0) # Standard operation mode.
119
+ plant1.set("Type", 0) # It's an existing plant.
120
+ plant1.set("NumberOfGeneratingUnits", 1)
121
+ plant1.set("NumberOfAlternativeFuels", 0) # No alternative fuels
122
+ plant1.set("CodeOfAlternativeFuels(:)", 0)
123
+ plant1.set("O&MCost", 0.0)
124
+ plant1.set("FuelTransportationCost", 0.0)
125
+ plant1.set("SpecificConsumptionSegment(1)", 100.0)
126
+ plant1.set("SpecificConsumptionSegment(2:3)", 0.0)
127
+ plant1.set("SpecificConsumption(1:3,1)", 1.0)
128
+ plant1.set("Co2EmissionCoefficient", 1.0)
129
+ # It's required to associate a thermal plant to a fuel.
130
+ plant1.set("RefFuels", [fuel1, ])
131
+ plant1.set("RefSystem", system)
132
+ # These references are optional and can be set as None.
133
+ plant1.set("RefGasNode", None)
134
+ study.add(plant1)
135
+
136
+ plant2 = psr.factory.create("ThermalPlant", context)
137
+ plant2.code = 2
138
+ plant2.name = "T2"
139
+ plant2.set("MaximumGenerationCapacity", 8.0)
140
+ plant2.set("InstalledCapacity", 8.0)
141
+ plant2.set("ThermalType", 0)
142
+ plant2.set("Type", 0)
143
+ plant2.set("NumberOfGeneratingUnits", 1)
144
+ plant2.set("NumberOfAlternativeFuels", 0)
145
+ plant2.set("CodeOfAlternativeFuels(:)", 0)
146
+ plant2.set("O&MCost", 0.0)
147
+ plant2.set("FuelTransportationCost", 0.0)
148
+ plant2.set("SpecificConsumptionSegment(1)", 100.0)
149
+ plant2.set("SpecificConsumptionSegment(2:3)", 0.0)
150
+ plant2.set("SpecificConsumption(1:3,1)", 1.0)
151
+ plant2.set("Co2EmissionCoefficient", 1.0)
152
+ plant2.set("RefFuels", [fuel2, ])
153
+ plant2.set("RefSystem", system)
154
+ study.add(plant2)
155
+
156
+ plant3 = plant2.clone()
157
+ plant3.code = 3
158
+ plant3.name = "T3"
159
+ plant3.set("MaximumGenerationCapacity", 4.0)
160
+ plant3.set("InstalledCapacity", 4.0)
161
+ plant3.set("RefFuels", [fuel3, ])
162
+ plant3.set("RefSystem", system)
163
+ study.add(plant3)
164
+
165
+ # Define gauging station for hydro plants inflows
166
+ station1 = psr.factory.create("HydroStation", context)
167
+ station1.code = 1
168
+ station1.name = "Estacion 1"
169
+
170
+ station2 = psr.factory.create("HydroStation", context)
171
+ station2.code = 2
172
+ station2.name = "Estacion 2"
173
+
174
+ for year in (2014, 2015, 2016):
175
+ station1.set_at("Inflow", f"01/{year}", 13.5)
176
+ station1.set_at("Inflow", f"02/{year}", 40.7)
177
+ station1.set_at("Inflow", f"03/{year}", 28.8)
178
+ station1.set_at("Inflow", f"04/{year}", 25.6)
179
+ station1.set_at("Inflow", f"05/{year}", 23.8)
180
+ station1.set_at("Inflow", f"06/{year}", 27.8)
181
+ station1.set_at("Inflow", f"07/{year}", 28.8)
182
+ station1.set_at("Inflow", f"08/{year}", 18.8)
183
+ station1.set_at("Inflow", f"09/{year}", 18.2)
184
+ station1.set_at("Inflow", f"10/{year}", 29.6)
185
+ station1.set_at("Inflow", f"11/{year}", 17.7)
186
+ station1.set_at("Inflow", f"12/{year}", 26.3)
187
+
188
+ for month in range(1, 12 + 1):
189
+ station2.set_at("Vazao", f"{month:02d}/{year}", 0.0)
190
+
191
+ study.add(station1)
192
+ study.add(station2)
193
+
194
+ # Define hydroplants
195
+ hydro1 = psr.factory.create("HydroPlant", context)
196
+ hydro1.code = 1
197
+ hydro1.name = "H1"
198
+ hydro1.set("Type", 0)
199
+ hydro1.set("NumberOfUnits", 1)
200
+ hydro1.set("InstalledCapacity", 5.5)
201
+ hydro1.set("MaximumTurbinedOutflow", 55.0)
202
+ hydro1.set("MeanProductionCoefficient", 0.1)
203
+ hydro1.set("MinimumStorage", 0.0)
204
+ hydro1.set("MaximumStorage", 50.0)
205
+ hydro1.set("InitialCondition", 0.2)
206
+ hydro1.set("RefSystem", system)
207
+ hydro1.set("RefStation", station1)
208
+ study.add(hydro1)
209
+
210
+ hydro2 = hydro1.clone()
211
+ hydro2.code = 2
212
+ hydro2.name = "H2"
213
+ hydro2.set("MaximumStorage", 0.0)
214
+ hydro2.set("InitialCondition", 1.0)
215
+ hydro2.set("RefSystem", system)
216
+ hydro2.set("RefStation", station2)
217
+ study.add(hydro2)
218
+
219
+ # Connect hydro plants
220
+ connection_spill = psr.factory.create("HydroPlantConnection", context)
221
+ connection_spill.set("IsVertimento", 1)
222
+ connection_spill.set("RefPlants", [hydro1, hydro2])
223
+ study.add(connection_spill)
224
+
225
+ connection_turb = psr.factory.create("HydroPlantConnection", context)
226
+ connection_turb.set("IsTurbinamento", 1)
227
+ connection_turb.set("RefPlants", [hydro1, hydro2])
228
+ study.add(connection_turb)
229
+
230
+ return study
231
+
232
+
233
+ if __name__ == "__main__":
234
+ case_path = get_case_path()
235
+ os.makedirs(case_path, exist_ok=True)
236
+ print("Creating example case... ", end="")
237
+ study = create_sddp_sample_case21()
238
+ print(" OK.")
239
+ print("Saving example case in \"{}\"... ".format(case_path), end="")
240
+ study.save(case_path)
241
+ print(" OK.")
psr/runner/runner.py CHANGED
@@ -48,6 +48,7 @@ else:
48
48
  def _get_semver_version(version: str) -> Tuple[int, int, Union[int, str], Optional[str]]:
49
49
  def get_tag_from_part(part: str) -> Tuple[int, Optional[str]]:
50
50
  to_try = ("beta", "rc")
51
+ part = part.lower()
51
52
  for tag_name in to_try:
52
53
  if tag_name in part:
53
54
  tag_pos = part.lower().index(tag_name)
@@ -124,6 +125,7 @@ def _write_mpi_settings(mpi_file_path: Union[str, pathlib.Path], cluster_setting
124
125
 
125
126
  def run_sddp(case_path: Union[str, pathlib.Path], sddp_path: Union[str, pathlib.Path], **kwargs):
126
127
  case_path = os.path.abspath(str(case_path))
128
+
127
129
  sddp_path = str(sddp_path)
128
130
  parallel_run = kwargs.get("parallel_run", True)
129
131
  cluster_settings: Optional[Union[int, bool, Dict[str, int]]] = kwargs.get("cluster_settings", False)
@@ -133,10 +135,6 @@ def run_sddp(case_path: Union[str, pathlib.Path], sddp_path: Union[str, pathlib.
133
135
  exec_mode = kwargs.get("_mode", None)
134
136
  mpi_path = kwargs.get("mpi_path", __default_mpi_path)
135
137
 
136
- if os.name == 'nt':
137
- sddp_path_full = os.path.join(sddp_path, "Oper")
138
- else:
139
- sddp_path_full = sddp_path
140
138
  # Append last / if missing.
141
139
  case_path = os.path.join(os.path.abspath(case_path), "")
142
140
 
@@ -146,6 +144,14 @@ def run_sddp(case_path: Union[str, pathlib.Path], sddp_path: Union[str, pathlib.
146
144
 
147
145
  major, minor, patch, tag = _get_semver_version(get_sddp_version(sddp_path))
148
146
 
147
+ if os.name == 'nt':
148
+ if major >= 18:
149
+ sddp_path_full = os.path.join(sddp_path, r"sddp\Oper")
150
+ else:
151
+ sddp_path_full = os.path.join(sddp_path, "Oper")
152
+
153
+ else:
154
+ sddp_path_full = sddp_path
149
155
  with change_cwd(sddp_path_full):
150
156
  # Write MPI settings if required
151
157
  if parallel_run and cluster_settings is not None:
@@ -190,7 +196,10 @@ def run_sddp_convert_fcf(case_path: Union[str, pathlib.Path], sddp_path: Union[s
190
196
 
191
197
  def get_sddp_version(sddp_path: Union[str, pathlib.Path]) -> str:
192
198
  sddp_path = str(sddp_path)
193
- if os.name == 'nt':
199
+
200
+ if os.name == 'nt' and "18" in sddp_path:
201
+ sddp_path_full = os.path.join(sddp_path, "sddp/Oper")
202
+ elif os.name == 'nt':
194
203
  sddp_path_full = os.path.join(sddp_path, "Oper")
195
204
  else:
196
205
  sddp_path_full = sddp_path
@@ -1,30 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: psr-factory
3
- Version: 4.1.0b5
3
+ Version: 4.1.0b10
4
4
  Summary: PSR database management module.
5
5
  Author-email: "PSR Inc." <psrfactory@psr-inc.com>
6
- License: MIT License
7
-
8
- Copyright (c) 2025 PSR Factory
9
-
10
- Permission is hereby granted, free of charge, to any person obtaining a copy
11
- of this software and associated documentation files (the "Software"), to deal
12
- in the Software without restriction, including without limitation the rights
13
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
- copies of the Software, and to permit persons to whom the Software is
15
- furnished to do so, subject to the following conditions:
16
-
17
- The above copyright notice and this permission notice shall be included in all
18
- copies or substantial portions of the Software.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
- SOFTWARE.
27
-
6
+ License-Expression: MIT
28
7
  Project-URL: documentation, https://docs.psr-inc.com/factory/
29
8
  Keywords: psr,factory,sddp
30
9
  Classifier: Development Status :: 4 - Beta
@@ -40,13 +19,12 @@ Classifier: Topic :: Software Development
40
19
  Classifier: Topic :: Scientific/Engineering
41
20
  Classifier: Operating System :: Microsoft :: Windows
42
21
  Classifier: Operating System :: POSIX :: Linux
43
- Classifier: License :: OSI Approved :: MIT License
44
22
  Requires-Python: >=3.9
45
23
  Description-Content-Type: text/markdown
46
24
  License-File: LICENSE.txt
47
25
  Dynamic: license-file
48
26
 
49
- PSR Factory (version 4.1.0b5)
27
+ PSR Factory (version 4.1.0b10)
50
28
  ============================
51
29
 
52
30
  Factory is a library that helps to manage SDDP cases.
@@ -67,7 +45,7 @@ pip install psr-factory
67
45
  Or, if the package directly from the wheel (whl) file:
68
46
 
69
47
  ```bash
70
- pip install psr_factory-4.1.0b5-py3-none-win_amd64.whl
48
+ pip install psr_factory-4.1.0b10-py3-none-win_amd64.whl
71
49
  ```
72
50
 
73
51
  Factory will be available to all Python scripts in your system after importing it:
@@ -10,22 +10,26 @@ psr/cloud/status.py,sha256=vcI4B9S6wCt9maT5NNrVwYaEgGIvy6kkC1UVpJjYbtw,3607
10
10
  psr/cloud/tempfile.py,sha256=1IOeye0eKWnmBynK5K5FMWiTaEVhn4GbQ8_y0THEva0,3893
11
11
  psr/cloud/version.py,sha256=RG2RB_TfKD_2sF3BR3PpbFPEmlXkWUJOgqpsnMmcVsc,192
12
12
  psr/cloud/xml.py,sha256=dmBh4iRieORCctm1obz1EGA2QN-KkZlH5_dQfBud-AI,1847
13
- psr/factory/__init__.py,sha256=Nl98tVqyFGyljAkoVgYtYUwVArZB-Obb7_rO3Wd9BV4,218
14
- psr/factory/api.py,sha256=-OV9OhO5KrULPiaeKXGOkBp6stYFc5_tmY94dAV0dUY,97854
15
- psr/factory/factory.dll,sha256=GgrAE4-pGqeoZhMmpy-Wtu566H_j7WfmnlRfWLwZZK8,12822568
16
- psr/factory/factory.pmd,sha256=sJytMHoS-EfdIc5mMugV0XevFAakdaHQc0_3jznfmFk,230920
17
- psr/factory/factory.pmk,sha256=YTuSJNfwgn8BE8-LT3eIYSdjXgkGwNM_oiR_PWtW060,569213
13
+ psr/factory/__init__.py,sha256=3IuHvbSNQtfVOkCgi4Dh3YrbBpgn5OH8-mrH4JU5l0s,219
14
+ psr/factory/api.py,sha256=StGPIDNkWcDLIlbwAm9arok3netOqr1fFXZNeX1GNUA,98497
15
+ psr/factory/factory.dll,sha256=qiwYjYrm1_klZ7N3XTDeW-FBQWh5bXsKxt9mVR0aw-o,12964120
16
+ psr/factory/factory.pmd,sha256=Fe1cedVdYb6h8hEJTC0u1qz53JmZnTIOK1GmJuUNo2g,230965
17
+ psr/factory/factory.pmk,sha256=zYyK8QEMa-J2r_kvYuRiqVzGLqMAiav_DP6h7-2wtX8,570074
18
18
  psr/factory/factorylib.py,sha256=xnhCFTo4DpU0e5oHtIWMmc-kk6ThtNAUI3cxpDXrBKE,27497
19
- psr/factory/libcurl-x64.dll,sha256=UqPBLcXSpPLHkQ56dyxohB2wzH_37Lrwj3Kwl-QJtPE,5319208
19
+ psr/factory/libcurl-x64.dll,sha256=6MVf69XKZf-LWdjiCj9rv_bykkU9uSxA4BUC8uRBk1g,5317904
20
20
  psr/factory/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ psr/factory/samples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ psr/factory/samples/sddp_1_stage_case01.py,sha256=7-HsTZLISQXWyez-MAi6U6cw-83-fj223C-ci54jfi0,5109
23
+ psr/factory/samples/sddp_sample_case01.py,sha256=49C7w86EQT5IuguaNvt7mz7OqbVRhov5c3zb7_l12FE,4994
24
+ psr/factory/samples/sddp_sample_case21.py,sha256=La9I6PcyEUCXDJMB0Mtn98Pl2V0RGPMEHAhGpboPvU8,8757
21
25
  psr/psrfcommon/__init__.py,sha256=WXR560XQllIjtFpWd0jiJEbUAQIyh5-6lwj-42_J95c,200
22
26
  psr/psrfcommon/psrfcommon.py,sha256=NABM5ahvyfSizDC9c0Vu9dVK1pD_vOzIGFHL1oz2E1o,1464
23
27
  psr/psrfcommon/tempfile.py,sha256=5S13wa2DCLYTUdwbLm_KMBRnDRJ0WDlu8GO2BmZoNdg,3939
24
28
  psr/runner/__init__.py,sha256=kI9HDX-B_LMQJUHHylFHas2rNpWfNNa0pZXoIvX_Alw,230
25
- psr/runner/runner.py,sha256=fiuwKDRnqOLfV5UKJamLMZqm7PneeVjgEEmhpZbMm98,26340
29
+ psr/runner/runner.py,sha256=xmo8YtrVvR4wzTHmnEeWxZzBQb9oRgg3bK_sPAGBcko,26599
26
30
  psr/runner/version.py,sha256=mch2Y8anSXGMn9w72Z78PhSRhOyn55EwaoLAYhY4McE,194
27
- psr_factory-4.1.0b5.dist-info/licenses/LICENSE.txt,sha256=N6mqZK2Ft3iXGHj-by_MHC_dJo9qwn0URjakEPys3H4,1089
28
- psr_factory-4.1.0b5.dist-info/METADATA,sha256=E1t4BjFK8F8Lw8f6ZqqOvMdbHTiU8Z4CYDULRfpy1-c,3721
29
- psr_factory-4.1.0b5.dist-info/WHEEL,sha256=4cvAR2LpmdqpvXM0-t_4duJjmI_AlyeOb6Zx6aFyoSA,97
30
- psr_factory-4.1.0b5.dist-info/top_level.txt,sha256=Jb393O96WQk3b5D1gMcrZBLKJJgZpzNjTPoldUi00ck,4
31
- psr_factory-4.1.0b5.dist-info/RECORD,,
31
+ psr_factory-4.1.0b10.dist-info/licenses/LICENSE.txt,sha256=N6mqZK2Ft3iXGHj-by_MHC_dJo9qwn0URjakEPys3H4,1089
32
+ psr_factory-4.1.0b10.dist-info/METADATA,sha256=J6xav8iS4WuFmukp5fvEaxPoUYWZshxodXwpR8THzM4,2429
33
+ psr_factory-4.1.0b10.dist-info/WHEEL,sha256=ZjXRCNaQ9YSypEK2TE0LRB0sy2OVXSszb4Sx1XjM99k,97
34
+ psr_factory-4.1.0b10.dist-info/top_level.txt,sha256=Jb393O96WQk3b5D1gMcrZBLKJJgZpzNjTPoldUi00ck,4
35
+ psr_factory-4.1.0b10.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.4.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-win_amd64
5
5