def setup_multi_level_advection_diffusion_benchmark( nvars, corr_len, max_eval_concurrency=1): r""" Compute functionals of the transient advection-diffusion (with 1 configure variables which controls the two spatial mesh resolutions and the timestep). An integer increase in the configure variable value will raise the 3 numerical discretiation paramaters by the same integer. See :func:`pyapprox_dev.advection_diffusion_wrappers.setup_advection_diffusion_benchmark` for details on function arguments and output. """ from scipy import stats from pyapprox.models.wrappers import TimerModelWrapper, PoolModel, \ WorkTrackingModel from pyapprox.models.wrappers import PoolModel from pyapprox.variables import IndependentMultivariateRandomVariable from pyapprox.benchmarks.benchmarks import Benchmark from pyapprox.models.wrappers import MultiLevelWrapper univariate_variables = [stats.uniform(-np.sqrt(3), 2*np.sqrt(3))]*nvars variable = IndependentMultivariateRandomVariable(univariate_variables) final_time, degree = 1.0, 1 options = {'corr_len': corr_len} base_model = AdvectionDiffusionModel( final_time, degree, qoi_functional_misc, second_order_timestepping=False, options=options) multilevel_model = MultiLevelWrapper( base_model, base_model.num_config_vars) # add wrapper to allow execution times to be captured timer_model = TimerModelWrapper(multilevel_model, base_model) pool_model = PoolModel( timer_model, max_eval_concurrency, base_model=base_model) model = WorkTrackingModel( pool_model, base_model, multilevel_model.num_config_vars) attributes = {'fun': model, 'variable': variable, 'multi_level_model': multilevel_model} return Benchmark(attributes)
def setup_model(num_vars, max_eval_concurrency): corr_len = 1 / 10 second_order_timestepping = False qoi_functional = qoi_functional_misc degree = 1 base_model = AdvectionDiffusionModel( num_vars, corr_len, 1.0e-0, degree, qoi_functional, add_work_to_qoi=False, boundary_condition_type=None, second_order_timestepping=second_order_timestepping) timer_model = TimerModelWrapper(base_model, base_model) model = PoolModel(timer_model, max_eval_concurrency, base_model=base_model) model = WorkTrackingModel(model, model.base_model) return model
def setup_advection_diffusion_benchmark(nvars, corr_len, max_eval_concurrency=1): r""" Compute functionals of the following model of transient advection-diffusion .. math:: \frac{\partial u}{\partial t}(x,t,\rv) + \nabla u(x,t,\rv)-\nabla\cdot\left[k(x,\rv) \nabla u(x,t,\rv)\right] &=g(x,t) \qquad (x,t,\rv)\in D\times [0,1]\times\rvdom\\ \mathcal{B}(x,t,\rv)&=0 \qquad\qquad (x,t,\rv)\in \partial D\times[0,1]\times\rvdom\\ u(x,t,\rv)&=u_0(x,\rv) \qquad (x,t,\rv)\in D\times\{t=0\}\times\rvdom Following [NTWSIAMNA2008]_, [JEGGIJNME2020]_ we set .. math:: g(x,t)=(1.5+\cos(2\pi t))\cos(x_1), the initial condition as :math:`u(x,z)=0`, :math:`B(x,t,z)` to be zero dirichlet boundary conditions. and we model the diffusivity :math:`k` as a random field represented by the Karhunen-Loeve (like) expansion (KLE) .. math:: \log(k(x,\rv)-0.5)=1+\rv_1\left(\frac{\sqrt{\pi L}}{2}\right)^{1/2}+\sum_{k=2}^d \lambda_k\phi(x)\rv_k, with .. math:: \lambda_k=\left(\sqrt{\pi L}\right)^{1/2}\exp\left(-\frac{(\lfloor\frac{k}{2}\rfloor\pi L)^2}{4}\right) k>1, \qquad\qquad \phi(x)= \begin{cases} \sin\left(\frac{(\lfloor\frac{k}{2}\rfloor\pi x_1)}{L_p}\right) & k \text{ even}\,,\\ \cos\left(\frac{(\lfloor\frac{k}{2}\rfloor\pi x_1)}{L_p}\right) & k \text{ odd}\,. \end{cases} where :math:`L_p=\max(1,2L_c)`, :math:`L=\frac{L_c}{L_p}`. Parameters ---------- nvars : integer The number of variables of the KLE corr_len : float The correlation length :math:`L_c` of the covariance kernel max_eval_concurrency : integer The maximum number of simulations that can be run in parallel. Should be no more than the maximum number of cores on the computer being used Returns -------- benchmark : pya.Benchmark Object containing the benchmark attributes """ from scipy import stats from pyapprox.models.wrappers import TimerModelWrapper, PoolModel, \ WorkTrackingModel from pyapprox.models.wrappers import PoolModel from pyapprox.variables import IndependentMultivariateRandomVariable from pyapprox.benchmarks.benchmarks import Benchmark univariate_variables = [stats.uniform(-np.sqrt(3), 2 * np.sqrt(3))] * nvars variable = IndependentMultivariateRandomVariable(univariate_variables) final_time, degree = 1.0, 1 options = {'corr_len': corr_len} base_model = AdvectionDiffusionModel(final_time, degree, qoi_functional_misc, second_order_timestepping=False, options=options) # add wrapper to allow execution times to be captured timer_model = TimerModelWrapper(base_model, base_model) pool_model = PoolModel(timer_model, max_eval_concurrency, base_model=base_model) # add wrapper that tracks execution times. model = WorkTrackingModel(pool_model, base_model) attributes = {'fun': model, 'variable': variable} return Benchmark(attributes)
# #Lets use the class with a function that takes a random amount of time. We will use the previous function but add a random pause between 0 and .1 seconds. Lets import some functions # #.. literalinclude:: ../../../../pyapprox/examples/setup_model_functions.py # :language: python # :start-at: def fun_pause_1 # :end-before: def fun_pause_2 # #.. Note for some reason text like this is needed after the literalinclude #.. Also note that path above is relative to source/auto_tutorials/foundations # from pyapprox.examples.setup_model_functions import pyapprox_fun_1, fun_pause_1 timer_fun = TimerModelWrapper(pyapprox_fun_1) worktracking_fun = WorkTrackingModel(timer_fun) values = worktracking_fun(samples) #%% #The :class:`pyapprox.models.wrappers.WorkTrackingModel` has an attribute :class:`pyapprox.models.wrappers.WorkTracker` which stores the execution time of each function evaluation as a dictionary. The key corresponds is the model id. For this example the id will always be the same, but the id can vary and this is useful when evaluating mutiple models, e.g. when using multi-fidelity methods. To print the dictionary use costs = worktracking_fun.work_tracker.costs print(costs) #%% #We can also call the work tracker to query the median cost for a model with a given id. The default id is 0. fun_id = np.atleast_2d([0]) print(worktracking_fun.work_tracker(fun_id)) #%% #Evaluating multiple models #^^^^^^^^^^^^^^^^^^^^^^^^^^
def setup_advection_diffusion_source_inversion_benchmark( measurement_times=np.array([0.05, 0.15]), source_strength=0.5, source_width=0.1, true_sample=np.array([[0.25, 0.75, 4, 4, 4]]).T, noise_stdev=0.4, max_eval_concurrency=1): r""" Compute functionals of the following model of transient diffusion of a contaminant .. math:: \frac{\partial u}{\partial t}(x,t,\rv) + \nabla u(x,t,\rv)-\nabla\cdot\left[k(x,\rv) \nabla u(x,t,\rv)\right] &=g(x,t) \qquad (x,t,\rv)\in D\times [0,1]\times\rvdom\\ \mathcal{B}(x,t,\rv)&=0 \qquad\qquad (x,t,\rv)\in \partial D\times[0,1]\times\rvdom\\ u(x,t,\rv)&=u_0(x,\rv) \qquad (x,t,\rv)\in D\times\{t=0\}\times\rvdom Following [MNRJCP2006]_, [LMSISC2014]_ we set .. math:: g(x,t)=\frac{s}{2\pi h^2}\exp\left(-\frac{\lvert x-x_\mathrm{src}\rvert^2}{2h^2}\right) the initial condition as :math:`u(x,z)=0`, :math:`B(x,t,z)` to be zero Neumann boundary conditions, i.e. .. math:: \nabla u\cdot n = 0 \quad\mathrm{on} \quad\partial D and we model the diffusivity :math:`k=1` as a constant. The quantities of interest are point observations :math:`u(x_l)` taken at :math:`P` points in time :math:`\{t_p\}_{p=1}^P` at :math:`L` locations :math:`\{x_l\}_{l=1}^L`. The final time :math:`T` is the last observation time. These functionals can be used to define the posterior distribution .. math:: \pi_{\text{post}}(\rv)=\frac{\pi(\V{y}|\rv)\pi(\rv)}{\int_{\rvdom} \pi(\V{y}|\rv)\pi(\rv)d\rv} where the prior is the tensor product of independent and identically distributed uniform variables on :math:`[0,1]` i.e. :math:`\pi(\rv)=1`, and the likelihood is given by .. math:: \pi(\V{y}|\rv)=\frac{1}{(2\pi)^{d/2}\sigma}\exp\left(-\frac{1}{2}\frac{(y-f(\rv))^T(y-f(\rv))}{\sigma^2}\right) and :math:`y` are noisy observations of the solution `u` at the 9 points of a uniform :math:`3\times 3` grid covering the physical domain :math:`D` at successive times :math:`\{t_p\}_{p=1}^P`. Here the noise is indepenent and Normally distrbuted with mean zero and variance :math:`\sigma^2`. Parameters ---------- measurement_times : np.ndarray (P) The times :math:`\{t_p\}_{p=1}^P` at which measurements of the contaminant concentration are taken source_strength : float The source strength :math:`s` source_width : float The source width :math:`h` true_sample : np.ndarray (2) The true location of the source used to generate the observations used in the likelihood function noise_stdev : float The standard deviation :math:`sigma` of the observational noise max_eval_concurrency : integer The maximum number of simulations that can be run in parallel. Should be no more than the maximum number of cores on the computer being used Returns ------- benchmark : pya.Benchmark Object containing the benchmark attributes documented below fun : callable The quantity of interest :math:`f(w)` with signature ``fun(w) -> np.ndarray`` where ``w`` is a 2D np.ndarray with shape (nvars+3,nsamples) and the output is a 2D np.ndarray with shape (nsamples,1). The first ``nvars`` rows of ``w`` are realizations of the random variables. The last 3 rows are configuration variables specifying the numerical discretization of the PDE model. Specifically the first and second configuration variables specify the levels :math:`l_{x_1}` and :math:`l_{x_2}` which dictate the resolution of the FEM mesh in the directions :math:`{x_1}` and :math:`{x_2}` respectively. The number of cells in the :math:`{x_i}` direction is given by :math:`2^{l_{x_i}+2}`. The third configuration variable specifies the level :math:`l_t` of the temporal discretization. The number of timesteps satisfies :math:`2^{l_{t}+2}` so the timestep size is and :math:`T/2^{l_{t}+2}`. variable : pya.IndependentMultivariateRandomVariable Object containing information of the joint density of the inputs z which is the tensor product of independent and identically distributed uniform variables on :math:`[0,1]`. Examples -------- >>> from pyapprox_dev.benchmarks.benchmarks import setup_benchmark >>> benchmark=setup_benchmark('advection-diffusion',nvars=2) >>> print(benchmark.keys()) dict_keys(['fun', 'variable']) References ---------- .. [MNRJCP2006] `Youssef M. Marzouk, Habib N. Najm, Larry A. Rahn, Stochastic spectral methods for efficient Bayesian solution of inverse problems, Journal of Computational Physics, Volume 224, Issue 2, 2007, Pages 560-586, <https://doi.org/10.1016/j.jcp.2006.10.010>`_ .. [LMSISC2014] `Jinglai Li and Youssef M. Marzouk. Adaptive Construction of Surrogates for the Bayesian Solution of Inverse Problems, SIAM Journal on Scientific Computing 2014 36:3, A1163-A1186 <https://doi.org/10.1137/130938189>`_ Notes ----- The example from [MNRJCP2006]_ can be obtained by setting `s=0.5`, `h=0.1`, `measurement_times=np.array([0.05,0.15])` and `noise_stdev=0.1` The example from [LMSISC2014]_ can be obtained by setting `s=2`, `h=0.05`, `measurement_times=np.array([0.1,0.2])` and `noise_stdev=0.1` """ from scipy import stats from pyapprox.models.wrappers import TimerModelWrapper, PoolModel, \ WorkTrackingModel from pyapprox.models.wrappers import PoolModel from pyapprox.variables import IndependentMultivariateRandomVariable from pyapprox.benchmarks.benchmarks import Benchmark univariate_variables = [stats.uniform(0, 1)] * 2 variable = IndependentMultivariateRandomVariable(univariate_variables) final_time, degree = measurement_times.max(), 2 options = { 'intermediate_times': measurement_times[:-1], 'source_strength': source_strength, 'source_width': source_width } base_model = AdvectionDiffusionSourceInversionModel( final_time, degree, qoi_functional_source_inversion, second_order_timestepping=False, options=options) # add wrapper to allow execution times to be captured timer_model = TimerModelWrapper(base_model, base_model) pool_model = PoolModel(timer_model, max_eval_concurrency, base_model=base_model) # add wrapper that tracks execution times. model = WorkTrackingModel(pool_model, base_model) from pyapprox.bayesian_inference.markov_chain_monte_carlo import \ GaussianLogLike if true_sample.shape != (5, 1): msg = 'true_sample must be the concatenation of random sample and the ' msg += 'configure sample' raise Exception(msg) noiseless_data = model(true_sample)[0, :] noise = np.random.normal(0, noise_stdev, (noiseless_data.shape[0])) data = noiseless_data + noise loglike = GaussianLogLike(model, data, noise_stdev) attributes = {'fun': model, 'variable': variable, 'loglike': loglike} return Benchmark(attributes)
def setup_advection_diffusion_benchmark(nvars, corr_len, max_eval_concurrency=1): r""" Compute functionals of the following model of transient advection-diffusion (with 3 configure variables which control the two spatial mesh resolutions and the timestep) .. math:: \frac{\partial u}{\partial t}(x,t,\rv) + \nabla u(x,t,\rv)-\nabla\cdot\left[k(x,\rv) \nabla u(x,t,\rv)\right] &=g(x,t) \qquad (x,t,\rv)\in D\times [0,1]\times\rvdom\\ \mathcal{B}(x,t,\rv)&=0 \qquad\qquad (x,t,\rv)\in \partial D\times[0,1]\times\rvdom\\ u(x,t,\rv)&=u_0(x,\rv) \qquad (x,t,\rv)\in D\times\{t=0\}\times\rvdom Following [NTWSIAMNA2008]_, [JEGGIJNME2020]_ we set .. math:: g(x,t)=(1.5+\cos(2\pi t))\cos(x_1), the initial condition as :math:`u(x,z)=0`, :math:`B(x,t,z)` to be zero dirichlet boundary conditions. and we model the diffusivity :math:`k` as a random field represented by the Karhunen-Loeve (like) expansion (KLE) .. math:: \log(k(x,\rv)-0.5)=1+\rv_1\left(\frac{\sqrt{\pi L}}{2}\right)^{1/2}+\sum_{k=2}^d \lambda_k\phi(x)\rv_k, with .. math:: \lambda_k=\left(\sqrt{\pi L}\right)^{1/2}\exp\left(-\frac{(\lfloor\frac{k}{2}\rfloor\pi L)^2}{4}\right) k>1, \qquad\qquad \phi(x)= \begin{cases} \sin\left(\frac{(\lfloor\frac{k}{2}\rfloor\pi x_1)}{L_p}\right) & k \text{ even}\,,\\ \cos\left(\frac{(\lfloor\frac{k}{2}\rfloor\pi x_1)}{L_p}\right) & k \text{ odd}\,. \end{cases} where :math:`L_p=\max(1,2L_c)`, :math:`L=\frac{L_c}{L_p}`. The quantity of interest :math:`f(z)` is the measurement of the solution at a location :math:`x_k` at the final time :math:`T=1` obtained via the linear functional .. math:: f(z)=\int_D u(x,T,z)\frac{1}{2\pi\sigma^2}\exp\left(-\frac{\lVert x-x_k \rVert^2_2}{\sigma^2}\right) dx Parameters ---------- nvars : integer The number of variables of the KLE corr_len : float The correlation length :math:`L_c` of the covariance kernel max_eval_concurrency : integer The maximum number of simulations that can be run in parallel. Should be no more than the maximum number of cores on the computer being used Returns ------- benchmark : pya.Benchmark Object containing the benchmark attributes documented below fun : callable The quantity of interest :math:`f(w)` with signature ``fun(w) -> np.ndarray`` where ``w`` is a 2D np.ndarray with shape (nvars+3,nsamples) and the output is a 2D np.ndarray with shape (nsamples,1). The first ``nvars`` rows of ``w`` are realizations of the random variables. The last 3 rows are configuration variables specifying the numerical discretization of the PDE model. Specifically the first and second configuration variables specify the levels :math:`l_{x_1}` and :math:`l_{x_2}` which dictate the resolution of the FEM mesh in the directions :math:`{x_1}` and :math:`{x_2}` respectively. The number of cells in the :math:`{x_i}` direction is given by :math:`2^{l_{x_i}+2}`. The third configuration variable specifies the level :math:`l_t` of the temporal discretization. The number of timesteps satisfies :math:`2^{l_{t}+2}` so the timestep size is and :math:`T/2^{l_{t}+2}`. variable : pya.IndependentMultivariateRandomVariable Object containing information of the joint density of the inputs z which is the tensor product of independent and identically distributed uniform variables on :math:`[-\sqrt{3},\sqrt{3}]`. Examples -------- >>> from pyapprox_dev.benchmarks.benchmarks import setup_benchmark >>> benchmark=setup_benchmark('advection-diffusion',nvars=2) >>> print(benchmark.keys()) dict_keys(['fun', 'variable']) """ from scipy import stats from pyapprox.models.wrappers import TimerModelWrapper, PoolModel, \ WorkTrackingModel from pyapprox.models.wrappers import PoolModel from pyapprox.variables import IndependentMultivariateRandomVariable from pyapprox.benchmarks.benchmarks import Benchmark univariate_variables = [stats.uniform(-np.sqrt(3), 2 * np.sqrt(3))] * nvars variable = IndependentMultivariateRandomVariable(univariate_variables) final_time, degree = 1.0, 1 options = {'corr_len': corr_len} base_model = AdvectionDiffusionModel( final_time, degree, qoi_functional_misc, second_order_timestepping=False, options=options, qoi_functional_grad=qoi_functional_grad_misc) # add wrapper to allow execution times to be captured timer_model = TimerModelWrapper(base_model, base_model) pool_model = PoolModel(timer_model, max_eval_concurrency, base_model=base_model) # add wrapper that tracks execution times. model = WorkTrackingModel(pool_model, base_model, base_model.num_config_vars) attributes = {'fun': model, 'variable': variable} return Benchmark(attributes)