fvMatrixSolve.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "LduMatrix.H"
30 #include "diagTensorField.H"
31 #include "profiling.H"
32 #include "PrecisionAdaptor.H"
33 
34 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
35 
36 template<class Type>
38 (
39  const label patchi,
40  const label facei,
41  const direction cmpt,
42  const scalar value
43 )
44 {
45  if (psi_.needReference())
46  {
47  if (Pstream::master())
48  {
49  internalCoeffs_[patchi][facei].component(cmpt) +=
50  diag()[psi_.mesh().boundary()[patchi].faceCells()[facei]];
51 
52  boundaryCoeffs_[patchi][facei].component(cmpt) +=
53  diag()[psi_.mesh().boundary()[patchi].faceCells()[facei]]
54  *value;
55  }
56  }
57 }
58 
59 
60 template<class Type>
62 (
63  const dictionary& solverControls
64 )
65 {
66  word regionName;
67  if (psi_.mesh().name() != polyMesh::defaultRegion)
68  {
69  regionName = psi_.mesh().name() + "::";
70  }
71  addProfiling(solve, "fvMatrix::solve.", regionName, psi_.name());
72 
73  if (debug)
74  {
75  Info.masterStream(this->mesh().comm())
76  << "fvMatrix<Type>::solveSegregatedOrCoupled"
77  "(const dictionary& solverControls) : "
78  "solving fvMatrix<Type>"
79  << endl;
80  }
81 
82  // Do not solve if maxIter == 0
83  if (solverControls.getOrDefault<label>("maxIter", -1) == 0)
84  {
85  return SolverPerformance<Type>();
86  }
87 
88  word type(solverControls.getOrDefault<word>("type", "segregated"));
89 
90  if (type == "segregated")
91  {
92  return solveSegregated(solverControls);
93  }
94  else if (type == "coupled")
95  {
96  return solveCoupled(solverControls);
97  }
98  else
99  {
100  FatalIOErrorInFunction(solverControls)
101  << "Unknown type " << type
102  << "; currently supported solver types are segregated and coupled"
103  << exit(FatalIOError);
104 
106  }
107 }
108 
109 
110 template<class Type>
112 (
113  const dictionary& solverControls
114 )
115 {
116  if (useImplicit_)
117  {
119  << "Implicit option is not allowed for type: " << Type::typeName
120  << exit(FatalError);
121  }
122 
123  if (debug)
124  {
125  Info.masterStream(this->mesh().comm())
126  << "fvMatrix<Type>::solveSegregated"
127  "(const dictionary& solverControls) : "
128  "solving fvMatrix<Type>"
129  << endl;
130  }
131 
132  const int logLevel =
133  solverControls.getOrDefault<int>
134  (
135  "log",
137  );
138 
139  auto& psi = psi_.constCast();
140 
141  SolverPerformance<Type> solverPerfVec
142  (
143  "fvMatrix<Type>::solveSegregated",
144  psi.name()
145  );
146 
147  scalarField saveDiag(diag());
148 
149  Field<Type> source(source_);
150 
151  // At this point include the boundary source from the coupled boundaries.
152  // This is corrected for the implicit part by updateMatrixInterfaces within
153  // the component loop.
154  addBoundarySource(source);
155 
156  typename Type::labelType validComponents
157  (
158  psi.mesh().template validComponents<Type>()
159  );
160 
161  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
162  {
163  if (validComponents[cmpt] == -1) continue;
164 
165  // copy field and source
166 
167  scalarField psiCmpt(psi.primitiveField().component(cmpt));
168  addBoundaryDiag(diag(), cmpt);
169 
170  scalarField sourceCmpt(source.component(cmpt));
171 
172  FieldField<Field, scalar> bouCoeffsCmpt
173  (
174  boundaryCoeffs_.component(cmpt)
175  );
176 
177  FieldField<Field, scalar> intCoeffsCmpt
178  (
179  internalCoeffs_.component(cmpt)
180  );
181 
182  lduInterfaceFieldPtrsList interfaces =
183  psi.boundaryField().scalarInterfaces();
184 
185  // Use the initMatrixInterfaces and updateMatrixInterfaces to correct
186  // bouCoeffsCmpt for the explicit part of the coupled boundary
187  // conditions
188  {
189  PrecisionAdaptor<solveScalar, scalar> sourceCmpt_ss(sourceCmpt);
190  ConstPrecisionAdaptor<solveScalar, scalar> psiCmpt_ss(psiCmpt);
191 
192  const label startRequest = UPstream::nRequests();
193 
194  initMatrixInterfaces
195  (
196  true,
197  bouCoeffsCmpt,
198  interfaces,
199  psiCmpt_ss(),
200  sourceCmpt_ss.ref(),
201  cmpt
202  );
203 
204  updateMatrixInterfaces
205  (
206  true,
207  bouCoeffsCmpt,
208  interfaces,
209  psiCmpt_ss(),
210  sourceCmpt_ss.ref(),
211  cmpt,
212  startRequest
213  );
214  }
215 
216  solverPerformance solverPerf;
217 
218  // Solver call
219  solverPerf = lduMatrix::solver::New
220  (
221  psi.name() + pTraits<Type>::componentNames[cmpt],
222  *this,
223  bouCoeffsCmpt,
224  intCoeffsCmpt,
225  interfaces,
226  solverControls
227  )->solve(psiCmpt, sourceCmpt, cmpt);
228 
229  if (logLevel)
230  {
231  solverPerf.print(Info.masterStream(this->mesh().comm()));
232  }
233 
234  solverPerfVec.replace(cmpt, solverPerf);
235  solverPerfVec.solverName() = solverPerf.solverName();
236 
237  psi.primitiveFieldRef().replace(cmpt, psiCmpt);
238  diag() = saveDiag;
239  }
240 
241  psi.correctBoundaryConditions();
242 
243  psi.mesh().data().setSolverPerformance(psi.name(), solverPerfVec);
245  return solverPerfVec;
246 }
247 
248 
249 template<class Type>
251 (
252  const dictionary& solverControls
253 )
254 {
255  if (debug)
256  {
257  Info.masterStream(this->mesh().comm())
258  << "fvMatrix<Type>::solveCoupled"
259  "(const dictionary& solverControls) : "
260  "solving fvMatrix<Type>"
261  << endl;
262  }
263 
264  const int logLevel =
265  solverControls.getOrDefault<int>
266  (
267  "log",
269  );
270 
271  auto& psi = psi_.constCast();
272 
273  LduMatrix<Type, scalar, scalar> coupledMatrix(psi.mesh());
274  coupledMatrix.diag() = diag();
275  coupledMatrix.upper() = upper();
276  coupledMatrix.lower() = lower();
277  coupledMatrix.source() = source();
278 
279  addBoundaryDiag(coupledMatrix.diag(), 0);
280  addBoundarySource(coupledMatrix.source(), false);
281 
282  coupledMatrix.interfaces() = psi.boundaryFieldRef().interfaces();
283  coupledMatrix.interfacesUpper() = boundaryCoeffs().component(0);
284  coupledMatrix.interfacesLower() = internalCoeffs().component(0);
285 
286  autoPtr<typename LduMatrix<Type, scalar, scalar>::solver>
287  coupledMatrixSolver
288  (
290  (
291  psi.name(),
292  coupledMatrix,
293  solverControls
294  )
295  );
296 
297  SolverPerformance<Type> solverPerf
298  (
299  coupledMatrixSolver->solve(psi)
300  );
301 
302  if (logLevel)
303  {
304  solverPerf.print(Info.masterStream(this->mesh().comm()));
305  }
306 
307  psi.correctBoundaryConditions();
308 
309  psi.mesh().data().setSolverPerformance(psi.name(), solverPerf);
310 
311  return solverPerf;
312 }
313 
314 
315 template<class Type>
317 {
318  return this->solveSegregatedOrCoupled(solverDict());
319 }
320 
321 
322 template<class Type>
324 (
325  const dictionary& solverControls
326 )
327 {
328  return psi_.mesh().solve(*this, solverControls);
329 }
330 
331 
332 template<class Type>
335 {
336  return solver(solverDict());
337 }
338 
339 
340 template<class Type>
342 {
343  return solve(fvMat_.solverDict());
344 }
345 
346 
347 template<class Type>
349 {
350  return this->solve(solverDict(name));
351 }
352 
353 
354 template<class Type>
356 {
357  return this->solve(solverDict());
358 }
359 
360 
361 template<class Type>
363 {
364  auto tres = tmp<Field<Type>>::New(source_);
365  auto& res = tres.ref();
366 
367  addBoundarySource(res);
368 
369  // Loop over field components
370  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
371  {
372  scalarField psiCmpt(psi_.primitiveField().component(cmpt));
373 
374  scalarField boundaryDiagCmpt(psi_.size(), Zero);
375  addBoundaryDiag(boundaryDiagCmpt, cmpt);
376 
377  FieldField<Field, scalar> bouCoeffsCmpt
378  (
379  boundaryCoeffs_.component(cmpt)
380  );
381 
382  res.replace
383  (
384  cmpt,
386  (
387  psiCmpt,
388  res.component(cmpt) - boundaryDiagCmpt*psiCmpt,
389  bouCoeffsCmpt,
391  cmpt
392  )
393  );
394  }
395 
396  return tres;
397 }
398 
399 
400 // ************************************************************************* //
UPtrList< const lduInterfaceField > lduInterfaceFieldPtrsList
List of coupled interface fields to be used in coupling.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
type
Types of root.
Definition: Roots.H:52
uint8_t direction
Definition: direction.H:46
const Internal::FieldType & primitiveField() const noexcept
Return a const-reference to the internal field values.
void addBoundaryDiag(scalarField &diag, const direction cmpt) const
Definition: fvMatrix.C:116
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
void residual(solveScalarField &rA, const solveScalarField &psi, const scalarField &source, const FieldField< Field, scalar > &interfaceBouCoeffs, const lduInterfaceFieldPtrsList &interfaces, const direction cmpt) const
lduInterfaceFieldPtrsList scalarInterfaces() const
Return a list of pointers for each patch field with only those pointing to interfaces being set...
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
#define addProfiling(Name,...)
Define profiling trigger with specified name and description string. The description is generated by ...
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
Definition: exprTraits.C:40
A field of fields is a PtrList of fields with reference counting.
Definition: FieldField.H:51
CEqn solve()
SolverPerformance< Type > solveCoupled(const dictionary &)
Solve coupled returning the solution statistics.
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
SolverPerformance< Type > solve()
Solve returning the solution statistics.
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
SolverPerformance is the class returned by the LduMatrix solver containing performance statistics...
Abstract base-class for lduMatrix solvers.
Definition: lduMatrix.H:151
tmp< Field< cmptType > > component(const direction) const
Return a component field of the field.
Definition: Field.C:607
SolverPerformance< Type > solveSegregatedOrCoupled()
Solve segregated or coupled returning the solution statistics.
int debug
Static debugging option.
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
void replace(const direction, const FieldField< Field, cmptType > &)
Replace a component field of the field.
Definition: FieldField.C:252
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:629
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
OSstream & masterStream(int communicator)
Return OSstream for output operations on the master process only, Snull on other processes.
autoPtr< fvSolver > solver()
Construct and return the solver.
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
messageStream Info
Information stream (stdout output on master, null elsewhere)
void addBoundarySource(Field< Type > &source, const bool couples=true) const
Definition: fvMatrix.C:169
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
const volScalarField & psi
void setComponentReference(const label patchi, const label facei, const direction cmpt, const scalar value)
Set reference level for a component of the solution on a given patch face.
Definition: fvMatrixSolve.C:31
SolverPerformance< Type > solveSegregated(const dictionary &)
Solve segregated returning the solution statistics.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
A class for managing temporary objects.
Definition: HashPtrTable.H:50
tmp< Field< Type > > residual() const
Return the matrix residual.
SolverPerformance< Type > solve()
Solve returning the solution statistics.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
SolverPerformance< scalar > solverPerformance
SolverPerformance instantiated for a scalar.
const dictionary & solverDict() const
Return the solver dictionary for psi, taking into account finalIteration.
Definition: fvMatrix.C:1528
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127