コード例 #1
0
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);
            }
        }
    }
}
コード例 #2
0
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);
    }
}
コード例 #3
0
ファイル: quadrature_conical.C プロジェクト: ZJLi2013/libmesh
// 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++;
      }
}
コード例 #4
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();
}
コード例 #5
0
ファイル: edge_edge3.C プロジェクト: paulovieira/libmesh
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();
      }
    }
}
コード例 #6
0
// ------------------------------------------------------------
// 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());
}
コード例 #7
0
ファイル: fe_szabab_shape_1D.C プロジェクト: elfring/libmesh
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.;
}
コード例 #8
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;
}
コード例 #9
0
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;
}
コード例 #10
0
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
}
コード例 #11
0
ファイル: fe_szabab_shape_1D.C プロジェクト: elfring/libmesh
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.;
}
コード例 #12
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());
}
コード例 #13
0
ファイル: system_norm.C プロジェクト: dschwen/libmesh
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);
}
コード例 #14
0
ファイル: mesh_base.C プロジェクト: rppawlo/libmesh
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());
}
コード例 #15
0
ファイル: mesh_base.C プロジェクト: dongliangchu/libmesh
// ------------------------------------------------------------
// 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());
}
コード例 #16
0
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.;
}
コード例 #17
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.;
}
コード例 #18
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
}
コード例 #19
0
ファイル: xdr_mgf.C プロジェクト: GENGCHN/libmesh
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);
    }

}
コード例 #20
0
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();
}
コード例 #21
0
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();
}
コード例 #22
0
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;
      }
  }
}
コード例 #23
0
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;
}
コード例 #24
0
ファイル: edge_edge4.C プロジェクト: YSB330/libmesh
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);
    }
}
コード例 #25
0
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();
}
コード例 #26
0
ファイル: fe_xyz_shape_2D.C プロジェクト: bwspenc/libmesh
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
}
コード例 #27
0
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);
    }
}
コード例 #28
0
//-----------------------------------------------------------------
// 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);
  }
}
コード例 #29
0
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;
}
コード例 #30
0
ファイル: equation_systems.C プロジェクト: anilkunwar/libmesh
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);
}