Dimensional Analysis, Units, and Scale: How Mathematical Models Stay Meaningful

Last Updated June 12, 2026

Dimensional analysis, units, and scale help mathematical models remain meaningful, consistent, and interpretable. A model can use elegant equations and still fail if quantities have incompatible units, parameters are scaled incorrectly, dimensions are ignored, or results are extrapolated beyond an appropriate range.

Units connect mathematical symbols to measurement. Dimensions describe the kind of quantity being represented: length, time, mass, temperature, amount, currency, probability, population, energy, information, or another meaningful category. Scale determines the range, magnitude, resolution, and level of aggregation at which a model operates.

Dimensional reasoning is one of the simplest and strongest checks in modeling. If two sides of an equation have incompatible dimensions, the equation cannot be right as written. If a parameter’s units do not match the time step, the model may behave incorrectly. If a result depends on scale, it may not transfer across contexts. Units and scale are not formatting details; they are part of model design.

Editorial illustration of a scholarly engineering workspace with measuring tools, geometric solids, scales, grids, and drafting studies representing dimensional analysis, units, and scale.
Dimensional analysis, units, and scale help ensure that mathematical models remain consistent, interpretable, and properly matched to the world they describe.

A model’s units tell readers what its quantities mean. A rate measured per day is not the same as a rate measured per year. A spatial model at household scale is not the same as a model at regional scale. A parameter calibrated in meters cannot be used as if it were calibrated in kilometers. A probability is bounded between zero and one, but a count is not. These distinctions shape both the mathematics and the interpretation.

Why Dimensional Analysis, Units, and Scale Matter

Dimensional analysis, units, and scale matter because mathematical models are not just symbolic systems. They are representations of quantities, relationships, and claims. A symbol in a model should stand for something that can be interpreted. Units and dimensions help preserve that interpretation.

A model may look plausible while hiding a unit error. A time-dependent parameter may be calibrated per day but applied per month. A spatial coefficient may be estimated per square kilometer but interpreted per square mile. A flow may be reported as volume per time while storage is reported as mass. These errors can produce outputs that are numerically precise but conceptually meaningless.

Modeling issue Unit or scale question Risk if ignored
Equation design Do both sides have the same dimensions? The equation may be invalid.
Parameter use Do parameter units match the model’s time and space scale? Dynamics may be too fast, too slow, or distorted.
Data integration Are all measurements expressed in compatible units? Inputs may be mixed incorrectly.
Model comparison Are outputs normalized or converted before comparison? Models may appear different or similar for the wrong reason.
Simulation Does the time step match the rate parameters? Numerical behavior may be unstable or invalid.
Interpretation Does the result apply at the scale being discussed? Conclusions may be overextended.
Communication Are units visible to readers? Outputs may be misunderstood.

Dimensional analysis is often associated with physics and engineering, but its broader lesson applies across modeling. Variables, parameters, rates, scores, probabilities, costs, risks, populations, and classifications all require interpretation. A model becomes more trustworthy when those meanings are explicit.

Back to top ↑

Dimensions and Units

A dimension describes the kind of quantity being measured. A unit describes the measurement convention used for that dimension. Length is a dimension. Meters, feet, kilometers, and miles are units. Time is a dimension. Seconds, days, and years are units.

In applied modeling, dimensions may include physical quantities, economic quantities, demographic quantities, probabilities, scores, counts, rates, or constructed indices. The key question is not only whether a quantity has a familiar physical unit, but whether its meaning is clear enough to be used in formal relationships.

Quantity Dimension Possible units Modeling concern
Distance Length meters, kilometers, miles Spatial scale and conversion.
Duration Time seconds, days, years Rate interpretation and time-step consistency.
Storage Amount or volume liters, cubic meters, tons Conservation and capacity constraints.
Flow Amount per time liters/day, tons/year Compatibility with storage and time step.
Rate Per time per day, per year Temporal scaling and conversion.
Probability Dimensionless bounded quantity unit interval Must remain between zero and one.
Cost Currency dollars, euros, local currency Inflation, time value, and comparability.
Population Count people, households, cases Aggregation level and integer meaning.
Index score Constructed scale points, normalized score Interpretation depends on construction.

Units should be documented in variable registers, parameter tables, datasets, output files, figure labels, and interpretation notes. A model that hides units leaves users guessing about what the symbols mean.

Back to top ↑

Dimensional Homogeneity

Dimensional homogeneity means that terms being added, subtracted, or equated must have compatible dimensions. Both sides of an equation must refer to the same kind of quantity. This principle provides a powerful check before computation begins.

\[
[A]=[B]
\]

Interpretation: If an equation states \(A=B\), then \(A\) and \(B\) must have the same dimensions.

For example, if storage \(S_t\) is measured in cubic meters, then inflow and demand must be converted into cubic meters per model time step before they can be added to or subtracted from storage.

\[
S_{t+1}=S_t+\Delta t(I_t-D_t)
\]

Interpretation: If \(I_t\) and \(D_t\) are flows per unit time, multiplying by \(\Delta t\) converts them into storage units for the update.

Operation Dimensional rule Example Common error
Addition Terms must share dimensions. storage + inflow converted to storage. Adding flow directly to storage without time conversion.
Subtraction Terms must share dimensions. available capacity − current storage. Subtracting a rate from a stock.
Equality Both sides must share dimensions. cost = price × quantity. Equating a cost with a rate.
Multiplication Dimensions combine. speed × time = distance. Forgetting the resulting unit.
Division Dimensions form ratios. distance / time = speed. Using ratio without interpreting denominator.
Exponentials and logarithms Arguments should be dimensionless. \(\exp(rt)\) where \(rt\) is dimensionless. Taking log of a dimensional quantity without normalization.

Dimensional homogeneity does not prove that a model is correct, but dimensional inconsistency is a strong warning that something is wrong. It can reveal missing time steps, wrong units, misinterpreted parameters, or invalid equations.

Back to top ↑

Unit Conversion and Measurement Consistency

Unit conversion is a basic but high-stakes modeling task. Mixing units can silently corrupt a model. If one dataset reports area in hectares and another reports square kilometers, they must be converted before comparison. If a rate is annual but a model advances monthly, the rate must be adjusted.

\[
x_{\text{new unit}}=x_{\text{old unit}}\times c
\]

Interpretation: A unit conversion multiplies a measured quantity by a conversion factor \(c\) that preserves the underlying dimension.

Conversion issue Modeling question Risk
Length conversion Are distances in meters, kilometers, feet, or miles? Spatial estimates may be off by orders of magnitude.
Area conversion Are areas in square meters, hectares, or square kilometers? Density and exposure may be distorted.
Time conversion Are rates per second, day, month, or year? Dynamics may be too fast or too slow.
Currency conversion Are values adjusted for currency, year, or inflation? Costs may not be comparable.
Population unit Are counts per person, household, case, or region? Aggregation may be misread.
Percentage versus proportion Is 5 percent represented as 5 or 0.05? Effects may be 100 times too large.

Every data pipeline should include unit checks. Units should not live only in documentation. They should appear in schemas, variable dictionaries, validation scripts, and output labels.

Back to top ↑

Rates, Time Steps, and Temporal Units

Rates are especially vulnerable to unit errors because they combine quantities with time. A loss rate per day is not a loss rate per year. A growth rate used in a continuous exponential model is not automatically the same as a discrete per-step growth factor.

\[
x_{t+\Delta t}=x_t+\Delta t\,r(x_t)
\]

Interpretation: A rate \(r(x_t)\) must be multiplied by the time step \(\Delta t\) before it changes the state \(x_t\).

For proportional growth or decay, the relationship between continuous and discrete rates must be handled carefully:

\[
x(t)=x_0e^{rt}
\]

Interpretation: In a continuous exponential model, \(r\) has units of inverse time, and the product \(rt\) is dimensionless.

Rate issue Example Required check
Per-step rate 5 percent per month. Apply only to monthly time steps unless converted.
Annual rate 12 percent per year. Convert before monthly or daily simulation.
Continuous rate \(r\) in \(e^{rt}\). Ensure \(rt\) is dimensionless.
Flow rate cubic meters per day. Multiply by time step before adding to storage.
Hazard rate events per person-year. Match exposure time and population unit.
Discount rate per year. Match compounding interval and time horizon.

Temporal scale also affects interpretation. A model with daily dynamics may reveal short-term volatility that an annual model smooths away. A model with yearly time steps may be appropriate for long-term strategy but unsuitable for operational control.

Back to top ↑

What Scale Means in Mathematical Modeling

Scale refers to the magnitude, range, resolution, and level of representation used in a model. It can be temporal, spatial, organizational, demographic, numerical, or conceptual. Scale determines what the model can see and what it averages away.

Scale type Meaning Example Modeling concern
Temporal scale Time horizon and time step. hours, days, years, decades. Dynamics, delays, and rates.
Spatial scale Geographic resolution and extent. block, city, region, globe. Aggregation and local variation.
Population scale Unit of analysis. individual, household, institution, nation. Heterogeneity and fairness.
Numerical scale Magnitude of variables and parameters. \(10^{-6}\), \(10^3\), \(10^9\). Conditioning and numerical stability.
Mechanism scale Level of causal detail. micro-behavior versus aggregate trend. Interpretability and transferability.
Decision scale Level at which decisions are made. operational, strategic, policy, institutional. Use limits and legitimacy.

Scale is not only a technical choice. It determines which differences become visible. A national average may hide local vulnerability. A city-level model may hide household variation. A short-term model may miss long-term accumulation. A fine-scale model may require data that do not exist.

Back to top ↑

Orders of Magnitude and Magnitude Checks

Orders of magnitude help modelers detect implausible results quickly. A result may not require exact validation to be suspicious. If a model predicts a population larger than the possible population, a cost ten thousand times larger than expected, or a rate that implies impossible change, the issue may be visible through magnitude checks.

\[
10^k \leq |x| \lt 10^{k+1}
\]

Interpretation: A quantity \(x\) is on the order of magnitude \(10^k\) when its absolute value falls between \(10^k\) and \(10^{k+1}\).

Magnitude check Question Warning sign
Range check Is the result within plausible minimum and maximum bounds? Output exceeds known limits.
Order check Is the magnitude roughly expected? Output differs by factors of 10, 100, or 1000.
Rate check Does implied change over time make sense? System changes faster than physically or socially plausible.
Density check Does amount per area or population make sense? Density exceeds known capacity.
Budget check Does cost align with feasible resources? Recommendation exceeds budget by orders of magnitude.
Probability check Are probabilities within valid bounds? Probability below zero or above one.

Magnitude checks are not a substitute for validation, but they are useful early warnings. They can reveal unit conversion mistakes, misplaced decimal points, incorrect scaling, invalid assumptions, or coding errors.

Back to top ↑

Nondimensionalization

Nondimensionalization converts variables into dimensionless quantities by scaling them against characteristic values. This can simplify equations, reveal important ratios, improve numerical behavior, and make models easier to compare across systems.

\[
x^\ast=\frac{x}{x_c}
\]

Interpretation: The dimensionless variable \(x^\ast\) compares \(x\) to a characteristic scale \(x_c\).

For example, if storage \(S_t\) is bounded by capacity \(K\), the ratio \(S_t/K\) expresses storage as a fraction of capacity. This dimensionless value can be compared across systems with different absolute capacities.

\[
s_t=\frac{S_t}{K}
\]

Interpretation: The dimensionless storage fraction \(s_t\) measures storage relative to capacity.

Scaling choice Dimensionless quantity Interpretation
Storage by capacity \(S/K\) Fraction of capacity used.
Time by characteristic time \(t/T\) Time relative to typical process duration.
Distance by length scale \(x/L\) Position relative to system size.
Flow by reference flow \(I/I_c\) Flow relative to typical or maximum flow.
Cost by budget \(C/B\) Cost relative to available budget.
Error by tolerance \(e/\tau\) Error relative to acceptable threshold.

Nondimensionalization is powerful because it exposes ratios that govern behavior. It can show whether a process is dominated by inflow, loss, capacity, delay, diffusion, inertia, or another mechanism. It also supports comparison across differently sized systems.

Back to top ↑

Scaling Laws and Similarity

Scaling laws describe how one quantity changes with another across scales. They often appear as power laws, proportional relationships, or similarity rules. In modeling, scaling laws can support extrapolation, comparison, experimental design, and simplification, but they must be justified.

\[
y=ax^b
\]

Interpretation: A power-law scaling relationship states that \(y\) changes with \(x\) according to exponent \(b\).

The exponent matters. If \(b=1\), the relationship is proportional. If \(b=2\), the quantity scales with area-like behavior. If \(b=3\), it scales with volume-like behavior. If \(b\lt1\), the relationship shows sublinear scaling. If \(b\gt1\), it shows superlinear scaling.

Scaling form Meaning Modeling concern
Linear scaling \(y\propto x\) Effect grows proportionally with size.
Area scaling \(y\propto L^2\) Surface or spatial coverage matters.
Volume scaling \(y\propto L^3\) Mass, volume, or capacity may dominate.
Sublinear scaling \(b\lt1\) Efficiency, saturation, or economies of scale.
Superlinear scaling \(b\gt1\) Amplification, congestion, or compounding effects.
Similarity scaling Dimensionless groups match across systems. Transfer depends on matching governing ratios.

Scaling laws can be seductive because they appear simple and powerful. They should not be used as universal shortcuts. A scaling law valid in one range may fail outside it. A fitted scaling relationship may not represent mechanism. A model should state the scale range over which the relationship is intended to apply.

Back to top ↑

Numerical Scale and Computational Stability

Numerical scale affects computation. Models that combine very small and very large numbers can become poorly conditioned. Optimization solvers, numerical differential equation methods, regression procedures, and simulation workflows may behave poorly when variables differ by many orders of magnitude.

Scaling variables can improve numerical stability and interpretability. Standardization, normalization, nondimensionalization, and unit conversion can all help, but each changes how quantities should be interpreted.

Numerical issue Cause Possible response Review concern
Poor conditioning Variables differ greatly in magnitude. Rescale variables. Keep interpretation clear.
Roundoff error Very small differences between large values. Use stable algorithms. Check sensitivity to precision.
Overflow or underflow Exponentials or products become extreme. Use log transformations carefully. Respect domain restrictions.
Solver difficulty Badly scaled constraints or objectives. Normalize constraints and variables. Ensure rescaled solution maps back correctly.
Misleading coefficients Input units differ widely. Report units and standardized effects separately. Avoid overinterpreting scaled coefficients.

Numerical scaling is not merely a computing concern. If scaling is used to make algorithms work, the model must still communicate what the original quantities mean.

Back to top ↑

Aggregation, Resolution, and Scale Dependence

Aggregation changes what a model can show. A model at one scale may not preserve relationships visible at another scale. Household patterns may disappear in city averages. Local hazards may disappear in regional summaries. Short-term shocks may disappear in annual averages.

Scale dependence occurs when the model’s conclusions change as the unit, resolution, or extent of analysis changes. This is not always an error. Sometimes it reveals that the process itself operates differently across scales. But it should be examined rather than ignored.

Scale decision What it changes Possible distortion
Spatial aggregation Combines smaller locations into larger regions. Local extremes may disappear.
Temporal aggregation Combines short intervals into longer periods. Peaks, delays, or cycles may be smoothed away.
Population aggregation Combines individuals or groups. Distributional effects may be hidden.
Mechanism aggregation Combines processes into summary coefficients. Causal detail may be lost.
Decision aggregation Combines outcomes into one score. Trade-offs and values may be obscured.

Aggregation should be chosen to match the model’s purpose. A model for public communication may use coarser scale than a model for operational control. A model for policy legitimacy may need distributional resolution that a technical efficiency model lacks.

Back to top ↑

Mathematical Lens: Dimension Vectors and Unit Consistency

Dimensions can be represented formally as vectors over base dimensions. For example, a velocity has length dimension divided by time dimension. A flow may have amount dimension divided by time dimension.

\[
[q]=L^aT^bM^c
\]

Interpretation: The dimension of quantity \(q\) can be expressed using powers of base dimensions such as length \(L\), time \(T\), and mass \(M\).

Dimensional homogeneity requires that terms in an equation share the same dimension:

\[
[x+y]\ \text{is defined only when}\ [x]=[y]
\]

Interpretation: Addition and subtraction require compatible dimensions.

For a rate equation:

\[
\frac{dS}{dt}=I-D-\lambda S
\]

Interpretation: Each term on the right side must have units of storage per time, matching \(dS/dt\).

If \(S\) is storage, then \(\lambda\) must have units of inverse time:

\[
[\lambda]=T^{-1}
\]

Interpretation: A proportional loss parameter must be measured per unit time so that \(\lambda S\) is storage per time.

This lens helps reveal missing factors, incorrect rates, invalid transformations, and inconsistent units before a model is implemented.

Back to top ↑

Example: Unit and Scale Checks in a Resource Model

Consider a resource model with storage \(S_t\), inflow \(I_t\), demand \(D_t\), capacity \(K\), loss rate \(\lambda\), and time step \(\Delta t\). If storage is measured in cubic meters and flows are measured in cubic meters per day, the update must include the time step:

\[
S_{t+1}=S_t+\Delta t(I_t-D_t-\lambda S_t)
\]

Interpretation: The flow terms are converted into storage units by multiplying by the time step \(\Delta t\).

The constrained update adds bounds:

\[
S_{t+1}=\min\left(K,\max\left(0,S_t+\Delta t(I_t-D_t-\lambda S_t)\right)\right)
\]

Interpretation: Storage is kept between zero and capacity after unit-consistent updating.

A dimensionless storage fraction can help compare systems of different sizes:

\[
s_t=\frac{S_t}{K}
\]

Interpretation: The storage fraction \(s_t\) expresses storage relative to capacity.

Quantity Meaning Unit Dimensional check
\(S_t\) Storage at time \(t\). cubic meters Stock quantity.
\(I_t\) Inflow rate. cubic meters per day Must be multiplied by \(\Delta t\).
\(D_t\) Demand rate. cubic meters per day Must be multiplied by \(\Delta t\).
\(\lambda\) Proportional loss rate. per day \(\lambda S_t\) has flow units.
\(\Delta t\) Time step. days Converts rates to stock changes.
\(K\) Capacity. cubic meters Same unit as storage.
\(s_t\) Storage fraction. dimensionless Comparable across capacities.

This example shows why units matter. Without \(\Delta t\), the model would add flows directly to storage. Without a capacity unit, the bound would be ambiguous. Without nondimensional storage, comparison across systems would be harder.

Back to top ↑

Validation, Sensitivity, and Scale Review

Validation should include unit and scale review. A model can fit observed data while still using fragile or poorly documented units. A model can validate at one scale and fail at another. A model can behave well for one time step and poorly when the time step changes.

Review area Question Diagnostic
Unit register Does every variable and parameter have a unit? Variable and parameter table.
Dimensional homogeneity Are equations dimensionally consistent? Equation audit.
Time-step consistency Do rates match the simulation step? Rate conversion check.
Scale sensitivity Do results change across time, space, or aggregation scale? Scale comparison.
Magnitude plausibility Are outputs in plausible ranges? Order-of-magnitude check.
Numerical conditioning Do variables differ greatly in size? Scaling and conditioning review.
Transferability Does the model apply outside the calibration scale? Scope and extrapolation review.

Scale review should be connected to purpose. A model intended for explanation may tolerate simpler scaling than a model intended for operational control. A model used in public policy may need distributional scale checks because aggregate outputs can hide localized harm.

Back to top ↑

Ethical Stakes of Units and Scale

Units and scale have ethical consequences because they influence what a model makes visible. A policy model expressed only in total cost may hide cost per affected person. A climate or infrastructure model at regional scale may hide neighborhood vulnerability. A health model that reports average risk may hide subgroup risk. A scoring model may treat a constructed index as if it were a direct measurement.

Choice Ethical risk Responsible practice
Aggregate unit Hides local or subgroup harm. Report distributional or disaggregated diagnostics.
Per-capita unit Can obscure total burden or institutional capacity. Report both per-capita and total values where relevant.
Normalized score May hide the original measurement meaning. Explain construction and limitations.
Short time horizon May ignore long-term accumulation. Include horizon sensitivity.
Large spatial scale May smooth away vulnerability. Test smaller-scale patterns where data allow.
Unit conversion error Can produce misleading recommendations. Use reproducible unit checks and clear labeling.

Responsible modeling requires attention to who or what disappears when units are aggregated, normalized, converted, or averaged. Scale is not only a technical parameter; it is a framing choice.

Back to top ↑

Python Workflow: Unit Register and Dimensional Audit

The Python workflow below creates a unit register, checks a resource model for time-step consistency, simulates several unit and scale scenarios, and exports audit tables.

# dimensional_analysis_units_scale_workflow.py
# Dependency-light workflow for unit registers, dimensional checks, and scale review.

from __future__ import annotations

from dataclasses import asdict, dataclass
from pathlib import Path
import csv
import json
from statistics import mean


ARTICLE_ROOT = Path(__file__).resolve().parents[1]
OUTPUTS = ARTICLE_ROOT / "outputs"
TABLES = OUTPUTS / "tables"
JSON_DIR = OUTPUTS / "json"


@dataclass(frozen=True)
class UnitRecord:
    key: str
    quantity_type: str
    unit: str
    dimension: str
    expected_range: str
    review_question: str
    status: str


@dataclass(frozen=True)
class ScaleScenario:
    name: str
    initial_storage_m3: float
    capacity_m3: float
    inflow_m3_per_day: float
    demand_m3_per_day: float
    loss_rate_per_day: float
    delta_t_days: float
    periods: int


def validate_scenario(scenario: ScaleScenario) -> None:
    if scenario.initial_storage_m3 < 0:
        raise ValueError("initial storage must be nonnegative.")
    if scenario.capacity_m3 <= 0:
        raise ValueError("capacity must be positive.")
    if scenario.initial_storage_m3 > scenario.capacity_m3:
        raise ValueError("initial storage cannot exceed capacity.")
    if scenario.inflow_m3_per_day < 0 or scenario.demand_m3_per_day < 0:
        raise ValueError("flows must be nonnegative.")
    if not 0 <= scenario.loss_rate_per_day <= 1:
        raise ValueError("loss rate must be between 0 and 1 per day.")
    if scenario.delta_t_days <= 0:
        raise ValueError("time step must be positive.")
    if scenario.periods < 1:
        raise ValueError("periods must be at least 1.")


def unit_register() -> list[UnitRecord]:
    return [
        UnitRecord(
            key="storage",
            quantity_type="stock",
            unit="m3",
            dimension="volume",
            expected_range="[0, capacity]",
            review_question="Does storage remain within physical bounds?",
            status="active",
        ),
        UnitRecord(
            key="capacity",
            quantity_type="stock_bound",
            unit="m3",
            dimension="volume",
            expected_range="positive",
            review_question="Is capacity in the same unit as storage?",
            status="active",
        ),
        UnitRecord(
            key="inflow",
            quantity_type="flow",
            unit="m3/day",
            dimension="volume/time",
            expected_range="nonnegative",
            review_question="Is inflow multiplied by the model time step?",
            status="review",
        ),
        UnitRecord(
            key="demand",
            quantity_type="flow",
            unit="m3/day",
            dimension="volume/time",
            expected_range="nonnegative",
            review_question="Is demand multiplied by the model time step?",
            status="review",
        ),
        UnitRecord(
            key="loss_rate",
            quantity_type="rate",
            unit="1/day",
            dimension="time^-1",
            expected_range="[0, 1] for daily fractional loss",
            review_question="Does the loss-rate unit match the time step?",
            status="review",
        ),
        UnitRecord(
            key="storage_fraction",
            quantity_type="dimensionless_ratio",
            unit="dimensionless",
            dimension="1",
            expected_range="[0, 1]",
            review_question="Is dimensionless storage used for cross-scale comparison?",
            status="active",
        ),
    ]


def simulate(scenario: ScaleScenario) -> list[dict[str, object]]:
    validate_scenario(scenario)
    storage = scenario.initial_storage_m3
    rows: list[dict[str, object]] = []

    for period in range(scenario.periods + 1):
        inflow_volume = scenario.delta_t_days * scenario.inflow_m3_per_day
        demand_volume = scenario.delta_t_days * scenario.demand_m3_per_day
        loss_volume = scenario.delta_t_days * scenario.loss_rate_per_day * storage
        raw_next = storage + inflow_volume - demand_volume - loss_volume
        shortage = max(0.0, -raw_next)
        overflow = max(0.0, raw_next - scenario.capacity_m3)
        next_storage = min(scenario.capacity_m3, max(0.0, raw_next))
        storage_fraction = next_storage / scenario.capacity_m3

        rows.append({
            "scenario": scenario.name,
            "period": period,
            "storage_m3": round(storage, 8),
            "inflow_volume_m3": round(inflow_volume, 8),
            "demand_volume_m3": round(demand_volume, 8),
            "loss_volume_m3": round(loss_volume, 8),
            "raw_next_storage_m3": round(raw_next, 8),
            "next_storage_m3": round(next_storage, 8),
            "storage_fraction": round(storage_fraction, 8),
            "shortage_m3": round(shortage, 8),
            "overflow_m3": round(overflow, 8),
            "domain_valid": 0.0 <= next_storage <= scenario.capacity_m3,
        })

        storage = next_storage

    return rows


def summarize(rows: list[dict[str, object]]) -> dict[str, object]:
    storage = [float(row["storage_m3"]) for row in rows]
    fractions = [float(row["storage_fraction"]) for row in rows]
    shortages = [float(row["shortage_m3"]) for row in rows]
    overflows = [float(row["overflow_m3"]) for row in rows]
    domain_flags = [bool(row["domain_valid"]) for row in rows]

    return {
        "scenario": str(rows[0]["scenario"]),
        "final_storage_m3": round(storage[-1], 8),
        "mean_storage_m3": round(mean(storage), 8),
        "min_storage_fraction": round(min(fractions), 8),
        "max_storage_fraction": round(max(fractions), 8),
        "shortage_periods": sum(1 for value in shortages if value > 0),
        "overflow_periods": sum(1 for value in overflows if value > 0),
        "domain_violations": sum(1 for value in domain_flags if not value),
        "total_shortage_m3": round(sum(shortages), 8),
        "total_overflow_m3": round(sum(overflows), 8),
    }


def unit_risk_score(record: UnitRecord) -> float:
    score = {"active": 1.0, "review": 5.0, "revise": 8.0, "archive": 2.0}.get(
        record.status.lower(),
        4.0,
    )
    text = f"{record.quantity_type} {record.unit} {record.review_question}".lower()
    for term in ["flow", "rate", "time step", "dimensionless", "capacity", "conversion"]:
        if term in text:
            score += 1.0
    return round(score, 3)


def write_csv(path: Path, rows: list[dict[str, object]]) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    if not rows:
        raise ValueError(f"No rows supplied for {path}")
    with path.open("w", newline="", encoding="utf-8") as handle:
        writer = csv.DictWriter(handle, fieldnames=list(rows[0].keys()))
        writer.writeheader()
        writer.writerows(rows)


def write_json(path: Path, payload: object) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    with path.open("w", encoding="utf-8") as handle:
        json.dump(payload, handle, indent=2, sort_keys=True)


def main() -> None:
    scenarios = [
        ScaleScenario("daily_baseline", 80.0, 100.0, 8.0, 6.0, 0.015, 1.0, 60),
        ScaleScenario("weekly_step", 80.0, 100.0, 8.0, 6.0, 0.015, 7.0, 12),
        ScaleScenario("high_demand", 80.0, 100.0, 8.0, 10.0, 0.015, 1.0, 60),
        ScaleScenario("tight_capacity", 70.0, 75.0, 8.0, 6.0, 0.015, 1.0, 60),
    ]

    all_rows: list[dict[str, object]] = []
    summary_rows: list[dict[str, object]] = []

    for scenario in scenarios:
        rows = simulate(scenario)
        all_rows.extend(rows)
        summary_rows.append(summarize(rows))

    unit_rows = [
        {**asdict(record), "unit_risk_score": unit_risk_score(record)}
        for record in unit_register()
    ]

    write_csv(TABLES / "unit_scale_timeseries.csv", all_rows)
    write_csv(TABLES / "unit_scale_summary.csv", summary_rows)
    write_csv(TABLES / "unit_register.csv", unit_rows)

    write_json(JSON_DIR / "dimensional_audit_card.json", {
        "article": "Dimensional Analysis, Units, and Scale",
        "unit_register": unit_rows,
        "scenario_summaries": summary_rows,
        "audit_checks": [
            "stocks and capacities share units",
            "flows are multiplied by the model time step",
            "loss-rate unit matches the time step",
            "dimensionless storage fraction remains between zero and one",
            "shortage and overflow are reported with units",
        ],
    })

    print("Dimensional analysis, units, and scale workflow complete.")
    print(f"Wrote outputs to {OUTPUTS}")


if __name__ == "__main__":
    main()

This workflow makes unit logic explicit. It separates storage units, flow units, rate units, time-step conversion, and dimensionless comparison so that errors are easier to detect and review.

Back to top ↑

R Workflow: Scale and Unit Diagnostics

The R workflow below reviews generated unit and scale summaries, classifies scenarios by shortage and domain behavior, and creates a diagnostic plot of storage fraction ranges.

# dimensional_analysis_units_scale_review.R
# Base R workflow for scale and unit diagnostics.

args <- commandArgs(trailingOnly = FALSE)
file_arg <- grep("^--file=", args, value = TRUE)

if (length(file_arg) > 0) {
  script_path <- normalizePath(sub("^--file=", "", file_arg[1]), mustWork = TRUE)
  article_root <- normalizePath(file.path(dirname(script_path), ".."), mustWork = TRUE)
} else {
  article_root <- getwd()
}

tables_dir <- file.path(article_root, "outputs", "tables")
figures_dir <- file.path(article_root, "outputs", "figures")
dir.create(tables_dir, recursive = TRUE, showWarnings = FALSE)
dir.create(figures_dir, recursive = TRUE, showWarnings = FALSE)

summary_path <- file.path(tables_dir, "unit_scale_summary.csv")
unit_path <- file.path(tables_dir, "unit_register.csv")

if (!file.exists(summary_path)) {
  stop("Missing unit_scale_summary.csv. Run the Python workflow first.")
}

summary_data <- read.csv(summary_path, stringsAsFactors = FALSE)

summary_data$scale_review <- ifelse(
  summary_data$domain_violations > 0,
  "domain violation detected",
  ifelse(
    summary_data$shortage_periods > 0 | summary_data$overflow_periods > 0,
    "constraint or scale limit active",
    "unit and scale behavior stable"
  )
)

write.csv(
  summary_data,
  file.path(tables_dir, "r_unit_scale_review_summary.csv"),
  row.names = FALSE
)

if (file.exists(unit_path)) {
  units <- read.csv(unit_path, stringsAsFactors = FALSE)

  units$priority <- ifelse(
    units$unit_risk_score >= 8,
    "high",
    ifelse(units$unit_risk_score >= 6, "medium", "low")
  )

  write.csv(
    units,
    file.path(tables_dir, "r_unit_review_queue.csv"),
    row.names = FALSE
  )
}

png(file.path(figures_dir, "r_storage_fraction_range.png"), width = 1100, height = 720)

barplot(
  height = rbind(summary_data$min_storage_fraction, summary_data$max_storage_fraction),
  beside = TRUE,
  names.arg = summary_data$scenario,
  las = 2,
  ylab = "Storage fraction",
  main = "Storage Fraction Ranges Across Unit and Scale Scenarios"
)

legend(
  "topright",
  legend = c("Minimum storage fraction", "Maximum storage fraction"),
  fill = gray.colors(2)
)

grid()
dev.off()

print(summary_data)

The R workflow helps reveal whether changing temporal scale, capacity scale, or demand magnitude changes the model’s behavior in ways that require review.

Back to top ↑

Haskell Workflow: Typed Units and Dimensions

Haskell is useful for this article because unit and dimension categories should not collapse into loose labels. A stock is different from a flow. A rate is different from a dimensionless ratio. A typed layer helps preserve those distinctions.

{-# OPTIONS_GHC -Wall #-}

module Main where

data Dimension
  = Volume
  | Time
  | VolumePerTime
  | InverseTime
  | Dimensionless
  deriving (Eq, Show)

data ReviewStatus
  = Active
  | RequiresReview
  | RequiresValidation
  | Revise
  deriving (Eq, Show)

data UnitRecord = UnitRecord
  { key :: String
  , dimension :: Dimension
  , unitLabel :: String
  , interpretation :: String
  , reviewQuestion :: String
  , status :: ReviewStatus
  } deriving (Eq, Show)

unitRegister :: [UnitRecord]
unitRegister =
  [ UnitRecord
      "storage"
      Volume
      "m^3"
      "Storage stock."
      "Does storage remain within physical bounds?"
      Active
  , UnitRecord
      "inflow"
      VolumePerTime
      "m^3/day"
      "Inflow rate."
      "Is inflow multiplied by the model time step?"
      RequiresReview
  , UnitRecord
      "demand"
      VolumePerTime
      "m^3/day"
      "Demand rate."
      "Is demand multiplied by the model time step?"
      RequiresReview
  , UnitRecord
      "loss_rate"
      InverseTime
      "1/day"
      "Proportional loss rate."
      "Does the loss-rate unit match the model time step?"
      RequiresValidation
  , UnitRecord
      "storage_fraction"
      Dimensionless
      "1"
      "Storage divided by capacity."
      "Is dimensionless comparison used responsibly?"
      Active
  ]

needsReview :: UnitRecord -> Bool
needsReview item =
  case status item of
    Active -> False
    _ -> True

main :: IO ()
main = do
  putStrLn "Typed unit and dimension records:"
  mapM_ print unitRegister

  putStrLn "\nUnit records requiring review:"
  mapM_ print (filter needsReview unitRegister)

This typed layer supports model governance by requiring each quantity to identify its dimension, unit, interpretation, review question, and status.

Back to top ↑

GitHub Repository

The companion repository for this article is designed as a reproducible mathematical-modeling workspace. It contains article-specific code, data, documentation, notebooks, schemas, and generated outputs for unit registers, dimensional audits, scale scenarios, time-step checks, nondimensional storage ratios, typed Haskell unit records, validation planning, and reproducible engineering/statistical workflows.

Back to top ↑

A Practical Method for Dimensional and Scale Review

Dimensional and scale review should be part of model design, implementation, validation, and communication. The method below can be used before coding, during repository review, or before publishing model results.

Step Task Question Artifact
1 List all quantities What variables, parameters, inputs, and outputs appear? Quantity register.
2 Assign units What unit is used for each quantity? Unit table.
3 Assign dimensions What kind of quantity is each symbol? Dimension table.
4 Check equations Are equations dimensionally homogeneous? Equation audit.
5 Check rates Do rates match the time step? Rate conversion note.
6 Check conversions Are all datasets converted consistently? Conversion log.
7 Review scale What temporal, spatial, population, and decision scale is used? Scale statement.
8 Test magnitude Are outputs plausible by order of magnitude? Magnitude check.
9 Communicate limits Where do units, scale, or aggregation limit interpretation? Use-limit note.

This method helps prevent unit and scale assumptions from disappearing into notation, data pipelines, or code. It also makes the model easier to reuse and audit.

Back to top ↑

Common Pitfalls

Unit and scale errors are common because they often look like ordinary numbers. The following pitfalls deserve special attention.

  • Adding stocks and flows: adding a flow directly to a stock without multiplying by a time step.
  • Rate mismatch: using an annual rate in a monthly or daily model without conversion.
  • Percentage confusion: treating 5 percent as 5 instead of 0.05.
  • Hidden unit conversion: converting units in code without documenting the conversion.
  • Dimensional inconsistency: equating or adding quantities with incompatible dimensions.
  • Invalid logarithms: taking logs of dimensional, zero, or negative values without proper transformation.
  • Scale overreach: applying results outside the scale where the model was designed or calibrated.
  • Aggregation blindness: using averages that hide local or subgroup variation.
  • Numerical scaling confusion: rescaling variables for computation but interpreting coefficients as if unscaled.
  • Unlabeled outputs: presenting figures, tables, or metrics without units.

These pitfalls can be reduced through unit registers, dimensional audits, conversion logs, scale statements, magnitude checks, and reproducible workflows that keep units visible from input to output.

Back to top ↑

Conclusion: Units Carry Meaning

Dimensional analysis, units, and scale are central to mathematical modeling because they preserve meaning. They tell us what quantities represent, how they can be combined, when equations are valid, how rates should be interpreted, and where conclusions can responsibly travel.

A model is not improved by notation alone. It becomes stronger when each variable has a unit, each parameter has a scale, each equation is dimensionally homogeneous, each rate matches the time step, and each output is interpreted within the correct range.

Dimensional reasoning is both a technical discipline and a communication practice. It helps modelers find errors early, compare systems carefully, explain results clearly, and avoid precise but meaningless conclusions.

Units are not decoration. Scale is not background. They are part of the model’s logic.

Back to top ↑

Back to top ↑

Further Reading

Back to top ↑

References

Back to top ↑

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top