Dimensionless Coefficients#

Overview#

Dimensionless coefficients (\(\Pi\)-groups) represent the fundamental output of dimensional analysis in PyDASA, transforming variable relationships into scale-invariant numerical expressions. The Coefficient class implements these dimensionless numbers following the Buckingham Pi-Theorem, providing the mathematical foundation for comparing systems across different scales, platforms, and operational contexts without dimensional constraints.

The Coefficient class inherits from BoundsSpecs (from numerical.py), combining dimensionless mathematical properties with numerical ranges for computational analysis. This composite architecture bridges dimensional theory and practical evaluation, supporting sensitivity analysis through coefficient value exploration across different ranges, and Monte Carlo simulation through stochastic sampling of coefficient distributions derived from variable behaviour.

Dimensional Analysis Result#

Dimensionless coefficients result from solving the dimensional model (diagonalizing the dimensional matrix), producing \(\Pi\)-groups with the the Buckingham Pi-Theorem. These coefficients serve three essential functions. One, represent Scale-Invariants by eliminating dimensional units through variable combinations with specific exponents. Two, reduce System Complexity by transforming n variables with m dimensions into exactly (n - m) dimensionless coefficients. And three, indicate Cross-Platform Equivalences by showing that identical coefficient values reflect equivalent system behavior regardless of scale or implementation.

Composite Architecture#

The Coefficient class combines three architectural layers to support dimensional analysis workflows:

  1. Foundation Layer (from Foundation base class) Provides identity and classification attributes:
    • Name (_name): Identifies coefficient purpose (e.g., “Performance Ratio”, “Mixing Coefficient”).

    • Symbol (_sym): Represents coefficient in mathematical expressions (e.g., “π₁”, “π₂”).

    • Index (_idx): Determines coefficient precedence in analysis ordering.

    • Framework (_fwk): Links to dimensional framework (PHYSICAL, COMPUTATION, SOFTWARE, CUSTOM).

    • Category (_cat): Classifies as COMPUTED (from matrix solution) or DERIVED (from other coefficients).

  2. Numerical Layer (from BoundsSpecs in numerical.py) inherits standardized numerical attributes for computational analysis:
    • Setpoint (_setpoint): Specifies reference value for nominal operating conditions.

    • Bounds (_min, _max): Define feasible coefficient range from variable combinations.

    • Statistics (_mean, _median, _dev): Store central tendency and dispersion measures.

    • Step (_step): Controls discretization granularity for sensitivity sweeps (default: 1e-3).

These attributes operate in dimensionless space, with values derived from standardized variable bounds through coefficient formulas.

  1. Coefficient-Specific Layer Adds dimensional analysis properties:
    • Variables (_variables): Stores Variable objects participating in coefficient construction.

    • Pi Expression (_pi_expr): Contains symbolic formula (e.g., “R*g/v**2” for π₁ = R·g/v²).

    • Variable Dimensions (var_dims): Maps variable symbols to their exponents in coefficient formula.

    • Dimensional Column (_dim_col): Provides vector representation from RREF matrix solution.

    • Pivot List (_pivot_lt): Records pivot column indices identifying core/residual matrix structure.

    • Data Array (_data): Holds computed coefficient values from simulations or measurements.

This layered architecture connects dimensional theory (coefficient construction) with numerical computation (range-based analysis), forming the bridge between symbolic dimensional analysis and quantitative system evaluation.

Analytical Workflows#

The Coefficient class supports two primary computational workflows by inheriting numerical range capabilities from BoundsSpecs:

Sensitivity Analysis: Variable bounds propagate through coefficient formulas to compute feasible ranges, which are discretized using the _step attribute for systematic parameter space exploration. This enables identifying which coefficients most strongly influence system behavior.

Monte Carlo Simulation: Variable distributions generate random samples that evaluate through coefficient formulas, producing coefficient value distributions. The _data array stores samples while _mean, _median, and _dev attributes quantify uncertainty propagation from variables to dimensionless coefficients.

Both workflows transform coefficients from symbolic expressions into computational objects with ranges, distributions, and statistical properties for quantitative system evaluation.

Practical Example#

Consider analyzing projectile motion where the Matrix class derives two coefficients:

import numpy as np
from pydasa import Variable, Schema, Matrix

# Schema and variables from Matrix example
schema = Schema(_fwk="PHYSICAL")
variables = {
    "R": Variable(_name="Range",
                    _sym="R", _cat="OUT",
                    _dims="L",
                    relevant=True,
                    _std_min=10, _std_max=100,
                    _units="m", _schema=schema),
    "v": Variable(_name="Velocity",
                    _sym="v", _cat="IN",
                    _dims="L*T^-1",
                    relevant=True,
                    _std_min=5, _std_max=50,
                    _units="m/s", _schema=schema),
    "g": Variable(_name="Gravity",
                    _sym="g", _cat="CTRL",
                    _dims="L*T^-2",
                    relevant=True,
                    _std_setpoint=9.81, _units="m/s^2",
                    _schema=schema)
}

# Generate dimensional matrix and coefficients
model = Matrix(_name="Projectile",
                _schema=schema,
                _variables=variables)
model.create_matrix()
model.solve_matrix()  # Produces π₁ = R·g/v², π₂ = θ (dimensionless)

# Access coefficient with inherited numerical properties
pi_0 = model.coefficients["\Pi_{0}"]             # Coefficient object for pi_0
print(f"Formula: {pi_0.pi_expr}")                # "R*g/v**2"
print(f"Variables: {pi_0.variables.keys()}")     # dict_keys(['R', 'g', 'v'])
print(f"Exponents: {pi_0.var_dims}")             # {'R': 1, 'g': 1, 'v': -2}

# can setup bounds and discretization to compute data
pi_0.min = variables["R"].std_min * variables["g"].std_setpoint / (variables["v"].std_max ** 2)  # (10*9.81)/(50**2) = 0.039
pi_0.max = variables["R"].std_max * variables["g"].std_setpoint / (variables["v"].std_min ** 2)  # (100*9.81)/(5**2) = 39.24
pi_0.step = 0.1  # Custom step for analysis
pi_0.data = np.arange(pi_0.min, pi_0.max, pi_0.step)  # Grid data for analysis

pi_0._data = np.array(data)
pi_0._mean = np.mean(pi_0._data)    # Average dimensionless coefficient
pi_0._dev = np.std(pi_0._data)      # Coefficient uncertainty
print(f"Monte Carlo mean: {pi_0.mean}, std: {pi_0.dev}")

# or generate data with Monte Carlo sampling using variable bounds
data = []
for _ in range(100):
    R_sample = np.random.uniform(variables["R"].std_min, variables["R"].std_max)
    v_sample = np.random.uniform(variables["v"].std_min, variables["v"].std_max)

    # Compute pi_0 for each sample
    point = pi_0.calculate_setpoint(dict(R=R_sample,
                                        v=v_sample,
                                        g=variables["g"].std_setpoint))
    # Compute pi_0 for each sample
    data.append(point)

pi_0._data = np.array(data)
pi_0._mean = np.mean(pi_0._data)    # Average dimensionless coefficient
pi_0._dev = np.std(pi_0._data)      # Coefficient uncertainty
print(f"Monte Carlo mean: {pi_0.mean}, std: {pi_0.dev}")

This example demonstrates how coefficients bridge dimensional theory and numerical computation: the Matrix class derives symbolic formulas (_pi_expr, var_dims), while inherited BoundsSpecs attributes (_min, _max, _step, _mean, _dev, _data) provide the numerical infrastructure for sensitivity analysis and Monte Carlo simulation without dimensional unit complications.