1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-6 H. Jasak All rights reserved
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 Segregated solver for symmetric and asymmetric matrices.
27 Calls scalar solver component-by-component
29 \*---------------------------------------------------------------------------*/
31 #include "SegregatedSolver.H"
33 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
35 // Construct from matrix and solver data stream
37 Foam::SegregatedSolver<Type>::SegregatedSolver
39 const word& fieldName,
40 const BlockLduMatrix<Type>& matrix,
41 const dictionary& dict
44 BlockLduSolver<Type>(fieldName, matrix, dict),
45 scalarX_(matrix.lduAddr().size()),
46 scalarMatrix_(matrix.mesh()),
47 scalarB_(matrix.lduAddr().size())
51 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
54 Foam::BlockSolverPerformance<Type> Foam::SegregatedSolver<Type>::solve
60 // Get reference to matrix, x and b
61 const BlockLduMatrix<Type>& blockMatrix = this->matrix_;
63 // Determine if the diagonal or off-diagonal is expanded
65 // Check switching diagonal
66 bool switchingDiag = false;
68 if (blockMatrix.diag().activeType() == blockCoeffBase::SCALAR)
70 scalarMatrix_.diag() = blockMatrix.diag().asScalar();
77 // Check switching upper
78 bool switchingUpper = false;
80 if (blockMatrix.thereIsUpper())
82 if (blockMatrix.upper().activeType() == blockCoeffBase::SCALAR)
84 scalarMatrix_.upper() = blockMatrix.upper().asScalar();
88 switchingUpper = true;
92 // Check switching lower
93 bool switchingLower = false;
95 if (blockMatrix.thereIsLower())
97 if (blockMatrix.lower().activeType() == blockCoeffBase::SCALAR)
99 scalarMatrix_.lower() = blockMatrix.lower().asScalar();
103 switchingLower = true;
107 // Decouple quadratic coupling by multiplying out the square coefficient
109 Field<Type>* dBPtr = NULL;
111 if (blockMatrix.componentCoupled())
113 if (BlockLduMatrix<Type>::debug >= 2)
115 Info << " Component coupled segregation" << endl;
118 dBPtr = new Field<Type>(b);
119 blockMatrix.segregateB(*dBPtr, x);
122 // Prepare solver performance
123 word segSolverName(this->dict().lookup("solver"));
125 BlockSolverPerformance<Type> solverPerf
127 typeName + "_" + segSolverName,
131 // Loop through the form component by component and call the
136 cmpt < pTraits<Type>::nComponents;
140 // Grab the x and b for the current component
141 scalarX_ = x.component(cmpt);
143 // Handle b decoupling
146 scalarB_ = dBPtr->component(cmpt);
150 scalarB_ = b.component(cmpt);
153 // Switch diagonal, upper and lower
156 scalarMatrix_.diag() = blockMatrix.diag().component(cmpt);
161 scalarMatrix_.upper() = blockMatrix.upper().component(cmpt);
166 scalarMatrix_.lower() = blockMatrix.lower().component(cmpt);
169 // Call the scalar solver
170 BlockSolverPerformance<scalar> scalarPerf =
171 blockScalarSolver::New
176 )->solve(scalarX_, scalarB_);
178 // Replace the solution component
179 x.replace(cmpt, scalarX_);
181 // Grab solver performance and combine
182 solverPerf.initialResidual().replace
185 scalarPerf.initialResidual()
188 solverPerf.finalResidual().replace
191 scalarPerf.finalResidual()
194 solverPerf.nIterations() =
197 solverPerf.nIterations(),
198 scalarPerf.nIterations()
201 solverPerf.converged() =
202 (solverPerf.converged() && scalarPerf.converged());
204 solverPerf.singular() =
205 solverPerf.singular() && scalarPerf.singular();
208 // Clear decoupled b if allocated
219 // ************************************************************************* //