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 50 of file PreconditionerBlock.h.

Constructor & Destructor Documentation

◆ PreconditionerBlock()

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

Definition at line 64 of file PreconditionerBlock.cpp.

67  : Preconditioner(plinsys, pLocToGloMap)
68 {
69 }
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.

74  {
75  }

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 110 of file PreconditionerBlock.cpp.

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

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 538 of file PreconditionerBlock.cpp.

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

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), 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, 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 54 of file PreconditionerBlock.h.

57  {
60  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 79 of file PreconditionerBlock.cpp.

80 {
81  GlobalLinSysKey key = m_linsys.lock()->GetKey();
82 
83  // Different setup for HDG and CG.
84  if (key.GetMatrixType() == StdRegions::eHybridDGHelmBndLam)
85  {
87  }
88  else
89  {
91  }
92 }
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 694 of file PreconditionerBlock.cpp.

696 {
697  int nDir = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
698  int nGlobal = m_locToGloMap.lock()->GetNumGlobalBndCoeffs();
699  int nNonDir = nGlobal - nDir;
700  DNekBlkMat &M = (*m_blkMat);
701  NekVector<NekDouble> r(nNonDir, pInput, eWrapper);
702  NekVector<NekDouble> z(nNonDir, pOutput, eWrapper);
703  z = M * r;
704 }
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, BlockMatrixTag > DNekBlkMat
Definition: NekTypeDefs.hpp:58

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 71 of file PreconditionerBlock.cpp.

72 {
73  GlobalSysSolnType solvertype = m_locToGloMap.lock()->GetGlobalSysSolnType();
75  solvertype == MultiRegions::ePETScStaticCond,
76  "Solver type not valid");
77 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215

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", PreconditionerBlock::create, "Block Diagonal Preconditioning")
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
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 78 of file PreconditionerBlock.h.

Referenced by BlockPreconditionerCG(), and BlockPreconditionerHDG().