1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 Tetrahedral Finite Element matrix boundary treatment tools
27 \*---------------------------------------------------------------------------*/
29 #include "tetFemMatrices.H"
30 #include "tetPointRef.H"
31 #include "constraint.H"
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40 // Add boundary source for gradient-type conditions
42 void tetFemMatrix<Type>::addBoundarySourceDiag()
44 // Loop through all boundaries and fix the condition
45 const FieldField<tetPolyPatchField, Type>& patches =
46 psi().boundaryField();
48 forAll (patches, patchI)
50 patches[patchI].addBoundarySourceDiag(*this);
56 void tetFemMatrix<Type>::storeBoundaryCoeffs() const
58 // Make a map of all possible equations and only fix the ones that are
59 // requested. Once the list of requested fixes is complete, collapse the
60 // list. Note the use of list of pointers for the first part of operation
61 // and creation of collapsed list by copying the pointers into a pointer
62 // list. HJ, 28/Feb/2001
64 if (!boundaryConditionsSet_)
66 boundaryConditionsSet_ = true;
68 // Loop through all boundaries and fix the condition
69 const FieldField<tetPolyPatchField, Type>& patches =
70 psi().boundaryField();
72 forAll (patches, patchI)
74 patches[patchI].setBoundaryCondition(fixedEqns_);
77 // Loop through all fixed equations and grab the matrix
78 labelList toc = fixedEqns_.toc();
82 fixedEqns_[toc[eqnI]].setMatrix(*this);
89 void tetFemMatrix<Type>::setComponentBoundaryConditions
93 scalarField& sourceCmpt
96 if (!boundaryConditionsSet_)
100 "void tetFemMatrix<Type>::setComponentBoundaryConditions("
101 "const direction& d, scalarField& psiCmpt, "
102 "scalarField& sourceCmpt)"
103 ) << "cannot reconstruct matrix: boundary conditions not set"
104 << abort(FatalError);
107 // Loop through all fixed equations and set boundary condition
108 labelList toc = fixedEqns_.toc();
112 fixedEqns_[toc[eqnI]].eliminateEquation(*this, d, sourceCmpt);
117 fixedEqns_[toc[eqnI]].setSourceDiag(*this, d, psiCmpt, sourceCmpt);
123 void tetFemMatrix<Type>::reconstructMatrix()
125 if (!boundaryConditionsSet_)
129 "void tetFemMatrix<Type>::reconstructMatrix()"
130 ) << "cannot reconstruct matrix: boundary conditions not set"
131 << abort(FatalError);
134 // Loop through all fixed equations and reconstruct the matrix
135 labelList toc = fixedEqns_.toc();
139 fixedEqns_[toc[eqnI]].reconstructMatrix(*this);
145 void tetFemMatrix<Type>::addCouplingCoeffs()
151 // Initialise diagonal transfer
152 forAll (psi_.boundaryField(), patchI)
154 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
158 ptf.initAddDiag(diag());
163 forAll (psi_.boundaryField(), patchI)
165 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
178 // Initialise upper transfer
179 forAll (psi_.boundaryField(), patchI)
181 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
185 ptf.initAddUpperLower(upper());
190 forAll (psi_.boundaryField(), patchI)
192 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
196 ptf.addUpperLower(upper());
205 // Initialise lower transfer
206 forAll (psi_.boundaryField(), patchI)
208 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
212 ptf.initAddUpperLower(lower());
217 forAll (psi_.boundaryField(), patchI)
219 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
223 ptf.addUpperLower(lower());
231 void tetFemMatrix<Type>::addCouplingSource(scalarField& sourceCmpt) const
233 // Initialise source transfer
234 forAll (psi_.boundaryField(), patchI)
236 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
240 ptf.initAddSource(sourceCmpt);
245 forAll (psi_.boundaryField(), patchI)
247 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
251 ptf.addSource(sourceCmpt);
258 void tetFemMatrix<Type>::eliminateCouplingCoeffs()
263 // Eliminate the upper
264 forAll (psi_.boundaryField(), patchI)
266 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
270 ptf.eliminateUpperLower(upper());
279 // Eliminate the lower
280 forAll (psi_.boundaryField(), patchI)
282 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
286 ptf.eliminateUpperLower(lower());
294 tmp<Field<Type> > tetFemMatrix<Type>::distributeSource
296 const Field<Type>& ef
299 const tetPolyMesh& mesh = psi().mesh();
301 // Make a field over all points
302 tmp<Field<Type> > tdistSu
310 Field<Type>& distSu = tdistSu();
312 // Go through all the tets and add a quarter of the volume times ef
313 // into each of the vertices. The cell integrals are prepared by the mesh
314 labelList localToGlobalBuffer(mesh.maxNPointsForCell());
315 labelList globalToLocalBuffer(lduAddr().size(), -1);
317 scalarField coeffsBuffer
319 mesh.maxNPointsForCell()*tetPointRef::nVertices
322 for (label cellI = 0; cellI < mesh.nCells(); cellI++)
332 mesh.volIntegral(cellI, coeffsBuffer, globalToLocalBuffer);
334 const Type& curEf = ef[cellI];
336 for (label localI = 0; localI < nCellPoints; localI++)
338 label globalI = localToGlobalBuffer[localI];
341 distSu[globalI] += coeffsBuffer[localI]*curEf;
344 // Clear addressing for element
358 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
360 } // End namespace Foam
362 // ************************************************************************* //