]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Redo the SmartPointer description in step-6.
authorDavid Wells <wellsd2@rpi.edu>
Sat, 28 Apr 2018 21:37:34 +0000 (17:37 -0400)
committerDavid Wells <wellsd2@rpi.edu>
Sat, 28 Apr 2018 21:40:12 +0000 (17:40 -0400)
The old version doesn't make sense anymore since a Triangulation does not store
a SmartPointer pointing to a manifold.

examples/step-6/doc/results.dox
examples/step-6/step-6.cc

index cdc3245d568855781103dc960cf52751285291cc..5338b1542c2f946656c4facb653bad0e3c7dd699 100644 (file)
@@ -113,16 +113,16 @@ For completeness, we show what happens if the code we commented about
 in the destructor of the <code>Step6</code> class is omitted
 from this example.
 
-@code
---------------------------------------------------------
-An error occurred in line <104> of file <source/base/subscriptor.cc> in function
+~~~{}
+An error occurred in line <104> of file <.../source/base/subscriptor.cc> in function
     void dealii::Subscriptor::check_no_subscribers() const
 The violated condition was:
     counter == 0
 Additional information:
-Object of class N6dealii17SphericalManifoldILi2ELi2EEE is still used by 1 other objects.
+    Object of class N6dealii15SparsityPatternE is still used by 1 other objects.
 
-(Additional information: <none>)
+(Additional information:
+  from Subscriber SparseMatrix)
 
 See the entry in the Frequently Asked Questions of deal.II (linked to from
 http://www.dealii.org/) for a lot more information on what this error means and
@@ -130,32 +130,31 @@ how to fix programs in which it happens.
 
 Stacktrace:
 -----------
-#0  /lib/libdeal_II.g.so: dealii::Subscriptor::check_no_subscribers() const
-#1  /lib/libdeal_II.g.so: dealii::Subscriptor::~Subscriptor()
-#2  /lib/libdeal_II.g.so: dealii::Manifold<2, 2>::~Manifold()
-#3  ./step-6: Step6<2>::~Step6()
-#4  ./step-6: main
+#0  .../lib/libdeal_II.g.so.9.0.0: dealii::Subscriptor::check_no_subscribers() const noexcept
+#   .../lib/libdeal_II.g.so.9.0.0: dealii::Subscriptor::~Subscriptor()
+#2  ./step-6: Step6<2>::~Step6()
+#3  ./step-6: main
 --------------------------------------------------------
-@endcode
+~~~
 
 From the above error message, we conclude that something is still using an
-object with type <code>N6dealii4FE_QILi2EE</code>. This is of course the <a
+object with type <code>N6dealii15SparsityPatternE</code>. This is of course the <a
 href="http://en.wikipedia.org/wiki/Name_mangling">"mangled" name</a> for
-<code>FE_Q</code>. The mangling works as follows: the <code>N6</code> indicates
+<code>SparsityPattern</code>. The mangling works as follows: the <code>N6</code> indicates
 a namespace with six characters (i.e., <code>dealii</code>) and the
-<code>4</code> indicates the number of characters of the template class (i.e.,
-<code>FE_Q</code>).
+<code>15</code> indicates the number of characters of the template class (i.e.,
+<code>SparsityPattern</code>).
 
-The rest of the text is then template arguments. From this we can already glean
-a little bit who's the culprit here, and who the victim: The one object that
-still uses the finite element is the <code>dof_handler</code> object.
+From this we can already glean a little bit who is the culprit here, and who the
+victim: The one object that still uses the SparsityPattern is the
+SparseMatrix.
 
 The stacktrace gives an indication of where the problem happened. We
 see that the exception was triggered in the
-destructor of the <code>FiniteElement</code> class that was called
+destructor of the SparseMatrix class (which inherits from Subscriptor) that was called
 through a few more functions from the destructor of the
 <code>Step6</code> class, exactly where we have commented out
-the call to <code>DoFHandler::clear()</code>.
+the call to SparseMatrix::clear().
 
 
 
index 543bcfc15b1b80180f47e578738639fc8b3ed37d..186c3f48829aa850e4dbe00a7ab0c7a959271fba 100644 (file)
@@ -120,8 +120,11 @@ private:
   // conditions.
   ConstraintMatrix     constraints;
 
-  SparsityPattern      sparsity_pattern;
+  // The sparsity pattern and sparse matrix are deliberately declared in the
+  // opposite of the order used in step-2 through step-5 to demonstrate the
+  // main use of Subscriptor and SmartPointer.
   SparseMatrix<double> system_matrix;
+  SparsityPattern      sparsity_pattern;
 
   Vector<double>       solution;
   Vector<double>       system_rhs;
@@ -161,61 +164,57 @@ Step6<dim>::Step6 ()
 
 // @sect4{Step6::~Step6}
 
-// Here comes the added destructor of the class. The reason why we want to add
-// it is to pick up an issue we already started to discuss in step-1:
-// the <code>boundary</code> object was defined before and not after the
-// <code>triangulation</code> object. Of course we could have left this order
-// unchanged, but we would like to show what happens if the order is reversed
-// since this produces a rather nasty side-effect and results in an error which
-// is difficult to track down if one does not know what happens.
+// Here comes the added destructor of the class. Some objects in deal.II store
+// pointers to other objects: in particular a SparseMatrix stores a SmartPointer
+// pointing to the SparsityPattern with which it was initialized. This example
+// deliberately declares the SparseMatrix before the SparsityPattern to make this
+// dependency clearer. Of course we could have left this order unchanged, but
+// we would like to show what happens if the order is reversed since this
+// produces a rather nasty side-effect and results in an error which is
+// difficult to track down if one does not know what happens.
 //
-// Basically what happens is the following: when we set a manifold description
-// to the triangulation using the function call
-// <code>triangulation.set_manifold (0, boundary)</code>, the
-// <code>Triangulation</code> object also stores a pointer to the
-// <code>Manifold</code> object in use. Since this pointer is used until either
-// another <code>Manifold</code> object is set as boundary description or until
-// the <code>Triangulation</code> object is destroyed, it would be unwise if we
-// would allow the <code>boundary</code> to be deleted before the
-// <code>triangulation</code>. To disallow this, the <code>triangulation</code>
-// increases a counter inside the <code>boundary</code> which counts how many
-// objects use it (this is what the
+// Basically what happens is the following: when we initialize a SparseMatrix,
+// the matrix stores a pointer to the provided SparsityPattern instead of
+// copying it.  Since this pointer is used until either another
+// SparsityPattern is attached or the SparseMatrix is destructed, it would be
+// unwise to allow the SparsityPattern to be destructed before the
+// SparseMatrix. To disallow this, the SparseMatrix increases a counter inside
+// the SparsityPattern which counts how many objects use it (this is what the
 // <code>Subscriptor</code>/<code>SmartPointer</code> class pair is used for,
 // in case you want something like this for your own programs; see step-7 for
-// a more complete discussion of this topic). The <code>boundary</code> will
-// refuse its destruction if that counter is larger than zero, since then some
-// other objects might rely on its persistence. An exception will then be
-// thrown and the program will usually abort upon the attempt to destroy
-// <code>boundary</code>.
+// a more complete discussion of this topic). If the counter is larger than
+// zero then the program will either abort (the default) or print an error
+// message and continue: see the documentation of AssertNothrow for more
+// details. In either case the program contains a bug and this facility will,
+// hopefully, point out where.
 //
-// To be fair, such exceptions about still used objects are not particularly
+// To be fair, such errors due to object dependencies are not particularly
 // popular among programmers using deal.II, since they only tell us that
-// something is wrong, namely that <i>some</i> other object is still using the object
-// that is presently being destroyed, but most of the time not <i>which</i> object is
-// still using it. It is therefore often rather time-consuming to find out where the
-// problem exactly is, although it is then usually straightforward to remedy
-// the situation. However, we believe that the effort to find invalid
-// references to objects that do no longer exist is less if the problem is
-// detected once the reference becomes invalid, rather than when non-existent
-// objects are actually accessed again, since then usually only invalid data
-// is accessed, but no error is immediately raised.
+// something is wrong, namely that <i>some</i> other object is still using the
+// object that is presently being destroyed, but most of the time not
+// <em>which</em> object is still using it. It is therefore often rather
+// time-consuming to find out where the problem exactly is, although it is
+// then usually straightforward to remedy the situation. However, we believe
+// that the effort to find invalid pointers to objects that no longer exist is
+// less if the problem is detected once the pointer becomes invalid, rather
+// than when non-existent objects are actually accessed again, since then
+// usually only invalid data is accessed, but no error is immediately raised.
 //
 // Coming back to the present situation, if we did not write this destructor,
 // the compiler will generate code that triggers exactly the behavior sketched
 // above. The reason is that member variables of the <code>Step6</code> class
 // are destroyed bottom-up (i.e., in reverse order of their declaration in the
-// class), as always in C++. Thus, the boundary object will be
-// destroyed before the triangulation object, since its declaration is below
-// the one of the triangulation. This triggers the situation above, and an
-// exception will be raised when the boundary object is
-// destroyed. What needs to be done is to tell the <code>triangulation</code>
-// object to release its lock to <code>boundary</code>. Of course, the
-// <code>triangulation</code> will only release its lock if it really does not
-// need the <code>boundary</code> any more. For this purpose, the
-// <code>Triangulation</code> class has a function <code>clear</code> which
-// resets the object into a virgin state by deleting all data and releases its
-// lock to the finite element. After this, you can safely destruct the
-// <code>boundary</code> object since its internal counter is then zero.
+// class), as always in C++. Thus, the SparsityPattern will be destroyed
+// before the SparseMatrix, since its declaration is below the one of the
+// sparsity pattern. This triggers the situation above, and an exception will
+// be raised when the SparsityPattern is destroyed. What needs to be done is
+// to tell the SparseMatrix to release its pointer to the SparsityPattern. Of
+// course, the SparseMatrix will only release its pointer if it really does
+// not need the SparsityPattern any more. For this purpose, the SparseMatrix
+// class has a function SparseMatrix::clear() which resets the object to its
+// default-constructed state by deleting all data and resetting its pointer to
+// the SparsityPattern to 0. After this, you can safely destruct the
+// SparsityPattern since its internal counter will be zero.
 //
 // For completeness, we add the output of the exception that would have been
 // triggered without this destructor, to the end of the results section of
@@ -223,7 +222,7 @@ Step6<dim>::Step6 ()
 template <int dim>
 Step6<dim>::~Step6 ()
 {
-  triangulation.clear ();
+  system_matrix.clear();
 }
 
 

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.