Skip to content

Commit

Permalink
refactor: create new classes for simulation Launchers
Browse files Browse the repository at this point in the history
  • Loading branch information
danielolsen committed Feb 2, 2021
1 parent 4154512 commit d07c39d
Showing 1 changed file with 92 additions and 73 deletions.
165 changes: 92 additions & 73 deletions pyreisejl/utility/call.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,89 +34,109 @@ def _record_scenario(scenario_id, runtime):
)


def launch_scenario(
start_date, end_date, interval, input_dir, execute_dir=None, threads=None
):
"""Launches the scenario.
class Launcher:
"""Parent class for solver-specific scenario launchers.
:param str start_date: start date of simulation as 'YYYY-MM-DD HH:MM:SS',
where HH, MM, and SS are optional.
where HH, MM, and SS are optional.
:param str end_date: end date of simulation as 'YYYY-MM-DD HH:MM:SS',
where HH, MM, and SS are optional.
where HH, MM, and SS are optional.
:param int interval: length of each interval in hours
:param str input_dir: directory with input data
:param None/str execute_dir: directory for execute data. None defaults to an
execute folder that will be created in the input directory
:param None/int threads: number of threads to use, None defaults to auto.
:return: (*int*) runtime of scenario in seconds
:raises InvalidDateArgument: if start_date is posterior to end_date
:raises InvalidInterval: if the interval does not evently divide the given date range
:raises InvalidInterval: if the interval doesn't evently divide the given date range
"""
# extract time limits from 'demand.csv'
with open(os.path.join(input_dir, "demand.csv")) as profile:
min_ts, max_ts, freq = extract_date_limits(profile)

dates = pd.date_range(start=min_ts, end=max_ts, freq=freq)

start_ts = validate_time_format(start_date)
end_ts = validate_time_format(end_date, end_date=True)

# make sure the dates are within the time frame we have data for
validate_time_range(start_ts, min_ts, max_ts)
validate_time_range(end_ts, min_ts, max_ts)

if start_ts > end_ts:
raise InvalidDateArgument(
f"The start date ({start_ts}) cannot be after the end date ({end_ts})."
def __init__(self, start_date, end_date, interval, input_dir):
"""Constructor."""
# extract time limits from 'demand.csv'
with open(os.path.join(input_dir, "demand.csv")) as profile:
min_ts, max_ts, freq = extract_date_limits(profile)

dates = pd.date_range(start=min_ts, end=max_ts, freq=freq)

start_ts = validate_time_format(start_date)
end_ts = validate_time_format(end_date, end_date=True)

# make sure the dates are within the time frame we have data for
validate_time_range(start_ts, min_ts, max_ts)
validate_time_range(end_ts, min_ts, max_ts)

if start_ts > end_ts:
raise InvalidDateArgument(
f"The start date ({start_ts}) cannot be after the end date ({end_ts})."
)

# Julia starts at 1
start_index = dates.get_loc(start_ts) + 1
end_index = dates.get_loc(end_ts) + 1

# Calculate number of intervals
ts_range = end_index - start_index + 1
if ts_range % interval > 0:
raise InvalidInterval(
"This interval does not evenly divide the given date range."
)
self.start_index = start_index
self.interval = interval
self.n_interval = int(ts_range / interval)
self.input_dir = input_dir
print("Validation complete!")

def _print_settings(self):
print("Launching scenario with parameters:")
print(
{
"interval": self.interval,
"n_interval": self.n_interval,
"start_index": self.start_index,
"input_dir": self.input_dir,
"execute_dir": self.execute_dir,
"threads": self.threads,
}
)

# Julia starts at 1
start_index = dates.get_loc(start_ts) + 1
end_index = dates.get_loc(end_ts) + 1

# Calculate number of intervals
ts_range = end_index - start_index + 1
if ts_range % interval > 0:
raise InvalidInterval(
"This interval does not evenly divide the given date range."
def launch_scenario(self):
# This should be defined in sub-classes
raise NotImplementedError


class GurobiLauncher(Launcher):
def launch_scenario(self, execute_dir=None, threads=None, solver_kwargs=None):
"""Launches the scenario.
:param None/str execute_dir: directory for execute data. None defaults to an
execute folder that will be created in the input directory
:param None/int threads: number of threads to use.
:param None/dict solver_kwargs: keyword arguments to pass to solver (if any).
:return: (*int*) runtime of scenario in seconds
"""
self.execute_dir = execute_dir
self.threads = threads
self._print_settings()
# Import these within function because there is a lengthy compilation step
from julia.api import Julia

Julia(compiled_modules=False)
from julia import Gurobi # noqa: F401
from julia import REISE

start = time()
REISE.run_scenario_gurobi(
interval=self.interval,
n_interval=self.n_interval,
start_index=self.start_index,
inputfolder=self.input_dir,
outputfolder=self.execute_dir,
threads=self.threads,
)
end = time()

n_interval = int(ts_range / interval)

# Import these within function because there is a lengthy compilation step
from julia.api import Julia

Julia(compiled_modules=False)
from julia import REISE

print("Validation complete! Launching scenario with parameters:")
print(
{
"interval": interval,
"n_interval": n_interval,
"start_index": start_index,
"input_dir": input_dir,
"execute_dir": execute_dir,
"threads": threads,
}
)

start = time()
REISE.run_scenario(
interval=interval,
n_interval=n_interval,
start_index=start_index,
inputfolder=input_dir,
outputfolder=execute_dir,
threads=threads,
)
end = time()

runtime = round(end - start)
hours, minutes, seconds = sec2hms(runtime)
print(f"Run time: {hours}:{minutes:02d}:{seconds:02d}")
runtime = round(end - start)
hours, minutes, seconds = sec2hms(runtime)
print(f"Run time: {hours}:{minutes:02d}:{seconds:02d}")

return runtime
return runtime


def main(args):
Expand All @@ -142,14 +162,13 @@ def main(args):
)
raise WrongNumberOfArguments(err_str)

runtime = launch_scenario(
launcher = GurobiLauncher(
args.start_date,
args.end_date,
args.interval,
args.input_dir,
args.execute_dir,
args.threads,
)
runtime = launcher.launch_scenario(args.execute_dir, args.threads)

# If using PowerSimData, record the runtime
if args.scenario_id:
Expand Down

0 comments on commit d07c39d

Please sign in to comment.