Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Multi-points (MPC)

En bref

Impose une relation linéaire entre plusieurs inconnues : deux nœuds à la même température, une périodicité, une liaison affine. Avec sense, une borne : une liaison à jeu.

opérateurpyrucast.model.mpc(terms, target, sense="=")
tagconstraint et celui de la cible ; constraint seul si la relation lie deux physiques
typecontrainte (label() : "Mpc")
supportun maillage POI1 par terme

terms est une liste de termes (maillage, variable, coefficient). Les maillages des termes sont appariés maille par maille : la relation \(r\) relie la maille \(r\) de chacun. Une périodicité entre deux surfaces de \(N\) nœuds est donc \(N\) relations d’un coup. L’ordre des mailles est à la charge de l’appelant ; la contrainte vérifie que tout est POI1, sur un même Coords, avec le même nombre de mailles par zone. target donne à chaque variable sa duale (Model.dual_of) ; une relation entre deux physiques se pose sur leur union.

Théorie

Chaque relation s’écrit

\[ \sum_k a_k\,u(n_k, v_k) = g \qquad (\text{ou } \ge,\ \le\ g). \]

C’est Dirichlet à plusieurs termes et coefficients quelconques. Chaque terme apporte une paire de blocs de coefficient \(a_k\) : \(C\), ligne (multiplicateur, imposed), colonne (n_k, v_k) ; et \(C^{\mathsf T}\), ligne (n_k, duale de v_k), colonne (multiplicateur, lambda). Tous les termes d’une relation partagent son nœud multiplicateur et sa ligne imposed, ce qui les additionne en une équation. La réaction, la force que la relation exerce sur la pièce, est \(-a_k\,\lambda\) au nœud de chaque terme.

Le nœud multiplicateur de chaque relation est créé à la position du nœud de son premier terme. Le second membre \(g\) s’écrit au chargement, à la composante imposed du nœud multiplicateur, par constraint_rhs([(un_noeud_de_la_relation, g)]), ou par constraint_rhs_by_index([(r, g)]) quand un nœud appartient à plusieurs relations. Une relation absente du chargement impose 0.

Les coefficients sont un par terme, les mêmes pour toutes ses mailles. Des coefficients qui varient d’un nœud à l’autre sont le cas du baignage.

Variables

primalelambda
dualeimposed
ce qu’elle contraintles variables des termes, inconnues de la cible
matériau, comportementaucun

Ce qu’elle produit

raideurune paire \(C\), \(C^{\mathsf T}\) par terme et par zone
masse, géométrique—
tangente= raideur
forces internes\(C^{\mathsf T}\lambda\) sur les duales, \(C\,u\) sur les lignes imposed
forces externesaucune

Exemple

Sur une barre en conduction, \(T(0) = 0\) par Dirichlet et \(T(1) - T(0) = 1\) par une MPC : d’où \(T = x\).

import pyrucast

c = pyrucast.Coords(dim=1)
nodes = [c.add_node([i / 4.0]) for i in range(5)]
mesh = pyrucast.Mesh(c, "SEG2")
for i in range(4):
    mesh.unit().add_cell([nodes[i], nodes[i + 1]])
fes = pyrucast.FiniteElementSpace(mesh)

base = pyrucast.model.heat_conduction(fes)
dual = base.dual_of("T")  # "q"

# Dirichlet T(0) = 0.
imposed0 = pyrucast.mesh.poi1_from_nodes([nodes[0]])
dirichlet = pyrucast.model.dirichlet(imposed0, base, "T")

# MPC 1·T(dernier) − 1·T(0) = 1.
mesh_last = pyrucast.mesh.poi1_from_nodes([nodes[-1]])
mesh_first = pyrucast.mesh.poi1_from_nodes([nodes[0]])
mpc = pyrucast.model.mpc(
    [(mesh_last, "T", 1.0), (mesh_first, "T", -1.0)],
    base,
)

model = base | dirichlet | mpc
materials = pyrucast.element_field.material_field(model, [("k", 1.0)])

# Chargement : valeur imposée de Dirichlet + second membre g de la MPC. Le
# `constraint_rhs` désigne chaque relation par un nœud (le nœud imposé pour
# Dirichlet, un nœud d'un terme pour la MPC) et trouve son nœud multiplicateur ;
# la composante est `imposed` pour les deux. Les deux se réunissent par `|`.
rhs = dirichlet.constraint_rhs([(nodes[0], 0.0)]) | mpc.constraint_rhs(
    [(nodes[-1], 1.0)]
)

solution = pyrucast.solver.solve(pyrucast.matrix.stiffness(model, materials), rhs)
assert abs(solution.value(nodes[2], "T") - 0.5) < 1e-10

examples/mpc_periodicite.py pose une périodicité.

Côté Rust

Mpc (src/models/mpc.rs) implémente Constraint. Ses blocs sortent du même constraint_block_pair que Dirichlet, avec le coefficient \(a_k\) au lieu de 1.