Пример #1
0
void
bc_matrl_index(Exo_DB *exo)
    
    /********************************************************************
     *
     * bc_matrl_index():
     *
     *    Find out what materials are on each side of a boundary
     *    condition. Note, some boundary conditions require one
     *    to specify this information in the form of an element block
     *    id. However, some others do not. This procedure attempts to
     *    calculate this for all boundary conditions and then fill in
     *    the BC_matrl_index_# elements of the Boundary_Condition
     *    structure.
     *
     *    The basic algorithm involves finding some information about
     *    the side or node set on which the boundary condition is
     *    applied. Then, given the bc name and this information,
     *    a decision is made as to what the BC_matrl_index_#'s should be
     *    set to.
     *
     *    We gather the following information to make this decision:
     *        1) element block indecises input from deck
     *        2) Number of nodes in the bc set in each material
     *        3) Number of elements, whoses sides are in the side set,
     *           in each material
     *        4) Node in the bc set which contains the minimum
     *           number of materials
     *        5) Node in the bc set  which contains the maximum
     *           number of materials
     *        6) A random node in the bc set which contains a
     *           specific number of materials (1, 2, 3, 4)
     *           
     *
     * HKM NOTE:
     *    This routine is a work in progress. Calculation of EDGE's and
     *    VERTICES are not done yet. Also, mp aspects haven't been
     *    figured out yet.
     *
     *******************************************************************/    
{
  int ibc, ss_index, side_index, k, node_num, i;
  int i_apply_meth, num_matrl_needed = -1;
  int found = FALSE, min_node_matrl, max_node_matrl, min_matrl,
      max_matrl, node_matrl_1, node_matrl_2, node_matrl_3,
      node_matrl_4, matrl_first;
  int *bin_matrl, *ind_matrl, *bin_matrl_elem,
      *node_flag_1ss, node_count;
  int mat_index, success, ielem;
  NODE_INFO_STRUCT *node_ptr;
  UMI_LIST_STRUCT *matrlLP;
  struct Boundary_Condition *bc_ptr;
  static char *yo = "bc_matrl_index :";

  bin_matrl = alloc_int_1(upd->Num_Mat * 4,   INT_NOINIT);
  ind_matrl = bin_matrl + upd->Num_Mat;
  bin_matrl_elem = ind_matrl +  upd->Num_Mat;
  node_flag_1ss = alloc_int_1(exo->num_nodes, INT_NOINIT);

  for (ibc = 0; ibc < Num_BC; ibc++) {
    bc_ptr = BC_Types + ibc;
    found = FALSE;
    /*
     *  Some boundary condition specifications already require
     *  you to specify the element blocks on either side of the
     *  side set.
     */
     switch (bc_ptr->BC_Name) {
       /*
	* For these boundary conditions, the element block ID numbers
	* are in the firest two integer slots
	*/
     case POROUS_PRESSURE_BC:
     case DARCY_CONTINUOUS_BC:
     case Y_DISCONTINUOUS_BC:
     case POROUS_GAS_BC:
     case VP_EQUIL_BC:
     case VN_POROUS_BC:
     case FLUID_SOLID_BC:
     case SOLID_FLUID_BC:
     case NO_SLIP_BC:
     case FLUID_SOLID_CONTACT_BC:
     case SOLID_FLUID_CONTACT_BC:
     case T_CONTACT_RESIS_BC:
     case T_CONTACT_RESIS_2_BC:
     case LIGHTP_JUMP_BC:
     case LIGHTM_JUMP_BC:
     case LIGHTP_JUMP_2_BC:
     case LIGHTM_JUMP_2_BC:
	 bc_ptr->BC_matrl_index_1 = map_mat_index(bc_ptr->BC_Data_Int[0]);
	 bc_ptr->BC_matrl_index_2 = map_mat_index(bc_ptr->BC_Data_Int[1]);
	 break;

	 /*
	  * For this boundary condition the element block numbers
	  * are in the second and third integer slots
	  */
     case VL_EQUIL_BC:
     case YFLUX_DISC_RXN_BC:
     case DISCONTINUOUS_VELO_BC:	 
	 bc_ptr->BC_matrl_index_1 = map_mat_index(bc_ptr->BC_Data_Int[1]);
	 bc_ptr->BC_matrl_index_2 = map_mat_index(bc_ptr->BC_Data_Int[2]);
	 break;
     }
     /*
      * Initialize quantities
      */
     for (i = 0; i < 4 * upd->Num_Mat; i++) bin_matrl[i] = 0;
     for (i = 0; i < exo->num_nodes; i++) node_flag_1ss[i] = 0;
     max_node_matrl = min_node_matrl = -1;
     min_matrl = 4000000;
     max_matrl = -1;
     node_matrl_1 = node_matrl_2 = node_matrl_3 = node_matrl_4 = -1;
     /*
      *  Determine how many materials each boundary condition needs
      *  based on the type of the boundary condition
      */
     i_apply_meth = BC_Types[ibc].desc->i_apply;
     if (i_apply_meth == CROSS_PHASE_DISCONTINUOUS ||
	 i_apply_meth == CROSS_PHASE) {
       num_matrl_needed = 2;
     } else if (i_apply_meth == SINGLE_PHASE) {
       num_matrl_needed = 1;
     }
     /*
      *  Loop over the nodes in the side set looking up what
      *  materials are located at each node
      *    -> this will work for side sets. Need to do node sets
      *       as well.
      */
     if (!strcmp(bc_ptr->Set_Type, "SS")) {
       for (ss_index = 0; ss_index < exo->num_side_sets; ss_index++) {
	 /*
	  * This logic works for one side set specifications. For
	  * two side set specifications (EDGES), we will have to go
	  * with a calculation of the union of side sets.
	  */
	 if (bc_ptr->BC_ID == exo->ss_id[ss_index]) {
	   found = TRUE;
	   for (side_index = 0;
		side_index < exo->ss_num_sides[ss_index];
		side_index++) {
	     /*
	      * Locate the element number, find the material index,
	      * then bin the result.
	      */
	     ielem = exo->ss_elem_list[exo->ss_elem_index[ss_index]+side_index];
	     mat_index = find_mat_number(ielem, exo);
	     bin_matrl_elem[mat_index]++;
	   
	     for (k = exo->ss_node_side_index[ss_index][side_index];
		  k < exo->ss_node_side_index[ss_index][side_index+1];
		  k++) {
	       node_num = exo->ss_node_list[ss_index][k];
	       if (!node_flag_1ss[node_num]) {
		 node_flag_1ss[node_num] = 1;
		 node_ptr = Nodes[node_num];
		 matrlLP = &(node_ptr->Mat_List);
		 /*
		  * Bin the materials at this node for later usage.
		  */
	      
		 for (i = 0; i < matrlLP->Length; i++) {
#ifdef DEBUG_IGNORE_ELEMENT_BLOCK_CAPABILITY
                   if (matrlLP->List[i] < 0) {
                     fprintf(stderr,"Material list contains negative number\n");
                     EH(-1,"logic error in ignoring an element block");
                   }
#endif
		   bin_matrl[matrlLP->List[i]]++;
		 }
		 /*
		  *  Find the max and min number of materials for a
		  *  node in this side set
		  */
		 if (matrlLP->Length > max_matrl) {
		   max_matrl = matrlLP->Length;
		   max_node_matrl = node_num;
		 }
		 if (matrlLP->Length < min_matrl) {
		   min_matrl = matrlLP->Length;
		   min_node_matrl = node_num;
		 }
		 /*
		  * Find representative nodes with specific
		  * numbers of materials
		  */
		 if (matrlLP->Length == 1) node_matrl_1 = node_num;
		 if (matrlLP->Length == 2) node_matrl_2 = node_num;
		 if (matrlLP->Length == 3) node_matrl_3 = node_num;
		 if (matrlLP->Length == 4) node_matrl_4 = node_num;
	       }
	     }
	   }
	 }
       } /* End of side set loop */
     } /* if SS */
     /*
      * Node Sets
      */
     if (!strcmp(bc_ptr->Set_Type, "NS")) {
       for (ss_index = 0; ss_index < exo->num_node_sets; ss_index++) {
	 /*
	  * This logic works for one side set specifications. For
	  * two side set specifications (EDGES), we will have to go
	  * with a calculation of the union of side sets.
	  */
	 if (bc_ptr->BC_ID == exo->ns_id[ss_index]) {
	   found = TRUE;

	   /*
	    * Loop over the number of nodes
	    */
	   for (k = 0; k < exo->ns_num_nodes[ss_index]; k++) {
	     node_num = exo->ns_node_list[exo->ns_node_index[ss_index]+k];
	     if (!node_flag_1ss[node_num]) {
	       node_flag_1ss[node_num] = 1;
	       node_ptr = Nodes[node_num];
	       matrlLP = &(node_ptr->Mat_List);
	       /*
		* Bin the materials at this node for later usage.
		*/
	      
	       for (i = 0; i < matrlLP->Length; i++) {
		 bin_matrl[matrlLP->List[i]]++;
	       }
	       /*
		*  Find the max and min number of materials for a
		*  node in this side set
		*/
	       if (matrlLP->Length > max_matrl) {
		 max_matrl = matrlLP->Length;
		 max_node_matrl = node_num;
	       }
	       if (matrlLP->Length < min_matrl) {
		 min_matrl = matrlLP->Length;
		 min_node_matrl = node_num;
	       }
	       /*
		* Find representative nodes with specific
		* numbers of materials
		*/
	       if (matrlLP->Length == 1) node_matrl_1 = node_num;
	       if (matrlLP->Length == 2) node_matrl_2 = node_num;
	       if (matrlLP->Length == 3) node_matrl_3 = node_num;
	       if (matrlLP->Length == 4) node_matrl_4 = node_num;
	     }
	   }	   
	 }
       } /* End of side set loop */
     } /* if NS */     

     /*
      *  Ok, we have obtained statistics on the side and node sets
      *  let's make a decision
      */
     
     if (found) {
       matrl_first = find_next_max(bin_matrl, ind_matrl, upd->Num_Mat);
       success = assign_matrl_2(bc_ptr, matrl_first);
       if (success < 0) {
	 printf("%s P_%d: problem in assigning first matrl index in ibc %d, %d:\n",
		yo, ProcID, ibc, matrl_first);
	 bc_matrl_index_print(bc_ptr, bin_matrl, bin_matrl_elem,
			      min_node_matrl, max_node_matrl, 
			      node_matrl_1, node_matrl_2, node_matrl_3,
			      node_matrl_4, ibc);
       }
       matrl_first = find_next_max(bin_matrl, ind_matrl, upd->Num_Mat);
       if (matrl_first >= 0) {
	 success = assign_matrl_2(bc_ptr, matrl_first);
	 if (success < 0) {
	   printf("%s P_%d: problem in assigning second matrl index in ibc %d, %d:\n",
		  yo, ProcID, ibc, matrl_first);
	   bc_matrl_index_print(bc_ptr, bin_matrl, bin_matrl_elem,
				min_node_matrl, max_node_matrl,
				node_matrl_1, node_matrl_2, node_matrl_3,
				node_matrl_4, ibc);
	 }
       } else {
         if (num_matrl_needed > 1) {
	   printf("%s P_%d: problem in finding a needed second matrl index:\n",
		  yo, ProcID);
	   EH(-1,"bc_matrl_index ERROR");
	 }
       }
     }
     /*
      * For debug purposes, print out everything that we have found
      * out and decided about this bc on all of the processors.
      */
#ifdef DEBUG_HKM
     print_sync_start(FALSE);
     bc_matrl_index_print(bc_ptr, bin_matrl, bin_matrl_elem,
			  min_node_matrl, max_node_matrl,
			  node_matrl_1, node_matrl_2, node_matrl_3,
			  node_matrl_4, ibc);
     print_sync_end(FALSE);
#endif

     /*
      * MP Fix: We may not get the same results on all processors
      *         In this case, just take the processor with the most
      *         nodes in this bc and with a valid result, and use
      *         that. Broadcast that result to all nodes. Cross your
      *         fingers.
      */
       
     node_count = 0;
     for (i = 0; i < exo->num_nodes; i++) {
       node_count += node_flag_1ss[i];
     }
#ifdef PARALLEL

     k = ProcWithMaxInt(node_count, &i);
     MPI_Bcast(&(bc_ptr->BC_matrl_index_1), 1, MPI_INT, k,
	       MPI_COMM_WORLD);
     MPI_Bcast(&(bc_ptr->BC_matrl_index_2), 1, MPI_INT, k,
	       MPI_COMM_WORLD);
     MPI_Bcast(&(bc_ptr->BC_matrl_index_3), 1, MPI_INT, k,
	       MPI_COMM_WORLD);
     MPI_Bcast(&(bc_ptr->BC_matrl_index_4), 1, MPI_INT, k,
	       MPI_COMM_WORLD);


#ifdef DEBUG_HKM
     print_sync_start(FALSE);
     if ( !ProcID ) {
       printf("Final matrl_index's for ibc = %d:\n", ibc);
       printf("\tBC_matrl_index_1 = %d\n",  bc_ptr->BC_matrl_index_1);
       printf("\tBC_matrl_index_2 = %d\n",  bc_ptr->BC_matrl_index_2);
       printf("\tBC_matrl_index_3 = %d\n",  bc_ptr->BC_matrl_index_3);
       printf("\tBC_matrl_index_4 = %d\n",  bc_ptr->BC_matrl_index_4);
       fflush(stdout);
     }
     print_sync_end(FALSE);
#endif
#endif
     
  }
  safer_free((void **) &bin_matrl);
  safer_free((void **) &node_flag_1ss);
}
Пример #2
0
int
ns_data_print(pp_Data * p, 
	      double x[], 
	      const Exo_DB * exo, 
	      const double time_value,
	      const double time_step_size)
{
  const int quantity       = p->data_type;
  int mat_num        = p->mat_num;
  const int elemBlock_id   = p->elem_blk_id;
  const int node_set_id    = p->ns_id;
  const int species_id     = p->species_number;
  const char * filenm      = p->data_filenm;
  const char * qtity_str   = p->data_type_name;
  const char * format_flag = p->format_flag;
  int * first_time         = &(p->first_time);

  static int err=0;
  int num_nodes_on_side;
  int ebIndex_first = -1;
  int local_side[2];
  int side_nodes[3];		/* Assume quad has no more than 3 per side. */
  int elem_list[4], elem_ct=0, face, ielem, node2;
  int local_node[4];
  int node = -1;
  int idx, idy, idz, id_var;
  int iprint;
  int nsp;			/* node set pointer for this node set */
  dbl x_pos, y_pos, z_pos;
  int j, wspec;
  int doPressure = 0;

#ifdef PARALLEL
  double some_time=0.0;
#endif
  double abscissa=0;
  double ordinate=0;
  double n1[3], n2[3];
  double xi[3];

  /*
   * Find an element block that has the desired material id.
   */
  if (elemBlock_id != -1) {
    for (j = 0; j < exo->num_elem_blocks; j++) {
      if (elemBlock_id == exo->eb_id[j]) {
	ebIndex_first = j;
	break;
      }
    }
    if (ebIndex_first == -1) {
      sprintf(err_msg, "Can't find an element block with the elem Block id %d\n", elemBlock_id);
    if (Num_Proc == 1) {
      EH(-1, err_msg);
    }
    }
    mat_num = Matilda[ebIndex_first];
    p->mat_num = mat_num;
    pd = pd_glob[mat_num];
  } else {
    mat_num = -1;
    p->mat_num = -1;
    pd = pd_glob[0];
  }

  nsp = match_nsid(node_set_id);  

  if( nsp != -1 )
    {
      node = Proc_NS_List[Proc_NS_Pointers[nsp]];
    }
  else
    {
      sprintf(err_msg, "Node set ID %d not found.", node_set_id);
      if( Num_Proc == 1 ) EH(-1,err_msg);
    }

  /* first right time stamp or run stamp to separate the sets */

  print_sync_start(FALSE);

  if (*first_time)
    {
      if ( format_flag[0] != '\0' ) 
	{
	  if (ProcID == 0)
	    {
	      uf = fopen(filenm,"a");
	      if (uf != NULL)
		{
		  fprintf(uf,"# %s %s @ nsid %d node (%d) \n", 
			  format_flag, qtity_str, node_set_id, node );
		  *first_time = FALSE;
		  fclose(uf);
		}
	    }
	}
    }

  if (format_flag[0] == '\0')
    {
      if (ProcID == 0)
	{
	  if ((uf = fopen(filenm,"a")) != NULL)
	    {
	      fprintf(uf,"Time/iteration = %e \n", time_value);
	      fprintf(uf,"  %s   Node_Set  %d Species %d\n", qtity_str,node_set_id,species_id);
	      fflush(uf);
	      fclose(uf);
	    }
	}
    }

  if (nsp != -1 ) {

    for (j = 0; j < Proc_NS_Count[nsp]; j++) {
      node = Proc_NS_List[Proc_NS_Pointers[nsp]+j];
      if (node < num_internal_dofs + num_boundary_dofs ) {
        idx = Index_Solution(node, MESH_DISPLACEMENT1, 0, 0, -1);
        if (idx == -1) {
          x_pos = Coor[0][node];
          WH(idx, "Mesh variable not found.  May get undeformed coords.");
        } else {
          x_pos = Coor[0][node] + x[idx];
        }
        idy = Index_Solution(node, MESH_DISPLACEMENT2, 0, 0, -1);
        if (idy == -1) {
          y_pos = Coor[1][node];
        } else {
          y_pos = Coor[1][node] + x[idy];
        }
        z_pos = 0.;
        if(pd->Num_Dim == 3) {
          idz = Index_Solution(node, MESH_DISPLACEMENT3, 0, 0, -1);
          if (idz == -1) {
	    z_pos = Coor[2][node];
          }  else{
	    z_pos = Coor[2][node] + x[idz];
          }
        }
        if (quantity == MASS_FRACTION) {
          id_var = Index_Solution(node, quantity, species_id, 0, mat_num);
        } else if (quantity < 0) {
          id_var = -1;
        } else {
          id_var = Index_Solution(node, quantity, 0, 0, mat_num);
        }

	/*
	 * In the easy case, the variable can be found somewhere in the
	 * big vector of unknowns. But sometimes we want a derived quantity
	 * that requires a little more work than an array reference.
	 *
	 * For now, save the good result if we have it.
	 */

	if ( id_var != -1 )
	  {
	    ordinate = x[id_var];
	    iprint = 1;
	  }
	else
	  {
	    /*
	     *  If we have an element based interpolation, let's calculate the interpolated value
	     */
	    if (quantity == PRESSURE) {
	      if ((pd->i[PRESSURE] == I_P1) || ( (pd->i[PRESSURE] > I_PQ1) && (pd->i[PRESSURE] < I_Q2_HVG) )) {
		doPressure = 1;
	      }
	    }
	    iprint = 0;
	  }

	/*
	 * If the quantity is "theta", an interior angle that only
	 * makes sense at a point, in 2D, we'll need to compute it.
	 */

	if ( strncasecmp(qtity_str, "theta", 5 ) == 0 || doPressure)
	  {
	    /*
	     * Look for the two sides connected to this node...?
	     *
	     * Premise:
	     *	1. The node appears in only one element(removed-RBS,6/14/06)
	     *          2. Exactly two sides emanate from the node.
	     *          3. Quadrilateral.
	     *
	     * Apologies to people who wish to relax premise 1. I know
	     * there are some obtuse angles out there that benefit from
	     * having more than one element at a vertex. With care, this
	     * procedure could be extended to cover that case as well.
	     */
	    
	    if ( ! exo->node_elem_conn_exists )
	      {
		EH(-1, "Cannot compute angle without node_elem_conn.");
	      }
	    
	    elem_list[0] = exo->node_elem_list[exo->node_elem_pntr[node]];

	    /*
	     * Find out where this node appears in the elements local
	     * node ordering scheme...
	     */

	    local_node[0] = in_list(node, exo->elem_node_pntr[elem_list[0]], 
				    exo->elem_node_pntr[elem_list[0]+1],
				    exo->elem_node_list);

	    EH(local_node[0], "Can not find node in elem node connectivity!?! ");
	    local_node[0] -= exo->elem_node_pntr[elem_list[0]];
	    /* check for neighbors*/
	    if( mat_num == find_mat_number(elem_list[0], exo))
	      {elem_ct = 1;}
	    else
	      {WH(-1,"block id doesn't match first element");}
	    for (face=0 ; face<ei->num_sides ; face++)
	      {
		ielem = exo->elem_elem_list[exo->elem_elem_pntr[elem_list[0]]+face];
		if (ielem != -1)
		  {
		    node2 = in_list(node, exo->elem_node_pntr[ielem], 
				    exo->elem_node_pntr[ielem+1],
				    exo->elem_node_list);
		    if (node2 != -1 && (mat_num == find_mat_number(ielem, exo)))
		      {
			elem_list[elem_ct] = ielem;
			local_node[elem_ct] = node2;
			local_node[elem_ct] -= exo->elem_node_pntr[ielem];
			elem_ct++;
		      }
		  }
	      }

	    /*
	     * Note that indeces are zero based!
	     */

	    ordinate = 0.0;
	    for (ielem = 0 ; ielem < elem_ct ; ielem++)
	      {
		if ( local_node[ielem] < 0 || local_node[ielem] > 3 ) 
		  {
		    if (strncasecmp(qtity_str, "theta", 5 ) == 0) {
		      EH(-1, "Node out of bounds.");
		    }
		  }

		/*
		 * Now, determine the local name of the sides adjacent to this
		 * node...this works for the exo patran convention for quads...
		 *
		 * Again, local_node and local_side are zero based...
		 */

		local_side[0] = (local_node[ielem]+3)%4;
		local_side[1] = local_node[ielem];

		/*
		 * With the side names, we can find the normal vector.
		 * Again, assume the sides live on the same element.
		 */
		load_ei(elem_list[ielem], exo, 0);

		/*
		 * We abuse the argument list under the conditions that
		 * we're going to do read-only operations and that
		 * we're not interested in old time steps, time derivatives
		 * etc.
		 */
		if (x == x_static) /* be the least disruptive possible */
		  {
		    err = load_elem_dofptr(elem_list[ielem], exo, x_static, x_old_static,
					   xdot_static, xdot_old_static, x_static, 1);
		  }
		else
		  {
		    err = load_elem_dofptr(elem_list[ielem], exo, x, x, x, x, x, 1);
		  }

		/*
		 * What are the local coordinates of the nodes in a quadrilateral?
		 */

		find_nodal_stu(local_node[ielem], ei->ielem_type, xi, xi+1, xi+2);

		err = load_basis_functions(xi, bfd);

		EH( err, "problem from load_basis_functions");
	    
		err = beer_belly();
		EH( err, "beer_belly");
	    
		err = load_fv();
		EH( err, "load_fv");
	    
		err = load_bf_grad();
		EH( err, "load_bf_grad");

		err = load_bf_mesh_derivs(); 
		EH(err, "load_bf_mesh_derivs");
		
		if (doPressure) {
		  ordinate = fv->P;
		  iprint = 1;
		} else {

		/* First, one side... */

		get_side_info(ei->ielem_type, local_side[0]+1, &num_nodes_on_side, 
			      side_nodes);

		surface_determinant_and_normal(elem_list[ielem], 
					       exo->elem_node_pntr[elem_list[ielem]],
					       ei->num_local_nodes,  
					       ei->ielem_dim-1, 
					       local_side[0]+1, 
					       num_nodes_on_side,
					       side_nodes);

		n1[0] = fv->snormal[0];
		n1[1] = fv->snormal[1];

		/* Second, the adjacent side of the quad... */

		get_side_info(ei->ielem_type, local_side[1]+1, &num_nodes_on_side, 
			      side_nodes);

		surface_determinant_and_normal(elem_list[ielem], 
					       exo->elem_node_pntr[elem_list[ielem]],
					       ei->num_local_nodes,  
					       ei->ielem_dim-1, 
					       local_side[1]+1, 
					       num_nodes_on_side,
					       side_nodes);

		n2[0] = fv->snormal[0];
		n2[1] = fv->snormal[1];

		/* cos (theta) = n1.n2 / ||n1|| ||n2|| */

		ordinate += 180. - (180./M_PI)*acos((n1[0]*n2[0] + n1[1]*n2[1])/
						    (sqrt(n1[0]*n1[0]+n1[1]*n1[1])*
						     sqrt(n2[0]*n2[0]+n2[1]*n2[1])));
		}
		iprint = 1;
	      }	/*ielem loop	*/
	  }
	else if ( strncasecmp(qtity_str, "timestepsize", 12 ) == 0 )
	  {
	    ordinate = time_step_size;
	    iprint = 1;
	  }
	else if ( strncasecmp(qtity_str, "cputime", 7 ) == 0 )
	  {
	    ordinate = ut();
	    iprint = 1;
	  }
	else if ( strncasecmp(qtity_str, "wallclocktime", 13 ) == 0 )
	  {
	    /* Get these from extern via main...*/
#ifdef PARALLEL
	    some_time = MPI_Wtime();
	    ordinate = some_time - time_goma_started;
#endif
#ifndef PARALLEL
            time_t now=0;
	    (void)time(&now);
	    ordinate = (double)(now) - time_goma_started;
#endif
	    iprint = 1;
	  }
	else if ( strncasecmp(qtity_str, "speed", 5 ) == 0 )
	  {
            id_var = Index_Solution(node, VELOCITY1, 0, 0, mat_num);
	    ordinate = SQUARE(x[id_var]);
            id_var = Index_Solution(node, VELOCITY2, 0, 0, mat_num);
	    ordinate += SQUARE(x[id_var]);
            id_var = Index_Solution(node, VELOCITY3, 0, 0, mat_num);
	    ordinate += SQUARE(x[id_var]);
	    ordinate = sqrt(ordinate);
	    iprint = 1;
	  }
        else if ( strncasecmp(qtity_str, "ac_pres", 7 ) == 0 )
          {
            id_var = Index_Solution(node, ACOUS_PREAL, 0, 0, mat_num);
            ordinate = SQUARE(x[id_var]);
            id_var = Index_Solution(node, ACOUS_PIMAG, 0, 0, mat_num);
            ordinate += SQUARE(x[id_var]);
            ordinate = sqrt(ordinate);
            iprint = 1;
          }
        else if ( strncasecmp(qtity_str, "light_comp", 10 ) == 0 )
          {
            id_var = Index_Solution(node, LIGHT_INTP, 0, 0, mat_num);
            ordinate = x[id_var];
            id_var = Index_Solution(node, LIGHT_INTM, 0, 0, mat_num);
            ordinate += x[id_var];
            iprint = 1;
          }
        else if ( strncasecmp(qtity_str, "nonvolatile", 11 ) == 0 )
          {
            ordinate = 1.0;
	    for(wspec = 0 ; wspec < pd->Num_Species_Eqn ; wspec++)
		{
            	id_var = Index_Solution(node, MASS_FRACTION, wspec, 0, mat_num);
            	ordinate -= x[id_var]*mp_glob[mat_num]->molar_volume[wspec];
		}
            iprint = 1;
          }
	else
	  {
	    WH(id_var,
	       "Requested print variable is not defined at all nodes. May get 0.");
	    if(id_var == -1) iprint = 0;
	  }

        if ((uf=fopen(filenm,"a")) != NULL)
	  {
	    if ( format_flag[0] == '\0' )
	      {
		if (iprint)
		  {
		    fprintf(uf,"  %e %e %e %e \n", x_pos, y_pos, z_pos, ordinate);
		  }
	      }
	    else
	      {
		if ( strncasecmp(format_flag, "t", 1) == 0 )
		  {
		    abscissa = time_value;
		  }
		else if (  strncasecmp(format_flag, "x", 1) == 0 )
		  {
		    abscissa = x_pos;		      
		  }
		else if (  strncasecmp(format_flag, "y", 1) == 0 )
		  {
		    abscissa = y_pos;		      
		  }
		else if (  strncasecmp(format_flag, "z", 1) == 0 )
		  {
		    abscissa = z_pos;		      
		  }
		else
		  {
		    abscissa = 0;
		  }
		if (iprint)
		  {
		    fprintf(uf, "%.16g\t%.16g\n", abscissa, ordinate);
		  }
	      }
	    fclose(uf);
	  }
      }
    }
  }
  print_sync_end(FALSE);

  return(1);
} /* END of routine ns_data_print */