Nektar++
Loading...
Searching...
No Matches
PreconditionerDiagonal.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: PreconditionerDiagonal.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: PreconditionerDiagonal definition
32//
33///////////////////////////////////////////////////////////////////////////////
34
39#include <cmath>
40
41using namespace std;
42
44{
45/**
46 * Registers the class with the Factory.
47 */
50 "Diagonal", PreconditionerDiagonal::create, "Diagonal Preconditioning");
51/**
52 * @class Preconditioner
53 *
54 * This class implements diagonal preconditioning for the conjugate
55 * gradient matrix solver.
56 */
57
59 const std::shared_ptr<GlobalLinSys> &plinsys,
60 const AssemblyMapSharedPtr &pLocToGloMap)
61 : Preconditioner(plinsys, pLocToGloMap)
62{
63}
64
68
70{
71 GlobalSysSolnType solvertype = m_locToGloMap.lock()->GetGlobalSysSolnType();
72 if (solvertype == eIterativeFull)
73 {
75 }
76 else if (solvertype == eIterativeStaticCond ||
77 solvertype == eIterativeMultiLevelStaticCond ||
78 solvertype == ePETScStaticCond ||
79 solvertype == ePETScMultiLevelStaticCond)
80 {
82 }
83 else
84 {
85 ASSERTL0(0, "Unsupported solver type");
86 }
87}
88
89/**
90 * Diagonal preconditioner computed by summing the relevant elements of
91 * the local matrix system.
92 */
94{
95 std::shared_ptr<MultiRegions::ExpList> expList =
96 ((m_linsys.lock())->GetLocMat()).lock();
97
98 auto asmMap = m_locToGloMap.lock();
99 int nGlobal = asmMap->GetNumGlobalCoeffs();
100 int nDir = asmMap->GetNumGlobalDirBndCoeffs();
101 int nInt = nGlobal - nDir;
102 int nElmt = expList->GetNumElmts();
103
104 Array<OneD, NekDouble> vOutput(nGlobal, 0.0);
105 for (int n = 0, cnt = 0; n < nElmt; ++n)
106 {
107 auto loc_mat = (m_linsys.lock())->GetBlock(n);
108 int loc_row = loc_mat->GetRows();
109 for (int i = 0; i < loc_row; ++i)
110 {
111 if (asmMap->GetLocalToGlobalSign(
112 cnt + i)) // check required for variable P
113 {
114 int gid1 = asmMap->GetLocalToGlobalMap(cnt + i);
115 vOutput[gid1] += (*loc_mat)(i, i);
116 }
117 }
118 cnt += loc_row;
119 }
120
121 // Assemble diagonal contributions across processes
122 asmMap->UniversalAssemble(vOutput);
124 Vmath::Sdiv(nInt, 1.0, &vOutput[nDir], 1, &m_diagonals[0], 1);
125}
126
127/**
128 * Diagonal preconditioner defined as the inverse of the main
129 * diagonal of the Schur complement
130 *
131 */
133{
134 auto asmMap = m_locToGloMap.lock();
135
136 int nGlobalBnd = asmMap->GetNumGlobalBndCoeffs();
137 int nDirBnd = asmMap->GetNumGlobalDirBndCoeffs();
138 int rows = nGlobalBnd - nDirBnd;
139
140 Array<OneD, NekDouble> vOutput(nGlobalBnd, 0.0);
141
142 // Extract diagonal contributions
144 for (unsigned int i = 0; i < rows; ++i)
145 {
146 vOutput[nDirBnd + i] = diagonals[i];
147 }
148
149 // Assemble diagonal contributions across processes
150 asmMap->UniversalAssembleBnd(vOutput);
151
153 Vmath::Sdiv(rows, 1.0, &vOutput[nDirBnd], 1, &m_diagonals[0], 1);
154}
155
156/**
157 *
158 */
160 const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput,
161 const bool &IsLocal)
162{
163 auto asmMap = m_locToGloMap.lock();
164
165 GlobalSysSolnType solvertype = asmMap->GetGlobalSysSolnType();
166
167 bool isFull = solvertype == eIterativeFull ? true : false;
168
169 int nGlobal = (isFull) ? asmMap->GetNumGlobalCoeffs()
170 : asmMap->GetNumGlobalBndCoeffs();
171 int nDir = asmMap->GetNumGlobalDirBndCoeffs();
172 int nNonDir = nGlobal - nDir;
173
174 if (IsLocal)
175 {
176 Array<OneD, NekDouble> wk(nGlobal);
177 (isFull) ? asmMap->Assemble(pInput, wk)
178 : asmMap->AssembleBnd(pInput, wk);
179 Vmath::Vmul(nNonDir, wk.data() + nDir, 1, m_diagonals.data(), 1,
180 wk.data() + nDir, 1);
181 Vmath::Zero(nDir, wk, 1);
182 (isFull) ? asmMap->GlobalToLocal(wk, pOutput)
183 : asmMap->GlobalToLocalBnd(wk, pOutput);
184 }
185 else
186 {
187 Vmath::Vmul(nNonDir, &pInput[0], 1, &m_diagonals[0], 1, &pOutput[0], 1);
188 }
189}
190
193 "Null", PreconditionerNull::create, "No Preconditioning");
194
195/**
196 * @class Null Preconditioner
197 *
198 * This class implements no preconditioning for the conjugate
199 * gradient matrix solver.
200 */
202 const std::shared_ptr<GlobalLinSys> &plinsys,
203 const AssemblyMapSharedPtr &pLocToGloMap)
204 : Preconditioner(plinsys, pLocToGloMap)
205{
206}
207
208/**
209 *
210 */
214
215/**
216 *
217 */
221
222/**
223 *
224 */
226 const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput,
227 const bool &isLocal)
228
229{
230 auto asmMap = m_locToGloMap.lock();
231
232 GlobalSysSolnType solvertype = asmMap->GetGlobalSysSolnType();
233
234 bool isFull = solvertype == eIterativeFull ? true : false;
235
236 int nGlobal = (isFull) ? asmMap->GetNumGlobalCoeffs()
237 : asmMap->GetNumGlobalBndCoeffs();
238 int nDir = asmMap->GetNumGlobalDirBndCoeffs();
239
240 if (isLocal)
241 {
242 Array<OneD, NekDouble> wk(nGlobal);
243 (isFull) ? asmMap->Assemble(pInput, wk)
244 : asmMap->AssembleBnd(pInput, wk);
245 Vmath::Zero(nDir, wk, 1);
246 (isFull) ? asmMap->GlobalToLocal(wk, pOutput)
247 : asmMap->GlobalToLocalBnd(wk, pOutput);
248 }
249 else
250 {
251 Vmath::Vcopy(pInput.size(), pInput, 1, pOutput, 1);
252 }
253}
254
255/**
256 * Registers the class with the Factory.
257 */
260 "Jacobi", PreconditionerJacobi::create, "Jacobi Preconditioning");
261/**
262 * @class PreconditionerJacobi
263 *
264 * This class implements jacobi preconditioning building on diagonal version
265 * above
266 */
267
269 const std::shared_ptr<GlobalLinSys> &plinsys,
270 const AssemblyMapSharedPtr &pLocToGloMap)
271 : PreconditionerDiagonal(plinsys, pLocToGloMap)
272{
273}
274
278
280{
282
283 auto expList = ((m_linsys.lock())->GetLocMat()).lock();
284 std::shared_ptr<LibUtilities::SessionReader> session =
285 expList->GetSession();
286
287 std::string var = m_locToGloMap.lock()->GetVariable();
288
289 if (session->DefinesGlobalSysSolnInfo(var, "JacobiIterations"))
290 {
291 m_niter = std::stoi(
292 session->GetGlobalSysSolnInfo(var, "JacobiIterations").c_str());
293 }
294 else
295 {
296 m_niter = 3;
297 }
298}
299
300/**
301 *
302 */
304 const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput,
305 const bool &IsLocal)
306{
307 auto asmMap = m_locToGloMap.lock();
308
309 GlobalSysSolnType solvertype = asmMap->GetGlobalSysSolnType();
310
311 int nGlobal = solvertype == eIterativeFull
312 ? asmMap->GetNumGlobalCoeffs()
313 : asmMap->GetNumGlobalBndCoeffs();
314 int nDir = asmMap->GetNumGlobalDirBndCoeffs();
315 int nNonDir = nGlobal - nDir;
316 Array<OneD, NekDouble> wk(nGlobal);
317
318 if (IsLocal)
319 {
320 int nLocal = solvertype == eIterativeFull
321 ? asmMap->GetNumLocalCoeffs()
322 : asmMap->GetNumLocalBndCoeffs();
323
324 // new sol = 1/diag b
325 Array<OneD, NekDouble> wk1(nLocal);
326 asmMap->Assemble(pInput, wk);
327 Vmath::Vmul(nNonDir, wk.data() + nDir, 1, m_diagonals.data(), 1,
328 wk.data() + nDir, 1);
329 Vmath::Zero(nDir, wk, 1);
330
331 for (int n = 1; n < m_niter; ++n)
332 {
333 asmMap->GlobalToLocal(wk, pOutput);
334
335 // do Ax operator
336 std::dynamic_pointer_cast<GlobalLinSysIterative>(m_linsys.lock())
337 ->DoMatrixMultiply(pOutput, wk1);
338
339 // b - Ax
340 Vmath::Vsub(nLocal, pInput, 1, wk1, 1, wk1, 1);
341
342 asmMap->Assemble(wk1, pOutput);
343 // new sol = 1/diag (b-Ax) + old sol
344 Vmath::Vvtvp(nNonDir, pOutput.data() + nDir, 1, m_diagonals.data(),
345 1, wk.data() + nDir, 1, wk.data() + nDir, 1);
346 }
347
348 asmMap->GlobalToLocal(wk, pOutput);
349 }
350 else
351 {
352 Array<OneD, NekDouble> wk1(nGlobal);
353
354 // x^k = 1/diag b
355 Vmath::Vmul(nNonDir, pInput.data(), 1, m_diagonals.data(), 1,
356 wk.data() + nDir, 1);
357 Vmath::Zero(nDir, wk, 1);
358
359 for (int n = 1; n < m_niter; ++n)
360 {
361 // do Ax^k operator
362 std::dynamic_pointer_cast<GlobalLinSysIterative>(m_linsys.lock())
363 ->DoMatrixMultiply(wk, wk1);
364
365 // b - Ax
366 Vmath::Vsub(nNonDir, pInput.data(), 1, wk1.data() + nDir, 1,
367 wk1.data() + nDir, 1);
368
369 // x^{k+1} = 1/diag (b-Ax^k) + x^k
370 Vmath::Vvtvp(nNonDir, wk1.data() + nDir, 1, m_diagonals.data(), 1,
371 wk.data() + nDir, 1, wk.data() + nDir, 1);
372 }
373
374 Vmath::Vcopy(nNonDir, wk.data() + nDir, 1, pOutput.data(), 1);
375 }
376}
377
378} // namespace Nektar::MultiRegions
#define ASSERTL0(condition, msg)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
static PreconditionerSharedPtr create(const std::shared_ptr< GlobalLinSys > &plinsys, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Creates an instance of this class.
PreconditionerDiagonal(const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)
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.
const std::weak_ptr< GlobalLinSys > m_linsys
Array< OneD, NekDouble > AssembleStaticCondGlobalDiagonals()
Performs global assembly of diagonal entries to global Schur complement matrix.
std::weak_ptr< AssemblyMap > m_locToGloMap
static PreconditionerSharedPtr create(const std::shared_ptr< GlobalLinSys > &plinsys, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Creates an instance of this class.
PreconditionerJacobi(const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)
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.
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.
static std::string className
Name of class.
PreconditionerNull(const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)
static PreconditionerSharedPtr create(const std::shared_ptr< GlobalLinSys > &plinsys, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Creates an instance of this class.
PreconFactory & GetPreconFactory()
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition AssemblyMap.h:50
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition Vmath.hpp:72
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition Vmath.hpp:366
void Sdiv(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha/x.
Definition Vmath.hpp:154
void Zero(int n, T *x, const int incx)
Zero vector.
Definition Vmath.hpp:273
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825
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.