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

#include <PreconditionerLowEnergy.h>

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

Public Member Functions

 PreconditionerLowEnergy (const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)
 
virtual ~PreconditionerLowEnergy ()
 
- 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 DoTransformToLowEnergy (Array< OneD, NekDouble > &pInOut, int offset)
 
void DoTransformToLowEnergy (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 
void DoTransformFromLowEnergy (Array< OneD, NekDouble > &pInOut)
 
void DoMultiplybyInverseTransformationMatrix (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 
void DoMultiplybyInverseTransposedTransformationMatrix (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
 
DNekBlkMatSharedPtr m_RBlk
 
DNekBlkMatSharedPtr m_InvRBlk
 
Array< OneD, NekDoublem_locToGloSignMult
 
Array< OneD, NekDoublem_multiplicity
 
Array< OneD, int > m_map
 
bool m_signChange
 
std::vector< std::pair< int, int > > m_sameBlock
 
- 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 Types

typedef std::map< LibUtilities::ShapeType, DNekScalMatSharedPtrShapeToDNekMap
 
typedef std::map< LibUtilities::ShapeType, LocalRegions::ExpansionSharedPtrShapeToExpMap
 
typedef std::map< LibUtilities::ShapeType, Array< OneD, unsigned int > > ShapeToIntArrayMap
 
typedef std::map< LibUtilities::ShapeType, Array< OneD, Array< OneD, unsigned int > > > ShapeToIntArrayArrayMap
 

Private Member Functions

void SetupBlockTransformationMatrix (void)
 
void SetUpReferenceElements (ShapeToDNekMap &maxRmat, ShapeToExpMap &maxElmt, ShapeToIntArrayMap &vertMapMaxR, ShapeToIntArrayArrayMap &edgeMapMaxR)
 Loop expansion and determine different variants of the transformation matrix. More...
 
void SetUpPyrMaxRMat (int nummodesmax, LocalRegions::PyrExpSharedPtr &PyrExp, ShapeToDNekMap &maxRmat, ShapeToIntArrayMap &vertMapMaxR, ShapeToIntArrayArrayMap &edgeMapMaxR, ShapeToIntArrayArrayMap &faceMapMaxR)
 
void ReSetTetMaxRMat (int nummodesmax, LocalRegions::TetExpSharedPtr &TetExp, ShapeToDNekMap &maxRmat, ShapeToIntArrayMap &vertMapMaxR, ShapeToIntArrayArrayMap &edgeMapMaxR, ShapeToIntArrayArrayMap &faceMapMaxR)
 
void ReSetPrismMaxRMat (int nummodesmax, LocalRegions::PrismExpSharedPtr &PirsmExp, ShapeToDNekMap &maxRmat, ShapeToIntArrayMap &vertMapMaxR, ShapeToIntArrayArrayMap &edgeMapMaxR, ShapeToIntArrayArrayMap &faceMapMaxR, bool UseTetOnly)
 
DNekMatSharedPtr ExtractLocMat (StdRegions::StdExpansionSharedPtr &locExp, DNekScalMatSharedPtr &maxRmat, LocalRegions::ExpansionSharedPtr &expMax, Array< OneD, unsigned int > &vertMapMaxR, Array< OneD, Array< OneD, unsigned int > > &edgeMapMaxR)
 
void CreateMultiplicityMap (void)
 
SpatialDomains::TetGeomSharedPtr CreateRefTetGeom (void)
 Sets up the reference tretrahedral element needed to construct a low energy basis. More...
 
SpatialDomains::PyrGeomSharedPtr CreateRefPyrGeom (void)
 Sets up the reference prismatic element needed to construct a low energy basis mapping arrays. More...
 
SpatialDomains::PrismGeomSharedPtr CreateRefPrismGeom (void)
 Sets up the reference prismatic element needed to construct a low energy basis. More...
 
SpatialDomains::HexGeomSharedPtr CreateRefHexGeom (void)
 Sets up the reference hexahedral element needed to construct a low energy basis. More...
 
virtual void v_InitObject ()
 
virtual void v_DoPreconditioner (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 
virtual void v_DoTransformToLowEnergy (Array< OneD, NekDouble > &pInOut, int offset)
 Transform the solution vector vector to low energy. More...
 
virtual void v_DoTransformToLowEnergy (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 Transform the solution vector to low energy form. More...
 
virtual void v_DoTransformFromLowEnergy (Array< OneD, NekDouble > &pInOut)
 transform the solution vector from low energy back to the original basis. More...
 
virtual void v_DoMultiplybyInverseTransformationMatrix (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 Multiply by the block inverse transformation matrix. More...
 
virtual void v_DoMultiplybyInverseTransposedTransformationMatrix (const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
 Multiply by the block tranposed inverse transformation matrix. More...
 
virtual void v_BuildPreconditioner ()
 Construct the low energy preconditioner from \(\mathbf{S}_{2}\). More...
 
virtual DNekScalMatSharedPtr v_TransformedSchurCompl (int n, int offset, const std::shared_ptr< DNekScalMat > &loc_mat)
 Set up the transformed block matrix system. More...
 

Additional Inherited Members

Detailed Description

This class implements low energy preconditioning for the conjugate gradient matrix solver.

Definition at line 53 of file PreconditionerLowEnergy.h.

Member Typedef Documentation

◆ ShapeToDNekMap

Definition at line 98 of file PreconditionerLowEnergy.h.

◆ ShapeToExpMap

Definition at line 100 of file PreconditionerLowEnergy.h.

◆ ShapeToIntArrayArrayMap

Definition at line 105 of file PreconditionerLowEnergy.h.

◆ ShapeToIntArrayMap

Definition at line 102 of file PreconditionerLowEnergy.h.

Constructor & Destructor Documentation

◆ PreconditionerLowEnergy()

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

Definition at line 67 of file PreconditionerLowEnergy.cpp.

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

◆ ~PreconditionerLowEnergy()

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

Definition at line 74 of file PreconditionerLowEnergy.h.

74 {}

Member Function Documentation

◆ create()

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

Creates an instance of this class.

Definition at line 57 of file PreconditionerLowEnergy.h.

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

60  {
62  p->InitObject();
63  return p;
64  }
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::shared_ptr< Preconditioner > PreconditionerSharedPtr
Definition: GlobalLinSys.h:60

◆ CreateMultiplicityMap()

void Nektar::MultiRegions::PreconditionerLowEnergy::CreateMultiplicityMap ( void  )
private

Create the inverse multiplicity map.

Definition at line 1441 of file PreconditionerLowEnergy.cpp.

References CG_Iterations::loc, Nektar::MultiRegions::Preconditioner::m_locToGloMap, m_locToGloSignMult, m_multiplicity, m_signChange, Vmath::Sdiv(), and sign.

Referenced by v_InitObject().

1442  {
1443  auto asmMap = m_locToGloMap.lock();
1444 
1445  unsigned int nGlobalBnd = asmMap->GetNumGlobalBndCoeffs();
1446  unsigned int nEntries = asmMap->GetNumLocalBndCoeffs();
1447  unsigned int i;
1448 
1449  const Array<OneD, const int> &vMap
1450  = asmMap->GetLocalToGlobalBndMap();
1451 
1452  const Array< OneD, const NekDouble > &sign
1453  = asmMap->GetLocalToGlobalBndSign();
1454 
1455  m_signChange=asmMap->GetSignChange();
1456 
1457  // Count the multiplicity of each global DOF on this process
1458  Array<OneD, NekDouble> vCounts(nGlobalBnd, 0.0);
1459  if(m_signChange)
1460  {
1461  for (i = 0; i < nEntries; ++i)
1462  {
1463  if(fabs(sign[i]) > 0.0)
1464  {
1465  vCounts[vMap[i]] += 1.0;
1466  }
1467  else // set zero modes to 1 so inverse below does not cause problems
1468  {
1469  vCounts[vMap[i]] = 1.0;
1470  }
1471  }
1472  }
1473  else
1474  {
1475  for (i = 0; i < nEntries; ++i)
1476  {
1477  vCounts[vMap[i]] += 1.0;
1478  }
1479  }
1480 
1481  // Get universal multiplicity by globally assembling counts
1482  asmMap->UniversalAssembleBnd(vCounts);
1483 
1484  // Construct a map of 1/multiplicity
1485  m_locToGloSignMult = Array<OneD, NekDouble>(nEntries);
1486  for (i = 0; i < nEntries; ++i)
1487  {
1488  if(m_signChange)
1489  {
1490  m_locToGloSignMult[i] = sign[i]*1.0/vCounts[vMap[i]];
1491  }
1492  else
1493  {
1494  m_locToGloSignMult[i] = 1.0/vCounts[vMap[i]];
1495  }
1496  }
1497 
1498  int nDirBnd = asmMap->GetNumGlobalDirBndCoeffs();
1499  int nGlobHomBnd = nGlobalBnd - nDirBnd;
1500  int nLocBnd = asmMap->GetNumLocalBndCoeffs();
1501 
1502  //Set up multiplicity array for inverse transposed transformation matrix
1503  Array<OneD,NekDouble> tmp(nGlobHomBnd,1.0);
1504  m_multiplicity = Array<OneD,NekDouble>(nGlobHomBnd,1.0);
1505  Array<OneD,NekDouble> loc(nLocBnd,1.0);
1506 
1507  asmMap->GlobalToLocalBnd(tmp,loc, nDirBnd);
1508  asmMap->AssembleBnd(loc,m_multiplicity, nDirBnd);
1509  Vmath::Sdiv(nGlobHomBnd,1.0,m_multiplicity,1,m_multiplicity,1);
1510 
1511  }
#define sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:16
void Sdiv(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha/y.
Definition: Vmath.cpp:274
std::weak_ptr< AssemblyMap > m_locToGloMap

◆ CreateRefHexGeom()

SpatialDomains::HexGeomSharedPtr Nektar::MultiRegions::PreconditionerLowEnergy::CreateRefHexGeom ( void  )
private

Sets up the reference hexahedral element needed to construct a low energy basis.

Definition at line 1767 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr().

Referenced by SetUpReferenceElements().

1768  {
1769  ////////////////////////////////
1770  // Set up Hexahedron vertices //
1771  ////////////////////////////////
1772 
1773  const int three=3;
1774 
1775  const int nVerts = 8;
1776  const double point[][3] = {
1777  {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0},
1778  {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1}
1779  };
1780 
1781  // Populate the list of verts
1783  for( int i = 0; i < nVerts; ++i ) {
1785  ::AllocateSharedPtr(three, i, point[i][0],
1786  point[i][1], point[i][2]);
1787  }
1788 
1789  /////////////////////////////
1790  // Set up Hexahedron Edges //
1791  /////////////////////////////
1792 
1793  // SegGeom (int id, const int coordim), EdgeComponent(id, coordim)
1794  const int nEdges = 12;
1795  const int vertexConnectivity[][2] = {
1796  {0,1}, {1,2}, {2,3}, {0,3}, {0,4}, {1,5},
1797  {2,6}, {3,7}, {4,5}, {5,6}, {6,7}, {4,7}
1798  };
1799 
1800  // Populate the list of edges
1801  SpatialDomains::SegGeomSharedPtr edges[nEdges];
1802  for( int i = 0; i < nEdges; ++i ) {
1803  SpatialDomains::PointGeomSharedPtr vertsArray[2];
1804  for( int j = 0; j < 2; ++j ) {
1805  vertsArray[j] = verts[vertexConnectivity[i][j]];
1806  }
1808  AllocateSharedPtr( i, three, vertsArray);
1809  }
1810 
1811  /////////////////////////////
1812  // Set up Hexahedron faces //
1813  /////////////////////////////
1814 
1815  const int nFaces = 6;
1816  const int edgeConnectivity[][4] = {
1817  {0,1,2,3}, {0,5,8,4}, {1,6,9,5},
1818  {2,7,10,6}, {3,7,11,4}, {8,9,10,11}
1819  };
1820 
1821  // Populate the list of faces
1822  SpatialDomains::QuadGeomSharedPtr faces[nFaces];
1823  for( int i = 0; i < nFaces; ++i ) {
1824  SpatialDomains::SegGeomSharedPtr edgeArray[4];
1825  for( int j = 0; j < 4; ++j ) {
1826  edgeArray[j] = edges[edgeConnectivity[i][j]];
1827  }
1829  }
1830 
1833  (0, faces);
1834 
1835  return geom;
1836  }
std::shared_ptr< QuadGeom > QuadGeomSharedPtr
Definition: HexGeom.h:46
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::shared_ptr< PointGeom > PointGeomSharedPtr
Definition: Geometry.h:59
bg::model::point< double, 3, bg::cs::cartesian > point
Definition: BLMesh.cpp:53
std::shared_ptr< HexGeom > HexGeomSharedPtr
Definition: HexGeom.h:90
std::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:62

◆ CreateRefPrismGeom()

SpatialDomains::PrismGeomSharedPtr Nektar::MultiRegions::PreconditionerLowEnergy::CreateRefPrismGeom ( void  )
private

Sets up the reference prismatic element needed to construct a low energy basis.

Definition at line 1517 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr().

Referenced by SetUpReferenceElements().

1518  {
1519  //////////////////////////
1520  // Set up Prism element //
1521  //////////////////////////
1522 
1523  const int three=3;
1524  const int nVerts = 6;
1525  const double point[][3] = {
1526  {-1,-1,0}, {1,-1,0}, {1,1,0},
1527  {-1,1,0}, {0,-1,sqrt(double(3))}, {0,1,sqrt(double(3))},
1528  };
1529 
1530  //std::shared_ptr<SpatialDomains::PointGeom> verts[6];
1532  for(int i=0; i < nVerts; ++i)
1533  {
1535  ( three, i, point[i][0], point[i][1], point[i][2] );
1536  }
1537  const int nEdges = 9;
1538  const int vertexConnectivity[][2] = {
1539  {0,1}, {1,2}, {3,2}, {0,3}, {0,4},
1540  {1,4}, {2,5}, {3,5}, {4,5}
1541  };
1542 
1543  // Populate the list of edges
1544  SpatialDomains::SegGeomSharedPtr edges[nEdges];
1545  for(int i=0; i < nEdges; ++i){
1546  SpatialDomains::PointGeomSharedPtr vertsArray[2];
1547  for(int j=0; j<2; ++j)
1548  {
1549  vertsArray[j] = verts[vertexConnectivity[i][j]];
1550  }
1551  edges[i] = MemoryManager<SpatialDomains::SegGeom>::AllocateSharedPtr(i, three, vertsArray);
1552  }
1553 
1554  ////////////////////////
1555  // Set up Prism faces //
1556  ////////////////////////
1557 
1558  const int nFaces = 5;
1559  //quad-edge connectivity base-face0, vertical-quadface2, vertical-quadface4
1560  const int quadEdgeConnectivity[][4] = { {0,1,2,3}, {1,6,8,5}, {3,7,8,4} };
1561  // QuadId ordered as 0, 1, 2, otherwise return false
1562  const int quadId[] = { 0,-1,1,-1,2 };
1563 
1564  //triangle-edge connectivity side-triface-1, side triface-3
1565  const int triEdgeConnectivity[][3] = { {0,5,4}, {2,6,7} };
1566  // TriId ordered as 0, 1, otherwise return false
1567  const int triId[] = { -1,0,-1,1,-1 };
1568 
1569  // Populate the list of faces
1570  SpatialDomains::Geometry2DSharedPtr faces[nFaces];
1571  for(int f = 0; f < nFaces; ++f){
1572  if(f == 1 || f == 3) {
1573  int i = triId[f];
1574  SpatialDomains::SegGeomSharedPtr edgeArray[3];
1575  for(int j = 0; j < 3; ++j){
1576  edgeArray[j] = edges[triEdgeConnectivity[i][j]];
1577  }
1579  }
1580  else {
1581  int i = quadId[f];
1582  SpatialDomains::SegGeomSharedPtr edgeArray[4];
1583  for(int j=0; j < 4; ++j){
1584  edgeArray[j] = edges[quadEdgeConnectivity[i][j]];
1585  }
1587  }
1588  }
1589 
1591 
1592  return geom;
1593  }
std::shared_ptr< Geometry2D > Geometry2DSharedPtr
Definition: Geometry.h:65
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::shared_ptr< PointGeom > PointGeomSharedPtr
Definition: Geometry.h:59
bg::model::point< double, 3, bg::cs::cartesian > point
Definition: BLMesh.cpp:53
std::shared_ptr< PrismGeom > PrismGeomSharedPtr
Definition: PrismGeom.h:88
std::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:62

◆ CreateRefPyrGeom()

SpatialDomains::PyrGeomSharedPtr Nektar::MultiRegions::PreconditionerLowEnergy::CreateRefPyrGeom ( void  )
private

Sets up the reference prismatic element needed to construct a low energy basis mapping arrays.

Definition at line 1599 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr().

Referenced by SetUpReferenceElements().

1600  {
1601  //////////////////////////
1602  // Set up Pyramid element //
1603  //////////////////////////
1604 
1605  const int nVerts = 5;
1606  const double point[][3] = {
1607  {-1,-1,0}, {1,-1,0}, {1,1,0},
1608  {-1,1,0}, {0,0,sqrt(double(2))}
1609  };
1610 
1611  //boost::shared_ptr<SpatialDomains::PointGeom> verts[6];
1612  const int three=3;
1614  for(int i=0; i < nVerts; ++i)
1615  {
1617  ( three, i, point[i][0], point[i][1], point[i][2] );
1618  }
1619  const int nEdges = 8;
1620  const int vertexConnectivity[][2] = {
1621  {0,1}, {1,2}, {2,3}, {3,0},
1622  {0,4}, {1,4}, {2,4}, {3,4}
1623  };
1624 
1625  // Populate the list of edges
1626  SpatialDomains::SegGeomSharedPtr edges[nEdges];
1627  for(int i=0; i < nEdges; ++i)
1628  {
1629  SpatialDomains::PointGeomSharedPtr vertsArray[2];
1630  for(int j=0; j<2; ++j)
1631  {
1632  vertsArray[j] = verts[vertexConnectivity[i][j]];
1633  }
1634  edges[i] = MemoryManager<SpatialDomains::SegGeom>::AllocateSharedPtr(i, three, vertsArray);
1635  }
1636 
1637  ////////////////////////
1638  // Set up Pyramid faces //
1639  ////////////////////////
1640 
1641  const int nFaces = 5;
1642  //quad-edge connectivity base-face0,
1643  const int quadEdgeConnectivity[][4] = {{0,1,2,3}};
1644 
1645  //triangle-edge connectivity side-triface-1, side triface-2
1646  const int triEdgeConnectivity[][3] = { {0,5,4}, {1,6,5}, {2,7,6}, {3,4,7}};
1647 
1648  // Populate the list of faces
1649  SpatialDomains::Geometry2DSharedPtr faces[nFaces];
1650  for(int f = 0; f < nFaces; ++f)
1651  {
1652  if(f == 0)
1653  {
1654  SpatialDomains::SegGeomSharedPtr edgeArray[4];
1655  for(int j=0; j < 4; ++j)
1656  {
1657  edgeArray[j] = edges[quadEdgeConnectivity[f][j]];
1658  }
1659 
1661  }
1662  else {
1663  int i = f-1;
1664  SpatialDomains::SegGeomSharedPtr edgeArray[3];
1665  for(int j = 0; j < 3; ++j)
1666  {
1667  edgeArray[j] = edges[triEdgeConnectivity[i][j]];
1668  }
1670  }
1671  }
1672 
1675 
1676  return geom;
1677  }
std::shared_ptr< Geometry2D > Geometry2DSharedPtr
Definition: Geometry.h:65
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::shared_ptr< PointGeom > PointGeomSharedPtr
Definition: Geometry.h:59
bg::model::point< double, 3, bg::cs::cartesian > point
Definition: BLMesh.cpp:53
std::shared_ptr< PyrGeom > PyrGeomSharedPtr
Definition: PyrGeom.h:80
std::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:62

◆ CreateRefTetGeom()

SpatialDomains::TetGeomSharedPtr Nektar::MultiRegions::PreconditionerLowEnergy::CreateRefTetGeom ( void  )
private

Sets up the reference tretrahedral element needed to construct a low energy basis.

Definition at line 1683 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr().

Referenced by SetUpReferenceElements().

1684  {
1685  /////////////////////////////////
1686  // Set up Tetrahedron vertices //
1687  /////////////////////////////////
1688 
1689  int i,j;
1690  const int three=3;
1691  const int nVerts = 4;
1692  const double point[][3] = {
1693  {-1,-1/sqrt(double(3)),-1/sqrt(double(6))},
1694  {1,-1/sqrt(double(3)),-1/sqrt(double(6))},
1695  {0,2/sqrt(double(3)),-1/sqrt(double(6))},
1696  {0,0,3/sqrt(double(6))}};
1697 
1698  std::shared_ptr<SpatialDomains::PointGeom> verts[4];
1699  for(i=0; i < nVerts; ++i)
1700  {
1701  verts[i] =
1704  ( three, i, point[i][0], point[i][1], point[i][2] );
1705  }
1706 
1707  //////////////////////////////
1708  // Set up Tetrahedron Edges //
1709  //////////////////////////////
1710 
1711  // SegGeom (int id, const int coordim), EdgeComponent(id, coordim)
1712  const int nEdges = 6;
1713  const int vertexConnectivity[][2] = {
1714  {0,1},{1,2},{0,2},{0,3},{1,3},{2,3}
1715  };
1716 
1717  // Populate the list of edges
1718  SpatialDomains::SegGeomSharedPtr edges[nEdges];
1719  for(i=0; i < nEdges; ++i)
1720  {
1721  std::shared_ptr<SpatialDomains::PointGeom>
1722  vertsArray[2];
1723  for(j=0; j<2; ++j)
1724  {
1725  vertsArray[j] = verts[vertexConnectivity[i][j]];
1726  }
1727 
1729  ::AllocateSharedPtr(i, three, vertsArray);
1730  }
1731 
1732  //////////////////////////////
1733  // Set up Tetrahedron faces //
1734  //////////////////////////////
1735 
1736  const int nFaces = 4;
1737  const int edgeConnectivity[][3] = {
1738  {0,1,2}, {0,4,3}, {1,5,4}, {2,5,3}
1739  };
1740 
1741  // Populate the list of faces
1742  SpatialDomains::TriGeomSharedPtr faces[nFaces];
1743  for(i=0; i < nFaces; ++i)
1744  {
1745  SpatialDomains::SegGeomSharedPtr edgeArray[3];
1746  for(j=0; j < 3; ++j)
1747  {
1748  edgeArray[j] = edges[edgeConnectivity[i][j]];
1749  }
1750 
1751 
1753  ::AllocateSharedPtr(i, edgeArray);
1754  }
1755 
1758  (0, faces);
1759 
1760  return geom;
1761  }
std::shared_ptr< TetGeom > TetGeomSharedPtr
Definition: TetGeom.h:88
std::shared_ptr< TriGeom > TriGeomSharedPtr
Definition: TriGeom.h:58
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
bg::model::point< double, 3, bg::cs::cartesian > point
Definition: BLMesh.cpp:53
std::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:62

◆ ExtractLocMat()

DNekMatSharedPtr Nektar::MultiRegions::PreconditionerLowEnergy::ExtractLocMat ( StdRegions::StdExpansionSharedPtr locExp,
DNekScalMatSharedPtr maxRmat,
LocalRegions::ExpansionSharedPtr expMax,
Array< OneD, unsigned int > &  vertMapMaxR,
Array< OneD, Array< OneD, unsigned int > > &  edgeMapMaxR 
)
private

Definition at line 2458 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::StdRegions::eDir1FwdDir1_Dir2FwdDir2, and Nektar::eFULL.

Referenced by ReSetPrismMaxRMat(), and SetupBlockTransformationMatrix().

2463  {
2464  NekDouble val;
2465  NekDouble zero = 0.0;
2466 
2467  int nRows = locExp->NumBndryCoeffs();
2469  AllocateSharedPtr(nRows,nRows,zero,eFULL);
2470 
2471  Array<OneD, unsigned int> vlocmap;
2472  Array<OneD, Array<OneD, unsigned int> > elocmap;
2473  Array<OneD, Array<OneD, unsigned int> > flocmap;
2474 
2475  locExp->GetInverseBoundaryMaps(vlocmap,elocmap,flocmap);
2476 
2477  // fill diagonal
2478  for(int i = 0; i < nRows; ++i)
2479  {
2480  val = 1.0;
2481  newmat->SetValue(i,i,val);
2482  }
2483 
2484  int nverts = locExp->GetNverts();
2485  int nedges = locExp->GetNedges();
2486  int nfaces = locExp->GetNfaces();
2487 
2488  // fill vertex to edge coupling
2489  for(int e = 0; e < nedges; ++e)
2490  {
2491  int nEdgeInteriorCoeffs = locExp->GetEdgeNcoeffs(e) -2;
2492 
2493  for(int v = 0; v < nverts; ++v)
2494  {
2495  for(int i = 0; i < nEdgeInteriorCoeffs; ++i)
2496  {
2497  val = (*maxRmat)(vmap[v],emap[e][i]);
2498  newmat->SetValue(vlocmap[v],elocmap[e][i],val);
2499  }
2500  }
2501  }
2502 
2503  for(int f = 0; f < nfaces; ++f)
2504  {
2505  // Get details to extrac this face from max reference matrix
2507  int m0,m1; //Local face expansion orders.
2508 
2509  int nFaceInteriorCoeffs = locExp->GetFaceIntNcoeffs(f);
2510 
2511  locExp->GetFaceNumModes(f,FwdOrient,m0,m1);
2512 
2513  Array<OneD, unsigned int> fmapRmat = maxExp->
2514  GetFaceInverseBoundaryMap(f,FwdOrient, m0,m1);
2515 
2516  // fill in vertex to face coupling
2517  for(int v = 0; v < nverts; ++v)
2518  {
2519  for(int i = 0; i < nFaceInteriorCoeffs; ++i)
2520  {
2521  val = (*maxRmat)(vmap[v],fmapRmat[i]);
2522  newmat->SetValue(vlocmap[v],flocmap[f][i],val);
2523  }
2524  }
2525 
2526  // fill in edges to face coupling
2527  for(int e = 0; e < nedges; ++e)
2528  {
2529  int nEdgeInteriorCoeffs = locExp->GetEdgeNcoeffs(e) -2;
2530 
2531  for(int j = 0; j < nEdgeInteriorCoeffs; ++j)
2532  {
2533 
2534  for(int i = 0; i < nFaceInteriorCoeffs; ++i)
2535  {
2536  val = (*maxRmat)(emap[e][j],fmapRmat[i]);
2537  newmat->SetValue(elocmap[e][j],flocmap[f][i],val);
2538  }
2539  }
2540  }
2541  }
2542 
2543  return newmat;
2544  }
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
double NekDouble

◆ ReSetPrismMaxRMat()

void Nektar::MultiRegions::PreconditionerLowEnergy::ReSetPrismMaxRMat ( int  nummodesmax,
LocalRegions::PrismExpSharedPtr PirsmExp,
ShapeToDNekMap maxRmat,
ShapeToIntArrayMap vertMapMaxR,
ShapeToIntArrayArrayMap edgeMapMaxR,
ShapeToIntArrayArrayMap faceMapMaxR,
bool  UseTetOnly 
)
private

Definition at line 2253 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::eFULL, Nektar::LibUtilities::eHexahedron, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::eTetrahedron, and ExtractLocMat().

Referenced by SetUpReferenceElements().

2260  {
2261  int nRows = PrismExp->NumBndryCoeffs();
2262  NekDouble val;
2263  NekDouble zero = 0.0;
2265  AllocateSharedPtr(nRows,nRows,zero,eFULL);
2266 
2267 
2268  int nfacemodes;
2269 
2270  if(UseTetOnly)
2271  {
2272  // copy existing system
2273  for(int i = 0; i < nRows; ++i)
2274  {
2275  for(int j = 0; j < nRows; ++j)
2276  {
2277  val = (*maxRmat[ePrism])(i,j);
2278  newmat->SetValue(i,j,val);
2279  }
2280  }
2281 
2282  // Reset vertex to edge mapping from tet.
2283  const int VETetVert[][2] = {{0,0},{1,1},{1,1},{0,0},{3,3},{3,3}};
2284  const int VETetEdge[][2] = {{0,3},{0,4},{0,4},{0,3},{3,4},{4,3}};
2285  const int VEPrismEdge[][2] = {{0,4},{0,5},{2,6},{2,7},{4,5},{6,7}};
2286 
2287  // fill vertex to edge coupling
2288  for(int v = 0; v < 6; ++v)
2289  {
2290  for(int e = 0; e < 2; ++e)
2291  {
2292  for(int i = 0; i < nummodesmax-2; ++i)
2293  {
2294  // Note this is using wrong shape but gives
2295  // answer that seems to have correct error!
2296  val = (*maxRmat[eTetrahedron])(
2297  vertMapMaxR[eTetrahedron][VETetVert[v][e]],
2298  edgeMapMaxR[eTetrahedron][VETetEdge[v][e]][i]);
2299  newmat->
2300  SetValue(vertMapMaxR[ePrism][v],
2301  edgeMapMaxR[ePrism][VEPrismEdge[v][e]][i],
2302  val);
2303  }
2304  }
2305  }
2306  }
2307  else
2308  {
2309 
2310  // set diagonal to 1
2311  for(int i = 0; i < nRows; ++i)
2312  {
2313  newmat->SetValue(i,i,1.0);
2314  }
2315 
2316 
2317  // Set vertex to edge mapping from Hex.
2318 
2319  // The following lists specify the number of adjacent
2320  // edges to each vertex (nadj) then the Hex vert to
2321  // use for each prism ver in the vert-edge map (VEVert)
2322  // followed by the hex edge to use for each prism edge
2323  // in the vert-edge map (VEEdge)
2324  const int VEHexVert[][3] = {{0,0,0},{1,1,1},{2,2,2},{3,3,3},
2325  {4,5,5},{6,7,7}};
2326  const int VEHexEdge[][3] = {{0,3,4},{0,1,5},{1,2,6},{2,3,7},
2327  {4,5,9},{6,7,11}};
2328  const int VEPrismEdge[][3] = {{0,3,4},{0,1,5},{1,2,6},{2,3,7},
2329  {4,5,8},{6,7,8}};
2330 
2331  // fill vertex to edge coupling
2332  for(int v = 0; v < 6; ++v)
2333  {
2334  for(int e = 0; e < 3; ++e)
2335  {
2336  for(int i = 0; i < nummodesmax-2; ++i)
2337  {
2338  // Note this is using wrong shape but gives
2339  // answer that seems to have correct error!
2340  val = (*maxRmat[eHexahedron])(
2341  vertMapMaxR[eHexahedron][VEHexVert[v][e]],
2342  edgeMapMaxR[eHexahedron][VEHexEdge[v][e]][i]);
2343  newmat->SetValue(vertMapMaxR[ePrism][v],
2344  edgeMapMaxR[ePrism][VEPrismEdge[v][e]][i],
2345  val);
2346  }
2347  }
2348  }
2349 
2350 
2351  // Setup vertex to face mapping from Hex
2352  const int VFHexVert[][2] = {{0,0},{1,1},{4,5},{2,2},{3,3},{6,7}};
2353  const int VFHexFace[][2] = {{0,4},{0,2},{4,2},{0,2},{0,4},{2,4}};
2354 
2355  const int VQFPrismVert[][2] = {{0,0},{1,1},{4,4},{2,2},{3,3},{5,5}};
2356  const int VQFPrismFace[][2] = {{0,4},{0,2},{4,2},{0,2},{0,4},{2,4}};
2357 
2358  nfacemodes = (nummodesmax-2)*(nummodesmax-2);
2359  // Replace two Quad faces on every vertex
2360  for(int v = 0; v < 6; ++v)
2361  {
2362  for(int f = 0; f < 2; ++f)
2363  {
2364  for(int i = 0; i < nfacemodes; ++i)
2365  {
2366  val = (*maxRmat[eHexahedron])(
2367  vertMapMaxR[eHexahedron][VFHexVert[v][f]],
2368  faceMapMaxR[eHexahedron][VFHexFace[v][f]][i]);
2369  newmat->SetValue(vertMapMaxR[ePrism][VQFPrismVert[v][f]],
2370  faceMapMaxR[ePrism][VQFPrismFace[v][f]][i],val);
2371  }
2372  }
2373  }
2374 
2375  // Mapping of Hex Edge-Face mappings to Prism Edge-Face Mappings
2376  const int nadjface[] = {1,2,1,2,1,1,1,1,2};
2377  const int EFHexEdge[][2] = {{0,-1},{1,1},{2,-1},{3,3},{4,-1},{5,-1},{6,-1},{7,-1},{9,11}};
2378  const int EFHexFace[][2] = {{0,-1},{0,2},{0,-1},{0,4},{4,-1},{2,-1},{2,-1},{4,-1},{2,4}};
2379  const int EQFPrismEdge[][2] = {{0,-1},{1,1},{2,-1},{3,3},{4,-1},{5,-1},{6,-1},{7,-1},{8,8}};
2380  const int EQFPrismFace[][2] = {{0,-1},{0,2},{0,-1},{0,4},{4,-1},{2,-1},{2,-1},{4,-1},{2,4}};
2381 
2382  // all base edges are coupled to face 0
2383  nfacemodes = (nummodesmax-2)*(nummodesmax-2);
2384  for(int e = 0; e < 9; ++e)
2385  {
2386  for(int f = 0; f < nadjface[e]; ++f)
2387  {
2388  for(int i = 0; i < nummodesmax-2; ++i)
2389  {
2390  for(int j = 0; j < nfacemodes; ++j)
2391  {
2392  int edgemapid = edgeMapMaxR[eHexahedron][EFHexEdge[e][f]][i];
2393  int facemapid = faceMapMaxR[eHexahedron][EFHexFace[e][f]][j];
2394 
2395  val = (*maxRmat[eHexahedron])(edgemapid,facemapid);
2396 
2397  int edgemapid1 = edgeMapMaxR[ePrism][EQFPrismEdge[e][f]][i];
2398  int facemapid1 = faceMapMaxR[ePrism][EQFPrismFace[e][f]][j];
2399  newmat->SetValue(edgemapid1, facemapid1, val);
2400  }
2401  }
2402  }
2403  }
2404  }
2405 
2406  const int VFTetVert[] = {0,1,3,1,0,3};
2407  const int VFTetFace[] = {1,1,1,1,1,1};
2408  const int VTFPrismVert[] = {0,1,4,2,3,5};
2409  const int VTFPrismFace[] = {1,1,1,3,3,3};
2410 
2411  // Handle all triangular faces from tetrahedron
2412  nfacemodes = (nummodesmax-3)*(nummodesmax-2)/2;
2413  for(int v = 0; v < 6; ++v)
2414  {
2415  for(int i = 0; i < nfacemodes; ++i)
2416  {
2417  val = (*maxRmat[eTetrahedron])
2418  (vertMapMaxR[eTetrahedron][VFTetVert[v]],
2419  faceMapMaxR[eTetrahedron][VFTetFace[v]][i]);
2420 
2421  newmat->SetValue(vertMapMaxR[ePrism][VTFPrismVert[v]],
2422  faceMapMaxR[ePrism][VTFPrismFace[v]][i],val);
2423  }
2424  }
2425 
2426  // Mapping of Tet Edge-Face mappings to Prism Edge-Face Mappings
2427  const int EFTetEdge[] = {0,3,4,0,4,3};
2428  const int EFTetFace[] = {1,1,1,1,1,1};
2429  const int ETFPrismEdge[] = {0,4,5,2,6,7};
2430  const int ETFPrismFace[] = {1,1,1,3,3,3};
2431 
2432  // handle all edge to triangular faces from tetrahedron
2433  // (only 6 this time)
2434  nfacemodes = (nummodesmax-3)*(nummodesmax-2)/2;
2435  for(int e = 0; e < 6; ++e)
2436  {
2437  for(int i = 0; i < nummodesmax-2; ++i)
2438  {
2439  for(int j = 0; j < nfacemodes; ++j)
2440  {
2441  int edgemapid = edgeMapMaxR[eTetrahedron][EFTetEdge[e]][i];
2442  int facemapid = faceMapMaxR[eTetrahedron][EFTetFace[e]][j];
2443  val = (*maxRmat[eTetrahedron])(edgemapid,facemapid);
2444 
2445  newmat->SetValue(edgeMapMaxR[ePrism][ETFPrismEdge[e]][i],
2446  faceMapMaxR[ePrism][ETFPrismFace[e]][j],val);
2447  }
2448  }
2449  }
2450 
2451 
2452  DNekScalMatSharedPtr PrismR
2454  maxRmat[ePrism] = PrismR;
2455  }
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
double NekDouble

◆ ReSetTetMaxRMat()

void Nektar::MultiRegions::PreconditionerLowEnergy::ReSetTetMaxRMat ( int  nummodesmax,
LocalRegions::TetExpSharedPtr TetExp,
ShapeToDNekMap maxRmat,
ShapeToIntArrayMap vertMapMaxR,
ShapeToIntArrayArrayMap edgeMapMaxR,
ShapeToIntArrayArrayMap faceMapMaxR 
)
private

Definition at line 2194 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::eFULL, Nektar::LibUtilities::eHexahedron, and Nektar::LibUtilities::eTetrahedron.

Referenced by SetUpReferenceElements().

2200  {
2201  boost::ignore_unused(faceMapMaxR);
2202 
2203  int nRows = TetExp->NumBndryCoeffs();
2204  NekDouble val;
2205  NekDouble zero = 0.0;
2207  AllocateSharedPtr(nRows,nRows,zero,eFULL);
2208 
2209  // copy existing system
2210  for(int i = 0; i < nRows; ++i)
2211  {
2212  for(int j = 0; j < nRows; ++j)
2213  {
2214  val = (*maxRmat[eTetrahedron])(i,j);
2215  newmat->SetValue(i,j,val);
2216  }
2217  }
2218 
2219  // The following lists specify the number of adjacent
2220  // edges to each vertex (nadj) then the Hex vert to
2221  // use for each pyramid ver in the vert-edge map (VEVert)
2222  // followed by the hex edge to use for each Tet edge
2223  // in the vert-edge map (VEEdge)
2224  const int VEHexVert[][4] = {{0,0,0},{1,1,1},{2,2,2},{4,5,6}};
2225  const int VEHexEdge[][4] = {{0,3,4},{0,1,5},{1,2,6},{4,5,6}};
2226  const int VETetEdge[][4] = {{0,2,3},{0,1,4},{1,2,5},{3,4,5}};
2227 
2228  // fill vertex to edge coupling
2229  for(int v = 0; v < 4; ++v)
2230  {
2231  for(int e = 0; e < 3; ++e)
2232  {
2233  for(int i = 0; i < nummodesmax-2; ++i)
2234  {
2235  // Note this is using wrong shape but gives
2236  // answer that seems to have correct error!
2237  val = (*maxRmat[eHexahedron])(
2238  vertMapMaxR[eHexahedron][VEHexVert[v][e]],
2239  edgeMapMaxR[eHexahedron][VEHexEdge[v][e]][i]);
2240  newmat->SetValue(vertMapMaxR[eTetrahedron][v],
2241  edgeMapMaxR[eTetrahedron][VETetEdge[v][e]][i],
2242  val);
2243  }
2244  }
2245  }
2246 
2247  DNekScalMatSharedPtr TetR =
2249 
2250  maxRmat[eTetrahedron] = TetR;
2251  }
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
double NekDouble

◆ SetupBlockTransformationMatrix()

void Nektar::MultiRegions::PreconditionerLowEnergy::SetupBlockTransformationMatrix ( void  )
private

Set a block transformation matrices for each element type. These are needed in routines that transform the schur complement matrix to and from the low energy basis.

Definition at line 957 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::eDIAGONAL, ExtractLocMat(), m_InvRBlk, Nektar::MultiRegions::Preconditioner::m_linsys, Nektar::MultiRegions::Preconditioner::m_locToGloMap, m_RBlk, m_sameBlock, and SetUpReferenceElements().

Referenced by v_InitObject().

958  {
959  std::shared_ptr<MultiRegions::ExpList>
960  expList=((m_linsys.lock())->GetLocMat()).lock();
963  map<int,int> EdgeSize;
964 
965  int n;
966 
967  std::map<ShapeType, DNekScalMatSharedPtr> maxRmat;
968  map<ShapeType, LocalRegions::ExpansionSharedPtr > maxElmt;
969  map<ShapeType, Array<OneD, unsigned int> > vertMapMaxR;
970  map<ShapeType, Array<OneD, Array<OneD, unsigned int> > > edgeMapMaxR;
971 
972 
973  //Sets up reference element and builds transformation matrix for
974  // maximum polynomial order meshes
975  SetUpReferenceElements(maxRmat,maxElmt,vertMapMaxR,edgeMapMaxR);
976 
977  const Array<OneD,const unsigned int>& nbdry_size
978  = m_locToGloMap.lock()->GetNumLocalBndCoeffsPerPatch();
979 
980  int n_exp=expList->GetNumElmts();
981 
982  MatrixStorage blkmatStorage = eDIAGONAL;
983 
984  //Variants of R matrices required for low energy preconditioning
986  ::AllocateSharedPtr(nbdry_size, nbdry_size , blkmatStorage);
988  ::AllocateSharedPtr(nbdry_size, nbdry_size , blkmatStorage);
989 
990  DNekMatSharedPtr rmat, invrmat;
991 
992  int offset = 0;
993 
994  // Set up transformation matrices whilst checking to see if
995  // consecutive matrices are the same and if so reuse the
996  // matrices and store how many consecutive offsets there
997  // are
998  for(n=0; n < n_exp; ++n)
999  {
1000  locExp = expList->GetExp(n);
1001  ShapeType eltype = locExp->DetShapeType();
1002 
1003  int nbndcoeffs = locExp->NumBndryCoeffs();
1004 
1005  if(m_sameBlock.size() == 0)
1006  {
1007  rmat = ExtractLocMat(locExp,maxRmat[eltype],
1008  maxElmt[eltype],
1009  vertMapMaxR[eltype],
1010  edgeMapMaxR[eltype]);
1011  //Block R matrix
1012  m_RBlk->SetBlock(n, n, rmat);
1013 
1015  invrmat->Invert();
1016 
1017  //Block inverse R matrix
1018  m_InvRBlk->SetBlock(n, n, invrmat);
1019 
1020  m_sameBlock.push_back(pair<int,int>(1,nbndcoeffs));
1021  locExpSav = locExp;
1022  }
1023  else
1024  {
1025  bool reuse = true;
1026 
1027  // check to see if same as previous matrix and
1028  // reuse if we can
1029  for(int i = 0; i < 3; ++i)
1030  {
1031  if(locExpSav->GetBasis(i) != locExp->GetBasis(i))
1032  {
1033  reuse = false;
1034  break;
1035  }
1036  }
1037 
1038  if(reuse)
1039  {
1040  m_RBlk->SetBlock(n, n, rmat);
1041  m_InvRBlk->SetBlock(n, n, invrmat);
1042 
1043  m_sameBlock[offset] =
1044  (pair<int,int>(m_sameBlock[offset].first+1,nbndcoeffs));
1045  }
1046  else
1047  {
1048  rmat = ExtractLocMat(locExp,maxRmat[eltype],
1049  maxElmt[eltype],
1050  vertMapMaxR[eltype],
1051  edgeMapMaxR[eltype]);
1052 
1053  //Block R matrix
1054  m_RBlk->SetBlock(n, n, rmat);
1055 
1057  invrmat->Invert();
1058  //Block inverse R matrix
1059  m_InvRBlk->SetBlock(n, n, invrmat);
1060 
1061  m_sameBlock.push_back(pair<int,int>(1,nbndcoeffs));
1062  offset++;
1063  locExpSav = locExp;
1064  }
1065  }
1066  }
1067  }
std::vector< std::pair< int, int > > m_sameBlock
const std::weak_ptr< GlobalLinSys > m_linsys
DNekMatSharedPtr ExtractLocMat(StdRegions::StdExpansionSharedPtr &locExp, DNekScalMatSharedPtr &maxRmat, LocalRegions::ExpansionSharedPtr &expMax, Array< OneD, unsigned int > &vertMapMaxR, Array< OneD, Array< OneD, unsigned int > > &edgeMapMaxR)
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
void SetUpReferenceElements(ShapeToDNekMap &maxRmat, ShapeToExpMap &maxElmt, ShapeToIntArrayMap &vertMapMaxR, ShapeToIntArrayArrayMap &edgeMapMaxR)
Loop expansion and determine different variants of the transformation matrix.
std::weak_ptr< AssemblyMap > m_locToGloMap

◆ SetUpPyrMaxRMat()

void Nektar::MultiRegions::PreconditionerLowEnergy::SetUpPyrMaxRMat ( int  nummodesmax,
LocalRegions::PyrExpSharedPtr PyrExp,
ShapeToDNekMap maxRmat,
ShapeToIntArrayMap vertMapMaxR,
ShapeToIntArrayArrayMap edgeMapMaxR,
ShapeToIntArrayArrayMap faceMapMaxR 
)
private

Definition at line 2058 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::eFULL, Nektar::LibUtilities::eHexahedron, Nektar::LibUtilities::ePyramid, and Nektar::LibUtilities::eTetrahedron.

Referenced by SetUpReferenceElements().

2064  {
2065  int nRows = PyrExp->NumBndryCoeffs();
2066  NekDouble val;
2067  NekDouble zero = 0.0;
2069  AllocateSharedPtr(nRows,nRows,zero,eFULL);
2070 
2071  // set diagonal to 1
2072  for(int i = 0; i < nRows; ++i)
2073  {
2074  newmat->SetValue(i,i,1.0);
2075  }
2076 
2077  // The following lists specify the number of adjacent
2078  // edges to each vertex (nadj) then the Hex vert to
2079  // use for each pyramid ver in the vert-edge map (VEVert)
2080  // followed by the hex edge to use for each pyramid edge
2081  // in the vert-edge map (VEEdge)
2082  const int nadjedge[] = {3,3,3,3,4};
2083  const int VEHexVert[][4] = {{0,0,0,-1},{1,1,1,-1},{2,2,2,-1},{3,3,3,-1},{4,5,6,7}};
2084  const int VEHexEdge[][4] = {{0,3,4,-1},{0,1,5,-1},{1,2,6,-1},{2,3,7,-1},{4,5,6,7}};
2085  const int VEPyrEdge[][4] = {{0,3,4,-1},{0,1,5,-1},{1,2,6,-1},{2,3,7,-1},{4,5,6,7}};
2086 
2087  // fill vertex to edge coupling
2088  for(int v = 0; v < 5; ++v)
2089  {
2090  for(int e = 0; e < nadjedge[v]; ++e)
2091  {
2092  for(int i = 0; i < nummodesmax-2; ++i)
2093  {
2094  // Note this is using wrong shape but gives
2095  // answer that seems to have correct error!
2096  val = (*maxRmat[eHexahedron])(
2097  vertMapMaxR[eHexahedron][VEHexVert[v][e]],
2098  edgeMapMaxR[eHexahedron][VEHexEdge[v][e]][i]);
2099  newmat->SetValue(vertMapMaxR[ePyramid][v],
2100  edgeMapMaxR[ePyramid][VEPyrEdge[v][e]][i],val);
2101  }
2102  }
2103  }
2104 
2105  int nfacemodes;
2106  nfacemodes = (nummodesmax-2)*(nummodesmax-2);
2107  // First four verties are all adjacent to base face
2108  for(int v = 0; v < 4; ++v)
2109  {
2110  for(int i = 0; i < nfacemodes; ++i)
2111  {
2112  val = (*maxRmat[eHexahedron])(vertMapMaxR[eHexahedron][v],
2113  faceMapMaxR[eHexahedron][0][i]);
2114  newmat->SetValue(vertMapMaxR[ePyramid][v],
2115  faceMapMaxR[ePyramid][0][i],val);
2116  }
2117  }
2118 
2119 
2120  const int nadjface[] = {2,2,2,2,4};
2121  const int VFTetVert[][4] = {{0,0,-1,-1},{1,1,-1,-1},{2,2,-1,-1},{0,2,-1,-1},{3,3,3,3}};
2122  const int VFTetFace[][4] = {{1,3,-1,-1},{1,2,-1,-1},{2,3,-1,-1},{1,3,-1,-1},{1,2,1,2}};
2123  const int VFPyrFace[][4] = {{1,4,-1,-1},{1,2,-1,-1},{2,3,-1,-1},{3,4,-1,-1},{1,2,3,4}};
2124 
2125  // next handle all triangular faces from tetrahedron
2126  nfacemodes = (nummodesmax-3)*(nummodesmax-2)/2;
2127  for(int v = 0; v < 5; ++v)
2128  {
2129  for(int f = 0; f < nadjface[v]; ++f)
2130  {
2131  for(int i = 0; i < nfacemodes; ++i)
2132  {
2133  val = (*maxRmat[eTetrahedron])(vertMapMaxR[eTetrahedron][VFTetVert[v][f]],
2134  faceMapMaxR[eTetrahedron][VFTetFace[v][f]][i]);
2135  newmat->SetValue(vertMapMaxR[ePyramid][v],
2136  faceMapMaxR[ePyramid][VFPyrFace[v][f]][i],val);
2137  }
2138 
2139  }
2140  }
2141 
2142  // Edge to face coupling
2143  // all base edges are coupled to face 0
2144  nfacemodes = (nummodesmax-2)*(nummodesmax-2);
2145  for(int e = 0; e < 4; ++e)
2146  {
2147  for(int i = 0; i < nummodesmax-2; ++i)
2148  {
2149  for(int j = 0; j < nfacemodes; ++j)
2150  {
2151  int edgemapid = edgeMapMaxR[eHexahedron][e][i];
2152  int facemapid = faceMapMaxR[eHexahedron][0][j];
2153 
2154  val = (*maxRmat[eHexahedron])(edgemapid,facemapid);
2155  newmat->SetValue(edgeMapMaxR[ePyramid][e][i],
2156  faceMapMaxR[ePyramid][0][j],val);
2157  }
2158 
2159  }
2160  }
2161 
2162  const int nadjface1[] = {1,1,1,1,2,2,2,2};
2163  const int EFTetEdge[][2] = {{0,-1},{1,-1},{0,-1},{2,-1},{3,3},{4,4},{5,5},{3,5}};
2164  const int EFTetFace[][2] = {{1,-1},{2,-1},{1,-1},{3,-1},{1,3},{1,2},{2,3},{1,3}};
2165  const int EFPyrFace[][2] = {{1,-1},{2,-1},{3,-1},{4,-1},{1,4},{1,2},{2,3},{3,4}};
2166 
2167  // next handle all triangular faces from tetrahedron
2168  nfacemodes = (nummodesmax-3)*(nummodesmax-2)/2;
2169  for(int e = 0; e < 8; ++e)
2170  {
2171  for(int f = 0; f < nadjface1[e]; ++f)
2172  {
2173  for(int i = 0; i < nummodesmax-2; ++i)
2174  {
2175  for(int j = 0; j < nfacemodes; ++j)
2176  {
2177  int edgemapid = edgeMapMaxR[eTetrahedron][EFTetEdge[e][f]][i];
2178  int facemapid = faceMapMaxR[eTetrahedron][EFTetFace[e][f]][j];
2179 
2180  val = (*maxRmat[eTetrahedron])(edgemapid,facemapid);
2181  newmat->SetValue(edgeMapMaxR[ePyramid][e][i],
2182  faceMapMaxR[ePyramid][EFPyrFace[e][f]][j],val);
2183  }
2184  }
2185  }
2186  }
2187 
2188  DNekScalMatSharedPtr PyrR;
2190  maxRmat[ePyramid] =PyrR;
2191  }
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
double NekDouble

◆ SetUpReferenceElements()

void Nektar::MultiRegions::PreconditionerLowEnergy::SetUpReferenceElements ( ShapeToDNekMap maxRmat,
ShapeToExpMap maxElmt,
ShapeToIntArrayMap vertMapMaxR,
ShapeToIntArrayArrayMap edgeMapMaxR 
)
private

Loop expansion and determine different variants of the transformation matrix.

Sets up multiple reference elements based on the element expansion.

Definition at line 1845 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), CreateRefHexGeom(), CreateRefPrismGeom(), CreateRefPyrGeom(), CreateRefTetGeom(), Nektar::LibUtilities::eGaussLobattoLegendre, Nektar::LibUtilities::eGaussRadauMAlpha1Beta0, Nektar::LibUtilities::eGaussRadauMAlpha2Beta0, Nektar::LibUtilities::eHexahedron, Nektar::StdRegions::eMass, Nektar::LibUtilities::eModified_A, Nektar::LibUtilities::eModified_B, Nektar::LibUtilities::eModified_C, Nektar::LibUtilities::eModifiedPyr_C, Nektar::StdRegions::ePreconR, Nektar::StdRegions::ePreconRMass, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::ePyramid, Nektar::LibUtilities::eTetrahedron, Nektar::MultiRegions::GlobalMatrixKey::GetConstFactors(), Nektar::MultiRegions::GlobalMatrixKey::GetMatrixType(), Nektar::MultiRegions::Preconditioner::m_comm, Nektar::MultiRegions::Preconditioner::m_linsys, Nektar::LibUtilities::ReduceMax, ReSetPrismMaxRMat(), ReSetTetMaxRMat(), SetUpPyrMaxRMat(), and Nektar::LibUtilities::SIZE_ShapeType.

Referenced by SetupBlockTransformationMatrix().

1850  {
1851 
1852  std::shared_ptr<MultiRegions::ExpList>
1853  expList=((m_linsys.lock())->GetLocMat()).lock();
1854  GlobalLinSysKey linSysKey=(m_linsys.lock())->GetKey();
1855 
1857 
1858  // face maps for pyramid and hybrid meshes - not need to return.
1859  map<ShapeType, Array<OneD, Array<OneD, unsigned int> > > faceMapMaxR;
1860 
1861  /* Determine the maximum expansion order for all elements */
1862  int nummodesmax = 0;
1863  Array<OneD, int> Shapes(LibUtilities::SIZE_ShapeType,0);
1864 
1865  for(int n = 0; n < expList->GetNumElmts(); ++n)
1866  {
1867  locExp = expList->GetExp(n);
1868 
1869  nummodesmax = max(nummodesmax, locExp->GetBasisNumModes(0));
1870  nummodesmax = max(nummodesmax, locExp->GetBasisNumModes(1));
1871  nummodesmax = max(nummodesmax, locExp->GetBasisNumModes(2));
1872 
1873  Shapes[locExp->DetShapeType()] = 1;
1874  }
1875 
1876 
1877  m_comm->AllReduce(nummodesmax, ReduceMax);
1878  m_comm->AllReduce(Shapes, ReduceMax);
1879 
1880  if(Shapes[ePyramid]) // if Pyramids used then need Tet and Hex expansion
1881  {
1882  Shapes[eTetrahedron] = 1;
1883  Shapes[eHexahedron] = 1;
1884  }
1885 
1886  StdRegions::MatrixType PreconR;
1887  if(linSysKey.GetMatrixType() == StdRegions::eMass)
1888  {
1889  PreconR = StdRegions::ePreconRMass;
1890  }
1891  else
1892  {
1893  PreconR = StdRegions::ePreconR;
1894  }
1895 
1896  Array<OneD, unsigned int> vmap;
1897  Array<OneD, Array<OneD, unsigned int> > emap;
1898  Array<OneD, Array<OneD, unsigned int> > fmap;
1899 
1900  /*
1901  * Set up a transformation matrices for equal max order
1902  * polynomial meshes
1903  */
1904 
1905  if(Shapes[eHexahedron])
1906  {
1908  //Bases for Hex element
1909  const BasisKey HexBa(eModified_A, nummodesmax,
1910  PointsKey(nummodesmax+1, eGaussLobattoLegendre));
1911  const BasisKey HexBb(eModified_A, nummodesmax,
1912  PointsKey(nummodesmax+1, eGaussLobattoLegendre));
1913  const BasisKey HexBc(eModified_A, nummodesmax,
1914  PointsKey(nummodesmax+1, eGaussLobattoLegendre));
1915 
1916  //Create reference Hexahdedral expansion
1918 
1920  ::AllocateSharedPtr(HexBa,HexBb,HexBc,
1921  hexgeom);
1922 
1923  maxElmt[eHexahedron] = HexExp;
1924 
1925  // Hex:
1926  HexExp->GetInverseBoundaryMaps(vmap,emap,fmap);
1927  vertMapMaxR[eHexahedron] = vmap;
1928  edgeMapMaxR[eHexahedron] = emap;
1929  faceMapMaxR[eHexahedron] = fmap;
1930 
1931  //Get hexahedral transformation matrix
1932  LocalRegions::MatrixKey HexR
1933  (PreconR, eHexahedron,
1934  *HexExp, linSysKey.GetConstFactors());
1935  maxRmat[eHexahedron] = HexExp->GetLocMatrix(HexR);
1936  }
1937 
1938  if(Shapes[eTetrahedron])
1939  {
1941  //Bases for Tetrahedral element
1942  const BasisKey TetBa(eModified_A, nummodesmax,
1943  PointsKey(nummodesmax+1, eGaussLobattoLegendre));
1944  const BasisKey TetBb(eModified_B, nummodesmax,
1945  PointsKey(nummodesmax, eGaussRadauMAlpha1Beta0));
1946  const BasisKey TetBc(eModified_C, nummodesmax,
1947  PointsKey(nummodesmax, eGaussRadauMAlpha2Beta0));
1948 
1949  //Create reference tetrahedral expansion
1951 
1953  ::AllocateSharedPtr(TetBa,TetBb,TetBc,tetgeom);
1954 
1955  maxElmt[eTetrahedron] = TetExp;
1956 
1957  TetExp->GetInverseBoundaryMaps(vmap,emap,fmap);
1958  vertMapMaxR[eTetrahedron] = vmap;
1959  edgeMapMaxR[eTetrahedron] = emap;
1960  faceMapMaxR[eTetrahedron] = fmap;
1961 
1962  //Get tetrahedral transformation matrix
1963  LocalRegions::MatrixKey TetR
1964  (PreconR, eTetrahedron,
1965  *TetExp, linSysKey.GetConstFactors());
1966  maxRmat[eTetrahedron] = TetExp->GetLocMatrix(TetR);
1967 
1968  if((Shapes[ePyramid])||(Shapes[eHexahedron]))
1969  {
1970  ReSetTetMaxRMat(nummodesmax, TetExp, maxRmat,
1971  vertMapMaxR, edgeMapMaxR, faceMapMaxR);
1972  }
1973  }
1974 
1975  if(Shapes[ePyramid])
1976  {
1978 
1979  //Bases for Pyramid element
1980  const BasisKey PyrBa(eModified_A, nummodesmax,
1981  PointsKey(nummodesmax+1, eGaussLobattoLegendre));
1982  const BasisKey PyrBb(eModified_A, nummodesmax,
1983  PointsKey(nummodesmax+1, eGaussLobattoLegendre));
1984  const BasisKey PyrBc(eModifiedPyr_C, nummodesmax,
1985  PointsKey(nummodesmax, eGaussRadauMAlpha2Beta0));
1986 
1987  //Create reference pyramid expansion
1989 
1991  ::AllocateSharedPtr(PyrBa,PyrBb,PyrBc,pyrgeom);
1992 
1993  maxElmt[ePyramid] = PyrExp;
1994 
1995  // Pyramid:
1996  PyrExp->GetInverseBoundaryMaps(vmap,emap,fmap);
1997  vertMapMaxR[ePyramid] = vmap;
1998  edgeMapMaxR[ePyramid] = emap;
1999  faceMapMaxR[ePyramid] = fmap;
2000 
2001  // Set up Pyramid Transformation Matrix based on Tet
2002  // and Hex expansion
2003  SetUpPyrMaxRMat(nummodesmax,PyrExp,maxRmat,vertMapMaxR,
2004  edgeMapMaxR,faceMapMaxR);
2005  }
2006 
2007  if(Shapes[ePrism])
2008  {
2010  //Bases for Prism element
2011  const BasisKey PrismBa(eModified_A, nummodesmax,
2012  PointsKey(nummodesmax+1, eGaussLobattoLegendre));
2013  const BasisKey PrismBb(eModified_A, nummodesmax,
2014  PointsKey(nummodesmax+1, eGaussLobattoLegendre));
2015  const BasisKey PrismBc(eModified_B, nummodesmax,
2016  PointsKey(nummodesmax, eGaussRadauMAlpha1Beta0));
2017 
2018  //Create reference prismatic expansion
2020 
2022  ::AllocateSharedPtr(PrismBa,PrismBb,PrismBc,prismgeom);
2023  maxElmt[ePrism] = PrismExp;
2024 
2025  // Prism:
2026  PrismExp->GetInverseBoundaryMaps(vmap,emap,fmap);
2027  vertMapMaxR[ePrism] = vmap;
2028  edgeMapMaxR[ePrism] = emap;
2029 
2030  faceMapMaxR[ePrism] = fmap;
2031 
2032  if((Shapes[ePyramid])||(Shapes[eHexahedron]))
2033  {
2034  ReSetPrismMaxRMat(nummodesmax, PrismExp, maxRmat,
2035  vertMapMaxR, edgeMapMaxR,
2036  faceMapMaxR, false);
2037  }
2038  else
2039  {
2040 
2041  //Get prismatic transformation matrix
2042  LocalRegions::MatrixKey PrismR
2043  (PreconR, ePrism,
2044  *PrismExp, linSysKey.GetConstFactors());
2045  maxRmat[ePrism] =
2046  PrismExp->GetLocMatrix(PrismR);
2047 
2048  if(Shapes[eTetrahedron]) // reset triangular faces from Tet
2049  {
2050  ReSetPrismMaxRMat(nummodesmax, PrismExp, maxRmat,
2051  vertMapMaxR, edgeMapMaxR,
2052  faceMapMaxR, true);
2053  }
2054  }
2055  }
2056  }
LibUtilities::CommSharedPtr m_comm
Principle Modified Functions .
Definition: BasisType.h:50
Principle Modified Functions .
Definition: BasisType.h:52
std::shared_ptr< TetGeom > TetGeomSharedPtr
Definition: TetGeom.h:88
const std::weak_ptr< GlobalLinSys > m_linsys
std::shared_ptr< HexExp > HexExpSharedPtr
Definition: HexExp.h:56
void ReSetTetMaxRMat(int nummodesmax, LocalRegions::TetExpSharedPtr &TetExp, ShapeToDNekMap &maxRmat, ShapeToIntArrayMap &vertMapMaxR, ShapeToIntArrayArrayMap &edgeMapMaxR, ShapeToIntArrayArrayMap &faceMapMaxR)
Principle Modified Functions .
Definition: BasisType.h:48
std::shared_ptr< TetExp > TetExpSharedPtr
Definition: TetExp.h:226
Gauss Radau pinned at x=-1, .
Definition: PointsType.h:58
SpatialDomains::HexGeomSharedPtr CreateRefHexGeom(void)
Sets up the reference hexahedral element needed to construct a low energy basis.
Principle Modified Functions .
Definition: BasisType.h:49
void SetUpPyrMaxRMat(int nummodesmax, LocalRegions::PyrExpSharedPtr &PyrExp, ShapeToDNekMap &maxRmat, ShapeToIntArrayMap &vertMapMaxR, ShapeToIntArrayArrayMap &edgeMapMaxR, ShapeToIntArrayArrayMap &faceMapMaxR)
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
SpatialDomains::PyrGeomSharedPtr CreateRefPyrGeom(void)
Sets up the reference prismatic element needed to construct a low energy basis mapping arrays...
std::shared_ptr< PyrExp > PyrExpSharedPtr
Definition: PyrExp.h:191
SpatialDomains::TetGeomSharedPtr CreateRefTetGeom(void)
Sets up the reference tretrahedral element needed to construct a low energy basis.
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:65
std::shared_ptr< PyrGeom > PyrGeomSharedPtr
Definition: PyrGeom.h:80
std::shared_ptr< PrismExp > PrismExpSharedPtr
Definition: PrismExp.h:220
std::shared_ptr< HexGeom > HexGeomSharedPtr
Definition: HexGeom.h:90
Gauss Radau pinned at x=-1, .
Definition: PointsType.h:59
SpatialDomains::PrismGeomSharedPtr CreateRefPrismGeom(void)
Sets up the reference prismatic element needed to construct a low energy basis.
std::shared_ptr< PrismGeom > PrismGeomSharedPtr
Definition: PrismGeom.h:88
void ReSetPrismMaxRMat(int nummodesmax, LocalRegions::PrismExpSharedPtr &PirsmExp, ShapeToDNekMap &maxRmat, ShapeToIntArrayMap &vertMapMaxR, ShapeToIntArrayArrayMap &edgeMapMaxR, ShapeToIntArrayArrayMap &faceMapMaxR, bool UseTetOnly)
1D Gauss-Lobatto-Legendre quadrature points
Definition: PointsType.h:51

◆ v_BuildPreconditioner()

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

Construct the low energy preconditioner from \(\mathbf{S}_{2}\).

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

where \(\mathbf{R}\) is the transformation matrix and \(\mathbf{S}_{2}\) the Schur complement of the modified basis, given by

\[\mathbf{S}_{2}=\mathbf{R}\mathbf{S}_{1}\mathbf{R}^{T}\]

where \(\mathbf{S}_{1}\) is the local schur complement matrix for each element.

  • Count edges, face and add up min edges and min face sizes

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 121 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::StdRegions::StdExpansion::as(), ASSERTL1, Vmath::Assmb(), Nektar::MultiRegions::DeterminePeriodicFaceOrient(), Nektar::eDIAGONAL, Nektar::SpatialDomains::eDirichlet, Nektar::eFULL, Gs::Gather(), Gs::gs_add, Gs::gs_min, Gs::Init(), CG_Iterations::loc, m_BlkMat, Nektar::MultiRegions::Preconditioner::m_comm, Nektar::MultiRegions::Preconditioner::m_linsys, Nektar::MultiRegions::Preconditioner::m_locToGloMap, m_locToGloSignMult, m_RBlk, m_signChange, Nektar::LibUtilities::ReduceMax, and Nektar::Transpose().

122  {
123  std::shared_ptr<MultiRegions::ExpList>
124  expList=((m_linsys.lock())->GetLocMat()).lock();
126  GlobalLinSysKey linSysKey=(m_linsys.lock())->GetKey();
127 
128  int i, j, k;
129  int nVerts, nEdges,nFaces;
130  int eid, fid, n, cnt, nmodes, nedgemodes, nfacemodes;
131  int nedgemodesloc;
132  NekDouble zero = 0.0;
133 
134  int vMap1, vMap2, sign1, sign2;
135  int m, v, eMap1, eMap2, fMap1, fMap2;
136  int offset, globalrow, globalcol, nCoeffs;
137 
138  // Periodic information
139  PeriodicMap periodicVerts;
140  PeriodicMap periodicEdges;
141  PeriodicMap periodicFaces;
142  expList->GetPeriodicEntities(periodicVerts,periodicEdges,periodicFaces);
143 
144  //matrix storage
145  MatrixStorage storage = eFULL;
146  MatrixStorage vertstorage = eDIAGONAL;
147  MatrixStorage blkmatStorage = eDIAGONAL;
148 
149  //local element static condensed matrices
150  DNekScalBlkMatSharedPtr loc_mat;
151  DNekScalMatSharedPtr bnd_mat;
152 
153  DNekMatSharedPtr pRSRT;
154 
155  DNekMat RS;
156  DNekMat RSRT;
157 
158  auto asmMap = m_locToGloMap.lock();
159 
160  int nDirBnd = asmMap->GetNumGlobalDirBndCoeffs();
161  int nNonDirVerts = asmMap->GetNumNonDirVertexModes();
162 
163  //Vertex, edge and face preconditioner matrices
165  AllocateSharedPtr(nNonDirVerts,nNonDirVerts,zero,vertstorage);
166 
167  Array<OneD, NekDouble> vertArray(nNonDirVerts,0.0);
168  Array<OneD, long> VertBlockToUniversalMap(nNonDirVerts,-1);
169 
170  //maps for different element types
171  int n_exp = expList->GetNumElmts();
172  int nNonDirEdgeIDs=asmMap->GetNumNonDirEdges();
173  int nNonDirFaceIDs=asmMap->GetNumNonDirFaces();
174 
175  set<int> edgeDirMap;
176  set<int> faceDirMap;
177  map<int,int> uniqueEdgeMap;
178  map<int,int> uniqueFaceMap;
179 
180  //this should be of size total number of local edges + faces
181  Array<OneD, int> modeoffset(1 + nNonDirEdgeIDs + nNonDirFaceIDs,0);
182  Array<OneD, int> globaloffset(1 + nNonDirEdgeIDs + nNonDirFaceIDs,0);
183 
184  const Array<OneD, const ExpListSharedPtr>& bndCondExp = expList->GetBndCondExpansions();
185  LocalRegions::Expansion2DSharedPtr bndCondFaceExp;
186  const Array<OneD, const SpatialDomains::BoundaryConditionShPtr>&
187  bndConditions = expList->GetBndConditions();
188 
189  int meshVertId;
190  int meshEdgeId;
191  int meshFaceId;
192 
193  const Array<OneD, const int> &extradiredges
194  = asmMap->GetExtraDirEdges();
195  for(i=0; i<extradiredges.num_elements(); ++i)
196  {
197  meshEdgeId=extradiredges[i];
198  edgeDirMap.insert(meshEdgeId);
199  }
200 
201  //Determine which boundary edges and faces have dirichlet values
202  for(i = 0; i < bndCondExp.num_elements(); i++)
203  {
204  cnt = 0;
205  for(j = 0; j < bndCondExp[i]->GetNumElmts(); j++)
206  {
207  bndCondFaceExp = std::dynamic_pointer_cast<
208  LocalRegions::Expansion2D>(bndCondExp[i]->GetExp(j));
209  if (bndConditions[i]->GetBoundaryConditionType() ==
211  {
212  for(k = 0; k < bndCondFaceExp->GetNedges(); k++)
213  {
214  meshEdgeId = bndCondFaceExp->as<LocalRegions::Expansion2D>()->GetGeom2D()->GetEid(k);
215  if(edgeDirMap.count(meshEdgeId) == 0)
216  {
217  edgeDirMap.insert(meshEdgeId);
218  }
219  }
220  meshFaceId = bndCondFaceExp->as<LocalRegions::Expansion2D>()->GetGeom2D()->GetGlobalID();
221  faceDirMap.insert(meshFaceId);
222  }
223  }
224  }
225 
226  int dof=0;
227  int maxFaceDof=0;
228  int maxEdgeDof=0;
229  int nlocalNonDirEdges=0;
230  int nlocalNonDirFaces=0;
231  int ntotalentries=0;
232 
233  map<int,int> EdgeSize;
234  map<int,int> FaceSize;
235  map<int,pair<int,int> >FaceModes;
236 
237  /// - Count edges, face and add up min edges and min face sizes
238  for(n = 0; n < n_exp; ++n)
239  {
240  locExpansion = expList->GetExp(n);
241 
242  nEdges = locExpansion->GetNedges();
243  for(j = 0; j < nEdges; ++j)
244  {
245  int nEdgeInteriorCoeffs = locExpansion->GetEdgeNcoeffs(j) - 2;
246  meshEdgeId = locExpansion->as<LocalRegions::Expansion3D>()
247  ->GetGeom3D()->GetEid(j);
248  if(EdgeSize.count(meshEdgeId) == 0)
249  {
250  EdgeSize[meshEdgeId] = nEdgeInteriorCoeffs;
251  }
252  else
253  {
254  EdgeSize[meshEdgeId] = min(EdgeSize[meshEdgeId],
255  nEdgeInteriorCoeffs);
256  }
257  }
258 
259  nFaces = locExpansion->GetNfaces();
260  for(j = 0; j < nFaces; ++j)
261  {
262  int nFaceInteriorCoeffs = locExpansion->GetFaceIntNcoeffs(j);
263  meshFaceId = locExpansion->as<LocalRegions::Expansion3D>()
264  ->GetGeom3D()->GetFid(j);
265  if(FaceSize.count(meshFaceId) == 0)
266  {
267  FaceSize[meshFaceId] = nFaceInteriorCoeffs;
268 
269  int m0,m1;
270  locExpansion->GetFaceNumModes(j,locExpansion->GetForient(j),m0,m1);
271  FaceModes[meshFaceId] = pair<int,int>(m0,m1);
272  }
273  else
274  {
275  if(nFaceInteriorCoeffs < FaceSize[meshFaceId])
276  {
277  FaceSize[meshFaceId] = nFaceInteriorCoeffs;
278  int m0,m1;
279  locExpansion->GetFaceNumModes(j,locExpansion->GetForient(j),m0,m1);
280  FaceModes[meshFaceId] = pair<int,int>(m0,m1);
281  }
282  }
283  }
284  }
285 
286  bool verbose =
287  expList->GetSession()->DefinesCmdLineArgument("verbose");
288 
289  // For parallel runs need to check have minimum of edges and faces over
290  // partition boundaries
291  if(m_comm->GetSize() > 1)
292  {
293  int EdgeSizeLen = EdgeSize.size();
294  int FaceSizeLen = FaceSize.size();
295  Array<OneD, long> FacetMap(EdgeSizeLen+FaceSizeLen,-1);
296  Array<OneD, NekDouble> FacetLen(EdgeSizeLen+FaceSizeLen,-1);
297 
298  map<int,int>::iterator it;
299 
300  cnt = 0;
301  int maxid = 0;
302  for(it = EdgeSize.begin(); it!=EdgeSize.end(); ++it,++cnt)
303  {
304  FacetMap[cnt] = it->first;
305  maxid = max(it->first,maxid);
306  FacetLen[cnt] = it->second;
307  }
308  maxid++;
309 
310  m_comm->AllReduce(maxid,ReduceMax);
311 
312  for(it = FaceSize.begin(); it!=FaceSize.end(); ++it,++cnt)
313  {
314  FacetMap[cnt] = it->first + maxid;
315  FacetLen[cnt] = it->second;
316  }
317 
318  //Exchange vertex data over different processes
319  Gs::gs_data *tmp = Gs::Init(FacetMap, m_comm, verbose);
320  Gs::Gather(FacetLen, Gs::gs_min, tmp);
321 
322  cnt = 0;
323  for(it = EdgeSize.begin(); it!=EdgeSize.end(); ++it,++cnt)
324  {
325  it->second = (int) FacetLen[cnt];
326  }
327 
328  for(it = FaceSize.begin(); it!=FaceSize.end(); ++it,++cnt)
329  {
330  it->second = (int)FacetLen[cnt];
331  }
332  }
333 
334  // Loop over all the elements in the domain and compute total edge
335  // DOF and set up unique ordering.
336  map<int,int> nblks;
337  int matrixlocation = 0;
338 
339  // First do periodic edges
340  for (auto &pIt : periodicEdges)
341  {
342  meshEdgeId = pIt.first;
343 
344  if(edgeDirMap.count(meshEdgeId)==0)
345  {
346  dof = EdgeSize[meshEdgeId];
347  if(uniqueEdgeMap.count(meshEdgeId)==0 && dof > 0)
348  {
349  bool SetUpNewEdge = true;
350 
351 
352  for (i = 0; i < pIt.second.size(); ++i)
353  {
354  if (!pIt.second[i].isLocal)
355  {
356  continue;
357  }
358 
359  int meshEdgeId2 = pIt.second[i].id;
360  if(edgeDirMap.count(meshEdgeId2)==0)
361  {
362  if(uniqueEdgeMap.count(meshEdgeId2)!=0)
363  {
364  // set unique map to same location
365  uniqueEdgeMap[meshEdgeId] =
366  uniqueEdgeMap[meshEdgeId2];
367  SetUpNewEdge = false;
368  }
369  }
370  else
371  {
372  edgeDirMap.insert(meshEdgeId);
373  SetUpNewEdge = false;
374  }
375  }
376 
377  if(SetUpNewEdge)
378  {
379  uniqueEdgeMap[meshEdgeId]=matrixlocation;
380  globaloffset[matrixlocation]+=ntotalentries;
381  modeoffset[matrixlocation]=dof*dof;
382  ntotalentries+=dof*dof;
383  nblks [matrixlocation++] = dof;
384  }
385  }
386  }
387  }
388 
389  for(cnt=n=0; n < n_exp; ++n)
390  {
391  locExpansion = expList->GetExp(n);
392 
393  for (j = 0; j < locExpansion->GetNedges(); ++j)
394  {
395  meshEdgeId = locExpansion->as<LocalRegions::Expansion3D>()->GetGeom3D()->GetEid(j);
396  dof = EdgeSize[meshEdgeId];
397  maxEdgeDof = (dof > maxEdgeDof ? dof : maxEdgeDof);
398 
399  if(edgeDirMap.count(meshEdgeId)==0)
400  {
401  if(uniqueEdgeMap.count(meshEdgeId)==0 && dof > 0)
402 
403  {
404  uniqueEdgeMap[meshEdgeId]=matrixlocation;
405 
406  globaloffset[matrixlocation]+=ntotalentries;
407  modeoffset[matrixlocation]=dof*dof;
408  ntotalentries+=dof*dof;
409  nblks[matrixlocation++] = dof;
410  }
411  nlocalNonDirEdges+=dof*dof;
412  }
413  }
414  }
415 
416  // Loop over all the elements in the domain and compute max face
417  // DOF. Reduce across all processes to get universal maximum.
418  // - Periodic faces
419  for (auto &pIt : periodicFaces)
420  {
421  meshFaceId = pIt.first;
422 
423  if(faceDirMap.count(meshFaceId)==0)
424  {
425  dof = FaceSize[meshFaceId];
426 
427  if(uniqueFaceMap.count(meshFaceId) == 0 && dof > 0)
428  {
429  bool SetUpNewFace = true;
430 
431  if(pIt.second[0].isLocal)
432  {
433  int meshFaceId2 = pIt.second[0].id;
434 
435  if(faceDirMap.count(meshFaceId2)==0)
436  {
437  if(uniqueFaceMap.count(meshFaceId2)!=0)
438  {
439  // set unique map to same location
440  uniqueFaceMap[meshFaceId] =
441  uniqueFaceMap[meshFaceId2];
442  SetUpNewFace = false;
443  }
444  }
445  else // set face to be a Dirichlet face
446  {
447  faceDirMap.insert(meshFaceId);
448  SetUpNewFace = false;
449  }
450  }
451 
452  if(SetUpNewFace)
453  {
454  uniqueFaceMap[meshFaceId]=matrixlocation;
455 
456  modeoffset[matrixlocation]=dof*dof;
457  globaloffset[matrixlocation]+=ntotalentries;
458  ntotalentries+=dof*dof;
459  nblks[matrixlocation++] = dof;
460  }
461  }
462  }
463  }
464 
465  for(cnt=n=0; n < n_exp; ++n)
466  {
467  locExpansion = expList->GetExp(n);
468 
469  for (j = 0; j < locExpansion->GetNfaces(); ++j)
470  {
471  meshFaceId = locExpansion->as<LocalRegions::Expansion3D>()->
472  GetGeom3D()->GetFid(j);
473 
474  dof = FaceSize[meshFaceId];
475  maxFaceDof = (dof > maxFaceDof ? dof : maxFaceDof);
476 
477  if(faceDirMap.count(meshFaceId)==0)
478  {
479  if(uniqueFaceMap.count(meshFaceId)==0 && dof > 0)
480  {
481  uniqueFaceMap[meshFaceId]=matrixlocation;
482  modeoffset[matrixlocation]=dof*dof;
483  globaloffset[matrixlocation]+=ntotalentries;
484  ntotalentries+=dof*dof;
485  nblks[matrixlocation++] = dof;
486  }
487  nlocalNonDirFaces+=dof*dof;
488  }
489  }
490  }
491 
492  m_comm->AllReduce(maxEdgeDof, ReduceMax);
493  m_comm->AllReduce(maxFaceDof, ReduceMax);
494 
495  //Allocate arrays for block to universal map (number of expansions * p^2)
496  Array<OneD, long> BlockToUniversalMap(ntotalentries,-1);
497  Array<OneD, int> localToGlobalMatrixMap(nlocalNonDirEdges +
498  nlocalNonDirFaces,-1);
499 
500  //Allocate arrays to store matrices (number of expansions * p^2)
501  Array<OneD, NekDouble> BlockArray(nlocalNonDirEdges +
502  nlocalNonDirFaces,0.0);
503 
504  int matrixoffset=0;
505  int vGlobal;
506  int uniEdgeOffset = 0;
507 
508  // Need to obtain a fixed offset for the universal number
509  // of the faces which come after the edge numbering
510  for(n=0; n < n_exp; ++n)
511  {
512  for(j = 0; j < locExpansion->GetNedges(); ++j)
513  {
514  meshEdgeId = locExpansion->as<LocalRegions::Expansion3D>()
515  ->GetGeom3D()->GetEid(j);
516 
517  uniEdgeOffset = max(meshEdgeId, uniEdgeOffset);
518  }
519  }
520  uniEdgeOffset++;
521 
522  m_comm->AllReduce(uniEdgeOffset,ReduceMax);
523  uniEdgeOffset = uniEdgeOffset*maxEdgeDof*maxEdgeDof;
524 
525  for(n=0; n < n_exp; ++n)
526  {
527  locExpansion = expList->GetExp(n);
528 
529  //loop over the edges of the expansion
530  for(j = 0; j < locExpansion->GetNedges(); ++j)
531  {
532  //get mesh edge id
533  meshEdgeId = locExpansion->as<LocalRegions::Expansion3D>()
534  ->GetGeom3D()->GetEid(j);
535 
536  nedgemodes = EdgeSize[meshEdgeId];
537 
538  if(edgeDirMap.count(meshEdgeId)==0 && nedgemodes > 0)
539  {
540  // Determine the Global edge offset
541  int edgeOffset = globaloffset[uniqueEdgeMap[meshEdgeId]];
542 
543  // Determine a universal map offset
544  int uniOffset = meshEdgeId;
545  auto pIt = periodicEdges.find(meshEdgeId);
546  if (pIt != periodicEdges.end())
547  {
548  for (int l = 0; l < pIt->second.size(); ++l)
549  {
550  uniOffset = min(uniOffset, pIt->second[l].id);
551  }
552  }
553  uniOffset = uniOffset*maxEdgeDof*maxEdgeDof;
554 
555  for(k=0; k<nedgemodes*nedgemodes; ++k)
556  {
557  vGlobal=edgeOffset+k;
558  localToGlobalMatrixMap[matrixoffset+k]=vGlobal;
559  BlockToUniversalMap[vGlobal] = uniOffset + k + 1;
560  }
561  matrixoffset+=nedgemodes*nedgemodes;
562  }
563  }
564 
565  Array<OneD, unsigned int> faceInteriorMap;
566  Array<OneD, int> faceInteriorSign;
567  //loop over the faces of the expansion
568  for(j = 0; j < locExpansion->GetNfaces(); ++j)
569  {
570  //get mesh face id
571  meshFaceId = locExpansion->as<LocalRegions::Expansion3D>()
572  ->GetGeom3D()->GetFid(j);
573 
574  nfacemodes = FaceSize[meshFaceId];
575 
576  //Check if face has dirichlet values
577  if(faceDirMap.count(meshFaceId)==0 && nfacemodes > 0)
578  {
579  // Determine the Global edge offset
580  int faceOffset = globaloffset[uniqueFaceMap[meshFaceId]];
581  // Determine a universal map offset
582  int uniOffset = meshFaceId;
583  // use minimum face edge when periodic
584  auto pIt = periodicFaces.find(meshFaceId);
585  if (pIt != periodicFaces.end())
586  {
587  uniOffset = min(uniOffset, pIt->second[0].id);
588  }
589  uniOffset = uniOffset * maxFaceDof * maxFaceDof;
590 
591  for(k=0; k<nfacemodes*nfacemodes; ++k)
592  {
593  vGlobal=faceOffset+k;
594 
595  localToGlobalMatrixMap[matrixoffset+k]
596  = vGlobal;
597 
598  BlockToUniversalMap[vGlobal] = uniOffset +
599  uniEdgeOffset + k + 1;
600  }
601  matrixoffset+=nfacemodes*nfacemodes;
602  }
603  }
604  }
605 
606  matrixoffset=0;
607 
608  map<int,int>::iterator it;
609  Array<OneD, unsigned int> n_blks(nblks.size()+1);
610  n_blks[0] = nNonDirVerts;
611  for(i =1, it = nblks.begin(); it != nblks.end(); ++it)
612  {
613  n_blks[i++] = it->second;
614  }
615 
617  ::AllocateSharedPtr(n_blks, n_blks, blkmatStorage);
618 
619  //Here we loop over the expansion and build the block low energy
620  //preconditioner as well as the block versions of the transformation
621  //matrices.
622  for(cnt=n=0; n < n_exp; ++n)
623  {
624  locExpansion = expList->GetExp(n);
625  nCoeffs=locExpansion->NumBndryCoeffs();
626 
627  //Get correct transformation matrix for element type
628  DNekMat &R = (*m_RBlk->GetBlock(n,n));
629 
631  (nCoeffs, nCoeffs, zero, storage);
632  RSRT = (*pRSRT);
633 
634  nVerts=locExpansion->GetGeom()->GetNumVerts();
635  nEdges=locExpansion->GetGeom()->GetNumEdges();
636  nFaces=locExpansion->GetGeom()->GetNumFaces();
637 
638  //Get statically condensed matrix
639  loc_mat = (m_linsys.lock())->GetStaticCondBlock(n);
640 
641  //Extract boundary block (elemental S1)
642  bnd_mat=loc_mat->GetBlock(0,0);
643 
644  //offset by number of rows
645  offset = bnd_mat->GetRows();
646 
647  DNekScalMat &S=(*bnd_mat);
648 
649  DNekMat Sloc(nCoeffs,nCoeffs);
650 
651  // For variable p we need to just use the active modes
652  NekDouble mask1 = 1.0;
653  NekDouble mask2 = 1.0;
654  NekDouble val;
655 
656  for(int i = 0; i < nCoeffs; ++i)
657  {
658  if(m_signChange)
659  {
660  mask1 = (m_locToGloSignMult[cnt+i] == 0.0)? 0.0:1.0;
661  }
662  for(int j = 0; j < nCoeffs; ++j)
663  {
664  if(m_signChange)
665  {
666  mask2 = (m_locToGloSignMult[cnt+j] == 0.0)? 0.0:1.0;
667  }
668  val = S(i,j)*mask1*mask2;
669  Sloc.SetValue(i,j,val);
670  }
671  }
672 
673  //Calculate R*S*trans(R)
674  RSRT = R*Sloc*Transpose(R);
675 
676  //loop over vertices of the element and return the vertex map
677  //for each vertex
678  for (v=0; v<nVerts; ++v)
679  {
680  vMap1=locExpansion->GetVertexMap(v);
681 
682  //Get vertex map
683  globalrow = asmMap->
684  GetLocalToGlobalBndMap(cnt+vMap1)-nDirBnd;
685 
686  if(globalrow >= 0)
687  {
688  for (m=0; m<nVerts; ++m)
689  {
690  vMap2=locExpansion->GetVertexMap(m);
691 
692  //global matrix location (without offset due to
693  //dirichlet values)
694  globalcol = asmMap->
695  GetLocalToGlobalBndMap(cnt+vMap2)-nDirBnd;
696 
697  //offset for dirichlet conditions
698  if (globalcol == globalrow)
699  {
700  //modal connectivity between elements
701  sign1 = asmMap->
702  GetLocalToGlobalBndSign(cnt + vMap1);
703  sign2 = asmMap->
704  GetLocalToGlobalBndSign(cnt + vMap2);
705 
706  vertArray[globalrow]
707  += sign1*sign2*RSRT(vMap1,vMap2);
708 
709 
710  meshVertId = locExpansion->as<LocalRegions::Expansion3D>()->GetGeom3D()->GetVid(v);
711 
712  auto pIt = periodicVerts.find(meshVertId);
713  if (pIt != periodicVerts.end())
714  {
715  for (k = 0; k < pIt->second.size(); ++k)
716  {
717  meshVertId = min(meshVertId, pIt->second[k].id);
718  }
719  }
720 
721  VertBlockToUniversalMap[globalrow]
722  = meshVertId + 1;
723  }
724  }
725  }
726  }
727 
728  //loop over edges of the element and return the edge map
729  for (eid=0; eid<nEdges; ++eid)
730  {
731 
732  meshEdgeId = locExpansion->as<LocalRegions::Expansion3D>()
733  ->GetGeom3D()->GetEid(eid);
734 
735 
736  nedgemodes = EdgeSize[meshEdgeId];
737  if(nedgemodes)
738  {
739  nedgemodesloc = locExpansion->GetEdgeNcoeffs(eid)-2;
740  DNekMatSharedPtr m_locMat =
742  (nedgemodes,nedgemodes,zero,storage);
743 
744  Array<OneD, unsigned int> edgemodearray = locExpansion->GetEdgeInverseBoundaryMap(eid);
745 
746  if(edgeDirMap.count(meshEdgeId)==0)
747  {
748  for (v=0; v<nedgemodesloc; ++v)
749  {
750  eMap1=edgemodearray[v];
751  sign1 = asmMap->
752  GetLocalToGlobalBndSign(cnt + eMap1);
753 
754  if(sign1 == 0)
755  {
756  continue;
757  }
758 
759  for (m=0; m<nedgemodesloc; ++m)
760  {
761  eMap2=edgemodearray[m];
762 
763  //modal connectivity between elements
764  sign2 = asmMap->
765  GetLocalToGlobalBndSign(cnt + eMap2);
766 
767  NekDouble globalEdgeValue = sign1*sign2*RSRT(eMap1,eMap2);
768 
769  if(sign2 != 0)
770  {
771  //if(eMap1 == eMap2)
772  BlockArray[matrixoffset+v*nedgemodes+m]=globalEdgeValue;
773  }
774  }
775  }
776  matrixoffset+=nedgemodes*nedgemodes;
777  }
778  }
779  }
780 
781  //loop over faces of the element and return the face map
782  for (fid=0; fid<nFaces; ++fid)
783  {
784  meshFaceId = locExpansion->as<LocalRegions::Expansion3D>()
785  ->GetGeom3D()->GetFid(fid);
786 
787  nfacemodes = FaceSize[meshFaceId];
788  if(nfacemodes > 0)
789  {
790  DNekMatSharedPtr m_locMat =
792  (nfacemodes,nfacemodes,zero,storage);
793 
794  if(faceDirMap.count(meshFaceId) == 0)
795  {
796  Array<OneD, unsigned int> facemodearray;
797  StdRegions::Orientation faceOrient =
798  locExpansion->GetForient(fid);
799 
800  auto pIt = periodicFaces.find(meshFaceId);
801  if (pIt != periodicFaces.end())
802  {
803  if(meshFaceId == min(meshFaceId, pIt->second[0].id))
804  {
805  faceOrient = DeterminePeriodicFaceOrient
806  (faceOrient,pIt->second[0].orient);
807  }
808  }
809 
810  facemodearray = locExpansion->GetFaceInverseBoundaryMap
811  (fid,faceOrient,FaceModes[meshFaceId].first,
812  FaceModes[meshFaceId].second);
813 
814  for (v=0; v<nfacemodes; ++v)
815  {
816  fMap1=facemodearray[v];
817 
818  sign1 = asmMap->
819  GetLocalToGlobalBndSign(cnt + fMap1);
820 
821  ASSERTL1(sign1 != 0,"Something is wrong since we "
822  "shoudl only be extracting modes for "
823  "lowest order expansion");
824 
825  for (m=0; m<nfacemodes; ++m)
826  {
827  fMap2=facemodearray[m];
828 
829  //modal connectivity between elements
830  sign2 = asmMap->
831  GetLocalToGlobalBndSign(cnt + fMap2);
832 
833  ASSERTL1(sign2 != 0,"Something is wrong since "
834  "we shoudl only be extracting modes for "
835  "lowest order expansion");
836 
837  // Get the face-face value from the
838  // low energy matrix (S2)
839  NekDouble globalFaceValue = sign1*sign2*
840  RSRT(fMap1,fMap2);
841 
842  //local face value to global face value
843  //if(fMap1 == fMap2)
844  BlockArray[matrixoffset+v*nfacemodes+m]=
845  globalFaceValue;
846  }
847  }
848  matrixoffset+=nfacemodes*nfacemodes;
849  }
850  }
851  }
852 
853  //offset for the expansion
854  cnt+=nCoeffs;
855  }
856 
857  if(nNonDirVerts!=0)
858  {
859  //Exchange vertex data over different processes
860  Gs::gs_data *tmp = Gs::Init(VertBlockToUniversalMap, m_comm, verbose);
861  Gs::Gather(vertArray, Gs::gs_add, tmp);
862 
863  }
864 
865  Array<OneD, NekDouble> GlobalBlock(ntotalentries,0.0);
866  if(ntotalentries)
867  {
868  //Assemble edge matrices of each process
869  Vmath::Assmb(BlockArray.num_elements(),
870  BlockArray,
871  localToGlobalMatrixMap,
872  GlobalBlock);
873  }
874 
875  //Exchange edge & face data over different processes
876  Gs::gs_data *tmp1 = Gs::Init(BlockToUniversalMap, m_comm, verbose);
877  Gs::Gather(GlobalBlock, Gs::gs_add, tmp1);
878 
879  // Populate vertex block
880  for (int i = 0; i < nNonDirVerts; ++i)
881  {
882  VertBlk->SetValue(i,i,1.0/vertArray[i]);
883  }
884 
885  //Set the first block to be the diagonal of the vertex space
886  m_BlkMat->SetBlock(0,0, VertBlk);
887 
888  //Build the edge and face matrices from the vector
889  DNekMatSharedPtr gmat;
890 
891  offset=0;
892  // -1 since we ignore vert block
893  for(int loc=0; loc<n_blks.num_elements()-1; ++loc)
894  {
895  nmodes = n_blks[1+loc];
897  (nmodes,nmodes,zero,storage);
898 
899  for (v=0; v<nmodes; ++v)
900  {
901  for (m=0; m<nmodes; ++m)
902  {
903  NekDouble Value = GlobalBlock[offset+v*nmodes+m];
904  gmat->SetValue(v,m,Value);
905 
906  }
907  }
908  m_BlkMat->SetBlock(1+loc,1+loc, gmat);
909  offset+=modeoffset[loc];
910  }
911 
912  // invert blocks.
913  int totblks=m_BlkMat->GetNumberOfBlockRows();
914  for (i=1; i< totblks; ++i)
915  {
916  unsigned int nmodes=m_BlkMat->GetNumberOfRowsInBlockRow(i);
917  if(nmodes)
918  {
919  DNekMatSharedPtr tmp_mat =
921  (nmodes,nmodes,zero,storage);
922 
923  tmp_mat=m_BlkMat->GetBlock(i,i);
924  tmp_mat->Invert();
925 
926  m_BlkMat->SetBlock(i,i,tmp_mat);
927  }
928  }
929  }
LibUtilities::CommSharedPtr m_comm
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
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:73
const std::weak_ptr< GlobalLinSys > m_linsys
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
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
StdRegions::Orientation DeterminePeriodicFaceOrient(StdRegions::Orientation faceOrient, StdRegions::Orientation perFaceOrient)
Determine relative orientation between two faces.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
NekMatrix< NekDouble, StandardMatrixTag > DNekMat
Definition: NekTypeDefs.hpp:51
double NekDouble
void Assmb(int n, const T *x, const int *y, T *z)
Assemble z[y[i]] += x[i]; z should be zero&#39;d first.
Definition: Vmath.cpp:712
std::map< int, std::vector< PeriodicEntity > > PeriodicMap
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:65
std::shared_ptr< Expansion2D > Expansion2DSharedPtr
Definition: Expansion1D.h:47
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
std::weak_ptr< AssemblyMap > m_locToGloMap
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, ScaledMatrixTag > DNekScalMat

◆ v_DoMultiplybyInverseTransformationMatrix()

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

Multiply by the block inverse transformation matrix.

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 1258 of file PreconditionerLowEnergy.cpp.

References ASSERTL1, Blas::Dgemm(), Nektar::eWrapper, Vmath::Gathr(), m_InvRBlk, Nektar::MultiRegions::Preconditioner::m_locToGloMap, m_locToGloSignMult, m_map, m_sameBlock, and Vmath::Vcopy().

1261  {
1262  auto asmMap = m_locToGloMap.lock();
1263 
1264  int nGlobBndDofs = asmMap->GetNumGlobalBndCoeffs();
1265  int nDirBndDofs = asmMap->GetNumGlobalDirBndCoeffs();
1266  int nGlobHomBndDofs = nGlobBndDofs - nDirBndDofs;
1267  int nLocBndDofs = asmMap->GetNumLocalBndCoeffs();
1268 
1269  ASSERTL1(pInput.num_elements() >= nGlobHomBndDofs,
1270  "Input array is greater than the nGlobHomBndDofs");
1271  ASSERTL1(pOutput.num_elements() >= nGlobHomBndDofs,
1272  "Output array is greater than the nGlobHomBndDofs");
1273 
1274  //vectors of length number of non-dirichlet boundary dofs
1275  NekVector<NekDouble> F_GlobBnd(nGlobHomBndDofs,pInput,eWrapper);
1276  NekVector<NekDouble> F_HomBnd(nGlobHomBndDofs,pOutput,
1277  eWrapper);
1278  //Block inverse transformation matrix
1279  DNekBlkMat &invR = *m_InvRBlk;
1280 
1281  Array<OneD, NekDouble> pLocal(nLocBndDofs, 0.0);
1282  NekVector<NekDouble> F_LocBnd(nLocBndDofs,pLocal,eWrapper);
1283  m_map = asmMap->GetLocalToGlobalBndMap();
1284  Array<OneD, NekDouble> pLocalIn(nLocBndDofs, 0.0);
1285 
1286  // Allocated array of size number of global boundary dofs and copy
1287  // the input array to the tmp array offset by Dirichlet boundary
1288  // conditions.
1289  Array<OneD,NekDouble> tmp(nGlobBndDofs,0.0);
1290  Vmath::Vcopy(nGlobHomBndDofs, pInput.get(), 1, tmp.get() + nDirBndDofs, 1);
1291 
1292  //Global boundary dofs (with zeroed dirichlet values) to
1293  //local boundary dofs
1294  Vmath::Gathr(m_map.num_elements(), m_locToGloSignMult.get(),
1295  tmp.get(), m_map.get(), pLocalIn.get());
1296 
1297  //Multiply by the inverse transformation matrix
1298  int cnt = 0;
1299  int cnt1 = 0;
1300  for(int i = 0; i < m_sameBlock.size(); ++i)
1301  {
1302  int nexp = m_sameBlock[i].first;
1303  int nbndcoeffs = m_sameBlock[i].second;
1304  Blas::Dgemm('N','N', nbndcoeffs, nexp, nbndcoeffs,
1305  1.0, &(invR.GetBlock(cnt1,cnt1)->GetPtr()[0]),
1306  nbndcoeffs,pLocalIn.get() + cnt, nbndcoeffs,
1307  0.0, pLocal.get() + cnt, nbndcoeffs);
1308  cnt += nbndcoeffs*nexp;
1309  cnt1 += nexp;
1310  }
1311 
1312 
1313  //Assemble local boundary to global non-dirichlet boundary
1314  asmMap->AssembleBnd(F_LocBnd,F_HomBnd,nDirBndDofs);
1315 
1316  }
std::vector< std::pair< int, int > > m_sameBlock
void Gathr(int n, const T *x, const int *y, T *z)
Gather vector z[i] = x[y[i]].
Definition: Vmath.cpp:647
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, BlockMatrixTag > DNekBlkMat
Definition: NekTypeDefs.hpp:59
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
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
std::weak_ptr< AssemblyMap > m_locToGloMap

◆ v_DoMultiplybyInverseTransposedTransformationMatrix()

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

Multiply by the block tranposed inverse transformation matrix.

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 1321 of file PreconditionerLowEnergy.cpp.

References ASSERTL1, Blas::Dgemm(), Nektar::eWrapper, m_InvRBlk, Nektar::MultiRegions::Preconditioner::m_locToGloMap, m_map, m_multiplicity, m_sameBlock, v_TransformedSchurCompl(), and Vmath::Vmul().

1324  {
1325  auto asmMap = m_locToGloMap.lock();
1326 
1327  int nGlobBndDofs = asmMap->GetNumGlobalBndCoeffs();
1328  int nDirBndDofs = asmMap->GetNumGlobalDirBndCoeffs();
1329  int nGlobHomBndDofs = nGlobBndDofs - nDirBndDofs;
1330  int nLocBndDofs = asmMap->GetNumLocalBndCoeffs();
1331 
1332  ASSERTL1(pInput.num_elements() >= nGlobHomBndDofs,
1333  "Input array is greater than the nGlobHomBndDofs");
1334  ASSERTL1(pOutput.num_elements() >= nGlobHomBndDofs,
1335  "Output array is greater than the nGlobHomBndDofs");
1336 
1337  //vectors of length number of non-dirichlet boundary dofs
1338  NekVector<NekDouble> F_GlobBnd(nGlobHomBndDofs,pInput,eWrapper);
1339  NekVector<NekDouble> F_HomBnd(nGlobHomBndDofs,pOutput,
1340  eWrapper);
1341  //Block inverse transformation matrix
1342  DNekBlkMat &invR = *m_InvRBlk;
1343 
1344  Array<OneD, NekDouble> pLocalIn(nLocBndDofs, 0.0);
1345  NekVector<NekDouble> F_LocBnd(nLocBndDofs,pLocalIn,eWrapper);
1346  m_map = asmMap->GetLocalToGlobalBndMap();
1347  Array<OneD, NekDouble> pLocal(nLocBndDofs, 0.0);
1348 
1349  asmMap->GlobalToLocalBnd(pInput,pLocalIn, nDirBndDofs);
1350 
1351 
1352  //Multiply by the transpose of block transformation matrix
1353  int cnt = 0;
1354  int cnt1 = 0;
1355  for(int i = 0; i < m_sameBlock.size(); ++i)
1356  {
1357  int nexp = m_sameBlock[i].first;
1358  int nbndcoeffs = m_sameBlock[i].second;
1359  Blas::Dgemm('T','N', nbndcoeffs, nexp, nbndcoeffs,
1360  1.0, &(invR.GetBlock(cnt1,cnt1)->GetPtr()[0]),
1361  nbndcoeffs,pLocalIn.get() + cnt, nbndcoeffs,
1362  0.0, pLocal.get() + cnt, nbndcoeffs);
1363  cnt += nbndcoeffs*nexp;
1364  cnt1 += nexp;
1365  }
1366 
1367 
1368  asmMap->AssembleBnd(pLocal,pOutput, nDirBndDofs);
1369 
1370  Vmath::Vmul(nGlobHomBndDofs,pOutput,1,m_multiplicity,1,pOutput,1);
1371  }
std::vector< std::pair< int, int > > m_sameBlock
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, BlockMatrixTag > DNekBlkMat
Definition: NekTypeDefs.hpp:59
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
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
std::weak_ptr< AssemblyMap > m_locToGloMap
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.cpp:186

◆ v_DoPreconditioner()

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

Apply the low energy preconditioner during the conjugate gradient routine

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 936 of file PreconditionerLowEnergy.cpp.

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

939  {
940  int nDir = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
941  int nGlobal = m_locToGloMap.lock()->GetNumGlobalBndCoeffs();
942  int nNonDir = nGlobal-nDir;
943  DNekBlkMat &M = (*m_BlkMat);
944 
945  NekVector<NekDouble> r(nNonDir,pInput,eWrapper);
946  NekVector<NekDouble> z(nNonDir,pOutput,eWrapper);
947 
948  z = M * r;
949  }
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, BlockMatrixTag > DNekBlkMat
Definition: NekTypeDefs.hpp:59
std::weak_ptr< AssemblyMap > m_locToGloMap

◆ v_DoTransformFromLowEnergy()

void Nektar::MultiRegions::PreconditionerLowEnergy::v_DoTransformFromLowEnergy ( Array< OneD, NekDouble > &  pInOut)
privatevirtual

transform the solution vector from low energy back to the original basis.

After the conjugate gradient routine the output vector is in the low energy basis and must be trasnformed back to the original basis in order to get the correct solution out. the solution vector i.e. \(\mathbf{x}=\mathbf{R^{T}}\mathbf{\overline{x}}\).

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 1202 of file PreconditionerLowEnergy.cpp.

References ASSERTL1, Vmath::Assmb(), Blas::Dgemm(), Nektar::eWrapper, Nektar::MultiRegions::Preconditioner::m_locToGloMap, m_locToGloSignMult, m_map, m_RBlk, m_sameBlock, and Vmath::Vcopy().

1204  {
1205  auto asmMap = m_locToGloMap.lock();
1206 
1207  int nGlobBndDofs = asmMap->GetNumGlobalBndCoeffs();
1208  int nDirBndDofs = asmMap->GetNumGlobalDirBndCoeffs();
1209  int nGlobHomBndDofs = nGlobBndDofs - nDirBndDofs;
1210  int nLocBndDofs = asmMap->GetNumLocalBndCoeffs();
1211 
1212  ASSERTL1(pInOut.num_elements() >= nGlobBndDofs,
1213  "Output array is greater than the nGlobBndDofs");
1214 
1215  //Block transformation matrix
1216  DNekBlkMat &R = *m_RBlk;
1217 
1218  Array<OneD, NekDouble> tmpOffset = pInOut + nDirBndDofs;
1219  NekVector<NekDouble> V_GlobHomBnd(nGlobHomBndDofs, tmpOffset, eWrapper);
1220 
1221  Array<OneD, NekDouble> pLocalIn(nLocBndDofs, 0.0);
1222  NekVector<NekDouble> V_LocBnd(nLocBndDofs,pLocalIn,eWrapper);
1223  m_map = asmMap->GetLocalToGlobalBndMap();
1224  Array<OneD,NekDouble> tmp(nGlobBndDofs,0.0);
1225  Array<OneD, NekDouble> pLocal(nLocBndDofs, 0.0);
1226 
1227  //Global boundary (less dirichlet) to local boundary
1228  asmMap->GlobalToLocalBnd(V_GlobHomBnd,V_LocBnd, nDirBndDofs);
1229 
1230  //Multiply by the transpose of block transformation matrix
1231  int cnt = 0;
1232  int cnt1 = 0;
1233  for(int i = 0; i < m_sameBlock.size(); ++i)
1234  {
1235  int nexp = m_sameBlock[i].first;
1236  int nbndcoeffs = m_sameBlock[i].second;
1237  Blas::Dgemm('T','N', nbndcoeffs, nexp, nbndcoeffs,
1238  1.0, &(R.GetBlock(cnt1,cnt1)->GetPtr()[0]),
1239  nbndcoeffs,pLocalIn.get() + cnt, nbndcoeffs,
1240  0.0, pLocal.get() + cnt, nbndcoeffs);
1241  cnt += nbndcoeffs*nexp;
1242  cnt1 += nexp;
1243  }
1244 
1245  //Assemble local boundary to global boundary
1246  Vmath::Assmb(nLocBndDofs, m_locToGloSignMult.get(),pLocal.get(), m_map.get(), tmp.get());
1247 
1248  //Universal assemble across processors
1249  asmMap->UniversalAssembleBnd(tmp);
1250 
1251  //copy non-dirichlet boundary values
1252  Vmath::Vcopy(nGlobBndDofs-nDirBndDofs, tmp.get() + nDirBndDofs, 1, pInOut.get() + nDirBndDofs, 1);
1253  }
std::vector< std::pair< int, int > > m_sameBlock
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, BlockMatrixTag > DNekBlkMat
Definition: NekTypeDefs.hpp:59
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
void Assmb(int n, const T *x, const int *y, T *z)
Assemble z[y[i]] += x[i]; z should be zero&#39;d first.
Definition: Vmath.cpp:712
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
std::weak_ptr< AssemblyMap > m_locToGloMap

◆ v_DoTransformToLowEnergy() [1/2]

void Nektar::MultiRegions::PreconditionerLowEnergy::v_DoTransformToLowEnergy ( Array< OneD, NekDouble > &  pInOut,
int  offset 
)
privatevirtual

Transform the solution vector vector to low energy.

As the conjugate gradient system is solved for the low energy basis, the solution vector \(\mathbf{x}\) must be transformed to the low energy basis i.e. \(\overline{\mathbf{x}}=\mathbf{R}\mathbf{x}\).

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 1076 of file PreconditionerLowEnergy.cpp.

References Blas::Dgemm(), Nektar::eWrapper, Vmath::Gathr(), Nektar::MultiRegions::Preconditioner::m_locToGloMap, m_locToGloSignMult, m_map, m_RBlk, m_sameBlock, and Vmath::Vcopy().

1079  {
1080  auto asmMap = m_locToGloMap.lock();
1081  int nGlobBndDofs = asmMap->GetNumGlobalBndCoeffs();
1082  int nDirBndDofs = asmMap->GetNumGlobalDirBndCoeffs();
1083  int nGlobHomBndDofs = nGlobBndDofs - nDirBndDofs;
1084  int nLocBndDofs = asmMap->GetNumLocalBndCoeffs();
1085 
1086  //Non-dirichlet boundary dofs
1087  Array<OneD, NekDouble> tmpOffset = pInOut + offset;
1088  NekVector<NekDouble> F_HomBnd(nGlobHomBndDofs, tmpOffset, eWrapper);
1089 
1090  //Block transformation matrix
1091  DNekBlkMat &R = *m_RBlk;
1092 
1093  Array<OneD, NekDouble> pLocal(nLocBndDofs, 0.0);
1094  NekVector<NekDouble> F_LocBnd(nLocBndDofs,pLocal,eWrapper);
1095  m_map = asmMap->GetLocalToGlobalBndMap();
1096  Array<OneD, NekDouble> pLocalIn(nLocBndDofs, 0.0);
1097 
1098  //Not actually needed but we should only work with the
1099  //Global boundary dofs
1100  Array<OneD,NekDouble> tmp(nGlobBndDofs,0.0);
1101  Vmath::Vcopy(nGlobBndDofs, pInOut.get(), 1, tmp.get(), 1);
1102 
1103  //Global boundary (with dirichlet values) to local
1104  //boundary with multiplicity
1105  Vmath::Gathr(m_map.num_elements(), m_locToGloSignMult.get(),
1106  tmp.get(), m_map.get(), pLocalIn.get());
1107 
1108  //Multiply by the block transformation matrix
1109  int cnt = 0;
1110  int cnt1 = 0;
1111  for(int i = 0; i < m_sameBlock.size(); ++i)
1112  {
1113  int nexp = m_sameBlock[i].first;
1114  int nbndcoeffs = m_sameBlock[i].second;
1115  Blas::Dgemm('N','N', nbndcoeffs, nexp, nbndcoeffs,
1116  1.0, &(R.GetBlock(cnt1,cnt1)->GetPtr()[0]),
1117  nbndcoeffs,pLocalIn.get() + cnt, nbndcoeffs,
1118  0.0, pLocal.get() + cnt, nbndcoeffs);
1119  cnt += nbndcoeffs*nexp;
1120  cnt1 += nexp;
1121  }
1122 
1123  //Assemble local boundary to global non-dirichlet Dofs
1124  asmMap->AssembleBnd(F_LocBnd,F_HomBnd, nDirBndDofs);
1125  }
std::vector< std::pair< int, int > > m_sameBlock
void Gathr(int n, const T *x, const int *y, T *z)
Gather vector z[i] = x[y[i]].
Definition: Vmath.cpp:647
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, BlockMatrixTag > DNekBlkMat
Definition: NekTypeDefs.hpp:59
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
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
std::weak_ptr< AssemblyMap > m_locToGloMap

◆ v_DoTransformToLowEnergy() [2/2]

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

Transform the solution vector to low energy form.

As the conjugate gradient system is solved for the low energy basis, the solution vector \(\mathbf{x}\) must be transformed to the low energy basis i.e. \(\overline{\mathbf{x}}=\mathbf{R}\mathbf{x}\).

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 1134 of file PreconditionerLowEnergy.cpp.

References ASSERTL1, Blas::Dgemm(), Nektar::eWrapper, Vmath::Gathr(), Nektar::MultiRegions::Preconditioner::m_locToGloMap, m_locToGloSignMult, m_map, m_RBlk, m_sameBlock, and Vmath::Vcopy().

1137  {
1138  auto asmMap = m_locToGloMap.lock();
1139 
1140  int nGlobBndDofs = asmMap->GetNumGlobalBndCoeffs();
1141  int nDirBndDofs = asmMap->GetNumGlobalDirBndCoeffs();
1142  int nGlobHomBndDofs = nGlobBndDofs - nDirBndDofs;
1143  int nLocBndDofs = asmMap->GetNumLocalBndCoeffs();
1144 
1145  //Input/output vectors should be length nGlobHomBndDofs
1146  ASSERTL1(pInput.num_elements() >= nGlobHomBndDofs,
1147  "Input array is greater than the nGlobHomBndDofs");
1148  ASSERTL1(pOutput.num_elements() >= nGlobHomBndDofs,
1149  "Output array is greater than the nGlobHomBndDofs");
1150 
1151  //vectors of length number of non-dirichlet boundary dofs
1152  NekVector<NekDouble> F_HomBnd(nGlobHomBndDofs,pOutput,
1153  eWrapper);
1154  //Block transformation matrix
1155  DNekBlkMat &R = *m_RBlk;
1156 
1157  Array<OneD, NekDouble> pLocal(nLocBndDofs, 0.0);
1158  NekVector<NekDouble> F_LocBnd(nLocBndDofs,pLocal,eWrapper);
1159  m_map = asmMap->GetLocalToGlobalBndMap();
1160  Array<OneD, NekDouble> pLocalIn(nLocBndDofs, 0.0);
1161 
1162  // Allocated array of size number of global boundary dofs and copy
1163  // the input array to the tmp array offset by Dirichlet boundary
1164  // conditions.
1165  Array<OneD,NekDouble> tmp(nGlobBndDofs,0.0);
1166  Vmath::Vcopy(nGlobHomBndDofs, pInput.get(), 1, tmp.get()
1167  + nDirBndDofs, 1);
1168 
1169  //Global boundary dofs (with zeroed dirichlet values) to
1170  //local boundary dofs - This also divides by the mulplicity
1171  Vmath::Gathr(m_map.num_elements(), m_locToGloSignMult.get(),
1172  tmp.get(), m_map.get(), pLocalIn.get());
1173 
1174  //Multiply by the block transformation matrix
1175  int cnt = 0;
1176  int cnt1 = 0;
1177  for(int i = 0; i < m_sameBlock.size(); ++i)
1178  {
1179  int nexp = m_sameBlock[i].first;
1180  int nbndcoeffs = m_sameBlock[i].second;
1181  Blas::Dgemm('N','N', nbndcoeffs, nexp, nbndcoeffs,
1182  1.0, &(R.GetBlock(cnt1,cnt1)->GetPtr()[0]),
1183  nbndcoeffs,pLocalIn.get() + cnt, nbndcoeffs,
1184  0.0, pLocal.get() + cnt, nbndcoeffs);
1185  cnt += nbndcoeffs*nexp;
1186  cnt1 += nexp;
1187  }
1188 
1189  //Assemble local boundary to global non-dirichlet boundary
1190  asmMap->AssembleBnd(F_LocBnd,F_HomBnd,nDirBndDofs);
1191  }
std::vector< std::pair< int, int > > m_sameBlock
void Gathr(int n, const T *x, const int *y, T *z)
Gather vector z[i] = x[y[i]].
Definition: Vmath.cpp:647
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, BlockMatrixTag > DNekBlkMat
Definition: NekTypeDefs.hpp:59
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
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
std::weak_ptr< AssemblyMap > m_locToGloMap

◆ v_InitObject()

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

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 74 of file PreconditionerLowEnergy.cpp.

References ASSERTL0, CreateMultiplicityMap(), Nektar::MultiRegions::eIterativeStaticCond, Nektar::MultiRegions::ePETScStaticCond, Nektar::MultiRegions::Preconditioner::m_comm, Nektar::MultiRegions::Preconditioner::m_linsys, Nektar::MultiRegions::Preconditioner::m_locToGloMap, and SetupBlockTransformationMatrix().

75  {
76  GlobalSysSolnType solvertype =
77  m_locToGloMap.lock()->GetGlobalSysSolnType();
78 
79  ASSERTL0(solvertype == eIterativeStaticCond ||
80  solvertype == ePETScStaticCond, "Solver type not valid");
81 
82  std::shared_ptr<MultiRegions::ExpList>
83  expList=((m_linsys.lock())->GetLocMat()).lock();
84 
85  m_comm = expList->GetComm();
86 
88 
89  locExpansion = expList->GetExp(0);
90 
91  int nDim = locExpansion->GetShapeDimension();
92 
93  ASSERTL0(nDim==3,
94  "Preconditioner type only valid in 3D");
95 
96  //Set up block transformation matrix
98 
99  //Sets up multiplicity map for transformation from global to local
101  }
LibUtilities::CommSharedPtr m_comm
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
const std::weak_ptr< GlobalLinSys > m_linsys
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:65
std::weak_ptr< AssemblyMap > m_locToGloMap

◆ v_TransformedSchurCompl()

DNekScalMatSharedPtr Nektar::MultiRegions::PreconditionerLowEnergy::v_TransformedSchurCompl ( int  n,
int  bndoffset,
const std::shared_ptr< DNekScalMat > &  loc_mat 
)
privatevirtual

Set up the transformed block matrix system.

Sets up a block elemental matrix in which each of the block matrix is the low energy equivalent i.e. \(\mathbf{S}_{2}=\mathbf{R}\mathbf{S}_{1}\mathbf{R}^{T}\)

Reimplemented from Nektar::MultiRegions::Preconditioner.

Definition at line 1382 of file PreconditionerLowEnergy.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::eFULL, Nektar::MultiRegions::Preconditioner::m_linsys, m_locToGloSignMult, m_RBlk, m_signChange, and Nektar::Transpose().

Referenced by v_DoMultiplybyInverseTransposedTransformationMatrix().

1385  {
1386  std::shared_ptr<MultiRegions::ExpList>
1387  expList=((m_linsys.lock())->GetLocMat()).lock();
1388 
1389  LocalRegions::ExpansionSharedPtr locExpansion;
1390  locExpansion = expList->GetExp(n);
1391  unsigned int nbnd=locExpansion->NumBndryCoeffs();
1392 
1393  MatrixStorage storage = eFULL;
1395  AllocateSharedPtr(nbnd,nbnd,0.0,storage);
1396 
1397  //transformation matrices
1398  DNekMat &R = (*m_RBlk->GetBlock(n,n));
1399 
1400  // Original Schur Complement
1401  DNekScalMat &S1 = (*loc_mat);
1402 
1403  DNekMat Sloc(nbnd,nbnd);
1404 
1405  // For variable p we need to just use the active modes
1406  NekDouble mask1 = 1.0;
1407  NekDouble mask2 = 1.0;
1408  NekDouble val;
1409 
1410  for(int i = 0; i < nbnd; ++i)
1411  {
1412  if(m_signChange)
1413  {
1414  mask1 = (m_locToGloSignMult[bndoffset+i] == 0.0)? 0.0:1.0;
1415  }
1416  for(int j = 0; j < nbnd; ++j)
1417  {
1418  if(m_signChange)
1419  {
1420  mask2 = (m_locToGloSignMult[bndoffset+j] == 0.0)? 0.0:1.0;
1421  }
1422  val = S1(i,j)*mask1*mask2;
1423  Sloc.SetValue(i,j,val);
1424  }
1425  }
1426 
1427  //create low energy matrix
1428  DNekMat &S2 = (*pS2);
1429 
1430  S2= R*Sloc*Transpose(R);
1431 
1432  DNekScalMatSharedPtr return_val;
1433  return_val = MemoryManager<DNekScalMat>::AllocateSharedPtr(1.0, pS2);
1434 
1435  return return_val;
1436  }
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
const std::weak_ptr< GlobalLinSys > m_linsys
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
NekMatrix< NekDouble, StandardMatrixTag > DNekMat
Definition: NekTypeDefs.hpp:51
double NekDouble
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:65
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, ScaledMatrixTag > DNekScalMat

Member Data Documentation

◆ className

string Nektar::MultiRegions::PreconditionerLowEnergy::className
static
Initial value:
"LowEnergyBlock",
"LowEnergy Preconditioning")

Name of class.

Registers the class with the Factory.

Definition at line 67 of file PreconditionerLowEnergy.h.

◆ m_BlkMat

DNekBlkMatSharedPtr Nektar::MultiRegions::PreconditionerLowEnergy::m_BlkMat
protected

Definition at line 78 of file PreconditionerLowEnergy.h.

Referenced by v_BuildPreconditioner().

◆ m_InvRBlk

DNekBlkMatSharedPtr Nektar::MultiRegions::PreconditionerLowEnergy::m_InvRBlk
protected

◆ m_locToGloSignMult

Array<OneD, NekDouble> Nektar::MultiRegions::PreconditionerLowEnergy::m_locToGloSignMult
protected

◆ m_map

Array<OneD, int> Nektar::MultiRegions::PreconditionerLowEnergy::m_map
protected

◆ m_multiplicity

Array<OneD, NekDouble> Nektar::MultiRegions::PreconditionerLowEnergy::m_multiplicity
protected

◆ m_RBlk

DNekBlkMatSharedPtr Nektar::MultiRegions::PreconditionerLowEnergy::m_RBlk
protected

◆ m_sameBlock

std::vector<std::pair<int,int> > Nektar::MultiRegions::PreconditionerLowEnergy::m_sameBlock
protected

◆ m_signChange

bool Nektar::MultiRegions::PreconditionerLowEnergy::m_signChange
protected