Zoltan2
Loading...
Searching...
No Matches
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
27using Teuchos::RCP;
28
29/*********************************************************/
30/* Typedefs */
31/*********************************************************/
32//Tpetra typedefs
33typedef Tpetra::MultiVector<double, int, int> tMVector_t;
34
35//Topology type helper function
36enum 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)
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)
47 else if (ttype==apf::Mesh::HEX)
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
62int 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/*****************************************************************************/
enum Zoltan2::EntityTopologyType topologyAPFtoZ2(enum apf::Mesh::Type ttype)
Tpetra::MultiVector< double, int, int > tMVector_t
Defines the APFMeshAdapter class.
int main()
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' optional entity weights.
virtual bool availAdjs(MeshEntityType source, MeshEntityType target) const
Returns whether a first adjacency combination is available.
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.
virtual size_t getLocalNumOf(MeshEntityType etype) const =0
Returns the global number of mesh entities of MeshEntityType.
virtual size_t getLocalNumAdjs(MeshEntityType source, MeshEntityType target) const
Returns the number of first adjacencies on this process.
virtual void getIDsViewOf(MeshEntityType etype, gno_t const *&Ids) const =0
Provide a pointer to this process' 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 void getAdjsView(MeshEntityType source, MeshEntityType target, const offset_t *&offsets, const gno_t *&adjacencyIds) const
Sets pointers to this process' mesh first adjacencies.
map_t::local_ordinal_type lno_t
map_t::global_ordinal_type gno_t
EntityTopologyType
Enumerate entity topology types for meshes: points,lines,polygons,triangles,quadrilaterals,...
MeshEntityType
Enumerate entity types for meshes: Regions, Faces, Edges, or Vertices.
static ArrayRCP< ArrayRCP< zscalar_t > > weights