void PetscVector<T>::localize (std::vector<T>& v_local) const { this->_restore_array(); // This function must be run on all processors at once parallel_only(); PetscErrorCode ierr=0; const PetscInt n = this->size(); const PetscInt nl = this->local_size(); PetscScalar *values; v_local.clear(); v_local.resize(n, 0.); ierr = VecGetArray (_vec, &values); CHKERRABORT(libMesh::COMM_WORLD,ierr); numeric_index_type ioff = first_local_index(); for (PetscInt i=0; i<nl; i++) v_local[i+ioff] = static_cast<T>(values[i]); ierr = VecRestoreArray (_vec, &values); CHKERRABORT(libMesh::COMM_WORLD,ierr); CommWorld.sum(v_local); }
PetscErrorCode DMLibMeshSetSystem(DM dm, NonlinearImplicitSystem& sys) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); PetscBool islibmesh; ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh); if(!islibmesh) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM oftype %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH); if(dm->setupcalled) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot reset the libMesh system after DM has been set up."); DM_libMesh *dlm = (DM_libMesh *)(dm->data); dlm->sys =&sys; /* Initially populate the sets of active blockids and varids using all of the existing blocks/variables (only variables are supported at the moment). */ DofMap& dofmap = dlm->sys->get_dof_map(); dlm->varids->clear(); dlm->varnames->clear(); for(unsigned int v = 0; v < dofmap.n_variables(); ++v) { std::string vname = dofmap.variable(v).name(); dlm->varids->insert(std::pair<std::string,unsigned int>(vname,v)); dlm->varnames->insert(std::pair<unsigned int,std::string>(v,vname)); } const MeshBase& mesh = dlm->sys->get_mesh(); dlm->blockids->clear(); dlm->blocknames->clear(); std::set<subdomain_id_type> blocks; /* The following effectively is a verbatim copy of MeshBase::n_subdomains(). */ // This requires an inspection on every processor parallel_only(); MeshBase::const_element_iterator el = mesh.active_elements_begin(); const MeshBase::const_element_iterator end = mesh.active_elements_end(); for (; el!=end; ++el) blocks.insert((*el)->subdomain_id()); // Some subdomains may only live on other processors Parallel::set_union(blocks); std::set<subdomain_id_type>::iterator bit = blocks.begin(); std::set<subdomain_id_type>::iterator bend = blocks.end(); if(bit == bend) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "No mesh blocks found."); for(; bit != bend; ++bit) { subdomain_id_type bid = *bit; std::string bname = mesh.subdomain_name(bid); if(!bname.length()) { /* Block names are currently implemented for Exodus II meshes only, so we might have to make up our own block names and maintain our own mapping of block ids to names. */ std::ostringstream ss; ss << "dm" << bid; bname = ss.str(); } dlm->blockids->insert(std::pair<std::string,unsigned int>(bname,bid)); dlm->blocknames->insert(std::pair<unsigned int,std::string>(bid,bname)); } ierr = DMLibMeshSetUpName_Private(dm); CHKERRQ(ierr); PetscFunctionReturn(0); }
subdomain_id_type MeshBase::n_subdomains() const { // This requires an inspection on every processor parallel_only(); std::set<subdomain_id_type> ids; this->subdomain_ids (ids); return ids.size(); }
void MeshBase::subdomain_ids (std::set<subdomain_id_type> &ids) const { // This requires an inspection on every processor parallel_only(); ids.clear(); const_element_iterator el = this->active_elements_begin(); const const_element_iterator end = this->active_elements_end(); for (; el!=end; ++el) ids.insert((*el)->subdomain_id()); // Some subdomains may only live on other processors CommWorld.set_union(ids); }
void LocationMap<T>::init(MeshBase& mesh) { // This function must be run on all processors at once // for non-serial meshes if (!mesh.is_serial()) parallel_only(); START_LOG("init()", "LocationMap"); // Clear the old map _map.clear(); // Cache a bounding box _lower_bound.clear(); _lower_bound.resize(LIBMESH_DIM, std::numeric_limits<Real>::max()); _upper_bound.clear(); _upper_bound.resize(LIBMESH_DIM, -std::numeric_limits<Real>::max()); MeshBase::node_iterator it = mesh.nodes_begin(); const MeshBase::node_iterator end = mesh.nodes_end(); for (; it != end; ++it) { Node* node = *it; for (unsigned int i=0; i != LIBMESH_DIM; ++i) { // Expand the bounding box if necessary _lower_bound[i] = std::min(_lower_bound[i], (*node)(i)); _upper_bound[i] = std::max(_upper_bound[i], (*node)(i)); } } // On a parallel mesh we might not yet have a full bounding box if (!mesh.is_serial()) { CommWorld.min(_lower_bound); CommWorld.max(_upper_bound); } this->fill(mesh); STOP_LOG("init()", "LocationMap"); }
void EpetraVector<T>::localize (std::vector<T>& v_local) const { // This function must be run on all processors at once parallel_only(); const unsigned int n = this->size(); const unsigned int nl = this->local_size(); libmesh_assert(this->_vec); v_local.clear(); v_local.reserve(n); // build up my local part for (unsigned int i=0; i<nl; i++) v_local.push_back((*this->_vec)[i]); CommWorld.allgather (v_local); }
void MeshRefinement::flag_elements_by_elem_fraction (const ErrorVector& error_per_cell, const Real refine_frac, const Real coarsen_frac, const unsigned int max_l) { parallel_only(); // The function arguments are currently just there for // backwards_compatibility if (!_use_member_parameters) { // If the user used non-default parameters, lets warn // that they're deprecated if (refine_frac != 0.3 || coarsen_frac != 0.0 || max_l != libMesh::invalid_uint) libmesh_deprecated(); _refine_fraction = refine_frac; _coarsen_fraction = coarsen_frac; _max_h_level = max_l; } // Check for valid fractions.. // The fraction values must be in [0,1] libmesh_assert_greater_equal (_refine_fraction, 0); libmesh_assert_less_equal (_refine_fraction, 1); libmesh_assert_greater_equal (_coarsen_fraction, 0); libmesh_assert_less_equal (_coarsen_fraction, 1); // The number of active elements in the mesh const unsigned int n_active_elem = _mesh.n_elem(); // The number of elements to flag for coarsening const unsigned int n_elem_coarsen = static_cast<unsigned int>(_coarsen_fraction * n_active_elem); // The number of elements to flag for refinement const unsigned int n_elem_refine = static_cast<unsigned int>(_refine_fraction * n_active_elem); // Clean up the refinement flags. These could be left // over from previous refinement steps. this->clean_refinement_flags(); // This vector stores the error and element number for all the // active elements. It will be sorted and the top & bottom // elements will then be flagged for coarsening & refinement std::vector<float> sorted_error; sorted_error.reserve (n_active_elem); // Loop over the active elements and create the entry // in the sorted_error vector MeshBase::element_iterator elem_it = _mesh.active_local_elements_begin(); const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end(); for (; elem_it != elem_end; ++elem_it) sorted_error.push_back (error_per_cell[(*elem_it)->id()]); CommWorld.allgather(sorted_error); // Now sort the sorted_error vector std::sort (sorted_error.begin(), sorted_error.end()); // If we're coarsening by parents: // Create a sorted error vector with coarsenable parent elements // only, sorted by lowest errors first ErrorVector error_per_parent, sorted_parent_error; if (_coarsen_by_parents) { Real parent_error_min, parent_error_max; create_parent_error_vector(error_per_cell, error_per_parent, parent_error_min, parent_error_max); sorted_parent_error = error_per_parent; std::sort (sorted_parent_error.begin(), sorted_parent_error.end()); // All the other error values will be 0., so get rid of them. sorted_parent_error.erase (std::remove(sorted_parent_error.begin(), sorted_parent_error.end(), 0.), sorted_parent_error.end()); } float top_error= 0., bottom_error = 0.; // Get the maximum error value corresponding to the // bottom n_elem_coarsen elements if (_coarsen_by_parents && n_elem_coarsen) { const unsigned int dim = _mesh.mesh_dimension(); unsigned int twotodim = 1; for (unsigned int i=0; i!=dim; ++i) twotodim *= 2; unsigned int n_parent_coarsen = n_elem_coarsen / (twotodim - 1); if (n_parent_coarsen) bottom_error = sorted_parent_error[n_parent_coarsen - 1]; } else if (n_elem_coarsen) { bottom_error = sorted_error[n_elem_coarsen - 1]; } if (n_elem_refine) top_error = sorted_error[sorted_error.size() - n_elem_refine]; // Finally, let's do the element flagging elem_it = _mesh.active_elements_begin(); for (; elem_it != elem_end; ++elem_it) { Elem* elem = *elem_it; Elem* parent = elem->parent(); if (_coarsen_by_parents && parent && n_elem_coarsen && error_per_parent[parent->id()] <= bottom_error) elem->set_refinement_flag(Elem::COARSEN); if (!_coarsen_by_parents && n_elem_coarsen && error_per_cell[elem->id()] <= bottom_error) elem->set_refinement_flag(Elem::COARSEN); if (n_elem_refine && elem->level() < _max_h_level && error_per_cell[elem->id()] >= top_error) elem->set_refinement_flag(Elem::REFINE); } }
//----------------------------------------------------------------- // Mesh refinement methods void MeshRefinement::flag_elements_by_error_fraction (const ErrorVector& error_per_cell, const Real refine_frac, const Real coarsen_frac, const unsigned int max_l) { parallel_only(); // The function arguments are currently just there for // backwards_compatibility if (!_use_member_parameters) { // If the user used non-default parameters, lets warn // that they're deprecated if (refine_frac != 0.3 || coarsen_frac != 0.0 || max_l != libMesh::invalid_uint) libmesh_deprecated(); _refine_fraction = refine_frac; _coarsen_fraction = coarsen_frac; _max_h_level = max_l; } // Check for valid fractions.. // The fraction values must be in [0,1] libmesh_assert_greater_equal (_refine_fraction, 0); libmesh_assert_less_equal (_refine_fraction, 1); libmesh_assert_greater_equal (_coarsen_fraction, 0); libmesh_assert_less_equal (_coarsen_fraction, 1); // Clean up the refinement flags. These could be left // over from previous refinement steps. this->clean_refinement_flags(); // We're getting the minimum and maximum error values // for the ACTIVE elements Real error_min = 1.e30; Real error_max = 0.; // And, if necessary, for their parents Real parent_error_min = 1.e30; Real parent_error_max = 0.; // Prepare another error vector if we need to sum parent errors ErrorVector error_per_parent; if (_coarsen_by_parents) { create_parent_error_vector(error_per_cell, error_per_parent, parent_error_min, parent_error_max); } // We need to loop over all active elements to find the minimum MeshBase::element_iterator el_it = _mesh.active_local_elements_begin(); const MeshBase::element_iterator el_end = _mesh.active_local_elements_end(); for (; el_it != el_end; ++el_it) { const unsigned int id = (*el_it)->id(); libmesh_assert_less (id, error_per_cell.size()); error_max = std::max (error_max, error_per_cell[id]); error_min = std::min (error_min, error_per_cell[id]); } CommWorld.max(error_max); CommWorld.min(error_min); // Compute the cutoff values for coarsening and refinement const Real error_delta = (error_max - error_min); const Real parent_error_delta = parent_error_max - parent_error_min; const Real refine_cutoff = (1.- _refine_fraction)*error_max; const Real coarsen_cutoff = _coarsen_fraction*error_delta + error_min; const Real parent_cutoff = _coarsen_fraction*parent_error_delta + error_min; // // Print information about the error // libMesh::out << " Error Information:" << std::endl // << " ------------------" << std::endl // << " min: " << error_min << std::endl // << " max: " << error_max << std::endl // << " delta: " << error_delta << std::endl // << " refine_cutoff: " << refine_cutoff << std::endl // << " coarsen_cutoff: " << coarsen_cutoff << std::endl; // Loop over the elements and flag them for coarsening or // refinement based on the element error MeshBase::element_iterator e_it = _mesh.active_elements_begin(); const MeshBase::element_iterator e_end = _mesh.active_elements_end(); for (; e_it != e_end; ++e_it) { Elem* elem = *e_it; const unsigned int id = elem->id(); libmesh_assert_less (id, error_per_cell.size()); const float elem_error = error_per_cell[id]; if (_coarsen_by_parents) { Elem* parent = elem->parent(); if (parent) { const unsigned int parentid = parent->id(); if (error_per_parent[parentid] >= 0. && error_per_parent[parentid] <= parent_cutoff) elem->set_refinement_flag(Elem::COARSEN); } } // Flag the element for coarsening if its error // is <= coarsen_fraction*delta + error_min else if (elem_error <= coarsen_cutoff) { elem->set_refinement_flag(Elem::COARSEN); } // Flag the element for refinement if its error // is >= refinement_cutoff. if (elem_error >= refine_cutoff) if (elem->level() < _max_h_level) elem->set_refinement_flag(Elem::REFINE); } }
bool MeshRefinement::flag_elements_by_nelem_target (const ErrorVector& error_per_cell) { parallel_only(); // Check for valid fractions.. // The fraction values must be in [0,1] libmesh_assert_greater_equal (_refine_fraction, 0); libmesh_assert_less_equal (_refine_fraction, 1); libmesh_assert_greater_equal (_coarsen_fraction, 0); libmesh_assert_less_equal (_coarsen_fraction, 1); // This function is currently only coded to work when coarsening by // parents - it's too hard to guess how many coarsenings will be // performed otherwise. libmesh_assert (_coarsen_by_parents); // The number of active elements in the mesh - hopefully less than // 2 billion on 32 bit machines const unsigned int n_active_elem = _mesh.n_active_elem(); // The maximum number of active elements to flag for coarsening const unsigned int max_elem_coarsen = static_cast<unsigned int>(_coarsen_fraction * n_active_elem) + 1; // The maximum number of elements to flag for refinement const unsigned int max_elem_refine = static_cast<unsigned int>(_refine_fraction * n_active_elem) + 1; // Clean up the refinement flags. These could be left // over from previous refinement steps. this->clean_refinement_flags(); // The target number of elements to add or remove const int n_elem_new = _nelem_target - n_active_elem; // Create an vector with active element errors and ids, // sorted by highest errors first const unsigned int max_elem_id = _mesh.max_elem_id(); std::vector<std::pair<float, unsigned int> > sorted_error; sorted_error.reserve (n_active_elem); // On a ParallelMesh, we need to communicate to know which remote ids // correspond to active elements. { std::vector<bool> is_active(max_elem_id, false); MeshBase::element_iterator elem_it = _mesh.active_local_elements_begin(); const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end(); for (; elem_it != elem_end; ++elem_it) { const unsigned int eid = (*elem_it)->id(); is_active[eid] = true; libmesh_assert_less (eid, error_per_cell.size()); sorted_error.push_back (std::make_pair(error_per_cell[eid], eid)); } CommWorld.max(is_active); CommWorld.allgather(sorted_error); } // Default sort works since pairs are sorted lexicographically std::sort (sorted_error.begin(), sorted_error.end()); std::reverse (sorted_error.begin(), sorted_error.end()); // Create a sorted error vector with coarsenable parent elements // only, sorted by lowest errors first ErrorVector error_per_parent; std::vector<std::pair<float, unsigned int> > sorted_parent_error; Real parent_error_min, parent_error_max; create_parent_error_vector(error_per_cell, error_per_parent, parent_error_min, parent_error_max); // create_parent_error_vector sets values for non-parents and // non-coarsenable parents to -1. Get rid of them. for (unsigned int i=0; i != error_per_parent.size(); ++i) if (error_per_parent[i] != -1) sorted_parent_error.push_back(std::make_pair(error_per_parent[i], i)); std::sort (sorted_parent_error.begin(), sorted_parent_error.end()); // Keep track of how many elements we plan to coarsen & refine unsigned int coarsen_count = 0; unsigned int refine_count = 0; const unsigned int dim = _mesh.mesh_dimension(); unsigned int twotodim = 1; for (unsigned int i=0; i!=dim; ++i) twotodim *= 2; // First, let's try to get our element count to target_nelem if (n_elem_new >= 0) { // Every element refinement creates at least // 2^dim-1 new elements refine_count = std::min(static_cast<unsigned int>(n_elem_new / (twotodim-1)), max_elem_refine); } else { // Every successful element coarsening is likely to destroy // 2^dim-1 net elements. coarsen_count = std::min(static_cast<unsigned int>(-n_elem_new / (twotodim-1)), max_elem_coarsen); } // Next, let's see if we can trade any refinement for coarsening while (coarsen_count < max_elem_coarsen && refine_count < max_elem_refine && coarsen_count < sorted_parent_error.size() && refine_count < sorted_error.size() && sorted_error[refine_count].first > sorted_parent_error[coarsen_count].first * _coarsen_threshold) { coarsen_count++; refine_count++; } // On a ParallelMesh, we need to communicate to know which remote ids // correspond to refinable elements unsigned int successful_refine_count = 0; { std::vector<bool> is_refinable(max_elem_id, false); for (unsigned int i=0; i != sorted_error.size(); ++i) { unsigned int eid = sorted_error[i].second; Elem *elem = _mesh.query_elem(eid); if (elem && elem->level() < _max_h_level) is_refinable[eid] = true; } CommWorld.max(is_refinable); if (refine_count > max_elem_refine) refine_count = max_elem_refine; for (unsigned int i=0; i != sorted_error.size(); ++i) { if (successful_refine_count >= refine_count) break; unsigned int eid = sorted_error[i].second; Elem *elem = _mesh.query_elem(eid); if (is_refinable[eid]) { if (elem) elem->set_refinement_flag(Elem::REFINE); successful_refine_count++; } } } // If we couldn't refine enough elements, don't coarsen too many // either if (coarsen_count < (refine_count - successful_refine_count)) coarsen_count = 0; else coarsen_count -= (refine_count - successful_refine_count); if (coarsen_count > max_elem_coarsen) coarsen_count = max_elem_coarsen; unsigned int successful_coarsen_count = 0; if (coarsen_count) { for (unsigned int i=0; i != sorted_parent_error.size(); ++i) { if (successful_coarsen_count >= coarsen_count * twotodim) break; unsigned int parent_id = sorted_parent_error[i].second; Elem *parent = _mesh.query_elem(parent_id); // On a ParallelMesh we skip remote elements if (!parent) continue; libmesh_assert(parent->has_children()); for (unsigned int c=0; c != parent->n_children(); ++c) { Elem *elem = parent->child(c); if (elem && elem != remote_elem) { libmesh_assert(elem->active()); elem->set_refinement_flag(Elem::COARSEN); successful_coarsen_count++; } } } } // Return true if we've done all the AMR/C we can if (!successful_coarsen_count && !successful_refine_count) return true; // And false if there may still be more to do. return false; }
void MeshRefinement::flag_elements_by_error_tolerance (const ErrorVector& error_per_cell_in) { parallel_only(); libmesh_assert_greater (_coarsen_threshold, 0); // Check for valid fractions.. // The fraction values must be in [0,1] libmesh_assert_greater_equal (_refine_fraction, 0); libmesh_assert_less_equal (_refine_fraction, 1); libmesh_assert_greater_equal (_coarsen_fraction, 0); libmesh_assert_less_equal (_coarsen_fraction, 1); // How much error per cell will we tolerate? const Real local_refinement_tolerance = _absolute_global_tolerance / std::sqrt(static_cast<Real>(_mesh.n_active_elem())); const Real local_coarsening_tolerance = local_refinement_tolerance * _coarsen_threshold; // Prepare another error vector if we need to sum parent errors ErrorVector error_per_parent; if (_coarsen_by_parents) { Real parent_error_min, parent_error_max; create_parent_error_vector(error_per_cell_in, error_per_parent, parent_error_min, parent_error_max); } MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); for (; elem_it != elem_end; ++elem_it) { Elem* elem = *elem_it; Elem* parent = elem->parent(); const unsigned int elem_number = elem->id(); const float elem_error = error_per_cell_in[elem_number]; if (elem_error > local_refinement_tolerance && elem->level() < _max_h_level) elem->set_refinement_flag(Elem::REFINE); if (!_coarsen_by_parents && elem_error < local_coarsening_tolerance) elem->set_refinement_flag(Elem::COARSEN); if (_coarsen_by_parents && parent) { float parent_error = error_per_parent[parent->id()]; if (parent_error >= 0.) { const Real parent_coarsening_tolerance = std::sqrt(parent->n_children() * local_coarsening_tolerance * local_coarsening_tolerance); if (parent_error < parent_coarsening_tolerance) elem->set_refinement_flag(Elem::COARSEN); } } } }
void ParmetisPartitioner::assign_partitioning (MeshBase& mesh) { // This function must be run on all processors at once parallel_only(); const unsigned int first_local_elem = _vtxdist[libMesh::processor_id()]; std::vector<std::vector<unsigned int> > requested_ids(libMesh::n_processors()), requests_to_fill(libMesh::n_processors()); MeshBase::element_iterator elem_it = mesh.active_elements_begin(); MeshBase::element_iterator elem_end = mesh.active_elements_end(); for (; elem_it != elem_end; ++elem_it) { Elem *elem = *elem_it; // we need to get the index from the owning processor // (note we cannot assign it now -- we are iterating // over elements again and this will be bad!) libmesh_assert_less (elem->processor_id(), requested_ids.size()); requested_ids[elem->processor_id()].push_back(elem->id()); } // Trade with all processors (including self) to get their indices for (unsigned int pid=0; pid<libMesh::n_processors(); pid++) { // Trade my requests with processor procup and procdown const unsigned int procup = (libMesh::processor_id() + pid) % libMesh::n_processors(); const unsigned int procdown = (libMesh::n_processors() + libMesh::processor_id() - pid) % libMesh::n_processors(); CommWorld.send_receive (procup, requested_ids[procup], procdown, requests_to_fill[procdown]); // we can overwrite these requested ids in-place. for (unsigned int i=0; i<requests_to_fill[procdown].size(); i++) { const unsigned int requested_elem_index = requests_to_fill[procdown][i]; libmesh_assert(_global_index_by_pid_map.count(requested_elem_index)); const unsigned int global_index_by_pid = _global_index_by_pid_map[requested_elem_index]; const unsigned int local_index = global_index_by_pid - first_local_elem; libmesh_assert_less (local_index, _part.size()); libmesh_assert_less (local_index, mesh.n_active_local_elem()); const unsigned int elem_procid = static_cast<unsigned int>(_part[local_index]); libmesh_assert_less (elem_procid, static_cast<unsigned int>(_nparts)); requests_to_fill[procdown][i] = elem_procid; } // Trade back CommWorld.send_receive (procdown, requests_to_fill[procdown], procup, requested_ids[procup]); } // and finally assign the partitioning. // note we are iterating in exactly the same order // used to build up the request, so we can expect the // required entries to be in the proper sequence. elem_it = mesh.active_elements_begin(); elem_end = mesh.active_elements_end(); for (std::vector<unsigned int> counters(libMesh::n_processors(), 0); elem_it != elem_end; ++elem_it) { Elem *elem = *elem_it; const unsigned int current_pid = elem->processor_id(); libmesh_assert_less (counters[current_pid], requested_ids[current_pid].size()); const unsigned int elem_procid = requested_ids[current_pid][counters[current_pid]++]; libmesh_assert_less (elem_procid, static_cast<unsigned int>(_nparts)); elem->processor_id() = elem_procid; } }
//----------------------------------------------------------------- // Mesh refinement methods bool MeshRefinement::limit_level_mismatch_at_node (const unsigned int max_mismatch) { // This function must be run on all processors at once parallel_only(); bool flags_changed = false; // Vector holding the maximum element level that touches a node. std::vector<unsigned char> max_level_at_node (_mesh.n_nodes(), 0); std::vector<unsigned char> max_p_level_at_node (_mesh.n_nodes(), 0); // Loop over all the active elements & fill the vector { MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); for (; elem_it != elem_end; ++elem_it) { const Elem* elem = *elem_it; const unsigned char elem_level = elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0); const unsigned char elem_p_level = elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0); // Set the max_level at each node for (unsigned int n=0; n<elem->n_nodes(); n++) { const unsigned int node_number = elem->node(n); libmesh_assert_less (node_number, max_level_at_node.size()); max_level_at_node[node_number] = std::max (max_level_at_node[node_number], elem_level); max_p_level_at_node[node_number] = std::max (max_p_level_at_node[node_number], elem_p_level); } } } // Now loop over the active elements and flag the elements // who violate the requested level mismatch { MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); for (; elem_it != elem_end; ++elem_it) { Elem* elem = *elem_it; const unsigned int elem_level = elem->level(); const unsigned int elem_p_level = elem->p_level(); // Skip the element if it is already fully flagged if (elem->refinement_flag() == Elem::REFINE && elem->p_refinement_flag() == Elem::REFINE) continue; // Loop over the nodes, check for possible mismatch for (unsigned int n=0; n<elem->n_nodes(); n++) { const unsigned int node_number = elem->node(n); // Flag the element for refinement if it violates // the requested level mismatch if ( (elem_level + max_mismatch) < max_level_at_node[node_number] && elem->refinement_flag() != Elem::REFINE) { elem->set_refinement_flag (Elem::REFINE); flags_changed = true; } if ( (elem_p_level + max_mismatch) < max_p_level_at_node[node_number] && elem->p_refinement_flag() != Elem::REFINE) { elem->set_p_refinement_flag (Elem::REFINE); flags_changed = true; } } } } // If flags changed on any processor then they changed globally CommWorld.max(flags_changed); return flags_changed; }
bool MeshRefinement::eliminate_unrefined_patches () { // This function must be run on all processors at once parallel_only(); bool flags_changed = false; MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); for (; elem_it != elem_end; ++elem_it) { Elem* elem = *elem_it; // First assume that we'll have to flag this element for both h // and p refinement, then change our minds if we see any // neighbors that are as coarse or coarser than us. bool h_flag_me = true, p_flag_me = true; // Skip the element if it is already fully flagged for refinement if (elem->p_refinement_flag() == Elem::REFINE) p_flag_me = false; if (elem->refinement_flag() == Elem::REFINE) { h_flag_me = false; if (!p_flag_me) continue; } // Test the parent if that is already flagged for coarsening else if (elem->refinement_flag() == Elem::COARSEN) { libmesh_assert(elem->parent()); elem = elem->parent(); // FIXME - this doesn't seem right - RHS if (elem->refinement_flag() != Elem::COARSEN_INACTIVE) continue; p_flag_me = false; } const unsigned int my_level = elem->level(); int my_p_adjustment = 0; if (elem->p_refinement_flag() == Elem::REFINE) my_p_adjustment = 1; else if (elem->p_refinement_flag() == Elem::COARSEN) { libmesh_assert_greater (elem->p_level(), 0); my_p_adjustment = -1; } const unsigned int my_new_p_level = elem->p_level() + my_p_adjustment; // Check all the element neighbors for (unsigned int n=0; n<elem->n_neighbors(); n++) { const Elem *neighbor = elem->neighbor(n); // Quit if the element is on a local boundary if (neighbor == NULL || neighbor == remote_elem) { h_flag_me = false; p_flag_me = false; break; } // if the neighbor will be equally or less refined than // we are, then we will not become an unrefined island. // So if we are still considering h refinement: if (h_flag_me && // If our neighbor is already at a lower level, // it can't end up at a higher level even if it // is flagged for refinement once ((neighbor->level() < my_level) || // If our neighbor is at the same level but isn't // flagged for refinement, it won't end up at a // higher level ((neighbor->active()) && (neighbor->refinement_flag() != Elem::REFINE)) || // If our neighbor is currently more refined but is // a parent flagged for coarsening, it will end up // at the same level. (neighbor->refinement_flag() == Elem::COARSEN_INACTIVE))) { // We've proven we won't become an unrefined island, // so don't h refine to avoid that. h_flag_me = false; // If we've also proven we don't need to p refine, // we don't need to check more neighbors if (!p_flag_me) break; } if (p_flag_me) { // if active neighbors will have a p level // equal to or lower than ours, then we do not need to p // refine ourselves. if (neighbor->active()) { int p_adjustment = 0; if (neighbor->p_refinement_flag() == Elem::REFINE) p_adjustment = 1; else if (neighbor->p_refinement_flag() == Elem::COARSEN) { libmesh_assert_greater (neighbor->p_level(), 0); p_adjustment = -1; } if (my_new_p_level >= neighbor->p_level() + p_adjustment) { p_flag_me = false; if (!h_flag_me) break; } } // If we have inactive neighbors, we need to // test all their active descendants which neighbor us else if (neighbor->ancestor()) { if (neighbor->min_new_p_level_by_neighbor(elem, my_new_p_level + 2) <= my_new_p_level) { p_flag_me = false; if (!h_flag_me) break; } } } } if (h_flag_me) { // Parents that would create islands should no longer // coarsen if (elem->refinement_flag() == Elem::COARSEN_INACTIVE) { for (unsigned int c=0; c<elem->n_children(); c++) { libmesh_assert_equal_to (elem->child(c)->refinement_flag(), Elem::COARSEN); elem->child(c)->set_refinement_flag(Elem::DO_NOTHING); } elem->set_refinement_flag(Elem::INACTIVE); } else elem->set_refinement_flag(Elem::REFINE); flags_changed = true; } if (p_flag_me) { if (elem->p_refinement_flag() == Elem::COARSEN) elem->set_p_refinement_flag(Elem::DO_NOTHING); else elem->set_p_refinement_flag(Elem::REFINE); flags_changed = true; } } // If flags changed on any processor then they changed globally CommWorld.max(flags_changed); return flags_changed; }
//----------------------------------------------------------------- // Mesh refinement methods bool MeshRefinement::limit_level_mismatch_at_edge (const unsigned int max_mismatch) { // This function must be run on all processors at once parallel_only(); bool flags_changed = false; // Maps holding the maximum element level that touches an edge std::map<std::pair<unsigned int, unsigned int>, unsigned char> max_level_at_edge; std::map<std::pair<unsigned int, unsigned int>, unsigned char> max_p_level_at_edge; // Loop over all the active elements & fill the maps { MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); for (; elem_it != elem_end; ++elem_it) { const Elem* elem = *elem_it; const unsigned char elem_level = elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0); const unsigned char elem_p_level = elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0); // Set the max_level at each edge for (unsigned int n=0; n<elem->n_edges(); n++) { AutoPtr<Elem> edge = elem->build_edge(n); unsigned int childnode0 = edge->node(0); unsigned int childnode1 = edge->node(1); if (childnode1 < childnode0) std::swap(childnode0, childnode1); for (const Elem *p = elem; p != NULL; p = p->parent()) { AutoPtr<Elem> pedge = p->build_edge(n); unsigned int node0 = pedge->node(0); unsigned int node1 = pedge->node(1); if (node1 < node0) std::swap(node0, node1); // If elem does not share this edge with its ancestor // p, refinement levels of elements sharing p's edge // are not restricted by refinement levels of elem. // Furthermore, elem will not share this edge with any // of p's ancestors, so we can safely break out of the // for loop early. if (node0 != childnode0 && node1 != childnode1) break; childnode0 = node0; childnode1 = node1; std::pair<unsigned int, unsigned int> edge_key = std::make_pair(node0, node1); if (max_level_at_edge.find(edge_key) == max_level_at_edge.end()) { max_level_at_edge[edge_key] = elem_level; max_p_level_at_edge[edge_key] = elem_p_level; } else { max_level_at_edge[edge_key] = std::max (max_level_at_edge[edge_key], elem_level); max_p_level_at_edge[edge_key] = std::max (max_p_level_at_edge[edge_key], elem_p_level); } } } } } // Now loop over the active elements and flag the elements // who violate the requested level mismatch { MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); for (; elem_it != elem_end; ++elem_it) { Elem* elem = *elem_it; const unsigned int elem_level = elem->level(); const unsigned int elem_p_level = elem->p_level(); // Skip the element if it is already fully flagged if (elem->refinement_flag() == Elem::REFINE && elem->p_refinement_flag() == Elem::REFINE) continue; // Loop over the nodes, check for possible mismatch for (unsigned int n=0; n<elem->n_edges(); n++) { AutoPtr<Elem> edge = elem->build_edge(n); unsigned int node0 = edge->node(0); unsigned int node1 = edge->node(1); if (node1 < node0) std::swap(node0, node1); std::pair<unsigned int, unsigned int> edge_key = std::make_pair(node0, node1); // Flag the element for refinement if it violates // the requested level mismatch if ( (elem_level + max_mismatch) < max_level_at_edge[edge_key] && elem->refinement_flag() != Elem::REFINE) { elem->set_refinement_flag (Elem::REFINE); flags_changed = true; } if ( (elem_p_level + max_mismatch) < max_p_level_at_edge[edge_key] && elem->p_refinement_flag() != Elem::REFINE) { elem->set_p_refinement_flag (Elem::REFINE); flags_changed = true; } } } } // If flags changed on any processor then they changed globally CommWorld.max(flags_changed); return flags_changed; }
void MeshBase::prepare_for_use (const bool skip_renumber_nodes_and_elements) { parallel_only(); // A distributed mesh may have processors with no elements (or // processors with no elements of higher dimension, if we ever // support mixed-dimension meshes), but we want consistent // mesh_dimension anyways. libmesh_assert(CommWorld.verify(this->is_serial())); if (!this->is_serial()) { unsigned int dim = this->mesh_dimension(); CommWorld.max(dim); this->set_mesh_dimension(dim); } // Renumber the nodes and elements so that they in contiguous // blocks. By default, _skip_renumber_nodes_and_elements is false. // // We may currently change that by passing // skip_renumber_nodes_and_elements==true to this function, but we // should use the allow_renumbering() accessor instead. // // Instances where you if prepare_for_use() should not renumber the nodes // and elements include reading in e.g. an xda/r or gmv file. In // this case, the ordering of the nodes may depend on an accompanying // solution, and the node ordering cannot be changed. if (skip_renumber_nodes_and_elements) { libmesh_deprecated(); this->allow_renumbering(false); } // Mesh modification operations might not leave us with consistent // id counts, but our partitioner might need that consistency. if(!_skip_renumber_nodes_and_elements) this->renumber_nodes_and_elements(); else this->update_parallel_id_counts(); // Let all the elements find their neighbors this->find_neighbors(); // Partition the mesh. this->partition(); // If we're using ParallelMesh, we'll want it parallelized. this->delete_remote_elements(); if(!_skip_renumber_nodes_and_elements) this->renumber_nodes_and_elements(); // Reset our PointLocator. This needs to happen any time the elements // in the underlying elements in the mesh have changed, so we do it here. this->clear_point_locator(); // The mesh is now prepared for use. _is_prepared = true; }
inline void SparseMatrix<T>::print(std::ostream& os, const bool sparse) const { parallel_only(); libmesh_assert (this->initialized()); if(!this->_dof_map) { os << std::endl << "Error! Trying to print a matrix with no dof_map set!" << std::endl << std::endl; libmesh_error(); } // We'll print the matrix from processor 0 to make sure // it's serialized properly if (libMesh::processor_id() == 0) { libmesh_assert(this->_dof_map->first_dof() == 0); for (unsigned int i=this->_dof_map->first_dof(); i!=this->_dof_map->end_dof(); ++i) { if(sparse) { for (unsigned int j=0; j<this->n(); j++) { T c = (*this)(i,j); if (c != static_cast<T>(0.0)) { os << i << " " << j << " " << c << std::endl; } } } else { for (unsigned int j=0; j<this->n(); j++) os << (*this)(i,j) << " "; os << std::endl; } } std::vector<unsigned int> ibuf, jbuf; std::vector<T> cbuf; unsigned int currenti = this->_dof_map->end_dof(); for (unsigned int p=1; p < libMesh::n_processors(); ++p) { Parallel::receive(p, ibuf); Parallel::receive(p, jbuf); Parallel::receive(p, cbuf); libmesh_assert(ibuf.size() == jbuf.size()); libmesh_assert(ibuf.size() == cbuf.size()); if (ibuf.empty()) continue; libmesh_assert(ibuf.front() >= currenti); libmesh_assert(ibuf.back() >= ibuf.front()); unsigned int currentb = 0; for (;currenti <= ibuf.back(); ++currenti) { if(sparse) { for (unsigned int j=0; j<this->n(); j++) { if (currentb < ibuf.size() && ibuf[currentb] == currenti && jbuf[currentb] == j) { os << currenti << " " << j << " " << cbuf[currentb] << std::endl; currentb++; } } } else { for (unsigned int j=0; j<this->n(); j++) { if (currentb < ibuf.size() && ibuf[currentb] == currenti && jbuf[currentb] == j) { os << cbuf[currentb] << " "; currentb++; } else os << static_cast<T>(0.0) << " "; } os << std::endl; } } } if(!sparse) { for (; currenti != this->m(); ++currenti) { for (unsigned int j=0; j<this->n(); j++) os << static_cast<T>(0.0) << " "; os << std::endl; } } } else { std::vector<unsigned int> ibuf, jbuf; std::vector<T> cbuf; // We'll assume each processor has access to entire // matrix rows, so (*this)(i,j) is valid if i is a local index. for (unsigned int i=this->_dof_map->first_dof(); i!=this->_dof_map->end_dof(); ++i) { for (unsigned int j=0; j<this->n(); j++) { T c = (*this)(i,j); if (c != static_cast<T>(0.0)) { ibuf.push_back(i); jbuf.push_back(j); cbuf.push_back(c); } } } Parallel::send(0,ibuf); Parallel::send(0,jbuf); Parallel::send(0,cbuf); } }
void ExactSolution::_compute_error(const std::string& sys_name, const std::string& unknown_name, std::vector<Real>& error_vals) { // This function must be run on all processors at once parallel_only(); // Make sure we aren't "overconfigured" libmesh_assert (!(_exact_values.size() && _equation_systems_fine)); // Get a reference to the system whose error is being computed. // If we have a fine grid, however, we'll integrate on that instead // for more accuracy. const System& computed_system = _equation_systems_fine ? _equation_systems_fine->get_system(sys_name) : _equation_systems.get_system (sys_name); const Real time = _equation_systems.get_system(sys_name).time; const unsigned int sys_num = computed_system.number(); const unsigned int var = computed_system.variable_number(unknown_name); const unsigned int var_component = computed_system.variable_scalar_number(var, 0); // Prepare a global solution and a MeshFunction of the coarse system if we need one AutoPtr<MeshFunction> coarse_values; AutoPtr<NumericVector<Number> > comparison_soln = NumericVector<Number>::build(); if (_equation_systems_fine) { const System& comparison_system = _equation_systems.get_system(sys_name); std::vector<Number> global_soln; comparison_system.update_global_solution(global_soln); comparison_soln->init(comparison_system.solution->size(), true, SERIAL); (*comparison_soln) = global_soln; coarse_values = AutoPtr<MeshFunction> (new MeshFunction(_equation_systems, *comparison_soln, comparison_system.get_dof_map(), comparison_system.variable_number(unknown_name))); coarse_values->init(); } // Initialize any functors we're going to use for (unsigned int i=0; i != _exact_values.size(); ++i) if (_exact_values[i]) _exact_values[i]->init(); for (unsigned int i=0; i != _exact_derivs.size(); ++i) if (_exact_derivs[i]) _exact_derivs[i]->init(); for (unsigned int i=0; i != _exact_hessians.size(); ++i) if (_exact_hessians[i]) _exact_hessians[i]->init(); // Get a reference to the dofmap and mesh for that system const DofMap& computed_dof_map = computed_system.get_dof_map(); const MeshBase& _mesh = computed_system.get_mesh(); const unsigned int dim = _mesh.mesh_dimension(); // Zero the error before summation // 0 - sum of square of function error (L2) // 1 - sum of square of gradient error (H1 semi) // 2 - sum of square of Hessian error (H2 semi) // 3 - sum of sqrt(square of function error) (L1) // 4 - max of sqrt(square of function error) (Linfty) // 5 - sum of square of curl error (HCurl semi) // 6 - sum of square of div error (HDiv semi) error_vals = std::vector<Real>(7, 0.); // Construct Quadrature rule based on default quadrature order const FEType& fe_type = computed_dof_map.variable_type(var); unsigned int n_vec_dim = FEInterface::n_vec_dim( _mesh, fe_type ); // FIXME: MeshFunction needs to be updated to support vector-valued // elements before we can use a reference solution. if( (n_vec_dim > 1) && _equation_systems_fine ) { libMesh::err << "Error calculation using reference solution not yet\n" << "supported for vector-valued elements." << std::endl; libmesh_not_implemented(); } AutoPtr<QBase> qrule = fe_type.default_quadrature_rule (dim, _extra_order); // Construct finite element object AutoPtr<FEGenericBase<OutputShape> > fe(FEGenericBase<OutputShape>::build(dim, fe_type)); // Attach quadrature rule to FE object fe->attach_quadrature_rule (qrule.get()); // The Jacobian*weight at the quadrature points. const std::vector<Real>& JxW = fe->get_JxW(); // The value of the shape functions at the quadrature points // i.e. phi(i) = phi_values[i][qp] const std::vector<std::vector<OutputShape> >& phi_values = fe->get_phi(); // The value of the shape function gradients at the quadrature points const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> >& dphi_values = fe->get_dphi(); // The value of the shape function curls at the quadrature points // Only computed for vector-valued elements const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputShape> >* curl_values = NULL; // The value of the shape function divergences at the quadrature points // Only computed for vector-valued elements const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputDivergence> >* div_values = NULL; if( FEInterface::field_type(fe_type) == TYPE_VECTOR ) { curl_values = &fe->get_curl_phi(); div_values = &fe->get_div_phi(); } #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES // The value of the shape function second derivatives at the quadrature points const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> >& d2phi_values = fe->get_d2phi(); #endif // The XYZ locations (in physical space) of the quadrature points const std::vector<Point>& q_point = fe->get_xyz(); // The global degree of freedom indices associated // with the local degrees of freedom. std::vector<dof_id_type> dof_indices; // // Begin the loop over the elements // // TODO: this ought to be threaded (and using subordinate // MeshFunction objects in each thread rather than a single // master) MeshBase::const_element_iterator el = _mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = _mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem* elem = *el; // reinitialize the element-specific data // for the current element fe->reinit (elem); // Get the local to global degree of freedom maps computed_dof_map.dof_indices (elem, dof_indices, var); // The number of quadrature points const unsigned int n_qp = qrule->n_points(); // The number of shape functions const unsigned int n_sf = libmesh_cast_int<unsigned int>(dof_indices.size()); // // Begin the loop over the Quadrature points. // for (unsigned int qp=0; qp<n_qp; qp++) { // Real u_h = 0.; // RealGradient grad_u_h; typename FEGenericBase<OutputShape>::OutputNumber u_h = 0.; typename FEGenericBase<OutputShape>::OutputNumberGradient grad_u_h; #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES typename FEGenericBase<OutputShape>::OutputNumberTensor grad2_u_h; #endif typename FEGenericBase<OutputShape>::OutputNumber curl_u_h = 0.0; typename FEGenericBase<OutputShape>::OutputNumberDivergence div_u_h = 0.0; // Compute solution values at the current // quadrature point. This reqiures a sum // over all the shape functions evaluated // at the quadrature point. for (unsigned int i=0; i<n_sf; i++) { // Values from current solution. u_h += phi_values[i][qp]*computed_system.current_solution (dof_indices[i]); grad_u_h += dphi_values[i][qp]*computed_system.current_solution (dof_indices[i]); #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES grad2_u_h += d2phi_values[i][qp]*computed_system.current_solution (dof_indices[i]); #endif if( FEInterface::field_type(fe_type) == TYPE_VECTOR ) { curl_u_h += (*curl_values)[i][qp]*computed_system.current_solution (dof_indices[i]); div_u_h += (*div_values)[i][qp]*computed_system.current_solution (dof_indices[i]); } } // Compute the value of the error at this quadrature point typename FEGenericBase<OutputShape>::OutputNumber exact_val = 0; RawAccessor<typename FEGenericBase<OutputShape>::OutputNumber> exact_val_accessor( exact_val, dim ); if (_exact_values.size() > sys_num && _exact_values[sys_num]) { for( unsigned int c = 0; c < n_vec_dim; c++) exact_val_accessor(c) = _exact_values[sys_num]-> component(var_component+c, q_point[qp], time); } else if (_equation_systems_fine) { // FIXME: Needs to be updated for vector-valued elements exact_val = (*coarse_values)(q_point[qp]); } const typename FEGenericBase<OutputShape>::OutputNumber val_error = u_h - exact_val; // Add the squares of the error to each contribution Real error_sq = TensorTools::norm_sq(val_error); error_vals[0] += JxW[qp]*error_sq; Real norm = sqrt(error_sq); error_vals[3] += JxW[qp]*norm; if(error_vals[4]<norm) { error_vals[4] = norm; } // Compute the value of the error in the gradient at this // quadrature point typename FEGenericBase<OutputShape>::OutputNumberGradient exact_grad; RawAccessor<typename FEGenericBase<OutputShape>::OutputNumberGradient> exact_grad_accessor( exact_grad, _mesh.spatial_dimension() ); if (_exact_derivs.size() > sys_num && _exact_derivs[sys_num]) { for( unsigned int c = 0; c < n_vec_dim; c++) for( unsigned int d = 0; d < _mesh.spatial_dimension(); d++ ) exact_grad_accessor(d + c*_mesh.spatial_dimension() ) = _exact_derivs[sys_num]-> component(var_component+c, q_point[qp], time)(d); } else if (_equation_systems_fine) { // FIXME: Needs to be updated for vector-valued elements exact_grad = coarse_values->gradient(q_point[qp]); } const typename FEGenericBase<OutputShape>::OutputNumberGradient grad_error = grad_u_h - exact_grad; error_vals[1] += JxW[qp]*grad_error.size_sq(); if( FEInterface::field_type(fe_type) == TYPE_VECTOR ) { // Compute the value of the error in the curl at this // quadrature point typename FEGenericBase<OutputShape>::OutputNumber exact_curl = 0.0; if (_exact_derivs.size() > sys_num && _exact_derivs[sys_num]) { exact_curl = TensorTools::curl_from_grad( exact_grad ); } else if (_equation_systems_fine) { // FIXME: Need to implement curl for MeshFunction and support reference // solution for vector-valued elements } const typename FEGenericBase<OutputShape>::OutputNumber curl_error = curl_u_h - exact_curl; error_vals[5] += JxW[qp]*TensorTools::norm_sq(curl_error); // Compute the value of the error in the divergence at this // quadrature point typename FEGenericBase<OutputShape>::OutputNumberDivergence exact_div = 0.0; if (_exact_derivs.size() > sys_num && _exact_derivs[sys_num]) { exact_div = TensorTools::div_from_grad( exact_grad ); } else if (_equation_systems_fine) { // FIXME: Need to implement div for MeshFunction and support reference // solution for vector-valued elements } const typename FEGenericBase<OutputShape>::OutputNumberDivergence div_error = div_u_h - exact_div; error_vals[6] += JxW[qp]*TensorTools::norm_sq(div_error); } #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES // Compute the value of the error in the hessian at this // quadrature point typename FEGenericBase<OutputShape>::OutputNumberTensor exact_hess; RawAccessor<typename FEGenericBase<OutputShape>::OutputNumberTensor> exact_hess_accessor( exact_hess, dim ); if (_exact_hessians.size() > sys_num && _exact_hessians[sys_num]) { //FIXME: This needs to be implemented to support rank 3 tensors // which can't happen until type_n_tensor is fully implemented // and a RawAccessor<TypeNTensor> is fully implemented if( FEInterface::field_type(fe_type) == TYPE_VECTOR ) libmesh_not_implemented(); for( unsigned int c = 0; c < n_vec_dim; c++) for( unsigned int d = 0; d < dim; d++ ) for( unsigned int e =0; e < dim; e++ ) exact_hess_accessor(d + e*dim + c*dim*dim) = _exact_hessians[sys_num]-> component(var_component+c, q_point[qp], time)(d,e); } else if (_equation_systems_fine) { // FIXME: Needs to be updated for vector-valued elements exact_hess = coarse_values->hessian(q_point[qp]); } const typename FEGenericBase<OutputShape>::OutputNumberTensor grad2_error = grad2_u_h - exact_hess; // FIXME: PB: Is this what we want for rank 3 tensors? error_vals[2] += JxW[qp]*grad2_error.size_sq(); #endif } // end qp loop } // end element loop // Add up the error values on all processors, except for the L-infty // norm, for which the maximum is computed. Real l_infty_norm = error_vals[4]; CommWorld.max(l_infty_norm); CommWorld.sum(error_vals); error_vals[4] = l_infty_norm; }
void ParmetisPartitioner::_do_repartition (MeshBase& mesh, const unsigned int n_sbdmns) { libmesh_assert_greater (n_sbdmns, 0); // Check for an easy return if (n_sbdmns == 1) { this->single_partition(mesh); return; } // This function must be run on all processors at once parallel_only(); // What to do if the Parmetis library IS NOT present #ifndef LIBMESH_HAVE_PARMETIS libmesh_here(); libMesh::err << "ERROR: The library has been built without" << std::endl << "Parmetis support. Using a Metis" << std::endl << "partitioner instead!" << std::endl; MetisPartitioner mp; mp.partition (mesh, n_sbdmns); // What to do if the Parmetis library IS present #else // Revert to METIS on one processor. if (libMesh::n_processors() == 1) { MetisPartitioner mp; mp.partition (mesh, n_sbdmns); return; } START_LOG("repartition()", "ParmetisPartitioner"); // Initialize the data structures required by ParMETIS this->initialize (mesh, n_sbdmns); // Make sure all processors have enough active local elements. // Parmetis tends to crash when it's given only a couple elements // per partition. { bool all_have_enough_elements = true; for (unsigned int pid=0; pid<_n_active_elem_on_proc.size(); pid++) if (_n_active_elem_on_proc[pid] < MIN_ELEM_PER_PROC) all_have_enough_elements = false; // Parmetis will not work unless each processor has some // elements. Specifically, it will abort when passed a NULL // partition array on *any* of the processors. if (!all_have_enough_elements) { // FIXME: revert to METIS, although this requires a serial mesh MeshSerializer serialize(mesh); STOP_LOG ("repartition()", "ParmetisPartitioner"); MetisPartitioner mp; mp.partition (mesh, n_sbdmns); return; } } // build the graph corresponding to the mesh this->build_graph (mesh); // Partition the graph std::vector<int> vsize(_vwgt.size(), 1); float itr = 1000000.0; MPI_Comm mpi_comm = libMesh::COMM_WORLD; // Call the ParMETIS adaptive repartitioning method. This respects the // original partitioning when computing the new partitioning so as to // minimize the required data redistribution. Parmetis::ParMETIS_V3_AdaptiveRepart(_vtxdist.empty() ? NULL : &_vtxdist[0], _xadj.empty() ? NULL : &_xadj[0], _adjncy.empty() ? NULL : &_adjncy[0], _vwgt.empty() ? NULL : &_vwgt[0], vsize.empty() ? NULL : &vsize[0], NULL, &_wgtflag, &_numflag, &_ncon, &_nparts, _tpwgts.empty() ? NULL : &_tpwgts[0], _ubvec.empty() ? NULL : &_ubvec[0], &itr, &_options[0], &_edgecut, _part.empty() ? NULL : &_part[0], &mpi_comm); // Assign the returned processor ids this->assign_partitioning (mesh); STOP_LOG ("repartition()", "ParmetisPartitioner"); #endif // #ifndef LIBMESH_HAVE_PARMETIS ... else ... }