Example #1
0
void PetscVector<T>::localize (std::vector<T>& v_local) const
{
  this->_restore_array();

  // This function must be run on all processors at once
  parallel_only();

  PetscErrorCode ierr=0;
  const PetscInt n = this->size();
  const PetscInt nl = this->local_size();
  PetscScalar *values;

  v_local.clear();
  v_local.resize(n, 0.);

  ierr = VecGetArray (_vec, &values);
	 CHKERRABORT(libMesh::COMM_WORLD,ierr);

  numeric_index_type ioff = first_local_index();

  for (PetscInt i=0; i<nl; i++)
    v_local[i+ioff] = static_cast<T>(values[i]);

  ierr = VecRestoreArray (_vec, &values);
	 CHKERRABORT(libMesh::COMM_WORLD,ierr);

  CommWorld.sum(v_local);
}
Example #2
0
PetscErrorCode DMLibMeshSetSystem(DM dm, NonlinearImplicitSystem& sys)
{
  PetscErrorCode ierr;
  PetscFunctionBegin;
  PetscValidHeaderSpecific(dm,DM_CLASSID,1);
  PetscBool islibmesh;
  ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh);
  if(!islibmesh) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM oftype %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
  
  if(dm->setupcalled) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot reset the libMesh system after DM has been set up.");
  DM_libMesh *dlm = (DM_libMesh *)(dm->data);
  dlm->sys =&sys;
  /* Initially populate the sets of active blockids and varids using all of the 
     existing blocks/variables (only variables are supported at the moment). */
  DofMap& dofmap = dlm->sys->get_dof_map();
  dlm->varids->clear();
  dlm->varnames->clear();
  for(unsigned int v = 0; v < dofmap.n_variables(); ++v) {
    std::string vname = dofmap.variable(v).name();
    dlm->varids->insert(std::pair<std::string,unsigned int>(vname,v));
    dlm->varnames->insert(std::pair<unsigned int,std::string>(v,vname));
  }
  const MeshBase& mesh = dlm->sys->get_mesh();
  dlm->blockids->clear();
  dlm->blocknames->clear();
  std::set<subdomain_id_type> blocks;
  /* The following effectively is a verbatim copy of MeshBase::n_subdomains(). */
  // This requires an inspection on every processor
  parallel_only();
  MeshBase::const_element_iterator       el  = mesh.active_elements_begin();
  const MeshBase::const_element_iterator end = mesh.active_elements_end();
  for (; el!=end; ++el)
    blocks.insert((*el)->subdomain_id());
  // Some subdomains may only live on other processors
  Parallel::set_union(blocks);

  std::set<subdomain_id_type>::iterator bit = blocks.begin();
  std::set<subdomain_id_type>::iterator bend = blocks.end();
  if(bit == bend) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "No mesh blocks found.");

  for(; bit != bend; ++bit) {
    subdomain_id_type bid = *bit;
    std::string bname = mesh.subdomain_name(bid);
    if(!bname.length()) {
      /* Block names are currently implemented for Exodus II meshes 
	 only, so we might have to make up our own block names and 
	 maintain our own mapping of block ids to names. 
      */
      std::ostringstream ss;
      ss << "dm" << bid;
      bname = ss.str();
    }
    dlm->blockids->insert(std::pair<std::string,unsigned int>(bname,bid));
    dlm->blocknames->insert(std::pair<unsigned int,std::string>(bid,bname));
  }
  ierr = DMLibMeshSetUpName_Private(dm); CHKERRQ(ierr);
  PetscFunctionReturn(0);
}
Example #3
0
subdomain_id_type MeshBase::n_subdomains() const
{
  // This requires an inspection on every processor
  parallel_only();

  std::set<subdomain_id_type> ids;

  this->subdomain_ids (ids);

  return ids.size();
}
Example #4
0
void MeshBase::subdomain_ids (std::set<subdomain_id_type> &ids) const
{
  // This requires an inspection on every processor
  parallel_only();

  ids.clear();
  
  const_element_iterator       el  = this->active_elements_begin();
  const const_element_iterator end = this->active_elements_end();

  for (; el!=end; ++el)
    ids.insert((*el)->subdomain_id());

  // Some subdomains may only live on other processors
  CommWorld.set_union(ids);
}
Example #5
0
void LocationMap<T>::init(MeshBase& mesh)
{
  // This function must be run on all processors at once
  // for non-serial meshes
  if (!mesh.is_serial())
    parallel_only();

  START_LOG("init()", "LocationMap");

  // Clear the old map
  _map.clear();

  // Cache a bounding box
  _lower_bound.clear();
  _lower_bound.resize(LIBMESH_DIM, std::numeric_limits<Real>::max());
  _upper_bound.clear();
  _upper_bound.resize(LIBMESH_DIM, -std::numeric_limits<Real>::max());

  MeshBase::node_iterator       it  = mesh.nodes_begin();
  const MeshBase::node_iterator end = mesh.nodes_end();

  for (; it != end; ++it)
    {
      Node* node = *it;

      for (unsigned int i=0; i != LIBMESH_DIM; ++i)
        {
          // Expand the bounding box if necessary
          _lower_bound[i] = std::min(_lower_bound[i],
                                     (*node)(i));
          _upper_bound[i] = std::max(_upper_bound[i],
                                     (*node)(i));
        }
    }

  // On a parallel mesh we might not yet have a full bounding box
  if (!mesh.is_serial())
    {
      CommWorld.min(_lower_bound);
      CommWorld.max(_upper_bound);
    }

  this->fill(mesh);

  STOP_LOG("init()", "LocationMap");
}
void EpetraVector<T>::localize (std::vector<T>& v_local) const
{
  // This function must be run on all processors at once
  parallel_only();

  const unsigned int n  = this->size();
  const unsigned int nl = this->local_size();

  libmesh_assert(this->_vec);

  v_local.clear();
  v_local.reserve(n);

  // build up my local part
  for (unsigned int i=0; i<nl; i++)
    v_local.push_back((*this->_vec)[i]);

  CommWorld.allgather (v_local);
}
void MeshRefinement::flag_elements_by_elem_fraction (const ErrorVector& error_per_cell,
						     const Real refine_frac,
						     const Real coarsen_frac,
						     const unsigned int max_l)
{
  parallel_only();

  // The function arguments are currently just there for
  // backwards_compatibility
  if (!_use_member_parameters)
  {
    // If the user used non-default parameters, lets warn
    // that they're deprecated
    if (refine_frac != 0.3 ||
	coarsen_frac != 0.0 ||
	max_l != libMesh::invalid_uint)
      libmesh_deprecated();

    _refine_fraction = refine_frac;
    _coarsen_fraction = coarsen_frac;
    _max_h_level = max_l;
  }

  // Check for valid fractions..
  // The fraction values must be in [0,1]
  libmesh_assert_greater_equal (_refine_fraction, 0);
  libmesh_assert_less_equal (_refine_fraction, 1);
  libmesh_assert_greater_equal (_coarsen_fraction, 0);
  libmesh_assert_less_equal (_coarsen_fraction, 1);

  // The number of active elements in the mesh
  const unsigned int n_active_elem  = _mesh.n_elem();

  // The number of elements to flag for coarsening
  const unsigned int n_elem_coarsen =
    static_cast<unsigned int>(_coarsen_fraction * n_active_elem);

  // The number of elements to flag for refinement
  const unsigned int n_elem_refine =
    static_cast<unsigned int>(_refine_fraction  * n_active_elem);



  // Clean up the refinement flags.  These could be left
  // over from previous refinement steps.
  this->clean_refinement_flags();


  // This vector stores the error and element number for all the
  // active elements.  It will be sorted and the top & bottom
  // elements will then be flagged for coarsening & refinement
  std::vector<float> sorted_error;

  sorted_error.reserve (n_active_elem);

  // Loop over the active elements and create the entry
  // in the sorted_error vector
  MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
  const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();

  for (; elem_it != elem_end; ++elem_it)
    sorted_error.push_back (error_per_cell[(*elem_it)->id()]);

  CommWorld.allgather(sorted_error);

  // Now sort the sorted_error vector
  std::sort (sorted_error.begin(), sorted_error.end());

  // If we're coarsening by parents:
  // Create a sorted error vector with coarsenable parent elements
  // only, sorted by lowest errors first
  ErrorVector error_per_parent, sorted_parent_error;
  if (_coarsen_by_parents)
  {
    Real parent_error_min, parent_error_max;

    create_parent_error_vector(error_per_cell,
			       error_per_parent,
			       parent_error_min,
			       parent_error_max);

    sorted_parent_error = error_per_parent;
    std::sort (sorted_parent_error.begin(), sorted_parent_error.end());

    // All the other error values will be 0., so get rid of them.
    sorted_parent_error.erase (std::remove(sorted_parent_error.begin(),
					   sorted_parent_error.end(), 0.),
			       sorted_parent_error.end());
  }


  float top_error= 0., bottom_error = 0.;

  // Get the maximum error value corresponding to the
  // bottom n_elem_coarsen elements
  if (_coarsen_by_parents && n_elem_coarsen)
    {
      const unsigned int dim = _mesh.mesh_dimension();
      unsigned int twotodim = 1;
      for (unsigned int i=0; i!=dim; ++i)
        twotodim *= 2;

      unsigned int n_parent_coarsen = n_elem_coarsen / (twotodim - 1);

      if (n_parent_coarsen)
	bottom_error = sorted_parent_error[n_parent_coarsen - 1];
    }
  else if (n_elem_coarsen)
    {
      bottom_error = sorted_error[n_elem_coarsen - 1];
    }

  if (n_elem_refine)
    top_error = sorted_error[sorted_error.size() - n_elem_refine];

  // Finally, let's do the element flagging
  elem_it  = _mesh.active_elements_begin();
  for (; elem_it != elem_end; ++elem_it)
    {
      Elem* elem = *elem_it;
      Elem* parent = elem->parent();

      if (_coarsen_by_parents && parent && n_elem_coarsen &&
          error_per_parent[parent->id()] <= bottom_error)
        elem->set_refinement_flag(Elem::COARSEN);

      if (!_coarsen_by_parents && n_elem_coarsen &&
          error_per_cell[elem->id()] <= bottom_error)
        elem->set_refinement_flag(Elem::COARSEN);

      if (n_elem_refine &&
          elem->level() < _max_h_level &&
          error_per_cell[elem->id()] >= top_error)
        elem->set_refinement_flag(Elem::REFINE);
    }
}
//-----------------------------------------------------------------
// Mesh refinement methods
void MeshRefinement::flag_elements_by_error_fraction (const ErrorVector& error_per_cell,
						      const Real refine_frac,
						      const Real coarsen_frac,
						      const unsigned int max_l)
{
  parallel_only();

  // The function arguments are currently just there for
  // backwards_compatibility
  if (!_use_member_parameters)
  {
    // If the user used non-default parameters, lets warn
    // that they're deprecated
    if (refine_frac != 0.3 ||
	coarsen_frac != 0.0 ||
	max_l != libMesh::invalid_uint)
      libmesh_deprecated();

    _refine_fraction = refine_frac;
    _coarsen_fraction = coarsen_frac;
    _max_h_level = max_l;
  }

  // Check for valid fractions..
  // The fraction values must be in [0,1]
  libmesh_assert_greater_equal (_refine_fraction, 0);
  libmesh_assert_less_equal (_refine_fraction, 1);
  libmesh_assert_greater_equal (_coarsen_fraction, 0);
  libmesh_assert_less_equal (_coarsen_fraction, 1);

  // Clean up the refinement flags.  These could be left
  // over from previous refinement steps.
  this->clean_refinement_flags();

  // We're getting the minimum and maximum error values
  // for the ACTIVE elements
  Real error_min = 1.e30;
  Real error_max = 0.;

  // And, if necessary, for their parents
  Real parent_error_min = 1.e30;
  Real parent_error_max = 0.;

  // Prepare another error vector if we need to sum parent errors
  ErrorVector error_per_parent;
  if (_coarsen_by_parents)
  {
    create_parent_error_vector(error_per_cell,
			       error_per_parent,
			       parent_error_min,
			       parent_error_max);
  }

  // We need to loop over all active elements to find the minimum
  MeshBase::element_iterator       el_it  =
    _mesh.active_local_elements_begin();
  const MeshBase::element_iterator el_end =
    _mesh.active_local_elements_end();

  for (; el_it != el_end; ++el_it)
  {
    const unsigned int id  = (*el_it)->id();
    libmesh_assert_less (id, error_per_cell.size());

    error_max = std::max (error_max, error_per_cell[id]);
    error_min = std::min (error_min, error_per_cell[id]);
  }
  CommWorld.max(error_max);
  CommWorld.min(error_min);

  // Compute the cutoff values for coarsening and refinement
  const Real error_delta = (error_max - error_min);
  const Real parent_error_delta = parent_error_max - parent_error_min;

  const Real refine_cutoff  = (1.- _refine_fraction)*error_max;
  const Real coarsen_cutoff = _coarsen_fraction*error_delta + error_min;
  const Real parent_cutoff = _coarsen_fraction*parent_error_delta + error_min;

//   // Print information about the error
//   libMesh::out << " Error Information:"                     << std::endl
// 	    << " ------------------"                     << std::endl
// 	    << "   min:              " << error_min      << std::endl
// 	    << "   max:              " << error_max      << std::endl
// 	    << "   delta:            " << error_delta    << std::endl
// 	    << "     refine_cutoff:  " << refine_cutoff  << std::endl
// 	    << "     coarsen_cutoff: " << coarsen_cutoff << std::endl;



  // Loop over the elements and flag them for coarsening or
  // refinement based on the element error

  MeshBase::element_iterator       e_it  =
    _mesh.active_elements_begin();
  const MeshBase::element_iterator e_end =
    _mesh.active_elements_end();
  for (; e_it != e_end; ++e_it)
  {
    Elem* elem             = *e_it;
    const unsigned int id  = elem->id();

    libmesh_assert_less (id, error_per_cell.size());

    const float elem_error = error_per_cell[id];

    if (_coarsen_by_parents)
    {
      Elem* parent           = elem->parent();
      if (parent)
      {
	const unsigned int parentid  = parent->id();
	if (error_per_parent[parentid] >= 0. &&
	    error_per_parent[parentid] <= parent_cutoff)
	  elem->set_refinement_flag(Elem::COARSEN);
      }
    }
    // Flag the element for coarsening if its error
    // is <= coarsen_fraction*delta + error_min
    else if (elem_error <= coarsen_cutoff)
    {
      elem->set_refinement_flag(Elem::COARSEN);
    }

    // Flag the element for refinement if its error
    // is >= refinement_cutoff.
    if (elem_error >= refine_cutoff)
      if (elem->level() < _max_h_level)
	elem->set_refinement_flag(Elem::REFINE);
  }
}
bool MeshRefinement::flag_elements_by_nelem_target (const ErrorVector& error_per_cell)
{
  parallel_only();

  // Check for valid fractions..
  // The fraction values must be in [0,1]
  libmesh_assert_greater_equal (_refine_fraction, 0);
  libmesh_assert_less_equal (_refine_fraction, 1);
  libmesh_assert_greater_equal (_coarsen_fraction, 0);
  libmesh_assert_less_equal (_coarsen_fraction, 1);

  // This function is currently only coded to work when coarsening by
  // parents - it's too hard to guess how many coarsenings will be
  // performed otherwise.
  libmesh_assert (_coarsen_by_parents);

  // The number of active elements in the mesh - hopefully less than
  // 2 billion on 32 bit machines
  const unsigned int n_active_elem  = _mesh.n_active_elem();

  // The maximum number of active elements to flag for coarsening
  const unsigned int max_elem_coarsen =
    static_cast<unsigned int>(_coarsen_fraction * n_active_elem) + 1;

  // The maximum number of elements to flag for refinement
  const unsigned int max_elem_refine  =
    static_cast<unsigned int>(_refine_fraction  * n_active_elem) + 1;

  // Clean up the refinement flags.  These could be left
  // over from previous refinement steps.
  this->clean_refinement_flags();

  // The target number of elements to add or remove
  const int n_elem_new = _nelem_target - n_active_elem;

  // Create an vector with active element errors and ids,
  // sorted by highest errors first
  const unsigned int max_elem_id = _mesh.max_elem_id();
  std::vector<std::pair<float, unsigned int> > sorted_error;

  sorted_error.reserve (n_active_elem);

  // On a ParallelMesh, we need to communicate to know which remote ids
  // correspond to active elements.
  {
    std::vector<bool> is_active(max_elem_id, false);

    MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
    const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
    for (; elem_it != elem_end; ++elem_it)
      {
        const unsigned int eid = (*elem_it)->id();
        is_active[eid] = true;
        libmesh_assert_less (eid, error_per_cell.size());
        sorted_error.push_back
          (std::make_pair(error_per_cell[eid], eid));
      }

    CommWorld.max(is_active);

    CommWorld.allgather(sorted_error);
  }

  // Default sort works since pairs are sorted lexicographically
  std::sort (sorted_error.begin(), sorted_error.end());
  std::reverse (sorted_error.begin(), sorted_error.end());

  // Create a sorted error vector with coarsenable parent elements
  // only, sorted by lowest errors first
  ErrorVector error_per_parent;
  std::vector<std::pair<float, unsigned int> > sorted_parent_error;
  Real parent_error_min, parent_error_max;

  create_parent_error_vector(error_per_cell,
                             error_per_parent,
                             parent_error_min,
                             parent_error_max);

  // create_parent_error_vector sets values for non-parents and
  // non-coarsenable parents to -1.  Get rid of them.
  for (unsigned int i=0; i != error_per_parent.size(); ++i)
    if (error_per_parent[i] != -1)
      sorted_parent_error.push_back(std::make_pair(error_per_parent[i], i));

  std::sort (sorted_parent_error.begin(), sorted_parent_error.end());

  // Keep track of how many elements we plan to coarsen & refine
  unsigned int coarsen_count = 0;
  unsigned int refine_count = 0;

  const unsigned int dim = _mesh.mesh_dimension();
  unsigned int twotodim = 1;
  for (unsigned int i=0; i!=dim; ++i)
    twotodim *= 2;

  // First, let's try to get our element count to target_nelem
  if (n_elem_new >= 0)
  {
    // Every element refinement creates at least
    // 2^dim-1 new elements
    refine_count =
      std::min(static_cast<unsigned int>(n_elem_new / (twotodim-1)),
	       max_elem_refine);
  }
  else
  {
    // Every successful element coarsening is likely to destroy
    // 2^dim-1 net elements.
    coarsen_count =
      std::min(static_cast<unsigned int>(-n_elem_new / (twotodim-1)),
	       max_elem_coarsen);
  }

  // Next, let's see if we can trade any refinement for coarsening
  while (coarsen_count < max_elem_coarsen &&
         refine_count < max_elem_refine &&
         coarsen_count < sorted_parent_error.size() &&
         refine_count < sorted_error.size() &&
         sorted_error[refine_count].first >
	 sorted_parent_error[coarsen_count].first * _coarsen_threshold)
  {
    coarsen_count++;
    refine_count++;
  }

  // On a ParallelMesh, we need to communicate to know which remote ids
  // correspond to refinable elements
  unsigned int successful_refine_count = 0;
  {
    std::vector<bool> is_refinable(max_elem_id, false);

    for (unsigned int i=0; i != sorted_error.size(); ++i)
      {
        unsigned int eid = sorted_error[i].second;
        Elem *elem = _mesh.query_elem(eid);
        if (elem && elem->level() < _max_h_level)
	  is_refinable[eid] = true;
      }
    CommWorld.max(is_refinable);

    if (refine_count > max_elem_refine)
      refine_count = max_elem_refine;
    for (unsigned int i=0; i != sorted_error.size(); ++i)
      {
        if (successful_refine_count >= refine_count)
          break;

        unsigned int eid = sorted_error[i].second;
        Elem *elem = _mesh.query_elem(eid);
        if (is_refinable[eid])
          {
            if (elem)
	      elem->set_refinement_flag(Elem::REFINE);
	    successful_refine_count++;
          }
      }
  }

  // If we couldn't refine enough elements, don't coarsen too many
  // either
  if (coarsen_count < (refine_count - successful_refine_count))
    coarsen_count = 0;
  else
    coarsen_count -= (refine_count - successful_refine_count);

  if (coarsen_count > max_elem_coarsen)
    coarsen_count = max_elem_coarsen;

  unsigned int successful_coarsen_count = 0;
  if (coarsen_count)
    {
      for (unsigned int i=0; i != sorted_parent_error.size(); ++i)
        {
          if (successful_coarsen_count >= coarsen_count * twotodim)
            break;

          unsigned int parent_id = sorted_parent_error[i].second;
          Elem *parent = _mesh.query_elem(parent_id);

          // On a ParallelMesh we skip remote elements
          if (!parent)
            continue;

          libmesh_assert(parent->has_children());
          for (unsigned int c=0; c != parent->n_children(); ++c)
            {
              Elem *elem = parent->child(c);
              if (elem && elem != remote_elem)
                {
                  libmesh_assert(elem->active());
                  elem->set_refinement_flag(Elem::COARSEN);
                  successful_coarsen_count++;
                }
            }
        }
    }

  // Return true if we've done all the AMR/C we can
  if (!successful_coarsen_count &&
      !successful_refine_count)
    return true;
  // And false if there may still be more to do.
  return false;
}
void MeshRefinement::flag_elements_by_error_tolerance (const ErrorVector& error_per_cell_in)
{
  parallel_only();

  libmesh_assert_greater (_coarsen_threshold, 0);

  // Check for valid fractions..
  // The fraction values must be in [0,1]
  libmesh_assert_greater_equal (_refine_fraction, 0);
  libmesh_assert_less_equal (_refine_fraction, 1);
  libmesh_assert_greater_equal (_coarsen_fraction, 0);
  libmesh_assert_less_equal (_coarsen_fraction, 1);

  // How much error per cell will we tolerate?
  const Real local_refinement_tolerance =
    _absolute_global_tolerance / std::sqrt(static_cast<Real>(_mesh.n_active_elem()));
  const Real local_coarsening_tolerance =
    local_refinement_tolerance * _coarsen_threshold;

  // Prepare another error vector if we need to sum parent errors
  ErrorVector error_per_parent;
  if (_coarsen_by_parents)
  {
    Real parent_error_min, parent_error_max;

    create_parent_error_vector(error_per_cell_in,
			       error_per_parent,
			       parent_error_min,
			       parent_error_max);
  }

  MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
  const MeshBase::element_iterator elem_end = _mesh.active_elements_end();

  for (; elem_it != elem_end; ++elem_it)
  {
    Elem* elem = *elem_it;
    Elem* parent = elem->parent();
    const unsigned int elem_number = elem->id();
    const float        elem_error  = error_per_cell_in[elem_number];

    if (elem_error > local_refinement_tolerance &&
	elem->level() < _max_h_level)
      elem->set_refinement_flag(Elem::REFINE);

    if (!_coarsen_by_parents && elem_error <
	local_coarsening_tolerance)
      elem->set_refinement_flag(Elem::COARSEN);

    if (_coarsen_by_parents && parent)
    {
      float parent_error = error_per_parent[parent->id()];
      if (parent_error >= 0.)
      {
	const Real parent_coarsening_tolerance =
	  std::sqrt(parent->n_children() *
		    local_coarsening_tolerance *
		    local_coarsening_tolerance);
	if (parent_error < parent_coarsening_tolerance)
	  elem->set_refinement_flag(Elem::COARSEN);
      }
    }
  }
}
void ParmetisPartitioner::assign_partitioning (MeshBase& mesh)
{
  // This function must be run on all processors at once
  parallel_only();

  const unsigned int
    first_local_elem = _vtxdist[libMesh::processor_id()];

  std::vector<std::vector<unsigned int> >
    requested_ids(libMesh::n_processors()),
    requests_to_fill(libMesh::n_processors());

  MeshBase::element_iterator elem_it  = mesh.active_elements_begin();
  MeshBase::element_iterator elem_end = mesh.active_elements_end();

  for (; elem_it != elem_end; ++elem_it)
    {
      Elem *elem = *elem_it;

      // we need to get the index from the owning processor
      // (note we cannot assign it now -- we are iterating
      // over elements again and this will be bad!)
      libmesh_assert_less (elem->processor_id(), requested_ids.size());
      requested_ids[elem->processor_id()].push_back(elem->id());
    }

  // Trade with all processors (including self) to get their indices
  for (unsigned int pid=0; pid<libMesh::n_processors(); pid++)
    {
      // Trade my requests with processor procup and procdown
      const unsigned int procup = (libMesh::processor_id() + pid) %
	                           libMesh::n_processors();
      const unsigned int procdown = (libMesh::n_processors() +
				     libMesh::processor_id() - pid) %
	                             libMesh::n_processors();

      CommWorld.send_receive (procup,   requested_ids[procup],
			      procdown, requests_to_fill[procdown]);

      // we can overwrite these requested ids in-place.
      for (unsigned int i=0; i<requests_to_fill[procdown].size(); i++)
	{
	  const unsigned int requested_elem_index =
	    requests_to_fill[procdown][i];

	  libmesh_assert(_global_index_by_pid_map.count(requested_elem_index));

	  const unsigned int global_index_by_pid =
	    _global_index_by_pid_map[requested_elem_index];

	  const unsigned int local_index =
	    global_index_by_pid - first_local_elem;

	  libmesh_assert_less (local_index, _part.size());
	  libmesh_assert_less (local_index, mesh.n_active_local_elem());

	  const unsigned int elem_procid =
	    static_cast<unsigned int>(_part[local_index]);

	  libmesh_assert_less (elem_procid, static_cast<unsigned int>(_nparts));

	  requests_to_fill[procdown][i] = elem_procid;
	}

      // Trade back
      CommWorld.send_receive (procdown, requests_to_fill[procdown],
			      procup,   requested_ids[procup]);
    }

   // and finally assign the partitioning.
   // note we are iterating in exactly the same order
   // used to build up the request, so we can expect the
   // required entries to be in the proper sequence.
   elem_it  = mesh.active_elements_begin();
   elem_end = mesh.active_elements_end();

   for (std::vector<unsigned int> counters(libMesh::n_processors(), 0);
	elem_it != elem_end; ++elem_it)
     {
       Elem *elem = *elem_it;

       const unsigned int current_pid = elem->processor_id();

       libmesh_assert_less (counters[current_pid], requested_ids[current_pid].size());

       const unsigned int elem_procid =
	 requested_ids[current_pid][counters[current_pid]++];

       libmesh_assert_less (elem_procid, static_cast<unsigned int>(_nparts));
       elem->processor_id() = elem_procid;
     }
}
//-----------------------------------------------------------------
// Mesh refinement methods
bool MeshRefinement::limit_level_mismatch_at_node (const unsigned int max_mismatch)
{
  // This function must be run on all processors at once
  parallel_only();

  bool flags_changed = false;


  // Vector holding the maximum element level that touches a node.
  std::vector<unsigned char> max_level_at_node (_mesh.n_nodes(), 0);
  std::vector<unsigned char> max_p_level_at_node (_mesh.n_nodes(), 0);


  // Loop over all the active elements & fill the vector
  {
    MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = _mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
	const Elem* elem = *elem_it;
	const unsigned char elem_level =
	  elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0);
	const unsigned char elem_p_level =
	  elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0);

	// Set the max_level at each node
	for (unsigned int n=0; n<elem->n_nodes(); n++)
	  {
	    const unsigned int node_number = elem->node(n);

	    libmesh_assert_less (node_number, max_level_at_node.size());

	    max_level_at_node[node_number] =
	      std::max (max_level_at_node[node_number], elem_level);
	    max_p_level_at_node[node_number] =
	      std::max (max_p_level_at_node[node_number], elem_p_level);
	  }
      }
  }


  // Now loop over the active elements and flag the elements
  // who violate the requested level mismatch
  {
    MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = _mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
	Elem* elem = *elem_it;
	const unsigned int elem_level = elem->level();
	const unsigned int elem_p_level = elem->p_level();

	// Skip the element if it is already fully flagged
	if (elem->refinement_flag() == Elem::REFINE &&
            elem->p_refinement_flag() == Elem::REFINE)
	  continue;

	// Loop over the nodes, check for possible mismatch
	for (unsigned int n=0; n<elem->n_nodes(); n++)
	  {
	    const unsigned int node_number = elem->node(n);

	    // Flag the element for refinement if it violates
	    // the requested level mismatch
	    if ( (elem_level + max_mismatch) < max_level_at_node[node_number]
                 && elem->refinement_flag() != Elem::REFINE)
	      {
		elem->set_refinement_flag (Elem::REFINE);
		flags_changed = true;
	      }
	    if ( (elem_p_level + max_mismatch) < max_p_level_at_node[node_number]
                 && elem->p_refinement_flag() != Elem::REFINE)
	      {
		elem->set_p_refinement_flag (Elem::REFINE);
		flags_changed = true;
	      }
	  }
      }
  }

  // If flags changed on any processor then they changed globally
  CommWorld.max(flags_changed);

  return flags_changed;
}
bool MeshRefinement::eliminate_unrefined_patches ()
{
  // This function must be run on all processors at once
  parallel_only();

  bool flags_changed = false;

  MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
  const MeshBase::element_iterator elem_end = _mesh.active_elements_end();

  for (; elem_it != elem_end; ++elem_it)
    {
      Elem* elem = *elem_it;
      // First assume that we'll have to flag this element for both h
      // and p refinement, then change our minds if we see any
      // neighbors that are as coarse or coarser than us.
      bool h_flag_me = true,
           p_flag_me = true;


      // Skip the element if it is already fully flagged for refinement
      if (elem->p_refinement_flag() == Elem::REFINE)
	p_flag_me = false;
      if (elem->refinement_flag() == Elem::REFINE)
        {
          h_flag_me = false;
          if (!p_flag_me)
            continue;
        }
      // Test the parent if that is already flagged for coarsening
      else if (elem->refinement_flag() == Elem::COARSEN)
        {
          libmesh_assert(elem->parent());
	  elem = elem->parent();
          // FIXME - this doesn't seem right - RHS
          if (elem->refinement_flag() != Elem::COARSEN_INACTIVE)
            continue;
          p_flag_me = false;
        }

      const unsigned int my_level = elem->level();
      int my_p_adjustment = 0;
      if (elem->p_refinement_flag() == Elem::REFINE)
        my_p_adjustment = 1;
      else if (elem->p_refinement_flag() == Elem::COARSEN)
        {
          libmesh_assert_greater (elem->p_level(), 0);
          my_p_adjustment = -1;
        }
      const unsigned int my_new_p_level = elem->p_level() +
                                          my_p_adjustment;

      // Check all the element neighbors
      for (unsigned int n=0; n<elem->n_neighbors(); n++)
        {
          const Elem *neighbor = elem->neighbor(n);
	  // Quit if the element is on a local boundary
	  if (neighbor == NULL || neighbor == remote_elem)
            {
              h_flag_me = false;
              p_flag_me = false;
              break;
            }
          // if the neighbor will be equally or less refined than
	  // we are, then we will not become an unrefined island.
          // So if we are still considering h refinement:
          if (h_flag_me &&
            // If our neighbor is already at a lower level,
            // it can't end up at a higher level even if it
            // is flagged for refinement once
             ((neighbor->level() < my_level) ||
            // If our neighbor is at the same level but isn't
            // flagged for refinement, it won't end up at a
            // higher level
             ((neighbor->active()) &&
              (neighbor->refinement_flag() != Elem::REFINE)) ||
            // If our neighbor is currently more refined but is
            // a parent flagged for coarsening, it will end up
            // at the same level.
             (neighbor->refinement_flag() == Elem::COARSEN_INACTIVE)))
            {
              // We've proven we won't become an unrefined island,
              // so don't h refine to avoid that.
	      h_flag_me = false;

              // If we've also proven we don't need to p refine,
              // we don't need to check more neighbors
              if (!p_flag_me)
                break;
            }
	  if (p_flag_me)
            {
	      // if active neighbors will have a p level
	      // equal to or lower than ours, then we do not need to p
              // refine ourselves.
              if (neighbor->active())
                {
                  int p_adjustment = 0;
                  if (neighbor->p_refinement_flag() == Elem::REFINE)
                    p_adjustment = 1;
                  else if (neighbor->p_refinement_flag() == Elem::COARSEN)
                    {
                      libmesh_assert_greater (neighbor->p_level(), 0);
                      p_adjustment = -1;
                    }
                  if (my_new_p_level >= neighbor->p_level() + p_adjustment)
                    {
                      p_flag_me = false;
                      if (!h_flag_me)
                        break;
                    }
                }
              // If we have inactive neighbors, we need to
              // test all their active descendants which neighbor us
              else if (neighbor->ancestor())
                {
                  if (neighbor->min_new_p_level_by_neighbor(elem,
                      my_new_p_level + 2) <= my_new_p_level)
                    {
                      p_flag_me = false;
                      if (!h_flag_me)
                        break;
                    }
                }
            }
        }

      if (h_flag_me)
	{
	  // Parents that would create islands should no longer
          // coarsen
          if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
            {
              for (unsigned int c=0; c<elem->n_children(); c++)
                {
                  libmesh_assert_equal_to (elem->child(c)->refinement_flag(),
                                          Elem::COARSEN);
                  elem->child(c)->set_refinement_flag(Elem::DO_NOTHING);
                }
              elem->set_refinement_flag(Elem::INACTIVE);
            }
          else
	    elem->set_refinement_flag(Elem::REFINE);
	  flags_changed = true;
	}
      if (p_flag_me)
	{
          if (elem->p_refinement_flag() == Elem::COARSEN)
	    elem->set_p_refinement_flag(Elem::DO_NOTHING);
          else
	    elem->set_p_refinement_flag(Elem::REFINE);
	  flags_changed = true;
	}
    }

  // If flags changed on any processor then they changed globally
  CommWorld.max(flags_changed);

  return flags_changed;
}
//-----------------------------------------------------------------
// Mesh refinement methods
bool MeshRefinement::limit_level_mismatch_at_edge (const unsigned int max_mismatch)
{
  // This function must be run on all processors at once
  parallel_only();

  bool flags_changed = false;


  // Maps holding the maximum element level that touches an edge
  std::map<std::pair<unsigned int, unsigned int>, unsigned char>
    max_level_at_edge;
  std::map<std::pair<unsigned int, unsigned int>, unsigned char>
    max_p_level_at_edge;

  // Loop over all the active elements & fill the maps
  {
    MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = _mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
	const Elem* elem = *elem_it;
	const unsigned char elem_level =
	  elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0);
	const unsigned char elem_p_level =
	  elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0);

	// Set the max_level at each edge
	for (unsigned int n=0; n<elem->n_edges(); n++)
	  {
            AutoPtr<Elem> edge = elem->build_edge(n);
            unsigned int childnode0 = edge->node(0);
            unsigned int childnode1 = edge->node(1);
            if (childnode1 < childnode0)
              std::swap(childnode0, childnode1);

	    for (const Elem *p = elem; p != NULL; p = p->parent())
	      {
                AutoPtr<Elem> pedge = p->build_edge(n);
		unsigned int node0 = pedge->node(0);
		unsigned int node1 = pedge->node(1);

                if (node1 < node0)
                  std::swap(node0, node1);

		// If elem does not share this edge with its ancestor
		// p, refinement levels of elements sharing p's edge
		// are not restricted by refinement levels of elem.
		// Furthermore, elem will not share this edge with any
		// of p's ancestors, so we can safely break out of the
		// for loop early.
		if (node0 != childnode0 && node1 != childnode1)
		  break;

                childnode0 = node0;
                childnode1 = node1;

                std::pair<unsigned int, unsigned int> edge_key =
                  std::make_pair(node0, node1);

                if (max_level_at_edge.find(edge_key) ==
                    max_level_at_edge.end())
                  {
                    max_level_at_edge[edge_key] = elem_level;
	            max_p_level_at_edge[edge_key] = elem_p_level;
                  }
                else
                  {
	            max_level_at_edge[edge_key] =
	              std::max (max_level_at_edge[edge_key], elem_level);
	            max_p_level_at_edge[edge_key] =
	              std::max (max_p_level_at_edge[edge_key], elem_p_level);
                  }
              }
	  }
      }
  }


  // Now loop over the active elements and flag the elements
  // who violate the requested level mismatch
  {
    MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = _mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
	Elem* elem = *elem_it;
	const unsigned int elem_level = elem->level();
	const unsigned int elem_p_level = elem->p_level();

	// Skip the element if it is already fully flagged
	if (elem->refinement_flag() == Elem::REFINE &&
            elem->p_refinement_flag() == Elem::REFINE)
	  continue;

	// Loop over the nodes, check for possible mismatch
	for (unsigned int n=0; n<elem->n_edges(); n++)
	  {
            AutoPtr<Elem> edge = elem->build_edge(n);
            unsigned int node0 = edge->node(0);
            unsigned int node1 = edge->node(1);
            if (node1 < node0)
              std::swap(node0, node1);

            std::pair<unsigned int, unsigned int> edge_key =
              std::make_pair(node0, node1);

	    // Flag the element for refinement if it violates
	    // the requested level mismatch
	    if ( (elem_level + max_mismatch) < max_level_at_edge[edge_key]
                 && elem->refinement_flag() != Elem::REFINE)
	      {
		elem->set_refinement_flag (Elem::REFINE);
		flags_changed = true;
	      }
	    if ( (elem_p_level + max_mismatch) < max_p_level_at_edge[edge_key]
                 && elem->p_refinement_flag() != Elem::REFINE)
	      {
		elem->set_p_refinement_flag (Elem::REFINE);
		flags_changed = true;
	      }
	  }
      }
  }

  // If flags changed on any processor then they changed globally
  CommWorld.max(flags_changed);

  return flags_changed;
}
Example #15
0
void MeshBase::prepare_for_use (const bool skip_renumber_nodes_and_elements)
{
  parallel_only();

  // A distributed mesh may have processors with no elements (or
  // processors with no elements of higher dimension, if we ever
  // support mixed-dimension meshes), but we want consistent
  // mesh_dimension anyways.
  libmesh_assert(CommWorld.verify(this->is_serial()));

  if (!this->is_serial())
    {
      unsigned int dim = this->mesh_dimension();
      CommWorld.max(dim);
      this->set_mesh_dimension(dim);
    }

  // Renumber the nodes and elements so that they in contiguous
  // blocks.  By default, _skip_renumber_nodes_and_elements is false.
  //
  // We may currently change that by passing
  // skip_renumber_nodes_and_elements==true to this function, but we
  // should use the allow_renumbering() accessor instead.
  //
  // Instances where you if prepare_for_use() should not renumber the nodes
  // and elements include reading in e.g. an xda/r or gmv file. In
  // this case, the ordering of the nodes may depend on an accompanying
  // solution, and the node ordering cannot be changed.

  if (skip_renumber_nodes_and_elements)
    {
      libmesh_deprecated();
      this->allow_renumbering(false);
    }

  // Mesh modification operations might not leave us with consistent
  // id counts, but our partitioner might need that consistency.
  if(!_skip_renumber_nodes_and_elements)
    this->renumber_nodes_and_elements();
  else
    this->update_parallel_id_counts();

  // Let all the elements find their neighbors
  this->find_neighbors();

  // Partition the mesh.
  this->partition();

  // If we're using ParallelMesh, we'll want it parallelized.
  this->delete_remote_elements();

  if(!_skip_renumber_nodes_and_elements)
    this->renumber_nodes_and_elements();

  // Reset our PointLocator.  This needs to happen any time the elements
  // in the underlying elements in the mesh have changed, so we do it here.
  this->clear_point_locator();

  // The mesh is now prepared for use.
  _is_prepared = true;
}
Example #16
0
inline
void SparseMatrix<T>::print(std::ostream& os, const bool sparse) const
{
  parallel_only();

  libmesh_assert (this->initialized());

  if(!this->_dof_map)
  {
    os << std::endl << "Error!  Trying to print a matrix with no dof_map set!" << std::endl << std::endl;
    libmesh_error();
  }

  // We'll print the matrix from processor 0 to make sure
  // it's serialized properly
  if (libMesh::processor_id() == 0)
    {
      libmesh_assert(this->_dof_map->first_dof() == 0);
      for (unsigned int i=this->_dof_map->first_dof();
           i!=this->_dof_map->end_dof(); ++i)
        {
	  if(sparse)
	    {
	      for (unsigned int j=0; j<this->n(); j++)
		{
		  T c = (*this)(i,j);
		  if (c != static_cast<T>(0.0))
		    {
		      os << i << " " << j << " " << c << std::endl;
		    }
		}
	    }
	  else
	    {
	      for (unsigned int j=0; j<this->n(); j++)
		os << (*this)(i,j) << " ";
	      os << std::endl;
	    }
        }

      std::vector<unsigned int> ibuf, jbuf;
      std::vector<T> cbuf;
      unsigned int currenti = this->_dof_map->end_dof();
      for (unsigned int p=1; p < libMesh::n_processors(); ++p)
        {
          Parallel::receive(p, ibuf);
          Parallel::receive(p, jbuf);
          Parallel::receive(p, cbuf);
          libmesh_assert(ibuf.size() == jbuf.size());
          libmesh_assert(ibuf.size() == cbuf.size());

          if (ibuf.empty())
            continue;
          libmesh_assert(ibuf.front() >= currenti);
          libmesh_assert(ibuf.back() >= ibuf.front());

          unsigned int currentb = 0;
          for (;currenti <= ibuf.back(); ++currenti)
            {
	      if(sparse)
		{
		  for (unsigned int j=0; j<this->n(); j++)
		    {
		      if (currentb < ibuf.size() &&
			  ibuf[currentb] == currenti &&
			  jbuf[currentb] == j)
			{
			  os << currenti << " " << j << " " << cbuf[currentb] << std::endl;
			  currentb++;
			}
		    }
		}
	      else
		{
		  for (unsigned int j=0; j<this->n(); j++)
		    {
		      if (currentb < ibuf.size() &&
			  ibuf[currentb] == currenti &&
			  jbuf[currentb] == j)
			{
			  os << cbuf[currentb] << " ";
			  currentb++;
			}
		      else
			os << static_cast<T>(0.0) << " ";
		    }
		  os << std::endl;
		}
            }
        }
      if(!sparse)
	{
	  for (; currenti != this->m(); ++currenti)
	    {
	      for (unsigned int j=0; j<this->n(); j++)
		os << static_cast<T>(0.0) << " ";
	      os << std::endl;
	    }
	}
    }
  else
    {
      std::vector<unsigned int> ibuf, jbuf;
      std::vector<T> cbuf;

      // We'll assume each processor has access to entire
      // matrix rows, so (*this)(i,j) is valid if i is a local index.
      for (unsigned int i=this->_dof_map->first_dof();
           i!=this->_dof_map->end_dof(); ++i)
        {
          for (unsigned int j=0; j<this->n(); j++)
	    {
              T c = (*this)(i,j);
              if (c != static_cast<T>(0.0))
                {
                  ibuf.push_back(i);
                  jbuf.push_back(j);
                  cbuf.push_back(c);
                }
	    }
        }
      Parallel::send(0,ibuf);
      Parallel::send(0,jbuf);
      Parallel::send(0,cbuf);
    }
}
Example #17
0
void ExactSolution::_compute_error(const std::string& sys_name,
				   const std::string& unknown_name,
				   std::vector<Real>& error_vals)
{
  // This function must be run on all processors at once
  parallel_only();

  // Make sure we aren't "overconfigured"
  libmesh_assert (!(_exact_values.size() && _equation_systems_fine));

  // Get a reference to the system whose error is being computed.
  // If we have a fine grid, however, we'll integrate on that instead
  // for more accuracy.
  const System& computed_system = _equation_systems_fine ?
    _equation_systems_fine->get_system(sys_name) :
    _equation_systems.get_system (sys_name);

  const Real time = _equation_systems.get_system(sys_name).time;

  const unsigned int sys_num = computed_system.number();
  const unsigned int var = computed_system.variable_number(unknown_name);
  const unsigned int var_component =
    computed_system.variable_scalar_number(var, 0);

  // Prepare a global solution and a MeshFunction of the coarse system if we need one
  AutoPtr<MeshFunction> coarse_values;
  AutoPtr<NumericVector<Number> > comparison_soln = NumericVector<Number>::build();
  if (_equation_systems_fine)
    {
      const System& comparison_system
	= _equation_systems.get_system(sys_name);

      std::vector<Number> global_soln;
      comparison_system.update_global_solution(global_soln);
      comparison_soln->init(comparison_system.solution->size(), true, SERIAL);
      (*comparison_soln) = global_soln;

      coarse_values = AutoPtr<MeshFunction>
	(new MeshFunction(_equation_systems,
			  *comparison_soln,
			  comparison_system.get_dof_map(),
			  comparison_system.variable_number(unknown_name)));
      coarse_values->init();
    }

  // Initialize any functors we're going to use
  for (unsigned int i=0; i != _exact_values.size(); ++i)
    if (_exact_values[i])
      _exact_values[i]->init();

  for (unsigned int i=0; i != _exact_derivs.size(); ++i)
    if (_exact_derivs[i])
      _exact_derivs[i]->init();

  for (unsigned int i=0; i != _exact_hessians.size(); ++i)
    if (_exact_hessians[i])
      _exact_hessians[i]->init();

  // Get a reference to the dofmap and mesh for that system
  const DofMap& computed_dof_map = computed_system.get_dof_map();

  const MeshBase& _mesh = computed_system.get_mesh();

  const unsigned int dim = _mesh.mesh_dimension();

  // Zero the error before summation
  // 0 - sum of square of function error (L2)
  // 1 - sum of square of gradient error (H1 semi)
  // 2 - sum of square of Hessian error (H2 semi)
  // 3 - sum of sqrt(square of function error) (L1)
  // 4 - max of sqrt(square of function error) (Linfty)
  // 5 - sum of square of curl error (HCurl semi)
  // 6 - sum of square of div error (HDiv semi)
  error_vals = std::vector<Real>(7, 0.);

  // Construct Quadrature rule based on default quadrature order
  const FEType& fe_type  = computed_dof_map.variable_type(var);

  unsigned int n_vec_dim = FEInterface::n_vec_dim( _mesh, fe_type );

  // FIXME: MeshFunction needs to be updated to support vector-valued
  //        elements before we can use a reference solution.
  if( (n_vec_dim > 1) && _equation_systems_fine )
    {
      libMesh::err << "Error calculation using reference solution not yet\n"
		   << "supported for vector-valued elements."
		   << std::endl;
      libmesh_not_implemented();
    }

  AutoPtr<QBase> qrule =
    fe_type.default_quadrature_rule (dim,
                                     _extra_order);

  // Construct finite element object

  AutoPtr<FEGenericBase<OutputShape> > fe(FEGenericBase<OutputShape>::build(dim, fe_type));

  // Attach quadrature rule to FE object
  fe->attach_quadrature_rule (qrule.get());

  // The Jacobian*weight at the quadrature points.
  const std::vector<Real>& JxW                               = fe->get_JxW();

  // The value of the shape functions at the quadrature points
  // i.e. phi(i) = phi_values[i][qp]
  const std::vector<std::vector<OutputShape> >&  phi_values         = fe->get_phi();

  // The value of the shape function gradients at the quadrature points
  const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> >& 
		    dphi_values = fe->get_dphi();

  // The value of the shape function curls at the quadrature points
  // Only computed for vector-valued elements
  const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputShape> >* curl_values = NULL;

  // The value of the shape function divergences at the quadrature points
  // Only computed for vector-valued elements
  const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputDivergence> >* div_values = NULL;

  if( FEInterface::field_type(fe_type) == TYPE_VECTOR )
    {
      curl_values = &fe->get_curl_phi();
      div_values = &fe->get_div_phi();
    }

#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
  // The value of the shape function second derivatives at the quadrature points
  const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> >& 
		    d2phi_values = fe->get_d2phi(); 
#endif

  // The XYZ locations (in physical space) of the quadrature points
  const std::vector<Point>& q_point                          = fe->get_xyz();

  // The global degree of freedom indices associated
  // with the local degrees of freedom.
  std::vector<dof_id_type> dof_indices;


  //
  // Begin the loop over the elements
  //
  // TODO: this ought to be threaded (and using subordinate
  // MeshFunction objects in each thread rather than a single
  // master)
  MeshBase::const_element_iterator       el     = _mesh.active_local_elements_begin();
  const MeshBase::const_element_iterator end_el = _mesh.active_local_elements_end();

  for ( ; el != end_el; ++el)
    {
      // Store a pointer to the element we are currently
      // working on.  This allows for nicer syntax later.
      const Elem* elem = *el;

      // reinitialize the element-specific data
      // for the current element
      fe->reinit (elem);

      // Get the local to global degree of freedom maps
      computed_dof_map.dof_indices    (elem, dof_indices, var);

      // The number of quadrature points
      const unsigned int n_qp = qrule->n_points();

      // The number of shape functions
      const unsigned int n_sf = 
	libmesh_cast_int<unsigned int>(dof_indices.size());

      //
      // Begin the loop over the Quadrature points.
      //
      for (unsigned int qp=0; qp<n_qp; qp++)
	{
	  // Real u_h = 0.;
	  // RealGradient grad_u_h;

	  typename FEGenericBase<OutputShape>::OutputNumber u_h = 0.;

	  typename FEGenericBase<OutputShape>::OutputNumberGradient grad_u_h;
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
	  typename FEGenericBase<OutputShape>::OutputNumberTensor grad2_u_h;
#endif
	  typename FEGenericBase<OutputShape>::OutputNumber curl_u_h = 0.0;
	  typename FEGenericBase<OutputShape>::OutputNumberDivergence div_u_h = 0.0;

	  // Compute solution values at the current
	  // quadrature point.  This reqiures a sum
	  // over all the shape functions evaluated
	  // at the quadrature point.
	  for (unsigned int i=0; i<n_sf; i++)
	    {
	      // Values from current solution.
	      u_h      += phi_values[i][qp]*computed_system.current_solution  (dof_indices[i]);
	      grad_u_h += dphi_values[i][qp]*computed_system.current_solution (dof_indices[i]);
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
	      grad2_u_h += d2phi_values[i][qp]*computed_system.current_solution (dof_indices[i]);
#endif
	      if( FEInterface::field_type(fe_type) == TYPE_VECTOR )
		{
		  curl_u_h += (*curl_values)[i][qp]*computed_system.current_solution (dof_indices[i]);
		  div_u_h += (*div_values)[i][qp]*computed_system.current_solution (dof_indices[i]);
		}
	    }

	  // Compute the value of the error at this quadrature point
	  typename FEGenericBase<OutputShape>::OutputNumber exact_val = 0;
	  RawAccessor<typename FEGenericBase<OutputShape>::OutputNumber> exact_val_accessor( exact_val, dim );
          if (_exact_values.size() > sys_num && _exact_values[sys_num])
	    {
	      for( unsigned int c = 0; c < n_vec_dim; c++)
		exact_val_accessor(c) =
		  _exact_values[sys_num]->
		  component(var_component+c, q_point[qp], time);
	    }
	  else if (_equation_systems_fine)
	    {
	      // FIXME: Needs to be updated for vector-valued elements
	      exact_val = (*coarse_values)(q_point[qp]);
	    }
	  const typename FEGenericBase<OutputShape>::OutputNumber val_error = u_h - exact_val;

	  // Add the squares of the error to each contribution
	  Real error_sq = TensorTools::norm_sq(val_error);
	  error_vals[0] += JxW[qp]*error_sq;

	  Real norm = sqrt(error_sq);
	  error_vals[3] += JxW[qp]*norm;

	  if(error_vals[4]<norm) { error_vals[4] = norm; }

	  // Compute the value of the error in the gradient at this
	  // quadrature point
	  typename FEGenericBase<OutputShape>::OutputNumberGradient exact_grad;
	  RawAccessor<typename FEGenericBase<OutputShape>::OutputNumberGradient> exact_grad_accessor( exact_grad, _mesh.spatial_dimension() );
	  if (_exact_derivs.size() > sys_num && _exact_derivs[sys_num])
	    {
	      for( unsigned int c = 0; c < n_vec_dim; c++)
		for( unsigned int d = 0; d < _mesh.spatial_dimension(); d++ )
		  exact_grad_accessor(d + c*_mesh.spatial_dimension() ) =
		    _exact_derivs[sys_num]->
		    component(var_component+c, q_point[qp], time)(d);
	    }
	  else if (_equation_systems_fine)
	    {
	      // FIXME: Needs to be updated for vector-valued elements
	      exact_grad = coarse_values->gradient(q_point[qp]);
	    }

	  const typename FEGenericBase<OutputShape>::OutputNumberGradient grad_error = grad_u_h - exact_grad;
	  
	  error_vals[1] += JxW[qp]*grad_error.size_sq();


	  if( FEInterface::field_type(fe_type) == TYPE_VECTOR )
	    {
	      // Compute the value of the error in the curl at this
	      // quadrature point
	      typename FEGenericBase<OutputShape>::OutputNumber exact_curl = 0.0;
	      if (_exact_derivs.size() > sys_num && _exact_derivs[sys_num])
		{
		  exact_curl = TensorTools::curl_from_grad( exact_grad );
		}
	      else if (_equation_systems_fine)
		{
		  // FIXME: Need to implement curl for MeshFunction and support reference
		  //        solution for vector-valued elements
		}

	      const typename FEGenericBase<OutputShape>::OutputNumber curl_error = curl_u_h - exact_curl;
	      
	      error_vals[5] += JxW[qp]*TensorTools::norm_sq(curl_error);

	      // Compute the value of the error in the divergence at this
	      // quadrature point
	      typename FEGenericBase<OutputShape>::OutputNumberDivergence exact_div = 0.0;
	      if (_exact_derivs.size() > sys_num && _exact_derivs[sys_num])
		{
		  exact_div = TensorTools::div_from_grad( exact_grad );
		}
	      else if (_equation_systems_fine)
		{
		  // FIXME: Need to implement div for MeshFunction and support reference
		  //        solution for vector-valued elements
		}
	      
	      const typename FEGenericBase<OutputShape>::OutputNumberDivergence div_error = div_u_h - exact_div;
	      
	      error_vals[6] += JxW[qp]*TensorTools::norm_sq(div_error);
	    }

#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
	  // Compute the value of the error in the hessian at this
	  // quadrature point
	  typename FEGenericBase<OutputShape>::OutputNumberTensor exact_hess;
	  RawAccessor<typename FEGenericBase<OutputShape>::OutputNumberTensor> exact_hess_accessor( exact_hess, dim );
	  if (_exact_hessians.size() > sys_num && _exact_hessians[sys_num])
	    {
	      //FIXME: This needs to be implemented to support rank 3 tensors 
	      //       which can't happen until type_n_tensor is fully implemented
	      //       and a RawAccessor<TypeNTensor> is fully implemented
	      if( FEInterface::field_type(fe_type) == TYPE_VECTOR )
		libmesh_not_implemented();

	      for( unsigned int c = 0; c < n_vec_dim; c++)
		for( unsigned int d = 0; d < dim; d++ )
		  for( unsigned int e =0; e < dim; e++ )
		    exact_hess_accessor(d + e*dim + c*dim*dim) =
		      _exact_hessians[sys_num]->
		      component(var_component+c, q_point[qp], time)(d,e);
	    }
	  else if (_equation_systems_fine)
	    {
	      // FIXME: Needs to be updated for vector-valued elements
	      exact_hess = coarse_values->hessian(q_point[qp]);
	    }
	  
	  const typename FEGenericBase<OutputShape>::OutputNumberTensor grad2_error = grad2_u_h - exact_hess;
	  
	  // FIXME: PB: Is this what we want for rank 3 tensors?
	  error_vals[2] += JxW[qp]*grad2_error.size_sq();
#endif

	} // end qp loop
    } // end element loop

  // Add up the error values on all processors, except for the L-infty
  // norm, for which the maximum is computed.
  Real l_infty_norm = error_vals[4];
  CommWorld.max(l_infty_norm);
  CommWorld.sum(error_vals);
  error_vals[4] = l_infty_norm;
}
void ParmetisPartitioner::_do_repartition (MeshBase& mesh,
					   const unsigned int n_sbdmns)
{
  libmesh_assert_greater (n_sbdmns, 0);

  // Check for an easy return
  if (n_sbdmns == 1)
    {
      this->single_partition(mesh);
      return;
    }

  // This function must be run on all processors at once
  parallel_only();

// What to do if the Parmetis library IS NOT present
#ifndef LIBMESH_HAVE_PARMETIS

  libmesh_here();
  libMesh::err << "ERROR: The library has been built without"  << std::endl
	        << "Parmetis support.  Using a Metis"           << std::endl
	        << "partitioner instead!"                       << std::endl;

  MetisPartitioner mp;

  mp.partition (mesh, n_sbdmns);

// What to do if the Parmetis library IS present
#else

  // Revert to METIS on one processor.
  if (libMesh::n_processors() == 1)
    {
      MetisPartitioner mp;
      mp.partition (mesh, n_sbdmns);
      return;
    }

  START_LOG("repartition()", "ParmetisPartitioner");

  // Initialize the data structures required by ParMETIS
  this->initialize (mesh, n_sbdmns);

  // Make sure all processors have enough active local elements.
  // Parmetis tends to crash when it's given only a couple elements
  // per partition.
  {
    bool all_have_enough_elements = true;
    for (unsigned int pid=0; pid<_n_active_elem_on_proc.size(); pid++)
      if (_n_active_elem_on_proc[pid] < MIN_ELEM_PER_PROC)
	all_have_enough_elements = false;

    // Parmetis will not work unless each processor has some
    // elements. Specifically, it will abort when passed a NULL
    // partition array on *any* of the processors.
    if (!all_have_enough_elements)
      {
	// FIXME: revert to METIS, although this requires a serial mesh
        MeshSerializer serialize(mesh);

	STOP_LOG ("repartition()", "ParmetisPartitioner");

	MetisPartitioner mp;
	mp.partition (mesh, n_sbdmns);

	return;
      }
  }

  // build the graph corresponding to the mesh
  this->build_graph (mesh);


  // Partition the graph
  std::vector<int> vsize(_vwgt.size(), 1);
  float itr = 1000000.0;
  MPI_Comm mpi_comm = libMesh::COMM_WORLD;

  // Call the ParMETIS adaptive repartitioning method.  This respects the
  // original partitioning when computing the new partitioning so as to
  // minimize the required data redistribution.
  Parmetis::ParMETIS_V3_AdaptiveRepart(_vtxdist.empty() ? NULL : &_vtxdist[0],
				       _xadj.empty()    ? NULL : &_xadj[0],
				       _adjncy.empty()  ? NULL : &_adjncy[0],
				       _vwgt.empty()    ? NULL : &_vwgt[0],
				       vsize.empty()    ? NULL : &vsize[0],
				       NULL,
				       &_wgtflag,
				       &_numflag,
				       &_ncon,
				       &_nparts,
				       _tpwgts.empty()  ? NULL : &_tpwgts[0],
				       _ubvec.empty()   ? NULL : &_ubvec[0],
				       &itr,
				       &_options[0],
				       &_edgecut,
				       _part.empty()    ? NULL : &_part[0],
				       &mpi_comm);

  // Assign the returned processor ids
  this->assign_partitioning (mesh);


  STOP_LOG ("repartition()", "ParmetisPartitioner");

#endif // #ifndef LIBMESH_HAVE_PARMETIS ... else ...

}