void use_case_5_generate_mesh( const std::string& mesh_options , stk::mesh::BulkData & mesh , const VectorFieldType & node_coord , stk::mesh::Part & hex_block , stk::mesh::Part & quad_shell_block ) { mesh.modification_begin(); const unsigned parallel_size = mesh.parallel_size(); const unsigned parallel_rank = mesh.parallel_rank(); double t = 0 ; size_t num_hex = 0 ; size_t num_shell = 0 ; size_t num_nodes = 0 ; size_t num_block = 0 ; int error_flag = 0 ; try { Iogn::GeneratedMesh gmesh( mesh_options, parallel_size, parallel_rank ); num_nodes = gmesh.node_count_proc(); num_block = gmesh.block_count(); t = stk::wall_time(); std::vector<int> node_map( num_nodes , 0 ); gmesh.node_map( node_map ); { for ( size_t i = 1 ; i <= num_block ; ++i ) { const size_t num_elem = gmesh.element_count_proc(i); const std::pair<std::string,int> top_info = gmesh.topology_type(i); std::vector<int> elem_map( num_elem , 0 ); std::vector<int> elem_conn( num_elem * top_info.second ); gmesh.element_map( i, elem_map ); gmesh.connectivity( i , elem_conn ); if ( top_info.second == 8 ) { for ( size_t j = 0 ; j < num_elem ; ++j ) { const int * const local_node_id = & elem_conn[ j * 8 ] ; const stk::mesh::EntityId node_id[8] = { local_node_id[0] , local_node_id[1] , local_node_id[2] , local_node_id[3] , local_node_id[4] , local_node_id[5] , local_node_id[6] , local_node_id[7] }; const stk::mesh::EntityId elem_id = elem_map[ j ]; stk::mesh::fem::declare_element( mesh , hex_block , elem_id , node_id ); ++num_hex ; } } else if ( top_info.second == 4 ) { for ( size_t j = 0 ; j < num_elem ; ++j ) { const int * const local_node_id = & elem_conn[ j * 4 ] ; const stk::mesh::EntityId node_id[4] = { local_node_id[0] , local_node_id[1] , local_node_id[2] , local_node_id[3] }; const stk::mesh::EntityId elem_id = elem_map[ j ]; stk::mesh::fem::declare_element( mesh , quad_shell_block , elem_id , node_id ); ++num_shell ; } } } } std::vector<double> node_coordinates( 3 * node_map.size() ); gmesh.coordinates( node_coordinates ); if ( 3 * node_map.size() != node_coordinates.size() ) { std::ostringstream msg ; msg << " P" << mesh.parallel_rank() << ": ERROR, node_map.size() = " << node_map.size() << " , node_coordinates.size() / 3 = " << ( node_coordinates.size() / 3 ); throw std::runtime_error( msg.str() ); } for ( unsigned i = 0 ; i < node_map.size() ; ++i ) { const unsigned i3 = i * 3 ; stk::mesh::Entity * const node = mesh.get_entity( stk::mesh::fem::FEMMetaData::NODE_RANK , node_map[i] ); if ( NULL == node ) { std::ostringstream msg ; msg << " P:" << mesh.parallel_rank() << " ERROR, Node not found: " << node_map[i] << " = node_map[" << i << "]" ; throw std::runtime_error( msg.str() ); } double * const data = field_data( node_coord , *node ); data[0] = node_coordinates[ i3 + 0 ]; data[1] = node_coordinates[ i3 + 1 ]; data[2] = node_coordinates[ i3 + 2 ]; } } catch ( const std::exception & X ) { std::cout << " P:" << mesh.parallel_rank() << ": " << X.what() << std::endl ; std::cout.flush(); error_flag = 1 ; } catch( ... ) { std::cout << " P:" << mesh.parallel_rank() << " Caught unknown exception" << std::endl ; std::cout.flush(); error_flag = 1 ; } stk::all_reduce( mesh.parallel() , stk::ReduceMax<1>( & error_flag ) ); if ( error_flag ) { std::string msg( "Failed mesh generation" ); throw std::runtime_error( msg ); } mesh.modification_end(); double dt = stk::wall_dtime( t ); stk::all_reduce( mesh.parallel() , stk::ReduceMax<1>( & dt ) ); std::cout << " P" << mesh.parallel_rank() << ": Meshed Hex = " << num_hex << " , Shell = " << num_shell << " , Node = " << num_nodes << " in " << dt << " sec" << std::endl ; std::cout.flush(); }
int write_vis(std::string &nemI_out_file, std::string &exoII_inp_file, Machine_Description* machine, Problem_Description* prob, Mesh_Description<INT>* mesh, LB_Description<INT>* lb) { int exid_vis, exid_inp; char title[MAX_LINE_LENGTH+1]; const char *coord_names[] = {"X", "Y", "Z"}; /*-----------------------------Execution Begins------------------------------*/ /* Generate the file name for the visualization file */ std::string vis_file_name = remove_extension(nemI_out_file); vis_file_name += "-vis.exoII"; /* Generate the title for the file */ strcpy(title, UTIL_NAME); strcat(title, " "); strcat(title, ELB_VERSION); strcat(title, " load balance visualization file"); /* * If the vis technique is to be by element block then calculate the * number of element blocks. */ int vis_nelem_blks; if(prob->type == ELEMENTAL) vis_nelem_blks = machine->num_procs; else vis_nelem_blks = machine->num_procs + 1; /* Create the ExodusII file */ std::cout << "Outputting load balance visualization file " << vis_file_name.c_str() << "\n"; int cpu_ws = 0; int io_ws = 0; int mode = EX_CLOBBER; if (prob->int64db|prob->int64api) { mode |= EX_NETCDF4|EX_NOCLASSIC|prob->int64db|prob->int64api; } if((exid_vis=ex_create(vis_file_name.c_str(), mode, &cpu_ws, &io_ws)) < 0) { Gen_Error(0, "fatal: unable to create visualization output file"); return 0; } ON_BLOCK_EXIT(ex_close, exid_vis); /* * Open the original input ExodusII file, read the values for the * element blocks and output them to the visualization file. */ int icpu_ws=0; int iio_ws=0; float vers=0.0; mode = EX_READ | prob->int64api; if((exid_inp=ex_open(exoII_inp_file.c_str(), mode, &icpu_ws, &iio_ws, &vers)) < 0) { Gen_Error(0, "fatal: unable to open input ExodusII file"); return 0; } ON_BLOCK_EXIT(ex_close, exid_inp); char **elem_type = (char**)array_alloc(2, mesh->num_el_blks, MAX_STR_LENGTH+1, sizeof(char)); if(!elem_type) { Gen_Error(0, "fatal: insufficient memory"); return 0; } ON_BLOCK_EXIT(free, elem_type); std::vector<INT> el_blk_ids(mesh->num_el_blks); std::vector<INT> el_cnt_blk(mesh->num_el_blks); std::vector<INT> node_pel_blk(mesh->num_el_blks); std::vector<INT> nattr_el_blk(mesh->num_el_blks); if(ex_get_elem_blk_ids(exid_inp, TOPTR(el_blk_ids)) < 0) { Gen_Error(0, "fatal: unable to get element block IDs"); return 0; } int acc_vis = ELB_TRUE; // Output a different element block per processor if (prob->vis_out == 2) acc_vis = ELB_FALSE; // Output a nodal/element variable showing processor size_t nsize = 0; /* * Find out if the mesh consists of mixed elements. If not then * element blocks will be used to visualize the partitioning. Otherwise * nodal/element results will be used. */ for(size_t ecnt=0; ecnt < mesh->num_el_blks; ecnt++) { if(ex_get_elem_block(exid_inp, el_blk_ids[ecnt], elem_type[ecnt], &el_cnt_blk[ecnt], &node_pel_blk[ecnt], &nattr_el_blk[ecnt]) < 0) { Gen_Error(0, "fatal: unable to get element block parameters"); return 0; } nsize += el_cnt_blk[ecnt]*node_pel_blk[ecnt]; if(strcmp(elem_type[0], elem_type[ecnt]) == 0) { if(node_pel_blk[0] != node_pel_blk[ecnt]) acc_vis = ELB_FALSE; } else acc_vis = ELB_FALSE; } if(acc_vis == ELB_TRUE) { /* Output the initial information */ if(ex_put_init(exid_vis, title, mesh->num_dims, mesh->num_nodes, mesh->num_elems, vis_nelem_blks, 0, 0) < 0) { Gen_Error(0, "fatal: unable to output initial params to vis file"); return 0; } /* Output the nodal coordinates */ float *xptr = nullptr; float *yptr = nullptr; float *zptr = nullptr; switch(mesh->num_dims) { case 3: zptr = (mesh->coords) + 2*mesh->num_nodes; /* FALLTHRU */ case 2: yptr = (mesh->coords) + mesh->num_nodes; /* FALLTHRU */ case 1: xptr = mesh->coords; } if(ex_put_coord(exid_vis, xptr, yptr, zptr) < 0) { Gen_Error(0, "fatal: unable to output coords to vis file"); return 0; } if(ex_put_coord_names(exid_vis, (char**)coord_names) < 0) { Gen_Error(0, "fatal: unable to output coordinate names"); return 0; } std::vector<INT> elem_block(mesh->num_elems); std::vector<INT> elem_map(mesh->num_elems); std::vector<INT> tmp_connect(nsize); for(size_t ecnt=0; ecnt < mesh->num_elems; ecnt++) { elem_map[ecnt] = ecnt+1; if(prob->type == ELEMENTAL) elem_block[ecnt] = lb->vertex2proc[ecnt]; else { int proc = lb->vertex2proc[mesh->connect[ecnt][0]]; int nnodes = get_elem_info(NNODES, mesh->elem_type[ecnt]); elem_block[ecnt] = proc; for(int ncnt=1; ncnt < nnodes; ncnt++) { if(lb->vertex2proc[mesh->connect[ecnt][ncnt]] != proc) { elem_block[ecnt] = machine->num_procs; break; } } } } int ccnt = 0; std::vector<INT> vis_el_blk_ptr(vis_nelem_blks+1); for(INT bcnt=0; bcnt < vis_nelem_blks; bcnt++) { vis_el_blk_ptr[bcnt] = ccnt; int pos = 0; int old_pos = 0; INT* el_ptr = TOPTR(elem_block); size_t ecnt = mesh->num_elems; while(pos != -1) { pos = in_list(bcnt, ecnt, el_ptr); if(pos != -1) { old_pos += pos + 1; ecnt = mesh->num_elems - old_pos; el_ptr = TOPTR(elem_block) + old_pos; int nnodes = get_elem_info(NNODES, mesh->elem_type[old_pos-1]); for(int ncnt=0; ncnt < nnodes; ncnt++) tmp_connect[ccnt++] = mesh->connect[old_pos-1][ncnt] + 1; } } } vis_el_blk_ptr[vis_nelem_blks] = ccnt; /* Output the element map */ if(ex_put_map(exid_vis, TOPTR(elem_map)) < 0) { Gen_Error(0, "fatal: unable to output element number map"); return 0; } /* Output the visualization element blocks */ for(int bcnt=0; bcnt < vis_nelem_blks; bcnt++) { /* * Note this assumes all the blocks contain the same type * element. */ int ecnt = (vis_el_blk_ptr[bcnt+1]-vis_el_blk_ptr[bcnt])/node_pel_blk[0]; if(ex_put_elem_block(exid_vis, bcnt+1, elem_type[0], ecnt, node_pel_blk[0], 0) < 0) { Gen_Error(0, "fatal: unable to output element block params"); return 0; } /* Output the connectivity */ if(ex_put_elem_conn(exid_vis, bcnt+1, &tmp_connect[vis_el_blk_ptr[bcnt]]) < 0) { Gen_Error(0, "fatal: unable to output element connectivity"); return 0; } } } else { /* For nodal/element results visualization of the partioning. */ // Copy the mesh portion to the vis file. ex_copy(exid_inp, exid_vis); /* Set up the file for nodal/element results */ float time_val = 0.0; if(ex_put_time(exid_vis, 1, &time_val) < 0) { Gen_Error(0, "fatal: unable to output time to vis file"); return 0; } const char *var_names[] = {"proc"}; if(prob->type == NODAL) { /* Allocate memory for the nodal values */ std::vector<float> proc_vals(mesh->num_nodes); if(ex_put_variable_param(exid_vis, EX_NODAL, 1) < 0) { Gen_Error(0, "fatal: unable to output var params to vis file"); return 0; } if(ex_put_variable_names(exid_vis, EX_NODAL, 1, (char**)var_names) < 0) { Gen_Error(0, "fatal: unable to output variable name"); return 0; } /* Do some problem specific assignment */ for(size_t ncnt=0; ncnt < mesh->num_nodes; ncnt++) proc_vals[ncnt] = lb->vertex2proc[ncnt]; for(int pcnt=0; pcnt < machine->num_procs; pcnt++) { for(auto & elem : lb->bor_nodes[pcnt]) proc_vals[elem] = machine->num_procs + 1; } /* Output the nodal variables */ if(ex_put_nodal_var(exid_vis, 1, 1, mesh->num_nodes, TOPTR(proc_vals)) < 0) { Gen_Error(0, "fatal: unable to output nodal variables"); return 0; } } else if(prob->type == ELEMENTAL) { /* Allocate memory for the element values */ std::vector<float> proc_vals(mesh->num_elems); if(ex_put_variable_param(exid_vis, EX_ELEM_BLOCK, 1) < 0) { Gen_Error(0, "fatal: unable to output var params to vis file"); return 0; } if(ex_put_variable_names(exid_vis, EX_ELEM_BLOCK, 1, (char**)var_names) < 0) { Gen_Error(0, "fatal: unable to output variable name"); return 0; } /* Do some problem specific assignment */ for(int proc=0; proc < machine->num_procs; proc++) { for (size_t e = 0; e < lb->int_elems[proc].size(); e++) { size_t ecnt = lb->int_elems[proc][e]; proc_vals[ecnt] = proc; } for (size_t e = 0; e < lb->bor_elems[proc].size(); e++) { size_t ecnt = lb->bor_elems[proc][e]; proc_vals[ecnt] = proc; } } /* Output the element variables */ size_t offset = 0; for (size_t i=0; i < mesh->num_el_blks; i++) { if(ex_put_var(exid_vis, 1, EX_ELEM_BLOCK, 1, el_blk_ids[i], el_cnt_blk[i], &proc_vals[offset]) < 0) { Gen_Error(0, "fatal: unable to output nodal variables"); return 0; } offset += el_cnt_blk[i]; } } } return 1; } /*---------------------------End write_vis()-------------------------------*/