propagators_example_00001.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 #if MIMMO_ENABLE_MPI
25 #include "mimmo_parallel.hpp"
26 #endif
27 #include "mimmo_propagators.hpp"
28 
29 #include <iostream>
30 #include <chrono>
31 typedef std::chrono::high_resolution_clock Clock;
32 
33 // =================================================================================== //
46 // =================================================================================== //
47 /*
48  Create a bulk volume mesh, and mark some boundary vertices for pidding purposes
49  (reported into bcdir1_vertlist bcdir2_vertlist
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  mesh->getPatch()->reserveVertices((nr+1)*(nt+1)*(nh+1));
82  mesh->getPatch()->reserveCells(nr*nt*nh);
83 
84  //pump up the vertices
85  for(const auto & vertex : verts){
86  mesh->addVertex(vertex); //automatic id assigned to vertices.
87  }
88 
89  //create connectivities for hexa elements
90  std::vector<long> conn(8,0);
91  for(int k=0; k<nh; ++k){
92  for(int j=0; j<nt; ++j){
93  for(int i=0; i<nr; ++i){
94  conn[0] = (nr+1)*(nt+1)*k + (nr+1)*j + i;
95  conn[1] = (nr+1)*(nt+1)*k + (nr+1)*j + i+1;
96  conn[2] = (nr+1)*(nt+1)*k + (nr+1)*(j+1) + i+1;
97  conn[3] = (nr+1)*(nt+1)*k + (nr+1)*(j+1) + i;
98  conn[4] = (nr+1)*(nt+1)*(k+1) + (nr+1)*j + i;
99  conn[5] = (nr+1)*(nt+1)*(k+1) + (nr+1)*j + i+1;
100  conn[6] = (nr+1)*(nt+1)*(k+1) + (nr+1)*(j+1) + i+1;
101  conn[7] = (nr+1)*(nt+1)*(k+1) + (nr+1)*(j+1) + i;
102 
103  mesh->addConnectedCell(conn, bitpit::ElementType::HEXAHEDRON);
104  }
105  }
106  }
107 
108  bcdir1_vertlist.clear();
109  bcdir2_vertlist.clear();
110  bcdir1_vertlist.reserve(mesh->getNVertices());
111  bcdir2_vertlist.reserve(mesh->getNVertices());
112 
113  for(int k=0; k<=nh; ++k){
114  for(int i=0; i<=nr; ++i){
115  bcdir1_vertlist.push_back((nr+1)*(nt+1)*k + i);
116  bcdir2_vertlist.push_back((nr+1)*(nt+1)*k + (nr+1)*nt + i);
117  }
118  }
119  }
120 
121  mesh->updateInterfaces();
122  mesh->update();
123 
124  return mesh;
125 }
126 
127 // =================================================================================== //
128 /*
129  Core function
130 */
131 int test00001() {
132 
133 #if MIMMO_ENABLE_MPI
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 #else
140  int rank = 0;
141 #endif
142 
143  //create the volume mesh
144  std::vector<long> bc1list, bc2list;
145  mimmo::MimmoSharedPointer<mimmo::MimmoObject> mesh = createTestVolumeMesh(rank, bc1list, bc2list);
146 
147  //calculate its boundary
148  mimmo::MimmoSharedPointer<mimmo::MimmoObject> boundary= mesh->extractBoundaryMesh();
149 
150  //pidding the portion of boundary using bc1list and bc2list
151  livector1D pidlist1 = boundary->getCellFromVertexList(bc1list, true);
152  livector1D pidlist2 = boundary->getCellFromVertexList(bc2list, true);
153 
154  for(long cellid : pidlist1){
155  boundary->setPIDCell(cellid, long(1));
156  }
157  for(long cellid : pidlist2){
158  boundary->setPIDCell(cellid, long(2));
159  }
160 
161  //create then a subpatch of the boundary using pidlist... and bc...list
162  mimmo::MimmoSharedPointer<mimmo::MimmoObject> bdirMesh(new mimmo::MimmoObject(boundary->getType()));
163 
164  if(rank == 0){ //create a subselection of the whole boundary
165  //vertices
166  std::unordered_set<long> potvertices(bc1list.begin(), bc1list.end());
167  potvertices.insert(bc2list.begin(), bc2list.end());
168  for(long idv: potvertices){
169  bdirMesh->addVertex(boundary->getVertexCoords(idv), idv);
170  }
171  //cell
172  //mark to delete all cells not in the pidlist1 and 2.
173  std::unordered_set<long> preservedcells (pidlist1.begin(), pidlist1.end());
174  preservedcells.insert(pidlist2.begin(), pidlist2.end());
175 
176  for(long idc: preservedcells){
177  bdirMesh->addCell(boundary->getPatch()->getCell(idc), idc, rank);
178  }
179  }
180  bdirMesh->updateInterfaces();
181  bdirMesh->update();
182 
183 std::chrono::time_point<Clock> t1,t2;
184 
185 #if MIMMO_ENABLE_MPI
186  /*
187  Distribute the volume mesh and bDirMesh on processes
188  */
189  mimmo::Partition* partition = new mimmo::Partition();
190  partition->setPlotInExecution(true);
191  partition->setGeometry(mesh);
192  partition->setBoundaryGeometry(bdirMesh);
193  partition->setPartitionMethod(mimmo::PartitionMethod::PARTGEOM);
194  partition->exec();
195 #endif
196 
197  // create a field of Dirichlet values on bDirMesh points.
199  bc_surf_field.setGeometry(bdirMesh);
201  bc_surf_field.reserve(bdirMesh->getNVertices());
202 
203  for(auto & cell : bdirMesh->getCells()){
204  if (cell.getPID() == 1){
205  for (long id : cell.getVertexIds()){
206  if (!bc_surf_field.exists(id))
207  bc_surf_field.insert(id, {{1., 1., 0.}});
208  }
209  }
210  if (cell.getPID() == 2){
211  for (long id : cell.getVertexIds()){
212  if (!bc_surf_field.exists(id))
213  bc_surf_field.insert(id, {{0., 0., 0.}});
214  }
215  }
216  }
217 
218  //update volume and dirichelet boundary mesh
219  mesh->update();
220  bdirMesh->update();
221 
222  /*
223  Define a propagator.
224  It will use dirichlet conditions in bc_surf_field defined on the dirichlet
225  patch bdirMesh, and propagate these info inside the bulk volume mesh.
226  Please see the doxygen documentation of PropagateVectorField for further information
227  on the tunable parameters of the class.
228  */
229  mimmo::PropagateVectorField * prop = new mimmo::PropagateVectorField();
230  prop->setGeometry(mesh);
231  prop->addDirichletBoundaryPatch(bdirMesh);
232  prop->addDirichletConditions(&bc_surf_field);
233  prop->setSolverMultiStep(10);
234  prop->setPlotInExecution(true);
235  prop->setApply(true);
236 
237  prop->setDamping(true);
238  prop->setDampingType(1);
239  prop->setDampingDecayFactor(1.0);
240  prop->setDampingInnerDistance(0.05);
241  prop->setDampingOuterDistance(0.35);
242  prop->addDampingBoundarySurface(bdirMesh);
243 
244  prop->setNarrowBand(false);
245  prop->setNarrowBandWidth(0.6);
246  prop->setNarrowBandRelaxation(0.7);
247  prop->addNarrowBandBoundarySurface(bdirMesh);
248 
249 
250  t1 = Clock::now();
251  if (rank == 0){
252  std::cout << "Start Propagator vector field " << std::endl;
253  }
254 
255  prop->exec();
256 
257  t2 = Clock::now();
258  if (rank ==0){
259  std::cout << "Propagator vector field execution time: "
260  << std::chrono::duration_cast<std::chrono::seconds>(t2 - t1).count()
261  << " seconds" << std::endl;
262  }
263 
264  //write the propagated field on file.
265  prop->getGeometry()->getPatch()->write("deformed");
266 
267  bool error = false;
268 
269 #if MIMMO_ENABLE_MPI
270  delete partition;
271 #endif
272  delete prop;
273 
274  return int(error);
275 }
276 
277 // =================================================================================== //
278 
279 int main( int argc, char *argv[] ) {
280 
281  BITPIT_UNUSED(argc);
282  BITPIT_UNUSED(argv);
283 
284 #if MIMMO_ENABLE_MPI
285  MPI_Init(&argc, &argv);
286 #endif
287 
288  int val = 1;
289  try{
291  val = test00001() ;
292  }
293  catch(std::exception & e){
294  std::cout<<"propagators_example_00001 exited with an error of type : "<<e.what()<<std::endl;
295  return 1;
296  }
297 
298 #if MIMMO_ENABLE_MPI
299  MPI_Finalize();
300 #endif
301 
302  return val;
303 }
MimmoObject is the basic geometry container for mimmo library.
std::vector< long > livector1D
MimmoPiercedVector is the basic data container for mimmo library.
void setGeometry(MimmoSharedPointer< MimmoObject > geo)
void setDataLocation(MPVLocation loc)