File: cpp_reminder.rst

package info (click to toggle)
siconos 4.3.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 82,496 kB
  • sloc: cpp: 159,693; ansic: 108,665; fortran: 33,248; python: 20,709; xml: 1,244; sh: 385; makefile: 226
file content (341 lines) | stat: -rw-r--r-- 11,455 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
.. _cpp_reminder:


C++ Refresher
=============

C++ is the basic language of Siconos input files, thus you need at least a basic knowledge of C++.
This topic is covered by many books or tutorials, try for example :cite:`eckel_cpp`.
However, you can find in this first section the main C++ commands you need to know to write a first input file.

This page presents some basic commands and things you need to know to write a first C++ driver for your simulation.

   Note: In recent versions it is possible to design complete Siconos
   simulations using the Python programming language.  If you are
   using the Python interface, most of this document can be ignored.
   However, the Python interface uses the same class names.  See the
   :ref:`siconos_python_reference`.

Building/destroying and using objects
-------------------------------------

.. highlight:: c++

To describe your problem, you will mainly need to build pointers to objects.
Siconos use smart pointers so you do not have to bother with deletion.
The namespace SP enclose typedefs of all Siconos classes as smart pointers.

So to build an object of class *CHILD* derived from base class *BASE*, the syntax will be::

  SP::BASE my_object_name(new CHILD(some args ...)

For example, suppose you want to build a LagrangianDS, which belongs
to the base class DynamicalSystem, then do::

  SP::DynamicalSystem nameOfMyDS(new LagrangianDS(someParameters));

*new* call will reserve memory and build the object.

For each object, different types of constructors may be available. For an
exhaustive list see :ref:`siconos_api_reference`.

Members/Methods access
----------------------

The access to the methods of the objects is done thanks to "*" or "->"::
  
  nameOfMyDS->getType(); // return the type of the DynamicalSystem
  (*nameOfMyDS).getType(); // Same thing. 

Matrices and vectors handling
-----------------------------

The basic classes available in the platform to deal with vectors and matrices are:

* :class:`SiconosVector` : vector of double, can be dense or sparse.
* :class:`BlockVector` : vector of :class:`SiconosVector`
* :class:`SimpleMatrix` : matrix of double, can be dense, sparse, triangular, banded, symmetric, zero or identity.
* :class:`BlockMatrix` : matrix of :class:`SimpleMatrix` 

All these objects are just an interface to `Boost Ublas library <http://www.boost.org/libs/numeric/ublas/doc/index.htm>`_ vector and matrix. 

Notice that BlockVector or BlockMatrix are no more that a collection of pointers to SiconosVector or SimpleMatrix.
Then in most cases, to build such an object, you just need to insert some existing objects.
The usual ways of construction are described below.

::

   # build a dense vector of 4 elements
   SP::SiconosVector v1(new SimpleVector(4));

   # build a sparse vector of size 4
   SP::SiconosVector vsparse(new SimpleVector(4, Siconos::SPARSE)

   # build a block vector, which contains 3 dense blocks of size 5
   SP::BlockVector vblock(new BlockVector(3, 5));

   # build a block vector, which contains 2 sparse
   SP::SiconosVector v2(new SiconosVector(4, Siconos::SPARSE)
   SP::SiconosVector v3(new SiconosVector(7, Siconos::SPARSE)
   SP::BlockVector vblock(new BlockVector(v2, v3));

   int row = 3, col = 3;
   // row X col Dense matrix:
   SP::SiconosMatrix m(new SimpleMatrix(row,col));
   // row X col matrix, all elements initialized with a scalar value:
   double a = 4.4;
   SP::SiconosMatrix m(new SimpleMatrix(row,col,a));
   // row X row Symmetric matrix:
   SP::SiconosMatrix m(new SimpleMatrix(row,row, Siconos::SYMMETRIC));
   // Read from a file
   SP::SiconosMatrix m2(new SimpleMatrix("mat.dat",1)); // 1: ascii, 0:binary
   // Build an empty vector and insert some existing vectors.
   SP::BlockVector V0(new BlockVector());
   // Pointer insertion: 
   V0->insertPtr(v1); 
   // V0 has now one block equal to v1.
   // warning: because of pointer equality, 
   // v1 and (*V0)[0] represent the same object
   // and thus have the same memory location.
   // Copy of an existing vector:
   V0->insert(*v2); 
   // A new block has been created in V0
   // and v2 has been copied into this block.
   // Thus v2 and (*V0)[1] contain the same 
   // elements but are two different objects.

Note that a BlockVector can also contain some other BlockVector::

  SP::BlockVector V1(new BlockVector());
  V1->insertPtr(V0);
  V1->insertPtr(v1);
  
V1 has now two blocks: the first one is a block of two blocks and the second is equal to v1.

::

   // m1 ... m4 some SP::SiconosMatrix
   SP::SiconosMatrix M(new BlockMatrix(m1,m2,m3,m4));
   // M is a 2X2 blocks matrix 
   // (first row: m1, m2, second: m3, m4).

   
Keywords for constructors, in Siconos namespace: DENSE (default), TRIANGULAR, SYMMETRIC, SPARSE, BANDED, ZERO, IDENTITY.


Check the complete list of available constructors in reference documentation of each class.


Read/write vectors and matrices from/to file
""""""""""""""""""""""""""""""""""""""""""""

This is done using :class:`ioVector` and :class:`ioMatrix` classes.

::

   // Read/write vector/matrix from/to file
   // v is a vector, m a matrix
   ioVector myOutput ("MyData","ascii"); 
   myOutput.read(v); // read v from file MyData
   ioMatrix myMat("outMat","ascii");
   myMat.write(m); // Write m in file outMat
   
Input/Ouput Files format:

On the first line, the dimensions, with space as separator. Then the data. 

Example, for a 2-rows, 3-columns matrix:

::

   2 3
   1 2 3
   4 5 6

However, if you give as a second argument to write function "noDim", the first line with dimensions will not be written.

Methods and operations on matrices and vectors
""""""""""""""""""""""""""""""""""""""""""""""

Important note: in many of the operators described below, a boolean argument "init" can be set. If equal to true (default value) then the operator used "=" and if set to 
false, "+=".

::
   
   v->size() // return the size of the vector
   m->size(0); // number of rows in the matrix
   m->size(1), // number of columns
   m->resize(a,b); // resize m, available also for vectors

   // To compute C = A*B
   prod(A,B,C,true);
   // or
   prod(A,B,C);

   // To compute C += A*B
   prod(A,B,C,false);

   //Single elements access or assignment: operator "()" or \e get/setValue functions.
   SP::SiconosVector v(new SimpleVector(3)); // v = [0 0 0]
   SimpleVector w(4);  			 // w = [0 0 0 0]
   (*v)(0) = 4;				 // v = [4 0 0] 
   // equivalent to:
   v->setValue(0,4); 
   w(1) = 2;
   w(2) = (*v)(0);				 // w = [0 2 4 0]
   // equivalent to:
   w.setValue( 2,v->getValue(0) );

   SP::SiconosMatrix M(new SimpleMatrix(3,3)); // M = [ 0 0 0 ]
                                               //     [ 0 0 0 ]
					       //     [ 0 0 0 ]
   SimpleMatrix P(1,2);   		       // P = [ 0 0 ]

   (*M)(1,2) = 2; 
   P(0,1) = 12;				   // P = [ 0 12.0 ]
   M->setValue(2,0,3.6);		   // M = [  0  0  0  ]
					   //     [  0  0 2.0 ]
					   //     [ 3.6 0  0  ]
	
   cout << P.getValue(0,1); // display 12.0

Note: for sparse matrices, assignment with operator "()" fails. It is then necessary to use setValue function.

::
   
   SP::SiconosMatrix A(new SimpleMatrix(10,10,SPARSE));
   (*A)(0,0) = 12; // WRONG
   A->setValue(0,0,12); // OK

For BlockVector: "()" and get/setValue functions have the same action as for SimpleVectors::

  // We suppose that v1 and v2 are two pointers to SimpleVector of size 3 and 4.
  SP::SiconosVector vB(new BlockVector(v1,v2)); // vB = [ [1 2 3] [4 5 6 7] ]
  (*vB)(4) = 12; 				      // vB = [ [1 2 3] [4 12 6 7] ]
  vB->setValue(6,8.6); 		              // vB = [ [1 2 3] [4 12 6 8.6] ]	
  // Warning: the given input for position is an "absolute" one, not a block position.

Remark: get/setValue functions are equivalent to "()" operator but mainly useful in Siconos-Python, since in that case operators can not be overloaded and thus
"()" is not available. The same remark applies for "[ ]" get/setVector and in a general way for all operators overloading.

::

   // Set vector or matrix to zero or identity
   x->zero();
   A->zero();
   A->eye(); 

   // Assignment of vectors or matrices: "A = B" or "x = y"
   // Operator =
   // Ok if A and x have been built before.
   A = B;
   x = y;
   // Remark: sizes must be consistents between A/B and x/y, 
   // else it results in a Siconos Exception.

   // Else copy constructor: memory allocation and initialization with B or x
   SP::SiconosMatrix A(new SimpleMatrix(*B));
   SP::SiconosVector x(new SimpleVector(*y));

   // Addition of matrices or vectors

   // add "in place": A = A+B  or x = x+y
   A += B;
   x += y;
   
   C = A+B;
   add(A,B,C);
   A -= B;
   C = A-B;
   sub(A,B,C);

   // Multiplication by a scalar:
   A *=a;
   B = a*A;
   scal(a,A,B);
   A /=a;
   x /=a;
   B = A/a;
   scal(1.0/a,A,B);
   // matrices product
   C = A*B;
   prod(A,B,C); 
                // C and A or B can be the same matrices (ie have common memory), 
	        // but that will slow down the operation.
   gemm(A,B,C); // Only for denses matrices.

   // It is also possible to compute product of sub-blocks of matrices or vectors:
   // Declare A, x, y ...
   // 
   std::vector<unsigned int> coord;
   // Set coord values ...
   bool init = false;
   subprod(A,x,y,coord,init);


Coord vector is equal to [r0A, r1A,, c0A, c1A, r0x, r1x, r0y, r1y]. The sub-matrix A is the matrix between row positions
r0A and r1A, column position between c0A and c1A. Same thing for x and y with rix, riy.
Then subprod computes suby = subA*subx if init = true, or suby += subA*subx if init = false.


::
   
   Matrix transpose:
   // in place:
   A->trans();
   // B = At
   B->trans(A);

   // inner product: a = x.y
   a = inner_prod(x,y);

   // Matrix-vector product: \f$y=A*x\f$
   y = prod(A,x);
   prod(A,x,y);

To handle a specific block, use "[ ]" or getVector and getVectorPtr functions::

  SP::SiconosVector v3(new SimpleVector(3));  // v3 = [0 0 0]
  SP::SiconosVector v4(new SimpleVector(4));  // v4 = [0 0 0 0]
  // get and copy a block:
  *v3 = *(*vB[0]); 			   // v3 = v1 = [1 2 3]
  // Equivalent to
  *v3 = *vB->getVectorPtr(0);

  // get and copy pointer to block:
  v4 = vB->getVectorPtr(1);		   // v4 = v2 = [4 12 6 8.6]
					   // AND pointer equality 
					   // between v4, vB[1] and v2
  // Equivalent to:
  v4 = (*vB)[1];			           // v4 = v2 = [4 12 6 8.6]. 

  // Assignment:
  SP::SiconosVector v5(new SimpleVector(3));  // v5 = [0 0 0]
  
  *(*vB)[0] = *v5; //  vB = [ [0 0 0] [4 5 6 7] ]
                   //  AND v1 = [0 0 0] because of pointer link between vB[0] and v1.
  // Equivalent to:
  vB->setVector(0,*v5);

  (*v5)(1) = 12;
  vB->setVectorPtr(0,v5); // vB = [ [0 0 0] [0 12 0] ]
  // Pointer equality between v5 and vB[0]. 
  // The pointer link between vB[0] and v1 has been canceled.

  // Warning: when using setVectorPtr(i,w), 
  // the vector w must be of the same size as the block[i] of v. 

About efficiency
""""""""""""""""

As you can see above, for most functionality, two solutions are available: either an overloaded operator or a function without any return value.
For example in the case of matrix addition::

  C = A + B;
  // or 
  add(A,B,C);

In a general way, if you need efficiency, always prefer functions to overloaded operators. 
The first solution is just there to give a more pleasant and readable, way of writing operations.

Try also to use pointers to objects to avoid temporary and time-consuming copies.