Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 40b0c30

Browse files
author
wwang2
committedAug 5, 2024
improve dtrans
1 parent f34c764 commit 40b0c30

File tree

3 files changed

+111
-69
lines changed

3 files changed

+111
-69
lines changed
 

‎ditto/modify/system_structure.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ def set_nominal_voltages_recur(self, *args):
237237
]
238238
)
239239
num_phases = len(self.model[trans_name].windings[0].phase_windings)
240+
if self.model[trans_name].is_threephaseunit == 0:
241+
new_value = new_value *1.732
240242
if num_phases!=3:
241243
new_value = new_value *1.732
242244
print(f"1num_phases={num_phases}")
@@ -255,6 +257,9 @@ def set_nominal_voltages_recur(self, *args):
255257
]
256258
)
257259
num_phases = len(self.model[trans_name].windings[0].phase_windings)
260+
if self.model[trans_name].is_threephaseunit == 0: # wenbo added this because naming convention in synergi warehouse.mdb
261+
new_value = new_value *1.732
262+
258263
if num_phases!=3:
259264
new_value = new_value *1.732
260265
print(f"2trans_name={trans_name}")

‎ditto/readers/synergi/read.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,13 @@ def parse(self, model):
172172
NodeID = self.get_data("Node", "NodeId")
173173
NodeX = self.get_data("Node", "X")
174174
NodeY = self.get_data("Node", "Y")
175+
176+
177+
NodeX = self.get_data("Node", "Latitude") # lat
178+
NodeY = self.get_data("Node", "Longitude") # lon
179+
180+
181+
175182

176183
## Preferences ########
177184
LengthUnits = self.get_data("SAI_Equ_Control", "LengthUnits")
@@ -1990,16 +1997,19 @@ def parse(self, model):
19901997
print("--> Parsing Loads...")
19911998

19921999
load_bus_map = {}
2000+
bus_load_map = {}
19932001

19942002
previous_load = None # this line is to check dubplicated load from previous load
2003+
previous_downstream_load = None
19952004
for i, obj in enumerate(LoadName):
19962005
# Create a Load DiTTo object
19972006
api_load = Load(model)
1998-
# if obj.replace(" ", "_").lower() == '230632.0DF0'.lower():
1999-
# breakpoint()
2007+
# if obj.replace(" ", "_").lower() == '440723.1df0'.lower():
2008+
# print('hold')
20002009
# Set the name
20012010
api_load.name = "Load_" + obj.replace(" ", "_").lower()
20022011
if api_load.name == previous_load:
2012+
#continue
20032013
api_load.name = "Load_" + obj.replace(" ", "_").lower() + '_dup'
20042014

20052015
#print(f'load_name = {api_load.name}')
@@ -2122,6 +2132,15 @@ def parse(self, model):
21222132

21232133
if api_load.name not in load_bus_map:
21242134
load_bus_map[obj.replace(" ", "_").lower()] = [api_load.connecting_element, api_load.phase_loads]
2135+
2136+
downstream_load = [load.p for load in api_load.phase_loads]
2137+
2138+
if 'dup' in api_load.name:
2139+
bus_load_map[api_load.connecting_element] += np.array(downstream_load)
2140+
else:
2141+
bus_load_map[api_load.connecting_element] = downstream_load
2142+
2143+
#previous_downstream_load = downstream_load
21252144

21262145
# else: # wenbo edit: kva is not read in synergi
21272146
# # Create the PhaseLoad DiTTo object
@@ -2217,24 +2236,6 @@ def parse(self, model):
22172236
api_load.vmin = 0.65
22182237
api_load.vmax = 1.1
22192238

2220-
# print('phase_load.phase={}, phase_load.p={}, phase_load.q={}'.format(phase_load.phase, phase_load.p, phase_load.q))
2221-
2222-
# else:
2223-
#
2224-
# # if there is no load information, place a small load instead of writing zero to the load
2225-
# phase_load = PhaseLoad(model)
2226-
#
2227-
# # Set the Phase
2228-
# phase_load.phase = phase
2229-
#
2230-
# # Set P
2231-
# phase_load.p = 0.01
2232-
#
2233-
# # Set Q
2234-
# phase_load.q = 0.01
2235-
#
2236-
# # Add the PhaseLoad to the list
2237-
# api_load.phase_loads.append(phase_load)
22382239

22392240

22402241

@@ -2280,7 +2281,12 @@ def parse(self, model):
22802281
api_transformer.conn = ['wye' , 'wye']
22812282
api_transformer.kvas = api_transformer.ConnKvaPh
22822283

2283-
2284+
# check if kvas and ConnKvaPh is enough to carry the load, then update it if needed
2285+
bus_loads = bus_load_map[api_transformer.connecting_element]
2286+
need_kvas = bus_loads
2287+
if sum(api_transformer.kvas)<sum(need_kvas):
2288+
new_kvas = [float((int(str(int(num))[0]) + 1) * 10 ** (len(str(int(num))) - 1)) for num in need_kvas]
2289+
api_transformer.kvas = new_kvas
22842290
####################################################################################
22852291
# #
22862292
# CAPACITORS #

‎ditto/writers/opendss/write.py

Lines changed: 79 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def __init__(self, **kwargs):
104104
self.feeders_redirect = {}
105105
self.mv_load_voltage_dict = {}
106106
self.feeder_head_line = None
107-
self.model_dtrans = False
107+
self.model_dtrans = True # this will decide if model secondary / dtrans
108108

109109
self.write_distribution_transformers = True
110110
self.write_taps = False
@@ -372,8 +372,8 @@ def write_bus_coordinates(self, model, delimiter=","):
372372

373373
txt += "{name}{delimiter}{X}{delimiter}{Y}\n".format(
374374
name=re.sub("[^0-9a-zA-Z]+", "_", i.name.lower()),
375-
X=i.positions[0].long,
376-
Y=i.positions[0].lat,
375+
X=i.positions[0].lat,
376+
Y=i.positions[0].long,
377377
delimiter=delimiter,
378378
)
379379
feeder_text_map[substation_name + "_" + feeder_name] = txt
@@ -1141,23 +1141,28 @@ def write_dtransformers(self, model):
11411141
# if hasattr(i, "bus2") and i.bus2 is not None:
11421142
# txt += i.bus2 + ")"
11431143
if hasattr(i, "conn") and i.conn is not None:
1144-
txt += f" conn = ({i.conn[0]}, {i.conn[1]})"
1144+
txt += f" conns = ({i.conn[0]}, {i.conn[1]})"
11451145

11461146
if hasattr(i, "nominal_voltage") and i.nominal_voltage is not None:
11471147
#txt += f" kvs = ({i.nominal_voltage/1000}, 0.24)"
11481148
if hasattr(i, "phase_loads") and i.phase_loads is not None and len(i.phase_loads)==1:
11491149
try:
1150-
kv1 = self.mv_load_voltage_dict[i.name.split('DTran_')[1]]
1150+
kv1 = self.mv_load_voltage_dict[i.name.split('_')[1]]
11511151
except:
1152+
11521153
kv1 = 0
1153-
1154+
logger.warning('WARNING: There is kv1=0 in dtrans object!')
1155+
1156+
11541157
txt += f" kvs = ({kv1}, 0.24)"
11551158
else:
11561159
try:
1157-
kv1 = self.mv_load_voltage_dict[i.name.split('DTran_')[1]]
1160+
kv1 = self.mv_load_voltage_dict[i.name.split('_')[1]]
11581161
except:
1159-
kv1 = 0
1160-
txt += f" kvs = ({kv1}, 0.208)"
1162+
kv1 = 0
1163+
logger.warning('WARNING: There is kv1=0 in dtrans object!')
1164+
1165+
txt += f" kvs = ({kv1}, 0.416)"
11611166

11621167

11631168
if hasattr(i, "kvas") and i.kvas is not None:
@@ -1495,35 +1500,50 @@ def write_PVs(self, model):
14951500

14961501
# nominal voltage
14971502
if hasattr(i, "nominal_voltage") and i.nominal_voltage is not None:
1498-
if i.nominal_voltage < 300:
1499-
if hasattr(i, "phases") and i.phases is not None:
1500-
txt += " phases=1"
1501-
txt += " kV={kV}".format(
1502-
kV=i.nominal_voltage * 10**-3
1503-
) # DiTTo in volts
1504-
else:
1505-
if hasattr(i, "phases") and i.phases is not None:
1506-
txt += " phases=3"
1507-
txt += " kV={kV}".format(
1508-
kV=i.nominal_voltage * 10**-3
1509-
) # DiTTo in volts
1503+
if hasattr(i, "phases") and i.phases is not None:
1504+
txt += f" phases={len(i.phases)}"
1505+
if len(i.phases) == 1:
1506+
txt +=f" kV={round(i.nominal_voltage * 10**-3/1.732,2)}"
1507+
else:
1508+
txt += f" kV={i.nominal_voltage * 10**-3}" # DiTTo in volts
1509+
1510+
# if i.nominal_voltage < 300:
1511+
# if hasattr(i, "phases") and i.phases is not None:
1512+
# txt += " phases=1"
1513+
# txt += " kV={kV}".format(
1514+
# kV=i.nominal_voltage * 10**-3
1515+
# ) # DiTTo in volts
1516+
# else:
1517+
# if hasattr(i, "phases") and i.phases is not None:
1518+
# txt += " phases=3"
1519+
# txt += " kV={kV}".format(
1520+
# kV=i.nominal_voltage * 10**-3
1521+
# ) # DiTTo in volts
15101522
if not substation_name + "_" + feeder_name in self._baseKV_feeders_:
15111523
self._baseKV_feeders_[
15121524
substation_name + "_" + feeder_name
15131525
] = set()
1514-
if (
1515-
i.nominal_voltage < 300
1516-
): # Line-Neutral voltage for 120 V (i.e. 240V)
1517-
self._baseKV_.add(i.nominal_voltage * 10**-3)
1518-
self._baseKV_feeders_[substation_name + "_" + feeder_name].add(
1519-
i.nominal_voltage * 2 * 10**-3
1520-
)
1521-
else:
1522-
self._baseKV_.add(i.nominal_voltage * 10**-3)
1523-
self._baseKV_feeders_[substation_name + "_" + feeder_name].add(
1524-
i.nominal_voltage * 10**-3
1525-
)
1526+
# if (
1527+
# i.nominal_voltage < 300
1528+
# ): # Line-Neutral voltage for 120 V (i.e. 240V)
1529+
# self._baseKV_.add(i.nominal_voltage * 10**-3)
1530+
# self._baseKV_feeders_[substation_name + "_" + feeder_name].add(
1531+
# i.nominal_voltage * 2 * 10**-3
1532+
# )
1533+
# else:
1534+
# self._baseKV_.add(i.nominal_voltage * 10**-3)
1535+
# self._baseKV_feeders_[substation_name + "_" + feeder_name].add(
1536+
# i.nominal_voltage * 10**-3
1537+
# )
1538+
self._baseKV_.add(i.nominal_voltage * 10**-3)
1539+
self._baseKV_feeders_[substation_name + "_" + feeder_name].add(
1540+
i.nominal_voltage * 10**-3
1541+
)
1542+
15261543
else:
1544+
logger.warning(
1545+
"Warning - check PV definition, possible no kv defined."
1546+
)
15271547
parent = model[i.connecting_element]
15281548
if (
15291549
hasattr(parent, "nominal_voltage")
@@ -1563,7 +1583,7 @@ def write_PVs(self, model):
15631583

15641584
if hasattr(i, "active_rating") and i.active_rating is not None:
15651585
pf_local = 1.0
1566-
if i.power_factor is not None:
1586+
if i.power_factor is not None and i.power_factor > 0:
15671587
pf_local = abs(i.power_factor)
15681588
txt += " kVA={kva}".format(
15691589
kva=i.active_rating / pf_local * 10**-3
@@ -1578,23 +1598,30 @@ def write_PVs(self, model):
15781598
** -3 # Set the inverter to be oversized by 10% if active rating not specified
15791599
) # DiTTo in watts
15801600

1601+
else:
1602+
# wenbo note: if no active rating, kva need to be defined still.
1603+
pf_local = 1.0
1604+
txt += " kVA={kva}".format(
1605+
kva=i.rated_power / pf_local * 10**-3
1606+
) # DiTTo in watts
1607+
15811608
if hasattr(i, "rated_power") and i.rated_power is not None:
15821609
txt += " Pmpp={kw}".format(
15831610
kw=i.rated_power
15841611
* 10
15851612
** -3 # Set the inverter to be oversized by 10% if active rating not specified
15861613
) # DiTTo in watts
15871614

1588-
if hasattr(i, "reactive_rating") and i.reactive_rating is not None:
1589-
if self.opendss_version >= 9:
1590-
kvarlimit_key = " kvarMax="
1591-
else:
1592-
kvarlimit_key = " kvarlimit="
1593-
txt += kvarlimit_key + "{kvar}".format(
1594-
kvar=i.reactive_rating
1595-
* 10
1596-
** -3 # Set the inverter to be oversized by 10% if active rating not specified
1597-
) # DiTTo in watts
1615+
# if hasattr(i, "reactive_rating") and i.reactive_rating is not None:
1616+
# if self.opendss_version >= 9:
1617+
# kvarlimit_key = " kvarMax="
1618+
# else:
1619+
# kvarlimit_key = " kvarlimit="
1620+
# txt += kvarlimit_key + "{kvar}".format(
1621+
# kvar=i.reactive_rating
1622+
# * 10
1623+
# ** -3 # Set the inverter to be oversized by 10% if active rating not specified
1624+
# ) # DiTTo in watts
15981625

15991626
# connection type
16001627
if hasattr(i, "connection_type") and i.connection_type is not None:
@@ -1636,7 +1663,7 @@ def write_PVs(self, model):
16361663
if hasattr(i, "control_type") and (
16371664
i.control_type is None or i.control_type == "powerfactor"
16381665
): # use powerfactor as default mode
1639-
if hasattr(i, "power_factor") and i.power_factor is not None:
1666+
if hasattr(i, "power_factor") and i.power_factor is not None and i.power_factor>0:
16401667
txt += " Model=1 pf={power_factor}".format(
16411668
power_factor=i.power_factor
16421669
)
@@ -2086,11 +2113,14 @@ def write_loads(self, model):
20862113

20872114
# Name
20882115
if hasattr(i, "name") and i.name is not None:
2116+
2117+
20892118
if i.name not in load_list:
20902119

20912120
txt += "New Load." + i.name
20922121
load_list.append(i.name)
20932122
else:
2123+
continue
20942124
txt += "New Load." + i.name + '_dup'
20952125
#print(f"i.name = {i.name}")
20962126
else:
@@ -2145,22 +2175,23 @@ def write_loads(self, model):
21452175
#print(f"i.phase_loads length = {len(i.phase_loads)}")
21462176
if self.model_dtrans:
21472177
if i.nominal_voltage < 300:
2178+
21482179
txt += " kV={volt}".format(volt=i.nominal_voltage * 10**-3)
21492180
# Wenbo: This is added because single phase load should be L-N, not L-L
21502181
elif hasattr(i, "phase_loads") and i.phase_loads is not None and len(i.phase_loads)==1:
21512182
#txt += " kV={volt}".format(volt=round(i.nominal_voltage * 10**-3/math.sqrt(3),2))
21522183
txt += " kV=0.24"
21532184
self.mv_load_voltage_dict[i.name.split('Load_')[1]] = round(i.nominal_voltage * 10**-3/1.732,2)
21542185
elif hasattr(i, "phase_loads") and i.phase_loads is not None and len(i.phase_loads)>1:
2155-
txt += " kV=0.208"
2186+
txt += " kV=0.416"
21562187
self.mv_load_voltage_dict[i.name.split('Load_')[1]] = round(i.nominal_voltage * 10**-3,2)
21572188
#txt += " kV={volt}".format(volt=i.nominal_voltage * 10**-3)
21582189
else:
21592190
if i.nominal_voltage < 300:
21602191
txt += " kV={volt}".format(volt=i.nominal_voltage * 10**-3)
21612192
# Wenbo: This is added because single phase load should be L-N, not L-L
21622193
elif hasattr(i, "phase_loads") and i.phase_loads is not None and len(i.phase_loads)==1:
2163-
txt += " kV={volt}".format(volt=round(i.nominal_voltage * 10**-3/math.sqrt(3),2))
2194+
txt += " kV={volt}".format(volt=round(i.nominal_voltage * 10**-3/math.sqrt(3),2))
21642195
else:
21652196
txt += " kV={volt}".format(volt=i.nominal_voltage * 10**-3)
21662197

@@ -4277,7 +4308,7 @@ def write_master_file(self, model):
42774308
):
42784309
fp.write("Redirect {file}\n".format(file=file))
42794310

4280-
_baseKV_list_ = list(self._baseKV_) + [0.208, 0.416]
4311+
_baseKV_list_ = list(self._baseKV_) + [0.24, 0.416]
42814312
_baseKV_list_ = sorted(_baseKV_list_)
42824313
fp.write("\nSet Voltagebases={}\n".format(_baseKV_list_))
42834314

0 commit comments

Comments
 (0)