fvMatrixSolve.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "LduMatrix.H"
27 #include "diagTensorField.H"
28 #include "Residuals.H"
29 
30 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
31 
32 template<class Type>
34 (
35  const label patchi,
36  const label facei,
37  const direction cmpt,
38  const scalar value
39 )
40 {
41  if (psi_.needReference())
42  {
43  if (Pstream::master())
44  {
45  internalCoeffs_[patchi][facei].component(cmpt) +=
46  diag()[psi_.mesh().boundary()[patchi].faceCells()[facei]];
47 
48  boundaryCoeffs_[patchi][facei].component(cmpt) +=
49  diag()[psi_.mesh().boundary()[patchi].faceCells()[facei]]
50  *value;
51  }
52  }
53 }
54 
55 
56 template<class Type>
58 (
59  const dictionary& solverControls
60 )
61 {
62  if (debug)
63  {
64  Info(this->mesh().comm())
65  << "fvMatrix<Type>::solve(const dictionary& solverControls) : "
66  "solving fvMatrix<Type>"
67  << endl;
68  }
69 
70  label maxIter = -1;
71  if (solverControls.readIfPresent("maxIter", maxIter))
72  {
73  if (maxIter == 0)
74  {
75  return SolverPerformance<Type>();
76  }
77  }
78 
79  word type(solverControls.lookupOrDefault<word>("type", "segregated"));
80 
81  if (type == "segregated")
82  {
83  return solveSegregated(solverControls);
84  }
85  else if (type == "coupled")
86  {
87  return solveCoupled(solverControls);
88  }
89  else
90  {
92  (
93  solverControls
94  ) << "Unknown type " << type
95  << "; currently supported solver types are segregated and coupled"
96  << exit(FatalIOError);
97 
98  return SolverPerformance<Type>();
99  }
100 }
101 
102 
103 template<class Type>
105 (
106  const dictionary& solverControls
107 )
108 {
109  if (debug)
110  {
111  Info(this->mesh().comm())
112  << "fvMatrix<Type>::solveSegregated"
113  "(const dictionary& solverControls) : "
114  "solving fvMatrix<Type>"
115  << endl;
116  }
117 
119  const_cast<VolField<Type>&>(psi_);
120 
121  SolverPerformance<Type> solverPerfVec
122  (
123  "fvMatrix<Type>::solveSegregated",
124  psi.name()
125  );
126 
127  scalarField saveDiag(diag());
128 
129  Field<Type> source(source_);
130 
131  // At this point include the boundary source from the coupled boundaries.
132  // This is corrected for the implicit part by updateMatrixInterfaces within
133  // the component loop.
134  addBoundarySource(source);
135 
136  typename Type::labelType validComponents
137  (
138  psi.mesh().template validComponents<Type>()
139  );
140 
141  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
142  {
143  if (validComponents[cmpt] == -1) continue;
144 
145  // copy field and source
146 
147  scalarField psiCmpt(psi.primitiveField().component(cmpt));
148  addBoundaryDiag(diag(), cmpt);
149 
150  scalarField sourceCmpt(source.component(cmpt));
151 
152  FieldField<Field, scalar> bouCoeffsCmpt
153  (
154  boundaryCoeffs_.component(cmpt)
155  );
156 
157  FieldField<Field, scalar> intCoeffsCmpt
158  (
159  internalCoeffs_.component(cmpt)
160  );
161 
162  lduInterfaceFieldPtrsList interfaces =
163  psi.boundaryField().scalarInterfaces();
164 
165  // Use the initMatrixInterfaces and updateMatrixInterfaces to correct
166  // bouCoeffsCmpt for the explicit part of the coupled boundary
167  // conditions
168  initMatrixInterfaces
169  (
170  bouCoeffsCmpt,
171  interfaces,
172  psiCmpt,
173  sourceCmpt,
174  cmpt
175  );
176 
177  updateMatrixInterfaces
178  (
179  bouCoeffsCmpt,
180  interfaces,
181  psiCmpt,
182  sourceCmpt,
183  cmpt
184  );
185 
186  solverPerformance solverPerf;
187 
188  // Solver call
189  solverPerf = lduMatrix::solver::New
190  (
191  psi.name() + pTraits<Type>::componentNames[cmpt],
192  *this,
193  bouCoeffsCmpt,
194  intCoeffsCmpt,
195  interfaces,
196  solverControls
197  )->solve(psiCmpt, sourceCmpt, cmpt);
198 
200  {
201  solverPerf.print(Info(this->mesh().comm()));
202  }
203 
204  solverPerfVec.replace(cmpt, solverPerf);
205  solverPerfVec.solverName() = solverPerf.solverName();
206 
207  psi.primitiveFieldRef().replace(cmpt, psiCmpt);
208  diag() = saveDiag;
209  }
210 
211  psi.correctBoundaryConditions();
212 
213  Residuals<Type>::append(psi.mesh(), solverPerfVec);
214 
215  return solverPerfVec;
216 }
217 
218 
219 template<class Type>
221 (
222  const dictionary& solverControls
223 )
224 {
225  if (debug)
226  {
227  Info(this->mesh().comm())
228  << "fvMatrix<Type>::solveCoupled"
229  "(const dictionary& solverControls) : "
230  "solving fvMatrix<Type>"
231  << endl;
232  }
233 
235  const_cast<VolField<Type>&>(psi_);
236 
237  LduMatrix<Type, scalar, scalar> coupledMatrix(psi.mesh());
238  coupledMatrix.diag() = diag();
239  coupledMatrix.upper() = upper();
240  coupledMatrix.lower() = lower();
241  coupledMatrix.source() = source();
242 
243  addBoundaryDiag(coupledMatrix.diag(), 0);
244  addBoundarySource(coupledMatrix.source(), false);
245 
246  coupledMatrix.interfaces() = psi.boundaryFieldRef().interfaces();
247  coupledMatrix.interfacesUpper() = boundaryCoeffs().component(0);
248  coupledMatrix.interfacesLower() = internalCoeffs().component(0);
249 
251  coupledMatrixSolver
252  (
254  (
255  psi.name(),
256  coupledMatrix,
257  solverControls
258  )
259  );
260 
261  SolverPerformance<Type> solverPerf
262  (
263  coupledMatrixSolver->solve(psi)
264  );
265 
267  {
268  solverPerf.print(Info(this->mesh().comm()));
269  }
270 
271  psi.correctBoundaryConditions();
272 
273  Residuals<Type>::append(psi.mesh(), solverPerf);
274 
275  return solverPerf;
276 }
277 
278 
279 template<class Type>
282 {
283  return solver
284  (
285  psi_.mesh().solution().solverDict
286  (
287  psi_.select
288  (
289  !psi_.mesh().schemes().steady()
290  && solutionControl::finalIteration(psi_.mesh())
291  )
292  )
293  );
294 }
295 
296 
297 template<class Type>
299 {
300  return solve
301  (
302  fvMat_.psi_.mesh().solution().solverDict
303  (
304  fvMat_.psi_.select
305  (
306  !fvMat_.psi_.mesh().schemes().steady()
307  && solutionControl::finalIteration(fvMat_.psi_.mesh())
308  )
309  )
310  );
311 }
312 
313 
314 template<class Type>
316 {
317  return solve
318  (
319  psi_.mesh().solution().solverDict
320  (
321  !psi_.mesh().schemes().steady()
322  && solutionControl::finalIteration(psi_.mesh())
323  ? word(name + "Final")
324  : name
325  )
326  );
327 }
328 
329 
330 template<class Type>
332 {
333  return solve
334  (
335  psi_.mesh().solution().solverDict
336  (
337  psi_.select
338  (
339  !psi_.mesh().schemes().steady()
340  && solutionControl::finalIteration(psi_.mesh())
341  )
342  )
343  );
344 }
345 
346 
347 template<class Type>
349 {
350  tmp<Field<Type>> tres(new Field<Type>(source_));
351  Field<Type>& res = tres.ref();
352 
353  addBoundarySource(res);
354 
355  // Loop over field components
356  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
357  {
358  scalarField psiCmpt(psi_.primitiveField().component(cmpt));
359 
360  scalarField boundaryDiagCmpt(psi_.size(), 0.0);
361  addBoundaryDiag(boundaryDiagCmpt, cmpt);
362 
363  FieldField<Field, scalar> bouCoeffsCmpt
364  (
365  boundaryCoeffs_.component(cmpt)
366  );
367 
368  res.replace
369  (
370  cmpt,
372  (
373  psiCmpt,
374  res.component(cmpt) - boundaryDiagCmpt*psiCmpt,
375  bouCoeffsCmpt,
376  psi_.boundaryField().scalarInterfaces(),
377  cmpt
378  )
379  );
380  }
381 
382  return tres;
383 }
384 
385 
386 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
387 
388 template<class Type>
390 (
391  fvMatrix<Type>& fvm,
392  const word& name
393 )
394 {
395  return fvm.solve(name);
396 }
397 
398 
399 template<class Type>
401 (
402  const tmp<fvMatrix<Type>>& tfvm,
403  const word& name
404 )
405 {
406  SolverPerformance<Type> solverPerf =
407  const_cast<fvMatrix<Type>&>(tfvm()).solve(name);
408 
409  tfvm.clear();
410 
411  return solverPerf;
412 }
413 
414 
415 template<class Type>
416 Foam::SolverPerformance<Type> Foam::solve(fvMatrix<Type>& fvm)
417 {
418  return fvm.solve();
419 }
420 
421 template<class Type>
422 Foam::SolverPerformance<Type> Foam::solve(const tmp<fvMatrix<Type>>& tfvm)
423 {
424  SolverPerformance<Type> solverPerf =
425  const_cast<fvMatrix<Type>&>(tfvm()).solve();
426 
427  tfvm.clear();
428 
429  return solverPerf;
430 }
431 
432 
433 // ************************************************************************* //
Generic field type.
Definition: FieldField.H:77
void replace(const direction, const UList< cmptType > &)
Replace a component field of the field.
Definition: Field.C:491
tmp< Field< cmptType > > component(const direction) const
Return a component field of the field.
Definition: Field.C:479
Generic GeometricField class.
void replace(const direction, const GeometricField< cmptType, PatchField, GeoMesh > &)
tmp< GeometricField< cmptType, PatchField, GeoMesh > > component(const direction) const
Return a component of the field.
LduMatrix is a general matrix class in which the coefficients are stored as three arrays,...
Definition: LduMatrix.H:85
DemandDrivenMeshObject to store the solver performance residuals of all the fields of the type it is ...
Definition: Residuals.H:61
SolverPerformance is the class returned by the LduMatrix solver containing performance statistics.
void print(Ostream &os) const
Print summary of solver performance to the given stream.
const word & solverName() const
Return solver name.
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:162
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T, if not found return the given default.
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
SolverPerformance< Type > solve()
Solve returning the solution statistics.
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvMatrix.H:118
autoPtr< fvSolver > solver()
Construct and return the solver.
SolverPerformance< Type > solve(const dictionary &)
Solve segregated or coupled returning the solution statistics.
Definition: fvMatrixSolve.C:58
SolverPerformance< Type > solve()
Solve returning the solution statistics.
void addBoundarySource(Field< Type > &source, const bool couples=true) const
Definition: fvMatrix.C:147
void setComponentReference(const label patchi, const label facei, const direction cmpt, const scalar value)
Set reference level for a component of the solution.
Definition: fvMatrixSolve.C:34
SolverPerformance< Type > solveCoupled(const dictionary &)
Solve coupled returning the solution statistics.
tmp< Field< Type > > residual() const
Return the matrix residual.
void addBoundaryDiag(scalarField &diag, const direction cmpt) const
Definition: fvMatrix.C:113
SolverPerformance< Type > solveSegregated(const dictionary &)
Solve segregated returning the solution statistics.
Abstract base-class for lduMatrix solvers.
Definition: lduMatrix.H:94
void residual(scalarField &rA, const scalarField &psi, const scalarField &source, const FieldField< Field, scalar > &interfaceBouCoeffs, const lduInterfaceFieldPtrsList &interfaces, const direction cmpt) const
Traits class for primitives.
Definition: pTraits.H:53
static bool finalIteration(const objectRegistry &registry)
Lookup solutionControl from the objectRegistry and return finalIter.
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:181
A class for handling words, derived from string.
Definition: word.H:62
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
label patchi
const volScalarField & psi
autoPtr< CompressibleMomentumTransportModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const viscosity &viscosity)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
messageStream Info
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
IOerror FatalIOError
uint8_t direction
Definition: direction.H:45
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
SolverPerformance< Type > solve(fvMatrix< Type > &, const word &)
Solve returning the solution statistics given convergence tolerance.