Equations and state
Simultaneous relations
Section titled “Simultaneous relations”relation ohm { voltage = resistance * current; }A relation constrains quantities. It is not an assignment or a sequence of commands.
Both sides must have matching dimensions and shapes. A relation may contain several
equations, all of which hold simultaneously. Use on body for a spatial relation
and at tick for a relation activated by a periodic clock.
Continuous state and initial equations
Section titled “Continuous state and initial equations”// A minimal implicit ODE: x decays at the rate supplied by the user.model decay() { // `x` is dimensionless and starts at 1. `rate` has inverse-time units. state x: 1; initial { x = 1; } parameter rate: 1 / s = 1;
// Eqiora writes the evolution law as a residual equal to zero. relation flow { derivative(x) + rate * x = 0; }}derivative(x) denotes the time derivative of a continuous state. Here the model
has the solution with the default rate of 1/s.
initial supplies the mathematical initial equation; a solver’s initial guess
or time step does not replace it.
A spatial block can name its support: initial on body { u = 1 + coordinate(0)/1[m]; }.
Python authoring uses component.initial((u, profile), on=body). The existing
coordinate axis and support checks apply; this does not request a separate
initialization solver.
The ODE lesson
continues through State.initial(plan) and execution. To continue an existing run,
use its accepted State rather than reinitializing the model at each output time.
Conservation laws and weak forms
Section titled “Conservation laws and weak forms”A law gives storage, outward flux, and source terms. A steady law has no storage
term. The following complete component uses Fourier conduction and four fixed
boundary temperatures:
/// Steady heat conduction on a unit square cross-section, per unit depth./// All four exterior faces are held at 300 K; this Component has no time evolution.public component HeatedBody( support body: volume(ambient_dimension = 2), support x_lower: boundary(parent = body), support x_upper: boundary(parent = body), support y_lower: boundary(parent = body), support y_upper: boundary(parent = body), parameter conductivity: W / (m * K), parameter heating: W / m^3) { variable temperature: K on body in h1; relation prescribed_x_lower on x_lower { trace(temperature) = 300[K]; } relation prescribed_x_upper on x_upper { trace(temperature) = 300[K]; } relation prescribed_y_lower on y_lower { trace(temperature) = 300[K]; } relation prescribed_y_upper on y_upper { trace(temperature) = 300[K]; } law heat_balance on body { flux -conductivity * grad(temperature); source heating; } form weak_heat for heat_balance { test w: 1 for temperature zero_on x_lower, x_upper, y_lower, y_upper; integrate(body, dot(grad(w), conductivity * grad(temperature))) = integrate(body, w * heating); }}Read its flux as and source as volumetric heating.
The local steady balance is .
form weak_heat for heat_balance attaches a weak form to that physical law.
test w: 1 for temperature zero_on ... associates a test field with temperature
and makes it vanish on the prescribed-temperature boundaries. integrate and
dot express the resulting integral equation.
For time-dependent storage, the same source provides:
/// Heat storage and conduction with complete constant initial and boundary data./// The caller supplies positive volumetric capacity; the reference temperature is 300 K.public component TransientHeatedBody( support body: volume(ambient_dimension = 2), support x_lower: boundary(parent = body), support x_upper: boundary(parent = body), support y_lower: boundary(parent = body), support y_upper: boundary(parent = body), parameter conductivity: W / (m * K), parameter heating: W / m^3, parameter capacity: J / (m^3 * K)) { state temperature: K on body in h1; initial { temperature = 300[K]; } relation prescribed_x_lower on x_lower { trace(temperature) = 300[K]; } relation prescribed_x_upper on x_upper { trace(temperature) = 300[K]; } relation prescribed_y_lower on y_lower { trace(temperature) = 300[K]; } relation prescribed_y_upper on y_upper { trace(temperature) = 300[K]; } law heat_balance on body { storage capacity * temperature; flux -conductivity * grad(temperature); source heating; }}The balance is now with constant volumetric heat capacity . The initial field is 300 K everywhere. Follow the thermal model walkthrough for package construction and execution, or weak forms and finite elements for the derivation.
Common spatial operators
Section titled “Common spatial operators”| Expression | Meaning |
|---|---|
grad(temperature) |
Spatial temperature gradient |
div(velocity) |
Divergence of a velocity field |
symmetric_part(grad(displacement)) |
Infinitesimal strain tensor |
trace(temperature) |
Temperature restricted to the relation’s boundary |
normal(stress) |
Stress contracted with the parent-outward normal, giving traction |
isotropic_lift(pressure) |
Pressure times the identity tensor |
dot(a, b) |
Inner product of compatible vectors |
The support and tensor shapes must match the operation. See continuum components for stress and boundary examples.
Periodic state
Section titled “Periodic state”model Counter() { clock tick = periodic(1[s] / 10, phase = 0[s] / 1); state memory: 1 at tick; initial { memory = 0; } relation advance at tick { next(memory) - pre(memory) - 1 = 0; }}The clock period is exactly 1/10 second, with phase zero. pre(memory) is the
value before a tick; next(memory) is the candidate updated value. The first tick
advances memory from 0 to 1. The update’s equations are simultaneous.
pre and next require a state on that exact clock; use derivative for continuous
state. Equal clock periods do not make independently declared clocks interchangeable.
Sampled controls provides reusable delay
and integration components and an executable project.
Inequalities and complementarity
Section titled “Inequalities and complementarity”model Contact(parameter load: N = 0) { variable gap: m; variable force: N; relation contact { 2[N/m] * gap - force = load; complementarity(0[m] <= gap, force >= 0[N]); inequality(gap <= 4[m]); }}The complementarity condition requires nonnegative gap and force with at least one equal to zero. A positive gap therefore has zero contact force; a positive contact force has zero gap. The inequality adds an upper bound on the gap.
inequality uses non-strict <= or >= between compatible real scalars.
complementarity takes two explicit nonnegativity predicates; its two operands
may have different dimensions, as above, but share support.
Execution handles finite, non-spatial problems whose active sets are affine. The Plan sets the constraint tolerances, in coherent SI units, and a limit on branch enumeration. No penalty or smoothing is added. Spatial contact and friction are not supported.