Monte Carlo Simulation#
Overview#
The MonteCarloSimulation class provides high-level interface to uncertainty quantification for dimensionless coefficients in PyDASA, abstracting stochastic computations with distribution/data modes. Generates coefficient distributions under parameter variations for robustness assessment.
The MonteCarloSimulation simplifies stochastic workflows through three core features:
Generates Simulations: Creates
MonteCarloobjects (one per coefficient) automatically.Samples Distributions: Draws values from uniform, normal, or custom distributions.
Accepts Inputs: Takes
AnalysisEngineoutputs for dimensional consistency.
Warning
Precondition: MonteCarloSimulation requires a completed dimensional analysis workflow. The analysis must provide:
Dimensional coefficients (from
AnalysisEngine.solve()orAnalysisEngine.run_analysis())Variable definitions with distribution specifications (
_dist_type,_dist_params,_dist_func)Consistent schema across all components
Use the exact model from Dimensional Analysis as input to ensure proper configuration.
Reynolds Number (\(Re\)) Monte Carlo Example#
This example demonstrates Monte Carlo simulation for the Reynolds number using the dimensional analysis workflow as precondition:
from pydasa import Variable, Schema, AnalysisEngine
from pydasa.dimensional.fundamental import Dimension
from pydasa.workflows.practical import MonteCarloSimulation
import random
import numpy as np
# ========================================================================
# STEP 1: Run Dimensional Analysis (Precondition)
# ========================================================================
# Define custom framework (T, M, L only)
custom_fdus = [
Dimension(_idx=0, _sym="T", _unit="s", _name="Time"),
Dimension(_idx=1, _sym="M", _unit="kg", _name="Mass"),
Dimension(_idx=2, _sym="L", _unit="m", _name="Length")
]
schema = Schema(_fwk="CUSTOM", _fdu_lt=custom_fdus)
# Define variables with distribution specifications
variables = {
"\\rho": Variable(_name="Density",
_sym="\\rho",
_cat="IN",
_dims="M*L^-3",
_units="kg/m³",
_dist_type="uniform",
_dist_params={"a": 990.0, "b": 1020.0},
_dist_func=lambda: random.uniform(990.0, 1020.0),
relevant=True,
_schema=schema),
"v": Variable(_name="Velocity",
_sym="v",
_cat="OUT",
_dims="L*T^-1",
_units="m/s",
_dist_type="uniform",
_dist_params={"a": 1.0, "b": 6.0},
_dist_func=lambda: random.uniform(1.0, 6.0),
relevant=True,
_schema=schema),
"D": Variable(_name="Diameter",
_sym="D",
_cat="IN",
_dims="L",
_units="m",
_dist_type="uniform",
_dist_params={"a": 0.04, "b": 0.06},
_dist_func=lambda: random.uniform(0.04, 0.06),
relevant=True,
_schema=schema),
"\\mu": Variable(_name="Viscosity",
_sym="\\mu",
_cat="IN",
_dims="M*L^-1*T^-1",
_units="Pa·s",
_dist_type="constant",
_dist_params={"value": 0.001002},
_dist_func=lambda: 0.001002,
relevant=True,
_schema=schema),
"g": Variable(_name="Gravity",
_sym="g",
_cat="CTRL",
_dims="L*T^-2",
_units="m/s²",
_dist_type="constant",
_dist_params={"value": 9.81},
_dist_func=lambda: 9.81,
relevant=False,
_schema=schema) # Excluded from matrix
}
# Create and run dimensional analysis
engine = AnalysisEngine(_name="Reynolds Number Analysis",
_fwk="CUSTOM",
_schema=schema,
_variables=variables)
engine.create_matrix()
coefficients = engine.solve()
print(f"Dimensional analysis complete: {list(coefficients.keys())}")
# ========================================================================
# STEP 2: Perform Monte Carlo Simulation
# ========================================================================
# Set seed for reproducibility
np.random.seed(42)
random.seed(42)
# Create Monte Carlo simulation workflow
mc_simulation = MonteCarloSimulation(_name="Reynolds Monte Carlo",
_fwk="CUSTOM",
_cat="DIST",
_experiments=1000,
_variables=variables,
_coefficients=coefficients)
# Run simulation
mc_simulation.run_simulation(iters=1000)
print(f"✓ Monte Carlo simulation complete")
print(f" Experiments: {mc_simulation.experiments}")
print(f" Simulations: {list(mc_simulation.simulations.keys())}")
# ========================================================================
# STEP 3: Extract Results and Statistics
# ========================================================================
# Get Reynolds number simulation results
re_key = "\\Pi_{0}"
re_simulation = mc_simulation.get_simulation(re_key)
print(f"\nReynolds Number Statistics:")
print(f"\tMean: {re_simulation.mean:.2e}")
print(f"\tMedian: {re_simulation.median:.2e}")
print(f"\tStd Dev: {re_simulation.dev:.2e}")
print(f"\tMin: {re_simulation.min:.2e}")
print(f"\tMax: {re_simulation.max:.2e}")
# Extract result arrays for further analysis
results_dict = mc_simulation.results
re_results = results_dict[re_key]["results"]
print(f"\nResult array shape: {re_results.shape}")
print(f"\tFirst 5 results: {re_results[:5]}...")
Displayed Capabilities#
In the example we appreciate the following PyDASA capabilities:
Requires Precondition: Demands completed dimensional analysis with solved coefficients.
Generates Objects: Creates
MonteCarloinstances per coefficient automatically.Configures Sampling: Sets distributions (uniform, constant) from variable specifications.
Runs Iterations: Executes Monte Carlo experiments with random sampling.
Calculates Statistics: Computes mean, median, std dev, min, max per coefficient.
Quantifies uncertainty propagation through dimensionless coefficients for robustness assessment.