Nektar++
GlobalLinSys.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File GlobalLinSys.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: GlobalLinSys definition
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <boost/core/ignore_unused.hpp>
36 
39 #include <LocalRegions/MatrixKey.h>
40 #include <LocalRegions/Expansion.h>
42 
45 
46 namespace Nektar
47 {
48  namespace MultiRegions
49  {
50  std::string GlobalLinSys::lookupIds[12] = {
52  "GlobalSysSoln", "DirectFull",
55  "GlobalSysSoln", "DirectStaticCond",
58  "GlobalSysSoln", "DirectMultiLevelStaticCond",
61  "GlobalSysSoln", "IterativeFull",
64  "GlobalSysSoln", "IterativeStaticCond",
67  "GlobalSysSoln", "IterativeMultiLevelStaticCond",
70  "GlobalSysSoln", "XxtFull",
73  "GlobalSysSoln", "XxtStaticCond",
76  "GlobalSysSoln", "XxtMultiLevelStaticCond",
79  "GlobalSysSoln", "PETScFull",
82  "GlobalSysSoln", "PETScStaticCond",
85  "GlobalSysSoln", "PETScMultiLevelStaticCond",
87  };
88 
89 #ifdef NEKTAR_USE_SCOTCH
91  RegisterDefaultSolverInfo("GlobalSysSoln",
92  "DirectMultiLevelStaticCond");
93 #else
95  RegisterDefaultSolverInfo("GlobalSysSoln",
96  "DirectStaticCond");
97 #endif
98 
99  /**
100  * @class GlobalLinSys
101  *
102  * Consider the linear system
103  * \f$\boldsymbol{M\hat{u}}_g=\boldsymbol{\hat{f}}\f$.
104  * Distinguishing between the boundary and interior components of
105  * \f$\boldsymbol{\hat{u}}_g\f$ and \f$\boldsymbol{\hat{f}}\f$ using
106  * \f$\boldsymbol{\hat{u}}_b\f$,\f$\boldsymbol{\hat{u}}_i\f$ and
107  * \f$\boldsymbol{\hat{f}}_b\f$,\f$\boldsymbol{\hat{f}}_i\f$
108  * respectively, this system can be split into its constituent parts as
109  * \f[\left[\begin{array}{cc}
110  * \boldsymbol{M}_b&\boldsymbol{M}_{c1}\\
111  * \boldsymbol{M}_{c2}&\boldsymbol{M}_i\\
112  * \end{array}\right]
113  * \left[\begin{array}{c}
114  * \boldsymbol{\hat{u}_b}\\
115  * \boldsymbol{\hat{u}_i}\\
116  * \end{array}\right]=
117  * \left[\begin{array}{c}
118  * \boldsymbol{\hat{f}_b}\\
119  * \boldsymbol{\hat{f}_i}\\
120  * \end{array}\right]\f]
121  * where \f$\boldsymbol{M}_b\f$ represents the components of
122  * \f$\boldsymbol{M}\f$ resulting from boundary-boundary mode
123  * interactions,
124  * \f$\boldsymbol{M}_{c1}\f$ and \f$\boldsymbol{M}_{c2}\f$ represent the
125  * components resulting from coupling between the boundary-interior
126  * modes, and \f$\boldsymbol{M}_i\f$ represents the components of
127  * \f$\boldsymbol{M}\f$ resulting from interior-interior mode
128  * interactions.
129  *
130  * The solution of the linear system can now be determined in two steps:
131  * \f{eqnarray*}
132  * \mathrm{step 1:}&\quad&(\boldsymbol{M}_b-\boldsymbol{M}_{c1}
133  * \boldsymbol{M}_i^{-1}\boldsymbol{M}_{c2}) \boldsymbol{\hat{u}_b} =
134  * \boldsymbol{\hat{f}}_b - \boldsymbol{M}_{c1}\boldsymbol{M}_i^{-1}
135  * \boldsymbol{\hat{f}}_i,\nonumber \\
136  * \mathrm{step 2:}&\quad&\boldsymbol{\hat{u}_i}=\boldsymbol{M}_i^{-1}
137  * \left( \boldsymbol{\hat{f}}_i
138  * - \boldsymbol{M}_{c2}\boldsymbol{\hat{u}_b}
139  * \right). \nonumber \\ \f}
140  * As the inverse of \f$\boldsymbol{M}_i^{-1}\f$ is
141  * \f[ \boldsymbol{M}_i^{-1} = \left [\underline{\boldsymbol{M}^e_i}
142  * \right ]^{-1} = \underline{[\boldsymbol{M}^e_i]}^{-1} \f]
143  * and the following operations can be evaluated as,
144  * \f{eqnarray*}
145  * \boldsymbol{M}_{c1}\boldsymbol{M}_i^{-1}\boldsymbol{\hat{f}}_i &
146  * =& \boldsymbol{\mathcal{A}}_b^T \underline{\boldsymbol{M}^e_{c1}}
147  * \underline{[\boldsymbol{M}^e_i]}^{-1} \boldsymbol{\hat{f}}_i \\
148  * \boldsymbol{M}_{c2} \boldsymbol{\hat{u}_b} &=&
149  * \underline{\boldsymbol{M}^e_{c2}} \boldsymbol{\mathcal{A}}_b
150  * \boldsymbol{\hat{u}_b}.\f}
151  * where \f$\boldsymbol{\mathcal{A}}_b \f$ is the permutation matrix
152  * which scatters from global to local degrees of freedom, only the
153  * following four matrices should be constructed:
154  * - \f$\underline{[\boldsymbol{M}^e_i]}^{-1}\f$
155  * - \f$\underline{\boldsymbol{M}^e_{c1}}
156  * \underline{[\boldsymbol{M}^e_i]}^{-1}\f$
157  * - \f$\underline{\boldsymbol{M}^e_{c2}}\f$
158  * - The Schur complement: \f$\boldsymbol{M}_{\mathrm{Schur}}=
159  * \quad\boldsymbol{M}_b-\boldsymbol{M}_{c1}\boldsymbol{M}_i^{-1}
160  * \boldsymbol{M}_{c2}\f$
161  *
162  * The first three matrices are just a concatenation of the
163  * corresponding local matrices and they can be created as such. They
164  * also allow for an elemental evaluation of the operations concerned.
165  *
166  * The global Schur complement however should be assembled from the
167  * concatenation of the local elemental Schur complements, that is,
168  * \f[ \boldsymbol{M}_{\mathrm{Schur}}=\boldsymbol{M}_b
169  * - \boldsymbol{M}_{c1}
170  * \boldsymbol{M}_i^{-1} \boldsymbol{M}_{c2} =
171  * \boldsymbol{\mathcal{A}}_b^T \left [\underline{\boldsymbol{M}^e_b -
172  * \boldsymbol{M}^e_{c1} [\boldsymbol{M}^e_i]^{-1}
173  * (\boldsymbol{M}^e_{c2})} \right ] \boldsymbol{\mathcal{A}}_b \f]
174  * and it is the only matrix operation that need to be evaluated on a
175  * global level when using static condensation.
176  * However, due to the size and sparsity of the matrix
177  * \f$\boldsymbol{\mathcal{A}}_b\f$, it is more efficient to assemble
178  * the global Schur matrix using the mapping array bmap\f$[e][i]\f$
179  * contained in the input argument \a locToGloMap. The global Schur
180  * complement is then constructed as:
181  * \f[\boldsymbol{M}_{\mathrm{Schur}}\left[\mathrm{\a bmap}[e][i]\right]
182  * \left[\mathrm{\a bmap}[e][j]\right]=\mathrm{\a bsign}[e][i]\cdot
183  * \mathrm{\a bsign}[e][j]
184  * \cdot\boldsymbol{M}^e_{\mathrm{Schur}}[i][j]\f]
185  * All four matrices are stored in the \a GlobalLinSys returned by this
186  * function.
187  */
188 
189  /**
190  * Given a block matrix, construct a global matrix system according to
191  * a local to global mapping. #m_linSys is constructed by
192  * AssembleFullMatrix().
193  * @param pkey Associated linear system key.
194  * @param locToGloMap Local to global mapping.
195  */
197  const std::weak_ptr<ExpList> &pExpList,
198  const std::shared_ptr<AssemblyMap>
199  &pLocToGloMap):
200  m_linSysKey(pKey),
201  m_expList(pExpList),
202  m_robinBCInfo(m_expList.lock()->GetRobinBCInfo()),
203  m_verbose(m_expList.lock()->GetSession()->
204  DefinesCmdLineArgument("verbose"))
205  {
206  boost::ignore_unused(pLocToGloMap);
207  }
208 
209  /**
210  *
211  */
213  {
214  static GlobalLinSysFactory instance;
215  return instance;
216  }
217 
218  /**
219  * @brief Create a preconditioner object from the parameters defined in
220  * the supplied assembly map.
221  *
222  * @param asmMap Assembly map used to construct the global system.
223  */
225  asmMap)
226  {
227  PreconditionerType pType = asmMap->GetPreconType();
228  std::string PreconType = MultiRegions::PreconditionerTypeMap[pType];
230  PreconType, GetSharedThisPtr(), asmMap);
231  }
232 
233 
234  /**
235  * @brief Get the number of blocks in this system.
236  *
237  * At the top level this corresponds to the number of elements in the
238  * expansion list.
239  */
241  {
242  return m_expList.lock()->GetExpSize();
243  }
244 
245 
246  /**
247  Assemble the matrix key for each block n
248  **/
249 
251  {
252 
253  std::shared_ptr<MultiRegions::ExpList> expList = m_expList.lock();
254  int cnt = 0;
255 
256  LocalRegions::ExpansionSharedPtr vExp = expList->GetExp( n );
257 
258  // need to be initialised with zero size for non variable
259  // coefficient case
260  StdRegions::VarCoeffMap vVarCoeffMap;
261 
262  StdRegions::ConstFactorMap vConstFactorMap =
264 
265  // setup variable factors
266  if(m_linSysKey.GetNVarFactors() > 0)
267  {
270  {
271  vConstFactorMap[StdRegions::eFactorSVVDiffCoeff] =
274 
277  "VarCoeffSVVCuroffRatio is set but "
278  " not FactorSVVCutoffRatio");
279 
280  vConstFactorMap[StdRegions::eFactorSVVCutoffRatio] =
283 
284  }
285 
288  {
289  vConstFactorMap[StdRegions::eFactorSVVPowerKerDiffCoeff] =
292  }
293 
296  {
297  vConstFactorMap[StdRegions::eFactorSVVDGKerDiffCoeff] =
300  }
301  }
302 
303  // retrieve variable coefficients
304  if(m_linSysKey.GetNVarCoeffs() > 0)
305  {
306  cnt = expList->GetPhys_Offset(n);
307 
308  for (auto &x : m_linSysKey.GetVarCoeffs())
309  {
310  vVarCoeffMap[x.first] = x.second + cnt;
311  }
312  }
313 
314 
316  vExp->DetShapeType(),
317  *vExp,
318  vConstFactorMap,
319  vVarCoeffMap);
320  return matkey;
321  }
322 
323  /**
324  * @brief Retrieves the block matrix from n-th expansion using the
325  * matrix key provided by the #m_linSysKey.
326  *
327  * @param n Number of the expansion.
328  * @return Block matrix for the specified expansion.
329  */
331  {
332  LocalRegions::ExpansionSharedPtr vExp = m_expList.lock()->GetExp( n );
333  DNekScalMatSharedPtr loc_mat;
334  loc_mat = vExp->GetLocMatrix(GetBlockMatrixKey(n));
335 
336  // apply robin boundary conditions to the matrix.
337  if(m_robinBCInfo.count(n) != 0) // add robin mass matrix
338  {
340 
341  // declare local matrix from scaled matrix.
342  int rows = loc_mat->GetRows();
343  int cols = loc_mat->GetColumns();
344  const NekDouble *dat = loc_mat->GetRawPtr();
346  AllocateSharedPtr(rows,cols,dat);
347  Blas::Dscal(rows*cols,loc_mat->Scale(),new_mat->GetRawPtr(),1);
348 
349  // add local matrix contribution
350  for(rBC = m_robinBCInfo.find(n)->second;rBC; rBC = rBC->next)
351  {
352  vExp->AddRobinMassMatrix(
353  rBC->m_robinID, rBC->m_robinPrimitiveCoeffs, new_mat);
354  }
355 
356  // redeclare loc_mat to point to new_mat plus the scalar.
358  1.0, new_mat);
359  }
360 
361  // finally return the matrix.
362  return loc_mat;
363  }
364 
365  /**
366  * @brief Retrieves a the static condensation block matrices from n-th
367  * expansion using the matrix key provided by the #m_linSysKey.
368  *
369  * @param n Number of the expansion
370  * @return 2x2 Block matrix holding the static condensation
371  * matrices for the n-th expansion.
372  */
374  unsigned int n)
375  {
376 
377  LocalRegions::ExpansionSharedPtr vExp = m_expList.lock()->GetExp( n );
378  DNekScalBlkMatSharedPtr loc_mat;
379  loc_mat = vExp->GetLocStaticCondMatrix(GetBlockMatrixKey(n));
380 
381  if(m_robinBCInfo.count(n) != 0) // add robin mass matrix
382  {
383  DNekScalMatSharedPtr tmp_mat;
385 
386  tmp_mat = loc_mat->GetBlock(0,0);
387 
388  // declare local matrix from scaled matrix.
389  int rows = tmp_mat->GetRows();
390  int cols = tmp_mat->GetColumns();
391  const NekDouble *dat = tmp_mat->GetRawPtr();
393  AllocateSharedPtr(rows, cols, dat);
394  Blas::Dscal(rows*cols,tmp_mat->Scale(),new_mat->GetRawPtr(),1);
395 
396  // add local matrix contribution
397  for(rBC = m_robinBCInfo.find(n)->second;rBC; rBC = rBC->next)
398  {
399  vExp->AddRobinMassMatrix(
400  rBC->m_robinID, rBC->m_robinPrimitiveCoeffs, new_mat);
401  }
402 
403  // redeclare loc_mat to point to new_mat plus the scalar.
405  1.0, new_mat);
406  DNekScalBlkMatSharedPtr new_loc_mat;
407  unsigned int exp_size[] = {tmp_mat->GetRows(), loc_mat->GetBlock(1,1)->GetRows()};
408  unsigned int nblks = 2;
409  new_loc_mat = MemoryManager<DNekScalBlkMat>::AllocateSharedPtr(nblks, nblks, exp_size, exp_size);
410 
411 
412  new_loc_mat->SetBlock(0,0,tmp_mat);
413  new_loc_mat->SetBlock(0,1,loc_mat->GetBlock(0,1));
414  new_loc_mat->SetBlock(1,0,loc_mat->GetBlock(1,0));
415  new_loc_mat->SetBlock(1,1,loc_mat->GetBlock(1,1));
416  loc_mat = new_loc_mat;
417  }
418 
419  return loc_mat;
420  }
421 
422  /**
423  * @brief Releases the static condensation block matrices from NekManager
424  * of n-th expansion using the matrix key provided by the #m_linSysKey.
425  *
426  * @param n Number of the expansion
427  */
429  {
430  LocalRegions::ExpansionSharedPtr vExp = m_expList.lock()->GetExp( n );
431  vExp->DropLocStaticCondMatrix(GetBlockMatrixKey(n));
432  }
433 
435  {
436  NEKERROR(ErrorUtil::efatal, "Method does not exist" );
437  }
438 
440  const std::shared_ptr<AssemblyMap>& pLocToGloMap)
441  {
442  boost::ignore_unused(pLocToGloMap);
443  NEKERROR(ErrorUtil::efatal, "Method does not exist" );
444  }
445  } //end of namespace
446 } //end of namespace
447 
#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:250
Provides a generic Factory class.
Definition: NekFactory.hpp:105
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:145
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.
virtual int v_GetNumBlocks()
Get the number of blocks in this system.
const std::weak_ptr< ExpList > m_expList
Local Matrix System.
Definition: GlobalLinSys.h:127
static std::string lookupIds[]
Definition: GlobalLinSys.h:163
std::shared_ptr< GlobalLinSys > GetSharedThisPtr()
Returns a shared pointer to the current object.
Definition: GlobalLinSys.h:105
LocalRegions::MatrixKey GetBlockMatrixKey(unsigned int n)
const std::map< int, RobinBCInfoSharedPtr > m_robinBCInfo
Robin boundary info.
Definition: GlobalLinSys.h:129
GlobalLinSys(const GlobalLinSysKey &pKey, const std::weak_ptr< ExpList > &pExpList, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Constructor for full direct matrix solve.
const GlobalLinSysKey m_linSysKey
Key associated with this linear system.
Definition: GlobalLinSys.h:125
virtual DNekScalMatSharedPtr v_GetBlock(unsigned int n)
Retrieves the block matrix from n-th expansion using the matrix key provided by the m_linSysKey.
PreconditionerSharedPtr CreatePrecon(AssemblyMapSharedPtr asmMap)
Create a preconditioner object from the parameters defined in the supplied assembly map.
virtual DNekScalBlkMatSharedPtr v_GetStaticCondBlock(unsigned int n)
Retrieves a the static condensation block matrices from n-th expansion using the matrix key provided ...
virtual void v_Initialise(const std::shared_ptr< AssemblyMap > &pLocToGloMap)
virtual void v_DropStaticCondBlock(unsigned int n)
Releases the static condensation block matrices from NekManager of n-th expansion using the matrix ke...
const Array< OneD, const NekDouble > & GetVarFactors(const StdRegions::ConstFactorType &coeff) const
const StdRegions::ConstFactorMap & GetConstFactors() const
Returns all the constants.
const StdRegions::VarCoeffMap & GetVarCoeffs() const
StdRegions::MatrixType GetMatrixType() const
Return the matrix type.
static void Dscal(const int &n, const double &alpha, double *x, const int &incx)
BLAS level 1: x = alpha x.
Definition: Blas.hpp:182
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
const char *const PreconditionerTypeMap[]
std::shared_ptr< RobinBCInfo > RobinBCInfoSharedPtr
GlobalLinSysFactory & GetGlobalLinSysFactory()
std::shared_ptr< Preconditioner > PreconditionerSharedPtr
Definition: GlobalLinSys.h:60
PreconFactory & GetPreconFactory()
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition: AssemblyMap.h:52
std::map< StdRegions::VarCoeffType, Array< OneD, NekDouble > > VarCoeffMap
Definition: StdRegions.hpp:272
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:314
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:73
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
double NekDouble