static int build_side_node_list(int elem, int face, int eb_index, Exo_DB *exo, int *snl) { int element_type; int i; int nodes_this_side; int num_sides; int shape; int local_nodeces[MAX_NODES_PER_SIDE]; /* * Assume a canonical ordering to the local nodes in an element according * to the PATRAN convention. Faces, too, are conventionally numbered, so * all that is needed is the kind of element we have. */ element_type = Elem_Type(exo, elem); shape = type2shape(element_type); num_sides = shape2sides(shape); /* * Count up the number of nodes and provide their local 0-based * indeces or offsets so their global names may be more easily retrieved. */ nodes_this_side = sides2nodes(face, shape, local_nodeces); EH(nodes_this_side, "Problem counting nodes on an element face."); for ( i=0; i<nodes_this_side; i++) { snl[i] = exo->elem_node_list[exo->elem_node_pntr[elem] +local_nodeces[i]]; } return(nodes_this_side); }
void build_node_node(Exo_DB *exo) { int curr_list_size; int dude; int e; int elem; int end; int i; int length; int max; int n; int node; int npe; int start; int this_node; int total_list_size; int n_elem; int *list; /* * Don't even attempt to do this without adequate preparation. */ if ( ! exo->node_elem_conn_exists ) { EH(-1, "node_elem conn must exist before node_node can be built."); } if ( ! exo->elem_node_conn_exists ) { EH(-1, "elem_node conn must exist before node_node can be built."); } /* * Intial memory allocation. The length of the node list will be less than * this number by probably about a factor of 2. We will realloc more * precisely later. Repeating - this is an overestimate. */ length = 0; max = -1; for ( node=0; node<exo->num_nodes; node++) { this_node = 0; for ( e=exo->node_elem_pntr[node]; e<exo->node_elem_pntr[node+1]; e++) { elem = exo->node_elem_list[e]; npe = exo->elem_node_pntr[elem+1] - exo->elem_node_pntr[elem]; length += npe; this_node += npe; } if ( this_node > max ) { max = this_node; } } exo->node_node_conn_exists = TRUE; exo->node_node_pntr = (int *) smalloc((exo->num_nodes+1)*sizeof(int)); exo->node_node_list = (int *) smalloc(length*sizeof(int)); exo->centroid_list = (int *) smalloc((exo->num_nodes)*sizeof(int)); /* * To build unique lists of nodes we'll need some little buffer arrays, too. */ list = (int *) smalloc(max*sizeof(int)); /* * Loop through each node and build a list of all the nodes to which it * is connected. Flatten the list by extracting duplicate entries. Finally, * sort it and attach it to the global list. */ exo->node_node_pntr[0] = 0; total_list_size = 0; for ( node=0; node<exo->num_nodes; node++) { exo->centroid_list[node] = -1; /* Clear out any old garbage... */ for ( i=0; i<max; i++) { list[i] = -1; } curr_list_size = 0; for ( e=exo->node_elem_pntr[node]; e<exo->node_elem_pntr[node+1]; e++) { elem = exo->node_elem_list[e]; start = exo->elem_node_pntr[elem]; end = exo->elem_node_pntr[elem+1]; for ( n=start; n<end; n++) { dude = exo->elem_node_list[n]; /* * If this dude is not in the list, then add it and make the list * suitably larger. */ if ( -1 == in_list(dude, 0, curr_list_size, list) ) { list[curr_list_size] = dude; curr_list_size++; } } } /* * add centroid nodes of surrounding elements if node is a centroid node * This feature is used in discontinuous Galerkin upwinding.... */ if ( ( exo->node_elem_pntr[node+1] - exo->node_elem_pntr[node] ) == 1 && ( Use_DG || TRUE ) ) /* Disable Use_DG switch */ { /* * This node belongs to only one element */ elem = exo->node_elem_list[ exo->node_elem_pntr[node] ]; if ( ( n = centroid_node( Elem_Type( exo, elem ) ) ) != -1 ) { if ( node == exo->elem_node_list[ exo->elem_node_pntr[elem] + n ] ) { /* This is a centroid node */ exo->centroid_list[node] = elem; for( e = exo->elem_elem_pntr[elem]; e < exo->elem_elem_pntr[elem+1]; e++ ) { if ( (n_elem = exo->elem_elem_list[e]) != -1 ) { n = centroid_node ( Elem_Type( exo , n_elem ) ); EH(n, "No centroid node exists for element type "); dude = exo->elem_node_list[ exo->elem_node_pntr[n_elem] + n ]; if ( -1 == in_list(dude, 0, curr_list_size, list) ) { list[curr_list_size++] = dude; } } } } } } /* * Sort the list before appending to the big concatenated list... */ isort(curr_list_size, list); /* * No, we're assuming we're never in danger of overrunning the buffer * since we were so profligate at the beginning... */ for ( i=0; i<curr_list_size; i++, total_list_size++) { exo->node_node_list[total_list_size] = list[i]; } exo->node_node_pntr[node+1] = total_list_size; } exo->node_node_list = (int *) realloc(exo->node_node_list, total_list_size*sizeof(int)); #ifdef DEBUG fprintf(stderr, "Printing node-node connectivities...\n"); for ( node=0; node<exo->num_nodes; node++) { fprintf(stderr, "Node (%d): ", node+1); /* f77 RuLZ, C++ sUx ! */ for ( n=exo->node_node_pntr[node]; n<exo->node_node_pntr[node+1]; n++) { fprintf(stderr, "(%d) ", exo->node_node_list[n] + 1); } fprintf(stderr, "\n"); } #endif safe_free(list); return; }
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; }
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; }
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 */