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 "NonSmoothDynamicalSystem.hpp"
19 #include "Interaction.hpp"
20 #include "Relation.hpp"
21 
22 #include <SiconosConfig.h>
23 #include <functional>
24 using namespace std::placeholders;
25 
26 #include <limits>
27 
28 // #define DEBUG_NOCOLOR
29 // #define DEBUG_MESSAGES
30 // #define DEBUG_STDOUT
31 #include "siconos_debug.h"
32 
33 
34 using namespace RELATION;
35 
36 //  constructor
NonSmoothDynamicalSystem(double t0,double T)37 NonSmoothDynamicalSystem::NonSmoothDynamicalSystem(double t0, double T):
38   _t0(t0), _T(T)
39 {
40   // === Builds an empty topology ===
41   _topology.reset(new Topology());
42   // we push a first element in the list to avoid acces to null when
43   // we call --_changeLog.end();
44   _changeLog.push_back(Change(clearTopology));
45   DEBUG_EXPR((--_changeLog.end())->display());
46 
47   // see Simulation::initialize() for an explanation of why we
48   // implement this changelog
49 };
50 
~NonSmoothDynamicalSystem()51 NonSmoothDynamicalSystem::~NonSmoothDynamicalSystem()
52 {
53   clear();
54 }
55 
56 // changelog
display() const57 void NonSmoothDynamicalSystem::Change::display() const
58 {
59   std::cout << "Changes display   " << this <<std::endl;
60   if(typeOfChange == addDynamicalSystem)
61   {
62     std::cout << "typeOfChange : " << typeOfChange << " : addDynamicalSystem" << std::endl;
63   }
64   else if(typeOfChange == rmDynamicalSystem)
65   {
66     std::cout << "typeOfChange : " << typeOfChange << " : rmDynamicalSystem" << std::endl;
67   }
68   else if(typeOfChange == addInteraction)
69   {
70     std::cout << "typeOfChange : " << typeOfChange << " : addInteraction" << std::endl;
71   }
72   else if(typeOfChange == rmInteraction)
73   {
74     std::cout << "typeOfChange : " << typeOfChange << " : rmInteraction" << std::endl;
75   }
76   else if(typeOfChange == clearTopology)
77   {
78     std::cout << "typeOfChange : " << typeOfChange << " : clearTopology" << std::endl;
79   }
80 }
81 
clearChangeLogTo(const ChangeLogIter & it)82 void NonSmoothDynamicalSystem::clearChangeLogTo(const ChangeLogIter& it)
83 {
84   /* Given an interator into the changelog list, clear everything that
85    * comes before it. User must be careful calling this if he has two
86    * simulations, but in the one-simulation case (currently 100% of
87    * cases), calling this will prevent changelog from building up
88    * forever. Important especially for simulations using an
89    * InteractionManager, e.g. mechanics_run.py. */
90   while(_changeLog.begin() != it.it)
91   {
92     _changeLog.pop_front();
93     assert((_changeLog.end() != it.it) && (_changeLog.begin() != _changeLog.end())
94            && "NSDS::clearChangeLogTo: iterator not in list!");
95   }
96 }
97 
98 
99 // === DynamicalSystems management ===
100 
display() const101 void NonSmoothDynamicalSystem::display() const
102 {
103   std::cout << " ===== Non Smooth Dynamical System display ===== " <<std::endl;
104   std::cout << "---> isBVP = " << _BVP <<std::endl;
105   dynamicalSystems()->begin();
106   _topology->indexSet0()->display();
107   std::cout << "---> last change : " <<std::endl;
108   (--_changeLog.end())->display();
109   std::cout << "===================================================" <<std::endl;
110 }
111 
insertDynamicalSystem(SP::DynamicalSystem ds)112 void  NonSmoothDynamicalSystem::insertDynamicalSystem(SP::DynamicalSystem ds)
113 {
114   // some checks here ...
115   if(!ds)
116   {
117     THROW_EXCEPTION("NonSmoothDynamicalSystem::insertDynamicalSystem :: DS is nul");
118   }
119 
120   // Do not insert the same ds several times : results in errors in initialisation process.
121   if(! _topology->hasDynamicalSystem(ds))
122   {
123     _topology->insertDynamicalSystem(ds);
124     _changeLog.push_back(Change(addDynamicalSystem,ds));
125     _mIsLinear = ((ds)->isLinear() && _mIsLinear);
126   }
127 }
128 
removeDynamicalSystem(SP::DynamicalSystem ds)129 void  NonSmoothDynamicalSystem::removeDynamicalSystem(SP::DynamicalSystem ds)
130 {
131   _topology->removeDynamicalSystem(ds);
132   _changeLog.push_back(Change(rmDynamicalSystem,ds));
133 }
removeInteraction(SP::Interaction inter)134 void  NonSmoothDynamicalSystem::removeInteraction(SP::Interaction inter)
135 {
136   _topology->removeInteraction(inter);
137   _changeLog.push_back(Change(rmInteraction,inter));
138 }
139 
link(SP::Interaction inter,SP::DynamicalSystem ds1,SP::DynamicalSystem ds2)140 void NonSmoothDynamicalSystem::link(SP::Interaction inter, SP::DynamicalSystem ds1, SP::DynamicalSystem ds2)
141 {
142   _mIsLinear = (inter->relation()->isLinear() && _mIsLinear);
143   _topology->link(inter, ds1, ds2);
144   _changeLog.push_back(Change(addInteraction,inter));
145 };
146 
147 
clear()148 void NonSmoothDynamicalSystem::clear()
149 {
150   _topology->clear();
151   _changeLog.push_back(Change(clearTopology));
152 }
153 
setSymmetric(bool val)154 void NonSmoothDynamicalSystem::setSymmetric(bool val)
155 {
156   _topology->setSymmetric(val);
157 }
158 
159 
reset()160 void NonSmoothDynamicalSystem::reset()
161 {
162   DynamicalSystemsGraph::VIterator vi;
163   for(vi = dynamicalSystems()->begin(); vi != dynamicalSystems()->end(); ++vi)
164   {
165     dynamicalSystems()->bundle(*vi)->resetNonSmoothPart(1);
166   }
167 }
168 
reset(unsigned int level)169 void NonSmoothDynamicalSystem::reset(unsigned int level)
170 {
171   DynamicalSystemsGraph::VIterator vi;
172   for(vi = dynamicalSystems()->begin(); vi != dynamicalSystems()->end(); ++vi)
173   {
174     dynamicalSystems()->bundle(*vi)->resetNonSmoothPart(level);
175   }
176 }
177 
swapInMemory()178 void NonSmoothDynamicalSystem::swapInMemory()
179 {
180   //could be better to call bind method
181   DynamicalSystemsGraph::VIterator vi;
182   for(vi = dynamicalSystems()->begin(); vi != dynamicalSystems()->end(); ++vi)
183   {
184     dynamicalSystems()->bundle(*vi)->swapInMemory();
185   }
186 }
pushInteractionsInMemory()187 void NonSmoothDynamicalSystem::pushInteractionsInMemory()
188 {
189   // Save Interactions state into Memory.
190 
191   if(_topology->indexSet0()->size() > 0)
192   {
193     // Temp FP : saveInOldVar was called for each osns and each osns call
194     // swapInOldVar for all interactions in the nsds.
195     // ==> let's do it only once, by the simu.
196 
197     InteractionsGraph::VIterator ui, uiend;
198     SP::InteractionsGraph indexSet0 = _topology->indexSet0();
199     for(std::tie(ui, uiend) = indexSet0->vertices(); ui != uiend; ++ui)
200     {
201       indexSet0->bundle(*ui)->swapInOldVariables();
202       indexSet0->bundle(*ui)->swapInMemory();
203     }
204   }
205 }
206 
updateInput(double time,unsigned int level)207 void NonSmoothDynamicalSystem::updateInput(double time, unsigned int level)
208 {
209 
210   DEBUG_BEGIN("Nonsmoothdynamicalsystem::updateInput(double time, unsigned int level)\n");
211   DEBUG_PRINTF("with level = %i\n", level);
212 
213 
214   // To compute input(level) (ie with lambda[level]) for all Interactions.
215   //  assert(level>=0);
216 
217   // Set dynamical systems non-smooth part to zero.
218   reset(level);
219 
220   // We compute input using lambda(level).
221   InteractionsGraph::VIterator ui, uiend;
222   SP::Interaction inter;
223   SP::InteractionsGraph indexSet0 = _topology->indexSet0();
224   for(std::tie(ui, uiend) = indexSet0->vertices(); ui != uiend; ++ui)
225   {
226     inter = indexSet0->bundle(*ui);
227     assert(inter->lowerLevelForInput() <= level);
228     assert(inter->upperLevelForInput() >= level);
229     inter->computeInput(time, level);
230   }
231 
232   DEBUG_END("Nonsmoothdynamicalsystem::updateInput(double time, unsigned int level)\n");
233 
234 }
235 
236 
updateOutput(double time,unsigned int level)237 void NonSmoothDynamicalSystem::updateOutput(double time, unsigned int level)
238 {
239 
240   // To compute output(level) (ie with y[level]) for all Interactions.
241   //  assert(level>=0);
242 
243   DEBUG_BEGIN("NonSmoothDynamicalSystem::updateOutput(unsigned int level)\n");
244   DEBUG_PRINTF("with level = %i\n", level);
245   InteractionsGraph::VIterator ui, uiend;
246   SP::Interaction inter;
247   SP::InteractionsGraph indexSet0 = _topology->indexSet0();
248   for(std::tie(ui, uiend) = indexSet0->vertices(); ui != uiend; ++ui)
249   {
250     inter = indexSet0->bundle(*ui);
251     assert(inter->lowerLevelForOutput() <= level);
252     assert(inter->upperLevelForOutput() >= level);
253     inter->computeOutput(time, level);
254   }
255   DEBUG_END("NonSmoothDynamicalSystem::updateOutput(unsigned int level)\n");
256 }
257 
258 
updateOutput(double time,unsigned int level_min,unsigned int level_max)259 void NonSmoothDynamicalSystem::updateOutput(double time, unsigned int level_min, unsigned int level_max)
260 {
261 
262   // To compute output(level) (ie with y[level]) for all Interactions in I0
263   // and for a range of levels in a single pass through I0.
264   //  assert(level>=0);
265 
266   InteractionsGraph::VIterator ui, uiend;
267   SP::Interaction inter;
268   SP::InteractionsGraph indexSet0 = _topology->indexSet0();
269   for(std::tie(ui, uiend) = indexSet0->vertices(); ui != uiend; ++ui)
270   {
271     inter = indexSet0->bundle(*ui);
272     assert(inter->lowerLevelForOutput() <= level_max);
273     assert(inter->upperLevelForOutput() >= level_min);
274     for(unsigned int level = level_min; level<=level_max; ++level)
275       inter->computeOutput(time, level);
276   }
277 }
278 
computeInteractionJacobians(double time)279 void NonSmoothDynamicalSystem::computeInteractionJacobians(double time)
280 {
281 
282   DEBUG_BEGIN("NonSmoothDynamicalSystem::computeInteractionJacobians(double time)\n");
283   InteractionsGraph::VIterator ui, uiend;
284   SP::Interaction inter;
285   SP::InteractionsGraph indexSet0 = _topology->indexSet0();
286   for(std::tie(ui, uiend) = indexSet0->vertices(); ui != uiend; ++ui)
287   {
288     inter = indexSet0->bundle(*ui);
289     inter->relation()->computeJach(time, *inter);
290     inter->relation()->computeJacg(time, *inter);
291   }
292   DEBUG_END("NonSmoothDynamicalSystem::computeInteractionJacobians(double time)\n");
293 }
294 
computeInteractionJacobians(double time,InteractionsGraph & indexSet)295 void NonSmoothDynamicalSystem::computeInteractionJacobians(double time, InteractionsGraph& indexSet)
296 {
297   DEBUG_BEGIN("NonSmoothDynamicalSystem::computeInteractionJacobians(double time)\n");
298   InteractionsGraph::VIterator ui, uiend;
299   SP::Interaction inter;
300   for(std::tie(ui, uiend) = indexSet.vertices(); ui != uiend; ++ui)
301   {
302     inter = indexSet.bundle(*ui);
303     inter->relation()->computeJach(time, *inter);
304     inter->relation()->computeJacg(time, *inter);
305   }
306   DEBUG_END("NonSmoothDynamicalSystem::computeInteractionJacobians(double time)\n");
307 }
308 
visitDynamicalSystems(SP::SiconosVisitor visitor)309 void NonSmoothDynamicalSystem::visitDynamicalSystems(SP::SiconosVisitor visitor)
310 {
311   DynamicalSystemsGraph &dsg = *dynamicalSystems();
312   DynamicalSystemsGraph::VIterator dsi, dsiend;
313   std::tie(dsi, dsiend) = dsg.vertices();
314   for(; dsi != dsiend; ++dsi)
315   {
316     dsg.bundle(*dsi)->acceptSP(visitor);
317   }
318 }
dynamicalSystemsVector() const319 std::vector<SP::DynamicalSystem> NonSmoothDynamicalSystem::dynamicalSystemsVector() const
320 {
321     std::vector<SP::DynamicalSystem> dynamicalSystemsVector;
322     DynamicalSystemsGraph &dsg = *dynamicalSystems();
323     DynamicalSystemsGraph::VIterator dsi, dsiend;
324     std::tie(dsi, dsiend) = dsg.vertices();
325     for(; dsi != dsiend; ++dsi)
326     {
327       dynamicalSystemsVector.push_back(dsg.bundle(*dsi));
328     }
329 
330     return dynamicalSystemsVector;
331   }
332