Nektar++
Loading...
Searching...
No Matches
GlobalLinSysIterativeFull.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: GlobalLinSysIterativeFull.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: GlobalLinSysIterativeFull definition
32//
33///////////////////////////////////////////////////////////////////////////////
34
37#include <map>
38
39using namespace std;
40
42{
43/**
44 * @class GlobalLinSysIterativeCG
45 *
46 * This class implements a conjugate gradient matrix solver.
47 * Preconditioning is implemented using a Jacobi (diagonal)
48 * preconditioner.
49 */
50
51/**
52 * Registers the class with the Factory.
53 */
56 "IterativeFull", GlobalLinSysIterativeFull::create,
57 "Iterative solver for full matrix system.");
58
59/**
60 * Constructor for full direct matrix solve.
61 * @param pKey Key specifying matrix to solve.
62 * @param pExp Shared pointer to expansion list for applying
63 * matrix evaluations.
64 * @param pLocToGloMap Local to global mapping.
65 */
67 const GlobalLinSysKey &pKey, const std::weak_ptr<ExpList> &pExp,
68 const std::shared_ptr<AssemblyMap> &pLocToGloMap)
69 : GlobalLinSys(pKey, pExp, pLocToGloMap),
70 GlobalLinSysIterative(pKey, pExp, pLocToGloMap),
71 m_locToGloMap(pLocToGloMap)
72{
74 "This routine should only be used when using an Iterative "
75 "conjugate gradient matrix solve.");
76}
77
78/**
79 * Solve a global linear system with Dirichlet forcing using a
80 * conjugate gradient method. This routine performs handling of the
81 * Dirichlet forcing terms and wraps the underlying iterative solver
82 * used for the remaining degrees of freedom.
83 *
84 * Consider solving for \f$x\f$, the matrix system \f$Ax=b\f$, where
85 * \f$b\f$ is known. To enforce the Dirichlet terms we instead solve
86 * \f[A(x-x_0) = b - Ax_0 \f]
87 * where \f$x_0\f$ is the Dirichlet forcing.
88 *
89 * @param pInput RHS of linear system, \f$b\f$.
90 * @param pOutput On input, values of dirichlet degrees
91 * of freedom with initial guess on other values.
92 * On output, the solution \f$x\f$.
93 * @param pLocToGloMap Local to global mapping.
94 * @param pDirForcing Precalculated Dirichlet forcing.
95 */
97 const Array<OneD, const NekDouble> &pLocInput,
98 Array<OneD, NekDouble> &pLocOutput,
99 const AssemblyMapSharedPtr &pLocToGloMap,
100 const Array<OneD, const NekDouble> &pDirForcing)
101{
102 m_locToGloMap = pLocToGloMap;
103
104 bool dirForcCalculated = (bool)pDirForcing.size();
105 int nDirDofs = pLocToGloMap->GetNumGlobalDirBndCoeffs();
106 int nGlobDofs = pLocToGloMap->GetNumGlobalCoeffs();
107 int nLocDofs = pLocToGloMap->GetNumLocalCoeffs();
108
109 int nDirTotal = nDirDofs;
110 std::shared_ptr<MultiRegions::ExpList> expList = m_expList.lock();
111 expList->GetComm()->GetRowComm()->AllReduce(nDirTotal,
113
114 if (nDirTotal)
115 {
116 Array<OneD, NekDouble> rhs(nLocDofs);
117
118 // Calculate the Dirichlet forcing
119 if (dirForcCalculated)
120 {
121 // Assume pDirForcing is in local space
122 ASSERTL0(
123 pDirForcing.size() >= nLocDofs,
124 "DirForcing is not of sufficient size. Is it in local space?");
125 Vmath::Vsub(nLocDofs, pLocInput, 1, pDirForcing, 1, rhs, 1);
126 }
127 else
128 {
129 // Calculate initial condition and Dirichlet forcing and subtract it
130 // from the rhs
131 expList->GeneralMatrixOp(m_linSysKey, pLocOutput, rhs);
132
133 // Iterate over all the elements computing Robin BCs where
134 // necessary
135 for (auto &r : m_robinBCInfo) // add robin mass matrix
136 {
139
140 int n = r.first;
141 int offset = expList->GetCoeff_Offset(n);
142
143 LocalRegions::ExpansionSharedPtr vExp = expList->GetExp(n);
144 // Add local matrix contribution
145 for (rBC = r.second; rBC; rBC = rBC->next)
146 {
147 vExp->AddRobinTraceContribution(
148 rBC->m_robinID, rBC->m_robinPrimitiveCoeffs,
149 pLocOutput + offset, rhsloc = rhs + offset);
150 }
151 }
152 Vmath::Vsub(nLocDofs, pLocInput, 1, rhs, 1, rhs, 1);
153 }
154
155 if (std::dynamic_pointer_cast<AssemblyMapCG>(pLocToGloMap))
156 {
157 Array<OneD, NekDouble> diff(nLocDofs);
158
159 // Solve for perturbation from initial guess in pOutput
160 SolveLinearSystem(nGlobDofs, rhs, diff, pLocToGloMap, nDirDofs);
161
162 // Add back initial and boundary condition
163 Vmath::Vadd(nLocDofs, diff, 1, pLocOutput, 1, pLocOutput, 1);
164 }
165 else
166 {
167 ASSERTL0(false, "Need DG solve if using Dir BCs");
168 }
169 }
170 else
171 {
172 SolveLinearSystem(nGlobDofs, pLocInput, pLocOutput, pLocToGloMap,
173 nDirDofs);
174 }
175}
176
177/**
178 *
179 */
181 const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput)
182{
183 bool isLocal = m_linsol->IsLocal();
184
185 std::shared_ptr<MultiRegions::ExpList> expList = m_expList.lock();
186
187 AssemblyMapSharedPtr asmMap = m_locToGloMap.lock();
188
189 int ncoeffs = expList->GetNcoeffs();
190 Array<OneD, NekDouble> InputLoc, OutputLoc;
191
192 if (isLocal)
193 {
194 InputLoc = pInput;
195 OutputLoc = pOutput;
196
197 // Perform matrix-vector operation A*d_i
198 expList->GeneralMatrixOp(m_linSysKey, InputLoc, OutputLoc);
199 }
200 else
201 {
202 ASSERTL1(pInput.size() >= asmMap->GetNumGlobalCoeffs(),
203 "Input array is not of suffiicent length "
204 "to support GlobalToLocal Call");
205 InputLoc = Array<OneD, NekDouble>(ncoeffs);
206 OutputLoc = Array<OneD, NekDouble>(ncoeffs);
207
208 asmMap->GlobalToLocal(pInput, InputLoc);
209 // Perform matrix-vector operation A*d_i
210 expList->GeneralMatrixOp(m_linSysKey, InputLoc, OutputLoc);
211 }
212
213 // Apply robin boundary conditions to the solution.
214 for (auto &r : m_robinBCInfo) // add robin mass matrix
215 {
218
219 int n = r.first;
220
221 int offset = expList->GetCoeff_Offset(n);
222 LocalRegions::ExpansionSharedPtr vExp = expList->GetExp(n);
223
224 // add local matrix contribution
225 for (rBC = r.second; rBC; rBC = rBC->next)
226 {
227 vExp->AddRobinTraceContribution(
228 rBC->m_robinID, rBC->m_robinPrimitiveCoeffs, InputLoc + offset,
229 tmp = OutputLoc + offset);
230 }
231 }
232
233 // put back in global coeffs
234 if (isLocal == false)
235 {
236 asmMap->Assemble(OutputLoc, pOutput);
237 }
238}
239
240/**
241 *
242 */
244{
245 m_map = m_locToGloMap.lock()->GetGlobalToUniversalMapUnique();
246}
247
249 const int nGlobal, const AssemblyMapSharedPtr &plocToGloMap, const int nDir)
250{
251 if (!m_linsol)
252 {
254 m_expList.lock()->GetComm()->GetRowComm();
256 m_expList.lock()->GetSession();
257
258 // Check such a module exists for this equation.
261 "NekLinSysIter '" + m_linSysIterSolver +
262 "' is not defined.\n");
263
264 // Create the key to hold solver settings
265 auto sysKey = LibUtilities::NekSysKey();
266 string variable = plocToGloMap->GetVariable();
267
268 // Either get the solnInfo from <GlobalSysSolInfo> or from
269 // <Parameters>
270 if (pSession->DefinesGlobalSysSolnInfo(variable,
271 "IterativeSolverTolerance"))
272 {
273 sysKey.m_NekLinSysTolerance = boost::lexical_cast<double>(
274 pSession
275 ->GetGlobalSysSolnInfo(variable, "IterativeSolverTolerance")
276 .c_str());
277 }
278 else
279 {
280 pSession->LoadParameter("IterativeSolverTolerance",
281 sysKey.m_NekLinSysTolerance,
283 }
284
285 if (pSession->DefinesGlobalSysSolnInfo(variable,
286 "NekLinSysMaxIterations"))
287 {
288 sysKey.m_NekLinSysMaxIterations = std::stoi(
289 pSession
290 ->GetGlobalSysSolnInfo(variable, "NekLinSysMaxIterations")
291 .c_str());
292 }
293 else
294 {
295 pSession->LoadParameter("NekLinSysMaxIterations",
296 sysKey.m_NekLinSysMaxIterations, 5000);
297 }
298
299 if (pSession->DefinesGlobalSysSolnInfo(variable, "LinSysMaxStorage"))
300 {
301 sysKey.m_LinSysMaxStorage = std::stoi(
302 pSession->GetGlobalSysSolnInfo(variable, "LinSysMaxStorage")
303 .c_str());
304 }
305 else
306 {
307 pSession->LoadParameter("LinSysMaxStorage",
308 sysKey.m_LinSysMaxStorage, 100);
309 }
310
311 if (pSession->DefinesGlobalSysSolnInfo(variable, "GMRESMaxHessMatBand"))
312 {
313 sysKey.m_KrylovMaxHessMatBand = std::stoi(
314 pSession->GetGlobalSysSolnInfo(variable, "GMRESMaxHessMatBand")
315 .c_str());
316 }
317 else
318 {
319 pSession->LoadParameter("GMRESMaxHessMatBand",
320 sysKey.m_KrylovMaxHessMatBand,
321 sysKey.m_LinSysMaxStorage + 1);
322 }
323
324 // The following settings have no correponding tests and are rarely
325 // used.
326 pSession->MatchSolverInfo("GMRESLeftPrecon", "True",
327 sysKey.m_NekLinSysLeftPrecon, false);
328 pSession->MatchSolverInfo("GMRESRightPrecon", "True",
329 sysKey.m_NekLinSysRightPrecon, true);
330
332 m_linSysIterSolver, pSession, vRowComm, nGlobal - nDir, sysKey);
333
334 m_linsol->SetSysOperators(m_NekSysOp);
335 v_UniqueMap();
336 m_linsol->SetUniversalUniqueMap(m_map);
337 }
338
339 if (!m_precon)
340 {
341 m_precon = CreatePrecon(plocToGloMap);
342 m_precon->BuildPreconditioner();
343 }
344}
345
346/**
347 *
348 */
350 const int nGlobal, const Array<OneD, const NekDouble> &pInput,
351 Array<OneD, NekDouble> &pOutput, const AssemblyMapSharedPtr &plocToGloMap,
352 const int nDir)
353{
354 Initialise(nGlobal, plocToGloMap, nDir);
355
356 m_linsol->SetRhsMagnitude(m_isAbsoluteTolerance ? 1.0 : m_rhs_magnitude);
357
358 if (m_useProjection)
359 {
360 Array<OneD, NekDouble> gloIn(nGlobal);
361 Array<OneD, NekDouble> gloOut(nGlobal, 0.0);
362 plocToGloMap->Assemble(pInput, gloIn);
363 DoProjection(nGlobal, gloIn, gloOut, nDir, m_isAconjugate);
364 plocToGloMap->GlobalToLocal(gloOut, pOutput);
365 }
366 else
367 {
368 if (m_linsol->IsLocal())
369 {
370 int nLocDofs = plocToGloMap->GetNumLocalCoeffs();
371 Vmath::Zero(nLocDofs, pOutput, 1);
372 m_linsol->SolveSystem(nLocDofs, pInput, pOutput, nDir);
373 }
374 else
375 {
376 Array<OneD, NekDouble> gloIn(nGlobal);
377 Array<OneD, NekDouble> gloOut(nGlobal, 0.0);
378
379 plocToGloMap->Assemble(pInput, gloIn);
380 m_linsol->SolveSystem(nGlobal, gloIn, gloOut, nDir);
381 plocToGloMap->GlobalToLocal(gloOut, pOutput);
382 }
383 }
384}
385
386} // namespace Nektar::MultiRegions
#define ASSERTL0(condition, msg)
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
A global linear system.
const std::weak_ptr< ExpList > m_expList
Local Matrix System.
const std::map< int, RobinBCInfoSharedPtr > m_robinBCInfo
Robin boundary info.
void SolveLinearSystem(const int pNumRows, const Array< OneD, const NekDouble > &pInput, Array< OneD, NekDouble > &pOutput, const AssemblyMapSharedPtr &locToGloMap, const int pNumDir=0)
Solve the linear system for given input and output vectors.
const GlobalLinSysKey m_linSysKey
Key associated with this linear system.
PreconditionerSharedPtr CreatePrecon(AssemblyMapSharedPtr asmMap)
Create a preconditioner object from the parameters defined in the supplied assembly map.
static GlobalLinSysSharedPtr create(const GlobalLinSysKey &pLinSysKey, const std::weak_ptr< ExpList > &pExpList, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Creates an instance of this class.
GlobalLinSysIterativeFull(const GlobalLinSysKey &pLinSysKey, const std::weak_ptr< ExpList > &pExpList, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Constructor for full direct matrix solve.
void Initialise(const int nGlobal, const AssemblyMapSharedPtr &plocToGloMap, const int nDir)
void v_DoMatrixMultiply(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput) override
void v_Solve(const Array< OneD, const NekDouble > &in, Array< OneD, NekDouble > &out, const AssemblyMapSharedPtr &locToGloMap, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray) override
Solve the linear system for given input and output vectors using a specified local to global map.
void v_SolveLinearSystem(const int pNumRows, const Array< OneD, const NekDouble > &pInput, Array< OneD, NekDouble > &pOutput, const AssemblyMapSharedPtr &locToGloMap, const int pNumDir) override
Solve the matrix system.
LibUtilities::NekLinSysIterSharedPtr m_linsol
void DoProjection(const int pNumRows, const Array< OneD, const NekDouble > &pInput, Array< OneD, NekDouble > &pOutput, const int pNumDir, const bool isAconjugate)
projection technique
bool m_useProjection
Whether to apply projection technique.
Array< OneD, int > m_map
Global to universal unique map.
NekDouble m_rhs_magnitude
dot product of rhs to normalise stopping criterion
std::string m_linSysIterSolver
Iterative solver: Conjugate Gradient, GMRES.
GlobalSysSolnType GetGlobalSysSolnType() const
Return the associated solution type.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
NekLinSysIterFactory & GetNekLinSysIterFactory()
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition Comm.h:55
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition Expansion.h:66
std::shared_ptr< RobinBCInfo > RobinBCInfoSharedPtr
GlobalLinSysFactory & GetGlobalLinSysFactory()
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition AssemblyMap.h:50
static const NekDouble kNekIterativeTol
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition Vmath.hpp:180
void Zero(int n, T *x, const int incx)
Zero vector.
Definition Vmath.hpp:273
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition Vmath.hpp:220
STL namespace.