parallel_example_00003.cpp
1 /*---------------------------------------------------------------------------*\
2  *
3  * mimmo
4  *
5  * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6  *
7  * -------------------------------------------------------------------------
8  * License
9  * This file is part of mimmo.
10  *
11  * mimmo is free software: you can redistribute it and/or modify it
12  * under the terms of the GNU Lesser General Public License v3 (LGPL)
13  * as published by the Free Software Foundation.
14  *
15  * mimmo is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18  * License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with mimmo. If not, see <http://www.gnu.org/licenses/>.
22  *
23  \ *---------------------------------------------------------------------------*/
24 #include "mimmo_parallel.hpp"
25 #include "mimmo_iogeneric.hpp"
26 #include <iostream>
27 #include <chrono>
28 #include <fstream>
29 
30 typedef std::chrono::high_resolution_clock Clock;
31 
32 // =================================================================================== //
33 /*
34  example parallel_example_00003.cpp
35 
36  brief Example of usage of Serialization of a partioned geometry.
37 
38  Using: Partition, MimmoGeometry.
39 
40  <b>To run</b>: mpirun -np X parallel_example_00003 \n
41 
42  <b> visit</b>: <a href="http://optimad.github.io/mimmo/">mimmo website</a> \n
43  */
44 
45 
46 // =================================================================================== //
47 /*
48  creating a mesh on master rank 0 and return 2 lists of marked boundary vertices
49  suitable for pidding creation
50 */
51 mimmo::MimmoSharedPointer<mimmo::MimmoObject> createTestVolumeMesh(int rank, std::vector<long> &bcdir1_vertlist, std::vector<long> &bcdir2_vertlist){
52 
53  std::array<double,3> center({{0.0,0.0,0.0}});
54  double radiusin(2.0), radiusout(5.0);
55  double azimuthin(0.0), azimuthout(0.5*BITPIT_PI);
56  double heightbottom(-1.0), heighttop(1.0);
57  int nr(20), nt(20), nh(20);
58 
59  double deltar = (radiusout - radiusin)/ double(nr);
60  double deltat = (azimuthout - azimuthin)/ double(nt);
61  double deltah = (heighttop - heightbottom)/ double(nh);
62 
63  std::vector<std::array<double,3> > verts ((nr+1)*(nt+1)*(nh+1));
64 
65  int counter = 0;
66  for(int k=0; k<=nh; ++k){
67  for(int j=0; j<=nt; ++j){
68  for(int i=0; i<=nr; ++i){
69  verts[counter][0] =(radiusin + i*deltar)*std::cos(azimuthin + j*deltat);
70  verts[counter][1] =(radiusin + i*deltar)*std::sin(azimuthin + j*deltat);
71  verts[counter][2] =(heightbottom + k*deltah);
72  ++counter;
73  }
74  }
75  }
76 
77  //create the volume mesh mimmo.
79 
80  if (rank == 0){
81 
82  mesh->getPatch()->reserveVertices((nr+1)*(nt+1)*(nh+1));
83  mesh->getPatch()->reserveCells(nr*nt*nh);
84 
85  //pump up the vertices
86  for(const auto & vertex : verts){
87  mesh->addVertex(vertex); //automatic id assigned to vertices.
88  }
89 
90  //create connectivities for hexa elements
91  std::vector<long> conn(8,0);
92  for(int k=0; k<nh; ++k){
93  for(int j=0; j<nt; ++j){
94  for(int i=0; i<nr; ++i){
95  conn[0] = (nr+1)*(nt+1)*k + (nr+1)*j + i;
96  conn[1] = (nr+1)*(nt+1)*k + (nr+1)*j + i+1;
97  conn[2] = (nr+1)*(nt+1)*k + (nr+1)*(j+1) + i+1;
98  conn[3] = (nr+1)*(nt+1)*k + (nr+1)*(j+1) + i;
99  conn[4] = (nr+1)*(nt+1)*(k+1) + (nr+1)*j + i;
100  conn[5] = (nr+1)*(nt+1)*(k+1) + (nr+1)*j + i+1;
101  conn[6] = (nr+1)*(nt+1)*(k+1) + (nr+1)*(j+1) + i+1;
102  conn[7] = (nr+1)*(nt+1)*(k+1) + (nr+1)*(j+1) + i;
103 
104  mesh->addConnectedCell(conn, bitpit::ElementType::HEXAHEDRON);
105  }
106  }
107  }
108 
109  bcdir1_vertlist.clear();
110  bcdir2_vertlist.clear();
111  bcdir1_vertlist.reserve(mesh->getNVertices());
112  bcdir2_vertlist.reserve(mesh->getNVertices());
113 
114  for(int k=0; k<=nh; ++k){
115  for(int i=0; i<=nr; ++i){
116  bcdir1_vertlist.push_back((nr+1)*(nt+1)*k + i);
117  bcdir2_vertlist.push_back((nr+1)*(nt+1)*k + (nr+1)*nt + i);
118  }
119  }
120  }
121 
122  mesh->updateInterfaces();
123  mesh->update();
124 
125  return mesh;
126 }
127 
128 // =================================================================================== //
129 /*
130  Core function
131 */
132 int test00003() {
133 
134  // Initialize mpi
135  int nProcs;
136  int rank;
137  MPI_Comm_size(MPI_COMM_WORLD, &nProcs);
138  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
139 
140  //create a volume mesh
141  std::vector<long> bc1list, bc2list;
142  mimmo::MimmoSharedPointer<mimmo::MimmoObject> mesh = createTestVolumeMesh(rank, bc1list, bc2list);
143  mimmo::MimmoSharedPointer<mimmo::MimmoObject> boundary= mesh->extractBoundaryMesh();
144 
145  //using marked list of boundary vertices to pid manually the portion of boundary involved.
146  livector1D pidlist1 = boundary->getCellFromVertexList(bc1list, true);
147  livector1D pidlist2 = boundary->getCellFromVertexList(bc2list, true);
148 
149  for(long cellid : pidlist1){
150  boundary->setPIDCell(cellid, long(1));
151  }
152  for(long cellid : pidlist2){
153  boundary->setPIDCell(cellid, long(2));
154  }
155 
156  //create a subselection of the boundary
157  mimmo::MimmoSharedPointer<mimmo::MimmoObject> bDirMesh(new mimmo::MimmoObject(boundary->getType()));
158 
159  if(rank == 0){ //create a subselection of the whole boundary
160  //vertices
161  std::unordered_set<long> potvertices(bc1list.begin(), bc1list.end());
162  potvertices.insert(bc2list.begin(), bc2list.end());
163  for(long idv: potvertices){
164  bDirMesh->addVertex(boundary->getVertexCoords(idv), idv);
165  }
166  //cell
167  //mark to delete all cells not in the pidlist1 and 2.
168  std::unordered_set<long> preservedcells (pidlist1.begin(), pidlist1.end());
169  preservedcells.insert(pidlist2.begin(), pidlist2.end());
170 
171  for(long idc: preservedcells){
172  bDirMesh->addCell(boundary->getPatch()->getCell(idc), idc, rank);
173  }
174  }
175  bDirMesh->updateInterfaces();
176  bDirMesh->update();
177 
178  /*
179  Distribute mesh and bDirMesh among processes.
180  */
181  mimmo::Partition* partition = new mimmo::Partition();
182  partition->setPlotInExecution(true);
183  partition->setGeometry(mesh);
184  partition->setBoundaryGeometry(bDirMesh);
185  partition->setPartitionMethod(mimmo::PartitionMethod::PARTGEOM);
186  auto t1 = Clock::now();
187  if (rank == 0)
188  std::cout << "#" << rank << " Start Partition mesh " << std::endl;
189  partition->exec();
190  auto t2 = Clock::now();
191  if (rank == 0){
192  std::cout << "#" << rank << " Partition mesh execution time: "
193  << std::chrono::duration_cast<std::chrono::seconds>(t2 - t1).count()
194  << " seconds" << std::endl;
195  }
196 
197  /*
198  dump the partitioned mesh to file into mimmo's own format
199  */
201  mimmoVolumeOut->setWriteDir("./");
202  mimmoVolumeOut->setWriteFileType(FileType::MIMMO);
203  mimmoVolumeOut->setWriteFilename("parallel_example_00003.volume.partitioned");
204  mimmoVolumeOut->setGeometry(mesh);
205  mimmoVolumeOut->exec();
206 
207  /*
208  restore the dumped partitioned mesh and convert it into parallel vtu format.
209  */
211  mimmoVolumeIn->setReadDir("./");
212  mimmoVolumeIn->setReadFileType(FileType::MIMMO);
213  mimmoVolumeIn->setReadFilename("parallel_example_00003.volume.partitioned");
214  mimmoVolumeIn->setWriteDir("./");
215  mimmoVolumeIn->setWriteFileType(FileType::VOLVTU);
216  mimmoVolumeIn->setWriteFilename("parallel_example_00003.volume.restored");
217  mimmoVolumeIn->exec();
218 
219  /*
220  Serialize the partitioned mesh
221  */
222  mimmo::Partition* serialize = new mimmo::Partition();
223  serialize->setName("mimmo.Serialization");
224  serialize->setPlotInExecution(true);
225  serialize->setGeometry(mesh);
226  serialize->setBoundaryGeometry(bDirMesh);
227  serialize->setPartitionMethod(mimmo::PartitionMethod::SERIALIZE);
228 
229  t1 = Clock::now();
230  if (rank == 0)
231  std::cout << "Start Serialize mesh " << std::endl;
232  serialize->exec();
233  t2 = Clock::now();
234  if (rank == 0){
235  std::cout << "Serialize mesh execution time: "
236  << std::chrono::duration_cast<std::chrono::seconds>(t2 - t1).count()
237  << " seconds" << std::endl;
238  }
239 
240  bool error = false;
241 
242  delete partition;
243  delete serialize;
244  return error;
245 }
246 
247 // =================================================================================== //
248 
249 int main( int argc, char *argv[] ) {
250 
251  BITPIT_UNUSED(argc);
252  BITPIT_UNUSED(argv);
253 
254 #if MIMMO_ENABLE_MPI
255  MPI_Init(&argc, &argv);
256 #endif
257 
258  int val = 1;
259  try{
261  val = test00003() ;
262  }
263  catch(std::exception & e){
264  std::cout<<"parallel_example_00003 exited with an error of type : "<<e.what()<<std::endl;
265  return 1;
266  }
267 
268 #if MIMMO_ENABLE_MPI
269  MPI_Finalize();
270 #endif
271 
272  return val;
273 }
MimmoObject is the basic geometry container for mimmo library.
void setGeometry(int type=1)
void setWriteFileType(FileType type)
std::vector< long > livector1D
void setWriteDir(std::string dir)
void setWriteFilename(std::string filename)
void setReadFilename(std::string filename)
MimmoGeometry is an executable block class wrapping(linking or internally instantiating) a Mimmo Obje...
void setReadFileType(FileType type)
void setReadDir(std::string dir)