void Albany::IossSTKMeshStruct::setFieldAndBulkData( const Teuchos::RCP<const Epetra_Comm>& comm, const Teuchos::RCP<Teuchos::ParameterList>& params, const unsigned int neq_, const AbstractFieldContainer::FieldContainerRequirements& req, const Teuchos::RCP<Albany::StateInfoStruct>& sis, const unsigned int worksetSize) { this->SetupFieldData(comm, neq_, req, sis, worksetSize); *out << "IOSS-STK: number of node sets = " << nsPartVec.size() << std::endl; *out << "IOSS-STK: number of side sets = " << ssPartVec.size() << std::endl; metaData->commit(); // Restart index to read solution from exodus file. int index = params->get("Restart Index",-1); // Default to no restart double res_time = params->get<double>("Restart Time",-1.0); // Default to no restart Ioss::Region *region = mesh_data->m_input_region; /* * The following code block reads a single mesh on PE 0, then distributes the mesh across * the other processors. stk_rebalance is used, which requires Zoltan * * This code is only compiled if ALBANY_MPI and ALBANY_ZOLTAN are true */ #ifdef ALBANY_ZOLTAN // rebalance needs Zoltan if(useSerialMesh){ bulkData->modification_begin(); if(comm->MyPID() == 0){ // read in the mesh on PE 0 stk::io::process_mesh_bulk_data(region, *bulkData); // Read solution from exodus file. if (index >= 0) { // User has specified a time step to restart at *out << "Restart Index set, reading solution index : " << index << std::endl; stk::io::input_mesh_fields(region, *bulkData, index); m_restartDataTime = region->get_state_time(index); m_hasRestartSolution = true; } else if (res_time >= 0) { // User has specified a time to restart at *out << "Restart solution time set, reading solution time : " << res_time << std::endl; stk::io::input_mesh_fields(region, *bulkData, res_time); m_restartDataTime = res_time; m_hasRestartSolution = true; } else { *out << "Neither restart index or time are set. Not reading solution data from exodus file"<< std::endl; } } bulkData->modification_end(); } // End UseSerialMesh - reading mesh on PE 0 else #endif /* * The following code block reads a single mesh when Albany is compiled serially, or a * Nemspread fileset if ALBANY_MPI is true. * */ { // running in Serial or Parallel read from Nemspread files stk::io::populate_bulk_data(*bulkData, *mesh_data); if (!usePamgen) { // Read solution from exodus file. if (index >= 0) { // User has specified a time step to restart at *out << "Restart Index set, reading solution index : " << index << std::endl; stk::io::process_input_request(*mesh_data, *bulkData, index); m_restartDataTime = region->get_state_time(index); m_hasRestartSolution = true; } else if (res_time >= 0) { // User has specified a time to restart at *out << "Restart solution time set, reading solution time : " << res_time << std::endl; stk::io::process_input_request(*mesh_data, *bulkData, res_time); m_restartDataTime = res_time; m_hasRestartSolution = true; } else { *out << "Restart Index not set. Not reading solution from exodus (" << index << ")"<< std::endl; } } bulkData->modification_end(); } // End Parallel Read - or running in serial if(m_hasRestartSolution){ Teuchos::Array<std::string> default_field; default_field.push_back("solution"); Teuchos::Array<std::string> restart_fields = params->get<Teuchos::Array<std::string> >("Restart Fields", default_field); // Get the fields to be used for restart // See what state data was initialized from the stk::io request // This should be propagated into stk::io const Ioss::ElementBlockContainer& elem_blocks = region->get_element_blocks(); /* // Uncomment to print what fields are in the exodus file Ioss::NameList exo_fld_names; elem_blocks[0]->field_describe(&exo_fld_names); for(std::size_t i = 0; i < exo_fld_names.size(); i++){ *out << "Found field \"" << exo_fld_names[i] << "\" in exodus file" << std::endl; } */ for (std::size_t i=0; i<sis->size(); i++) { Albany::StateStruct& st = *((*sis)[i]); if(elem_blocks[0]->field_exists(st.name)) for(std::size_t j = 0; j < restart_fields.size(); j++) if(boost::iequals(st.name, restart_fields[j])){ *out << "Restarting from field \"" << st.name << "\" found in exodus file." << std::endl; st.restartDataAvailable = true; break; } } } // coordinates_field = metaData->get_field<VectorFieldType>(std::string("coordinates")); //#ifdef ALBANY_FELIX // surfaceHeight_field = metaData->get_field<ScalarFieldType>(std::string("surface height")); //#endif // Refine the mesh before starting the simulation if indicated uniformRefineMesh(comm); // Rebalance the mesh before starting the simulation if indicated rebalanceInitialMesh(comm); // Build additional mesh connectivity needed for mesh fracture (if indicated) computeAddlConnectivity(); }
void Albany::IossSTKMeshStruct::setFieldAndBulkData ( const Teuchos::RCP<const Teuchos_Comm>& commT, const Teuchos::RCP<Teuchos::ParameterList>& params, const unsigned int neq_, const AbstractFieldContainer::FieldContainerRequirements& req, const Teuchos::RCP<Albany::StateInfoStruct>& sis, const unsigned int worksetSize) { this->SetupFieldData(commT, neq_, req, sis, worksetSize); mesh_data->set_bulk_data(*bulkData); *out << "IOSS-STK: number of node sets = " << nsPartVec.size() << std::endl; *out << "IOSS-STK: number of side sets = " << ssPartVec.size() << std::endl; mesh_data->add_all_mesh_fields_as_input_fields(); std::vector<stk::io::MeshField> missing; metaData->commit(); // Restart index to read solution from exodus file. int index = params->get("Restart Index",-1); // Default to no restart double res_time = params->get<double>("Restart Time",-1.0); // Default to no restart Ioss::Region& region = *(mesh_data->get_input_io_region()); /* * The following code block reads a single mesh on PE 0, then distributes the mesh across * the other processors. stk_rebalance is used, which requires Zoltan * * This code is only compiled if ALBANY_MPI and ALBANY_ZOLTAN are true */ #ifdef ALBANY_ZOLTAN // rebalance needs Zoltan if(useSerialMesh){ // trick to avoid hanging bulkData->modification_begin(); if(commT->getRank() == 0){ // read in the mesh on PE 0 //stk::io::process_mesh_bulk_data(region, *bulkData); mesh_data->populate_bulk_data(); //bulkData = &mesh_data->bulk_data(); // Read solution from exodus file. if (index >= 0) { // User has specified a time step to restart at *out << "Restart Index set, reading solution index : " << index << std::endl; mesh_data->read_defined_input_fields(index, &missing); m_restartDataTime = region.get_state_time(index); m_hasRestartSolution = true; } else if (res_time >= 0) { // User has specified a time to restart at *out << "Restart solution time set, reading solution time : " << res_time << std::endl; mesh_data->read_defined_input_fields(res_time, &missing); m_restartDataTime = res_time; m_hasRestartSolution = true; } else { *out << "Neither restart index or time are set. Not reading solution data from exodus file"<< std::endl; } } else { // trick to avoid hanging bulkData->modification_begin(); bulkData->modification_begin(); } bulkData->modification_end(); } // End UseSerialMesh - reading mesh on PE 0 else #endif /* * The following code block reads a single mesh when Albany is compiled serially, or a * Nemspread fileset if ALBANY_MPI is true. * */ { // running in Serial or Parallel read from Nemspread files mesh_data->populate_bulk_data(); if (!usePamgen) { // Read solution from exodus file. if (index >= 0) { // User has specified a time step to restart at *out << "Restart Index set, reading solution index : " << index << std::endl; mesh_data->read_defined_input_fields(index, &missing); m_restartDataTime = region.get_state_time(index); m_hasRestartSolution = true; } else if (res_time >= 0) { // User has specified a time to restart at *out << "Restart solution time set, reading solution time : " << res_time << std::endl; mesh_data->read_defined_input_fields(res_time, &missing); m_restartDataTime = res_time; m_hasRestartSolution = true; } else { *out << "Neither restart index or time are set. We still read defined fields in case they are needed (e.g., parameters)."<< std::endl; // *out << "Restart Index not set. Not reading solution from exodus (" << index << ")"<< std::endl; } } bulkData->modification_end(); } // End Parallel Read - or running in serial if(m_hasRestartSolution){ Teuchos::Array<std::string> default_field; default_field.push_back("solution"); Teuchos::Array<std::string> restart_fields = params->get<Teuchos::Array<std::string> >("Restart Fields", default_field); // Get the fields to be used for restart // See what state data was initialized from the stk::io request // This should be propagated into stk::io const Ioss::ElementBlockContainer& elem_blocks = region.get_element_blocks(); /* // Uncomment to print what fields are in the exodus file Ioss::NameList exo_fld_names; elem_blocks[0]->field_describe(&exo_fld_names); for(std::size_t i = 0; i < exo_fld_names.size(); i++){ *out << "Found field \"" << exo_fld_names[i] << "\" in exodus file" << std::endl; } */ for (std::size_t i=0; i<sis->size(); i++) { Albany::StateStruct& st = *((*sis)[i]); if(elem_blocks[0]->field_exists(st.name)) for(std::size_t j = 0; j < restart_fields.size(); j++) if(boost::iequals(st.name, restart_fields[j])){ *out << "Restarting from field \"" << st.name << "\" found in exodus file." << std::endl; st.restartDataAvailable = true; break; } } } #ifdef ALBANY_FELIX // Load required fields stk::mesh::Selector select_owned_in_part = stk::mesh::Selector(metaData->universal_part()) & stk::mesh::Selector(metaData->locally_owned_part()); stk::mesh::Selector select_overlap_in_part = stk::mesh::Selector(metaData->universal_part()) & (stk::mesh::Selector(metaData->locally_owned_part()) | stk::mesh::Selector(metaData->globally_shared_part())); std::vector<stk::mesh::Entity> nodes; stk::mesh::get_selected_entities(select_overlap_in_part, bulkData->buckets(stk::topology::NODE_RANK), nodes); std::vector<stk::mesh::Entity> elems; stk::mesh::get_selected_entities(select_owned_in_part, bulkData->buckets(stk::topology::ELEM_RANK), elems); GO numOwnedNodes(0); GO numOwnedElems(0); numOwnedNodes = stk::mesh::count_selected_entities(select_owned_in_part, bulkData->buckets(stk::topology::NODE_RANK)); numOwnedElems = stk::mesh::count_selected_entities(select_owned_in_part, bulkData->buckets(stk::topology::ELEM_RANK)); GO numGlobalVertices = 0; GO numGlobalElements = 0; Teuchos::reduceAll<int, GO>(*commT, Teuchos::REDUCE_SUM, 1, &numOwnedNodes, &numGlobalVertices); Teuchos::reduceAll<int, GO>(*commT, Teuchos::REDUCE_SUM, 1, &numOwnedElems, &numGlobalElements); if (commT->getRank() == 0) { *out << "Checking if requirements are already stored in the mesh. If not, we import them from ascii files.\n"; } Teuchos::Array<GO> nodeIndices(nodes.size()), elemIndices(elems.size()); for (int i = 0; i < nodes.size(); ++i) nodeIndices[i] = bulkData->identifier(nodes[i]) - 1; for (int i = 0; i < elems.size(); ++i) elemIndices[i] = bulkData->identifier(elems[i]) - 1; // Creating the serial and parallel node maps const Tpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid (); Teuchos::RCP<const Tpetra_Map> nodes_map = Tpetra::createNonContigMapWithNode<LO, GO> (nodeIndices, commT, KokkosClassic::Details::getNode<KokkosNode>()); Teuchos::RCP<const Tpetra_Map> elems_map = Tpetra::createNonContigMapWithNode<LO, GO> (elemIndices, commT, KokkosClassic::Details::getNode<KokkosNode>()); int numMyNodes = (commT->getRank() == 0) ? numGlobalVertices : 0; int numMyElements = (commT->getRank() == 0) ? numGlobalElements : 0; Teuchos::RCP<const Tpetra_Map> serial_nodes_map = Teuchos::rcp(new const Tpetra_Map(INVALID, numMyNodes, 0, commT)); Teuchos::RCP<const Tpetra_Map> serial_elems_map = Teuchos::rcp(new const Tpetra_Map(INVALID, numMyElements, 0, commT)); // Creating the Tpetra_Import object (to transfer from serial to parallel vectors) Tpetra_Import importOperatorNode (serial_nodes_map, nodes_map); Tpetra_Import importOperatorElem (serial_elems_map, elems_map); Teuchos::ParameterList* req_fields_info; if (params->isSublist("Required Fields Info")) { req_fields_info = ¶ms->sublist("Required Fields Info"); for (AbstractFieldContainer::FieldContainerRequirements::const_iterator it=req.begin(); it!=req.end(); ++it) { // Get the file name std::string temp_str = *it + " File Name"; std::string fname = req_fields_info->get<std::string>(temp_str,""); // Ge the file type (if not specified, assume Scalar) temp_str = *it + " Field Type"; std::string ftype = req_fields_info->get<std::string>(temp_str,""); if (ftype=="") { *out << "Warning! No field type specified for field " << *it << ". We skip it and hope is already present in the mesh...\n"; continue; } stk::mesh::Entity node, elem; stk::mesh::EntityId nodeId, elemId; int lid; double* values; typedef AbstractSTKFieldContainer::QPScalarFieldType QPScalarFieldType; typedef AbstractSTKFieldContainer::QPVectorFieldType QPVectorFieldType; typedef AbstractSTKFieldContainer::ScalarFieldType ScalarFieldType; typedef AbstractSTKFieldContainer::VectorFieldType VectorFieldType; // Depending on the field type, we need to use different pointers if (ftype == "Node Scalar") { // Creating the serial and (possibly) parallel Tpetra service vectors Tpetra_Vector serial_req_vec(serial_nodes_map); Tpetra_Vector req_vec(nodes_map); temp_str = *it + " Value"; if (req_fields_info->isParameter(temp_str)) { *out << "Discarding other info about Node Scalar field " << *it << " and filling it with constant value " << req_fields_info->get<double>(temp_str) << "\n"; // For debug, we allow to fill the field with a given uniform value fillTpetraVec (serial_req_vec,req_fields_info->get<double>(temp_str)); } else if (fname!="") { *out << "Reading Node Scalar field " << *it << " from file " << fname << "\n"; // Read the input file and stuff it in the Tpetra vector readScalarFileSerial (fname,serial_req_vec,commT); temp_str = *it + " Scale Factor"; if (req_fields_info->isParameter(temp_str)) { double scale_factor = req_fields_info->get<double>(temp_str); serial_req_vec.scale (scale_factor); } } else { bool found = false; for (int i(0); i<missing.size(); ++i) { if (missing[i].field()->name()==*it) { *out << "No file name nor constant value specified for Node Scalar field " << *it << "; initializing it to 0.\n"; fillTpetraVec (serial_req_vec,0.); found = true; break; } } if (!found) { *out << "Using mesh-stored values for Node Scalar field " << *it << " since no constant value nor filename has been specified\n"; continue; } } // Fill the (possibly) parallel vector req_vec.doImport(serial_req_vec,importOperatorNode,Tpetra::INSERT); // Extracting the mesh field and the tpetra vector view ScalarFieldType* field = metaData->get_field<ScalarFieldType>(stk::topology::NODE_RANK, *it); TEUCHOS_TEST_FOR_EXCEPTION (field==0, std::logic_error, "Error! Field " << *it << " not present (perhaps is 'Elem Scalar'?).\n"); Teuchos::ArrayRCP<const ST> req_vec_view = req_vec.get1dView(); //Now we have to stuff the vector in the mesh data for (int i(0); i<nodes.size(); ++i) { nodeId = bulkData->identifier(nodes[i]) - 1; lid = nodes_map->getLocalElement((GO)(nodeId)); values = stk::mesh::field_data(*field, nodes[i]); values[0] = req_vec_view[lid]; } } else if (ftype == "Elem Scalar") { // Creating the serial and (possibly) parallel Tpetra service vectors Tpetra_Vector serial_req_vec(serial_elems_map); Tpetra_Vector req_vec(elems_map); temp_str = *it + " Value"; if (req_fields_info->isParameter(temp_str)) { *out << "Discarding other info about Elem Scalar field " << *it << " and filling it with constant value " << req_fields_info->get<double>(temp_str) << "\n"; // For debug, we allow to fill the field with a given uniform value fillTpetraVec (serial_req_vec,req_fields_info->get<double>(temp_str)); } else if (fname!="") { *out << "Reading Elem Scalar field " << *it << " from file " << fname << "\n"; // Read the input file and stuff it in the Tpetra vector readScalarFileSerial (fname,serial_req_vec,commT); temp_str = *it + " Scale Factor"; if (req_fields_info->isParameter(temp_str)) { double scale_factor = req_fields_info->get<double>(temp_str); serial_req_vec.scale (scale_factor); } } else { bool found = false; for (int i(0); i<missing.size(); ++i) { if (missing[i].field()->name()==*it) { *out << "No file name nor constant value specified for Elem Scalar field " << *it << "; initializing it to 0.\n"; fillTpetraVec (serial_req_vec,0.); found = true; break; } } if (!found) { *out << "Using mesh-stored values for Elem Scalar field " << *it << " since no constant value nor filename has been specified\n"; continue; } } // Fill the (possibly) parallel vector req_vec.doImport(serial_req_vec,importOperatorElem,Tpetra::INSERT); // Extracting the mesh field and the tpetra vector view QPScalarFieldType* field = metaData->get_field<QPScalarFieldType>(stk::topology::ELEM_RANK, *it); TEUCHOS_TEST_FOR_EXCEPTION (field==0, std::logic_error, "Error! Field " << *it << " not present (perhaps is 'Node Scalar'?).\n"); Teuchos::ArrayRCP<const ST> req_vec_view = req_vec.get1dView(); //Now we have to stuff the vector in the mesh data for (int i(0); i<elems.size(); ++i) { elemId = bulkData->identifier(elems[i]) - 1; lid = elems_map->getLocalElement((GO)(elemId)); values = stk::mesh::field_data(*field, elems[i]); values[0] = req_vec_view[lid]; } } else if (ftype == "Node Vector") { // Loading the dimension of the Vector Field (by default equal to the mesh dimension) temp_str = *it + " Field Dimension"; int fieldDim = req_fields_info->get<int>(temp_str,this->meshSpecs[0]->numDim); // Creating the serial and (possibly) parallel Tpetra service multivectors Tpetra_MultiVector serial_req_mvec(serial_nodes_map,fieldDim); Tpetra_MultiVector req_mvec(nodes_map,fieldDim); temp_str = *it + " Value"; if (req_fields_info->isParameter(temp_str)) { *out << "Discarding other info about Node Vector field " << *it << " and filling it with constant value " << req_fields_info->get<Teuchos::Array<double> >(temp_str) << "\n"; // For debug, we allow to fill the field with a given uniform value fillTpetraMVec (serial_req_mvec,req_fields_info->get<Teuchos::Array<double> >(temp_str)); } else if (fname!="") { *out << "Reading Node Vector field " << *it << " from file " << fname << "\n"; // Read the input file and stuff it in the Tpetra multivector readVectorFileSerial (fname,serial_req_mvec,commT); temp_str = *it + " Scale Factor"; if (req_fields_info->isParameter(temp_str)) { double scale_factor = req_fields_info->get<double>(temp_str); serial_req_mvec.scale (scale_factor); } } else { bool found = false; for (int i(0); i<missing.size(); ++i) { if (missing[i].field()->name()==*it) { *out << "No file name nor constant value specified for Node Vector field " << *it << "; initializing it to 0.\n"; Teuchos::Array<double> vals(fieldDim,0.); fillTpetraMVec (serial_req_mvec,vals); found = true; break; } } if (!found) { *out << "Using mesh-stored values for Node Vector field " << *it << " since no constant value nor filename has been specified\n"; continue; } } // Fill the (possibly) parallel vector req_mvec.doImport(serial_req_mvec,importOperatorNode,Tpetra::INSERT); // Extracting the mesh field and the tpetra vector views VectorFieldType* field = metaData->get_field<VectorFieldType>(stk::topology::NODE_RANK, *it); TEUCHOS_TEST_FOR_EXCEPTION (field==0, std::logic_error, "Error! Field " << *it << " not present (perhaps is 'Elem Vector'?).\n"); std::vector<Teuchos::ArrayRCP<const ST> > req_mvec_view; for (int i(0); i<fieldDim; ++i) req_mvec_view.push_back(req_mvec.getVector(i)->get1dView()); //Now we have to stuff the vector in the mesh data for (int i(0); i<nodes.size(); ++i) { nodeId = bulkData->identifier(nodes[i]) - 1; lid = nodes_map->getLocalElement((GO)(nodeId)); values = stk::mesh::field_data(*field, nodes[i]); for (int iDim(0); iDim<fieldDim; ++iDim) values[iDim] = req_mvec_view[iDim][lid]; } } else if (ftype == "Elem Vector") { // Loading the dimension of the Vector Field (by default equal to the mesh dimension) temp_str = *it + " Field Dimension"; int fieldDim = req_fields_info->get<int>(temp_str,this->meshSpecs[0]->numDim); // Creating the serial and (possibly) parallel Tpetra service multivectors Tpetra_MultiVector serial_req_mvec(serial_elems_map,fieldDim); Tpetra_MultiVector req_mvec(elems_map,fieldDim); temp_str = *it + " Value"; if (req_fields_info->isParameter(temp_str)) { *out << "Discarding other info about Elem Vector field " << *it << " and filling it with constant value " << req_fields_info->get<Teuchos::Array<double> >(temp_str) << "\n"; // For debug, we allow to fill the field with a given uniform value fillTpetraMVec (serial_req_mvec,req_fields_info->get<Teuchos::Array<double> >(temp_str)); } else if (fname!="") { *out << "Reading Elem Vector field " << *it << " from file " << fname << "\n"; // Read the input file and stuff it in the Tpetra multivector readVectorFileSerial (fname,serial_req_mvec,commT); temp_str = *it + " Scale Factor"; if (req_fields_info->isParameter(temp_str)) { double scale_factor = req_fields_info->get<double>(temp_str); serial_req_mvec.scale (scale_factor); } } else { bool found = false; for (int i(0); i<missing.size(); ++i) { if (missing[i].field()->name()==*it) { *out << "No file name nor constant value specified for Elem Vector field " << *it << "; initializing it to 0.\n"; Teuchos::Array<double> vals(fieldDim,0.); fillTpetraMVec (serial_req_mvec,vals); found = true; break; } } if (!found) { *out << "Using mesh-stored values for Elem Vector field " << *it << " since no constant value nor filename has been specified\n"; continue; } } // Fill the (possibly) parallel vector req_mvec.doImport(serial_req_mvec,importOperatorElem,Tpetra::INSERT); // Extracting the mesh field and the tpetra vector views VectorFieldType* field = metaData->get_field<VectorFieldType>(stk::topology::ELEM_RANK, *it); TEUCHOS_TEST_FOR_EXCEPTION (field==0, std::logic_error, "Error! Field " << *it << " not present (perhaps is 'Node Vector'?).\n"); std::vector<Teuchos::ArrayRCP<const ST> > req_mvec_view; for (int i(0); i<fieldDim; ++i) req_mvec_view.push_back(req_mvec.getVector(i)->get1dView()); //Now we have to stuff the vector in the mesh data for (int i(0); i<elems.size(); ++i) { elemId = bulkData->identifier(elems[i]) - 1; lid = elems_map->getLocalElement((GO)(elemId)); values = stk::mesh::field_data(*field, nodes[i]); for (int iDim(0); iDim<fieldDim; ++iDim) values[iDim] = req_mvec_view[iDim][lid]; } } else { TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameterValue, "Sorry, I haven't yet implemented the case of field that are not Scalar nor Vector or that is not at nodal nor elemental.\n"); } } } if (params->get<bool>("Write points coordinates to ascii file", false)) { AbstractSTKFieldContainer::VectorFieldType* coordinates_field = fieldContainer->getCoordinatesField(); std::ofstream ofile; ofile.open("coordinates.ascii"); if (!ofile.is_open()) { TEUCHOS_TEST_FOR_EXCEPTION (true, std::logic_error, "Error! Cannot open coordinates file.\n"); } ofile << nodes.size() << " " << 4 << "\n"; stk::mesh::Entity node; for (int i(0); i<nodes.size(); ++i) { node = bulkData->get_entity(stk::topology::NODE_RANK, i + 1); double* coord = stk::mesh::field_data(*coordinates_field, node); ofile << bulkData->identifier (nodes[i]) << " " << coord[0] << " " << coord[1] << " " << coord[2] << "\n"; } ofile.close(); } #endif // Refine the mesh before starting the simulation if indicated uniformRefineMesh(commT); // Rebalance the mesh before starting the simulation if indicated rebalanceInitialMeshT(commT); // Build additional mesh connectivity needed for mesh fracture (if indicated) computeAddlConnectivity(); }