Skip to content

Commit

Permalink
moving ProtectionSettingsOptimizer solver to omf from monsterMicrogri…
Browse files Browse the repository at this point in the history
…dModel
  • Loading branch information
lilycatolson committed Apr 8, 2024
1 parent 02c9a2b commit 9aa564c
Show file tree
Hide file tree
Showing 9 changed files with 680 additions and 5 deletions.
6 changes: 3 additions & 3 deletions omf/models/microgridDesign.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,13 @@ def work(modelDir, inputDict):
#['om_cost_us_dollars_per_kwh'] = dieselOMCostKwh
scenario['ElectricLoad']['critical_loads_kw'] = jsonifiableCriticalLoad
# diesel has a quirk in how it gets inputted to REopt such that when strictly specified, allOutputData["sizeDiesel1"] = allInputData['dieselMax'] + allInputData['genExisting']
#todo: check if still true for reopt.jl
#todo: check if still true for reopt.jl => doesn't seem to be
#if dieselMax - genExisting > 0:
# scenario['Generator']['max_kw'] = dieselMax - genExisting
scenario['Generator']['max_kw'] = dieselMax # - genExisting
#else:
# scenario['Generator']['max_kw'] = 0
#if dieselMin - genExisting > 0:
# scenario['Generator']['min_kw'] = dieselMin - genExisting
scenario['Generator']['min_kw'] = dieselMin # - genExisting
#else:
# scenario['Generator']['min_kw'] = 0
#adding outage results (REopt.jl)
Expand Down
3 changes: 2 additions & 1 deletion omf/solvers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
from omf.solvers import VB
from omf.solvers import mohca_cl
from omf.solvers import sdsmc
from omf.solvers import reopt_jl
from omf.solvers import reopt_jl
from omf.solvers import protsetopt
17 changes: 17 additions & 0 deletions omf/solvers/protsetopt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
`omf.solvers.protsetopt`

Solver for Protection Settings Optimizer ( https://github.com/sandialabs/Protection-settings-optimizer )

### Installation :
```
python -m pip install git+https://github.com/lilycatolson/Protection-settings-optimizer.git
```

### Testing :

Integration testing framework located here: https://github.com/dpinney/monsterMicrogridModel/blob/main/mmm/tests/test_protsetopt.py

Testing in OMF :
```
python __init__.py
```
129 changes: 129 additions & 0 deletions omf/solvers/protsetopt/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import os, json
from dss import DSS as dssObj

try:
import RSO_pack
except ImportError:
from . import RSO_pack

thisDir = os.path.abspath(os.path.dirname(__file__))

# helper functions: modified from ProtectionSettingsOptimizer OpenDSS example

def runDSS( file ):
''' compiles and solves the given opendss file '''
dssText = dssObj.Text
dssCircuit = dssObj.ActiveCircuit
dssText.Command = 'clear'
dssText.Command = 'compile '+ file
dssText.Command = 'set maxcontroliter = 500'
dssText.Command = 'solve'
return dssText, dssCircuit

def parseSysInfo(SysInfo):
''' returns the Lines, Names, and Buses of the Relays and Reclosers in the circuit '''
Buses = SysInfo['Buses']
devLines = [x['MonitoredObj'].split('Line.')[1] for x in SysInfo['Relays']]
devLines += [x['MonitoredObj'].split('Line.')[1] for x in SysInfo['Recs']]
devNames = [x['Name'] for x in SysInfo['Relays']]
devNames += [x['Name'] for x in SysInfo['Recs']]
dev_BusV = [Buses[RSO_pack.index_dict(Buses,'Name',x['Bus1'])]['kV']*1e3 for x in SysInfo['Relays'] ]
dev_BusV += [Buses[RSO_pack.index_dict(Buses,'Name',x['Bus1'])]['kV']*1e3 for x in SysInfo['Recs'] ]
return Buses, devLines, devNames, dev_BusV

def parseFaultInfo(Buses):
''' returns the Names and Nodes of the Buses in the circuit '''
faultBuses = [x['Name'] for x in Buses]
faultBusPhases = [None]*len(faultBuses)
for ii in range(len(faultBuses)):
faultBusPhases[ii] = Buses[RSO_pack.index_dict(Buses,'Name',faultBuses[ii])]['nodes']
return faultBuses, faultBusPhases

def loadFaultCSV(FData, testPath):
''' copies the Fault data in FData to <testPath>/FData.csv'''
Fault_File_loc = os.path.normpath(os.path.join(testPath,'FData.csv'))
FData.to_csv(Fault_File_loc,index=False,header=False)
Fault_Data_CSV = RSO_pack.read_Fault_CSV_Data(Fault_File_loc)
return Fault_Data_CSV

def parseSwitchInfo(SysInfo):
''' returns the Lines and States of the switches in the circuit '''
#lines where switch = True
switchLines = [x['Name'] for x in SysInfo['Lines'] if x['isSwitch']]
#lines that are enabled
switchStates = [1 if x['Enabled'] else 0 for x in SysInfo['Lines'] if x['isSwitch']]
return switchLines, switchStates

def writeSettingsAndInfo(testPath, settings, old_info):
''' copies the settings and previous info to <testPath>/settings_rso_out.json and <testPath>old_info_rso_out.json '''
settingsFile = os.path.normpath(os.path.join(testPath, 'settings_rso_out.json'))
with open(settingsFile, "w") as f:
j = json.dumps(settings, default=str)
f.write(j)
infoFile = os.path.normpath(os.path.join(testPath, 'old_info_rso_out.json'))
with open(infoFile, "w") as f:
j = json.dumps(old_info, default=str)
f.write(j)

def run(testPath, testFile):
''' runs setting optimization on the given opendss file, given constant program setting inputs '''
#fault resistances to test
Fres = ['0.001','1']
#supported fault types
Fts = ['3ph','SLG','LL']

# program settings
Force_NOIBR = 1
#DOC = 0
enableIT = 0
CTI = 0.25
OTmax = 10
Sho_Plots=1
type_select = False
Fault_Res = ['R0_001','R1']
Min_Ip = [0.1,0.1]
Substation_bus = 'sourcebus'
initpop = None
SetDir=False

dssText, dssCircuit = runDSS(os.path.normpath(os.path.join(testPath, testFile)))
# collect system info from OpenDSS
SysInfo = RSO_pack.getSysInfo(dssCircuit)

Buses, devLines, devNames, dev_BusV = parseSysInfo(SysInfo)
Device_Data_CSV = RSO_pack.getDeviceData(dssCircuit,devNames,devLines,dev_BusV)

# collect fault data
faultBuses, faultBusPhases = parseFaultInfo(Buses)

FData = RSO_pack.getFaultInfo(dssCircuit,dssText,faultBuses,faultBusPhases,Fres,Fts,devLines,devNames,dev_BusV)
Fault_Data_CSV = loadFaultCSV(FData, testPath)

switchLines, switchStates = parseSwitchInfo(SysInfo)
settings,old_info = RSO_pack.runSettingsOptimizer(testPath,
switchStates,
switchLines,
Device_Data_CSV,
Fault_Data_CSV,
Fault_Res,
SysInfo,
Substation_bus,
Min_Ip,
enableIT,
Force_NOIBR,
CTI,
OTmax,
type_select,
SetDir,
Sho_Plots,
GA_initial_seed=initpop)

writeSettingsAndInfo(testPath, settings, old_info)

def _test():
testPath = os.path.normpath(os.path.join(thisDir, 'testFiles'))
testFile = 'IEEE34Test.dss'
run(testPath, testFile)

if __name__ == "__main__":
_test()
35 changes: 35 additions & 0 deletions omf/solvers/protsetopt/testFiles/IEEE34Test.dss
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
clear

Compile ieee34Mod2_Relays.dss
New Energymeter.M1 Line.Sw1 1

Transformer.reg1a.wdg=2 Tap=(0.00625 12 * 1 +) ! Tap 12
Transformer.reg1b.wdg=2 Tap=(0.00625 5 * 1 +) ! Tap 5
Transformer.reg1c.wdg=2 Tap=(0.00625 5 * 1 +) ! Tap 5
Transformer.reg2a.wdg=2 Tap=(0.00625 13 * 1 +) ! Tap 13
Transformer.reg2b.wdg=2 Tap=(0.00625 11 * 1 +) ! Tap 11
Transformer.reg2c.wdg=2 Tap=(0.00625 12 * 1 +) ! Tap 12

Set Controlmode=OFF ! prevents further tap changes



New Relay.Relay1 monitoredObj=line.Sw1
New Relay.Relay2A monitoredObj=line.Sw2a
New Relay.Relay2B monitoredObj=line.Sw2b
New Relay.Relay3 monitoredObj=line.Sw3
New Relay.Relay4 monitoredObj=line.Sw4
New Relay.Relay5 monitoredObj=line.Sw5
New Relay.Relay6 monitoredObj=line.Sw6


Buscoords IEEE34_BusXY.csv
solve


Set MarkTransformers=yes
Interpolate ! requires an energyMeter
!plot circuit Power max=2000 y y C1=$00FF0000


!Plot profile phases=all
47 changes: 47 additions & 0 deletions omf/solvers/protsetopt/testFiles/IEEE34_BusXY.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
SourceBus,-300,0
R1,-150,0
800,0,0
802,400,0
806,700,0
808,1000,0
810,1000,-800
812,1300,0
814,1600,0
850,2500,0
816,2900,0
R2a,2900,350
818,2900,400
R2b,2900,750
820,2900,800
822,2900,1100
R3,3150,0
824,3200,0
826,3500,0
828,3200,-1200
830,3700,-1200
854,4000,-1200
R4,4100,-1200
mid856,4200,-1200
856,4400,-1200
852,4000,-900
832,4000,-400
888,4700,-400
890,5000,-400
mid858,4000,-200
R5,4000,-100
858,4000,0
864,4000,400
834,4400,0
842,4400,400
844,4400,700
846,4400,1100
848,4400,1400
860,5000,0
mid836,5300,0
R6,5500,0
836,5600,0
840,6000,0
862,5600,-400
838,5600,-800
814r,2100,0
852r,4000,-600
Loading

0 comments on commit 9aa564c

Please sign in to comment.