HyPar  1.0
Finite-Difference Hyperbolic-Parabolic PDE Solver on Cartesian Grids
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
InitializeImmersedBoundaries.c
Go to the documentation of this file.
1 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <arrayfunctions.h>
9 #include <mathfunctions.h>
10 #include <immersedboundaries.h>
11 #include <io.h>
12 #include <mpivars.h>
13 #include <simulation_object.h>
14 
23  int nsims
24  )
25 {
26  SimulationObject* simobj = (SimulationObject*) s;
27  int n;
28 
29  for (n = 0; n < nsims; n++) {
30 
31  HyPar *solver = &(simobj[n].solver);
32  MPIVariables *mpi = &(simobj[n].mpi);
33 
34  ImmersedBoundary *ib = NULL;
35  Body3D *body = NULL;
36 
37  int stat, d, ndims = solver->ndims;
38 
39  if ((!solver->flag_ib) || (ndims != _IB_NDIMS_)) {
40  solver->ib = NULL;
41  continue;
42  }
43 
44  /* Read in immersed body from file */
45  IBReadBodySTL(&body,solver->ib_filename,mpi,&stat);
46  if (stat) {
47  if (!mpi->rank) {
48  fprintf(stderr,"Error in InitializeImmersedBoundaries(): Unable to ");
49  fprintf(stderr,"read immersed body from file %s.\n",solver->ib_filename);
50  }
51  solver->flag_ib = 0;
52  solver->ib = NULL;
53  return(1);
54  }
56 
57  /* allocate immersed boundary object and set it up */
58  ib = (ImmersedBoundary*) calloc (1, sizeof(ImmersedBoundary));
59  ib->tolerance = 1e-12;
60  ib->delta = 1e-6;
61  ib->itr_max = 500;
62  ib->body = body;
63  solver->ib = ib;
64 
65  int offset_global, offset_local,
66  *dim_local = solver->dim_local,
67  *dim_global = solver->dim_global,
68  ghosts = solver->ghosts,
69  size = dim_global[0] + dim_global[1] + dim_global[2],
70  count = 0;
71  double *Xg = (double*) calloc(size,sizeof(double));
72 
73  /* assemble the global grid on rank 0 */
74  offset_global = offset_local = 0;
75  for (d=0; d<ndims; d++) {
76  IERR MPIGatherArray1D(mpi,(mpi->rank?NULL:&Xg[offset_global]),
77  &solver->x[offset_local+ghosts],
78  mpi->is[d],mpi->ie[d],dim_local[d],0); CHECKERR(ierr);
79  offset_global += dim_global[d];
80  offset_local += dim_local [d] + 2*ghosts;
81  }
82  /* send the global grid to other ranks */
83  MPIBroadcast_double(Xg,size,0,&mpi->world);
84 
85  /* identify whether this is a 3D or "pseudo-2D" simulation */
86  IBIdentifyMode(Xg,dim_global,solver->ib);
87 
88  /* identify grid points inside the immersed body */
89  int count_inside_body = 0;
90  count = IBIdentifyBody(solver->ib,dim_global,dim_local,ghosts,mpi,Xg,solver->iblank);
91  MPISum_integer(&count_inside_body,&count,1,&mpi->world);
92  free(Xg);
93 
94  /* At ghost points corresponding to the physical boundary, extrapolate from the interior
95  (this should also work for bodies that are adjacent to physical boundaries). At interior
96  (MPI) boundaries, exchange iblank across MPI ranks.
97  */
98  int indexb[ndims], indexi[ndims], bounds[ndims], offset[ndims];
99  for (d = 0; d < ndims; d++) {
100  /* left boundary */
101  if (!mpi->ip[d]) {
102  _ArrayCopy1D_(dim_local,bounds,ndims); bounds[d] = ghosts;
103  _ArraySetValue_(offset,ndims,0); offset[d] = -ghosts;
104  int done = 0; _ArraySetValue_(indexb,ndims,0);
105  while (!done) {
106  _ArrayCopy1D_(indexb,indexi,ndims); indexi[d] = ghosts-1-indexb[d];
107  int p1; _ArrayIndex1DWO_(ndims,dim_local,indexb,offset,ghosts,p1);
108  int p2; _ArrayIndex1D_ (ndims,dim_local,indexi,ghosts,p2);
109  solver->iblank[p1] = solver->iblank[p2];
110  _ArrayIncrementIndex_(ndims,bounds,indexb,done);
111  }
112  }
113  /* right boundary */
114  if (mpi->ip[d] == mpi->iproc[d]-1) {
115  _ArrayCopy1D_(dim_local,bounds,ndims); bounds[d] = ghosts;
116  _ArraySetValue_(offset,ndims,0); offset[d] = dim_local[d];
117  int done = 0; _ArraySetValue_(indexb,ndims,0);
118  while (!done) {
119  _ArrayCopy1D_(indexb,indexi,ndims); indexi[d] = dim_local[d]-1-indexb[d];
120  int p1; _ArrayIndex1DWO_(ndims,dim_local,indexb,offset,ghosts,p1);
121  int p2; _ArrayIndex1D_ (ndims,dim_local,indexi,ghosts,p2);
122  solver->iblank[p1] = solver->iblank[p2];
123  _ArrayIncrementIndex_(ndims,bounds,indexb,done);
124  }
125  }
126  }
127  MPIExchangeBoundariesnD(ndims,1,dim_local,ghosts,mpi,solver->iblank);
128 
129  /* identify and create a list of immersed boundary points on each rank */
130  int count_boundary_points = 0;
131  count = IBIdentifyBoundary(solver->ib,mpi,dim_local,ghosts,solver->iblank);
132  MPISum_integer(&count_boundary_points,&count,1,&mpi->world);
133 
134  /* find the nearest facet for each immersed boundary point */
135  double ld = 0, xmin, xmax, ymin, ymax, zmin, zmax;
136  _GetCoordinate_(0,0 ,dim_local,ghosts,solver->x,xmin);
137  _GetCoordinate_(0,dim_local[0]-1,dim_local,ghosts,solver->x,xmax);
138  _GetCoordinate_(1,0 ,dim_local,ghosts,solver->x,ymin);
139  _GetCoordinate_(1,dim_local[1]-1,dim_local,ghosts,solver->x,ymax);
140  _GetCoordinate_(2,0 ,dim_local,ghosts,solver->x,zmin);
141  _GetCoordinate_(2,dim_local[2]-1,dim_local,ghosts,solver->x,zmax);
142  double xlen = xmax - xmin;
143  double ylen = ymax - ymin;
144  double zlen = zmax - zmin;
145  ld = max3(xlen,ylen,zlen);
146  count = IBNearestFacetNormal(solver->ib,mpi,solver->x,ld,dim_local,ghosts);
147  if (count) {
148  fprintf(stderr, "Error in InitializeImmersedBoundaries():\n");
149  fprintf(stderr, " IBNearestFacetNormal() returned with error code %d on rank %d.\n",
150  count, mpi->rank);
151  return(count);
152  }
153 
154  /* For the immersed boundary points, find the interior points for extrapolation,
155  and compute their interpolation coefficients */
156  count = IBInterpCoeffs(solver->ib,mpi,solver->x,dim_local,ghosts,solver->iblank);
157  if (count) {
158  fprintf(stderr, "Error in InitializeImmersedBoundaries():\n");
159  fprintf(stderr, " IBInterpCoeffs() returned with error code %d on rank %d.\n",
160  count, mpi->rank);
161  return(count);
162  }
163 
164  /* Create facet mapping */;
165  count = IBCreateFacetMapping(ib,mpi,solver->x,dim_local,ghosts);
166  if (count) {
167  fprintf(stderr, "Error in InitializeImmersedBoundaries():\n");
168  fprintf(stderr, " IBCreateFacetMapping() returned with error code %d on rank %d.\n",
169  count, mpi->rank);
170  return(count);
171  }
172 
173  /* Done */
174  if (!mpi->rank) {
175  double percentage;
176  printf("Immersed body read from %s:\n",solver->ib_filename);
177  if (nsims > 1) printf("For domain %d,\n", n);
178  printf(" Number of facets: %d\n Bounding box: [%3.1f,%3.1lf] X [%3.1f,%3.1lf] X [%3.1f,%3.1lf]\n",
179  body->nfacets,body->xmin,body->xmax,body->ymin,body->ymax,body->zmin,body->zmax);
180  percentage = ((double)count_inside_body)/((double)solver->npoints_global)*100.0;
181  printf(" Number of grid points inside immersed body: %d (%4.1f%%).\n",count_inside_body,percentage);
182  percentage = ((double)count_boundary_points)/((double)solver->npoints_global)*100.0;
183  printf(" Number of immersed boundary points : %d (%4.1f%%).\n",count_boundary_points,percentage);
184  printf(" Immersed body simulation mode : %s.\n", ib->mode);
185  }
186 
187  }
188 
189  return(0);
190 }
char ib_filename[_MAX_STRING_SIZE_]
Definition: hypar.h:439
int MPISum_integer(int *, int *, int, void *)
Definition: MPISum.c:16
#define _ArraySetValue_(x, size, value)
int IBInterpCoeffs(void *, void *, double *, int *, int, double *)
int IBComputeBoundingBox(Body3D *)
#define max3(a, b, c)
Definition: math_ops.h:27
int IBCreateFacetMapping(void *, void *, double *, int *, int)
int IBIdentifyBoundary(void *, void *, int *, int, double *)
Structure containing variables for immersed boundary implementation.
Structure defining a body.
int * dim_global
Definition: hypar.h:33
double * iblank
Definition: hypar.h:436
int MPIBroadcast_double(double *, int, int, void *)
Definition: MPIBroadcast.c:9
Structures and function definitions for immersed boundaries.
int IBIdentifyBody(void *, int *, int *, int, void *, double *, double *)
void * ib
Definition: hypar.h:443
#define _ArrayIncrementIndex_(N, imax, i, done)
int npoints_global
Definition: hypar.h:40
int MPIGatherArray1D(void *, double *, double *, int, int, int, int)
int InitializeImmersedBoundaries(void *, int)
#define _IB_NDIMS_
int flag_ib
Definition: hypar.h:441
int * dim_local
Definition: hypar.h:37
MPI related function definitions.
char mode[_MAX_STRING_SIZE_]
#define _GetCoordinate_(dir, i, dim, ghosts, x, coord)
Definition: basic.h:31
Function declarations for file I/O functions.
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
MPI_Comm world
int IBReadBodySTL(Body3D **, char *, void *, int *)
Definition: IBReadBodySTL.c:21
Contains function definitions for common mathematical functions.
#define _ArrayIndex1DWO_(N, imax, i, offset, ghost, index)
Simulation object.
#define _ArrayCopy1D_(x, y, size)
#define CHECKERR(ierr)
Definition: basic.h:18
int IBNearestFacetNormal(void *, void *, double *, double, int *, int)
Structure defining a simulation.
int ndims
Definition: hypar.h:26
Contains macros and function definitions for common array operations.
#define IERR
Definition: basic.h:16
int MPIExchangeBoundariesnD(int, int, int *, int, void *, double *)
Structure of MPI-related variables.
double * x
Definition: hypar.h:107
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int IBIdentifyMode(double *, int *, void *)