void CompressFile ( FILE *input, BFILE *output) { int i; int c; int look_ahead_bytes; int current_pos; int replace_count; int match_len; int match_pos; current_pos = 1; for ( i = 0; i < LOOK_AHEAD_SIZE; i++) { if ( (c = getc (input)) == EOF ) break; window [current_pos + i] = (uchar) c; } look_ahead_bytes = i; InitTree (current_pos); match_len = 0; match_pos = 0; while (look_ahead_bytes > 0) { if (match_len > look_ahead_bytes) match_len = look_ahead_bytes; if (match_len <= BREAK_EVEN) { replace_count = 1; WriteBit ( output, 1); WriteBits ( output, (ulong) window [current_pos], 8); } else { WriteBit ( output, 0); WriteBits ( output, (ulong) match_pos, INDEX_BITS); WriteBits ( output, (ulong) ( match_len - (BREAK_EVEN + 1)), LENGTH_BITS); replace_count = match_len; } for ( i = 0; i < replace_count; i++) { DeleteString ( MODULO (current_pos + LOOK_AHEAD_SIZE)); if ( (c = getc (input)) == EOF ) look_ahead_bytes--; else window [MODULO (current_pos + LOOK_AHEAD_SIZE)] = (uchar) c; current_pos = MODULO (current_pos + 1); if (look_ahead_bytes) match_len = AddString ( current_pos, &match_pos); } } WriteBit ( output, 0); WriteBits ( output, (ulong) END_OF_STREAM, INDEX_BITS); }
int AddString ( int new_node, int *match_pos) { int i; int test_node; int delta; int match_len; int *child; if (new_node == END_OF_STREAM) return (0); test_node = tree [TREE_ROOT].larger_child; match_len = 0; for (;;) { for ( i = 0; i < LOOK_AHEAD_SIZE; i++) { delta = window [MODULO (new_node + i)] - window [MODULO (test_node + i)]; if (delta != 0) break; } if (i >= match_len) { match_len = i; *match_pos = test_node; if (match_len >= LOOK_AHEAD_SIZE) { ReplaceNode ( test_node, new_node); return match_len; } } if (delta >= 0) child = &tree [test_node].larger_child; else child = &tree [test_node].smaller_child; if (*child == UNUSED) { *child = new_node; tree [new_node].parent = test_node; tree [new_node].larger_child = UNUSED; tree [new_node].smaller_child = UNUSED; return match_len; } test_node = *child; } }
/* * flip_direction() * * perform the state transitions and terrain transformation for the * "look backwards/look forwards" bonus */ static void flip_direction (struct state *st) { int i, ip, in, j, t; st->direction = -st->direction; st->bonus_bright = 20; for (i=0; i < TERRAIN_LENGTH; i++) { in = st->nearest + i; MODULO(in, TERRAIN_BREADTH); ip = st->nearest - i; MODULO(ip, TERRAIN_BREADTH); for (j=0; j < TERRAIN_BREADTH; j++) { t = st->terrain[ip][j]; st->terrain[ip][j] = st->terrain[in][j]; st->terrain[in][j] = t; } } }
/* * generate_smooth (start, end) * * generate smooth terrain between i=start and i=end inclusive */ static void generate_smooth (struct state *st, int start, int end) { int i,j, ii; assert (start < end); for (i=start; i <= end; i++) { ii = i; MODULO(ii, TERRAIN_LENGTH); for (j=0; j < TERRAIN_BREADTH; j++) { st->terrain[i][j] = STEEL_ELEVATION; } } }
void ExpandFile ( BFILE *input, FILE *output) { int i; int current_pos; int c; int match_len; int match_pos; current_pos = 1; for (;;) { if (ReadBit (input)) { c = (int) ReadBits ( input, 8); putc ( c, output); window [current_pos] = (uchar) c; current_pos = MODULO (current_pos + 1); } else { match_pos = (int) ReadBits ( input, INDEX_BITS); if (match_pos == END_OF_STREAM) break; match_len = (int) ReadBits ( input, LENGTH_BITS); match_len += BREAK_EVEN; for ( i = 0; i <= match_len; i++) { c = window [MODULO (match_pos + i)]; putc ( c, output); window [current_pos] = (uchar) c; current_pos = MODULO (current_pos + 1); } } } }
/* * generate_straight (start, end) * * zero the curvature and wideness between i=start and i=end inclusive */ static void generate_straight (struct state *st, int start, int end) { int i,j, ii; assert (start < end); for (i=start; i <= end; i++) { ii = i; MODULO(ii, TERRAIN_LENGTH); for (j=0; j < TERRAIN_BREADTH; j++) { st->xcurvature[ii] = 0; st->ycurvature[ii] = 0; st->zcurvature[ii] = 0; st->wideness[ii] = 0; } } }
double Interpolate_3D(double *f, Geometry *geometry, Stencil *st, int l, int m) { register int i, j; int index, offset1, offset2, xbase[NCC], ybase[NCC], zbase[2]; bool_t monotonic = TRUE; double value; value = 0.0; switch (st->plane) { case XY: offset1 = st->zbase[0] * geometry->Nplane; switch (input.interpolate_3D) { case LINEAR_3D: for (i = 0; i < 2; i++) { xbase[i] = MODULO(l + st->xbase[i], geometry->Nx); ybase[i] = MODULO(m + st->ybase[i], geometry->Ny); } for (j = 0; j < 2; j++) { offset2 = offset1 + ybase[j] * geometry->Nx; for (i = 0; i < 2; i++) value += f[offset2 + xbase[i]] * st->xkernel[i] * st->ykernel[j]; } break; case BICUBIC_3D: for (i = 0; i < NCC; i++) { xbase[i] = MODULO(l + st->xbase[i], geometry->Nx); ybase[i] = MODULO(m + st->ybase[i], geometry->Ny); } value = cubicconvol(f + offset1, geometry->Nx, xbase, ybase, st->xkernel, st->ykernel, monotonic); } break; case XZ: for (i = 0; i < 2; i++) xbase[i] = MODULO(l + st->xbase[i], geometry->Nx); offset1 = MODULO(m + st->ybase[0], geometry->Ny) * geometry->Nx; for (j = 0; j < 2; j++) { offset2 = offset1 + st->zbase[j] * geometry->Nplane; for (i = 0; i < 2; i++) value += f[offset2 + xbase[i]] * st->xkernel[i] * st->zkernel[j]; } break; case YZ: offset1 = MODULO(l + st->xbase[0], geometry->Nx); for (i = 0; i < 2; i++) ybase[i] = MODULO(m + st->ybase[i], geometry->Ny); for (j = 0; j < 2; j++) { offset2 = st->zbase[j] * geometry->Nplane + offset1; for (i = 0; i < 2; i++) { index = offset2 + ybase[i] * geometry->Nx; value += f[index] * st->ykernel[i] * st->zkernel[j]; } } } return value; }
/* * perspective() * * perspective map the world coordinates worldx[i][j], worldy[i][j] onto * screen coordinates xvals[t][j], yvals[t][j] */ static void perspective (struct state *st) { int i, j, jj, t=0, depth, view_pos; int rotation_bias, r; double xc=0.0, yc=0.0, zc=0.0; double xcc=0.0, ycc=0.0, zcc=0.0; double xx, yy; double zfactor, zf; zf = 8.0*28.0 / (double)(st->width*TERRAIN_LENGTH); if (st->be_wormy) zf *= 3.0; depth = TERRAIN_PDIST - INTERP + st->pindex; view_pos = (st->nearest+3*TERRAIN_LENGTH/4)%TERRAIN_LENGTH; st->xoffset += - st->xcurvature[view_pos]*st->curviness/8; st->xoffset /= 2; st->yoffset += - st->ycurvature[view_pos]*st->curviness/4; st->yoffset /= 2; st->rotation_offset += (int)((st->zcurvature[view_pos]-st->zcurvature[st->nearest])*ROTS/8); st->rotation_offset /= 2; rotation_bias = st->orientation + st->spin_bonus - st->rotation_offset; if (st->bumps_flag) { if (st->be_wormy) { st->yoffset -= ((st->terrain[view_pos][TERRAIN_BREADTH/4] * st->width /(8*1600))); rotation_bias += (st->terrain[view_pos][TERRAIN_BREADTH/4+2] - st->terrain[view_pos][TERRAIN_BREADTH/4-2])/8; } else { st->yoffset -= ((st->terrain[view_pos][TERRAIN_BREADTH/4] * st->width /(2*1600))); rotation_bias += (st->terrain[view_pos][TERRAIN_BREADTH/4+2] - st->terrain[view_pos][TERRAIN_BREADTH/4-2])/16; } } MODULO(rotation_bias, ROTS); for (t=0; t < TERRAIN_LENGTH; t++) { i = st->nearest + t; MODULO(i, TERRAIN_LENGTH); xc += st->xcurvature[i]; yc += st->ycurvature[i]; zc += st->zcurvature[i]; xcc += xc; ycc += yc; zcc += zc; st->maxx[i] = st->maxy[i] = 0; st->minx[i] = st->width; st->miny[i] = st->height; } for (t=0; t < TERRAIN_LENGTH; t++) { i = st->nearest - 1 - t; MODULO(i, TERRAIN_LENGTH); zfactor = (double)depth* (12.0 - TERRAIN_LENGTH/8.0) * zf; for (j=0; j < TERRAIN_BREADTH; j++) { jj = st->direction * j; MODULO(jj, TERRAIN_BREADTH); /* jwz: not totally sure if this is right, but it avoids div0 */ if (zfactor != 0) { xx = (st->worldx[i][jj]-(st->vertigo*xcc))/zfactor; yy = (st->worldy[i][j]-(st->vertigo*ycc))/zfactor; } else { xx = 0; yy = 0; } r = rotation_bias + (int)(st->vertigo*zcc); MODULO(r, ROTS); st->xvals[t][j] = st->xoffset + (st->width>>1) + (int)(xx * st->costab[r] - yy * st->sintab[r]); st->maxx[t] = MAX(st->maxx[t], st->xvals[t][j]); st->minx[t] = MIN(st->minx[t], st->xvals[t][j]); st->yvals[t][j] = st->yoffset + st->height/2 + (int)(xx * st->sintab[r] + yy * st->costab[r]); st->maxy[t] = MAX(st->maxy[t], st->yvals[t][j]); st->miny[t] = MIN(st->miny[t], st->yvals[t][j]); } xcc -= xc; ycc -= yc; zcc -= zc; xc -= st->xcurvature[i]; yc -= st->ycurvature[i]; zc -= st->zcurvature[i]; depth -= INTERP; } }
void fillMesh(Geometry *geometry) { register int mu, k, l; enum triplet vtriplet, htriplet; enum SC_order horder, vorder; enum boundary hboundary = geometry->hboundary; int Nx = geometry->Nx, Nz = geometry->Nz, Nrays = geometry->Nrays, count, Nlongchar = 0, Nstart, Nend; double mux, muz, dx, dz, fraction; Stencil *st; LongChar *lc; if (input.Eddington) return; getCPU(2, TIME_START, NULL); /* --- Allocate space for interpolation stencils -- -------------- */ geometry->stencil = (Stencil **) malloc(Nrays * sizeof(Stencil *)); for (mu = 0; mu < Nrays; mu++) { geometry->stencil[mu] = (Stencil *) malloc(Nx*Nz * sizeof(Stencil)); } /* --- If the horizontal boundary conditions are PERIODIC allocate space for possible long characteristics -- -------------- */ if (hboundary == PERIODIC) { geometry->longchar = (LongChar **) malloc(Nrays * sizeof(LongChar *)); for (mu = 0; mu < Nrays; mu++) geometry->longchar[mu] = (LongChar *) malloc(2*Nz * sizeof(LongChar)); } else geometry->longchar = NULL; horder = SC_QUADRATIC; /* --- For each direction ray go through the x-z grid and store the stencil of interpolation indices and coefficients in the Geometry structure -- -------------- */ for (mu = 0; mu < Nrays; mu++) { mux = geometry->mux[mu]; muz = geometry->muz[mu]; /* --- Distinguish between mux > 0.0, mu = 0.0, and mux < 0.0. Rays with mux > 0.0 run from right to left in the downsweep, ie. with decreasing l. -- -------------- */ if (mux > 0.0) { /* --- First evaluate the UPWIND interpolation weigths and indices for the DOWN sweep. These will be the DOWNWIND ones in the reverse (UP) sweep of the formal solution -- -------------- */ vtriplet = LOWER_TRIPLET; for (k = 1; k < Nz; k++) { dz = geometry->dz[k-1]; if (k == 1) vorder = SC_LINEAR; else vorder = SC_QUADRATIC; count = 0; if (hboundary == PERIODIC) Nend = Nx; else Nend = Nx - 1; for (l = 0; l < Nend; l++) { st = &geometry->stencil[mu][k*Nx + l]; dx = geometry->dx[l]; if (hboundary == FIXED && l == Nx-2) htriplet = LOWER_TRIPLET; else htriplet = UPPER_TRIPLET; fraction = mux*dz / (muz*dx); /* --- Characteristic intersects horizontal grid line? -- - */ if (fraction <= 1.0) { count++; setStencil(geometry, st, UPWIND, HORIZONTAL, dz/muz, fraction, l, k-1, htriplet, horder); } else { setStencil(geometry, st, UPWIND, VERTICAL, dx/mux, 1.0 - 1.0/fraction, l+1, k-1, vtriplet, vorder); } } /* --- If no horizontal intersection occurred use long characteristic, otherwise find proper starting point - */ if (geometry->longchar != NULL) { lc = &geometry->longchar[mu][DOWN*Nz + k]; if (count == 0) { lc->lstart = Nx-1; fillLongChar(geometry, mu, k, DOWN); Nlongchar++; } else { lc->Nlc = 0; lc->lstart = 0; st = &geometry->stencil[mu][k*Nx + lc->lstart]; while(st->intersect[UPWIND] == VERTICAL) { lc->lstart++; st++; } } } } /* --- Evaluate the DOWNWIND interpolation weights and indices for the DOWN sweep. These will be the UPWIND ones in the reverse (UP) sweep. -- ------------ */ vtriplet = UPPER_TRIPLET; for (k = 0; k < Nz-1; k++) { dz = geometry->dz[k]; if (k == Nz - 2) vorder = SC_LINEAR; else vorder = SC_QUADRATIC; count = 0; if (hboundary == PERIODIC) Nstart = 0; else Nstart = 1; for (l = Nstart; l < Nx; l++) { st = &geometry->stencil[mu][k*Nx + l]; if (hboundary == FIXED) { dx = geometry->dx[l-1]; if (l == 1) htriplet = UPPER_TRIPLET; else htriplet = LOWER_TRIPLET; } else { dx = geometry->dx[MODULO(l-1, Nx)]; htriplet = LOWER_TRIPLET; } fraction = mux*dz / (muz*dx); /* --- Characteristic intersects horizontal grid line? -- - */ if (fraction <= 1.0) { count++; setStencil(geometry, st, DOWNWIND, HORIZONTAL, dz/muz, 1.0 - fraction, l-1, k+1, htriplet, horder); } else { setStencil(geometry, st, DOWNWIND, VERTICAL, dx/mux, 1.0/fraction, l-1, k, vtriplet, vorder); } } /* --- If no horizontal intersection occurred use long characteristic, otherwise find proper starting point - */ if (geometry->longchar != NULL) { lc = &geometry->longchar[mu][UP*Nz + k]; if (count == 0) { lc->lstart = 0; fillLongChar(geometry, mu, k, UP); Nlongchar++; } else { lc->Nlc = 0; lc->lstart = Nx - 1; st = &geometry->stencil[mu][k*Nx + lc->lstart]; while(st->intersect[DOWNWIND] == VERTICAL) { lc->lstart--; st--; } } } } } else if (mux == 0.0) { /* --- Case for purely vertical rays -- -------------- */ for (k = 1; k < Nz; k++) { dz = geometry->dz[k-1]; for (l = 0; l < Nx; l++) { st = &geometry->stencil[mu][k*Nx + l]; setVertStencil(geometry, st, UPWIND, dz, l, k-1); } if (geometry->hboundary == PERIODIC) { lc = &geometry->longchar[mu][DOWN*Nz + k]; lc->Nlc = 0; lc->lstart = 0; } } for (k = 0; k < Nz-1; k++) { dz = geometry->dz[k]; for (l = 0; l < Nx; l++) { st = &geometry->stencil[mu][k*Nx + l]; setVertStencil(geometry, st, DOWNWIND, dz, l, k+1); } if (geometry->hboundary == PERIODIC) { lc = &geometry->longchar[mu][UP*Nz + k]; lc->Nlc = 0; lc->lstart = 0; } } } else { /* --- Rays with mux < 0.0 run from left to right in the downsweep, ie. with increasing l. First evaluate the UPWIND interpolation weigths and indices for the DOWN sweep. These will be the DOWNWIND ones in the reverse (UP) sweep of the formal solution -- -------------- */ vtriplet = LOWER_TRIPLET; for (k = 1; k < Nz; k++) { dz = geometry->dz[k-1]; if (k == 1) vorder = SC_LINEAR; else vorder = SC_QUADRATIC; count = 0; if (hboundary == PERIODIC) Nstart = 0; else Nstart = 1; for (l = Nstart; l < Nx; l++) { st = &geometry->stencil[mu][k*Nx + l]; if (hboundary == FIXED) { dx = geometry->dx[l-1]; if (l == 1) htriplet = UPPER_TRIPLET; else htriplet = LOWER_TRIPLET; } else { dx = geometry->dx[MODULO(l-1, Nx)]; htriplet = LOWER_TRIPLET; } fraction = -mux*dz / (muz*dx); /* --- Characteristic intersects horizontal grid line? -- - */ if (fraction <= 1.0) { count++; setStencil(geometry, st, UPWIND, HORIZONTAL, dz/muz, 1.0 - fraction, l-1, k-1, htriplet, horder); } else { setStencil(geometry, st, UPWIND, VERTICAL, -dx/mux, 1.0 - 1.0/fraction, l-1, k-1, vtriplet, vorder); } } /* --- If no horizontal intersection occurred use long characteristic, otherwise find proper starting point - */ if (geometry->longchar != NULL) { lc = &geometry->longchar[mu][DOWN*Nz + k]; if (count == 0) { lc->lstart = 0; fillLongChar(geometry, mu, k, DOWN); Nlongchar++; } else { lc->Nlc = 0; lc->lstart = Nx-1; st = &geometry->stencil[mu][k*Nx + lc->lstart]; while(st->intersect[UPWIND] == VERTICAL) { lc->lstart--; st--; } } } } /* --- Evaluate the DOWNWIND interpolation weights and indices for the DOWN sweep. These will be the UPWIND ones in the reverse (UP) sweep. -- ------------ */ vtriplet = UPPER_TRIPLET; for (k = 0; k < Nz-1; k++) { dz = geometry->dz[k]; if (k == Nz - 2) vorder = SC_LINEAR; else vorder = SC_QUADRATIC; count = 0; if (hboundary == PERIODIC) Nend = Nx; else Nend = Nx - 1; for (l = 0; l < Nend; l++) { st = &geometry->stencil[mu][k*Nx + l]; dx = geometry->dx[l]; if (hboundary == FIXED && l == Nx - 2) htriplet = LOWER_TRIPLET; else htriplet = UPPER_TRIPLET; fraction = -mux*dz / (muz*dx); /* --- Characteristic intersects horizontal grid line? -- - */ if (fraction <= 1.0) { count++; setStencil(geometry, st, DOWNWIND, HORIZONTAL, dz/muz, fraction, l, k+1, htriplet, horder); } else { setStencil(geometry, st, DOWNWIND, VERTICAL, -dx/mux, 1.0/fraction, l+1, k, vtriplet, vorder); } } /* --- If no horizontal intersection occurred use long characteristic, otherwise find proper starting point - */ if (geometry->longchar != NULL) { lc =&geometry->longchar[mu][UP*Nz + k]; if (count == 0) { lc->lstart = Nx-1; fillLongChar(geometry, mu, k, UP); Nlongchar++; } else { lc->Nlc = 0; lc->lstart = 0; st = &geometry->stencil[mu][k*Nx + lc->lstart]; while(st->intersect[DOWNWIND] == VERTICAL) { lc->lstart++; st++; } } } } } } sprintf(messageStr, "\n-Used %d Long Characteristics\n\n", Nlongchar); Error(MESSAGE, NULL, messageStr); getCPU(2, TIME_POLL, "Geometry"); }
void fillLongChar(Geometry *geometry, int mu, int k, enum sweep sweep) { register int l, n; enum triplet htriplet, vtriplet; enum SC_order vorder; int Nx = geometry->Nx, Nz = geometry->Nz, dl, k_upwind, count, l_intersect; double mux, muz, dx_total, dx_intersect, dz, dz_total, ds_total, ds, fraction; LongChar *lc; /* --- Fills the appropriate LongChar structure of the interpolation mesh with indices and quadratic coefficients to solve along a long characteristic when, with periodic or even boundary conditions, no shortcharacteristic intersects a horizontal grid line for a given k. -- -------------- */ lc = geometry->longchar[mu]+(sweep*Nz + k); mux = geometry->mux[mu]; muz = geometry->muz[mu]; l = lc->lstart; if (sweep == DOWN) { vtriplet = LOWER_TRIPLET; if (k == 1) vorder = SC_LINEAR; else vorder = SC_QUADRATIC; k_upwind = k-1; dz = geometry->dz[k_upwind]; if (mux >= 0.0) { htriplet = UPPER_TRIPLET; dl = 1; } else { htriplet = LOWER_TRIPLET; dl = -1; } } else { vtriplet = UPPER_TRIPLET; if (k == Nz-2) vorder = SC_LINEAR; else vorder = SC_QUADRATIC; k_upwind = k+1; dz = geometry->dz[k]; if (mux >= 0.0) { htriplet = LOWER_TRIPLET; dl = -1; } else { htriplet = UPPER_TRIPLET; dl = 1; } } /* --- Find first intersection with horizontal grid line -- ------- */ count = 0; dx_total = 0.0; dx_intersect = dz/muz * fabs(mux); if (dl > 0) { while (dx_total < dx_intersect) { dx_total += geometry->dx[l]; l = MODULO(l + 1, Nx); count++; } l = MODULO(l - 1, Nx); } else { while (dx_total < dx_intersect) { l = MODULO(l - 1, Nx); dx_total += geometry->dx[l]; count++; } } /* --- Allocate space for long characteristic indices, interpolation coefficients, and pathlength. Note: Interpolation data is stored in an array of Stencil structures so that the setStencil function can be used to determine the interpolation coefficients, and Quadr can be used to do the actual interpolation. Only the UPWIND half of each stencil is used because the long characteristic is solved only in one direction, towards the root. -- -------------- */ lc->Nlc = count; lc->stencil = (Stencil *) malloc(count * sizeof(Stencil)); /* --- Store the interpolation in the horizontal grid line -- ----- */ if (dl > 0) { fraction = 1.0 - (dx_total - dx_intersect)/geometry->dx[l]; ds = fraction * geometry->dx[l] / fabs(mux); } else { fraction = (dx_total - dx_intersect)/geometry->dx[l]; ds = (1.0 - fraction)*geometry->dx[l] / fabs(mux); } setStencil(geometry, &lc->stencil[0], UPWIND, HORIZONTAL, ds, fraction, l, k_upwind, htriplet, SC_QUADRATIC); /* --- Then segment for segment the vertical crossings -- --------- */ ds_total = 0.0; for (n = 1; n < count; n++) { ds_total += lc->stencil[n-1].ds[UPWIND]; dz_total = ds_total * muz; if (dl > 0) l_intersect = l; else l_intersect = MODULO(l + 1, Nx); l = MODULO(l - dl, Nx); ds = geometry->dx[l] / fabs(mux); if (sweep == DOWN) { fraction = dz_total / dz; setStencil(geometry, &lc->stencil[n], UPWIND, VERTICAL, ds, fraction, l_intersect, k_upwind, vtriplet, vorder); } else { fraction = 1.0 - dz_total / dz; setStencil(geometry, &lc->stencil[n], UPWIND, VERTICAL, ds, fraction, l_intersect, k, vtriplet, vorder); } } }
void setStencil(Geometry *geometry, Stencil *stencil, enum direction direction, enum intersect intersect, double ds, double fraction, int l, int k, enum triplet triplet, enum SC_order order) { const char routineName[] = "setStencil"; register int n; int Nx = geometry->Nx, index[3]; double d0, d1, d2, ds0, ds1, ds2; if (fraction < 0.0) { Error(ERROR_LEVEL_2, routineName, "Fractional index for interpolation should be > 0.0\n"); } switch (direction) { case UPWIND: break; case DOWNWIND: break; default: Error(ERROR_LEVEL_2, routineName, "Invalid direction index for Stencil"); } stencil->intersect[direction] = intersect; stencil->ds[direction] = ds; stencil->fraction[direction] = fraction; stencil->triplet[direction] = triplet; stencil->order[direction] = order; if (order == SC_LINEAR) { if (intersect == HORIZONTAL) { if (geometry->hboundary == PERIODIC) { stencil->index[direction][0] = k*Nx + MODULO(l, Nx); stencil->index[direction][1] = k*Nx + MODULO(l+1, Nx); } else { stencil->index[direction][0] = k*Nx + l; stencil->index[direction][1] = k*Nx + l+1; } } else { if (geometry->hboundary == PERIODIC) l = MODULO(l, Nx); stencil->index[direction][0] = k*Nx + l; stencil->index[direction][1] = (k+1)*Nx + l; } stencil->coeff[direction][0] = (1.0 - fraction); stencil->coeff[direction][1] = fraction; } else { if (triplet == LOWER_TRIPLET) { if (intersect == HORIZONTAL) l--; else k--; } if (intersect == HORIZONTAL) { for (n = 0; n < 3; n++) { if (geometry->hboundary == PERIODIC) index[n] = MODULO(l + n, Nx); else index[n] = l + n; stencil->index[direction][n] = k*Nx + index[n]; } ds0 = geometry->dx[index[0]]; ds1 = geometry->dx[index[1]]; } else { if (geometry->hboundary == PERIODIC) l = MODULO(l, Nx); for (n = 0; n < 3; n++) { index[n] = k + n; stencil->index[direction][n] = index[n]*Nx + l; } ds0 = geometry->dz[index[0]]; ds1 = geometry->dz[index[1]]; } ds2 = ds0 + ds1; if (triplet == UPPER_TRIPLET) { d0 = fraction * ds0; d1 = ds0 - d0; } else { d1 = -fraction * ds1; d0 = ds0 - d1; } d2 = d1 + ds1; stencil->coeff[direction][0] = d1*d2 / (ds0*ds2); stencil->coeff[direction][1] = d0*d2 / (ds0*ds1); stencil->coeff[direction][2] = -d0*d1 / (ds2*ds1); } }