HyPar  1.0
Finite-Difference Hyperbolic-Parabolic PDE Solver on Cartesian Grids
InitializeImmersedBoundaries.c File Reference

Initialize the immersed boundary implementation. More...

#include <stdio.h>
#include <stdlib.h>
#include <arrayfunctions.h>
#include <mathfunctions.h>
#include <immersedboundaries.h>
#include <io.h>
#include <mpivars.h>
#include <simulation_object.h>

Go to the source code of this file.

Functions

int InitializeImmersedBoundaries (void *s, int nsims)
 

Detailed Description

Initialize the immersed boundary implementation.

Author
Debojyoti Ghosh

Definition in file InitializeImmersedBoundaries.c.

Function Documentation

◆ InitializeImmersedBoundaries()

int InitializeImmersedBoundaries ( void *  s,
int  nsims 
)

Initialize the immersed boundaries, if present.

  • Read in immersed body from STL file.
  • Allocate and set up ImmersedBoundary object.
  • Identify blanked-out grid points based on immersed body geometry.
  • Identify and make a list of immersed boundary points on each rank.
  • For each immersed boundary point, find the "nearest" facet.
Parameters
sArray of simulation objects of type SimulationObject
nsimsNumber of simulation objects

Definition at line 22 of file InitializeImmersedBoundaries.c.

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.
#define CHECKERR(ierr)
Definition: basic.h:18
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
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
int ghosts
Definition: hypar.h:52
Structure of MPI-related variables.
char mode[_MAX_STRING_SIZE_]
int IBInterpCoeffs(void *, void *, double *, int *, int, double *)
#define _ArrayCopy1D_(x, y, size)
int * dim_global
Definition: hypar.h:33
int IBIdentifyBoundary(void *, void *, int *, int, double *)