After looking at example 9 again, I have to ask:
Better yet: is there a way to augment the sparsity pattern without this
function? I've read that I should

"
  To do this, you need to cast your matrix to a PetscMatrix, then do
  petsc_matrix->mat() to get the PETSc Mat that you can pass to
MatSetOption.

  PetscMatrix<Number> * NonlocalStiffness_petsc =
&(this->get_matrix("NonlocalStiffness"));
  MatSetOption( NonlocalStiffness_petsc.mat() ,
MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
"

Suppose I added a sparse matrix "TestMat" to the system.  How do I do this,
explicitly?
Thanks!

On Tue, Sep 18, 2018 at 3:40 AM Charlie Talbot <[email protected]> wrote:

> Hi, I modified the files in miscellaneous example 9 to augment the
> sparsity pattern to include elements found using Patch, and I can't seem to
> get this to work, what am I missing? Thanks!
>
> #ifndef AUGMENT_SPARSITY_NONLOCAL_H
> #define AUGMENT_SPARSITY_NONLOCAL_H
>
> #include "libmesh/ghosting_functor.h"
> #include "libmesh/mesh_base.h"
> #include "libmesh/patch.h"
> using libMesh::Elem;
> using libMesh::GhostingFunctor;
> using libMesh::MeshBase;
> using libMesh::boundary_id_type;
> using libMesh::processor_id_type;
>
> // Convenient typedef for a map for (element, side id) --> element neighbor
> typedef std::map<std::pair<const Elem *, unsigned char>, const Elem *>
> ElementSideMap;
>
> // And the inverse map, but without sides in the key
> typedef std::map<const Elem *, const Elem *> ElementMap;
>
> class AugmentSparsityNonlocal : public GhostingFunctor
> {
> private:
>
>   /**
>    * The Mesh we're calculating on
>    */
>   MeshBase & _mesh;
>
>   /**
>    * A map from (lower element ID, side ID) to matching upper element ID.
> Here "lower"
>    * and "upper" refer to the lower and upper (wrt +z direction) sides of
> the crack in
>    * our mesh.
>    */
>   ElementSideMap _lower_to_upper;
>
>   /**
>    * The inverse (ignoring sides) of the above map.
>    */
>   ElementMap _upper_to_lower;
>
>   /**
>    * Boundary IDs for the lower and upper faces of the "crack" in the mesh.
>    */
>   boundary_id_type _crack_boundary_lower, _crack_boundary_upper;
>
>   /**
>    * Make sure we've been initialized before use
>    */
>   bool _initialized;
>
> public:
>   unsigned int _target_patch_size;
>
>   /**
>    * Constructor.
>    */
>   AugmentSparsityNonlocal(MeshBase & mesh,
>     unsigned int target_patch_size);
>                              // boundary_id_type crack_boundary_lower,
>                              // boundary_id_type crack_boundary_upper);
>
>   /**
>    * @return a const reference to the lower-to-upper element ID map.
>    */
>   const ElementSideMap & get_lower_to_upper() const;
>
>   /**
>    * User-defined function to augment the sparsity pattern.
>    */
>   virtual void operator() (const MeshBase::const_element_iterator &
> range_begin,
>                            const MeshBase::const_element_iterator &
> range_end,
>                            processor_id_type p,
>                            map_type & coupled_elements) override;
>
>   /**
>    * Rebuild the cached _lower_to_upper map whenever our Mesh has
>    * changed.
>    */
>   virtual void mesh_reinit () override;
>
>   /**
>    * Update the cached _lower_to_upper map whenever our Mesh has been
>    * redistributed.  We'll be lazy and just recalculate from scratch.
>    */
>   virtual void redistribute () override
>   { this->mesh_reinit(); }
>
>
> };
>
> #endif
>
>
>
>
>
>
>
>
>
>
>
>
> // local includes
> #include "augment_sparsity_nonlocal.h"
>
> // libMesh includes
> #include "libmesh/elem.h"
>
> using namespace libMesh;
>
> AugmentSparsityNonlocal::AugmentSparsityNonlocal(MeshBase & mesh,
>   unsigned int target_patch_size):
>                                                        // boundary_id_type
> crack_boundary_lower,
>                                                        // boundary_id_type
> crack_boundary_upper) :
>   _mesh(mesh),
>   // _crack_boundary_lower(crack_boundary_lower),
>   // _crack_boundary_upper(crack_boundary_upper),
>   _initialized(false)
> {
>   this->mesh_reinit();
>   this->_target_patch_size = target_patch_size;
>
> }
>
>
> const ElementSideMap & AugmentSparsityNonlocal::get_lower_to_upper() const
> {
>   libmesh_assert(this->_initialized);
>   return _lower_to_upper;
> }
>
> void AugmentSparsityNonlocal::mesh_reinit ()
> {
>   this->_initialized = true;
>
>   // Loop over all elements (not just local elements) to make sure we find
>   // "neighbor" elements on opposite sides of the crack.
>
>   // Map from (elem, side) to centroid
>   std::map<std::pair<const Elem *, unsigned char>, Point> lower_centroids;
>   std::map<std::pair<const Elem *, unsigned char>, Point> upper_centroids;
>
>   // for (const auto & elem : _mesh.active_element_ptr_range())
>   //   for (auto side : elem->side_index_range())
>   //     if (elem->neighbor_ptr(side) == nullptr)
>   //       {
>   //         if (_mesh.get_boundary_info().has_boundary_id(elem, side,
> _crack_boundary_lower))
>   //           {
>   //             std::unique_ptr<const Elem> side_elem =
> elem->build_side_ptr(side);
>
>   //             lower_centroids[std::make_pair(elem, side)] =
> side_elem->centroid();
>   //           }
>
>   //         if (_mesh.get_boundary_info().has_boundary_id(elem, side,
> _crack_boundary_upper))
>   //           {
>   //             std::unique_ptr<const Elem> side_elem =
> elem->build_side_ptr(side);
>
>   //             upper_centroids[std::make_pair(elem, side)] =
> side_elem->centroid();
>   //           }
>   //       }
>
>   // If we're doing a reinit on a distributed mesh then we may not see
>   // all the centroids, or even a matching number of centroids.
>   // std::size_t n_lower_centroids = lower_centroids.size();
>   // std::size_t n_upper_centroids = upper_centroids.size();
>   // libmesh_assert(n_lower_centroids == n_upper_centroids);
>
>   // Clear _lower_to_upper. This map will be used for matrix assembly
> later on.
>   _lower_to_upper.clear();
>
>   // Clear _upper_to_lower. This map will be used for element ghosting
>   // on distributed meshes, communication send_list construction in
>   // parallel, and sparsity calculations
>   _upper_to_lower.clear();
>
>   // We do an N^2 search to find elements with matching centroids. This
> could be optimized,
>   // e.g. by first sorting the centroids based on their (x,y,z) location.
>   {
>     std::map<std::pair<const Elem *, unsigned char>, Point>::iterator it
>    = lower_centroids.begin();
>     std::map<std::pair<const Elem *, unsigned char>, Point>::iterator
> it_end = lower_centroids.end();
>     for ( ; it != it_end; ++it)
>       {
>         Point lower_centroid = it->second;
>
>         // find closest centroid in upper_centroids
>         Real min_distance = std::numeric_limits<Real>::max();
>
>         std::map<std::pair<const Elem *, unsigned char>, Point>::iterator
> inner_it     = upper_centroids.begin();
>         std::map<std::pair<const Elem *, unsigned char>, Point>::iterator
> inner_it_end = upper_centroids.end();
>
>         for ( ; inner_it != inner_it_end; ++inner_it)
>           {
>             Point upper_centroid = inner_it->second;
>
>             Real distance = (upper_centroid - lower_centroid).norm();
>             if (distance < min_distance)
>               {
>                 min_distance = distance;
>                 _lower_to_upper[it->first] = inner_it->first.first;
>               }
>           }
>
>         // For pairs with local elements, we should have found a
>         // matching pair by now.
>         const Elem * elem     = it->first.first;
>         const Elem * neighbor = _lower_to_upper[it->first];
>         if (min_distance < TOLERANCE)
>           {
>             // fill up the inverse map
>             _upper_to_lower[neighbor] = elem;
>           }
>         else
>           {
>             libmesh_assert_not_equal_to(elem->processor_id(),
> _mesh.processor_id());
>             // This must have a false positive; a remote element would
>             // have been closer.
>             _lower_to_upper.erase(it->first);
>           }
>       }
>
>     // Let's make sure we didn't miss any upper elements either
> // #ifndef NDEBUG
> //     std::map<std::pair<const Elem *, unsigned char>, Point>::iterator
> inner_it     = upper_centroids.begin();
> //     std::map<std::pair<const Elem *, unsigned char>, Point>::iterator
> inner_it_end = upper_centroids.end();
>
> //     for ( ; inner_it != inner_it_end; ++inner_it)
> //       {
> //         const Elem * neighbor = inner_it->first.first;
> //         if (neighbor->processor_id() != _mesh.processor_id())
> //           continue;
> //         ElementMap::const_iterator utl_it =
> //           _upper_to_lower.find(neighbor);
> //         libmesh_assert(utl_it != _upper_to_lower.end());
> //       }
> // #endif
>   }
> }
>
> void AugmentSparsityNonlocal::operator()
>   (const MeshBase::const_element_iterator & range_begin,
>    const MeshBase::const_element_iterator & range_end,
>    processor_id_type p,
>    map_type & coupled_elements)
> {
>   libmesh_assert(this->_initialized);
>
>   const CouplingMatrix * const null_mat = nullptr;
>
>   for (const auto & elem : as_range(range_begin, range_end))
>     {
>       if (elem->processor_id() != p)
>         coupled_elements.insert (std::make_pair(elem, null_mat));
>
>       for (auto side : elem->side_index_range())
>         if (elem->neighbor_ptr(side) == nullptr)
>           {
>             ElementSideMap::const_iterator ltu_it =
>               _lower_to_upper.find(std::make_pair(elem, side));
>             if (ltu_it != _lower_to_upper.end())
>               {
>                 const Elem * neighbor = ltu_it->second;
>                 if (neighbor->processor_id() != p)
>                   coupled_elements.insert (std::make_pair(neighbor,
> null_mat));
>               }
>           }
>
>       ElementMap::const_iterator utl_it =
>         _upper_to_lower.find(elem);
>       if (utl_it != _upper_to_lower.end())
>         {
>           const Elem * neighbor = utl_it->second;
>           if (neighbor->processor_id() != p)
>             coupled_elements.insert (std::make_pair(neighbor, null_mat));
>         }
>
>     }
>
>
> /*
> Nonlocal augment
> */
>   // const CouplingMatrix * const null_mat = nullptr;
>   libMesh::Patch::PMF patchtype = &Patch::add_face_neighbors;
>   // #ifndef this->_target_patch_size
>   // const unsigned int _target_patch_size=4;
>   // #endif
> /* build element patches */
>   for (const auto & elem : as_range(range_begin, range_end))
>     {
>       libMesh::Patch patch(_mesh.processor_id());
>       patch.build_around_element(elem, _target_patch_size, patchtype);
>       std::vector<const Elem *> patchvec;
>       patchvec.reserve(patch.size());
>       Patch::const_iterator        patch_it  = patch.begin();
>       const Patch::const_iterator  patch_end = patch.end();
>       for (; patch_it != patch_end; ++patch_it)
>       {
>         const Elem * elem2 = *patch_it;
>         coupled_elements.insert (std::make_pair(elem2, null_mat));
>           // patchvec.push_back(elem2);
>       }
>     }
> }
>
>
>
> // MatSetOption(this->get_matrix("NonlocalStiffness"),
> MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
> //     DoFRenumbering::Cuthill_McKee (dof_handler);
> //     hanging_node_constraints.clear();
> //
>  
> DoFTools::make_hanging_node_constraints(dof_handler,hanging_node_constraints);
>
> //     hanging_node_constraints.close();
>
> //     DynamicSparsityPattern dsp(dof_handler.n_dofs(),
> dof_handler.n_dofs());
> //     DoFTools::make_sparsity_pattern(dof_handler, dsp);
> //     hanging_node_constraints.condense(dsp);
> //     sparsity_pattern.copy_from(dsp);
>
> //     stiffness_matrix.reinit(sparsity_pattern);
> //     mass_matrix.reinit(sparsity_pattern);
>
>
>
>
>
>
>
>
>
>

_______________________________________________
Libmesh-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-users

Reply via email to