Nektar++
PreconditionerLinear.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: PreconditionerLinear.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: PreconditionerLinear definition
32//
33///////////////////////////////////////////////////////////////////////////////
34
40
41#ifdef NEKTAR_USING_PETSC
43#endif
44
46#include <cmath>
47
48using namespace std;
49
50namespace Nektar
51{
52namespace MultiRegions
53{
54/**
55 * Registers the class with the Factory.
56 */
57
60 "FullLinearSpace", PreconditionerLinear::create,
61 "Full Linear space inverse Preconditioning");
62
65 "Xxt");
68 "LinearPreconSolver", "PETSc", MultiRegions::eLinearPreconPETSc),
70 "LinearPreconSolver", "Xxt", MultiRegions::eLinearPreconXxt)};
71
72/**
73 * @class PreconditionerLinear
74 *
75 * This class implements preconditioning for the conjugate
76 * gradient matrix solver.
77 */
78
80 const std::shared_ptr<GlobalLinSys> &plinsys,
81 const AssemblyMapSharedPtr &pLocToGloMap)
82 : Preconditioner(plinsys, pLocToGloMap)
83{
84}
85
87{
88}
89
91{
92 GlobalSysSolnType sType = m_locToGloMap.lock()->GetGlobalSysSolnType();
94 "This type of preconditioning is not implemented "
95 "for this solver");
96
97 std::shared_ptr<MultiRegions::ExpList> expList =
98 ((m_linsys.lock())->GetLocMat()).lock();
99
101 expList->GetSession()->GetSolverInfoAsEnum<LinearPreconSolver>(
102 "LinearPreconSolver");
103
104 GlobalSysSolnType linSolveType;
105
106 switch (solveType)
107 {
109 {
110 linSolveType = ePETScFullMatrix;
111#ifndef NEKTAR_USING_PETSC
112 NEKERROR(ErrorUtil::efatal, "Nektar++ has not been compiled with "
113 "PETSc support.");
114#endif
115 break;
116 }
117 case eLinearPreconXxt:
118 default:
119 {
120 linSolveType = eXxtFullMatrix;
121 break;
122 }
123 }
124
126 m_locToGloMap.lock()->LinearSpaceMap(*expList, linSolveType);
127
129
130 // Generate linear solve system.
132 m_linsys.lock()->GetKey().GetMatrixType() == StdRegions::eMass
135
136 GlobalLinSysKey preconKey(mType, m_vertLocToGloMap,
137 (m_linsys.lock())->GetKey().GetConstFactors());
138
139 switch (solveType)
140 {
141 case eLinearPreconXxt:
142 {
145 preconKey, expList, m_vertLocToGloMap);
146 break;
147 }
149 {
150#ifdef NEKTAR_USING_PETSC
153 preconKey, expList, m_vertLocToGloMap);
154#else
155 ASSERTL0(false, "Nektar++ has not been compiled with "
156 "PETSc support.");
157#endif
158 }
159 }
160}
161
162/**
163 *
164 */
166 const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput,
167 const bool &isLocal)
168{
169 ASSERTL0(isLocal == false, "PreconditionerLinear is only set up for Global"
170 " iteratives sovles");
173}
174
175/**
176 *
177 */
179 const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput,
180 const Array<OneD, NekDouble> &pNonVertOutput,
181 Array<OneD, NekDouble> &pVertForce)
182{
183 GlobalSysSolnType solvertype = m_locToGloMap.lock()->GetGlobalSysSolnType();
184 switch (solvertype)
185 {
188 {
189 int i, val;
190 int nloc = m_vertLocToGloMap->GetNumLocalCoeffs();
191 // mapping from full space to vertices
192 Array<OneD, int> LocToGloBnd =
193 m_vertLocToGloMap->GetLocalToGlobalBndMap();
194
195 // Global to local for linear solver (different from above)
196 Array<OneD, int> LocToGlo =
197 m_vertLocToGloMap->GetLocalToGlobalMap();
198
199 // number of Dir coeffs in from full problem
200 int nDirFull = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
201
202#if 0
203 int nglo = m_vertLocToGloMap->GetNumGlobalCoeffs();
204 Array<OneD, NekDouble> In(nglo, 0.0);
205 Array<OneD, NekDouble> Out(nglo, 0.0);
206
207 // Gather rhs to local linear space.
208 for (i = 0; i < nloc; ++i)
209 {
210 val = LocToGloBnd[i];
211 if (val >= nDirFull)
212 {
213 In[LocToGlo[i]] = pInput[val - nDirFull];
214 }
215 }
216#else
217 Array<OneD, NekDouble> In(nloc, 0.0);
218 Array<OneD, NekDouble> Out(nloc, 0.0);
219
220 // Gather rhs to local linear space.
221 for (i = 0; i < nloc; ++i)
222 {
223 val = LocToGloBnd[i];
224 if (val >= nDirFull)
225 {
226 In[i] = pInput[val - nDirFull] * m_invMult[i];
227 }
228 }
229#endif
230
231 // Do solve without enforcing any boundary conditions.
232 m_vertLinsys->SolveLinearSystem(
233 m_vertLocToGloMap->GetNumGlobalCoeffs(), In, Out,
235 m_vertLocToGloMap->GetNumGlobalDirBndCoeffs());
236
237 if (pNonVertOutput != NullNekDouble1DArray)
238 {
239 ASSERTL1(pNonVertOutput.size() >= pOutput.size(),
240 "Non Vert output is not of sufficient length");
241 Vmath::Vcopy(pOutput.size(), pNonVertOutput, 1, pOutput, 1);
242 }
243 else
244 {
245 // Copy input to output as a unit preconditioner on
246 // any other value
247 Vmath::Vcopy(pInput.size(), pInput, 1, pOutput, 1);
248 }
249
250#if 0
251 if (pVertForce != NullNekDouble1DArray)
252 {
253 Vmath::Zero(pVertForce.size(), pVertForce, 1);
254 // Scatter back soln from linear solve
255 for (i = 0; i < nloc; ++i)
256 {
257 val = LocToGloBnd[i];
258 if (val >= nDirFull)
259 {
260 pOutput[val - nDirFull] = Out[LocToGlo[i]];
261 // copy vertex forcing into this vector
262 pVertForce[val - nDirFull] = In[LocToGlo[i]];
263 }
264 }
265 }
266 else
267 {
268 // Scatter back soln from linear solve
269 for (i = 0; i < nloc; ++i)
270 {
271 val = LocToGloBnd[i];
272 if (val >= nDirFull)
273 {
274 pOutput[val - nDirFull] = Out[LocToGlo[i]];
275 }
276 }
277 }
278#else
279 if (pVertForce != NullNekDouble1DArray)
280 {
281 Vmath::Zero(pVertForce.size(), pVertForce, 1);
282 // Scatter back soln from linear solve
283 for (i = 0; i < nloc; ++i)
284 {
285 val = LocToGloBnd[i];
286 if (val >= nDirFull)
287 {
288 pOutput[val - nDirFull] = Out[i];
289 // copy vertex forcing into this vector
290 pVertForce[val - nDirFull] = In[i];
291 }
292 }
293 }
294 else
295 {
296 // Scatter back soln from linear solve
297 for (i = 0; i < nloc; ++i)
298 {
299 val = LocToGloBnd[i];
300 if (val >= nDirFull)
301 {
302 pOutput[val - nDirFull] = Out[i];
303 }
304 }
305 }
306#endif
307 }
308 break;
309 default:
310 ASSERTL0(0, "Unsupported solver type");
311 break;
312 }
313}
314/**
315 * Create the inverse multiplicity map.
316 * @param locToGloMap Local to global mapping information.
317 */
319 const std::shared_ptr<AssemblyMap> &pLocToGloMap)
320{
321 const Array<OneD, const int> &vMap = pLocToGloMap->GetLocalToGlobalMap();
322 unsigned int nGlo = pLocToGloMap->GetNumGlobalCoeffs();
323 unsigned int nEntries = pLocToGloMap->GetNumLocalCoeffs();
324 unsigned int i;
325
326 // Count the multiplicity of each global DOF on this process
327 Array<OneD, NekDouble> vCounts(nGlo, 0.0);
328 for (i = 0; i < nEntries; ++i)
329 {
330 vCounts[vMap[i]] += 1.0;
331 }
332
333 // Get universal multiplicity by globally assembling counts
334 pLocToGloMap->UniversalAssemble(vCounts);
335
336 // Construct a map of 1/multiplicity for use in XXT solve
338 for (i = 0; i < nEntries; ++i)
339 {
340 m_invMult[i] = 1.0 / vCounts[vMap[i]];
341 }
342}
343} // namespace MultiRegions
344} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
static std::string RegisterEnumValue(std::string pEnum, std::string pString, int pEnumValue)
Registers an enumeration value.
static std::string RegisterDefaultSolverInfo(const std::string &pName, const std::string &pValue)
Registers the default string value of a solver info property.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
const std::weak_ptr< GlobalLinSys > m_linsys
std::weak_ptr< AssemblyMap > m_locToGloMap
virtual void v_DoPreconditioner(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput, const bool &isLocal=false) override
Apply a preconditioner to the conjugate gradient method.
PreconditionerLinear(const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)
void SetupInvMult(const std::shared_ptr< AssemblyMap > &pLocToGloMap)
static PreconditionerSharedPtr create(const std::shared_ptr< GlobalLinSys > &plinsys, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Creates an instance of this class.
std::shared_ptr< AssemblyMap > m_vertLocToGloMap
static std::string className1
Name of class.
virtual void v_DoPreconditionerWithNonVertOutput(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput, const Array< OneD, NekDouble > &pNonVertOutput, Array< OneD, NekDouble > &pVertForce) override
Apply a preconditioner to the conjugate gradient method with an output for non-vertex degrees of free...
PreconFactory & GetPreconFactory()
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition: AssemblyMap.h:52
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
static Array< OneD, NekDouble > NullNekDouble1DArray
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:487
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1191