Core library: catalogue¶
The framework every application builds on: the network, the layers, the model, the set-up helpers, and the general-purpose constitutive laws and drives. Every application is set up the same way; see Using noodl.
Import from noodl.topology and the modules named in each table. The full reference, with every parameter, is in the API reference.
Set-up¶
Build the model and its starting state and inputs.
| Name | What it does | How to call it |
|---|---|---|
drivers_fromnoodl.refs |
A drivers dictionary from {key: {label: value}} and/or {key: tensor}. |
drivers_from(model, values, *, base=None) |
state_fromnoodl.refs |
A state dictionary, as drivers_from builds drivers. |
state_from(model, values, *, base=None) |
initial_driversnoodl.refs |
A copy of the model's driver template (model.driver_template, which an application's build_model records), then values (see drivers_from). |
initial_drivers(model, *, values=None) |
check_setupnoodl.validation |
Check model and, when given, state and drivers; return a SetupReport. |
check_setup(model, state=None, drivers=None, *, dt=None, probe=False, steady=False, names=None) |
Layers and model¶
The conservation layers and the model that steps them.
| Name | What it does | How to call it |
|---|---|---|
Networknoodl.topology |
Directed multigraph with typed edges and tensor-valued topology operators. | Network(dtype=torch.float32) |
Portsnoodl.model |
What a coupled or external model may prescribe and read. | Ports(boundary_nodes, prescribed_keys, boundary_flows, flow_keys=<factory>) |
Modelnoodl.model |
Layers on one Network, stepped together. See the module docstring for the keys. |
Model(net, layers, closures=(), reactions=(), coupling='pingpong', iterate_tol=None, iterate_max=20, substeps=None, adjoint_rtol=1e-10, iterate_relaxation=0.5, reaction_order='after_transport', iterate_acceleration=None, iterate_memory=5, iterate_flow_tol=None, iterate_on_limit='raise') |
AllocatedFlowLayernoodl.layers |
Flows allocated by rule, not by a potential: each edge's requested flow is clipped to the arc's capacity and the receiving node's free storage, one explicit step at a time, conserving storage exactly (WSIMOD's push/pull semantics). quantity, unit and flow_unit are reported by model.refs, never used numerically. |
AllocatedFlowLayer(net, name, kind, *, s_max, c_arc, preference=None, mode='hard', tau=None, n_passes=5, quantity='storage', unit='', flow_unit='') |
KirchhoffLayernoodl.layers |
Flows driven by a potential (pressure, head): solves nodal conservation A_I g(A^T phi) = s_I for the interior potentials by Newton's method, with the constitutive laws on its edge kinds, drives added to the potential differences, and prescribed potentials at its boundary nodes; differentiable through the converged solution. flow_unit is reported by model.refs, never used numerically. |
KirchhoffLayer(net, name, laws, drives=(), boundary=(), linear_solver='auto', *, node_sources=(), quantity='potential', unit='', flow_unit='', phasor=False, analytic_primal=False, newton_defaults=None) |
TransportLayernoodl.layers |
dx/dt = M x + N x_b + sources / capacity on this layer's ACTIVE interior nodes. | TransportLayer(net, name, *, capacity, flow_kind, boundary, n_species=1, carrier=1.0, transmission=None, kinetics=None, removal=None, conduction_kind=None, conductance=None, dilution=None, dilution_mode='signed', storage_free=(), scheme='exact', linear_solver='auto', quantity='scalar', unit='', species_names=None, source_unit='', capacity_unit='', flow_unit='') |
CoupledModelnoodl.couple |
Returned by union. .step takes and returns {model_tag: State} / {model_tag: Drivers} -- each model keeps its own dicts; nothing is merged. |
CoupledModel(models, links, aliases, substeps, *, relaxation=0.5, iterate_rtol=1e-08, iterate_atol=0.0, iterate_max=50, adjoint_rtol=1e-10) |
Constitutive laws¶
The relation between the flow through an edge and the potential difference across it.
| Name | What it does | How to call it |
|---|---|---|
AffinityFannoodl.elements |
A fan curve run at another speed and air density, by the fan laws (ContamX's performance-curve fan, measured against ContamX 3.4.1.7). | AffinityFan(curve, *, src, tgt, rho_ref, speed_key=None, off=0.0, multiplier=1.0, shutoff=None, rho_key='rho', kind=None) |
AirDuctnoodl.elements |
A duct segment, F (kg/s) from dp (Pa): Darcy-Weisbach with ContamX's friction factor. | AirDuct(length, diameter, roughness, loss=0.0, *, area=None, src, tgt, rho_key='rho', temperature_key=None, kind='duct', learnable=False) |
Conductancenoodl.elements |
q = g dp, the linear branch law used for thermal conduction and passive exchange; g is in the flow unit per unit of potential (W/K for heat, kg/s per Pa for air). |
Conductance(g, *, kind='conduction', learnable=False) |
CubicSplineFlownoodl.elements |
An airflow element given by measured points, fitted as ContamX fits them (SplineCurve): CONTAM's cubic-spline elements. |
CubicSplineFlow(x, y, *, independent='pressure', volume=False, multiplier=1.0, src, tgt, rho_key='rho', kind='airpath') |
Dampernoodl.elements |
Separate power-law coefficient and exponent for each flow direction: C_pos/n_pos for dp > 0 and C_neg/n_neg for dp < 0, each as in PowerLaw (C in the flow unit per Pa^n, n dimensionless). |
Damper(C_pos, n_pos, C_neg, n_neg, *, dp_transition=0.001, src=None, tgt=None, m=0.0, rho_ref=1.2041, rho_key='rho', kind='damper', learnable=False) |
DoorCompartmentalso MBLDoorCompartmentnoodl.elements |
One compartment of Buildings.Airflow.Multizone.DoorDiscretizedOpen per edge. |
DoorCompartment(*, src, tgt, medium, dA, CD=0.65, m=0.5, dp_turbulent=0.01, vZer=0.001, T_key='T', Xw_key='X_w', p_key='p_abs', kind='door', learnable=False) |
DoorPortStreamalso MBLDoorPortStreamnoodl.elements |
One of the two port streams of a whole discretised door, as ONE edge from side A to side B: direction="ab" returns port_a1.m_flow = mAB_flow, "ba" returns port_b2.m_flow = -port_a2.m_flow = -mBA_flow (kg/s, both positive from A to B), from the compartment law comp (:class:DoorCompartment or :class:OperableDoorCompartment, one door) at the compartment pressure differences dp + head(drivers) (:class:DoorCompartmentHead). The edge's own dp is the zones' potential difference phi_A - phi_B. |
DoorPortStream(comp, head, direction, kind) |
Ductnoodl.elements |
Colebrook duct: F(dp) with friction from the Colebrook equation, laminar below Re_t. Length L, diameter D and roughness eps (m); sum_C the dimensionless sum of dynamic loss coefficients; A (m2) defaults to the circular area; rho (kg/m3) and mu (Pa s); the flow is a mass flow in kg/s. |
Duct(L, D, eps, sum_C=0.0, *, A=None, Re_t=2000.0, rho=1.2041, mu=1.81625e-05, n_iter=4, kind='duct', learnable=False) |
DuctTerminalnoodl.elements |
A duct terminal, the zero-length duct between a junction and its zone, F (kg/s) from dp (Pa), as ContamX 3.4.1.7 computes it (measured). | DuctTerminal(area, loss, *, src, tgt, rho_key='rho', temperature_key=None, opening_key=None, kind='duct_terminal', learnable=False) |
FanCurvenoodl.elements |
Cubic pressure-flow curve inverted for q given dp on [0, q_max]: coeffs are (a0, a1, a2, a3) of P(q) = a0 + a1 q + a2 q^2 + a3 q^3 in Pa for q in the flow unit, and q_max is the largest flow the curve covers, in that unit. |
FanCurve(coeffs, q_max, *, kind='airpath', learnable=False) |
FixedFlownoodl.elements |
q = q0 regardless of dp (q0 in the flow unit); dflow = 0; linear_init = (q0, 0). |
FixedFlow(q0, *, kind='airpath', learnable=False) |
FixedVolumeFlownoodl.elements |
F = Q rho_up whatever dp: a constant volume flow volume_flow Q (m3/s, one per edge) delivered as mass flow at the density of the node it draws from (src when Q >= 0, tgt otherwise), read from drivers[rho_key] (full node order). ContamX's constant-volume fan in a duct (measured). |
FixedVolumeFlow(volume_flow, *, src, tgt, rho_key='rho', kind='fan', learnable=False) |
OpenDooralso MBLDoorOpennoodl.elements |
Buildings.Airflow.Multizone.DoorOpen: one direction of the always-open door. |
OpenDoor(*, direction, src, tgt, medium, wOpe=0.9, hOpe=2.1, CD=0.65, m=0.5, dp_turbulent=0.01, T_key='T', kind='door', learnable=False) |
OperableDooralso MBLDoorOperablenoodl.elements |
Buildings.Airflow.Multizone.DoorOperable: the door blended between open and closed by the opening signal y read from drivers[y_key]. |
OperableDoor(*, direction, src, tgt, medium, y_key, LClo, wOpe=0.9, hOpe=2.1, CDOpe=0.65, mOpe=0.5, mClo=0.65, dpCloRat=4.0, CDCloRat=1.0, dp_turbulent=0.01, T_key='T', kind='door', learnable=False) |
OperableDoorCompartmentalso MBLDoorCompartmentOperablenoodl.elements |
One compartment of Buildings.Airflow.Multizone.DoorDiscretizedOperable per edge, blended between the open door and the closed crack by y = drivers[y_key]. |
OperableDoorCompartment(*, src, tgt, medium, y_key, AOpe, LClo, nCom, CDOpe=0.65, CDClo=0.65, CDCloRat=1.0, dpCloRat=4.0, mOpe=0.5, mClo=0.65, dp_turbulent=0.01, vZer=0.001, T_key='T', Xw_key='X_w', p_key='p_abs', kind='door', learnable=False) |
PowerLawnoodl.elements |
q = C sign(dp) |dp|^n, laminar-blended or smoothly regularised near dp = 0. dp is in Pa; C is in the flow unit per Pa^n (kg/s for a mass-flow coefficient, m3/s for a volume-flow one), so the flow comes out in whatever unit C carries; n is dimensionless (0.5 for an orifice, towards 1 for a laminar crack). |
PowerLaw(C, n, *, dp_transition=0.001, regularised=None, kind='airpath', learnable=False) |
PrescribedFlownoodl.elements |
F = drivers[key] whatever dp: a flow (kg/s, one value per edge of the kind) that a closure or an input prescribes every step, e.g. an air handler's supply flows. dtype is the layer's: linear_init, which has no dp to take it from, returns it. |
PrescribedFlow(key, *, kind, dtype=torch.float64) |
Quadraticnoodl.elements |
q = sign(dp) * 2|dp| / (sqrt(a^2 + 4 b |dp|) + a): the inverse of dp = a q + b |q| q, with dp in Pa, a in Pa per flow unit and b in Pa per flow unit squared. |
Quadratic(a, b, *, kind='airpath', learnable=False) |
RegularizedPowerLawalso MBLPowerLawnoodl.elements |
MBL's regularised power law, q = C sign(dp) \|dp\|^m, volume or mass form. |
RegularizedPowerLaw(C, m, *, dp_turbulent=0.1, form, rho_default, kind='airpath', learnable=False) |
Scalednoodl.elements |
F = s F_law: law's flow times the dimensionless multiplier drivers[key]. |
Scaled(law, key) |
SplineFlowTablealso MBLTablenoodl.elements |
MBL's tabulated flow law: a monotone cubic Hermite spline through (dp, flow) knots, linearly extrapolated outside them; flow(dp) always returns MASS flow in kg/s. |
SplineFlowTable(dp_points, flow_points, *, form, rho_default=None, kind='airpath') |
UpstreamDensityPowerLawnoodl.elements |
PowerLaw with C scaled by (rho_upstream / rho_ref) ** m, upstream by sign(dp). |
UpstreamDensityPowerLaw(C, n, *, src, tgt, m, rho_ref=1.2041, rho_key='rho', dp_transition=0.001, regularised=None, kind='airpath', learnable=False) |
Drives¶
Terms added to an edge's potential difference (stack, wind, fans).
| Name | What it does | How to call it |
|---|---|---|
DoorCompartmentHeadnoodl.elements |
The hydrostatic part of DoorDiscretized.mo:64-66, as a noodl drive: rho_A hAg[i] - rho_B hBg[i] per compartment edge, shape (..., n_edges). |
DoorCompartmentHead(kind, *, src, tgt, hAg, hBg, medium, T_key='T', Xw_key='X_w', p_key='p_abs') |
ConstantDrivenoodl.drives |
A drive that reads a pre-computed, already batched value from drivers. |
ConstantDrive(kind, key) |
Stacknoodl.drives |
Hydrostatic stack term (CONTAM TN 1887r1 eq. 17 with eq. 64-65 at the path elevation). | Stack(kind, *, src, tgt, z_path, z_ref, rho_key='rho', g=9.80665) |
DuctStacknoodl.drives |
Hydrostatic term of a duct segment between two junctions: the air column at the density of the junctions' MEAN TEMPERATURE (ContamX 3.4.1.7, measured), which at one pressure is the harmonic mean of the two node densities. | DuctStack(kind, *, src, tgt, z_ref, rho_key='rho', g=9.80665) |
WindProfilenoodl.drives |
CONTAM wind pressure profile: Cp versus relative wind angle, periodic in the angle. | WindProfile(angles_deg, cp, *, curve='linear') |
Windnoodl.drives |
Wind pressure on envelope paths (CONTAM TN 1887r1 section 3.15). Drivers: rho_amb in kg/m3, V_met in m/s and theta_w in the unit the azimuth edge attribute uses (degrees for networks read from CONTAM). |
Wind(kind, *, sign, envelope, azimuth, ch, cp_const, profile_index, profiles=(), rho_key='rho_amb', speed_key='V_met', direction_key='theta_w') |
Closures¶
Functions of the state that compute drivers each step (densities, flows, levels).
| Name | What it does | How to call it |
|---|---|---|
AlgebraicClosurenoodl.contracts |
A closure that only computes drivers from the state and the drivers: called as closure(state, drivers), it returns the driver entries it adds or replaces. |
AlgebraicClosure(...) |
IntegratingClosurenoodl.contracts |
A closure that advances state of its own over the step (integrates = True). |
IntegratingClosure(...) |
ClosureSpecnoodl.contracts |
A closure and its declarations, read once by closure_spec. |
ClosureSpec(closure, label, integrates, declares_integrates, state_keys, key_labels, reads, writes, edge_kinds, requires_coupling, reads_flows_of, species_columns, output_units=<factory>, owner='Model') |
Reactions¶
Transformations applied to transported species each step.
| Name | What it does | How to call it |
|---|---|---|
FirstOrderDecaynoodl.layers |
x <- x * exp(-rate * dt); rate broadcasts against x. |
FirstOrderDecay(rate) |
Files¶
Readers and writers of other tools' file formats.
| Name | What it does | How to call it |
|---|---|---|
write_atnoodl.layout |
target with value written (add=True: ADDED) at node position, in the caller's own layout (reduced (..., n) or stacked (..., n, 1)) but not necessarily its own shape: a batched value written into an unbatched target broadcasts the target up to the value's batch. Never writes into target itself. where prefixes the layout error. |
write_at(target, n, position, value, *, add=False, where='layout.write_at') |
Other classes¶
Supporting types.
| Name | What it does | How to call it |
|---|---|---|
StepContextnoodl.contracts |
What a state transition needs from the model: the interval it must integrate over (None under steady(), which an integrating closure refuses) and, when the caller tracks it, the time at the start of the step. |
StepContext(dt, t=None) |
ClosureAttributenoodl.contracts |
One optional attribute of a closure: its name, the type it must have, what it defaults to when absent, what it means and which code consumes it. | ClosureAttribute(name, type, default, meaning, consumer) |
Fieldnoodl.refs |
A state or driver key that also knows the layout of the tensor stored under it. | Field(key, *, role, layer, axis, labels, ordering, settable=None, n_species=1, species=None, quantity='', unit='', required='optional', default=0.0, description='', dtype=torch.float64, device='cpu', aliases=None, column=False, scalar=False) |
LayerRefnoodl.refs |
One registered layer of a model, with its keys as discoverable Field attributes. |
LayerRef(name, layer, kind, *, flow_owner=None) |
KeyOwnershipnoodl.refs |
Who writes and who reads one key of a model: writers and readers are tuples of "layer <name>", "closure <label>" or "caller" (the dictionary the caller gives). field is the key's Field when the model knows its layout. Closure entries come from the closure's DECLARATIONS (inputs, outputs, state_keys), so a closure that declares nothing is absent. |
KeyOwnership(key, field, writers, readers) |
LayerRefsnoodl.refs |
Registered layer name -> LayerRef, plus the model's closure-carried keys. |
LayerRefs(model) |
Issuenoodl.validation |
One finding: level is "error", "warning" or "info"; key the key concerned, if any. |
Issue(level, code, message, key=None) |
InputRownoodl.validation |
One known key: what is expected and what was given. | InputRow(key, role, layer, required, ordering, expected, unit, given, status) |
SetupReportnoodl.validation |
The result of check_setup. ok is true when there are no errors. |
SetupReport(issues=<factory>, rows=<factory>, probed=False, driver_reads=frozenset(), state_reads=frozenset(), closure_outputs=frozenset()) |
UndefinedSteadyStatenoodl.layers |
A steady transport solve has no answer: a stored node keeps everything that enters it (nothing leaves it, or it belongs to a closed group whose contents never reach a boundary outflow, a removal or a filter loss). A ValueError, raised before the solve and naming the nodes; layer is the layer's name and nodes the nodes refused. |
UndefinedSteadyState(message, *, layer, nodes) |
AirMediumalso MBLMediumnoodl.elements |
An air medium's default state and the two densities its flow elements need. | AirMedium(name, p_default, T_default, X_default, rho_default, has_moisture, _buoyancy, _density=None, _cp=None) |
LawContextnoodl.elements |
What a dynamic or implicit constitutive law needs besides its own edge values. | LawContext(mode, dt=None, t=None, integration='trapezoidal', dp_prev=None, q_prev=None, omega=None) |
SplineCurvenoodl.elements |
A measured curve y(x) fitted as ContamX fits it (see the module docstring). | SplineCurve(x, y, *, name='') |
Conversionnoodl.couple |
One registered conversion and the UNITS it maps between, (from_unit, to_unit, fn). |
Conversion(from_unit, to_unit, fn) |
ValueLinknoodl.couple |
One shared-node value relationship. | ValueLink(from_model, from_key, from_index, to_model, to_key, to_index=0, convert=None, two_way=False, convert_back=None, sources_key=None) |
DriverAliasnoodl.couple |
One driver value shared across models: source is authoritative; every target is overwritten from it through that target's own registered conversion (or none). |
DriverAlias(source, targets) |
Functions¶
Calculations and helpers.
| Name | What it does | How to call it |
|---|---|---|
closure_specnoodl.contracts |
Read closure's declarations into a ClosureSpec: the only reader of the closure attributes (CLOSURE_ATTRIBUTES). index is the closure's position, for the message about a non-callable; owner prefixes every message. |
closure_spec(closure, *, index, owner='Model') |
call_closurenoodl.contracts |
Call a closure (or its ClosureSpec) by the one dispatch rule: three arguments for an integrating closure, two otherwise. For callers outside Model that run a closure themselves; a bare closure is read with closure_spec first. |
call_closure(closure_or_spec, state, drivers, ctx=None) |
reaction_species_columnsnoodl.contracts |
A Reaction's optional species_columns (the same member as a closure's), {} when it declares none. TypeError if malformed. |
reaction_species_columns(reaction) |
check_species_columnsnoodl.contracts |
Raise ValueError unless every {layer: {name: column}} in declared names a transport layer of transport, has column < n_species, and, when the layer has species_names, species_names[column] == name. A layer without species_names cannot verify names, so it accepts only declarations that give distinct columns. label names the closure or reaction in the message. |
check_species_columns(label, declared, transport) |
batch_shapenoodl.layout |
The batch shape of x: its shape without its last n_trailing physical dimensions. ValueError if x has fewer dimensions than that. |
batch_shape(x, n_trailing) |
broadcast_batchnoodl.layout |
Broadcast the batch shapes of items, each (tensor, number of trailing physical dims). Returns the common batch shape and every tensor .expand()-ed to that batch plus its own trailing shape (views, no copies). The batch is aligned on the LEFT of the physical axes, never against them, so a batch of size n cannot be mistaken for a node axis. RuntimeError naming the shapes if the batches do not broadcast. |
broadcast_batch(*items) |
per_instancenoodl.layout |
A float, or a tensor with one value per instance (B...), as (B..., 1, ...) with n_trailing trailing singleton axes, in like's dtype and device. It then broadcasts against like (B..., physical...) over the batch only, never against a physical axis (a batch of size n is not a node axis). RuntimeError if its batch does not broadcast with like's. |
per_instance(value, like, n_trailing) |
is_stackednoodl.layout |
True when x is in STACKED layout (..., n, K): at least min_dim dimensions (never fewer than 2) and trailing shape (n, K). With K == 1 this is the (..., n, 1) column, as opposed to the reduced (..., n). |
is_stacked(x, n, K=1, *, min_dim=2) |
as_stackednoodl.layout |
(x as (..., n, K), reduced?) by the one rule: stacked (..., n, K) first; for K == 1 also reduced (..., n), returned with a trailing axis and reduced=True. min_dim is the fewest dimensions of the stacked form (the reduced form needs one fewer): 3 where the leading axis is time. ValueError("{where}: {name!r} must be ...") otherwise. |
as_stacked(x, n, K, *, name, where, min_dim=2) |
as_layoutnoodl.layout |
x_stacked (..., n, 1) back in the caller's layout: (..., n) if reduced, unchanged otherwise (the inverse of as_stacked for one species). |
as_layout(x_stacked, reduced) |
reduced_singlenoodl.layout |
A single-species tensor in REDUCED layout (..., n), whether it came stacked (..., n, 1) or reduced. A batched (1, 1) is both and holds one number, so the ambiguity at n == 1 is harmless. ValueError("{where}: ...") if its last axis is not n entries. |
reduced_single(x, n, *, where) |
species_columnsnoodl.layout |
The column of each wanted species name in the declared order (a layer's species_names). order="any" allows a subset in any order; order="exact" requires wanted == declared. Unknown and repeated names raise ValueError, naming them, with where as prefix. With declared=None (the layer names no species) the names cannot be resolved: the identity [0, 1, ...] is returned, only when len(wanted) == n_species. |
species_columns(declared, wanted, *, where, n_species=None, order='any') |
normalize_unitnoodl.refs |
A unit string in one canonical spelling, for comparison only (this is not a units library: nothing is converted, and two different units never compare equal). | normalize_unit(unit) |
units_agreenoodl.refs |
Whether two unit strings are the same unit up to normalize_unit's spellings. |
units_agree(a, b) |
input_fieldnoodl.refs |
A Field for an input a closure, reaction, law or drive reads itself (a wind speed, an inflow), as a closure's input_specs or a builder's model.input_specs declares it. |
input_field(model, key, *, description, unit='', over=None, required=True, ordering=None) |
input_unit_declarationsnoodl.refs |
(origin, key, unit) for every input a model, closure or reaction declares in input_specs, in declaration order; unit is "" when the spec gives none. origin names the declarer ("model", a closure's or reaction's repr). |
input_unit_declarations(model) |
required_state_keysnoodl.refs |
The state keys Model.step reads from the step-start state. |
required_state_keys(model) |
active_interiornoodl.layers |
Split the non-boundary nodes of net into the ones kinds touch and the ones it does not: (interior_idx, inactive_idx), both in NODE order, both excluding boundary. |
active_interior(net, kinds, boundary) |
Orificenoodl.elements |
PowerLaw(C = Cd * A * sqrt(2 / rho), n = 0.5): the sharp-edged orifice equation, as a VOLUME flow in m3/s from Cd (dimensionless discharge coefficient), A (m2) and rho (kg/m3). |
Orifice(Cd, A, *, rho=1.2, dp_transition=0.001, regularised=None, kind='airpath', learnable=False) |
air_viscositynoodl.elements |
Dynamic viscosity of air (Pa s) at temperature T (K): ContamX's linear law, 1.81625e-5 + 4.92859e-8 (T - 293.15), measured between 253 and 333 K. |
air_viscosity(T) |
discretized_dooralso mbl_discretized_doornoodl.elements |
One DoorDiscretizedOpen as nCom edges of kind: the compartment element and its head drive. Defaults are MBL's (DoorDiscretized.mo:6-11, TwoWayFlowElementBuoyancy.mo:6-14, DoorDiscretizedOpen.mo:6, TwoWayFlowElement.mo:19). dA = wOpe hOpe / nCom on every edge (DoorDiscretizedOpen.mo:23, DoorDiscretized.mo:60). |
discretized_door(*, src, tgt, medium, nCom=10, wOpe=0.9, hOpe=2.1, hA=1.35, hB=1.35, CD=0.65, m=0.5, dp_turbulent=0.01, vZer=0.001, kind='door', T_key='T', Xw_key='X_w', p_key='p_abs') |
discretized_operable_dooralso mbl_discretized_operable_doornoodl.elements |
One DoorDiscretizedOperable as nCom edges of kind; see :func:discretized_door. AOpe = wOpe hOpe (DoorDiscretizedOperable.mo:35); LClo has no MBL default. |
discretized_operable_door(*, src, tgt, medium, y_key, LClo, nCom=10, wOpe=0.9, hOpe=2.1, hA=1.35, hB=1.35, CDOpe=0.65, CDClo=0.65, CDCloRat=1.0, dpCloRat=4.0, mOpe=0.5, mClo=0.65, dp_turbulent=0.01, vZer=0.001, kind='door', T_key='T', Xw_key='X_w', p_key='p_abs') |
effective_leakage_areaalso mbl_elanoodl.elements |
EffectiveAirLeakageArea.mo:3-5,7-14,16: C = L * CDRat * sqrt(2 / rho_default) * dpRat ** (0.5 - m), m = 0.65 by default (:4), dpRat = 4 Pa (:7-9), CDRat = 1 (:11-14). |
effective_leakage_area(L, dpRat=4.0, CDRat=1.0, m=0.65, dp_turbulent=0.1, *, rho_default, kind='airpath', learnable=False) |
mediumnoodl.elements |
Look up one of the three air media, by physical name or by Modelica class path. | medium(name) |
open_door_pairalso mbl_door_pairnoodl.elements |
Both edges of one DoorOpen (or of several, with per-door src/tgt): the "ab" edge (path 1) with kind f"{kind}_ab" and the "ba" edge (path 2) with kind f"{kind}_ba", sharing every keyword argument of :class:OpenDoor. |
open_door_pair(*, kind='door', **kwargs) |
operable_door_pairalso mbl_operable_door_pairnoodl.elements |
Both edges of one DoorOperable; see :func:open_door_pair. |
operable_door_pair(*, kind='door', **kwargs) |
power_law_coefficientalso mbl_coefficientnoodl.elements |
Coefficient_V_flow.mo/Coefficient_m_flow.mo: C/k and m given directly, with no further formula -- a direct pass-through to :class:RegularizedPowerLaw. |
power_law_coefficient(C, m, form, dp_turbulent=0.1, *, rho_default, kind='airpath', learnable=False) |
power_law_from_pointalso mbl_pointnoodl.elements |
Point_m_flow.mo:4-5: k = mMea_flow_nominal / dpMea_nominal ** m, fit from one measured (dp, m_flow) pair; m stays a free parameter (default 0.5, inherited from Coefficient_m_flow's PowerLawResistanceParameters(m=0.5), Coefficient_m_flow.mo:27-28). |
power_law_from_point(dpMea, mMea_flow, m=0.5, dp_turbulent=0.1, *, rho_default, kind='airpath', learnable=False) |
power_law_from_pointsalso mbl_pointsnoodl.elements |
Points_m_flow.mo:4-6,15-16: the flow exponent itself is derived from two measured (dp, m_flow) pairs, m = (ln(mMea[0]) - ln(mMea[1])) / (ln(dpMea[0]) - ln(dpMea[1])), then k = mMea[0] / dpMea[0] ** m. dpMea/mMea_flow are each a 2-element sequence. |
power_law_from_points(dpMea, mMea_flow, dp_turbulent=0.1, *, rho_default, kind='airpath', learnable=False) |
regularized_orificealso mbl_orificenoodl.elements |
Orifice.mo:3-5,9: C = CD * A * sqrt(2 / rho_default), m = 0.5 by default (overridable, per Orifice.mo:3's non-final m=0.5 modifier); C itself is final in MBL (does not depend on m). CD defaults to 0.65 (Orifice.mo:9, the sharp-edged-orifice discharge coefficient). |
regularized_orifice(A, CD=0.65, m=0.5, dp_turbulent=0.1, *, rho_default, kind='airpath', learnable=False) |
check_drive_signaturenoodl.drives |
Raise TypeError unless drive is callable as drive(drivers). |
check_drive_signature(drive, *, where) |
apply_conversionnoodl.couple |
value unchanged if name is None; the registered conversion otherwise. |
apply_conversion(name, value, drivers) |
transport_boundary_inflownoodl.couple |
Net mass INFLOW, (...,), at the boundary node boundary_idx[node_position], in a transport layer's own units, for a SINGLE-SPECIES layer (x_interior/x_boundary are (..., n_i)/(..., n_b), never (..., n_i, K)). |
transport_boundary_inflow(net, q, flow_kinds, x_interior, x_boundary, interior_idx, boundary_idx, node_position) |
unionnoodl.couple |
Couple models by exchanging the driver/state values shared names, WITHOUT merging any model's Network, layers, or closures. Never modifies the Model/State/Drivers objects passed in -- returns fresh dict copies. |
union(models, shared, *, substeps=None, relaxation=0.5, iterate_rtol=1e-08, iterate_atol=0.0, iterate_max=50, adjoint_rtol=1e-10) |
Constants and tables¶
Named values and option tables.
| Name | Value |
|---|---|
CLOSURE_ATTRIBUTES |
tuple |
Base classes (for extending)¶
Subclass these to add a constitutive law, drive, closure, reaction or node source; see Extending noodl.
| Name | What it does | How to call it |
|---|---|---|
Reactionnoodl.layers |
A local, per-node nonlinear map applied to the state after a transport step (or before it, under Model(reaction_order="before_transport")). |
Reaction(...) |
ConstitutiveLawnoodl.elements |
Abstract branch law: flow as a function of potential difference. | ConstitutiveLaw(kind) |
ImplicitLawnoodl.elements |
A constitutive law written as a relation residual(dp, q, drivers, ctx) = 0. |
ImplicitLaw(kind) |
Drivenoodl.drives |
A drive must read every differentiable quantity from drivers, never own one. |
Drive(...) |
NodeSourcenoodl.nodesources |
Base class: a potential-dependent withdrawal at a fixed set of nodes. | NodeSource(nodes) |