Flow123d
time_marks.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id: time_marks.cc 1334 2011-09-19 13:58:59Z jan.brezina $
21  * $Revision: 1334 $
22  * $LastChangedBy: jan.brezina $
23  * $LastChangedDate: 2011-09-19 15:58:59 +0200 (Po, 19 zář 2011) $
24  *
25  * @file
26  * @brief
27  *
28  * @author Jan Brezina
29  */
30 
31 #include "system/system.hh"
32 #include "time_marks.hh"
33 #include "time_governor.hh"
34 #include <algorithm>
35 #include <limits>
36 
37 // ------------------------------------------------------
38 // implementation of members of class TimeMark
39 // ------------------------------------------------------
40 
41 ostream& operator<<(ostream& stream, const TimeMark &mark)
42 {
43  //return ( stream << mark.time()<<": 0o" << oct << mark.mark_type() << dec ); //octal output
44  return ( stream << mark.time()<<": 0x" << hex << mark.mark_type() << dec );
45 }
46 
49 
50 
51 //This mask is replaced by type_fixed_time_ defined in constructor of TimeMarks //OBSOLETE
52 //const TimeMark::Type TimeMark::strict = 0x1;
53 
54 
55 // ------------------------------------------------------
56 // implementation of members of class TimeMarks
57 // ------------------------------------------------------
58 
60 : next_mark_type_(0x1)
61 {
62  // add predefined base mark types
66 
67  // insert start and end stoppers
68  marks_.push_back(TimeMark(-INFINITY, TimeMark::every_type));
69  marks_.push_back(TimeMark(+INFINITY, TimeMark::every_type));
70 }
71 
72 
74  ASSERT(next_mark_type_ != 0, "Can not allocate new mark type. The limit is 32 mark types.\n");
75  TimeMark::Type current_type = next_mark_type_;
76 
77  next_mark_type_ <<= 1;
78  return current_type;
79 }
80 
81 //TimeMark::Type TimeMarks::new_strict_mark_type() {
82 // return new_mark_type() | TimeMark::strict;
83 //}
84 
85 void TimeMarks::add(const TimeMark &mark) {
86  // find first mark with time greater or equal to the new mark
87  vector<TimeMark>::iterator first_ge = std::lower_bound(marks_.begin(), marks_.end(), mark);
88 
89  // check equivalence with found mark
90  if (fabs(first_ge->time() - mark.time()) < 2*numeric_limits<double>::epsilon()) {
91  //if "equal" does bitwise OR with the mark type at the first_ge iterator position
92  first_ge->add_to_type(mark.mark_type());
93  return;
94  }
95  // possibly check equivalence with previous mark
96  if (first_ge != marks_.begin()) {
97  vector<TimeMark>::iterator previous = first_ge;
98  --previous;
99  if (fabs(previous->time() - mark.time()) < 2*numeric_limits<double>::epsilon()) {
100  previous->add_to_type(mark.mark_type());
101  return;
102  }
103  }
104 
105  marks_.insert(first_ge, mark);
106 }
107 
108 void TimeMarks::add_time_marks(double time, double dt, double end_time, TimeMark::Type type) {
109  ASSERT(end_time != TimeGovernor::inf_time, "Can not add time marks on infinite interval.\n");
110  ASSERT(dt > numeric_limits<double>::epsilon(), "TimeMark's step less then machine precision.\n");
111  //if (end_time == TimeGovernor::inf_time) {
112  // if (time == TimeGovernor::inf_time) return;
113  // else add(TimeMark(time, type));
114  //} else
115  //if (dt == 0) {
116  // prevent infinite loop - add only initial time
117  // add(TimeMark(time, type));
118  //}
119  //else {
120  for (double t = time; t <= end_time*1.001; t += dt) {
121  auto mark = TimeMark(t, type);
122  add(mark);
123  }
124  // }
125 }
126 
127 bool TimeMarks::is_current(const TimeGovernor &tg, const TimeMark::Type &mask) const
128 {
129  if (tg.t() == TimeGovernor::inf_time) return tg.is_end();
130  const TimeMark &tm = *last(tg, mask);
131  return tg.lt(tm.time() + tg.dt()); // last_t + dt < mark_t + dt
132 }
133 
135 {
136  vector<TimeMark>::const_iterator first_ge = std::lower_bound(marks_.begin(), marks_.end(), TimeMark(tg.t(),mask));
137  while ( ! tg.lt(first_ge->time()) || ! first_ge->match_mask(mask) ) {
138  ++first_ge;
139  }
140  return TimeMarksIterator(marks_, first_ge, mask);
141 }
142 
144 {
145  vector<TimeMark>::const_iterator first_ge = std::lower_bound(marks_.begin(), marks_.end(), TimeMark(tg.t()+0.01*tg.dt(),mask));
146  while ( ! tg.ge(first_ge->time()) || ! first_ge->match_mask(mask) ) {
147  --first_ge;
148  }
149  // cout << "TimeMark::last(): " << *first_ge << endl;
150  return TimeMarksIterator(marks_, first_ge, mask);
151 }
152 
153 
154 
156 {
157  auto it = TimeMarksIterator(marks_, --marks_.end(), mask); // +INF time mark
158  --it;
159  return it;
160 }
161 
162 
163 
165 {
166  return TimeMarksIterator(marks_, marks_.begin(), mask);
167 }
168 
169 
170 
172 {
173  return TimeMarksIterator(marks_, --marks_.end(), mask);
174 }
175 
176 
177 
178 ostream& operator<<(ostream& stream, const TimeMarks &marks)
179 {
180  stream << "time marks:" << endl;
181  for(vector<TimeMark>::const_iterator it = marks.marks_.begin(); it != marks.marks_.end(); ++it)
182  stream << *it << endl;
183  return stream;
184 }