Пример #1
0
void LBInitializeBC(
                    Lattice *    lattice,
                    Problem *    problem,
                    ProblemData *problem_data)
{
  /*------------------------------------------------------------*
  * Local variables
  *------------------------------------------------------------*/

  /* Lattice variables */
  Grid  *grid = (lattice->grid);
  Vector *pressure = (lattice->pressure);
  Vector *perm = (lattice->perm);
  CharVector *cellType = (lattice->cellType);
  double time = (lattice->t);

  /* Structures */
  BCPressureData *bc_pressure_data = ProblemDataBCPressureData(problem_data);
  TimeCycleData   *time_cycle_data;
  SubgridArray   *subgrids = GridSubgrids(grid);
  GrGeomSolid    *gr_domain;

  /* Patch variables */
  double       ***values;
  double         *patch_values = NULL;
  int            *fdir;

  /* Grid parameters */
  Subgrid   *subgrid;
  int nx, ny, nz;
  int ix, iy, iz;
  int nx_v, ny_v, nz_v;

  /* Indices and counters */
  int num_patches;
  int num_phases;
  int ipatch, is, i, j, k, ival;
  int cycle_number, interval_number;
  int r;

  /* Physical variables and coefficients */
  Subvector *sub_p;
  double    *pp;
  Subvector *sub_perm;
  double    *permp;
  Subcharvector *sub_cellType;
  char      *cellTypep;
  double rho_g;

  /* Communications */
  VectorUpdateCommHandle *handle;

  /*--------------------------
   *  Initializations
   *--------------------------*/
  rho_g = ProblemGravity(problem) * RHO;
  num_patches = BCPressureDataNumPatches(bc_pressure_data);
  gr_domain = ProblemDataGrDomain(problem_data);
  num_phases = BCPressureDataNumPhases(bc_pressure_data);
  if (num_patches > 0)
  {
    time_cycle_data = BCPressureDataTimeCycleData(bc_pressure_data);
    values = ctalloc(double **, num_patches);

    for (ipatch = 0; ipatch < num_patches; ipatch++)
    {
      values[ipatch] = ctalloc(double *, SubgridArraySize(subgrids));

      cycle_number = BCPressureDataCycleNumber(bc_pressure_data, ipatch);
      interval_number = TimeCycleDataComputeIntervalNumber(problem, time,
                                                           time_cycle_data, cycle_number);

      switch (BCPressureDataType(bc_pressure_data, ipatch))
      {
        case 0:
        {
          BCPressureType0 *bc_pressure_type0;

          GeomSolid       *ref_solid;

          double z, dz2;
          double         **elevations;
          int ref_patch, iel;

          bc_pressure_type0 = (BCPressureType0*)BCPressureDataIntervalValue(
                                                                            bc_pressure_data, ipatch, interval_number);
          ref_solid = ProblemDataSolid(problem_data,
                                       BCPressureType0RefSolid(bc_pressure_type0));
          ref_patch = BCPressureType0RefPatch(bc_pressure_type0);

          /* Calculate elevations at (x,y) points on reference patch. */
          elevations = CalcElevations(ref_solid, ref_patch, subgrids, problem_data);

          ForSubgridI(is, subgrids)
          {
            /* subgrid = GridSubgrid(grid, is); */
            subgrid = SubgridArraySubgrid(subgrids, is);
            sub_p = VectorSubvector(pressure, is);
            sub_perm = VectorSubvector(perm, is);
            sub_cellType = CharVectorSubcharvector(cellType, is);

            nx = SubgridNX(subgrid);
            ny = SubgridNY(subgrid);
            nz = SubgridNZ(subgrid);

            ix = SubgridIX(subgrid);
            iy = SubgridIY(subgrid);
            iz = SubgridIZ(subgrid);

            /* RDF: assume resolution is the same in all 3 directions */
            r = SubgridRX(subgrid);

            pp = SubvectorData(sub_p);
            permp = SubvectorData(sub_perm);
            cellTypep = SubcharvectorData(sub_cellType);

            nx_v = SubvectorNX(sub_p);
            ny_v = SubvectorNY(sub_p);
            nz_v = SubvectorNZ(sub_p);

            values[ipatch][is] = patch_values;

            dz2 = RealSpaceDZ(0) / 2.0;

            GrGeomPatchLoop(i, j, k, fdir, gr_domain, ipatch,
                            r, ix, iy, iz, nx, ny, nz,
            {
              ival = SubvectorEltIndex(sub_p, i, j, k);
              iel = (i - ix) + (j - iy) * nx;
              z = RealSpaceZ(k, 0) + fdir[2] * dz2;

              pp[ival] = BCPressureType0Value(bc_pressure_type0)
                         - rho_g * (z - elevations[is][iel]);

              cellTypep[ival] = 0;
            });

            tfree(elevations[is]);
          }       /* End subgrid loop */

          tfree(elevations);
          break;
        }

        case 1:
        {
          BCPressureType1 *bc_pressure_type1;
          int num_points;
          double x, y, z, dx2, dy2, dz2;
          double unitx, unity, line_min, line_length, xy, slope;
          int ip;

          bc_pressure_type1 = (BCPressureType1*)BCPressureDataIntervalValue(bc_pressure_data, ipatch, interval_number);

          ForSubgridI(is, subgrids)
          {
            /* subgrid = GridSubgrid(grid, is); */
            subgrid = SubgridArraySubgrid(subgrids, is);
            sub_p = VectorSubvector(pressure, is);
            sub_perm = VectorSubvector(perm, is);
            sub_cellType = CharVectorSubcharvector(cellType, is);

            nx = SubgridNX(subgrid);
            ny = SubgridNY(subgrid);
            nz = SubgridNZ(subgrid);

            ix = SubgridIX(subgrid);
            iy = SubgridIY(subgrid);
            iz = SubgridIZ(subgrid);

            /* RDF: assume resolution is the same in all 3 directions */
            r = SubgridRX(subgrid);

            pp = SubvectorData(sub_p);
            permp = SubvectorData(sub_perm);
            cellTypep = SubcharvectorData(sub_cellType);

            nx_v = SubvectorNX(sub_p);
            ny_v = SubvectorNY(sub_p);
            nz_v = SubvectorNZ(sub_p);

            values[ipatch][is] = patch_values;

            dx2 = RealSpaceDX(0) / 2.0;
            dy2 = RealSpaceDY(0) / 2.0;
            dz2 = RealSpaceDZ(0) / 2.0;

            /* compute unit direction vector for piecewise linear line */
            unitx = BCPressureType1XUpper(bc_pressure_type1) - BCPressureType1XLower(bc_pressure_type1);
            unity = BCPressureType1YUpper(bc_pressure_type1) - BCPressureType1YLower(bc_pressure_type1);
            line_length = sqrt(unitx * unitx + unity * unity);
            unitx /= line_length;
            unity /= line_length;
            line_min = BCPressureType1XLower(bc_pressure_type1) * unitx
                       + BCPressureType1YLower(bc_pressure_type1) * unity;

            GrGeomPatchLoop(i, j, k, fdir, gr_domain, ipatch,
                            r, ix, iy, iz, nx, ny, nz,
            {
              ival = SubvectorEltIndex(sub_p, i, j, k);

              x = RealSpaceX(i, 0) + fdir[0] * dx2;
              y = RealSpaceY(j, 0) + fdir[1] * dy2;
              z = RealSpaceZ(k, 0) + fdir[2] * dz2;

              /* project center of BC face onto piecewise line */
              xy = (x * unitx + y * unity - line_min) / line_length;

              /* find two neighboring points */
              ip = 1;
              /* Kludge; this needs to be fixed. */
              num_points = 2;
              for (; ip < (num_points - 1); ip++)
              {
                if (xy < BCPressureType1Point(bc_pressure_type1, ip))
                  break;
              }

              /* compute the slope */
              slope = ((BCPressureType1Value(bc_pressure_type1, ip) - BCPressureType1Value(bc_pressure_type1, (ip - 1)))
                       / (BCPressureType1Point(bc_pressure_type1, ip) - BCPressureType1Point(bc_pressure_type1, (ip - 1))));

              pp[ival] = BCPressureType1Value(bc_pressure_type1, ip - 1)
                         + slope * (xy - BCPressureType1Point(
                                                              bc_pressure_type1, ip - 1))
                         - rho_g * z;

              cellTypep[ival] = 0;
            });
          }      /* End subgrid loop */
Пример #2
0
void OverlandSum(ProblemData *problem_data, 
		 Vector      *pressure,       /* Current pressure values */
		 double dt, 
		 Vector *overland_sum)
{
   GrGeomSolid *gr_domain         = ProblemDataGrDomain(problem_data);

   double       dx, dy, dz;
   int          i, j, r, is;
   int          ix, iy, iz;
   int          nx, ny;

   Subgrid     *subgrid;
   Grid        *grid              = VectorGrid(pressure);

   Vector      *slope_x           = ProblemDataTSlopeX(problem_data); 
   Vector      *slope_y           = ProblemDataTSlopeY(problem_data);
   Vector      *mannings          = ProblemDataMannings(problem_data);
   Vector      *top               = ProblemDataIndexOfDomainTop(problem_data);

   Subvector   *overland_sum_subvector;
   Subvector   *slope_x_subvector;
   Subvector   *slope_y_subvector;
   Subvector   *mannings_subvector;
   Subvector   *pressure_subvector;
   Subvector   *top_subvector;
   
   int index_overland_sum;
   int index_slope_x;
   int index_slope_y;
   int index_mannings;
   int index_pressure;
   int index_top;

   double *overland_sum_ptr;
   double *slope_x_ptr;
   double *slope_y_ptr;
   double *mannings_ptr;
   double *pressure_ptr;
   double *top_ptr;

   int ipatch;
   
   BCStruct    *bc_struct;

   BCPressureData *bc_pressure_data = ProblemDataBCPressureData(problem_data);
   int num_patches                  = BCPressureDataNumPatches(bc_pressure_data);

   bc_struct = NewBCStruct(GridSubgrids(grid), 
			   gr_domain,
			   num_patches,
			   BCPressureDataPatchIndexes(bc_pressure_data),
			   BCPressureDataBCTypes(bc_pressure_data),
			   NULL);

   if (num_patches > 0)
   {
      for (ipatch = 0; ipatch < num_patches; ipatch++)
      {
	 switch(BCPressureDataType(bc_pressure_data,ipatch))
         {
	    case 7:
	    {

	       ForSubgridI(is, GridSubgrids(grid))
	       {
	       
		  subgrid = GridSubgrid(grid, is);
		  
		  overland_sum_subvector = VectorSubvector(overland_sum, is);
		  slope_x_subvector      = VectorSubvector(slope_x, is);
		  slope_y_subvector      = VectorSubvector(slope_y, is);
		  mannings_subvector     = VectorSubvector(mannings, is);
		  pressure_subvector     = VectorSubvector(pressure, is);
		  top_subvector          = VectorSubvector(top, is);
		  
		  r = SubgridRX(subgrid);
		  
		  ix = SubgridIX(subgrid);
		  iy = SubgridIY(subgrid);
		  iz = SubgridIZ(subgrid);

		  nx = SubgridNX(subgrid);
		  ny = SubgridNY(subgrid);

		  dx = SubgridDX(subgrid);
		  dy = SubgridDY(subgrid);
		  dz = SubgridDZ(subgrid);
		  
		  overland_sum_ptr = SubvectorData(overland_sum_subvector);
		  slope_x_ptr      = SubvectorData(slope_x_subvector);
		  slope_y_ptr      = SubvectorData(slope_y_subvector);
		  mannings_ptr     = SubvectorData(mannings_subvector);
		  pressure_ptr     = SubvectorData(pressure_subvector);
		  top_ptr          = SubvectorData(top_subvector);

		  int state;
		  const int inactive = -1;
		  const int active = 1;

		  for(i = ix; i < ix + nx; i++) 
		  {
		     j = iy - 1;

		     index_top = SubvectorEltIndex(top_subvector, i, j, 0);
		     int k = (int)top_ptr[index_top];

		     if( k < 0 ) {
			state = inactive;
		     } else {
			state = active;
		     }

		     while( j < iy + ny) {
			
			if( state == inactive) {
			   index_top = SubvectorEltIndex(top_subvector, i, j, 0);
			   k = (int)top_ptr[index_top];
			   while( k < 0 && j <= iy + ny) {
			      j++;
			      index_top = SubvectorEltIndex(top_subvector, i, j, 0);
			      k = (int)top_ptr[index_top];
			   }

			   // If still in interior
			   if( j < iy + ny) {

			      if ( k >=0 ) {
				 
				 // inactive to active
				 
				 index_slope_y         = SubvectorEltIndex(slope_y_subvector, i, j, 0);
				 
				 // sloping to inactive active from active
				 if( slope_y_ptr[index_slope_y] > 0) {
				    index_pressure        = SubvectorEltIndex(pressure_subvector, i, j, k);
				    
				    if(pressure_ptr[index_pressure] > 0) 
				    {
				       index_overland_sum    = SubvectorEltIndex(overland_sum_subvector,  i, j, 0);
				       index_mannings        = SubvectorEltIndex(mannings_subvector, i, j, 0);
				       
				       overland_sum_ptr[index_overland_sum] += 
					  (sqrt( fabs(slope_y_ptr[index_slope_y]) ) / mannings_ptr[index_mannings] ) *
					  pow(pressure_ptr[index_pressure], 5.0 / 3.0) * dx * dt;
				    }
				 }
			      }

			      state = active;
			   }

			} else {
			   index_top = SubvectorEltIndex(top_subvector, i, j+1, 0);
			   k = (int)top_ptr[index_top];
			   while( k >= 0 && j <= iy + ny) {
			      j++;
			      index_top = SubvectorEltIndex(top_subvector, i, j+1, 0);
			      k = (int)top_ptr[index_top];
			   }

			   // If still in interior
			   if( j < iy + ny) {

			      index_top     = SubvectorEltIndex(top_subvector, i, j, 0);
			      k = (int)top_ptr[index_top];

			      // active to inactive

			      
			      index_slope_y         = SubvectorEltIndex(slope_y_subvector, i, j, 0);

			      // sloping from active to inactive
			      if( slope_y_ptr[index_slope_y] < 0) {
				 index_pressure        = SubvectorEltIndex(pressure_subvector, i, j, k);

				 if(pressure_ptr[index_pressure] > 0) 
				 {
				    index_overland_sum    = SubvectorEltIndex(overland_sum_subvector,  i, j, 0);
				    index_mannings        = SubvectorEltIndex(mannings_subvector, i, j, 0);
				    
				    overland_sum_ptr[index_overland_sum] += 
				    (sqrt( fabs(slope_y_ptr[index_slope_y]) ) / mannings_ptr[index_mannings] ) *
				       pow(pressure_ptr[index_pressure], 5.0 / 3.0) * dx * dt;
				 }
			      }
			   }

			   state = inactive;
			}
			j++;
		     }
		  }

#if 0
		  for(i = ix; i < ix + nx; i++) 
		  {
		     for(j = iy; j < iy + ny; j++) 
		     {
			index_top             = SubvectorEltIndex(top_subvector, i, j, 0);

			int k = (int)top_ptr[index_top];
			if ( !(k < 0)) 
			{
			   /*
			     Compute runnoff if slope is running off of active region
			   */
			   index_overland_sum    = SubvectorEltIndex(overland_sum_subvector,  i, j, 0);
			   index_slope_x         = SubvectorEltIndex(slope_x_subvector, i, j, 0);
			   index_slope_y         = SubvectorEltIndex(slope_y_subvector, i, j, 0);
			   index_mannings        = SubvectorEltIndex(mannings_subvector, i, j, 0);
			   index_pressure        = SubvectorEltIndex(pressure_subvector, i, j, k);

			   if( slope_y_ptr[index_slope_y] > 0 ) 
			   {
			      if(pressure_ptr[index_pressure] > 0) 
			      {
				 overland_sum_ptr[index_overland_sum] += 
				    (sqrt( fabs(slope_y_ptr[index_slope_y]) ) / mannings_ptr[index_mannings] ) *
				    pow(pressure_ptr[index_pressure], 5.0 / 3.0) * dx * dt;
			      }
			   }
			   
			   /*
			     Loop until going back outside of active area 
			   */
			   while( (j + 1 < iy + ny) && !(top_ptr[SubvectorEltIndex(top_subvector, i, j+1, 0)] < 0) ) 
			   {
			      j++;
			   }
			   
			   /* 
			      Found either domain boundary or outside of active area.
			      Compute runnoff if slope is running off of active region.
			   */

			   index_top             = SubvectorEltIndex(top_subvector, i, j, 0);
			   k = (int)top_ptr[index_top];
			   index_overland_sum    = SubvectorEltIndex(overland_sum_subvector,  i, j, 0);
			   index_slope_x         = SubvectorEltIndex(slope_x_subvector, i, j, 0);
			   index_slope_y         = SubvectorEltIndex(slope_y_subvector, i, j, 0);
			   index_mannings        = SubvectorEltIndex(mannings_subvector, i, j, 0);
			   index_pressure        = SubvectorEltIndex(pressure_subvector, i, j, k);

			   if( slope_y_ptr[index_slope_y] < 0 ) 
			   {
			      if(pressure_ptr[index_pressure] > 0) 
			      {

				 overland_sum_ptr[index_overland_sum] += 
				    (sqrt( fabs(slope_y_ptr[index_slope_y]) ) / mannings_ptr[index_mannings] ) *
				    pow(pressure_ptr[index_pressure], 5.0 / 3.0) * dx * dt;
			      }
			   }
			}
		     }
		  }
#endif


		  for(j = iy; j < iy + ny; j++) 
		  {
		     i = ix - 1;

		     index_top = SubvectorEltIndex(top_subvector, i, j, 0);
		     int k = (int)top_ptr[index_top];

		     if( k < 0 ) {
			state = inactive;
		     } else {
			state = active;
		     }

		     while( i < ix + nx) {
			
			if( state == inactive) {
			   index_top = SubvectorEltIndex(top_subvector, i, j, 0);
			   k = (int)top_ptr[index_top];
			   while( k < 0 && i <= ix + nx) {
			      i++;
			      index_top = SubvectorEltIndex(top_subvector, i, j, 0);
			      k = (int)top_ptr[index_top];
			   }

			   // If still in interior
			   if( i < ix + nx) {

			      if ( k >=0 ) {
				 
				 // inactive to active
				 
				 index_slope_x         = SubvectorEltIndex(slope_x_subvector, i, j, 0);
				 
				 // sloping to inactive active from active
				 if( slope_x_ptr[index_slope_x] > 0) {
				    index_pressure        = SubvectorEltIndex(pressure_subvector, i, j, k);
				    
				    if(pressure_ptr[index_pressure] > 0) 
				    {
				       index_overland_sum    = SubvectorEltIndex(overland_sum_subvector,  i, j, 0);
				       index_mannings        = SubvectorEltIndex(mannings_subvector, i, j, 0);
				       
				       overland_sum_ptr[index_overland_sum] += 
					  (sqrt( fabs(slope_x_ptr[index_slope_x]) ) / mannings_ptr[index_mannings] ) *
					  pow(pressure_ptr[index_pressure], 5.0 / 3.0) * dy * dt;
				    }
				 }
			      }

			      state = active;
			   }

			} else {
			   index_top = SubvectorEltIndex(top_subvector, i+1, j, 0);
			   k = (int)top_ptr[index_top];
			   while( k >= 0 && i <= ix + nx) {
			      i++;
			      index_top = SubvectorEltIndex(top_subvector, i+1, j, 0);
			      k = (int)top_ptr[index_top];
			   }

			   // If still in interior
			   if( i < ix + nx) {

			      index_top     = SubvectorEltIndex(top_subvector, i, j, 0);
			      k = (int)top_ptr[index_top];

			      // active to inactive
			      index_slope_x         = SubvectorEltIndex(slope_x_subvector, i, j, 0);

			      // sloping from active to inactive
			      if( slope_x_ptr[index_slope_x] < 0) {
				 index_pressure        = SubvectorEltIndex(pressure_subvector, i, j, k);

				 if(pressure_ptr[index_pressure] > 0) 
				 {
				    index_overland_sum    = SubvectorEltIndex(overland_sum_subvector,  i, j, 0);
				    index_mannings        = SubvectorEltIndex(mannings_subvector, i, j, 0);
				    
				    overland_sum_ptr[index_overland_sum] += 
				    (sqrt( fabs(slope_x_ptr[index_slope_x]) ) / mannings_ptr[index_mannings] ) *
				       pow(pressure_ptr[index_pressure], 5.0 / 3.0) * dy * dt;
				 }
			      }
			   }

			   state = inactive;
			}
			i++;
		     }
		  }

#if 0

		  for(j = iy; j < iy + ny; j++) 
		  {
		     for(i = ix; i < ix + nx; i++) 
		     {
			
			index_top             = SubvectorEltIndex(top_subvector, i, j, 0);

			int k = (int)top_ptr[index_top];
			if ( !(k < 0)) 
			{

			   /*
			     Compute runnoff if slope is running off of active region
			   */
			   index_overland_sum    = SubvectorEltIndex(overland_sum_subvector,  i, j, 0);
			   index_slope_x         = SubvectorEltIndex(slope_x_subvector, i, j, 0);
			   index_slope_y         = SubvectorEltIndex(slope_y_subvector, i, j, 0);
			   index_mannings        = SubvectorEltIndex(mannings_subvector, i, j, 0);
			   index_pressure        = SubvectorEltIndex(pressure_subvector, i, j, k);

			   if( slope_x_ptr[index_slope_x] > 0 ) 
			   {
			      if(pressure_ptr[index_pressure] > 0) 
			      {
				 overland_sum_ptr[index_overland_sum] += 
				    (sqrt( fabs(slope_x_ptr[index_slope_y]) ) / mannings_ptr[index_mannings] ) *
				    pow(pressure_ptr[index_pressure], 5.0 / 3.0) * dy * dt;
			      }
			   }
			   
			   /*
			     Loop until going back outside of active area 
			   */
			   while( (i + 1 < ix + nx) && !(top_ptr[SubvectorEltIndex(top_subvector, i+1, j, 0)] < 0) ) 
			   {
			      i++;
			   }
			   
			   /* 
			      Found either domain boundary or outside of active area.
			      Compute runnoff if slope is running off of active region.
			   */
			   index_top             = SubvectorEltIndex(top_subvector, i, j, 0);
			   k = (int)top_ptr[index_top];
			   index_overland_sum    = SubvectorEltIndex(overland_sum_subvector,  i, j, 0);
			   index_slope_x         = SubvectorEltIndex(slope_x_subvector, i, j, 0);
			   index_slope_y         = SubvectorEltIndex(slope_y_subvector, i, j, 0);
			   index_mannings        = SubvectorEltIndex(mannings_subvector, i, j, 0);
			   index_pressure        = SubvectorEltIndex(pressure_subvector, i, j, k);

			   if( slope_x_ptr[index_slope_x] < 0 ) 
			   {
			      if(pressure_ptr[index_pressure] > 0) 
			      {
				 overland_sum_ptr[index_overland_sum] += 
				    (sqrt( fabs(slope_x_ptr[index_slope_x]) ) / mannings_ptr[index_mannings] ) *
				    pow(pressure_ptr[index_pressure], 5.0 / 3.0) * dy * dt;
			      }
			   }
			}
		     }
		  }
#endif


	       }
	    }
	 }
      }
   }
Пример #3
0
void ComputeTop(Problem *    problem,      /* General problem information */
                ProblemData *problem_data  /* Contains geometry information for the problem */
                )
{
  GrGeomSolid   *gr_solid = ProblemDataGrDomain(problem_data);
  Vector        *top = ProblemDataIndexOfDomainTop(problem_data);
  Vector        *perm_x = ProblemDataPermeabilityX(problem_data);

  Grid          *grid2d = VectorGrid(top);
  SubgridArray  *grid2d_subgrids = GridSubgrids(grid2d);

  /* use perm grid as top is 2D and want to loop over Z */
  Grid          *grid3d = VectorGrid(perm_x);
  SubgridArray  *grid3d_subgrids = GridSubgrids(grid3d);


  double *top_data;
  int index;

  VectorUpdateCommHandle   *handle;

  (void)problem;

  InitVectorAll(top, -1);
//   PFVConstInit(-1, top);

  int is;
  ForSubgridI(is, grid3d_subgrids)
  {
    Subgrid       *grid2d_subgrid = SubgridArraySubgrid(grid2d_subgrids, is);
    Subgrid       *grid3d_subgrid = SubgridArraySubgrid(grid3d_subgrids, is);

    Subvector     *top_subvector = VectorSubvector(top, is);

    int grid3d_ix = SubgridIX(grid3d_subgrid);
    int grid3d_iy = SubgridIY(grid3d_subgrid);
    int grid3d_iz = SubgridIZ(grid3d_subgrid);

    int grid2d_iz = SubgridIZ(grid2d_subgrid);

    int grid3d_nx = SubgridNX(grid3d_subgrid);
    int grid3d_ny = SubgridNY(grid3d_subgrid);
    int grid3d_nz = SubgridNZ(grid3d_subgrid);

    int grid3d_r = SubgridRX(grid3d_subgrid);

    top_data = SubvectorData(top_subvector);

    int i, j, k;
    GrGeomInLoop(i, j, k,
                 gr_solid, grid3d_r,
                 grid3d_ix, grid3d_iy, grid3d_iz,
                 grid3d_nx, grid3d_ny, grid3d_nz,
    {
      index = SubvectorEltIndex(top_subvector, i, j, grid2d_iz);

      if (top_data[index] < k)
      {
        top_data[index] = k;
      }
    });