From bc4648e0217ee00e27b7c82c9eaef86bb54b37da Mon Sep 17 00:00:00 2001 From: Dimitris Tsapetis Date: Sun, 8 May 2022 15:43:36 -0400 Subject: [PATCH 1/2] Removes import warnings --- src/UQpy/sampling/mcmc/DRAM.py | 4 +--- src/UQpy/sampling/mcmc/baseclass/MCMC.py | 2 ++ .../surrogates/gaussian_process/GaussianProcessRegression.py | 2 +- src/UQpy/utilities/MinimizeOptimizer.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/UQpy/sampling/mcmc/DRAM.py b/src/UQpy/sampling/mcmc/DRAM.py index 3bfe64671..79e18e35a 100644 --- a/src/UQpy/sampling/mcmc/DRAM.py +++ b/src/UQpy/sampling/mcmc/DRAM.py @@ -1,10 +1,8 @@ import logging from typing import Callable import warnings - -import numpy as np - warnings.filterwarnings('ignore') +import numpy as np from beartype import beartype from UQpy.sampling.mcmc.baseclass.MCMC import MCMC diff --git a/src/UQpy/sampling/mcmc/baseclass/MCMC.py b/src/UQpy/sampling/mcmc/baseclass/MCMC.py index 9481be501..a863c9d7b 100644 --- a/src/UQpy/sampling/mcmc/baseclass/MCMC.py +++ b/src/UQpy/sampling/mcmc/baseclass/MCMC.py @@ -1,5 +1,7 @@ import logging from typing import Callable, Tuple, List +import warnings +warnings.filterwarnings('ignore') import numpy as np from beartype import beartype diff --git a/src/UQpy/surrogates/gaussian_process/GaussianProcessRegression.py b/src/UQpy/surrogates/gaussian_process/GaussianProcessRegression.py index 4e4f2973b..1d4741e58 100755 --- a/src/UQpy/surrogates/gaussian_process/GaussianProcessRegression.py +++ b/src/UQpy/surrogates/gaussian_process/GaussianProcessRegression.py @@ -38,7 +38,7 @@ def __init__( input attribute defines the dimension of input training point, thus its length/shape should be equal to the input dimension plus one (d+1), this list/array includes 'd' length scale and process standard deviation. In case of noisy observations/output, its length/shape should be equal to the input dimension plus two (d+2), this - list/array includes 'd' lengthscales, process standar deviation and noise variance. + list/array includes 'd' lengthscales, process standard deviation and noise variance. :param regression_model: A class object, which computes the basis function at a sample point. If regression_model is None, this class will train GP with regression. Default: None diff --git a/src/UQpy/utilities/MinimizeOptimizer.py b/src/UQpy/utilities/MinimizeOptimizer.py index 7bde05daa..aa76a99ec 100644 --- a/src/UQpy/utilities/MinimizeOptimizer.py +++ b/src/UQpy/utilities/MinimizeOptimizer.py @@ -4,7 +4,7 @@ class MinimizeOptimizer: - def __init__(self, method: str = 'bfgs', bounds=None): + def __init__(self, method: str = 'l-bfgs-b', bounds=None): # super().__init__(bounds) self._bounds = None self.logger = logging.getLogger(__name__) From eb6437812e371b8109c539ff6556c3acfcda8f67 Mon Sep 17 00:00:00 2001 From: Dimitris Tsapetis Date: Sun, 8 May 2022 16:44:23 -0400 Subject: [PATCH 2/2] Example updates --- docs/code/RunModel/abaqus_example.py | 16 ++-- .../code/RunModel/ls_dyna_example_multijob.py | 16 +--- .../RunModel/ls_dyna_example_singlejob.py | 14 +-- docs/code/RunModel/matlab_example.py | 92 +++++++++---------- docs/code/RunModel/opensees_example.py | 11 ++- docs/code/RunModel/python_example.py | 32 ++++--- docs/source/runmodel_doc.rst | 88 +++++++++--------- .../model_execution/ThirdPartyModel.py | 4 +- 8 files changed, 131 insertions(+), 142 deletions(-) diff --git a/docs/code/RunModel/abaqus_example.py b/docs/code/RunModel/abaqus_example.py index 211c1e4be..0cb1cd02d 100644 --- a/docs/code/RunModel/abaqus_example.py +++ b/docs/code/RunModel/abaqus_example.py @@ -4,18 +4,18 @@ ================================== """ - # %% md # # Import the necessary libraries. # %% - +import glob import pickle import time - +import os from UQpy.distributions import Normal, Uniform -from UQpy.run_model.RunModel import * +from UQpy.run_model.RunModel import RunModel +from UQpy.run_model.model_execution.ThirdPartyModel import ThirdPartyModel from UQpy.sampling import MonteCarloSampling calling_directory = os.getcwd() @@ -36,12 +36,12 @@ # %% -abaqus_sfe_model = RunModel(model_script='abaqus_fire_analysis.py', input_template='abaqus_input.py', - output_script='extract_abaqus_output.py', var_names=var_names, ntasks=24, - model_dir='SFE_MCS', verbose=True, cores_per_task=1) +m = ThirdPartyModel(model_script='abaqus_fire_analysis.py', input_template='abaqus_input.py', + output_script='extract_abaqus_output.py', var_names=var_names, + model_dir='SFE_MCS', ) +abaqus_sfe_model = RunModel(cores_per_task=1, ntasks=24, model=m) print('Example: Created the model object.') - # %% md # # Towards defining the sampling scheme diff --git a/docs/code/RunModel/ls_dyna_example_multijob.py b/docs/code/RunModel/ls_dyna_example_multijob.py index 7294caa56..425fcccdc 100644 --- a/docs/code/RunModel/ls_dyna_example_multijob.py +++ b/docs/code/RunModel/ls_dyna_example_multijob.py @@ -4,7 +4,6 @@ ================================== """ - # %% md # # Import the necessary libraries. @@ -12,6 +11,7 @@ # %% from UQpy.distributions import Uniform from UQpy.run_model.RunModel import RunModel +from UQpy.run_model.model_execution.ThirdPartyModel import ThirdPartyModel from UQpy.sampling import MonteCarloSampling # %% md @@ -42,13 +42,7 @@ # Run the model. # %% - -run_ = RunModel(samples=x.samples, ntasks=6, model_script='dyna_script.py', input_template='dyna_input.k', - var_names=['x0', 'y0', 'z0', 'R0', 'x1', 'y1', 'z1', 'R1'], model_dir='dyna_test', cluster=True, - verbose=False, fmt='{:>10.4f}', cores_per_task=12) - - - - - - +m = ThirdPartyModel(model_script='dyna_script.py', input_template='dyna_input.k', + var_names=['x0', 'y0', 'z0', 'R0', 'x1', 'y1', 'z1', 'R1'], model_dir='dyna_test', + fmt='{:>10.4f}') +run_ = RunModel(samples=x.samples, ntasks=6, cores_per_task=12, model=m) diff --git a/docs/code/RunModel/ls_dyna_example_singlejob.py b/docs/code/RunModel/ls_dyna_example_singlejob.py index 486b2fd00..9b1925425 100644 --- a/docs/code/RunModel/ls_dyna_example_singlejob.py +++ b/docs/code/RunModel/ls_dyna_example_singlejob.py @@ -4,7 +4,6 @@ ================================== """ - # %% md # # Import the necessary libraries. @@ -12,6 +11,7 @@ # %% from UQpy.distributions import Uniform from UQpy.run_model.RunModel import RunModel +from UQpy.run_model.model_execution.ThirdPartyModel import ThirdPartyModel from UQpy.sampling import MonteCarloSampling # %% md @@ -40,12 +40,6 @@ # Run the model. # %% -run_ = RunModel(samples=x.samples, ntasks=1, model_script='dyna_script.py', input_template='dyna_input.k', - var_names=['x0', 'y0', 'z0', 'R0', 'x1', 'y1', 'z1', 'R1'], model_dir='dyna_test', cluster=True, - verbose=False, fmt='{:>10.4f}', cores_per_task=48) - - - - - - +m = ThirdPartyModel(model_script='dyna_script.py', input_template='dyna_input.k', + var_names=['x0', 'y0', 'z0', 'R0', 'x1', 'y1', 'z1', 'R1'], model_dir='dyna_test', fmt='{:>10.4f}') +run_ = RunModel(samples=x.samples, ntasks=1, cores_per_task=48, model=m) diff --git a/docs/code/RunModel/matlab_example.py b/docs/code/RunModel/matlab_example.py index a85fa287f..fa2fbf33c 100644 --- a/docs/code/RunModel/matlab_example.py +++ b/docs/code/RunModel/matlab_example.py @@ -4,7 +4,6 @@ ================================== """ - # %% md # # The RunModel class is capable of passing input in different formats into a single computational model. This means that @@ -64,6 +63,7 @@ from UQpy.sampling import MonteCarloSampling from UQpy.run_model.RunModel import RunModel +from UQpy.run_model.model_execution.ThirdPartyModel import ThirdPartyModel from UQpy.distributions import Normal import time import numpy as np @@ -133,10 +133,11 @@ if pick_model == 'scalar' or pick_model == 'all': # Call to RunModel - Here we run the model while instantiating the RunModel object. t = time.time() - m = RunModel(ntasks=1, model_script='matlab_model_sum_scalar.py', - input_template='sum_scalar.m', var_names=names, model_object_name="matlab", - output_script='process_matlab_output.py', output_object_name='read_output', - resume=False, model_dir='Matlab_Model', fmt="{:>10.4f}", verbose=True) + model = ThirdPartyModel(model_script='matlab_model_sum_scalar.py', + input_template='sum_scalar.m', var_names=names, model_object_name="matlab", + output_script='process_matlab_output.py', output_object_name='read_output', + model_dir='Matlab_Model', fmt="{:>10.4f}") + m = RunModel(ntasks=1, model=model) m.run(x_mcs.samples) t_ser_matlab = time.time() - t print("\nTime for serial execution:") @@ -145,7 +146,6 @@ print("The values returned from the Matlab simulation:") print(m.qoi_list) - # %% md # # 1.2 Samples passed as list, no format specification, parallel execution @@ -161,10 +161,11 @@ if pick_model == 'scalar' or pick_model == 'all': # Call to RunModel with samples as a list - Again we run the model while instantiating the RunModel object. t = time.time() - m = RunModel(samples=x_mcs_list, ntasks=2, model_script='matlab_model_sum_scalar.py', - input_template='sum_scalar.m', var_names=names, model_object_name="matlab", - output_script='process_matlab_output.py', output_object_name='read_output', resume=False, - model_dir='Matlab_Model', verbose=True) + model = ThirdPartyModel(model_script='matlab_model_sum_scalar.py', + input_template='sum_scalar.m', var_names=names, model_object_name="matlab", + output_script='process_matlab_output.py', output_object_name='read_output', + model_dir='Matlab_Model') + m = RunModel(samples=x_mcs_list, ntasks=2, model=model) t_par_matlab = time.time() - t print("\nTime for parallel execution:") print(t_par_matlab) @@ -172,7 +173,6 @@ print("The values retured from the Matlab simulation:") print(m.qoi_list) - # %% md # # Example 2: Single tri-variate random variable @@ -228,13 +228,12 @@ if pick_model == 'vector' or pick_model == 'all': # Call to RunModel - Here we run the model while instantiating the RunModel object. - # Notice that we do not specify var_names. This will default to a single variable with name x0. In this case, - # we will read them in by indexing in the input_template. t = time.time() - m = RunModel(samples=x_mcs_tri, ntasks=1, model_script='matlab_model_sum_vector_indexed.py', - input_template='sum_vector_indexed.m', model_object_name="matlab", - output_script='process_matlab_output.py', output_object_name='read_output', - resume=False, model_dir='Matlab_Model', fmt="{:>10.4f}") + model = ThirdPartyModel(model_script='matlab_model_sum_vector_indexed.py', + input_template='sum_vector_indexed.m', model_object_name="matlab", + output_script='process_matlab_output.py', output_object_name='read_output', + model_dir='Matlab_Model', fmt="{:>10.4f}", var_names=['x0']) + m = RunModel(samples=x_mcs_tri, ntasks=1, model=model) t_ser_matlab = time.time() - t print("\nTime for serial execution:") print(t_ser_matlab) @@ -255,13 +254,12 @@ if pick_model == 'vector' or pick_model == 'all': # Call to RunModel - Here we run the model while instantiating the RunModel object. - # Notice that we do not specify var_names. This will default to a single variable with name x0. In this case, - # we will read them in by indexing in the input_template. t = time.time() - m = RunModel(samples=x_mcs_tri_list, ntasks=2, model_script='matlab_model_sum_vector_indexed.py', - input_template='sum_vector_indexed.m', model_object_name="matlab", - output_script='process_matlab_output.py', output_object_name='read_output', - resume=False, model_dir='Matlab_Model') + model = ThirdPartyModel(model_script='matlab_model_sum_vector_indexed.py', + input_template='sum_vector_indexed.m', model_object_name="matlab", + output_script='process_matlab_output.py', output_object_name='read_output', + model_dir='Matlab_Model', var_names=['x0']) + m = RunModel(samples=x_mcs_tri_list, ntasks=2, model=model) t_ser_matlab = time.time() - t print("\nTime for parallel execution:") print(t_ser_matlab) @@ -285,10 +283,11 @@ # Notice that we do not specify var_names. This will default to a single variable with name x0. In this case, # we will read them in by indexing in the input_template. t = time.time() - m = RunModel(samples=x_mcs_tri, ntasks=1, model_script='matlab_model_sum_vector.py', - input_template='sum_vector.m', model_object_name="matlab", - output_script='process_matlab_output.py', output_object_name='read_output', - resume=False, model_dir='Matlab_Model', fmt="{:>10.4f}") + model = ThirdPartyModel(model_script='matlab_model_sum_vector.py', + input_template='sum_vector.m', model_object_name="matlab", + output_script='process_matlab_output.py', output_object_name='read_output', + model_dir='Matlab_Model', fmt="{:>10.4f}", var_names=['x0']) + m = RunModel(samples=x_mcs_tri, ntasks=1, model=model) t_ser_matlab = time.time() - t print("\nTime for serial execution:") print(t_ser_matlab) @@ -296,7 +295,6 @@ print("The values returned from the Matlab simulation:") print(m.qoi_list) - # %% md # # Example 3: Passing a scalar and an array to RunModel @@ -388,10 +386,11 @@ # case, x0 is a scalar and x1 is a 3x3 matrix. We will read the matrix in without indexing in the # input_template. t = time.time() - m = RunModel(samples=x_mixed_array, ntasks=1, model_script='matlab_model_det.py', - input_template='prod_determinant.m', model_object_name="matlab", - output_script='process_matlab_output.py', output_object_name='read_output', - resume=False, model_dir='Matlab_Model', fmt="{:>10.4f}") + model = ThirdPartyModel(model_script='matlab_model_det.py', + input_template='prod_determinant.m', model_object_name="matlab", var_names=['x0', 'x1'], + output_script='process_matlab_output.py', output_object_name='read_output', + model_dir='Matlab_Model', fmt="{:>10.4f}") + m = RunModel(samples=x_mixed_array, ntasks=1, model=model) t_ser_matlab = time.time() - t print("\nTime for serial execution:") print(t_ser_matlab) @@ -412,14 +411,13 @@ if pick_model == 'mixed' or pick_model == 'all': # Call to RunModel - Here we run the model while instantiating the RunModel object. - # Notice that we do not specify var_names. This will default to two variables with names x0 and x1. In this - # case, x0 is a scalar and x1 is a 3x3 matrix. We will read the matrix in with indexing in the - # input_template. + # We will read the matrix in with indexing in the input_template. t = time.time() - m = RunModel(samples=x_mixed_array, ntasks=1, model_script='matlab_model_det_index.py', + model = ThirdPartyModel(model_script='matlab_model_det_index.py', input_template='prod_determinant_index.m', model_object_name="matlab", output_script='process_matlab_output.py', output_object_name='read_output', - resume=False, model_dir='Matlab_Model', fmt="{:>10.4f}") + model_dir='Matlab_Model', fmt="{:>10.4f}", var_names=['x0', 'x1']) + m = RunModel(samples=x_mixed_array, ntasks=1, model=model) t_ser_matlab = time.time() - t print("\nTime for serial execution:") print(t_ser_matlab) @@ -442,14 +440,12 @@ if pick_model == 'mixed' or pick_model == 'all': # Call to RunModel - Here we run the model while instantiating the RunModel object. - # Notice that we do not specify var_names. This will default to two variables with names x0 and x1. In this - # case, x0 is a scalar and x1 is a 3x3 matrix. We will read the matrix in without indexing in the - # input_template. t = time.time() - m = RunModel(samples=x_mixed, ntasks=2, model_script='matlab_model_det.py', + model = ThirdPartyModel(model_script='matlab_model_det.py', input_template='prod_determinant.m', model_object_name="matlab", output_script='process_matlab_output.py', output_object_name='read_output', - resume=False, model_dir='Matlab_Model') + model_dir='Matlab_Model', var_names=['x0', 'x1']) + m = RunModel(samples=x_mixed, ntasks=2, model=model) t_ser_matlab = time.time() - t print("\nTime for serial execution:") print(t_ser_matlab) @@ -477,10 +473,11 @@ # case, x0 is a scalar and x1 is a 3x3 matrix. We will read the matrix in with indexing in the # input_template. t = time.time() - m = RunModel(samples=x_mixed, ntasks=2, model_script='matlab_model_det_index.py', + model = ThirdPartyModel(model_script='matlab_model_det_index.py', input_template='prod_determinant_index.m', model_object_name="matlab", output_script='process_matlab_output.py', output_object_name='read_output', - resume=False, model_dir='Matlab_Model') + model_dir='Matlab_Model', var_names=['x0', 'x1']) + m = RunModel(samples=x_mixed, ntasks=2, model=model) t_ser_matlab = time.time() - t print("\nTime for serial execution:") print(t_ser_matlab) @@ -508,13 +505,14 @@ # case, x0 is a scalar and x1 is a 3x3 matrix. We will read the matrix in with indexing in the # input_template. t = time.time() - m = RunModel(samples=x_mixed_array, ntasks=1, model_script='matlab_model_det_partial.py', + model = ThirdPartyModel(model_script='matlab_model_det_partial.py', input_template='prod_determinant_partial.m', model_object_name="matlab", output_script='process_matlab_output.py', output_object_name='read_output', - resume=False, model_dir='Matlab_Model', fmt="{:>10.4f}") + model_dir='Matlab_Model', fmt="{:>10.4f}", var_names=['x0', 'x1']) + m = RunModel(samples=x_mixed_array, ntasks=1, model=model) t_ser_matlab = time.time() - t print("\nTime for serial execution:") print(t_ser_matlab) print() print("The values returned from the Python simulation:") - print(m.qoi_list) \ No newline at end of file + print(m.qoi_list) diff --git a/docs/code/RunModel/opensees_example.py b/docs/code/RunModel/opensees_example.py index 21af0b8cc..c0870cbcf 100644 --- a/docs/code/RunModel/opensees_example.py +++ b/docs/code/RunModel/opensees_example.py @@ -4,7 +4,6 @@ ================================== """ - # %% md # # Import the necessary libraries. @@ -14,6 +13,7 @@ from UQpy.distributions import Uniform from UQpy.run_model.RunModel import RunModel +from UQpy.run_model.model_execution.ThirdPartyModel import ThirdPartyModel from UQpy.sampling import MonteCarloSampling # %% md @@ -41,12 +41,13 @@ # %% -names_ = ['fc1', 'fy1', 'Es1', 'fc2', 'fy2', 'Es2', 'fc3', 'fy3', 'Es3', 'fc4', 'fy4', 'Es4', 'fc5', 'fy5', 'Es5', +names_ = ['fc1', 'fy1', 'Es1', 'fc2', 'fy2', 'Es2', 'fc3', 'fy3', 'Es3', 'fc4', 'fy4', 'Es4', 'fc5', 'fy5', 'Es5', 'fc6', 'fy6', 'Es6'] -opensees_rc6_model = RunModel(samples=samples, ntasks=5, model_script='opensees_model.py', - input_template='import_variables.tcl', var_names=names_, model_object_name="opensees_run", - output_script='process_opensees_output.py', output_object_name='read_output') +m = ThirdPartyModel(model_script='opensees_model.py', input_template='import_variables.tcl', var_names=names_, + model_object_name="opensees_run", output_script='process_opensees_output.py', + output_object_name='read_output') +opensees_rc6_model = RunModel(samples=samples, ntasks=5, model=m) outputs = opensees_rc6_model.qoi_list print(outputs) diff --git a/docs/code/RunModel/python_example.py b/docs/code/RunModel/python_example.py index 55ae35916..a1b522847 100644 --- a/docs/code/RunModel/python_example.py +++ b/docs/code/RunModel/python_example.py @@ -70,6 +70,7 @@ from UQpy.sampling import MonteCarloSampling from UQpy.run_model.RunModel import RunModel +from UQpy.run_model.model_execution.PythonModel import PythonModel from UQpy.distributions import Normal import time import numpy as np @@ -139,7 +140,8 @@ if pick_model in {'scalar', 'all'}: # Call to RunModel - Here we run the model while instantiating the RunModel object. t = time.time() - m11 = RunModel(ntasks=1, model_script='python_model.py', model_object_name='SumRVs', model_dir='Python_Runs', verbose=True) + m = PythonModel(model_script='python_model.py', model_object_name='SumRVs') + m11 = RunModel(model=m, ntasks=1 ) m11.run(samples=x_mcs.samples,) t_ser_python = time.time() - t print("\nTime for serial execution:") @@ -160,8 +162,8 @@ if pick_model in {'scalar', 'all'}: # Call to RunModel - Here we run the model while instantiating the RunModel object. t = time.time() - m12 = RunModel(samples=x_mcs_list, ntasks=2, model_script='python_model.py', - model_object_name='sum_rvs', model_dir='Python_Runs') + m = PythonModel(model_script='python_model.py', model_object_name='sum_rvs') + m12 = RunModel(model=m, samples=x_mcs_list, ntasks=2) t_par_python = time.time() - t print("\nTime for parallel execution:") print(t_par_python) @@ -222,8 +224,8 @@ if pick_model in {'vector', 'all'}: # Call to RunModel - Here we run the model while instantiating the RunModel object. t = time.time() - m21 = RunModel(samples=x_mcs_tri, ntasks=1, model_script='python_model.py', - model_object_name='sum_rvs_vec', model_dir='Python_Runs') + m=PythonModel(model_script='python_model.py', model_object_name='sum_rvs_vec') + m21 = RunModel(samples=x_mcs_tri, ntasks=1, model=m) t_ser_python = time.time() - t print("\nTime for serial execution:") print(t_ser_python) @@ -243,8 +245,8 @@ if pick_model == 'vector' or pick_model == 'all': # Call to RunModel - Here we run the model while instantiating the RunModel object. t = time.time() - m22 = RunModel(samples=x_mcs_tri_list, ntasks=2, model_script='python_model.py', - model_object_name='SumRVs', model_dir='Python_Runs') + m=PythonModel(model_script='python_model.py', model_object_name='SumRVs') + m22 = RunModel(samples=x_mcs_tri_list, ntasks=2, model=m) t_par_python = time.time() - t print("\nTime for parallel execution:") print(t_par_python) @@ -337,8 +339,8 @@ if pick_model == 'mixed' or pick_model == 'all': # Call to RunModel - Here we run the model while instantiating the RunModel object. t = time.time() - m31 = RunModel(samples=x_mixed_array, ntasks=1, model_script='python_model.py', - model_object_name='DetRVs', model_dir='Python_Runs', vec=False) + m=PythonModel(model_script='python_model.py', model_object_name='DetRVs') + m31 = RunModel(samples=x_mixed_array, ntasks=1, model=m) t_ser_python = time.time() - t print("\nTime for serial execution:") print(t_ser_python) @@ -359,8 +361,8 @@ # Call to RunModel - Here we run the model while instantiating the RunModel object. # Note that the parallel model_object handles only one sample at a time. t = time.time() - m32 = RunModel(samples=x_mixed, ntasks=1, model_script='python_model.py', - model_object_name='det_rvs_par', model_dir='Python_Runs', vec=False) + m=PythonModel(model_script='python_model.py', model_object_name='det_rvs_par') + m32 = RunModel(samples=x_mixed, ntasks=1, model=m) t_par_python = time.time() - t print("\nTime for parallel execution:") print(t_par_python) @@ -419,8 +421,8 @@ if pick_model == 'mixed' or pick_model == 'all': # Call to RunModel - Here we run the model while instantiating the RunModel object. t = time.time() - m41 = RunModel(samples=x_mcs_array, ntasks=1, model_script='python_model.py', - model_object_name='det_rvs_fixed', model_dir='Python_Runs', vec=False, coeff=x) + m=PythonModel(model_script='python_model.py', model_object_name='det_rvs_fixed') + m41 = RunModel(samples=x_mcs_array, ntasks=1, model=m, coeff=x) t_ser_python = time.time() - t print("\nTime for serial execution:") print(t_ser_python) @@ -438,8 +440,8 @@ if pick_model == 'mixed' or pick_model == 'all': # Call to RunModel - Here we run the model while instantiating the RunModel object. t = time.time() - m42 = RunModel(samples=x_mcs_list, ntasks=1, model_script='python_model.py', - model_object_name='det_rvs_fixed', model_dir='Python_Runs', vec=False, coeff=x) + m=PythonModel(model_script='python_model.py', model_object_name='det_rvs_fixed') + m42 = RunModel(samples=x_mcs_list, ntasks=1, model=m, coeff=x) t_ser_python = time.time() - t print("\nTime for serial execution:") print(t_ser_python) diff --git a/docs/source/runmodel_doc.rst b/docs/source/runmodel_doc.rst index d8aff5c91..dd094dcb1 100644 --- a/docs/source/runmodel_doc.rst +++ b/docs/source/runmodel_doc.rst @@ -25,8 +25,7 @@ for execution of either a Python computational model, in which case the model is execution of a third-party software model. When running with a third-party software model, :class:`RunModel` interfaces with the model through text-based input files and serves as the "driver" to initiate the necessary calculations. At the second level, the jobs that are run by :class:`.RunModel` can either be executed -in series or in parallel. Within the third-party model parallel execution workflow, there are two cases, which are -triggered by the ``cluster`` variable. In the following sections the workflow is discussed in detail. +in series or in parallel. In the following sections the workflow is discussed in detail. .. image:: _static/Runmodel_workflow.png :width: 600 @@ -36,7 +35,7 @@ Python Model Workflow: Serial Execution ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A common workflow in :py:mod:`UQpy` is when the computational model being evaluated is written in Python. This workflow is -invoked by calling :class:`.RunModel` without specifying an ``input_template`` (i.e. ``input_template = None``) and setting +invoked by calling :class:`.RunModel` using a :class:`.PythonModel` without specifying an ``input_template`` (i.e. ``input_template = None``) and setting ``model_script`` to the user-defined Python script containing the model. This python model is run serially by setting ``ntasks = 1``. @@ -53,8 +52,10 @@ Python Model Workflow: Parallel Execution ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The python model is executed in parallel by setting ``ntasks`` equal to the desired number of tasks (greater than 1) to be executed concurrently. In this -case, the ``model_script`` and corresponding ``model_object`` should be defined to accept a single sample. :class:`.RunModel` uses the ``multiprocessing`` library for -parallel execution of python models, which restricts parallelization to the cores available within a single computer. A workaround to this, to run in parallel across multiple compute nodes, is to treat the python model as a third-party model and run with the third-party parallel execution workflow discussed below. +case, the ``model_script`` and corresponding ``model_object`` should be defined to accept a single sample. :class:`.RunModel` uses the ``mpi4py`` library for +parallel execution of python models. OpenMPI library is essential for ``mpi4py`` +and must be installed on the computer running the model. Information regarding how to install ``OpenMPI`` is provided +at `https://www.open-mpi.org/faq/?category=building `_. Details for ``model_script`` can be found in the Section entitled `Files & Scripts Used by RunModel`_. @@ -88,23 +89,22 @@ This workflow operates in three steps as explained in the following: Third-Party Model Workflow: Parallel Execution ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Parallel execution in :class:`.RunModel` is carried out by the `GNU parallel` library :cite:`GNU_parallel`. GNU parallel is essential -and must be installed on the computer running the model. Information regarding how to install GNU parallel is provided -at `https://www.gnu.org/software/parallel `_. Parallel execution is activated in +Parallel execution in :class:`.RunModel` is carried out by the ``mpi4py`` library. OpenMPI library is essential for ``mpi4py`` +and must be installed on the computer running the model. Information regarding how to install ``OpenMPI`` is provided +at `https://www.open-mpi.org/faq/?category=building `_. Parallel execution is activated in :class:`.RunModel` by setting the parameter ``ntasks>1``. The key differences in terms of the workflow are listed below. -1. During parallel execution, all required input files are generated prior to model execution as opposed to serial execution where input files are generated +1. During parallel execution, the execution of different samples is distributed among the different tasks and required input files are generated individually prior to each run. individually prior to each run. -2. `GNU parallel` divides the total number of jobs into a number of chunks specified by the variable ``ntasks``. +2. `OpenMPI` divides the total number of jobs into a number of chunks specified by the variable ``ntasks``. ``ntasks`` number of jobs are executed in parallel and - this continues until all the jobs finish executing. Note that the jobs can be executed across multiple compute nodes when ``cluster = True`` using the SLURM - workload manager. This is specified by setting ``cores_per_task`` and ``nodes`` appropriately. Details can be found in the description of the :class:`.RunModel`. + this continues until all the jobs finish executing. This is specified by setting ``cores_per_task`` and ``nodes`` appropriately. Details can be found in the description of the :class:`.RunModel`. Whether in serial or parallel, the sample index is used by :class:`.RunModel` to keep track of model execution and to link the samples to their corresponding outputs. :class:`.RunModel` achieves this by consistently naming all the input files using the sample index (see Step 1) and passing the sample index into ``model_script``. More details on the precise structure of ``model_script`` are discussed in the Section entitled `Files & Scripts Used by RunModel`_. -3. Output processing in the parallel case is performed after all the runs are completed, whereas in the serial case it is done after every individual run. +3. Output processing in the parallel case is performed after every individual run. Directory Structure During Third-Party Model Evaluation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,18 +165,18 @@ Python model may be structured are provided below. .. code-block:: python class ModelClass: - def __init__(self, input=one_sample, **kwargs): - # Execute the model using the input and get the output - self.qoi = output + def __init__(self, input=one_sample, **kwargs): + # Execute the model using the input and get the output + self.qoi = output **Example:** Model object as a function: .. code-block:: python def model_function(input=one_sample, **kwargs): - # Execute the model using the input and get the output - return output - + # Execute the model using the input and get the output + return output + * *Third-Party Software Model:* When running a third-party model, :class:`.RunModel` does not import ``model_script``. Instead, :class:`.RunModel` calls the model script through @@ -202,7 +202,7 @@ Instead, :class:`.RunModel` calls the model script through ``matlab_model_script.py`` .. code-block:: python - + import os import fire @@ -212,13 +212,13 @@ Instead, :class:`.RunModel` calls the model script through def model(sample_index): # Copy the input file into the cwd command1 = "cp ./InputFiles/matlab_model_" + str(index+1) + - ".m ." + ".m ." command2 = "matlab -nosplash -nojvm -nodisplay -nodesktop -r - 'run matlab_model_" + str(sample_index + 1) + ".m; - exit'" + 'run matlab_model_" + str(sample_index + 1) + ".m; + exit'" # Rename the output file command3 = "mv y.txt y_" + str(sample_index+1) + ".txt" - + os.system(command1) os.system(command2) os.system(command3) @@ -276,19 +276,19 @@ the quantity of interest after execution. Examples for how the output object may .. code-block:: python class OutputClass: - def __init__(self, input=sample_index): - # Postprocess the output files corresponding to the - # sample number and extract the quantity of interest - self.qoi = output + def __init__(self, input=sample_index): + # Postprocess the output files corresponding to the + # sample number and extract the quantity of interest + self.qoi = output **Example:** Output object as a function: .. code-block:: python def output_function(input=sample_index): - # Postprocess the output files corresponding to the sample - # number and extract the quantity of interest - return output + # Postprocess the output files corresponding to the sample + # number and extract the quantity of interest + return output **Executable Software** @@ -313,11 +313,23 @@ Several simple mathematical python models are provided in a Jupyter script entit models in python using :class:`.RunModel`. The notebook executes models in serial and in parallel. The models themselves are provided in the python file `python_model.py`. +PythonModel Class +------------------- + +.. autoclass:: UQpy.run_model.model_execution.PythonModel + :members: + **Third-Party Models** :class:`.RunModel` can be used to execute nearly any third-party model. In the `example` folder, we provide files for the execution of several commonly-used engineering software packages. +ThirdPartyModel Class +----------------------- + +.. autoclass:: UQpy.run_model.model_execution.ThirdPartyModel + :members: + *Abaqus Model* Code is provided for execution of 100 Monte Carlo samples of two random variables for the analysis of a beam subject to @@ -399,23 +411,11 @@ The other necessary files are the following: Note that this example is not intended to represent the accurate pushover analysis a real structure. It is for :py:mod:`UQpy` illustration purposes only. -PythonModel Class -------------------- - -.. autoclass:: UQpy.run_model.model_execution.PythonModel - :members: - -ThirdPartyModel Class ------------------------ - -.. autoclass:: UQpy.run_model.model_execution.ThirdPartyModel - :members: - RunModel Class -------------- .. autoclass:: UQpy.run_model.RunModel - :members: + :members: diff --git a/src/UQpy/run_model/model_execution/ThirdPartyModel.py b/src/UQpy/run_model/model_execution/ThirdPartyModel.py index 85501b7e9..9b5c7b97e 100644 --- a/src/UQpy/run_model/model_execution/ThirdPartyModel.py +++ b/src/UQpy/run_model/model_execution/ThirdPartyModel.py @@ -13,8 +13,8 @@ class ThirdPartyModel: - def __init__(self, var_names: list[str], input_template: str, model_script: str, model_object_name: str, - output_script: str, output_object_name: str, fmt: str = None, separator: str = ', ', + def __init__(self, var_names: list[str], input_template: str, model_script: str, output_script: str = None, + model_object_name: str = None, output_object_name: str = None, fmt: str = None, separator: str = ', ', delete_files: bool = False, model_dir: str = "Model_Runs"): """