Skip to content
Snippets Groups Projects
Commit 0f0ad12b authored by Hu Zhao's avatar Hu Zhao
Browse files

docs: improve example of running ravaflow24 using RunSimulator

parent ae672131
Branches
No related tags found
No related merge requests found
...@@ -33,16 +33,16 @@ dir_sim = os.path.join(cwd, 'temp1_run_Ravaflow24Mixture_example') ...@@ -33,16 +33,16 @@ dir_sim = os.path.join(cwd, 'temp1_run_Ravaflow24Mixture_example')
# %% md # %% md
# #
# Now, we can create an instance of :class:`.Ravaflow24Mixture` by given # Given ``dir_sim``, we can create an instance of :class:`.Ravaflow24Mixture`.
# ``dir_sim``. To reduce simulation time, we set ``time_end`` to :math:`50`. # To reduce simulation time, we set ``time_end`` to :math:`50`. Other parameters
# Other parameters are set to their default values. # are set to their default values.
voellmy_model = Ravaflow24Mixture(dir_sim, time_end=50) voellmy_model = Ravaflow24Mixture(dir_sim, time_end=50)
# %% md # %% md
# #
# In this example, we define a `simulator` that takes required inputs and returns # The `simulator` in this example is defined based on ``voellmy_model`` as follows.
# the overall impact area based on ``voellmy_model``. # It takes required inputs and returns the overall impact area.
import numpy as np import numpy as np
...@@ -50,7 +50,7 @@ def simulator(prefix, elevation, hrelease, basal_friction, turbulent_friction, E ...@@ -50,7 +50,7 @@ def simulator(prefix, elevation, hrelease, basal_friction, turbulent_friction, E
"""Preprocess required inputs, run simulation, and return output as a numpy array.""" """Preprocess required inputs, run simulation, and return output as a numpy array."""
grass_location, sh_file = voellmy_model.preprocess(prefix=prefix, elevation=elevation, grass_location, sh_file = voellmy_model.preprocess(prefix=prefix, elevation=elevation,
hrelease=hrelease, basal_friction=basal_friction, turbulent_friction=turbulent_friction, EPSG=EPSG) hrelease=hrelease, basal_friction=basal_friction, turbulent_friction=turbulent_friction, EPSG=EPSG)
voellmy_model.run(grass_location, sh_file) # running this line, r.avaflow will write outputs to dir_sim voellmy_model.run(grass_location, sh_file) # run this line, r.avaflow will write outputs to dir_sim
impact_area = voellmy_model.extract_impact_area(prefix) impact_area = voellmy_model.extract_impact_area(prefix)
return np.array([impact_area]) # define dir_out and set save_out to True, returned numpy array will be saved to dir_out return np.array([impact_area]) # define dir_out and set save_out to True, returned numpy array will be saved to dir_out
...@@ -58,8 +58,9 @@ def simulator(prefix, elevation, hrelease, basal_friction, turbulent_friction, E ...@@ -58,8 +58,9 @@ def simulator(prefix, elevation, hrelease, basal_friction, turbulent_friction, E
# %% md # %% md
# #
# We are going to run multiple simulations at different values of ``basal_friction`` # To demonstrate how to run multiple simulations using :class:`.RunSimulator`,
# and ``turbulent_friction``. # we choose ``basal_friction`` and ``turbulent_friction`` as variable input
# parameters. Each has two different values, leading to four simulations.
import itertools import itertools
...@@ -72,7 +73,9 @@ var_samples = np.array( ...@@ -72,7 +73,9 @@ var_samples = np.array(
# %% md # %% md
# #
# Other parameters are fixed. # Other parameters of the `simulator`, including ``elevation``, ``hrelease``, and
# ``EPSG`` are treated as fixed input. It means that their values are the same in
# all simulations.
dir_data = os.path.abspath('../../../tests/data/') dir_data = os.path.abspath('../../../tests/data/')
elevation = os.path.join(dir_data, 'synthetic_topo.tif') elevation = os.path.join(dir_data, 'synthetic_topo.tif')
...@@ -83,7 +86,6 @@ fix_inp = {'elevation': elevation, 'hrelease': hrelease, 'EPSG': '2326'} ...@@ -83,7 +86,6 @@ fix_inp = {'elevation': elevation, 'hrelease': hrelease, 'EPSG': '2326'}
# #
# The parameter ``prefix`` of the `simulator` is special. It is not involved in # The parameter ``prefix`` of the `simulator` is special. It is not involved in
# the computational model, but only used to name output files generated by r.avaflow. # the computational model, but only used to name output files generated by r.avaflow.
# Usually, we need a unique value of ``prefix`` for each simulation to avoid conflict.
# Such parameter is not defined in ``var_inp_parameter`` or ``fix_inp`` of # Such parameter is not defined in ``var_inp_parameter`` or ``fix_inp`` of
# :class:`.RunSimulator`. Instead, we use a seperate parameter, called ``o_parameter`` # :class:`.RunSimulator`. Instead, we use a seperate parameter, called ``o_parameter``
# for this purpose. # for this purpose.
...@@ -93,14 +95,12 @@ o_parameter = 'prefix' ...@@ -93,14 +95,12 @@ o_parameter = 'prefix'
# %% md # %% md
# #
# We may want to save outputs returned by `simulator` at each simulation for # We may want to save outputs returned by the `simulator` at each simulation for
# later inspection or processing. In that case, we need to define ``dir_out`` and # later inspection or processing. In that case, we need to define ``dir_out`` and
# set ``save_out`` as `True`. # set ``save_out`` as `True`.
import os import os
# Here we create a folder called `temp2_run_Ravaflow24Mixture_example` to save outputs
# returned at each simulation.
cwd = os.getcwd() cwd = os.getcwd()
if not os.path.exists('temp2_run_Ravaflow24Mixture_example'): if not os.path.exists('temp2_run_Ravaflow24Mixture_example'):
os.mkdir('temp2_run_Ravaflow24Mixture_example') os.mkdir('temp2_run_Ravaflow24Mixture_example')
...@@ -108,15 +108,28 @@ dir_out = os.path.join(cwd, 'temp2_run_Ravaflow24Mixture_example') ...@@ -108,15 +108,28 @@ dir_out = os.path.join(cwd, 'temp2_run_Ravaflow24Mixture_example')
# %% md # %% md
# #
# .. warning:: ``dir_sim`` and ``dir_out`` are two different directories for # .. note:: Please note that ``dir_out`` and ``dir_sim`` are two different
# different purposes. ``dir_sim`` stores outputs generated by the function body # parameters for different purposes.
# of `simulator`, usually a third-party software or solver (here r.avaflow). #
# ``dir_out`` stores returned numpy array of `simulator`, which include outputs # - ``dir_out`` is a parameter of :class:`.RunSimulator`. The `simulator`
# of interest (here impact area). They can be the same directory if file names # returns output of interest as a numpy array for each simulation. If
# we want to save this returned output of interest (here impact area)
# to our local machine, we need to specify the value of ``dir_out`` which
# represents the directory in which output of interest will be saved and
# set ``save_out`` to `True`. Otherwise, we do not need ``dir_out`` and
# leave ``save_out`` to `False`.
# - ``dir_sim`` is a parameter of :class:`.Ravaflow24Mixture`. :class:`.Ravaflow24Mixture`
# relies on the third party software r.avaflow 2.4. When we call
# :py:meth:`.Ravaflow24Mixture.run` in the function body of above `simulator`,
# r.avaflow 2.4 will be run and it generates output files. The value of
# ``dir_sim`` specifies the directory in which output files generated by
# r.avaflow 2.4 are going to be saved.
#
# The value of ``dir_out`` and ``dir_sim`` can be the same if file names
# have no conflict. We recommend to keep them seperate. In addition, if the function # have no conflict. We recommend to keep them seperate. In addition, if the function
# body of `simulator` does not save files to disk, ``dir_sim`` is not needed. Our # body of the `simulator` does not write files to disk, ``dir_sim`` is not required. Our
# :class:`.MassPointModel` is an example. Similarly, if we do not want to save # :class:`.MassPointModel` is an example. Similarly, if we do not want to save
# returned numpy array of `simulator`, ``dir_out`` is not needed. # returned numpy array of the `simulator`, ``dir_out`` is not needed.
# %% md # %% md
# #
...@@ -130,12 +143,19 @@ run_simulator = RunSimulator(simulator, var_inp_parameter, fix_inp, o_parameter, ...@@ -130,12 +143,19 @@ run_simulator = RunSimulator(simulator, var_inp_parameter, fix_inp, o_parameter,
# %% md # %% md
# #
# Define prefixes which will be used to name files generated by each r.avaflow # Before running simulations, we need to specify values of ``prefixes`` which
# simulation and each returned numpy array of `simulator`. # will be used to name files generated by each r.avaflow simulation and
# each returned numpy array of `simulator`.
serial_prefixes = ["serial"+str(i) for i in range(len(var_samples))] serial_prefixes = ["serial"+str(i) for i in range(len(var_samples))]
parallel_prefixes = ["parallel"+str(i) for i in range(len(var_samples))] parallel_prefixes = ["parallel"+str(i) for i in range(len(var_samples))]
# %% md
#
# Now we can use :py:meth:`.RunSimulator.serial_run` method or
# :py:meth:`.RunSimulator.parallel_run` method to run the simulations
# in serial or parallelly.
import time import time
start = time.time() start = time.time()
...@@ -145,6 +165,8 @@ serial_output = run_simulator.outputs ...@@ -145,6 +165,8 @@ serial_output = run_simulator.outputs
print(f"serial_output: {serial_output}") print(f"serial_output: {serial_output}")
start = time.time() start = time.time()
# append setting to True means that simulation outputs of parallel run will be
# appended to above serial run outputs
run_simulator.parallel_run(var_samples, prefixes=parallel_prefixes, run_simulator.parallel_run(var_samples, prefixes=parallel_prefixes,
max_workers=2, append=True) max_workers=2, append=True)
parallel_time = time.time() - start parallel_time = time.time() - start
...@@ -156,4 +178,35 @@ print(f"parallel_output: {parallel_output}") ...@@ -156,4 +178,35 @@ print(f"parallel_output: {parallel_output}")
print("Serial run time: ", serial_time) print("Serial run time: ", serial_time)
print("Parallel run time: ", parallel_time) print("Parallel run time: ", parallel_time)
# %% md
#
# All output files returned by the `simulator` are
os.listdir(dir_out)
# %% md
#
# All output files/directories generated by r.avaflow simulations
# (including files/directories generated during preprocessing) are
os.listdir(dir_sim)
# %% md
# .. warning:: If one simulation failed due to whatever reason, the error massage
# will be printed to the screen but other simulations will continue. In that
# case, the output file of failed simulation will not be writted to ``dir_out``.
# Also, the element of :py:attr:`.RunSimulator.outputs` corresponding to that
# simulation will be a string representing the error message, instead of a
# numpy array.
# %% md
#
# In the end, we delete the folder `temp1_run_Ravaflow24Mixture_example` and
# `temp2_run_Ravaflow24Mixture_example` and all files therein.
import shutil
shutil.rmtree(dir_sim)
shutil.rmtree(dir_out)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment