std::pair<Real, Real> Tri3::min_and_max_angle() const { Point v10 ( this->point(1) - this->point(0) ); Point v20 ( this->point(2) - this->point(0) ); Point v21 ( this->point(2) - this->point(1) ); const Real len_10=v10.size(), len_20=v20.size(), len_21=v21.size() ; const Real theta0=std::acos(( v10*v20)/len_10/len_20), theta1=std::acos((-v10*v21)/len_10/len_21), theta2=libMesh::pi - theta0 - theta1 ; libmesh_assert_greater (theta0, 0.); libmesh_assert_greater (theta1, 0.); libmesh_assert_greater (theta2, 0.); return std::make_pair(std::min(theta0, std::min(theta1,theta2)), std::max(theta0, std::max(theta1,theta2))); }
void QBase::scale(std::pair<Real, Real> old_range, std::pair<Real, Real> new_range) { // Make sure we are in 1D libmesh_assert_equal_to (_dim, 1); Real h_new = new_range.second - new_range.first, h_old = old_range.second - old_range.first; // Make sure that we have sane ranges libmesh_assert_greater (h_new, 0.); libmesh_assert_greater (h_old, 0.); // Make sure there are some points libmesh_assert_greater (_points.size(), 0); // Compute the scale factor Real scfact = h_new/h_old; // We're mapping from old_range -> new_range for (unsigned int i=0; i<_points.size(); i++) { _points[i](0) = new_range.first + (_points[i](0) - old_range.first) * scfact; // Scale the weights _weights[i] *= scfact; } }
void QBase::scale(std::pair<Real, Real> old_range, std::pair<Real, Real> new_range) { // Make sure we are in 1D libmesh_assert_equal_to (_dim, 1); // Make sure that we have sane ranges libmesh_assert_greater (new_range.second, new_range.first); libmesh_assert_greater (old_range.second, old_range.first); // Make sure there are some points libmesh_assert_greater (_points.size(), 0); // We're mapping from old_range -> new_range for (unsigned int i=0; i<_points.size(); i++) { _points[i](0) = (_points[i](0) - old_range.first) * (new_range.second - new_range.first) / (old_range.second - old_range.first) + new_range.first; } // Compute the scale factor and scale the weights const Real scfact = (new_range.second - new_range.first) / (old_range.second - old_range.first); for (unsigned int i=0; i<_points.size(); i++) _weights[i] *= scfact; }
Real Sphere::distance (const Sphere & other_sphere) const { libmesh_assert_greater ( this->radius(), 0. ); libmesh_assert_greater ( other_sphere.radius(), 0. ); const Real the_distance = (this->center() - other_sphere.center()).norm(); return the_distance - (this->radius() + other_sphere.radius()); }
void MAST::Examples::ThermalJacobianScaling::set_acceleration_factor(Real f) { libmesh_assert_greater(f, 0.); _accel_factor = f; }
void SubdomainPartitioner::_do_partition (MeshBase & mesh, const unsigned int n) { libmesh_assert_greater (n, 0); // Check for an easy return. If the user has not specified any // entries in the chunks vector, we just do a single partitioning. if ((n == 1) || chunks.empty()) { this->single_partition (mesh); return; } // Now actually do the partitioning. LOG_SCOPE ("_do_partition()", "SubdomainPartitioner"); // For each chunk, construct an iterator range for the set of // subdomains in question, and pass it to the internal Partitioner. for (std::size_t c=0; c<chunks.size(); ++c) { MeshBase::element_iterator it = mesh.active_subdomain_set_elements_begin(chunks[c]), end = mesh.active_subdomain_set_elements_end(chunks[c]); _internal_partitioner->partition_range(mesh, it, end, n); } }
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); } } } }
Sphere::Sphere (const Point & c, const Real r) { libmesh_assert_greater (r, 0.); this->create_from_center_radius (c, r); }
void Sphere::create_from_center_radius (const Point & c, const Real r) { this->center() = c; this->radius() = r; libmesh_assert_greater (this->radius(), 0.); }
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(); }
Point Sphere::unit_normal (const Point & p) const { libmesh_assert_greater (this->radius(), 0.); libmesh_assert_not_equal_to (p, this->center()); // Create a vector from the center to the point Point n = p - this->center(); return n.unit(); }
bool Sphere::above_surface (const Point & p) const { libmesh_assert_greater (this->radius(), 0.); // create a vector from the center to the point. const Point w = p - this->center(); if (w.norm() > this->radius()) return true; return false; }
void MeshFunction::init (const Trees::BuildType /*point_locator_build_type*/) { // are indices of the desired variable(s) provided? libmesh_assert_greater (this->_system_vars.size(), 0); // Don't do twice... if (this->_initialized) { libmesh_assert(this->_point_locator); return; } /* * set up the PointLocator: either someone else * is the master (go and get the address of his * point locator) or this object is the master * (build the point locator on our own). */ if (this->_master != NULL) { // we aren't the master const MeshFunction* master = cast_ptr<const MeshFunction*>(this->_master); if (master->_point_locator == NULL) libmesh_error_msg("ERROR: When the master-servant concept is used, the master has to be initialized first!"); else { this->_point_locator = master->_point_locator; } } else { // we are the master: build the point locator // constant reference to the other mesh const MeshBase& mesh = this->_eqn_systems.get_mesh(); // build the point locator. Only \p TREE version available //UniquePtr<PointLocatorBase> ap (PointLocatorBase::build (TREE, mesh)); //this->_point_locator = ap.release(); // this->_point_locator = new PointLocatorTree (mesh, point_locator_build_type); this->_point_locator = mesh.sub_point_locator().release(); // Point locator no longer needs to be initialized. // this->_point_locator->init(); } // ready for use this->_initialized = true; }
void MAST::GCMMAOptimizationInterface::set_integer_parameter(const std::string &nm, int val) { if (nm == "max_inner_iters") { libmesh_assert_greater(val, 0); _max_inner_iters = val; } else libMesh::out << "Unrecognized integer parameter: " << nm << std::endl; }
void MAST::GCMMAOptimizationInterface::set_real_parameter(const std::string &nm, Real val) { if (nm == "constraint_penalty") { libmesh_assert_greater(val, 0.); _constr_penalty = val; } else libMesh::out << "Unrecognized real parameter: " << nm << std::endl; }
Point Sphere::closest_point (const Point & p) const { libmesh_assert_greater (this->radius(), 0.); // get the normal from the surface in the direction // of p Point normal = this->unit_normal (p); // The closest point on the sphere is in the direction // of the normal a distance r from the center. const Point cp = this->center() + normal*this->radius(); return cp; }
bool Sphere::on_surface (const Point & p) const { libmesh_assert_greater (this->radius(), 0.); // Create a vector from the center to the point. const Point w = p - this->center(); // if the size of that vector is the same as the radius() then // the point is on the surface. if (std::abs(w.norm() - this->radius()) < 1.e-10) return true; return false; }
void MeshTools::Subdivision::prepare_subdivision_mesh(MeshBase & mesh, bool ghosted) { mesh.prepare_for_use(); // convert all mesh elements to subdivision elements all_subdivision(mesh); if (!ghosted) { // add the ghost elements for the boundaries add_boundary_ghosts(mesh); } else { // This assumes that the mesh already has the ghosts. Only tagging them is required here. tag_boundary_ghosts(mesh); } mesh.prepare_for_use(); std::vector<std::vector<const Elem *> > nodes_to_elem_map; MeshTools::build_nodes_to_elem_map(mesh, nodes_to_elem_map); // compute the node valences MeshBase::const_node_iterator nd = mesh.nodes_begin(); const MeshBase::const_node_iterator end_nd = mesh.nodes_end(); for (; nd != end_nd; ++nd) { Node * node = *nd; std::vector<const Node *> neighbors; MeshTools::find_nodal_neighbors(mesh, *node, nodes_to_elem_map, neighbors); const unsigned int valence = cast_int<unsigned int>(neighbors.size()); libmesh_assert_greater(valence, 1); node->set_valence(valence); } MeshBase::const_element_iterator el = mesh.elements_begin(); const MeshBase::const_element_iterator end_el = mesh.elements_end(); for (; el != end_el; ++el) { Tri3Subdivision * elem = dynamic_cast<Tri3Subdivision *>(*el); libmesh_assert(elem); if (!elem->is_ghost()) elem->prepare_subdivision_properties(); } }
// ------------------------------------------------------------ // LinearPartitioner implementation void LinearPartitioner::_do_partition (MeshBase& mesh, const unsigned int n) { libmesh_assert_greater (n, 0); // Check for an easy return if (n == 1) { this->single_partition (mesh); return; } // Create a simple linear partitioning { START_LOG ("partition()", "LinearPartitioner"); const dof_id_type n_active_elem = mesh.n_active_elem(); const dof_id_type blksize = n_active_elem/n; dof_id_type e = 0; 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) { if ((e/blksize) < n) { Elem *elem = *elem_it; elem->processor_id() = libmesh_cast_int<processor_id_type>(e/blksize); } else { Elem *elem = *elem_it; elem->processor_id() = 0; elem = elem->parent(); } e++; } STOP_LOG ("partition()", "LinearPartitioner"); } }
void LaspackMatrix<T>::init (const numeric_index_type libmesh_dbg_var(m_in), const numeric_index_type libmesh_dbg_var(n_in), const numeric_index_type libmesh_dbg_var(m_l), const numeric_index_type libmesh_dbg_var(n_l), const numeric_index_type libmesh_dbg_var(nnz), const numeric_index_type, const numeric_index_type) { // noz ignored... only used for multiple processors! libmesh_assert_equal_to (m_in, m_l); libmesh_assert_equal_to (n_in, n_l); libmesh_assert_equal_to (m_in, n_in); libmesh_assert_greater (nnz, 0); libmesh_error_msg("ERROR: Only the init() member that uses the DofMap is implemented for Laspack matrices!"); this->_is_initialized = true; }
void EigenSparseMatrix<T>::init (const numeric_index_type m_in, const numeric_index_type n_in, const numeric_index_type libmesh_dbg_var(m_l), const numeric_index_type libmesh_dbg_var(n_l), const numeric_index_type nnz, const numeric_index_type, const numeric_index_type) { // noz ignored... only used for multiple processors! libmesh_assert_equal_to (m_in, m_l); libmesh_assert_equal_to (n_in, n_l); libmesh_assert_equal_to (m_in, n_in); libmesh_assert_greater (nnz, 0); _mat.resize(m_in, n_in); _mat.reserve(Eigen::Matrix<numeric_index_type, Eigen::Dynamic, 1>::Constant(m_in,nnz)); this->_is_initialized = true; }
void LaspackMatrix<T>::init (const unsigned int libmesh_dbg_var(m), const unsigned int libmesh_dbg_var(n), const unsigned int libmesh_dbg_var(m_l), const unsigned int libmesh_dbg_var(n_l), const unsigned int libmesh_dbg_var(nnz), const unsigned int) { // noz ignored... only used for multiple processors! libmesh_assert_equal_to (m, m_l); libmesh_assert_equal_to (n, n_l); libmesh_assert_equal_to (m, n); libmesh_assert_greater (nnz, 0); libMesh::err << "ERROR: Only the init() member that uses the" << std::endl << "DofMap is implemented for Laspack matrices!" << std::endl; libmesh_error(); this->_is_initialized = true; }
Sphere::Sphere(const Point & pa, const Point & pb, const Point & pc, const Point & pd) { Point pad = pa - pd; Point pbd = pb - pd; Point pcd = pc - pd; TensorValue<Real> T(pad,pbd,pcd); Real D = T.det(); // The points had better not be coplanar libmesh_assert_greater (std::abs(D), 1e-12); Real e = 0.5*(pa.norm_sq() - pd.norm_sq()); Real f = 0.5*(pb.norm_sq() - pd.norm_sq()); Real g = 0.5*(pc.norm_sq() - pd.norm_sq()); TensorValue<Real> T1(e,pad(1),pad(2), f,pbd(1),pbd(2), g,pcd(1),pcd(2)); Real sx = T1.det()/D; TensorValue<Real> T2(pad(0),e,pad(2), pbd(0),f,pbd(2), pcd(0),g,pcd(2)); Real sy = T2.det()/D; TensorValue<Real> T3(pad(0),pad(1),e, pbd(0),pbd(1),f, pcd(0),pcd(1),g); Real sz = T3.det()/D; Point c(sx,sy,sz); Real r = (c-pa).norm(); this->create_from_center_radius(c,r); }
void NonlinearNeoHookeCurrentConfig::init_for_qp(VectorValue<Gradient> & grad_u, unsigned int qp) { this->current_qp = qp; F.zero(); S.zero(); { RealTensor invF; invF.zero(); for (unsigned int i = 0; i < 3; ++i) for (unsigned int j = 0; j < 3; ++j) { invF(i, j) += libmesh_real(grad_u(i)(j)); } F.add(inv(invF)); libmesh_assert_greater (F.det(), -TOLERANCE); } if (this->calculate_linearized_stiffness) { this->calculate_tangent(); } this->calculate_stress(); }
void FEXYZMap::compute_face_map(int dim, const std::vector<Real>& qw, const Elem* side) { libmesh_assert(side); START_LOG("compute_face_map()", "FEXYZMap"); // The number of quadrature points. const unsigned int n_qp = libmesh_cast_int<unsigned int>(qw.size()); switch(dim) { case 2: { // Resize the vectors to hold data at the quadrature points { this->xyz.resize(n_qp); this->dxyzdxi_map.resize(n_qp); this->d2xyzdxi2_map.resize(n_qp); this->tangents.resize(n_qp); this->normals.resize(n_qp); this->curvatures.resize(n_qp); this->JxW.resize(n_qp); } // Clear the entities that will be summed // Compute the tangent & normal at the quadrature point for (unsigned int p=0; p<n_qp; p++) { this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D this->xyz[p].zero(); this->dxyzdxi_map[p].zero(); this->d2xyzdxi2_map[p].zero(); } // compute x, dxdxi at the quadrature points for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes { const Point& side_point = side->point(i); for (unsigned int p=0; p<n_qp; p++) // for each quadrature point... { this->xyz[p].add_scaled (side_point, this->psi_map[i][p]); this->dxyzdxi_map[p].add_scaled (side_point, this->dpsidxi_map[i][p]); this->d2xyzdxi2_map[p].add_scaled(side_point, this->d2psidxi2_map[i][p]); } } // Compute the tangent & normal at the quadrature point for (unsigned int p=0; p<n_qp; p++) { const Point n(this->dxyzdxi_map[p](1), -this->dxyzdxi_map[p](0), 0.); this->normals[p] = n.unit(); this->tangents[p][0] = this->dxyzdxi_map[p].unit(); #if LIBMESH_DIM == 3 // Only good in 3D space this->tangents[p][1] = this->dxyzdxi_map[p].cross(n).unit(); #endif // The curvature is computed via the familiar Frenet formula: // curvature = [d^2(x) / d (xi)^2] dot [normal] // For a reference, see: // F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill, p. 310 // // Note: The sign convention here is different from the // 3D case. Concave-upward curves (smiles) have a positive // curvature. Concave-downward curves (frowns) have a // negative curvature. Be sure to take that into account! const Real numerator = this->d2xyzdxi2_map[p] * this->normals[p]; const Real denominator = this->dxyzdxi_map[p].size_sq(); libmesh_assert_not_equal_to (denominator, 0); this->curvatures[p] = numerator / denominator; } // compute the jacobian at the quadrature points for (unsigned int p=0; p<n_qp; p++) { const Real the_jac = std::sqrt(this->dxdxi_map(p)*this->dxdxi_map(p) + this->dydxi_map(p)*this->dydxi_map(p)); libmesh_assert_greater (the_jac, 0.); this->JxW[p] = the_jac*qw[p]; } break; } case 3: { // Resize the vectors to hold data at the quadrature points { this->xyz.resize(n_qp); this->dxyzdxi_map.resize(n_qp); this->dxyzdeta_map.resize(n_qp); this->d2xyzdxi2_map.resize(n_qp); this->d2xyzdxideta_map.resize(n_qp); this->d2xyzdeta2_map.resize(n_qp); this->tangents.resize(n_qp); this->normals.resize(n_qp); this->curvatures.resize(n_qp); this->JxW.resize(n_qp); } // Clear the entities that will be summed for (unsigned int p=0; p<n_qp; p++) { this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D this->xyz[p].zero(); this->dxyzdxi_map[p].zero(); this->dxyzdeta_map[p].zero(); this->d2xyzdxi2_map[p].zero(); this->d2xyzdxideta_map[p].zero(); this->d2xyzdeta2_map[p].zero(); } // compute x, dxdxi at the quadrature points for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes { const Point& side_point = side->point(i); for (unsigned int p=0; p<n_qp; p++) // for each quadrature point... { this->xyz[p].add_scaled (side_point, this->psi_map[i][p]); this->dxyzdxi_map[p].add_scaled (side_point, this->dpsidxi_map[i][p]); this->dxyzdeta_map[p].add_scaled (side_point, this->dpsideta_map[i][p]); this->d2xyzdxi2_map[p].add_scaled (side_point, this->d2psidxi2_map[i][p]); this->d2xyzdxideta_map[p].add_scaled(side_point, this->d2psidxideta_map[i][p]); this->d2xyzdeta2_map[p].add_scaled (side_point, this->d2psideta2_map[i][p]); } } // Compute the tangents, normal, and curvature at the quadrature point for (unsigned int p=0; p<n_qp; p++) { const Point n = this->dxyzdxi_map[p].cross(this->dxyzdeta_map[p]); this->normals[p] = n.unit(); this->tangents[p][0] = this->dxyzdxi_map[p].unit(); this->tangents[p][1] = n.cross(this->dxyzdxi_map[p]).unit(); // Compute curvature using the typical nomenclature // of the first and second fundamental forms. // For reference, see: // 1) http://mathworld.wolfram.com/MeanCurvature.html // (note -- they are using inward normal) // 2) F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill const Real L = -this->d2xyzdxi2_map[p] * this->normals[p]; const Real M = -this->d2xyzdxideta_map[p] * this->normals[p]; const Real N = -this->d2xyzdeta2_map[p] * this->normals[p]; const Real E = this->dxyzdxi_map[p].size_sq(); const Real F = this->dxyzdxi_map[p] * this->dxyzdeta_map[p]; const Real G = this->dxyzdeta_map[p].size_sq(); const Real numerator = E*N -2.*F*M + G*L; const Real denominator = E*G - F*F; libmesh_assert_not_equal_to (denominator, 0.); this->curvatures[p] = 0.5*numerator/denominator; } // compute the jacobian at the quadrature points, see // http://sp81.msi.umn.edu:999/fluent/fidap/help/theory/thtoc.htm for (unsigned int p=0; p<n_qp; p++) { const Real g11 = (this->dxdxi_map(p)*this->dxdxi_map(p) + this->dydxi_map(p)*this->dydxi_map(p) + this->dzdxi_map(p)*this->dzdxi_map(p)); const Real g12 = (this->dxdxi_map(p)*this->dxdeta_map(p) + this->dydxi_map(p)*this->dydeta_map(p) + this->dzdxi_map(p)*this->dzdeta_map(p)); const Real g21 = g12; const Real g22 = (this->dxdeta_map(p)*this->dxdeta_map(p) + this->dydeta_map(p)*this->dydeta_map(p) + this->dzdeta_map(p)*this->dzdeta_map(p)); const Real the_jac = std::sqrt(g11*g22 - g12*g21); libmesh_assert_greater (the_jac, 0.); this->JxW[p] = the_jac*qw[p]; } break; } default: libmesh_error_msg("Invalid dim = " << dim); } // switch(dim) STOP_LOG("compute_face_map()", "FEXYZMap"); return; }
// ------------------------------------------------------------ // SFCPartitioner implementation void SFCPartitioner::_do_partition (MeshBase & mesh, const unsigned int n) { libmesh_assert_greater (n, 0); // Check for an easy return if (n == 1) { this->single_partition (mesh); return; } // What to do if the sfcurves library IS NOT present #ifndef LIBMESH_HAVE_SFCURVES libmesh_here(); libMesh::err << "ERROR: The library has been built without" << std::endl << "Space Filling Curve support. Using a linear" << std::endl << "partitioner instead!" << std::endl; LinearPartitioner lp; lp.partition (mesh, n); // What to do if the sfcurves library IS present #else LOG_SCOPE("sfc_partition()", "SFCPartitioner"); const dof_id_type n_active_elem = mesh.n_active_elem(); const dof_id_type n_elem = mesh.n_elem(); // the forward_map maps the active element id // into a contiguous block of indices std::vector<dof_id_type> forward_map (n_elem, DofObject::invalid_id); // the reverse_map maps the contiguous ids back // to active elements std::vector<Elem *> reverse_map (n_active_elem, libmesh_nullptr); int size = static_cast<int>(n_active_elem); std::vector<double> x (size); std::vector<double> y (size); std::vector<double> z (size); std::vector<int> table (size); // We need to map the active element ids into a // contiguous range. { MeshBase::element_iterator elem_it = mesh.active_elements_begin(); const MeshBase::element_iterator elem_end = mesh.active_elements_end(); dof_id_type el_num = 0; for (; elem_it != elem_end; ++elem_it) { libmesh_assert_less ((*elem_it)->id(), forward_map.size()); libmesh_assert_less (el_num, reverse_map.size()); forward_map[(*elem_it)->id()] = el_num; reverse_map[el_num] = *elem_it; el_num++; } libmesh_assert_equal_to (el_num, n_active_elem); } // Get the centroid for each active element { // const_active_elem_iterator elem_it (mesh.const_elements_begin()); // const const_active_elem_iterator elem_end(mesh.const_elements_end()); 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; libmesh_assert_less (elem->id(), forward_map.size()); const Point p = elem->centroid(); x[forward_map[elem->id()]] = p(0); y[forward_map[elem->id()]] = p(1); z[forward_map[elem->id()]] = p(2); } } // build the space-filling curve if (_sfc_type == "Hilbert") Sfc::hilbert (&x[0], &y[0], &z[0], &size, &table[0]); else if (_sfc_type == "Morton") Sfc::morton (&x[0], &y[0], &z[0], &size, &table[0]); else { libmesh_here(); libMesh::err << "ERROR: Unknown type: " << _sfc_type << std::endl << " Valid types are" << std::endl << " \"Hilbert\"" << std::endl << " \"Morton\"" << std::endl << " " << std::endl << "Proceeding with a Hilbert curve." << std::endl; Sfc::hilbert (&x[0], &y[0], &z[0], &size, &table[0]); } // Assign the partitioning to the active elements { // { // std::ofstream out ("sfc.dat"); // out << "variables=x,y,z" << std::endl; // out << "zone f=point" << std::endl; // for (unsigned int i=0; i<n_active_elem; i++) // out << x[i] << " " // << y[i] << " " // << z[i] << std::endl; // } const dof_id_type blksize = (n_active_elem+n-1)/n; for (dof_id_type i=0; i<n_active_elem; i++) { libmesh_assert_less (static_cast<unsigned int>(table[i]-1), reverse_map.size()); Elem * elem = reverse_map[table[i]-1]; elem->processor_id() = cast_int<processor_id_type> (i/blksize); } } #endif }
Real FE<2,HIERARCHIC>::shape(const Elem* elem, const Order order, const unsigned int i, const Point& p) { libmesh_assert(elem); const Order totalorder = static_cast<Order>(order+elem->p_level()); libmesh_assert_greater (totalorder, 0); switch (elem->type()) { case TRI3: case TRI6: { const Real zeta1 = p(0); const Real zeta2 = p(1); const Real zeta0 = 1. - zeta1 - zeta2; libmesh_assert_less (i, (totalorder+1u)*(totalorder+2u)/2); libmesh_assert (elem->type() == TRI6 || totalorder < 2); // Vertex DoFs if (i == 0) return zeta0; else if (i == 1) return zeta1; else if (i == 2) return zeta2; // Edge DoFs else if (i < totalorder + 2u) { // Avoid returning NaN on vertices! if (zeta0 + zeta1 == 0.) return 0.; const unsigned int basisorder = i - 1; // Get factors to account for edge-flipping Real f0 = 1; if (basisorder%2 && (elem->point(0) > elem->point(1))) f0 = -1.; Real edgeval = (zeta1 - zeta0) / (zeta1 + zeta0); Real crossfunc = zeta0 + zeta1; for (unsigned int n=1; n != basisorder; ++n) crossfunc *= (zeta0 + zeta1); return f0 * crossfunc * FE<1,HIERARCHIC>::shape(EDGE3, totalorder, basisorder, edgeval); } else if (i < 2u*totalorder + 1) { // Avoid returning NaN on vertices! if (zeta1 + zeta2 == 0.) return 0.; const unsigned int basisorder = i - totalorder; // Get factors to account for edge-flipping Real f1 = 1; if (basisorder%2 && (elem->point(1) > elem->point(2))) f1 = -1.; Real edgeval = (zeta2 - zeta1) / (zeta2 + zeta1); Real crossfunc = zeta2 + zeta1; for (unsigned int n=1; n != basisorder; ++n) crossfunc *= (zeta2 + zeta1); return f1 * crossfunc * FE<1,HIERARCHIC>::shape(EDGE3, totalorder, basisorder, edgeval); } else if (i < 3u*totalorder) { // Avoid returning NaN on vertices! if (zeta0 + zeta2 == 0.) return 0.; const unsigned int basisorder = i - (2u*totalorder) + 1; // Get factors to account for edge-flipping Real f2 = 1; if (basisorder%2 && (elem->point(2) > elem->point(0))) f2 = -1.; Real edgeval = (zeta0 - zeta2) / (zeta0 + zeta2); Real crossfunc = zeta0 + zeta2; for (unsigned int n=1; n != basisorder; ++n) crossfunc *= (zeta0 + zeta2); return f2 * crossfunc * FE<1,HIERARCHIC>::shape(EDGE3, totalorder, basisorder, edgeval); } // Interior DoFs else { const unsigned int basisnum = i - (3u*totalorder); unsigned int exp0 = triangular_number_column[basisnum] + 1; unsigned int exp1 = triangular_number_row[basisnum] + 1 - triangular_number_column[basisnum]; Real returnval = 1; for (unsigned int n = 0; n != exp0; ++n) returnval *= zeta0; for (unsigned int n = 0; n != exp1; ++n) returnval *= zeta1; returnval *= zeta2; return returnval; } } // Hierarchic shape functions on the quadrilateral. case QUAD4: libmesh_assert_less (totalorder, 2); case QUAD8: case QUAD9: { // Compute quad shape functions as a tensor-product const Real xi = p(0); const Real eta = p(1); libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u)); // Example i, i0, i1 values for totalorder = 5: // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 0, 0, 0, 0, 2, 3, 3, 2, 4, 4, 4, 3, 2, 5, 5, 5, 5, 4, 3, 2}; // static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 2, 2, 3, 3, 2, 3, 4, 4, 4, 2, 3, 4, 5, 5, 5, 5}; unsigned int i0, i1; // Vertex DoFs if (i == 0) { i0 = 0; i1 = 0; } else if (i == 1) { i0 = 1; i1 = 0; } else if (i == 2) { i0 = 1; i1 = 1; } else if (i == 3) { i0 = 0; i1 = 1; } // Edge DoFs else if (i < totalorder + 3u) { i0 = i - 2; i1 = 0; } else if (i < 2u*totalorder + 2) { i0 = 1; i1 = i - totalorder - 1; } else if (i < 3u*totalorder + 1) { i0 = i - 2u*totalorder; i1 = 1; } else if (i < 4u*totalorder) { i0 = 0; i1 = i - 3u*totalorder + 1; } // Interior DoFs else { unsigned int basisnum = i - 4*totalorder; i0 = square_number_column[basisnum] + 2; i1 = square_number_row[basisnum] + 2; } // Flip odd degree of freedom values if necessary // to keep continuity on sides Real f = 1.; if ((i0%2) && (i0 > 2) && (i1 == 0)) f = (elem->point(0) > elem->point(1))?-1.:1.; else if ((i0%2) && (i0>2) && (i1 == 1)) f = (elem->point(3) > elem->point(2))?-1.:1.; else if ((i0 == 0) && (i1%2) && (i1>2)) f = (elem->point(0) > elem->point(3))?-1.:1.; else if ((i0 == 1) && (i1%2) && (i1>2)) f = (elem->point(1) > elem->point(2))?-1.:1.; return f*(FE<1,HIERARCHIC>::shape(EDGE3, totalorder, i0, xi)* FE<1,HIERARCHIC>::shape(EDGE3, totalorder, i1, eta)); } default: libMesh::err << "ERROR: Unsupported element type!" << std::endl; libmesh_error(); } return 0.; }
Real FE<2,HIERARCHIC>::shape_deriv(const Elem* elem, const Order order, const unsigned int i, const unsigned int j, const Point& p) { libmesh_assert(elem); const ElemType type = elem->type(); const Order totalorder = static_cast<Order>(order+elem->p_level()); libmesh_assert_greater (totalorder, 0); switch (type) { // 1st & 2nd-order Hierarchics. case TRI3: case TRI6: { const Real eps = 1.e-6; libmesh_assert_less (j, 2); switch (j) { // d()/dxi case 0: { const Point pp(p(0)+eps, p(1)); const Point pm(p(0)-eps, p(1)); return (FE<2,HIERARCHIC>::shape(elem, order, i, pp) - FE<2,HIERARCHIC>::shape(elem, order, i, pm))/2./eps; } // d()/deta case 1: { const Point pp(p(0), p(1)+eps); const Point pm(p(0), p(1)-eps); return (FE<2,HIERARCHIC>::shape(elem, order, i, pp) - FE<2,HIERARCHIC>::shape(elem, order, i, pm))/2./eps; } default: libmesh_error(); } } case QUAD4: libmesh_assert_less (totalorder, 2); case QUAD8: case QUAD9: { // Compute quad shape functions as a tensor-product const Real xi = p(0); const Real eta = p(1); libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u)); // Example i, i0, i1 values for totalorder = 5: // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 0, 0, 0, 0, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5}; // static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; unsigned int i0, i1; // Vertex DoFs if (i == 0) { i0 = 0; i1 = 0; } else if (i == 1) { i0 = 1; i1 = 0; } else if (i == 2) { i0 = 1; i1 = 1; } else if (i == 3) { i0 = 0; i1 = 1; } // Edge DoFs else if (i < totalorder + 3u) { i0 = i - 2; i1 = 0; } else if (i < 2u*totalorder + 2) { i0 = 1; i1 = i - totalorder - 1; } else if (i < 3u*totalorder + 1u) { i0 = i - 2u*totalorder; i1 = 1; } else if (i < 4u*totalorder) { i0 = 0; i1 = i - 3u*totalorder + 1; } // Interior DoFs else { unsigned int basisnum = i - 4*totalorder; i0 = square_number_column[basisnum] + 2; i1 = square_number_row[basisnum] + 2; } // Flip odd degree of freedom values if necessary // to keep continuity on sides Real f = 1.; if ((i0%2) && (i0 > 2) && (i1 == 0)) f = (elem->point(0) > elem->point(1))?-1.:1.; else if ((i0%2) && (i0>2) && (i1 == 1)) f = (elem->point(3) > elem->point(2))?-1.:1.; else if ((i0 == 0) && (i1%2) && (i1>2)) f = (elem->point(0) > elem->point(3))?-1.:1.; else if ((i0 == 1) && (i1%2) && (i1>2)) f = (elem->point(1) > elem->point(2))?-1.:1.; switch (j) { // d()/dxi case 0: return f*(FE<1,HIERARCHIC>::shape_deriv(EDGE3, totalorder, i0, 0, xi)* FE<1,HIERARCHIC>::shape (EDGE3, totalorder, i1, eta)); // d()/deta case 1: return f*(FE<1,HIERARCHIC>::shape (EDGE3, totalorder, i0, xi)* FE<1,HIERARCHIC>::shape_deriv(EDGE3, totalorder, i1, 0, eta)); default: libmesh_error(); } } default: libMesh::err << "ERROR: Unsupported element type!" << std::endl; libmesh_error(); } return 0.; }
// The main program int main(int argc, char** argv) { // Initialize libMesh LibMeshInit init(argc, argv); // Parameters GetPot infile("fem_system_params.in"); const Real global_tolerance = infile("global_tolerance", 0.); const unsigned int nelem_target = infile("n_elements", 400); const bool transient = infile("transient", true); const Real deltat = infile("deltat", 0.005); unsigned int n_timesteps = infile("n_timesteps", 1); //const unsigned int coarsegridsize = infile("coarsegridsize", 1); const unsigned int coarserefinements = infile("coarserefinements", 0); const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10); //const unsigned int dim = 2; #ifdef LIBMESH_HAVE_EXODUS_API const unsigned int write_interval = infile("write_interval", 5); #endif // Create a mesh, with dimension to be overridden later, distributed // across the default MPI communicator. Mesh mesh(init.comm()); GetPot infileForMesh("convdiff_mprime.in"); std::string find_mesh_here = infileForMesh("mesh","psiLF_mesh.xda"); mesh.read(find_mesh_here); std::cout << "Read in mesh from: " << find_mesh_here << "\n\n"; // And an object to refine it MeshRefinement mesh_refinement(mesh); mesh_refinement.coarsen_by_parents() = true; mesh_refinement.absolute_global_tolerance() = global_tolerance; mesh_refinement.nelem_target() = nelem_target; mesh_refinement.refine_fraction() = 0.3; mesh_refinement.coarsen_fraction() = 0.3; mesh_refinement.coarsen_threshold() = 0.1; //mesh_refinement.uniformly_refine(coarserefinements); // Print information about the mesh to the screen. mesh.print_info(); // Create an equation systems object. EquationSystems equation_systems (mesh); // Name system ConvDiff_MprimeSys & system = equation_systems.add_system<ConvDiff_MprimeSys>("Diff_ConvDiff_MprimeSys"); // Steady-state problem system.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system)); // Sanity check that we are indeed solving a steady problem libmesh_assert_equal_to (n_timesteps, 1); // Read in all the equation systems data from the LF solve (system, solutions, rhs, etc) std::string find_psiLF_here = infileForMesh("psiLF_file","psiLF.xda"); std::cout << "Looking for psiLF at: " << find_psiLF_here << "\n\n"; equation_systems.read(find_psiLF_here, READ, EquationSystems::READ_HEADER | EquationSystems::READ_DATA | EquationSystems::READ_ADDITIONAL_DATA); // Check that the norm of the solution read in is what we expect it to be Real readin_L2 = system.calculate_norm(*system.solution, 0, L2); std::cout << "Read in solution norm: "<< readin_L2 << std::endl << std::endl; //DEBUG //equation_systems.write("right_back_out.xda", WRITE, EquationSystems::WRITE_DATA | // EquationSystems::WRITE_ADDITIONAL_DATA); #ifdef LIBMESH_HAVE_GMV //GMVIO(equation_systems.get_mesh()).write_equation_systems(std::string("right_back_out.gmv"), equation_systems); #endif // Initialize the system //equation_systems.init (); //already initialized by read-in // And the nonlinear solver options NewtonSolver *solver = new NewtonSolver(system); system.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver); solver->quiet = infile("solver_quiet", true); solver->verbose = !solver->quiet; solver->max_nonlinear_iterations = infile("max_nonlinear_iterations", 15); solver->relative_step_tolerance = infile("relative_step_tolerance", 1.e-3); solver->relative_residual_tolerance = infile("relative_residual_tolerance", 0.0); solver->absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0); // And the linear solver options solver->max_linear_iterations = infile("max_linear_iterations", 50000); solver->initial_linear_tolerance = infile("initial_linear_tolerance", 1.e-3); // Print information about the system to the screen. equation_systems.print_info(); // Now we begin the timestep loop to compute the time-accurate // solution of the equations...not that this is transient, but eh, why not... for (unsigned int t_step=0; t_step != n_timesteps; ++t_step) { // A pretty update message std::cout << "\n\nSolving time step " << t_step << ", time = " << system.time << std::endl; // Adaptively solve the timestep unsigned int a_step = 0; for (; a_step != max_adaptivesteps; ++a_step) { // VESTIGIAL for now ('vestigial' eh ? ;) ) std::cout << "\n\n I should be skipped what are you doing here lalalalalalala *!**!*!*!*!*!* \n\n"; system.solve(); system.postprocess(); ErrorVector error; AutoPtr<ErrorEstimator> error_estimator; // To solve to a tolerance in this problem we // need a better estimator than Kelly if (global_tolerance != 0.) { // We can't adapt to both a tolerance and a mesh // size at once libmesh_assert_equal_to (nelem_target, 0); UniformRefinementEstimator *u = new UniformRefinementEstimator; // The lid-driven cavity problem isn't in H1, so // lets estimate L2 error u->error_norm = L2; error_estimator.reset(u); } else { // If we aren't adapting to a tolerance we need a // target mesh size libmesh_assert_greater (nelem_target, 0); // Kelly is a lousy estimator to use for a problem // not in H1 - if we were doing more than a few // timesteps we'd need to turn off or limit the // maximum level of our adaptivity eventually error_estimator.reset(new KellyErrorEstimator); } // Calculate error std::vector<Real> weights(9,1.0); // based on u, v, p, c, their adjoints, and source parameter // Keep the same default norm type. std::vector<FEMNormType> norms(1, error_estimator->error_norm.type(0)); error_estimator->error_norm = SystemNorm(norms, weights); error_estimator->estimate_error(system, error); // Print out status at each adaptive step. Real global_error = error.l2_norm(); std::cout << "Adaptive step " << a_step << ": " << std::endl; if (global_tolerance != 0.) std::cout << "Global_error = " << global_error << std::endl; if (global_tolerance != 0.) std::cout << "Worst element error = " << error.maximum() << ", mean = " << error.mean() << std::endl; if (global_tolerance != 0.) { // If we've reached our desired tolerance, we // don't need any more adaptive steps if (global_error < global_tolerance) break; mesh_refinement.flag_elements_by_error_tolerance(error); } else { // If flag_elements_by_nelem_target returns true, this // should be our last adaptive step. if (mesh_refinement.flag_elements_by_nelem_target(error)) { mesh_refinement.refine_and_coarsen_elements(); equation_systems.reinit(); a_step = max_adaptivesteps; break; } } // Carry out the adaptive mesh refinement/coarsening mesh_refinement.refine_and_coarsen_elements(); equation_systems.reinit(); std::cout << "Refined mesh to " << mesh.n_active_elem() << " active elements and " << equation_systems.n_active_dofs() << " active dofs." << std::endl; } // End loop over adaptive steps // Do one last solve if necessary if (a_step == max_adaptivesteps) { QoISet qois; std::vector<unsigned int> qoi_indices; qoi_indices.push_back(0); qois.add_indices(qoi_indices); qois.set_weight(0, 1.0); system.assemble_qoi_sides = true; //QoI doesn't involve sides std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve start ~*~*~*~*~*~*~*~*~\n" << std::endl; std::pair<unsigned int, Real> adjsolve = system.adjoint_solve(); std::cout << "number of iterations to solve adjoint: " << adjsolve.first << std::endl; std::cout << "final residual of adjoint solve: " << adjsolve.second << std::endl; std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve end ~*~*~*~*~*~*~*~*~" << std::endl; NumericVector<Number> &dual_solution = system.get_adjoint_solution(0); NumericVector<Number> &primal_solution = *system.solution; primal_solution.swap(dual_solution); ExodusII_IO(mesh).write_timestep("super_adjoint.exo", equation_systems, 1, /* This number indicates how many time steps are being written to the file */ system.time); primal_solution.swap(dual_solution); system.assemble(); //overwrite residual read in from psiLF solve // The total error estimate system.postprocess(); //to compute M_HF(psiLF) and M_LF(psiLF) terms Real QoI_error_estimate = (-0.5*(system.rhs)->dot(dual_solution)) + system.get_MHF_psiLF() - system.get_MLF_psiLF(); std::cout << "\n\n 0.5*M'_HF(psiLF)(superadj): " << std::setprecision(17) << 0.5*(system.rhs)->dot(dual_solution) << "\n"; std::cout << " M_HF(psiLF): " << std::setprecision(17) << system.get_MHF_psiLF() << "\n"; std::cout << " M_LF(psiLF): " << std::setprecision(17) << system.get_MLF_psiLF() << "\n"; std::cout << "\n\n Residual L2 norm: " << system.calculate_norm(*system.rhs, L2) << "\n"; std::cout << " Residual discrete L2 norm: " << system.calculate_norm(*system.rhs, DISCRETE_L2) << "\n"; std::cout << " Super-adjoint L2 norm: " << system.calculate_norm(dual_solution, L2) << "\n"; std::cout << " Super-adjoint discrete L2 norm: " << system.calculate_norm(dual_solution, DISCRETE_L2) << "\n"; std::cout << "\n\n QoI error estimate: " << std::setprecision(17) << QoI_error_estimate << "\n\n"; //DEBUG std::cout << "\n------------ herp derp ------------" << std::endl; //libMesh::out.precision(16); //dual_solution.print(); //system.get_adjoint_rhs().print(); AutoPtr<NumericVector<Number> > adjresid = system.solution->clone(); (system.matrix)->vector_mult(*adjresid,system.get_adjoint_solution(0)); SparseMatrix<Number>& adjmat = *system.matrix; (system.matrix)->get_transpose(adjmat); adjmat.vector_mult(*adjresid,system.get_adjoint_solution(0)); //std::cout << "******************** matrix-superadj product (libmesh) ************************" << std::endl; //adjresid->print(); adjresid->add(-1.0, system.get_adjoint_rhs(0)); //std::cout << "******************** superadjoint system residual (libmesh) ***********************" << std::endl; //adjresid->print(); std::cout << "\n\nadjoint system residual (discrete L2): " << system.calculate_norm(*adjresid,DISCRETE_L2) << std::endl; std::cout << "adjoint system residual (L2, all): " << system.calculate_norm(*adjresid,L2) << std::endl; std::cout << "adjoint system residual (L2, 0): " << system.calculate_norm(*adjresid,0,L2) << std::endl; std::cout << "adjoint system residual (L2, 1): " << system.calculate_norm(*adjresid,1,L2) << std::endl; std::cout << "adjoint system residual (L2, 2): " << system.calculate_norm(*adjresid,2,L2) << std::endl; std::cout << "adjoint system residual (L2, 3): " << system.calculate_norm(*adjresid,3,L2) << std::endl; std::cout << "adjoint system residual (L2, 4): " << system.calculate_norm(*adjresid,4,L2) << std::endl; std::cout << "adjoint system residual (L2, 5): " << system.calculate_norm(*adjresid,5,L2) << std::endl; /* AutoPtr<NumericVector<Number> > sadj_matlab = system.solution->clone(); AutoPtr<NumericVector<Number> > adjresid_matlab = system.solution->clone(); if(FILE *fp=fopen("superadj_matlab.txt","r")){ Real value; int counter = 0; int flag = 1; while(flag != -1){ flag = fscanf(fp,"%lf",&value); if(flag != -1){ sadj_matlab->set(counter, value); counter += 1; } } fclose(fp); } (system.matrix)->vector_mult(*adjresid_matlab,*sadj_matlab); //std::cout << "******************** matrix-superadj product (matlab) ***********************" << std::endl; //adjresid_matlab->print(); adjresid_matlab->add(-1.0, system.get_adjoint_rhs(0)); //std::cout << "******************** superadjoint system residual (matlab) ***********************" << std::endl; //adjresid_matlab->print(); std::cout << "\n\nmatlab import adjoint system residual (discrete L2): " << system.calculate_norm(*adjresid_matlab,DISCRETE_L2) << "\n" << std::endl; */ /* AutoPtr<NumericVector<Number> > sadj_fwd_hack = system.solution->clone(); AutoPtr<NumericVector<Number> > adjresid_fwd_hack = system.solution->clone(); if(FILE *fp=fopen("superadj_forward_hack.txt","r")){ Real value; int counter = 0; int flag = 1; while(flag != -1){ flag = fscanf(fp,"%lf",&value); if(flag != -1){ sadj_fwd_hack->set(counter, value); counter += 1; } } fclose(fp); } (system.matrix)->vector_mult(*adjresid_fwd_hack,*sadj_fwd_hack); //std::cout << "******************** matrix-superadj product (fwd_hack) ***********************" << std::endl; //adjresid_fwd_hack->print(); adjresid_fwd_hack->add(-1.0, system.get_adjoint_rhs(0)); //std::cout << "******************** superadjoint system residual (fwd_hack) ***********************" << std::endl; //adjresid_fwd_hack->print(); std::cout << "\n\nfwd_hack import adjoint system residual (discrete L2): " << system.calculate_norm(*adjresid_fwd_hack,DISCRETE_L2) << "\n" << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 0): " << system.calculate_norm(*adjresid_fwd_hack,0,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 1): " << system.calculate_norm(*adjresid_fwd_hack,1,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 2): " << system.calculate_norm(*adjresid_fwd_hack,2,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 3): " << system.calculate_norm(*adjresid_fwd_hack,3,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 4): " << system.calculate_norm(*adjresid_fwd_hack,4,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 5): " << system.calculate_norm(*adjresid_fwd_hack,5,L2) << std::endl; */ //std::cout << "************************ system.matrix ***********************" << std::endl; //system.matrix->print(); std::cout << "\n------------ herp derp ------------" << std::endl; // The cell wise breakdown ErrorVector cell_wise_error; cell_wise_error.resize((system.rhs)->size()); for(unsigned int i = 0; i < (system.rhs)->size() ; i++) { if(i < system.get_mesh().n_elem()) cell_wise_error[i] = fabs(-0.5*((system.rhs)->el(i) * dual_solution(i)) + system.get_MHF_psiLF(i) - system.get_MLF_psiLF(i)); else cell_wise_error[i] = fabs(-0.5*((system.rhs)->el(i) * dual_solution(i))); /*csv from 'save data' from gmv output gives a few values at each node point (value for every element that shares that node), yet paraview display only seems to show one of them -> the value in an element is given at each of the nodes that it has, hence the repetition; what is displayed in paraview is each element's value; even though MHF_psiLF and MLF_psiLF are stored by element this seems to give elemental contributions that agree with if we had taken the superadj-residual dot product by integrating over elements*/ /*at higher mesh resolutions and lower k, weird-looking artifacts start to appear and it no longer agrees with output from manual integration of superadj-residual...*/ } // Plot it std::ostringstream error_gmv; error_gmv << "error.gmv"; cell_wise_error.plot_error(error_gmv.str(), equation_systems.get_mesh()); //alternate element-wise breakdown, outputed as values matched to element centroids; for matlab plotz primal_solution.swap(dual_solution); system.postprocess(1); primal_solution.swap(dual_solution); system.postprocess(2); std::cout << "\n\n -0.5*M'_HF(psiLF)(superadj): " << std::setprecision(17) << system.get_half_adj_weighted_resid() << "\n"; primal_solution.swap(dual_solution); std::string write_error_here = infileForMesh("error_est_output_file", "error_est_breakdown.dat"); std::ofstream output(write_error_here); for(unsigned int i = 0 ; i < system.get_mesh().n_elem(); i++) { Point elem_cent = system.get_mesh().elem(i)->centroid(); if(output.is_open()) { output << elem_cent(0) << " " << elem_cent(1) << " " << fabs(system.get_half_adj_weighted_resid(i) + system.get_MHF_psiLF(i) - system.get_MLF_psiLF(i)) << "\n"; } } output.close(); } // End if at max adaptive steps #ifdef LIBMESH_HAVE_EXODUS_API // Write out this timestep if we're requested to if ((t_step+1)%write_interval == 0) { std::ostringstream file_name; /* // We write the file in the ExodusII format. file_name << "out_" << std::setw(3) << std::setfill('0') << std::right << t_step+1 << ".e"; //this should write out the primal which should be the same as what's read in... ExodusII_IO(mesh).write_timestep(file_name.str(), equation_systems, 1, //number of time steps written to file system.time); */ } #endif // #ifdef LIBMESH_HAVE_EXODUS_API } // All done. return 0; } //end main
LibMeshInit::LibMeshInit (int argc, const char* const* argv, MPI_Comm COMM_WORLD_IN) #endif { // should _not_ be initialized already. libmesh_assert (!libMesh::initialized()); // Build a command-line parser. command_line.reset (new GetPot (argc, argv)); // Disable performance logging upon request { if (libMesh::on_command_line ("--disable-perflog")) libMesh::perflog.disable_logging(); } // Build a task scheduler { // Get the requested number of threads, defaults to 1 to avoid MPI and // multithreading competition. If you would like to use MPI and multithreading // at the same time then (n_mpi_processes_per_node)x(n_threads) should be the // number of processing cores per node. std::vector<std::string> n_threads(2); n_threads[0] = "--n_threads"; n_threads[1] = "--n-threads"; libMesh::libMeshPrivateData::_n_threads = libMesh::command_line_value (n_threads, 1); // Set the number of OpenMP threads to the same as the number of threads libMesh is going to use #ifdef LIBMESH_HAVE_OPENMP omp_set_num_threads(libMesh::libMeshPrivateData::_n_threads); #endif task_scheduler.reset (new Threads::task_scheduler_init(libMesh::n_threads())); } // Construct singletons who may be at risk of the // "static initialization order fiasco" Singleton::setup(); // Make sure the construction worked libmesh_assert(remote_elem); #if defined(LIBMESH_HAVE_MPI) // Allow the user to bypass MPI initialization if (!libMesh::on_command_line ("--disable-mpi")) { // Check whether the calling program has already initialized // MPI, and avoid duplicate Init/Finalize int flag; MPI_Initialized (&flag); if (!flag) { #if MPI_VERSION > 1 int mpi_thread_provided; const int mpi_thread_requested = libMesh::n_threads() > 1 ? MPI_THREAD_FUNNELED : MPI_THREAD_SINGLE; MPI_Init_thread (&argc, const_cast<char***>(&argv), mpi_thread_requested, &mpi_thread_provided); if ((libMesh::n_threads() > 1) && (mpi_thread_provided < MPI_THREAD_FUNNELED)) { libmesh_warning("Warning: MPI failed to guarantee MPI_THREAD_FUNNELED\n" << "for a threaded run.\n" << "Be sure your library is funneled-thread-safe..." << std::endl); // Ideally, if an MPI stack tells us it's unsafe for us // to use threads, we shouldn't use threads. // In practice, we've encountered one MPI stack (an // mvapich2 configuration) that returned // MPI_THREAD_SINGLE as a proper warning, two stacks // that handle MPI_THREAD_FUNNELED properly, and two // current stacks plus a couple old stacks that return // MPI_THREAD_SINGLE but support libMesh threaded runs // anyway. // libMesh::libMeshPrivateData::_n_threads = 1; // task_scheduler.reset (new Threads::task_scheduler_init(libMesh::n_threads())); } #else if (libMesh::libMeshPrivateData::_n_threads > 1) { libmesh_warning("Warning: using MPI1 for threaded code.\n" << "Be sure your library is funneled-thread-safe..." << std::endl); } MPI_Init (&argc, const_cast<char***>(&argv)); #endif libmesh_initialized_mpi = true; } // Duplicate the input communicator for internal use // And get a Parallel::Communicator copy too, to use // as a default for that API this->_comm = COMM_WORLD_IN; libMesh::GLOBAL_COMM_WORLD = COMM_WORLD_IN; #ifndef LIBMESH_DISABLE_COMMWORLD libMesh::COMM_WORLD = COMM_WORLD_IN; Parallel::Communicator_World = COMM_WORLD_IN; #endif //MPI_Comm_set_name not supported in at least SGI MPT's MPI implementation //MPI_Comm_set_name (libMesh::COMM_WORLD, "libMesh::COMM_WORLD"); libMeshPrivateData::_processor_id = libmesh_cast_int<processor_id_type>(this->comm().rank()); libMeshPrivateData::_n_processors = libmesh_cast_int<processor_id_type>(this->comm().size()); // Set up an MPI error handler if requested. This helps us get // into a debugger with a proper stack when an MPI error occurs. if (libMesh::on_command_line ("--handle-mpi-errors")) { #if MPI_VERSION > 1 MPI_Comm_create_errhandler(libMesh_MPI_Handler, &libmesh_errhandler); MPI_Comm_set_errhandler(libMesh::GLOBAL_COMM_WORLD, libmesh_errhandler); MPI_Comm_set_errhandler(MPI_COMM_WORLD, libmesh_errhandler); #else MPI_Errhandler_create(libMesh_MPI_Handler, &libmesh_errhandler); MPI_Errhandler_set(libMesh::GLOBAL_COMM_WORLD, libmesh_errhandler); MPI_Errhandler_set(MPI_COMM_WORLD, libmesh_errhandler); #endif // #if MPI_VERSION > 1 } } // Could we have gotten bad values from the above calls? libmesh_assert_greater (libMeshPrivateData::_n_processors, 0); // The libmesh_cast_int already tested _processor_id>=0 // libmesh_assert_greater_equal (libMeshPrivateData::_processor_id, 0); // Let's be sure we properly initialize on every processor at once: libmesh_parallel_only(this->comm()); #endif #if defined(LIBMESH_HAVE_PETSC) // Allow the user to bypass PETSc initialization if (!libMesh::on_command_line ("--disable-petsc") #if defined(LIBMESH_HAVE_MPI) // If the user bypassed MPI, we'd better be safe and assume that // PETSc was built to require it; otherwise PETSc initialization // dies. && !libMesh::on_command_line ("--disable-mpi") #endif ) { int ierr=0; PETSC_COMM_WORLD = libMesh::GLOBAL_COMM_WORLD; // Check whether the calling program has already initialized // PETSc, and avoid duplicate Initialize/Finalize PetscBool petsc_already_initialized; ierr = PetscInitialized(&petsc_already_initialized); CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr); if (petsc_already_initialized != PETSC_TRUE) libmesh_initialized_petsc = true; # if defined(LIBMESH_HAVE_SLEPC) // If SLEPc allows us to check whether the calling program // has already initialized it, we do that, and avoid // duplicate Initialize/Finalize. // We assume that SLEPc will handle PETSc appropriately, // which it does in the versions we've checked. # if !SLEPC_VERSION_LESS_THAN(2,3,3) if (!SlepcInitializeCalled) # endif { ierr = SlepcInitialize (&argc, const_cast<char***>(&argv), NULL, NULL); CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr); libmesh_initialized_slepc = true; } # else if (libmesh_initialized_petsc) { ierr = PetscInitialize (&argc, const_cast<char***>(&argv), NULL, NULL); CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr); } # endif } #endif // Re-parse the command-line arguments. Note that PETSc and MPI // initialization above may have removed command line arguments // that are not relevant to this application in the above calls. // We don't want a false-positive by detecting those arguments. command_line->parse_command_line (argc, argv); // The following line is an optimization when simultaneous // C and C++ style access to output streams is not required. // The amount of benefit which occurs is probably implementation // defined, and may be nothing. On the other hand, I have seen // some IO tests where IO peformance improves by a factor of two. if (!libMesh::on_command_line ("--sync-with-stdio")) std::ios::sync_with_stdio(false); // Honor the --separate-libmeshout command-line option. // When this is specified, the library uses an independent ostream // for libMesh::out/libMesh::err messages, and // std::cout and std::cerr are untouched by any other options if (libMesh::on_command_line ("--separate-libmeshout")) { // Redirect. We'll share streambufs with cout/cerr for now, but // presumably anyone using this option will want to replace the // bufs later. std::ostream* newout = new std::ostream(std::cout.rdbuf()); libMesh::out = *newout; std::ostream* newerr = new std::ostream(std::cerr.rdbuf()); libMesh::err = *newerr; } // Honor the --redirect-stdout command-line option. // When this is specified each processor sends // libMesh::out/libMesh::err messages to // stdout.processor.#### if (libMesh::on_command_line ("--redirect-stdout")) { std::ostringstream filename; filename << "stdout.processor." << libMesh::global_processor_id(); _ofstream.reset (new std::ofstream (filename.str().c_str())); // Redirect, saving the original streambufs! out_buf = libMesh::out.rdbuf (_ofstream->rdbuf()); err_buf = libMesh::err.rdbuf (_ofstream->rdbuf()); } // redirect libMesh::out to nothing on all // other processors unless explicitly told // not to via the --keep-cout command-line argument. if (libMesh::global_processor_id() != 0) if (!libMesh::on_command_line ("--keep-cout")) libMesh::out.rdbuf (NULL); // Check command line to override printing // of reference count information. if(libMesh::on_command_line("--disable-refcount-printing") ) ReferenceCounter::disable_print_counter_info(); #ifdef LIBMESH_ENABLE_EXCEPTIONS // Set our terminate handler to write stack traces in the event of a // crash old_terminate_handler = std::set_terminate(libmesh_terminate_handler); #endif if (libMesh::on_command_line("--enable-fpe")) libMesh::enableFPE(true); // The library is now ready for use libMeshPrivateData::_is_initialized = true; // Make sure these work. Library methods // depend on these being implemented properly, // so this is a good time to test them! libmesh_assert (libMesh::initialized()); libmesh_assert (!libMesh::closed()); }