Memosa-FVM  0.2
IBManager.cpp
Go to the documentation of this file.
1 // This file os part of FVM
2 // Copyright (c) 2012 FVM Authors
3 // See LICENSE file for terms.
4 
5 #include "IBManager.h"
6 #include "AABB.h"
7 #include "KSearchTree.h"
8 #include "Mesh.h"
9 #include "GradientModel.h"
10 #include <stack>
11 #include <iostream>
12 #include <fstream>
13 
14 #ifdef FVM_PARALLEL
15 #include <mpi.h>
16 #endif
17 
18 
19 
21  Mesh& solidBoundaryMesh,
22  const MeshList& fluidMeshes):
23  fluidNeighborsPerIBFace(50),
24  fluidNeighborsPerSolidFace(50),
25  solidNeighborsPerIBFace(50),
26  IBNeighborsPerSolidFace(50),
27  _geomFields(geomFields),
28  _solidBoundaryMesh(solidBoundaryMesh),
29  _fluidMeshes(fluidMeshes)
30 {}
31 
33 {
34  AABB sMeshesAABB(_solidBoundaryMesh);
35 
36  const StorageSite& solidMeshFaces = _solidBoundaryMesh.getFaces();
37 
38  const Vec3DArray& solidMeshCoords =
39  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[solidMeshFaces]);
40 
41  KSearchTree solidMeshKSearchTree(solidMeshCoords);
42 
43  const int numFluidMeshes = _fluidMeshes.size();
44 
45  for (int n=0; n<numFluidMeshes; n++)
46  {
47  Mesh& fluidMesh = *_fluidMeshes[n];
48  markIntersections(fluidMesh, sMeshesAABB);
49  }
50 
51 
52  int nIter=0;
53  int nFound=0;
54 
55  // repeat till we find no more fluid cells
56  do
57  {
58  nFound = 0;
60 
61  for (int n=0; n<numFluidMeshes; n++)
62  {
63  Mesh& fluidMesh = *_fluidMeshes[n];
64 
65  nFound += markFluid(fluidMesh);
66  }
67 #ifdef FVM_PARALLEL
68  MPI::COMM_WORLD.Allreduce( MPI::IN_PLACE, &nFound, 1, MPI::INT, MPI::SUM );
69  if ( MPI::COMM_WORLD.Get_rank() == 0 )
70  cout << "iteration " << nIter << ": found " << nFound << " fluid cells " << endl;
71 #endif
72 
73 #ifndef FVM_PARALLEL
74  cout << "iteration " << nIter << ": found " << nFound << " fluid cells " << endl;
75 #endif
76 
77  nIter++;
78  }
79  while(nFound > 0);
80 
81  nFound=0;
82  for (int n=0; n<numFluidMeshes; n++)
83  {
84  Mesh& fluidMesh = *_fluidMeshes[n];
85 
86  nFound += markSolid(fluidMesh);
87  }
89 
90  for (int n=0; n<numFluidMeshes; n++)
91  {
92  Mesh& fluidMesh = *_fluidMeshes[n];
93 
94  markIBTypePlus(fluidMesh);
95  }
96 
97  for (int n=0; n<numFluidMeshes; n++)
98  {
99  Mesh& fluidMesh = *_fluidMeshes[n];
100 
101  createIBFaces(fluidMesh);
102  }
103 
104  vector<NearestCell> solidFacesNearestCell(solidMeshFaces.getCount());
105  // vector<NearestIBFace> solidFacesNearestIBFace(solidMeshFaces.getCount());
106 
107  for (int n=0; n<numFluidMeshes; n++) {
108  Mesh& fluidMesh = *_fluidMeshes[n];
109 
110  if (!fluidMesh.isShell()){
111 
112  const StorageSite& cells = fluidMesh.getCells();
113  const int numCells = cells.getSelfCount();
114  // StorageSite& ibFaces = fluidMesh.getIBFaces();
115  // const int nIBFaces = ibFaces.getCount();
116  IntArray& cellIBType = dynamic_cast<IntArray&>(_geomFields.ibType[cells]);
117 
118  const Vec3DArray& cellCoords =
119  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[cells]);
120  // const Vec3DArray& ibFaceCoords =
121  // dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[ibFaces]);
122  KSearchTree fluidCellsTree;
123  for(int c=0; c<numCells; c++)
124  {
125  if (cellIBType[c] == Mesh::IBTYPE_FLUID)
126  fluidCellsTree.insert(cellCoords[c],c);
127  }
128  // for(int c=0; c<nIBFaces; c++)
129  // {
130  // IBFacesTree.insert(ibFaceCoords[c],c);
131  // }
132  createIBInterpolationStencil(fluidMesh,fluidCellsTree,solidMeshKSearchTree);
133 
134  findNearestCellForSolidFaces(fluidMesh,fluidCellsTree,solidFacesNearestCell);
135 
136  }
137  }
138 
139 
140 #ifdef FVM_PARALLEL
141  vector<doubleIntStruct> solidFacesNearestCellMPI(solidMeshFaces.getCount());
142  const int procID = MPI::COMM_WORLD.Get_rank();
143  const int faceCount = solidMeshFaces.getCount();
144  for( int i = 0; i < faceCount; i++ ){
145  const Mesh* mesh = solidFacesNearestCell[i].mesh;
146  if ( mesh != NULL){
147  const int meshID = mesh->getID();
148  const int tag = (std::max(procID, meshID) << 16 ) | ( std::min(procID,meshID) );
149  const double val = solidFacesNearestCell[i].distanceSquared;
150  solidFacesNearestCellMPI[i].VALUE = val;
151  solidFacesNearestCellMPI[i].TAG = tag;
152  } else {
153  const double LARGE_VALUE = 1.0e+15;
154  solidFacesNearestCellMPI[i].VALUE = LARGE_VALUE;
155  solidFacesNearestCellMPI[i].TAG = -1;
156 
157  }
158  }
159  //mpi comminuction
160  MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &solidFacesNearestCellMPI[0], faceCount, MPI::DOUBLE_INT, MPI::MINLOC);
161  //now update solidFAcesNearestCell
162  for ( int i = 0; i < faceCount; i++ ){
163  const Mesh* meshThis = solidFacesNearestCell[i].mesh;
164  if ( meshThis != NULL ){
165  const int meshIDThis = meshThis->getID();
166  const int tagThis = (std::max(procID, meshIDThis) << 16 ) | ( std::min(procID,meshIDThis) );
167  if ( tagThis != solidFacesNearestCellMPI[i].TAG ){
168  solidFacesNearestCell[i].mesh = NULL;
169  }
170 
171  }
172  }
173 #endif
174 
175 
176  for (int n=0; n<numFluidMeshes; n++)
177  {
178  Mesh& fluidMesh = *_fluidMeshes[n];
179  if (!fluidMesh.isShell()){
180  StorageSite& ibFaces = fluidMesh.getIBFaces();
181  const StorageSite& faces = fluidMesh.getFaces();
182  const Vec3DArray& faceCoords =
183  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[faces]);
184  const int nIBFaces = ibFaces.getCount();
185  const Array<int>& ibFaceIndices = fluidMesh.getIBFaceList();
186  KSearchTree IBFacesTree;
187  for(int c=0; c<nIBFaces; c++)
188  {
189  const int gf=ibFaceIndices[c];
190  IBFacesTree.insert(faceCoords[gf],c);
191  }
192  // findNearestIBFaceForSolidFaces(fluidMesh,IBFacesTree,solidFacesNearestIBFace);
193  createSolidInterpolationStencil(fluidMesh,IBFacesTree,solidFacesNearestCell);
194 
195  }
196  }
197 
198 }
199 
200 
201 
202 void
203 IBManager::markIntersections(Mesh& fluidMesh, AABB& sMeshesAABB)
204 {
205 
206  const StorageSite& cells = fluidMesh.getCells();
207  IntArray& cellIBType = dynamic_cast<IntArray&>(_geomFields.ibType[cells]);
208 
209  cellIBType = Mesh::IBTYPE_UNKNOWN;
210 
211  if (fluidMesh.isShell())
212  {
213  cellIBType = Mesh::IBTYPE_FLUID;
214  return;
215  }
216 
217  const Array<Vector<double,3> >& meshCoords = fluidMesh.getNodeCoordinates();
218 
219  const StorageSite& faces = fluidMesh.getFaces();
220  const CRConnectivity& faceCells = fluidMesh.getAllFaceCells();
221  const CRConnectivity& cellNodes = fluidMesh.getCellNodes();
222 
223 
224  const int nFaces = faces.getCount();
225 
226  int nIntersections = 0;
227 
228  const bool is2D = fluidMesh.getDimension() == 2;
229 
230  if (is2D)
231  {
232  const int nCells = cells.getSelfCount();
233  for(int n=0; n<nCells; n++)
234  {
235  const Vec3D& a = meshCoords[cellNodes(n,0)];
236  const Vec3D& b = meshCoords[cellNodes(n,1)];
237  const Vec3D& c = meshCoords[cellNodes(n,2)];
238 
239  if (sMeshesAABB.hasIntersectionWithTriangle(a,b,c))
240  {
241  cellIBType[n] = Mesh::IBTYPE_BOUNDARY;
242 
243  nIntersections++;
244  }
245  else if (cellNodes.getCount(n) == 4)
246  {
247 
248  const Vec3D& d = meshCoords[cellNodes(n,3)];
249  if (sMeshesAABB.hasIntersectionWithTriangle(c,d,a))
250  {
251  cellIBType[n] = Mesh::IBTYPE_BOUNDARY;
252  nIntersections++;
253  }
254  }
255  }
256  }
257  else
258  {
259  const CRConnectivity& faceNodes = fluidMesh.getAllFaceNodes();
260  // loop through all the faces to find cells that intersect the AABB
261  // faces and mark them to be of type boundary
262 
263  for(int f=0; f<nFaces; f++)
264  {
265  const int c0 = faceCells(f,0);
266  const int c1 = faceCells(f,1);
267 
268  const Vec3D& a = meshCoords[faceNodes(f,0)];
269  const Vec3D& b = meshCoords[faceNodes(f,1)];
270  const Vec3D& c = meshCoords[faceNodes(f,2)];
271 
272  // check the triangle formed by the first three vertices
273  if (sMeshesAABB.hasIntersectionWithTriangle(a,b,c))
274  {
275  cellIBType[c0] = Mesh::IBTYPE_BOUNDARY;
276  cellIBType[c1] = Mesh::IBTYPE_BOUNDARY;
277 
278  nIntersections++;
279  }
280  else if (faceNodes.getCount(f) == 4)
281  {
282  // check the other triangle if this is a quad face
283  const Vec3D& d = meshCoords[faceNodes(f,3)];
284  if (sMeshesAABB.hasIntersectionWithTriangle(c,d,a))
285  {
286  cellIBType[c0] = Mesh::IBTYPE_BOUNDARY;
287  cellIBType[c1] = Mesh::IBTYPE_BOUNDARY;
288  nIntersections++;
289  }
290  }
291  }
292  }
293 
294 
295  // mark all cells adjacent to the boundaries as fluid unless they
296  // have been found to be IBTYPE_BOUNDARY in the loop above
297 
298  foreach(const FaceGroupPtr fgPtr, fluidMesh.getBoundaryFaceGroups())
299  {
300  const FaceGroup& fg = *fgPtr;
301  const StorageSite& faces = fg.site;
302 
303  const CRConnectivity& faceCells = fluidMesh.getFaceCells(faces);
304  const int nFaces = faces.getCount();
305  for(int f=0; f<nFaces; f++)
306  {
307  const int c0 = faceCells(f,0);
308  const int c1 = faceCells(f,1);
309 
310  if ((cellIBType[c0] == Mesh::IBTYPE_UNKNOWN) &&
311  (cellIBType[c1] == Mesh::IBTYPE_UNKNOWN))
312  {
313  cellIBType[c1] = Mesh::IBTYPE_FLUID;
314  cellIBType[c0] = Mesh::IBTYPE_FLUID;
315  }
316  else if (cellIBType[c0] == Mesh::IBTYPE_BOUNDARY)
317  {
318  cellIBType[c1] = Mesh::IBTYPE_BOUNDARY;
319  }
320  }
321  }
322 
323 }
324 
325 
326 int
328 {
329 
330  const StorageSite& cells = fluidMesh.getCells();
331 
332  IntArray& cellIBType = dynamic_cast<IntArray&>(_geomFields.ibType[cells]);
333 
334 
335  const int nCellsTotal = cells.getCount();
336 
337  int nFound=0;
338 
339 
340  const CRConnectivity& cellCells = fluidMesh.getCellCells();
341 
342 
343  // loop over all cells including externals and if they are of type
344  // fluid mark any other cells that are unknown but can be reached
345  // from there
346 
347  for(int c=0; c<nCellsTotal; c++)
348  {
349  if (cellIBType[c] == Mesh::IBTYPE_FLUID)
350  {
351 
352  stack<int> cellsToCheck;
353  cellsToCheck.push(c);
354 
355 
356  while(!cellsToCheck.empty())
357  {
358  int c_nb = cellsToCheck.top();
359  cellsToCheck.pop();
360  const int nNeighbors = cellCells.getCount(c_nb);
361  for(int nn=0; nn<nNeighbors; nn++)
362  {
363  const int neighbor = cellCells(c_nb,nn);
364  if (cellIBType[neighbor] == Mesh::IBTYPE_UNKNOWN)
365  {
366  cellIBType[neighbor] = Mesh::IBTYPE_FLUID;
367  nFound++;
368  cellsToCheck.push(neighbor);
369  }
370  }
371 
372  }
373  }
374  }
375 
376  return nFound;
377 }
378 
379 int
381 {
382 
383  const StorageSite& cells = fluidMesh.getCells();
384 
385  IntArray& cellIBType = dynamic_cast<IntArray&>(_geomFields.ibType[cells]);
386 
387 
388  const int nCellsTotal = cells.getSelfCount();
389 
390  int nFound=0;
391 
392  //everything that is not marked is solid
393  for(int c=0; c<nCellsTotal; c++)
394  {
395  if (cellIBType[c] == Mesh::IBTYPE_UNKNOWN)
396  {
397  cellIBType[c] = Mesh::IBTYPE_SOLID;
398  nFound++;
399  }
400  }
401 
402  return nFound;
403 }
404 
405 
406 void
408 {
409 
410 #if 0
411  int nFluid=0;
412  int nSolid=0;
413  int nBoundary=0;
414 
415  StorageSite& cells = fluidMesh.getCells();
416  const int nCellsTotal = cells.getCountLevel1();
417  const IntArray& cellIBType = dynamic_cast<IntArray&>(_geomFields.ibType[cells]);
418 
419 
420  cout << " found " << nFluid << " fluid, "
421  << nSolid << " solid and "
422  << nBoundary << " boundary cells " << endl;
423 
424 #endif
425 
426 #ifdef FVM_PARALLEL
427 
428 #if 0
429  int nCellsInner = cells.getSelfCount();
430  int nFluidGlobal=0;
431  int nSolidGlobal=0;
432  int nBoundaryGlobal=0;
433  vector<int> ibTypeCells;
434  const Array<int>& localToGlobal = fluidMesh.getLocalToGlobal();
435 
436  for(int c=0; c<nCellsInner; c++)
437  {
438  if (cellIBType[c] == Mesh::IBTYPE_FLUID)
439  nFluid++;
440  else if (cellIBType[c] == Mesh::IBTYPE_SOLID)
441  nSolid++;
442  else if (cellIBType[c] == Mesh::IBTYPE_BOUNDARY){
443  nBoundary++;
444  ibTypeCells.push_back(localToGlobal[c]);
445  }
446  else{
447  throw CException("invalid ib type");
448  }
449  }
450 
451  MPI::COMM_WORLD.Allreduce( &nFluid, &nFluidGlobal , 1, MPI::INT, MPI::SUM);
452  MPI::COMM_WORLD.Allreduce( &nSolid, &nSolidGlobal , 1, MPI::INT, MPI::SUM);
453  MPI::COMM_WORLD.Allreduce( &nBoundary, &nBoundaryGlobal, 1, MPI::INT, MPI::SUM);
454  vector<int> ibTypeCellsGlobal(nBoundaryGlobal);
455  const int nsize = MPI::COMM_WORLD.Get_size();
456  const int rank = MPI::COMM_WORLD.Get_rank();
457  int counts [nsize];
458  int offsets[nsize];
459  MPI::COMM_WORLD.Allgather(&nBoundary, 1, MPI::INT, &counts[0], 1, MPI::INT);
460  //form offsets
461  offsets[0] = 0;
462  for ( int p=1; p < nsize; p++){
463  offsets[p] = counts[p-1] + offsets[p-1];
464  }
465 
466  //gathering/
467  MPI::COMM_WORLD.Gatherv(&ibTypeCells[0],counts[rank], MPI::INT,
468  &ibTypeCellsGlobal[0], counts, offsets, MPI::INT, 0);
469 
470 
471  if ( MPI::COMM_WORLD.Get_rank() == 0 ){
472  set<int> ibTypeCellSet;
473  for( int i = 0; i < int(ibTypeCellsGlobal.size()); i++ ){
474  ibTypeCellSet.insert( ibTypeCellsGlobal[i] );
475  }
476 
477 
478  ofstream debugFile;
479  debugFile.open("IBManagerDEBUG.dat");
480  debugFile << " found (global) " << nFluidGlobal << " fluid, " << nSolidGlobal << " solid and "
481  << nBoundaryGlobal << " boundary cells " << endl;
482  debugFile << "IBTYPE_BOUNDARY CELLS (GLOBAL NUMBERING)" << endl;
483  foreach ( const set<int>::value_type cellID, ibTypeCellSet){
484  debugFile << cellID << endl;
485  }
486 
487  debugFile.close();
488 
489  }
490 #endif
491 
492 #endif
493 
494 
495 }
496 
497 void
499 {
500 
501  if (fluidMesh.isShell())
502  return;
503  const StorageSite& faces = fluidMesh.getFaces();
504  const StorageSite& cells = fluidMesh.getCells();
505 
506  const CRConnectivity& faceCells = fluidMesh.getAllFaceCells();
507 
508  IntArray& cellIBType = dynamic_cast<IntArray&>(_geomFields.ibType[cells]);
509  IntArray& ibFaceIndex = dynamic_cast<IntArray&>(_geomFields.ibFaceIndex[faces]);
510 
511  const int nFaces = faces.getCount();
512 
513  ibFaceIndex = -1;
514 
515  // find number of IBFaces
516 
517  int nIBFaces=0;
518  for(int f=0; f<nFaces; f++)
519  {
520  const int c0 = faceCells(f,0);
521  const int c1 = faceCells(f,1);
522 
523  const int ibType0 = cellIBType[c0];
524  const int ibType1 = cellIBType[c1];
525 
526  if ((ibType0 == Mesh::IBTYPE_FLUID && ibType1 == Mesh::IBTYPE_BOUNDARY) ||
527  (ibType1 == Mesh::IBTYPE_FLUID && ibType0 == Mesh::IBTYPE_BOUNDARY))
528  {
529  ibFaceIndex[f]=nIBFaces++;
530  }
531 
532  if ((ibType0 == Mesh::IBTYPE_FLUID && ibType1 == Mesh::IBTYPE_SOLID) ||
533  (ibType1 == Mesh::IBTYPE_FLUID && ibType0 == Mesh::IBTYPE_SOLID))
534  {
535  throw CException("found face between solid and fluid cells");
536  }
537 
538  }
539 
540  StorageSite& ibFaces = fluidMesh.getIBFaces();
541  ibFaces.setCount(nIBFaces);
542 
543  shared_ptr<IntArray > ibFaceListPtr(new IntArray(nIBFaces));
544 
545  IntArray& ibFaceList = *ibFaceListPtr;
546 
547  nIBFaces = 0;
548  for(int f=0; f<nFaces; f++)
549  {
550  const int c0 = faceCells(f,0);
551  const int c1 = faceCells(f,1);
552 
553  const int ibType0 = cellIBType[c0];
554  const int ibType1 = cellIBType[c1];
555 
556  if ((ibType0 == Mesh::IBTYPE_FLUID && ibType1 == Mesh::IBTYPE_BOUNDARY) ||
557  (ibType1 == Mesh::IBTYPE_FLUID && ibType0 == Mesh::IBTYPE_BOUNDARY))
558  {
559  ibFaceList[nIBFaces++] = f;
560  }
561  }
562 
563  fluidMesh.setIBFaces(ibFaceListPtr);
564  cout << " found " << nIBFaces << " ib Faces " << endl;
565 
567 }
568 
575 void addFluidNeighbors(set<int>& neighbors,
576  const CRConnectivity& cellCells,
577  const Array<int>& ibType)
578 {
579  set<int> newNeighbors;
580  foreach(int c, neighbors)
581  {
582  const int neighborCount = cellCells.getCount(c);
583  for(int nnb=0; nnb<neighborCount; nnb++)
584  {
585  const int c_nb = cellCells(c,nnb);
586  if (ibType[c_nb] == Mesh::IBTYPE_FLUID)
587  newNeighbors.insert(c_nb);
588  }
589  }
590  neighbors.insert(newNeighbors.begin(),newNeighbors.end());
591 }
592 
593 void
595  KSearchTree& fluidCellsTree,
596  KSearchTree& solidFacesTree)
597 {
598  const StorageSite& cells = mesh.getCells();
599  const StorageSite& solidMeshFaces = _solidBoundaryMesh.getFaces();
600  StorageSite& ibFaces = mesh.getIBFaces();
601  const int nIBFaces = ibFaces.getCount();
602 
603  if (nIBFaces == 0)
604  return;
605 
606  const Vec3DArray& faceCentroid =
607  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[mesh.getFaces()]);
608 
609  Array<int> solidNeighbors(solidNeighborsPerIBFace);
610 
611  const Array<int>& ibFaceIndices = mesh.getIBFaceList();
612 
613  shared_ptr<CRConnectivity> ibFaceToCells
614  (new CRConnectivity(ibFaces,cells));
615 
616  shared_ptr<CRConnectivity> ibFaceToSolid
617  (new CRConnectivity(ibFaces,solidMeshFaces));
618 
619 
620  //const CRConnectivity& cellCells = mesh.getCellCells();
621  const CRConnectivity& cellCells2 = mesh.getCellCells2();
622  IntArray& cellIBType = dynamic_cast<IntArray&>(_geomFields.ibType[cells]);
623 
624  vector<NearestCell> nearestCellForIBFace(nIBFaces);
625 
626  const Vec3DArray& cellCoords =
627  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[cells]);
628 
629  const Vec3DArray& solidMeshCoords =
630  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[solidMeshFaces]);
631 
632  Array<int> desiredNeighbors(fluidNeighborsPerIBFace);
633 
634  ibFaceToCells->initCount();
635  ibFaceToSolid->initCount();
636 
637  for(int f=0; f<nIBFaces; f++)
638  {
639  ibFaceToSolid->addCount(f,solidNeighborsPerIBFace);
640  }
641 
642  ibFaceToSolid->finishCount();
643 
644  // in first pass we find the number of fluid cells and also set all the solid neighbors
645  for(int f=0; f<nIBFaces; f++)
646  {
647  // the index of this ib face in the mesh faces
648  const int gf = ibFaceIndices[f];
649  const Vec3D& xf = faceCentroid[gf];
650 
651  // find the closest fluid cell
652  Array<int> fluidNeighbors(1);
653  fluidNeighbors[0] = -9999;
654  fluidCellsTree.findNeighbors(xf, 1, fluidNeighbors);
655  NearestCell& nc = nearestCellForIBFace[f];
656  if ( fluidNeighbors[0] != -9999 ){
657  nc.neighbors.push_back(fluidNeighbors[0]);
658  const int c = fluidNeighbors[0];
659  const int neighborCount = cellCells2.getCount(c);
660  for(int nnb=0; nnb<neighborCount; nnb++) {
661  const int c_nb = cellCells2(c,nnb);
662  if (cellIBType[c_nb] == Mesh::IBTYPE_FLUID)
663  nc.neighbors.push_back(c_nb);
664  }
665  }
666 
667  if ((int) nc.neighbors.size() > fluidNeighborsPerIBFace)
668  {
669 
670  // create a search tree to find the desired number of neighbors out of this set
671 
672  KSearchTree dtree;
673  foreach(int nb, nc.neighbors)
674  {
675  dtree.insert( cellCoords[nb], nb);
676  }
677  bool swap = true;
678  while (swap == true){
679  swap = false;
680  for (int i=1; i<=(nc.neighbors.size()-1); i++){
681  const int nbLeft = nc.neighbors[i-1];
682  const int nbRight = nc.neighbors[i];
683  const double distanceLeft = mag2(cellCoords[nbLeft]-solidMeshCoords[f]);
684  const double distanceRight = mag2(cellCoords[nbRight]-solidMeshCoords[f]);
685  if (distanceLeft > distanceRight){
686  nc.neighbors[i-1] = nbRight;
687  nc.neighbors[i] = nbLeft;
688  swap = true;
689  }
690  }
691  }
692 
693  //dtree.findNeighbors(solidMeshCoords[f], fluidNeighborsPerSolidFace, desiredNeighbors);
694  for (int i=0; i< fluidNeighborsPerIBFace; i++)
695  desiredNeighbors[i] = nc.neighbors[i];
696 
697  // clear the current set of neighbors and add the desired ones
698  nc.neighbors.clear();
699  for(int i=0; i<fluidNeighborsPerIBFace; i++)
700  nc.neighbors.push_back(desiredNeighbors[i]);
701  }
702 
703 
704 
705 #if 0
706  int nLayers=0;
707  // repeat till we have the required number but also protect
708  // against infinite loop by capping the max number of layers
709  while( ((int)nc.neighbors.size() < fluidNeighborsPerIBFace) && (nLayers < 10)) {
710  addFluidNeighbors(nc.neighbors,cellCells,cellIBType);
711  nLayers++;
712  }
713 
714  if (nLayers == 10)
715  throw CException("not enough fluid cells for IB face interpolation");
716 #endif
717 
718  ibFaceToCells->addCount(f,nc.neighbors.size());
719 
720  // locate the required number of solid faces
721  solidFacesTree.findNeighbors(xf, solidNeighborsPerIBFace, solidNeighbors);
722 
723  for(int n=0; n<solidNeighborsPerIBFace; n++)
724  ibFaceToSolid->add(f,solidNeighbors[n]);
725  }
726 
727  ibFaceToCells->finishCount();
728  ibFaceToSolid->finishAdd();
729 
730  for(int f=0; f<nIBFaces; f++)
731  {
732  NearestCell& nc = nearestCellForIBFace[f];
733  foreach(int nb, nc.neighbors)
734  {
735  ibFaceToCells->add(f,nb);
736 // if (f==42){
737 // cout << f << " " << nb << endl;
738 // const int gf = ibFaceIndices[f];
739 // cout << "face coordinate " << faceCentroid[gf] << endl;
740 // cout << "cell coordinate " << cellCoords[nb] << endl;
741 // }
742  }
743  }
744 
745  ibFaceToCells->finishAdd();
746 #ifdef FVM_PARALLEL
747 #if 0
748  CRConnectivityPrintFile( *ibFaceToCells, "ibFaceToCells", MPI::COMM_WORLD.Get_rank() );
749  CRConnectivityPrintFile( *ibFaceToSolid, "ibFaceToSolid", MPI::COMM_WORLD.Get_rank() );
750 #endif
751 #endif
752 
753  mesh.setConnectivity(ibFaces,cells,ibFaceToCells);
754  mesh.setConnectivity(ibFaces,solidMeshFaces,ibFaceToSolid);
755 
756 }
757 
758 void
760  KSearchTree& fluidCellsTree,
761  vector<NearestCell>& nearest)
762 
763 {
764  const StorageSite& cells = mesh.getCells();
765  const StorageSite& solidMeshFaces = _solidBoundaryMesh.getFaces();
766 
767  const int nSolidFaces = solidMeshFaces.getCount();
768 
769  const Vec3DArray& cellCentroid =
770  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[cells]);
771 
772  const Vec3DArray& solidFaceCentroid =
773  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[solidMeshFaces]);
774 
775 
776  for(int f=0; f<nSolidFaces; f++)
777  {
778  Array<int> fluidNeighbors(1);
779  fluidNeighbors[0] = -9999;
780  const Vec3D& xf = solidFaceCentroid[f];
781  fluidCellsTree.findNeighbors(xf, 1, fluidNeighbors);
782  if ( fluidNeighbors[0] != -9999 ){
783  const int c = fluidNeighbors[0];
784  const Vec3D& xc = cellCentroid[c];
785  const double distanceSquared = mag2(xf-xc);
786  NearestCell& nc = nearest[f];
787  if ((nc.mesh == 0) || (nc.distanceSquared > distanceSquared))
788  {
789  nc.mesh = &mesh;
790  nc.cell = c;
791  nc.distanceSquared = distanceSquared;
792  }
793  }
794 
795  }
796 
797 }
798 
799 
800 
801 // void
802 // IBManager::findNearestIBFaceForSolidFaces(Mesh& mesh,
803 // KSearchTree& IBFacesTree,
804 // vector<NearestIBFace>& nearestIB)
805 
806 // {
807 // const StorageSite& cells = mesh.getCells();
808 // const StorageSite& solidMeshFaces = _solidBoundaryMesh.getFaces();
809 // StorageSite& ibFaces = mesh.getIBFaces();
810 // const int nSolidFaces = solidMeshFaces.getCount();
811 // const Vec3DArray& cellCentroid =
812 // dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[cells]);
813 
814 // const Vec3DArray& solidFaceCentroid =
815 // dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[solidMeshFaces]);
816 // const Vec3DArray& IBFaceCentroid =
817 // dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[ibFaces]);
818 
819 // for(int f=0; f<nSolidFaces; f++)
820 // {
821 // Array<int> IBNeighbors(1);
822 // IBNeighbors[0] = -9999;
823 // const Vec3D& xf = solidFaceCentroid[f];
824 // IBFacesTree.findNeighbors(xf, 1, IBNeighbors);
825 // if ( IBNeighbors[0] != -9999 ){
826 // const int c = IBNeighbors[0];
827 // const Vec3D& xc = IBFaceCentroid[c];
828 // const double distanceSquared = mag2(xf-xc);
829 // NearestIBFace& nc = nearestIB[f];
830 // if ((nc.mesh == 0) || (nc.distanceSquared > distanceSquared))
831 // {
832 // nc.mesh = &mesh;
833 // nc.IBFace = c;
834 // nc.distanceSquared = distanceSquared;
835 // }
836 // }
837 
838 // }
839 
840 // }
841 
842 
843 void
845  KSearchTree& IBFacesTree,
846  vector<NearestCell>& nearest)
847  // vector<NearestIBFace>& nearestIB)
848 
849 {
850  const StorageSite& cells = mesh.getCells();
851  const StorageSite& faces = mesh.getFaces();
852  const int nFaces = faces.getCount();
853  const StorageSite& solidMeshFaces = _solidBoundaryMesh.getFaces();
854  const Vec3DArray& faceCoords =
855  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[faces]);
856  const Vec3DArray& cellCoords =
857  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[cells]);
858  StorageSite& ibFaces = mesh.getIBFaces();
859  const Vec3DArray& solidMeshCoords =
860  dynamic_cast<const Vec3DArray&>(_geomFields.coordinate[solidMeshFaces]);
861 
862  const int nSolidFaces = solidMeshFaces.getCount();
863  IntArray& cellIBType = dynamic_cast<IntArray&>(_geomFields.ibType[cells]);
864  //const CRConnectivity& cellCells = mesh.getCellCells();
865  const CRConnectivity& cellCells2 = mesh.getCellCells2();
866 
867 
868  shared_ptr<CRConnectivity> solidFacesToCells
869  (new CRConnectivity(solidMeshFaces,cells));
870  shared_ptr<CRConnectivity> solidToIBFaces
871  (new CRConnectivity(solidMeshFaces,ibFaces));
872  solidFacesToCells->initCount();
873  solidToIBFaces->initCount();
874  Array<int> desiredNeighbors(fluidNeighborsPerSolidFace);
875  Array<int> desiredNeighborsforIBFaces(IBNeighborsPerSolidFace);
876  for(int f=0; f<nSolidFaces; f++)
877  {
878  solidToIBFaces->addCount(f,IBNeighborsPerSolidFace);
879  }
880 
881  solidToIBFaces->finishCount();
882 
883  for(int f=0; f<nSolidFaces; f++)
884  {
885  NearestCell& nc = nearest[f];
886  if (nc.mesh == &mesh)
887  {
888  const int c = nc.cell;
889  nc.neighbors.push_back(c);
890 
891  const int neighborCount = cellCells2.getCount(c);
892  for(int nnb=0; nnb<neighborCount; nnb++) {
893  const int c_nb = cellCells2(c,nnb);
894  if (cellIBType[c_nb] == Mesh::IBTYPE_FLUID)
895  nc.neighbors.push_back(c_nb);
896  }
897 
898 
899  if ((int) nc.neighbors.size() > fluidNeighborsPerSolidFace)
900  {
901  // create a search tree to find the desired number of neighbors out of this set
902 
903  KSearchTree dtree;
904  foreach(int nb, nc.neighbors)
905  {
906  dtree.insert( cellCoords[nb], nb);
907  }
908  // sort out the neighborlist by distance to ibface
909  bool swap = true;
910  while (swap == true){
911  swap = false;
912  for (int i=1; i<=(nc.neighbors.size()-1); i++){
913  const int nbLeft = nc.neighbors[i-1];
914  const int nbRight = nc.neighbors[i];
915  const double distanceLeft = mag2(cellCoords[nbLeft]-solidMeshCoords[f]);
916  const double distanceRight = mag2(cellCoords[nbRight]-solidMeshCoords[f]);
917  if (distanceLeft > distanceRight){
918  nc.neighbors[i-1] = nbRight;
919  nc.neighbors[i] = nbLeft;
920  swap = true;
921  }
922  }
923  }
924 
925 
926  //dtree.findNeighbors(solidMeshCoords[f], fluidNeighborsPerSolidFace, desiredNeighbors);
927  for (int i=0; i< fluidNeighborsPerSolidFace; i++)
928  desiredNeighbors[i] = nc.neighbors[i];
929 
930  // clear the current set of neighbors and add the desired ones
931  nc.neighbors.clear();
932  for(int i=0; i<fluidNeighborsPerSolidFace; i++)
933  nc.neighbors.push_back(desiredNeighbors[i]);
934  }
935 
936 
937 #if 0
938  int nLayers=0;
939  // repeat till we have the required number but also protect
940  // against infinite loop by capping the max number of layers
941  while( ((int)nc.neighbors.size() < fluidNeighborsPerIBFace) && (nLayers < 10)) {
942  addFluidNeighbors(nc.neighbors,cellCells,cellIBType);
943  nLayers++;
944  }
945 
946  //if (nLayers == 10)
947  // throw CException("not enough fluid cells for solid face interpolation");
948 #endif
949  solidFacesToCells->addCount(f,nc.neighbors.size());
950 
951  }
952 
953  }
954 
955  solidFacesToCells->finishCount();
956 
957 
958  for(int f=0; f<nSolidFaces; f++)
959  {
960  NearestCell& nc = nearest[f];
961  if (nc.mesh == &mesh)
962  {
963  foreach(int nb, nc.neighbors)
964  {
965  solidFacesToCells->add(f,nb);
966  //if (f==100){
967  // cout << f << " " << nb << endl;
968  // cout << "face coordinate " << solidMeshCoords[f] << endl;
969  // cout << "cell coordinate " << cellCoords[nb] << endl;
970  //}
971  }
972  }
973  }
974 
975  solidFacesToCells->finishAdd();
976  mesh.setConnectivity(solidMeshFaces,cells,solidFacesToCells);
977 
978  for(int f=0; f<nSolidFaces; f++)
979  {
980  // the index of this ib face in the mesh faces
981  const Vec3D& xf = solidMeshCoords[f];
982  const Array<int>& ibFaceIndices = mesh.getIBFaceList();
983  IBFacesTree.findNeighbors(xf, IBNeighborsPerSolidFace, desiredNeighborsforIBFaces);
984  for(int n=0; n< IBNeighborsPerSolidFace; n++){
985  solidToIBFaces->add(f, desiredNeighborsforIBFaces[n]);
986  // if (f==20){
987 // cout << f << " " << desiredNeighborsforIBFaces[n]<< endl;
988 // cout << "face coordinate " << solidMeshCoords[f] << endl;
989 // cout << "cell coordinate " << faceCoords[ibFaceIndices[desiredNeighborsforIBFaces[n]]] << endl;
990  // }
991  }
992  }
993 
994  solidToIBFaces->finishAdd();
995  mesh.setConnectivity(solidMeshFaces,ibFaces,solidToIBFaces);
996 
997 #ifdef FVM_PARALLEL
998 #if 0
999  CRConnectivityPrintFile( *solidFacesToCells, "solidFacesToCells", MPI::COMM_WORLD.Get_rank() );
1000 #endif
1001 #endif
1002 }
1003 
1004 
1005 void
1006 IBManager::CRConnectivityPrintFile(const CRConnectivity& conn, const string& name, const int procID) const
1007 {
1008 #ifdef FVM_PARALLEL
1009  if ( MPI::COMM_WORLD.Get_rank() == procID ){
1010  ofstream debugFile;
1011  stringstream ss(stringstream::in | stringstream::out);
1012  ss << procID;
1013  string fname = name + ss.str() + ".dat";
1014  debugFile.open( fname.c_str() );
1015  ss.str("");
1016 
1017  debugFile << name << " :" << endl;
1018  debugFile << endl;
1019  const Array<int>& row = conn.getRow();
1020  const Array<int>& col = conn.getCol();
1021  for ( int i = 0; i < row.getLength()-1; i++ ){
1022  debugFile << " i = " << i << ", ";
1023  for ( int j = row[i]; j < row[i+1]; j++ )
1024  debugFile << col[j] << " ";
1025  debugFile << endl;
1026  }
1027  debugFile << endl;
1028  }
1029 #endif
1030 }
void markIntersections(Mesh &fluidMesh, AABB &sMeshesAABB)
Definition: IBManager.cpp:203
const CRConnectivity & getAllFaceNodes() const
Definition: Mesh.cpp:368
const FaceGroupList & getBoundaryFaceGroups() const
Definition: Mesh.h:187
const Array< int > & getCol() const
int getCount(const int i) const
const Array< int > & getRow() const
shared_ptr< FaceGroup > FaceGroupPtr
Definition: Mesh.h:46
int getSelfCount() const
Definition: StorageSite.h:40
const StorageSite & getIBFaces() const
Definition: Mesh.h:111
Field coordinate
Definition: GeomFields.h:19
vector< int > neighbors
Definition: IBManager.h:33
void addFluidNeighbors(set< int > &neighbors, const CRConnectivity &cellCells, const Array< int > &ibType)
Definition: IBManager.cpp:575
void CRConnectivityPrintFile(const CRConnectivity &conn, const string &name, const int procID) const
Definition: IBManager.cpp:1006
void createSolidInterpolationStencil(Mesh &mesh, KSearchTree &IBFacesTree, vector< NearestCell > &nearest)
Definition: IBManager.cpp:844
Definition: Mesh.h:28
double distanceSquared
Definition: IBManager.h:32
int fluidNeighborsPerIBFace
Definition: IBManager.h:70
int markSolid(Mesh &fluidMesh)
Definition: IBManager.cpp:380
bool hasIntersectionWithTriangle(Vec3D a, Vec3D b, Vec3D c)
Definition: AABB.cpp:81
const Array< int > & getIBFaceList() const
Definition: Mesh.cpp:686
Definition: Mesh.h:49
double max(double x, double y)
Definition: Octree.cpp:18
int markFluid(Mesh &fluidMesh)
Definition: IBManager.cpp:327
void update()
Definition: IBManager.cpp:32
void setCount(const int selfCount, const int nGhost=0)
Definition: StorageSite.h:42
void setConnectivity(const StorageSite &rowSite, const StorageSite &colSite, shared_ptr< CRConnectivity > conn)
Definition: Mesh.cpp:352
const Mesh * mesh
Definition: IBManager.h:30
void createIBInterpolationStencil(Mesh &mesh, KSearchTree &fluidCellsTree, KSearchTree &solidFacesTree)
Definition: IBManager.cpp:594
Field ibType
Definition: GeomFields.h:38
Array< int > IntArray
Definition: IBManager.h:62
const CRConnectivity & getAllFaceCells() const
Definition: Mesh.cpp:378
const Array< VecD3 > & getNodeCoordinates() const
Definition: Mesh.h:218
Array< int > & getLocalToGlobal()
Definition: Mesh.h:240
IBManager(GeomFields &geomFields, Mesh &solidBoundaryMesh, const MeshList &fluidMeshes)
Definition: IBManager.cpp:20
void markIBTypePlus(Mesh &fluidMesh)
Definition: IBManager.cpp:407
Definition: AABB.h:29
void setIBFaces(shared_ptr< Array< int > > faceList)
Definition: Mesh.h:290
void findNeighbors(const Vec3D &p, const int k, Array< int > &neighbors)
Definition: KSearchTree.cpp:30
const StorageSite & getFaces() const
Definition: Mesh.h:108
void createIBFaces(Mesh &fluidMesh)
Definition: IBManager.cpp:498
const CRConnectivity & getCellCells() const
Definition: Mesh.cpp:480
Field ibFaceIndex
Definition: GeomFields.h:40
const StorageSite & getCells() const
Definition: Mesh.h:109
static void clearGradientMatrix(const Mesh &mesh)
int solidNeighborsPerIBFace
Definition: IBManager.h:72
Mesh & _solidBoundaryMesh
Definition: IBManager.h:74
int getCountLevel1() const
Definition: StorageSite.h:72
int IBNeighborsPerSolidFace
Definition: IBManager.h:73
const CRConnectivity & getFaceCells(const StorageSite &site) const
Definition: Mesh.cpp:388
Definition: Array.h:14
const MeshList _fluidMeshes
Definition: IBManager.h:102
void findNearestCellForSolidFaces(Mesh &mesh, KSearchTree &fluidCellsTree, vector< NearestCell > &nearest)
Definition: IBManager.cpp:759
bool isShell() const
Definition: Mesh.h:323
const CRConnectivity & getCellCells2() const
Definition: Mesh.cpp:495
int getCount() const
Definition: StorageSite.h:39
GeomFields & _geomFields
Definition: IBManager.h:101
double min(double x, double y)
Definition: Octree.cpp:23
int getDimension() const
Definition: Mesh.h:105
int fluidNeighborsPerSolidFace
Definition: IBManager.h:71
void syncLocal()
Definition: Field.cpp:334
int getID() const
Definition: Mesh.h:106
const CRConnectivity & getCellNodes() const
Definition: Mesh.cpp:426
vector< Mesh * > MeshList
Definition: Mesh.h:439
StorageSite site
Definition: Mesh.h:40
void insert(const Vec3D &v, const int n)
Definition: KSearchTree.cpp:23
int getLength() const
Definition: Array.h:87
T mag2(const Vector< T, 3 > &a)
Definition: Vector.h:267