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
19 #include "FirstOrderNonLinearDS.hpp"
20 #include "PluginTypes.hpp"
21
22 // #define DEBUG_MESSAGES
23 // #define DEBUG_STDOUT
24 #include "siconos_debug.h"
25 #include <iostream>
26
27 // ===== CONSTRUCTORS =====
28
_init(SP::SiconosVector initial_state)29 void FirstOrderNonLinearDS::_init(SP::SiconosVector initial_state)
30 {
31 DEBUG_PRINT("internal _init from FirstOrderNonLinearDS\n");
32
33 // Memory allocation only for required parts of the DS:
34 // state (initial and current). All other operators are optional and
35 // allocated with 'set'-like methods.
36 assert(_n > 0 && "dynamical system dimension should be greater than 0.");
37 // Set initial conditions
38 _x0 = initial_state;
39
40 // == Current state ==
41 // x is composed of two blocks of size n, x[0] = \f$ x \f$ and x[1]=\f$ \dot x \f$.
42 // x[0] initialized with x0.
43 // _x.resize(2); done in base class constructor.
44 _x[0].reset(new SiconosVector(*_x0));
45 _x[1].reset(new SiconosVector(_n));
46 _r.reset(new SiconosVector(_n)); // FP: move this to initializeNonSmoothInput?
47 _zeroPlugin();
48 }
49
50 // From a minimum set of data
FirstOrderNonLinearDS(SP::SiconosVector initial_state)51 FirstOrderNonLinearDS::FirstOrderNonLinearDS(SP::SiconosVector initial_state):
52 DynamicalSystem(initial_state->size())
53 {
54 _init(initial_state);
55 // dot x = r
56 }
57
58 // From a minimum set of data
FirstOrderNonLinearDS(SP::SiconosVector initial_state,const std::string & fPlugin,const std::string & jacobianfxPlugin)59 FirstOrderNonLinearDS::FirstOrderNonLinearDS(SP::SiconosVector initial_state, const std::string& fPlugin, const std::string& jacobianfxPlugin):
60 DynamicalSystem(initial_state->size())
61 {
62 _init(initial_state);
63 // == f and its jacobian ==
64 // Allocation and link with the plug-in
65 setComputeFFunction(SSLH::getPluginName(fPlugin), SSLH::getPluginFunctionName(fPlugin));
66 setComputeJacobianfxFunction(SSLH::getPluginName(jacobianfxPlugin), SSLH::getPluginFunctionName(jacobianfxPlugin));
67 // dot x = f(x, z , t) + r
68 }
69
70 // Copy constructor
FirstOrderNonLinearDS(const FirstOrderNonLinearDS & FONLDS)71 FirstOrderNonLinearDS::FirstOrderNonLinearDS(const FirstOrderNonLinearDS & FONLDS): DynamicalSystem(FONLDS)
72 {
73 _zeroPlugin();
74
75 if(FONLDS.M())
76 _M.reset(new SimpleMatrix(*(FONLDS.M())));
77 if(FONLDS.f())
78 _f.reset(new SiconosVector(*(FONLDS.f())));
79 if(FONLDS.jacobianfx())
80 _jacobianfx.reset(new SimpleMatrix(*(FONLDS.jacobianfx())));
81 if(FONLDS.getPluginF())
82 _pluginf.reset(new PluggedObject(*(FONLDS.getPluginF())));
83 if(FONLDS.getPluginJacxf())
84 _pluginJacxf.reset(new PluggedObject(*(FONLDS.getPluginJacxf())));
85 if(FONLDS.getPluginM())
86 _pluginM.reset(new PluggedObject(*(FONLDS.getPluginM())));
87 if(FONLDS.invM())
88 _invM.reset(new SimpleMatrix(*(FONLDS.invM())));
89
90 // Memory stuff to me moved to graph/osi
91 if(FONLDS.fold())
92 _fold.reset(new SiconosVector(*(FONLDS.fold())));
93 _rMemory = FONLDS.rMemory();
94 }
95
96
_zeroPlugin()97 void FirstOrderNonLinearDS::_zeroPlugin()
98 {
99 _pluginf.reset(new PluggedObject());
100 _pluginJacxf.reset(new PluggedObject());
101 _pluginM.reset(new PluggedObject());
102 }
103
initRhs(double time)104 void FirstOrderNonLinearDS::initRhs(double time)
105 {
106 computeRhs(time);
107
108
109 // !! jacxRhs must always be allocated (we must check this?)!!
110 if(! _jacxRhs) // if not allocated with a set or anything else
111 {
112 if(_jacobianfx && ! _M) // if M is not defined, then jacobianfx = jacobianRhsx, no memory allocation for that one.
113 _jacxRhs = _jacobianfx;
114 else// if (_jacobianfx && _M) or if(!jacobianRhsx)
115 _jacxRhs.reset(new SimpleMatrix(_n, _n));
116
117 // else no allocation, jacobian is equal to 0.
118 }
119 computeJacobianRhsx(time);
120 }
121
updatePlugins(double time)122 void FirstOrderNonLinearDS::updatePlugins(double time)
123 {
124 if(_M)
125 computeM(time);
126 if(_f)
127 {
128 computef(time, _x[0]);
129 computeJacobianfx(time, _x[0]);
130 }
131 }
132
initializeNonSmoothInput(unsigned int level)133 void FirstOrderNonLinearDS::initializeNonSmoothInput(unsigned int level)
134 {
135 /**\warning V.A. _r should be initialized here and not in the constructor
136 * The level should also be used if we need more that one _r
137 */
138 if(!_r)
139 _r.reset(new SiconosVector(_n));
140 }
141
142
143
144 // ===== MEMORY MANAGEMENT FUNCTIONS =====
145
initMemory(unsigned int steps)146 void FirstOrderNonLinearDS::initMemory(unsigned int steps)
147 {
148 DynamicalSystem::initMemory(steps);
149
150 if(_f && !_fold)
151 _fold.reset(new SiconosVector(_n));
152
153 if(steps == 0)
154 std::cout << "Warning : FirstOrderNonLinearDS::initMemory with size equal to zero" <<std::endl;
155 else
156 _rMemory.setMemorySize(steps, _n);
157 }
158
swapInMemory()159 void FirstOrderNonLinearDS::swapInMemory()
160 {
161 DEBUG_BEGIN("void FirstOrderNonLinearDS::swapInMemory()\n");
162 _xMemory.swap(*_x[0]);
163 _rMemory.swap(*_r);
164 if(_f)
165 {
166 assert(_fold);
167 *_fold = *_f;
168 }
169 DEBUG_EXPR(_xMemory.display());
170 DEBUG_END("void FirstOrderNonLinearDS::swapInMemory()\n");
171 }
172
173 // ===== COMPUTE PLUGINS FUNCTIONS =====
174
setComputeMFunction(const std::string & pluginPath,const std::string & functionName)175 void FirstOrderNonLinearDS::setComputeMFunction(const std::string& pluginPath, const std::string& functionName)
176 {
177 if(!_M)
178 _M.reset(new SimpleMatrix(_n, _n));
179
180 _pluginM->setComputeFunction(pluginPath, functionName);
181 }
182
setComputeMFunction(FPtr1 fct)183 void FirstOrderNonLinearDS::setComputeMFunction(FPtr1 fct)
184 {
185 if(!_M)
186 _M.reset(new SimpleMatrix(_n, _n));
187
188 _pluginM->setComputeFunction((void *)fct);
189 }
190
setComputeFFunction(const std::string & pluginPath,const std::string & functionName)191 void FirstOrderNonLinearDS::setComputeFFunction(const std::string& pluginPath, const std::string& functionName)
192 {
193 if(!_f)
194 _f.reset(new SiconosVector(_n));
195
196 _pluginf->setComputeFunction(pluginPath, functionName);
197 }
198
setComputeFFunction(FPtr1 fct)199 void FirstOrderNonLinearDS::setComputeFFunction(FPtr1 fct)
200 {
201 if(!_f)
202 _f.reset(new SiconosVector(_n));
203 _pluginf->setComputeFunction((void *)fct);
204 }
205
setComputeJacobianfxFunction(const std::string & pluginPath,const std::string & functionName)206 void FirstOrderNonLinearDS::setComputeJacobianfxFunction(const std::string& pluginPath, const std::string& functionName)
207 {
208 if(!_jacobianfx)
209 _jacobianfx.reset(new SimpleMatrix(_n, _n));
210 _pluginJacxf->setComputeFunction(pluginPath, functionName);
211 }
212
setComputeJacobianfxFunction(FPtr1 fct)213 void FirstOrderNonLinearDS::setComputeJacobianfxFunction(FPtr1 fct)
214 {
215 if(!_jacobianfx)
216 _jacobianfx.reset(new SimpleMatrix(_n, _n));
217 _pluginJacxf->setComputeFunction((void *)fct);
218 }
219
computeM(double time)220 void FirstOrderNonLinearDS::computeM(double time)
221 {
222 if(_pluginM->fPtr && _M)
223 {
224 ((FNLDSPtrfct)_pluginM->fPtr)(time, _n, &((*(_x[0]))(0)), &(*_M)(0, 0), _z->size(), &(*_z)(0));
225 }
226 }
227
computef(double time,SP::SiconosVector state)228 void FirstOrderNonLinearDS::computef(double time, SP::SiconosVector state)
229 {
230 if(_f && _pluginf->fPtr)
231 ((FNLDSPtrfct)_pluginf->fPtr)(time, _n, &(*state)(0), &(*_f)(0), _z->size(), &(*_z)(0));
232 }
233
computeJacobianfx(double time,SP::SiconosVector state)234 void FirstOrderNonLinearDS::computeJacobianfx(double time, SP::SiconosVector state)
235 {
236 if(_jacobianfx && _pluginJacxf->fPtr)
237 ((FNLDSPtrfct)_pluginJacxf->fPtr)(time, _n, state->getArray(), &(*_jacobianfx)(0, 0), _z->size(), _z->getArray());
238 }
239
computeRhs(double time)240 void FirstOrderNonLinearDS::computeRhs(double time)
241 {
242 // second argument is useless at the time - Used in derived classes
243
244 // compute rhs = M-1*( f + r ).
245
246 *_x[1] = *_r; // Warning: p update is done in Interactions/Relations
247
248 if(_f)
249 {
250 computef(time, _x[0]);
251 *(_x[1]) += *_f;
252 }
253
254 if(_M)
255 {
256 computeM(time);
257 // allocate invM at the first call of the present function
258 if(! _invM)
259 _invM.reset(new SimpleMatrix(*_M));
260 else if(_pluginM->fPtr) // if M is plugged, invM must be updated
261 *_invM = *_M;
262
263 _invM->Solve(*_x[1]);
264 }
265 }
266
computeJacobianRhsx(double time)267 void FirstOrderNonLinearDS::computeJacobianRhsx(double time)
268 {
269 // second argument is useless at the time - Used in derived classes
270
271 // compute jacobian of rhs according to x, = M-1(jacobianfx + jacobianX(T.u))
272 // At the time, second term is set to zero.
273 //assert(!_pluginJacxf->fPtr && "FirstOrderNonLinearDS::computeJacobianRhsx: there is no plugin to compute the jacobian of f");
274
275 computeJacobianfx(time, _x[0]);
276 // solve M*jacobianXRhS = jacobianfx
277 if(_M && _jacobianfx)
278 {
279 *_jacxRhs = *_jacobianfx;
280 // copy _M into _invM for LU-factorisation, at the first call of this function.
281
282 computeM(time);
283
284 if(! _invM)
285 _invM.reset(new SimpleMatrix(*_M));
286 else if(_pluginM->fPtr) // if M is plugged, invM must be updated
287 *_invM = *_M;
288 _invM->Solve(*_jacxRhs);
289 }
290 // else jacobianRhsx = jacobianfx, pointers equality set in initRhs
291
292 }
293
294 // ===== MISCELLANEOUS ====
295
display(bool brief) const296 void FirstOrderNonLinearDS::display(bool brief) const
297 {
298 std::cout << " =====> First Order Non Linear DS (number: " << _number << ")." <<std::endl;
299 std::cout << "- n (size) : " << _n <<std::endl;
300 std::cout << "- x " <<std::endl;
301 if(_x[0]) _x[0]->display();
302 else std::cout << "-> nullptr" <<std::endl;
303 std::cout << "- x0 " <<std::endl;
304 if(_x0) _x0->display();
305 else std::cout << "-> nullptr" <<std::endl;
306 std::cout << "- M: " <<std::endl;
307 if(_M) _M->display();
308 else std::cout << "-> nullptr" <<std::endl;
309 std::cout << " ============================================" <<std::endl;
310 }
311
resetAllNonSmoothParts()312 void FirstOrderNonLinearDS::resetAllNonSmoothParts()
313 {
314 _r->zero();
315 }
316
resetNonSmoothPart(unsigned int level)317 void FirstOrderNonLinearDS::resetNonSmoothPart(unsigned int level)
318 {
319 // V.A. 28/05/2012: for the moment various level are not used for First Order systems
320 //assert(0);
321 _r->zero();
322 }
323