]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
Fixed: If an FEValues object was kept around until after the triangulation include...
authorbangerth <bangerth@0785d39b-7218-0410-832d-ea1e28bc413d>
Thu, 2 Jun 2011 18:05:50 +0000 (18:05 +0000)
committerbangerth <bangerth@0785d39b-7218-0410-832d-ea1e28bc413d>
Thu, 2 Jun 2011 18:05:50 +0000 (18:05 +0000)
on which it works has been refined or coarsened, and is then reinitialized
with a cell from the refined triangulation, it could compute wrong results or
crash outright. This has now been fixed.

git-svn-id: https://svn.dealii.org/trunk@23767 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/doc/news/changes.h
deal.II/include/deal.II/fe/fe_values.h
deal.II/source/fe/fe_values.cc

index 354009e903aa592f5e5f22e2500234531e515919..75d53930a5cbe189b650ed0dea25a0b47b66b373 100644 (file)
@@ -175,6 +175,13 @@ should be fixed now.
 <h3>Specific improvements</h3>
 
 <ol>
+<li> Fixed: If an FEValues object was kept around until after the triangulation
+on which it works has been refined or coarsened, and is then reinitialized
+with a cell from the refined triangulation, it could compute wrong results or
+crash outright. This has now been fixed.
+<br>
+(Wolfgang Bangerth 2011/06/02)
+
 <li> Changed: The TrilinosWrappers::SparsityPattern::trilinos_sparsity_pattern()
 function returned a reference to an object of kind Epetra_CrsMatrix. However, the
 actual object pointed to is of derived class Epetra_FECrsMatrix. The function
index f30324bfcb2aab5e8fd8a2d75109ea29c98104f7..aed910f276b320f07b1fe5a44a3b2f8b113580dc 100644 (file)
@@ -3019,6 +3019,34 @@ class FEValuesBase : protected FEValuesData<dim,spacedim>,
                                      */
     std::auto_ptr<const CellIteratorBase> present_cell;
 
+    /**
+     * A signal connection we use to ensure we get informed whenever the
+     * triangulation changes. We need to know about that because it
+     * invalidates all cell iterators and, as part of that, the
+     * 'present_cell' iterator we keep around between subsequent
+     * calls to reinit() in order to compute the cell similarity.
+     */
+    boost::signals2::connection tria_listener;
+    
+    /**
+     * A function that is connected to the triangulation in
+     * order to reset the stored 'present_cell' iterator to an invalid
+     * one whenever the triangulation is changed and the iterator consequently
+     * becomes invalid.
+     */
+    void invalidate_present_cell ();
+    
+    /**
+     * This function is called by the various reinit() functions in derived
+     * classes. Given the cell indicated by the argument, test whether
+     * we have to throw away the previously stored present_cell argument
+     * because it would require us to compare cells from different
+     * triangulations. In checking all this, also make sure that we have
+     * tria_listener connected to the triangulation to which we will set
+     * present_cell right after calling this function.
+     */
+    void maybe_invalidate_previous_present_cell (const typename Triangulation<dim,spacedim>::active_cell_iterator &cell);
+    
                                     /**
                                      * Storage for the mapping object.
                                      */
index 6e329476d71ca512fe9a620956f0c356b73e1b50..2f8a68645827fb24e95e05fcc4b36f364cc98646 100644 (file)
@@ -1703,6 +1703,8 @@ FEValuesBase<dim,spacedim>::~FEValuesBase ()
       mapping_data=0;
       delete tmp1;
     }
+    
+  tria_listener.disconnect ();
 }
 
 
@@ -3237,6 +3239,53 @@ FEValuesBase<dim,spacedim>::compute_update_flags (const UpdateFlags update_flags
 }
 
 
+template <int dim, int spacedim>
+void
+FEValuesBase< dim, spacedim >::invalidate_present_cell ()
+{
+  // if there is no present cell, then we shouldn't be
+  // connected via a signal to a triangulation
+  Assert (present_cell.get() != 0, ExcInternalError());
+  present_cell.reset ();
+}
+
+
+template <int dim, int spacedim>
+void
+FEValuesBase< dim, spacedim >::
+maybe_invalidate_previous_present_cell (const typename Triangulation<dim,spacedim>::active_cell_iterator &cell)
+{
+  if (present_cell.get() != 0)
+  {
+    if (&cell->get_triangulation() !=
+        &static_cast<const typename Triangulation<dim,spacedim>::cell_iterator>(*present_cell)
+       ->get_triangulation())
+      {
+       // the triangulations for the previous cell and the current cell
+       // do not match. disconnect from the previous triangulation and
+       // connect to the current one; also invalidate the previous
+       // cell because we shouldn't be comparing cells from different
+       // triangulations
+       tria_listener.disconnect ();
+       invalidate_present_cell();
+       tria_listener = 
+         cell->get_triangulation().signals.post_refinement.connect
+         (std_cxx1x::bind (&FEValuesBase<dim,spacedim>::invalidate_present_cell,
+                           std_cxx1x::ref(static_cast<FEValuesBase<dim,spacedim>&>(*this))));
+      }
+  }
+  else
+  {
+    // if this FEValues has never been set to any cell at all, then
+    // at least subscribe to the triangulation to get notified of
+    // changes
+    tria_listener = 
+    cell->get_triangulation().signals.post_refinement.connect
+    (std_cxx1x::bind (&FEValuesBase<dim,spacedim>::invalidate_present_cell,
+                     std_cxx1x::ref(static_cast<FEValuesBase<dim,spacedim>&>(*this))));
+  }
+}
+
 
 template <int dim, int spacedim>
 inline
@@ -3246,7 +3295,7 @@ FEValuesBase<dim,spacedim>::check_cell_similarity
 {
                                   // case that there has not been any cell
                                   // before
-  if (&*this->present_cell == 0)
+  if (this->present_cell.get() == 0)
     cell_similarity = CellSimilarity::none;
   else
                                     // in MappingQ, data can have been
@@ -3376,6 +3425,7 @@ FEValues<dim,spacedim>::reinit (const typename DoFHandler<dim,spacedim>::cell_it
          static_cast<const FiniteElementData<dim>&>(cell->get_fe()),
          typename FEVB::ExcFEDontMatch());
 
+  this->maybe_invalidate_previous_present_cell (cell);
   check_cell_similarity(cell);
 
                                   // set new cell. auto_ptr will take
@@ -3410,6 +3460,7 @@ FEValues<dim,spacedim>::reinit (const typename hp::DoFHandler<dim,spacedim>::cel
          static_cast<const FiniteElementData<dim>&>(cell->get_fe()),
          typename FEVB::ExcFEDontMatch());
 
+  this->maybe_invalidate_previous_present_cell (cell);
   check_cell_similarity(cell);
 
                                   // set new cell. auto_ptr will take
@@ -3451,6 +3502,7 @@ FEValues<dim,spacedim>::reinit (const typename MGDoFHandler<dim,spacedim>::cell_
 //       static_cast<const FiniteElementData<dim>&>(cell->get_fe()),
 //       typename FEValuesBase<dim,spacedim>::ExcFEDontMatch());
 
+  this->maybe_invalidate_previous_present_cell (cell);
   check_cell_similarity(cell);
 
                                   // set new cell. auto_ptr will take
@@ -3477,6 +3529,7 @@ void FEValues<dim,spacedim>::reinit (const typename Triangulation<dim,spacedim>:
 {
                                   // no FE in this cell, so no assertion
                                   // necessary here
+  this->maybe_invalidate_previous_present_cell (cell);
   check_cell_similarity(cell);
 
                                   // set new cell. auto_ptr will take
@@ -3657,6 +3710,7 @@ void FEFaceValues<dim,spacedim>::reinit (const typename DoFHandler<dim,spacedim>
                                   // destroyed and also that this
                                   // object gets destroyed in the
                                   // destruction of this class
+  this->maybe_invalidate_previous_present_cell (cell);
   this->present_cell.reset
     (new typename FEValuesBase<dim,spacedim>::template
      CellIterator<typename DoFHandler<dim,spacedim>::cell_iterator> (cell));
@@ -3693,6 +3747,7 @@ void FEFaceValues<dim,spacedim>::reinit (const typename hp::DoFHandler<dim,space
                                   // destroyed and also that this
                                   // object gets destroyed in the
                                   // destruction of this class
+  this->maybe_invalidate_previous_present_cell (cell);
   this->present_cell.reset
     (new typename FEValuesBase<dim,spacedim>::template
      CellIterator<typename hp::DoFHandler<dim,spacedim>::cell_iterator> (cell));
@@ -3733,6 +3788,7 @@ void FEFaceValues<dim,spacedim>::reinit (const typename MGDoFHandler<dim,spacedi
                                   // destroyed and also that this
                                   // object gets destroyed in the
                                   // destruction of this class
+  this->maybe_invalidate_previous_present_cell (cell);
   this->present_cell.reset
     (new typename FEValuesBase<dim,spacedim>::template
      CellIterator<typename MGDoFHandler<dim,spacedim>::cell_iterator> (cell));
@@ -3758,6 +3814,7 @@ void FEFaceValues<dim,spacedim>::reinit (const typename Triangulation<dim,spaced
                                   // destroyed and also that this
                                   // object gets destroyed in the
                                   // destruction of this class
+  this->maybe_invalidate_previous_present_cell (cell);
   this->present_cell.reset
     (new typename FEValuesBase<dim,spacedim>::TriaCellIterator (cell));
 
@@ -3905,6 +3962,7 @@ void FESubfaceValues<dim,spacedim>::reinit (const typename DoFHandler<dim,spaced
                                   // destroyed and also that this
                                   // object gets destroyed in the
                                   // destruction of this class
+  this->maybe_invalidate_previous_present_cell (cell);
   this->present_cell.reset
     (new typename FEValuesBase<dim,spacedim>::template
      CellIterator<typename DoFHandler<dim,spacedim>::cell_iterator> (cell));
@@ -3947,6 +4005,7 @@ void FESubfaceValues<dim,spacedim>::reinit (const typename hp::DoFHandler<dim,sp
                                   // destroyed and also that this
                                   // object gets destroyed in the
                                   // destruction of this class
+  this->maybe_invalidate_previous_present_cell (cell);
   this->present_cell.reset
     (new typename FEValuesBase<dim,spacedim>::template
      CellIterator<typename hp::DoFHandler<dim,spacedim>::cell_iterator> (cell));
@@ -3983,6 +4042,7 @@ void FESubfaceValues<dim,spacedim>::reinit (const typename MGDoFHandler<dim,spac
                                   // destroyed and also that this
                                   // object gets destroyed in the
                                   // destruction of this class
+  this->maybe_invalidate_previous_present_cell (cell);
   this->present_cell.reset
     (new typename FEValuesBase<dim,spacedim>::template
      CellIterator<typename MGDoFHandler<dim,spacedim>::cell_iterator> (cell));
@@ -4012,6 +4072,7 @@ void FESubfaceValues<dim,spacedim>::reinit (const typename Triangulation<dim,spa
                                   // destroyed and also that this
                                   // object gets destroyed in the
                                   // destruction of this class
+  this->maybe_invalidate_previous_present_cell (cell);
   this->present_cell.reset
     (new typename FEValuesBase<dim,spacedim>::TriaCellIterator (cell));
 

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.