zoomy_core.model.derivation.nondim

zoomy_core.model.derivation.nondim#

Non-dimensional scaling of a derivation Model, the order-based shallow truncation and the closure inserted in the scaled frame (design: docs/dev/symbolic_solver/research/ nondimensional_scaling.md).

The pipeline acts on the 3-D balance laws in physical coordinates, before the sigma map:

m.apply(NonDimensionalize(...))     # scales + groups (Buckingham-Pi checked)
m.apply(ShallowScaling(...))        # drop every term beyond its row's eps order
m.apply(InsertClosure(closures))    # material law in the scaled frame, consistency check
m.apply(ShallowScaling())           # same orders: the closure's own sub-leading terms
m.apply(Dimensionalize())           # back to the physical variables

NonDimensionalize rewrites every term c * T(fields) of a row as Pi(groups) * T(hat fields): fields are replaced by scale * hat, a derivative in a coordinate picks up 1 / scale, the row is divided by its scale and every dimensional constant is written through the repeating reference scales and the groups, which must then cancel (dimensional homogeneity). The coordinate symbols are kept and read as the scaled coordinates. Group coefficients always stand in front of the field part, so the eps order of a term is read off its coefficient.

Module Contents#

Classes#

Dim

Physical dimension M^a L^b T^c (rational exponents).

PiBasis

The Buckingham-Pi check of a set of target groups over dimensional quantities.

Role

The kind of a scaled row; ShallowScaling takes one truncation order per role.

Affine

A field scaled about a known background: f = background + scale * hat, e.g. the pressure p = rho g (s - z) + rho U^2 q_hat (thesis eq. (pressure-scaling)).

Regime

The orders of the groups in the small parameter, {group name: k} for group = O(eps^k), e.g. Regime(De=1) for De = O(eps). Groups not listed take their default order (the scaling’s, then the closures’); the small parameter itself is order 1.

NonDimState

The scaled frame of a model: fields and coordinates with their scales, the groups and the Pi basis, the scaled rows (role, scale), the regime and orders once truncated, and the closure record of InsertClosure.

NonDimensionalize

Rewrite the listed rows of a model in scaled variables and dimensionless groups.

ShallowScaling

Drop every term of a scaled row whose eps order exceeds the row’s order.

ClosureRecord

What InsertClosure decided, read by the model after Dimensionalize.

InsertClosure

Insert the material law in the scaled frame and check it against the stress ansatz.

Dimensionalize

Back from the scaled frame to the physical variables (inverse of NonDimensionalize).

Data#

API#

class zoomy_core.model.derivation.nondim.Dim(M=0, L=0, T=0)#

Physical dimension M^a L^b T^c (rational exponents).

Initialization

Store the exponents of mass, length and time.

property dimensionless#

True for M^0 L^0 T^0.

zoomy_core.model.derivation.nondim.ONE#

‘Dim(…)’

zoomy_core.model.derivation.nondim.VELOCITY#

None

zoomy_core.model.derivation.nondim.ACCELERATION#

None

zoomy_core.model.derivation.nondim.DENSITY#

None

zoomy_core.model.derivation.nondim.STRESS#

None

zoomy_core.model.derivation.nondim.KINEMATIC_VISCOSITY#

None

zoomy_core.model.derivation.nondim.PARAMETER_DIMENSIONS#

None

exception zoomy_core.model.derivation.nondim.DimensionError#

Bases: ValueError

A scale, group or term that is not dimensionally consistent.

Initialization

Initialize self. See help(type(self)) for accurate signature.

exception zoomy_core.model.derivation.nondim.ScalingError#

Bases: ValueError

A closure or term that is inconsistent with the scaling (the consistency check).

Initialization

Initialize self. See help(type(self)) for accurate signature.

class zoomy_core.model.derivation.nondim.PiBasis(quantities, groups, prefer=())#

The Buckingham-Pi check of a set of target groups over dimensional quantities.

Verifies that every group is dimensionless, that the groups are independent, and that they are complete (#groups = #quantities - rank(dimension matrix)), then writes every quantity as a monomial of the repeating quantities and the groups. The groups are never chosen here (the choice is not unique); suggest() proposes a basis.

Args

  • quantities: {Symbol: Dim} of the reference scales and parameters.

  • groups: {group Symbol: definition}, a definition a monomial of the quantities and of the groups defined before it.

  • prefer: quantities to try first as repeating variables, in order.

Initialization

Run the check; raises DimensionError naming the offending or missing group.

suggest()#

A basis of dimensionless groups over the quantities (integer exponents).

class zoomy_core.model.derivation.nondim.Role#

Bases: zoomy_core.misc.options.Option

The kind of a scaled row; ShallowScaling takes one truncation order per role.

Initialization

Initialize self. See help(type(self)) for accurate signature.

horizontal#

‘horizontal’

vertical#

‘vertical’

mass#

‘mass’

class zoomy_core.model.derivation.nondim.Affine(background, scale, name=None)#

A field scaled about a known background: f = background + scale * hat, e.g. the pressure p = rho g (s - z) + rho U^2 q_hat (thesis eq. (pressure-scaling)).

Args

  • background: dimensional expression in the model’s fields and coordinates.

  • scale: scale of the fluctuation.

  • name: name of the fluctuation’s scaled field (default: the field’s name).

Initialization

Store the background, the scale and the scaled field’s name.

class zoomy_core.model.derivation.nondim.Regime(**orders)#

The orders of the groups in the small parameter, {group name: k} for group = O(eps^k), e.g. Regime(De=1) for De = O(eps). Groups not listed take their default order (the scaling’s, then the closures’); the small parameter itself is order 1.

Initialization

Store the orders by group name.

merged(defaults)#

These orders over defaults ({name: k}).

class zoomy_core.model.derivation.nondim.NonDimState(fields, coord_scales, references, parameters, groups, rows, small, default_orders, prefer=())#

The scaled frame of a model: fields and coordinates with their scales, the groups and the Pi basis, the scaled rows (role, scale), the regime and orders once truncated, and the closure record of InsertClosure.

Initialization

Build the state and run the Pi check over the reference scales and parameters.

extend(parameters=None, groups=None, orders=None)#

Add closure parameters ({Symbol: Dim}), their groups and default orders, and rerun the Pi check (a parameter without a group fails it, naming the missing group).

bind(reference, value, parameters)#

Fix the free reference scale reference to value, an expression in the other quantities and the new parameters ({Symbol: Dim}), e.g. the stress scale S = rho nu U / H of a Newtonian closure: the groups and field scales are rewritten and the Pi check is rerun without reference.

scale_of(field)#

The scale of a field (head or applied) or of a coordinate symbol.

to_groups(coeff, what='')#

Write the dimensional constant coeff through the groups; raises DimensionError when a repeating quantity is left (the term is not dimensionally homogeneous).

from_groups(coeff)#

The dimensional value of a group coefficient (groups -> definitions).

order_map()#

{group Symbol: order} of the active regime (small parameter: 1).

split(term)#

(coefficient, field part) of a scaled term; the coefficient is the product of the constant factors. Raises when a group is left inside the field part.

order(term)#

eps order of a scaled term, read off its group coefficient.

scaled(e)#

Dimensional expression -> scaled fields with explicit dimensional constants.

unscaled(e)#

Scaled field part -> dimensional fields (inverse of scaled, constants in front).

to_scaled_row(expr, name)#

A dimensional row -> sum Pi_k T_k(hat fields) divided by the row scale.

normalize(expr, name)#

Re-split a scaled row whose derivatives may carry group factors inside (after a substitution), so every coefficient stands in front again.

to_dimensional_row(expr, name)#

A scaled row -> its dimensional form (times the row scale).

class zoomy_core.model.derivation.nondim.NonDimensionalize(scales, groups, references, dimensions, rows, small, orders=None, prefer=(), name='nondimensionalize')#

Bases: zoomy_core.model.operations.Operation

Rewrite the listed rows of a model in scaled variables and dimensionless groups.

Every coordinate, field, parameter and stress component gets a scale (scales); every symbol declares its dimension (dimensions, the model parameters default to PARAMETER_DIMENSIONS). The target groups (groups) are the user’s choice and are only validated (PiBasis): dimensionless, independent and complete.

Args

  • scales: {applied field | coordinate Symbol: scale | Affine}.

  • groups: {group Symbol: definition} over the reference scales and parameters.

  • references: {reference-scale Symbol: Dim} (e.g. L, H, U, S).

  • dimensions: {applied field | coordinate: Dim} of every scaled field and coordinate.

  • rows: {equation name: (Role, row scale)}; the row is divided by its scale.

  • small: the group that is the expansion parameter (order 1).

  • orders: default regime {group name: order}.

  • prefer: reference scales tried first as repeating quantities.

Initialization

Store the scaling specification.

whole_model_op#

True

apply_to_model(m)#

Check the scales and groups, rewrite the rows, record m.nondim.

class zoomy_core.model.derivation.nondim.ShallowScaling(horizontal=None, vertical=None, mass=0, regime=None, name='shallow_scaling')#

Bases: zoomy_core.model.operations.Operation

Drop every term of a scaled row whose eps order exceeds the row’s order.

The order of a term is read off its group coefficient with the regime’s group orders (Regime; default: the scaling’s, e.g. Fr, De = O(1)). Horizontal and vertical rows keep separate orders: vertical=0 is the hydrostatic (SME-type) balance, vertical=2 keeps the eps^2 vertical inertia (VAM-type). Without arguments (after InsertClosure) it repeats the orders of the first truncation, which drops the closure’s own sub-leading terms.

Args

  • horizontal: order of the horizontal momentum rows.

  • vertical: order of the vertical momentum row.

  • mass: order of the mass balance.

  • regime: the Regime; fixed by the first truncation.

Initialization

Store the orders and the regime.

whole_model_op#

True

orders()#

{Role: order} of the given orders.

apply_to_model(m)#

Truncate the scaled rows; records the regime and orders on the first call.

class zoomy_core.model.derivation.nondim.ClosureRecord#

What InsertClosure decided, read by the model after Dimensionalize.

Attributes

  • tensor: {key: dimensional closure stress} of the bulk closure, untruncated.

  • shear: {key: dimensional bulk shear} of each horizontal row’s own tau_dz that the row’s order keeps; it stays a closure variable until the projection (its traces carry the bed / surface traction).

  • inplane: a horizontal row keeps an in-plane / normal stress component.

  • vertical_stress: the vertical row keeps a stress component.

  • dropped: names of the closures whose every contribution is beyond the order.

  • orders: {(closure, component): eps order of its scaled stress} (the consistency check).

  • shear_only: name of a bulk closure that gives only the vertical shear (no tensor); it closes the horizontal rows’ own tau_dz after the projection, as in the unclosed case, and is allowed only when no row keeps another stress component.

  • unchecked: names of the bed / surface closures without scaling information (dimensions, scaling_groups): their traction enters after the projection as before, without the consistency check.

Initialization

Empty record.

class zoomy_core.model.derivation.nondim.InsertClosure(closures, name='insert_closure')#

Bases: zoomy_core.model.operations.Operation

Insert the material law in the scaled frame and check it against the stress ansatz.

The bulk closure’s stress tensor (tensor(m, uvel, w, horiz), physical coordinates) is written in the scaled variables, tau_ij = scale_ij * tau_hat_ij. Its own scale, the scale of its vertical shear (expression), fixes the free stress scale (Newtonian: S = rho nu U / H, so De = eps U H / nu). Consistency check: every term of every tau_hat_ij must be O(1) or smaller in eps (no negative order with the regime); a component larger than its ansatz raises ScalingError naming it. The bed and surface closures (traction) go through the same check with their own groups (scaling_groups).

The closure is substituted into every stress component of the scaled rows except the horizontal shear tau_dz of the horizontal rows, which stays a closure variable: the projection integrates d_z tau_dz by parts and its traces carry the bed / surface traction. For it, the bulk closure’s terms that the row’s order keeps are recorded (ClosureRecord).

A bulk closure without a tensor (it gives only the vertical shear: Elder, Bingham, an eddy viscosity) is not inserted; it closes the horizontal rows’ tau_dz after the projection, and the order must keep no other stress component (else ScalingError). Bed / surface closures without scaling information (dimensions, scaling_groups, e.g. RoughWall) enter after the projection unchecked; the record and the log name them.

Args

  • closures: the model’s closure list.

Initialization

Store the closures.

whole_model_op#

True

apply_to_model(m)#

Check, bind the stress scale, substitute; records m.nondim.closure.

class zoomy_core.model.derivation.nondim.Dimensionalize(name='dimensionalize')#

Bases: zoomy_core.model.operations.Operation

Back from the scaled frame to the physical variables (inverse of NonDimensionalize).

Initialization

Name the operation.

whole_model_op#

True

apply_to_model(m)#

Rewrite the scaled rows dimensionally and leave the scaled frame.