Nektar++
PreconditionerDiagonal.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File Preconditioner.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: Preconditioner definition
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
39 #include <math.h>
40 
41 using namespace std;
42 
43 namespace Nektar
44 {
45  namespace MultiRegions
46  {
47  /**
48  * Registers the class with the Factory.
49  */
50  string PreconditionerDiagonal::className
52  "Diagonal",
53  PreconditionerDiagonal::create,
54  "Diagonal Preconditioning");
55  /**
56  * @class Preconditioner
57  *
58  * This class implements diagonal preconditioning for the conjugate
59  * gradient matrix solver.
60  */
61 
62  PreconditionerDiagonal::PreconditionerDiagonal(
63  const std::shared_ptr<GlobalLinSys> &plinsys,
64  const AssemblyMapSharedPtr &pLocToGloMap)
65  : Preconditioner(plinsys, pLocToGloMap)
66  {
67  }
68 
70  {
71  }
72 
74  {
75  GlobalSysSolnType solvertype =
76  m_locToGloMap.lock()->GetGlobalSysSolnType();
77  if (solvertype == eIterativeFull)
78  {
80  }
81  else if(solvertype == eIterativeStaticCond ||
82  solvertype == eIterativeMultiLevelStaticCond ||
83  solvertype == ePETScStaticCond ||
84  solvertype == ePETScMultiLevelStaticCond)
85  {
87  }
88  else
89  {
90  ASSERTL0(0,"Unsupported solver type");
91  }
92  }
93 
94  /**
95  * Diagonal preconditioner computed by summing the relevant elements of
96  * the local matrix system.
97  */
99  {
100  std::shared_ptr<MultiRegions::ExpList> expList =
101  ((m_linsys.lock())->GetLocMat()).lock();
102 
104 
105  auto asmMap = m_locToGloMap.lock();
106 
107  int i,j,n,cnt,gid1,gid2;
108  NekDouble sign1,sign2,value;
109  int nGlobal = asmMap->GetNumGlobalCoeffs();
110  int nDir = asmMap->GetNumGlobalDirBndCoeffs();
111  int nInt = nGlobal - nDir;
112 
113  // fill global matrix
114  DNekScalMatSharedPtr loc_mat;
115  Array<OneD, NekDouble> vOutput(nGlobal,0.0);
116 
117  int loc_row;
118  int nElmt = expList->GetNumElmts();
119  for(n = cnt = 0; n < nElmt; ++n)
120  {
121  loc_mat = (m_linsys.lock())->GetBlock(n);
122  loc_row = loc_mat->GetRows();
123 
124  for(i = 0; i < loc_row; ++i)
125  {
126  gid1 = asmMap->GetLocalToGlobalMap(cnt+i)-nDir;
127  sign1 = asmMap->GetLocalToGlobalSign(cnt+i);
128 
129  if(gid1 >= 0)
130  {
131  for(j = 0; j < loc_row; ++j)
132  {
133  gid2 = asmMap->GetLocalToGlobalMap(cnt+j)
134  - nDir;
135  sign2 = asmMap->GetLocalToGlobalSign(cnt+j);
136  if(gid2 == gid1)
137  {
138  // When global matrix is symmetric,
139  // only add the value for the upper
140  // triangular part in order to avoid
141  // entries to be entered twice
142  value = vOutput[gid1 + nDir]
143  + sign1*sign2*(*loc_mat)(i,j);
144  vOutput[gid1 + nDir] = value;
145  }
146  }
147  }
148  }
149  cnt += loc_row;
150  }
151 
152  // Assemble diagonal contributions across processes
153  asmMap->UniversalAssemble(vOutput);
154 
156  Vmath::Sdiv(nInt, 1.0, &vOutput[nDir], 1, &m_diagonals[0], 1);
157  }
158 
159  /**
160  * Diagonal preconditioner defined as the inverse of the main
161  * diagonal of the Schur complement
162  *
163  */
165  {
166  auto asmMap = m_locToGloMap.lock();
167 
168  int nGlobalBnd = asmMap->GetNumGlobalBndCoeffs();
169  int nDirBnd = asmMap->GetNumGlobalDirBndCoeffs();
170  int rows = nGlobalBnd - nDirBnd;
171 
172  Array<OneD, NekDouble> vOutput(nGlobalBnd,0.0);
173 
174  // Extract diagonal contributions
176  for (unsigned int i = 0; i < rows; ++i)
177  {
178  vOutput[nDirBnd + i] = diagonals[i];
179  }
180 
181  // Assemble diagonal contributions across processes
182  asmMap->UniversalAssembleBnd(vOutput);
183 
185  Vmath::Sdiv(rows, 1.0, &vOutput[nDirBnd], 1, &m_diagonals[0], 1);
186  }
187 
188  /**
189  *
190  */
192  const Array<OneD, NekDouble>& pInput,
193  Array<OneD, NekDouble>& pOutput)
194  {
195  auto asmMap = m_locToGloMap.lock();
196 
197  GlobalSysSolnType solvertype = asmMap->GetGlobalSysSolnType();
198 
199  int nGlobal = solvertype == eIterativeFull ?
200  asmMap->GetNumGlobalCoeffs() :
201  asmMap->GetNumGlobalBndCoeffs();
202  int nDir = asmMap->GetNumGlobalDirBndCoeffs();
203  int nNonDir = nGlobal-nDir;
204  Vmath::Vmul(nNonDir, &pInput[0], 1, &m_diagonals[0], 1, &pOutput[0], 1);
205  }
206 
209  "Null",
211  "No Preconditioning");
212 
213  /**
214  * @class Null Preconditioner
215  *
216  * This class implements no preconditioning for the conjugate
217  * gradient matrix solver.
218  */
220  const std::shared_ptr<GlobalLinSys> &plinsys,
221  const AssemblyMapSharedPtr &pLocToGloMap)
222  : Preconditioner(plinsys, pLocToGloMap)
223  {
224  }
225 
226  /**
227  *
228  */
230  {
231  }
232 
233  /**
234  *
235  */
237  {
238  }
239 
240  /**
241  *
242  */
244  const Array<OneD, NekDouble>& pInput,
245  Array<OneD, NekDouble>& pOutput)
246  {
247  Vmath::Vcopy(pInput.num_elements(), pInput, 1, pOutput, 1);
248  }
249 
250 
251  }
252 }
253 
254 
255 
256 
257 
258 
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
virtual void v_DoPreconditioner(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
Apply a preconditioner to the conjugate gradient method.
const std::weak_ptr< GlobalLinSys > m_linsys
static PreconditionerSharedPtr create(const std::shared_ptr< GlobalLinSys > &plinsys, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Creates an instance of this class.
virtual void v_DoPreconditioner(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
Apply a preconditioner to the conjugate gradient method.
PreconFactory & GetPreconFactory()
STL namespace.
void Sdiv(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha/y.
Definition: Vmath.cpp:274
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition: AssemblyMap.h:52
Array< OneD, NekDouble > AssembleStaticCondGlobalDiagonals()
Performs global assembly of diagonal entries to global Schur complement matrix.
PreconditionerNull(const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)
double NekDouble
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:65
static std::string className
Name of class.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
std::weak_ptr< AssemblyMap > m_locToGloMap
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.cpp:186