Dendro  5.01
Dendro in Greek language means tree. The Dendro library is a large scale (262K cores on ORNL's Titan) distributed memory adaptive octree framework. The main goal of Dendro is to perform large scale multiphysics simulations efficeiently in mordern supercomputers. Dendro consists of efficient parallel data structures and algorithms to perform variational ( finite element) methods and finite difference mthods on 2:1 balanced arbitary adaptive octrees which enables the users to perform simulations raning from black holes (binary black hole mergers) to blood flow in human body, where applications ranging from relativity, astrophysics to biomedical engineering.
feVector.h
1 //
2 // Created by milinda on 10/30/18.
3 //
4 
10 #ifndef DENDRO_5_0_FEVECTOR_H
11 #define DENDRO_5_0_FEVECTOR_H
12 
13 #include "feVec.h"
14 
15 template <typename T>
16 class feVector : public feVec {
17 
18 protected:
19 
21  unsigned int m_uiDof;
22 
24  VECType * m_uiEleVecIn;
25 
26  /***@brief element nodal vecOut */
27  VECType * m_uiEleVecOut;
28 
30  double * m_uiEleCoords;
31 
32 
33 public:
38  feVector(ot::DA* da,unsigned int dof=1);
39 
40  ~feVector();
41 
46  //virtual void evalVec(VECType* out,double scale=1.0);
47 
48 
55  virtual void computeVec(const VECType* in,VECType* out,double scale=1.0);
56 
57 
59  //virtual void elementalEvalVec(VECType* out,double scale=1.0)=0;
60 
63  virtual void elementalComputVec(const VECType* in,VECType* out,double* coords=NULL,double scale=1.0)=0;
64 
65 #ifdef BUILD_WITH_PETSC
66 
73  virtual void computeVec(const Vec& in,Vec& out,double scale=1.0);
74 
75 #endif
76 
77 
78  T& asLeaf() { return static_cast<T&>(*this);}
79 
80  bool preComputeVec(const VECType* in, VECType* out,double scale=1.0) {
81  return asLeaf().preComputeVec(in,out,scale);
82  }
83 
84  bool postComputeVec(const VECType* in, VECType* out,double scale=1.0) {
85  return asLeaf().postComputeVec(in,out,scale);
86  }
87 
88  bool preEvalVec(const VECType* in, VECType* out,double scale=1.0) {
89  return asLeaf().preEvalVec(in,out,scale);
90  }
91 
92  bool postEvalVec(const VECType* in, VECType* out,double scale=1.0) {
93  return asLeaf().postEvalVec(in,out,scale);
94  }
95 
96 };
97 
98 template <typename T>
99 feVector<T>::feVector(ot::DA *da,unsigned int dof) : feVec(da)
100 {
101  m_uiDof=dof;
102  const unsigned int nPe=m_uiOctDA->getNumNodesPerElement();
103  m_uiEleVecIn = new VECType[m_uiDof*nPe];
104  m_uiEleVecOut = new VECType[m_uiDof*nPe];
105 
106  m_uiEleCoords= new double[m_uiDim*nPe];
107 }
108 
109 template <typename T>
111 {
112  delete [] m_uiEleVecIn;
113  delete [] m_uiEleVecOut;
114 
115  delete [] m_uiEleCoords;
116 }
117 
118 
119 template <typename T>
120 void feVector<T>::computeVec(const VECType* in,VECType* out,double scale)
121 {
122 
123 
124  VECType* _in=NULL;
125  VECType* _out=NULL;
126 
127  if(!(m_uiOctDA->isActive()))
128  return;
129 
130  preComputeVec(in,out,scale);
131 
132  m_uiOctDA->nodalVecToGhostedNodal(in,_in,false,m_uiDof);
133  m_uiOctDA->createVector(_out,false,true,m_uiDof);
134 
135  VECType * val=new VECType[m_uiDof];
136  for(unsigned int var=0;var<m_uiDof;var++)
137  val[var]=(VECType)0;
138 
139  m_uiOctDA->setVectorByScalar(_out,val,false,true,m_uiDof);
140 
141  delete [] val;
142 
143 
144  const ot::Mesh * pMesh = m_uiOctDA->getMesh();
145  const unsigned int nPe = pMesh->getNumNodesPerElement();
146  double * qMat = new double[nPe*nPe];
147  const unsigned int * e2n_cg = &(*(pMesh->getE2NMapping().begin()));
148  const ot::TreeNode* allElements = &(*(pMesh->getAllElements().begin()));
149 
150  m_uiOctDA->readFromGhostBegin(_in, m_uiDof);
151  const unsigned int totalNodalSize = m_uiOctDA->getTotalNodalSz();
152  for (m_uiOctDA->init<ot::DA_FLAGS::INDEPENDENT>(); m_uiOctDA->curr() < m_uiOctDA->end<ot::DA_FLAGS::INDEPENDENT>(); m_uiOctDA->next<ot::DA_FLAGS::INDEPENDENT>()) {
153 
154  m_uiOctDA->getElementNodalValues(_in, m_uiEleVecIn, m_uiOctDA->curr(), m_uiDof);
155  const unsigned int currentId = m_uiOctDA->curr();
156  pMesh->getElementQMat(m_uiOctDA->curr(),qMat,true);
158  elementalComputVec(m_uiEleVecIn, m_uiEleVecOut, m_uiEleCoords, scale);
159  for (unsigned int dof = 0; dof < m_uiDof; dof++) {
160  for (unsigned int i = 0; i < nPe; i++) {
161  VECType ss = (VECType) 0;
162  for (unsigned int j = 0; j < nPe; j++) {
163  ss += qMat[j * nPe + i] * m_uiEleVecOut[dof*nPe + j];
164  }
165  _out[dof*totalNodalSize + e2n_cg[currentId * nPe + i]] += (VECType) ss;
166 
167  }
168  }
169 
170  }
171 
172  m_uiOctDA->readFromGhostEnd(_in, m_uiDof);
173 
174  const unsigned int eleLocalBegin = pMesh->getElementLocalBegin();
175  const unsigned int eleLocalEnd = pMesh -> getElementLocalEnd();
176 
177  for (m_uiOctDA->init<ot::DA_FLAGS::W_DEPENDENT>(); m_uiOctDA->curr() < m_uiOctDA->end<ot::DA_FLAGS::W_DEPENDENT>(); m_uiOctDA->next<ot::DA_FLAGS::W_DEPENDENT>()) {
178 
179  // temporary fix to skip ghost writable.
180  if( m_uiOctDA->curr()< eleLocalBegin || m_uiOctDA->curr()>=eleLocalEnd )
181  continue;
182 
183  m_uiOctDA->getElementNodalValues(_in, m_uiEleVecIn, m_uiOctDA->curr(), m_uiDof);
184  const unsigned int currentId = m_uiOctDA->curr();
185  pMesh->getElementQMat(m_uiOctDA->curr(),qMat,true);
187  elementalComputVec(m_uiEleVecIn, m_uiEleVecOut, m_uiEleCoords, scale);
188 
189  for (unsigned int dof = 0; dof < m_uiDof; dof++) {
190  for (unsigned int i = 0; i < nPe; i++) {
191  VECType ss = (VECType) 0;
192  for (unsigned int j = 0; j < nPe; j++) {
193  ss += qMat[j * nPe + i] * m_uiEleVecOut[dof*nPe + j];
194  }
195  _out[dof*totalNodalSize + e2n_cg[currentId * nPe + i]] += (VECType) ss;
196 
197  }
198  }
199 
200  }
201 
202 
203  delete [] qMat;
204 
205  m_uiOctDA->writeToGhostsBegin(_out,m_uiDof);
206  m_uiOctDA->writeToGhostsEnd(_out,ot::DA_FLAGS::WriteMode::ADD_VALUES,m_uiDof);
207 
208  m_uiOctDA->ghostedNodalToNodalVec(_out,out,true,m_uiDof);
209 
210  m_uiOctDA->destroyVector(_in);
211  m_uiOctDA->destroyVector(_out);
212 
213  postComputeVec(in,out,scale);
214 
215  return;
216 
217 
218 }
219 
220 
221 #ifdef BUILD_WITH_PETSC
222 
223 
224 template <typename T>
225 void feVector<T>::computeVec(const Vec &in, Vec &out, double scale)
226 {
227  const PetscScalar * inArry=NULL;
228  PetscScalar * outArry=NULL;
229 
230  VecGetArrayRead(in,&inArry);
231  VecGetArray(out,&outArry);
232 
233  computeVec(inArry,outArry,scale);
234 
235  VecRestoreArrayRead(in,&inArry);
236  VecRestoreArray(out,&outArry);
237 }
238 #endif
239 
240 
241 #endif //DENDRO_5_0_FEVECTOR_H
unsigned int getNumNodesPerElement() const
get number of nodes per element
Definition: oda.h:257
void getElementQMat(unsigned int currentId, double *&qMat, bool isAllocated=true) const
: Compute the elemental interpolation matrix.
Definition: mesh.cpp:9436
feVec.h abstract interface based on Dendro 4. feVec contains an abstract interface to perform FEM acc...
virtual void computeVec(const VECType *in, VECType *out, double scale=1.0)
Evaluates the RHS of the PDE at specific points (for example evaluation at the quadrature points) ...
Definition: feVector.h:120
class that derived from abstract class feMat RHS computation of the weak formulation ...
Definition: feVector.h:16
A class to manage octants.
Definition: TreeNode.h:35
void readFromGhostEnd(T *vec, unsigned int dof=1)
Sync the ghost element exchange.
unsigned int end()
Returns if the current element has reached end or not.
void next()
: increment it to the next element.
virtual void elementalComputVec(const VECType *in, VECType *out, double *coords=NULL, double scale=1.0)=0
evalVec for the elemental vec
void getElementNodalValues(const T *in, T *eleVecOut, unsigned int eleID, unsigned int dof=1) const
computes the element nodal values using interpolation if needed.
Definition: mesh.h:179
void ghostedNodalToNodalVec(const T *gVec, T *&local, bool isAllocated=false, unsigned int dof=1) const
convert ghosted nodal vector to local vector (without ghosting)
void readFromGhostBegin(T *vec, unsigned int dof=1)
Initiate the ghost nodal value exchange.
void nodalVecToGhostedNodal(const T *in, T *&out, bool isAllocated=false, unsigned int dof=1) const
convert nodal local vector with ghosted buffer regions.
unsigned int getElementLocalBegin() const
return the begin location of element local
Definition: mesh.h:1030
double * m_uiEleCoords
Definition: feVector.h:30
void destroyVector(T *&local) const
deallocates the memory allocated for a vector
const std::vector< ot::TreeNode > & getAllElements() const
returns the pointer to All elements array.
Definition: mesh.h:1058
unsigned int getNumNodesPerElement() const
return the number of nodes per element.
Definition: mesh.h:1090
VECType * m_uiEleVecIn
element nodal vec in
Definition: feVector.h:24
feVector(ot::DA *da, unsigned int dof=1)
constructs an FEM stiffness matrix class.
Definition: feVector.h:99
unsigned int curr()
get the current elmenent in the iteration
Definition: oda.h:125
const std::vector< unsigned int > & getE2NMapping() const
Definition: mesh.h:1073
void writeToGhostsEnd(T *vec, DA_FLAGS::WriteMode mode, unsigned int dof=1)
Sync accumilation across ghost elements.
void getElementalCoords(unsigned int eleID, double *coords) const
computes the elementCoordinates (based on the nodal placement)
Definition: oda.cpp:264
bool isActive() const
see if the current DA is active
Definition: oda.h:254
int createVector(T *&local, bool isElemental=false, bool isGhosted=false, unsigned int dof=1) const
Creates a ODA vector.
unsigned int m_uiDof
number of unknowns
Definition: feVector.h:21
void setVectorByScalar(T *local, const T *value, bool isElemental=false, bool isGhosted=false, unsigned int dof=1) const
initialize a variable vector to a function depends on spatial coords.
void writeToGhostsBegin(T *vec, unsigned int dof=1)
Initiate accumilation across ghost elements.
Definition: feVec.h:20
ot::DA * m_uiOctDA
: pointer to OCT DA
Definition: feVec.h:24
const ot::Mesh * getMesh() const
returns the mesh
Definition: oda.h:269
unsigned int getTotalNodalSz() const
returns the total nodal size (this includes the ghosted region as well.)
Definition: oda.h:245
void init()
initialize the loop counters.