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