1 /* Siconos is a program dedicated to modeling, simulation and control
2  * of non smooth dynamical systems.
3  *
4  * Copyright 2021 INRIA.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17 */
18 /*! \file TimeDiscretisation.hpp
19 
20   \brief A time-discretisation scheme for a given interval.
21  */
22 #ifndef TIMEDISCRETISATION_H
23 #define TIMEDISCRETISATION_H
24 
25 #include <vector>
26 #include <gmp.h>
27 #include "SiconosFwd.hpp"
28 #include "SiconosSerialization.hpp" // for ACCEPT_SERIALIZATION
29 
30 typedef std::vector<double> TkVector;
31 
32 /** A time discretisation scheme
33 
34     A TimeDiscretisation object is used to discretized a given time interval. \n
35     TimeDiscretisation are used:
36     - in the simulation, as a user-input to discretized [t0,T]
37     - in Sensor and Actuator, to define the set of time instants where the sensor or actuator
38     must operate.
39 
40     A TimeDiscretisation is defined with a starting time (t0), a time step size (h, non necessarily constant),
41     the number of the current time step (k). \n
42     The time instant values are saved in a vector tk. Depending on the way of construction of the TimeDiscretisation,
43     all or only current and next times are saved in tk. The difference is just a question of saving memory. \n
44 
45     Note that the TimeDiscretisation is not linked to the Model. It's up to the user to check that the way he builds his time-discretisation fits with the t0 and T given in the model.
46 
47     \section tdMfunc Main functions:
48     - setCurrentTimeStep(), to set current h. This value will be used for all future time steps, until next change.
49     - increment(), shift to next time step (increment k, and shift t[k] and t[k+1])
50     - currentTime(), return t[k]
51 
52     \section tdBuild Construction
53 
54     - input = the complete vector tk. This defines t0, T, number of time steps and time step size
55     (which is not necessarily constant). In this case, the whole vector is saved in the memory.
56     - inputs = number of time steps, t0 and T.
57     size h is computed with t0,T and nSteps. Only two values are saved: t[k] and t[k+1] = t[k] + h.
58     h can be changed at any time.
59     - inputs = h and t0. Only two values are saved: t[k] and t[k+1] = t[k] + h.
60     h can be changed at any time.
61     - inputs = t0 and h.  Only two values are saved: t[k] and t[k+1] = t[k] + h.
62     h can be changed at any time.
63 
64  */
65 class TimeDiscretisation
66 {
67 private:
68   /** serialization hooks
69   */
70   ACCEPT_SERIALIZATION(TimeDiscretisation);
71 
72 
73   /** Default value for the time step (tk+1 - tk) */
74   double _h;
75 
76   /** vector of time values at each step (=> size = n1+n2+1 - Default size = 2 - Max size= nSteps+1) */
77   TkVector _tkV;
78 
79   /** Origin of time*/
80   double _t0;
81 
82   /** Timestep stored as mpf_t, for high precision computations */
83   mpf_t _hgmp;
84 
85   /** Time at t_{k+1}, in mpf_t, used to compute a good timestep */
86   mpf_t _tkp1;
87 
88   /** Time at t_{k+1}, in mpf_t, used to compute a good timestep */
89   mpf_t _tk;
90 
91    /** Starting time, used to compute a good timestep */
92   mpf_t _t0gmp;
93 
94   /** default constructor (private => no copy nor pass-by value)
95    */
96   TimeDiscretisation();
97 
98   /** Assignment Operator (private => forbidden)
99    * \param td unused
100    * \return TimeDiscretisation&
101    */
102   TimeDiscretisation& operator =(const TimeDiscretisation& td);
103 
104   /** Get the origin of time t0
105    * \return the origin of time
106    */
getT0() const107   inline double getT0() const
108   {
109     return _t0;
110   }
111 
112 public:
113 
114   // --- Straightforward constructors ---
115 
116   /** constructor with tk vector of instant times values.
117    *  \param newTk a TkVector describing the discretisation
118    */
119   TimeDiscretisation(const TkVector& newTk);
120 
121   /** constructor with the size of the default time step and t0
122    *  \param t0 initial time value
123    *  \param h the time step
124    */
125   TimeDiscretisation(double t0, double h);
126 
127   /** constructor with the number of steps, t0 and T
128    *  \param nSteps the number of steps
129    *  \param t0 initial time value
130    *  \param T the final time
131    */
132   TimeDiscretisation(unsigned int nSteps, double t0, double T);
133 
134   /** Constructor with the size of the default timestep and t0.
135    * It creates a TimeDiscretisation using GMP for all its computation
136    *  \param t0 initial time value
137    *  \param str the time step in form of a string
138    */
139   TimeDiscretisation(double t0, const std::string& str);
140 
141   /** Copy constructor
142    * \param td the TimeDiscretisation to copy
143    */
144   TimeDiscretisation(const TimeDiscretisation& td);
145 
146   // Destructor
147   ~TimeDiscretisation();
148 
149   // --- GETTERS/SETTERS ---
150 
151   /** get the timestep \f$t_{k+1} - t_k\f$
152    * \param k the index of the timestep
153    * \return the current time step
154    */
155   double currentTimeStep(const unsigned int k);
156 
157   /** get the timestep in gmp format
158    * \return a pointer to the timestep in mpf_t format
159    */
currentTimeStep() const160   inline const mpf_t* currentTimeStep() const
161   {
162     return &_hgmp;
163   };
164 
165   /** determine whether the timestep is constant
166    * \return true if the timestep is constant
167    */
hConst() const168   inline bool hConst() const
169   {
170     return _tkV.empty() ? true : false;
171   };
172 
173   /** determine whether the TimeDiscretisation is using GMP
174    * \return true if the TimeDiscretisation is using GMP
175    */
hGmp() const176   inline bool hGmp() const
177   {
178     return ((_h == 0.0) && (_tkV.empty()))  ? true : false;
179   }
180 
181   /** get the value of tk at step k
182    * \param indx the step
183    * \return a double
184    */
185   double getTk(const unsigned int indx);
186 
187   /** get the TkVector _tkV
188    *  \return a reference to the TkVector _tkV
189    */
getTkVector() const190   inline const TkVector& getTkVector() const { return _tkV; };
191 
192   /** set the TkVector _tkV
193    *  \param newTk the new value for _tkV
194    */
195   void setTkVector(const TkVector& newTk);
196 
197   /** change t0 before the simulation starts (useful for delays)
198    *  \param val the new value for t0
199    */
200   void setT0(double val);
201 
202   // --- OTHER FUNCTIONS ---
203   /** print the discretisation data to the screen
204    */
205   void display() const;
206 
207 };
208 
209 #endif // TIMEDISCRETISATION_H
210