* Triangulation.
*
* This class attaches a signal to the Triangulation passed at construction
- * time, and rebuilds all the structures specified in the list of specified
- * TriangulationInfoCacheFlags, whenever the Triangulation is changed.
- *
- * If you try to access one of the objects that has not been cached (due to a
- * missing TriangulationInfoCacheFlags flag), an Assertion is thrown.
+ * time to keep track about refinement changes, and allows the user to query
+ * some of the data structures constructed using functions in the GridTools
+ * namespace which are computed only once, and then cached inside this class
+ * for faster access whenever the triangulation has not changed.
*
* Notice that this class only notices if the underlying Triangulation has
- * changed due to a Triangulation::Signals::any_change() signal being triggered.
+ * changed due to a Triangulation::Signals::any_change() signal being
+ * triggered.
*
- * If the triangulation changes due to a MappingQEulerian being passed to this
- * class, or because you manually change some vertex locations, then some of
- * the structures in this class become obsolete, and you will have to call the
- * method update() manually.
+ * If the triangulation changes due to a MappingQEulerian being passed to
+ * this class, or because you manually change some vertex locations, then
+ * some of the structures in this class become obsolete, and you will have to
+ * call the method update() manually.
*
* @author Luca Heltai, 2017.
*/
/**
* Constructor.
*
- * You can specify what to cache by passing appropriate
- * TriangulationInfoCacheFlags. If you provide the optional `mapping`
- * argument, then this is used whenever a mapping is required.
+ * If you provide the optional `mapping` argument, then this is used
+ * whenever a mapping is required.
*
* @param tria The triangulation for which to store information
- * @param flags TriangulationInfoCacheFlags that specify what to cache
* @param mapping The mapping to use when computing cached objects
*/
Cache (const Triangulation<dim,spacedim> &tria,
- const TriangulationInfoCacheFlags &flags = cache_nothing,
const Mapping<dim,spacedim> &mapping=StaticMappingQ1<dim,spacedim>::mapping);
~Cache();
/**
- * Loop over all TriangulationInfoCacheFlags and rebuilds the specific data
- * structure.
+ * Make sure that the objects marked for update are recomputed during
+ * subsequent calls to the `get_*` functions defined in this class.
*
- * The optional parameter can be set to true to update only data that is
- * dependent on the position of the vertices. This may happen, for example,
- * if you have a MappingQEulerian class associated to the triangulation. In
- * this case, even if the Triangulation has not changed, the vector that
- * specifies the position of the vertices may actually change *independently*
- * of the triangulation, requiring you to recompute vertex dependent things.
- * In this case, the topological information is not changed, and does not
- * need to be updated.
+ * Notice that no work is performed when you call this function. The actual
+ * data structures are computed the next time you call the corresponding
+ * `get_*` method.
*
- * @param topology_is_unchanged
+ * @param flags What to mark for update
*/
- void update(bool topology_is_unchanged=false);
+ void mark_for_update(const CacheFlags &flags=update_all);
/**
const KDTree<spacedim> &get_vertex_kdtree() const;
#endif
+ private:
/**
- * Exception for uninitialized cache fields.
+ * Keep track of what needs to be updated next.
*/
- DeclException2(ExcAccessToInvalidCacheObject,
- TriangulationInfoCacheFlags &,
- TriangulationInfoCacheFlags &,
- << "You tried to access a cache object that has not "
- << "been constructed by this class. You specified "
- << arg2 << " at construction time, but you need also "
- << arg1 << " to access the field you are requesting now.");
- private:
+ mutable CacheFlags update_flags;
+
/**
* A pointer to the Triangulation.
*/
SmartPointer<const Triangulation<dim,spacedim>,
Cache<dim,spacedim>> tria;
- /**
- * Specifies what to cache.
- */
- const TriangulationInfoCacheFlags flags;
-
/**
* Mapping to use when computing on the Triangulation.
*/
* Store vertex to cell map information, as generated by
* GridTools::vertex_to_cell_map()
*/
- std::vector< std::set<typename Triangulation<dim,spacedim>::active_cell_iterator> > vertex_to_cells;
+ mutable std::vector< std::set<typename Triangulation<dim,spacedim>::active_cell_iterator> >
+ vertex_to_cells;
/**
* Store vertex to cell center directions, as generated by
* GridTools::vertex_to_cell_centers_directions.
*/
- std::vector<std::vector<Tensor<1,spacedim>>> vertex_to_cell_centers;
+ mutable std::vector<std::vector<Tensor<1,spacedim>>> vertex_to_cell_centers;
#ifdef DEAL_II_WITH_NANOFLANN
/**
* A KDTree object constructed with the vertices of the triangulation.
*/
- KDTree<spacedim> vertex_kdtree;
+ mutable KDTree<spacedim> vertex_kdtree;
#endif
/**
/**
* The enum type given to the Cache class to select what
- * information to cache.
+ * information to update.
*
* You can select more than one flag by concatenation using the bitwise or
- * <code>operator|(TriangulationInfoCacheFlags,TriangulationInfoCacheFlags)</code>.
+ * <code>operator|(CacheFlags,CacheFlags)</code>.
*
* @author Luca Heltai, 2017.
*/
- enum TriangulationInfoCacheFlags
+ enum CacheFlags
{
/**
- * Cache Nothing.
+ * Update Nothing.
*/
- cache_nothing = 0,
+ update_nothing = 0x00,
/**
- * Cache vertex_to_cell_map, as returned by GridTools::vertex_to_cell_map().
+ * Update vertex_to_cell_map, as returned by GridTools::vertex_to_cell_map().
*/
- cache_vertex_to_cell_map = 0x0001,
+ update_vertex_to_cell_map = 0x01,
/**
- * Cache vertex_to_cell_centers_directions, as returned by
+ * Update vertex_to_cell_centers_directions, as returned by
* GridTools::vertex_to_cell_centers_directions()
*/
- cache_vertex_to_cell_centers_directions = cache_vertex_to_cell_map | 0x0002,
+ update_vertex_to_cell_centers_directions = update_vertex_to_cell_map | 0x0002,
#ifdef DEAL_II_WITH_NANOFLANN
/**
- * Cache a KDTree object, initialized with the vertices of the Triangulation.
+ * Update a KDTree object, initialized with the vertices of the Triangulation.
*/
- cache_vertex_kdtree = 0x0004,
+ update_vertex_kdtree = 0x04,
#endif
+
+ /**
+ * Update all objects.
+ */
+ update_all = 0xFF,
};
/**
* Output operator which outputs assemble flags as a set of or'd text values.
*
- * @ref TriangulationInfoCacheFlags
+ * @ref CacheFlags
*/
template <class StreamType>
inline
- StreamType &operator << (StreamType &s, TriangulationInfoCacheFlags u)
+ StreamType &operator << (StreamType &s, CacheFlags u)
{
- s << " TriangulationInfoCacheFlags";
- if (u & cache_vertex_to_cell_map) s << "|vertex_to_cell_map";
- if (u & cache_vertex_to_cell_centers_directions) s << "|vertex_to_cells_centers_directions";
+ s << " CacheFlags";
+ if (u & update_vertex_to_cell_map) s << "|vertex_to_cell_map";
+ if (u & update_vertex_to_cell_centers_directions) s << "|vertex_to_cells_centers_directions";
#ifdef DEAL_II_WITH_NANOFLANN
- if (u & cache_vertex_kdtree) s << "|vertex_kdtree";
+ if (u & update_vertex_kdtree) s << "|vertex_kdtree";
#endif
return s;
}
* either set in the first or the second argument. This operator exists since
* if it did not then the result of the bit-or <tt>operator |</tt> would be an
* integer which would in turn trigger a compiler warning when we tried to
- * assign it to an object of type TriangulationInfoCacheFlags.
+ * assign it to an object of type CacheFlags.
*
- * @ref TriangulationInfoCacheFlags
+ * @ref CacheFlags
*/
inline
- TriangulationInfoCacheFlags
- operator | (TriangulationInfoCacheFlags f1, TriangulationInfoCacheFlags f2)
+ CacheFlags
+ operator | (CacheFlags f1, CacheFlags f2)
{
- return static_cast<TriangulationInfoCacheFlags> (
+ return static_cast<CacheFlags> (
static_cast<unsigned int> (f1) |
static_cast<unsigned int> (f2));
}
+ /**
+ * Global operator which returns an object in which all bits are set which are
+ * not set in the argument. This operator exists since
+ * if it did not then the result of the bit-negation <tt>operator ~</tt> would be an
+ * integer which would in turn trigger a compiler warning when we tried to
+ * assign it to an object of type CacheFlags.
+ *
+ * @ref CacheFlags
+ */
+ inline
+ CacheFlags
+ operator ~ (CacheFlags f1)
+ {
+ return static_cast<CacheFlags> (
+ ~static_cast<unsigned int> (f1)
+ );
+ }
* Global operator which sets the bits from the second argument also in the
* first one.
*
- * @ref TriangulationInfoCacheFlags
+ * @ref CacheFlags
*/
inline
- TriangulationInfoCacheFlags &
- operator |= (TriangulationInfoCacheFlags &f1, TriangulationInfoCacheFlags f2)
+ CacheFlags &
+ operator |= (CacheFlags &f1, CacheFlags f2)
{
f1 = f1 | f2;
return f1;
* set in the first as well as the second argument. This operator exists since
* if it did not then the result of the bit-and <tt>operator &</tt> would be
* an integer which would in turn trigger a compiler warning when we tried to
- * assign it to an object of type TriangulationInfoCacheFlags.
+ * assign it to an object of type CacheFlags.
*
- * @ref TriangulationInfoCacheFlags
+ * @ref CacheFlags
*/
inline
- TriangulationInfoCacheFlags
- operator & (TriangulationInfoCacheFlags f1, TriangulationInfoCacheFlags f2)
+ CacheFlags
+ operator & (CacheFlags f1, CacheFlags f2)
{
- return static_cast<TriangulationInfoCacheFlags> (
+ return static_cast<CacheFlags> (
static_cast<unsigned int> (f1) &
static_cast<unsigned int> (f2));
}
* Global operator which clears all the bits in the first argument if they are
* not also set in the second argument.
*
- * @ref TriangulationInfoCacheFlags
+ * @ref CacheFlags
*/
inline
- TriangulationInfoCacheFlags &
- operator &= (TriangulationInfoCacheFlags &f1, TriangulationInfoCacheFlags f2)
+ CacheFlags &
+ operator &= (CacheFlags &f1, CacheFlags f2)
{
f1 = f1 & f2;
return f1;
template<int dim, int spacedim>
Cache<dim,spacedim>::Cache(
const Triangulation<dim, spacedim> &tria,
- const TriangulationInfoCacheFlags &flags,
const Mapping<dim, spacedim> &mapping) :
+ update_flags(update_all),
tria(&tria),
- flags(flags),
mapping(&mapping)
{
tria_signal = tria.signals.any_change.connect([&]()
{
- update();
+ mark_for_update(update_all);
});
-
- if (tria.n_active_cells()>0)
- update();
}
template<int dim, int spacedim>
template<int dim, int spacedim>
- void Cache<dim,spacedim>::update(bool topology_is_unchanged)
+ void Cache<dim,spacedim>::mark_for_update(const CacheFlags &flags)
{
- // If the triangulation is empty, just clear everything.
- if (tria->n_active_cells() == 0)
- {
- vertex_to_cells.clear();
- vertex_to_cell_centers.clear();
-#ifdef DEAL_II_WITH_NANOFLANN
- vertex_kdtree.set_points(tria->get_vertices());
-#endif
- return;
- }
-
- if (topology_is_unchanged == false)
- {
- if (cache_vertex_to_cell_map & flags)
- vertex_to_cells = GridTools::vertex_to_cell_map(*tria);
-
-#ifdef DEAL_II_WITH_NANOFLANN
- if (cache_vertex_kdtree & flags)
- vertex_kdtree.set_points(tria->get_vertices());
-#endif
- }
-
- if (cache_vertex_to_cell_centers_directions & flags)
- vertex_to_cell_centers =
- GridTools::vertex_to_cell_centers_directions(*tria, vertex_to_cells);
-
+ update_flags |= flags;
}
const std::vector<std::set<typename Triangulation<dim,spacedim>::active_cell_iterator> > &
Cache<dim,spacedim>::get_vertex_to_cell_map() const
{
- Assert(flags & cache_vertex_to_cell_map,
- ExcAccessToInvalidCacheObject(cache_vertex_to_cell_map, flags));
+ if (update_flags & update_vertex_to_cell_map)
+ {
+ vertex_to_cells = GridTools::vertex_to_cell_map(*tria);
+ update_flags = update_flags & ~update_vertex_to_cell_map;
+ }
return vertex_to_cells;
}
const std::vector<std::vector<Tensor<1,spacedim>>> &
Cache<dim,spacedim>::get_vertex_to_cell_centers_directions() const
{
- Assert(flags & cache_vertex_to_cell_centers_directions,
- ExcAccessToInvalidCacheObject(cache_vertex_to_cell_centers_directions, flags));
+ if (update_flags & update_vertex_to_cell_centers_directions)
+ {
+ vertex_to_cell_centers =
+ GridTools::vertex_to_cell_centers_directions(*tria, get_vertex_to_cell_map());
+ update_flags = update_flags & ~update_vertex_to_cell_centers_directions;
+ }
return vertex_to_cell_centers;
}
template<int dim, int spacedim>
const KDTree<spacedim> &Cache<dim,spacedim>::get_vertex_kdtree() const
{
- Assert(flags & cache_vertex_kdtree,
- ExcAccessToInvalidCacheObject(cache_vertex_kdtree, flags));
+ if (update_flags & update_vertex_kdtree)
+ {
+ vertex_kdtree.set_points(tria->get_vertices());
+ update_flags = update_flags & ~update_vertex_kdtree;
+ }
return vertex_kdtree;
}
#endif
GridGenerator::hyper_cube(tria);
tria.refine_global(1);
- GridTools::Cache<dim> cache(tria, GridTools::cache_vertex_to_cell_map);
+ GridTools::Cache<dim> cache(tria);
auto m = cache.get_vertex_to_cell_map();
<< ", spacedim = " << spacedim << std::endl;
Triangulation<dim> tria;
- GridTools::Cache<dim> cache(tria, GridTools::cache_vertex_to_cell_map);
+ GridTools::Cache<dim> cache(tria);
GridGenerator::hyper_cube(tria);