XALM  1.0
 Vše Třídy Prostory jmen Soubory Funkce Proměnné Výčty Hodnoty výčtu Friends Definice maker
xalm.cpp
Zobrazit dokumentaci tohoto souboru.
1 #include "xalm.h"
2 #include "gelib.h"
3 #include "arrays.h"
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 
8 
9 namespace xalm {
10 
11 // *****************************************************************************************
12 // ************************* VEŘEJNÉ METODY ************************
13 // *****************************************************************************************
16 {
17  step = 0;
18  loadLevel = 0.0;
19  status = 0;
20 
22  xalm_NR_ModeTick = -1; // do not swith to xalm_NR_OldMode
23  xalm_MANRMSteps = 0;
24 
25  nsteps = 0;
27  nsMin = 0;
28  nsReq = 5;
29  nsMax = 60;
30 
31  Psi = 0.0; // displacement control on
32  //Psi = 1.0; // load control on
33 
34  verbose = 1;
35  rtolf = rtold = 1.e-3;
36 
37  neq = -1;
38 
39  // Variables for Hyper Plane Control
40  xalm_Control = xalm_hpc_off; // HPControl is not default
41 }
42 
45 {
46 
47 }
48 
49 
50 // *****************************************************************************************
51 // ************************* CHRÁNĚNÉ METODY A ATRIBUTY ************************
52 // *****************************************************************************************
55 {
56  if (neq == -1) _errorr("Number of equations was not set.");
57 
60 
63 
66 
67  //internalForcesEBENorm.resize_ignore_vals(neq);
68  //internalForcesEBENorm.zero();
69 
71 }
72 
73 
74 
76 int XALM :: solve (void)
77 {
78  // zde se inicializuji pocatecni nastaveni tridy XALM, alokuji a resizuji pole
79  // tato fce musi byt v kazde XALM_interface tride
80  this->initialize();
81 
82  // Nastavení soukromých atributů a kontrola konzistence zadání.
84 
85  status = 1;
86 
87  // Iterační smyčka.
88  for (step = 0; step <nsteps; step++) {
92 
93  if (status == 0) break;
94 
95  this->update_step();
96  }
97 
98  return status;
99 }
100 
107 void XALM :: solve_step (Dvctr *R, Dvctr *R0, Dvctr *X, Dvctr *dX, Dvctr *F, long step)
108 {
109  Dvctr rhs, deltaXt, deltaX_, dXm1, ddX;
110  Dvctr XInitial;
111 
112  double XX, RR, RR0, XR, p;
113  double deltaLambda, Lambda, eta, DeltaLambdam1, DeltaLambda;
114  double deltaL;
115  double drProduct;
116  int irest = 0;
117  int HPsize, i, ind;
118  double _RR, _XX;
119  bool converged, errorOutOfRangeFlag;
120 
121  //
122  deltaL = this->initialStepLength;
123 
124  if (verbose) fprintf(stdout, "XALM: Initial step length: %-15e\n", deltaL);
125  if (verbose) fprintf(stdout, "XALM: Iteration LoadLevel ForceError DisplError \n");
126  if (verbose) fprintf(stdout, "----------------------------------------------------------------------------\n");
127 
128 
129  //
130  if ( xalm_NR_ModeTick == 0 )
132  else
133  if ( xalm_NR_ModeTick > 0 )
135 
136  // zaloha pro pripad restartu
137  XInitial.beCopyOf(X);
138 
139  ddX .resize_ignore_vals(neq); ddX .zero();
140  deltaXt.resize_ignore_vals(neq); deltaXt.zero();
141 
142 
148 
149  if ( R0 ) RR0 = R0->compute_squared_norm();
150  else RR0 = 0.0;
151 
152  //
153  // A initial step (predictor)
154  //
155  //
156 
157  //
158  // A.2. We assume positive-definitive (0)Kt (tangent stiffness mtrx).
159  //
160  RR = R->compute_squared_norm();
161 
162  restart:
163  //
164  // A.1. calculation of (0)VarRt
165  //
166  dX->zero();
168  this->lineq_solve(&deltaXt, R);
169 
170  p = 0.0;
171  if ( xalm_Control == xalm_hpc_off ) {
172  XX = deltaXt.compute_squared_norm();
173  p = sqrt(XX + Psi * Psi * RR);
174  }
175  else if ( xalm_Control == xalm_hpc_on ) {
177  _XX = 0;
178  _RR = 0;
179  for (i=0; i < HPsize; i++) {
180  if ( ( ind = xalm_HPCIndirectDofMask[i] - 1 ) != 0 ) {
181  _XX += deltaXt[ind] * deltaXt[ind];
182  _RR += (*R)[ind] * (*R)[ind];
183  }
184  }
185 
186  p = sqrt(_XX + Psi * Psi * _RR);
187  }
188  else if ( xalm_Control == xalml_hpc ) {
190  p = 0.;
191  for (i=0; i < HPsize; i++) {
192  if ( ( ind = xalm_HPCIndirectDofMask[i] -1 ) != 0 ) {
193  p += deltaXt[ind] * xalm_HPCWeights[i];
194  }
195  }
196 
197  }
198 
199  XR = deltaXt.give_dotproduct(*R);
200 
201  /* XR is unscaled Bergan's param of current stiffness XR = deltaXt^T k deltaXt
202  * this is used to test whether k has negative or positive slope */
203 
204  Lambda = loadLevel;
205  DeltaLambda = deltaLambda = sgn(XR) * deltaL / p;
206  Lambda += DeltaLambda;
207  //
208  // A.3.
209  //
210 
211  rhs.beCopyOf(R);
212  rhs.tmsby(DeltaLambda);
213  if ( R0 ) {
214  rhs.add(*R0);
215  }
216  this->lineq_solve(dX, &rhs);
217 
218  X->add(*dX);
219 
221 
222  int nite = 0;
223 
224  do {
225  nite++;
226  dXm1.beCopyOf(dX);
227  DeltaLambdam1 = DeltaLambda;
228 
229  // Sestavení nové tečné matice tuhosti a deltaXt.
230  if ( ( xalm_NR_Mode == xalm_fullNRM ) || ( xalm_NR_Mode == xalm_accelNRM && nite % xalm_MANRMSteps == 0 ) ) {
232  this->lineq_solve(&deltaXt, R);
233  }
234 
235  rhs.beCopyOf(R);
236  rhs.tmsby(Lambda);
237  if (R0) rhs.add(*R0);
238 
239  rhs.sbt(*F);
240  deltaX_.resize_ignore_vals(neq);
241 
242  this->lineq_solve(&deltaX_, &rhs);
243  eta = 1.0;
244  //
245  if ( this->computeDeltaLambda(deltaLambda, * dX, deltaXt, deltaX_, * R, RR, eta, deltaL, DeltaLambda, neq) ) {
246  irest++;
247 
248  // Problem konvergence, snížení délky kroku a restart.
249  if ( irest <= XALM_MAX_RESTARTS ) {
250  status = 2;
251  deltaL = deltaL * XALM_RESET_STEP_REDUCE;
252  if ( deltaL < minStepLength )
253  deltaL = minStepLength;
254 
255  // Znovunastavení počátečních hodnot.
256  X->beCopyOf(XInitial);
257  dX->zero();
259 
260  if (verbose) fprintf(stdout, "XALM: Iteration Reset ...\n");
261 
265  goto restart;
266  }
267  else {
268  if (verbose) _warningg("XALM :: solve - can't continue further");
269  status = 0;
270  return;
271  }
272  }
273 
274  //
275  ddX.resize_ignore_vals(neq);
276  ddX.addtms(deltaXt, eta*deltaLambda);
277  ddX.addtms(deltaX_, eta);
278  dX->beCopyOf(dXm1);
279  dX->add(ddX);
280  X->beCopyOf(XInitial);
281  X->add(*dX);
282 
283  drProduct = ddX.compute_squared_norm();
284 
285  //
286  DeltaLambda = DeltaLambdam1 + deltaLambda;
287  Lambda = loadLevel + DeltaLambda;
288 
290 
291  // Kontrola konvergence.
292  converged = this->checkConvergence(* R, R0, * F, * X, ddX, Lambda, RR0, RR, drProduct,
293  nite, errorOutOfRangeFlag);
294 
295  if ( ( nite >= nsMax ) || errorOutOfRangeFlag ) {
296  irest++;
297 
298  // Problem konvergence, snížení délky kroku a restart.
299  if ( irest <= XALM_MAX_RESTARTS ) {
300  status = 2;
301  deltaL = deltaL * XALM_RESET_STEP_REDUCE;
302  if ( deltaL < minStepLength )
303  deltaL = minStepLength;
304 
305  // Znovunastavení počátečních hodnot.
306  X->beCopyOf(XInitial);
307  dX->zero();
309 
310  if (verbose) fprintf(stdout, "XALM: Iteration Reset ...\n");
311 
315  goto restart;
316  }
317  else {
318  if (verbose) _warningg("XALM :: solve - can't continue further");
319  status = 0;
320  return;
321  }
322  }
323  } while ( !converged || ( nite < nsMin ) );
324 
325  // Upravení délky kroku, aby bylo dosaženo požadovaného počtu iterací.
326  if ( nite > nsReq ) {
327  deltaL = deltaL * nsReq / nite;
328  }
329  else {
330  deltaL = deltaL * sqrt( sqrt( ( double ) nsReq / ( double ) nite ) );
331  }
332 
333  if (deltaL > maxStepLength) deltaL = maxStepLength;
334  if (deltaL < minStepLength) deltaL = minStepLength;
335 
336  if (verbose) fprintf(stdout, "XALM: Adjusted step length: %-15e\n", deltaL);
337 
338  loadLevel = Lambda;
339 } // end of XALM :: solve
340 
342 bool XALM :: checkConvergence (const Dvctr &R, const Dvctr *R0, const Dvctr &F,
343  const Dvctr &X, const Dvctr &ddX,
344  double Lambda, double RR0, double RR, double drProduct,
345  int nite, bool &errorOutOfRange)
346 {
347  double forceErr, dispErr;
348  Dvctr rhs; // residual of momentum balance eq (unbalanced nodal forces)
349  bool answer;
350 
351  answer = true;
352  errorOutOfRange = false;
353 
354  // compute residual vector
355  rhs.beCopyOf(R);
356 
357  rhs.tmsby(Lambda);
358  if ( R0 ) {
359  rhs.add(*R0);
360  }
361 
362  rhs.sbt(F);
363 
364  //
365  // compute force error(s)
366  //
367  double dXX;
368 
369  // err is relative error of unbalanced forces
370  forceErr = rhs.compute_squared_norm();
371  // err is relative displacement change
372  dXX = X.compute_squared_norm();
373 
374  // double eNorm = internalForcesEBENorm.give_sum();
375  // we compute a relative error norm
376  if ( ( RR0 + RR * Lambda * Lambda ) > XALM_SMALL_ERROR_NUM ) {
377  forceErr = sqrt( forceErr / ( RR0 + RR * Lambda * Lambda ) );
378  }
379  // else if ( eNorm > XALM_SMALL_ERROR_NUM ) {
380  // forceErr = sqrt(forceErr / eNorm );
381  // }
382  else {
383  forceErr = sqrt(forceErr);
384  }
385 
386  //
387  // compute displacement error
388  //
389  if ( dXX < XALM_SMALL_ERROR_NUM ) {
390  dispErr = drProduct;
391  } else {
392  dispErr = drProduct / dXX;
393  dispErr = sqrt(dispErr);
394  }
395 
396  if ( ( fabs(forceErr) > rtolf * XALM_MAX_REL_ERROR_BOUND ) ||
397  ( fabs(dispErr) > rtold * XALM_MAX_REL_ERROR_BOUND ) ) {
398  errorOutOfRange = true;
399  }
400 
401  if ( ( fabs(forceErr) > rtolf ) || ( fabs(dispErr) > rtold ) ) {
402  answer = false;
403  }
404 
405  if (verbose) fprintf (stdout, "XALM: %-15d %-15e %-15e %-15e\n", nite, Lambda, forceErr, dispErr);
406 
407 
408  return answer;
409 }
423 
452 
496 
497 int XALM :: computeDeltaLambda (double &deltaLambda, const Dvctr &dX, const Dvctr &deltaXt,
498  const Dvctr &deltaX_, const Dvctr &R, double RR, double eta,
499  double deltaL, double DeltaLambda0, int neq)
500 {
501  double a1 = 0.0, a2 = 0.0, a3 = 0.0, a4, a5;
502  double _RR, _rr, _a2, _a3, _pr;
503  double lam1, lam2, cos1, cos2;
504  int i, ind, HPsize = 0;
505  Dvctr help;
506  double XX;
507 
508  //
509  // B.3.
510  //
511  if ( ( xalm_Control == xalm_hpc_off ) || ( xalm_Control == xalm_hpc_on ) ) {
512  if ( xalm_Control == xalm_hpc_off ) {
513  // this two lines are necessary if NRM is used
514  // (for MNRM they can be computed at startup A1).
515 
516  XX = deltaXt.compute_squared_norm();
517  a1 = eta * eta * XX + Psi * Psi * RR;
518  a2 = RR * Psi * Psi * DeltaLambda0 * 2.0;
519  a2 += 2.0 * eta * dX.give_dotproduct(deltaXt);
520  a2 += 2.0 * eta * eta * deltaX_.give_dotproduct(deltaXt);
521  a3 = dX.compute_squared_norm();
522  a3 += 2.0 *eta * dX.give_dotproduct(deltaX_);
523  a3 += eta * eta * deltaX_.compute_squared_norm();
524  a3 += DeltaLambda0 * DeltaLambda0 * RR * Psi * Psi - deltaL * deltaL;
525 
526  }
527  else if ( xalm_Control == xalm_hpc_on ) {
529  _rr = 0.;
530  _RR = 0.;
531  _a2 = _a3 = 0.;
532  for ( i = 0; i < HPsize; i++ ) {
533  if ( ( ind = xalm_HPCIndirectDofMask[i] - 1 ) != 0 ) {
534  _rr += deltaXt[ind] * deltaXt[ind];
535  _RR += R[ind] * R[ind];
536  _pr = ( dX[ind] + eta * deltaX_[ind] );
537  _a2 += eta * deltaXt[ind] * _pr;
538  _a3 += _pr * _pr;
539  }
540  }
541 
542  a1 = eta * eta * _rr + Psi * Psi * _RR;
543  a2 = _RR * Psi * Psi * DeltaLambda0 * 2.0;
544  a2 += 2.0 * _a2;
545  a3 = _a3 - deltaL * deltaL + DeltaLambda0 * DeltaLambda0 * _RR * Psi * Psi;
546 
547  //printf ("\na1=%e, a2=%e, a3=%e", a1,a2,a3);
548  }
549 
550  // solution of quadratic eqn.
551  double discr = a2 * a2 - 4.0 * a1 * a3;
552 
553  if ( discr < 0.0 ) {
554  if (verbose) _warningg("XALM :: computeDeltaLambda: discriminant is negative, solution failed");
555  status = 0;
556  }
557 
558  discr = sqrt(discr);
559  lam1 = ( -a2 + discr ) / 2. / a1;
560  lam2 = ( -a2 - discr ) / 2. / a1;
561 
562  // select better lam (according to angle between deltar0 and deltar1(2).
563  //
564  // up to there rewritten
565  //
566  if ( xalm_Control == xalm_hpc_off ) {
567  a4 = eta * dX.give_dotproduct(deltaX_) + dX.compute_squared_norm();
568  a5 = eta * dX.give_dotproduct(deltaXt);
569  }
570  else {
571  a4 = 0.;
572  a5 = 0.;
573  for ( i = 0; i < HPsize; i++ ) {
574  if ( ( ind = xalm_HPCIndirectDofMask[i] - 1 ) != 0 ) {
575  a4 += eta * dX[ind] * deltaX_[ind] + dX[ind] * dX[ind];
576  a5 += eta * dX[ind] * deltaXt[ind];
577  }
578  }
579  }
580 
581  cos1 = ( a4 + a5 * lam1 ) / deltaL / deltaL;
582  cos2 = ( a4 + a5 * lam2 ) / deltaL / deltaL;
583 
584  if ( cos1 > cos2 ) deltaLambda = lam1;
585  else deltaLambda = lam2;
586 
587  //printf ("eta=%e, lam1=%e, lam2=%e", eta, lam1, lam2);
588  }
589  else if ( xalm_Control == xalml_hpc ) {
590  // linearized control
591  double nom = 0., denom = 0.;
592 
594  for ( i = 0; i < HPsize; i++ ) {
595  if ( ( ind = xalm_HPCIndirectDofMask[i] - 1 ) != 0 ) {
596  nom += ( dX[ind] + eta * deltaX_[ind] ) * xalm_HPCWeights[i];
597  denom += eta * deltaXt[ind] * xalm_HPCWeights[i];
598  }
599  }
600 
601  if ( fabs(denom) < XALM_SMALL_NUM ) {
602  if (verbose) _warningg("XALM :: \nxalm: zero denominator in linearized control");
603  status = 0;
604  }
605 
606  deltaLambda = ( deltaL - nom ) / denom;
607  }
608 
609  return 0;
610 }
611 
612 
613 
614 } // namespace xalm
double sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1) ...
Definition: mathlib.h:41
double give_dotproduct(const Dvctr &v) const
Definition: arrays.cpp:386
#define _warningg(_1)
Definition: gelib.h:163
int xalm_NR_ModeTick
Počet kroků zbývajících do konce dočasné změny iteračního schématu.
Definition: xalm.h:99
Dvctr * resize_ignore_vals(long newsize)
Definition: arrays.h:622
double minStepLength
Minimalní délka kroku.
Definition: xalm.h:156
void initialize_and_check_consistency(void)
Funkce pro nastavení soukromých atributů a kontrolu konzistence zadání.
Definition: xalm.cpp:54
General functions.
int nsMin
Minimální počet kroků dorovnání nerovnováhy v jednom iteračním přitěžovacím kroku.
Definition: xalm.h:159
virtual void lineq_solve(Dvctr *X, const Dvctr *R)=0
Linearized ALM (only displacements), taking into account only selected dofs with given weight...
Definition: xalm.h:19
virtual long give_size(void) const
Definition: arrays.h:414
double compute_squared_norm(void) const
Definition: arrays.cpp:491
int verbose
Pokud je větší než nule - budou vypisovány informace.
Definition: xalm.h:163
Definition: xalm.cpp:9
void tmsby(double val)
Definition: arrays.cpp:408
#define XALM_MAX_REL_ERROR_BOUND
Definition: xalm.h:32
int computeDeltaLambda(double &deltaLambda, const Dvctr &dX, const Dvctr &deltaXt, const Dvctr &deltaX_, const Dvctr &R, double RR, double eta, double deltaL, double DeltaLambda0, int neq)
Definition: xalm.cpp:497
int nsReq
Požadovaný počet kroků dorovnání nerovnováhy v jednom iteračním přitěžovacím kroku.
Definition: xalm.h:160
Modifikovaná NR metoda (defaultní hodnota) - matice se počítá jen na začátku každého zatěžovacího kro...
Definition: xalm.h:24
Dvctr initialLoadVector
Vektor pocatecniho zatizeni, nemeni se behem vypoctu, je aplikovan cely.
Definition: xalm.h:171
Lvctr xalm_HPCIndirectDofMask
Definition: xalm.h:122
Dvctr totalDisplacement
Vektor celkových posunutí.
Definition: xalm.h:94
Dvctr incrementOfDisplacement
Vektor přírůstku posunutí.
Definition: xalm.h:95
xalm_NR_ModeType xalm_NR_OldMode
Záloha proměnné xalm_NR_Mode.
Definition: xalm.h:98
Class XALM.
void sbt(const Dvctr &src)
Definition: arrays.cpp:399
int solve(void)
Funkce solve je hlavní, a jediná, výkonná funkce knihovny XALM.
Definition: xalm.cpp:76
#define XALM_DEFAULT_NRM_TICKS
Definition: xalm.h:31
Structs Elem3D, PoinT and VectoR; classes Array, Array1d, Xscal, Dscal, Xvctr, Lvctr, Dvctr, Xmtrx, Lmtrx and Dmtrx.
long nsteps
Počet zatěžovacích kroků.
Definition: xalm.h:155
void beCopyOf(const PoinT &src)
Definition: arrays.h:659
double rtold
Tolerance relativní chyby nevyrovnaných posunů.
Definition: xalm.h:165
double Psi
Parametr kontroly kroku. Pokud je rovno 0, tak se jedná o kontrolu přírůstkem posunutí, pokud je rovno nekonečnu, tak se jedná o kontrolu přírůstkem zatížení.
Definition: xalm.h:162
virtual void update_internal_forces(Dvctr *internalForces, const Dvctr *X)=0
double rtolf
Tolerance relativní chyby nevyrovnaných sil.
Definition: xalm.h:164
bool checkConvergence(const Dvctr &R, const Dvctr *R0, const Dvctr &F, const Dvctr &X, const Dvctr &ddX, double Lambda, double RR0, double RR, double drProduct, int nite, bool &errorOutOfRange)
Kontrola konvergence.
Definition: xalm.cpp:342
#define XALM_SMALL_ERROR_NUM
Definition: xalm.h:35
int nsMax
Maximální počet kroků dorovnání nerovnováhy v jednom iteračním přitěžovacím kroku.
Definition: xalm.h:161
XALM(void)
Constructor.
Definition: xalm.cpp:15
double maxStepLength
Maximalní délka kroku.
Definition: xalm.h:157
Full ALM with quadratic constrain and all dofs.
Definition: xalm.h:17
virtual void initialize(void)=0
Funkce nemá parametry a nic nevrací.
Dvctr incrementalLoadVector
Vektor prirustkoveho zatizeni, meni se se stupnem lambda.
Definition: xalm.h:170
xalm_NR_ModeType xalm_NR_Mode
Proměnná určující strategii, kdy se bude počítat tečná matice tuhosti soustavy.
Definition: xalm.h:153
#define XALM_MAX_RESTARTS
Definition: xalm.h:30
virtual ~XALM(void)
Destructor.
Definition: xalm.cpp:44
#define _errorr(_1)
Definition: gelib.h:160
void zero(void)
Definition: arrays.h:657
double initialStepLength
Počáteční délka kroku.
Definition: xalm.h:158
Plná NR metoda - matice se během zatěžovacího kroku počítá při každé iteraci.
Definition: xalm.h:25
virtual void update_stiffness_matrix(const Dvctr *X)=0
int status
0 - nedopočítáno, 1- spočítáno, 2 - počítáno s problémy, změněn krok
Definition: xalm.h:97
void solve_step(Dvctr *R, Dvctr *R0, Dvctr *X, Dvctr *dX, Dvctr *F, long step)
R - incrementalLoadVector R0 - initialLoadVector.
Definition: xalm.cpp:107
double loadLevel
Dosažený stupeň přírůstkového zatížení.
Definition: xalm.h:93
Dvctr xalm_HPCWeights
Definition: xalm.h:121
#define XALM_SMALL_NUM
Definition: xalm.h:34
void help(void)
prints help / syntax
Definition: xalmtest.cpp:50
Akcelerovaná NR metoda - matice se počítá jen na začátku každého n-tého zatěžovacího kroku...
Definition: xalm.h:26
Dvctr internalForces
Vektor vnitřních sil v uzlech.
Definition: xalm.h:96
void add(const Dvctr &src)
Definition: arrays.cpp:397
virtual void update_step(void)=0
Ve funkci je možné po každém provedeném iteračním kroku vykonat požadované úkony. ...
int step
Aktuální krok.
Definition: xalm.h:92
Full ALM with quadratic constrain, taking into account only selected dofs.
Definition: xalm.h:18
void addtms(const Dvctr &src, double tms)
Definition: arrays.cpp:398
int xalm_MANRMSteps
Počet kroků, po kterých se má znovu počítat matice, pouze pokud xalm_NR_Mode == xalm_accelNRM.
Definition: xalm.h:154
#define XALM_RESET_STEP_REDUCE
Definition: xalm.h:29
long neq
Pocet rovnic v matici soustavy = pocet neznamych.
Definition: xalm.h:169
xalm_ControlType xalm_Control
Definition: xalm.h:120