diff --git a/docs/examples/simulator/plot_run_ravaflow24.py b/docs/examples/simulator/plot_run_ravaflow24.py index 96a2cbc0e87964bdd63329ccc5d1afeb007c998a..67666519fd53a5b7ecb6b6565307935b8cf4d85c 100644 --- a/docs/examples/simulator/plot_run_ravaflow24.py +++ b/docs/examples/simulator/plot_run_ravaflow24.py @@ -33,16 +33,16 @@ dir_sim = os.path.join(cwd, 'temp1_run_Ravaflow24Mixture_example') # %% md # -# Now, we can create an instance of :class:`.Ravaflow24Mixture` by given -# ``dir_sim``. To reduce simulation time, we set ``time_end`` to :math:`50`. -# Other parameters are set to their default values. +# Given ``dir_sim``, we can create an instance of :class:`.Ravaflow24Mixture`. +# To reduce simulation time, we set ``time_end`` to :math:`50`. Other parameters +# are set to their default values. voellmy_model = Ravaflow24Mixture(dir_sim, time_end=50) # %% md # -# In this example, we define a `simulator` that takes required inputs and returns -# the overall impact area based on ``voellmy_model``. +# The `simulator` in this example is defined based on ``voellmy_model`` as follows. +# It takes required inputs and returns the overall impact area. import numpy as np @@ -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.""" grass_location, sh_file = voellmy_model.preprocess(prefix=prefix, elevation=elevation, 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) 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 # %% md # -# We are going to run multiple simulations at different values of ``basal_friction`` -# and ``turbulent_friction``. +# To demonstrate how to run multiple simulations using :class:`.RunSimulator`, +# we choose ``basal_friction`` and ``turbulent_friction`` as variable input +# parameters. Each has two different values, leading to four simulations. import itertools @@ -72,7 +73,9 @@ var_samples = np.array( # %% 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/') elevation = os.path.join(dir_data, 'synthetic_topo.tif') @@ -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 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 # :class:`.RunSimulator`. Instead, we use a seperate parameter, called ``o_parameter`` # for this purpose. @@ -93,14 +95,12 @@ o_parameter = 'prefix' # %% 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 # set ``save_out`` as `True`. import os -# Here we create a folder called `temp2_run_Ravaflow24Mixture_example` to save outputs -# returned at each simulation. cwd = os.getcwd() if not os.path.exists('temp2_run_Ravaflow24Mixture_example'): os.mkdir('temp2_run_Ravaflow24Mixture_example') @@ -108,15 +108,28 @@ dir_out = os.path.join(cwd, 'temp2_run_Ravaflow24Mixture_example') # %% md # -# .. warning:: ``dir_sim`` and ``dir_out`` are two different directories for -# different purposes. ``dir_sim`` stores outputs generated by the function body -# of `simulator`, usually a third-party software or solver (here r.avaflow). -# ``dir_out`` stores returned numpy array of `simulator`, which include outputs -# of interest (here impact area). They can be the same directory if file names +# .. note:: Please note that ``dir_out`` and ``dir_sim`` are two different +# parameters for different purposes. +# +# - ``dir_out`` is a parameter of :class:`.RunSimulator`. The `simulator` +# 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 -# 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 -# returned numpy array of `simulator`, ``dir_out`` is not needed. +# returned numpy array of the `simulator`, ``dir_out`` is not needed. # %% md # @@ -130,12 +143,19 @@ run_simulator = RunSimulator(simulator, var_inp_parameter, fix_inp, o_parameter, # %% md # -# Define prefixes which will be used to name files generated by each r.avaflow -# simulation and each returned numpy array of `simulator`. +# Before running simulations, we need to specify values of ``prefixes`` which +# 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))] 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 start = time.time() @@ -145,6 +165,8 @@ serial_output = run_simulator.outputs print(f"serial_output: {serial_output}") 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, max_workers=2, append=True) parallel_time = time.time() - start @@ -156,4 +178,35 @@ print(f"parallel_output: {parallel_output}") print("Serial run time: ", serial_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