Line data Source code
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 59360 : void SolutionHistory::find_stored_entry(Real time, bool storing) 28 : { 29 59360 : if (stored_data.begin() == stored_data.end()) 30 448 : 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 1672 : stored_data_iterator lower_bound_it = stored_data.lower_bound(time); 41 : 42 : // For the key right before the lower bound 43 1672 : 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 58520 : 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 11760 : if(storing) 52 : { 53 336 : 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 0 : lower_bound_it = std::prev(lower_bound_it); 61 : } 62 : } 63 46760 : else if(lower_bound_it == stored_data.begin()) // At the beginning, so we cant go back any further 64 : { 65 3080 : stored_datum = stored_data.begin(); 66 3080 : return; 67 : } 68 : else // A decremented iterator, to perform the sandwich test for the key closest to time 69 : { 70 43680 : 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 44928 : if(std::abs(lower_bound_it->first - time) < TOLERANCE) 75 : { 76 36680 : stored_datum = lower_bound_it; 77 : } 78 7200 : else if(std::abs(lower_bound_it_decremented->first - time) < TOLERANCE) 79 : { 80 7000 : stored_datum = lower_bound_it_decremented; 81 : } 82 : else // Neither of the two candidate keys matched our time 83 : { 84 0 : if(storing) // If we are storing, this is fine, we need to create a new entry, so just return 85 : { 86 0 : 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 0 : libmesh_error_msg("Failed to set stored solutions iterator to a valid value."); 91 : } 92 : } 93 : } 94 : 95 0 : void SolutionHistory::erase(Real time) 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 0 : 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 0 : this->find_stored_entry(time, false); 104 : 105 : // map::erase behaviour is undefined if the iterator is pointing 106 : // to a non-existent element. 107 0 : libmesh_assert(stored_datum != stored_data.end()); 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 0 : 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 0 : if(stored_datum == stored_datum_last) 115 0 : stored_datum--; 116 : 117 0 : stored_data.erase(stored_datum_copy); 118 0 : } 119 : 120 : } 121 : // End namespace libMesh