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 #include "FirstOrderLinearR.hpp"
19 #include "Interaction.hpp"
20 #include "PluggedObject.hpp"
21 #include "SimpleMatrix.hpp"
22 #include "BlockVector.hpp"
23 #include "SimulationGraphs.hpp"
24 #include "SiconosAlgebraProd.hpp" // for matrix-vector prod
25 
26 #include <iostream>
27 
28 // #define DEBUG_NOCOLOR
29 // #define DEBUG_STDOUT
30 // #define DEBUG_MESSAGES
31 #include "siconos_debug.h"
32 using namespace RELATION;
33 
FirstOrderLinearR()34 FirstOrderLinearR::FirstOrderLinearR():
35   FirstOrderR(LinearR)
36 {
37   ;
38 }
39 
40 // Constructor with C and B plug-in names
FirstOrderLinearR(const std::string & Cname,const std::string & Bname)41 FirstOrderLinearR::FirstOrderLinearR(const std::string& Cname, const std::string& Bname):
42   FirstOrderR(LinearR)
43 {
44   // Warning: we cannot allocate memory for C/D matrix since no interaction
45   // is connected to the relation. This will be done during initialize.
46   // We only set the name of the plugin-function and connect it to the user-defined function.
47   _pluginJachx->setComputeFunction(Cname);
48   _pluginJacglambda->setComputeFunction(Bname);
49 }
50 
51 // Constructor from a complete set of data (plugin)
FirstOrderLinearR(const std::string & Cname,const std::string & Dname,const std::string & Fname,const std::string & Ename,const std::string & Bname)52 FirstOrderLinearR::FirstOrderLinearR(const std::string& Cname, const std::string& Dname, const std::string& Fname, const std::string& Ename, const std::string& Bname): FirstOrderR(LinearR)
53 {
54   _pluginJachx->setComputeFunction(Cname);
55   _pluginJachlambda->setComputeFunction(Dname);
56   _pluginJacglambda->setComputeFunction(Bname);
57   _pluginf->setComputeFunction(Fname);
58   _plugine->setComputeFunction(Ename);
59 }
60 
61 // Minimum data (C, B as pointers) constructor
FirstOrderLinearR(SP::SimpleMatrix C,SP::SimpleMatrix B)62 FirstOrderLinearR::FirstOrderLinearR(SP::SimpleMatrix C, SP::SimpleMatrix B):
63   FirstOrderR(LinearR)
64 {
65   _C = C;
66   _B = B;
67 }
68 
69 // // Constructor from a complete set of data
FirstOrderLinearR(SP::SimpleMatrix C,SP::SimpleMatrix D,SP::SimpleMatrix F,SP::SiconosVector E,SP::SimpleMatrix B)70 FirstOrderLinearR::FirstOrderLinearR(SP::SimpleMatrix C, SP::SimpleMatrix D, SP::SimpleMatrix F, SP::SiconosVector E, SP::SimpleMatrix B):
71   FirstOrderR(LinearR)
72 {
73   _C = C;
74   _B = B;
75   _D = D;
76   _F = F;
77   _e = E;
78 }
79 
initialize(Interaction & inter)80 void FirstOrderLinearR::initialize(Interaction& inter)
81 {
82 
83   FirstOrderR::initialize(inter);
84 
85   // get interesting size
86   unsigned int sizeY = inter.dimension();
87   unsigned int sizeX = inter.getSizeOfDS();
88 
89   VectorOfBlockVectors& DSlink = inter.linkToDSVariables();
90   unsigned int sizeZ = DSlink[FirstOrderR::z]->size();
91   VectorOfSMatrices& relationMat = inter.relationMatrices();
92   VectorOfVectors & relationVec= inter.relationVectors();
93 
94   if(!_C && _pluginJachx->fPtr)
95     relationMat[FirstOrderR::mat_C].reset(new SimpleMatrix(sizeY, sizeX));
96   if(!_D && _pluginJachlambda->fPtr)
97     relationMat[FirstOrderR::mat_D].reset(new SimpleMatrix(sizeY, sizeY));
98   if(!_B && _pluginJacglambda->fPtr)
99     relationMat[FirstOrderR::mat_B].reset(new SimpleMatrix(sizeX, sizeY));
100   if(!_F && _pluginf->fPtr)
101     relationMat[FirstOrderR::mat_F].reset(new SimpleMatrix(sizeY, sizeZ));
102   if(!_e && _plugine->fPtr)
103     relationVec[FirstOrderR::e].reset(new SiconosVector(sizeY));
104 
105   checkSize(inter);
106 }
107 
108 
checkSize(Interaction & inter)109 void FirstOrderLinearR::checkSize(Interaction& inter)
110 {
111 
112   VectorOfBlockVectors& DSlink = inter.linkToDSVariables();
113 
114   // get interesting size
115   unsigned int sizeY = inter.dimension();
116   unsigned int sizeX = inter.getSizeOfDS();
117   unsigned int sizeZ = DSlink[FirstOrderR::z]->size();
118 
119   // Check if various operators sizes are consistent.
120   // Reference: interaction.
121 
122   if(_C)
123   {
124     if(_C->size(0) == 0)
125       _C->resize(sizeX, sizeY);
126     else
127       assert((_C->size(0) == sizeY && _C->size(1) == sizeX) && "FirstOrderLinearR::initialize , inconsistent size between C and Interaction.");
128   }
129   if(_B)
130   {
131     if(_B->size(0) == 0)
132       _B->resize(sizeY, sizeX);
133     else
134       assert((_B->size(1) == sizeY && _B->size(0) == sizeX) && "FirstOrderLinearR::initialize , inconsistent size between B and interaction.");
135   }
136   // C and B are the minimum inputs. The others may remain null.
137 
138   if(_D)
139   {
140     if(_D->size(0) == 0)
141       _D->resize(sizeY, sizeY);
142     else
143       assert((_D->size(0) == sizeY || _D->size(1) == sizeY) && "FirstOrderLinearR::initialize , inconsistent size between C and D.");
144   }
145 
146   if(_F)
147   {
148     if(_F->size(0) == 0)
149       _F->resize(sizeY, sizeZ);
150     else
151       assert(((_F->size(0) == sizeY) && (_F->size(1) == sizeZ)) && "FirstOrderLinearR::initialize , inconsistent size between C and F.");
152   }
153 
154   if(_e)
155   {
156     if(_e->size() == 0)
157       _e->resize(sizeY);
158     else
159       assert(_e->size() == sizeY && "FirstOrderLinearR::initialize , inconsistent size between C and e.");
160   }
161 }
computeC(double time,BlockVector & z,SimpleMatrix & C)162 void FirstOrderLinearR::computeC(double time, BlockVector& z, SimpleMatrix& C)
163 {
164   if(_pluginJachx->fPtr)
165   {
166     auto zp = z.prepareVectorForPlugin();
167     ((FOMatPtr1)(_pluginJachx->fPtr))(time, C.size(0), C.size(1), &(C)(0, 0), zp->size(), &(*zp)(0));
168     z = *zp;
169   }
170 }
171 
computeD(double time,BlockVector & z,SimpleMatrix & D)172 void FirstOrderLinearR::computeD(double time, BlockVector& z, SimpleMatrix& D)
173 {
174   if(_pluginJachlambda->fPtr)
175   {
176     auto zp = z.prepareVectorForPlugin();
177     ((FOMatPtr1)(_pluginJachlambda->fPtr))(time, D.size(0), D.size(1), &(D)(0, 0), zp->size(), &(*zp)(0));
178     z = *zp;
179   }
180 }
181 
computeF(double time,BlockVector & z,SimpleMatrix & F)182 void FirstOrderLinearR::computeF(double time, BlockVector& z, SimpleMatrix& F)
183 {
184   if(_pluginf->fPtr)
185   {
186     auto zp = z.prepareVectorForPlugin();
187     ((FOMatPtr1)(_pluginf->fPtr))(time, F.size(0), F.size(1), &(F)(0, 0), zp->size(), &(*zp)(0));
188     z = *zp;
189   }
190 }
191 
computee(double time,BlockVector & z,SiconosVector & e)192 void FirstOrderLinearR::computee(double time, BlockVector& z, SiconosVector& e)
193 {
194 
195   if(_plugine->fPtr)
196   {
197     auto zp = z.prepareVectorForPlugin();
198     ((FOVecPtr) _plugine->fPtr)(time, e.size(), &(e)(0), zp->size(), &(*zp)(0));
199     z = *zp;
200   }
201 }
202 
computeB(double time,BlockVector & z,SimpleMatrix & B)203 void FirstOrderLinearR::computeB(double time, BlockVector& z, SimpleMatrix& B)
204 {
205   if(_pluginJacglambda->fPtr)
206   {
207     auto zp = z.prepareVectorForPlugin();
208     ((FOMatPtr1) _pluginJacglambda->fPtr)(time, B.size(0), B.size(1), &(B)(0, 0), zp->size(), &(*zp)(0));
209     z = *zp;
210   }
211 }
212 
computeh(double time,const BlockVector & x,const SiconosVector & lambda,BlockVector & z,SiconosVector & y)213 void FirstOrderLinearR::computeh(double time, const BlockVector& x, const SiconosVector& lambda,
214                                  BlockVector& z, SiconosVector& y)
215 {
216 
217   y.zero();
218   if(_pluginJachx->fPtr)
219   {
220     if(!_C)
221       _C.reset(new SimpleMatrix(y.size(),x.size()));
222     computeC(time, z, *_C);
223   }
224   if(_pluginJachlambda->fPtr)
225   {
226     if(!_D)
227       _D.reset(new SimpleMatrix(y.size(),lambda.size()));
228     computeD(time, z, *_D);
229   }
230   if(_pluginf->fPtr)
231   {
232     if(!_F)
233       _F.reset(new SimpleMatrix(y.size(),z.size()));
234     computeF(time, z, *_F);
235   }
236   if(_plugine->fPtr)
237   {
238     if(!_e)
239       _e.reset(new SiconosVector(y.size()));
240     computee(time, z, *_e);
241   }
242 
243   if(_C)
244     prod(*_C, x, y, false);
245 
246   if(_D)
247     prod(*_D, lambda, y, false);
248 
249   if(_e)
250     y += *_e;
251 
252   if(_F)
253     prod(*_F, z, y, false);
254 
255 }
256 
computeOutput(double time,Interaction & inter,unsigned int level)257 void FirstOrderLinearR::computeOutput(double time, Interaction& inter, unsigned int level)
258 {
259   DEBUG_BEGIN("FirstOrderLinearR::computeOutput \n");
260   VectorOfBlockVectors& DSlink = inter.linkToDSVariables();
261   BlockVector& z = *DSlink[FirstOrderR::z];
262   BlockVector& x = *DSlink[FirstOrderR::x];
263 
264   SiconosVector& y = *inter.y(level);
265   SiconosVector& lambda = *inter.lambda(level);
266 
267   computeh(time, x, lambda, z, y);
268 
269   DEBUG_END("FirstOrderLinearR::computeOutput \n");
270 }
271 
computeg(double time,const SiconosVector & lambda,BlockVector & z,BlockVector & r)272 void FirstOrderLinearR::computeg(double time, const SiconosVector& lambda, BlockVector& z, BlockVector& r)
273 {
274   if(_pluginJacglambda->fPtr)
275   {
276     if(!_B)
277       _B.reset(new SimpleMatrix(r.size(),lambda.size()));
278     computeB(time, z, *_B);
279   }
280 
281   prod(*_B, lambda, r, false);
282 
283 }
284 
285 
computeInput(double time,Interaction & inter,unsigned int level)286 void FirstOrderLinearR::computeInput(double time, Interaction& inter, unsigned int level)
287 {
288 
289 
290   SiconosVector& lambda = *inter.lambda(level);
291   VectorOfBlockVectors& DSlink = inter.linkToDSVariables();
292   BlockVector& z = *DSlink[FirstOrderR::z];
293   computeg(time, lambda, z, *DSlink[FirstOrderR::r]);
294 }
295 
296 
display() const297 void FirstOrderLinearR::display() const
298 {
299   std::cout << " ===== Linear Time Invariant relation display ===== " <<std::endl;
300   std::cout << "| C " <<std::endl;
301   if(_C) _C->display();
302   else std::cout << "->nullptr" <<std::endl;
303   std::cout << "| D " <<std::endl;
304   if(_D) _D->display();
305   else std::cout << "->nullptr" <<std::endl;
306   std::cout << "| F " <<std::endl;
307   if(_F) _F->display();
308   else std::cout << "->nullptr" <<std::endl;
309   std::cout << "| e " <<std::endl;
310   if(_e) _e->display();
311   else std::cout << "->nullptr" <<std::endl;
312   std::cout << "| B " <<std::endl;
313   if(_B) _B->display();
314   else std::cout << "->nullptr" <<std::endl;
315   std::cout << " ================================================== " <<std::endl;
316 }
317