Nektar++
Loading...
Searching...
No Matches
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
41
44
46{
47std::string GlobalLinSys::lookupIds[12] = {
49 "GlobalSysSoln", "DirectFull", MultiRegions::eDirectFullMatrix),
51 "GlobalSysSoln", "DirectStaticCond", MultiRegions::eDirectStaticCond),
53 "GlobalSysSoln", "DirectMultiLevelStaticCond",
56 "GlobalSysSoln", "IterativeFull", MultiRegions::eIterativeFull),
58 "GlobalSysSoln", "IterativeStaticCond",
61 "GlobalSysSoln", "IterativeMultiLevelStaticCond",
64 "GlobalSysSoln", "XxtFull", MultiRegions::eXxtFullMatrix),
66 "GlobalSysSoln", "XxtStaticCond", MultiRegions::eXxtStaticCond),
68 "GlobalSysSoln", "XxtMultiLevelStaticCond",
71 "GlobalSysSoln", "PETScFull", MultiRegions::ePETScFullMatrix),
73 "GlobalSysSoln", "PETScStaticCond", MultiRegions::ePETScStaticCond),
75 "GlobalSysSoln", "PETScMultiLevelStaticCond",
77
78#ifdef NEKTAR_USE_SCOTCH
79std::string GlobalLinSys::def =
81 "GlobalSysSoln", "DirectMultiLevelStaticCond");
82#else
83std::string GlobalLinSys::def =
85 "DirectStaticCond");
86#endif
87
88/**
89 *
90 */
92{
93 static GlobalLinSysFactory instance;
94 return instance;
95}
96
97/**
98 * @class GlobalLinSys
99 *
100 * Consider the linear system
101 * \f$\boldsymbol{M\hat{u}}_g=\boldsymbol{\hat{f}}\f$.
102 * Distinguishing between the boundary and interior components of
103 * \f$\boldsymbol{\hat{u}}_g\f$ and \f$\boldsymbol{\hat{f}}\f$ using
104 * \f$\boldsymbol{\hat{u}}_b\f$,\f$\boldsymbol{\hat{u}}_i\f$ and
105 * \f$\boldsymbol{\hat{f}}_b\f$,\f$\boldsymbol{\hat{f}}_i\f$
106 * respectively, this system can be split into its constituent parts as
107 * \f[\left[\begin{array}{cc}
108 * \boldsymbol{M}_b&\boldsymbol{M}_{c1}\\
109 * \boldsymbol{M}_{c2}&\boldsymbol{M}_i\\
110 * \end{array}\right]
111 * \left[\begin{array}{c}
112 * \boldsymbol{\hat{u}_b}\\
113 * \boldsymbol{\hat{u}_i}\\
114 * \end{array}\right]=
115 * \left[\begin{array}{c}
116 * \boldsymbol{\hat{f}_b}\\
117 * \boldsymbol{\hat{f}_i}\\
118 * \end{array}\right]\f]
119 * where \f$\boldsymbol{M}_b\f$ represents the components of
120 * \f$\boldsymbol{M}\f$ resulting from boundary-boundary mode
121 * interactions,
122 * \f$\boldsymbol{M}_{c1}\f$ and \f$\boldsymbol{M}_{c2}\f$ represent the
123 * components resulting from coupling between the boundary-interior
124 * modes, and \f$\boldsymbol{M}_i\f$ represents the components of
125 * \f$\boldsymbol{M}\f$ resulting from interior-interior mode
126 * interactions.
127 *
128 * The solution of the linear system can now be determined in two steps:
129 * \f{eqnarray*}
130 * \mathrm{step 1:}&\quad&(\boldsymbol{M}_b-\boldsymbol{M}_{c1}
131 * \boldsymbol{M}_i^{-1}\boldsymbol{M}_{c2}) \boldsymbol{\hat{u}_b} =
132 * \boldsymbol{\hat{f}}_b - \boldsymbol{M}_{c1}\boldsymbol{M}_i^{-1}
133 * \boldsymbol{\hat{f}}_i,\nonumber \\
134 * \mathrm{step 2:}&\quad&\boldsymbol{\hat{u}_i}=\boldsymbol{M}_i^{-1}
135 * \left( \boldsymbol{\hat{f}}_i
136 * - \boldsymbol{M}_{c2}\boldsymbol{\hat{u}_b}
137 * \right). \nonumber \\ \f}
138 * As the inverse of \f$\boldsymbol{M}_i^{-1}\f$ is
139 * \f[ \boldsymbol{M}_i^{-1} = \left [\underline{\boldsymbol{M}^e_i}
140 * \right ]^{-1} = \underline{[\boldsymbol{M}^e_i]}^{-1} \f]
141 * and the following operations can be evaluated as,
142 * \f{eqnarray*}
143 * \boldsymbol{M}_{c1}\boldsymbol{M}_i^{-1}\boldsymbol{\hat{f}}_i &
144 * =& \boldsymbol{\mathcal{A}}_b^T \underline{\boldsymbol{M}^e_{c1}}
145 * \underline{[\boldsymbol{M}^e_i]}^{-1} \boldsymbol{\hat{f}}_i \\
146 * \boldsymbol{M}_{c2} \boldsymbol{\hat{u}_b} &=&
147 * \underline{\boldsymbol{M}^e_{c2}} \boldsymbol{\mathcal{A}}_b
148 * \boldsymbol{\hat{u}_b}.\f}
149 * where \f$\boldsymbol{\mathcal{A}}_b \f$ is the permutation matrix
150 * which scatters from global to local degrees of freedom, only the
151 * following four matrices should be constructed:
152 * - \f$\underline{[\boldsymbol{M}^e_i]}^{-1}\f$
153 * - \f$\underline{\boldsymbol{M}^e_{c1}}
154 * \underline{[\boldsymbol{M}^e_i]}^{-1}\f$
155 * - \f$\underline{\boldsymbol{M}^e_{c2}}\f$
156 * - The Schur complement: \f$\boldsymbol{M}_{\mathrm{Schur}}=
157 * \quad\boldsymbol{M}_b-\boldsymbol{M}_{c1}\boldsymbol{M}_i^{-1}
158 * \boldsymbol{M}_{c2}\f$
159 *
160 * The first three matrices are just a concatenation of the
161 * corresponding local matrices and they can be created as such. They
162 * also allow for an elemental evaluation of the operations concerned.
163 *
164 * The global Schur complement however should be assembled from the
165 * concatenation of the local elemental Schur complements, that is,
166 * \f[ \boldsymbol{M}_{\mathrm{Schur}}=\boldsymbol{M}_b
167 * - \boldsymbol{M}_{c1}
168 * \boldsymbol{M}_i^{-1} \boldsymbol{M}_{c2} =
169 * \boldsymbol{\mathcal{A}}_b^T \left [\underline{\boldsymbol{M}^e_b -
170 * \boldsymbol{M}^e_{c1} [\boldsymbol{M}^e_i]^{-1}
171 * (\boldsymbol{M}^e_{c2})} \right ] \boldsymbol{\mathcal{A}}_b \f]
172 * and it is the only matrix operation that need to be evaluated on a
173 * global level when using static condensation.
174 * However, due to the size and sparsity of the matrix
175 * \f$\boldsymbol{\mathcal{A}}_b\f$, it is more efficient to assemble
176 * the global Schur matrix using the mapping array bmap\f$[e][i]\f$
177 * contained in the input argument \a locToGloMap. The global Schur
178 * complement is then constructed as:
179 * \f[\boldsymbol{M}_{\mathrm{Schur}}\left[\mathrm{\a bmap}[e][i]\right]
180 * \left[\mathrm{\a bmap}[e][j]\right]=\mathrm{\a bsign}[e][i]\cdot
181 * \mathrm{\a bsign}[e][j]
182 * \cdot\boldsymbol{M}^e_{\mathrm{Schur}}[i][j]\f]
183 * All four matrices are stored in the \a GlobalLinSys returned by this
184 * function.
185 */
186
187/**
188 * Given a block matrix, construct a global matrix system according to
189 * a local to global mapping. #m_linSys is constructed by
190 * AssembleFullMatrix().
191 * @param pkey Associated linear system key.
192 * @param locToGloMap Local to global mapping.
193 */
195 const GlobalLinSysKey &pKey, const std::weak_ptr<ExpList> &pExpList,
196 [[maybe_unused]] const std::shared_ptr<AssemblyMap> &pLocToGloMap)
197 : m_linSysKey(pKey), m_expList(pExpList),
198 m_robinBCInfo(m_expList.lock()->GetRobinBCInfo()),
199 m_verbose(
200 m_expList.lock()->GetSession()->DefinesCmdLineArgument("verbose"))
201{
202}
203
204/**
205 * @brief Create a preconditioner object from the parameters defined in
206 * the supplied assembly map.
207 *
208 * @param asmMap Assembly map used to construct the global system.
209 */
211{
212 std::string PreconType = asmMap->GetPreconType();
213 return GetPreconFactory().CreateInstance(PreconType, GetSharedThisPtr(),
214 asmMap);
215}
216
217/**
218 * @brief Get the number of blocks in this system.
219 *
220 * At the top level this corresponds to the number of elements in the
221 * expansion list.
222 */
224{
225 return m_expList.lock()->GetExpSize();
226}
227
228/**
229 Assemble the matrix key for each block n
230**/
231
233{
234
235 std::shared_ptr<MultiRegions::ExpList> expList = m_expList.lock();
236
237 LocalRegions::ExpansionSharedPtr vExp = expList->GetExp(n);
238
239 // need to be initialised with zero size for non variable
240 // coefficient case
241 StdRegions::VarCoeffMap vVarCoeffMap;
242 StdRegions::VarFactorsMap vVarFactorsMap;
244
245 // setup variable factors
246 if (m_linSysKey.GetNVarFactors() > 0)
247 {
248 if (m_linSysKey.GetVarFactors().count(
250 {
251 vConstFactorMap[StdRegions::eFactorSVVDiffCoeff] =
253
256 "VarCoeffSVVCuroffRatio is set but "
257 " not FactorSVVCutoffRatio");
258
259 vConstFactorMap[StdRegions::eFactorSVVCutoffRatio] =
261 }
262
263 if (m_linSysKey.GetVarFactors().count(
265 {
269 }
270
271 if (m_linSysKey.GetVarFactors().count(
273 {
274 vConstFactorMap[StdRegions::eFactorSVVDGKerDiffCoeff] =
277 }
278 }
279
280 // retrieve variable coefficients
281 if (m_linSysKey.GetNVarCoeffs() > 0)
282 {
284 expList->GetPhys_Offset(n),
285 vExp->GetTotPoints());
286 }
287
289
290 // replace mtype with GJP version if required - necessary for preconditioner
291 if (vConstFactorMap.count(StdRegions::eFactorGJP) &&
292 expList->GetGJPData()->IsImplicit())
293 {
294
295 switch (mtype)
296 {
299 // do nothing
300 break;
303 break;
306 break;
308 mtype = StdRegions::eMassGJP;
309 break;
310 default:
312 "GJP matrix flag not being set in GlobalLinSys");
313 break;
314 }
315 }
316
317 if (vConstFactorMap.count(StdRegions::eFactorGJP) &&
318 (expList->GetGJPData()->IsSemiImplicit() ||
319 expList->GetGJPData()->IsImplicit()))
320 {
321 vVarFactorsMap[StdRegions::eFactorGJPTraceWeight] =
324 .data() +
325 6 * n);
326 }
327
328 LocalRegions::MatrixKey matkey(mtype, vExp->DetShapeType(), *vExp,
329 vConstFactorMap, vVarCoeffMap,
330 vVarFactorsMap);
331 return matkey;
332}
333
334/**
335 * @brief Retrieves the block matrix from n-th expansion using the
336 * matrix key provided by the #m_linSysKey.
337 *
338 * @param n Number of the expansion.
339 * @return Block matrix for the specified expansion.
340 */
342{
343 LocalRegions::ExpansionSharedPtr vExp = m_expList.lock()->GetExp(n);
344 DNekScalMatSharedPtr loc_mat;
345 loc_mat = vExp->GetLocMatrix(GetBlockMatrixKey(n));
346
347 // apply robin boundary conditions to the matrix.
348 if (m_robinBCInfo.count(n) != 0) // add robin mass matrix
349 {
351
352 // declare local matrix from scaled matrix.
353 int rows = loc_mat->GetRows();
354 int cols = loc_mat->GetColumns();
355 const NekDouble *dat = loc_mat->GetRawPtr();
356 DNekMatSharedPtr new_mat =
358 Blas::Dscal(rows * cols, loc_mat->Scale(), new_mat->GetRawPtr(), 1);
359
360 // add local matrix contribution
361 for (rBC = m_robinBCInfo.find(n)->second; rBC; rBC = rBC->next)
362 {
363 vExp->AddRobinMassMatrix(rBC->m_robinID,
364 rBC->m_robinPrimitiveCoeffs, new_mat);
365 }
366
367 // redeclare loc_mat to point to new_mat plus the scalar.
368 loc_mat = MemoryManager<DNekScalMat>::AllocateSharedPtr(1.0, new_mat);
369 }
370
371 // finally return the matrix.
372 return loc_mat;
373}
374
375/**
376 * @brief Retrieves a the static condensation block matrices from n-th
377 * expansion using the matrix key provided by the #m_linSysKey.
378 *
379 * @param n Number of the expansion
380 * @return 2x2 Block matrix holding the static condensation
381 * matrices for the n-th expansion.
382 */
384{
385
386 LocalRegions::ExpansionSharedPtr vExp = m_expList.lock()->GetExp(n);
388 loc_mat = vExp->GetLocStaticCondMatrix(GetBlockMatrixKey(n));
389
390 if (m_robinBCInfo.count(n) != 0) // add robin mass matrix
391 {
392 DNekScalMatSharedPtr tmp_mat;
394
395 tmp_mat = loc_mat->GetBlock(0, 0);
396
397 // declare local matrix from scaled matrix.
398 int rows = tmp_mat->GetRows();
399 int cols = tmp_mat->GetColumns();
400 const NekDouble *dat = tmp_mat->GetRawPtr();
401 DNekMatSharedPtr new_mat =
403 Blas::Dscal(rows * cols, tmp_mat->Scale(), new_mat->GetRawPtr(), 1);
404
405 // add local matrix contribution
406 for (rBC = m_robinBCInfo.find(n)->second; rBC; rBC = rBC->next)
407 {
408 vExp->AddRobinMassMatrix(rBC->m_robinID,
409 rBC->m_robinPrimitiveCoeffs, new_mat);
410 }
411
412 // redeclare loc_mat to point to new_mat plus the scalar.
413 tmp_mat = MemoryManager<DNekScalMat>::AllocateSharedPtr(1.0, new_mat);
414 DNekScalBlkMatSharedPtr new_loc_mat;
415 unsigned int exp_size[] = {tmp_mat->GetRows(),
416 loc_mat->GetBlock(1, 1)->GetRows()};
417 unsigned int nblks = 2;
419 nblks, nblks, exp_size, exp_size);
420
421 new_loc_mat->SetBlock(0, 0, tmp_mat);
422 new_loc_mat->SetBlock(0, 1, loc_mat->GetBlock(0, 1));
423 new_loc_mat->SetBlock(1, 0, loc_mat->GetBlock(1, 0));
424 new_loc_mat->SetBlock(1, 1, loc_mat->GetBlock(1, 1));
425 loc_mat = new_loc_mat;
426 }
427
428 return loc_mat;
429}
430
431/**
432 * @brief Releases the static condensation block matrices from NekManager
433 * of n-th expansion using the matrix key provided by the #m_linSysKey.
434 *
435 * @param n Number of the expansion
436 */
438{
439 LocalRegions::ExpansionSharedPtr vExp = m_expList.lock()->GetExp(n);
440 vExp->DropLocStaticCondMatrix(GetBlockMatrixKey(n));
441}
442
443/**
444 * @brief Releases the local block matrix from NekManager
445 * of n-th expansion using the matrix key provided by the #m_linSysKey.
446 *
447 * @param n Number of the expansion
448 */
449void GlobalLinSys::v_DropBlock(unsigned int n)
450{
451 LocalRegions::ExpansionSharedPtr vExp = m_expList.lock()->GetExp(n);
452 vExp->DropLocMatrix(GetBlockMatrixKey(n));
453}
454
456{
457 NEKERROR(ErrorUtil::efatal, "Method does not exist");
458}
459
461 [[maybe_unused]] const std::shared_ptr<AssemblyMap> &pLocToGloMap)
462{
463 NEKERROR(ErrorUtil::efatal, "Method does not exist");
464}
465} // namespace Nektar::MultiRegions
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Provides a generic Factory class.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
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.
LocalRegions::MatrixKey GetBlockMatrixKey(unsigned int n)
std::shared_ptr< GlobalLinSys > GetSharedThisPtr()
Returns a shared pointer to the current object.
const std::map< int, RobinBCInfoSharedPtr > m_robinBCInfo
Robin boundary info.
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.
virtual DNekScalMatSharedPtr v_GetBlock(unsigned int n)
Retrieves the block matrix from n-th expansion using the matrix key provided by the m_linSysKey.
virtual void v_DropBlock(unsigned int n)
Releases the local block matrix from NekManager of n-th expansion using the matrix key provided by th...
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:124
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition Expansion.h:66
std::shared_ptr< RobinBCInfo > RobinBCInfoSharedPtr
GlobalLinSysFactory & GetGlobalLinSysFactory()
std::shared_ptr< Preconditioner > PreconditionerSharedPtr
PreconFactory & GetPreconFactory()
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition AssemblyMap.h:50
std::map< StdRegions::ConstFactorType, Array< OneD, NekDouble > > VarFactorsMap
VarCoeffMap RestrictCoeffMap(const VarCoeffMap &m, size_t offset, size_t cnt)
std::map< ConstFactorType, NekDouble > ConstFactorMap
std::map< StdRegions::VarCoeffType, VarCoeffEntry > VarCoeffMap
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
std::shared_ptr< DNekMat > DNekMatSharedPtr