Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/NREL/PyDSS
Browse files Browse the repository at this point in the history
# Conflicts:
#	.idea/PyDSS-heco.iml
#	.idea/misc.xml
#	.idea/workspace.xml
#	LICENSE
#	PyDSS/PyPlots/Plots/FrequencySweep.py
#	PyDSS/PyPlots/Plots/GISplot.py
#	PyDSS/PyPlots/Plots/Histogram.py
#	PyDSS/PyPlots/Plots/SagPlot.py
#	PyDSS/PyPlots/Plots/TimeSeries.py
#	PyDSS/PyPlots/Plots/Topology.py
#	PyDSS/PyPlots/Plots/XYPlot.py
#	PyDSS/ResultContainer.py
#	PyDSS/SolveMode.py
#	PyDSS/dssInstance.py
#	PyDSS/pyAnalyzer/dssGraphicsGenerator.py
#	PyDSS/pyAnalyzer/dssPlots/dssFrequencySweep.py
#	PyDSS/pyAnalyzer/dssPlots/dssPDFplot.py
#	PyDSS/pyAnalyzer/dssPlots/dssProfilePlot.py
#	PyDSS/pyAnalyzer/dssSimulationResult.py
#	PyDSS/pyContrReader.py
#	PyDSS/pyControllers/Controllers/FaultController.py
#	PyDSS/pyControllers/Controllers/PvController.py
#	PyDSS/pyControllers/Controllers/PvControllerGen.py
#	PyDSS/pyControllers/Controllers/StorageController.py
#	build/lib/PyDSS/dssInstance.py
#	build/lib/pyControllers/HybridController.py
#	build/lib/pyControllers/StorageController.py
  • Loading branch information
Aadil Latif committed Nov 22, 2019
2 parents d4207cd + 98cba91 commit 6d8ed9a
Show file tree
Hide file tree
Showing 60 changed files with 5,214 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .idea/PyDSS-heco.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

748 changes: 745 additions & 3 deletions .idea/workspace.xml

Large diffs are not rendered by default.

12 changes: 11 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,20 @@ Copyright (c) 2018, Alliance for Sustainable Energy LLC, All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

<<<<<<< HEAD
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

- Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=======
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
180 changes: 180 additions & 0 deletions PyDSS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
from PyDSS.pyAnalyzer.dssSimulationResult import ResultObject
from PyDSS.pyAnalyzer.dssGraphicsGenerator import CreatePlots
from PyDSS import dssInstance
import subprocess
import click
import toml
import sys
import os



valid_settings = {
'Log Results' : {'type': bool, 'Options': [True, False]},
'Return Results': {'type': bool, 'Options': [True, False]},
'Export Mode': {'type': str, 'Options': ["byClass", "byElement"]},
'Export Style': {'type': str, 'Options': ["Single file", "Separate files"]},

'Create dynamic plots': {'type': bool, 'Options': [True, False]},
'Open plots in browser': {'type': bool, 'Options': [True, False]},

'Project Path': {'type': str},
'Start Year' : {'type': int, 'Options': range(1970, 2099)},
'Start Day' : {'type': int, 'Options': range(0, 365)},
'Start Time (min)' : {'type': float, 'Options': range(0, 1440)},
'End Day' : {'type': int, 'Options': range(0, 365)},
'End Time (min)' : {'type': float, 'Options': range(0, 1440)},
'Date offset' : {'type': int, 'Options': range(0, 365)},
'Step resolution (sec)' : {'type': float},
'Max Control Iterations' : {'type': int},
'Error tolerance' : {'type': float},
'Simulation Type' : {'type': str, 'Options': ["QSTS", "Dynamic", "Snapshot", "Monte Carlo"]},
'Active Project' : {'type': str},
'Active Scenario' : {'type': str},
'DSS File' : {'type': str},

'Co-simulation Mode': {'type': bool, 'Options': [True, False]},
'Federate name' : {'type': str},
'Time delta' : {'type': float},
'Core type' : {'type': str},
'Uninterruptible' : {'type': bool, 'Options': [True, False]},
'Helics logging level' : {'type': int, 'Options': range(0, 10)},


'Logging Level' : {'type': str, 'Options': ["DEBUG", "INFO", "WARNING" , "ERROR"]},
'Log to external file' : {'type': bool, 'Options': [True, False]},
'Display on screen' : {'type': bool, 'Options': [True, False]},
'Clear old log file' : {'type': bool, 'Options': [True, False]},

'Control mode' : {'type': str, 'Options': ["Static", "Time"]},
'Disable PyDSS controllers' : {'type': bool, 'Options': [True, False]},

'Enable frequency sweep' : {'type': bool, 'Options': [True, False]},
'Fundamental frequency' : {'type': int, 'Options': [50, 60]},
'Start frequency' : {'type': float},
'End frequency' : {'type': float},
'frequency increment' : {'type': float},
'Neglect shunt admittance' : {'type': bool, 'Options': [True, False]},
'Percentage load in series' : {'type': float, 'Options': range(0, 100)},

'Number of Monte Carlo scenarios' : {'type': int},
}

def RunSimulations(Batch_TOML_file):
settings_text = ''
f = open(Batch_TOML_file, "r")
text = settings_text.join(f.readlines())
Simulations_args = toml.loads(text)
f.close()
SimulationResults = {}

if Simulations_args['Simulations']['Run_bokeh_server']:
BokehServer = subprocess.Popen(["bokeh", "serve"], stdout=subprocess.PIPE)


for scenario in Simulations_args['Simulations']['Scenarios']:
dss_args, ResultObject = RunScenario(
scenario,
Simulations_args['Simulations']['Run_simulations'],
Simulations_args['Simulations']['Generate_visuals']
)
SimulationResults['{}-{}-{}-{}-{}'.format(
dss_args["Active Project"],
dss_args["Active Scenario"],
dss_args["Start Year"],
dss_args["Start Day"],
dss_args["End Day"],
)] = (dss_args, ResultObject)

if Simulations_args['Simulations']['Generate_visuals']:
CreatePlots(Simulations_args, SimulationResults)

if Simulations_args['Simulations']['Run_bokeh_server']:
BokehServer.terminate()
return


def RunScenario(Scenario_TOML_file_path, run_simulation=True, generate_visuals=False):
settings_text = ''
f = open(Scenario_TOML_file_path, "r")
text = settings_text.join(f.readlines())
dss_args = toml.loads(text, _dict=dict)
__validate_settings(dss_args)
dss_args["Start Time (min)"] += 0.3
dss_args["End Time (min)"] += 0.3
f.close()

if run_simulation:
dss = dssInstance.OpenDSS(**dss_args)
print('Running scenario: {}'.format(Scenario_TOML_file_path))
if dss_args['Simulation Type'] == "Monte Carlo":
#TODO: Fix the broken MC code
dss.RunMCsimulation(MCscenarios=dss_args['Number of Monte Carlo scenarios'])
else:
dss.RunSimulation()
dss.DeleteInstance()
del dss
# dss.CreateGraph(Visualize=True)

if generate_visuals:
return dss_args, ResultObject(os.path.join(
dss_args['Project Path'],
dss_args["Active Project"],
'Exports',
dss_args['Active Scenario']
))
else:
return dss_args, None

def __validate_settings(dss_args):
for key, ctype in dss_args.items():
assert (key in valid_settings), "'{}' is not a valid PyDSS argument".format(key)
assert (isinstance(ctype, valid_settings[key]['type'])), "'{}' can only be a '{}' data type. Was passed {}".format(
key, valid_settings[key]['type'], type(ctype)
)
if 'Options' in valid_settings[key]:
if isinstance(valid_settings[key]['Options'], list):
assert (ctype in (valid_settings[key]['Options'])),\
"Invalid argument value '{}'. Possible values are: {}".format(ctype ,valid_settings[key]['Options'])
elif isinstance(valid_settings[key]['Options'], range):
assert (min(valid_settings[key]['Options']) <= ctype <= max(valid_settings[key]['Options'])), \
"Value '{}' out of bounds for '{}'. Allowable range is: {}-{}".format(
ctype,
key,
min(valid_settings[key]['Options']),
max(valid_settings[key]['Options'])
)

for key, ctype in valid_settings.items():
assert (key in dss_args), "'{}' definition is missing in the TOML file".format(key)

assert (dss_args['End frequency'] >= dss_args['Start frequency']),\
"'End frequency' can not be smaller than 'Start frequency'"
assert (dss_args['End Day'] >= dss_args['Start Day']), \
"'End day' can not be smaller than 'Start day'"
assert (os.path.exists(dss_args['Project Path'])), \
"Project path {} does not exist.".format(dss_args['Project Path'])
assert (os.path.exists(os.path.join(dss_args['Project Path'], dss_args["Active Project"]))), \
"Project '{}' does not exist.".format(dss_args["Active Project"])

assert (os.path.exists(os.path.join(dss_args['Project Path'],
dss_args["Active Project"],
'PyDSS Scenarios',
dss_args['Active Scenario']))), \
"Scenario '{}' does not exist.".format( dss_args['Active Scenario'])

assert (os.path.exists(os.path.join(dss_args['Project Path'],
dss_args["Active Project"],
'DSSfiles',
dss_args['DSS File']))), \
"Master DSS file '{}' does not exist.".format(dss_args['DSS File'])
return

if __name__ == '__main__':
#Batch_file = r'C:\Users\alatif\Desktop\PyDSS-Projects\MySpohnTest\PyDSS Scenarios\PlotsTOML.toml'
#RunSimulations(Batch_file)
toml_file_path = r'C:\Users\alatif\Desktop\PyDSS-Projects\MySpohnTest\PyDSS Scenarios\helics\PyDSS_settings.toml'
RunScenario(toml_file_path)
print('End')
# process(sys.argv[3:])

23 changes: 23 additions & 0 deletions PyDSS/PyPlots/Plots/FrequencySweep.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<<<<<<< HEAD
from PyDSS.pyPlots.pyPlotAbstract import PlotAbstract
from bokeh.plotting import figure, curdoc
from bokeh.io import output_file
Expand All @@ -7,6 +8,21 @@
class FrequencySweep(PlotAbstract):
def __init__(self, PlotProperties, dssBuses, dssObjects, dssCircuit, dssSolver):
super(FrequencySweep).__init__()
=======
from bokeh.plotting import figure, curdoc
from bokeh.io import output_file
from bokeh.models import ColumnDataSource, ColorBar, \
LinearColorMapper, HoverTool, BoxSelectTool, BoxZoomTool, \
PanTool, WheelZoomTool, ResetTool, SaveTool, Label
from bokeh.palettes import Plasma
from bokeh.client import push_session
import pandas as pd
import numpy as np


class FrequencySweep:
def __init__(self, PlotProperties, dssBuses, dssObjects, dssCircuit, dssSolver):
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
self.__dssSolver = dssSolver
self.__dssBuses = dssBuses
self.__dssObjs = dssObjects
Expand Down Expand Up @@ -37,9 +53,12 @@ def __init__(self, PlotProperties, dssBuses, dssObjects, dssCircuit, dssSolver):
self.__time = dssSolver.GetDateTime()
return

<<<<<<< HEAD
def GetSessionID(self):
return self.session.id

=======
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
def getObjectValue(self, Obj, ObjPpty, Index):
pptyValue = Obj.GetVariable(ObjPpty)
if pptyValue is not None:
Expand Down Expand Up @@ -82,5 +101,9 @@ def UpdatePlot(self):
freq = self.__dssSolver.getFrequency()

self.data[self.__PlotProperties['Property']].append(yVal)
<<<<<<< HEAD
self.data['frequency'].append(freq[freq])
=======
self.data['frequency'].append(freq)
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
self.data_source.data = self.data
15 changes: 15 additions & 0 deletions PyDSS/PyPlots/Plots/GISplot.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<<<<<<< HEAD
from PyDSS.pyPlots.pyPlotAbstract import PlotAbstract
=======
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
from bokeh.models import ColumnDataSource, HoverTool, BoxSelectTool, PanTool, WheelZoomTool, MultiLine, Square, Circle,\
Triangle
#from bokeh.tile_providers import CARTODBPOSITRON
Expand All @@ -18,6 +21,7 @@
except ImportError:
print('Package pyproj not installed. Cannot use GISplot')
quit()
<<<<<<< HEAD

class GISplot(PlotAbstract):

Expand All @@ -30,6 +34,17 @@ def __init__(self,PlotProperties,dssBuses,dssObjectsByClass,dssCircuit, dssSolve
self.VoltagePhase = 0
self.CurrentPhase = 0

=======

class GISplot:
Vmin = 0.95
Vmax = 1.05
Imin = 0
Imax = 100
VoltagePhase = 0
CurrentPhase = 0
def __init__(self,PlotProperties,dssBuses,dssObjectsByClass,dssCircuit, dssSolver):
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
self.__dssBuses = dssBuses
self.__dssCircuit = dssCircuit
self.__PlotProperties = PlotProperties
Expand Down
8 changes: 8 additions & 0 deletions PyDSS/PyPlots/Plots/Histogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
import numpy as np
import math

<<<<<<< HEAD
class Histogram(PlotAbstract):
def __init__(self,PlotProperties, dssBuses, dssObjectsbyClass, dssCircuit, dssSolver):
super(Histogram).__init__()
=======
class Histogram:
def __init__(self,PlotProperties, dssBuses, dssObjectsbyClass, dssCircuit, dssSolver):
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
Data = []
self.__dssBuses = dssBuses
self.__PlotProperties = PlotProperties
Expand Down Expand Up @@ -68,9 +73,12 @@ def __init__(self,PlotProperties, dssBuses, dssObjectsbyClass, dssCircuit, dssSo
#self.session.show(self.__Figure)
return

<<<<<<< HEAD
def GetSessionID(self):
return self.session.id

=======
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
def GetFigure(self):
return self.__Figure

Expand Down
6 changes: 6 additions & 0 deletions PyDSS/PyPlots/Plots/SagPlot.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@
import numpy as np
import math

<<<<<<< HEAD
class SagPlot(PlotAbstract):
def __init__(self,PlotProperties, dssBuses, dssObjectsbyClass, dssCircuit, dssSolver):
super(SagPlot).__init__()
=======
class SagPlot:
def __init__(self,PlotProperties, dssBuses, dssObjectsbyClass, dssCircuit, dssSolver):

>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
self.__dssBuses = dssBuses
self.__PlotProperties = PlotProperties
self.__dssObjectsByClass = dssObjectsbyClass
Expand Down
5 changes: 5 additions & 0 deletions PyDSS/PyPlots/Plots/TimeSeries.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
from bokeh.palettes import Set1
from ast import literal_eval as LE

<<<<<<< HEAD
class TimeSeries(PlotAbstract):
def __init__(self,PlotProperties, dssBuses, dssObjects, dssCircuit, dssSolver):
super(TimeSeries).__init__()
=======
class TimeSeries:
def __init__(self,PlotProperties, dssBuses, dssObjects, dssCircuit, dssSolver):
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
self.__dssBuses = dssBuses
self.__dssObjs = dssObjects
self.__PlotProperties = PlotProperties
Expand Down
8 changes: 8 additions & 0 deletions PyDSS/PyPlots/Plots/Topology.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<<<<<<< HEAD
from PyDSS.pyPlots.pyPlotAbstract import PlotAbstract
=======
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
from bokeh.models import ColumnDataSource, ColorBar, \
LinearColorMapper, HoverTool, BoxSelectTool, BoxZoomTool, \
PanTool, WheelZoomTool, ResetTool, SaveTool, Label
Expand All @@ -7,9 +10,14 @@
import pandas as pd
import numpy as np

<<<<<<< HEAD
class Topology(PlotAbstract):
def __init__(self,PlotProperties,dssBuses,dssObjectsByClass,dssCircuit,dssSolver):
super(Topology).__init__()
=======
class Topology:
def __init__(self,PlotProperties,dssBuses,dssObjectsByClass,dssCircuit,dssSolver):
>>>>>>> 98cba91204224c1b5c9e477759bf012e2f70a369
self.__dssBuses = dssBuses
self.__dssCircuit = dssCircuit
self.__PlotProperties = PlotProperties
Expand Down
Loading

0 comments on commit 6d8ed9a

Please sign in to comment.