1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM 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 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 Tetrahedral Finite Element matrix boundary treatment tools
28 \*---------------------------------------------------------------------------*/
30 #include "tetFemMatrices.H"
31 #include "tetPointRef.H"
32 #include "constraint.H"
34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 // Add boundary source for gradient-type conditions
43 void tetFemMatrix<Type>::addBoundarySourceDiag()
45 // Loop through all boundaries and fix the condition
46 const FieldField<tetPolyPatchField, Type>& patches =
47 psi().boundaryField();
49 forAll (patches, patchI)
51 patches[patchI].addBoundarySourceDiag(*this);
57 void tetFemMatrix<Type>::storeBoundaryCoeffs() const
59 // Make a map of all possible equations and only fix the ones that are
60 // requested. Once the list of requested fixes is complete, collapse the
61 // list. Note the use of list of pointers for the first part of operation
62 // and creation of collapsed list by copying the pointers into a pointer
63 // list. HJ, 28/Feb/2001
65 if (!boundaryConditionsSet_)
67 boundaryConditionsSet_ = true;
69 // Loop through all boundaries and fix the condition
70 const FieldField<tetPolyPatchField, Type>& patches =
71 psi().boundaryField();
73 forAll (patches, patchI)
75 patches[patchI].setBoundaryCondition(fixedEqns_);
78 // Loop through all fixed equations and grab the matrix
79 labelList toc = fixedEqns_.toc();
83 fixedEqns_[toc[eqnI]].setMatrix(*this);
90 void tetFemMatrix<Type>::setComponentBoundaryConditions
94 scalarField& sourceCmpt
97 if (!boundaryConditionsSet_)
101 "void tetFemMatrix<Type>::setComponentBoundaryConditions("
102 "const direction& d, scalarField& psiCmpt, "
103 "scalarField& sourceCmpt)"
104 ) << "cannot reconstruct matrix: boundary conditions not set"
105 << abort(FatalError);
108 // Loop through all fixed equations and set boundary condition
109 labelList toc = fixedEqns_.toc();
113 fixedEqns_[toc[eqnI]].eliminateEquation(*this, d, sourceCmpt);
118 fixedEqns_[toc[eqnI]].setSourceDiag(*this, d, psiCmpt, sourceCmpt);
124 void tetFemMatrix<Type>::reconstructMatrix()
126 if (!boundaryConditionsSet_)
130 "void tetFemMatrix<Type>::reconstructMatrix()"
131 ) << "cannot reconstruct matrix: boundary conditions not set"
132 << abort(FatalError);
135 // Loop through all fixed equations and reconstruct the matrix
136 labelList toc = fixedEqns_.toc();
140 fixedEqns_[toc[eqnI]].reconstructMatrix(*this);
146 void tetFemMatrix<Type>::addCouplingCoeffs()
152 // Initialise diagonal transfer
153 forAll (psi_.boundaryField(), patchI)
155 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
159 ptf.initAddDiag(diag());
164 forAll (psi_.boundaryField(), patchI)
166 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
179 // Initialise upper transfer
180 forAll (psi_.boundaryField(), patchI)
182 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
186 ptf.initAddUpperLower(upper());
191 forAll (psi_.boundaryField(), patchI)
193 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
197 ptf.addUpperLower(upper());
206 // Initialise lower transfer
207 forAll (psi_.boundaryField(), patchI)
209 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
213 ptf.initAddUpperLower(lower());
218 forAll (psi_.boundaryField(), patchI)
220 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
224 ptf.addUpperLower(lower());
232 void tetFemMatrix<Type>::addCouplingSource(scalarField& sourceCmpt) const
234 // Initialise source transfer
235 forAll (psi_.boundaryField(), patchI)
237 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
241 ptf.initAddSource(sourceCmpt);
246 forAll (psi_.boundaryField(), patchI)
248 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
252 ptf.addSource(sourceCmpt);
259 void tetFemMatrix<Type>::eliminateCouplingCoeffs()
264 // Eliminate the upper
265 forAll (psi_.boundaryField(), patchI)
267 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
271 ptf.eliminateUpperLower(upper());
280 // Eliminate the lower
281 forAll (psi_.boundaryField(), patchI)
283 const tetPolyPatchField<Type>& ptf = psi_.boundaryField()[patchI];
287 ptf.eliminateUpperLower(lower());
295 tmp<Field<Type> > tetFemMatrix<Type>::distributeSource
297 const Field<Type>& ef
300 const tetPolyMesh& mesh = psi().mesh();
302 // Make a field over all points
303 tmp<Field<Type> > tdistSu(mesh.nPoints(), pTraits<Type>::zero);
304 Field<Type>& distSu = tdistSu();
306 // Go through all the tets and add a quarter of the volume times ef
307 // into each of the vertices. The cell integrals are prepared by the mesh
308 labelList localToGlobalBuffer(mesh.maxNPointsForCell());
309 labelList globalToLocalBuffer(lduAddr.size(), -1);
311 scalarField coeffsBuffer
313 this->mesh.maxNTetsForCell()*tetPointRef::nVertices
316 for (label cellI = 0; cellI < mesh.nCells(); cellI++)
326 mesh.volIntegral(cellI, coeffsBuffer, globalToLocalBuffer);
328 const Type& curEf = ef[cellI];
330 for (label localI = 0; localI < nCellPoints; localI++)
332 label globalI = localToGlobalBuffer[localI];
335 distSu[globalI] += coeffsBuffer[localI]*curEf;
338 // Clear addressing for element
352 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
354 } // End namespace Foam
356 // ************************************************************************* //