Nektar++
GlobalLinSysStaticCond.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: GlobalLinSysStaticCond.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: Implementation to linear solver using single-
32 // or multi-level static condensation
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
41 
42 using namespace std;
43 
44 namespace Nektar
45 {
46 namespace MultiRegions
47 {
48 /**
49  * @class GlobalLinSysStaticCond
50  *
51  * Solves a linear system using single- or multi-level static
52  * condensation.
53  */
54 
55 /**
56  * For a matrix system of the form @f[
57  * \left[ \begin{array}{cc}
58  * \boldsymbol{A} & \boldsymbol{B}\\
59  * \boldsymbol{C} & \boldsymbol{D}
60  * \end{array} \right]
61  * \left[ \begin{array}{c} \boldsymbol{x_1}\\ \boldsymbol{x_2}
62  * \end{array}\right]
63  * = \left[ \begin{array}{c} \boldsymbol{y_1}\\ \boldsymbol{y_2}
64  * \end{array}\right],
65  * @f]
66  * where @f$\boldsymbol{D}@f$ and
67  * @f$(\boldsymbol{A-BD^{-1}C})@f$ are invertible, store and assemble
68  * a static condensation system, according to a given local to global
69  * mapping. #m_linSys is constructed by AssembleSchurComplement().
70  * @param mKey Associated matrix key.
71  * @param pLocMatSys LocalMatrixSystem
72  * @param locToGloMap Local to global mapping.
73  */
74 GlobalLinSysStaticCond::GlobalLinSysStaticCond(
75  const GlobalLinSysKey &pKey, const std::weak_ptr<ExpList> &pExpList,
76  const std::shared_ptr<AssemblyMap> &pLocToGloMap)
77  : GlobalLinSys(pKey, pExpList, pLocToGloMap), m_locToGloMap(pLocToGloMap)
78 {
79 }
80 
82 {
83  // Allocate memory for top-level structure
85 
86  // Construct this level
87  Initialise(m_locToGloMap.lock());
88 }
89 
90 /**
91  *
92  */
94 {
95 }
96 
97 /**
98  *
99  */
101  const Array<OneD, const NekDouble> &pLocInput,
102  Array<OneD, NekDouble> &pLocOutput,
103  const AssemblyMapSharedPtr &pLocToGloMap,
104  const Array<OneD, const NekDouble> &dirForcing)
105 {
106  boost::ignore_unused(dirForcing);
107  ASSERTL1(dirForcing.size() == 0,
108  "GlobalLinSysStaticCond: Not setup for dirForcing");
109 
110  bool atLastLevel = pLocToGloMap->AtLastLevel();
111  int scLevel = pLocToGloMap->GetStaticCondLevel();
112 
113  int nGlobDofs = pLocToGloMap->GetNumGlobalCoeffs();
114  int nLocBndDofs = pLocToGloMap->GetNumLocalBndCoeffs();
115  int nGlobBndDofs = pLocToGloMap->GetNumGlobalBndCoeffs();
116  int nDirBndDofs = pLocToGloMap->GetNumGlobalDirBndCoeffs();
117  int nIntDofs = nGlobDofs - nGlobBndDofs;
118 
119  if ((nGlobDofs - nDirBndDofs) == 0)
120  {
121  return; // nothing to solve;
122  }
123 
124  Array<OneD, NekDouble> F_bnd, F_bnd1, F_int, V_bnd;
126 
127  F_bnd = m_wsp;
128  F_bnd1 = m_wsp + nLocBndDofs;
129  V_bnd = m_wsp + 2 * nLocBndDofs;
130  F_int = m_wsp + 3 * nLocBndDofs;
131 
132  pLocToGloMap->LocalToLocalBnd(pLocOutput, V_bnd);
133 
134  NekVector<NekDouble> F_Int(nIntDofs, F_int, eWrapper);
135  NekVector<NekDouble> V_Bnd(nLocBndDofs, V_bnd, eWrapper);
136 
137  if (nIntDofs)
138  {
139  m_locToGloMap.lock()->LocalToLocalInt(pLocInput, F_int);
140  }
141 
142  // Boundary system solution
143  if (nGlobBndDofs - nDirBndDofs)
144  {
145  pLocToGloMap->LocalToLocalBnd(pLocInput, F_bnd);
146 
147  // set up normalisation factor for right hand side on first SC level
148  v_PreSolve(scLevel, F_bnd);
149 
150  // Gather boundary expansison into locbnd
151  NekVector<NekDouble> F_Bnd(nLocBndDofs, F_bnd1, eWrapper);
152 
153  // construct boundary forcing
154  if (nIntDofs)
155  {
156  DNekScalBlkMat &BinvD = *m_BinvD;
157 
158  F_Bnd = BinvD * F_Int;
159 
160  Vmath::Vsub(nLocBndDofs, F_bnd, 1, F_bnd1, 1, F_bnd, 1);
161  }
162 
163  if (atLastLevel)
164  {
165  // Transform to new basis if required
166  v_BasisFwdTransform(F_bnd);
167 
168  DNekScalBlkMat &SchurCompl = *m_schurCompl;
169 
170  v_CoeffsFwdTransform(V_bnd, V_bnd);
171 
172  // subtract dirichlet boundary forcing
173  F_Bnd = SchurCompl * V_Bnd;
174 
175  Vmath::Vsub(nLocBndDofs, F_bnd, 1, F_bnd1, 1, F_bnd, 1);
176 
177  Array<OneD, NekDouble> F_hom, pert(nGlobBndDofs, 0.0);
178 
179  pLocToGloMap->AssembleBnd(F_bnd, F_bnd1);
180 
181  // Solve for difference from initial solution given inout;
182  SolveLinearSystem(nGlobBndDofs, F_bnd1, pert, pLocToGloMap,
183  nDirBndDofs);
184 
185  Array<OneD, NekDouble> outloc = F_bnd;
186  pLocToGloMap->GlobalToLocalBnd(pert, outloc);
187 
188  // Add back initial conditions onto difference
189  Vmath::Vadd(nLocBndDofs, V_bnd, 1, outloc, 1, V_bnd, 1);
190 
191  // Transform back to original basis
192  v_CoeffsBwdTransform(V_bnd);
193 
194  // put final bnd solution back in output array
195  m_locToGloMap.lock()->LocalBndToLocal(V_bnd, pLocOutput);
196  }
197  else // Process next level of recursion for multi level SC
198  {
199  AssemblyMapSharedPtr nextLevLocToGloMap =
200  pLocToGloMap->GetNextLevelLocalToGlobalMap();
201 
202  // partially assemble F for next level and
203  // reshuffle V_bnd
204  nextLevLocToGloMap->PatchAssemble(F_bnd, F_bnd);
205  nextLevLocToGloMap->PatchLocalToGlobal(V_bnd, V_bnd);
206 
207  m_recursiveSchurCompl->Solve(F_bnd, V_bnd, nextLevLocToGloMap);
208 
209  // unpack V_bnd
210  nextLevLocToGloMap->PatchGlobalToLocal(V_bnd, V_bnd);
211 
212  // place V_bnd in output array
213  m_locToGloMap.lock()->LocalBndToLocal(V_bnd, pLocOutput);
214  }
215  }
216 
217  // solve interior system
218  if (nIntDofs)
219  {
220  Array<OneD, NekDouble> V_int(nIntDofs);
221  NekVector<NekDouble> V_Int(nIntDofs, V_int, eWrapper);
222 
223  // get array of local solutions
224  DNekScalBlkMat &invD = *m_invD;
225  DNekScalBlkMat &C = *m_C;
226 
227  F_Int = F_Int - C * V_Bnd;
228 
229  Multiply(V_Int, invD, F_Int);
230 
231  m_locToGloMap.lock()->LocalIntToLocal(V_int, pLocOutput);
232  }
233 }
234 
235 /**
236  * If at the last level of recursion (or the only level in the case of
237  * single-level static condensation), assemble the Schur complement.
238  * For other levels, in the case of multi-level static condensation,
239  * the next level of the condensed system is computed.
240  * @param pLocToGloMap Local to global mapping.
241  */
243  const std::shared_ptr<AssemblyMap> &pLocToGloMap)
244 {
245  int nLocalBnd = m_locToGloMap.lock()->GetNumLocalBndCoeffs();
246  int nIntDofs = m_locToGloMap.lock()->GetNumLocalCoeffs() - nLocalBnd;
247  m_wsp = Array<OneD, NekDouble>(3 * nLocalBnd + nIntDofs, 0.0);
248 
249  if (pLocToGloMap->AtLastLevel())
250  {
251  v_AssembleSchurComplement(pLocToGloMap);
252  }
253  else
254  {
256  pLocToGloMap->GetNextLevelLocalToGlobalMap());
257  }
258 }
259 
261 {
262  return m_schurCompl->GetNumberOfBlockRows();
263 }
264 
265 /**
266  * For the first level in multi-level static condensation, or the only
267  * level in the case of single-level static condensation, allocate the
268  * condensed matrices and populate them with the local matrices
269  * retrieved from the expansion list.
270  * @param
271  */
273  const std::shared_ptr<AssemblyMap> &pLocToGloMap)
274 {
275  int n;
276  int n_exp = m_expList.lock()->GetNumElmts();
277 
278  const Array<OneD, const unsigned int> &nbdry_size =
279  pLocToGloMap->GetNumLocalBndCoeffsPerPatch();
280  const Array<OneD, const unsigned int> &nint_size =
281  pLocToGloMap->GetNumLocalIntCoeffsPerPatch();
282 
283  // Setup Block Matrix systems
284  MatrixStorage blkmatStorage = eDIAGONAL;
286  nbdry_size, nbdry_size, blkmatStorage);
288  nbdry_size, nint_size, blkmatStorage);
290  nint_size, nbdry_size, blkmatStorage);
292  nint_size, nint_size, blkmatStorage);
293 
294  for (n = 0; n < n_exp; ++n)
295  {
297  {
299  m_schurCompl->SetBlock(n, n, loc_mat);
300  }
301  else
302  {
303  DNekScalBlkMatSharedPtr loc_schur =
306  m_schurCompl->SetBlock(n, n, t = loc_schur->GetBlock(0, 0));
307  m_BinvD->SetBlock(n, n, t = loc_schur->GetBlock(0, 1));
308  m_C->SetBlock(n, n, t = loc_schur->GetBlock(1, 0));
309  m_invD->SetBlock(n, n, t = loc_schur->GetBlock(1, 1));
310  }
311  }
312 }
313 
314 /**
315  *
316  */
318  const AssemblyMapSharedPtr &pLocToGloMap)
319 {
320  int i, j, n, cnt;
321  DNekScalBlkMatSharedPtr blkMatrices[4];
322 
323  // Create temporary matrices within an inner-local scope to ensure
324  // any references to the intermediate storage is lost before
325  // the recursive step, rather than at the end of the routine.
326  // This allows the schur complement matrix from this level to be
327  // disposed of in the next level after use without being retained
328  // due to lingering shared pointers.
329  {
330 
331  const Array<OneD, const unsigned int> &nBndDofsPerPatch =
332  pLocToGloMap->GetNumLocalBndCoeffsPerPatch();
333  const Array<OneD, const unsigned int> &nIntDofsPerPatch =
334  pLocToGloMap->GetNumLocalIntCoeffsPerPatch();
335 
336  // STEP 1:
337  // Based upon the schur complement of the the current level we
338  // will substructure this matrix in the form
339  // -- --
340  // | A B |
341  // | C D |
342  // -- --
343  // All matrices A,B,C and D are (diagonal) blockmatrices.
344  // However, as a start we will use an array of DNekMatrices as
345  // it is too hard to change the individual entries of a
346  // DNekScalBlkMatSharedPtr.
347 
348  // In addition, we will also try to ensure that the memory of
349  // the blockmatrices will be contiguous. This will probably
350  // enhance the efficiency
351  // - Calculate the total number of entries in the blockmatrices
352  int nPatches = pLocToGloMap->GetNumPatches();
353  int nEntriesA = 0;
354  int nEntriesB = 0;
355  int nEntriesC = 0;
356  int nEntriesD = 0;
357 
358  for (i = 0; i < nPatches; i++)
359  {
360  nEntriesA += nBndDofsPerPatch[i] * nBndDofsPerPatch[i];
361  nEntriesB += nBndDofsPerPatch[i] * nIntDofsPerPatch[i];
362  nEntriesC += nIntDofsPerPatch[i] * nBndDofsPerPatch[i];
363  nEntriesD += nIntDofsPerPatch[i] * nIntDofsPerPatch[i];
364  }
365 
366  // Now create the DNekMatrices and link them to the memory
367  // allocated above
368  Array<OneD, DNekMatSharedPtr> substructuredMat[4] = {
369  Array<OneD, DNekMatSharedPtr>(nPatches), // Matrix A
370  Array<OneD, DNekMatSharedPtr>(nPatches), // Matrix B
371  Array<OneD, DNekMatSharedPtr>(nPatches), // Matrix C
372  Array<OneD, DNekMatSharedPtr>(nPatches)}; // Matrix D
373 
374  // Initialise storage for the matrices. We do this separately
375  // for each matrix so the matrices may be independently
376  // deallocated when no longer required.
377  Array<OneD, NekDouble> storageA(nEntriesA, 0.0);
378  Array<OneD, NekDouble> storageB(nEntriesB, 0.0);
379  Array<OneD, NekDouble> storageC(nEntriesC, 0.0);
380  Array<OneD, NekDouble> storageD(nEntriesD, 0.0);
381 
382  Array<OneD, NekDouble> tmparray;
383  PointerWrapper wType = eWrapper;
384  int cntA = 0;
385  int cntB = 0;
386  int cntC = 0;
387  int cntD = 0;
388 
389  // Use symmetric storage for invD if possible
390  MatrixStorage storageTypeD = eFULL;
394  {
395  storageTypeD = eSYMMETRIC;
396  }
397 
398  for (i = 0; i < nPatches; i++)
399  {
400  // Matrix A
401  tmparray = storageA + cntA;
402  substructuredMat[0][i] = MemoryManager<DNekMat>::AllocateSharedPtr(
403  nBndDofsPerPatch[i], nBndDofsPerPatch[i], tmparray, wType);
404  // Matrix B
405  tmparray = storageB + cntB;
406  substructuredMat[1][i] = MemoryManager<DNekMat>::AllocateSharedPtr(
407  nBndDofsPerPatch[i], nIntDofsPerPatch[i], tmparray, wType);
408  // Matrix C
409  tmparray = storageC + cntC;
410  substructuredMat[2][i] = MemoryManager<DNekMat>::AllocateSharedPtr(
411  nIntDofsPerPatch[i], nBndDofsPerPatch[i], tmparray, wType);
412  // Matrix D
413  tmparray = storageD + cntD;
414  substructuredMat[3][i] = MemoryManager<DNekMat>::AllocateSharedPtr(
415  nIntDofsPerPatch[i], nIntDofsPerPatch[i], tmparray, wType,
416  storageTypeD);
417 
418  cntA += nBndDofsPerPatch[i] * nBndDofsPerPatch[i];
419  cntB += nBndDofsPerPatch[i] * nIntDofsPerPatch[i];
420  cntC += nIntDofsPerPatch[i] * nBndDofsPerPatch[i];
421  cntD += nIntDofsPerPatch[i] * nIntDofsPerPatch[i];
422  }
423 
424  // Then, project SchurComplement onto
425  // the substructured matrices of the next level
427  DNekScalMatSharedPtr schurComplSubMat;
428  int schurComplSubMatnRows;
429  Array<OneD, const int> patchId, dofId;
432 
433  for (n = cnt = 0; n < SchurCompl->GetNumberOfBlockRows(); ++n)
434  {
435  schurComplSubMat = SchurCompl->GetBlock(n, n);
436  schurComplSubMatnRows = schurComplSubMat->GetRows();
437 
438  patchId =
439  pLocToGloMap->GetPatchMapFromPrevLevel()->GetPatchId() + cnt;
440  dofId = pLocToGloMap->GetPatchMapFromPrevLevel()->GetDofId() + cnt;
441  isBndDof =
442  pLocToGloMap->GetPatchMapFromPrevLevel()->IsBndDof() + cnt;
443  sign = pLocToGloMap->GetPatchMapFromPrevLevel()->GetSign() + cnt;
444 
445  // Set up Matrix;
446  for (i = 0; i < schurComplSubMatnRows; ++i)
447  {
448  int pId = patchId[i];
449  Array<OneD, NekDouble> subMat0 =
450  substructuredMat[0][pId]->GetPtr();
451  Array<OneD, NekDouble> subMat1 =
452  substructuredMat[1][patchId[i]]->GetPtr();
453  Array<OneD, NekDouble> subMat2 =
454  substructuredMat[2][patchId[i]]->GetPtr();
455  DNekMatSharedPtr subMat3 = substructuredMat[3][patchId[i]];
456  int subMat0rows = substructuredMat[0][pId]->GetRows();
457  int subMat1rows = substructuredMat[1][pId]->GetRows();
458  int subMat2rows = substructuredMat[2][pId]->GetRows();
459 
460  if (isBndDof[i])
461  {
462  for (j = 0; j < schurComplSubMatnRows; ++j)
463  {
464  ASSERTL0(patchId[i] == patchId[j],
465  "These values should be equal");
466 
467  if (isBndDof[j])
468  {
469  subMat0[dofId[i] + dofId[j] * subMat0rows] +=
470  sign[i] * sign[j] * (*schurComplSubMat)(i, j);
471  }
472  else
473  {
474  subMat1[dofId[i] + dofId[j] * subMat1rows] +=
475  sign[i] * sign[j] * (*schurComplSubMat)(i, j);
476  }
477  }
478  }
479  else
480  {
481  for (j = 0; j < schurComplSubMatnRows; ++j)
482  {
483  ASSERTL0(patchId[i] == patchId[j],
484  "These values should be equal");
485 
486  if (isBndDof[j])
487  {
488  subMat2[dofId[i] + dofId[j] * subMat2rows] +=
489  sign[i] * sign[j] * (*schurComplSubMat)(i, j);
490  }
491  else
492  {
493  if (storageTypeD == eSYMMETRIC)
494  {
495  if (dofId[i] <= dofId[j])
496  {
497  (*subMat3)(dofId[i], dofId[j]) +=
498  sign[i] * sign[j] *
499  (*schurComplSubMat)(i, j);
500  }
501  }
502  else
503  {
504  (*subMat3)(dofId[i], dofId[j]) +=
505  sign[i] * sign[j] *
506  (*schurComplSubMat)(i, j);
507  }
508  }
509  }
510  }
511  }
512  cnt += schurComplSubMatnRows;
513  }
514 
515  // STEP 2: condense the system
516  // This can be done elementally (i.e. patch per patch)
517  for (i = 0; i < nPatches; i++)
518  {
519  if (nIntDofsPerPatch[i])
520  {
521  Array<OneD, NekDouble> subMat0 =
522  substructuredMat[0][i]->GetPtr();
523  Array<OneD, NekDouble> subMat1 =
524  substructuredMat[1][i]->GetPtr();
525  Array<OneD, NekDouble> subMat2 =
526  substructuredMat[2][i]->GetPtr();
527  int subMat0rows = substructuredMat[0][i]->GetRows();
528  int subMat1rows = substructuredMat[1][i]->GetRows();
529  int subMat2rows = substructuredMat[2][i]->GetRows();
530  int subMat2cols = substructuredMat[2][i]->GetColumns();
531 
532  // 1. D -> InvD
533  substructuredMat[3][i]->Invert();
534  // 2. B -> BInvD
535  (*substructuredMat[1][i]) =
536  (*substructuredMat[1][i]) * (*substructuredMat[3][i]);
537  // 3. A -> A - BInvD*C (= schurcomplement)
538  // (*substructuredMat[0][i]) =(*substructuredMat[0][i])-
539  // (*substructuredMat[1][i])*(*substructuredMat[2][i]);
540  // Note: faster to use blas directly
541  if (subMat1rows && subMat2cols)
542  {
543  Blas::Dgemm('N', 'N', subMat1rows, subMat2cols, subMat2rows,
544  -1.0, &subMat1[0], subMat1rows, &subMat2[0],
545  subMat2rows, 1.0, &subMat0[0], subMat0rows);
546  }
547  }
548  }
549 
550  // STEP 3: fill the block matrices. However, do note that we
551  // first have to convert them to a DNekScalMat in order to be
552  // compatible with the first level of static condensation
553  const Array<OneD, const unsigned int> &nbdry_size =
554  pLocToGloMap->GetNumLocalBndCoeffsPerPatch();
555  const Array<OneD, const unsigned int> &nint_size =
556  pLocToGloMap->GetNumLocalIntCoeffsPerPatch();
557  MatrixStorage blkmatStorage = eDIAGONAL;
558 
560  nbdry_size, nbdry_size, blkmatStorage);
562  nbdry_size, nint_size, blkmatStorage);
564  nint_size, nbdry_size, blkmatStorage);
566  nint_size, nint_size, blkmatStorage);
567 
568  DNekScalMatSharedPtr tmpscalmat;
569  for (i = 0; i < nPatches; i++)
570  {
571  for (j = 0; j < 4; j++)
572  {
574  1.0, substructuredMat[j][i]);
575  blkMatrices[j]->SetBlock(i, i, tmpscalmat);
576  }
577  }
578  }
579 
580  // We've finished with the Schur complement matrix passed to this
581  // level, so return the memory to the system. The Schur complement
582  // matrix need only be retained at the last level. Save the other
583  // matrices at this level though.
584  m_schurCompl.reset();
585 
587  v_Recurse(m_linSysKey, m_expList, blkMatrices[0], blkMatrices[1],
588  blkMatrices[2], blkMatrices[3], pLocToGloMap);
589 }
590 } // namespace MultiRegions
591 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
#define sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:49
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
A global linear system.
Definition: GlobalLinSys.h:72
const std::weak_ptr< ExpList > m_expList
Local Matrix System.
Definition: GlobalLinSys.h:124
void SolveLinearSystem(const int pNumRows, const Array< OneD, const NekDouble > &pInput, Array< OneD, NekDouble > &pOutput, const AssemblyMapSharedPtr &locToGloMap, const int pNumDir=0)
Solve the linear system for given input and output vectors.
Definition: GlobalLinSys.h:192
const GlobalLinSysKey m_linSysKey
Key associated with this linear system.
Definition: GlobalLinSys.h:122
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 DNekScalBlkMatSharedPtr v_GetStaticCondBlock(unsigned int n)
Retrieves a the static condensation block matrices from n-th expansion using the matrix key provided ...
void Initialise(const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Definition: GlobalLinSys.h:205
DNekScalBlkMatSharedPtr m_schurCompl
Block Schur complement matrix.
virtual void v_CoeffsFwdTransform(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
std::weak_ptr< AssemblyMap > m_locToGloMap
Local to global map.
void SetupTopLevel(const std::shared_ptr< AssemblyMap > &locToGloMap)
Set up the storage for the Schur complement or the top level of the multi-level Schur complement.
Array< OneD, NekDouble > m_wsp
Workspace array for matrix multiplication.
virtual void v_AssembleSchurComplement(std::shared_ptr< AssemblyMap > pLoctoGloMap)
virtual void v_PreSolve(int scLevel, Array< OneD, NekDouble > &F_bnd)
virtual void v_BasisFwdTransform(Array< OneD, NekDouble > &pInOut)
GlobalLinSysStaticCondSharedPtr m_recursiveSchurCompl
Schur complement for Direct Static Condensation.
virtual void v_CoeffsBwdTransform(Array< OneD, NekDouble > &pInOut)
virtual void v_Initialise(const std::shared_ptr< AssemblyMap > &locToGloMap) override
Initialise this object.
virtual void v_Solve(const Array< OneD, const NekDouble > &in, Array< OneD, NekDouble > &out, const AssemblyMapSharedPtr &locToGloMap, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray) override
Solve the linear system for given input and output vectors using a specified local to global map.
DNekScalBlkMatSharedPtr m_BinvD
Block matrix.
virtual GlobalLinSysStaticCondSharedPtr v_Recurse(const GlobalLinSysKey &mkey, const std::weak_ptr< ExpList > &pExpList, const DNekScalBlkMatSharedPtr pSchurCompl, const DNekScalBlkMatSharedPtr pBinvD, const DNekScalBlkMatSharedPtr pC, const DNekScalBlkMatSharedPtr pInvD, const std::shared_ptr< AssemblyMap > &locToGloMap)=0
void ConstructNextLevelCondensedSystem(const std::shared_ptr< AssemblyMap > &locToGloMap)
DNekScalBlkMatSharedPtr m_C
Block matrix.
virtual int v_GetNumBlocks() override
Get the number of blocks in this system.
DNekScalBlkMatSharedPtr m_invD
Block matrix.
StdRegions::MatrixType GetMatrixType() const
Return the matrix type.
static void Dgemm(const char &transa, const char &transb, const int &m, const int &n, const int &k, const double &alpha, const double *a, const int &lda, const double *b, const int &ldb, const double &beta, double *c, const int &ldc)
BLAS level 3: Matrix-matrix multiply C = A x B where op(A)[m x k], op(B)[k x n], C[m x n] DGEMM perfo...
Definition: Blas.hpp:368
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition: AssemblyMap.h:51
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
void Multiply(NekMatrix< ResultDataType, StandardMatrixTag > &result, const NekMatrix< LhsDataType, LhsMatrixType > &lhs, const ResultDataType &rhs)
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:79
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:75
PointerWrapper
Specifies if the pointer passed to a NekMatrix or NekVector is copied into an internal representation...
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.cpp:359
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.cpp:419