Beispiel #1
0
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);
}
Beispiel #2
0
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;
		}
	}
}
Beispiel #5
0
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;
		}
	}
}
Beispiel #7
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;
	}
}
Beispiel #9
0
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");
}
Beispiel #10
0
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);
    }
  }
}
Beispiel #11
0
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);
  }
}