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  */
107  const AssemblyMapSharedPtr &pLocToGloMap,
108  const Array<OneD, const NekDouble> &dirForcing)
109  {
110  bool dirForcCalculated = (bool) dirForcing.num_elements();
111  bool atLastLevel = pLocToGloMap->AtLastLevel();
112  int scLevel = pLocToGloMap->GetStaticCondLevel();
113 
114  int nGlobDofs = pLocToGloMap->GetNumGlobalCoeffs();
115  int nGlobBndDofs = pLocToGloMap->GetNumGlobalBndCoeffs();
116  int nDirBndDofs = pLocToGloMap->GetNumGlobalDirBndCoeffs();
117  int nGlobHomBndDofs = nGlobBndDofs - nDirBndDofs;
118  int nLocBndDofs = pLocToGloMap->GetNumLocalBndCoeffs();
119  int nIntDofs = pLocToGloMap->GetNumGlobalCoeffs()
120  - nGlobBndDofs;
121 
122  Array<OneD, NekDouble> F = m_wsp + 2*nLocBndDofs + nGlobHomBndDofs;
124  if(nDirBndDofs && dirForcCalculated)
125  {
126  Vmath::Vsub(nGlobDofs,in.get(),1,dirForcing.get(),1,F.get(),1);
127  }
128  else
129  {
130  Vmath::Vcopy(nGlobDofs,in.get(),1,F.get(),1);
131  }
132 
133  NekVector<NekDouble> F_HomBnd(nGlobHomBndDofs,tmp=F+nDirBndDofs,
134  eWrapper);
135  NekVector<NekDouble> F_GlobBnd(nGlobBndDofs,F,eWrapper);
136  NekVector<NekDouble> F_Int(nIntDofs,tmp=F+nGlobBndDofs,eWrapper);
137 
138  NekVector<NekDouble> V_GlobBnd(nGlobBndDofs,out,eWrapper);
139  NekVector<NekDouble> V_GlobHomBnd(nGlobHomBndDofs,
140  tmp=out+nDirBndDofs,
141  eWrapper);
142  NekVector<NekDouble> V_Int(nIntDofs,tmp=out+nGlobBndDofs,eWrapper);
143  NekVector<NekDouble> V_LocBnd(nLocBndDofs,m_wsp,eWrapper);
144 
145  NekVector<NekDouble> V_GlobHomBndTmp(
146  nGlobHomBndDofs,tmp = m_wsp + 2*nLocBndDofs,eWrapper);
147 
148  // set up normalisation factor for right hand side on first SC level
149  DNekScalBlkMatSharedPtr sc = v_PreSolve(scLevel, F_GlobBnd);
150 
151  if(nGlobHomBndDofs)
152  {
153  // construct boundary forcing
154  if( nIntDofs && ((!dirForcCalculated) && (atLastLevel)) )
155  {
156  DNekScalBlkMat &BinvD = *m_BinvD;
157  DNekScalBlkMat &SchurCompl = *sc;
158 
159  // include dirichlet boundary forcing
160  pLocToGloMap->GlobalToLocalBnd(V_GlobBnd,V_LocBnd);
161  V_LocBnd = BinvD*F_Int + SchurCompl*V_LocBnd;
162  }
163  else if((!dirForcCalculated) && (atLastLevel))
164  {
165  // include dirichlet boundary forcing
166  DNekScalBlkMat &SchurCompl = *sc;
167  pLocToGloMap->GlobalToLocalBnd(V_GlobBnd,V_LocBnd);
168  V_LocBnd = SchurCompl*V_LocBnd;
169  }
170  else
171  {
172  DNekScalBlkMat &BinvD = *m_BinvD;
173  DiagonalBlockFullScalMatrixMultiply( V_LocBnd, BinvD, F_Int);
174  }
175 
176  pLocToGloMap->AssembleBnd(V_LocBnd,V_GlobHomBndTmp,
177  nDirBndDofs);
178  Subtract(F_HomBnd, F_HomBnd, V_GlobHomBndTmp);
179 
180  // Transform from original basis to low energy
181  v_BasisFwdTransform(F, nDirBndDofs);
182 
183  // For parallel multi-level static condensation some
184  // processors may have different levels to others. This
185  // routine receives contributions to partition vertices from
186  // those lower levels, whilst not sending anything to the
187  // other partitions, and includes them in the modified right
188  // hand side vector.
189  int lcLevel = pLocToGloMap->GetLowestStaticCondLevel();
190  if(atLastLevel && scLevel < lcLevel)
191  {
192  // If this level is not the lowest level across all
193  // processes, we must do dummy communication for the
194  // remaining levels
195  Array<OneD, NekDouble> tmp(nGlobBndDofs);
196  for (int i = scLevel; i < lcLevel; ++i)
197  {
198  Vmath::Fill(nGlobBndDofs, 0.0, tmp, 1);
199  pLocToGloMap->UniversalAssembleBnd(tmp);
200  Vmath::Vcopy(nGlobHomBndDofs,
201  tmp.get()+nDirBndDofs, 1,
202  V_GlobHomBndTmp.GetPtr().get(), 1);
203  Subtract( F_HomBnd, F_HomBnd, V_GlobHomBndTmp);
204  }
205  }
206 
207  // solve boundary system
208  if(atLastLevel)
209  {
210  Array<OneD, NekDouble> pert(nGlobBndDofs,0.0);
211 
212  // Solve for difference from initial solution given inout;
214  nGlobBndDofs, F, pert, pLocToGloMap, nDirBndDofs);
215 
216  // Transform back to original basis
217  v_BasisBwdTransform(pert);
218 
219  // Add back initial conditions onto difference
220  Vmath::Vadd(nGlobHomBndDofs,&out[nDirBndDofs],1,
221  &pert[nDirBndDofs],1,&out[nDirBndDofs],1);
222  }
223  else
224  {
225  m_recursiveSchurCompl->Solve(F,
226  V_GlobBnd.GetPtr(),
227  pLocToGloMap->GetNextLevelLocalToGlobalMap());
228  }
229  }
230 
231  // solve interior system
232  if(nIntDofs)
233  {
234  DNekScalBlkMat &invD = *m_invD;
235 
236  if(nGlobHomBndDofs || nDirBndDofs)
237  {
238  DNekScalBlkMat &C = *m_C;
239 
240  if(dirForcCalculated && nDirBndDofs)
241  {
242  pLocToGloMap->GlobalToLocalBnd(V_GlobHomBnd,V_LocBnd,
243  nDirBndDofs);
244  }
245  else
246  {
247  pLocToGloMap->GlobalToLocalBnd(V_GlobBnd,V_LocBnd);
248  }
249  F_Int = F_Int - C*V_LocBnd;
250  }
251  Multiply( V_Int, invD, F_Int);
252  }
253  }
254 
255 
256  /**
257  * If at the last level of recursion (or the only level in the case of
258  * single-level static condensation), assemble the Schur complement.
259  * For other levels, in the case of multi-level static condensation,
260  * the next level of the condensed system is computed.
261  * @param pLocToGloMap Local to global mapping.
262  */
264  const std::shared_ptr<AssemblyMap>& pLocToGloMap)
265  {
266  int nLocalBnd = m_locToGloMap.lock()->GetNumLocalBndCoeffs();
267  int nGlobal = m_locToGloMap.lock()->GetNumGlobalCoeffs();
268  int nGlobBndDofs = pLocToGloMap->GetNumGlobalBndCoeffs();
269  int nDirBndDofs = pLocToGloMap->GetNumGlobalDirBndCoeffs();
270  int nGlobHomBndDofs = nGlobBndDofs - nDirBndDofs;
272  (2*nLocalBnd + nGlobal + nGlobHomBndDofs, 0.0);
273 
274  if (pLocToGloMap->AtLastLevel())
275  {
276  v_AssembleSchurComplement(pLocToGloMap);
277  }
278  else
279  {
281  pLocToGloMap->GetNextLevelLocalToGlobalMap());
282  }
283  }
284 
286  {
287  return m_schurCompl->GetNumberOfBlockRows();
288  }
289 
290  /**
291  * For the first level in multi-level static condensation, or the only
292  * level in the case of single-level static condensation, allocate the
293  * condensed matrices and populate them with the local matrices
294  * retrieved from the expansion list.
295  * @param
296  */
298  const std::shared_ptr<AssemblyMap>& pLocToGloMap)
299  {
300  int n;
301  int n_exp = m_expList.lock()->GetNumElmts();
302 
303  const Array<OneD,const unsigned int>& nbdry_size
304  = pLocToGloMap->GetNumLocalBndCoeffsPerPatch();
305  const Array<OneD,const unsigned int>& nint_size
306  = pLocToGloMap->GetNumLocalIntCoeffsPerPatch();
307 
308  // Setup Block Matrix systems
309  MatrixStorage blkmatStorage = eDIAGONAL;
311  ::AllocateSharedPtr(nbdry_size, nbdry_size, blkmatStorage);
313  ::AllocateSharedPtr(nbdry_size, nint_size , blkmatStorage);
315  ::AllocateSharedPtr(nint_size , nbdry_size, blkmatStorage);
317  ::AllocateSharedPtr(nint_size , nint_size , blkmatStorage);
318 
319  for(n = 0; n < n_exp; ++n)
320  {
321  if (m_linSysKey.GetMatrixType() ==
323  {
324  DNekScalMatSharedPtr loc_mat
326  m_schurCompl->SetBlock(n,n,loc_mat);
327  }
328  else
329  {
330  DNekScalBlkMatSharedPtr loc_schur
333  m_schurCompl->SetBlock(n, n, t = loc_schur->GetBlock(0,0));
334  m_BinvD ->SetBlock(n, n, t = loc_schur->GetBlock(0,1));
335  m_C ->SetBlock(n, n, t = loc_schur->GetBlock(1,0));
336  m_invD ->SetBlock(n, n, t = loc_schur->GetBlock(1,1));
337  }
338  }
339  }
340 
341  /**
342  *
343  */
345  const AssemblyMapSharedPtr& pLocToGloMap)
346  {
347  int i,j,n,cnt;
348  DNekScalBlkMatSharedPtr blkMatrices[4];
349 
350  // Create temporary matrices within an inner-local scope to ensure
351  // any references to the intermediate storage is lost before
352  // the recursive step, rather than at the end of the routine.
353  // This allows the schur complement matrix from this level to be
354  // disposed of in the next level after use without being retained
355  // due to lingering shared pointers.
356  {
357 
358  const Array<OneD,const unsigned int>& nBndDofsPerPatch
359  = pLocToGloMap->GetNumLocalBndCoeffsPerPatch();
360  const Array<OneD,const unsigned int>& nIntDofsPerPatch
361  = pLocToGloMap->GetNumLocalIntCoeffsPerPatch();
362 
363  // STEP 1:
364  // Based upon the schur complement of the the current level we
365  // will substructure this matrix in the form
366  // -- --
367  // | A B |
368  // | C D |
369  // -- --
370  // All matrices A,B,C and D are (diagonal) blockmatrices.
371  // However, as a start we will use an array of DNekMatrices as
372  // it is too hard to change the individual entries of a
373  // DNekScalBlkMatSharedPtr.
374 
375  // In addition, we will also try to ensure that the memory of
376  // the blockmatrices will be contiguous. This will probably
377  // enhance the efficiency
378  // - Calculate the total number of entries in the blockmatrices
379  int nPatches = pLocToGloMap->GetNumPatches();
380  int nEntriesA = 0; int nEntriesB = 0;
381  int nEntriesC = 0; int nEntriesD = 0;
382 
383  for(i = 0; i < nPatches; i++)
384  {
385  nEntriesA += nBndDofsPerPatch[i]*nBndDofsPerPatch[i];
386  nEntriesB += nBndDofsPerPatch[i]*nIntDofsPerPatch[i];
387  nEntriesC += nIntDofsPerPatch[i]*nBndDofsPerPatch[i];
388  nEntriesD += nIntDofsPerPatch[i]*nIntDofsPerPatch[i];
389  }
390 
391  // Now create the DNekMatrices and link them to the memory
392  // allocated above
393  Array<OneD, DNekMatSharedPtr> substructuredMat[4]
394  = {Array<OneD, DNekMatSharedPtr>(nPatches), //Matrix A
395  Array<OneD, DNekMatSharedPtr>(nPatches), //Matrix B
396  Array<OneD, DNekMatSharedPtr>(nPatches), //Matrix C
397  Array<OneD, DNekMatSharedPtr>(nPatches)}; //Matrix D
398 
399  // Initialise storage for the matrices. We do this separately
400  // for each matrix so the matrices may be independently
401  // deallocated when no longer required.
402  Array<OneD, NekDouble> storageA(nEntriesA,0.0);
403  Array<OneD, NekDouble> storageB(nEntriesB,0.0);
404  Array<OneD, NekDouble> storageC(nEntriesC,0.0);
405  Array<OneD, NekDouble> storageD(nEntriesD,0.0);
406 
407  Array<OneD, NekDouble> tmparray;
408  PointerWrapper wType = eWrapper;
409  int cntA = 0;
410  int cntB = 0;
411  int cntC = 0;
412  int cntD = 0;
413 
414  // Use symmetric storage for invD if possible
415  MatrixStorage storageTypeD = eFULL;
419  {
420  storageTypeD = eSYMMETRIC;
421  }
422 
423  for(i = 0; i < nPatches; i++)
424  {
425  // Matrix A
426  tmparray = storageA+cntA;
427  substructuredMat[0][i] = MemoryManager<DNekMat>
428  ::AllocateSharedPtr(nBndDofsPerPatch[i],
429  nBndDofsPerPatch[i],
430  tmparray, wType);
431  // Matrix B
432  tmparray = storageB+cntB;
433  substructuredMat[1][i] = MemoryManager<DNekMat>
434  ::AllocateSharedPtr(nBndDofsPerPatch[i],
435  nIntDofsPerPatch[i],
436  tmparray, wType);
437  // Matrix C
438  tmparray = storageC+cntC;
439  substructuredMat[2][i] = MemoryManager<DNekMat>
440  ::AllocateSharedPtr(nIntDofsPerPatch[i],
441  nBndDofsPerPatch[i],
442  tmparray, wType);
443  // Matrix D
444  tmparray = storageD+cntD;
445  substructuredMat[3][i] = MemoryManager<DNekMat>
446  ::AllocateSharedPtr(nIntDofsPerPatch[i],
447  nIntDofsPerPatch[i],
448  tmparray, wType,
449  storageTypeD);
450 
451  cntA += nBndDofsPerPatch[i] * nBndDofsPerPatch[i];
452  cntB += nBndDofsPerPatch[i] * nIntDofsPerPatch[i];
453  cntC += nIntDofsPerPatch[i] * nBndDofsPerPatch[i];
454  cntD += nIntDofsPerPatch[i] * nIntDofsPerPatch[i];
455  }
456 
457  // Then, project SchurComplement onto
458  // the substructured matrices of the next level
460  DNekScalMatSharedPtr schurComplSubMat;
461  int schurComplSubMatnRows;
462  Array<OneD, const int> patchId, dofId;
465 
466  for(n = cnt = 0; n < SchurCompl->GetNumberOfBlockRows(); ++n)
467  {
468  schurComplSubMat = SchurCompl->GetBlock(n,n);
469  schurComplSubMatnRows = schurComplSubMat->GetRows();
470 
471  patchId = pLocToGloMap->GetPatchMapFromPrevLevel()
472  ->GetPatchId() + cnt;
473  dofId = pLocToGloMap->GetPatchMapFromPrevLevel()
474  ->GetDofId() + cnt;
475  isBndDof = pLocToGloMap->GetPatchMapFromPrevLevel()
476  ->IsBndDof() + cnt;
477  sign = pLocToGloMap->GetPatchMapFromPrevLevel()
478  ->GetSign() + cnt;
479 
480  // Set up Matrix;
481  for(i = 0; i < schurComplSubMatnRows; ++i)
482  {
483  int pId = patchId[i];
484  Array<OneD, NekDouble> subMat0
485  = substructuredMat[0][pId]->GetPtr();
486  Array<OneD, NekDouble> subMat1
487  = substructuredMat[1][patchId[i]]->GetPtr();
488  Array<OneD, NekDouble> subMat2
489  = substructuredMat[2][patchId[i]]->GetPtr();
490  DNekMatSharedPtr subMat3
491  = substructuredMat[3][patchId[i]];
492  int subMat0rows = substructuredMat[0][pId]->GetRows();
493  int subMat1rows = substructuredMat[1][pId]->GetRows();
494  int subMat2rows = substructuredMat[2][pId]->GetRows();
495 
496  if(isBndDof[i])
497  {
498  for(j = 0; j < schurComplSubMatnRows; ++j)
499  {
500  ASSERTL0(patchId[i]==patchId[j],
501  "These values should be equal");
502 
503  if(isBndDof[j])
504  {
505  subMat0[dofId[i]+dofId[j]*subMat0rows] +=
506  sign[i]*sign[j]*
507  (*schurComplSubMat)(i,j);
508  }
509  else
510  {
511  subMat1[dofId[i]+dofId[j]*subMat1rows] +=
512  sign[i]*sign[j]*
513  (*schurComplSubMat)(i,j);
514  }
515  }
516  }
517  else
518  {
519  for(j = 0; j < schurComplSubMatnRows; ++j)
520  {
521  ASSERTL0(patchId[i]==patchId[j],
522  "These values should be equal");
523 
524  if(isBndDof[j])
525  {
526  subMat2[dofId[i]+dofId[j]*subMat2rows] +=
527  sign[i]*sign[j]*
528  (*schurComplSubMat)(i,j);
529  }
530  else
531  {
532  if (storageTypeD == eSYMMETRIC)
533  {
534  if (dofId[i] <= dofId[j])
535  {
536  (*subMat3)(dofId[i],dofId[j]) +=
537  sign[i]*sign[j]*
538  (*schurComplSubMat)(i,j);
539  }
540  }
541  else
542  {
543  (*subMat3)(dofId[i],dofId[j]) +=
544  sign[i]*sign[j]*
545  (*schurComplSubMat)(i,j);
546  }
547  }
548  }
549  }
550  }
551  cnt += schurComplSubMatnRows;
552  }
553 
554  // STEP 2: condense the system
555  // This can be done elementally (i.e. patch per patch)
556  for(i = 0; i < nPatches; i++)
557  {
558  if(nIntDofsPerPatch[i])
559  {
560  Array<OneD, NekDouble> subMat0
561  = substructuredMat[0][i]->GetPtr();
562  Array<OneD, NekDouble> subMat1
563  = substructuredMat[1][i]->GetPtr();
564  Array<OneD, NekDouble> subMat2
565  = substructuredMat[2][i]->GetPtr();
566  int subMat0rows = substructuredMat[0][i]->GetRows();
567  int subMat1rows = substructuredMat[1][i]->GetRows();
568  int subMat2rows = substructuredMat[2][i]->GetRows();
569  int subMat2cols = substructuredMat[2][i]->GetColumns();
570 
571  // 1. D -> InvD
572  substructuredMat[3][i]->Invert();
573  // 2. B -> BInvD
574  (*substructuredMat[1][i]) = (*substructuredMat[1][i])*
575  (*substructuredMat[3][i]);
576  // 3. A -> A - BInvD*C (= schurcomplement)
577  // (*substructuredMat[0][i]) =(*substructuredMat[0][i])-
578  // (*substructuredMat[1][i])*(*substructuredMat[2][i]);
579  // Note: faster to use blas directly
580  Blas::Dgemm('N','N', subMat1rows, subMat2cols,
581  subMat2rows, -1.0, &subMat1[0], subMat1rows,
582  &subMat2[0], subMat2rows, 1.0, &subMat0[0],
583  subMat0rows);
584  }
585  }
586 
587  // STEP 3: fill the block matrices. However, do note that we
588  // first have to convert them to a DNekScalMat in order to be
589  // compatible with the first level of static condensation
590  const Array<OneD,const unsigned int>& nbdry_size
591  = pLocToGloMap->GetNumLocalBndCoeffsPerPatch();
592  const Array<OneD,const unsigned int>& nint_size
593  = pLocToGloMap->GetNumLocalIntCoeffsPerPatch();
594  MatrixStorage blkmatStorage = eDIAGONAL;
595 
596  blkMatrices[0] = MemoryManager<DNekScalBlkMat>
597  ::AllocateSharedPtr(nbdry_size, nbdry_size, blkmatStorage);
598  blkMatrices[1] = MemoryManager<DNekScalBlkMat>
599  ::AllocateSharedPtr(nbdry_size, nint_size , blkmatStorage);
600  blkMatrices[2] = MemoryManager<DNekScalBlkMat>
601  ::AllocateSharedPtr(nint_size , nbdry_size, blkmatStorage);
602  blkMatrices[3] = MemoryManager<DNekScalBlkMat>
603  ::AllocateSharedPtr(nint_size , nint_size , blkmatStorage);
604 
605  DNekScalMatSharedPtr tmpscalmat;
606  for(i = 0; i < nPatches; i++)
607  {
608  for(j = 0; j < 4; j++)
609  {
610  tmpscalmat= MemoryManager<DNekScalMat>
611  ::AllocateSharedPtr(1.0,substructuredMat[j][i]);
612  blkMatrices[j]->SetBlock(i,i,tmpscalmat);
613  }
614  }
615  }
616 
617  // We've finished with the Schur complement matrix passed to this
618  // level, so return the memory to the system. The Schur complement
619  // matrix need only be retained at the last level. Save the other
620  // matrices at this level though.
621  m_schurCompl.reset();
622 
624  m_linSysKey, m_expList, blkMatrices[0], blkMatrices[1],
625  blkMatrices[2], blkMatrices[3], pLocToGloMap);
626  }
627  }
628 }
Array< OneD, NekDouble > m_wsp
Workspace array for matrix multiplication.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
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
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...
void DiagonalBlockFullScalMatrixMultiply(NekVector< double > &result, const NekMatrix< NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, ScaledMatrixTag >, BlockMatrixTag > &lhs, const NekVector< double > &rhs)
#define sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:16
std::weak_ptr< AssemblyMap > m_locToGloMap
Local to global map.
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
DNekScalBlkMatSharedPtr m_schurCompl
Block Schur complement matrix.
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:73
GlobalLinSysStaticCondSharedPtr m_recursiveSchurCompl
Schur complement for Direct Static Condensation.
DNekScalBlkMatSharedPtr m_C
Block matrix.
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
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
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...
STL namespace.
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
virtual DNekScalBlkMatSharedPtr v_GetStaticCondBlock(unsigned int n)
Retrieves a the static condensation block matrices from n-th expansion using the matrix key provided ...
DNekScalBlkMatSharedPtr m_invD
Block matrix.
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 A[m x n], B[n x k], C[m x k].
Definition: Blas.hpp:213
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition: AssemblyMap.h:52
void Multiply(NekMatrix< ResultDataType, StandardMatrixTag > &result, const NekMatrix< LhsDataType, LhsMatrixType > &lhs, const ResultDataType &rhs)
StdRegions::MatrixType GetMatrixType() const
Return the matrix type.
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_PreSolve(int scLevel, NekVector< NekDouble > &F_GlobBnd)
void ConstructNextLevelCondensedSystem(const std::shared_ptr< AssemblyMap > &locToGloMap)
virtual void v_AssembleSchurComplement(std::shared_ptr< AssemblyMap > pLoctoGloMap)
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
Describe a linear system.
virtual void v_Initialise(const std::shared_ptr< AssemblyMap > &locToGloMap)
Initialise this object.
PointerWrapper
Specifies if the pointer passed to a NekMatrix or NekVector is copied into an internal representation...
const GlobalLinSysKey m_linSysKey
Key associated with this linear system.
Definition: GlobalLinSys.h:125
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:346
virtual void v_BasisFwdTransform(Array< OneD, NekDouble > &pInOut, int offset)
virtual void v_BasisBwdTransform(Array< OneD, NekDouble > &pInOut)
virtual int v_GetNumBlocks()
Get the number of blocks in this system.
A global linear system.
Definition: GlobalLinSys.h:72
const std::weak_ptr< ExpList > m_expList
Local Matrix System.
Definition: GlobalLinSys.h:127
void Initialise(const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Definition: GlobalLinSys.h:216
RhsMatrixType void Subtract(NekMatrix< DataType, StandardMatrixTag > &result, const NekMatrix< LhsDataType, LhsMatrixType > &lhs, const NekMatrix< RhsDataType, RhsMatrixType > &rhs)
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
DNekScalBlkMatSharedPtr m_BinvD
Block matrix.
Array< OneD, DataType > & GetPtr()
Definition: NekVector.cpp:227
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:302