libMesh
solution_history.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 #include "libmesh/solution_history.h"
19 #include <cmath>
20 #include <iterator>
21 
22 namespace libMesh
23 {
24  // This function finds, if it can, the entry where we're supposed to
25  // be storing data, leaves stored_datum unchanged if it cant find an entry
26  // with the key corresponding to time.
27  void SolutionHistory::find_stored_entry(Real time, bool storing)
28  {
29  if (stored_data.begin() == stored_data.end())
30  return;
31 
32  // We will use the map::lower_bound operation to find the key which
33  // is the least upper bound among all existing keys for time.
34  // (key before map::lower_bound) < time < map::lower_bound, one of these
35  // should be within TOLERANCE of time (unless we are creating a new map entry)
36  // If the lower bound iterator points to:
37  // begin -> we are looking for the solution at the initial time
38  // end -> we are creating a new entry
39  // anything else, we are looking for an existing entry
40  stored_data_iterator lower_bound_it = stored_data.lower_bound(time);
41 
42  // For the key right before the lower bound
43  stored_data_iterator lower_bound_it_decremented;
44 
45  // If we are at end, we could be creating a new entry (depends on the storing bool), return
46  // Otherwise, get a decremented iterator for the sandwich test
47  if(lower_bound_it == stored_data.end())
48  {
49  // If we are storing and lower_bound_it points to stored_data.end(), we assume
50  // that this is a brand new entry in the map. We leave stored_datum unchanged.
51  if(storing)
52  {
53  return;
54  }
55  else
56  {
57  // We are trying to retrieve and none of the keys was an upper bound.
58  // We could have a situation in which the time is greatest key + FPE.
59  // So we can check the key before the end and see if it matches time, else we have an error.
60  lower_bound_it = std::prev(lower_bound_it);
61  }
62  }
63  else if(lower_bound_it == stored_data.begin()) // At the beginning, so we cant go back any further
64  {
65  stored_datum = stored_data.begin();
66  return;
67  }
68  else // A decremented iterator, to perform the sandwich test for the key closest to time
69  {
70  lower_bound_it_decremented = std::prev(lower_bound_it);
71  }
72 
73  // Set the stored sols iterator as per the key which is within TOLERANCE of time
74  if(std::abs(lower_bound_it->first - time) < TOLERANCE)
75  {
76  stored_datum = lower_bound_it;
77  }
78  else if(std::abs(lower_bound_it_decremented->first - time) < TOLERANCE)
79  {
80  stored_datum = lower_bound_it_decremented;
81  }
82  else // Neither of the two candidate keys matched our time
83  {
84  if(storing) // If we are storing, this is fine, we need to create a new entry, so just return
85  {
86  return;
87  }
88  else // If we are not storing, then we expected to find something but didn't, so we have a problem
89  {
90  libmesh_error_msg("Failed to set stored solutions iterator to a valid value.");
91  }
92  }
93  }
94 
96  {
97  // We cant erase the stored_datum iterator which is used in other places
98  // So save its current value for the future
99  stored_data_iterator stored_datum_last = stored_datum;
100  //std::map<Real, unsigned int>::iterator timeTotimestamp_iterator_last = timeTotimestamp_iterator;
101 
102  // This will map the stored_datum iterator to the current time
103  this->find_stored_entry(time, false);
104 
105  // map::erase behaviour is undefined if the iterator is pointing
106  // to a non-existent element.
108 
109  // We want to keep using the stored_datum iterator, so we have to create
110  // a new one to erase the concerned entry
111  stored_data_iterator stored_datum_copy = stored_datum;
112 
113  // If we're asking to erase the entry at stored_datum, then move stored_datum somewhere safer first
114  if(stored_datum == stored_datum_last)
115  stored_datum--;
116 
117  stored_data.erase(stored_datum_copy);
118  }
119 
120 }
121 // End namespace libMesh
static constexpr Real TOLERANCE
static const unsigned int prev[3]
A lookup table for the decrement modulo 3 operation, for iterating through the three nodes per elemen...
The libMesh namespace provides an interface to certain functionality in the library.
void erase(Real time)
Erase stored_data entry at time.
libmesh_assert(ctx)
map_type::iterator stored_data_iterator
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
stored_data_iterator stored_datum
void find_stored_entry(Real time, bool storing=false)