Esempio n. 1
0
void 
extract_elem_vec(const double sol_vec[],
		 const int    ev_indx,
		 const int    var_no,
		 double ***gvec_elem,
		 const Exo_DB *exo )
     
  /***************************************************
   *
   * This function puts the element values of the selected variable
   * into a global solution vector which contains all the elements,
   *
   * Now this is set up to be at least compatible w/ parallel computing.
   * We actually load the nodal vector for the current processor only.
   *
   *
   * Written by: Randy Lober  13 August 1998
   *
   * Revised: 
   *
   ***************************************************/
{
  int eb_index;
  int mn, e_start, e_end, ielem, ielem_type, num_local_nodes;
  int ielem_dim, iconnect_ptr, var, ktype, i, I, index;
  int found_quantity;

  for ( eb_index=0; eb_index < exo->num_elem_blocks; eb_index++ ) {

    mn = Matilda[eb_index];
    pd = pd_glob[mn];

    /* 
     * Not all element variables exist in all element blocks.
     * Thus, create_truth_table() didn't malloc all 
     * spots in gvec_elem. For those cases, just skip the 
     * calculation below
     */
    if (gvec_elem[eb_index][ev_indx] == NULL) {
      continue;
    }

    /* 
     * Assign local pointer pd to appropriate material
     */

    e_start = exo->eb_ptr[eb_index];
    e_end   = exo->eb_ptr[eb_index+1];
      
    for (ielem = e_start; ielem < e_end; ielem++) {

      ielem_type      = Elem_Type(exo, ielem); /* func defd in el_geom.h */
      num_local_nodes = elem_info(NNODES, ielem_type);
      ielem_dim       = elem_info(NDIM, ielem_type);
      iconnect_ptr    = Proc_Connect_Ptr[ielem]; /* find ptr to beginning */
      /* of this element's */
      /* connectivity list */
      var   = var_no;
      ktype = 0;

      /* We're looking at a nodal quantity that should be defined at only 1 
	 node of this element (aka, the pressure value off the hanging center
	 node). If we find it at more than 1 node, we have a serious problem
	 so we're leaving. If we don't find any values, we set the element
	 value to 0. RRl */
      found_quantity = FALSE;
      /* Only do this for elements with a haning center node, otherwise the
	 extraction of the quantity can be ambiguous for non-regular grid models */
      if (ielem_type == BIQUAD_QUAD ||
	  ielem_type == TRIQUAD_HEX ||
	  ielem_type == C_BILINEAR_QUAD ||
	  ielem_type == C_TRILINEAR_HEX ) {
	for (i = 0; i < num_local_nodes; i++) {
	  I     = Proc_Elem_Connect[iconnect_ptr + i];
	  /* NOTE: here, the element variables (such as PRESSURE) are being
	     extracted from the solution vector coming off of the hanging
	     interior nodes, or a given specified node for such a quantity.
	     There should never be more than one of this quantity defined
	     per element, or we have a problem treating it as an element
	     variable. Hence the found_quantity check.                       */
	  index = Index_Solution(I, var, ktype, 0, mn);
	  if (index != -1) {
	    /* This should be the one node that has our value - set the element
	       value to this */
	    gvec_elem[eb_index][ev_indx][ielem - e_start] = sol_vec[index];
	    if (found_quantity == TRUE) {
	      fprintf(stderr,
		      "Warning: Too many nodes returning quantities for element variable %s (%s) - may not be accurate\n",
		      Exo_Var_Names[var].name2,
		      Exo_Var_Names[var].name1 );
	      exit (-1);
	    }
	    found_quantity = TRUE;
	  }
	}
      }
      if (found_quantity == FALSE) {
	gvec_elem[eb_index][ev_indx][ielem - e_start] = 0.;   
	/* Field variable is zero where it
	 * is not defined.                 */
      }
#ifdef RRLOBER
      if (found_quantity == FALSE) {
	printf(" No quantity found for variable %s (%s), element %d (%d)\n",
	       Exo_Var_Names[var].name2, Exo_Var_Names[var].name1,
	       ielem, ielem - e_start );
      }
#endif
    }
  }
  return;
}
Esempio n. 2
0
void 
sum_total_stress(double sol_vec[],
		 int    var_no,
		 int    k,
		 double nodal_vec[],
		 Exo_DB *exo)

  /*********************************************************************
   *
   * This function gets the nodal stress values for each mode
   * and sums them into a total stress tensor which contains all the
   * mesh nodes, and interpolates the mid-side and centroid values of 
   * all variables with Q1 interpolation on a
   * 9-NODE mesh and interpolates to find their values at the mid-side
   * nodes and at the centroid
   *
   * Now this is set up to be at least compatible w/ parallel computing.
   * We actually load the nodal vector for the current processor only.
   *
   ********************************************************************/
{
  int eb_index;
  int mn, e_start, e_end, ielem, ielem_type, ip_total, num_local_nodes;
  int ielem_dim, iconnect_ptr, var, ktype, i, I, index, ileft, Ileft;

  int iright, Iright;
  int mode;
  
  for (eb_index=0; eb_index<exo->num_elem_blocks; eb_index++)
    {
      mn = Matilda[eb_index];
      pd = pd_glob[mn];
      vn  = vn_glob[mn];

      /* 
       * Assign local pointer pd to appropriate material
       */
      e_start = exo->eb_ptr[eb_index];
      e_end   = exo->eb_ptr[eb_index+1];
      
      for( ielem = e_start; ielem < e_end; ielem++)
	{
	  ielem_type      = Elem_Type(exo, ielem); 
	  ip_total        = elem_info(NQUAD, ielem_type);
	                     /* number of quadrature points */
	  num_local_nodes = elem_info(NNODES, ielem_type);
                             /* number of local  basis functions */
    
	  ielem_dim       = elem_info(NDIM, ielem_type);
	  iconnect_ptr    = Proc_Connect_Ptr[ielem];
	                     /* find ptr to beginning of this element's */
     			     /* connectivity list */
	  ktype = k;

	  /* 
	   * First, place the known nodal variable values for this
	   * particular variable and type into the nodal vector.
	   */
	  /* This will zero out the midside node for conjugate problems
	   * at the interface between material.
	   * It needs to be fixed! -RRR
	   */

	  for (i=0; i<num_local_nodes; i++)
	    {
	      I     = Proc_Elem_Connect[iconnect_ptr + i];
	      if(Num_Var_In_Type[var_no])
		{
		  index = Index_Solution(I, var_no, ktype, 0, mn);
		  if (index != -1)
		    {
		      nodal_vec[I] = sol_vec[index];
		      /* BEWARE: this routine depends upon the exact
		       * ordering in re_fem_const.h. Don't change
		       * it or bad things will happen!
		       */
		      var = var_no + 24;
		      for ( mode=1; mode<vn->modes; mode++)
			{
			  index = Index_Solution(I, var, ktype, 0, mn);
			  nodal_vec[I] += sol_vec[index];
			  var += 6;
			}
		    }
		  else
		    {
		      /* Field variable is zero where it is not defined. */
		      nodal_vec[I] = 0.;       
		    }
		}
	    }

	  /*
	   * Rich's famous patch up for lesserly interpolated variables.
	   * Promote quadrilateral Q1 variables to Q2 status, 8 node serendipity
	   * at least, and 9-node biquadratic at best.
	   */

	  /* RRR notes a problem here in 3D.  Should add
	   * check for TRIQUAD_QUAD elem type
	   */

	  if ( pd->v[var_no] &&
	       ( pd->i[var_no] == I_Q1 ||
                 pd->i[var_no] == I_Q1_G ||
		 pd->i[var_no] == I_Q1_GP ||
		 pd->i[var_no] == I_Q1_GN ||
                 pd->i[var_no] == I_Q1_XV ||
                 pd->i[var_no] == I_Q1_XG ||
                 pd->i[var_no] == I_Q1_HV ||
                 pd->i[var_no] == I_Q1_HG ||
                 pd->i[var_no] == I_Q1_HVG ||
                 pd->i[var_no] == I_SP) && 
	       (ielem_type ==  S_BIQUAD_QUAD || ielem_type == BIQUAD_QUAD ))
	    {
	      /* now interpolate Q1 variables onto 9-node mesh if needed */
	      for (i=4; i<8; i++)
		{
		  I = Proc_Elem_Connect[iconnect_ptr + i]; 
		  /* 
		   * Double check to insure there really are no dofs here.
		   */
		  if (Index_Solution(I,var_no,ktype, 0, mn) == -1)
		    {
		      /* 
		       * make node lie halfway between adjacent nodes 
		       * cf. PATRAN local numbering scheme for element.
		       */
		      ileft = i - 4;
		      Ileft = Proc_Elem_Connect[iconnect_ptr + ileft];
		      iright = i - 3;
		      if (iright == 4) iright = 0;
		      Iright = Proc_Elem_Connect[iconnect_ptr + iright];
		      nodal_vec[I] = 
			0.5 * (sol_vec[Index_Solution(Ileft, var_no, ktype, 0, mn)] +
			       sol_vec[Index_Solution(Iright, var_no, ktype, 0, mn)]);
		      var = var_no + 24;
		      for ( mode=1; mode<vn->modes; mode++)
			{
			  nodal_vec[I] += 
			    0.5 * (sol_vec[Index_Solution(Ileft, var, ktype, 0, mn)] +
				   sol_vec[Index_Solution(Iright, var, ktype, 0, mn)]);
			  var += 6;
			}
		    }
                  /*
		   * only interpolate centroid in BIQUAD_QUAD
                   */		  
		  if (ielem_type == BIQUAD_QUAD) 
		    {
		      /*
		       *  put centroid in center
		       *  but only if there are no dofs here
		       */
		      I = Proc_Elem_Connect[iconnect_ptr + 8];
        nodal_vec[I] = 0.;
		      if (Index_Solution(I, var_no, ktype, 0, mn) == -1)
			{
     for (ileft=0; ileft<4; ileft++)
			    {
			      Ileft = Proc_Elem_Connect[iconnect_ptr + ileft];
			      nodal_vec[I] += 0.25 * 
				sol_vec[Index_Solution(Ileft, var_no, ktype, 0, mn)];
			      var = var_no + 24;
			      for ( mode=1; mode<vn->modes; mode++)
				{
				  nodal_vec[I] += 0.25 * 
			 	    sol_vec[Index_Solution(Ileft, var, ktype, 0, mn)];
				  var += 6;
				}

			    }
			}
		    }
		}
	    }
	}
    }
  return;
} /* end of sum_total_stress */
Esempio n. 3
0
void 
extract_nodal_eb_vec(double sol_vec[], int var_no, int ktype, int matIndex,
		     int eb_index, double nodal_vec[], Exo_DB *exo, 
		     int timeDerivative, double time)

  /******************************************************************************
   *
   * extract_nodal_eb_vec:
   *
   *      This function extracts the a particular nodal variable specified
   *  by the program arguments and loads it up into a global vector.
   *  This routine only operates on one element block.
   *
   * This function puts the nodal values of the selected variable
   * into a global solution vector which contains all the mesh nodes,
   * and interpolates the mid-side and centroid values of 
   * all variables with Q1 interpolation on a
   * 9-NODE mesh and interpolates to find their values at the mid-side
   * nodes and at the centroid
   *
   *  Input
   * --------
   *  sol_vec[] = Current global solution vector
   *  var_no    = Variable type to be extracted
   *  ktype     = sub_var number of the variable type to be extracted
   *  matIndex  = material index of the variable to be extracted.
   *             -1 : extract the nonspecific variable
   *             -2 : extract the first variable with var_no no
   *                  matter what material index.
   *  exo       = Exodus database structure
   *  timeDerivative = Are we extracting a time derivative? if so,
   *              then this is true. If not, false.
   *
   * Output
   * -------
   *  nodal_vec[] = nodal vector which receives the value
   *                of the extracted vector. (length number
   *                of nodes)
   *********************************************************************************/
{
  int mn, e_start, e_end, ielem, ielem_type, ip_total, num_local_nodes;
  int ielem_dim, iconnect_ptr, i, I, index;
  int ileft, Ileft, iright, Iright, midside;
  int lastSpeciesSum, iDof, j;
  MATRL_PROP_STRUCT *matrl;
  double rho;
#ifdef DEBUG_HKM
  int nunks, interpType;
#endif

  /*
   * Find out the material number, mn, from the element block index
   */
  mn = Matilda[eb_index];
  matrl = mp_glob[mn];

  /* 
   * Assign local pointer pd to appropriate material
   */
  pd = pd_glob[mn];

  /*
   *  Check for the existence of a special case for the sum of
   *  the last species constraint condition
   */
  lastSpeciesSum = FALSE;
  if (var_no == MASS_FRACTION) {
    if (matrl->Num_Species_Eqn < matrl->Num_Species) {
      if (ktype == matrl->Num_Species - 1) lastSpeciesSum = TRUE;
    }
  }

  /*
   *  Found out the beginning element number and ending element number
   *  from the element block index
   */
  e_start =  exo->eb_ptr[eb_index];
  e_end   =  exo->eb_ptr[eb_index+1];

  /*
   *  Loop over elements in the element block
   */
  for (ielem = e_start; ielem < e_end; ielem++) {

    /*
     *  Get the element type for this element -> Isn't this the
     *  same for all elements in the element block?
     *  
     */
    ielem_type      = Elem_Type(exo, ielem);

    /*
     *  Get the total number of quadrature points
     */
    ip_total        = elem_info(NQUAD, ielem_type); 

    /*
     *  Get the dimensionality of the elements in the element block
     */
    ielem_dim       = elem_info(NDIM, ielem_type);

    /*
     * Number of local nodes in the element
     */
    num_local_nodes = elem_info(NNODES, ielem_type);

    /*
     *  find ptr to beginning of this element's connectivity list 
     *
     */
    iconnect_ptr = Proc_Connect_Ptr[ielem]; 

    /* 
     * First, place the known nodal variable values for this
     * particular variable and type into the nodal vector.
     *
     * This will zero out the midside node for conjugate problems
     * at the interface between material.
     * It needs to be fixed! -RRR
     *
     *  The field variable is zero where it is not defined
     */

    for (i = 0; i < num_local_nodes; i++) {
      I = Proc_Elem_Connect[iconnect_ptr + i];
      iDof = 0;
      /*
       * HKM -> Special compatibility section
       */
#ifdef DEBUG_HKM
      interpType = pd_glob[mn]->i[var_no];
      nunks = node_info(i, ielem_type, var_no, I);
      if (nunks > 1) {
	if (interpType == I_P0 || interpType == I_P1) {
	} else {
	  if (((exo->eb_id[eb_index] + 1) % 2) == 0) {
	    iDof = 0;
	  } else {
	    iDof = 1;
	  }
	}
      }
#endif
      if (lastSpeciesSum) {
	index = Index_Solution(I, var_no, 0, iDof, matIndex);
	if (index != -1) {
	  nodal_vec[I] = 0.0;
	  for (j = 0; j < matrl->Num_Species_Eqn; j++) {
	    index = Index_Solution(I, var_no, j, iDof, matIndex);
	    nodal_vec[I] -= sol_vec[index];
	  }
	  switch (matrl->Species_Var_Type) {
	  case SPECIES_CONCENTRATION:
	      if (matrl->DensityModel == DENSITY_CONSTANT_LAST_CONC) {
		nodal_vec[I] = matrl->u_density[0];
	      } else {
		rho = calc_concentration(matrl, FALSE, NULL);
		nodal_vec[I] += rho;
	      }
	      break;
	  case SPECIES_DENSITY:
	      rho = calc_density(matrl, FALSE, NULL, time);
	      nodal_vec[I] += rho;
	      break;
	  default:
	      if (!timeDerivative) {
		nodal_vec[I] += 1.0;
	      }
	      break;
	  }
	}
      } else {
	index = Index_Solution(I, var_no, ktype, iDof, matIndex);
	if (index != -1) {
	  nodal_vec[I] = sol_vec[index];
	} 
      }
    }

    /*
     * Rich's famous patch up for lesserly interpolated variables.
     * Promote quadrilateral Q1 variables to Q2 status, 8 node serendipity
     * at least, and 9-node biquadratic at best.
     */
    /* RRR notes a problem here in 3D. 
     *     Should add check for TRIQUAD_QUAD elem type */

    midside = 0;  
    if (((pd->i[var_no] == I_Q1)   ||
         (pd->i[var_no] == I_Q1_G)   ||
	 (pd->i[var_no] == I_Q1_GP)   ||
	 (pd->i[var_no] == I_Q1_GN)   ||
         (pd->i[var_no] == I_Q1_XV)   ||
         (pd->i[var_no] == I_Q1_XG)   ||
         (pd->i[var_no] == I_Q1_HV)   ||
         (pd->i[var_no] == I_Q1_HG)   ||
         (pd->i[var_no] == I_Q1_HVG)   ||
	 (pd->i[var_no] == I_Q1_D) ||
	 (pd->i[var_no] == I_SP)      )
	&& ((ielem_type == S_BIQUAD_QUAD)  ||
	    (ielem_type == BIQUAD_QUAD)         )) {
      midside = 1;
    }
  
    if (midside) {
      /* now interpolate Q1 variables onto 9-node mesh if needed */
      for (i = 4; i < 8; i++) {
	I = Proc_Elem_Connect[iconnect_ptr + i]; 
	/* 
	 * Double check to insure there really are no dofs here.
	 */
	if (Index_Solution(I, var_no, ktype, 0, matIndex) == -1) {
	  /* 
	   * make node lie halfway between adjacent nodes 
	   * cf. PATRAN local numbering scheme for element.
	   */
	  ileft = i - 4;
	  Ileft = Proc_Elem_Connect[iconnect_ptr + ileft];
	  iright = i - 3;
	  if (iright == 4) iright = 0;
	  Iright = Proc_Elem_Connect[iconnect_ptr + iright];
	  nodal_vec[I] = 
	      0.5 * (nodal_vec[Ileft] + nodal_vec[Iright]);
#if 0
          if ((pd->i[var_no] == I_Q1_HV)   ||
              (pd->i[var_no] == I_Q1_HG)   ||
              (pd->i[var_no] == I_Q1_HVG)) nodal_vec[I] = -1.;
#endif
	}
      }
      /*
       *  Only interpolate centroid in  BIQUAD_QUAD
       */
      if (ielem_type == BIQUAD_QUAD) {
	I = Proc_Elem_Connect[iconnect_ptr + 8];
	nodal_vec[I] = 0.0; 
	if ( (Index_Solution(I, var_no, ktype, 0, matIndex) == -1) ||
             /* for P0 jumps, overwrite jump with interpolant */
             (pd->i[var_no] == I_Q1_HV ||
              pd->i[var_no] == I_Q1_HG ||
              pd->i[var_no] == I_Q1_HVG) ) {
	  for (ileft = 0; ileft < 4; ileft++) {
	    Ileft = Proc_Elem_Connect[iconnect_ptr + ileft];
	    nodal_vec[I] += 0.25 * nodal_vec[Ileft];
	  }
#if 0
          if ((pd->i[var_no] == I_Q1_HV)   ||
              (pd->i[var_no] == I_Q1_HG)   ||
              (pd->i[var_no] == I_Q1_HVG)) nodal_vec[I] = -1.;
#endif
	}     
      }
    } /* END if (midside) */
  } /* END for (ielem = e_start; ielem < e_end; ielem++) */
  return;
}
Esempio n. 4
0
File: wr_exo.c Progetto: goma/goma
/*
 * create_truth_table() -- Test each proposed element against each element
 * block for existance and populate the truth table. This saves file
 * rewrites later (a netcdf phenom) when each variable is written sequentially
 * later.
 *
 * Created: 1998/08/19 08:17 MDT [email protected]
 */
void
create_truth_table(struct Results_Description *rd, Exo_DB *exo,
		   double ***gvec_elem )
{
  char err_msg[MAX_CHAR_IN_INPUT], if_ev;
  int   i, j, eb_indx, ev_indx, mat_num, error, check, iii;
  int	tev, found_match, ip_total;
  ELEM_BLK_STRUCT *eb_ptr;

  static const char yo[] = "create_truth_table";

  tev = 0;
  i = 0;
  exo->elem_var_tab = (int *) smalloc( (exo->num_elem_blocks*rd->nev)*sizeof(int));
  exo->truth_table_existance_key = (int *) smalloc( (V_LAST - V_FIRST)*sizeof(int));

  for ( i = 0; i < V_LAST - V_FIRST; i++ ) {
    exo->truth_table_existance_key[i] = 0;
  }

  /* This first cycle is a test to detect which potential elem variables 
     (treated as nodal in goma) exist in which block via tests below on
     whether the variables have been requested at all by the user and if
     requested, are of the appropriate integration order for conversion
     to an elem var.

     This is necessary since the array of the truth table cycles through
     the element var index fastest, and if a given element var is defined
     for one block but not another, the block in which it is undefined 
     will not know the difference between a defined variable that is 
     of the wrong interpolation order for this block, and a variable
     that is not defined at all for the problem. This first cycle scopes
     for these cases and sets up a temp array of all possible elem vars 
     model wide that must be treated (1 or 0) in the truth table. RRL */

  if_ev = FALSE;

  for ( eb_indx = 0; eb_indx < exo->num_elem_blocks; eb_indx++ ) {
    /* First test for all the potential elem vars from primary nodal vars
       for this block */
    mat_num = Matilda[eb_indx];
    if (mat_num < 0) {
      continue;
    }
    for ( j = V_FIRST; j < V_LAST; j++) {
      if ( pd_glob[mat_num]->v[j] != V_NOTHING ) {
	if ( pd_glob[mat_num]->i[j] == I_P0 ) {
	  if ( Num_Var_In_Type[j] > 1 ) {
	    fprintf(stderr,
		    "%s: Too many components in variable type for element variable %s (%s)\n",
		    yo,
		    Exo_Var_Names[j].name2,
		    Exo_Var_Names[j].name1 );
	    exit (-1);
	  }
	  if ( exo->truth_table_existance_key[j - V_FIRST] == 0 ) {
	    /* We just found a candidate for an element variable */
	    tev += Num_Var_In_Type[j];
	    exo->truth_table_existance_key[j - V_FIRST] = 1;
	  }
        }
      }
    }

    /* Now pick up all the post processing variables for this block 
       - yes, for now they must
       each be listed separately and painfully */
    if (ERROR_ZZ_VEL != -1 && Num_Var_In_Type[R_MOMENTUM1]) {
      tev++;
      if (ERROR_ZZ_VEL_ELSIZE  != -1) {
	tev++;	
      }
    }
    if (ERROR_ZZ_Q != -1 && Num_Var_In_Type[R_ENERGY]) {
      tev++;
      if (ERROR_ZZ_Q_ELSIZE  != -1) {
	tev++;	
      }
    }
    check = 0;
    for ( i = 0; i < upd->Num_Mat; i++ ) {
      if( pd_glob[i]->MeshMotion == LAGRANGIAN ||
	  pd_glob[i]->MeshMotion == DYNAMIC_LAGRANGIAN) check = 1;
    }

    if (ERROR_ZZ_P != -1 && (Num_Var_In_Type[R_MOMENTUM1] || check)) {
      tev++;
      if (ERROR_ZZ_P_ELSIZE  != -1) {
	tev++;	
      }
    }

    /* Finally pick up all of the element-level-storage continuation
     * variables, e.g. for saturation hysteresis function 
     */
    mat_num = Matilda[eb_indx];
    mp = mp_glob[mat_num];
    eb_ptr = Element_Blocks + eb_indx;
    ip_total = elem_info(NQUAD, eb_ptr->Elem_Type);
    if((mp->PorousMediaType == POROUS_UNSATURATED ||
	mp->PorousMediaType == POROUS_SHELL_UNSATURATED ||
	mp->PorousMediaType == POROUS_TWO_PHASE) &&
       mp->SaturationModel == TANH_HYST &&
       !if_ev)
      {
	for ( j = 0; j < ip_total; j++) {
	  if(SAT_CURVE_TYPE != -1) tev++; /*For Sat curve type */
	  if(CAP_PRESS_SWITCH != -1) tev++; /*For saturation switch */
	  if(SAT_QP_SWITCH != -1) tev++; /*for cap press switch point*/
	}
	if_ev = TRUE;
      }
  }

  /* Sanity check */
  if ( tev != rd->nev ) {
    sr = sprintf(err_msg, 
		 "%s: Elem var count mismatch: tev(%d)<>rd->nev(%d)!?",
		 yo, tev, rd->nev);
    EH(-1, err_msg);
    /*
    fprintf(stderr,
	    "%s: Disagreement over number of element variables\n",
	    yo );
    exit (-1);    
    */
  }
  
  /* Now do the real loop and populate the truth table */
  i = 0;
  for ( eb_indx = 0; eb_indx < exo->num_elem_blocks; eb_indx++ ) {
    /* First test for all the potential elem vars from primary nodal vars
       for this block */
    mat_num = Matilda[eb_indx];
    ev_indx = 0;
    for ( j = V_FIRST; j < V_LAST; j++) {
      found_match = FALSE;
      if ( pd_glob[mat_num]->v[j] != V_NOTHING ) {
	if ( pd_glob[mat_num]->i[j] == I_P0 ) {
	  if ( Num_Var_In_Type[j] > 1 ) {
	    fprintf(stderr,
		    "%s: Too many components in variable type for element variable %s (%s)\n",
		    yo,
		    Exo_Var_Names[j].name2,
		    Exo_Var_Names[j].name1 );
	    exit (-1);
	  }
	  /* We just found a candidate for an element variable */
	  exo->elem_var_tab[i++] = 1;
	  found_match = TRUE;
	  ev_indx++;
	  /* malloc the entry for this block by number of elems for this block 
	     but - only if the variable exists for this block! (by the truth table) */
	  if ( has_been_called == 0 ) {
	    /* NOTE: this final array dim is only to be malloc'd once; when a user 
	       is annealing the mesh, anneal mesh calls wr_result_prelim_exo again,
	       and hence create_truth_table, which would realloc this dim of gvec_elem.
	       this test will prevent that. - RRL */
	    asdv ( &gvec_elem[eb_indx][ev_indx - 1],
		   exo->eb_num_elems[eb_indx] );
	  }
	}
      }
      if ( found_match == FALSE && exo->truth_table_existance_key[j - V_FIRST] == 1 ) {
	exo->elem_var_tab[i++] = 0;
	ev_indx++;
      }
    }

    /* Now pick up all the post processing variables for this block 
       - yes, for now they must
       each be listed separately and painfully */

    if (ERROR_ZZ_VEL != -1 && Num_Var_In_Type[R_MOMENTUM1]) {
      exo->elem_var_tab[i++] = 1;   
      ev_indx++;
      /* malloc the entry for this block by number of elems for this block 
	 but - only if the variable exists for this block! (by the truth table) */
      if ( has_been_called == 0 ) {
	/* NOTE: this final array dim is only to be malloc'd once; when a user 
	   is annealing the mesh, anneal mesh calls wr_result_prelim_exo again,
	   and hence create_truth_table, which would realloc this dim of gvec_elem.
	   this test will prevent that. - RRL */
	asdv ( &gvec_elem[eb_indx][ev_indx - 1],
	       exo->eb_num_elems[eb_indx] );
      }
      if (ERROR_ZZ_VEL_ELSIZE  != -1) {
	exo->elem_var_tab[i++] = 1;   
	ev_indx++;
	/* malloc the entry for this block by number of elems for this block 
	   but - only if the variable exists for this block! (by the truth table) */
	if ( has_been_called == 0 ) {
	  /* NOTE: this final array dim is only to be malloc'd once; when a user 
	     is annealing the mesh, anneal mesh calls wr_result_prelim_exo again,
	     and hence create_truth_table, which would realloc this dim of gvec_elem.
	     this test will prevent that. - RRL */
	  asdv ( &gvec_elem[eb_indx][ev_indx - 1],
		 exo->eb_num_elems[eb_indx] );
	}
      }
    }

    if (ERROR_ZZ_Q != -1 && Num_Var_In_Type[R_ENERGY]) {
      exo->elem_var_tab[i++] = 1;   
      ev_indx++;
      /* malloc the entry for this block by number of elems for this block 
	 but - only if the variable exists for this block! (by the truth table) */
      if ( has_been_called == 0 ) {
	/* NOTE: this final array dim is only to be malloc'd once; when a user 
	   is annealing the mesh, anneal mesh calls wr_result_prelim_exo again,
	   and hence create_truth_table, which would realloc this dim of gvec_elem.
	   this test will prevent that. - RRL */
	asdv ( &gvec_elem[eb_indx][ev_indx - 1],
	       exo->eb_num_elems[eb_indx] );
      }
      if (ERROR_ZZ_Q_ELSIZE  != -1) {
	exo->elem_var_tab[i++] = 1;   
	ev_indx++;
	/* malloc the entry for this block by number of elems for this block 
	   but - only if the variable exists for this block! (by the truth table) */
	if ( has_been_called == 0 ) {
	  /* NOTE: this final array dim is only to be malloc'd once; when a user 
	     is annealing the mesh, anneal mesh calls wr_result_prelim_exo again,
	     and hence create_truth_table, which would realloc this dim of gvec_elem.
	     this test will prevent that. - RRL */
	  asdv ( &gvec_elem[eb_indx][ev_indx - 1],
		 exo->eb_num_elems[eb_indx] );
	}
      }
    }

    check = 0;
    for ( iii = 0; iii < upd->Num_Mat; iii++ ) {
      if( pd_glob[iii]->MeshMotion == LAGRANGIAN ||
	  pd_glob[iii]->MeshMotion == DYNAMIC_LAGRANGIAN) check = 1;
    }

    if (ERROR_ZZ_P != -1 && (Num_Var_In_Type[R_MOMENTUM1] || check)) {
      exo->elem_var_tab[i++] = 1;   
      ev_indx++;
      /* malloc the entry for this block by number of elems for this block 
	 but - only if the variable exists for this block! (by the truth table) */
      if ( has_been_called == 0 ) {
	/* NOTE: this final array dim is only to be malloc'd once; when a user 
	   is annealing the mesh, anneal mesh calls wr_result_prelim_exo again,
	   and hence create_truth_table, which would realloc this dim of gvec_elem.
	   this test will prevent that. - RRL */
	asdv ( &gvec_elem[eb_indx][ev_indx - 1],
	       exo->eb_num_elems[eb_indx] );
      }
      if (ERROR_ZZ_P_ELSIZE  != -1) {
	exo->elem_var_tab[i++] = 1;   
	ev_indx++;
	/* malloc the entry for this block by number of elems for this block 
	   but - only if the variable exists for this block! (by the truth table) */
	if ( has_been_called == 0 ) {
	  /* NOTE: this final array dim is only to be malloc'd once; when a user 
	     is annealing the mesh, anneal mesh calls wr_result_prelim_exo again,
	     and hence create_truth_table, which would realloc this dim of gvec_elem.
	     this test will prevent that. - RRL */
	  asdv ( &gvec_elem[eb_indx][ev_indx - 1],
		 exo->eb_num_elems[eb_indx] );
	  has_been_called++;
	}
      }
    }

    /*Now finally the saturation hysteresis variables */
    if(SAT_CURVE_TYPE != -1 || CAP_PRESS_SWITCH != -1 || SAT_QP_SWITCH != -1)
       {
	 eb_ptr = Element_Blocks + eb_indx;
	 ip_total = elem_info(NQUAD, eb_ptr->Elem_Type);
	 for(j=0; j < ip_total; j++)
	   {
	     /*Note that we will set these for all 3 var types because you
	      *will never see them individually. 
	      */
	     exo->elem_var_tab[i++] = 1;
	     ev_indx++;
	     if ( has_been_called == 0 ) 
	       {
		 asdv ( &gvec_elem[eb_indx][ev_indx - 1],
		      exo->eb_num_elems[eb_indx] );
	       }
	     exo->elem_var_tab[i++] = 1;
	     ev_indx++;
	     if ( has_been_called == 0 ) 
	       {
		 asdv ( &gvec_elem[eb_indx][ev_indx - 1],
		      exo->eb_num_elems[eb_indx] );
	       }
	     exo->elem_var_tab[i++] = 1;
	     ev_indx++;
	     if ( has_been_called == 0 ) 
	       {
		 asdv ( &gvec_elem[eb_indx][ev_indx - 1],
		      exo->eb_num_elems[eb_indx] );
	       }
	   }
       }
  }

  /* write out table */
  error      = ex_put_truth_table ( exo->exoid, EX_ELEM_BLOCK,
				    exo->num_elem_blocks,
				    rd->nev,
				    exo->elem_var_tab );
  EH(error, "ex_put_truth_table EX_ELEM_BLOCK");

  /* Now set truth table exists flag */
  exo->elem_var_tab_exists = TRUE;
}