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

docs: add example of running mpm using RunSimulator

parent 1e6c9379
Branches
No related tags found
No related merge requests found
"""
RunSimulator: Mass Point Model
==============================
"""
# %% md
#
# This example shows how to run multiple MassPointModel simulations in serial
# and parallelly using :class:`.RunSimulator`.
#
#
# %% md
#
# First, we import the class :class:`.MassPointModel` and define a `simulator`
# based on :py:meth:`.MassPointModel.run` method.
from psimpy.simulator import MassPointModel
mpm = MassPointModel()
mpm_simulator = mpm.run
# %% md
#
# This simulator takes required input data, solves the mass point model, and
# returns time history of the mass point's location and velocity
# (see :py:meth:`.MassPointModel.run`).
#
# Required inputs for `mpm_simulator` include:
# 1. topographic data: digital elevation model (in `ESRI ascii` format)
# 2. friction coefficients: coulomb friction and turbulent friction coefficients
# 3. initial state: initial location and initial velocity of the masspoint
# 4. computational parameters: such as time step, end time, etc.
#
# The synthetic topography ``synthetic_topo.asc`` is used here for illustration.
# It is located at the `/tests/data/` folder.
import os
dir_data = os.path.abspath('../../../tests/data/')
elevation = os.path.join(dir_data, 'synthetic_topo.asc')
# %% md
# .. note:: You may need to modify ``dir_data`` according to where you save
# ``synthetic_topo.asc`` on your local machine.
# %% md
#
# For this example, we are going to run multiple simulations at different values
# of coulomb friction coefficient (``coulomb_friction``) and turbulent friction
# coefficient (``turbulent_friction``) while keep other inputs fixed. Namely,
# ``coulomb_friction`` and ``turbulent_friction`` are variable input parameters.
# All other inputs are fixed input parameters.
#
import numpy as np
import itertools
# Variable iput parameters are defined as a list of strings. Their values will be
# passed as a numpy array (var_samples) when run simulations.
var_inp_parameter = ['coulomb_friction', 'turbulent_friction']
coulomb_friction = np.arange(0.1, 0.31, 0.1)
turbulent_friction = np.arange(500, 2001, 400)
var_samples = np.array(
[x for x in itertools.product(coulomb_friction, turbulent_friction)])
print("Number of variable input samples are: ", len(var_samples))
# Fixed input parameters are defined as a dictionary. Their values are given.
fix_inp = {'elevation': elevation, 'x0': 200, 'y0': 2000, 'tend': 50}
# %% md
# .. note:: Parameters of `mpm_simulator` which are not included in
# ``var_inp_parameter`` and ``fix_inp``, such as ``ux0``, ``uy0`` and
# ``curvature``, will automatically take their default values.
# %% md
#
# We may want to save outputs returned by `mpm_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 `temp_run_MassPointModel_example` to save outputs
# returned at each simulation.
cwd = os.getcwd()
if not os.path.exists('temp_run_MassPointModel_example'):
os.mkdir('temp_run_MassPointModel_example')
dir_out = os.path.join(cwd, 'temp_run_MassPointModel_example')
# %% md
#
# Now we can define an object of :class:`.RunSimulator` by
from psimpy.simulator import RunSimulator
run_mpm_simulator = RunSimulator(mpm_simulator, var_inp_parameter, fix_inp,
dir_out=dir_out, save_out=True)
# %% md
# .. note:: Since outputs of each simulation are saved in the same folder ``dir_out``,
# we need to give each file a unique name in order to avoid conflict. This is
# realized by defining ``prefixes``.
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
#
# Using :py:meth:`.RunSimulator.serial_run` method or
# :py:meth:`.RunSimulator.parallel_run` method, we can run the simulations
# in serial or parallelly.
import time
start = time.time()
run_mpm_simulator.serial_run(var_samples=var_samples, prefixes=serial_prefixes)
serial_time = time.time() - start
serial_output = run_mpm_simulator.outputs
start = time.time()
run_mpm_simulator.parallel_run(var_samples, prefixes=parallel_prefixes, max_workers=4)
parallel_time = time.time() - start
parallel_output = run_mpm_simulator.outputs
print("Serial run time: ", serial_time)
print("Parallel run time: ", parallel_time)
# %% md
#
# Once a simulation is done, its output is saved to ``dir_out``. All output files
# generated by above simulations are as follows:
os.listdir(dir_out)
# %% md
#
# Once all simulations are done, their outputs can also be accessed by
# :py:attr:`.RunSimulator.outputs` attribute, which is a list.
# Here we print the maximum velocity of each simulation in the parallel run.
max_v = [np.max(output[:,5]) for output in parallel_output]
print(
f"Maximum velocity of {parallel_prefixes[0]} to {parallel_prefixes[-1]} are: ",
'\n',
max_v)
# %% 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
#
# Here we delete the folder `temp_run_MassPointModel_example` and all files therein.
import shutil
shutil.rmtree(dir_out)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment