proteus 1.9.0
C/C++/Fortran libraries
Loading...
Searching...
No Matches
ParallelMeshConverter.cpp
Go to the documentation of this file.
1#include <algorithm>
2#include <mpi.h>
3#include <PCU.h>
4#include <sstream>
5
6#include "MeshAdaptPUMI.h"
7#include "mesh.h"
8
9#include "DumpMesh.h"
10
17
18static int countTotal(apf::Mesh* m, int dim, PCU_t PCUObj)
19{
20 int total = apf::countOwned(m, dim);
21 PCU_Add_Ints(PCUObj, &total, 1);
22 return total;
23}
24
26{
27 mesh.subdomainp = &subdomain_mesh;
28 initializeMesh(subdomain_mesh);
29 if (!PCU_Comm_Self(PCUObj))
30 std::cerr << "Constructing parallel proteus mesh\n";
31
32 int dim = m->getDimension();
33 int numGlobElem = countTotal(m, dim, PCUObj);
34 mesh.nElements_global = numGlobElem;
35
36 int numLocElem = m->count(dim);
37 mesh.subdomainp->nElements_global = numLocElem;
38
39 int numGlobNodes = countTotal(m, 0, PCUObj);
40 mesh.nNodes_global = numGlobNodes;
41
42 int numLocNodes = m->count(0);
43 mesh.subdomainp->nNodes_global = numLocNodes;
44
45 int numGlobFaces = countTotal(m, 2, PCUObj);
46 int numLocFaces = m->count(2);
47
48 int numGlobEdges = countTotal(m, 1, PCUObj);
49 mesh.nEdges_global = numGlobEdges;
50
51 int numLocEdges = m->count(1);
52 mesh.subdomainp->nEdges_global = numLocEdges;
53
54 if(dim==3){
55 mesh.nElementBoundaries_global = numGlobFaces;
56 mesh.subdomainp->nElementBoundaries_global = numLocFaces;
57 //nNodes_element for now is constant for the entire mesh, Ask proteus about using mixed meshes
58 //therefore currently this code only supports tet meshes
59 mesh.subdomainp->nNodes_element = 4; //hardcode: for tets, number of nodes per element
60 mesh.subdomainp->nNodes_elementBoundary = 3; //hardcode: for tets, looks like number of nodes of a face
61 mesh.subdomainp->nElementBoundaries_element = 4; //hardcode: for tets, looks like number of faces/element
62 }
63 else if(dim==2){
64 mesh.nElementBoundaries_global = numGlobEdges;
65 mesh.subdomainp->nElementBoundaries_global = numLocEdges;
66 mesh.subdomainp->nNodes_element = 3; //hardcode: for tets, number of nodes per element
67 mesh.subdomainp->nNodes_elementBoundary = 2; //hardcode: for tets, looks like number of nodes of a face
68 mesh.subdomainp->nElementBoundaries_element = 3; //hardcode: for tets, looks like number of faces/element
69 }
70
71
72#ifdef MESH_INFO
73 for (int i = 0; i < PCU_Comm_Peers(PCUObj); ++i) {
74 if (i == PCU_Comm_Self(PCUObj)) {
75 std::cerr << "*******Local Proteus Mesh Stats*********\n";
76 std::cerr << "Rank: " << comm_rank << ": Number of elements " << mesh.subdomainp->nElements_global << "\n";
77 std::cerr << "Rank: " << comm_rank << ": Number of nodes " << mesh.subdomainp->nNodes_global << "\n";
78 std::cerr << "Rank: " << comm_rank << ": Number of boundaries " << mesh.subdomainp->nElementBoundaries_global << "\n";
79 std::cerr << "Rank: " << comm_rank << ": Number of edges " << mesh.subdomainp->nEdges_global << "\n";
80 std::cerr << "*****************************************\n";
81 }
82 PCU_Barrier(PCUObj);
83 }
84
85 if(comm_rank==0) {
86 std::cerr << "*******Global Proteus Mesh Stats*********\n";
87 std::cerr << ": Number of elements " << mesh.nElements_global << "\n";
88 std::cerr << ": Number of nodes " << mesh.nNodes_global << "\n";
89 std::cerr << ": Number of boundaries " << mesh.nElementBoundaries_global << "\n";
90 std::cerr << ": Number of edges " << mesh.nEdges_global << "\n";
91 std::cerr << "*****************************************\n";
92 }
93#endif
94
95 constructGlobalNumbering(mesh);
97 constructNodes(*mesh.subdomainp);
98 constructElements(*mesh.subdomainp);
99 constructBoundaries(*mesh.subdomainp);
100 constructEdges(*mesh.subdomainp);
101 constructMaterialArrays(*mesh.subdomainp);
102 constructGlobalStructures(mesh);
103
104/* Turn on only for debugging
105 std::stringstream ss;
106 ss << "ToProteus_t" << nAdapt<<".smb";
107 std::string s = ss.str();
108 m->writeNative(s.c_str());
109*/
110 return 0;
111}
112
113#include <cstring>
114int MeshAdaptPUMIDrvr::constructGlobalNumbering(Mesh &mesh)
115{
116 /* N^2 data structures and algorithms are terrible for scalability.
117 Going along because Proteus is structured this way. */
118 mesh.elementOffsets_subdomain_owned = new int[comm_size+1];
119 mesh.elementBoundaryOffsets_subdomain_owned = new int[comm_size+1];
120 mesh.edgeOffsets_subdomain_owned = new int[comm_size+1];
121 mesh.nodeOffsets_subdomain_owned = new int[comm_size+1];
122
123 if(m->getDimension()==3){
124 for (int dim = 0; dim <= m->getDimension(); ++dim) {
125
126 int nLocalOwned = apf::countOwned(m, dim);
127 int localOffset = nLocalOwned;
128 PCU_Exscan_Ints(PCUObj, &localOffset, 1);
129
130 int* allOffsets;
131 if(dim==3){
132 allOffsets = mesh.elementOffsets_subdomain_owned;
133 }
134 if(dim==2){
136 }
137 if(dim==1){
138 allOffsets = mesh.edgeOffsets_subdomain_owned;
139 }
140 if(dim==0){
141 allOffsets = mesh.nodeOffsets_subdomain_owned;
142 }
143
144 /* one of the many reasons N^2 algorithms are bad */
145 MPI_Allgather(&localOffset, 1, MPI_INT,
146 allOffsets, 1, MPI_INT, MPI_COMM_WORLD);
147 allOffsets[PCU_Comm_Peers(PCUObj)] = countTotal(m, dim, PCUObj);
148
149 std::stringstream ss;
150 ss << "proteus_global_";
151 ss << dim;
152 std::string name = ss.str();
153 /* this algorithm does global numbering properly,
154 without O(#procs) runtime */
155 global[dim] = apf::makeGlobal(apf::numberOwnedDimension(m, name.c_str(), dim));
156 apf::synchronize(global[dim]);
157 } //loop on entity dimensions
158 }
159 else if(m->getDimension()==2){
160 for (int dim = 0; dim <= m->getDimension(); ++dim) {
161
162 int nLocalOwned = apf::countOwned(m, dim);
163 int localOffset = nLocalOwned;
164 PCU_Exscan_Ints(PCUObj, &localOffset, 1);
165
166 int* allOffsets;
167 if(dim==2){
168 allOffsets = mesh.elementOffsets_subdomain_owned;
169 }
170 if(dim==1){
172 }
173 if(dim==0){
174 allOffsets = mesh.nodeOffsets_subdomain_owned;
175 }
176
177 /* one of the many reasons N^2 algorithms are bad */
178 MPI_Allgather(&localOffset, 1, MPI_INT,
179 allOffsets, 1, MPI_INT, MPI_COMM_WORLD);
180 allOffsets[PCU_Comm_Peers(PCUObj)] = countTotal(m, dim, PCUObj);
181 std::stringstream ss;
182 ss << "proteus_global_";
183 ss << dim;
184 std::string name = ss.str();
185 /* this algorithm does global numbering properly,
186 without O(#procs) runtime */
187 global[dim] = apf::makeGlobal(apf::numberOwnedDimension(m, name.c_str(), dim));
188 apf::synchronize(global[dim]);
189 } //loop on entity dimensions
190 std::memcpy(mesh.edgeOffsets_subdomain_owned,mesh.elementBoundaryOffsets_subdomain_owned,sizeof(int)*(comm_size+1));
191 }
192 return 0;
193}
194
195int MeshAdaptPUMIDrvr::constructGlobalStructures(Mesh &mesh)
196{
201
202 if(m->getDimension()==3){
203 for (int d = 0; d <= m->getDimension(); ++d) {
204 int* temp_subdomain2global;
205 if(d==3) temp_subdomain2global = mesh.elementNumbering_subdomain2global;
206 if(d==2) temp_subdomain2global = mesh.elementBoundaryNumbering_subdomain2global;
207 if(d==1) temp_subdomain2global = mesh.edgeNumbering_subdomain2global;
208 if(d==0) temp_subdomain2global = mesh.nodeNumbering_subdomain2global;
209
210 apf::MeshIterator* it = m->begin(d);
211 apf::MeshEntity* e;
212 while ((e = m->iterate(it))) {
213 int i = localNumber(e);
214 temp_subdomain2global[i] = apf::getNumber(global[d], apf::Node(e, 0));
215 }
216 m->end(it);
217 apf::destroyGlobalNumbering(global[d]);
218 }
219 }
220 else if(m->getDimension()==2){
221 for (int d = 0; d <= m->getDimension(); ++d) {
222 int* temp_subdomain2global;
223 int* temp_subdomain2global2; //just for the edge and element boundary array overlap
224 if(d==2) temp_subdomain2global = mesh.elementNumbering_subdomain2global;
225 if(d==1) temp_subdomain2global = mesh.elementBoundaryNumbering_subdomain2global;
226 if(d==0) temp_subdomain2global = mesh.nodeNumbering_subdomain2global;
227 apf::MeshIterator* it = m->begin(d);
228 apf::MeshEntity* e;
229 while ((e = m->iterate(it))) {
230 int i = localNumber(e);
231 temp_subdomain2global[i] = apf::getNumber(global[d], apf::Node(e, 0));
232 }
233 m->end(it);
234 apf::destroyGlobalNumbering(global[d]);
235 }
237 }
238
239 return 0;
240}
241
243{
244 std::stringstream ss;
245 ss << "dan_debug_" << PCU_Comm_Self(PCUObj) << ".txt";
246 std::string s = ss.str();
247 FILE* f = fopen(s.c_str(), "w");
248 dump_proteus_mesh(&mesh, f, PCUObj);
249 fclose(f);
250 return 0;
251}
252
void dump_proteus_mesh(Mesh *m, FILE *f, PCU_t PCUObj)
Definition DumpMesh.cpp:163
Double f
Definition Headers.h:64
Double s
Definition Headers.h:84
#define DEFAULT_ELEMENT_MATERIAL
int localNumber(apf::MeshEntity *e)
int constructFromParallelPUMIMesh(Mesh &mesh, Mesh &subdomain_mesh)
void initializeMesh(Mesh &mesh)
Definition mesh.h:93
const int INTERIOR_ELEMENT_BOUNDARY_MATERIAL
Definition mesh.cpp:52
const int EXTERIOR_NODE_MATERIAL
Definition mesh.cpp:51
const int DEFAULT_NODE_MATERIAL
Definition mesh.cpp:49
const int INTERIOR_NODE_MATERIAL
Definition mesh.cpp:50
const int EXTERIOR_ELEMENT_BOUNDARY_MATERIAL
Definition mesh.cpp:53
Definition mesh.h:30
int * edgeNumbering_subdomain2global
Definition mesh.h:85
int * elementBoundaryNumbering_subdomain2global
Definition mesh.h:83
int nEdges_global
Definition mesh.h:41
int nNodes_elementBoundary
Definition mesh.h:35
int * nodeNumbering_subdomain2global
Definition mesh.h:81
int nNodes_element
Definition mesh.h:34
int * elementBoundaryOffsets_subdomain_owned
Definition mesh.h:82
int nElements_global
Definition mesh.h:32
int * elementOffsets_subdomain_owned
Definition mesh.h:78
int nNodes_global
Definition mesh.h:33
int nElementBoundaries_element
Definition mesh.h:36
int * elementNumbering_subdomain2global
Definition mesh.h:79
int * nodeOffsets_subdomain_owned
Definition mesh.h:80
int * edgeOffsets_subdomain_owned
Definition mesh.h:84
Mesh * subdomainp
Definition mesh.h:90
int nElementBoundaries_global
Definition mesh.h:37