MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
gradienttest.cc
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/libraries/libmbmath/gradienttest.cc,v 1.6 2017/01/12 14:43:53 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 
32 /*
33  AUTHOR: Reinhard Resch <r.resch@secop.com>
34  Copyright (C) 2013(-2017) all rights reserved.
35 
36  The copyright of this code is transferred
37  to Pierangelo Masarati and Paolo Mantegazza
38  for use in the software MBDyn as described
39  in the GNU Public License version 2.1
40 */
41 
42 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
43 
44 #include <ctime>
45 #include <cstdlib>
46 #include <iostream>
47 #include <iomanip>
48 #include <functional>
49 #include <typeinfo>
50 #include <cmath>
51 
52 #ifdef HAVE_FEENABLEEXCEPT
53 #define _GNU_SOURCE 1
54 #include <fenv.h>
55 #endif
56 
57 #ifdef HAVE_BLITZ
58 #include <blitz/blitz.h>
59 #include <blitz/array.h>
60 #include <blitz/tinyvec.h>
61 #include <blitz/tinyvec-et.h>
62 #include <blitz/tinymat.h>
63 #include <blitz/matrix.h>
64 #endif
65 
66 #ifndef M_PI
67 #define M_PI 3.14159265358979
68 #endif
69 
70 #ifndef GRADIENT_DEBUG
71  #define GRADIENT_DEBUG 1
72 #endif
73 
74 #include "clock_time.h"
75 #include "gradient.h"
76 
77 using namespace grad;
78 
79 int NLoops = 1;
80 int NLoopsAss = 1;
81 
82 void tic();
83 void tic(doublereal& dTime);
84 doublereal toc();
85 
87  return 2 * (doublereal(rand()) / RAND_MAX) - 1;
88 }
89 
90 template <typename T>
91 bool bCompare(const T& a, const T& b, doublereal dTolRel = 0.) {
92  doublereal dTolAbs = std::max<T>(1., std::max<T>(std::abs(a), std::abs(b))) * dTolRel;
93 
94  if (!(std::abs(a - b) <= dTolAbs)) {
95  std::cerr << "a = " << a << " != b = " << b << std::endl;
96  return false;
97  }
98 
99  return true;
100 }
101 
102 template <index_type N_SIZE>
103 bool bCompare(const Gradient<N_SIZE>& a, const Gradient<N_SIZE>& b, doublereal dTolRel = 0.) {
104  doublereal dTolAbs = std::max(1., std::max(std::abs(a.dGetValue()), std::abs(b.dGetValue()))) * dTolRel;
105 
106  if (std::abs(a.dGetValue() - b.dGetValue()) > dTolAbs) {
107  std::cerr << "a = " << a.dGetValue() << " != b = " << b.dGetValue() << std::endl;
108  return false;
109  }
110 
111  index_type iStart = std::min(a.iGetStartIndexLocal(), b.iGetStartIndexLocal());
112  index_type iEnd = std::max(a.iGetEndIndexLocal(), b.iGetEndIndexLocal());
113 
114  for (index_type i = iStart; i < iEnd; ++i) {
115  doublereal dTolAbs = std::max(1., std::max(std::abs(a.dGetDerivativeLocal(i)), std::abs(b.dGetDerivativeLocal(i)))) * dTolRel;
116 
117  if (std::abs(a.dGetDerivativeLocal(i) - b.dGetDerivativeLocal(i)) > dTolAbs) {
118  std::cerr << "ad(" << i << ") = " << a.dGetDerivativeLocal(i) << " != bd(" << i << ") = " << b.dGetDerivativeLocal(i) << std::endl;
119  return false;
120  }
121  }
122 
123  return true;
124 }
125 
126 template <int N_SIZE>
128  std::cout << "testRangeVector<" << N_SIZE << ">();\n";
129  assert(N_SIZE == 0 || N_SIZE >= 6);
130  index_type start = 3;
131  index_type end = 6;
132  RangeVector<doublereal, N_SIZE> v(start, end, 0.);
135 
136  int k = 0;
137 
138  for (index_type i = start; i < end; ++i) {
139  v.SetValue(i, ++k);
140  }
141 
142  v2 = v;
143  vf = v;
144  vf.Reset();
145  vf.Reserve(N_SIZE == 0 ? vf.iGetEndIndex() * 2 : 2 * N_SIZE);
146  vf = v2;
147  const RangeVector<float, N_SIZE> v3(v2);
148  v2.Reset();
149  v2 = v3;
150  v2.Reserve(N_SIZE == 0 ? v2.iGetEndIndex() * 2 : N_SIZE);
151 
152  std::cout << "v(" << v.iGetStartIndex() << ":" << v.iGetEndIndex() - 1 << ")\n";
153 
154  for (index_type i = v.iGetStartIndex(); i < v.iGetEndIndex(); ++i) {
155  std::cout << "v[" << i << "]=" << v.GetValue(i) << std::endl;
156  }
157 
158  for (index_type i = vf.iGetStartIndex(); i < vf.iGetEndIndex(); ++i) {
159  std::cout << "vf[" << i << "]=" << vf.GetValue(i) << std::endl;
160  }
161 
162  for (index_type i = v2.iGetStartIndex(); i < v2.iGetEndIndex(); ++i) {
163  std::cout << "v2[" << i << "]=" << v2.GetValue(i) << std::endl;
164  }
165 
166  for (index_type i = v3.iGetStartIndex(); i < v3.iGetEndIndex(); ++i) {
167  std::cout << "v3[" << i << "]=" << v3.GetValue(i) << std::endl;
168  }
169 
170  std::cout << std::endl;
171 
172  for (index_type i = 0; i < v.iGetEndIndex(); ++i)
173  {
174  assert(v.GetValue(i) == vf.GetValue(i));
175  assert(v2.GetValue(i) == v.GetValue(i));
176  }
177 
178  v2.ResizeReset(v.iGetStartIndex(), v.iGetEndIndex(), 0.);
179 
180  for (index_type i = v.iGetStartIndexVector(); i < v.iGetEndIndexVector(); ++i)
181  {
182  v2.SetVectorValue(i, v.GetVectorValue(i));
183  }
184 
185  for (index_type i = v.iGetStartIndex(); i < v.iGetEndIndex(); ++i)
186  {
187  assert(v2.GetValue(i) == v.GetValue(i));
188  }
189 
190  vf.ResizeReset(0, 12, 0.0f);
191 
192  for (index_type i = vf.iGetStartIndex(); i < vf.iGetEndIndex(); ++i)
193  {
194  vf.SetValue(i, float(i + 1));
195  }
196 
197  vf2.ResizeReset(vf.iGetStartIndex(), vf.iGetEndIndex(), 0.0f);
198 
199  for (index_type i = vf.iGetStartIndexVector(); i < vf.iGetEndIndexVector(); ++i)
200  {
201  vf2.SetVectorValue(i, vf.GetVectorValue(i));
202  }
203 
204  for (index_type i = vf.iGetStartIndex(); i < vf.iGetEndIndex(); ++i)
205  {
206  assert(vf.GetValue(i) == vf2.GetValue(i));
207  }
208 
209  for (index_type i = vf2.iGetStartIndex(); i < vf2.iGetEndIndex(); ++i) {
210  std::cout << "vf2[" << i << "]=" << vf2.GetValue(i) << std::endl;
211  }
212 
213  std::cout << std::endl;
214 
215  v.ResizePreserve(1, 6);
216 
217  std::cout << "v(" << v.iGetStartIndex() << ":" << v.iGetEndIndex() - 1 << ")\n";
218 
219  for (index_type i = v.iGetStartIndex(); i < v.iGetEndIndex(); ++i) {
220  std::cout << "v[" << i << "]=" << v.GetValue(i) << std::endl;
221  }
222 
223  std::cout << std::endl;
224 
225  v.ResizePreserve(1, 5);
226 
227  std::cout << "v(" << v.iGetStartIndex() << ":" << v.iGetEndIndex() - 1 << ")\n";
228 
229  for (index_type i = v.iGetStartIndex(); i < v.iGetEndIndex(); ++i) {
230  std::cout << "v[" << i << "]=" << v.GetValue(i) << std::endl;
231  }
232 
233  std::cout << std::endl;
234 
235  v.ResizePreserve(0, 6);
236 
237  std::cout << "v(" << v.iGetStartIndex() << ":" << v.iGetEndIndex() - 1 << ")\n";
238 
239  for (index_type i = v.iGetStartIndex(); i < v.iGetEndIndex(); ++i) {
240  std::cout << "v[" << i << "]=" << v.GetValue(i) << std::endl;
241  }
242 
243  std::cout << std::endl;
244 
245  v.ResizePreserve(4, 5);
246 
247  std::cout << "v(" << v.iGetStartIndex() << ":" << v.iGetEndIndex() - 1 << ")\n";
248 
249  for (index_type i = v.iGetStartIndex(); i < v.iGetEndIndex(); ++i) {
250  std::cout << "v[" << i << "]=" << v.GetValue(i) << std::endl;
251  }
252 
253  std::cout << std::endl;
254 
255  v.ResizePreserve(0, 6);
256 
257  std::cout << "v(" << v.iGetStartIndex() << ":" << v.iGetEndIndex() - 1 << ")\n";
258 
259  for (index_type i = v.iGetStartIndex(); i < v.iGetEndIndex(); ++i) {
260  std::cout << "v[" << i << "]=" << v.GetValue(i) << std::endl;
261  }
262 
263  std::cout << std::endl;
264 }
265 
266 template <int N_SIZE>
268  assert(N_SIZE == 0 || N_SIZE == 19);
270 
271  const int iCount = 4;
272 
273  MapVector<N_SIZE> v[iCount] = { MapVector<N_SIZE>(&dof, 501, 506+1, MapVector<N_SIZE>::GLOBAL, 1.),
274  MapVector<N_SIZE>(&dof, 601, 606+1, MapVector<N_SIZE>::GLOBAL, 2.),
275  MapVector<N_SIZE>(&dof, 701, 706+1, MapVector<N_SIZE>::GLOBAL, 3.),
276  MapVector<N_SIZE>(&dof, 801, 801+1, MapVector<N_SIZE>::GLOBAL, 4.) };
277 
278  MapVector<N_SIZE> v1(&dof, 0, 1+1, MapVector<N_SIZE>::LOCAL, 5.);
279  MapVector<N_SIZE> v2(&dof, 1, 2+1, MapVector<N_SIZE>::LOCAL, 6.);
280 
281  for (index_type j = 0; j < dof.Size(); ++j) {
282  for (int i = 0; i < iCount; ++i) {
283  if (j >= v[i].iGetStartIndexLocal() && j < v[i].iGetEndIndexLocal()) {
284  doublereal dVal = v[i].dGetLocalVector(j);
285 
286  std::cout << "v[" << i << "][" << j << "->" << dof.iGetGlobalDof(j) << "]=" << dVal << std::endl;
287  }
288  }
289  }
290 
291  for (index_type j = 0; j < dof.Size(); ++j) {
292  if (j >= v1.iGetStartIndexLocal() && j < v1.iGetEndIndexLocal()) {
293  doublereal dVal = v1.dGetLocalVector(j);
294 
295  std::cout << "v1[" << j << "->" << dof.iGetGlobalDof(j) << "]=" << dVal << std::endl;
296  }
297  }
298 
299  for (index_type j = 0; j < dof.Size(); ++j) {
300  if (j >= v2.iGetStartIndexLocal() && j < v2.iGetEndIndexLocal()) {
301  doublereal dVal = v2.dGetLocalVector(j);
302 
303  std::cout << "v2[" << j << "->" << dof.iGetGlobalDof(j) << "]=" << dVal << std::endl;
304  }
305  }
306 }
307 
308 template <typename T>
309 void func(const T& u, const T& v, const T& w, doublereal e, T& f) {
310  f = ((((3 * u + 2 * v) * (u - v) / (1 - w) * pow(u/w, v - 1) * sin(v) * cos(w) * (1 - tan(-w + v))) * e + 1. - 11. + 4.5 - 1.) * 3.5 / 2.8 + u - v) * w / u;
311 }
312 
313 template <typename T>
314 void func_tmp(const T& u, const T& v, const T& w, doublereal e, T& f) {
315  f = u;
316  f *= 3;
317  f += 2 * v;
318  f *= (u - v);
319  f /= (1 - w);
320  f *= pow(u/w, v - 1);
321  f *= sin(v);
322  f *= cos(w);
323  f *= (1 - tan(-w + v));
324  f *= e;
325 
326 #if GRADIENT_DEBUG > 0
327  const T tmp1 =
328 #endif
329  f++;
330 
331  GRADIENT_ASSERT(tmp1 == f - 1);
332 
333  f -= 11.;
334  f += 4.5;
335 
336 #if GRADIENT_DEBUG > 0
337  const T tmp2 =
338 #endif
339  --f;
340 
341  GRADIENT_ASSERT(tmp2 == f);
342 
343 #if GRADIENT_DEBUG > 0
344  const T tmp3 = f;
345  f += f;
346  GRADIENT_ASSERT(bCompare(f, 2 * tmp3));
347  f -= f;
348  GRADIENT_ASSERT(bCompare(f, T()));
349  f = tmp3;
350 #endif
351 
352  f *= 3.5;
353  f /= 2.8;
354  f += u;
355  f -= v;
356  f *= w;
357  f /= u;
358 }
359 
361  return 1./cos(x);
362 }
363 
364 void funcDeriv(index_type N, doublereal u, const doublereal ud[], doublereal v, const doublereal vd[], doublereal w, const doublereal wd[], doublereal e, doublereal& f, doublereal fd[]) {
365  const doublereal tmp1 = sin(v);
366  const doublereal tmp2 = cos(w);
367  const doublereal tmp3 = u/w;
368  const doublereal tmp6 = pow(tmp3, v-1);
369  const doublereal tmp4 = tmp1*tmp6*tmp2;
370  const doublereal tmp5 = (tan(w-v)+1);
371  const doublereal tmp7 = ((2*v+3*u)*tmp4*tmp5);
372  const doublereal tmp8 = pow(sec(w-v),2);
373  const doublereal tmp9 = (u-v);
374  const doublereal tmp10 = (1-w);
375  const doublereal tmp11 = (v-1);
376  const doublereal tmp12 = (2*v+3*u);
377  const doublereal tmp13 = tmp9*tmp4*tmp5;
378  const doublereal tmp14 = tmp12*tmp4*tmp5;
379  const doublereal tmp15 = (tmp9*tmp12*tmp4*tmp8);
380  const doublereal tmp16 = (tmp9*tmp11*tmp14);
381  const doublereal tmp17 = tmp15/tmp10;
382  const doublereal tmp18 = tmp6*tmp2*tmp5;
383  const doublereal tmp19 = tmp9*tmp12*tmp1;
384  const doublereal tmp20 = tmp7/tmp10;
385  const doublereal tmp21 = 3.5 / 2.8;
386  const doublereal tmp22 = e * tmp21;
387  const doublereal tmp23 = ((((tmp9*tmp14)/tmp10) * e + 1. - 11. + 4.5 - 1.) * tmp21 + u - v);
388 
389  f = tmp23 * w / u;
390 
391  doublereal df_du = ((tmp16/(u*tmp10)+tmp20+(3*tmp13)/tmp10)*tmp22 + 1.) * w / u - tmp23 * w / (u * u);
392 
393  doublereal df_dv = (((tmp19*log(tmp3)*tmp18)/tmp10-tmp20+(2*tmp13)/tmp10+(tmp9*tmp12*cos(v)*tmp18)/tmp10-tmp17)*tmp22 - 1.) * w / u;
394 
395  doublereal df_dw = (-(tmp19*tmp6*sin(w)*tmp5)/tmp10-tmp16/(tmp10*w)+(tmp9*tmp14)/pow(1-w,2)+tmp17)*tmp22 * w / u + tmp23 / u;
396 
397  for (index_type i = 0; i < N; ++i) {
398  fd[i] = df_du * ud[i] + df_dv * vd[i] + df_dw * wd[i];
399  }
400 }
401 
402 template <int N_SIZE>
404  assert(N_SIZE == 0 || N_SIZE == N);
405 
406  srand(0);
407 
409  Gradient<N_SIZE> u, v, w, f, f_tmp;
410  doublereal f_d;
411 
412  u.SetValuePreserve(fabs(random1()) * 10);
413  v.SetValuePreserve(random1() * 3);
414  w.SetValuePreserve(random1() * 0.01);
415 
416  u.DerivativeResizeReset(&dof, 0, N, MapVectorBase::GLOBAL, 0.);
417  v.DerivativeResizeReset(&dof, 0, N, MapVectorBase::GLOBAL, 0.);
418  w.DerivativeResizeReset(&dof, 0, N, MapVectorBase::GLOBAL, 0.);
419 
420  for (index_type i = 0; i < N; ++i) {
421  u.SetDerivativeGlobal(i, random1() * 0.01);
422  v.SetDerivativeGlobal(i, random1() * 3);
423  w.SetDerivativeGlobal(i, random1() * 10);
424  }
425 
426  doublereal* ud_C = new doublereal[N];
427  doublereal* vd_C = new doublereal[N];
428  doublereal* wd_C = new doublereal[N];
429  doublereal f_C;
430  doublereal* fd_C = new doublereal[N];
431 
432  for (index_type i = 0; i < N; ++i) {
433  ud_C[i] = u.dGetDerivativeGlobal(i);
434  vd_C[i] = v.dGetDerivativeGlobal(i);
435  wd_C[i] = w.dGetDerivativeGlobal(i);
436  }
437 
438  doublereal t_AD = 0., t_AD_tmp = 0., t_C = 0., t_d = 0.;
439 
440  for (int i = 0; i < NLoops; ++i) {
441  const doublereal e = random1();
442  doublereal start, stop;
443 
444  tic(start);
445  func(u, v, w, e, f);
446  tic(stop);
447 
448  t_AD += stop - start;
449 
450  tic(start);
451  func(u.dGetValue(), v.dGetValue(), w.dGetValue(), e, f_d);
452  tic(stop);
453 
454  t_d += stop - start;
455 
456  tic(start);
457  func(u, v, w, e, f_tmp);
458  tic(stop);
459 
460  t_AD_tmp += stop - start;
461 
462  tic(start);
463  funcDeriv(N,
464  u.dGetValue(),
465  ud_C,
466  v.dGetValue(),
467  vd_C,
468  w.dGetValue(),
469  wd_C,
470  e,
471  f_C,
472  fd_C);
473  tic(stop);
474 
475  t_C += stop - start;
476 
477  assert(bCompare(f, f_tmp, std::numeric_limits<doublereal>::epsilon()));
478  assert(bCompare(f.dGetValue(), f_C, sqrt(std::numeric_limits<doublereal>::epsilon())));
479  assert(bCompare(f.dGetValue(), f_d, std::numeric_limits<doublereal>::epsilon()));
480 
481  for (index_type j = 0; j < N; ++j) {
482  doublereal err = std::abs(f.dGetDerivativeGlobal(j) / fd_C[j] - 1.);
483  assert(err < sqrt(std::numeric_limits<scalar_deriv_type>::epsilon()));
484  }
485  }
486 
487  std::cerr << "testGradient<" << N_SIZE << ">(" << N << ")" << std::endl;
488 
489  std::cout << "dof map:" << std::endl << dof << std::endl;
490  std::cout << "u=" << u << std::endl;
491  std::cout << "v=" << v << std::endl;
492  std::cout << "w=" << w << std::endl;
493  std::cout << "f=" << f << std::endl;
494  std::cout << "f_tmp=" << f_tmp << std::endl;
495 
496  std::cout << "f_C=" << f_C << std::endl;
497  std::cout << "fd_C=" << std::endl;
498 
499  for (int i = 0; i < N; ++i) {
500  std::cout << " " << fd_C[i] << std::endl;
501  }
502 
503  std::cout << std::endl;
504 
505  std::cerr << "t_AD=" << t_AD << "s" << std::endl;
506  std::cerr << "t_d=" << t_d << "s" << std::endl;
507  std::cerr << "t_AD_tmp=" << t_AD_tmp << "s" << std::endl;
508  std::cerr << "t_C=" << t_C << "s" << std::endl;
509  std::cerr << "overhead:" << t_AD / t_C << std::endl;
510  std::cerr << "overhead tmp:" << t_AD_tmp / t_C << std::endl;
511 
512  delete [] ud_C;
513  delete [] vd_C;
514  delete [] wd_C;
515  delete [] fd_C;
516 }
517 
518 template <index_type N_SIZE>
520  assert(N_SIZE == 0 || N_SIZE == 3);
521 
522  const doublereal dTol = sqrt(std::numeric_limits<doublereal>::epsilon());
523 
524  srand(0);
525 
527  Gradient<N_SIZE> u, v, w, f;
528 
529  u.SetValuePreserve(fabs(random1()) * 10);
530  v.SetValuePreserve(fabs(random1()) * 3);
531  w.SetValuePreserve(fabs(random1()) * 0.01);
532 
536 
537  doublereal ud_C[3];
538  doublereal vd_C[3];
539  doublereal wd_C[3];
540  doublereal f_C;
541  doublereal fd_C[3];
542 
543  for (index_type i = 0; i < 3; ++i) {
544  ud_C[i] = u.dGetDerivativeGlobal(i);
545  vd_C[i] = v.dGetDerivativeGlobal(i);
546  wd_C[i] = w.dGetDerivativeGlobal(i);
547  }
548 
549  doublereal t_AD = 0., t_C = 0.;
550 
551  for (int i = 0; i < NLoops; ++i) {
552  const doublereal e = random1();
553  doublereal start, stop;
554 
555  tic(start);
556  func(u, v, w, e, f);
557  tic(stop);
558 
559  t_AD += stop - start;
560 
561  tic(start);
562  funcDeriv(3,
563  u.dGetValue(),
564  ud_C,
565  v.dGetValue(),
566  vd_C,
567  w.dGetValue(),
568  wd_C,
569  e,
570  f_C,
571  fd_C);
572  tic(stop);
573 
574  t_C += stop - start;
575 
576  assert(bCompare(f.dGetValue(), f_C, dTol));
577  //assert(bCompare(Y[0], f_C, dTol));
578 
579  for (index_type j = 0; j < 3; ++j) {
580  assert(bCompare<scalar_deriv_type>(f.dGetDerivativeGlobal(j), fd_C[j], sqrt(std::numeric_limits<scalar_deriv_type>::epsilon())));
581  // assert(bCompare(jac[j], fd_C[j], dTol));
582  }
583  }
584 
585  std::cerr << "testGradient2<" << N_SIZE << ">(3)" << std::endl;
586 
587  std::cout << "dof map:" << std::endl << dof << std::endl;
588  std::cout << "u=" << u << std::endl;
589  std::cout << "v=" << v << std::endl;
590  std::cout << "w=" << w << std::endl;
591  std::cout << "f=" << f << std::endl;
592 
593  std::cout << "f_C=" << f_C << std::endl;
594  std::cout << "fd_C=" << std::endl;
595 
596  for (int i = 0; i < 3; ++i) {
597  std::cout << " " << fd_C[i] << std::endl;
598  }
599 
600  std::cout << std::endl;
601 
602  std::cerr << "t_AD=" << t_AD << "s" << std::endl;
603  std::cerr << "t_C=" << t_C << "s" << std::endl;
604  std::cerr << "overhead:" << t_AD / t_C << std::endl;
605 
606  Gradient<N_SIZE> w2 = 3 * u + 2 * v + 0.5 * w;
607 
608  w = 3 * u + 2 * v + 0.5 * Alias(w);
609 
610  GRADIENT_ASSERT(bCompare(w, w2));
611 
612  std::cout << "w=" << w << std::endl;
613  std::cout << "w2=" << w2 << std::endl;
614 }
615 #if 0
616 void testGradient3(index_type N)
617 {
618  srand(0);
619 
621  Gradient<N_SIZE> u, v, w, f;
622 
623  u.SetValuePreserve(random1() * 10);
624  v.SetValuePreserve(random1() * 3);
625  w.SetValuePreserve(random1() * 0.01);
626 
630 
631 
632  doublereal t_AD = 0., t_C = 0.;
633 
634  for (int i = 0; i < NLoops; ++i) {
635  const doublereal e = random1();
636  doublereal start, stop;
637 
638  tic(start);
639  func3(u, v, w, e, f);
640  tic(stop);
641 
642  t_AD += stop - start;
643  }
644 }
645 #endif
646 void testGradientCopy(int N) {
647  LocalDofMap map1, map2;
648  bool bFirst = true;
649 
650  std::cerr << "testGradientCopy(" << N << ")\n";
651 
652  tic();
653 
654  for (int i = 0; i < NLoops; ++i) {
655  MapVector<0> ud(&map1, 100, 102, MapVectorBase::GLOBAL, 1.);
656 
657  for (int i = 0; i < N; ++i) {
658  MapVector<0> dummy(&map1, 102 + i, MapVectorBase::GLOBAL, 1.5);
659  }
660 
661  MapVector<0> vd(&map1, 200, 203, MapVectorBase::GLOBAL, 2.);
662 
663  for (int i = 0; i < N; ++i) {
664  MapVector<0> dummy(&map1, 203 + i, MapVectorBase::GLOBAL, 2.5);
665  }
666 
667  MapVector<0> wd(&map1, 300, 302, MapVectorBase::GLOBAL, 3.);
668 
669  for (int i = 0; i < N; ++i) {
670  MapVector<0> dummy(&map1, 302 + i, MapVectorBase::GLOBAL, 3.5);
671  }
672 
673  Gradient<0> u(100., ud);
674  Gradient<0> v(200., vd);
675  Gradient<0> w(300., wd);
676 
677  assert(u != 100.001);
678  assert(u >= 100.);
679  assert(u <= 100.);
680  assert(u == 100.);
681  assert(u > 99.999);
682  assert(u < 100.001);
683  assert(100. == u);
684  assert(100.001 != u);
685  assert(100. <= u);
686  assert(100. >= u);
687  assert(99.999 < u);
688  assert(100.001 > u);
689 
690  assert(v != 200.001);
691  assert(v >= 200.);
692  assert(v <= 200.);
693  assert(v == 200.);
694  assert(v > 199.999);
695  assert(v < 200.001);
696  assert(200. == v);
697  assert(200.001 != v);
698  assert(200. <= v);
699  assert(200. >= v);
700  assert(199.999 < v);
701  assert(200.001 > v);
702 
703  Gradient<0> x = v + w;
704 
705  if (bFirst) {
706  std::cout << std::endl;
707  std::cout << "map1=" << std::endl << map1 << std::endl;
708  std::cout << "u=" << u << std::endl;
709  std::cout << "v=" << v << std::endl;
710  std::cout << "w=" << w << std::endl;
711  std::cout << "x=" << x << std::endl;
712  std::cout << std::endl;
713  }
714 
715  Gradient<5> y(x, &map2);
716 
717  if (bFirst) {
718  std::cout << "map2=" << std::endl << map2 << std::endl;
719  std::cout << "y=" << y << std::endl;
720  std::cout << std::endl;
721  }
722 
723  bFirst = false;
724  }
725 
726  std::cerr << "t=" << toc() << "s" << std::endl;
727 }
728 
729 template <index_type N_SIZE>
731  {
732  LocalDofMap dofMap1, dofMap2;
733 
734  Gradient<N_SIZE> g1(1000., MapVector<N_SIZE>(&dofMap1, 100, 100 + N, MapVectorBase::GLOBAL, 1.));
735  Gradient<N_SIZE> g2(2000., MapVector<N_SIZE>(&dofMap2, 102, 102 + N, MapVectorBase::GLOBAL, 2.));
736 
737  std::cerr << "testDifferentDofMaps<" << N_SIZE << ">(" << N << "): operator+=()\n";
738  std::cerr << "g1=" << g1 << std::endl;
739  std::cerr << "g2=" << g2 << std::endl;
740 
741  g1 += g2;
742 
743  std::cerr << "g1=" << g1 << std::endl;
744 
745  assert(g1.dGetValue() == 3000.);
746 
747  for (index_type i = 100; i < 102 + N; ++i) {
748  if (i < 100 + N || i >= 102) {
749  const doublereal d = g1.dGetDerivativeGlobal(i);
750  if (i >= 102 && i < 100 + N) {
751  assert(d == 3.);
752  } else if (i < 100 + N) {
753  assert(d == 1.);
754  } else {
755  assert(d == 2.);
756  }
757  }
758  }
759  }
760  {
761  LocalDofMap dofMap1, dofMap2;
762 
763  const doublereal u = 3, v = 4, du = 5., dv = 6.;
764  Gradient<N_SIZE> g1(u, MapVector<N_SIZE>(&dofMap1, 100, 100 + N, MapVectorBase::GLOBAL, du));
765  Gradient<N_SIZE> g2(v, MapVector<N_SIZE>(&dofMap2, 102, 102 + N, MapVectorBase::GLOBAL, dv));
766 
767  std::cerr << "testDifferentDofMaps<" << N_SIZE << ">(" << N << "): operator*=()\n";
768  std::cerr << "g1=" << g1 << std::endl;
769  std::cerr << "g2=" << g2 << std::endl;
770 
771  g1 *= g2;
772 
773  std::cerr << "g1=" << g1 << std::endl;
774 
775  assert(g1.dGetValue() == u * v);
776 
777  for (index_type i = 100; i < 102 + N; ++i) {
778  if (i < 100 + N || i >= 102) {
779  const doublereal d = g1.dGetDerivativeGlobal(i);
780  if (i >= 102 && i < 100 + N) {
781  assert(d == du * v + u * dv);
782  } else if (i < 100 + N) {
783  assert(d == du * v);
784  } else {
785  assert(d == u * dv);
786  }
787  }
788  }
789  }
790 }
791 
792 template <index_type N_SIZE>
793 void testGradientLin(int N) {
794  Gradient<N_SIZE> A11, A12, A13, A14;
795  Gradient<N_SIZE> x1, x2, x3, x4;
796  LocalDofMap oDof;
797 
798  A11.SetValuePreserve(1);
799  A12.SetValuePreserve(2);
800  A13.SetValuePreserve(3);
801  A14.SetValuePreserve(4);
802 
807 
808  std::cout << "A11=" << A11 << std::endl;
809  std::cout << "A12=" << A12 << std::endl;
810  std::cout << "A13=" << A13 << std::endl;
811  std::cout << "A14=" << A14 << std::endl;
812 
813  x1.SetValuePreserve(1);
814  x2.SetValuePreserve(1);
815  x3.SetValuePreserve(1);
816  x4.SetValuePreserve(1);
817 
822 
823  std::cout << "x1=" << x1 << std::endl;
824  std::cout << "x2=" << x2 << std::endl;
825  std::cout << "x3=" << x3 << std::endl;
826  std::cout << "x4=" << x4 << std::endl;
827 
828  Gradient<N_SIZE> y1 = A11 * x1;
829  Gradient<N_SIZE> y2 = A12 * x2;
830  Gradient<N_SIZE> y3 = A13 * x3;
831  Gradient<N_SIZE> y4 = A14 * x4;
832 
833  std::cout << "y1=" << y1 << std::endl;
834  std::cout << "y2=" << y2 << std::endl;
835  std::cout << "y3=" << y3 << std::endl;
836  std::cout << "y4=" << y4 << std::endl;
837 
838  Gradient<N_SIZE> y_2 = y1 + y2;
839  Gradient<N_SIZE> y_3 = y_2 + y3;
840  Gradient<N_SIZE> y_4 = y_3 + y4;
841 
842  Gradient<N_SIZE> y_1 = y1 + y2 + y3 + y4;
843  Gradient<N_SIZE> y = A11 * x1 + A12 * x2 + A13 * x3 + A14 * x4;
844 
845  std::cout << "y=" << y << std::endl;
846  std::cout << "y_1=" << y_1 << std::endl;
847  std::cout << "y_2=" << y_2 << std::endl;
848  std::cout << "y_3=" << y_3 << std::endl;
849  std::cout << "y_4=" << y_4 << std::endl;
850 
851  assert(y.bIsEqual(y_1));
852  assert(y.bIsEqual(y_4));
853  assert(y.dGetValue() == 10);
854  assert(y.dGetDerivativeGlobal(0) == 2);
855  assert(y.dGetDerivativeGlobal(1) == 3);
856  assert(y.dGetDerivativeGlobal(2) == 4);
857  assert(y.dGetDerivativeGlobal(3) == 5);
858 }
859 
861 
862 void tic(doublereal& dTime) {
863  dTime = mbdyn_clock_time();
864 }
865 
866 void tic() {
868 }
869 
871  return mbdyn_clock_time() - dStartTime;
872 }
873 
874 #ifdef HAVE_BLITZ
875 namespace gradAssTest {
876 
877 using namespace blitz;
878 
879 const int I1 = 0, I2 = 1, I3 = 2;
880 
881 template <typename T>
882 void Euler123ToMatR(const TinyVector<T, 3>& theta, TinyMatrix<T, 3, 3>& R1) {
883  const T cos_theta2 = cos(theta(I2));
884  const T cos_theta3 = cos(theta(I3));
885  const T sin_theta2 = sin(theta(I2));
886  const T sin_theta3 = sin(theta(I3));
887  const T sin_theta1 = sin(theta(I1));
888  const T cos_theta1 = cos(theta(I1));
889  const T sin_theta1_sin_theta2 = sin_theta1 * sin_theta2;
890  const T cos_theta1_sin_theta3 = cos_theta1 * sin_theta3;
891  const T cos_theta1_cos_theta3 = cos_theta1 * cos_theta3;
892  R1(I1, I1) = cos_theta2 * cos_theta3;
893  R1(I1, I2) = cos_theta2 * sin_theta3;
894  R1(I1, I3) = -sin_theta2;
895  R1(I2, I1) = sin_theta1_sin_theta2 * cos_theta3 - cos_theta1_sin_theta3;
896  R1(I2, I2) = sin_theta1_sin_theta2 * sin_theta3 + cos_theta1_cos_theta3;
897  R1(I2, I3) = sin_theta1 * cos_theta2;
898  R1(I3, I1) = sin_theta1 * sin_theta3 + cos_theta1_cos_theta3 * sin_theta2;
899  R1(I3, I2) = cos_theta1_sin_theta3 * sin_theta2 - sin_theta1 * cos_theta3;
900  R1(I3, I3) = cos_theta1 * cos_theta2;
901 }
902 
903 template <typename T, int N_rows, int N_cols>
904 TinyMatrix<T, N_cols, N_rows>& transpose(const TinyMatrix<T, N_rows, N_cols>& A, TinyMatrix<T, N_cols, N_rows>& A_T) {
905  for (int i = 0; i < N_rows; ++i) {
906  for (int j = 0; j < N_cols; ++j) {
907  A_T(j, i) = A(i, j);
908  }
909  }
910 
911  return A_T;
912 }
913 
914 template <typename T, int N_rows, int N_cols>
915 TinyVector<T, N_cols>& MatTDotVec(const TinyMatrix<T, N_rows, N_cols>& A, const TinyVector<T, N_rows>& x, TinyVector<T, N_cols>& v) {
916  for (int i = 0; i < N_cols; ++i) {
917  v(i) = T(0.);
918 
919  for (int j = 0; j < N_rows; ++j) {
920  v(i) += A(j, i) * x(j);
921  }
922  }
923 
924  return v;
925 }
926 
927 template <typename T, int R1, int C1, int C2>
928 TinyMatrix<T, R1, C2> product(const TinyMatrix<T, R1, C1>& A, const TinyMatrix<T, C1, C2>& B) {
929  TinyMatrix<T, R1, C2> C;
930  C.initialize(T(0.));
931 
932  for (int i = 0; i < R1; ++i) {
933  for (int j = 0; j < C2; ++j) {
934  for (int k = 0; k < C1; ++k) {
935  C(i, j) += A(i, k) * B(k, j);
936  }
937  }
938  }
939 
940  return C;
941 }
942 
943 template <typename T>
944 TinyMatrix<T, 3, 3>& skew(TinyMatrix<T, 3, 3>& skew_g, const TinyVector<T, 3>& g) {
945  skew_g(0, 0) = T(0.);
946  skew_g(1, 1) = T(0.);
947  skew_g(2, 2) = T(0.);
948 
949  skew_g(0, 1) = -g(2);
950  skew_g(1, 0) = g(2);
951 
952  skew_g(0, 2) = g(1);
953  skew_g(2, 0) = -g(1);
954 
955  skew_g(1, 2) = -g(0);
956  skew_g(2, 1) = g(0);
957 
958  return skew_g;
959 }
960 
961 template <typename T>
962 TinyMatrix<T, 3, 3> skew(const TinyVector<T, 3>& g) {
963  TinyMatrix<T, 3, 3> skew_g;
964  /*
965  skew(g) = [ 0, -z, y;
966  z, 0, -x;
967  -y, x, 0 ];
968  */
969 
970  skew(skew_g, g);
971 
972  return skew_g;
973 }
974 
975 template <typename T>
976 TinyMatrix<T, 3, 3>& skew_skew(TinyMatrix<T, 3, 3>& skew_g_skew_g, const TinyVector<T, 3>& g) {
977  skew_g_skew_g(0, 0) = -g(2)*g(2)-g(1)*g(1);
978  skew_g_skew_g(0, 1) = g(0)*g(1);
979  skew_g_skew_g(0, 2) = g(0)*g(2);
980  skew_g_skew_g(1, 0) = g(0)*g(1);
981  skew_g_skew_g(1, 1) = -g(2)*g(2)-g(0)*g(0);
982  skew_g_skew_g(1, 2) = g(1)*g(2);
983  skew_g_skew_g(2, 0) = g(0)*g(2);
984  skew_g_skew_g(2, 1) = g(1)*g(2);
985  skew_g_skew_g(2, 2) = -g(1)*g(1)-g(0)*g(0);
986 
987  return skew_g_skew_g;
988 }
989 
990 template <typename T>
991 TinyMatrix<T, 3, 3> transpose(const TinyMatrix<T, 3, 3>& A) {
992  TinyMatrix<T, 3, 3> At;
993 
994  for (int i = 0; i < 3; ++i) {
995  for (int j = 0; j < 3; ++j) {
996  At(i, j) = A(j, i);
997  }
998  }
999 
1000  return At;
1001 }
1002 
1003 template <typename T, int N_rows, int N_cols>
1004 TinyMatrix<T, N_rows, N_cols> operator-(const TinyMatrix<T, N_rows, N_cols>& A) {
1005  TinyMatrix<T, N_rows, N_cols> B(A);
1006 
1007  for (int i = 0; i < N_rows; ++i) {
1008  for (int j = 0; j < N_cols; ++j) {
1009  B(i, j) *= -1.;
1010  }
1011  }
1012 
1013  return B;
1014 }
1015 
1016 template <typename T, int N_rows, int N_cols>
1017 TinyMatrix<T, N_rows, N_cols> operator-(const TinyMatrix<T, N_rows, N_cols>& A, const TinyMatrix<T, N_rows, N_cols>& B) {
1018  TinyMatrix<T, N_rows, N_cols> C(A);
1019 
1020  for (int i = 0; i < N_rows; ++i) {
1021  for (int j = 0; j < N_cols; ++j) {
1022  C(i, j) -= B(i, j);
1023  }
1024  }
1025 
1026  return C;
1027 }
1028 
1029 template <typename T, int N_rows, int N_cols>
1030 TinyMatrix<T, N_rows, N_cols> operator+(const TinyMatrix<T, N_rows, N_cols>& A, const TinyMatrix<T, N_rows, N_cols>& B) {
1031  TinyMatrix<T, N_rows, N_cols> C(A);
1032 
1033  for (int i = 0; i < N_rows; ++i) {
1034  for (int j = 0; j < N_cols; ++j) {
1035  C(i, j) += B(i, j);
1036  }
1037  }
1038 
1039  return C;
1040 }
1041 
1042 class Node {
1043 public:
1044  Node(const TinyVector<doublereal, 3>& X_0,
1045  const TinyVector<doublereal, 3>& XP_0,
1046  const TinyMatrix<doublereal, 3, 3>& R_0,
1047  const TinyVector<doublereal, 3>& W_0)
1048  :iFirstDofIndex(-1), R0(R_0), W0(W_0) {
1049 
1050  for (int i = 0; i < 3; ++i) {
1051  X(i).SetValuePreserve(X_0(i));
1052  X(i).DerivativeResizeReset(&dof, i, MapVectorBase::LOCAL, 0.);
1053 
1054  XP(i).SetValuePreserve(XP_0(i));
1055  XP(i).DerivativeResizeReset(&dof, i, MapVectorBase::LOCAL, 0.);
1056  XP(i).SetDerivativeLocal(i, -1.); // derivative will be always -1
1057 
1058  g(i).SetValuePreserve(0.);
1059  g(i).DerivativeResizeReset(&dof, i, MapVectorBase::LOCAL, 0.);
1060 
1061  gP(i).SetValuePreserve(0.);
1062  gP(i).DerivativeResizeReset(&dof, i, MapVectorBase::LOCAL, 0.);
1063  gP(i).SetDerivativeLocal(i, -1.); // derivative will be always -1
1064  }
1065  }
1066 
1067  void SetValue(Array<doublereal, 1>& XCurr, Array<doublereal, 1>& XPrimeCurr) {
1068  assert(iFirstDofIndex != -1);
1069 
1070  for (int i = 0; i < 3; ++i) {
1071  XCurr(iFirstDofIndex + i) = X(i).dGetValue();
1072  XPrimeCurr(iFirstDofIndex + i) = XP(i).dGetValue();
1073  XCurr(iFirstDofIndex + i + 3) = g(i).dGetValue();
1074  XPrimeCurr(iFirstDofIndex + i + 3) = gP(i).dGetValue();
1075  }
1076  }
1077 
1078  void Update(const Array<doublereal, 1>& XCurr, const Array<doublereal, 1>& XPrimeCurr, doublereal dCoef) {
1079  assert(iFirstDofIndex != -1);
1080 
1081  for (int i = 0; i < 3; ++i) {
1082  X(i).SetValuePreserve(XCurr(iFirstDofIndex + i));
1083  X(i).SetDerivativeLocal(i, -dCoef);
1084  XP(i).SetValuePreserve(XPrimeCurr(iFirstDofIndex + i));
1085  g(i).SetValuePreserve(XCurr(iFirstDofIndex + i + 3));
1086  g(i).SetDerivativeLocal(i, -dCoef);
1087  gP(i).SetValuePreserve(XPrimeCurr(iFirstDofIndex + i + 3));
1088  }
1089 
1090  UpdateRotation();
1091  }
1092 
1093  void UpdateRotation() {
1094  TinyMatrix<Gradient<NADVars>, 3, 3> RDelta, G;
1095  TinyMatrix<Gradient<NADVars>, 3, 3> skew_g;
1096  TinyMatrix<Gradient<NADVars>, 3, 3> skew_skew_g;
1097 
1098  skew(skew_g, g);
1099  skew_skew(skew_skew_g, g);
1100 
1101  const Gradient<NADVars> d = 4. / (4. + dot(g, g));
1102 
1103  for (int i = 0; i < 3; ++i) {
1104  RDelta(i, i).SetValuePreserve(1.);
1105  G(i, i) = d;
1106  }
1107 
1108  for (int i = 0; i < 3; ++i) {
1109  for (int j = 0; j < 3; ++j) {
1110  RDelta(i, j) += d * (skew_g(i, j) + 0.5 * skew_skew_g(i, j));
1111  G(i, j) += 0.5 * d * skew_g(i, j);
1112  }
1113  }
1114 
1115  R = product(RDelta, R0);
1116  W = product(G, gP) + product(RDelta, W0);
1117  }
1118 
1119  void AfterConvergence(const Array<doublereal, 1>& XCurr, const Array<doublereal, 1>& XPrimeCurr) {
1120  for (int i = 0; i < 3; ++i) {
1121  W0(i) = W(i).dGetValue();
1122  g(i).SetValuePreserve(0.);
1123  gP(i).SetValuePreserve(0.);
1124 
1125  for (int j = 0; j < 3; ++j) {
1126  R0(i, j) = R(i, j).dGetValue();
1127  }
1128  }
1129  }
1130 
1131  void SetFirstDofIndex(int iDofIndex) {
1132  iFirstDofIndex = iDofIndex;
1133  }
1134 
1135  int iGetFirstIndex() const {
1136  return iFirstDofIndex;
1137  }
1138 
1139  int iGetNumDof() const {
1140  return 6;
1141  }
1142 
1143  void GetXCurr(TinyVector<doublereal, 3>& XCurr, LocalDofMap*) const {
1144  for (int i = 0; i < 3; ++i) {
1145  XCurr(i) = X(i).dGetValue();
1146  }
1147  }
1148 
1149  template <index_type N_SIZE>
1150  void GetXCurr(TinyVector<Gradient<N_SIZE>, 3>& XCurr, LocalDofMap* pDofMap) const {
1151  assert(iFirstDofIndex != -1);
1152  assert(pDofMap != 0);
1153 
1154  for (int i = 0; i < 3; ++i) {
1155  XCurr(i).SetValuePreserve(X(i).dGetValue());
1156  XCurr(i).DerivativeResizeReset(pDofMap, iFirstDofIndex + X(i).iGetStartIndexLocal(), iFirstDofIndex + X(i).iGetEndIndexLocal(), MapVectorBase::GLOBAL, 0.);
1157 
1158  for (index_type j = X(i).iGetStartIndexLocal(); j < X(i).iGetEndIndexLocal(); ++j) {
1159  XCurr(i).SetDerivativeGlobal(iFirstDofIndex + j, X(i).dGetDerivativeLocal(j));
1160  }
1161  }
1162  }
1163 
1164  void GetVCurr(TinyVector<doublereal, 3>& VCurr, LocalDofMap*) const {
1165  for (int i = 0; i < 3; ++i) {
1166  VCurr(i) = XP(i).dGetValue();
1167  }
1168  }
1169 
1170  template <index_type N_SIZE>
1171  void GetVCurr(TinyVector<Gradient<N_SIZE>, 3>& VCurr, LocalDofMap* pDofMap) const {
1172  assert(iFirstDofIndex != -1);
1173  assert(pDofMap != 0);
1174 
1175  for (int i = 0; i < 3; ++i) {
1176  VCurr(i).SetValuePreserve(XP(i).dGetValue());
1177  VCurr(i).DerivativeResizeReset(pDofMap, iFirstDofIndex + XP(i).iGetStartIndexLocal(), iFirstDofIndex + XP(i).iGetEndIndexLocal(), MapVectorBase::GLOBAL, 0.);
1178 
1179  for (index_type j = XP(i).iGetStartIndexLocal(); j < XP(i).iGetEndIndexLocal(); ++j) {
1180  VCurr(i).SetDerivativeGlobal(iFirstDofIndex + j, XP(i).dGetDerivativeLocal(j));
1181  }
1182  }
1183  }
1184 
1185  void GetRCurr(TinyMatrix<doublereal, 3, 3>& RCurr, LocalDofMap*) const {
1186  for (int i = 0; i < 3; ++i) {
1187  for (int j = 0; j < 3; ++j) {
1188  RCurr(i, j) = R(i, j).dGetValue();
1189  }
1190  }
1191  }
1192 
1193  template <index_type N_SIZE>
1194  void GetRCurr(TinyMatrix<Gradient<N_SIZE>, 3, 3>& RCurr, LocalDofMap* pDofMap) const {
1195  assert(iFirstDofIndex != -1);
1196  assert(pDofMap != 0);
1197 
1198  for (int i = 0; i < 3; ++i) {
1199  for (int j = 0; j < 3; ++j) {
1200  RCurr(i, j).SetValuePreserve(R(i, j).dGetValue());
1201  RCurr(i, j).DerivativeResizeReset(pDofMap, iFirstDofIndex + R(i, j).iGetStartIndexLocal() + 3, iFirstDofIndex + R(i, j).iGetEndIndexLocal() + 3, MapVectorBase::GLOBAL, 0.);
1202 
1203  for (index_type k = R(i, j).iGetStartIndexLocal(); k < R(i, j).iGetEndIndexLocal(); ++k) {
1204  RCurr(i, j).SetDerivativeGlobal(iFirstDofIndex + k + 3, R(i, j).dGetDerivativeLocal(k));
1205  }
1206  }
1207  }
1208  }
1209 
1210  const TinyMatrix<doublereal, 3, 3>& GetRRef() const {
1211  return R0;
1212  }
1213 
1214  void GetWCurr(TinyVector<doublereal, 3>& WCurr, LocalDofMap*) const {
1215  for (int i = 0; i < 3; ++i) {
1216  WCurr(i) = W(i).dGetValue();
1217  }
1218  }
1219 
1220  template <index_type N_SIZE>
1221  void GetWCurr(TinyVector<Gradient<N_SIZE>, 3>& WCurr, LocalDofMap* pDofMap) const {
1222  assert(iFirstDofIndex != -1);
1223  assert(pDofMap != 0);
1224 
1225  for (int i = 0; i < 3; ++i) {
1226  WCurr(i).SetValuePreserve(W(i).dGetValue());
1227  WCurr(i).DerivativeResizeReset(pDofMap, iFirstDofIndex + W(i).iGetStartIndexLocal() + 3, iFirstDofIndex + W(i).iGetEndIndexLocal() + 3, MapVectorBase::GLOBAL, 0.);
1228 
1229  for (index_type j = W(i).iGetStartIndexLocal(); j < W(i).iGetEndIndexLocal(); ++j) {
1230  WCurr(i).SetDerivativeGlobal(iFirstDofIndex + j + 3, W(i).dGetDerivativeLocal(j));
1231  }
1232  }
1233  }
1234 
1235  const TinyVector<doublereal, 3>& GetWRef() const {
1236  return W0;
1237  }
1238 
1239 private:
1240  int iFirstDofIndex;
1241  TinyMatrix<doublereal, 3, 3> R0;
1242  TinyVector<doublereal, 3> W0;
1243  static const int NADVars = 3;
1244  TinyVector<Gradient<NADVars>, 3> X, XP, g, gP, W;
1245  TinyMatrix<Gradient<NADVars>, 3, 3> R;
1246  LocalDofMap dof;
1247 };
1248 
1249 template <typename T>
1250 struct ResItem {
1251  int iEquIndex;
1252  T dCoef;
1253 
1254  ResItem(int iEquIndex_=-1, T dCoef_=T(0.))
1255  :iEquIndex(iEquIndex_), dCoef(dCoef_) {
1256  }
1257 };
1258 
1259 class FullSubMatrixHandler {
1260 public:
1261  FullSubMatrixHandler(index_type iNumRows=0, index_type iNumCols=0) {
1262  ResizeReset(iNumRows, iNumCols);
1263  }
1264 
1265  void ResizeReset(index_type iNumRows, index_type iNumCols) {
1266  oWorkMat.resize(iNumRows, iNumCols);
1267  oRowIndex.resize(iNumRows);
1268  oColIndex.resize(iNumCols);
1269  oWorkMat.initialize(0.);
1270  oRowIndex.initialize(-1);
1271  oColIndex.initialize(-1);
1272  }
1273 
1274  void PutRowIndex(int iSubRow, int iRow) {
1275  assert(iSubRow < oRowIndex.rows());
1276  oRowIndex(iSubRow) = iRow;
1277  }
1278 
1279  void PutColIndex(int iSubCol, int iCol) {
1280  assert(iSubCol < oColIndex.rows());
1281  oColIndex(iSubCol) = iCol;
1282  }
1283 
1284  void PutCoef(int iSubRow, int iSubCol, doublereal dCoef) {
1285  assert(iSubRow >= 0 && iSubRow < oWorkMat.rows());
1286  assert(iSubCol >= 0 && iSubCol < oWorkMat.cols());
1287 
1288  oWorkMat(iSubRow, iSubCol) = dCoef;
1289  }
1290 
1291  void IncCoef(int iSubRow, int iSubCol, doublereal dCoef) {
1292  assert(iSubRow >= 0 && iSubRow < oWorkMat.rows());
1293  assert(iSubCol >= 0 && iSubCol < oWorkMat.cols());
1294 
1295  oWorkMat(iSubRow, iSubCol) += dCoef;
1296  }
1297 
1298  void AddTo(Array<doublereal, 2>& JacMat) const {
1299  for (int i = 0; i < oWorkMat.rows(); ++i) {
1300  for (int j = 0; j < oWorkMat.cols(); ++j) {
1301  assert(oRowIndex(i) >= 0);
1302  assert(oRowIndex(i) < JacMat.rows());
1303  assert(oColIndex(j) >= 0);
1304  assert(oColIndex(j) < JacMat.cols());
1305  JacMat(oRowIndex(i), oColIndex(j)) += oWorkMat(i, j);
1306  }
1307  }
1308  }
1309 
1310 private:
1311  Array<doublereal, 2> oWorkMat;
1312  Array<int, 1> oRowIndex, oColIndex;
1313 };
1314 
1315 class SparseSubMatrixHandler {
1316 public:
1317  struct JacItem {
1318  int iEquIndex;
1319  int iDofIndex;
1320  doublereal dCoef;
1321 
1322  JacItem(int iEquIndex=-1, int iDofIndex=-1, doublereal dCoef=0.)
1323  :iEquIndex(iEquIndex), iDofIndex(iDofIndex), dCoef(dCoef) {
1324  }
1325  };
1326 
1327  typedef std::vector<JacItem> VectorType;
1328  typedef VectorType::const_iterator const_iterator;
1329 
1330  SparseSubMatrixHandler(int iNumItems=0) {
1331  if (iNumItems > 0) {
1332  WorkMat.reserve(iNumItems);
1333  }
1334  }
1335 
1336  template <index_type N_SIZE, typename T>
1337  SparseSubMatrixHandler& AssJac(T* pElem, LocalDofMap* pDofMap, Array<ResItem<Gradient<N_SIZE> >, 1>& WorkVec, doublereal dCoef) {
1338  pElem->AssRes(WorkVec, dCoef, pDofMap);
1339  ResizeReset(0);
1340 
1341  for (int i = 0; i < WorkVec.rows(); ++i) {
1342  const ResItem<Gradient<N_SIZE> >& resItem = WorkVec(i);
1343 
1344  for (index_type j = resItem.dCoef.iGetStartIndexLocal(); j < resItem.dCoef.iGetEndIndexLocal(); ++j) {
1345  index_type iDofIndex = resItem.dCoef.iGetGlobalDof(j);
1346  InsertItem(JacItem(resItem.iEquIndex, iDofIndex, resItem.dCoef.dGetDerivativeLocal(j)));
1347  }
1348  }
1349 
1350  return *this;
1351  }
1352 
1353  void ResizeReset(int iNumItems) {
1354  WorkMat.resize(iNumItems);
1355  }
1356 
1357  int iGetSize() const { return WorkMat.size(); }
1358 
1359  void InsertItem(const JacItem& item) {
1360  WorkMat.push_back(item);
1361  }
1362 
1363  void AddTo(Array<doublereal, 2>& JacMat) const {
1364  for (const_iterator j = begin(); j != end(); ++j) {
1365  JacMat(j->iEquIndex, j->iDofIndex) += j->dCoef;
1366  }
1367  }
1368  const_iterator begin() const { return WorkMat.begin(); }
1369  const_iterator end() const { return WorkMat.end(); }
1370 
1371 private:
1372  VectorType WorkMat;
1373 };
1374 
1375 class Element {
1376 public:
1377  virtual blitz::Array<ResItem<doublereal>, 1>& AssRes(blitz::Array<ResItem<doublereal>, 1>& WorkVec, doublereal dCoef)=0;
1378  virtual SparseSubMatrixHandler& AssJac(SparseSubMatrixHandler& WorkMat, doublereal dCoef)=0;
1379  virtual FullSubMatrixHandler& AssJac(FullSubMatrixHandler& WorkMat, doublereal dCoef)=0;
1380  virtual index_type iGetNumRows() const=0;
1381  virtual index_type iGetNumCols() const=0;
1382  virtual ~Element() { }
1383 };
1384 
1385 class Element1: public Element {
1386 private:
1387  Node* node1;
1388  Node* node2;
1389  TinyVector<doublereal, 3> o1, o2;
1390  TinyMatrix<doublereal, 3, 3> S, D;
1391  static const int NADVars = 12;
1392  LocalDofMap dofMap;
1393 
1394 public:
1395  Element1(Node* node1_,
1396  const TinyVector<doublereal, 3>& o1_,
1397  Node* node2_,
1398  const TinyVector<doublereal, 3>& o2_,
1399  doublereal s,
1400  doublereal d)
1401  :node1(node1_),
1402  node2(node2_),
1403  o1(o1_),
1404  o2(o2_),
1405  dofMap(iGetNumCols()) {
1406 
1407  S.initialize(0.);
1408  D.initialize(0.);
1409 
1410  /*
1411  S=[ s, -s, 0;
1412  -s, 2*s, -s;
1413  0, -s, 2*s];
1414  */
1415 
1416  S(0, 0) = s;
1417  S(1, 0) = -s;
1418  S(0, 1) = -s;
1419  S(1, 1) = 2*s;
1420  S(2, 1) = -s;
1421  S(1, 2) = -s;
1422  S(2, 2) = 2*s;
1423 
1424  /*
1425  D=[ d, -d, 0;
1426  -d, 2 * d, -d;
1427  0, -d, 2 * d];
1428  */
1429 
1430  D(0, 0) = d;
1431  D(1, 0) = -d;
1432  D(0, 1) = -d;
1433  D(1, 1) = 2*d;
1434  D(2, 1) = -d;
1435  D(1, 2) = -d;
1436  D(2, 2) = 2*d;
1437  }
1438 
1439  template <typename T>
1440  Array<ResItem<T>, 1>& AssRes(Array<ResItem<T>, 1>& WorkVec, doublereal dCoef, LocalDofMap *pDofMap) {
1441  WorkVec.resize(iGetNumRows());
1442 
1443  TinyVector<T, 3> X1, X2, V1, V2, W1, W2;
1444  TinyMatrix<T, 3, 3> R1, R2;
1445 
1446  node1->GetXCurr(X1, pDofMap);
1447  node1->GetVCurr(V1, pDofMap);
1448  node1->GetRCurr(R1, pDofMap);
1449  node1->GetWCurr(W1, pDofMap);
1450  node2->GetXCurr(X2, pDofMap);
1451  node2->GetVCurr(V2, pDofMap);
1452  node2->GetRCurr(R2, pDofMap);
1453  node2->GetWCurr(W2, pDofMap);
1454 
1455  const TinyVector<T, 3> R1o1 = product(R1, o1);
1456  const TinyVector<T, 3> R2o2 = product(R2, o2);
1457  const TinyMatrix<T, 3, 3> R1_T = transpose(R1);
1458  const TinyVector<T, 3> dX = product(R1_T, TinyVector<T, 3>(X1 + R1o1 - X2 - R2o2));
1459  const TinyVector<T, 3> dV = product(R1_T, TinyVector<T, 3>(V1 + cross(W1, R1o1) - V2 - cross(W2, R2o2)));
1460  const TinyVector<T, 3> F1 = product(R1, TinyVector<T, 3>(product(-S, dX) - product(D, dV)));
1461  const TinyVector<T, 3> M1 = cross(R1o1, F1), M2 = -cross(R2o2, F1);
1462 
1463  for (int i = 0; i < 6; ++i) {
1464  WorkVec(i).iEquIndex = node1->iGetFirstIndex() + i;
1465  WorkVec(i + 6).iEquIndex = node2->iGetFirstIndex() + i;
1466  }
1467 
1468  for (int i = 0; i < 3; ++i) {
1469  WorkVec(i).dCoef = F1(i);
1470  WorkVec(i + 3).dCoef = M1(i);
1471  WorkVec(i + 6).dCoef = -F1(i);
1472  WorkVec(i + 9).dCoef = M2(i);
1473  }
1474 
1475  return WorkVec;
1476  }
1477 
1478  virtual Array<ResItem<doublereal>, 1>& AssRes(Array<ResItem<doublereal>, 1>& WorkVec, doublereal dCoef) {
1479  return AssRes(WorkVec, dCoef, 0);
1480  }
1481 
1482  virtual SparseSubMatrixHandler& AssJac(SparseSubMatrixHandler& WorkMat, doublereal dCoef) {
1483  Array<ResItem<Gradient<NADVars> >, 1> WorkVec;
1484  return WorkMat.AssJac(this, &dofMap, WorkVec, dCoef);
1485  }
1486 
1487  virtual FullSubMatrixHandler& AssJac(FullSubMatrixHandler& WorkMat, doublereal dCoef) {
1488  WorkMat.ResizeReset(iGetNumRows(), iGetNumCols());
1489 
1490  for (int i = 0; i < 6; ++i) {
1491  WorkMat.PutColIndex(i, node1->iGetFirstIndex() + i);
1492  WorkMat.PutColIndex(i + 6, node2->iGetFirstIndex() + i);
1493  WorkMat.PutRowIndex(i, node1->iGetFirstIndex() + i);
1494  WorkMat.PutRowIndex(i + 6, node2->iGetFirstIndex() + i);
1495  }
1496 
1497  const TinyVector<doublereal, 3>& W1_0 = node1->GetWRef();
1498  const TinyVector<doublereal, 3>& W2_0 = node2->GetWRef();
1499  const TinyMatrix<doublereal, 3, 3>& R1_0 = node1->GetRRef();
1500  const TinyMatrix<doublereal, 3, 3>& R2_0 = node2->GetRRef();
1501 
1502  TinyVector<doublereal, 3> X1, X2, V1, V2, W1, W2;
1503  TinyMatrix<doublereal, 3, 3> R1, R2;
1504 
1505  node1->GetXCurr(X1, 0);
1506  node1->GetVCurr(V1, 0);
1507  node1->GetRCurr(R1, 0);
1508  node1->GetWCurr(W1, 0);
1509 
1510  node2->GetXCurr(X2, 0);
1511  node2->GetVCurr(V2, 0);
1512  node2->GetRCurr(R2, 0);
1513  node2->GetWCurr(W2, 0);
1514 
1515  const TinyMatrix<doublereal, 3, 3> skew_W2_0 = skew(W2_0);
1516  const TinyVector<doublereal, 3> R1o1 = product(R1, o1);
1517  const TinyMatrix<doublereal, 3, 3> skew_R1o1 = skew(R1o1);
1518  const TinyVector<doublereal, 3> R1_0o1 = product(R1_0, o1);
1519  const TinyMatrix<doublereal, 3, 3> skew_R1_0o1 = skew(R1_0o1);
1520  const TinyVector<doublereal, 3> R2o2 = product(R2, o2);
1521  const TinyMatrix<doublereal, 3, 3> skew_R2o2 = skew(R2o2);
1522  const TinyVector<doublereal, 3> R2_0o2 = product(R2_0, o2);
1523  const TinyMatrix<doublereal, 3, 3> skew_R2_0o2 = skew(R2_0o2);
1524  const TinyMatrix<doublereal, 3, 3> R1_T = transpose(R1);
1525  const TinyVector<doublereal, 3> dX = product(R1_T, TinyVector<doublereal, 3>(X1 + R1o1 - X2 - R2o2));
1526  const TinyVector<doublereal, 3> dV = product(R1_T, TinyVector<doublereal, 3>(V1 + cross(W1, R1o1) - V2 - cross(W2, R2o2)));
1527  const TinyVector<doublereal, 3> F1_R1 = -(product(S, dX) + product(D, dV));
1528  const TinyVector<doublereal, 3> F1 = product(R1, F1_R1);
1529  const TinyVector<doublereal, 3> F2 = -F1;
1530  const TinyVector<doublereal, 3> M1 = cross(R1o1, F1), M2 = -cross(R2o2, F1);
1531  const TinyMatrix<doublereal, 3, 3> R1_0_T = transpose(R1_0);
1532  const TinyMatrix<doublereal, 3, 3> dF1_dX1 = product(R1, product(-S, R1_T));
1533 
1534  const TinyMatrix<doublereal, 3, 3> ddX_dg1 = product(R1_0_T, skew(TinyVector<doublereal, 3>(X1 + R1o1 - X2 - R2o2))) - product(R1_T, skew_R1_0o1);
1535  const TinyMatrix<doublereal, 3, 3> ddV_dg1 = product(R1_0_T, skew(TinyVector<doublereal, 3>(V1 + cross(W1, R1o1) - V2 - cross(W2, R2o2))))
1536  + product(R1_T, TinyMatrix<doublereal, 3, 3>(product(skew(R1o1), skew(W1_0)) - product(skew(W1), skew_R1_0o1)));
1537  const TinyMatrix<doublereal, 3, 3> dF1_dg1 = skew(TinyVector<doublereal, 3>(product(R1_0, TinyVector<doublereal, 3>(-F1_R1))))
1538  - TinyMatrix<doublereal, 3, 3>(product(R1, TinyMatrix<doublereal, 3, 3>(product(S, ddX_dg1) + product(D, ddV_dg1))));
1539 
1540  const TinyMatrix<doublereal, 3, 3> dF1_dX2 = product(R1, product(S, R1_T));
1541  const TinyMatrix<doublereal, 3, 3> ddX_dg2 = product(R1_T, skew_R2_0o2);
1542  const TinyMatrix<doublereal, 3, 3> ddV_dg2 = product(R1_T, TinyMatrix<doublereal, 3, 3>(product(skew_R2o2, -skew_W2_0)) + TinyMatrix<doublereal, 3, 3>(product(skew_W2_0, skew_R2_0o2)));
1543  const TinyMatrix<doublereal, 3, 3> dF1_dg2 = -product(R1, product(S, ddX_dg2) + product(D, ddV_dg2));
1544 
1545  const TinyMatrix<doublereal, 3, 3> dF2_dX1 = -dF1_dX1;
1546  const TinyMatrix<doublereal, 3, 3> dF2_dg1 = -dF1_dg1;
1547  const TinyMatrix<doublereal, 3, 3> dF2_dX2 = -dF1_dX2;
1548  const TinyMatrix<doublereal, 3, 3> dF2_dg2 = -dF1_dg2;
1549 
1550  const TinyMatrix<doublereal, 3, 3> dM1_dX1 = product(skew_R1o1, dF1_dX1);
1551  const TinyMatrix<doublereal, 3, 3> dM1_dg1 = product(skew(F1), skew_R1_0o1) + product(skew_R1o1, dF1_dg1);
1552  const TinyMatrix<doublereal, 3, 3> dM1_dX2 = product(skew_R1o1, dF1_dX2);
1553  const TinyMatrix<doublereal, 3, 3> dM1_dg2 = product(skew_R1o1, dF1_dg2);
1554 
1555  const TinyMatrix<doublereal, 3, 3> dM2_dX1 = product(skew_R2o2, dF2_dX1);
1556  const TinyMatrix<doublereal, 3, 3> dM2_dg1 = product(skew_R2o2, dF2_dg1);
1557  const TinyMatrix<doublereal, 3, 3> dM2_dX2 = product(skew_R2o2, dF2_dX2);
1558  const TinyMatrix<doublereal, 3, 3> dM2_dg2 = product(skew(F2), skew_R2_0o2) + product(skew_R2o2, dF2_dg2);
1559 
1560  const TinyMatrix<doublereal, 3, 3> dF1_dV1 = product(R1, product(-D, R1_T));
1561  const TinyMatrix<doublereal, 3, 3> ddV_dgP1 = product(-R1_T, skew_R1o1);
1562  const TinyMatrix<doublereal, 3, 3> dF1_dgP1 = product(R1, product(-D, ddV_dgP1));
1563  const TinyMatrix<doublereal, 3, 3> dF1_dV2 = product(R1, product(D, R1_T));
1564  const TinyMatrix<doublereal, 3, 3> ddV_dgP2 = product(R1_T, skew_R2o2);
1565  const TinyMatrix<doublereal, 3, 3> dF1_dgP2 = product(R1, product(-D, ddV_dgP2));
1566 
1567  const TinyMatrix<doublereal, 3, 3> dM1_dV1 = product(skew_R1o1, dF1_dV1);
1568  const TinyMatrix<doublereal, 3, 3> dM1_dgP1 = product(skew_R1o1, dF1_dgP1);
1569  const TinyMatrix<doublereal, 3, 3> dM1_dV2 = product(skew_R1o1, dF1_dV2);
1570  const TinyMatrix<doublereal, 3, 3> dM1_dgP2 = product(skew_R1o1, dF1_dgP2);
1571 
1572  const TinyMatrix<doublereal, 3, 3> dF2_dV1 = -dF1_dV1;
1573  const TinyMatrix<doublereal, 3, 3> dF2_dgP1 = -dF1_dgP1;
1574  const TinyMatrix<doublereal, 3, 3> dF2_dV2 = -dF1_dV2;
1575  const TinyMatrix<doublereal, 3, 3> dF2_dgP2 = -dF1_dgP2;
1576 
1577  const TinyMatrix<doublereal, 3, 3> dM2_dV1 = product(skew_R2o2, dF2_dV1);
1578  const TinyMatrix<doublereal, 3, 3> dM2_dgP1 = product(skew_R2o2, dF2_dgP1);
1579  const TinyMatrix<doublereal, 3, 3> dM2_dV2 = product(skew_R2o2, dF2_dV2);
1580  const TinyMatrix<doublereal, 3, 3> dM2_dgP2 = product(skew_R2o2, dF2_dgP2);
1581 
1582  for (int i = 0; i < 3; ++i) {
1583  for (int j = 0; j < 3; ++j) {
1584  WorkMat.PutCoef(i, j, -dF1_dV1(i, j) - dCoef * dF1_dX1(i, j));
1585  WorkMat.PutCoef(i, j + 3, -dF1_dgP1(i, j) - dCoef * dF1_dg1(i, j));
1586  WorkMat.PutCoef(i, j + 6, -dF1_dV2(i, j) - dCoef * dF1_dX2(i, j));
1587  WorkMat.PutCoef(i, j + 9, -dF1_dgP2(i, j) - dCoef * dF1_dg2(i, j));
1588 
1589  WorkMat.PutCoef(i + 3, j, -dM1_dV1(i, j) - dCoef * dM1_dX1(i, j));
1590  WorkMat.PutCoef(i + 3, j + 3, -dM1_dgP1(i, j) - dCoef * dM1_dg1(i, j));
1591  WorkMat.PutCoef(i + 3, j + 6, -dM1_dV2(i, j) - dCoef * dM1_dX2(i, j));
1592  WorkMat.PutCoef(i + 3, j + 9, -dM1_dgP2(i, j) - dCoef * dM1_dg2(i, j));
1593 
1594  WorkMat.PutCoef(i + 6, j, -dF2_dV1(i, j) - dCoef * dF2_dX1(i, j));
1595  WorkMat.PutCoef(i + 6, j + 3, -dF2_dgP1(i, j) - dCoef * dF2_dg1(i, j));
1596  WorkMat.PutCoef(i + 6, j + 6, -dF2_dV2(i, j) - dCoef * dF2_dX2(i, j));
1597  WorkMat.PutCoef(i + 6, j + 9, -dF2_dgP2(i, j) - dCoef * dF2_dg2(i, j));
1598 
1599  WorkMat.PutCoef(i + 9, j, -dM2_dV1(i, j) - dCoef * dM2_dX1(i, j));
1600  WorkMat.PutCoef(i + 9, j + 3, -dM2_dgP1(i, j) - dCoef * dM2_dg1(i, j));
1601  WorkMat.PutCoef(i + 9, j + 6, -dM2_dV2(i, j) - dCoef * dM2_dX2(i, j));
1602  WorkMat.PutCoef(i + 9, j + 9, -dM2_dgP2(i, j) - dCoef * dM2_dg2(i, j));
1603  }
1604  }
1605  return WorkMat;
1606  }
1607 
1608  index_type iGetNumRows() const { return 12; }
1609  index_type iGetNumCols() const { return NADVars; }
1610 };
1611 
1612 TinyMatrix<doublereal, 3, 3> Euler123ToMatR(const TinyVector<doublereal, 3>& v) {
1613  doublereal d = v(0);
1614  doublereal dCosAlpha(cos(d));
1615  doublereal dSinAlpha(sin(d));
1616  d = v(1);
1617  doublereal dCosBeta(cos(d));
1618  doublereal dSinBeta(sin(d));
1619  d = v(2);
1620  doublereal dCosGamma(cos(d));
1621  doublereal dSinGamma(sin(d));
1622 
1623  TinyMatrix<doublereal, 3, 3> R;
1624 
1625 
1626  R(0, 0) = dCosBeta*dCosGamma;
1627  R(1, 0) = dCosAlpha*dSinGamma + dSinAlpha*dSinBeta*dCosGamma;
1628  R(2, 0) = dSinAlpha*dSinGamma - dCosAlpha*dSinBeta*dCosGamma;
1629  R(0, 1) = -dCosBeta*dSinGamma;
1630  R(1, 1) = dCosAlpha*dCosGamma - dSinAlpha*dSinBeta*dSinGamma;
1631  R(2, 1) = dSinAlpha*dCosGamma + dCosAlpha*dSinBeta*dSinGamma;
1632  R(0, 2) = dSinBeta;
1633  R(1, 2) = -dSinAlpha*dCosBeta;
1634  R(2, 2) = dCosAlpha*dCosBeta;
1635 
1636  return R;
1637 }
1638 
1639 void testAssembly() {
1640  doublereal tckRes = 0;
1641  doublereal tckJacAD = 0;
1642  doublereal tckJac = 0;
1643  doublereal tckStart;
1644  long iIterCnt = 0;
1645  tic(tckStart);
1646 
1647  for (int loop = 0; loop < NLoopsAss; ++loop) {
1648  const int iNumNodes = 3;
1649 
1650  Node* nodes[iNumNodes] = { 0 };
1651 
1652  for (int i = 0; i < iNumNodes; ++i) {
1653  TinyVector<doublereal, 3> X0, XP0, Phi0, W0;
1654 
1655  for (int j = 0; j < 3; ++j) {
1656  X0(j) = ((i + 1) * 10 + j + 1);
1657  XP0(j) = ((i + 1) * 1000 + (j + 1) * 100);
1658  Phi0(j) = ((i + 1) * 0.1 + (j + 1) * 0.01);
1659  W0(j) = ((i + 1) * 0.1 + (j + 1) * 0.01);
1660  }
1661 
1662  TinyMatrix<doublereal, 3, 3> R0 = Euler123ToMatR(Phi0);
1663 
1664  nodes[i] = new Node(X0, XP0, R0, W0);
1665  }
1666 
1667  int iNumDof = 0;
1668 
1669  for (int i = 0; i < iNumNodes; ++i) {
1670  nodes[i]->SetFirstDofIndex(iNumDof);
1671  iNumDof += nodes[i]->iGetNumDof();
1672  }
1673 
1674  const int iNumElem = iNumNodes - 1;
1675 
1676  Element* elements[iNumElem] = {0};
1677 
1678  for (int i = 0; i < iNumElem; ++i) {
1679  TinyVector<doublereal, 3> o1, o2;
1680 
1681  o1(0) = 1.;
1682  o1(1) = 2.;
1683  o1(2) = 3.;
1684  o2(0) = 4.;
1685  o2(1) = 5.;
1686  o2(2) = 6.;
1687 
1688  doublereal s = 100 * (i + 1);
1689  doublereal d = 10 * (i + 1);
1690  elements[i] = new Element1(nodes[i], o1, nodes[i + 1], o2, s, d);
1691  }
1692 
1693  Array<doublereal, 1> XCurr(iNumDof), XPrimeCurr(iNumDof);
1694 
1695  XCurr.initialize(0.);
1696  XPrimeCurr.initialize(0.);
1697 
1698  for (int i = 0; i < iNumNodes; ++i) {
1699  nodes[i]->SetValue(XCurr, XPrimeCurr);
1700  }
1701 
1702  Array<ResItem<doublereal>, 1> WorkVec;
1703  SparseSubMatrixHandler WorkMatSp;
1704  FullSubMatrixHandler WorkMatFull;
1705  Array<doublereal, 1> ResVec;
1706  Array<doublereal, 2> JacMatAD, JacMat;
1707 
1708  ResVec.resize(iNumDof);
1709  JacMatAD.resize(iNumDof, iNumDof);
1710  JacMat.resize(iNumDof, iNumDof);
1711 
1712  ResVec.initialize(0.);
1713  JacMatAD.initialize(0.);
1714  JacMat.initialize(0.);
1715 
1716  const doublereal dCoef = 0.001;
1717 
1718  for (int iTime = 0; iTime < 100; ++iTime) {
1719  iIterCnt++;
1720 
1721  for (int i = 0; i < iNumNodes; ++i) {
1722  nodes[i]->Update(XCurr, XPrimeCurr, dCoef);
1723  }
1724 
1725  for (int i = 0; i < iNumElem; ++i) {
1726  tic();
1727 
1728  elements[i]->AssRes(WorkVec, dCoef);
1729 
1730  tckRes += toc();
1731 
1732  for (int j = 0; j < WorkVec.rows(); ++j) {
1733  ResVec(WorkVec(j).iEquIndex) += WorkVec(j).dCoef;
1734  }
1735 
1736  tic();
1737 
1738  elements[i]->AssJac(WorkMatSp, dCoef);
1739 
1740  tckJacAD += toc();
1741 
1742  WorkMatSp.AddTo(JacMatAD);
1743 
1744  tic();
1745 
1746  elements[i]->AssJac(WorkMatFull, dCoef);
1747 
1748  tckJac += toc();
1749 
1750  WorkMatFull.AddTo(JacMat);
1751  }
1752 
1753  for (int i = 0; i < JacMat.rows(); ++i) {
1754  for (int j = 0; j < JacMat.cols(); ++j) {
1755  const doublereal dTol = sqrt(std::numeric_limits<scalar_deriv_type>::epsilon()) * std::max(1., std::max(std::abs(JacMat(i, j)), std::abs(JacMatAD(i, j))));
1756  if(std::abs(JacMat(i, j) - JacMatAD(i, j)) > dTol) {
1757  throw std::runtime_error("testAssembly(): incorrect result");
1758  }
1759  }
1760  }
1761  }
1762 
1763  if (loop == 0) {
1764  std::cout << "ResVec = [" << std::endl;
1765 
1766  for (int i = 0; i < iNumDof; ++i) {
1767  std::cout << setw(10) << ResVec(i) << std::endl;
1768  }
1769 
1770  std::cout << "]" << std::endl;
1771 
1772  std::cout << "JacMatAD = [" << std::endl;
1773 
1774  for (int i = 0; i < iNumDof; ++i) {
1775  for (int j = 0; j < iNumDof; ++j) {
1776  std::cout << setw(10) << std::setprecision(16) << JacMatAD(i, j) << " ";
1777  }
1778  std::cout << std::endl;
1779  }
1780 
1781  std::cout << "]" << std::endl;
1782 
1783  std::cout << "JacMat = [" << std::endl;
1784 
1785  for (int i = 0; i < iNumDof; ++i) {
1786  for (int j = 0; j < iNumDof; ++j) {
1787  std::cout << setw(10) << std::setprecision(16) << JacMat(i, j) << " ";
1788  }
1789  std::cout << std::endl;
1790  }
1791 
1792  std::cout << "]" << std::endl;
1793  }
1794 
1795  for (int i = 0; i < iNumElem; ++i) {
1796  delete elements[i];
1797  }
1798 
1799  for (int i = 0; i < iNumNodes; ++i) {
1800  delete nodes[i];
1801  }
1802  }
1803 
1804  doublereal tckEnd;
1805  tic(tckEnd);
1806  std::cerr << "number of iterations:" << iIterCnt << std::endl;
1807  std::cerr << "AssRes:" << tckRes / iIterCnt << std::endl;
1808  std::cerr << "AssJacAD:" << tckJacAD / iIterCnt << std::endl;
1809  std::cerr << "AssJac:" << tckJac / iIterCnt << std::endl;
1810  std::cerr << "overhead:" << tckJacAD / tckJac << std::endl;
1811  std::cerr << "total time:" << (tckEnd - tckStart) / iIterCnt << std::endl;
1812 }
1813 
1814 } // namespace
1815 #endif
1816 
1817 int main(int argc, char* argv[]) {
1818 #ifdef HAVE_FEENABLEEXCEPT
1819  feenableexcept(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW);
1820 #endif
1821 
1822  if (argc > 1) {
1823  NLoops = atol(argv[1]);
1824  }
1825 
1826  if (argc > 2) {
1827  NLoopsAss = atol(argv[2]);
1828  }
1829 
1830  testRangeVector<0>();
1831  testRangeVector<6>();
1832  testMapVector<0>();
1833  testMapVector<19>();
1834 
1835  for (index_type i = 1; i <= 12; ++i) {
1836  testGradient<0>(i);
1837  }
1838 
1839  testGradient<1>(1);
1840  testGradient<2>(2);
1841  testGradient<4>(4);
1842  testGradient<6>(6);
1843  testGradient<8>(8);
1844  testGradient<10>(10);
1845  testGradient<12>(12);
1846  testGradient2<0>();
1847  testGradient2<3>();
1848 
1849  testGradientCopy(0);
1850  testGradientCopy(1);
1851  testGradientCopy(2);
1852  testGradientCopy(4);
1853  testGradientCopy(6);
1854  testGradientCopy(8);
1855  testGradientCopy(10);
1856  testGradientCopy(15);
1857  testGradientLin<4>(4);
1858  testGradientLin<0>(4);
1859 
1860 #ifdef HAVE_BLITZ
1861  gradAssTest::testAssembly();
1862 #endif
1863 
1864  testDifferentDofMaps<3>(1);
1865  testDifferentDofMaps<4>(2);
1866  testDifferentDofMaps<5>(3);
1867  testDifferentDofMaps<6>(4);
1868  testDifferentDofMaps<7>(5);
1869  testDifferentDofMaps<8>(6);
1870 
1871  for (integer i = 1; i <= 10; ++i) {
1872  testDifferentDofMaps<0>(i);
1873  testDifferentDofMaps<12>(i);
1874  testDifferentDofMaps<14>(i);
1875  testDifferentDofMaps<16>(i);
1876  }
1877 
1878 #ifndef NDEBUG
1879  std::cerr << "All tests passed" << std::endl;
1880 #else
1881  std::cerr << "No tests have been done" << std::endl;
1882 #endif
1883 
1884  std::cerr << "GRADIENT_DEBUG=" << GRADIENT_DEBUG << std::endl;
1885 
1886  return 0;
1887 }
void SetVectorValue(index_type i, const vector_type &d)
Definition: gradient.h:529
scalar_deriv_type dGetDerivativeGlobal(index_type iGlobalDof) const
Definition: gradient.h:2532
bool bIsEqual(const Gradient &g) const
Definition: gradient.h:2604
scalar_func_type dGetValue(scalar_func_type d)
Definition: gradient.h:2845
void PutColIndex(integer iSubCol, integer iCol)
Definition: submat.h:325
index_type iGetStartIndexLocal() const
Definition: gradient.h:2576
void testMapVector()
index_type Size() const
Definition: gradient.h:1128
GradientExpression< BinaryExpr< FuncPow, LhsExpr, RhsExpr > > pow(const GradientExpression< LhsExpr > &u, const GradientExpression< RhsExpr > &v)
Definition: gradient.h:2961
void Reserve(index_type iMaxSizeNew)
Definition: gradient.h:487
GradientExpression< UnaryExpr< FuncSin, Expr > > sin(const GradientExpression< Expr > &u)
Definition: gradient.h:2977
Definition: node.h:67
doublereal sec(doublereal x)
index_type iGetEndIndexLocal() const
Definition: gradient.h:1271
double mbdyn_clock_time()
Definition: clock_time.cc:51
int main(int argc, char *argv[])
MatrixHandler & AddTo(MatrixHandler &MH) const
Definition: submat.cc:604
void PutCoef(integer iRow, integer iCol, const doublereal &dCoef)
Definition: submat.h:672
integer index_type
Definition: gradient.h:104
index_type iGetStartIndexLocal() const
Definition: gradient.h:1270
Definition: matvec3.h:50
MatrixHandler & AddTo(MatrixHandler &MH) const
Definition: submat.cc:1415
void testGradientLin(int N)
GradientExpression< UnaryExpr< FuncFabs, Expr > > fabs(const GradientExpression< Expr > &u)
Definition: gradient.h:2973
void ResizeReset(index_type iStartNew, index_type iEndNew, const T &dVal)
Definition: gradient.h:451
#define GRADIENT_DEBUG
Definition: gradienttest.cc:71
void tic()
index_type iGetStartIndexVector() const
Definition: gradient.h:497
void func(const T &u, const T &v, const T &w, doublereal e, T &f)
doublereal toc()
void SetDerivativeGlobal(index_type iGlobalDof, scalar_deriv_type dCoef)
Definition: gradient.h:2566
doublereal random1()
Definition: gradienttest.cc:86
index_type iGetEndIndexVector() const
Definition: gradient.h:498
void testDifferentDofMaps(index_type N)
void testGradientCopy(int N)
GradientExpression< BinaryExpr< FuncMinus, LhsExpr, RhsExpr > > operator-(const GradientExpression< LhsExpr > &u, const GradientExpression< RhsExpr > &v)
Definition: gradient.h:2958
GradientExpression< UnaryExpr< FuncLog, Expr > > log(const GradientExpression< Expr > &u)
Definition: gradient.h:2976
static const char * dof[]
Definition: drvdisp.cc:195
void func_tmp(const T &u, const T &v, const T &w, doublereal e, T &f)
void funcDeriv(index_type N, doublereal u, const doublereal ud[], doublereal v, const doublereal vd[], doublereal w, const doublereal wd[], doublereal e, doublereal &f, doublereal fd[])
void SetValuePreserve(scalar_func_type dVal)
Definition: gradient.h:2511
index_type iGetGlobalDof(index_type iLocal) const
Definition: gradient.h:1061
bool bCompare(const T &a, const T &b, doublereal dTolRel=0.)
Definition: gradienttest.cc:91
int NLoopsAss
Definition: gradienttest.cc:80
void func3(const Matrix< T, 3, 3 > &R1, const Matrix< T, 3, 3 > &R2, const Vector< T, 3 > &a, const Vector< T, 3 > &b, Vector< T, 3 > &c, doublereal e)
Definition: matvectest.cc:356
GradientExpression< UnaryExpr< FuncSqrt, Expr > > sqrt(const GradientExpression< Expr > &u)
Definition: gradient.h:2974
void DerivativeResizeReset(LocalDofMap *pMap, index_type iStartGlobal, index_type iEndGlobal, MapVectorBase::GlobalScope s, scalar_deriv_type dVal)
Definition: gradient.h:2538
const int I3
Definition: matvectest.cc:1787
virtual void ResizeReset(integer, integer)
Definition: submat.cc:182
GradientExpression< BinaryExpr< FuncPlus, LhsExpr, RhsExpr > > operator+(const GradientExpression< LhsExpr > &u, const GradientExpression< RhsExpr > &v)
Definition: gradient.h:2957
static int nodes
virtual unsigned int iGetNumDof(void) const =0
GradientExpression< DirectExpr< Gradient< N_SIZE >, true > > Alias(const Gradient< N_SIZE > &g)
Definition: gradient.h:2866
index_type iGetStartIndex() const
Definition: gradient.h:493
Matrix< T, 3, 3 > & Euler123ToMatR(const Vector< T, 3 > &v, Matrix< T, 3, 3 > &R)
Definition: matvectest.cc:1790
vector_type GetVectorValue(index_type i) const
Definition: gradient.h:520
void testRangeVector()
void PutRowIndex(integer iSubRow, integer iRow)
Definition: submat.h:311
Definition: matvec3.h:49
const int I2
Definition: matvectest.cc:1787
scalar_type dGetLocalVector(index_type i) const
Definition: gradient.h:1265
GradientExpression< UnaryExpr< FuncCos, Expr > > cos(const GradientExpression< Expr > &u)
Definition: gradient.h:2978
scalar_func_type dGetValue() const
Definition: gradient.h:2502
static const doublereal a
Definition: hfluid_.h:289
doublereal dStartTime
scalar_type GetValue(index_type i) const
Definition: gradient.h:502
void testGradient(index_type N)
scalar_deriv_type dGetDerivativeLocal(index_type iLocalDof) const
Definition: gradient.h:2516
virtual void SetValue(DataManager *pDM, VectorHandler &X, VectorHandler &XP, SimulationEntity::Hints *h=0)
Definition: simentity.cc:63
double doublereal
Definition: colamd.c:52
long int integer
Definition: colamd.c:51
index_type iGetEndIndexLocal() const
Definition: gradient.h:2580
GradientExpression< UnaryExpr< FuncTan, Expr > > tan(const GradientExpression< Expr > &u)
Definition: gradient.h:2979
#define GRADIENT_ASSERT(expr)
Definition: gradient.h:74
int NLoops
Definition: gradienttest.cc:79
void SetValue(index_type i, const scalar_type &d)
Definition: gradient.h:511
void testGradient2()
const int I1
Definition: matvectest.cc:1787
index_type iGetEndIndex() const
Definition: gradient.h:494
Mat3x3 R
void ResizePreserve(index_type iStartNew, index_type iEndNew)
Definition: gradient.h:461
virtual void Update(const VectorHandler &XCurr, const VectorHandler &XPrimeCurr)
Definition: simentity.cc:98