The Conley-Morse Graphs Software
odeintegr.h
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2///
3/// @file odeintegr.h
4///
5/// ODE integration parameters: guessing, adjusting, saving.
6///
7/// @author Pawel Pilarczyk
8///
9/////////////////////////////////////////////////////////////////////////////
10
11// Copyright (C) 1997-2014 by Pawel Pilarczyk.
12//
13// This file is part of my research software package. This is free software:
14// you can redistribute it and/or modify it under the terms of the GNU
15// General Public License as published by the Free Software Foundation,
16// either version 3 of the License, or (at your option) any later version.
17//
18// This software is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with this software; see the file "license.txt". If not,
25// please, see <https://www.gnu.org/licenses/>.
26
27// Started on March 24, 2013. Last revision: November 27, 2013.
28
29
30#ifndef _CMGRAPHS_ODEINTEGR_H_
31#define _CMGRAPHS_ODEINTEGR_H_
32
33
34// include some standard C++ header files
35#include <string>
36#include <sstream>
37#include <vector>
38#include <iostream>
39#include <iomanip>
40#include <algorithm>
41#include <memory>
42#include <utility>
43
44// include all the necessary header files from the CHomP library
45#include "chomp/system/config.h"
46#include "chomp/system/textfile.h"
47#include "chomp/multiwork/mwdata.h"
48
49// include local header files
50#include "datavector.h"
51#include "mapparam.h"
52#include "datatext.h"
53
54
55// --------------------------------------------------
56// ----------- ODE integration parameters -----------
57// --------------------------------------------------
58
59/// A class whose objects are responsible for adjusting the integration
60/// parameters such as step size and the number of steps for an ODE.
62{
63public:
64 /// The constructor which takes the suggested values for the order
65 /// of the method, the step size, and the number of steps.
66 OdeIntegrParam (int order, double step, int n);
67
68 /// The destructor.
70
71 /// Sets the parameters to the given intervals defined by their
72 /// left and right coordinates.
73 void setParam (const double *left, const double *right, int n);
74
75 /// Provides recommended values for integration:
76 /// the order of the Taylor method, the size of the integration step,
77 /// and the number of steps.
78 void get (int &order, double &step, int &n, int subdiv);
79
80 /// Adjusts parameters if necessary after a successful computation
81 /// or after an unsuccessful computation of the graph of the map
82 /// at a specific subdivision depth.
83 /// Returns true iff it is necessary to repeat the computation.
84 bool adjust (bool successful, int subdiv);
85
86 /// Returns a line (or lines) with a summary of information
87 /// about the knowledge gathered through the "adjust" function,
88 /// for later use.
89 std::string getInfo () const;
90
91 /// Analyzes a previously saved line with a summary of information
92 /// and adjusts the data accordingly.
93 void useInfo (const std::string &info);
94
95 /// Saves the data for serialization.
96 void saveData (chomp::multiwork::mwData &data) const;
97
98 /// Retrieves a serialized object.
99 void loadData (chomp::multiwork::mwData &data);
100
101private:
102 /// The copy constructor should not be used.
104
105 /// The assignment operator should not be used.
107
108 /// The parameters of the map.
110
111 /// Step sizes at subsequent subdivision depths.
112 std::vector<double> stepSizes;
113
114 /// Strategy for trying another step size at each subdivision depth.
115 /// 0 = increase if successful (no attempt has yet been made);
116 /// 1 = increase if successful (previous attempt was successful);
117 /// 2 = an unsuccessful attempt encountered, don't try anything else
118 /// if successful, decrease if unsuccessful;
119 /// 3 = don't increase even if successful,
120 /// it is known that this is a good guess already.
121 std::vector<int> strategy;
122
123 /// Extends the internal arrays to make sure that the entries
124 /// for the given subdivision depth are valid.
125 void extendVectors (int subdiv);
126
127 /// The order of the Taylor method suggested to use.
129
130 /// The size of the step suggested for itegrating the flow.
132
133 /// The number of steps suggested to use.
135
136 /// Was this information set up based on previous results?
138
139 /// Were the parameters changed, so that it is worth to share them?
141
142}; /* class OdeIntegrParam */
143
144// --------------------------------------------------
145
146inline OdeIntegrParam::OdeIntegrParam (int order, double step, int n):
147 defaultOrder (order), defaultStepSize (step),
148 defaultNumberOfSteps (n),
149 usingPrevious (false), changed (false)
150{
151 return;
152} /* OdeIntegrParam::OdeIntegrParam */
153
155{
156 return;
157} /* OdeIntegrParam::~OdeIntegrParam */
158
160{
161 throw "Trying to use the copy constructor of OdeIntegrParam.";
162 return;
163} /* OdeIntegrParam::OdeIntegrParam */
164
166{
167 throw "Trying to use the assignment operator of OdeIntegrParam.";
168 return *this;
169} /* OdeIntegrParam::OdeIntegrParam */
170
171inline void OdeIntegrParam::setParam (const double *left, const double *right,
172 int n)
173{
174 param. define (left, right, n);
175 return;
176} /* OdeIntegrParam::setParam */
177
178inline void OdeIntegrParam::get (int &order, double &step, int &n,
179 int subdiv)
180{
181 // make sure that the entries for the subdivision depth are defined
182 extendVectors (subdiv);
183
184 // prepare the order of the Taylor method
185 order = defaultOrder;
186
187 // prepare the step size
188 step = stepSizes [subdiv];
189
190 // prepare the number of steps
192
193 // show info on the step size if necessary
194 static int prevSubdiv = 0;
195 if (subdiv > prevSubdiv)
196 {
197 using chomp::homology::sbug;
198 sbug << "Using step size " << step << " at depth " <<
199 subdiv << ".\n";
200 prevSubdiv = subdiv;
201 }
202
203 return;
204} /* OdeIntegrParam::get */
205
206inline bool OdeIntegrParam::adjust (bool successful, int subdiv)
207{
208 using chomp::homology::sbug;
209
210 // extend the vectors to make sure that the entries for the given
211 // subdivision depth are defined
212 extendVectors (subdiv);
213
214 // prepare coefficients for increasing and decreasing step size
215 const double incCoef = 2.0;
216 const double decCoef = 0.9;
217
218 // if successful then increase the step size, unless not feasible
219 if (successful)
220 {
221 if ((strategy [subdiv] == 2) || (strategy [subdiv] == 3))
222 return false;
223 sbug << "Good!\nSuccessful integration at depth " <<
224 subdiv << " with step size = " <<
225 stepSizes [subdiv] << ". Trying ";
226 stepSizes [subdiv] *= incCoef;
227 sbug << stepSizes [subdiv] << ".\n";
228 changed = true;
229 return true;
230 }
231 changed = true;
232
233 // make a note that an unsuccessful attempt took place
234 strategy [subdiv] = 2;
235
236 // show a message that the integration failed
237 sbug << "Integration at depth " << subdiv <<
238 " failed with step size " << stepSizes [subdiv] << ". ";
239
240 // decrease the step size and suggest to try again
241 // (in a more sophisticated version, the decrease can be different,
242 // depending on the largest successful step size
243 // encountered at previous computations)
244 stepSizes [subdiv] *= decCoef;
245 sbug << "Trying " << stepSizes [subdiv] << ".\n";
246
247 return true;
248} /* OdeIntegrParam::adjust */
249
250inline void OdeIntegrParam::extendVectors (int subdiv)
251{
252 // extend the vector with step sizes
253 while (static_cast<int> (stepSizes. size ()) <= subdiv)
254 {
255 if (static_cast<int> (stepSizes. size ()) <= initialDepth)
256 {
257 stepSizes. push_back (defaultStepSize);
258 }
259 else if (static_cast<int> (stepSizes. size ()) <= finalDepth)
260 {
261 stepSizes. push_back
262 (2 * stepSizes [stepSizes. size () - 1]);
263 }
264 else
265 {
266 stepSizes. push_back
267 (stepSizes [stepSizes. size () - 1]);
268 }
269 changed = true;
270 }
271
272 // extend the vector with strategy numbers
273 while (static_cast<int> (strategy. size ()) <= subdiv)
274 {
275 strategy. push_back (0);
276 }
277
278 return;
279} /* OdeIntegrParam::extendVectors */
280
281inline std::string OdeIntegrParam::getInfo () const
282{
283 // if there is no new information then don't return anything
284 if (usingPrevious && !changed)
285 return std::string ();
286
287 // prepare a string stream to write the data to
288 std::ostringstream s;
289
290 // save the map parameters
291 s << param;
292
293#ifdef ODEPARAM_APPROXIMATE
294 // save an identification code
295 s << ' ' << 'S';
296
297 // save the vector stepSizes
298 s << ' ' << stepSizes. size ();
299 int precision = s. precision ();
300 int hiprec = 12;
301 s << std::setprecision (hiprec);
302 for (size_t n = 0; n < stepSizes. size (); ++ n)
303 s << ' ' << stepSizes [n];
304 s << std::setprecision (precision);
305#else
306 // save an identification code
307 s << ' ' << 'B';
308
309 // serialize the new information
310 chomp::multiwork::mwData data;
311 data << param;
312 data << stepSizes;
313
314 // encode the binary data to a simple string
315 s << ' ' << data2text (data);
316#endif
317 // write an ending control character
318 s << ' ' << 'Q';
319
320 // return the string
321 return s. str ();
322} /* OdeIntegrParam::getInfo */
323
324inline void OdeIntegrParam::useInfo (const std::string &info)
325{
326 // prepare a string stream to read the data from
327 using chomp::homology::ignorecomments;
328 std::istringstream s (info);
329
330 // read the parameters of the map and check if they agree
331 MapParam _param;
332 s >> _param;
333 if (!intersect (param, _param) || !shareInteriors (param, _param))
334 return;
335 ignorecomments (s);
336
337#ifdef ODEPARAM_APPROXIMATE
338 // read the identification code
339 if (s. get () != 'S')
340 return;
341
342 // read the vector stepSizes
343 size_t stepSizesSize = 0;
344 s >> stepSizesSize;
345 stepSizes. resize (stepSizesSize);
346 for (size_t n = 0; n < stepSizesSize; ++ n)
347 s >> stepSizes [n];
348#else
349 // read the identification code
350 if (s. get () != 'B')
351 return;
352 ignorecomments (s);
353
354 // decode the binary data from the input string
355 std::string str;
356 s >> str;
357 chomp::multiwork::mwData data;
358 text2data (str, data);
359
360 // extract the parameters and check if they agree
361 MapParam _paramExact;
362 data >> _paramExact;
363 if (!(param == _paramExact))
364 return;
365
366 // extract the step sizes
367 data >> stepSizes;
368#endif
369 // make sure that there is the right control character at the end
370 // of the input line
371 ignorecomments (s);
372 if (s. get () != 'Q')
373 throw "Missing 'Q' at the end of ODE integr info.";
374
375 // make a note that the previously tested settings will be used
376 usingPrevious = true;
377 strategy. clear ();
378 strategy. resize (stepSizes. size (), 3);
379
380 return;
381} /* OdeIntegrParam::useInfo */
382
383inline void OdeIntegrParam::saveData (chomp::multiwork::mwData &data) const
384{
385 data << stepSizes;
386 data << strategy;
387
388 return;
389} /* OdeIntegrParam::saveData */
390
391inline void OdeIntegrParam::loadData (chomp::multiwork::mwData &data)
392{
393 data >> stepSizes;
394 data >> strategy;
395
396 return;
397} /* OdeIntegrParam::loadData */
398
399// --------------------------------------------------
400
401/// Serializes an object with ODE parameters.
402inline chomp::multiwork::mwData &operator << (chomp::multiwork::mwData &data,
403 const OdeIntegrParam &odeIntegrParam)
404{
405 odeIntegrParam. saveData (data);
406 return data;
407} /* operator << */
408
409/// Deserializes an object with ODE parameters.
410inline chomp::multiwork::mwData &operator >> (chomp::multiwork::mwData &data,
411 OdeIntegrParam &odeIntegrParam)
412{
413 odeIntegrParam. loadData (data);
414 return data;
415} /* operator >> */
416
417
418#endif // _CMGRAPHS_ODEINTEGR_H_
419
A data structure for storing map parameters.
Definition: mapparam.h:57
A class whose objects are responsible for adjusting the integration parameters such as step size and ...
Definition: odeintegr.h:62
void saveData(chomp::multiwork::mwData &data) const
Saves the data for serialization.
Definition: odeintegr.h:383
void useInfo(const std::string &info)
Analyzes a previously saved line with a summary of information and adjusts the data accordingly.
Definition: odeintegr.h:324
bool adjust(bool successful, int subdiv)
Adjusts parameters if necessary after a successful computation or after an unsuccessful computation o...
Definition: odeintegr.h:206
std::vector< double > stepSizes
Step sizes at subsequent subdivision depths.
Definition: odeintegr.h:112
std::string getInfo() const
Returns a line (or lines) with a summary of information about the knowledge gathered through the "adj...
Definition: odeintegr.h:281
int defaultOrder
The order of the Taylor method suggested to use.
Definition: odeintegr.h:128
MapParam param
The parameters of the map.
Definition: odeintegr.h:109
~OdeIntegrParam()
The destructor.
Definition: odeintegr.h:154
std::vector< int > strategy
Strategy for trying another step size at each subdivision depth.
Definition: odeintegr.h:121
void get(int &order, double &step, int &n, int subdiv)
Provides recommended values for integration: the order of the Taylor method, the size of the integrat...
Definition: odeintegr.h:178
bool changed
Were the parameters changed, so that it is worth to share them?
Definition: odeintegr.h:140
double defaultStepSize
The size of the step suggested for itegrating the flow.
Definition: odeintegr.h:131
OdeIntegrParam(int order, double step, int n)
The constructor which takes the suggested values for the order of the method, the step size,...
Definition: odeintegr.h:146
OdeIntegrParam & operator=(const OdeIntegrParam &)
The assignment operator should not be used.
Definition: odeintegr.h:165
void setParam(const double *left, const double *right, int n)
Sets the parameters to the given intervals defined by their left and right coordinates.
Definition: odeintegr.h:171
bool usingPrevious
Was this information set up based on previous results?
Definition: odeintegr.h:137
void loadData(chomp::multiwork::mwData &data)
Retrieves a serialized object.
Definition: odeintegr.h:391
int defaultNumberOfSteps
The number of steps suggested to use.
Definition: odeintegr.h:134
void extendVectors(int subdiv)
Extends the internal arrays to make sure that the entries for the given subdivision depth are valid.
Definition: odeintegr.h:250
Converting a binary data buffer into a printable text and vice versa.
void text2data(const std::string &str, chomp::multiwork::mwData &data)
Decodes a prevously prepared text back into binary data.
Definition: datatext.h:76
std::string data2text(const chomp::multiwork::mwData &data)
Encodes the entire binary data into a text string (single line, printable characters only).
Definition: datatext.h:48
Data conversion for sending/receiving: std::vectors and hashed sets of any objects.
A simple aggregate data structure for map parameters.
bool intersect(const MapParam &par1, const MapParam &par2)
Checks if two aggregate parameter objects are so close to each other that after a small blow-up they ...
Definition: mapparam.h:257
bool shareInteriors(const MapParam &par1, const MapParam &par2)
Checks if two aggregate parameter objects that intersect actually share interiors in the parameters o...
Definition: mapparam.h:282
const int initialDepth
The initial depth of subdivisions in the phase space.
Definition: p_differ.h:55
const int finalDepth
The final depth of subdivisions in the phase space.
Definition: p_differ.h:58
chomp::multiwork::mwData & operator<<(chomp::multiwork::mwData &data, const OdeIntegrParam &odeIntegrParam)
Serializes an object with ODE parameters.
Definition: odeintegr.h:402
chomp::multiwork::mwData & operator>>(chomp::multiwork::mwData &data, OdeIntegrParam &odeIntegrParam)
Deserializes an object with ODE parameters.
Definition: odeintegr.h:410