Skip to content

Commit

Permalink
Integrate pypower solver (#172)
Browse files Browse the repository at this point in the history
Signed-off-by: David P. Chassin <[email protected]>
  • Loading branch information
David P. Chassin authored Mar 13, 2024
1 parent 66429bd commit 5f094d6
Show file tree
Hide file tree
Showing 61 changed files with 4,847 additions and 6 deletions.
3 changes: 3 additions & 0 deletions converters/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ dist_pkgdata_DATA += converters/mdb-table2glm-player.py
# omd -> glm
dist_pkgdata_DATA += converters/omd2glm.py

# py->glm
dist_pkgdata_DATA += converters/py2glm.py

# tmy3 -> glm
dist_pkgdata_DATA += converters/tmy32glm.py

Expand Down
2 changes: 2 additions & 0 deletions converters/autotest/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ solver_nr_profile.csv
table2glm_input_noclass.glm
table2glm_input_noname.glm
table2glm_input.glm
pypower_casedata.py
pypower_results.py
133 changes: 133 additions & 0 deletions converters/py2glm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import json
import os
import sys, getopt
import datetime
import importlib, copy
from importlib import util


config = {"input":"py","output":"glm","type":["pypower"]}

def help():
return """py2glm.py -i <inputfile> -o <outputfile> [options...]
-c|--config output converter configuration data
-h|--help output this help
-i|--ifile <filename> [REQUIRED] PY input file
-o|--ofile <filename> [OPTIONAL] GLM output file name
-t|--type type of input file
-N|--name do not autoname objects
"""

def main():
filename_py = None
filename_glm = None
py_type = 'pypower'
autoname = True
try :
opts, args = getopt.getopt(sys.argv[1:],
"chi:o:t:N",
["config","help","ifile=","ofile=","type=","name"],
)
except getopt.GetoptError:
sys.exit(2)
if not opts :
print('ERROR [py2glm.py]: missing command arguments')
sys.exit(2)
for opt, arg in opts:
if opt in ("-c","--config"):
print(config)
sys.exit()
elif opt in ("-h","--help"):
print(help())
sys.exit()
elif opt in ("-i", "--ifile"):
filename_py = arg
elif opt in ("-o", "--ofile"):
filename_glm = arg
elif opt in ("-t", "--type"):
py_type = arg
elif opt in ("-N","--name"):
autoname = False
else :
print(f"ERROR [py2glm.py]: {opt}={arg} is not a valid option")
sys.exit(1)

if not filename_py:
print(f"ERROR [py2glm.py]: input filename not specified")
sys.exit(1)

try:
convert(
ifile = filename_py,
ofile = filename_glm,
options = dict(
py_type = py_type,
autoname = autoname),
)
except Exception as err:
print(f"ERROR [py2glm.py]: {err}")
import traceback
traceback.print_exception(err,file=sys.stderr)
sys.exit(9)

def convert(ifile,ofile,options={}):
"""Default converter is pypower case"""

py_type = options['py_type'] if 'py_type' in options else "pypower"
autoname = options['autoname'] if 'autoname' in options else True

assert(py_type in ['pypower'])

modspec = util.spec_from_file_location("glm",ifile)
modname = os.path.splitext(ifile)[0]
mod = importlib.import_module(os.path.basename(modname))
casedef = getattr(mod,os.path.basename(modname))
data = casedef()

NL='\n'
with open(ofile,"w") as glm:
glm.write(f"""// generated by {' '.join(sys.argv)}
module pypower
{{
version {data['version']};
baseMVA {data['baseMVA']};
}}
""")

for name,spec in dict(
# pypower properties must be in the save order as the case array columns
bus = "bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin",
gen = "bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min"\
+ " Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf",
branch = "fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax",
).items():
glm.write(f"{NL}//{NL}// {name}{NL}//{NL}")
for n,line in enumerate(data[name]):
oname = f"{NL} name pp_{name}_{n+1};" if autoname else ""
glm.write(f"""object pypower.{name}
{{{oname}
{NL.join([f" {x} {line[n]};" for n,x in enumerate(spec.split())])}
}}
""")
if 'gencost' in data:
glm.write("\n//\n// gencost\n//\n")
for n,line in enumerate(data['gencost']):
model = line[0]
startup = line[1]
shutdown = line[2]
count = line[3]
costs = line[4:]
assert(len(costs)==count)
oname = f"{NL} name pp_gencost_{n};" if autoname else ""
glm.write(f"""object pypower.gencost
{{{oname}
model {int(model)};
startup {startup};
shutdown {shutdown};
costs "{','.join([str(x) for x in costs])}";
}}
""")

if __name__ == '__main__':
main()

24 changes: 24 additions & 0 deletions docs/Converters/Import/PyPower_cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[[/Converters/Import/Ami_data]] -- AMI data import

# Synopsis

GLM:

~~~
#input "casefile.py" -t pypower [-N|--name]
~~~

Shell:

~~~
$ gridlabd convert -i inputfile.py -o outputfile.glm -t pypower [-N|--name]
~~~

# Description

The `py2glm.py` converter support conversion of PyPower case files to GLM
models. The `-N|--name` option suppresses autonaming of PyPower objects.

# See also

* [[/Module/Pypower]]
Loading

0 comments on commit 5f094d6

Please sign in to comment.