Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
APFMeshInput.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 //
11 // Basic testing of Zoltan2::APFMeshAdapter
12 
14 
15 #ifdef HAVE_ZOLTAN2_PARMA
16 #include <apf.h>
17 #include <apfMesh.h>
18 #include <apfMDS.h>
19 #include <apfMesh2.h>
20 #include <PCU.h>
21 #include <gmi_mesh.h>
22 #endif
23 
24 // Teuchos includes
25 #include "Teuchos_XMLParameterListHelpers.hpp"
26 
27 using Teuchos::RCP;
28 
29 /*********************************************************/
30 /* Typedefs */
31 /*********************************************************/
32 //Tpetra typedefs
33 typedef Tpetra::MultiVector<double, int, int> tMVector_t;
34 
35 //Topology type helper function
36 enum Zoltan2::EntityTopologyType topologyAPFtoZ2(enum apf::Mesh::Type ttype) {
37  if (ttype==apf::Mesh::VERTEX)
38  return Zoltan2::POINT;
39  else if (ttype==apf::Mesh::EDGE)
40  return Zoltan2::LINE_SEGMENT;
41  else if (ttype==apf::Mesh::TRIANGLE)
42  return Zoltan2::TRIANGLE;
43  else if (ttype==apf::Mesh::QUAD)
45  else if (ttype==apf::Mesh::TET)
46  return Zoltan2::TETRAHEDRON;
47  else if (ttype==apf::Mesh::HEX)
48  return Zoltan2::HEXAHEDRON;
49  else if (ttype==apf::Mesh::PRISM)
50  return Zoltan2::PRISM;
51  else if (ttype==apf::Mesh::PYRAMID)
52  return Zoltan2::PYRAMID;
53  else
54  throw "No such APF topology type";
55 
56 }
57 
58 /*****************************************************************************/
59 /******************************** MAIN ***************************************/
60 /*****************************************************************************/
61 
62 int main(int narg, char *arg[]) {
63 
64  Tpetra::ScopeGuard tscope(&narg, &arg);
65  Teuchos::RCP<const Teuchos::Comm<int> > CommT = Tpetra::getDefaultComm();
66 
67 #ifdef HAVE_ZOLTAN2_PARMA
68  //Open up PCU for communication required by all APF operations
69  PCU_Comm_Init();
70 
71  //Open up the mesh
72  gmi_register_mesh();
73  apf::Mesh2* m = apf::loadMdsMesh("pumiTri14/plate.dmg","pumiTri14/2/");
74  apf::verify(m);
75 
76  int dim = m->getDimension();
77 
78  //Contruct the MeshAdapter
80  typedef Adapter::lno_t lno_t;
81  typedef Adapter::gno_t gno_t;
82  typedef Adapter::scalar_t scalar_t;
83  typedef Adapter::offset_t offset_t;
84 
85  std::string pri = "face";
86  std::string adj = "vertex";
87  if (dim==3) {
88  adj=pri;
89  pri="region";
90  }
91 
92  Zoltan2::APFMeshAdapter<apf::Mesh2*> ia(*CommT,m,pri,adj,true);
93 
98 
99  //Check the local number of each entity
100  bool* has = new bool[dim+1];
101  for (int i=0;i<=dim;i++) {
102 
103  has[i]=true;
104  if (ia.getLocalNumOf(ents[i])==0) {
105  has[i]=false;
106  continue;
107  }
108  if (ia.getLocalNumOf(ents[i])!=m->count(i)) {
109  std::cerr<<"Local number of entities does not match in dimension "<<i<<"\n";
110  return 1;
111  }
112 
113  }
114 
115 
116  //Check the coordinate dimension
117  apf::GlobalNumbering** gnums = new apf::GlobalNumbering*[dim];
118  apf::Numbering** lnums = new apf::Numbering*[dim];
119  int sub=0;
120  for (int i=0;i<=dim;i++) {
121  if (!has[i]) {
122  sub++;
123  continue;
124  }
125  gnums[i] = m->getGlobalNumbering(i-sub);
126  lnums[i] = m->getNumbering(i-sub);
127  }
128 
129  for (int i=0;i<=dim;i++) {
130  if (!has[i])
131  continue;
132  const gno_t* gids;
133  const Zoltan2::EntityTopologyType* topTypes;
134  const scalar_t* x_coords;
135  const scalar_t* y_coords;
136  const scalar_t* z_coords;
137  int x_stride;
138  int y_stride;
139  int z_stride;
140  const offset_t** offsets = new const offset_t*[dim];
141  const gno_t** adj_gids = new const gno_t*[dim];
142 
143  ia.getIDsViewOf(ents[i],gids);
144  ia.getTopologyViewOf(ents[i],topTypes);
145  ia.getCoordinatesViewOf(ents[i],x_coords,x_stride,0);
146  ia.getCoordinatesViewOf(ents[i],y_coords,y_stride,1);
147  ia.getCoordinatesViewOf(ents[i],z_coords,z_stride,2);
148  //Check availability of First Adjacency
149  for (int j=0;j<=dim;j++) {
150  if (!has[j])
151  continue;
152  if (ia.availAdjs(ents[i],ents[j])!=(i!=j)) {
153  std::cerr<<"First Adjacency does not exist from "<<i<<" to "<< j<<"\n";
154  return 5;
155  }
156  ia.getAdjsView(ents[i],ents[j],offsets[j],adj_gids[j]);
157  }
158  int j=0;
159  apf::MeshIterator* itr = m->begin(i);
160  apf::MeshEntity* ent;
161  size_t* numAdjs = new size_t[dim+1];
162  for (int k=0;k<=dim;k++)
163  numAdjs[k]=0;
164  while ((ent=m->iterate(itr))) {
165  //Check Local ID numbers
166  if (apf::getNumber(lnums[i],ent,0,0)!=j) {
167  std::cerr<<"Local numbering does not match in dimension "<<i<<" on entity "<<j<<"\n";
168  return 2;
169  }
170  //Check Global Id numbers
171  if (apf::getNumber(gnums[i],apf::Node(ent,0))!=gids[j]) {
172  std::cerr<<"Global numbering does not match in dimension "<<i<<" on entity "<<j<<"\n";
173  return 2;
174  }
175 
176  //Check Topology Types
177  if (topologyAPFtoZ2(m->getType(ent))!=topTypes[j]) {
178  std::cerr<<"Topology types do not match in dimension "<<i<<" on entity "<<j<<"\n";
179  return 3;
180  }
181 
182  //Check the coordinates
183  apf::Vector3 pnt;
184  if (i==0)
185  m->getPoint(ent,0,pnt);
186  else
187  pnt = apf::getLinearCentroid(m,ent);
188  float eps=.00001;
189  if (fabs(pnt[0] - x_coords[j*x_stride])>eps) {
190  std::cerr<<"X coordinate do not match in dimension "<<i<<" on entity "<<j<<"\n";
191  return 4;
192  }
193  if (fabs(pnt[1] - y_coords[j*y_stride])>eps) {
194  std::cerr<<"Y coordinate do not match in dimension "<<i<<" on entity "<<j<<"\n";
195  return 4;
196  }
197  if (fabs(pnt[2] - z_coords[j*z_stride])>eps) {
198  std::cerr<<"Z coordinate do not match in dimension "<<i<<" on entity "<<j<<"\n";
199  return 4;
200  }
201 
202  //Check first adjacencies
203  for (int k=0;k<=dim;k++) {
204  if (!has[k])
205  continue;
206  if (i==k) {
207  //Check first adjacency to self is set to NULL
208  if (offsets[k]!=NULL || adj_gids[k]!=NULL) {
209  std::cerr<<"[WARNING] First adjacency to self is not set to NULL in dimension "<<i
210  <<" to dimension "<<k<<"\n";
211  }
212 
213  continue;
214  }
215  apf::Adjacent adjs;
216  m->getAdjacent(ent,k,adjs);
217  offset_t ind = offsets[k][j];
218  for (unsigned int l=0;l<adjs.getSize();l++) {
219  if (apf::getNumber(gnums[k],apf::Node(adjs[l],0))!=adj_gids[k][ind]) {
220  std::cerr<<"First adjacency does not match in dimension " <<i<<" to dimension "<<k
221  <<" on entity "<<j<<"\n";
222  return 7;
223  }
224  ind++;
225  }
226  if (ind!=offsets[k][j+1]) {
227  std::cerr<<"First adjacency length does not match in dimension "<<i<<" to dimension "
228  <<k<<" on entity "<<j<<"\n";
229  return 8;
230  }
231  numAdjs[k]+=adjs.getSize();
232 
233  }
234  j++;
235  }
236  m->end(itr);
237  delete [] offsets;
238  delete [] adj_gids;
239  //Check the number of first adjacency
240  for (int k=0;k<=dim;k++) {
241  if (!has[k])
242  continue;
243  if (ia.getLocalNumAdjs(ents[i],ents[k])!=numAdjs[k]) {
244  std::cerr<<"Local number of first adjacencies do not match in dimension "<<i
245  <<" through dimension "<<k<<"\n";
246  return 6;
247  }
248  }
249  delete [] numAdjs;
250 
251  }
252  delete [] lnums;
253  delete [] gnums;
254  const Adapter::scalar_t arr[] = {1,2,1,3,1,5,1,2,1,6,1,7,1,8};
255  ia.setWeights(Zoltan2::MESH_FACE,arr,2);
256 
258  std::cerr<<"Number of weights incorrect\n";
259  return 9;
260 
261  }
262 
263 
264  const Adapter::scalar_t* arr2;
265  int stride;
266  ia.getWeightsViewOf(Zoltan2::MESH_FACE,arr2,stride);
267  for (int i=0;i<7;i++) {
268  if (arr[i*stride]!=arr2[i*stride]) {
269  std::cerr<<"Weights do not match the original input\n";
270  return 10;
271 
272  }
273  }
274  bool ifIdontfeellikeit = false;
275  apf::MeshTag* weights = m->createDoubleTag("weights",2);
276  apf::MeshIterator* itr = m->begin(0);
277  apf::MeshEntity* ent;
278  while ((ent=m->iterate(itr))) {
279  if (!ifIdontfeellikeit||PCU_Comm_Self()) {
280  double w[]={1.0,PCU_Comm_Self()+1.0};
281  m->setDoubleTag(ent,weights,w);
282  }
283  ifIdontfeellikeit=!ifIdontfeellikeit;
284  }
285  m->end(itr);
286 
287 
288 
289  ia.setWeights(Zoltan2::MESH_VERTEX,m,weights);
291  std::cerr<<"Number of weights incorrect\n";
292  return 9;
293 
294  }
295 
296  ia.getWeightsViewOf(Zoltan2::MESH_VERTEX,arr2,stride,0);
297 
298  itr = m->begin(0);
299 
300  int i=0;
301  while ((ent=m->iterate(itr))) {
302  double w=1;
303  if (w!=arr2[i*stride]) {
304  std::cerr<<"Weights do not match the original input\n";
305  return 10;
306 
307  }
308  i++;
309  }
310  m->end(itr);
311 
312  ia.getWeightsViewOf(Zoltan2::MESH_VERTEX,arr2,stride,1);
313 
314  itr = m->begin(0);
315  i=0;
316  while ((ent=m->iterate(itr))) {
317  double w[2];
318  if (PCU_Comm_Self())
319  m->getDoubleTag(ent,weights,w);
320  else
321  w[1]=1;
322  if (w[1]!=arr2[i*stride]) {
323  std::cerr<<"Weights do not match the original input\n";
324  return 10;
325 
326  }
327  i++;
328  }
329  m->end(itr);
330 
331  //ia.print(PCU_Comm_Self(),5);
332 
333  //Delete the MeshAdapter
334  ia.destroy();
335 
336  //Delete the APF Mesh
337  m->destroyNative();
338  apf::destroyMesh(m);
339 
340  //End PCU communications
341  PCU_Comm_Free();
342 #endif
343  std::cout<<"PASS\n";
344 
345  return 0;
346 }
347 /*****************************************************************************/
348 /********************************* END MAIN **********************************/
349 /*****************************************************************************/
virtual void getAdjsView(MeshEntityType source, MeshEntityType target, const offset_t *&offsets, const gno_t *&adjacencyIds) const
Sets pointers to this process&#39; mesh first adjacencies.
virtual bool availAdjs(MeshEntityType source, MeshEntityType target) const
Returns whether a first adjacency combination is available.
static ArrayRCP< ArrayRCP< zscalar_t > > weights
virtual size_t getLocalNumOf(MeshEntityType etype) const =0
Returns the global number of mesh entities of MeshEntityType.
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
virtual void getWeightsViewOf(MeshEntityType etype, const scalar_t *&weights, int &stride, int idx=0) const
Provide a pointer to one of the number of this process&#39; optional entity weights.
int main(int narg, char **arg)
Definition: coloring1.cpp:164
Defines the APFMeshAdapter class.
virtual void getIDsViewOf(MeshEntityType etype, gno_t const *&Ids) const =0
Provide a pointer to this process&#39; identifiers.
virtual void getCoordinatesViewOf(MeshEntityType etype, const scalar_t *&coords, int &stride, int coordDim) const
Provide a pointer to one dimension of entity coordinates.
virtual size_t getLocalNumAdjs(MeshEntityType source, MeshEntityType target) const
Returns the number of first adjacencies on this process.
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:26
EntityTopologyType
Enumerate entity topology types for meshes: points,lines,polygons,triangles,quadrilaterals, polyhedrons, tetrahedrons, hexhedrons, prisms, or pyramids.
enum Zoltan2::EntityTopologyType topologyAPFtoZ2(enum apf::Mesh::Type ttype)
MeshEntityType
Enumerate entity types for meshes: Regions, Faces, Edges, or Vertices.
virtual int getNumWeightsPerOf(MeshEntityType etype) const
Return the number of weights per entity.
virtual void getTopologyViewOf(MeshEntityType etype, enum EntityTopologyType const *&Types) const
Provide a pointer to the entity topology types.
Tpetra::MultiVector< zscalar_t, zlno_t, zgno_t, znode_t > tMVector_t
Vector::node_type Node
Definition: coloring1.cpp:46