EXPORT void set_dual_grid( RECT_GRID *dual_gr, const RECT_GRID *gr) { int dlbuf[MAXD], dubuf[MAXD]; int i; if (dual_gr == NULL || gr == NULL) return; dual_gr->dim = gr->dim; for (i = 0; i < gr->dim; ++i) { dlbuf[i] = gr->lbuf[i] - 1; if (dlbuf[i] < 0) dlbuf[i] = 0; dubuf[i] = gr->ubuf[i] - 1; if (dubuf[i] < 0) dubuf[i] = 0; dual_gr->gmax[i] = gr->gmax[i] + 1; dual_gr->L[i] = gr->L[i] - 0.5*gr->h[i]; dual_gr->U[i] = gr->U[i] + 0.5*gr->h[i]; /*This is wrong */ dual_gr->GL[i] = gr->GL[i] - 0.5*gr->h[i]; dual_gr->GU[i] = gr->GU[i] + 0.5*gr->h[i]; } set_rect_grid(dual_gr->L,dual_gr->U,gr->GL,gr->GU,dlbuf,dubuf, dual_gr->gmax,gr->dim,&gr->Remap,dual_gr); for (i = 0; i < gr->dim; ++i) dual_gr->h[i] = gr->h[i]; } /*end set_dual_grid*/
EXPORT void i_init_remap_and_rect_grid( RECT_GRID* r_grid) { double *L = r_grid->L, *U = r_grid->U; int i, dim = r_grid->dim; const char **dnm, **Dnm, **dirs; static const char *plural[3] = { "", "s", "s"}; prompt_for_remap(dim,&Remap); dnm = Remap.dnm; Dnm = Remap.Dnm; dirs = Remap.dirs; for (i = 0; i < dim; ++i) { screen("Enter the computational limits in the " "%s direction, %sL, %sU: ",dnm[i],Dnm[i],Dnm[i]); (void) Scanf("%f %f\n",L+i,U+i); if (U[i] <= L[i]) { screen("ERROR in i_init_remap_and_rect_grid(), " "invalid computational limits L[%d] = %g, U[%d] = %g\n", i,L[i],i,U[i]); clean_up(ERROR); } } screen("Enter the number%s of grid intervals of the\n\t",plural[dim-1]); screen("computational grid in the %s direction%s: ",dirs[dim-1], plural[dim-1]); for (i = 0; i < dim; ++i) { (void) Scanf("%d",&r_grid->gmax[i]); r_grid->h[i] = (U[i] - L[i]) / r_grid->gmax[i]; } (void) Scanf("\n"); /* Grab trailing newline */ /* Set Default values for subdomain specifications */ /* correct for scalar runs */ set_rect_grid(L,U,L,U,NOBUF,NOBUF,r_grid->gmax,dim,&Remap,r_grid); Remap.area = r_grid->Remap.area; } /*end i_init_remap_and_rect_grid*/
EXPORT void zoom_rect_grid( RECT_GRID *gr1, const RECT_GRID *gr2) { double h[MAXD]; double L[MAXD], U[MAXD]; int gmax[MAXD]; int dim, i; dim = gr1->dim; for (i = 0; i < dim; ++i) { L[i] = gr2->L[i]; U[i] = gr2->U[i]; h[i] = gr1->h[i]; gmax[i] = irint((U[i] - L[i])/h[i]); } set_rect_grid(L,U,gr2->GL,gr2->GU,gr2->lbuf,gr2->ubuf,gmax,dim, &gr2->Remap,gr1); } /*end zoom_rect_grid*/
EXPORT void rotate_and_zoom_rect_grid( RECT_GRID *gr, double *L, double *U, double **Q) { double **Qi = NULL; int i, j, dim = gr->dim; static double **pc = NULL; if (pc == NULL) bi_array(&pc,MAXNCORNERS,MAXD,FLOAT); if (Q != NULL) { static double** M = NULL; if (M == NULL) bi_array(&M,MAXD,MAXD,FLOAT); Qi = M; for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) Qi[i][j] = Q[j][i]; } calculate_box(L,U,pc,Q,Qi,dim); for (i = 0; i < dim; i++) { gr->gmax[i] = irint(_scaled_separation(pc[1<<i],pc[0],gr->h,dim)); if (gr->gmax[i] < 1) gr->gmax[i] = 1; } if (Qi != NULL) { rotate_point(L,U,Qi,gr->U,dim); rotate_point(L,gr->GU,Qi,gr->GU,dim); rotate_point(L,gr->GL,Qi,gr->GL,dim); } set_rect_grid(L,gr->U,gr->GL,gr->GU,gr->lbuf,gr->ubuf,gr->gmax, dim,&gr->Remap,gr); } /*end rotate_and_zoom_rect_grid*/
EXPORT void set_remap_and_rect_grid( double *L, double *U, int *gmax, GEOMETRY_REMAP geom_remap, RECT_GRID *r_grid) { int i, dim = r_grid->dim; set_remap(dim,geom_remap,&Remap); for (i = 0; i < dim; ++i) { r_grid->L[i] = L[i]; r_grid->U[i] = U[i]; r_grid->gmax[i] = gmax[i]; r_grid->h[i] = (U[i] - L[i]) / gmax[i]; } /* Set Default values for subdomain specifications */ /* correct for scalar runs */ set_rect_grid(L,U,L,U,NOBUF,NOBUF,r_grid->gmax,dim,&Remap,r_grid); Remap.area = r_grid->Remap.area; } /*end i_init_remap_and_rect_grid*/
EXPORT PP_GRID *set_pp_grid( INIT_DATA *init, RECT_GRID *comp_glbgr) { float L[MAXD], U[MAXD], *GL, *GU; float *h = comp_glbgr->h; int lbuf[MAXD], ubuf[MAXD]; int gmax[MAXD]; int icoords[MAXD]; int i, dim = comp_glbgr->dim; int myid = pp_mynode(); static PP_GRID Pp_grid; PP_GRID *pp_grid = &Pp_grid; char s[1028]; debug_print("init_pp_grid","Entered set_pp_grid():\n"); copy_rect_grid(&pp_grid->Global_grid,comp_glbgr); pp_grid->nn = 1; for (i = 0; i < dim; ++i) { int Gmax, Pmax, k; int basic_slices, extra_slices; pp_grid->buf[i] = buffer_zones(init)[i]; Pmax = pp_grid->gmax[i] = subdomains(init)[i]; pp_grid->nn *= Pmax; uni_array(&pp_grid->dom[i],Pmax + 1,FLOAT); pp_grid->dom[i][0] = comp_glbgr->L[i]; pp_grid->dom[i][Pmax] = comp_glbgr->U[i]; Gmax = comp_glbgr->gmax[i]; basic_slices = Gmax / Pmax; extra_slices = Gmax % Pmax; for (k = 1; k < Pmax; ++k) { if (k < extra_slices) pp_grid->dom[i][k] = k*(basic_slices + 1)*h[i] + pp_grid->dom[i][0]; else pp_grid->dom[i][k] = (k*basic_slices + extra_slices)*h[i] + pp_grid->dom[i][0]; } } /* Clip rectangular grid to subdomain */ GL = pp_grid->Global_grid.L; GU = pp_grid->Global_grid.U; find_Cartesian_coordinates(myid,pp_grid,icoords); for (i = 0; i < dim; ++i) { L[i] = pp_grid->dom[i][icoords[i]]; U[i] = pp_grid->dom[i][icoords[i] + 1]; gmax[i] = irint((U[i] - L[i])/h[i]); switch (dim) /* TODO Unify 2 and 3 D */ { case 1: case 2: lbuf[i] = (icoords[i] > 0) ? pp_grid->buf[i] : 0; ubuf[i] = (icoords[i]<(pp_grid->gmax[i]-1))?pp_grid->buf[i]:0; break; case 3: lbuf[i] = pp_grid->buf[i]; ubuf[i] = pp_grid->buf[i]; break; } } set_rect_grid(L,U,GL,GU,lbuf,ubuf,gmax,dim,&comp_glbgr->Remap, &pp_grid->Zoom_grid); if (debugging("init_pp_grid")) { (void) printf("pp_grid after set_pp_grid()\n"); (void) print_PP_GRID_structure(pp_grid); } debug_print("init_pp_grid","Left i_set_pp_grid():\n"); return pp_grid; } /*end set_pp_grid*/
EXPORT void set_topological_grid( INTERFACE *intfc, RECT_GRID *input_grid) { enum { DEFAULT_GMAX = 20 }; HYPER_SURF *hs; HYPER_SURF_ELEMENT *hse; POINT *p; RECT_GRID *top_grid = &topological_grid(intfc); double *L, *U; int dim = intfc->dim; int i; static int dgmax[3] = {DEFAULT_GMAX, DEFAULT_GMAX, DEFAULT_GMAX}; if (DEBUG) (void) printf("\n\nEntered set_topological_grid()\n"); intfc->table->new_grid = YES; if (input_grid != NULL) { copy_rect_grid(top_grid,input_grid); intfc->table->fixed_grid = YES; if (DEBUG) (void) printf("Left set_topological_grid()\n\n"); return; } else intfc->table->fixed_grid = NO; /* Find Rectangle Containing INTERFACE: */ L = top_grid->L; U = top_grid->U; for (i = 0; i < dim; ++i) { L[i] = HUGE_VAL; U[i] = -HUGE_VAL; } (void) next_point(intfc,NULL,NULL,NULL); while (next_point(intfc,&p,&hse,&hs)) { for (i = 0; i < dim; ++i) { L[i] = min(L[i],Coords(p)[i]); U[i] = max(U[i],Coords(p)[i]); } } if (DEBUG) { (void) printf("Rectsolid: "); print_general_vector("L = ",L,dim,""); print_general_vector("U = ",L,dim,"\n"); } set_rect_grid(L,U,L,U,NOBUF,NOBUF,dgmax,dim,remap_info(),top_grid); if (DEBUG) (void) printf("Left set_topological_grid()\n\n"); return; } /*end set_toplogical_grid*/
EXPORT boolean adjust_top_grid_for_square( RECT_GRID *top_grid, const RECT_GRID *r_grid) { int dim; int n[MAXD]; int i, j, k; boolean square_grid; double h[MAXD]; double X[MAXD]; double sqr_tol; static const double SQR_TOL = 0.001; /* TOLERANCE */ static const int NUM_ITER = 20; /* TOLERANCE */ if (top_grid == NULL || r_grid == NULL) { (void) printf("WARNING in adjust_top_grid_for_square(), "); if (top_grid == NULL && r_grid == NULL) (void) printf("top_grid = NULL, and r_grid = NULL\n"); else if (top_grid == NULL) (void) printf("top_grid = NULL\n"); else (void) printf("r_grid = NULL\n"); return NO; } dim = top_grid->dim; sqr_tol = SQR_TOL; for (i = 0; i < dim; ++i) sqr_tol = min(sqr_tol,0.5*r_grid->h[i]); for (i = 0; i < dim; ++i) { X[i] = top_grid->U[i] - top_grid->L[i]; n[i] = top_grid->gmax[i]; h[i] = X[i]/n[i]; } square_grid = YES; for (i = 0; i < dim-1; ++i) { for (j = i+1; j < dim; ++j) { if (fabs(h[i]/h[j] - 1.0) > sqr_tol) { square_grid = NO; break; } } if (square_grid == NO) break; } if (square_grid == NO) { for (i = 0; i < dim-1; ++i) { h[i] = X[i]/n[i]; for (j = i+1; j < dim; ++j) { h[j] = X[j]/n[j]; while (h[i]/h[j] > 1.0) { if (fabs(h[i]/h[j] - 1.0) < sqr_tol) break; if (n[j] == 1) break; n[j]--; h[j] = X[j]/n[j]; } while (h[i]/h[j] < 1.0) { if (fabs(h[i]/h[j] - 1.0) < sqr_tol) break; if (n[i] == 1) break; n[i]--; h[i] = X[i]/n[i]; } } } for (k = 0; k < NUM_ITER; ++k) { for (i = 0; i < dim-1; ++i) { h[i] = X[i]/n[i]; for (j = i+1; j < dim; ++j) { h[j] = X[j]/n[j]; while (h[i]/h[j] < 1.0) { if (fabs(h[i]/h[j] - 1.0) < sqr_tol) break; ++n[j]; h[j] = X[j]/n[j]; } while (h[i]/h[j] > 1.0) { if (fabs(h[i]/h[j] - 1.0) < sqr_tol) break; ++n[i]; h[i] = X[i]/n[i]; } } } } } set_rect_grid(top_grid->L,top_grid->U,top_grid->GL,top_grid->GU, top_grid->lbuf,top_grid->ubuf,n,top_grid->dim, &r_grid->Remap,top_grid); return (square_grid == YES) ? NO : YES; } /*end adjust_top_grid_for_square*/
EXPORT void init_topological_grid( RECT_GRID *top_grid, const RECT_GRID *r_grid) { char *c; const char *dimname; static const char *blanks = " \t"; const char *fmt1,*fmt2,*fmt3; char *message; double cor_fac; int len; int i, dim = r_grid->dim; int n_ints, n_floats, gmax[3]; static const char *dimnames[] = {"one", "two", "three"}; char s[Gets_BUF_SIZE]; dimname = dimnames[dim-1]; copy_rect_grid(top_grid,r_grid); (void) adjust_top_grid_for_square(top_grid,r_grid); for (i = 0; i < dim; ++i) gmax[i] = top_grid->gmax[i]; fmt1 = "The topological grid is a grid used for the construction of " "the tracked front topology. " "It is constrained to be a square grid. " "You specify the grid in one of two ways. " "If you enter a single number, it will be used as a " "coarseness factor for the topological grid relative to the " "computational grid entered above. " "In this case the length of a topological grid block cell " "side is the nearest allowable multiple of the shortest side " "of the computational grid by the coarseness factor. "; fmt2 = "Otherwise the code will read the %s integers input for the " "number of grid cells in each coordinate direction of the " "topological grid. " "If your input values do not yield a square grid they will " "be corrected to produce a square grid. " "This correction will attempt to produce values close to those " "input, but if the input values are highly rectangular, " "the resulting values may differ considerably from those " "entered. "; fmt3 = "The default for this input option is the nearest " "square grid that matches the computational grid. " "Generally the topological grid is coarser than the " "computational grid. " "Larger coarseness factors yield coarser grids, a value one " "gives the nearest square grid to the computational grid.\n"; len = 500; uni_array(&message,len,CHAR); (void) sprintf(message,fmt1,dimname); screen_print_long_string(message); (void) sprintf(message,fmt2,dimname); screen_print_long_string(message); (void) sprintf(message,fmt3,dimname); screen_print_long_string(message); free(message); message = NULL; if (dim == 1) { screen_print_long_string( "\tBe sure to use a decimal point to " "indicate a floating point number " "if you choose to input a coarseness factor.\n"); } screen("Enter your choice (cor_fac, %s integer%s, or return)\n", dimname,(dim > 1) ? "s" : ""); screen("\t(defaults are"); for (i = 0; i < dim; ++i) screen(" %d",gmax[i]); screen("): "); (void) Gets(s); if (s[0] != '\0') { n_floats = sscan_float(s,&cor_fac); if (dim == 1) { /* * To distinguish whether the input is a * coarseness factor search for a "." in s */ if (strstr(s,".") == NULL) { n_floats = 0; cor_fac = ERROR_FLOAT; } } for (n_ints = 0, c = strtok(s,blanks); c != NULL; c = strtok(NULL,blanks), ++n_ints) { (void) sscanf(c,"%d",gmax+n_ints%dim); } if (n_ints == 2*dim) { /* There is a secret undocumemted option here. * Enter the topological grid sizes twice and the * code will use these values whether they give a square grid * or not. This makes nearest_interface_point() * invalid, but you can get what you ask for. */ set_rect_grid(top_grid->L,top_grid->U,top_grid->L,top_grid->U, NOBUF,NOBUF,gmax,dim,&r_grid->Remap,top_grid); } else if ((n_ints == 1) && (n_floats > 0)) { int imin; imin = 0; for (i = 1; i < dim; ++i) if (r_grid->h[i] < r_grid->h[imin]) imin = i; top_grid->gmax[imin] = irint(r_grid->gmax[imin]/cor_fac); if (top_grid->gmax[imin] <= 0) top_grid->gmax[imin] = 1; top_grid->h[imin] = (top_grid->U[imin] - top_grid->L[imin]) / top_grid->gmax[imin]; for (i = 0; i < dim; ++i) { double tmp_gmax; if (i == imin) continue; tmp_gmax = (top_grid->U[i] - top_grid->L[i]) / top_grid->h[imin]; top_grid->gmax[i] = (int)(tmp_gmax); } (void) adjust_top_grid_for_square(top_grid,r_grid); set_rect_grid(top_grid->L,top_grid->U,top_grid->L,top_grid->U, NOBUF,NOBUF,top_grid->gmax,dim,&r_grid->Remap,top_grid); } else if (n_ints == dim) { for (i = 0; i < dim; ++i) top_grid->gmax[i] = gmax[i]; (void) adjust_top_grid_for_square(top_grid,r_grid); set_rect_grid(top_grid->L,top_grid->U,top_grid->L,top_grid->U, NOBUF,NOBUF,top_grid->gmax,dim,&r_grid->Remap,top_grid); } else { screen("ERROR in init_topological_grid(), " "invalid input of topogical grid mesh\n"); clean_up(ERROR); } } screen("The topological mesh used is "); for (i = 0; i < dim; ++i) screen(" %d",top_grid->gmax[i]); screen("\n\n"); } /*end init_topological_grid*/
EXPORT void read_rectangular_grid( const IO_TYPE *io_type, RECT_GRID *gr, boolean bufzones, REMAP *remap) { FILE *file = io_type->file; char Line[2048]; char ss[120]; long offset; int i, c; int dim; int maxd = MAXD, size_float = FLOAT; boolean b_iput; int status; char *string; if (gr == NULL) { (void) printf("WARNING in read_rectangular_grid(), grid is null\n"); return; } zero_scalar(gr,sizeof(RECT_GRID)); gr->Remap = *remap; if (fgetstring(file,"Grid Dimension = ") == FUNCTION_FAILED) { gr->dim = 2; } else { status = fscanf(file,"%d",&dim); while ((c = getc(file)) != '\n'); if ((c = getc(file)) == '\f') /* Binary input */ { c = getc(file); if (c == 1) /*oldstyle printout*/ { size_t nbytes; (void) printf("WARNING in read_rectangular_grid(), " "old style binary IO only valid for\n" "reading from runs with same floating " "point precision and endian as output\n"); nbytes = fread((void *)gr,sizeof(RECT_GRID),1,file); return; } if (c != 0) { screen("ERROR in read_rectangular_grid(), " "Improper output format\n"); clean_up(ERROR); return; } b_iput = YES; status = fscanf(file,"%*s%*s%d%*s%*s%d",&maxd,&size_float); (void) getc(file); /* newline */ } else { b_iput = NO; (void) ungetc(c,file); } } gr->dim = dim; (void) sprintf(ss,"%10s = ",remap->Dnm[0]); if (fgetstring(file,ss) == FUNCTION_FAILED) { (void) printf("WARNING in read_rectangular_grid(), " "grid not found\n"); return; } string = fgets(Line,2046,file); /* clear end of X,Y line */ #define read_grid_float(x) \ if (b_iput) \ { \ (void) getc(file); /* get blank */ \ (void) read_binary_real_array(x,1,io_type); \ } \ else \ (void) fscan_float(file,(x)) /* Read grid endpoints */ for (i = 0; i < dim; ++i) { status = fscanf(file,"%*s%*s"); read_grid_float(gr->L+i); status = fscanf(file,"%*s%*s"); read_grid_float(gr->U+i); } /* Read grid spacings */ for (i = 0; i < dim; ++i) { status = fscanf(file,"%*s%*s"); read_grid_float(gr->h+i); status = fscanf(file,"%*s%*s%d",gr->gmax+i); } offset = ftell(file); (void) sprintf(ss," G%sL = ",remap->Dnm[0]); if (fgetstring(file,ss) == FUNCTION_FAILED) { for (i = 0; i < dim; ++i) { if (bufzones == YES) { gr->lbuf[i] = gr->ubuf[i] = 1; gr->GL[i] = gr->L[i]; gr->GU[i] = gr->U[i]; gr->VL[i] = gr->L[i] - cell_width(0,i,gr); gr->VU[i] = gr->U[i] + cell_width(gr->gmax[i]-1,i,gr); } else { gr->lbuf[i] = gr->ubuf[i] = 0; gr->GL[i] = gr->L[i]; gr->GU[i] = gr->U[i]; gr->VL[i] = gr->L[i]; gr->VU[i] = gr->U[i]; } } return; } (void) fseek(file,offset,SEEK_SET); /* Read global grid endpoints */ for (i = 0; i < dim; ++i) { status = fscanf(file,"%*s%*s"); read_grid_float(gr->GL+i); status = fscanf(file,"%*s%*s"); read_grid_float(gr->GU+i); } /* Read virtual domain endpoints */ for (i = 0; i < dim; ++i) { status = fscanf(file,"%*s%*s"); read_grid_float(gr->VL+i); status = fscanf(file,"%*s%*s"); read_grid_float(gr->VU+i); } /* Read buffer zone widths */ for (i = 0; i < dim; ++i) status = fscanf(file,"%*s%*s%d%*s%*s%d",gr->lbuf+i,gr->ubuf+i); set_rect_grid(gr->L,gr->U,gr->GL,gr->GU,gr->lbuf,gr->ubuf,gr->gmax, dim,&gr->Remap,gr); #undef read_grid_float return; } /*end read_rectangular_grid*/