28. Loci Face Orientation and Cell Incidence#

Stream uses Loci to assemble its finite-volume equations. Loci stores one orientation for each face. This appendix explains how Loci orients a face, how the upper and lower maps relate a cell to its faces, and how these conventions determine the sign of a face contribution to a cell balance.

28.1. Stored Face Orientation#

For an internal face \(f\), let \(\operatorname{cl}(f)\) and \(\operatorname{cr}(f)\) denote its left and right cells. The cl and cr maps take a face and return its left and right cells. The stored face area vector is

(28.1.1)#\[\vec S_f=A_f\hat{\vec n}_f, \qquad \hat{\vec n}_f:\operatorname{cl}(f)\longrightarrow\operatorname{cr}(f).\]

Put simply, the stored face normal points away from the cl cell and toward the cr cell. The mesh construction process chooses which adjacent cell is cl and which is cr; these labels do not denote fixed spatial directions. The ordered face nodes, the stored normal, and the cl and cr maps share this orientation. An oriented face flux \(F_f\) is positive from \(\operatorname{cl}(f)\) to \(\operatorname{cr}(f)\). For example,

(28.1.2)#\[\Phi_f=\vec u_f\mathbin{\cdot}\vec S_f\]

is positive in the stored face direction. The face orientation is fixed, but it is not outward from both cells sharing the face.

28.2. Upper and Lower Face Sets#

For a cell \(P\), let \(\mathcal F_P^{\mathrm{int}}\) denote all internal faces that touch the cell. Loci divides these faces into two lists. The upper list contains faces for which \(P\) is the cl cell, and the lower list contains faces for which \(P\) is the cr cell:

(28.2.1)#\[\mathcal U(P) = \left\{f\in\mathcal F_P^{\mathrm{int}}:\operatorname{cl}(f)=P\right\}, \qquad \mathcal L(P) = \left\{f\in\mathcal F_P^{\mathrm{int}}:\operatorname{cr}(f)=P\right\}.\]

These mathematical sets are exactly the face lists returned by the Loci multimaps upper and lower:

(28.2.2)#\[\mathcal U(P)=\operatorname{upper}(P)=\operatorname{cl}^{-1}(P), \qquad \mathcal L(P)=\operatorname{lower}(P)=\operatorname{cr}^{-1}(P).\]

Here, \(\operatorname{cl}^{-1}(P)\) means “follow cl backward” and collect every internal face that cl maps to \(P\); it is not a reciprocal. The same interpretation applies to \(\operatorname{cr}^{-1}(P)\). Every internal face touching \(P\) belongs to exactly one of the two lists:

(28.2.3)#\[\mathcal F_P^{\mathrm{int}} = \mathcal U(P)\mathbin{\dot\cup}\mathcal L(P).\]

The dot over the union sign states that the lists do not overlap. The names upper and lower come from the matrix ordering. In the equation row for \(P\), an upper face connects to a neighbor with a higher equation number, while a lower face connects to a neighbor with a lower equation number. The corresponding off-diagonal coefficients lie in the upper and lower triangular parts of the matrix. The names do not describe physical directions in the mesh.

The upper and lower multimaps contain faces. If two cells share more than one face, each connecting face remains a separate entry and contributes separately to a face sum. The cell across an internal face is

(28.2.4)#\[\begin{split}N_f(P)= \begin{cases} \operatorname{cr}(f), & f\in\mathcal U(P),\\ \operatorname{cl}(f), & f\in\mathcal L(P). \end{cases}\end{split}\]

Across an upper face, \(P\) is cl, so cr gives the neighboring cell. Across a lower face, \(P\) is cr, so cl gives the neighbor. A Loci rule therefore reads a neighboring value through upper->cr->X or lower->cl->X.

28.2.1. Splitting a Face-Based Neighbor Sum#

If \(a_{Pf}\) is the coefficient contributed by face \(f\), a neighbor term assembled face by face can be split over the two lists without changing the sum:

(28.2.1.1)#\[\sum_{f\in\mathcal F_P^{\mathrm{int}}} a_{Pf}\phi_{N_f(P)} = \sum_{f\in\mathcal U(P)} a_{Pf}\phi_{\operatorname{cr}(f)} + \sum_{f\in\mathcal L(P)} a_{Pf}\phi_{\operatorname{cl}(f)}.\]

The first term uses upper->cr->phi; the second uses lower->cl->phi. If the final algebraic equation uses one coefficient for each distinct neighbor, contributions from multiple faces connecting the same two cells are added into that coefficient.

28.2.2. Boundary Faces#

For an ordinary non-periodic boundary face, the physical owner satisfies \(\operatorname{ci}(f)=\operatorname{cl}(f)=P\), and the stored normal points outward from \(P\). The boundary faces of \(P\) are

(28.2.2.1)#\[\mathcal F_P^{\mathrm{bnd}} = \operatorname{boundary\_map}(P) = \left\{f\in\mathcal F^{\mathrm{bnd}}:\operatorname{ci}(f)=P\right\}.\]

The final expression says to collect every boundary face whose physical owner ci is cell \(P\).

28.3. Converting to the Cell-Outward Direction#

From the perspective of cell \(P\), an upper-face quantity keeps its stored sign and a lower-face quantity changes sign. The incidence sign \(\sigma_{Pf}\) records that choice:

(28.3.1)#\[\begin{split}\sigma_{Pf}= \begin{cases} +1, & f\in\mathcal U(P)\ \text{or}\ f\in\mathcal F_P^{\mathrm{bnd}},\\ -1, & f\in\mathcal L(P). \end{cases}\end{split}\]

On an upper face, the stored normal already points out of \(P\), so the sign is \(+1\). On a lower face, the stored normal points into \(P\), so the sign is \(-1\). An ordinary boundary-face normal points out of its physical owner and also uses \(+1\).

The outward unit normal, area vector, and signed flux relative to cell \(P\) are

(28.3.2)#\[\hat{\vec n}_{Pf}=\sigma_{Pf}\hat{\vec n}_f, \qquad \vec S_{Pf}=\sigma_{Pf}\vec S_f, \qquad F_{Pf}=\sigma_{Pf}F_f.\]

Therefore, \(F_f>0\) means flow from cl to cr, while \(F_{Pf}>0\) means flow leaving cell \(P\).

Cell role at \(f\)

Mathematical set

Loci map

\(\sigma_{Pf}\)

Stored normal relative to \(P\)

\(P=\operatorname{cl}(f)\)

\(\mathcal U(P)\)

upper(P)

\(+1\)

Outward

\(P=\operatorname{cr}(f)\)

\(\mathcal L(P)\)

lower(P)

\(-1\)

Inward

Boundary owner

\(\mathcal F_P^{\mathrm{bnd}}\)

boundary_map(P)

\(+1\)

Outward

No incidence-sign field is stored in the fact database. The sign follows directly from the face-to-cell maps.

28.4. Cell Balance and Conservation#

For the complete face set

(28.4.1)#\[\mathcal F_P = \mathcal U(P)\mathbin{\dot\cup}\mathcal L(P) \mathbin{\dot\cup}\mathcal F_P^{\mathrm{bnd}},\]

This says that the upper faces, lower faces, and boundary faces together contain every face of \(P\), exactly once.

With this partition, the outward face sum is

(28.4.2)#\[\sum_{f\in\mathcal F_P}F_{Pf} = \sum_{f\in\mathcal U(P)}F_f - \sum_{f\in\mathcal L(P)}F_f + \sum_{f\in\mathcal F_P^{\mathrm{bnd}}}F_f.\]

In words: add the stored flux on upper and boundary faces, and subtract it on lower faces. The result is the net outward flux for cell \(P\).

An internal face contributes \(+F_f\) to its left cell and \(-F_f\) to its right cell:

(28.4.3)#\[F_{\operatorname{cl}(f),f}=+F_f, \qquad F_{\operatorname{cr}(f),f}=-F_f.\]

The two contributions cancel when the neighboring cell balances are added. One stored face flux can therefore be applied conservatively to both cell equations.

28.5. Meaning in Loci Rules#

A mapping such as (cl,cr)->(...) supplies access to the two adjacent cells; it does not insert an algebraic sign. A reduction that assembles a divergence or outward residual must add \(F_f\) to cl and subtract \(F_f\) from cr. A right-hand side that stores the negative of that residual uses the opposite signs. When the outward sum is assembled by traversing the inverse maps, the rule adds upper contributions and subtracts lower contributions.

The same convention applies to moving-grid quantities. Both volFlux and gridVolFlux use the stored cl-to-cr orientation, so their difference retains that orientation.

28.6. Notation for Face-Based Derivations#

When a derivation distinguishes the stored and cell-outward orientations, a face-only subscript denotes the stored orientation:

(28.6.1)#\[\vec S_f,\quad \Phi_f,\quad \dot m_f,\quad F_f.\]

A cell-face subscript denotes the outward orientation of a particular cell:

(28.6.2)#\[\vec S_{Pf},\quad \Phi_{Pf},\quad \dot m_{Pf},\quad F_{Pf}.\]

A local two-cell derivation may set \(P=\operatorname{cl}(f)\) and \(N=\operatorname{cr}(f)\) explicitly. Under that stated choice, the stored face direction is also outward from \(P\). Outward normals in continuum surface integrals and on physical domain boundaries remain outward geometric normals; they do not imply that every stored internal-face normal is outward from every incident cell.