void MeshRefinement::flag_elements_by_error_tolerance (const ErrorVector & error_per_cell_in) { parallel_object_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); } for (auto & elem : _mesh.active_element_ptr_range()) { Elem * parent = elem->parent(); const dof_id_type elem_number = elem->id(); const ErrorVectorReal 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) { ErrorVectorReal 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 MeshRefinement::flag_elements_by_mean_stddev (const ErrorVector & error_per_cell, const Real refine_frac, const Real coarsen_frac, const unsigned int max_l) { // 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; } // Get the mean value from the error vector const Real mean = error_per_cell.mean(); // Get the standard deviation. This equals the // square-root of the variance const Real stddev = std::sqrt (error_per_cell.variance()); // Check for valid fractions 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 refine and coarsen cutoff const Real refine_cutoff = mean + _refine_fraction * stddev; const Real coarsen_cutoff = std::max(mean - _coarsen_fraction * stddev, 0.); // Loop over the elements and flag them for coarsening or // refinement based on the element error for (auto & elem : _mesh.active_element_ptr_range()) { const dof_id_type id = elem->id(); libmesh_assert_less (id, error_per_cell.size()); const ErrorVectorReal elem_error = error_per_cell[id]; // Possibly flag the element for coarsening ... if (elem_error <= coarsen_cutoff) elem->set_refinement_flag(Elem::COARSEN); // ... or refinement if ((elem_error >= refine_cutoff) && (elem->level() < _max_h_level)) elem->set_refinement_flag(Elem::REFINE); } }
// Builds and scales a Gauss rule and a Jacobi rule. // Then combines them to compute points and weights // of a 3D conical product rule for the Tet. void QConical::conical_product_tet(unsigned int p) { // Be sure the underlying rule object was built with the same dimension as the // rule we are about to construct. libmesh_assert_equal_to (this->get_dim(), 3); QGauss gauss1D(1,static_cast<Order>(_order+2*p)); QJacobi jacA1D(1,static_cast<Order>(_order+2*p),1,0); QJacobi jacB1D(1,static_cast<Order>(_order+2*p),2,0); // The Gauss rule needs to be scaled to [0,1] std::pair<Real, Real> old_range(-1.0L, 1.0L); std::pair<Real, Real> new_range( 0.0L, 1.0L); gauss1D.scale(old_range, new_range); // Now construct the points and weights for the conical product rule. // All rules should have the same number of points libmesh_assert_equal_to (gauss1D.n_points(), jacA1D.n_points()); libmesh_assert_equal_to (jacA1D.n_points(), jacB1D.n_points()); // Save the number of points as a convenient variable const unsigned int np = gauss1D.n_points(); // All rules should be between x=0 and x=1 libmesh_assert_greater_equal (gauss1D.qp(0)(0), 0.0); libmesh_assert_less_equal (gauss1D.qp(np-1)(0), 1.0); libmesh_assert_greater_equal (jacA1D.qp(0)(0), 0.0); libmesh_assert_less_equal (jacA1D.qp(np-1)(0), 1.0); libmesh_assert_greater_equal (jacB1D.qp(0)(0), 0.0); libmesh_assert_less_equal (jacB1D.qp(np-1)(0), 1.0); // Resize the points and weights vectors _points.resize(np * np * np); _weights.resize(np * np * np); // Compute the conical product unsigned int gp = 0; for (unsigned int i=0; i<np; i++) for (unsigned int j=0; j<np; j++) for (unsigned int k=0; k<np; k++) { _points[gp](0) = jacB1D.qp(k)(0); //t[k]; _points[gp](1) = jacA1D.qp(j)(0) * (1.-jacB1D.qp(k)(0)); //s[j]*(1.-t[k]); _points[gp](2) = gauss1D.qp(i)(0) * (1.-jacA1D.qp(j)(0)) * (1.-jacB1D.qp(k)(0)); //r[i]*(1.-s[j])*(1.-t[k]); _weights[gp] = gauss1D.w(i) * jacA1D.w(j) * jacB1D.w(k); //A[i]*B[j]*C[k]; gp++; } }
void EpetraVector<T>::localize (const numeric_index_type first_local_idx, const numeric_index_type last_local_idx, const std::vector<numeric_index_type> & send_list) { // Only good for serial vectors. libmesh_assert_equal_to (this->size(), this->local_size()); libmesh_assert_greater (last_local_idx, first_local_idx); libmesh_assert_less_equal (send_list.size(), this->size()); libmesh_assert_less (last_local_idx, this->size()); const unsigned int my_size = this->size(); const unsigned int my_local_size = (last_local_idx - first_local_idx + 1); // Don't bother for serial cases if ((first_local_idx == 0) && (my_local_size == my_size)) return; // Build a parallel vector, initialize it with the local // parts of (*this) EpetraVector<T> parallel_vec(this->comm(), PARALLEL); parallel_vec.init (my_size, my_local_size, true, PARALLEL); // Copy part of *this into the parallel_vec for (numeric_index_type i=first_local_idx; i<=last_local_idx; i++) parallel_vec.set(i,this->el(i)); // localize like normal parallel_vec.close(); parallel_vec.localize (*this, send_list); this->close(); }
void Edge3::connectivity(const unsigned int sc, const IOPackage iop, std::vector<unsigned int>& conn) const { libmesh_assert_less_equal (sc, 1); libmesh_assert_less (sc, this->n_sub_elem()); libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE); // Create storage conn.resize(2); switch (iop) { case TECPLOT: { switch (sc) { case 0: conn[0] = this->node(0)+1; conn[1] = this->node(2)+1; return; case 1: conn[0] = this->node(2)+1; conn[1] = this->node(1)+1; return; default: libmesh_error(); } } case VTK: { switch (sc) { case 0: conn[0] = this->node(0); conn[1] = this->node(2); return; case 1: conn[0] = this->node(2); conn[1] = this->node(1); return; default: libmesh_error(); } } default: { libmesh_error(); } } }
// ------------------------------------------------------------ // MeshBase class member functions MeshBase::MeshBase (const Parallel::Communicator & comm_in, unsigned char d) : ParallelObject (comm_in), boundary_info (new BoundaryInfo(*this)), _n_parts (1), _is_prepared (false), _point_locator (), _count_lower_dim_elems_in_point_locator(true), _partitioner (), #ifdef LIBMESH_ENABLE_UNIQUE_ID _next_unique_id(DofObject::invalid_unique_id), #endif _skip_noncritical_partitioning(false), _skip_all_partitioning(libMesh::on_command_line("--skip-partitioning")), _skip_renumber_nodes_and_elements(false), _allow_remote_element_removal(true), _spatial_dimension(d), _default_ghosting(new GhostPointNeighbors(*this)), _point_locator_close_to_point_tol(0.) { _elem_dims.insert(d); _ghosting_functors.insert(_default_ghosting.get()); libmesh_assert_less_equal (LIBMESH_DIM, 3); libmesh_assert_greater_equal (LIBMESH_DIM, d); libmesh_assert (libMesh::initialized()); }
Real FE<1,SZABAB>::shape_deriv(const ElemType, const Order libmesh_dbg_var(order), const unsigned int i, const unsigned int libmesh_dbg_var(j), const Point& p) { // only d()/dxi in 1D! libmesh_assert_equal_to (j, 0); const Real xi = p(0); const Real xi2 = xi*xi; // Use this libmesh_assert rather than a switch with a single entry... // It will go away in optimized mode, essentially has the same effect. libmesh_assert_less_equal (order, SEVENTH); // switch (order) // { // case FIRST: // case SECOND: // case THIRD: // case FOURTH: // case FIFTH: // case SIXTH: // case SEVENTH: switch(i) { case 0: return -1./2.; case 1: return 1./2.; case 2: return 1./2.*2.4494897427831780982*xi; case 3: return -1./4.*3.1622776601683793320+3./4.*3.1622776601683793320*xi2; case 4: return 1./16.*3.7416573867739413856*(-12.+20*xi2)*xi; case 5: return 9./16.*1.4142135623730950488+(-45./8.*1.4142135623730950488+105./16.*1.4142135623730950488*xi2)*xi2; case 6: return 1./32.*4.6904157598234295546*(30.+(-140.+126.*xi2)*xi2)*xi; case 7: return -5./32.*5.0990195135927848300+(105./32.*5.0990195135927848300+(-315./32.*5.0990195135927848300+231./32.*5.0990195135927848300*xi2)*xi2)*xi2; case 8: return 1./256.*5.4772255750516611346*(-280.+(2520.+(-5544.+3432.*xi2)*xi2)*xi2)*xi; default: libMesh::err << "Invalid shape function index!" << std::endl; libmesh_error(); } // default: // { // libMesh::err << "ERROR: Unsupported polynomial order!" << std::endl; // libmesh_error(); // } // } libmesh_error(); return 0.; }
void EigenSparseVector<T>::localize (NumericVector<T>& v_local_in, const std::vector<numeric_index_type>& libmesh_dbg_var(send_list)) const { // Make sure the NumericVector passed in is really a EigenSparseVector EigenSparseVector<T>* v_local = libmesh_cast_ptr<EigenSparseVector<T>*>(&v_local_in); libmesh_assert(v_local); libmesh_assert_less_equal (send_list.size(), v_local->size()); *v_local = *this; }
void MAST::Examples::ExampleBase::update_load_parameters(Real scale) { libmesh_assert_greater_equal(scale, 0.); libmesh_assert_less_equal (scale, 1.); std::map<MAST::Parameter*, const Real>::iterator it = _load_parameters.begin(), end = _load_parameters.end(); for ( ; it != end; it++) (*it->first) = scale*it->second; }
void EigenSparseVector<T>::localize (const numeric_index_type libmesh_dbg_var(first_local_idx), const numeric_index_type libmesh_dbg_var(last_local_idx), const std::vector<numeric_index_type>& libmesh_dbg_var(send_list)) { libmesh_assert_equal_to (first_local_idx, 0); libmesh_assert_equal_to (last_local_idx+1, this->size()); libmesh_assert_less_equal (send_list.size(), this->size()); #ifndef NDEBUG this->_is_closed = true; #endif }
Real FE<1,SZABAB>::shape(const ElemType, const Order libmesh_dbg_var(order), const unsigned int i, const Point& p) { const Real xi = p(0); const Real xi2 = xi*xi; // Use this libmesh_assert rather than a switch with a single entry... // It will go away in optimized mode, essentially has the same effect. libmesh_assert_less_equal (order, SEVENTH); // switch (order) // { // case FIRST: // case SECOND: // case THIRD: // case FOURTH: // case FIFTH: // case SIXTH: // case SEVENTH: switch(i) { //nodal shape functions case 0: return 1./2.-1./2.*xi; case 1: return 1./2.+1./2.*xi; case 2: return 1./4. *2.4494897427831780982*(xi2-1.); case 3: return 1./4. *3.1622776601683793320*(xi2-1.)*xi; case 4: return 1./16. *3.7416573867739413856*((5.*xi2-6.)*xi2+1.); case 5: return 3./16. *1.4142135623730950488*(3.+(-10.+7.*xi2)*xi2)*xi; case 6: return 1./32. *4.6904157598234295546*(-1.+(15.+(-35.+21.*xi2)*xi2)*xi2); case 7: return 1./32. *5.0990195135927848300*(-5.+(35.+(-63.+33.*xi2)*xi2)*xi2)*xi; case 8: return 1./256.*5.4772255750516611346*(5.+(-140.+(630.+(-924.+429.*xi2)*xi2)*xi2)*xi2); default: libMesh::err << "Invalid shape function index!" << std::endl; libmesh_error(); } // default: // { // libMesh::err << "ERROR: Unsupported polynomial order!" << std::endl; // libmesh_error(); // } // } libmesh_error(); return 0.; }
// ------------------------------------------------------------ // MeshBase class member functions MeshBase::MeshBase (unsigned int d) : boundary_info (new BoundaryInfo(*this)), _n_parts (1), _dim (d), _is_prepared (false), _point_locator (NULL), _partitioner (NULL), _skip_partitioning(false), _skip_renumber_nodes_and_elements(false) { libmesh_assert_less_equal (LIBMESH_DIM, 3); libmesh_assert_greater_equal (LIBMESH_DIM, _dim); libmesh_assert (libMesh::initialized()); }
Real SystemNorm::calculate_norm(const std::vector<Real> & v1, const std::vector<Real> & v2) { // The vectors are assumed to both be vectors of the (same number // of) components std::size_t vsize = v1.size(); libmesh_assert_equal_to (vsize, v2.size()); // We'll support implicitly defining weights, but if the user sets // more weights than he uses then something's probably wrong std::size_t diagsize = this->_weights.size(); libmesh_assert_greater_equal (vsize, diagsize); // Initialize the variable val Real val = 0.; // Loop over all the components of the system with explicit // weights for (std::size_t i = 0; i != diagsize; i++) { val += this->_weights[i] * v1[i] * v2[i]; } // Loop over all the components of the system with implicit // weights for (std::size_t i = diagsize; i < vsize; i++) { val += v1[i] * v2[i]; } // Loop over the components of the system std::size_t nrows = this->_off_diagonal_weights.size(); libmesh_assert_less_equal (vsize, nrows); for (std::size_t i = 0; i != nrows; i++) { std::size_t ncols = this->_off_diagonal_weights[i].size(); for (std::size_t j=0; j != ncols; j++) { // The diagonal weights here were set to zero in the // constructor. val += this->_off_diagonal_weights[i][j] * v1[i] * v2[j]; } } return(val); }
MeshBase::MeshBase (unsigned char d) : ParallelObject (CommWorld), boundary_info (new BoundaryInfo(*this)), _n_parts (1), _is_prepared (false), _point_locator (), _partitioner (), #ifdef LIBMESH_ENABLE_UNIQUE_ID _next_unique_id(DofObject::invalid_unique_id), #endif _skip_partitioning(libMesh::on_command_line("--skip-partitioning")), _skip_renumber_nodes_and_elements(false) { _elem_dims.insert(d); libmesh_assert_less_equal (LIBMESH_DIM, 3); libmesh_assert_greater_equal (LIBMESH_DIM, d); libmesh_assert (libMesh::initialized()); }
// ------------------------------------------------------------ // MeshBase class member functions MeshBase::MeshBase (const Parallel::Communicator &comm_in, unsigned int d) : ParallelObject (comm_in), boundary_info (new BoundaryInfo(*this)), _n_parts (1), _dim (d), _is_prepared (false), _point_locator (NULL), _partitioner (NULL), #ifdef LIBMESH_ENABLE_UNIQUE_ID _next_unique_id(DofObject::invalid_unique_id), #endif _skip_partitioning(false), _skip_renumber_nodes_and_elements(false) { libmesh_assert_less_equal (LIBMESH_DIM, 3); libmesh_assert_greater_equal (LIBMESH_DIM, _dim); libmesh_assert (libMesh::initialized()); }
Real FE<1,MONOMIAL>::shape_deriv(const ElemType, const Order libmesh_dbg_var(order), const unsigned int i, const unsigned int libmesh_dbg_var(j), const Point& p) { // only d()/dxi in 1D! libmesh_assert_equal_to (j, 0); const Real xi = p(0); libmesh_assert_less_equal (i, static_cast<unsigned int>(order)); // monomials. since they are hierarchic we only need one case block. switch (i) { case 0: return 0.; case 1: return 1.; case 2: return 2.*xi; case 3: return 3.*xi*xi; case 4: return 4.*xi*xi*xi; default: Real val = i; for (unsigned int index = 1; index != i; ++index) val *= xi; return val; } libmesh_error(); return 0.; }
Real FE<1,MONOMIAL>::shape_second_deriv(const ElemType, const Order libmesh_dbg_var(order), const unsigned int i, const unsigned int libmesh_dbg_var(j), const Point& p) { // only d()/dxi in 1D! libmesh_assert_equal_to (j, 0); const Real xi = p(0); libmesh_assert_less_equal (i, static_cast<unsigned int>(order)); switch (i) { case 0: case 1: return 0.; case 2: return 2.; case 3: return 6.*xi; case 4: return 12.*xi*xi; default: Real val = 2.; for (unsigned int index = 2; index != i; ++index) val *= (index+1) * xi; return val; } libmesh_error(); return 0.; }
// FIXME: it'll be tricky getting this to work with 64-bit dof_id_type void DofObject::unpack_indexing(std::vector<int>::const_iterator begin) { _idx_buf.clear(); #ifdef LIBMESH_ENABLE_AMR this->clear_old_dof_object(); const int has_old_dof_object = *begin++; libmesh_assert(has_old_dof_object == 1 || has_old_dof_object == 0); #endif const int size = *begin++; _idx_buf.reserve(size); std::copy(begin, begin+size, back_inserter(_idx_buf)); // Check as best we can for internal consistency now libmesh_assert(_idx_buf.empty() || (_idx_buf[0] <= _idx_buf.size())); #ifdef DEBUG if (!_idx_buf.empty()) for (unsigned int i=1; i < _idx_buf[0]; ++i) { libmesh_assert_greater_equal (_idx_buf[i], _idx_buf[i-1]); libmesh_assert_equal_to ((_idx_buf[i] - _idx_buf[i-1])%2, 0); libmesh_assert_less_equal (_idx_buf[i], _idx_buf.size()); } #endif #ifdef LIBMESH_ENABLE_AMR if (has_old_dof_object) { this->old_dof_object = new DofObject(); this->old_dof_object->unpack_indexing(begin+size); } #endif }
void XdrMGF::init (XdrMGF::XdrIO_TYPE t, const char* fn, const char*, int) { m_type=t; // Close old file if necessary if (mp_fp) this->fini(); // Open file switch (m_type) { #ifdef LIBMESH_HAVE_XDR case (XdrMGF::ENCODE): case (XdrMGF::DECODE): { mp_fp = fopen (fn, (m_type == ENCODE) ? "w" : "r"); // Make sure the file is ready for use if (!mp_fp) libmesh_error_msg("XDR Error: Accessing file: " << fn << " failed."); // Create the XDR handle mp_xdr_handle = new XDR; xdrstdio_create(mp_xdr_handle, mp_fp, ((m_type == ENCODE) ? XDR_ENCODE : XDR_DECODE)); break; } #endif case (XdrMGF::R_ASCII): { mp_in.open(fn, std::ios::in); // Make sure it opened correctly if (!mp_in.good()) libmesh_file_error(fn); break; } case (XdrMGF::W_ASCII): { mp_out.open(fn, std::ios::out); // Make sure it opened correctly if (!mp_out.good()) libmesh_file_error(fn); break; } default: libmesh_error_msg("Unrecognized file access type!"); } // Read/Write the file signature const int bufLen = 12; char buf[bufLen+1]; switch (m_type) { #ifdef LIBMESH_HAVE_XDR case (XdrMGF::ENCODE): { char* p = &buf[0]; const LegacyXdrIO::FileFormat orig = this->get_orig_flag(); std::ostringstream name; if (orig == LegacyXdrIO::DEAL) name << "DEAL 003:003"; else if (orig == LegacyXdrIO::MGF) name << "MGF 002:000"; else if (orig == LegacyXdrIO::LIBM) name << "LIBM " << this->get_num_levels(); else libmesh_error_msg("Unknown orig " << orig); // Fill the buffer std::sprintf(&buf[0], "%s", name.str().c_str()); xdr_string(mp_xdr_handle, &p, bufLen); // Writes binary signature break; } case (XdrMGF::DECODE): { char* p = &buf[0]; xdr_string(mp_xdr_handle, &p, bufLen); // Reads binary signature // Set the number of levels used in the mesh this->tokenize_first_line(p); break; } #endif case (XdrMGF::W_ASCII): { const LegacyXdrIO::FileFormat orig = this->get_orig_flag(); if (orig == LegacyXdrIO::DEAL) std::sprintf(&buf[0], "%s %03d:%03d", "DEAL", 3, 3); else if (orig == LegacyXdrIO::MGF) std::sprintf(&buf[0], "%s %03d:%03d", "MGF ", 2, 0); else if (orig == LegacyXdrIO::LIBM) std::sprintf(&buf[0], "%s %d", "LIBM", this->get_num_levels()); mp_out << buf << '\n'; break; } case (XdrMGF::R_ASCII): { #ifdef __HP_aCC // weirdly, _only_ here aCC // is not fond of mp_in.getline() // however, using mp_in.getline() // further below is ok... std::string buf_buf; std::getline (mp_in, buf_buf, '\n'); libmesh_assert_less_equal (buf_buf.size(), bufLen); buf_buf.copy (buf, std::string::npos); #else // Here we first use getline() to grab the very // first line of the file into a char buffer. Then // this line is tokenized to look for: // 1.) The name LIBM, which specifies the new Mesh style. // 2.) The number of levels in the Mesh which is being read. // Note that "buf" will be further processed below, here we // are just attempting to get the number of levels. mp_in.getline(buf, bufLen+1); #endif // Determine the number of levels in this mesh this->tokenize_first_line(buf); break; } default: libmesh_error_msg("Unknown m_type" << m_type); } // If you are reading or decoding, process the signature if ((m_type == R_ASCII) || (m_type == DECODE)) { char name[5]; std::strncpy(name, &buf[0], 4); name[4] = '\0'; if (std::strcmp (name, "DEAL") == 0) { this->orig_flag = LegacyXdrIO::DEAL; // 0 is the DEAL identifier by definition } else if (std::strcmp (name, "MGF ") == 0) { this->orig_flag = LegacyXdrIO::MGF; // 1 is the MGF identifier by definition } else if (std::strcmp (name, "LIBM") == 0) { this->orig_flag = LegacyXdrIO::LIBM; // the New and Improved XDA } else libmesh_error_msg("ERROR: No originating software can be determined for header string '" << name); } }
RealGradient FE<3,NEDELEC_ONE>::shape_second_deriv(const Elem * elem, const Order order, const unsigned int i, const unsigned int j, const Point & libmesh_dbg_var(p)) { #if LIBMESH_DIM == 3 libmesh_assert(elem); // j = 0 ==> d^2 phi / dxi^2 // j = 1 ==> d^2 phi / dxi deta // j = 2 ==> d^2 phi / deta^2 // j = 3 ==> d^2 phi / dxi dzeta // j = 4 ==> d^2 phi / deta dzeta // j = 5 ==> d^2 phi / dzeta^2 libmesh_assert_less (j, 6); const Order totalorder = static_cast<Order>(order + elem->p_level()); switch (totalorder) { // linear Lagrange shape functions case FIRST: { switch (elem->type()) { case HEX20: case HEX27: { libmesh_assert_less (i, 12); #ifndef NDEBUG const Real xi = p(0); const Real eta = p(1); const Real zeta = p(2); #endif libmesh_assert_less_equal ( std::fabs(xi), 1.0+TOLERANCE ); libmesh_assert_less_equal ( std::fabs(eta), 1.0+TOLERANCE ); libmesh_assert_less_equal ( std::fabs(zeta), 1.0+TOLERANCE ); switch (j) { // d^2()/dxi^2 case 0: { // All d^2()/dxi^2 derivatives for linear hexes are zero. return RealGradient(); } // j=0 // d^2()/dxideta case 1: { switch(i) { case 0: case 1: case 2: case 3: case 8: case 9: case 10: case 11: return RealGradient(); case 4: { if( elem->point(0) > elem->point(4) ) return RealGradient( 0.0, 0.0, -0.125 ); else return RealGradient( 0.0, 0.0, 0.125 ); } case 5: { if( elem->point(1) > elem->point(5) ) return RealGradient( 0.0, 0.0, 0.125 ); else return RealGradient( 0.0, 0.0, -0.125 ); } case 6: { if( elem->point(2) > elem->point(6) ) return RealGradient( 0.0, 0.0, -0.125 ); else return RealGradient( 0.0, 0.0, 0.125 ); } case 7: { if( elem->point(3) > elem->point(7) ) return RealGradient( 0.0, 0.0, 0.125 ); else return RealGradient( 0.0, 0.0, -0.125 ); } default: libmesh_error_msg("Invalid i = " << i); } // switch(i) } // j=1 // d^2()/deta^2 case 2: { // All d^2()/deta^2 derivatives for linear hexes are zero. return RealGradient(); } // j = 2 // d^2()/dxidzeta case 3: { switch(i) { case 0: case 2: case 4: case 5: case 6: case 7: case 8: case 10: return RealGradient(); case 1: { if( elem->point(1) > elem->point(2) ) return RealGradient( 0.0, 0.125 ); else return RealGradient( 0.0, -0.125 ); } case 3: { if( elem->point(3) > elem->point(0) ) return RealGradient( 0.0, -0.125 ); else return RealGradient( 0.0, 0.125 ); } case 9: { if( elem->point(5) > elem->point(6) ) return RealGradient( 0.0, -0.125, 0.0 ); else return RealGradient( 0.0, 0.125, 0.0 ); } case 11: { if( elem->point(4) > elem->point(7) ) return RealGradient( 0.0, 0.125, 0.0 ); else return RealGradient( 0.0, -0.125, 0.0 ); } default: libmesh_error_msg("Invalid i = " << i); } // switch(i) } // j = 3 // d^2()/detadzeta case 4: { switch(i) { case 1: case 3: case 4: case 5: case 6: case 7: case 9: case 11: return RealGradient(); case 0: { if( elem->point(0) > elem->point(1) ) return RealGradient( -0.125, 0.0, 0.0 ); else return RealGradient( 0.125, 0.0, 0.0 ); } case 2: { if( elem->point(2) > elem->point(3) ) return RealGradient( 0.125, 0.0, 0.0 ); else return RealGradient( -0.125, 0.0, 0.0 ); } case 8: { if( elem->point(4) > elem->point(5) ) return RealGradient( 0.125, 0.0, 0.0 ); else return RealGradient( -0.125, 0.0, 0.0 ); } case 10: { if( elem->point(7) > elem->point(6) ) return RealGradient( -0.125, 0.0, 0.0 ); else return RealGradient( 0.125, 0.0, 0.0 ); } default: libmesh_error_msg("Invalid i = " << i); } // switch(i) } // j = 4 // d^2()/dzeta^2 case 5: { // All d^2()/dzeta^2 derivatives for linear hexes are zero. return RealGradient(); } // j = 5 default: libmesh_error_msg("Invalid j = " << j); } return RealGradient(); } case TET10: { libmesh_assert_less (i, 6); libmesh_not_implemented(); return RealGradient(); } default: libmesh_error_msg("ERROR: Unsupported 3D element type!: " << elem->type()); } //switch(type) } // case FIRST: // unsupported order default: libmesh_error_msg("ERROR: Unsupported 3D FE order!: " << totalorder); } #endif libmesh_error_msg("We'll never get here!"); return RealGradient(); }
RealGradient FE<3,NEDELEC_ONE>::shape(const Elem * elem, const Order order, const unsigned int i, const Point & p) { #if LIBMESH_DIM == 3 libmesh_assert(elem); const Order totalorder = static_cast<Order>(order + elem->p_level()); switch (totalorder) { // linear Lagrange shape functions case FIRST: { switch (elem->type()) { case HEX20: case HEX27: { libmesh_assert_less (i, 12); const Real xi = p(0); const Real eta = p(1); const Real zeta = p(2); // Even with a loose inverse_map tolerance we ought to // be nearly on the element interior in master // coordinates libmesh_assert_less_equal ( std::fabs(xi), 1.0+10*TOLERANCE ); libmesh_assert_less_equal ( std::fabs(eta), 1.0+10*TOLERANCE ); libmesh_assert_less_equal ( std::fabs(zeta), 1.0+10*TOLERANCE ); switch(i) { case 0: { if( elem->point(0) > elem->point(1) ) return RealGradient( -0.125*(1.0-eta-zeta+eta*zeta), 0.0, 0.0 ); else return RealGradient( 0.125*(1.0-eta-zeta+eta*zeta), 0.0, 0.0 ); } case 1: { if( elem->point(1) > elem->point(2) ) return RealGradient( 0.0, -0.125*(1.0+xi-zeta-xi*zeta), 0.0 ); else return RealGradient( 0.0, 0.125*(1.0+xi-zeta-xi*zeta), 0.0 ); } case 2: { if( elem->point(2) > elem->point(3) ) return RealGradient( 0.125*(1.0+eta-zeta-eta*zeta), 0.0, 0.0 ); else return RealGradient( -0.125*(1.0+eta-zeta-eta*zeta), 0.0, 0.0 ); } case 3: { if( elem->point(3) > elem->point(0) ) return RealGradient( 0.0, 0.125*(1.0-xi-zeta+xi*zeta), 0.0 ); else return RealGradient( 0.0, -0.125*(1.0-xi-zeta+xi*zeta), 0.0 ); } case 4: { if( elem->point(0) > elem->point(4) ) return RealGradient( 0.0, 0.0, -0.125*(1.0-xi-eta+xi*eta) ); else return RealGradient( 0.0, 0.0, 0.125*(1.0-xi-eta+xi*eta) ); } case 5: { if( elem->point(1) > elem->point(5) ) return RealGradient( 0.0, 0.0, -0.125*(1.0+xi-eta-xi*eta) ); else return RealGradient( 0.0, 0.0, 0.125*(1.0+xi-eta-xi*eta) ); } case 6: { if( elem->point(2) > elem->point(6) ) return RealGradient( 0.0, 0.0, -0.125*(1.0+xi+eta+xi*eta) ); else return RealGradient( 0.0, 0.0, 0.125*(1.0+xi+eta+xi*eta) ); } case 7: { if( elem->point(3) > elem->point(7) ) return RealGradient( 0.0, 0.0, -0.125*(1.0-xi+eta-xi*eta) ); else return RealGradient( 0.0, 0.0, 0.125*(1.0-xi+eta-xi*eta) ); } case 8: { if( elem->point(4) > elem->point(5) ) return RealGradient( -0.125*(1.0-eta+zeta-eta*zeta), 0.0, 0.0 ); else return RealGradient( 0.125*(1.0-eta+zeta-eta*zeta), 0.0, 0.0 ); } case 9: { if( elem->point(5) > elem->point(6) ) return RealGradient( 0.0, -0.125*(1.0+xi+zeta+xi*zeta), 0.0 ); else return RealGradient( 0.0, 0.125*(1.0+xi+zeta+xi*zeta), 0.0 ); } case 10: { if( elem->point(7) > elem->point(6) ) return RealGradient( -0.125*(1.0+eta+zeta+eta*zeta), 0.0, 0.0 ); else return RealGradient( 0.125*(1.0+eta+zeta+eta*zeta), 0.0, 0.0 ); } case 11: { if( elem->point(4) > elem->point(7) ) return RealGradient( 0.0, -0.125*(1.0-xi+zeta-xi*zeta), 0.0 ); else return RealGradient( 0.0, 0.125*(1.0-xi+zeta-xi*zeta), 0.0 ); } default: libmesh_error_msg("Invalid i = " << i); } return RealGradient(); } case TET10: { libmesh_assert_less (i, 6); libmesh_not_implemented(); return RealGradient(); } default: libmesh_error_msg("ERROR: Unsupported 3D element type!: " << elem->type()); } } // unsupported order default: libmesh_error_msg("ERROR: Unsupported 3D FE order!: " << totalorder); } #endif libmesh_error_msg("We'll never get here!"); return RealGradient(); }
void ParmetisPartitioner::initialize (const MeshBase & mesh, const unsigned int n_sbdmns) { const dof_id_type n_active_local_elem = mesh.n_active_local_elem(); // Set parameters. _pmetis->wgtflag = 2; // weights on vertices only _pmetis->ncon = 1; // one weight per vertex _pmetis->numflag = 0; // C-style 0-based numbering _pmetis->nparts = static_cast<Parmetis::idx_t>(n_sbdmns); // number of subdomains to create _pmetis->edgecut = 0; // the numbers of edges cut by the // partition // Initialize data structures for ParMETIS _pmetis->vtxdist.resize (mesh.n_processors()+1); std::fill (_pmetis->vtxdist.begin(), _pmetis->vtxdist.end(), 0); _pmetis->tpwgts.resize (_pmetis->nparts); std::fill (_pmetis->tpwgts.begin(), _pmetis->tpwgts.end(), 1./_pmetis->nparts); _pmetis->ubvec.resize (_pmetis->ncon); std::fill (_pmetis->ubvec.begin(), _pmetis->ubvec.end(), 1.05); _pmetis->part.resize (n_active_local_elem); std::fill (_pmetis->part.begin(), _pmetis->part.end(), 0); _pmetis->options.resize (5); _pmetis->vwgt.resize (n_active_local_elem); // Set the options _pmetis->options[0] = 1; // don't use default options _pmetis->options[1] = 0; // default (level of timing) _pmetis->options[2] = 15; // random seed (default) _pmetis->options[3] = 2; // processor distribution and subdomain distribution are decoupled // Find the number of active elements on each processor. We cannot use // mesh.n_active_elem_on_proc(pid) since that only returns the number of // elements assigned to pid which are currently stored on the calling // processor. This will not in general be correct for parallel meshes // when (pid!=mesh.processor_id()). _n_active_elem_on_proc.resize(mesh.n_processors()); mesh.comm().allgather(n_active_local_elem, _n_active_elem_on_proc); // count the total number of active elements in the mesh. Note we cannot // use mesh.n_active_elem() in general since this only returns the number // of active elements which are stored on the calling processor. // We should not use n_active_elem for any allocation because that will // be inheritly unscalable, but it can be useful for libmesh_assertions. dof_id_type n_active_elem=0; // Set up the vtxdist array. This will be the same on each processor. // ***** Consult the Parmetis documentation. ***** libmesh_assert_equal_to (_pmetis->vtxdist.size(), cast_int<std::size_t>(mesh.n_processors()+1)); libmesh_assert_equal_to (_pmetis->vtxdist[0], 0); for (processor_id_type pid=0; pid<mesh.n_processors(); pid++) { _pmetis->vtxdist[pid+1] = _pmetis->vtxdist[pid] + _n_active_elem_on_proc[pid]; n_active_elem += _n_active_elem_on_proc[pid]; } libmesh_assert_equal_to (_pmetis->vtxdist.back(), static_cast<Parmetis::idx_t>(n_active_elem)); // ParMetis expects the elements to be numbered in contiguous blocks // by processor, i.e. [0, ne0), [ne0, ne0+ne1), ... // Since we only partition active elements we should have no expectation // that we currently have such a distribution. So we need to create it. // Also, at the same time we are going to map all the active elements into a globally // unique range [0,n_active_elem) which is *independent* of the current partitioning. // This can be fed to ParMetis as the initial partitioning of the subdomains (decoupled // from the partitioning of the objects themselves). This allows us to get the same // resultant partitioning independed of the input partitioning. MeshTools::BoundingBox bbox = MeshTools::bounding_box(mesh); _global_index_by_pid_map.clear(); // Maps active element ids into a contiguous range independent of partitioning. // (only needs local scope) vectormap<dof_id_type, dof_id_type> global_index_map; { std::vector<dof_id_type> global_index; // create the mapping which is contiguous by processor dof_id_type pid_offset=0; for (processor_id_type pid=0; pid<mesh.n_processors(); pid++) { MeshBase::const_element_iterator it = mesh.active_pid_elements_begin(pid); const MeshBase::const_element_iterator end = mesh.active_pid_elements_end(pid); // note that we may not have all (or any!) the active elements which belong on this processor, // but by calling this on all processors a unique range in [0,_n_active_elem_on_proc[pid]) // is constructed. Only the indices for the elements we pass in are returned in the array. MeshCommunication().find_global_indices (mesh.comm(), bbox, it, end, global_index); for (dof_id_type cnt=0; it != end; ++it) { const Elem * elem = *it; libmesh_assert (!_global_index_by_pid_map.count(elem->id())); libmesh_assert_less (cnt, global_index.size()); libmesh_assert_less (global_index[cnt], _n_active_elem_on_proc[pid]); _global_index_by_pid_map.insert(std::make_pair(elem->id(), global_index[cnt++] + pid_offset)); } pid_offset += _n_active_elem_on_proc[pid]; } // create the unique mapping for all active elements independent of partitioning { MeshBase::const_element_iterator it = mesh.active_elements_begin(); const MeshBase::const_element_iterator end = mesh.active_elements_end(); // Calling this on all processors a unique range in [0,n_active_elem) is constructed. // Only the indices for the elements we pass in are returned in the array. MeshCommunication().find_global_indices (mesh.comm(), bbox, it, end, global_index); for (dof_id_type cnt=0; it != end; ++it) { const Elem * elem = *it; libmesh_assert (!global_index_map.count(elem->id())); libmesh_assert_less (cnt, global_index.size()); libmesh_assert_less (global_index[cnt], n_active_elem); global_index_map.insert(std::make_pair(elem->id(), global_index[cnt++])); } } // really, shouldn't be close! libmesh_assert_less_equal (global_index_map.size(), n_active_elem); libmesh_assert_less_equal (_global_index_by_pid_map.size(), n_active_elem); // At this point the two maps should be the same size. If they are not // then the number of active elements is not the same as the sum over all // processors of the number of active elements per processor, which means // there must be some unpartitioned objects out there. if (global_index_map.size() != _global_index_by_pid_map.size()) libmesh_error_msg("ERROR: ParmetisPartitioner cannot handle unpartitioned objects!"); } // Finally, we need to initialize the vertex (partition) weights and the initial subdomain // mapping. The subdomain mapping will be independent of the processor mapping, and is // defined by a simple mapping of the global indices we just found. { std::vector<dof_id_type> subdomain_bounds(mesh.n_processors()); const dof_id_type first_local_elem = _pmetis->vtxdist[mesh.processor_id()]; for (processor_id_type pid=0; pid<mesh.n_processors(); pid++) { dof_id_type tgt_subdomain_size = 0; // watch out for the case that n_subdomains < n_processors if (pid < static_cast<unsigned int>(_pmetis->nparts)) { tgt_subdomain_size = n_active_elem/std::min (cast_int<Parmetis::idx_t>(mesh.n_processors()), _pmetis->nparts); if (pid < n_active_elem%_pmetis->nparts) tgt_subdomain_size++; } if (pid == 0) subdomain_bounds[0] = tgt_subdomain_size; else subdomain_bounds[pid] = subdomain_bounds[pid-1] + tgt_subdomain_size; } libmesh_assert_equal_to (subdomain_bounds.back(), n_active_elem); MeshBase::const_element_iterator elem_it = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator elem_end = mesh.active_local_elements_end(); for (; elem_it != elem_end; ++elem_it) { const Elem * elem = *elem_it; libmesh_assert (_global_index_by_pid_map.count(elem->id())); const dof_id_type global_index_by_pid = _global_index_by_pid_map[elem->id()]; libmesh_assert_less (global_index_by_pid, n_active_elem); const dof_id_type local_index = global_index_by_pid - first_local_elem; libmesh_assert_less (local_index, n_active_local_elem); libmesh_assert_less (local_index, _pmetis->vwgt.size()); // TODO:[BSK] maybe there is a better weight? _pmetis->vwgt[local_index] = elem->n_nodes(); // find the subdomain this element belongs in libmesh_assert (global_index_map.count(elem->id())); const dof_id_type global_index = global_index_map[elem->id()]; libmesh_assert_less (global_index, subdomain_bounds.back()); const unsigned int subdomain_id = std::distance(subdomain_bounds.begin(), std::lower_bound(subdomain_bounds.begin(), subdomain_bounds.end(), global_index)); libmesh_assert_less (subdomain_id, static_cast<unsigned int>(_pmetis->nparts)); libmesh_assert_less (local_index, _pmetis->part.size()); _pmetis->part[local_index] = subdomain_id; } } }
unsigned int NewtonSolver::solve() { START_LOG("solve()", "NewtonSolver"); // Reset any prior solve result _solve_result = INVALID_SOLVE_RESULT; NumericVector<Number> &newton_iterate = *(_system.solution); UniquePtr<NumericVector<Number> > linear_solution_ptr = newton_iterate.zero_clone(); NumericVector<Number> &linear_solution = *linear_solution_ptr; NumericVector<Number> &rhs = *(_system.rhs); newton_iterate.close(); linear_solution.close(); rhs.close(); #ifdef LIBMESH_ENABLE_CONSTRAINTS _system.get_dof_map().enforce_constraints_exactly(_system); #endif SparseMatrix<Number> &matrix = *(_system.matrix); // Set starting linear tolerance Real current_linear_tolerance = initial_linear_tolerance; // Start counting our linear solver steps _inner_iterations = 0; // Now we begin the nonlinear loop for (_outer_iterations=0; _outer_iterations<max_nonlinear_iterations; ++_outer_iterations) { if (verbose) libMesh::out << "Assembling the System" << std::endl; _system.assembly(true, true); rhs.close(); Real current_residual = rhs.l2_norm(); if (libmesh_isnan(current_residual)) { libMesh::out << " Nonlinear solver DIVERGED at step " << _outer_iterations << " with residual Not-a-Number" << std::endl; libmesh_convergence_failure(); continue; } if (current_residual == 0) { if (verbose) libMesh::out << "Linear solve unnecessary; residual = 0" << std::endl; // We're not doing a solve, but other code may reuse this // matrix. matrix.close(); if (absolute_residual_tolerance > 0) _solve_result |= CONVERGED_ABSOLUTE_RESIDUAL; if (relative_residual_tolerance > 0) _solve_result |= CONVERGED_RELATIVE_RESIDUAL; if (absolute_step_tolerance > 0) _solve_result |= CONVERGED_ABSOLUTE_STEP; if (relative_step_tolerance > 0) _solve_result |= CONVERGED_RELATIVE_STEP; break; } // Prepare to take incomplete steps Real last_residual = current_residual; max_residual_norm = std::max (current_residual, max_residual_norm); // Compute the l2 norm of the whole solution Real norm_total = newton_iterate.l2_norm(); max_solution_norm = std::max(max_solution_norm, norm_total); if (verbose) libMesh::out << "Nonlinear Residual: " << current_residual << std::endl; // Make sure our linear tolerance is low enough current_linear_tolerance = std::min (current_linear_tolerance, current_residual * linear_tolerance_multiplier); // But don't let it be too small if (current_linear_tolerance < minimum_linear_tolerance) { current_linear_tolerance = minimum_linear_tolerance; } // At this point newton_iterate is the current guess, and // linear_solution is now about to become the NEGATIVE of the next // Newton step. // Our best initial guess for the linear_solution is zero! linear_solution.zero(); if (verbose) libMesh::out << "Linear solve starting, tolerance " << current_linear_tolerance << std::endl; // Solve the linear system. const std::pair<unsigned int, Real> rval = linear_solver->solve (matrix, _system.request_matrix("Preconditioner"), linear_solution, rhs, current_linear_tolerance, max_linear_iterations); if (track_linear_convergence) { LinearConvergenceReason linear_c_reason = linear_solver->get_converged_reason(); // Check if something went wrong during the linear solve if (linear_c_reason < 0) { // The linear solver failed somehow _solve_result |= DiffSolver::DIVERGED_LINEAR_SOLVER_FAILURE; // Print a message libMesh::out << "Linear solver failed during Newton step, dropping out." << std::endl; break; } } // We may need to localize a parallel solution _system.update (); // The linear solver may not have fit our constraints exactly #ifdef LIBMESH_ENABLE_CONSTRAINTS _system.get_dof_map().enforce_constraints_exactly (_system, &linear_solution, /* homogeneous = */ true); #endif const unsigned int linear_steps = rval.first; libmesh_assert_less_equal (linear_steps, max_linear_iterations); _inner_iterations += linear_steps; const bool linear_solve_finished = !(linear_steps == max_linear_iterations); if (verbose) libMesh::out << "Linear solve finished, step " << linear_steps << ", residual " << rval.second << std::endl; // Compute the l2 norm of the nonlinear update Real norm_delta = linear_solution.l2_norm(); if (verbose) libMesh::out << "Trying full Newton step" << std::endl; // Take a full Newton step newton_iterate.add (-1., linear_solution); newton_iterate.close(); if (this->linear_solution_monitor.get()) { // Compute the l2 norm of the whole solution norm_total = newton_iterate.l2_norm(); rhs.close(); (*this->linear_solution_monitor)(linear_solution, norm_delta, newton_iterate, norm_total, rhs, rhs.l2_norm(), _outer_iterations); } // Check residual with full Newton step, if that's useful for determining // whether to line search, whether to quit early, or whether to die after // hitting our max iteration count if (this->require_residual_reduction || this->require_finite_residual || _outer_iterations+1 < max_nonlinear_iterations || !continue_after_max_iterations) { _system.assembly(true, false); rhs.close(); current_residual = rhs.l2_norm(); if (verbose) libMesh::out << " Current Residual: " << current_residual << std::endl; // don't fiddle around if we've already converged if (test_convergence(current_residual, norm_delta, linear_solve_finished && current_residual <= last_residual)) { if (!quiet) print_convergence(_outer_iterations, current_residual, norm_delta, linear_solve_finished && current_residual <= last_residual); _outer_iterations++; break; // out of _outer_iterations for loop } } // since we're not converged, backtrack if necessary Real steplength = this->line_search(std::sqrt(TOLERANCE), last_residual, current_residual, newton_iterate, linear_solution); norm_delta *= steplength; // Check to see if backtracking failed, // and break out of the nonlinear loop if so... if (_solve_result == DiffSolver::DIVERGED_BACKTRACKING_FAILURE) { _outer_iterations++; break; // out of _outer_iterations for loop } if (_outer_iterations + 1 >= max_nonlinear_iterations) { libMesh::out << " Nonlinear solver reached maximum step " << max_nonlinear_iterations << ", latest evaluated residual " << current_residual << std::endl; if (continue_after_max_iterations) { _solve_result = DiffSolver::DIVERGED_MAX_NONLINEAR_ITERATIONS; libMesh::out << " Continuing..." << std::endl; } else { libmesh_convergence_failure(); } continue; } // Compute the l2 norm of the whole solution norm_total = newton_iterate.l2_norm(); max_solution_norm = std::max(max_solution_norm, norm_total); // Print out information for the // nonlinear iterations. if (verbose) libMesh::out << " Nonlinear step: |du|/|u| = " << norm_delta / norm_total << ", |du| = " << norm_delta << std::endl; // Terminate the solution iteration if the difference between // this iteration and the last is sufficiently small. if (test_convergence(current_residual, norm_delta / steplength, linear_solve_finished)) { if (!quiet) print_convergence(_outer_iterations, current_residual, norm_delta / steplength, linear_solve_finished); _outer_iterations++; break; // out of _outer_iterations for loop } } // end nonlinear loop // The linear solver may not have fit our constraints exactly #ifdef LIBMESH_ENABLE_CONSTRAINTS _system.get_dof_map().enforce_constraints_exactly(_system); #endif // We may need to localize a parallel solution _system.update (); STOP_LOG("solve()", "NewtonSolver"); // Make sure we are returning something sensible as the // _solve_result, except in the edge case where we weren't really asked to // solve. libmesh_assert (_solve_result != DiffSolver::INVALID_SOLVE_RESULT || !max_nonlinear_iterations); return _solve_result; }
void Edge4::connectivity(const unsigned int sc, const IOPackage iop, std::vector<dof_id_type> & conn) const { libmesh_assert_less_equal (sc, 2); libmesh_assert_less (sc, this->n_sub_elem()); libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE); // Create storage conn.resize(2); switch(iop) { case TECPLOT: { switch (sc) { case 0: conn[0] = this->node(0)+1; conn[1] = this->node(2)+1; return; case 1: conn[0] = this->node(2)+1; conn[1] = this->node(3)+1; return; case 2: conn[0] = this->node(3)+1; conn[1] = this->node(1)+1; return; default: libmesh_error_msg("Invalid sc = " << sc); } } case VTK: { switch (sc) { case 0: conn[0] = this->node(0); conn[1] = this->node(2); return; case 1: conn[0] = this->node(2); conn[1] = this->node(3); return; case 2: conn[0] = this->node(3); conn[1] = this->node(1); return; default: libmesh_error_msg("Invalid sc = " << sc); } } default: libmesh_error_msg("Unsupported IO package " << iop); } }
RealGradient FE<2,NEDELEC_ONE>::shape(const Elem* elem, const Order order, const unsigned int i, const Point& p) { #if LIBMESH_DIM > 1 libmesh_assert(elem); const Order total_order = static_cast<Order>(order + elem->p_level()); switch (total_order) { case FIRST: { switch (elem->type()) { case QUAD8: case QUAD9: { libmesh_assert_less (i, 4); const Real xi = p(0); const Real eta = p(1); // Even with a loose inverse_map tolerance we ought to // be nearly on the element interior in master // coordinates libmesh_assert_less_equal ( std::fabs(xi), 1.0+10*TOLERANCE ); libmesh_assert_less_equal ( std::fabs(eta), 1.0+10*TOLERANCE ); switch(i) { case 0: { if( elem->point(0) > elem->point(1) ) return RealGradient( -0.25*(1.0-eta), 0.0 ); else return RealGradient( 0.25*(1.0-eta), 0.0 ); } case 1: { if( elem->point(1) > elem->point(2) ) return RealGradient( 0.0, -0.25*(1.0+xi) ); else return RealGradient( 0.0, 0.25*(1.0+xi) ); } case 2: { if( elem->point(2) > elem->point(3) ) return RealGradient( 0.25*(1.0+eta), 0.0 ); else return RealGradient( -0.25*(1.0+eta), 0.0 ); } case 3: { if( elem->point(3) > elem->point(0) ) return RealGradient( 0.0, -0.25*(xi-1.0) ); else return RealGradient( 0.0, 0.25*(xi-1.0) ); } default: libmesh_error(); } return RealGradient(); } case TRI6: { const Real xi = p(0); const Real eta = p(1); libmesh_assert_less (i, 3); switch(i) { case 0: { if( elem->point(0) > elem->point(1) ) return RealGradient( -1.0+eta, -xi ); else return RealGradient( 1.0-eta, xi ); } case 1: { if( elem->point(1) > elem->point(2) ) return RealGradient( eta, -xi ); else return RealGradient( -eta, xi ); } case 2: { if( elem->point(2) > elem->point(0) ) return RealGradient( eta, -xi+1.0 ); else return RealGradient( -eta, xi-1.0 ); } default: libmesh_error(); } } default: { libMesh::err << "ERROR: Unsupported 2D element type!: " << elem->type() << std::endl; libmesh_error(); } } } // unsupported order default: { libMesh::err << "ERROR: Unsupported 2D FE order!: " << total_order << std::endl; libmesh_error(); } } #endif // LIBMESH_DIM > 1 libmesh_error(); return RealGradient(); }
Real FE<2,XYZ>::shape_second_deriv(const Elem* elem, const Order libmesh_dbg_var(order), const unsigned int i, const unsigned int j, const Point& point_in) { #if LIBMESH_DIM > 1 libmesh_assert_less_equal (j, 2); libmesh_assert(elem); // Only recompute the centroid if the element // has changed from the last one we computed. // This avoids repeated centroid calculations // when called in succession with the same element. if (elem->id() != old_elem_id) { centroid = elem->centroid(); old_elem_id = elem->id(); max_distance = Point(0.,0.,0.); for (unsigned int p = 0; p < elem->n_nodes(); p++) for (unsigned int d = 0; d < 2; d++) { const Real distance = std::abs(centroid(d) - elem->point(p)(d)); max_distance(d) = std::max(distance, max_distance(d)); } } // Using static globals for old_elem_id, etc. will fail // horribly with more than one thread. libmesh_assert_equal_to (libMesh::n_threads(), 1); const Real x = point_in(0); const Real y = point_in(1); const Real xc = centroid(0); const Real yc = centroid(1); const Real distx = max_distance(0); const Real disty = max_distance(1); const Real dx = (x - xc)/distx; const Real dy = (y - yc)/disty; const Real dist2x = pow(distx,2.); const Real dist2y = pow(disty,2.); const Real distxy = distx * disty; #ifndef NDEBUG // totalorder is only used in the assertion below, so // we avoid declaring it when asserts are not active. const unsigned int totalorder = order + elem->p_level(); #endif libmesh_assert_less (i, (totalorder+1)*(totalorder+2)/2); // monomials. since they are hierarchic we only need one case block. switch (j) { // d^2()/dx^2 case 0: { switch (i) { // constants case 0: // linears case 1: case 2: return 0.; // quadratics case 3: return 2./dist2x; case 4: case 5: return 0.; // cubics case 6: return 6.*dx/dist2x; case 7: return 2.*dy/dist2x; case 8: case 9: return 0.; // quartics case 10: return 12.*dx*dx/dist2x; case 11: return 6.*dx*dy/dist2x; case 12: return 2.*dy*dy/dist2x; case 13: case 14: return 0.; default: unsigned int o = 0; for (; i >= (o+1)*(o+2)/2; o++) { } unsigned int i2 = i - (o*(o+1)/2); Real val = (o - i2) * (o - i2 - 1); for (unsigned int index=i2+2; index < o; index++) val *= dx; for (unsigned int index=0; index != i2; index++) val *= dy; return val/dist2x; } } // d^2()/dxdy case 1: { switch (i) { // constants case 0: // linears case 1: case 2: return 0.; // quadratics case 3: return 0.; case 4: return 1./distxy; case 5: return 0.; // cubics case 6: return 0.; case 7: return 2.*dx/distxy; case 8: return 2.*dy/distxy; case 9: return 0.; // quartics case 10: return 0.; case 11: return 3.*dx*dx/distxy; case 12: return 4.*dx*dy/distxy; case 13: return 3.*dy*dy/distxy; case 14: return 0.; default: unsigned int o = 0; for (; i >= (o+1)*(o+2)/2; o++) { } unsigned int i2 = i - (o*(o+1)/2); Real val = (o - i2) * i2; for (unsigned int index=i2+1; index < o; index++) val *= dx; for (unsigned int index=1; index < i2; index++) val *= dy; return val/distxy; } } // d^2()/dy^2 case 2: { switch (i) { // constants case 0: // linears case 1: case 2: return 0.; // quadratics case 3: case 4: return 0.; case 5: return 2./dist2y; // cubics case 6: return 0.; case 7: return 0.; case 8: return 2.*dx/dist2y; case 9: return 6.*dy/dist2y; // quartics case 10: case 11: return 0.; case 12: return 2.*dx*dx/dist2y; case 13: return 6.*dx*dy/dist2y; case 14: return 12.*dy*dy/dist2y; default: unsigned int o = 0; for (; i >= (o+1)*(o+2)/2; o++) { } unsigned int i2 = i - (o*(o+1)/2); Real val = i2 * (i2 - 1); for (unsigned int index=i2; index != o; index++) val *= dx; for (unsigned int index=2; index < i2; index++) val *= dy; return val/dist2y; } } } libmesh_error(); return 0.; #endif }
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 EquationSystems::build_variable_names (std::vector<std::string>& var_names, const FEType *type, const std::set<std::string>* system_names) const { libmesh_assert (this->n_systems()); unsigned int var_num=0; const_system_iterator pos = _systems.begin(); const const_system_iterator end = _systems.end(); // Need to size var_names by scalar variables plus all the // vector components for all the vector variables //Could this be replaced by a/some convenience methods?[PB] { unsigned int n_scalar_vars = 0; unsigned int n_vector_vars = 0; for (; pos != end; ++pos) { // Check current system is listed in system_names, and skip pos if not bool use_current_system = (system_names == NULL); if (!use_current_system) use_current_system = system_names->count(pos->first); if (!use_current_system) continue; for (unsigned int vn=0; vn<pos->second->n_vars(); vn++) { if( FEInterface::field_type(pos->second->variable_type(vn)) == TYPE_VECTOR ) n_vector_vars++; else n_scalar_vars++; } } // Here, we're assuming the number of vector components is the same // as the mesh dimension. Will break for mixed dimension meshes. unsigned int dim = this->get_mesh().mesh_dimension(); unsigned int nv = n_scalar_vars + dim*n_vector_vars; // We'd better not have more than dim*his->n_vars() (all vector variables) libmesh_assert_less_equal ( nv, dim*this->n_vars() ); // Here, we're assuming the number of vector components is the same // as the mesh dimension. Will break for mixed dimension meshes. var_names.resize( nv ); } // reset pos = _systems.begin(); for (; pos != end; ++pos) { // Check current system is listed in system_names, and skip pos if not bool use_current_system = (system_names == NULL); if (!use_current_system) use_current_system = system_names->count(pos->first); if (!use_current_system) continue; for (unsigned int vn=0; vn<pos->second->n_vars(); vn++) { std::string var_name = pos->second->variable_name(vn); FEType fe_type = pos->second->variable_type(vn); unsigned int n_vec_dim = FEInterface::n_vec_dim( pos->second->get_mesh(), fe_type); // Filter on the type if requested if (type == NULL || (type && *type == fe_type)) { if( FEInterface::field_type(fe_type) == TYPE_VECTOR ) { switch(n_vec_dim) { case 0: case 1: var_names[var_num++] = var_name; break; case 2: var_names[var_num++] = var_name+"_x"; var_names[var_num++] = var_name+"_y"; break; case 3: var_names[var_num++] = var_name+"_x"; var_names[var_num++] = var_name+"_y"; var_names[var_num++] = var_name+"_z"; break; default: libmesh_error_msg("Invalid dim in build_variable_names"); } } else var_names[var_num++] = var_name; } } } // Now resize again in case we filtered any names var_names.resize(var_num); }