From: Wolfgang Bangerth Date: Sat, 6 Apr 2013 00:01:34 +0000 (+0000) Subject: Augment documentation with a section stolen from the Aspect module. X-Git-Tag: v8.0.0~763 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9dc535ec0b908417fb711061d614e632a5673356;p=dealii.git Augment documentation with a section stolen from the Aspect module. git-svn-id: https://svn.dealii.org/trunk@29208 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/include/deal.II/distributed/tria.h b/deal.II/include/deal.II/distributed/tria.h index a9963c5439..b504986449 100644 --- a/deal.II/include/deal.II/distributed/tria.h +++ b/deal.II/include/deal.II/distributed/tria.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // $Id$ // -// Copyright (C) 2008, 2009, 2010, 2011, 2012 by the deal.II authors +// Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 by the deal.II authors // // This file is subject to QPL and may not be distributed // without copyright and license information. Please refer @@ -195,7 +195,7 @@ namespace parallel * 1 sets the boundary indicators of the external boundaries of the cell it owns * to 42. Since processor 0 does not own this cell, it doesn't set the boundary * indicators of its ghost cell copy of this cell. Now, assume we do several mesh - * refinement cycles and end up with a configuration where suddenly finds itself + * refinement cycles and end up with a configuration where this processor suddenly finds itself * as the owner of this cell. If boundary indicator 42 means that we need to * integrate Neumann boundary conditions along this boundary, then processor 0 * will forget to do so because it has never set the boundary indicator along @@ -207,7 +207,98 @@ namespace parallel * for sequential triangulations because, there, these flags are inherited * from mother to child cell and remain with a cell even if it is refined * and the children are later coarsened again, but this does not hold for - * distributed triangulations. + * distributed triangulations. It is made even more difficult by the fact + * that in the process of refining a parallel distributed triangulation, + * the triangulation may call dealii::Triangulation::execute_coarsening_and_refinement + * multiple times and this function needs to know about boundaries. In + * other words, it is not enough to just set boundary indicators on + * newly created faces only after calling + * distributed::parallel::Triangulation::execute_coarsening_and_refinement: + * it actually has to happen while that function is still running. + * + * The way to do this is by writing a function that sets boundary + * indicators and that will be called by the dealii::Triangulation class. The + * triangulation does not provide a pointer to itself to the function being + * called, nor any other information, so the trick is to get this information + * into the function. C++ provides a nice mechanism for this that is best + * explained using an example: + * @code + * #include + * + * template + * void set_boundary_indicators (parallel::distributed::Triangulation &triangulation) + * { + * ... set boundary indicators on the triangulation object ... + * } + * + * template + * void + * MyClass:: + * create_coarse_mesh (parallel::distributed::Triangulation &coarse_grid) const + * { + * ... create the coarse mesh ... + * + * coarse_grid.signals.post_refinement.connect + * (std_cxx1x::bind (&set_boundary_indicators, + * std_cxx1x::ref(coarse_grid))); + * + * } + * @endcode + * + * What the call to std_cxx1x::bind does is to produce an object that + * can be called like a function with no arguments. It does so by taking the + * address of a function that does, in fact, take an argument but permanently fix + * this one argument to a reference to the coarse grid triangulation. After each + * refinement step, the triangulation will then call the object so created which + * will in turn call set_boundary_indicators with the reference + * to the coarse grid as argument. + * + * This approach can be generalized. In the example above, we have used a global + * function that will be called. However, sometimes it is necessary that this + * function is in fact a member function of the class that generates the mesh, + * for example because it needs to access run-time parameters. This can be + * achieved as follows: assuming the set_boundary_indicators() + * function has been declared as a (non-static, but possibly private) member + * function of the MyClass class, then the following will work: + * @code + * #include + * + * template + * void + * MyClass:: + * set_boundary_indicators (parallel::distributed::Triangulation &triangulation) const + * { + * ... set boundary indicators on the triangulation object ... + * } + * + * template + * void + * MyClass:: + * create_coarse_mesh (parallel::distributed::Triangulation &coarse_grid) const + * { + * ... create the coarse mesh ... + * + * coarse_grid.signals.post_refinement.connect + * (std_cxx1x::bind (&MyGeometry::set_boundary_indicators, + * std_cxx1x::cref(*this), + * std_cxx1x::ref(coarse_grid))); + * } + * @endcode + * Here, like any other member function, set_boundary_indicators + * implicitly takes a pointer or reference to the object it belongs to as first + * argument. std::bind again creates an object that can be called like a + * global function with no arguments, and this object in turn calls + * set_boundary_indicators with a pointer to the current object and a + * reference to the triangulation to work on. Note that because the + * create_coarse_mesh function is declared as const, it is + * necessary that the set_boundary_indicators function is also + * declared const. + * + * Note:For reasons that have to do with the way the + * parallel::distributed::Triangulation is implemented, functions that + * have been attached to the post-refinement signal of the triangulation are + * called more than once, sometimes several times, every time the triangulation + * is actually refined. * * * @author Wolfgang Bangerth, Timo Heister 2008, 2009, 2010, 2011