Run#
The Run submodule of polaris-studio is used to setup both individual and iterative runs of the core POLARIS simulation engine.
The philosophy used to design this module is to make simple model runs “easy” while allowing significant complexity to be added by the user to achieve their experimental objectives. Running the model can be as simple as three lines of code:
from polaris import Polaris
model = Polaris.from_dir("/folder/that/contains/our/model")
model.run(num_threads=4, do_abm_init=True, do_skim=True, num_abm_runs=1)
Important
This will use the model run parameters that are specified in /folder/that/contains/our/model/convergence_control.yaml
with the overrides that are specified as keyword arguments to the run method. The run method accepts any keyword argument that corresponds to a parameter of the ConvergenceConfig
class (see below).
The iterative process#
The main form of a convergence run is shown in the image below and described here:
Determine which iterations will run
Do any pre-loop setup
For each iteration
Do any pre-processing required for this iteration
Build an iteration specific
scenario.modified.json
configuration (starting from the template)Use the POLARIS engine to do a full day simulation using that
scenario.modified.json
Copy back results from the simulation sub-directory to the model root directory
Run any post-processing for this iteration. There are two sets of these:
In-line processing (i.e. required prior to running subsequent iterations)
Asynchronous processing which can be run in a background thread while the next iteration starts (e.g. zipping up outputs of previous iteration for archival)
Do any post-loop cleanup
Model run configurations#
The model run configurations control the entire model run and are stored in the convergence_control.yaml
file.
There are over 40 parameters that can be set, but they all mainly have sensible default values such that a typical
configuration used in practice will often look like the following:
do_abm_init: true
do_skim: true
num_abm_runs: 1
population_scale_factor: 0.25
num_threads: 12
When running the model, the user can see and modify the run configurations by calling the run_config
attribute of the model object, as shown below.
from polaris import Polaris
model = Polaris.from_dir("/folder/that/contains/our/model")
my_model_configs = model.run_config
Detailed configuration for these configurations can be found below:
Configuration class for the POLARIS iterative convergence process |
Configuration class for the POLARIS workplace stabilization process. |
Configuration class for the POLARIS calibration procedure. |
Customising the process#
The iterative process used by POLARIS is fully customizable using callback functions.
In the following example we demonstrate how non-default callbacks can be inserted to achieve specific modelling objectives.
from polaris.runs.convergence.convergence_callback_functions import default_end_of_loop_fn, default_start_of_loop_fn, do_nothing
from polaris.runs.convergence.scenario_mods import get_scenario_for_iteration
def scenario_json_fn(config, current_iteration):
# A method that returns a base scenario json file and some modifications to make it appropriate for this iteration
return get_scenario_for_iteration(config, current_iteration)
def my_custom_start_of_loop_fn(config, current_iteration, mods, scenario_file):
# User code goes here -----------------------------------------
logging.info(" I'm about to do some pre-processing")
# -------------------------------------------------------------
# Call the default start of loop function from the standard library
default_start_of_loop_fn(config, current_iteration, mods, scenario_file)
def my_custom_end_of_loop_fn(config, current_iteration, output_dir, polaris_inputs):
# Call the default end of loop function from the standard library
default_end_of_loop_fn(config, current_iteration, mods, scenario_file)
# User code goes here -----------------------------------------
logging.info(" I'm about to do something with my run outputs")
# -------------------------------------------------------------
These callbacks are then inserted into the run function
model.run(num_threads=4,
do_abm_init=False,
do_skim=False,
num_abm_runs=1,
get_scenario_json_fn=get_scenario_for_iteration,
end_of_loop_fn=my_custom_end_of_loop_fn,
start_of_loop_fn=my_custom_start_of_loop_fn)
This allows almost infinite flexibility in how the iterative process is structured and an interested reader is encouraged to use the examples provided in the polaris.hpc.eqsql.examples.run_convergence
module and in the various study repositories as a starting point for their first serious customization.