From: bangerth Date: Thu, 2 Jun 2011 18:05:50 +0000 (+0000) Subject: Fixed: If an FEValues object was kept around until after the triangulation include... X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b08a27dec43bb2382058d670af0c984d5a0f4292;p=dealii-svn.git Fixed: If an FEValues object was kept around until after the triangulation include source doc 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 --- diff --git a/deal.II/doc/news/changes.h b/deal.II/doc/news/changes.h index 354009e903..75d53930a5 100644 --- a/deal.II/doc/news/changes.h +++ b/deal.II/doc/news/changes.h @@ -175,6 +175,13 @@ should be fixed now.

Specific improvements

    +
  1. 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. +
    +(Wolfgang Bangerth 2011/06/02) +
  2. 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 diff --git a/deal.II/include/deal.II/fe/fe_values.h b/deal.II/include/deal.II/fe/fe_values.h index f30324bfcb..aed910f276 100644 --- a/deal.II/include/deal.II/fe/fe_values.h +++ b/deal.II/include/deal.II/fe/fe_values.h @@ -3019,6 +3019,34 @@ class FEValuesBase : protected FEValuesData, */ std::auto_ptr 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::active_cell_iterator &cell); + /** * Storage for the mapping object. */ diff --git a/deal.II/source/fe/fe_values.cc b/deal.II/source/fe/fe_values.cc index 6e329476d7..2f8a686458 100644 --- a/deal.II/source/fe/fe_values.cc +++ b/deal.II/source/fe/fe_values.cc @@ -1703,6 +1703,8 @@ FEValuesBase::~FEValuesBase () mapping_data=0; delete tmp1; } + + tria_listener.disconnect (); } @@ -3237,6 +3239,53 @@ FEValuesBase::compute_update_flags (const UpdateFlags update_flags } +template +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 +void +FEValuesBase< dim, spacedim >:: +maybe_invalidate_previous_present_cell (const typename Triangulation::active_cell_iterator &cell) +{ + if (present_cell.get() != 0) + { + if (&cell->get_triangulation() != + &static_cast::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::invalidate_present_cell, + std_cxx1x::ref(static_cast&>(*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::invalidate_present_cell, + std_cxx1x::ref(static_cast&>(*this)))); + } +} + template inline @@ -3246,7 +3295,7 @@ FEValuesBase::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::reinit (const typename DoFHandler::cell_it static_cast&>(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::reinit (const typename hp::DoFHandler::cel static_cast&>(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::reinit (const typename MGDoFHandler::cell_ // static_cast&>(cell->get_fe()), // typename FEValuesBase::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::reinit (const typename Triangulation: { // 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::reinit (const typename DoFHandler // 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::template CellIterator::cell_iterator> (cell)); @@ -3693,6 +3747,7 @@ void FEFaceValues::reinit (const typename hp::DoFHandlermaybe_invalidate_previous_present_cell (cell); this->present_cell.reset (new typename FEValuesBase::template CellIterator::cell_iterator> (cell)); @@ -3733,6 +3788,7 @@ void FEFaceValues::reinit (const typename MGDoFHandlermaybe_invalidate_previous_present_cell (cell); this->present_cell.reset (new typename FEValuesBase::template CellIterator::cell_iterator> (cell)); @@ -3758,6 +3814,7 @@ void FEFaceValues::reinit (const typename Triangulationmaybe_invalidate_previous_present_cell (cell); this->present_cell.reset (new typename FEValuesBase::TriaCellIterator (cell)); @@ -3905,6 +3962,7 @@ void FESubfaceValues::reinit (const typename DoFHandlermaybe_invalidate_previous_present_cell (cell); this->present_cell.reset (new typename FEValuesBase::template CellIterator::cell_iterator> (cell)); @@ -3947,6 +4005,7 @@ void FESubfaceValues::reinit (const typename hp::DoFHandlermaybe_invalidate_previous_present_cell (cell); this->present_cell.reset (new typename FEValuesBase::template CellIterator::cell_iterator> (cell)); @@ -3983,6 +4042,7 @@ void FESubfaceValues::reinit (const typename MGDoFHandlermaybe_invalidate_previous_present_cell (cell); this->present_cell.reset (new typename FEValuesBase::template CellIterator::cell_iterator> (cell)); @@ -4012,6 +4072,7 @@ void FESubfaceValues::reinit (const typename Triangulationmaybe_invalidate_previous_present_cell (cell); this->present_cell.reset (new typename FEValuesBase::TriaCellIterator (cell));