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 | Copyright (C) 2011-2016 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 
29 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
30 
31 template<class Type>
33 (
34  const label patchi,
35  const label facei,
36  const direction cmpt,
37  const scalar value
38 )
39 {
40  if (psi_.needReference())
41  {
42  if (Pstream::master())
43  {
44  internalCoeffs_[patchi][facei].component(cmpt) +=
45  diag()[psi_.mesh().boundary()[patchi].faceCells()[facei]];
46 
47  boundaryCoeffs_[patchi][facei].component(cmpt) +=
48  diag()[psi_.mesh().boundary()[patchi].faceCells()[facei]]
49  *value;
50  }
51  }
52 }
53 
54 
55 template<class Type>
57 (
58  const dictionary& solverControls
59 )
60 {
61  if (debug)
62  {
63  Info.masterStream(this->mesh().comm())
64  << "fvMatrix<Type>::solve(const dictionary& solverControls) : "
65  "solving fvMatrix<Type>"
66  << endl;
67  }
68 
69  label maxIter = -1;
70  if (solverControls.readIfPresent("maxIter", maxIter))
71  {
72  if (maxIter == 0)
73  {
74  return SolverPerformance<Type>();
75  }
76  }
77 
78  word type(solverControls.lookupOrDefault<word>("type", "segregated"));
79 
80  if (type == "segregated")
81  {
82  return solveSegregated(solverControls);
83  }
84  else if (type == "coupled")
85  {
86  return solveCoupled(solverControls);
87  }
88  else
89  {
91  (
92  solverControls
93  ) << "Unknown type " << type
94  << "; currently supported solver types are segregated and coupled"
95  << exit(FatalIOError);
96 
97  return SolverPerformance<Type>();
98  }
99 }
100 
101 
102 template<class Type>
104 (
105  const dictionary& solverControls
106 )
107 {
108  if (debug)
109  {
110  Info.masterStream(this->mesh().comm())
111  << "fvMatrix<Type>::solveSegregated"
112  "(const dictionary& solverControls) : "
113  "solving fvMatrix<Type>"
114  << endl;
115  }
116 
119 
120  SolverPerformance<Type> solverPerfVec
121  (
122  "fvMatrix<Type>::solveSegregated",
123  psi.name()
124  );
125 
126  scalarField saveDiag(diag());
127 
128  Field<Type> source(source_);
129 
130  // At this point include the boundary source from the coupled boundaries.
131  // This is corrected for the implict part by updateMatrixInterfaces within
132  // the component loop.
133  addBoundarySource(source);
134 
135  typename Type::labelType validComponents
136  (
137  psi.mesh().template validComponents<Type>()
138  );
139 
140  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
141  {
142  if (validComponents[cmpt] == -1) continue;
143 
144  // copy field and source
145 
146  scalarField psiCmpt(psi.primitiveField().component(cmpt));
147  addBoundaryDiag(diag(), cmpt);
148 
149  scalarField sourceCmpt(source.component(cmpt));
150 
151  FieldField<Field, scalar> bouCoeffsCmpt
152  (
153  boundaryCoeffs_.component(cmpt)
154  );
155 
156  FieldField<Field, scalar> intCoeffsCmpt
157  (
158  internalCoeffs_.component(cmpt)
159  );
160 
161  lduInterfaceFieldPtrsList interfaces =
162  psi.boundaryField().scalarInterfaces();
163 
164  // Use the initMatrixInterfaces and updateMatrixInterfaces to correct
165  // bouCoeffsCmpt for the explicit part of the coupled boundary
166  // conditions
167  initMatrixInterfaces
168  (
169  bouCoeffsCmpt,
170  interfaces,
171  psiCmpt,
172  sourceCmpt,
173  cmpt
174  );
175 
176  updateMatrixInterfaces
177  (
178  bouCoeffsCmpt,
179  interfaces,
180  psiCmpt,
181  sourceCmpt,
182  cmpt
183  );
184 
185  solverPerformance solverPerf;
186 
187  // Solver call
188  solverPerf = lduMatrix::solver::New
189  (
190  psi.name() + pTraits<Type>::componentNames[cmpt],
191  *this,
192  bouCoeffsCmpt,
193  intCoeffsCmpt,
194  interfaces,
195  solverControls
196  )->solve(psiCmpt, sourceCmpt, cmpt);
197 
199  {
200  solverPerf.print(Info.masterStream(this->mesh().comm()));
201  }
202 
203  solverPerfVec.replace(cmpt, solverPerf);
204 
205  psi.primitiveFieldRef().replace(cmpt, psiCmpt);
206  diag() = saveDiag;
207  }
208 
210 
211  psi.mesh().setSolverPerformance(psi.name(), solverPerfVec);
212 
213  return solverPerfVec;
214 }
215 
216 
217 template<class Type>
219 (
220  const dictionary& solverControls
221 )
222 {
223  if (debug)
224  {
225  Info.masterStream(this->mesh().comm())
226  << "fvMatrix<Type>::solveCoupled"
227  "(const dictionary& solverControls) : "
228  "solving fvMatrix<Type>"
229  << endl;
230  }
231 
234 
235  LduMatrix<Type, scalar, scalar> coupledMatrix(psi.mesh());
236  coupledMatrix.diag() = diag();
237  coupledMatrix.upper() = upper();
238  coupledMatrix.lower() = lower();
239  coupledMatrix.source() = source();
240 
241  addBoundaryDiag(coupledMatrix.diag(), 0);
242  addBoundarySource(coupledMatrix.source(), false);
243 
244  coupledMatrix.interfaces() = psi.boundaryFieldRef().interfaces();
245  coupledMatrix.interfacesUpper() = boundaryCoeffs().component(0);
246  coupledMatrix.interfacesLower() = internalCoeffs().component(0);
247 
249  coupledMatrixSolver
250  (
252  (
253  psi.name(),
254  coupledMatrix,
255  solverControls
256  )
257  );
258 
259  SolverPerformance<Type> solverPerf
260  (
261  coupledMatrixSolver->solve(psi)
262  );
263 
265  {
266  solverPerf.print(Info.masterStream(this->mesh().comm()));
267  }
268 
270 
271  psi.mesh().setSolverPerformance(psi.name(), solverPerf);
272 
273  return solverPerf;
274 }
275 
276 
277 template<class Type>
280 {
281  return solver
282  (
283  psi_.mesh().solverDict
284  (
285  psi_.select
286  (
287  psi_.mesh().data::template lookupOrDefault<bool>
288  ("finalIteration", false)
289  )
290  )
291  );
292 }
293 
294 
295 template<class Type>
297 {
298  return solve
299  (
300  fvMat_.psi_.mesh().solverDict
301  (
302  fvMat_.psi_.select
303  (
304  fvMat_.psi_.mesh().data::template lookupOrDefault<bool>
305  ("finalIteration", false)
306  )
307  )
308  );
309 }
310 
311 
312 template<class Type>
314 {
315  return solve
316  (
317  psi_.mesh().solverDict
318  (
319  psi_.select
320  (
321  psi_.mesh().data::template lookupOrDefault<bool>
322  ("finalIteration", false)
323  )
324  )
325  );
326 }
327 
328 
329 template<class Type>
331 {
332  tmp<Field<Type>> tres(new Field<Type>(source_));
333  Field<Type>& res = tres.ref();
334 
335  addBoundarySource(res);
336 
337  // Loop over field components
338  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
339  {
340  scalarField psiCmpt(psi_.primitiveField().component(cmpt));
341 
342  scalarField boundaryDiagCmpt(psi_.size(), 0.0);
343  addBoundaryDiag(boundaryDiagCmpt, cmpt);
344 
345  FieldField<Field, scalar> bouCoeffsCmpt
346  (
347  boundaryCoeffs_.component(cmpt)
348  );
349 
350  res.replace
351  (
352  cmpt,
354  (
355  psiCmpt,
356  res.component(cmpt) - boundaryDiagCmpt*psiCmpt,
357  bouCoeffsCmpt,
358  psi_.boundaryField().scalarInterfaces(),
359  cmpt
360  )
361  );
362  }
363 
364  return tres;
365 }
366 
367 
368 // ************************************************************************* //
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
uint8_t direction
Definition: direction.H:46
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
Traits class for primitives.
Definition: pTraits.H:50
const Internal::FieldType & primitiveField() const
Return a const-reference to the internal field.
Generic GeometricField class.
void replace(const direction, const UList< cmptType > &)
Replace a component field of the field.
Definition: Field.C:662
Generic field type.
Definition: FieldField.H:51
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
void addBoundaryDiag(scalarField &diag, const direction cmpt) const
Definition: fvMatrix.C:111
SolverPerformance< Type > solveCoupled(const dictionary &)
Solve coupled returning the solution statistics.
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
dynamicFvMesh & mesh
void residual(scalarField &rA, const scalarField &psi, const scalarField &source, const FieldField< Field, scalar > &interfaceBouCoeffs, const lduInterfaceFieldPtrsList &interfaces, const direction cmpt) const
SolverPerformance< Type > solve()
Solve returning the solution statistics.
void print(Ostream &os) const
Print summary of solver performance to the given stream.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
tmp< Field< Type > > residual() const
Return the matrix residual.
A class for handling words, derived from string.
Definition: word.H:59
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
SolverPerformance is the class returned by the LduMatrix solver containing performance statistics...
Abstract base-class for lduMatrix solvers.
Definition: lduMatrix.H:93
rhoEqn solve()
void addBoundarySource(Field< Type > &source, const bool couples=true) const
Definition: fvMatrix.C:145
Internal::FieldType & primitiveFieldRef()
Return a reference to the internal field.
tmp< Field< cmptType > > component(const direction) const
Return a component field of the field.
Definition: Field.C:650
OSstream & masterStream(const label communicator)
Convert to OSstream.
Definition: messageStream.C:59
Field< DType > & diag()
Definition: LduMatrix.C:190
label patchi
fileName::Type type(const fileName &)
Return the file type: DIRECTORY or FILE.
Definition: POSIX.C:461
Boundary & boundaryFieldRef()
Return a reference to the boundary field.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
const Mesh & mesh() const
Return mesh.
LduMatrix is a general matrix class in which the coefficients are stored as three arrays...
Definition: LduMatrix.H:69
autoPtr< fvSolver > solver()
Construct and return the solver.
void correctBoundaryConditions()
Correct boundary field.
messageStream Info
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:53
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.
Definition: fvMatrixSolve.C:33
SolverPerformance< Type > solveSegregated(const dictionary &)
Solve segregated returning the solution statistics.
A class for managing temporary objects.
Definition: PtrList.H:54
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:174
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
SolverPerformance< Type > solve()
Solve returning the solution statistics.
const word & name() const
Return name.
Definition: IOobject.H:260
IOerror FatalIOError