test_propagators_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 
25 #include "mimmo_propagators.hpp"
26 #if MIMMO_ENABLE_MPI
27 #include "mimmo_parallel.hpp"
28 #endif
29 
30 // =================================================================================== //
46 // =================================================================================== //
47 
48 // =================================================================================== //
49 
51 
52  std::array<double,3> center({{0.0,0.0,0.0}});
53  double radiusin(2.0), radiusout(5.0);
54  double azimuthin(0.0), azimuthout(0.5*BITPIT_PI);
55  double heightbottom(-1.0), heighttop(1.0);
56  int nr(6), nt(10), nh(6);
57 
58  double deltar = (radiusout - radiusin)/ double(nr);
59  double deltat = (azimuthout - azimuthin)/ double(nt);
60  double deltah = (heighttop - heightbottom)/ double(nh);
61 
62  std::vector<std::array<double,3> > verts ((nr+1)*(nt+1)*(nh+1));
63 
64  int counter = 0;
65  for(int k=0; k<=nh; ++k){
66  for(int j=0; j<=nt; ++j){
67  for(int i=0; i<=nr; ++i){
68  verts[counter][0] =(radiusin + i*deltar)*std::cos(azimuthin + j*deltat);
69  verts[counter][1] =(radiusin + i*deltar)*std::sin(azimuthin + j*deltat);
70  verts[counter][2] =(heightbottom + k*deltah);
71  ++counter;
72  }
73  }
74  }
75 
76  //create the volume mesh mimmo.
78 
79  if (rank == 0){
80  mesh->getPatch()->reserveVertices((nr+1)*(nt+1)*(nh+1));
81 
82  //pump up the vertices
83  for(const auto & vertex : verts){
84  mesh->addVertex(vertex); //automatic id assigned to vertices.
85  }
86  mesh->getPatch()->reserveCells(nr*nt*nh);
87 
88  //create connectivities for hexa elements
89  std::vector<long> conn(8,0);
90  for(int k=0; k<nh; ++k){
91  for(int j=0; j<nt; ++j){
92  for(int i=0; i<nr; ++i){
93  conn[0] = (nr+1)*(nt+1)*k + (nr+1)*j + i;
94  conn[1] = (nr+1)*(nt+1)*k + (nr+1)*j + i+1;
95  conn[2] = (nr+1)*(nt+1)*k + (nr+1)*(j+1) + i+1;
96  conn[3] = (nr+1)*(nt+1)*k + (nr+1)*(j+1) + i;
97  conn[4] = (nr+1)*(nt+1)*(k+1) + (nr+1)*j + i;
98  conn[5] = (nr+1)*(nt+1)*(k+1) + (nr+1)*j + i+1;
99  conn[6] = (nr+1)*(nt+1)*(k+1) + (nr+1)*(j+1) + i+1;
100  conn[7] = (nr+1)*(nt+1)*(k+1) + (nr+1)*(j+1) + i;
101  mesh->addConnectedCell(conn, bitpit::ElementType::HEXAHEDRON);
102  }
103  }
104  }
105  }// end rank 0
106 
107  mesh->update();
108  boundary = mesh->extractBoundaryMesh();
109 
110  //decompose manually the six boundary faces.
111  std::vector<std::vector<long>> bverts(6, std::vector<long>());
112 
113  //vertex at azimuthal limits.
114  for(int k=0; k<=nh; ++k){
115  for(int i=0; i<=nr; ++i){
116  bverts[0].push_back((nr+1)*(nt+1)*k + i);
117  bverts[1].push_back((nr+1)*(nt+1)*k + (nr+1)*nt + i);
118  }
119  }
120 
121  //vertex at quote limits.
122  for(int j=0; j<=nt; ++j){
123  for(int i=0; i<=nr; ++i){
124  bverts[2].push_back((nr+1)*j + i);
125  bverts[3].push_back((nr+1)*(nt+1)*nh + (nr+1)*j + i);
126  }
127  }
128 
129  //vertex at radius limits.
130  for(int k=0; k<=nh; ++k){
131  for(int j=0; j<=nt; ++j){
132  bverts[4].push_back((nr+1)*(nt+1)*k + (nr+1)*j);
133  bverts[5].push_back((nr+1)*(nt+1)*k + (nr+1)*j + nr);
134  }
135  }
136 
137  //put together
139  long pidder = 1;
140  for(livector1D & vert : bverts ){
141  livector1D boundaryfaces = boundary->getCellFromVertexList(vert, true);
142  for(long id : boundaryfaces){
143  pidfaces.insert(id, pidder);
144  }
145  ++pidder;
146  }
147  bverts.clear();
148 
149  for(auto it= pidfaces.begin(); it!= pidfaces.end(); ++it){
150  boundary->setPIDCell(it.getId(), *it);
151  }
152 
153  boundary->updateAdjacencies();
154  boundary->update();
155  boundary->getPatch()->write("piddedBoundary_test3");
156 
157  return mesh;
158 }
159 
160 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
162  if(!boundary) return nullptr;
163 
164  livector1D cellsID = boundary->extractPIDCells(pids);
165  livector1D vertID = boundary->getVertexFromCellList(cellsID);
166 
168 
169  extracted->getPatch()->reserveVertices(vertID.size());
170  extracted->getPatch()->reserveCells(cellsID.size());
171 
172  for(long id: vertID){
173  extracted->addVertex(boundary->getVertexCoords(id), id);
174  }
175  for(long id: cellsID){
176  extracted->addCell(boundary->getCells().at(id), id);
177  }
178 
179  extracted->updateAdjacencies();
180  extracted->update();
181  return extracted;
182 }
183 
184 // =================================================================================== //
185 
186 int test1() {
187 
188 #if MIMMO_ENABLE_MPI
189  // Initialize mpi
190  int nProcs;
191  int rank;
192  MPI_Comm_size(MPI_COMM_WORLD, &nProcs);
193  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
194 #else
195  int rank = 0;
196 #endif
197 
199  mimmo::MimmoSharedPointer<mimmo::MimmoObject> mesh = createTestVolumeMesh(rank, bDirMesh);
200 
201 #if MIMMO_ENABLE_MPI
202  /* Instantiation of a Partition object with default patition method space filling curve.
203  * Plot Optional results during execution active for Partition block.
204  */
205  mimmo::Partition* partition = new mimmo::Partition();
206  partition->setPlotInExecution(true);
207  partition->setGeometry(mesh);
208  partition->setBoundaryGeometry(bDirMesh);
209  partition->setPartitionMethod(mimmo::PartitionMethod::PARTGEOM);
210  partition->exec();
211 #endif
212 
213  mimmo::MimmoSharedPointer<mimmo::MimmoObject> bDIR = pidExtractor(bDirMesh, {{1,2}});
214  mimmo::MimmoSharedPointer<mimmo::MimmoObject> bSLIP = pidExtractor(bDirMesh, {{5,6}});
215 
216  //TESTING THE VECTOR PROPAGATOR //////
217  // and the scalar field of Dirichlet values on pidded surface 0 and 1 nodes.
219  bc_surf_3Dfield.setGeometry(bDIR);
220  bc_surf_3Dfield.setDataLocation(mimmo::MPVLocation::POINT);
221  bc_surf_3Dfield.reserve(bDIR->getNVertices());
222 
223  std::vector<long> d1 = bDIR->getVertexFromCellList(bDIR->extractPIDCells(1));
224  for(long id : d1){
225  bc_surf_3Dfield.insert(id, {{0.0, 0.0, 0.0}});
226  }
227  //apply a rotation of alpha around z centered in the origin 0,0,0, so that deformation is
228  //x-directed and equal to tan(alpha) * y-coord of the point.
229  //BEWARE IF THE ROTATION ARC IS similar to a linear segment, this deformation works,
230  //for large rotation, where the arc path is very different from a different segment, this
231  // could lead to not properly expected results.
232  double alpha = 25.0*BITPIT_PI/180.0;
233  std::vector<long> d2 = bDIR->getVertexFromCellList(bDIR->extractPIDCells(2));
234  for(long id : d2){
235  darray3E coord = bDIR->getVertexCoords(id);
236  double normc = std::sqrt(coord[0]*coord[0] + coord[1]*coord[1]);
237  bc_surf_3Dfield.insert(id, {{std::sin(alpha)*normc,
238  (std::cos(alpha)-1.0)*normc,
239  0.0}} );
240  }
241 
242  // Now create a PropagateScalarField and solve the laplacian.
243  mimmo::PropagateVectorField * prop3D = new mimmo::PropagateVectorField();
244  prop3D->setName("test00003_PropagateVectorField");
245  prop3D->setGeometry(mesh);
246  prop3D->addDirichletBoundaryPatch(bDIR);
247  prop3D->addDirichletConditions(&bc_surf_3Dfield);
248  prop3D->addSlipBoundarySurface(bSLIP);
249  prop3D->addSlipReferenceSurface(bSLIP);
250 
251  prop3D->setDamping(true);
252  prop3D->setDampingType(0);
253  prop3D->setDampingDecayFactor(2.0);
254  prop3D->setDampingInnerDistance(0.5);
255  prop3D->setDampingOuterDistance(2.5);
256 
257  prop3D->setSolverMultiStep(40);
258 
259  prop3D->setPlotInExecution(true);
260 
261  prop3D->exec();
262 
263  //deform the mesh and write deformation
264  mimmo::dmpvecarr3E * values3D = prop3D->getPropagatedField();
265  darray3E work;
266  for(auto it=values3D->begin(); it!=values3D->end(); ++it){
267  work = mesh->getVertexCoords(it.getId());
268  mesh->modifyVertex(work + *it, it.getId());
269  }
270  mesh->update();
271  mesh->getPatch()->write("test00003_deformedMesh");
272 
273  bool check = false;
274  long targetNode = (10 +1)*(6+1)*3 + (6+1)*5 + 3;
275  darray3E value;
276  value.fill(-1.0*std::numeric_limits<double>::max());
277  if(values3D->exists(targetNode)) value = values3D->at(targetNode);
278 
279 #if MIMMO_ENABLE_MPI
280  MPI_Allreduce(MPI_IN_PLACE, value.data(), 3, MPI_DOUBLE, MPI_MAX, prop3D->getCommunicator());
281 #endif
282 
283  if(rank == 0){
284  std::cout<<targetNode<<" "<<value<<std::endl;
285  check = check || (norm2(values3D->at(targetNode)-std::array<double,3>({{0.601253, -0.284719, 0.}})) > 1.0E-5);
286  }
287  delete prop3D;
288 #if MIMMO_ENABLE_MPI
289  delete partition;
290 #endif
291  return check;
292 }
293 
294 // =================================================================================== //
295 
296 int main( int argc, char *argv[] ) {
297 
298  BITPIT_UNUSED(argc);
299  BITPIT_UNUSED(argv);
300 
301 #if MIMMO_ENABLE_MPI
302  MPI_Init(&argc, &argv);
303 #endif
304 
305  int val = 1;
306  try{
307  val = test1() ;
308  }
309  catch(std::exception & e){
310  std::cout<<"test_propagators_00003 exited with an error of type : "<<e.what()<<std::endl;
311  return 1;
312  }
313 #if MIMMO_ENABLE_MPI
314  MPI_Finalize();
315 #endif
316 
317  return val;
318 }
MimmoObject is the basic geometry container for mimmo library.
std::vector< long > livector1D
void setGeometry(MimmoSharedPointer< MimmoObject > geo)
std::array< double, 3 > darray3E