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