Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work on making a pip installable HERON package. #216

Merged
merged 19 commits into from
Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
42415d5
Switching main stuff to function.
joshua-cogliati-inl Oct 11, 2022
e478f57
Updating several places that used raven loc to set path.
joshua-cogliati-inl Oct 11, 2022
51c97b8
Add docstring.
joshua-cogliati-inl Oct 11, 2022
95a16bf
Allow getting directory (but print warning.)
joshua-cogliati-inl Oct 11, 2022
bcbe317
Load externalROMloader lazily.
joshua-cogliati-inl Oct 11, 2022
10b2698
importing FARM.src is more reliable to check for FARM.
joshua-cogliati-inl Oct 11, 2022
521fb93
Reverting lazy loading of exteralROMloader
joshua-cogliati-inl Oct 11, 2022
0d17603
externalROMloader was used to open a pickle file.
joshua-cogliati-inl Oct 12, 2022
6af7fd9
Switching to ROMLoader.
joshua-cogliati-inl Oct 12, 2022
6446ff2
Switching to using ROMLoader.
joshua-cogliati-inl Oct 12, 2022
f459ae6
Switching to ROMLoader.
joshua-cogliati-inl Oct 12, 2022
71c5efb
Updates for use as pip package.
joshua-cogliati-inl Oct 13, 2022
150e7ad
Use path relative to working directory.
joshua-cogliati-inl Oct 13, 2022
e502808
Allow a list of solvers to try.
joshua-cogliati-inl Oct 13, 2022
fb5abaa
Check that execuatble exists, otherwise check if in path.
joshua-cogliati-inl Oct 13, 2022
e49478c
Fixing logic for finding solver.
joshua-cogliati-inl Oct 13, 2022
320fe11
Ignoring some more files generated by testing.
joshua-cogliati-inl Oct 13, 2022
764ce1c
Reduce memory consumption by memoizing get_synthhist_structure
dylanjm Oct 13, 2022
49361b9
Removing commented out code.
joshua-cogliati-inl Oct 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@ __pycache__
tests/integration_tests/mechanics/optimizedDispatch2Hybrid/hybrid_compatible_dispatch.txt
tests/integration_tests/mechanics/optimizedDispatch2Hybrid/user_input.txt
/tests/integration_tests/workflows/HERD/*/*.csv
tests/integration_tests/mechanics/hybrid_load/heron_input.xml
tests/integration_tests/workflows/HERD/nuclearCase_Sine/temp_initialized_model.json
tests/integration_tests/workflows/HERD/nuclearCase_notebook_match/temp_initialized_model.json
7 changes: 5 additions & 2 deletions src/Cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@
from HERON.src.validators.Factory import get_class as get_validator

import HERON.src._utils as hutils
framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
try:
import ravenframework
except ModuleNotFoundError:
framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
from ravenframework.utils import InputData, InputTypes

class Case(Base):
Expand Down
7 changes: 5 additions & 2 deletions src/Components.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
from HERON.src.ValuedParamHandler import ValuedParamHandler
from HERON.src import _utils as hutils

framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
try:
import ravenframework
except ModuleNotFoundError:
framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
from ravenframework.utils import InputData, xmlUtils,InputTypes

# TODO can we use EntityFactory from RAVEN?
Expand Down
20 changes: 12 additions & 8 deletions src/DispatchManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@
from . import _utils as hutils
from . import SerializationManager

raven_path = hutils.get_raven_loc()
sys.path.append(raven_path)
from ravenframework.PluginBaseClasses.ExternalModelPluginBase import ExternalModelPluginBase
sys.path.pop()

cashflow_path = os.path.abspath(os.path.join(hutils.get_cashflow_loc(raven_path=raven_path), '..'))
sys.path.append(cashflow_path)
import TEAL
try:
from ravenframework.PluginBaseClasses.ExternalModelPluginBase import ExternalModelPluginBase
import TEAL
except ModuleNotFoundError:
raven_path = hutils.get_raven_loc()
sys.path.append(raven_path)
from ravenframework.PluginBaseClasses.ExternalModelPluginBase import ExternalModelPluginBase
sys.path.pop()

cashflow_path = os.path.abspath(os.path.join(hutils.get_cashflow_loc(raven_path=raven_path), '..'))
sys.path.append(cashflow_path)
import TEAL
from TEAL.src import CashFlows
from TEAL.src.main import run as CashFlow_run

Expand Down
7 changes: 5 additions & 2 deletions src/Economics.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
from HERON.src import ValuedParams
from HERON.src.ValuedParamHandler import ValuedParamHandler
import HERON.src._utils as hutils
framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
try:
import ravenframework
except ModuleNotFoundError:
framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
from ravenframework.utils import InputData, xmlUtils,InputTypes


Expand Down
15 changes: 8 additions & 7 deletions src/Herd.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
from pyomo.opt import SolverFactory
import numpy as np
import _utils as hutils
path_to_raven = hutils.get_raven_loc()
sys.path.append(path.abspath(path.join(path_to_raven, 'scripts')))
sys.path.append(path.abspath(path.join(path_to_raven, 'plugins')))
sys.path.append(path_to_raven)
try:
import ravenframework
except ModuleNotFoundError:
path_to_raven = hutils.get_raven_loc()
sys.path.append(path.abspath(path.join(path_to_raven, 'plugins')))
sys.path.append(path_to_raven)
from ravenframework.utils import xmlUtils
import externalROMloader as ROMloader
from ravenframework.ROMExternal import ROMLoader

# Nuclear flowsheet function imports
# NOTE: these paths will change for next DISPATCHES release
Expand Down Expand Up @@ -282,8 +284,7 @@ def sample_from_ROM(self, signal, multiplier):

# Initializing ravenROMexternal object gives PATH access to xmlUtils
target_file = getattr(source, "_target_file")
runner = ROMloader.ravenROMexternal( binaryFileName=target_file,
whereFrameworkIs=hutils.get_raven_loc())
runner = ROMLoader( binaryFileName=target_file)

# TODO expand to change other pickledROM settings withing this method
inp = {'scaling': [1]}
Expand Down
16 changes: 8 additions & 8 deletions src/Moped.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@

from HERON.src import _utils as hutils
from HERON.src.base import Base
path_to_raven = hutils.get_raven_loc()
sys.path.append(os.path.abspath(os.path.join(path_to_raven, 'scripts')))
sys.path.append(os.path.abspath(os.path.join(path_to_raven, 'plugins')))
sys.path.append(path_to_raven)
try:
import ravenframework
except ModuleNotFoundError:
path_to_raven = hutils.get_raven_loc()
sys.path.append(os.path.abspath(os.path.join(path_to_raven, 'plugins')))
sys.path.append(path_to_raven)
from TEAL.src import main as RunCashFlow
from TEAL.src import CashFlows
import externalROMloader as ROMloader
from ravenframework.ROMExternal import ROMLoader
from ravenframework.MessageHandler import MessageHandler

class MOPED(Base):
Expand Down Expand Up @@ -153,9 +155,7 @@ def loadSyntheticHistory(self, signal, multiplier):
if signal not in self._sources[0]._var_names:
raise IOError('The requested signal name is not available'
'from the synthetic history, check DataGenerators node in input')
# Initializing ravenROMexternal object gives PATH access to xmlUtils
runner = ROMloader.ravenROMexternal(self._sources[0]._target_file,
hutils.get_raven_loc())
runner = ROMLoader(self._sources[0]._target_file)
from ravenframework.utils import xmlUtils
inp = {'scaling': [1]}
# TODO expand to change other pickledROM settings withing this method
Expand Down
16 changes: 9 additions & 7 deletions src/Placeholders.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
import HERON.src._utils as hutils
from HERON.src.base import Base

FRAMEWORK_PATH = hutils.get_raven_loc()
sys.path.append(FRAMEWORK_PATH)
try:
import ravenframework
except ModuleNotFoundError:
FRAMEWORK_PATH = hutils.get_raven_loc()
sys.path.append(FRAMEWORK_PATH)
from ravenframework.utils import InputData, InputTypes, utils, xmlUtils
sys.path.pop()

sys.path.append(os.path.join(FRAMEWORK_PATH, 'scripts'))
from externalROMloader import ravenROMexternal
sys.path.pop()
from ravenframework.ROMExternal import ROMLoader


class Placeholder(Base):
"""
Expand Down Expand Up @@ -379,7 +380,8 @@ def read_input(self, xml):
@ Out, None
"""
super().read_input(xml)
self._runner = ravenROMexternal(self._target_file, FRAMEWORK_PATH)

self._runner = ROMLoader(self._target_file)
# TODO is this serializable? or get/set state for this?

def evaluate(self, rlz):
Expand Down
7 changes: 5 additions & 2 deletions src/ValuedParamHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
from HERON.src.ValuedParams import Parametric
from HERON.src.ValuedParams import factory as VPFactory

framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
try:
import ravenframework
except ModuleNotFoundError:
framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
from ravenframework.utils import InputData, InputTypes
from ravenframework.BaseClasses import MessageUser

Expand Down
7 changes: 5 additions & 2 deletions src/ValuedParams/ValuedParam.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
"""
import sys
from HERON.src import _utils as hutils
framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
try:
import ravenframework
except ModuleNotFoundError:
framework_path = hutils.get_raven_loc()
sys.path.append(framework_path)
from ravenframework.utils import InputData, InputTypes
from ravenframework.BaseClasses import MessageUser

Expand Down
24 changes: 18 additions & 6 deletions src/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import importlib
import xml.etree.ElementTree as ET
import warnings
import pickle
from functools import cache
from os import path

import pandas as pd
Expand All @@ -28,6 +30,14 @@ def get_raven_loc():
@ In, None
@ Out, loc, string, absolute location of RAVEN
"""
try:
import ravenframework
print("WARNING: get_raven_loc deprecated")
import traceback
traceback.print_stack()
return path.dirname(ravenframework.__path__[0])
except ModuleNotFoundError:
pass
config = path.abspath(path.join(path.dirname(__file__),'..','.ravenconfig.xml'))
if not path.isfile(config):
raise IOError(
Expand Down Expand Up @@ -107,6 +117,7 @@ def get_project_lifetime(case, components):
econ_settings.setParams(econ_params)
return getProjectLength(econ_settings, econ_comps)

@cache
def get_synthhist_structure(fpath):
"""
Extracts synthetic history info from ROM (currently ARMA ROM)
Expand All @@ -115,12 +126,13 @@ def get_synthhist_structure(fpath):
"""
# TODO could this be a function of the ROM itself?
# TODO or could we interrogate the ROM directly instead of the XML?
raven_loc = get_raven_loc()
from externalROMloader import ravenROMexternal as ravenROM
# Why should we get warnings from RAVEN when we are just trying to write an input file.
with warnings.catch_warnings():
warnings.simplefilter('ignore')
rom = ravenROM(fpath, raven_loc).rom
try:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that this method gets called repeatedly in the DispatchManager.py for each ARMA realization. I was able to reduce quite a significant amount of memory consumption by memoizing this function. Instead of making a whole new PR, it might be worth to just add here. All you need to do is:

at the top in the imports:

from functools import cache

and then add the decorator to the function:

@cache
get_synthhist_structure

Copy link
Collaborator

@PaulTalbot-INL PaulTalbot-INL Oct 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ohhh, because RAVEN runs this each time instead of once ever ... maybe Mohammad's work will fix this to some degree. Good catch.

Does cacheing fix this if parallelized?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed: 764ce1c

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty should this cache is per process, so non-shared memory parallelism would have to cache it multiple times.

import ravenframework
except ModuleNotFoundError:
#If ravenframework not in path, need to add, otherwise loading rom will fail
raven_path = hutils.get_raven_loc()
sys.path.append(os.path.expanduser(raven_path))
rom = pickle.load(open(fpath, 'rb'))

structure = {}
meta = rom.writeXML().getRoot()
Expand Down
7 changes: 5 additions & 2 deletions src/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
import sys

import HERON.src._utils as hutils
raven_path = hutils.get_raven_loc()
sys.path.append(os.path.expanduser(raven_path))
try:
import ravenframework
except ModuleNotFoundError:
raven_path = hutils.get_raven_loc()
sys.path.append(os.path.expanduser(raven_path))
from ravenframework.BaseClasses import MessageUser


Expand Down
26 changes: 16 additions & 10 deletions src/dispatch/pyomo_dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
# allows pyomo to solve on threaded processes
import pyutilib.subprocess.GlobalData
pyutilib.subprocess.GlobalData.DEFINE_SIGNAL_HANDLERS_DEFAULT = False
from pyutilib.common._exceptions import ApplicationError
from pyomo.common.errors import ApplicationError

from .Dispatcher import Dispatcher
from .DispatchState import DispatchState, NumpyState
Expand All @@ -33,9 +33,9 @@

# Choose solver; CBC is a great choice unless we're on Windows
if platform.system() == 'Windows':
SOLVER = 'glpk'
SOLVERS = ['glpk', 'cbc', 'ipopt']
else:
SOLVER = 'cbc'
SOLVERS = ['cbc', 'glpk', 'ipopt']


class Pyomo(Dispatcher):
Expand Down Expand Up @@ -109,15 +109,21 @@ def read_input(self, specs):
if solver_node is not None:
self._solver = solver_node.value

# check solver exists
if self._solver is None:
self._solver = SOLVER
found_solver = True
try:
if not pyo.SolverFactory(self._solver).available():
solvers_to_check = SOLVERS
else:
solvers_to_check = [self._solver]
# check solver exists
for solver in solvers_to_check:
self._solver = solver
found_solver = True
try:
if not pyo.SolverFactory(self._solver).available():
found_solver = False
else:
break
except ApplicationError:
found_solver = False
except ApplicationError:
found_solver = False
# NOTE: we probably need a consistent way to test and check viable solvers,
# maybe through a unit test that mimics the model setup here. For now, I assume
# that anything that shows as not available or starts with an underscore is not
Expand Down
9 changes: 6 additions & 3 deletions src/input_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
from . import ValuedParams

from . import _utils as hutils
raven_path = hutils.get_raven_loc()
sys.path.append(raven_path)
try:
import ravenframework
except ModuleNotFoundError:
raven_path = hutils.get_raven_loc()
sys.path.append(raven_path)
from ravenframework.utils import xmlUtils
sys.path.pop()



def load(name):
Expand Down
16 changes: 14 additions & 2 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@

sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
import HERON.src._utils as hutils
sys.path.append(hutils.get_raven_loc())
try:
import ravenframework
except ModuleNotFoundError:
sys.path.append(hutils.get_raven_loc())

from HERON.src import input_loader
from HERON.src.base import Base
Expand Down Expand Up @@ -130,7 +133,12 @@ def run_dispatches_workflow(self):
dispatches.setInitialParams(case, components, sources)
dispatches.run()

if __name__ == '__main__':
def main():
"""
Runs HERON input from command line arguments
@ In, None
@ Out, None
"""
parser = argparse.ArgumentParser(description='Holistic Energy Resource Optimization Network (HERON)')
parser.add_argument('xml_input_file', help='HERON XML input file')
args = parser.parse_args()
Expand All @@ -146,3 +154,7 @@ def run_dispatches_workflow(self):
sim.run_dispatches_workflow()
# TODO someday? sim.run()


if __name__ == '__main__':
main()

22 changes: 17 additions & 5 deletions src/validators/Factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,25 @@
# set up path of raven
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import _utils as hutils
raven_path = hutils.get_raven_loc()
try:
import FARM.src
farm_loc = FARM.__path__
except ModuleNotFoundError:
try:
raven_path = hutils.get_raven_loc()

# set up path of farm
farm_loc = hutils.get_farm_loc(raven_path=raven_path)

if farm_loc is not None:
farm_path = os.path.abspath(os.path.join(farm_loc))
sys.path.append(farm_path)
except ModuleNotFoundError:
farm_loc = None
except OSError:
farm_loc = None

# set up path of farm
farm_loc = hutils.get_farm_loc(raven_path=raven_path)
if farm_loc is not None:
farm_path = os.path.abspath(os.path.join(farm_loc))
sys.path.append(farm_path)
from FARM.src.FARMValidatorsForHeron import FARM_Beta, FARM_Gamma_LTI, FARM_Gamma_FMU, FARM_Delta_FMU

# default known validators
Expand Down
Loading