HyPar  1.0
Finite-Difference Hyperbolic-Parabolic PDE Solver on Cartesian Grids
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 }
#define max3(a, b, c)
Definition: math_ops.h:27
int IBIdentifyMode(double *, int *, void *)
char ib_filename[_MAX_STRING_SIZE_]
Definition: hypar.h:439
Structure defining a body.
#define IERR
Definition: basic.h:16
Structure containing variables for immersed boundary implementation.
MPI related function definitions.
#define CHECKERR(ierr)
Definition: basic.h:18
Contains function definitions for common mathematical functions.
Structure defining a simulation.
int IBNearestFacetNormal(void *, void *, double *, double, int *, int)
int MPIExchangeBoundariesnD(int, int, int *, int, void *, double *)
void * ib
Definition: hypar.h:443
Simulation object.
int flag_ib
Definition: hypar.h:441
double * iblank
Definition: hypar.h:436
double * x
Definition: hypar.h:107
int IBCreateFacetMapping(void *, void *, double *, int *, int)
int ndims
Definition: hypar.h:26
int MPISum_integer(int *, int *, int, void *)
Definition: MPISum.c:16
int MPIBroadcast_double(double *, int, int, void *)
Definition: MPIBroadcast.c:9
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int MPIGatherArray1D(void *, double *, double *, int, int, int, int)
int npoints_global
Definition: hypar.h:40
MPI_Comm world
#define _ArrayIndex1D_(N, imax, i, ghost, index)
#define _ArrayIndex1DWO_(N, imax, i, offset, ghost, index)
#define _ArraySetValue_(x, size, value)
int * dim_local
Definition: hypar.h:37
int IBReadBodySTL(Body3D **, char *, void *, int *)
Definition: IBReadBodySTL.c:21
#define _IB_NDIMS_
int IBIdentifyBody(void *, int *, int *, int, void *, double *, double *)
#define _ArrayIncrementIndex_(N, imax, i, done)
int IBComputeBoundingBox(Body3D *)
#define _GetCoordinate_(dir, i, dim, ghosts, x, coord)
Definition: basic.h:31
Structures and function definitions for immersed boundaries.
int InitializeImmersedBoundaries(void *s, int nsims)
int ghosts
Definition: hypar.h:52
Structure of MPI-related variables.
char mode[_MAX_STRING_SIZE_]
int IBInterpCoeffs(void *, void *, double *, int *, int, double *)
Function declarations for file I/O functions.
#define _ArrayCopy1D_(x, y, size)
Contains macros and function definitions for common array operations.
int * dim_global
Definition: hypar.h:33
int IBIdentifyBoundary(void *, void *, int *, int, double *)