<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>multiPhysicsFoam – Partitioned-Coupling</title><link>https://multiphysicsfoam.com/tags/partitioned-coupling/</link><description>Recent content in Partitioned-Coupling on multiPhysicsFoam</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://multiphysicsfoam.com/tags/partitioned-coupling/index.xml" rel="self" type="application/rss+xml"/><item><title>Docs: defaultInterface</title><link>https://multiphysicsfoam.com/docs/user-guide/interface-physics/defaultinterface/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://multiphysicsfoam.com/docs/user-guide/interface-physics/defaultinterface/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>&lt;code>defaultInterface&lt;/code> is the generic interface type. It adds no interface physics
of its own: &lt;code>correct()&lt;/code> is a no-op, &lt;code>getMinDeltaT()&lt;/code> returns &lt;code>GREAT&lt;/code> and
&lt;code>info()&lt;/code> prints nothing. All of its behaviour comes from the base class
&lt;code>regionInterfaceType&lt;/code>, which every interface type inherits: it pairs two
patches of two regions, builds the patch-to-patch mapping and provides the
residuals for the DNA (partitioned) coupling loop. The coupling conditions
themselves are set by the boundary conditions on the two patches.&lt;/p>
&lt;p>With the generic &lt;code>regionCoupledScalarJump&lt;/code> / &lt;code>regionCoupledScalarFlux&lt;/code> boundary
conditions, &lt;code>defaultInterface&lt;/code> couples a scalar quantity that is continuous
(or continuous up to a constant partition coefficient) and whose diffusive flux
is conserved across the interface. Examples are temperature and electric
potential across a perfectly conducting contact, as between an
&lt;a href="https://multiphysicsfoam.com/docs/user-guide/region-physics/electrochemistry-models/ntgk/">&lt;code>NTGK&lt;/code>&lt;/a> battery region and its
&lt;a href="https://multiphysicsfoam.com/docs/user-guide/region-physics/electrochemistry-models/conductpotentialtemperature/">&lt;code>conductPotentialTemperature&lt;/code>&lt;/a>
current-collector tabs.&lt;/p>
&lt;p>This page also documents the base-class behaviour (interface naming,
dictionary keywords, interface-to-interface mapping, generic coupled boundary
conditions). It applies to every interface type unless the derived type
overrides it.&lt;/p>
&lt;h2 id="interface-conditions">Interface Conditions&lt;/h2>
&lt;p>The conditions are set by the boundary-condition pair, not by
&lt;code>defaultInterface&lt;/code>. One side of the interface carries a jump (Dirichlet) BC,
side $J$, and the other side carries a flux (Neumann) BC, side $F$. Which
region gets which BC does not depend on the patch order in
&lt;code>coupledPatchPair&lt;/code>. The tutorial uses different assignments for different
fields.&lt;/p>
&lt;h3 id="jump-condition">Jump condition&lt;/h3>
&lt;p>&lt;code>regionCoupledScalarJump&lt;/code> sets the patch value on side $J$ from the neighbour
value, interpolated onto the side-$J$ faces:&lt;/p>
$$
\phi_J = c \, \phi_F \quad \text{on } \Gamma
$$
&lt;p>Internally this is $\phi_J = \phi_F + \Delta\phi$ with
&lt;code>valueJump()&lt;/code> $\Delta\phi = (c - 1)\,\phi_F$. If the &lt;code>jumpCoefficient&lt;/code> keyword
is not given, $c = 1$, which gives continuity.&lt;/p>
&lt;h3 id="flux-condition">Flux condition&lt;/h3>
&lt;p>&lt;code>regionCoupledScalarFlux&lt;/code> sets the normal gradient on side $F$ so that the
diffusive flux matches the flux computed on side $J$:&lt;/p>
$$
\Gamma_F \nabla \phi_F \cdot \mathbf{n}_F + \Gamma_J \nabla \phi_J \cdot \mathbf{n}_J = 0 \quad \text{on } \Gamma
$$
&lt;p>In code this is &lt;code>gradient() = (-flux_J + fluxJump())/k_F&lt;/code>, where
&lt;code>flux_J = k_J * snGrad(phi_J)&lt;/code> is interpolated onto the side-$F$ faces.
&lt;code>regionCoupledScalarFlux::fluxJump()&lt;/code> returns zero.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Symbol&lt;/th>
&lt;th>Keyword / field&lt;/th>
&lt;th>Description&lt;/th>
&lt;th>Unit&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>$\phi$&lt;/td>
&lt;td>field listed in &lt;code>coupledFields&lt;/code> (e.g. &lt;code>T&lt;/code>, &lt;code>phiPos&lt;/code>, &lt;code>phiNeg&lt;/code>)&lt;/td>
&lt;td>Coupled scalar field (same name in both regions)&lt;/td>
&lt;td>field-dependent&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$\Gamma_J$, $\Gamma_F$&lt;/td>
&lt;td>&lt;code>diffusivity&lt;/code> (BC keyword)&lt;/td>
&lt;td>Diffusivity on each side&lt;/td>
&lt;td>field-dependent&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$c$&lt;/td>
&lt;td>&lt;code>jumpCoefficient&lt;/code> (jump-BC keyword)&lt;/td>
&lt;td>Value-jump (partition) coefficient, default 1&lt;/td>
&lt;td>—&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$\mathbf{n}_J$, $\mathbf{n}_F$&lt;/td>
&lt;td>—&lt;/td>
&lt;td>Outward patch normals of each side&lt;/td>
&lt;td>—&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="interface-residuals">Interface residuals&lt;/h3>
&lt;p>The DNA loop (&lt;code>src/numerics/dnaSolutionControl&lt;/code>) measures convergence with
residuals computed by the BCs and collected by
&lt;code>regionInterfaceType::normJumpRes&lt;/code> / &lt;code>normFluxRes&lt;/code>:&lt;/p>
$$
r_\text{jump} = \frac{\lVert \phi_J - \phi_F - \Delta\phi \rVert_2}
{\max\left(\min\left(\lVert \phi_J \rVert_2,\ \lVert \phi_F + \Delta\phi \rVert_2\right),\ \text{SMALL}\right)}
$$
$$
r_\text{flux} = \frac{\lVert \Gamma_F \partial_n \phi_F + q_J \rVert_2}
{\max\left(\min\left(\lVert \Gamma_F \partial_n \phi_F \rVert_2,\ \lVert q_J \rVert_2\right),\ \text{SMALL}\right)}
$$
&lt;p>with $q_J = \Gamma_J \partial_n \phi_J$ interpolated onto side $F$, and with
the neighbour quantity always interpolated onto the evaluating side. These are
compared with &lt;code>maxJumpRes&lt;/code> / &lt;code>maxFluxRes&lt;/code> in &lt;code>multiRegionProperties&lt;/code>. If the
interface is not coupled (see &lt;code>coupled&lt;/code> below), both residuals are 0.&lt;/p>
&lt;h2 id="implementation">Implementation&lt;/h2>
&lt;p>&lt;code>defaultInterface&lt;/code> only implements the pure virtuals of &lt;code>regionInterfaceType&lt;/code>
(&lt;code>correct()&lt;/code>, &lt;code>getMinDeltaT()&lt;/code>, &lt;code>info()&lt;/code>) as no-ops. Everything below is
base-class behaviour.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Construction&lt;/strong> (&lt;code>regionInterfaceTypeList::reset&lt;/code>): for each entry of
&lt;code>partitionedCoupledPatches&lt;/code> (and &lt;code>monolithicCoupledPatches&lt;/code>) in
&lt;code>constant/regionInterfaceProperties&lt;/code>, the two patches of &lt;code>coupledPatchPair&lt;/code>
are looked up. One interface object is created &lt;strong>per entry of the
&lt;code>interfaceType&lt;/code> list&lt;/strong>, all on the same patch pair. The first pair entry
becomes side A and the second becomes side B.&lt;/li>
&lt;li>&lt;strong>Naming&lt;/strong>: the interface name is
&lt;code>&amp;lt;regionA&amp;gt;&amp;lt;PatchA&amp;gt;&amp;lt;RegionB&amp;gt;&amp;lt;PatchB&amp;gt;&amp;lt;InterfaceType&amp;gt;&lt;/code>, where every part after
the first is capitalised. For example, the tutorial gives
&lt;code>batteryRegionToNegTabNegTabRegionToCellFromNegDefaultInterface&lt;/code>. This name
appears in the log and in the DNA residual output.&lt;/li>
&lt;li>&lt;strong>interfaceKey&lt;/strong>: the interface is also an &lt;code>interfaceKey&lt;/code>, an unordered pair
of words. Equality is symmetric (&lt;code>(a,b) == (b,a)&lt;/code>) and the hash is the sum
of the two word hashes. The interface object itself is keyed by the two
&lt;strong>patch&lt;/strong> names. The coupled-field tables of &lt;code>regionInterfaceTypeList&lt;/code>
are keyed by &lt;code>(&amp;lt;regionA&amp;gt;&amp;lt;patchA&amp;gt;, &amp;lt;regionB&amp;gt;&amp;lt;patchB&amp;gt;)&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Global patches&lt;/strong>: on construction, a &lt;code>globalPolyPatch&lt;/code> is built for each
side. It is a copy of the patch reconstructed in full on every processor,
which is what makes the mapping work in parallel. The mapping object is
created at the same time (&lt;code>interfaceToInterface()&lt;/code>), so that a &lt;code>directMap&lt;/code>
can read its maps on restart.&lt;/li>
&lt;li>&lt;strong>Field transfer&lt;/strong>: the BCs call &lt;code>interpolateFacesFromA/B&lt;/code> (and the point
variants). These convert the patch field to the global patch, transfer it
with the selected &lt;code>interfaceToInterfaceMapping&lt;/code>, and scatter it back to the
local patch. Only &lt;code>scalar&lt;/code> and &lt;code>vector&lt;/code> fields have specialisations. Other
types hit a &lt;code>notImplemented&lt;/code> fallback.&lt;/li>
&lt;li>&lt;strong>Update per BC evaluation&lt;/strong>: every coupled BC calls
&lt;code>regionInterfaceType::update()&lt;/code> in its &lt;code>updateCoeffs()&lt;/code>. This function
rebuilds the global patches after a topology change (mesh changing but not
moving), updates the finite-area curvature if an &lt;code>faMesh&lt;/code> exists, then calls
&lt;code>correct()&lt;/code>, which is a no-op for &lt;code>defaultInterface&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Update per time step&lt;/strong>: &lt;code>multiRegionSystem::preSolve()&lt;/code> calls
&lt;code>regionInterfaceTypeList::update()&lt;/code>. For interfaces whose mesh A is changing,
this rebuilds the mapping and global patches at the frequency set by
&lt;code>interpolatorUpdateFrequency&lt;/code> (and always after a topology change), then
calls &lt;code>info()&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Time step&lt;/strong>: &lt;code>getMinDeltaT()&lt;/code> returns &lt;code>GREAT&lt;/code>, so &lt;code>defaultInterface&lt;/code> never
limits the time step.&lt;/li>
&lt;/ol>
&lt;h3 id="interface-to-interface-mapping">Interface-to-interface mapping&lt;/h3>
&lt;p>The mapping is selected &lt;strong>globally&lt;/strong> for all interfaces by the top-level
keyword &lt;code>interfaceTransferMethod&lt;/code> in &lt;code>regionInterfaceProperties&lt;/code>. It is not set
per interface entry. The default is &lt;code>AMI&lt;/code>. The matching &lt;code>&amp;lt;method&amp;gt;Coeffs&lt;/code>
sub-dictionary is read with &lt;code>subDict&lt;/code>, so it &lt;strong>must exist even when it is
empty&lt;/strong>. Neither &lt;code>AMI&lt;/code> nor &lt;code>directMap&lt;/code> reads any keyword from it.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Method&lt;/th>
&lt;th>Class (&lt;code>src/numerics/interfaceToInterfaceMappings&lt;/code>)&lt;/th>
&lt;th>Behaviour&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>AMI&lt;/code> (default)&lt;/td>
&lt;td>&lt;code>amiInterfaceToInterfaceMapping&lt;/code>&lt;/td>
&lt;td>Wraps &lt;code>amiZoneInterpolation&lt;/code> (face-area weighted, &lt;code>requireMatch&lt;/code> on, &lt;code>lowWeightCorrection -1&lt;/code>) on the global patches; non-conformal patches allowed. Prints the max face-centre mapping error (&lt;code>interface-to-interface face error&lt;/code>) on construction.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>directMap&lt;/code>&lt;/td>
&lt;td>&lt;code>directMapInterfaceToInterfaceMapping&lt;/code>&lt;/td>
&lt;td>One-to-one face/point map for &lt;strong>conformal&lt;/strong> patches; fatal error if face or point counts differ. Faces/points are matched by centre/position within &lt;code>0.001 * min edge length&lt;/code>. Maps (&lt;code>zoneAToZoneBFaceMap_&amp;lt;patchA&amp;gt;_to_&amp;lt;patchB&amp;gt;&lt;/code>, …) are written to and re-read from the time directory.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>RBF&lt;/code>&lt;/td>
&lt;td>&lt;code>rbfInterfaceToInterfaceMapping&lt;/code>&lt;/td>
&lt;td>Radial basis function interpolation. &lt;strong>Disabled&lt;/strong>: commented out in &lt;code>src/multiRegionSystem/Make/files&lt;/code> (needs Eigen), so not selectable.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="generic-coupled-boundary-conditions">Generic coupled boundary conditions&lt;/h3>
&lt;p>&lt;code>genericRegionCoupledJump&amp;lt;Type&amp;gt;&lt;/code> (derived from &lt;code>fixedValue&lt;/code>) and
&lt;code>genericRegionCoupledFlux&amp;lt;Type&amp;gt;&lt;/code> (derived from &lt;code>fixedGradient&lt;/code>) are the base
classes of all partitioned coupling BCs. Both are registered for &lt;code>scalar&lt;/code> and
&lt;code>vector&lt;/code>, but their &lt;code>valueJump()&lt;/code> / &lt;code>fluxJump()&lt;/code> are &lt;code>notImplemented&lt;/code>, so they
cannot be used directly in a case. &lt;code>regionCoupledScalarJump&lt;/code> /
&lt;code>regionCoupledScalarFlux&lt;/code> are the concrete scalar versions and the only
coupled BCs that do not need a specific interface type. All other
&lt;code>regionCoupled*&lt;/code> BCs (&lt;code>regionCoupledTemperatureJump&lt;/code>,
&lt;code>regionCoupledVelocityValue&lt;/code>, &lt;code>regionCoupledTraction&lt;/code>, …) cast the interface to
&lt;code>heatTransferInterface&lt;/code>, &lt;code>capillaryInterface&lt;/code>, &lt;code>fsiInterface&lt;/code>, etc.&lt;/p>
&lt;p>Behaviour shared by both generic BCs:&lt;/p>
&lt;ul>
&lt;li>The owning interface is found from the BC&amp;rsquo;s &lt;code>interfaceType&lt;/code> list (only the
&lt;strong>first&lt;/strong> entry is used) and the local region/patch name. It is a fatal
error if no interface or more than one interface of that type contains the
patch. The neighbour region and patch are taken from the matched interface.&lt;/li>
&lt;li>The neighbour field is looked up under the &lt;strong>same name&lt;/strong> as the local field.&lt;/li>
&lt;li>If the interface is not &lt;code>coupled&lt;/code>, &lt;code>updateCoeffs()&lt;/code> returns early and the
BC keeps its last value or gradient.&lt;/li>
&lt;li>After the new value (jump side) or gradient (flux side) is set, it is
relaxed by the BC&amp;rsquo;s acceleration model (&lt;code>src/numerics/acceleration&lt;/code>).&lt;/li>
&lt;li>&lt;code>diffCoeff()&lt;/code> takes the diffusivity named by &lt;code>diffusivity&lt;/code> from a
&lt;code>volScalarField&lt;/code> of that name in the local region if one exists. Otherwise it
reads a &lt;code>dimensionedScalar&lt;/code> of that name from the region&amp;rsquo;s
&lt;code>transportProperties&lt;/code>. For a field named &lt;code>pKin&lt;/code> the diffusivity is forced
to 1.&lt;/li>
&lt;li>Snapping the gradient (&lt;code>snGrad&lt;/code>, jump side) and evaluating the patch value
(flux side) use the cell gradient (&lt;code>grad(&amp;lt;field&amp;gt;)&lt;/code> if registered, otherwise
&lt;code>fvc::grad&lt;/code>) for the optional non-orthogonal (&lt;code>nonOrthCorr&lt;/code>) and
second-order (&lt;code>secondOrder&lt;/code>) corrections.&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Keyword&lt;/th>
&lt;th>Side&lt;/th>
&lt;th>Default&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>type&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>—&lt;/td>
&lt;td>&lt;code>regionCoupledScalarJump&lt;/code> or &lt;code>regionCoupledScalarFlux&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>interfaceType&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>&lt;strong>required&lt;/strong>&lt;/td>
&lt;td>List of interface type names, e.g. &lt;code>(defaultInterface)&lt;/code>; only the first is used&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>diffusivity&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>&lt;code>word::null&lt;/code>&lt;/td>
&lt;td>Name of the diffusivity (&lt;code>volScalarField&lt;/code> or &lt;code>transportProperties&lt;/code> entry). Effectively required: the flux side always needs it, and the jump side needs it to supply its flux to the flux side&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>jumpCoefficient&lt;/code>&lt;/td>
&lt;td>jump&lt;/td>
&lt;td>&lt;code>word::null&lt;/code> (→ $c = 1$)&lt;/td>
&lt;td>Name of a &lt;code>volScalarField&lt;/code> or &lt;code>transportProperties&lt;/code> entry giving $c$&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>neighbourFieldName&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>local field name&lt;/td>
&lt;td>Read and written, but not used by the generic jump/flux evaluation, which always uses the local field name&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>accType&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>&lt;code>fixed&lt;/code>&lt;/td>
&lt;td>Acceleration model: &lt;code>fixed&lt;/code>, &lt;code>aitken&lt;/code>, &lt;code>IQNILS&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>relax&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>&lt;code>1.0&lt;/code>&lt;/td>
&lt;td>(Initial) relaxation factor&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>couplingReuse&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>&lt;code>0&lt;/code>&lt;/td>
&lt;td>&lt;code>IQNILS&lt;/code> only: number of previous time steps reused&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>nonOrthCorr&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>&lt;code>false&lt;/code>&lt;/td>
&lt;td>Non-orthogonal correction&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>secondOrder&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>&lt;code>false&lt;/code>&lt;/td>
&lt;td>Second-order patch gradient / value&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>value&lt;/code>&lt;/td>
&lt;td>both&lt;/td>
&lt;td>read if present&lt;/td>
&lt;td>Initial patch value&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>gradient&lt;/code>&lt;/td>
&lt;td>flux&lt;/td>
&lt;td>read if present&lt;/td>
&lt;td>Initial patch gradient&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="coupled-fields">Coupled Fields&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Field&lt;/th>
&lt;th>Required boundary conditions (side A / side B)&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>any &lt;code>volScalarField&lt;/code> present in both regions under the same name&lt;/td>
&lt;td>&lt;code>regionCoupledScalarJump&lt;/code> / &lt;code>regionCoupledScalarFlux&lt;/code> (either order)&lt;/td>
&lt;td>Generic continuity + flux conservation, optional partition coefficient&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>T&lt;/code> (tutorial)&lt;/td>
&lt;td>&lt;code>regionCoupledScalarJump&lt;/code> (battery) / &lt;code>regionCoupledScalarFlux&lt;/code> (tab)&lt;/td>
&lt;td>Temperature, &lt;code>diffusivity &amp;quot;k&amp;quot;&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>phiNeg&lt;/code> (tutorial)&lt;/td>
&lt;td>&lt;code>regionCoupledScalarJump&lt;/code> (battery) / &lt;code>regionCoupledScalarFlux&lt;/code> (negative tab)&lt;/td>
&lt;td>Negative-electrode potential, &lt;code>diffusivity &amp;quot;sigmaNeg&amp;quot;&lt;/code> / &lt;code>&amp;quot;sigma&amp;quot;&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>phiPos&lt;/code> (tutorial)&lt;/td>
&lt;td>&lt;code>regionCoupledScalarFlux&lt;/code> (battery) / &lt;code>regionCoupledScalarJump&lt;/code> (positive tab)&lt;/td>
&lt;td>Positive-electrode potential, &lt;code>diffusivity &amp;quot;sigmaPos&amp;quot;&lt;/code> / &lt;code>&amp;quot;sigma&amp;quot;&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>The flux side casts the neighbour patch field to
&lt;code>genericRegionCoupledJump&lt;/code>, so the BCs must be one jump and one flux. Two flux
BCs fail with a bad cast. A field listed in &lt;code>coupledFields&lt;/code> that is missing in
one of the regions is skipped by the DNA residual check (&lt;code>couplesField()&lt;/code>).
That is why the tutorial can list &lt;code>phiPos&lt;/code> and &lt;code>phiNeg&lt;/code> on both tab
interfaces, although each tab region holds only one of them.&lt;/p>
&lt;h2 id="compatible-region-types">Compatible Region Types&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Region type (side A)&lt;/th>
&lt;th>Region type (side B)&lt;/th>
&lt;th>Notes&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>NTGK&lt;/code>&lt;/td>
&lt;td>&lt;code>conductPotentialTemperature&lt;/code>&lt;/td>
&lt;td>Tested in tutorial: &lt;code>phiPos&lt;/code>/&lt;code>phiNeg&lt;/code> and &lt;code>T&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>any region that assembles the field in &lt;code>setCoupledEqns()&lt;/code>&lt;/td>
&lt;td>any such region&lt;/td>
&lt;td>The field must exist under the same name on both sides and the &lt;code>diffusivity&lt;/code> must be resolvable in each region. Not covered by a tutorial&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;a href="https://multiphysicsfoam.com/docs/user-guide/region-physics/heat-transfer-models/laplacianfluid/">&lt;code>laplacianFluid&lt;/code>&lt;/a> lists &lt;code>defaultInterface&lt;/code> for
&lt;code>T&lt;/code> in its coupling table, but no tutorial uses that combination (untested).&lt;/p>
&lt;h2 id="case-setup">Case Setup&lt;/h2>
&lt;h3 id="regioninterfaceproperties-entry">&lt;code>regionInterfaceProperties&lt;/code> entry&lt;/h3>
&lt;p>From &lt;code>tutorials/electrochemistry/NTGKBatteryWithTabs/constant/regionInterfaceProperties&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">partitionedCoupledPatches
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">(
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> cellToNegTab
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> interfaceType (defaultInterface);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> coupledPatchPair
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> (
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> (batteryRegion toNegTab)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> (negTabRegion toCellFromNeg)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> );
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> coupledFields
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> (
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> phiPos
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> phiNeg
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> T
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> );
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> defaultInterfaceCoeffs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> cellToPosTab
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> // same, with (batteryRegion toPosTab) (posTabRegion toCellFromPos)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">monolithicCoupledPatches
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">();
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curvatureCorrectedSurfacePatches 0();
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">interpolatorUpdateFrequency 0;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">interfaceTransferMethod directMap;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">directMapCoeffs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Interface-entry keywords:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Keyword&lt;/th>
&lt;th>Default&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>interfaceType&lt;/code>&lt;/td>
&lt;td>&lt;strong>required&lt;/strong>&lt;/td>
&lt;td>List of interface types; one interface object per entry is built on the same patch pair&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>coupledPatchPair&lt;/code>&lt;/td>
&lt;td>&lt;strong>required&lt;/strong>&lt;/td>
&lt;td>&lt;code>((regionA patchA) (regionB patchB))&lt;/code>; exactly two entries, otherwise a fatal error&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>coupledFields&lt;/code>&lt;/td>
&lt;td>&lt;strong>required&lt;/strong>&lt;/td>
&lt;td>Field names coupled through this patch pair; their union across all entries defines the partitioned-coupled fields&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>coupled&lt;/code>&lt;/td>
&lt;td>&lt;code>true&lt;/code>&lt;/td>
&lt;td>Switch the interface coupling on or off&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>couplingStartTime&lt;/code>&lt;/td>
&lt;td>&lt;code>0&lt;/code>&lt;/td>
&lt;td>If &lt;code>coupled false&lt;/code> and this value is &amp;gt; 0, coupling is switched on once &lt;code>time &amp;gt;= couplingStartTime&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;interfaceType&amp;gt;Coeffs&lt;/code>&lt;/td>
&lt;td>—&lt;/td>
&lt;td>Not read by &lt;code>defaultInterface&lt;/code>. Kept for consistency with other interface types&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Top-level keywords (shared by all interfaces):&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Keyword&lt;/th>
&lt;th>Default&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>partitionedCoupledPatches&lt;/code>&lt;/td>
&lt;td>&lt;strong>required&lt;/strong>&lt;/td>
&lt;td>List of partitioned interface entries&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>monolithicCoupledPatches&lt;/code>&lt;/td>
&lt;td>&lt;strong>required&lt;/strong>&lt;/td>
&lt;td>List of monolithic interface entries (may be empty: &lt;code>()&lt;/code>)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>curvatureCorrectedSurfacePatches&lt;/code>&lt;/td>
&lt;td>&lt;strong>required&lt;/strong>&lt;/td>
&lt;td>&lt;code>faPatch&lt;/code> names for curvature correction at wedge axes (used only when an &lt;code>faMesh&lt;/code> exists); &lt;code>0()&lt;/code> otherwise&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>interpolatorUpdateFrequency&lt;/code>&lt;/td>
&lt;td>&lt;code>1&lt;/code>&lt;/td>
&lt;td>Rebuild mapping/global patches every N time steps on changing meshes; &lt;code>0&lt;/code> disables periodic rebuild&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>interfaceTransferMethod&lt;/code>&lt;/td>
&lt;td>&lt;code>AMI&lt;/code>&lt;/td>
&lt;td>&lt;code>AMI&lt;/code> or &lt;code>directMap&lt;/code> (see above)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;method&amp;gt;Coeffs&lt;/code>&lt;/td>
&lt;td>&lt;strong>required&lt;/strong>&lt;/td>
&lt;td>Sub-dictionary for the chosen method; may be empty&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;code>regionInterfaceProperties&lt;/code> is not read in &lt;code>singleRegionMode&lt;/code>.&lt;/p>
&lt;h3 id="multiregionproperties-dna-entry">&lt;code>multiRegionProperties&lt;/code> DNA entry&lt;/h3>
&lt;p>From the same tutorial:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">regions
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">(
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> (batteryRegion (NTGK) )
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> (negTabRegion (conductPotentialTemperature) )
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> (posTabRegion (conductPotentialTemperature) )
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">DNA
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> phiPos
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> maxCoupleIter 50;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> residualControl
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> maxJumpRes 1e-05;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> outputJumpResField no;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> maxFluxRes 1e-05;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> outputFluxResField no;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> phiNeg { maxCoupleIter 25; residualControl { maxJumpRes 1e-05; maxFluxRes 1e-05; } }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> T { maxCoupleIter 10; residualControl { maxJumpRes 1e-05; maxFluxRes 1e-05; } }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>maxCoupleIter&lt;/code> defaults to 1. Either both &lt;code>maxJumpRes&lt;/code> and &lt;code>maxFluxRes&lt;/code>, or a
single &lt;code>maxIntRes&lt;/code>, may be given. &lt;code>defaultInterface&lt;/code> does not override
&lt;code>normIntRes()&lt;/code>, which returns 0, so use &lt;code>maxJumpRes&lt;/code> / &lt;code>maxFluxRes&lt;/code>.&lt;/p>
&lt;h3 id="boundary-conditions">Boundary conditions&lt;/h3>
&lt;p>Jump side, &lt;code>0/batteryRegion/orig/partitioned/T&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">toNegTab
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> type regionCoupledScalarJump;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> interfaceType (defaultInterface);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> diffusivity &amp;#34;k&amp;#34;;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> accType aitken;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> relax 0.75;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> secondOrder false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nonOrthCorr false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> value $internalField;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Flux side, &lt;code>0/negTabRegion/orig/partitioned/T&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">toCellFromNeg
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> type regionCoupledScalarFlux;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> interfaceType (defaultInterface);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> diffusivity &amp;#34;k&amp;#34;;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> secondOrder false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nonOrthCorr false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> value $internalField;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Flux side with an initial gradient, &lt;code>0/batteryRegion/orig/partitioned/phiPos&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">toPosTab
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> type regionCoupledScalarFlux;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> interfaceType (defaultInterface);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> diffusivity &amp;#34;sigmaPos&amp;#34;;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> secondOrder false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nonOrthCorr false;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> value $internalField;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> gradient uniform 0.1266;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>On a patch where a field is not coupled (e.g. &lt;code>phiNeg&lt;/code> on the battery&amp;rsquo;s
&lt;code>toPosTab&lt;/code>), use an ordinary BC such as &lt;code>zeroGradient&lt;/code>.&lt;/p>
&lt;h2 id="known-limitations">Known Limitations&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>No interface physics&lt;/strong>: &lt;code>correct()&lt;/code> and &lt;code>info()&lt;/code> are empty and the
&lt;code>defaultInterfaceCoeffs&lt;/code> dictionary is never read. Any jump or source at the
interface must come from the BCs. With the generic BCs, this is limited to a
constant or field-valued partition coefficient (&lt;code>jumpCoefficient&lt;/code>) and a zero
flux jump.&lt;/li>
&lt;li>&lt;strong>Scalar fields only in practice&lt;/strong>: field transfer is specialised only for
&lt;code>scalar&lt;/code> and &lt;code>vector&lt;/code>. The only concrete BCs usable with &lt;code>defaultInterface&lt;/code>
are &lt;code>regionCoupledScalarJump&lt;/code> / &lt;code>regionCoupledScalarFlux&lt;/code>. The generic
&lt;code>vector&lt;/code> BCs have &lt;code>notImplemented&lt;/code> jumps, and all vector &lt;code>regionCoupled*&lt;/code> BCs
require &lt;code>capillaryInterface&lt;/code>, &lt;code>fsiInterface&lt;/code> or a mass-transfer interface.
Coupling a vector field via &lt;code>defaultInterface&lt;/code> would need a new BC.&lt;/li>
&lt;li>&lt;strong>Same field name on both sides&lt;/strong>: the generic BCs always look up the
neighbour field under the local field name. &lt;code>neighbourFieldName&lt;/code> is ignored
there.&lt;/li>
&lt;li>&lt;strong>Global mapping choice&lt;/strong>: &lt;code>interfaceTransferMethod&lt;/code> and its &lt;code>Coeffs&lt;/code>
sub-dictionary are top-level keywords. All interfaces in a case share one
mapping method. &lt;code>directMap&lt;/code> requires conformal patches. &lt;code>RBF&lt;/code> is not
compiled.&lt;/li>
&lt;li>&lt;strong>Only the first BC &lt;code>interfaceType&lt;/code> is used&lt;/strong>: if several interface types
are listed on one patch, the BC binds to the first. A patch may belong to at
most one interface of a given type.&lt;/li>
&lt;li>&lt;strong>Neighbour detection by patch name only&lt;/strong>
(&lt;code>interfaceToInterfaceCoupleManager::nbrPatch()/nbrMesh()/interpolateFromNbrField()&lt;/code>):
the local patch is compared with &lt;code>patchA&lt;/code> by &lt;strong>name only&lt;/strong>, without the
region. If both sides of an interface use the same patch name, side B would
identify itself as A and couple to itself (inferred from the code,
untested). Give the two patches different names.&lt;/li>
&lt;li>&lt;strong>&lt;code>diffusivity &amp;quot;v&amp;quot;&lt;/code> handling is ineffective&lt;/strong> (inferred from the code):
&lt;code>diffCoeff()&lt;/code> renames &lt;code>&amp;quot;v&amp;quot;&lt;/code> to &lt;code>&amp;quot;rho&amp;quot;&lt;/code> before it checks for &lt;code>&amp;quot;v&amp;quot;&lt;/code> to take
the reciprocal, so the reciprocal is never applied.&lt;/li>
&lt;li>&lt;strong>Monolithic coupling not available&lt;/strong>: &lt;code>monolithicCoupledPatches&lt;/code> is parsed,
but the monolithic solve in &lt;code>multiRegionSystem::solve()&lt;/code> is commented out.&lt;/li>
&lt;li>&lt;strong>Residual control requires generic BCs&lt;/strong>: if neither patch field derives
from &lt;code>genericRegionCoupledJump&lt;/code> / &lt;code>genericRegionCoupledFlux&lt;/code>, a warning is
printed and the residual is set to &lt;code>GREAT&lt;/code>. The DNA loop then always runs to
&lt;code>maxCoupleIter&lt;/code> (inferred).&lt;/li>
&lt;/ul>
&lt;h2 id="tutorials">Tutorials&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Tutorial&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>tutorials/electrochemistry/NTGKBatteryWithTabs&lt;/code>&lt;/td>
&lt;td>&lt;code>NTGK&lt;/code> battery cell coupled to a negative and a positive &lt;code>conductPotentialTemperature&lt;/code> tab via two &lt;code>defaultInterface&lt;/code> entries (&lt;code>phiPos&lt;/code>, &lt;code>phiNeg&lt;/code>, &lt;code>T&lt;/code>; &lt;code>directMap&lt;/code>; &lt;code>./Allrun -p -S&lt;/code>)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="references">References&lt;/h2>
&lt;ul>
&lt;li>Alkfri, A., Habes, C., Marschall, H., &lt;em>multiRegionFoam: A Unified Multiphysics Framework for Multi-Region Coupled Continuum-Physical Problems&lt;/em>, Engineering with Computers, 2023.
DOI: &lt;a href="https://doi.org/10.1007/s00366-024-01974-4">10.1007/s00366-024-01974-4&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>