Nektar++
Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Attributes | Private Member Functions | List of all members
Nektar::MultiRegions::PreconditionerBlock Class Reference

#include <PreconditionerBlock.h>

Inheritance diagram for Nektar::MultiRegions::PreconditionerBlock:
[legend]

Public Member Functions

 PreconditionerBlock (const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)
 
virtual ~PreconditionerBlock ()
 
- Public Member Functions inherited from Nektar::MultiRegions::Preconditioner
 Preconditioner (const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)
 
virtual ~Preconditioner ()
 
void DoPreconditioner (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 
void DoPreconditionerWithNonVertOutput (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput, const Array< OneD, NekDouble > &pNonVertOutput, Array< OneD, NekDouble > &pVertForce=NullNekDouble1DArray)
 
void DoTransformBasisToLowEnergy (Array< OneD, NekDouble > &pInOut)
 
void DoTransformCoeffsFromLowEnergy (Array< OneD, NekDouble > &pInOut)
 
void DoTransformCoeffsToLowEnergy (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 
void DoTransformBasisFromLowEnergy (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 
void BuildPreconditioner ()
 
void InitObject ()
 
Array< OneD, NekDoubleAssembleStaticCondGlobalDiagonals ()
 Performs global assembly of diagonal entries to global Schur complement matrix. More...
 
const DNekScalBlkMatSharedPtrGetBlockTransformedSchurCompl () const
 
const DNekScalBlkMatSharedPtrGetBlockCMatrix () const
 
const DNekScalBlkMatSharedPtrGetBlockInvDMatrix () const
 
const DNekScalBlkMatSharedPtrGetBlockSchurCompl () const
 
const DNekScalBlkMatSharedPtrGetBlockTransformationMatrix () const
 
const DNekScalBlkMatSharedPtrGetBlockTransposedTransformationMatrix () const
 
DNekScalMatSharedPtr TransformedSchurCompl (int offset, int bndoffset, const std::shared_ptr< DNekScalMat > &loc_mat)
 

Static Public Member Functions

static PreconditionerSharedPtr create (const std::shared_ptr< GlobalLinSys > &plinsys, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
 Creates an instance of this class. More...
 

Static Public Attributes

static std::string className
 Name of class. More...
 

Protected Attributes

DNekBlkMatSharedPtr m_blkMat
 
- Protected Attributes inherited from Nektar::MultiRegions::Preconditioner
const std::weak_ptr< GlobalLinSysm_linsys
 
PreconditionerType m_preconType
 
DNekMatSharedPtr m_preconditioner
 
std::weak_ptr< AssemblyMapm_locToGloMap
 
LibUtilities::CommSharedPtr m_comm
 

Private Member Functions

void BlockPreconditionerCG (void)
 Construct a block preconditioner from \(\mathbf{S}_{1}\) for the continuous Galerkin system. More...
 
void BlockPreconditionerHDG (void)
 Construct a block preconditioner for the hybridized discontinuous Galerkin system. More...
 
virtual void v_InitObject ()
 
virtual void v_DoPreconditioner (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 Apply preconditioner to pInput and store the result in pOutput. More...
 
virtual void v_BuildPreconditioner ()
 

Additional Inherited Members

- Protected Member Functions inherited from Nektar::MultiRegions::Preconditioner
virtual DNekScalMatSharedPtr v_TransformedSchurCompl (int offset, int bndoffset, const std::shared_ptr< DNekScalMat > &loc_mat)
 Get block elemental transposed transformation matrix \(\mathbf{R}^{T}\). More...
 

Detailed Description

Definition at line 51 of file PreconditionerBlock.h.

Constructor & Destructor Documentation

◆ PreconditionerBlock()

Nektar::MultiRegions::PreconditionerBlock::PreconditionerBlock ( const std::shared_ptr< GlobalLinSys > &  plinsys,
const AssemblyMapSharedPtr pLocToGloMap 
)

Definition at line 66 of file PreconditionerBlock.cpp.

69  : Preconditioner(plinsys, pLocToGloMap)
70  {
71  }
Preconditioner(const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)

◆ ~PreconditionerBlock()

virtual Nektar::MultiRegions::PreconditionerBlock::~PreconditionerBlock ( )
inlinevirtual

Definition at line 73 of file PreconditionerBlock.h.

73 {}

Member Function Documentation

◆ BlockPreconditionerCG()

void Nektar::MultiRegions::PreconditionerBlock::BlockPreconditionerCG ( void  )
private

Construct a block preconditioner from \(\mathbf{S}_{1}\) for the continuous Galerkin system.

The preconditioner is defined as:

\[\mathbf{M}^{-1}=\left[\begin{array}{ccc} \mathrm{Diag}[(\mathbf{S_{1}})_{vv}] & & \\ & (\mathbf{S}_{1})_{eb} & \\ & & (\mathbf{S}_{1})_{fb} \end{array}\right] \]

where \(\mathbf{S}_{1}\) is the local Schur complement matrix for each element and the subscript denotes the portion of the Schur complement associated with the vertex, edge and face blocks respectively.

Definition at line 113 of file PreconditionerBlock.cpp.

114  {
115  ExpListSharedPtr expList = m_linsys.lock()->GetLocMat().lock();
117  DNekScalBlkMatSharedPtr loc_mat;
118  DNekScalMatSharedPtr bnd_mat;
119 
120  int i, j, k, n, cnt, gId;
121  int meshVertId, meshEdgeId, meshFaceId;
122 
123  auto asmMap = m_locToGloMap.lock();
124 
125  const int nExp = expList->GetExpSize();
126  const int nDirBnd = asmMap->GetNumGlobalDirBndCoeffs();
127 
128  // Grab periodic geometry information.
129  PeriodicMap periodicVerts, periodicEdges, periodicFaces;
130  expList->GetPeriodicEntities(
131  periodicVerts, periodicEdges, periodicFaces);
132 
133  // The vectors below are of size 3 to have separate storage for
134  // vertices, edges and faces.
135 
136  // Maps from geometry ID to the matrix representing the extracted
137  // portion of S_1. For example idMats[2] folds the S_1 face blocks.
138  vector<map<int, vector<NekDouble> > > idMats(3);
139 
140  // Maps from the global ID, as obtained from AssemblyMapCG's
141  // localToGlobalMap, to the geometry ID.
142  vector<map<int, int> > gidMeshIds(3);
143 
144  // Maps from the global ID to the number of degrees of freedom for
145  // this geometry object.
146  vector<map<int, int> > gidDofs(3);
147 
148  // Array containing maximum information needed for the universal
149  // numbering later. For i = 0,1,2 for each geometry dimension:
150  //
151  // maxVertIds[2*i] = maximum geometry ID at dimension i
152  // maxVertIds[2*i+1] = maximum number of degrees of freedom for all
153  // elements of dimension i.
154  Array<OneD, int> maxVertIds(6, -1);
155 
156  // Figure out mapping from each elemental contribution to offset in
157  // (vert,edge,face) triples.
158  for (cnt = n = 0; n < nExp; ++n)
159  {
160  exp = expList->GetExp(n);
161 
162  // Grab reference to local Schur complement matrix.
163  DNekScalMatSharedPtr schurMat =
164  m_linsys.lock()->GetStaticCondBlock(n)->GetBlock(0,0);
165 
166  // Process vertices to extract relevant portion of the Schur
167  // complement matrix.
168  for (i = 0; i < exp->GetNverts(); ++i)
169  {
170  meshVertId = exp->GetGeom()->GetVid(i);
171  int locId = exp->GetVertexMap(i);
172 
173  // Get the global ID of this vertex.
174  gId = asmMap->GetLocalToGlobalMap(
175  cnt + locId) - nDirBnd;
176 
177  // Ignore all Dirichlet vertices.
178  if (gId < 0)
179  {
180  continue;
181  }
182 
183  gidDofs[0][gId] = 1;
184 
185  // Extract vertex value from Schur complement matrix.
186  NekDouble vertVal = (*schurMat)(locId,locId);
187 
188  // See if we have processed this vertex from another
189  // element.
190  auto gIt = idMats[0].find(gId);
191 
192  if (gIt == idMats[0].end())
193  {
194  // If not then put our 'matrix' inside idMats.
195  idMats[0][gId] = vector<NekDouble>(1, vertVal);
196  }
197  else
198  {
199  // Otherwise combine with the value that is already
200  // there (i.e. do assembly on this degree of freedom).
201  gIt->second[0] += vertVal;
202  }
203 
204  // Now check to see if the vertex is periodic. If it is,
205  // then we change meshVertId to be the minimum of all the
206  // other periodic vertices, so that we don't end up
207  // duplicating the matrix in our final block matrix.
208  auto pIt = periodicVerts.find(meshVertId);
209  if (pIt != periodicVerts.end())
210  {
211  for (j = 0; j < pIt->second.size(); ++j)
212  {
213  meshVertId = min(meshVertId, pIt->second[j].id);
214  }
215  }
216 
217  // Finally record the other information we need into the
218  // other matrices.
219  gidMeshIds[0][gId] = meshVertId;
220  maxVertIds[0] = max(maxVertIds[0], meshVertId);
221  maxVertIds[1] = 1;
222  }
223 
224  // Process edges. This logic is mostly the same as the previous
225  // block.
226  for (i = 0; i < exp->GetGeom()->GetNumEdges(); ++i)
227  {
228  meshEdgeId = exp->GetGeom()->GetEid(i);
229 
230  Array<OneD, unsigned int> bmap, bmap2;
231  Array<OneD, int> sign;
232  StdRegions::Orientation edgeOrient =
233  exp->GetGeom()->GetEorient(i);
234 
235  // Check if this edge is periodic. We may need to flip
236  // orientation if it is.
237  auto pIt = periodicEdges.find(meshEdgeId);
238  if (pIt != periodicEdges.end())
239  {
240  pair<int, StdRegions::Orientation> idOrient =
242  meshEdgeId, edgeOrient, pIt->second);
243  meshEdgeId = idOrient.first;
244  edgeOrient = idOrient.second;
245  }
246 
247  // Grab edge interior map, and the edge inverse boundary
248  // map, so that we can extract this edge from the Schur
249  // complement matrix.
250  if(exp->GetGeom()->GetNumFaces()) // 3D Element calls
251  {
252  exp->as<LocalRegions::Expansion3D>()->
253  GetEdgeInteriorToElementMap(i, bmap, sign, edgeOrient);
254  bmap2 = exp->as<LocalRegions::Expansion3D>()->
255  GetEdgeInverseBoundaryMap(i);
256  }
257  else
258  {
259  exp->GetTraceInteriorToElementMap(i, bmap, sign, edgeOrient);
260  bmap2 = exp->as<LocalRegions::Expansion2D>()->
261  GetTraceInverseBoundaryMap(i);
262  }
263 
264  // Allocate temporary storage for the extracted edge matrix.
265  const int nEdgeCoeffs = bmap.size();
266  vector<NekDouble> tmpStore(nEdgeCoeffs*nEdgeCoeffs);
267 
268  gId = asmMap->GetLocalToGlobalMap(cnt + bmap[0]);
269 
270  for (j = 0; j < nEdgeCoeffs; ++j)
271  {
272  // We record the minimum ID from the edge for our
273  // maps. This follows the logic that the assembly map
274  // ordering will always give us a contiguous ordering of
275  // global degrees of freedom for edge interior
276  // coefficients.
277  gId = min(gId,
278  asmMap->GetLocalToGlobalMap(
279  cnt + bmap[j])
280  - nDirBnd);
281 
282  // Ignore Dirichlet edges.
283  if (gId < 0)
284  {
285  continue;
286  }
287 
288  const NekDouble sign1 = sign[j];
289 
290  // Extract this edge, along with sign array for assembly
291  // later.
292  for (k = 0; k < nEdgeCoeffs; ++k)
293  {
294  tmpStore[k+j*nEdgeCoeffs] =
295  sign1*sign[k]*(*schurMat)(bmap2[j], bmap2[k]);
296  }
297  }
298 
299  if (gId < 0)
300  {
301  continue;
302  }
303 
304  gidDofs[1][gId] = nEdgeCoeffs;
305 
306  // Assemble this edge matrix with another one, if it exists.
307  auto gIt = idMats[1].find(gId);
308  if (gIt == idMats[1].end())
309  {
310  idMats[1][gId] = tmpStore;
311  }
312  else
313  {
314  ASSERTL1(tmpStore.size() == gIt->second.size(),
315  "Number of modes mismatch");
316  Vmath::Vadd(nEdgeCoeffs*nEdgeCoeffs, &gIt->second[0], 1,
317  &tmpStore[0], 1, &gIt->second[0], 1);
318  }
319 
320  gidMeshIds[1][gId] = meshEdgeId;
321  maxVertIds[2] = max(maxVertIds[2], meshEdgeId);
322  maxVertIds[3] = max(maxVertIds[3], nEdgeCoeffs);
323  }
324 
325  // Process faces. This logic is mostly the same as the previous
326  // block.
327  for (i = 0; i < exp->GetGeom()->GetNumFaces(); ++i)
328  {
329  meshFaceId = exp->GetGeom()->GetFid(i);
330 
331  Array<OneD, unsigned int> bmap, bmap2;
332  Array<OneD, int> sign;
333  StdRegions::Orientation faceOrient =
334  exp->GetGeom()->GetForient(i);
335 
336  // Check if this face is periodic. We may need to flip
337  // orientation if it is.
338  auto pIt = periodicFaces.find(meshFaceId);
339  if (pIt != periodicFaces.end())
340  {
341  meshFaceId = min(meshFaceId, pIt->second[0].id);
342  faceOrient = DeterminePeriodicFaceOrient(
343  faceOrient, pIt->second[0].orient);
344  }
345 
346  exp->GetTraceInteriorToElementMap(i, bmap, sign, faceOrient);
347  bmap2 = exp->as<LocalRegions::Expansion3D>()
348  ->GetTraceInverseBoundaryMap(i);
349 
350  // Allocate temporary storage for the extracted face matrix.
351  const int nFaceCoeffs = bmap.size();
352  vector<NekDouble> tmpStore(nFaceCoeffs*nFaceCoeffs);
353 
354  gId = asmMap->GetLocalToGlobalMap(cnt + bmap[0]);
355 
356  for (j = 0; j < nFaceCoeffs; ++j)
357  {
358  gId = min(gId,
359  asmMap->GetLocalToGlobalMap(cnt + bmap[j])
360  - nDirBnd);
361 
362  // Ignore Dirichlet faces.
363  if (gId < 0)
364  {
365  continue;
366  }
367 
368  const NekDouble sign1 = sign[j];
369 
370  // Extract this face, along with sign array for assembly
371  // later.
372  for (k = 0; k < nFaceCoeffs; ++k)
373  {
374  tmpStore[k+j*nFaceCoeffs] =
375  sign1*sign[k]*(*schurMat)(bmap2[j], bmap2[k]);
376  }
377  }
378 
379  if (gId < 0)
380  {
381  continue;
382  }
383 
384  gidDofs[2][gId] = nFaceCoeffs;
385 
386  // Assemble this face matrix with another one, if it exists.
387  auto gIt = idMats[2].find(gId);
388  if (gIt == idMats[2].end())
389  {
390  idMats[2][gId] = tmpStore;
391  }
392  else
393  {
394  ASSERTL1(tmpStore.size() == gIt->second.size(),
395  "Number of modes mismatch");
396  Vmath::Vadd(nFaceCoeffs*nFaceCoeffs, &gIt->second[0], 1,
397  &tmpStore[0], 1, &gIt->second[0], 1);
398  }
399 
400  gidMeshIds[2][gId] = meshFaceId;
401  maxVertIds[4] = max(maxVertIds[4], meshFaceId);
402  maxVertIds[5] = max(maxVertIds[5], nFaceCoeffs);
403  }
404 
405  cnt += exp->GetNcoeffs();
406  }
407 
408  // Perform a reduction to find maximum vertex, edge and face
409  // geometry IDs.
410  m_comm = expList->GetSession()->GetComm()->GetRowComm();
411  m_comm->AllReduce(maxVertIds, LibUtilities::ReduceMax);
412 
413  // Concatenate all matrices into contiguous storage and figure out
414  // universal ID numbering.
415  vector<NekDouble> storageBuf;
416  vector<long> globalToUniversal;
417 
418  for (i = 0, cnt = 1; i < 3; ++i)
419  {
420  const int maxDofs = maxVertIds[2*i+1];
421 
422  // Note that iterating over the map uses the property that keys
423  // are accessed in order of ascending order, putting everything
424  // in the right order for the global system.
425  for (auto &gIt : idMats[i])
426  {
427  // Copy matrix into storage.
428  storageBuf.insert(storageBuf.end(),
429  gIt.second.begin(), gIt.second.end());
430 
431  // Get mesh ID from global ID number.
432  ASSERTL1(gidMeshIds[i].count(gIt.first) > 0,
433  "Unable to find global ID " +
434  boost::lexical_cast<string>(gIt.first) +
435  " inside map");
436  meshVertId = gidMeshIds[i][gIt.first];
437 
438  for (j = 0; j < gIt.second.size(); ++j)
439  {
440  globalToUniversal.push_back(
441  cnt + meshVertId*maxDofs*maxDofs + j);
442  }
443 
444  // Free up the temporary storage.
445  gIt.second.clear();
446  }
447 
448  cnt += (maxVertIds[2*i]+1)*maxDofs*maxDofs;
449  }
450 
451  ASSERTL1(storageBuf.size() == globalToUniversal.size(),
452  "Storage buffer and global to universal map size does "
453  "not match");
454 
455  Array<OneD, NekDouble> storageData(
456  storageBuf.size(), &storageBuf[0]);
457  Array<OneD, long> globalToUniversalMap(
458  globalToUniversal.size(), &globalToUniversal[0]);
459 
460  // Use GS to assemble data between processors.
461  Gs::gs_data *tmpGs = Gs::Init(
462  globalToUniversalMap, m_comm,
463  expList->GetSession()->DefinesCmdLineArgument("verbose"));
464  Gs::Gather(storageData, Gs::gs_add, tmpGs);
465 
466  // Figure out what storage we need in the block matrix.
467  Array<OneD, unsigned int> n_blks(
468  1 + idMats[1].size() + idMats[2].size());
469 
470  // Vertex block is a diagonal matrix.
471  n_blks[0] = idMats[0].size();
472 
473  // Now extract number of rows in each edge and face block from the
474  // gidDofs map.
475  cnt = 1;
476  for (i = 1; i < 3; ++i)
477  {
478  for (auto &gIt : idMats[i])
479  {
480  ASSERTL1(gidDofs[i].count(gIt.first) > 0,
481  "Unable to find number of degrees of freedom for "
482  "global ID " + boost::lexical_cast<string>(
483  gIt.first));
484 
485  n_blks[cnt++] = gidDofs[i][gIt.first];
486  }
487  }
488 
489  // Allocate storage for the block matrix.
491  ::AllocateSharedPtr(n_blks, n_blks, eDIAGONAL);
492 
493  // We deal with the vertex matrix separately since all vertices can
494  // be condensed into a single, block-diagonal matrix.
496  ::AllocateSharedPtr(n_blks[0], n_blks[0], 0.0, eDIAGONAL);
497 
498  // Fill the vertex matrix with the inverse of each vertex value.
499  cnt = 0;
500  for (auto gIt = idMats[0].begin(); gIt != idMats[0].end();
501  ++gIt, ++cnt)
502  {
503  (*vertMat)(cnt, cnt) = 1.0/storageData[cnt];
504  }
505 
506  // Put the vertex matrix in the block matrix.
507  m_blkMat->SetBlock(0,0,vertMat);
508 
509  // Finally, grab the matrices from the block storage, invert them
510  // and place them in the correct position inside the block matrix.
511  int cnt2 = 1;
512  for (i = 1; i < 3; ++i)
513  {
514  for (auto &gIt : idMats[i])
515  {
516  int nDofs = gidDofs[i][gIt.first];
517 
519  ::AllocateSharedPtr(nDofs, nDofs);
520 
521  for (j = 0; j < nDofs; ++j)
522  {
523  for (k = 0; k < nDofs; ++k)
524  {
525  (*tmp)(j,k) = storageData[k+j*nDofs + cnt];
526  }
527  }
528 
529  cnt += nDofs*nDofs;
530 
531  tmp->Invert();
532  m_blkMat->SetBlock(cnt2, cnt2, tmp);
533  ++cnt2;
534  }
535  }
536  }
#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.
LibUtilities::CommSharedPtr m_comm
const std::weak_ptr< GlobalLinSys > m_linsys
std::weak_ptr< AssemblyMap > m_locToGloMap
static void Gather(Nektar::Array< OneD, NekDouble > pU, gs_op pOp, gs_data *pGsh, Nektar::Array< OneD, NekDouble > pBuffer=NullNekDouble1DArray)
Performs a gather-scatter operation of the provided values.
Definition: GsLib.hpp:245
@ gs_add
Definition: GsLib.hpp:53
static gs_data * Init(const Nektar::Array< OneD, long > pId, const LibUtilities::CommSharedPtr &pComm, bool verbose=true)
Initialise Gather-Scatter map.
Definition: GsLib.hpp:167
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
pair< int, StdRegions::Orientation > DeterminePeriodicEdgeOrientId(int meshEdgeId, StdRegions::Orientation edgeOrient, const vector< PeriodicEntity > &periodicEdges)
Determine orientation of an edge to its periodic equivalents, as well as the ID of the representative...
std::map< int, std::vector< PeriodicEntity > > PeriodicMap
StdRegions::Orientation DeterminePeriodicFaceOrient(StdRegions::Orientation faceOrient, StdRegions::Orientation perFaceOrient)
Determine relative orientation between two faces.
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
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

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL1, Nektar::MultiRegions::DeterminePeriodicEdgeOrientId(), Nektar::MultiRegions::DeterminePeriodicFaceOrient(), Nektar::eDIAGONAL, Gs::Gather(), Gs::gs_add, Gs::Init(), m_blkMat, Nektar::MultiRegions::Preconditioner::m_comm, Nektar::MultiRegions::Preconditioner::m_linsys, Nektar::MultiRegions::Preconditioner::m_locToGloMap, Nektar::LibUtilities::ReduceMax, sign, and Vmath::Vadd().

Referenced by v_BuildPreconditioner().

◆ BlockPreconditionerHDG()

void Nektar::MultiRegions::PreconditionerBlock::BlockPreconditionerHDG ( void  )
private

Construct a block preconditioner for the hybridized discontinuous Galerkin system.

This system is built in a similar fashion to its continuous variant found in PreconditionerBlock::BlockPreconditionerCG. In this setting however, the matrix is constructed as:

\[ M^{-1} = \mathrm{Diag}[ (\mathbf{S_{1}})_{f}^{-1} ] \]

where each matrix is the Schur complement system restricted to a single face of the trace system.

Definition at line 551 of file PreconditionerBlock.cpp.

552  {
553  std::shared_ptr<MultiRegions::ExpList>
554  expList = ((m_linsys.lock())->GetLocMat()).lock();
555  std::shared_ptr<MultiRegions::ExpList> trace = expList->GetTrace();
557  DNekScalBlkMatSharedPtr loc_mat;
558  DNekScalMatSharedPtr bnd_mat;
559 
560  AssemblyMapDGSharedPtr asmMap = std::dynamic_pointer_cast<
561  AssemblyMapDG>(m_locToGloMap.lock());
562 
563  int i, j, k, n, cnt, cnt2;
564 
565  // Figure out number of Dirichlet trace elements
566  int nTrace = expList->GetTrace()->GetExpSize();
567  int nDir = asmMap->GetNumGlobalDirBndCoeffs();
568 
569  for (cnt = n = 0; n < nTrace; ++n)
570  {
571  if (cnt >= nDir)
572  {
573  break;
574  }
575 
576  cnt += trace->GetExp(n)->GetNcoeffs();
577  }
578 
579  nDir = n;
580 
581  // Allocate storage for block matrix. Need number of unique faces in
582  // trace space.
583  int maxTraceSize = -1;
584  map<int, int> arrayOffsets;
585 
586  for (cnt = 0, n = nDir; n < nTrace; ++n)
587  {
588  int nCoeffs = trace->GetExp(n)->GetNcoeffs();
589  int nCoeffs2 = nCoeffs * nCoeffs;
590 
591  arrayOffsets[n] = cnt;
592  cnt += nCoeffs2;
593 
594  if (maxTraceSize < nCoeffs2)
595  {
596  maxTraceSize = nCoeffs2;
597  }
598  }
599 
600  // Find maximum trace size.
601  m_comm = expList->GetSession()->GetComm()->GetRowComm();
602  m_comm->AllReduce(maxTraceSize, LibUtilities::ReduceMax);
603 
604  // Zero matrix storage.
605  Array<OneD, NekDouble> tmpStore(cnt, 0.0);
606 
607  // Assemble block matrices for each trace element.
608  for (cnt = n = 0; n < expList->GetExpSize(); ++n)
609  {
610  int elmt = n;
611  locExpansion = expList->GetExp(elmt);
612 
613  Array<OneD, LocalRegions::ExpansionSharedPtr> &elmtToTraceMap =
614  asmMap->GetElmtToTrace()[elmt];
615 
616  // Block matrix (lambda)
617  loc_mat = (m_linsys.lock())->GetStaticCondBlock(n);
618  bnd_mat = loc_mat->GetBlock(0,0);
619 
620  int nFacets = locExpansion->GetNtraces();
621 
622  for (cnt2 = i = 0; i < nFacets; ++i)
623  {
624  int nCoeffs = elmtToTraceMap[i]->GetNcoeffs();
625  int elmtId = elmtToTraceMap[i]->GetElmtId ();
626 
627  // Ignore Dirichlet edges.
628  if (elmtId < nDir)
629  {
630  cnt += nCoeffs;
631  cnt2 += nCoeffs;
632  continue;
633  }
634 
635  NekDouble *off = &tmpStore[arrayOffsets[elmtId]];
636 
637  for (j = 0; j < nCoeffs; ++j)
638  {
639  NekDouble sign1 = asmMap->GetLocalToGlobalBndSign(
640  cnt + j);
641  for (k = 0; k < nCoeffs; ++k)
642  {
643  NekDouble sign2 = asmMap->GetLocalToGlobalBndSign(
644  cnt + k);
645  off[j*nCoeffs + k] +=
646  (*bnd_mat)(cnt2+j, cnt2+k) * sign1 * sign2;
647  }
648  }
649 
650  cnt += nCoeffs;
651  cnt2 += nCoeffs;
652  }
653  }
654 
655  // Set up IDs for universal numbering.
656  Array<OneD, long> uniIds(tmpStore.size());
657  for (cnt = 0, n = nDir; n < nTrace; ++n)
658  {
659  LocalRegions::ExpansionSharedPtr traceExp = trace->GetExp(n);
660  int nCoeffs = traceExp->GetNcoeffs();
661  int geomId = traceExp->GetGeom()->GetGlobalID();
662 
663  for (i = 0; i < nCoeffs*nCoeffs; ++i)
664  {
665  uniIds[cnt++] = geomId * maxTraceSize + i + 1;
666  }
667  }
668 
669  // Assemble matrices across partitions.
670  Gs::gs_data *gsh = Gs::Init(
671  uniIds, m_comm,
672  expList->GetSession()->DefinesCmdLineArgument("verbose"));
673  Gs::Gather(tmpStore, Gs::gs_add, gsh);
674 
675  // Set up diagonal block matrix
676  Array<OneD, unsigned int> n_blks(nTrace - nDir);
677  for (n = 0; n < nTrace - nDir; ++n)
678  {
679  n_blks[n] = trace->GetExp(n + nDir)->GetNcoeffs();
680  }
681 
683  ::AllocateSharedPtr(n_blks, n_blks, eDIAGONAL);
684 
685  for (n = 0; n < nTrace - nDir; ++n)
686  {
687  int nCoeffs = trace->GetExp(n + nDir)->GetNcoeffs();
689  ::AllocateSharedPtr(nCoeffs, nCoeffs);
690  NekDouble *off = &tmpStore[arrayOffsets[n+nDir]];
691 
692  for (i = 0; i < nCoeffs; ++i)
693  {
694  for (j = 0; j < nCoeffs; ++j)
695  {
696  (*tmp)(i,j) = off[i*nCoeffs + j];
697  }
698  }
699 
700  tmp->Invert();
701  m_blkMat->SetBlock(n, n, tmp);
702  }
703  }
std::shared_ptr< AssemblyMapDG > AssemblyMapDGSharedPtr
Definition: AssemblyMapDG.h:47

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::eDIAGONAL, Gs::Gather(), Nektar::MultiRegions::AssemblyMap::GetNumGlobalDirBndCoeffs(), Gs::gs_add, Gs::Init(), m_blkMat, Nektar::MultiRegions::Preconditioner::m_comm, Nektar::MultiRegions::Preconditioner::m_linsys, Nektar::MultiRegions::Preconditioner::m_locToGloMap, and Nektar::LibUtilities::ReduceMax.

Referenced by v_BuildPreconditioner().

◆ create()

static PreconditionerSharedPtr Nektar::MultiRegions::PreconditionerBlock::create ( const std::shared_ptr< GlobalLinSys > &  plinsys,
const std::shared_ptr< AssemblyMap > &  pLocToGloMap 
)
inlinestatic

Creates an instance of this class.

Definition at line 55 of file PreconditionerBlock.h.

58  {
60  ::AllocateSharedPtr(plinsys,pLocToGloMap);
61  p->InitObject();
62  return p;
63  }
std::shared_ptr< Preconditioner > PreconditionerSharedPtr
Definition: GlobalLinSys.h:60

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), and CellMLToNektar.cellml_metadata::p.

◆ v_BuildPreconditioner()

void Nektar::MultiRegions::PreconditionerBlock::v_BuildPreconditioner ( )
privatevirtual

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 82 of file PreconditionerBlock.cpp.

83  {
84  GlobalLinSysKey key = m_linsys.lock()->GetKey();
85 
86  // Different setup for HDG and CG.
87  if (key.GetMatrixType() == StdRegions::eHybridDGHelmBndLam)
88  {
90  }
91  else
92  {
94  }
95  }
void BlockPreconditionerCG(void)
Construct a block preconditioner from for the continuous Galerkin system.
void BlockPreconditionerHDG(void)
Construct a block preconditioner for the hybridized discontinuous Galerkin system.

References BlockPreconditionerCG(), BlockPreconditionerHDG(), Nektar::StdRegions::eHybridDGHelmBndLam, Nektar::MultiRegions::GlobalMatrixKey::GetMatrixType(), and Nektar::MultiRegions::Preconditioner::m_linsys.

◆ v_DoPreconditioner()

void Nektar::MultiRegions::PreconditionerBlock::v_DoPreconditioner ( const Array< OneD, NekDouble > &  pInput,
Array< OneD, NekDouble > &  pOutput 
)
privatevirtual

Apply preconditioner to pInput and store the result in pOutput.

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 709 of file PreconditionerBlock.cpp.

712  {
713  int nDir = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
714  int nGlobal = m_locToGloMap.lock()->GetNumGlobalBndCoeffs();
715  int nNonDir = nGlobal-nDir;
716  DNekBlkMat &M = (*m_blkMat);
717  NekVector<NekDouble> r(nNonDir,pInput,eWrapper);
718  NekVector<NekDouble> z(nNonDir,pOutput,eWrapper);
719  z = M * r;
720  }
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, BlockMatrixTag > DNekBlkMat
Definition: NekTypeDefs.hpp:59

References Nektar::eWrapper, and Nektar::MultiRegions::Preconditioner::m_locToGloMap.

◆ v_InitObject()

void Nektar::MultiRegions::PreconditionerBlock::v_InitObject ( )
privatevirtual

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 73 of file PreconditionerBlock.cpp.

74  {
75  GlobalSysSolnType solvertype =
76  m_locToGloMap.lock()->GetGlobalSysSolnType();
78  solvertype == MultiRegions::ePETScStaticCond,
79  "Solver type not valid");
80  }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216

References ASSERTL0, Nektar::MultiRegions::eIterativeStaticCond, Nektar::MultiRegions::ePETScStaticCond, and Nektar::MultiRegions::Preconditioner::m_locToGloMap.

Member Data Documentation

◆ className

string Nektar::MultiRegions::PreconditionerBlock::className
static
Initial value:
"Block",
"Block Diagonal Preconditioning")
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:200
static PreconditionerSharedPtr create(const std::shared_ptr< GlobalLinSys > &plinsys, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Creates an instance of this class.
PreconFactory & GetPreconFactory()

Name of class.

Registers the class with the Factory.

Definition at line 66 of file PreconditionerBlock.h.

◆ m_blkMat

DNekBlkMatSharedPtr Nektar::MultiRegions::PreconditionerBlock::m_blkMat
protected

Definition at line 76 of file PreconditionerBlock.h.

Referenced by BlockPreconditionerCG(), and BlockPreconditionerHDG().