1 //#**************************************************************
2 //#
3 //# filename: timeint.cpp
4 //#
5 //# author: Gerstmayr Johannes
6 //#
7 //# generated: 09.06.99
8 //# description: Class for implicit and explicit Runge Kutta Time integration,
9 //# variable stepsize and arbitrary order
10 //# remarks: The file tableaus.txt must be provided in Project/Release or Debug !!!
11 //#
12 //# Copyright (c) 2003-2013 Johannes Gerstmayr, Linz Center of Mechatronics GmbH, Austrian
13 //# Center of Competence in Mechatronics GmbH, Institute of Technical Mechanics at the
14 //# Johannes Kepler Universitaet Linz, Austria. All rights reserved.
15 //#
16 //# This file is part of HotInt.
17 //# HotInt is free software: you can redistribute it and/or modify it under the terms of
18 //# the HOTINT license. See folder 'licenses' for more details.
19 //#
20 //# bug reports are welcome!!!
21 //# WWW: www.hotint.org
22 //# email: bug_reports@hotint.org or support@hotint.org
23 //#***************************************************************************************
24
25 //
26 //
27 // TODO:
28 // Add option: continue anyway, even if not converged
29 //
30 //
31 //
32 //
33
34
35 //#include "stdafx.h"
36 #include "ioincludes.h"
37
38 #include <assert.h>
39 #include <string.h>
40 #include <time.h>
41 #include <sys/timeb.h>
42 #include <math.h>
43
44 #include "mystring.h"
45
46 #include "tarray.h" //i1
47 #include "myfile.h" //i1
48
49 //#include "femath.h" //+i2
50 #include "timeint.h"
51 #include "options_auto.h"
52
53 //$ YV 2013-01-03: this cannot be done in this way any longer
54 //#include "..\ElementsLib\contact_globalvariables.h" //access these (extern global) variables for reasons of log-output
55 //double global_time; //global time
56
57 #ifdef gencnt
58 int generated_vectors;
59 int generated_matrices;
60 int * genvec = &generated_vectors;
61 int * genmat = &generated_matrices;
62 #endif
63
64 UserOutputInterface * global_uo;
65
TimeInt()66 TimeInt::TimeInt():stage_tableaus(), tableaus()
67 {
68 //AP 2013-01-15: set global_uo pointer already in constructor,
69 // it is needed in CreateWCDObject() in WorkingModule.cpp,
70 // line 96: pModelsLibrary->SetGlobalVariablesPointers(global_uo, &TMtspent, &TMtstart);
71 global_uo = &UO();
72
73 TIInit();
74 };
75
InitFirst()76 void TimeInt::InitFirst()
77 {
78 //AD: Initialize the paused flag to zero - otherwise pressing the pause button may result in crashes
79 bPause = 0;
80
81 //drawing:
82 transparency_on = 1;
83
84 reduceimage = 1;
85 TIdrawtexres = 4;
86 texImage = NULL;
87 texstorenn = 0;
88 SetTexStoreResolution(3); //32
89
90 InitializeOptions();
91
92 SetJacobianComputationFlag(0);
93
94 //AP 2013-01-15: global_uo pointer is set already in constructor TimeInt()
95 //global_uo = &UO();
96
97 // hook UserOutput object to solver settings
98 //$ YV 2012-12-14: UO() and the actual one are the same, no need to hook
99 /*UO().HookToSolverSettings(& GetOptions()->LoggingOptions()->OutputLevel(), & GetOptions()->LoggingOptions()->FileOutputLevel(), &logout, & GetOptions()->LoggingOptions()->CriticalLogFileSize(), & GetOptions()->LoggingOptions()->MaxErrorMessages(), & GetOptions()->LoggingOptions()->MaxWarningMessages(),
100 & GetOptions()->LoggingOptions()->OutputPrecisionDouble(), & GetOptions()->LoggingOptions()->OutputPrecisionVector(), & GetOptions()->LoggingOptions()->OutputPrecisionMatrix()); //$ PG 2012-2-3: substituted solset.output_level by GetOptions()->LoggingOptions()->OutputLevel()*/
101
102 //called from Working module base class after first initialization
103 //do only once initialization:
104 numsol = NumNLSolver(this, &solset); //solset: set a reference to solset for variables, which show immediate effect of modification during simulation (e.g. logging of newton iterations)
105 //numsol.SetReferenceToSolverOptions(solset);
106
107 TIkv = 1;
108 drawlines = 0;
109 drawlinesh = 0;
110
111 loadfact = 1;
112
113 NLS_SetJacCol(0);
114
115 SetTime(0);
116 TIstep = 0;
117 act_tableau = 1;
118
119 //$ RL 2012-5-29:[ get correct path of tableaus.txt
120 mystr tableaus_file("tableaus.txt");
121 if(__argc>0)
122 {
123 mystr strarg(__argv[0]); // first argument is path of hotint.exe, where also tableaus.txt is located
124 int until;
125 for(until=strarg.Length()-1;until>=0;until--)
126 {
127 if(strarg.PosPeek(until) == '\\')
128 break; // until <=> last backslash
129 }
130 mystr path("");
131 for(int i=0;i<=until;i++)
132 {
133 path += strarg.PosPeek(i); // path until last backslash
134 }
135 tableaus_file = path + "tableaus.txt";
136 }
137 LoadTableaus(tableaus_file);
138 //$ RL 2012-5-29:] get correct path of tableaus.txt
139
140 TMResetTimer();
141 }
142
TIInit()143 void TimeInt::TIInit()
144 {
145 TIsteprecommendation = 1e100;
146
147 TIfinished = 0;
148 TIdrawtime = 0;
149
150 TImincol = 1e30;
151 TImaxcol = -1e30;
152 flag_compute_minmax_FEcol = 0;
153
154 TInoincs = 0;
155 TIwritesolevery = 0.;
156
157 ada_err_sum = 0;
158
159 acterror = 0;
160 acterror_damp = 0;
161 TIm_initialized = 0;
162 bandwidthm = 0;
163 reducedbandsize = 0;
164
165 drawnow = 1;
166 TInumber_of_solution_data_steps = 0; //PG old: .SetLen(0);
167
168 lastloadresults = -1e100;
169 laststoredata = -1e100;
170
171 tidraw_offx = 0.;
172 tidraw_offy = 0.;
173 tidraw_offz = 0.;
174
175 TIissubstep = 0;
176 oldenergy = 0;
177
178 TIcomptime = 0;
179 TItimeperstep = 0;
180 colline = Vector3D(0.1,0.1,0.1);
181
182 log.Init();
183 logout_name = "hotint.log";
184 }
185
SetStartVector(const Vector & x0)186 void TimeInt::SetStartVector(const Vector& x0)
187 {
188 TIx0 = x0;
189 TIx0draw = x0;
190
191 TISaveState(TIlastnonlinit_state);
192
193 if (TIkv)
194 {
195 int sos = GetSecondOrderSize();
196 int es = GetFirstOrderSize();
197 int is = GetImplicitSize();
198
199 TIk0.SetLen(2*sos+es+is);
200 TIk0.SetAll(0);
201 int m_invertable = 0;
202
203 if (sos != 0 && m_invertable)
204 {
205 evalf.SetLen(sos);
206 Matrix m(sos,sos);
207 EvalF2(x0, evalf, TItime); //compute F-Ku-Gv
208 EvalM(x0, m, TItime);
209 Vector xh(sos);
210 if (!m.Invert2()) {uo << "K-version, Init: Mass matrix not invertible!!!" << ENDL;}
211 else {xh = m*evalf;}
212
213 //second order start vector
214 TIk0.Copy(TIx0,1+sos,1,sos);
215 TIk0.Copy(xh,1,1+sos,sos);
216 }
217 //first order start vector
218 if (es != 0)
219 {
220 evalf.SetLen(es);
221 EvalF(x0, evalf, TItime); //compute First order equ.
222 TIk0.Copy(evalf,1,1+2*sos,es);
223 }
224
225 //implicit start vector
226 TIk0.Copy(TIx0,1+2*sos+es,1+2*sos+es,is);
227
228 }
229 }
230
NonlinSubStep()231 int TimeInt::NonlinSubStep()
232 {
233 TMStartTimer(21);
234 int rv = 1;
235 int end = 0;
236 double corerr;
237 int it = 0;
238 TISaveState(TIlastnonlinit_state);
239
240
241 TIdiscontstep = 0;
242
243 //global_time = TItime;
244
245 int olddiscont;
246 while (!end && rv)
247 {
248 olddiscont = TIdiscontstep;
249
250 TIRestoreState(TIlastnonlinit_state);
251
252 it++;
253 log.TInonlinit = it;
254 //Vector f(GetSystemSize());
255
256 rv = GeneralIStep();
257 corerr = PostNewtonStep(TItime);
258
259
260 if (corerr == -1)
261 {
262 rv = 0; end = 1;
263 reduce_order = 2;
264 }
265 else if (corerr < DiscontinuousAccuracy())
266 {
267 end = 1;
268 }
269 else if (TIdiscontstep != olddiscont)
270 {
271 reduce_order = 2;
272 numsol.DestroyOldJac(TIstep);
273 }
274
275
276 if (GetStepRecommendation() < TIstep && TIstep > TIminstep)
277 {
278 end = 2;
279 rv = 0;
280 //uo << "Step Recommendation:" << GetStepRecommendation() << "\n";
281 }
282
283 if (it >= MaxDiscontinuousIt())
284 {
285 end = 1;/* uo << "ERROR to many iterations in nonlinear-corrector iteration!!!" << ENDL;*/
286 if(!solset.ignore_maxdiscontinuousit) rv = 0;
287 }
288 }
289
290 if (end != 2)
291 {
292 PostprocessingStep();
293 }
294 TInonls = it;
295
296 TMStopTimer(21);
297
298 return rv;
299 }
300
301 int flag_applyjac = 0;
302 int minstepwarned = 0;
303 //ofstream errout("..\\..\\output\\comperr.txt");
FullStep()304 int TimeInt::FullStep()
305 {
306 TISaveState(TIlaststep_state); //save state of end of last step (or initial step)
307 SetStepRecommendation(1e100);
308
309 int mode = 3; //1 is single step, 2 is adaptive substep if failure, 3 is adaptive stepreduction
310 StartTimeStep();
311 TIstep = TIstepnew;
312 // AP: TItemp_state is used to save state after StartTimeStep(), for AND this means after transport
313 TISaveState(TItemp_state);
314
315 if (GetStepRecommendation() < TIstepnew)
316 {
317 TIstep = GetStepRecommendation();
318 }
319
320 if (mode == 1)
321 {
322 log.TInewtonit = 0;
323 int rv = NonlinSubStep();
324 FinishStep();
325
326 return rv;
327 }
328 else if (mode == 3)
329 {
330
331 double savestep = TIstep;
332 log.TInewtonit = 0;
333 double TItimeold = TItime;
334 int rv = 0;
335 double it = 0;
336 while (it < 15 && !rv)
337 {
338 it++;
339 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: sub-iteration = ")+mystr(it)+mystr(", time increment = ")+mystr(TIstep)+mystr(", time = ")+mystr(TItime)+mystr("\n");
340 SetStepRecommendation(1e100);
341 //if (TIstep != savestep) numsol.DestroyOldJac(TIstep);
342 if (TItime+TIstep > solset.endtime)
343 {
344 TIstep = solset.endtime - TItime;
345 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: set time increment = ")+mystr(TIstep)+mystr(", otherwise end time would be exceed.\n");
346 }
347
348 rv = NonlinSubStep();
349
350 if (!rv && it < 15)
351 {
352
353 TIRestoreState(TIlaststep_state); //set to old TIx0, reset all internal nonlinear variables
354
355 if (GetStepRecommendation() < TIstep)
356 {
357 TIstep = GetStepRecommendation();
358 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: recommended time increment: ")+mystr(TIstep)+mystr("\n");
359
360 if (it > 3)
361 {
362 TIstep *= 0.5;
363 if (SolverPrintsDetailedOutput()) SolverUO() << "step: time increment multiplied by 0.5\n";
364 }
365 else if (it > 7)
366 {
367 TIstep *= 0.1;
368 if (SolverPrintsDetailedOutput()) SolverUO() << "step: time increment multiplied by 0.1\n";
369 }
370 }
371 else
372 {
373 TIstep *= 0.5;
374 if (SolverPrintsDetailedOutput()) SolverUO() << "step: time increment multiplied by 0.5\n";
375
376 if (TIstep <= TIminstep)
377 {
378 it = 14;
379 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: set sub-iteration = 14 to perform final sub-iteration (max-sub-iterations=15), since time increment ")+mystr(TIstep)+mystr(" is less equal TIminstep=")+mystr(TIminstep)+mystr("\n");
380 }
381 }
382 //?only limit minimum step size in case that step is reduced due to bad convergence
383 if (TIstep < TIminstep)
384 {
385
386 TIstep = TIminstep;
387 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: set time increment to TIminstep=")+mystr(TIminstep)+mystr(", since it's been already smaller than that.\n");
388 }
389 //}
390 }
391 }
392 //if (it > 1) uo << "stepsize = " << TIstep << "\n";
393
394 if (!rv)
395 {
396 if (!minstepwarned) uo << "ERROR: Step at minimal stepsize, step not fully converged. Further warning suppressed!" << ENDL;
397 minstepwarned = 1;
398 //rv = 1;
399 }
400
401 FinishStep();
402
403 TIstep = savestep;
404
405 return rv;
406 }
407 else
408 {
409 double savestep = TIstep;
410 log.TInewtonit = 0;
411 double TItimeold = TItime;
412 int rv = 0;
413
414 double it = 1;
415 double it2 = 1;
416 while ((TIstep > TIminstep || TIstep == TIstepnew) && rv == 0)
417 {
418 SetStepRecommendation(1);
419
420 TItime = TItimeold;
421 TIstep = savestep/it;
422 if (it > 1) numsol.DestroyOldJac(TIstep);
423 if (TIstep > TIminstep && it < 256) numsol.MaxFullNewtonSteps() = 0;
424 else numsol.MaxFullNewtonSteps() = NLS_MaxFullNewtonSteps();
425
426 for (int i=1; i <= it2; i++)
427 {
428 rv += abs(NonlinSubStep()-1);
429 TItime += TIstep;
430 }
431 if (rv == 0) rv = 1;
432 else rv = 0;
433
434 if (!rv)
435 {
436 TIRestoreState(TIlaststep_state); //set to old TIx0, reset all internal nonlinear variables
437 if (mode == 2)
438 {
439 it *= 2.;
440 it2 *= 2;
441 }
442 else
443 {
444 if (TIstepnew/GetStepRecommendation() > it)
445 {
446 it = TIstepnew/GetStepRecommendation();
447 //uo << "reducestep=" << TIstepnew/it << ", it=" << it << "\n";
448 }
449 else
450 it *= 2.;
451
452 if (GetStepRecommendation() < TIminstep) it = TIstepnew/TIminstep;
453 }
454 }
455 }
456 //if (it > 1) uo << "stepsize = " << TIstep << "\n";
457
458 TIstep = savestep;
459 TItime = TItimeold;
460
461 if (!rv) uo << "ERROR: Step at minimal stepsize, computation terminated" << ENDL;
462 FinishStep();
463
464 return rv;
465 }
466
467
468 }
469
TISaveState(TIstepsave & stepsave)470 void TimeInt::TISaveState(TIstepsave& stepsave)
471 {
472 stepsave.x0 = TIx0;
473 stepsave.k0 = TIk0;
474 stepsave.time = TItime;
475 stepsave.data = TIdata;
476 /*
477 TIx0save = TIx0;
478 TIk0save = TIk0;
479 TItimesave = TItime;
480 */
481 SaveState(); //for multibody system, if internal states exist (should not happen)
482 }
483
TIRestoreState(const TIstepsave & stepsave)484 void TimeInt::TIRestoreState(const TIstepsave& stepsave)
485 {
486 TIx0 = stepsave.x0;
487 TIk0 = stepsave.k0;
488 TItime = stepsave.time;
489 TIdata = stepsave.data;
490 /*
491 TIx0 = TIx0save;
492 TIk0 = TIk0save;
493 TItime = TItimesave;
494 */
495 RestoreState(); //for multibody system, if internal states exist (should not happen)
496 }
497
FullAdaptiveStep()498 int TimeInt::FullAdaptiveStep()
499 {
500 int comp_ref=0; //no exact reference-value computation
501
502 TIstep = TIstepnew;
503 int success = 1;
504 TInoincs=1;
505 int end = 0;
506 int firstrun = 1;
507 log.TInewtonit = 0;
508 TIactlocerr = AbsAccuracy();
509
510 double value1;
511 double value2;
512 double value3;
513
514 double acterror_damp_save = acterror_damp;
515 oldenergy = GetEnergy();
516
517 int rv; //0=success, 1=failure
518
519 //parameters for adaptive strategy
520 //double smin=tableaus[act_tableau]->ODE_order;
521 //if (smin < 2) {smin = 2;}
522 double smin=2; //4
523 double smax=smin*smin; //smin^2
524 double tsmaxinc = 5; //5
525 double tsmininc = 2; //2
526 double tsmindec = 2; //2
527 double err_damp_fact = 0.1; //0.1
528
529 //safety parameter
530 double sts=1;
531
532 TISaveState(TIlaststep_state); //save state of end of last step (or initial step)
533
534 TIrejectedsteps--;
535 //try until successful timestep
536 while (!end)
537 {
538 TIrejectedsteps++;
539 //restore old state:
540 TIRestoreState(TIlaststep_state); //set to old TIx0, reset all internal nonlinear variables
541 acterror_damp = acterror_damp_save;
542
543 int largestep_discont=0;
544
545 //compute error in this timestep:
546 TIstepnew = TIstep; //suggestion for next timestep
547 double prevstep = TIstep;
548 comperr=0;
549
550 double disttoraster = ((int(TItime/TImaxstep))*TImaxstep)+TImaxstep-TItime;
551 if (fabs(disttoraster) <= 0.1*TIminstep)
552 {disttoraster += TImaxstep;}
553
554 if (TIstep >= (1-0.1*TIminstep)*disttoraster)
555 {
556 TIstep = disttoraster;
557 prevstep = TIstep;
558 }
559 else if (TIstep > 0.8*disttoraster)
560 {
561 TIstep = 0.5*disttoraster;
562 prevstep = TIstep;
563 }
564
565 TIissubstep = 0;
566 rv = abs(NonlinSubStep()-1); //0 = ok, 1 = failure
567
568 if (rv==0)
569 {
570 //1. Vergleichswert ok
571 value1=GetError();
572 if (TIdiscontstep) largestep_discont = 1;
573 TIstep *= 0.5;
574 }
575 else
576 {
577 //not converged
578 if (TIstep == TIminstep)
579 {
580 uo << "ERROR: Step at minimal stepsize, computation terminated" << ENDL;
581 return 0;
582 }
583
584 log.changestep++;
585 reduce_order += 1;
586
587 TIstep *= 0.5;
588 TIstep = Maximum(TIstep, TIminstep);
589 rv=0;
590 continue;
591 }
592
593 //restore old state:
594 TIRestoreState(TIlaststep_state); //set to old TIx0, reset all internal nonlinear variables
595
596
597 TIissubstep = 1;
598
599 rv = abs(NonlinSubStep()-1); TItime+=TIstep;
600 rv += abs(NonlinSubStep()-1);
601
602 if (rv!=0)
603 {
604 log.changestep++;
605 reduce_order += 1;
606
607 if (prevstep == TIminstep)
608 {
609 uo << "ERROR: Step at minimal stepsize, computation terminated" << ENDL;
610 return 0;
611 }
612
613 TIstep *= 0.5;
614 TIstep = Maximum(TIstep, TIminstep);
615 continue;
616
617 }
618
619 //store/compare error:
620 value2=GetError();
621
622 TIissubstep = 0;
623
624 if (comp_ref)
625 {
626
627 //restore old state:
628 TIstep = prevstep;
629 TIRestoreState(TIlaststep_state); //set to old TIx0, reset all internal nonlinear variables
630
631 //Sehr genauen wert berechnen f�r Vergleichszwecke:
632 double fineness = 10;
633 TIstep /= fineness;
634 rv = 0;
635 for (int ii = 1; ii <= fineness ; ii++)
636 {
637 rv += abs(NonlinSubStep()-1);
638 TItime += TIstep;
639 }
640 value3=GetError();
641
642 if (rv==1)
643 {
644 uo << "ERROR: FullAdaptive Step-Failure at 0.1 base-step" << ENDL;
645 uo << "Exit" << ENDL;
646 return 0;
647 }
648 comperr=sts*fabs(value2-value3);
649 }
650
651 TItime = TIlaststep_state.time; //old starttime
652
653
654 TIstep = prevstep;
655
656 //compute Errors
657
658 double D1=fabs(value1-value2);
659
660 double rowsum = 1./(pow(2.,tableaus[act_tableau]->ODE_order)-1.);
661 double ada_error=sts*D1*rowsum;
662
663 acterror = ada_error;
664 if (acterror < acterror_damp) {acterror_damp = acterror;}
665 else {acterror_damp = (acterror_damp*(1.-err_damp_fact)+acterror*err_damp_fact);}
666
667 ada_error = acterror_damp;
668
669 //uo << "val1=" << value1 << ",val2=" << value2 << ", step=" << TIstep << ", err=" << acterror << ", adaerr=" << ada_error << ", crit=" << AbsAccuracy() << "\n";
670
671
672 //double CalcErr;
673 double TIstepold = TIstep;
674
675 //suggest new (larger) timestep-size
676 if (ada_error <= AbsAccuracy()/smax && TIstep<TImaxstep)
677 {
678 end=1; //timestep completed
679
680 if (ada_error == 0.) {ada_error = 1e-16;}
681 if (tableaus[act_tableau]->nstages == 0.)
682 {(*global_uo) << "Internal Error: tableaus[act_tableau]->nstages is Zero!" << "\n";}
683
684 //cout << "Aktuelle Zeitschrittweite: " << TIstep << endl;
685 TIstepnew=TIstep*pow(AbsAccuracy()/(ada_error*smin),1./(double)tableaus[act_tableau]->ODE_order);
686 log.changestep++;
687
688 if ((1.9*TIstep < TIstepnew) && (TIstepnew < 3*TIstep))
689 {
690 TIstepnew = 2.*TIstep;
691 }
692
693 if (TIstepnew>TImaxstep)
694 {
695 TIstepnew=TImaxstep;
696 }
697
698 if (TIstepnew > tsmaxinc*TIstep)
699 {
700 TIstepnew = tsmaxinc*TIstep;
701 }
702
703 if (TIstepnew <= tsmininc*TIstep)
704 {
705 TIstepnew = TIstep;
706 log.changestep--;
707 }
708 }
709 else if(ada_error > AbsAccuracy())
710 {
711 if (TIstep==TIminstep)
712 {
713 uo << "ERROR: Step at minimal stepsize, computation terminated\n";
714 uo << "**** Consider changing error tolerance and Newton accuracy ****\n";
715 return 0;
716 }
717 //suggest smaller timestep (> minstepsize, otherwise success=0)
718 log.changestep++;
719
720 {
721 TIstepold = TIstep;
722 //cout << "Aktuelle Zeitschrittweite: " << TIstep << endl;
723 double od = tableaus[act_tableau]->ODE_order;
724
725 if (largestep_discont && od > 2)
726 {
727 od = 2;
728 }
729
730 TIstep=TIstepold*pow(AbsAccuracy()/(smin*ada_error),1./od);
731
732 if (largestep_discont && TIstep < 0.25*TIstepold)
733 {
734 TIstep = 0.25*TIstepold;
735 }
736
737 if (TIstep*tsmindec > TIstepold)
738 {
739 TIstep = TIstepold/tsmindec;
740 }
741 }
742 if (TIstep < TIminstep) {TIstep = TIminstep;}
743
744 end=0;
745 TInoincs++;
746
747 }
748 else
749 {
750 end=1;
751
752 }
753 }
754
755 //Needs average (min/max) variables of last 20 to 50 steps:
756 // newtonits, nonlinits, isdiscontinuous, ...
757 // also steps/Jacobianupdate --> stage selection lower if frequently ???
758 steps_since_orderchange++;
759 min_newtonits = Minimum(min_newtonits, GetNewtonIt());
760 newjacobians_since_orderchange = log.jaccount - last_jaccount;
761
762 if (solset.variable_order)
763 {
764 const int minsteps = 30;
765 int old_stage = act_stage;
766 if (newjacobians_since_orderchange == 0) newjacobians_since_orderchange = 1;
767
768 double steps_per_jac = (double)steps_since_orderchange/(double)newjacobians_since_orderchange;
769
770 if (act_stage > 1)
771 {
772 if (reduce_order || (steps_since_orderchange > minsteps && (steps_per_jac <= 2 || min_newtonits > 11)))
773 {
774 act_stage--;
775 if (reduce_order > 1) act_stage = 1;
776 else TIstepnew *= 0.5;
777 act_tableau = stage_tableaus(act_stage);
778 }
779 }
780 if (act_stage < stage_tableaus.Length())
781 {
782 if (!reduce_order && steps_per_jac >= 4 &&
783 min_newtonits <= 6 && (steps_since_orderchange > minsteps))
784 {
785 act_stage++;
786 int old_tab = act_tableau;
787 act_tableau = stage_tableaus(act_stage);
788
789 TIstepnew *= 4;
790 //pow(2,tableaus(act_tableau)->ODE_order)/tableaus(act_tableau)->ODE_order;
791 }
792 }
793
794 if (old_stage != act_stage)
795 {numsol.DestroyOldJacs();}
796
797 if (old_stage != act_stage || reduce_order || steps_since_orderchange > 1.5*minsteps)
798 {
799 steps_since_orderchange = 0;
800 min_newtonits = NLS_MaxNewtonSteps();
801 newjacobians_since_orderchange = 0;
802 last_jaccount = log.jaccount;
803 reduce_order = 0;
804 }
805 if (old_stage != act_stage)
806 {
807 uo << "change ODE-order to = " << tableaus(act_tableau)->ODE_order << ENDL;
808 /* uo << "steps_per_jac=" << steps_per_jac <<
809 ", min_newtonits = " << min_newtonits <<
810 ", newjacs = " << newjacobians_since_orderchange <<
811 ", steps_since=" << steps_since_orderchange <<
812 ", reduce_order=" << reduce_order << ENDL;
813 */
814 }
815 }
816
817 FinishStep();
818
819 //return success; //1= succeeded, 0=failed
820 return 1;
821
822 }
823
FinishStep()824 void TimeInt::FinishStep()
825 {
826 // new!
827 TItime += TIstep;
828
829 EndTimeStep();
830
831 //if (solset.writeresults)
832 //{
833 //does not work for IO discrete elements
834 //if (!FullAdaptive() && TIwritesolevery != 0)
835 //{
836 // //interpolated output:
837 // TISaveState(TItemp_state);
838 // double t0 = TItime;
839 // IRK_Tableau* t = tableaus[act_tableau];
840 // int ns = t->nstages;
841 // const Vector& ct = t->c;
842
843 // while (TItime+TIstep >= (TIlastwritesol+TIwritesolevery-0.1*TIminstep))
844 // {
845 // TIlastwritesol+=TIwritesolevery;
846
847 // double tau = (TIlastwritesol-t0)/TIstep;
848 // //compute interpolant for states, start and end point
849 // mystatic Vector c;
850 // //mystatic Vector f;
851 // mystatic Vector xh;
852 // int offs = 0;
853 // int nip = ns;
854 // if (ct(1) != 0) {nip++; offs=1; }
855 // if (ct(ns) != 1) {nip++;}
856 // c.SetLen(nip);
857 // //f.SetLen(nip);
858 // c(1) = 0;
859 // c(nip) = 1;
860 // for (int i=2; i <= nip; i++)
861 // {
862 // if (!(i == nip && ct(ns) != 1)) c(i) = ct(i-offs);
863 // }
864 // //uo << "c=" << c << ENDL;
865
866 // TIx0.SetAll(0);
867 // //xi[i] contain stage solutions
868 // //TIx0start: solution at t_rel=0
869 // //TIx0save: solution at t_rel=1
870 // for (int i=1; i <= nip; i++)
871 // {
872 // double Li = LagrangeWeight(i,tau,c);
873 // //uo << "L" << i << "=" << Li << ENDL;
874 // if (i == 1) TIx0 += Li*TIx0start;
875 // else if (i == nip && ct(ns) != 1) TIx0 += Li*TItemp_state.x0;
876 // else
877 // {
878 // TIx0 += Li*xi[i-1];
879 // }
880 // }
881
882 // WriteSol();
883 // }
884 // TIRestoreState(TItemp_state);
885 // TItime += TIstep; //possibly this is too late ...
886 //}
887 //else
888 WriteSol();
889 //}
890 TIDrawAndStore();
891 }
892
TIDrawAndStore()893 void TimeInt::TIDrawAndStore()
894 {
895 //redraw frequency: 0..off, 1..draw last frame, 2..100sec, 3..20sec, 4..2sec, 5..200ms, 6..50ms, 7..20ms, 8..every 10 frames, 9..every frame
896 if (((solset.withgraphics >= 1 && solset.withgraphics <= 8) && (drawnow != 0)) || solset.withgraphics == 9)
897 {
898 if (GetCompTime() > 2 + lastloadresults || TIfinished!=0)
899 {
900 TIx0draw = TIx0;
901 TIdrawtime = TItime;
902 // Set XData vector
903 TIdrawdata = TIdata;
904 }
905 drawnow=0;
906 pCFB->ResultsUpdated(1); //redraw only, no results updated
907 }
908
909 pCFB->ResultsUpdated(2); //update results only, no redraw
910
911 //$ PG 2012-6-18:[
912 // user may pause calculation by pause-button (see CWCDriver3DDlg::OnButtonPause)
913 // the pause functionality is primarily needed for save operations with the data manager during a simulation.
914 // it is safest to pause the calculation immediately (and only) after the draw-configuration is copied from the computation-configuration (TIx0draw = TIx0, etc.).
915 if (PauseCalculation())
916 {
917 pCFB->PausedComputation();
918 int memo = bComputationIsInProgress;
919 bComputationIsInProgress = 0;
920 while (PauseCalculation()) {/*computation thread keeps stuck here*/ uo.pUI->SleepX(100); }
921 bComputationIsInProgress = memo;
922 }
923 //$ PG 2012-6-18:]
924 }
925
StoreResultsIsOn()926 int TimeInt::StoreResultsIsOn()
927 {
928 if (solset.storedata == 0) return 0;
929 else if (solset.storedata == -2) return 1;
930 else if (solset.storedata == -1 && (GetTime()+0.1*TIminstep >= laststoredata+TImaxstep)) {laststoredata = GetTime(); return 1;}
931 else if (solset.storedata > 0 && (GetTime()+0.1*TIminstep) >= laststoredata+solset.storedata) {laststoredata = GetTime(); return 1;}
932 return 0;
933 }
934
RemoveResults()935 int TimeInt::RemoveResults()
936 {
937 return 0;
938 }
939
StoreResults(DataSaver & storage,double & m_TimePoint)940 void TimeInt::StoreResults(DataSaver & storage, double &m_TimePoint)
941 {
942 const Vector& v = GetSolVector();
943 const Vector& d = GetDataVector();
944
945 if (solset.sol_data_to_files)
946 {
947 TArray<double> data_container(3+v.Length()+d.Length());
948 int idx = 1;
949
950 m_TimePoint = GetTime();
951 int vlen = (double) v.Length();
952 int dlen = (double) d.Length();
953
954 data_container(idx++) = m_TimePoint;
955 data_container(idx++) = vlen;
956 data_container(idx++) = dlen;
957 for (int i=1; i<=vlen; i++)
958 {
959 data_container(idx++) = v(i);
960 }
961 for (int i=1; i<=dlen; i++)
962 {
963 data_container(idx++) = d(i);
964 }
965
966 // store iteration number in array (which is written to file info.txt at the end of the simulation)
967 //TInumber_of_solution_data_steps.Add(TIit);
968 TInumber_of_solution_data_steps++;
969
970 // store solution and data of this iteration in own file
971 CMFile file(mystr(solset.sol_directory)+mystr("solution_data\\")+mystr(TInumber_of_solution_data_steps)+mystr(".dat"), TFMwrite, 1);
972 for (int i=1; i<=data_container.Length(); i++)
973 {
974 file.RWbinaryDouble(data_container(i));
975 }
976 }
977 else
978 {
979 storage.SetTime(GetTime());
980
981 storage << v.GetLen();
982 for (int i=1; i<=v.GetLen(); i++)
983 {
984 storage << v(i);
985 }
986
987 storage << d.Length();
988 for (int i=1; i<=d.GetLen(); i++)
989 {
990 storage << d(i);
991 }
992 }
993 }
994
LoadResults(DataLoader & loader,int m_TimePointNumber)995 void TimeInt::LoadResults(DataLoader & loader, int m_TimePointNumber)
996 {
997 lastloadresults = GetCompTime();
998
999 if (solset.sol_data_to_files)
1000 {
1001 CMFile file(mystr(solset.sol_directory)+mystr("solution_data\\")+mystr(m_TimePointNumber)+mystr(".dat"), TFMread, 1);
1002
1003 //int drawtimestep; file.RWbinaryDouble(drawtimestep);
1004
1005 double drawtime; file.RWbinaryDouble(drawtime);
1006 SetDrawTime(drawtime);
1007
1008 double len_double; file.RWbinaryDouble(len_double);
1009 int vlen = (int) len_double;
1010 TIx0draw.SetLen(vlen);
1011 TIx0draw.SetAll(0.);
1012 file.RWbinaryDouble(len_double);
1013 int dlen = (int) len_double;
1014 TIdrawdata.SetLen(dlen);
1015 TIdrawdata.SetAll(0.);
1016 for (int i=1; i<=vlen; i++)
1017 {
1018 file.RWbinaryDouble(TIx0draw(i));
1019 }
1020 TIdrawdata.SetAll(0.);
1021 for (int i=1; i<=dlen; i++)
1022 {
1023 file.RWbinaryDouble(TIdrawdata(i));
1024 }
1025 }
1026 else
1027 {
1028 SetDrawTime(loader.GetTime());
1029
1030 int len;
1031 loader >> len;
1032
1033 TIx0draw.SetLen(len);
1034 TIx0draw.SetAll(0.);
1035
1036 for (int i=1; i<=len; i++)
1037 {
1038 loader >> TIx0draw(i);
1039 }
1040
1041 loader >> len;
1042
1043 TIdrawdata.SetLen(len);
1044 TIdrawdata.SetAll(0.);
1045
1046 for (int i=1; i<=len; i++)
1047 {
1048 loader >> TIdrawdata(i);
1049 }
1050 }
1051 }
1052
FirstStep()1053 int TimeInt::FirstStep()
1054 {
1055 TIlastwritesol = 0;
1056
1057 if (solset.writeresults)
1058 {
1059 double step = TIstep; //...necessary for output file
1060 TIstep = 0; //==>GetStepEndTime = TItime = 0 //...necessary for output file
1061 WriteSol();
1062 TIstep = step;//...necessary for output file
1063 }
1064
1065 //Compute initial conditions for algebraic part
1066 return 1;
1067 }
1068
GeneralIStep()1069 int TimeInt::GeneralIStep()
1070 {
1071 //macht einen Schritt
1072
1073 int ss = GetSystemSize();
1074 int is = GetImplicitSize();
1075 int es = GetFirstOrderSize();
1076 int sos = GetSecondOrderSize();
1077 int sos_rs = GetSecondOrderSize_RS();
1078 //int rs = GetResortSize();
1079 //if (GetTime() < 0.9*GetStepSize()) uo << "*****************\nWARNING: changed bandsize-6\n******************\n";
1080 numsol.SetBandSize(sos_rs - reducedbandsize); //for banded-solver, which part is banded!
1081
1082 //UO() << "sos_rs=" << sos_rs << ", sos=" << sos << "\n";
1083
1084 int rv = 1;
1085
1086 //als Start f�r beide L�sungen den letzten Zustand verwenden
1087 int i,j;
1088 IRK_Tableau* t = tableaus[act_tableau];
1089 int ns = t->nstages;
1090
1091 //Kversion of Runge Kutta schemes:
1092 if (TIkv && t->implicit)
1093 {
1094 //TI-KVersion!!!!!!!!!!!
1095 int ns = t->nstages;
1096 int c0f = 0; //for lobattoIIIC und RadauIA methods!!!!
1097 if (t->c(1) == 0)
1098 {
1099 c0f = 1;
1100 }
1101
1102 mystatic Vector GSxs;
1103 mystatic Vector ke[global_maxstages]; //explicit equations
1104 mystatic Vector ku[global_maxstages]; //sos equations, u
1105 mystatic Vector kv[global_maxstages]; //sos equations, v
1106 mystatic Vector evalf;
1107 mystatic Vector xh2;
1108 mystatic Vector xh3;
1109 mystatic Vector iv[global_maxstages];
1110
1111 mystatic Vector g1e; //first order
1112 mystatic Vector g1u; //second order u
1113 mystatic Vector g1v; //second order v
1114
1115 TIu0.SetLen(sos);
1116 TIu0e.SetLen(es);
1117 TIku0e.SetLen(es);
1118 TIv0.SetLen(sos);
1119 TIi0.SetLen(is);
1120
1121 TIu0.Copy(TIx0,1,1,sos); //needed for NLF
1122 TIv0.Copy(TIx0,1+sos,1,sos); //needed for NLF
1123 TIu0e.Copy(TIx0,1+2*sos,1,es); //needed for NLF
1124 TIi0.Copy(TIx0,1+es+2*sos,1,is);//needed for NLF
1125
1126 TIkv0.SetLen(sos);
1127 TIku0 = TIv0;
1128 TIkv0.Copy(TIk0,1+sos,1,sos);
1129 TIku0e.Copy(TIk0,1+2*sos,1,es);
1130
1131 GSxs.SetLen((ns-c0f)*(sos+es+is));
1132 for (i = 1; i <= (ns-c0f); i++)
1133 {
1134 GSxs.Copy(TIkv0,1,1+(i-1)*sos,sos);
1135 GSxs.Copy(TIku0e,1,1+(ns-c0f)*sos+(i-1)*es,es);
1136 GSxs.Copy(TIi0,1,1+(ns-c0f)*(sos+es)+(i-1)*is,is);
1137 }
1138
1139 impl_equ_flag = 0;
1140 //mystatic Vector xss = GSxs;
1141 if (!flag_applyjac)
1142 {
1143 numsol.NLSolveInfo() = TIstep;
1144 rv = numsol.NLSolve(GSxs); //call Newton
1145 } else
1146 {
1147 mystatic Vector F;
1148 mystatic Vector dx;
1149 F.SetLen(GSxs.GetLen());
1150 dx.SetLen(GSxs.GetLen());
1151 NLF(GSxs,F);
1152 rv = numsol.ApplyJac(F, dx); //apply only Jacobian
1153 GSxs -= dx;
1154 if (!rv) uo << "ApplyJac=0\n";
1155 }
1156
1157 log.jaccount += numsol.GetJacCount();
1158 log.TInewtonitsum += numsol.GetNewtonIts();
1159 log.TInewtonit = Maximum(numsol.GetNewtonIts(), log.TInewtonit);
1160 TIcondnum = numsol.GetJacCondnum();
1161
1162
1163 if (c0f)
1164 {
1165 ku[1] = TIku0;
1166 kv[1] = TIkv0;
1167 ke[1] = TIku0e;
1168 }
1169
1170 for (i = 1; i <= (ns-c0f); i++)
1171 {
1172 kv[i+c0f].SetLen(sos);
1173 kv[i+c0f].Copy(GSxs,1+sos*(i-1),1,sos);
1174 }
1175
1176 for (i = 1; i <= (ns-c0f); i++)
1177 {
1178 ke[i+c0f].SetLen(es);
1179 ke[i+c0f].Copy(GSxs,1+sos*(ns-c0f)+(i-1)*es,1,es);
1180 }
1181
1182 //Compute ku[i]
1183 for (i = 1; i <= (ns-c0f); i++)
1184 {
1185 ku[i+c0f] = TIv0;
1186 for (j = 1; j <= ns; j++)
1187 {
1188 xh = kv[j];
1189 xh *= TIstep * t->A(i+c0f,j);
1190 ku[i+c0f] += xh;
1191 }
1192 }
1193
1194 //Evaluation step with coefficients b_i
1195 //with decomposition gu/gv
1196
1197 g1u = TIu0;
1198 g1v = TIv0;
1199 g1e = TIu0e;
1200 xh.SetLen(sos);
1201 xh2.SetLen(es);
1202
1203 for (i = 1; i <= ns; i++)
1204 {
1205 xh = ku[i];
1206 xh *= TIstep * t->b(i);
1207 g1u += xh;
1208
1209 xh = kv[i];
1210 xh *= TIstep * t->b(i);
1211 g1v += xh;
1212
1213 xh2 = ke[i];
1214 xh2 *= TIstep * t->b(i);
1215 g1e += xh2;
1216 }
1217
1218 //compute new TIx0:
1219 TIx0.Copy(g1u,1,1,sos);
1220 TIx0.Copy(g1v,1,1+sos,sos);
1221 TIx0.Copy(g1e,1,1+2*sos,es);
1222
1223 //generate new TIk0 for next timestep:
1224 TIk0.Copy(ku[ns],1,1,sos);
1225 TIk0.Copy(kv[ns],1,1+sos,sos);
1226 TIk0.Copy(ke[ns],1,1+2*sos,es);
1227 TIk0.Copy(GSxs,(ns-c0f)*(sos+es)+1+is*((ns-c0f)-1),1+2*sos+es,is); //iv[ns]
1228
1229 //compute final value of implicit solution, extrapolate
1230 //maybe there is some error, esp for c1=0 ???
1231 if (t->Ainvertable && t->c(ns) != 1 && is!=0)
1232 {
1233 double k0 = 1. - t->bAinv.Sum();
1234 xh3.SetLen(is);
1235
1236 if (c0f) {k0+=t->bAinv(1);}
1237 TIi0 *= k0;
1238 for (i = 1; i <= (ns-c0f); i++)
1239 {
1240 xh3.Copy(GSxs,1+(ns-c0f)*(sos+es)+is*(i-1),1,is);
1241 xh3 *= t->bAinv(i+c0f);
1242 TIi0 += xh3;
1243 }
1244 TIx0.Copy(TIi0,1,1+2*sos+es,is); //iv[ns]
1245 }
1246 else
1247 {
1248 TIx0.Copy(GSxs,(ns-c0f)*(sos+es)+1+is*((ns-c0f)-1),1+2*sos+es,is); //iv[ns]
1249 }
1250 }
1251 //pure first order equations (with constraints):
1252 else if (GetSecondOrderSize() == 0 && t->implicit)
1253 {
1254
1255 mystatic Vector gv[global_maxstages];
1256 mystatic Vector iv[global_maxstages];
1257 mystatic Vector evalf;
1258 mystatic Vector GSxs;
1259 mystatic Vector gb;
1260 mystatic Vector gx;
1261
1262 TIu0e.SetLen(es);
1263 TIu0e.Copy(TIx0,1,1,es);
1264
1265 TIi0.SetLen(is);
1266 TIi0.Copy(TIx0,es+1,1,is);
1267
1268 GSxs.SetLen(ns*(es+is));
1269 //find start-vector for newton
1270 for (i = 0; i < ns; i++)
1271 {
1272 GSxs.Copy(TIu0e,1,1+es*i,es);
1273 }
1274 for (i = 0; i < ns; i++)
1275 {
1276 GSxs.Copy(TIi0,1,1+es*ns+is*i,is);
1277 }
1278
1279 impl_equ_flag = 0;
1280
1281 rv = numsol.NLSolve(GSxs); //call Newton
1282
1283 log.jaccount += numsol.GetJacCount();
1284 log.TInewtonitsum += numsol.GetNewtonIts();
1285 log.TInewtonit = Maximum(numsol.GetNewtonIts(), log.TInewtonit);
1286 TIcondnum = numsol.GetJacCondnum();
1287
1288 for (i = 1; i <= ns; i++)
1289 {
1290 gv[i].SetLen(es);
1291 gv[i].Copy(GSxs,1+es*(i-1),1,es);
1292 //gv[i] = GSxs.SubVector(1+es*(i-1), i*es);
1293 }
1294 for (i = 1; i <= ns; i++)
1295 {
1296 iv[i].SetLen(is);
1297 iv[i].Copy(GSxs,1+es*ns+is*(i-1),1,is);
1298 //iv[i] = GSxs.SubVector(ns*es+1+is*(i-1), ns*es+is*i);
1299 }
1300
1301 gb.SetLen(es);
1302 gb = TIu0e;
1303
1304 evalf.SetLen(es);
1305 gx.SetLen(es+is);
1306
1307 for (i = 1; i <= ns; i++)
1308 {
1309 gx.Copy(gv[i],1,1,es);
1310 gx.Copy(iv[i],1,es+1,is);
1311 EvalF(gx,evalf,TItime+TIstep*t->c(i));
1312 evalf.Mult(TIstep*t->b(i));
1313 gb += evalf;
1314 }
1315
1316 TIx0.Copy(gb,1,1,es);
1317 TIx0.Copy(iv[ns],1,es+1,is);
1318 EvalF(TIx0, evalf,TItime+TIstep); //write new state into system variables
1319
1320 }
1321 else if (!t->implicit && is==0)
1322 {
1323 //explicit Runge Kutta!!!
1324
1325 //very inefficient mass matrix!!!
1326 mystatic Matrix mass[global_maxstages];
1327
1328 evalf.SetLen(sos);
1329 TIu0.SetLen(sos);
1330 TIu0.Copy(TIx0,1,1,sos);
1331 TIv0.SetLen(sos);
1332 TIv0.Copy(TIx0,1+sos,1,sos);
1333 TIu0e.SetLen(es);
1334 TIu0e.Copy(TIx0,1+2*sos,1,es);
1335
1336 //build gu, gv, gue
1337 gu[1] = TIu0;
1338 gv[1] = TIv0;
1339 gue[1] = TIu0e;
1340
1341 for (i=1; i <= ns; i++)
1342 {
1343 //evaluate right hand sides for first and second order equations
1344 kv[i].SetLen(sos);
1345 kue[i].SetLen(es);
1346 xi[i].SetLen(2*sos+es);
1347
1348 xi[i].Copy(gu[i],1,1,sos);
1349 xi[i].Copy(gv[i],1,1+sos,sos);
1350 xi[i].Copy(gue[i],1,1+2*sos,es);
1351
1352 //compute RK-f(x,t) for gu,gue and gv
1353 ku[i] = gv[i];
1354 evalfe.SetLen(es);
1355 if (es != 0)
1356 {
1357 EvalF(xi[i],kue[i],TItime+TIstep*t->c(i));
1358 }
1359
1360 if (sos != 0)
1361 {
1362 mass[i].SetSize(sos,sos);
1363 mass[i].FillWithZeros();
1364 evalf.SetLen(sos);
1365 EvalM(xi[i], mass[i], TItime+TIstep*t->c(i));
1366 EvalF2(xi[i], evalf, TItime+TIstep*t->c(i));
1367
1368 if (!mass[i].Solve(evalf,kv[i])) {uo << "Error in GeneralIStep: Mass matrix is singular!" << ENDL; return 0;}
1369 }
1370
1371 //compute next stage
1372 if (i < ns)
1373 {
1374 gu[i+1] = TIu0;
1375 gv[i+1] = TIv0;
1376 gue[i+1] = TIu0e;
1377 for (j = 1; j <= i; j++)
1378 {
1379 gu[i+1] += TIstep*t->A(i+1,j)*ku[j];
1380 gv[i+1] += TIstep*t->A(i+1,j)*kv[j];
1381 gue[i+1]+= TIstep*t->A(i+1,j)*kue[j];
1382 }
1383 }
1384 }
1385
1386 //compute evaluation step
1387 for (i = 1; i <= ns; i++)
1388 {
1389 TIu0 += TIstep*t->b(i)*ku[i];
1390 TIv0 += TIstep*t->b(i)*kv[i];
1391 TIu0e += TIstep*t->b(i)*kue[i];
1392 }
1393
1394 //compute new TIx0:
1395 TIx0.Copy(TIu0,1,1,sos);
1396 TIx0.Copy(TIv0,1,1+sos,sos);
1397 TIx0.Copy(TIu0e,1,1+2*sos,es);
1398 }
1399 else
1400 {
1401 uo << "Mixed first-second order system not yet implemented!!!" << ENDL;
1402 }
1403
1404
1405 //TInewtonitsum += TInewtonit;
1406 if (rv != 1)
1407 {
1408 //uo << "NL-Solve (Newton) failed" << ENDL;
1409 rv=0;
1410 }
1411 return rv;
1412 }
1413
1414
1415 //Compute (df/dx)
LocalJacobianF(Matrix & m,Vector & x)1416 void TimeInt::LocalJacobianF(Matrix& m, Vector& x)
1417 {
1418 int i,j;
1419 int is = GetImplicitSize();
1420 int es = GetFirstOrderSize();
1421 int ss = GetSystemSize();
1422 if (es == 0) return;
1423
1424 locjacf0.SetLen(es);
1425 locjacf1.SetLen(es);
1426 locjacf2.SetLen(es);
1427
1428 double numdiffepsi = numsol.NumDiffepsi();
1429 double eps;
1430 NLS_SetJacCol(0);
1431
1432 double t = TItime+0.5*TIstep;
1433 if (!numsol.SymmetricJacobian())
1434 EvalF(x,locjacf0,t);
1435
1436 for (i = 1; i <= ss; i++)
1437 {
1438 NLS_SetJacCol(i);
1439 eps = numdiffepsi*Maximum(1e-2,fabs(x(i)));
1440 if (numsol.SymmetricJacobian())
1441 {
1442 x(i) += eps;
1443 EvalF(x,locjacf1,t);
1444
1445 x(i) -= 2*eps;
1446 EvalF(x,locjacf2,t);
1447 x(i) += eps;
1448 }
1449 else
1450 {
1451 x(i) += 2*eps;
1452 EvalF(x,locjacf1,t);
1453 x(i) -= 2*eps;
1454 //EvalF(x,locjacf2,t);
1455 locjacf2 = locjacf0;
1456 }
1457
1458 for (j=1; j<=es;j++)
1459 {
1460 m(j,i)=0.5/eps*(locjacf1(j)-locjacf2(j));
1461 }
1462 }
1463 NLS_SetJacCol(0);
1464 }
1465
1466 //Compute (df2/dx)
LocalJacobianF2(Matrix & m,Vector & x)1467 void TimeInt::LocalJacobianF2(Matrix& m, Vector& x)
1468 {
1469 int i,j;
1470 int sos= GetSecondOrderSize();
1471 if (sos == 0) return;
1472 int ss = GetSystemSize();
1473 int is = GetImplicitSize();
1474
1475 locjacf20.SetLen(sos);
1476 locjacf21.SetLen(sos);
1477 locjacf22.SetLen(sos);
1478
1479
1480 double numdiffepsi = numsol.NumDiffepsi();
1481 double eps;
1482
1483 double t = TItime+0.5*TIstep;
1484 NLS_SetJacCol(0);
1485
1486 if (!numsol.SymmetricJacobian())
1487 EvalF2(x,locjacf20,t);
1488 double storex;
1489
1490 //uo << "x0=" << x << "\n";
1491
1492 for (i = 1; i <= ss; i++)
1493 {
1494 NLS_SetJacCol(i);
1495 eps = numdiffepsi*Maximum(1e-2,fabs(x(i)));
1496 if (numsol.SymmetricJacobian())
1497 {
1498 storex = x(i);
1499 x(i) += eps;
1500 EvalF2(x,locjacf21,t);
1501
1502 x(i) -= 2*eps;
1503 EvalF2(x,locjacf22,t);
1504 x(i) = storex;
1505 }
1506 else
1507 {
1508 x(i) += 2*eps;
1509 EvalF2(x,locjacf21,t);
1510
1511 x(i) -= 2*eps;
1512 locjacf22 = locjacf20;
1513 }
1514
1515 for (j=1; j<=sos;j++)
1516 {
1517 m(j,i)=0.5/eps*(locjacf21(j)-locjacf22(j));
1518 }
1519 //uo << "jac1=" << 0.5/eps*(locjacf21-locjacf22) << "\n";
1520 //uo << "m=" << m << "\n";
1521 }
1522 NLS_SetJacCol(0);
1523 }
1524
1525 //Compute (df2/dx)
LocalJacobianF2(SparseMatrix & m,Vector & x)1526 void TimeInt::LocalJacobianF2(SparseMatrix& m, Vector& x)
1527 {
1528 //uo << "m=" << m.Getrows() << ", " << m.Getcols() << "\n";
1529
1530 int i,j;
1531 int sos= GetSecondOrderSize();
1532 if (sos == 0) return;
1533 int ss = GetSystemSize();
1534 int is = GetImplicitSize();
1535
1536 slocjacf20.SetLen(sos,32);
1537 slocjacf21.SetLen(sos,32);
1538 slocjacf22.SetLen(sos,32);
1539
1540 locjacf20.SetLen(sos); //for un-symmetric computation
1541 locjacf21.SetLen(sos);
1542 locjacf22.SetLen(sos);
1543
1544
1545 temprowind.SetLen(sos);
1546 for (i = 1; i <= temprowind.Length(); i++) temprowind(i) = 0;
1547
1548 double numdiffepsi = numsol.NumDiffepsi();
1549 double eps;
1550
1551 double t = TItime+0.5*TIstep;
1552 static TArray<int> elems(100);
1553 static TArray<int> oldelems(100);
1554 elems.SetLen(0);
1555 oldelems.SetLen(0);
1556
1557 NLS_SetJacCol(0);
1558 m.FillWithZeros(); //no costs, but necessary, because not everything filled in!!!
1559
1560 if (!numsol.SymmetricJacobian())
1561 EvalF2(x,locjacf20,t);
1562
1563 double storex;
1564 int nprint = 6000;
1565 if (ss > nprint) uo << "JacF2(" << ss <<")";
1566
1567 //int testcnt = 0;
1568
1569
1570 for (i = 1; i <= ss; i++)
1571 {
1572 if (ss > nprint && i%1000==0) uo << ".";
1573 //if (i%1000 == 0) uo << "i=" << i << "\n";
1574 NLS_SetJacCol(i);
1575 eps = numdiffepsi*Maximum(1e-2,fabs(x(i)));
1576 //eps2 = eps;
1577
1578 if (i==sos+1 || i==ss-is+1) oldelems.SetLen(0);
1579
1580 if (numsol.SymmetricJacobian())
1581 {
1582 if (0)
1583 {
1584 storex = x(i);
1585 x(i) += 2*eps;
1586 EvalF2(x,slocjacf21,t,temprowind, tempclearind, elems);
1587 if (!IsEqual(elems, oldelems)) //if equal then use old slocjacf22!!!
1588 {
1589 oldelems = elems;
1590 x(i) -= 2*eps;
1591 EvalF2(x,slocjacf22,t,temprowind, tempclearind, elems);
1592 }
1593 x(i) = storex;
1594 }
1595 else
1596 {
1597 storex = x(i);
1598 x(i) += eps;
1599 EvalF2(x,slocjacf21,t,temprowind, tempclearind, elems);
1600 x(i) -= 2*eps;
1601 EvalF2(x,slocjacf22,t,temprowind, tempclearind, elems);
1602 x(i) = storex;
1603 }
1604 }
1605 else
1606 {
1607 x(i) += 2*eps;
1608 EvalF2(x,locjacf21,t);
1609
1610 x(i) -= 2*eps;
1611 }
1612
1613 if (numsol.SymmetricJacobian())
1614 {
1615 for (j=1; j<=slocjacf21.NEntries();j++)
1616 {
1617 slocjacf21.Entry(j) = (slocjacf21.Entry(j)-slocjacf22.Entry(j))/(2*eps);
1618 }
1619 m.SetColVector(slocjacf21,i);
1620 }
1621 else
1622 {
1623 for (j=1; j <= sos;j++)
1624 {
1625 locjacf21(j)=(locjacf21(j)-locjacf20(j))/eps;
1626 }
1627 m.SetColVector(locjacf21,1,sos,i);
1628 }
1629 }
1630 if (ss > nprint) uo << "\n";
1631
1632 //uo << "m=" << m << "\n";
1633 //uo << "jac-evalf=" << testcnt << "\n";
1634 NLS_SetJacCol(0);
1635 }
1636
LocalJacobianG(Matrix & m,Vector & x)1637 void TimeInt::LocalJacobianG(Matrix& m, Vector& x)
1638 {
1639 int is = GetImplicitSize();
1640 if (is == 0) return;
1641
1642 int i,j;
1643 int es = GetFirstOrderSize();
1644 int ss = GetSystemSize();
1645
1646 locjacg0.SetLen(is);
1647 locjacg1.SetLen(is);
1648 locjacg2.SetLen(is);
1649
1650 double numdiffepsi = numsol.NumDiffepsi();
1651 double eps;
1652
1653 double t = TItime+0.5*TIstep;
1654 NLS_SetJacCol(0);
1655 if (!numsol.SymmetricJacobian())
1656 EvalG(x,locjacg0,t);
1657
1658 for (i = 1; i <= ss; i++)
1659 {
1660 NLS_SetJacCol(i);
1661 eps = numdiffepsi*Maximum(1e-2,fabs(x(i)));
1662 if (numsol.SymmetricJacobian())
1663 {
1664 x(i) += eps;
1665 EvalG(x,locjacg1,t);
1666
1667 x(i) -= 2*eps;
1668 EvalG(x,locjacg2,t);
1669 x(i) += eps;
1670 }
1671 else
1672 {
1673 x(i) += 2*eps;
1674 EvalG(x,locjacg1,t);
1675 x(i) -= 2*eps;
1676 locjacg2 = locjacg0;
1677 }
1678
1679 for (j=1; j<=is;j++)
1680 {
1681 m(j,i)=0.5/eps*(locjacg1(j)-locjacg2(j));
1682 }
1683 }
1684 NLS_SetJacCol(0);
1685
1686 }
1687
LocalJacobianG(SparseMatrix & m,Vector & x)1688 void TimeInt::LocalJacobianG(SparseMatrix& m, Vector& x)
1689 {
1690 int i,j;
1691 int sos= GetSecondOrderSize();
1692 int ss = GetSystemSize();
1693 int is = GetImplicitSize();
1694 if (is == 0) return;
1695
1696 slocjacg0.SetLen(is,32);
1697 slocjacg1.SetLen(is,32);
1698 slocjacg2.SetLen(is,32);
1699
1700 locjacg0.SetLen(is); //for un-symertric computation
1701 locjacg1.SetLen(is);
1702 locjacg2.SetLen(is);
1703
1704 temprowind.SetLen(is);
1705 for (i = 1; i <= temprowind.Length(); i++) temprowind(i) = 0;
1706
1707 double numdiffepsi = numsol.NumDiffepsi();
1708 double eps;
1709
1710 double t = TItime+0.5*TIstep;
1711 NLS_SetJacCol(0);
1712 m.FillWithZeros(); //no costs, but necessary, because not everything filled in!!!
1713
1714 if (!numsol.SymmetricJacobian())
1715 EvalG(x,locjacg0,t);
1716
1717 for (i = 1; i <= ss; i++)
1718 {
1719 NLS_SetJacCol(i);
1720 eps = numdiffepsi*Maximum(1e-2,fabs(x(i)));
1721 if (numsol.SymmetricJacobian())
1722 {
1723 x(i) += eps;
1724 EvalG(x,slocjacg1,t,temprowind, tempclearind);
1725
1726 x(i) -= 2*eps;
1727 EvalG(x,slocjacg2,t,temprowind, tempclearind);
1728 x(i) += eps;
1729 }
1730 else
1731 {
1732 x(i) += 2*eps;
1733 EvalG(x,locjacg1,t);
1734 x(i) -= 2*eps;
1735 }
1736
1737 if (numsol.SymmetricJacobian())
1738 {
1739 for (j=1; j<=slocjacg1.NEntries();j++)
1740 {
1741 slocjacg1.Entry(j) = 0.5/eps*(slocjacg1.Entry(j)-slocjacg2.Entry(j));
1742 }
1743 m.SetColVector(slocjacg1,i);
1744 }
1745 else
1746 {
1747 for (j=1; j <= is;j++)
1748 {
1749 locjacg1(j)=0.5/eps*(locjacg1(j)-locjacg0(j));
1750 }
1751 m.SetColVector(locjacg1,1,is,i);
1752 }
1753 }
1754 NLS_SetJacCol(0);
1755 }
1756
1757
1758
LocalJacobianM(Matrix & m,Vector & x)1759 void TimeInt::LocalJacobianM(Matrix& m, Vector& x)
1760 {
1761 NLS_SetJacCol(0);
1762 int i,j;
1763
1764 int is = GetImplicitSize();
1765 int es = GetFirstOrderSize();
1766 int ss = GetSystemSize();
1767 int sos= GetSecondOrderSize();
1768 if (sos == 0) return;
1769
1770 locjacf20.SetLen(sos);
1771 locjacf21.SetLen(sos);
1772 locjacf22.SetLen(sos);
1773
1774 mystatic Vector TIkv0(sos,sos);
1775 mystatic Matrix locm;
1776 locm.SetSize(sos,sos);
1777 locm = 0.;
1778
1779 TIkv0.SetLen(sos);
1780 TIkv0.Copy(TIk0,1+sos,1,sos);
1781
1782
1783 double numdiffepsi = numsol.NumDiffepsi();
1784 double eps;
1785
1786 double t = TItime+0.5*TIstep;
1787 NLS_SetJacCol(0);
1788
1789 if (!numsol.SymmetricJacobian())
1790 {
1791 EvalM(x,locm,t);
1792 locjacf20 = locm*TIkv0;
1793 }
1794
1795 for (i = 1; i <= sos; i++)
1796 {
1797 eps = numdiffepsi*Maximum(1e-2,fabs(x(i)));
1798 if (numsol.SymmetricJacobian())
1799 {
1800 x(i) += eps;
1801 EvalM(x,locm,t);
1802 locjacf21 = locm*TIkv0;
1803
1804 x(i) -= 2*eps;
1805 EvalM(x,locm,t);
1806 locjacf22 = locm*TIkv0;
1807
1808 x(i) += eps;
1809 }
1810 else
1811 {
1812 x(i) += 2*eps;
1813 EvalM(x,locm,t);
1814 locjacf21 = locm*TIkv0;
1815
1816 x(i) -= 2*eps;
1817 locjacf22 = locjacf20;
1818 }
1819
1820 for (j=1; j<=sos;j++)
1821 {
1822 m(j,i)=0.5/eps*(locjacf21(j)-locjacf22(j));
1823 }
1824 }
1825 NLS_SetJacCol(0);
1826 }
1827
1828 //Compute Full Jacobian
FullJacobian(Matrix & m,Vector & x)1829 void TimeInt::FullJacobian(Matrix& m, Vector& x)
1830 {
1831 }
1832
ComputeStiffnessAndDampingMatrix(SparseMatrix & k,SparseMatrix & d,Vector & x)1833 void TimeInt::ComputeStiffnessAndDampingMatrix(SparseMatrix& k, SparseMatrix& d, Vector& x)
1834 {
1835 TMStartTimer(19);
1836 int is = GetImplicitSize();
1837 int es = GetFirstOrderSize();
1838 int sos = GetSecondOrderSize();
1839 int ss = GetSystemSize();
1840
1841 // $ MSax 2013-07-25 : [ removed because not used
1842 //mystatic Vector f1;
1843 //mystatic Vector f2;
1844 //f1.SetLen(x.GetLen());
1845 //f2.SetLen(x.GetLen());
1846 // $ MSax 2013-07-25 : ] removed because not used
1847
1848 NLS_SetJacCol(0);
1849
1850 int m_initsize = MaxSparseBandwidth()*2;//2; //initial sparse matrix size
1851 mlocgs.SetSize(is,ss,m_initsize);
1852
1853 xx = x; // positions AND velocities !!
1854
1855 k.SetSize((sos+es+is),(sos+es+is), m_initsize);
1856 k.FillWithZeros();
1857 d.SetSize((sos+es+is),(sos+es+is), m_initsize);
1858 d.FillWithZeros();
1859
1860 mlocf2s.SetSize(sos,ss,m_initsize);
1861 if (sos) LocalJacobianF2(mlocf2s,xx);
1862
1863 //Matrix K(sos,ss);
1864 //LocalJacobianF2(K,xx); //!!!!!!!!!!!
1865 //uo << "KD=" << K << "\n";
1866
1867
1868 k.AddSubmatrix(mlocf2s,1,1,1,1,sos,sos,1.);
1869 d.AddSubmatrix(mlocf2s,1,1+sos,1,1,sos,sos,1.);
1870
1871 ////Stiffness part
1872 //m.AddSubmatrix(mlocf2s,1,1+sos,1,1,sos,sos,1);
1873 //m.AddSubmatrix(mlocf2s,1,1+2*sos+es,1,1+sos+es,sos,is,1);
1874
1875 //if (is) LocalJacobianG(mlocgs,xx);
1876 //if (es) {UO() << "Sparse static solver not implemented for first order ODEs!\n"; return; }
1877
1878 ////Constraint part
1879 //m.AddSubmatrix(mlocgs, 1,1,sos+es+1,1,is,sos,1);
1880 //m.AddSubmatrix(mlocgs, 1,1+2*sos+es,sos+es+1,1+sos+es,is,is,1);
1881
1882 TMStopTimer(19);
1883 }
1884
ComputeGyroscopicMatrix(SparseMatrix & gy)1885 void TimeInt::ComputeGyroscopicMatrix(SparseMatrix& gy)//, Vector& x) // $ MSax 2013-07-25 : added
1886 {
1887 }
1888
StaticJacobian(SparseMatrix & m,Vector & x)1889 void TimeInt::StaticJacobian(SparseMatrix& m, Vector& x)
1890 {
1891 int newmode = solset.static_experimental_sparse_jacobian; //new mode using less memory (using mbs->StaticJacobianF2(...))
1892
1893 TMStartTimer(19);
1894 int is = GetImplicitSize();
1895 int es = GetFirstOrderSize();
1896 int sos = GetSecondOrderSize();
1897 int ss = GetSystemSize();
1898
1899 mystatic Vector f1;
1900 mystatic Vector f2;
1901 f1.SetLen(x.GetLen());
1902 f2.SetLen(x.GetLen());
1903
1904 IVector usage_per_row;
1905 ComputeSparseMatrixUsage(usage_per_row);
1906
1907 NLS_SetJacCol(0);
1908
1909 int m_initsize = MaxSparseBandwidth()*2;//2; //initial sparse matrix size
1910 mlocgs.SetSize(is,ss,m_initsize);
1911
1912 xx.SetLen(ss);
1913 //xx = TIx0;
1914 for (int i=1; i <= sos; i++)
1915 {
1916 xx(i) = x(i);
1917 xx(i+sos) = 0.; //velocities set to zero!
1918 }
1919 for (int i=1; i <= es; i++)
1920 xx(i+2*sos) = x(i+sos);
1921 for (int i=1; i <= is; i++)
1922 xx(i+2*sos+es) = x(i+sos+es);
1923
1924 //uo << "JacobianF2" << ", initsize=" << m_initsize << "\n";
1925 if (newmode)
1926 {
1927 m.SetSizePerColumn((sos+es+is),(sos+es+is), usage_per_row);
1928 m.FillWithZeros();
1929
1930 //fill in stiffness matrix directly:
1931 if (sos) StaticJacobianF2(m,xx);
1932 }
1933 else
1934 {
1935 m.SetSize((sos+es+is),(sos+es+is), m_initsize);
1936 m.FillWithZeros();
1937
1938 mlocf2s.SetSize(sos,ss,m_initsize);
1939 if (sos) LocalJacobianF2(mlocf2s,xx);
1940 //Stiffness part
1941 m.AddSubmatrix(mlocf2s,1,1,1,1,sos,sos,1);
1942 m.AddSubmatrix(mlocf2s,1,1+2*sos+es,1,1+sos+es,sos,is,1);
1943 }
1944
1945 if (is) LocalJacobianG(mlocgs,xx);
1946 if (es) {UO() << "Sparse static solver not implemented for first order ODEs!\n"; return; }
1947
1948 //Constraint part
1949 m.AddSubmatrix(mlocgs, 1,1,sos+es+1,1,is,sos,1);
1950 m.AddSubmatrix(mlocgs, 1,1+2*sos+es,sos+es+1,1+sos+es,is,is,1);
1951
1952 //UO() << "sparse jac=" << m << "\n";
1953
1954 //double msize = m.GetLAlloc();
1955 //double mused = m.CountEntries();
1956 //UO(UO_LVL_all) << "sparse matrix entries=" << mused << "\n";
1957 //UO(UO_LVL_all) << "sparse matrix allocated=" << msize << "\n";
1958
1959 //UO(UO_LVL_all) << "sparse matrix size=" << msize*8/1.e6 << "MB\n";
1960 //UO(UO_LVL_all) << "sparse matrix used=" << mused*8/1.e6 << "MB\n";
1961 //UO(UO_LVL_all) << "factor=" << msize/mused << "\n";
1962
1963 //for (int i=1; i <= m.Getrows(); i++)
1964 //{
1965 // if (m.RowLen(i) > usage_per_row(i))
1966 // {
1967 // UO(UO_LVL_all) << "rowlen(" << i << ")=" << m.RowLen(i) << ", est.=" << usage_per_row(i);
1968 // UO(UO_LVL_all) << " WARNING!";
1969 // UO(UO_LVL_all) << "\n";
1970 // }
1971
1972 //}
1973
1974 //uo << "ready\n";
1975
1976
1977 //UO(UO_LVL_all) << "mdiff=" << (mf-mf2).MaxNorm() << "\n";
1978 //UO(UO_LVL_all) << "mnew=" << mf2 << "\n";
1979 //UO(UO_LVL_all) << "inverse returns=" << mf.Invert2() << "\n";
1980
1981 //UO().InstantMessageText("wait");
1982
1983 //UO() << "jac_F2=" << mlocf2s << "\n";
1984 //UO() << "sparse jac=" << mf << "\n";
1985
1986 TMStopTimer(19);
1987 }
1988
1989
1990 int fullnewtonwarnedsparse = 0;
1991 //Compute approximate Jacobian (if modified newton) or call base function
Jacobian(SparseMatrix & m,Vector & x)1992 void TimeInt::Jacobian(SparseMatrix& m, Vector& x)
1993 {
1994 //UO() << "jac\n";
1995
1996 SetJacobianComputationFlag(1);
1997 //return;
1998 NLS_SetJacCol(0);
1999 IRK_Tableau* t = tableaus[act_tableau];
2000 int ns = t->nstages;
2001
2002 if (DoStaticComputation())
2003 {
2004 //uo << "jacobian...";
2005 StaticJacobian(m,x);
2006 //uo << "computed!\n";
2007 }
2008 else
2009 {
2010 if (!numsol.ModifiedNewtonActive() && !fullnewtonwarnedsparse)
2011 {
2012 uo << "ERROR: Full Newton called for Sparse Matrices!!!\n";
2013 fullnewtonwarnedsparse = 1;
2014
2015 //SetJacobianComputationFlag(0); //do this before return!!!
2016 //return;
2017 }
2018
2019
2020 TMStartTimer(19);
2021
2022 int m_initsize = MaxSparseBandwidth(); //initial sparse matrix size
2023 //UO() << "maxbandwidth=" << m_initsize << "\n";
2024 int i;
2025 int j;
2026
2027 int c0f = 0; //for lobattoIIIC und RadauIA methods!!!!
2028 if (t->c(1) == 0)
2029 {
2030 c0f = 1;
2031 }
2032
2033 int is = GetImplicitSize();
2034 int es = GetFirstOrderSize();
2035 int sos = GetSecondOrderSize();
2036 int ss = GetSystemSize();
2037 double tau = TIstep;
2038 double tau2 = TIstep*TIstep;
2039
2040 xx.SetLen(ss);
2041 xx = TIx0;
2042
2043 mlocms.SetSize(sos,sos,m_initsize); //usually 32
2044 mlocf2s.SetSize(sos,ss,m_initsize);
2045 mlocgs.SetSize(is,ss,m_initsize);
2046
2047 int locjacm_on = 0; //compute dM/TIkv ... normally not necessary!!!
2048
2049 mlocf.SetSize(es,ss);
2050 if (locjacm_on) mlocm2.SetSize(sos,sos);
2051
2052 diag.SetSize(es,es);
2053 diag.FillWithZeros();
2054 for (i=1; i<=es; i++)
2055 {
2056 diag(i,i) = 1.;
2057 }
2058
2059 if (es)
2060 {
2061 LocalJacobianF(mlocf,xx);
2062 }
2063
2064 if (sos)
2065 {
2066 LocalJacobianF2(mlocf2s,xx);
2067 EvalM(xx,mlocms,TItime+0.5*TIstep);
2068
2069 if (locjacm_on) LocalJacobianM(mlocm2,xx);
2070 }
2071
2072 if (is)
2073 {
2074 LocalJacobianG(mlocgs,xx);
2075 }
2076
2077 TMStopTimer(19);
2078 TMStartTimer(4);
2079
2080 m.SetSize((ns-c0f)*(sos+es+is),(ns-c0f)*(sos+es+is), m_initsize*(ns-c0f));
2081 m.FillWithZeros();
2082
2083
2084 for(i=1; i<= (ns-c0f); i++)
2085 {
2086 for(j=1; j<= (ns-c0f); j++)
2087 {
2088 int offri = sos*(i-1)+1;
2089 int offcj = sos*(j-1)+1;
2090 int offrif = sos*(ns-c0f)+es*(i-1)+1;
2091 int offcjf = sos*(ns-c0f)+es*(j-1)+1;
2092 int offrig = (sos+es)*(ns-c0f)+is*(i-1)+1;
2093 int offcjg = (sos+es)*(ns-c0f)+is*(j-1)+1;
2094
2095 //Part A: sos
2096 if (i==j) m.AddSubmatrix(mlocms,1,1,offri,offcj,sos,sos,-1);
2097 if (locjacm_on && i==j) m.AddSubmatrix(mlocm2,1,1,offri,offcj,sos,sos,-1*tau2*t->A2(i+c0f,j+c0f));
2098
2099 m.AddSubmatrix(mlocf2s,1,1, offri,offcj,sos,sos,tau2*t->A2(i+c0f,j+c0f));
2100 m.AddSubmatrix(mlocf2s,1,1+sos, offri,offcj,sos,sos,tau*t->A(i+c0f,j+c0f));
2101 m.AddSubmatrix(mlocf2s,1,1+sos*2, offri,offcjf,sos,es,tau*t->A(i+c0f,j+c0f));
2102 if (i==j) m.AddSubmatrix(mlocf2s,1,1+sos*2+es,offri,offcjg,sos,is,1);
2103
2104 //Part B: es
2105 m.AddSubmatrix(mlocf,1,1, offrif,offcj,es,sos,tau2*t->A2(i+c0f,j+c0f));
2106 m.AddSubmatrix(mlocf,1,1+sos, offrif,offcj,es,sos,tau*t->A(i+c0f,j+c0f));
2107 if (i==j) m.AddSubmatrix(diag,1,1,offrif,offcjf,es,es,-1);
2108 m.AddSubmatrix(mlocf,1,1+sos*2, offrif,offcjf,es,es,tau*t->A(i+c0f,j+c0f));
2109 if (i==j) m.AddSubmatrix(mlocf,1,1+sos*2+es,offrif,offcjg,es,is,1);
2110
2111 //Part C: is
2112 m.AddSubmatrix(mlocgs,1,1, offrig,offcj,is,sos,tau2*t->A2(i+c0f,j+c0f));
2113 m.AddSubmatrix(mlocgs,1,1+sos, offrig,offcj,is,sos,tau*t->A(i+c0f,j+c0f));
2114 m.AddSubmatrix(mlocgs,1,1+sos*2, offrig,offcjf,is,es,tau*t->A(i+c0f,j+c0f));
2115 if (i==j) m.AddSubmatrix(mlocgs,1,1+sos*2+es,offrig,offcjg,is,is,1);
2116
2117 }
2118 }
2119
2120 /*
2121 uo << "sos=" << sos << ",es=" << es << ",is=" << is << ",ns=" << ns << ",c0f=" << c0f << ",m=" << m.Getrows() << "x" << m.Getcols() << "\n";
2122 uo << "m-alloc=" << m.GetLAlloc() << "\n";
2123 uo << "mlocms-alloc=" << mlocms.GetLAlloc() << "\n";
2124 uo << "mlocf2s-alloc=" << mlocf2s.GetLAlloc() << "\n";
2125 uo << "mlocgs-alloc=" << mlocgs.GetLAlloc() << "\n";
2126 */
2127 //uo << "K=" << mlocf2s << "\n";
2128 //uo << "M=" << mlocms << "\n";
2129 }
2130
2131 //if (!system_matrices_written && solset.write_MK2file) //$ PG 2012-2-3: modified (see next line)
2132 if (!system_matrices_written && GetOptions()->LoggingOptions()->WriteMassAndStiffnessMatrix())
2133 {
2134 system_matrices_written= 1;
2135
2136 mystr dir = solset.sol_directory;
2137 mystr fileload = "loadMK.m";
2138 mystr fileK = "Kdat.dat";
2139 mystr fileM = "Mdat.dat";
2140
2141 ofstream fout((dir+fileload).c_str());
2142 fout << "load Kdat.dat\nK = spconvert(Kdat);\n";
2143 ofstream Kdat((dir+fileK).c_str());
2144 ofstream Mdat((dir+fileM).c_str());
2145
2146 if (!DoStaticComputation())
2147 {
2148 int dim = mlocms.Getcols();
2149 SparseMatrix KS;
2150 KS.CopyFrom(mlocf2s,1,1,dim,dim);
2151 KS.PrintToMatlabSparse(Kdat);
2152
2153 mlocms.PrintToMatlabSparse(Mdat);//mlocms=massenmatrix, schreibe in Mdat-File im Matlab-Format
2154
2155 fout << "load Mdat.dat\nM = spconvert(Mdat);\n";
2156 //uo << "M=" << mlocms.GetMatrix() << "\n";
2157 //uo << "K=" << KS.GetMatrix() << "\n";
2158 }
2159 else
2160 {
2161 m.PrintToMatlabSparse(Kdat);
2162 //uo << "K=" << m << "\n";
2163 }
2164 fout << flush;
2165
2166 UO() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
2167 UO() << "M and K written to file '" << (dir+fileM) << "'\nand '" << (dir+fileK) << "'!\n";
2168 UO() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
2169
2170 //PrintMatrix01(m.GetMatrix());
2171 }
2172
2173 SetJacobianComputationFlag(0);
2174 }
2175
2176 //Compute approximate Jacobian (if modified newton) or call base function
2177 int fulljacobianwarned = 0;
Jacobian(Matrix & m,Vector & x)2178 void TimeInt::Jacobian(Matrix& m, Vector& x)
2179 {
2180 SetJacobianComputationFlag(1);
2181
2182 NLS_SetJacCol(0);
2183 IRK_Tableau* t = tableaus[act_tableau];
2184 int ns = t->nstages;
2185
2186 if (DoStaticComputation())
2187 {
2188 TMStartTimer(3);
2189 int i,j;
2190 mystatic Vector f1;
2191 mystatic Vector f2;
2192 f1.SetLen(x.GetLen());
2193 f2.SetLen(x.GetLen());
2194
2195 m.SetSize(x.GetLen(),x.GetLen());
2196
2197 int usefullnewton = 1; //0 is faster
2198
2199 if (usefullnewton)
2200 {
2201 double numdiffepsi = this->NLS_NumDiffepsi();
2202 NLS_SetJacCol(0);
2203 NLS_SetJacFullNewton(1);
2204
2205 FullNewtonCnt()++;
2206
2207 if (!NLS_SymmetricJacobian())
2208 {
2209 NLF(x,f2);
2210 }
2211 double eps;
2212 double xstore;
2213 //UO() << "len=" << m.Getcols() << "\n";
2214 for (i = 1; i <= m.Getcols(); i++)
2215 {
2216 eps = numdiffepsi*Maximum(1e-2,fabs(x(i)));
2217 if (NLS_SymmetricJacobian())
2218 {
2219 int jc = i;
2220 if (i > GetSecondOrderSize()) jc += GetSecondOrderSize();
2221 NLS_SetJacCol(jc);
2222
2223 xstore = x(i);
2224 x(i) += eps;
2225 NLF(x,f1);
2226
2227 x(i) -= 2*eps;
2228 NLF(x,f2);
2229
2230 //$ PG 2013-4-24: [ debugging output
2231 //int gsize=f2.Length()-GetSecondOrderSize();
2232 //Vector differenc(gsize);
2233 //for(int j=1; j<=gsize; j++) differenc(j) = f2(GetSecondOrderSize()+j) - f1(GetSecondOrderSize()+j);
2234 //UO(UO_LVL_dbg1) << "i=" <<i<<", diff = " << differenc << "\n";
2235 //$ PG 2013-4-24: ]
2236
2237 x(i) = xstore;
2238 }
2239 else
2240 {
2241 xstore = x(i);
2242 x(i) += 2*eps;
2243 NLF(x,f1);
2244 x(i) = xstore;
2245 }
2246
2247 for (j=1; j<=f1.GetLen(); j++)
2248 {
2249 m(j,i)=0.5/eps*(f1(j)-f2(j));
2250 }
2251 }
2252
2253 NLS_SetJacFullNewton(0);
2254 NLS_SetJacCol(0);
2255 }
2256 else
2257 {
2258 int is = GetImplicitSize();
2259 int es = GetFirstOrderSize();
2260 int sos = GetSecondOrderSize();
2261 int ss = GetSystemSize();
2262
2263 mlocf.SetSize(es,ss);
2264 mlocf2.SetSize(sos,ss);
2265 mlocg.SetSize(is,ss);
2266
2267 xx.SetLen(ss);
2268 for (int i=1; i <= sos; i++)
2269 {
2270 xx(i) = x(i);
2271 xx(i+sos) = 0.; //velocities set to zero!
2272 }
2273 for (int i=1; i <= es; i++)
2274 xx(i+2*sos) = x(i+sos);
2275 for (int i=1; i <= is; i++)
2276 xx(i+2*sos+es) = x(i+sos+es);
2277
2278 if (sos)
2279 {
2280 LocalJacobianF2(mlocf2,xx);
2281 }
2282 if (es)
2283 {
2284 LocalJacobianF(mlocf,xx);
2285 }
2286 if (is)
2287 {
2288 LocalJacobianG(mlocg,xx);
2289 }
2290
2291 int j1;
2292 for (int j=1; j <= sos+es+is; j++)
2293 {
2294 j1 = j;
2295 if (j > sos) j1+=sos;
2296 for (int i = 1; i <= sos; i++)
2297 m(i,j) = mlocf2(i,j1);
2298
2299 for (int i = 1; i <= es; i++)
2300 m(i+sos,j) = mlocf(i,j1);
2301
2302 for (int i = 1; i <= is; i++)
2303 m(i+sos+es,j) = mlocg(i,j1);
2304 }
2305
2306 }
2307 TMStopTimer(3);
2308
2309 //UO() << "jac_static=" << m << "\n";
2310 //uo << "Jac=\n"; PrintMatrix01(m);
2311
2312 //if (!system_matrices_written && solset.write_MK2file) //$ PG 2012-2-3: modified (see next line)
2313 if (!system_matrices_written && GetOptions()->LoggingOptions()->WriteMassAndStiffnessMatrix())
2314 {
2315 system_matrices_written= 1;
2316
2317 mystr dir = solset.sol_directory;
2318 mystr fileK = "Kdat.dat";
2319 mystr fileload = "loadK.m";
2320
2321 ofstream fout((dir+fileload).c_str());
2322 ofstream Kdat((dir+fileK).c_str());
2323
2324 SparseMatrix KS(m);
2325 KS.PrintToMatlabSparse(Kdat);
2326 fout << "load Kdat.dat\nK = spconvert(Kdat);\n";
2327
2328 uo << "jacobian written to '" << (dir+fileK) << "\n";
2329 }
2330
2331 //uo << "Jac=\n"; PrintMatrix01(m);
2332
2333 SetJacobianComputationFlag(0);
2334 return;
2335 }
2336
2337 if (!numsol.ModifiedNewtonActive())
2338 {
2339 if (0)
2340 {
2341 NumNLSys::NLS_SetTIstages(ns);
2342 NumNLSys::Jacobian(m,x);
2343 SetJacobianComputationFlag(0);
2344 return;
2345 }
2346 else
2347 {
2348 if (!fulljacobianwarned)
2349 {
2350 fulljacobianwarned=1;
2351 uo << "Warning: Full Jacobian turned off!!!\n";
2352 }
2353 }
2354 }
2355
2356 //compute kversionjacobian +++
2357 if (KVersion())
2358 {
2359 TMStartTimer(19);
2360 int i;
2361 int j;
2362
2363 int c0f = 0; //for lobattoIIIC und RadauIA methods!!!!
2364 if (t->c(1) == 0)
2365 {
2366 c0f = 1;
2367 }
2368
2369 int is = GetImplicitSize();
2370 int es = GetFirstOrderSize();
2371 int sos = GetSecondOrderSize();
2372 int ss = GetSystemSize();
2373 double tau = TIstep;
2374 double tau2 = TIstep*TIstep;
2375
2376 xx.SetLen(ss);
2377 xx = TIx0;
2378
2379 mlocf.SetSize(es,ss);
2380 mlocf2.SetSize(sos,ss);
2381
2382 int minit = 0;
2383 if (mlocm.Getcols() != sos) minit = 1;
2384 mlocm.SetSize(sos,sos);
2385 if (minit) mlocm = 0.;
2386
2387 mlocg.SetSize(is,ss);
2388 mlocm2.SetSize(sos,sos);
2389 int locjacm_on = 0; //compute dM/TIkv ... normally not necessary!!!
2390
2391 diag.SetSize(es,es);
2392 diag.FillWithZeros();
2393 for (i=1; i<=es; i++)
2394 {
2395 diag(i,i) = 1.;
2396 }
2397
2398 if (es)
2399 {
2400 LocalJacobianF(mlocf,xx);
2401 }
2402 if (sos)
2403 {
2404 LocalJacobianF2(mlocf2,xx);
2405 EvalM(xx,mlocm,TItime+0.5*TIstep);
2406
2407 if (locjacm_on) LocalJacobianM(mlocm2,xx);
2408 }
2409 if (is)
2410 {
2411 LocalJacobianG(mlocg,xx);
2412 }
2413 TMStopTimer(19);
2414 TMStartTimer(4);
2415
2416 m.SetSize((ns-c0f)*(sos+es+is),(ns-c0f)*(sos+es+is));
2417 m.FillWithZeros(1, 1, (ns-c0f)*(sos+es+is), (ns-c0f)*(sos+es+is));
2418
2419
2420 for(i=1; i<= (ns-c0f); i++)
2421 {
2422 for(j=1; j<= (ns-c0f); j++)
2423 {
2424 int offri = sos*(i-1)+1;
2425 int offcj = sos*(j-1)+1;
2426 int offrif = sos*(ns-c0f)+es*(i-1)+1;
2427 int offcjf = sos*(ns-c0f)+es*(j-1)+1;
2428 int offrig = (sos+es)*(ns-c0f)+is*(i-1)+1;
2429 int offcjg = (sos+es)*(ns-c0f)+is*(j-1)+1;
2430
2431 //Part A: sos
2432 if (i==j) m.AddSubmatrix(mlocm,1,1,offri,offcj,sos,sos,-1);
2433 if (locjacm_on && i==j) m.AddSubmatrix(mlocm2,1,1,offri,offcj,sos,sos,-1*tau2*t->A2(i+c0f,j+c0f));
2434 m.AddSubmatrix(mlocf2,1,1, offri,offcj,sos,sos,tau2*t->A2(i+c0f,j+c0f));
2435 m.AddSubmatrix(mlocf2,1,1+sos, offri,offcj,sos,sos,tau*t->A(i+c0f,j+c0f));
2436 m.AddSubmatrix(mlocf2,1,1+sos*2, offri,offcjf,sos,es,tau*t->A(i+c0f,j+c0f));
2437 if (i==j) m.AddSubmatrix(mlocf2,1,1+sos*2+es,offri,offcjg,sos,is,1);
2438
2439 //Part B: es
2440 m.AddSubmatrix(mlocf,1,1, offrif,offcj,es,sos,tau2*t->A2(i+c0f,j+c0f));
2441 m.AddSubmatrix(mlocf,1,1+sos, offrif,offcj,es,sos,tau*t->A(i+c0f,j+c0f));
2442 if (i==j) m.AddSubmatrix(diag,1,1,offrif,offcjf,es,es,-1);
2443 m.AddSubmatrix(mlocf,1,1+sos*2, offrif,offcjf,es,es,tau*t->A(i+c0f,j+c0f));
2444 if (i==j) m.AddSubmatrix(mlocf,1,1+sos*2+es,offrif,offcjg,es,is,1);
2445
2446
2447 //Part C: is, original
2448 m.AddSubmatrix(mlocg,1,1, offrig,offcj,is,sos,tau2*t->A2(i+c0f,j+c0f));
2449 m.AddSubmatrix(mlocg,1,1+sos, offrig,offcj,is,sos,tau*t->A(i+c0f,j+c0f));
2450 m.AddSubmatrix(mlocg,1,1+sos*2, offrig,offcjf,is,es,tau*t->A(i+c0f,j+c0f));
2451 if (i==j) m.AddSubmatrix(mlocg,1,1+sos*2+es,offrig,offcjg,is,is,1);
2452 /*
2453 //Part A: sos
2454 if (i==j) m.AddSubmatrix(mlocm,1,1,offri,offcj,sos,sos,-1);
2455 if (locjacm_on && i==j) m.AddSubmatrix(mlocm2,1,1,offri,offcj,sos,sos,-1*tau2*t->A2(i+c0f,j+c0f));
2456 m.AddSubmatrix(mlocf2,1,1, offri,offcj,sos,sos,tau2*t->A2(i+c0f,j+c0f));
2457 m.AddSubmatrix(mlocf2,1,1+sos, offri,offcj,sos,sos,tau*t->A(i+c0f,j+c0f));
2458 m.AddSubmatrix(mlocf2,1,1+sos*2, offri,offcjf,sos,es,tau*t->A(i+c0f,j+c0f));
2459 if (i==j) m.AddSubmatrix(mlocf2,1,1+sos*2+es,offri,offcjg,sos,is,1);
2460
2461 //Part C: is
2462 m.AddSubmatrix(mlocg,1,1, offrig,offcj,is,sos,tau2*t->A2(i+c0f,j+c0f));
2463 m.AddSubmatrix(mlocg,1,1+sos, offrig,offcj,is,sos,tau*t->A(i+c0f,j+c0f));
2464 m.AddSubmatrix(mlocg,1,1+sos*2, offrig,offcjf,is,es,tau*t->A(i+c0f,j+c0f));
2465 if (i==j) m.AddSubmatrix(mlocg,1,1+sos*2+es,offrig,offcjg,is,is,1);
2466 */
2467 }
2468 }
2469
2470 TMStopTimer(4);
2471
2472
2473 //if (!system_matrices_written && solset.write_MK2file /*&& RelApproxi(GetTime(), 0.320)*/) //$ PG 2012-2-3: modified (see next line)
2474 if (!system_matrices_written && GetOptions()->LoggingOptions()->WriteMassAndStiffnessMatrix() /*&& RelApproxi(GetTime(), 0.320)*/)
2475 {
2476 system_matrices_written= 1;
2477
2478 mystr dir = solset.sol_directory;
2479 mystr fileload = "loadMK.m";
2480 mystr fileK = "Kdat.dat";
2481 mystr fileM = "Mdat.dat";
2482 mystr fileD = "Ddat.dat";
2483
2484 ofstream fout((dir+fileload).c_str());
2485 ofstream Kdat((dir+fileK).c_str());
2486 ofstream Mdat((dir+fileM).c_str());
2487 ofstream Ddat((dir+fileD).c_str());
2488
2489 int dim = mlocm.Getcols();
2490 Matrix KK; KK.CopyFrom(mlocf2,1,1,dim,dim);
2491
2492 //int dim = m.Getcols(); //full jacobian
2493 //Matrix KK; KK.CopyFrom(m,1,1,dim,dim);
2494
2495
2496 SparseMatrix KS(KK);
2497 KS.PrintToMatlabSparse(Kdat);
2498 fout << "load Kdat.dat\nK = spconvert(Kdat);\n";
2499
2500 Matrix DD; DD.CopyFrom(mlocf2,1,1+dim,dim,dim*2);
2501 SparseMatrix DS(DD);
2502 DS.PrintToMatlabSparse(Ddat);
2503 fout << "load Ddat.dat\nD = spconvert(Ddat);\n";
2504
2505 SparseMatrix MS(mlocm);
2506 MS.PrintToMatlabSparse(Mdat);
2507 fout << "load Mdat.dat\nM = spconvert(Mdat);\n";
2508 fout << "% use command FULL to show complete matrices\n";
2509
2510 fout << flush;
2511
2512 UO() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
2513 UO() << "M and K written to file '" << (dir+fileM) << "'\nand '" << (dir+fileK) << "'!\n";
2514 UO() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
2515 }
2516
2517
2518 /*
2519 uo << "Jac=" << m << "\n";
2520 uo << "K=" << mlocf2 << "\n";
2521 uo << "M=" << mlocm << "\n";
2522 PrintMatrix01(m); */
2523 /*
2524 Matrix mi = m;
2525 mi.Invert();
2526 uo << "minv=" << mi << "\n";
2527 uo << "m*minv=" << (m*mi) << "\n";
2528 */
2529 /*
2530 uo << "TIx0=" << TIx0 << "\n";
2531 //PrintMatrix01(m);
2532 uo << m << "\n";
2533 */
2534
2535 //if (RelApproxi(TItime, 0.0) || RelApproxi(TItime, 0.320))
2536 {
2537 //uo << "Jac=" << m << "\n";
2538 //uo << "K=" << mlocf2 << "\n";
2539 //uo << "M=" << mlocm << "\n";
2540 }
2541
2542 /*
2543 Matrix minv = m;
2544 uo << "Jac-invertible=" << minv.Invert2() << "\n";
2545 uo << "M^-1=" << minv << "\n";*/
2546
2547
2548
2549
2550 }
2551 else if (GetSecondOrderSize()==0)
2552 {
2553 IRK_Tableau* t = tableaus[act_tableau];
2554
2555 int i;
2556 int j;
2557
2558 int is = GetImplicitSize();
2559 int es = GetFirstOrderSize();
2560 int ss = GetSystemSize();
2561
2562
2563 mlocf.SetSize(es,ss);
2564 mlocg.SetSize(is,ss);
2565 mlocf2.SetSize(es,ss);
2566
2567 diag.SetSize(es,es);
2568 diag.FillWithZeros();
2569 for (i=1; i<=es; i++)
2570 {
2571 diag(i,i) = -1.;
2572 }
2573
2574 LocalJacobianF(mlocf,x);
2575 LocalJacobianG(mlocg,x);
2576
2577 m.SetSize(ns*(es+is),ns*(es+is));
2578
2579 for(i=1; i<= ns; i++)
2580 {
2581 for(j=1; j<= ns; j++)
2582 {
2583 mlocf2 = mlocf;
2584 mlocf2 *= (TIstep * t->A(i,j));
2585
2586 if (i==j)
2587 {
2588 mlocf2.AddMatrix(1,1,diag);
2589 m.InsertMatrix(es*ns+1+(i-1)*is,1+(j-1)*es,mlocg,1,1,is,es);
2590 m.InsertMatrix(es*ns+1+(i-1)*is,1+es*ns+(j-1)*is,mlocg,1,es+1,is,is);
2591 }
2592 else
2593 {
2594 m.FillWithZeros(es*ns+1+(i-1)*is,1+(j-1)*es,is,es);
2595 m.FillWithZeros(es*ns+1+(i-1)*is,1+es*ns+(j-1)*is,is,is);
2596 }
2597 m.InsertMatrix(1+(i-1)*es,1+(j-1)*es,mlocf2,1,1,es,es);
2598 m.InsertMatrix(1+(i-1)*es,1+es*ns+(j-1)*is,mlocf2,1,1+es,es,is);
2599 }
2600 }
2601 }
2602 else
2603 {
2604 NumNLSys::Jacobian(m,x);
2605 SetJacobianComputationFlag(0);
2606 return;
2607 }
2608
2609 //uo << "Jac=\n"; PrintMatrix01(m);
2610
2611 SetJacobianComputationFlag(0);
2612 }
2613
NLF(const Vector & x,Vector & f)2614 void TimeInt::NLF(const Vector& x, Vector& f)
2615 {
2616 TMStartTimer(13);
2617 int ss = GetSystemSize();
2618 int is = GetImplicitSize();
2619 int es = GetFirstOrderSize();
2620 int sos = GetSecondOrderSize();
2621
2622 if (DoStaticComputation())
2623 {
2624 //$$$
2625 evalf.SetLen(sos);
2626 evalfe.SetLen(es);
2627 evalg.SetLen(is);
2628 xh.SetLen(2*sos+es+is);
2629
2630 //use vector xh - help vector
2631 //copy components and set velocities 0
2632 xh.Copy(x,1,1,sos);
2633 xh.Copy(x,1+sos,1+2*sos,es);
2634 xh.Copy(x,1+sos+es,1+2*sos+es,is);
2635 for (int i = 1+sos; i <= 2*sos; i++) xh(i) = 0;
2636 //uo << "xh=" << xh << "\n";
2637 EvalF2(xh, evalf, TItime);
2638 EvalF(xh,evalfe, TItime);
2639 EvalG(xh,evalg, TItime);
2640 //uo << "evalf=" << evalf << "\n";
2641
2642 //does not work, spring-type regularisation:
2643 if (solset.static_spring_type_reg_param != 0.)
2644 {
2645 for (int i=1; i <= sos; i++) evalf(i) -= LoadFact()*solset.static_spring_type_reg_param*x(i);
2646 }
2647 f.SetLen(sos+es+is);
2648 f.Copy(evalf, 1,1,sos);
2649 f.Copy(evalfe,1,1+sos,es);
2650 f.Copy(evalg, 1,1+sos+es,is);
2651
2652 //uo << "NLF=" << f << "\n";
2653 TMStopTimer(13);
2654 return;
2655 }
2656
2657
2658 IRK_Tableau* t = tableaus[act_tableau];
2659 int ns = t->nstages;
2660
2661 if (!impl_equ_flag)
2662 {
2663
2664 int i, j;
2665
2666 //Kversion of Runge Kutta schemes:
2667 if (TIkv)
2668 {
2669 evalf.SetLen(sos);
2670 evalfe.SetLen(es);
2671 evalg.SetLen(is);
2672 int ns = t->nstages;
2673 int c0f = 0; //for lobattoIIIC und RadauIA methods!!!!
2674 if (t->c(1) == 0)
2675 {
2676 c0f = 1;
2677 }
2678
2679 if (c0f)
2680 {
2681 ku[1] = TIku0;
2682 kv[1] = TIkv0;
2683 kue[1] = TIku0e;
2684 }
2685
2686 //construct kv[i]
2687 for (i = 1; i <= (ns-c0f); i++)
2688 {
2689 kv[i+c0f].SetLen(sos);
2690 kv[i+c0f].Copy(x,1+sos*(i-1),1,sos);
2691 }
2692 //construct kue[i]
2693 for (i = 1; i <= (ns-c0f); i++)
2694 {
2695 kue[i+c0f].SetLen(es);
2696 kue[i+c0f].Copy(x,1+sos*(ns-c0f)+es*(i-1),1,es);
2697 }
2698
2699 xh.SetLen(sos);
2700 //compute ku[i]
2701 for (i = 1; i <= (ns-c0f); i++)
2702 {
2703 ku[i+c0f] = TIv0;
2704 for (j = 1; j <= ns; j++)
2705 {
2706 /*
2707 xh = kv[j];
2708 xh *= TIstep * t->A(i+c0f,j);
2709 ku[i+c0f] += xh;*/
2710 ku[i+c0f].MultAdd(TIstep * t->A(i+c0f,j), kv[j]);
2711 }
2712 }
2713 //TIu0, TIv0, TIu0e passed from GeneralIStep
2714
2715 //++++++++++++++++++++++++++++++++++++++++++++++++
2716 //construct xi[i]:
2717
2718 //Compute gu[i]
2719 for (i = 1; i <= ns; i++)
2720 {
2721 gu[i] = TIu0;
2722 for (j = 1; j <= ns; j++)
2723 {
2724 /*xh = ku[j];
2725 xh *= TIstep * t->A(i,j);
2726 gu[i] += xh;*/
2727 gu[i].MultAdd(TIstep * t->A(i,j),ku[j]);
2728 }
2729 }
2730
2731 //Compute gv[i]
2732 for (i = 1; i <= ns; i++)
2733 {
2734 gv[i] = TIv0;
2735 for (j = 1; j <= ns; j++)
2736 {
2737 /*xh = kv[j];
2738 xh *= TIstep * t->A(i,j);
2739 gv[i] += xh;*/
2740 gv[i].MultAdd(TIstep * t->A(i,j),kv[j]);
2741 }
2742 }
2743
2744 //Compute gue[i]
2745 if (es!=0)
2746 {
2747 xh2.SetLen(es);
2748 for (i = 1; i <= ns; i++)
2749 {
2750 gue[i] = TIu0e;
2751 for (j = 1; j <= ns; j++)
2752 {
2753 /*xh2 = kue[j];
2754 xh2 *= TIstep * t->A(i,j);
2755 gue[i] += xh2;*/
2756 gue[i].MultAdd(TIstep * t->A(i,j),kue[j]);
2757 }
2758 }
2759 }
2760 //construct iv[i]
2761 for (i = 1; i <= (ns-c0f); i++)
2762 {
2763 iv[i].SetLen(is);
2764 iv[i].Copy(x,(ns-c0f)*(sos+es)+1+is*(i-1),1,is);
2765 }
2766
2767 for (i = 1; i <= (ns-c0f); i++)
2768 {
2769 xi[i].SetLen(2*sos+es+is);
2770 xi[i].Copy(gu[i+c0f],1,1,sos);
2771 xi[i].Copy(gv[i+c0f],1,1+sos,sos);
2772 xi[i].Copy(gue[i+c0f],1,1+2*sos,es);
2773 xi[i].Copy(iv[i],1,1+2*sos+es,is);
2774 }
2775 //++++++++++++++++++++++++++++++++++++++++++++++++
2776
2777 f.SetLen((sos+is+es)*(ns-c0f));
2778 if (sos != 0)
2779 {
2780 //Compute -M_i K_i + F(u_i,v_i)
2781 evalf.SetLen(sos);
2782 xh.SetLen(sos);
2783 for (i = 1; i <= (ns-c0f); i++)
2784 {
2785 PrecomputeEvalFunctions(); //$ PG 2012-1-15: precomputation for EvalF(), EvalF2(), EvalG(), EvalM(), and also for CqTLambda() in case of constraints //BUG: at the moment only available for EvalF2() and EvalM() //Has to be fixed via reorganizing loops in NLF(..)
2786 if (!UseSparseMass())
2787 {
2788 TIm.SetSize(sos,sos);
2789 if (!TIm_initialized)
2790 {
2791 TIm.FillWithZeros();
2792 TIm_initialized = 1;
2793 EvalM(xi[i], TIm, TItime+TIstep*t->c(i+c0f));
2794
2795 if (TransformJacApply())
2796 {
2797 //uo << "***********************\nERROR: Buggy Mass matrix used!!!!!!!!!!\n***********************\n";
2798 uo << "***********************\nWARNING: Modified Mass matrix used!!!!!!!!!!\n***********************\n";
2799 }
2800 }
2801 if (!TransformJacApply() && !solset.assume_constant_mass_matrix)
2802 {
2803 EvalM(xi[i], TIm, TItime+TIstep*t->c(i+c0f));
2804 }
2805 }
2806 else
2807 {
2808 //use sparse mass matrix:
2809 if (!TIm_initialized || !TransformJacApply())
2810 {
2811 TIm_initialized = 1;
2812 TIm_sparse.SetSize(sos,sos,MaxSparseBandwidth());
2813 TIm_sparse.FillWithZeros();
2814 EvalM(xi[i], TIm_sparse, TItime+TIstep*t->c(i+c0f));
2815 if (TransformJacApply())
2816 uo << "***********************\nWARNING: Modified Mass matrix used!!!!!!!!!!\n***********************\n";
2817 //uo << "***************\nERROR: Buggy Mass matrix used!!!!!!!!!!\n***************\n";
2818 }
2819 else if (!TransformJacApply() && !solset.assume_constant_mass_matrix)
2820 {
2821 //sometimes not needed!!!
2822 TIm_sparse.FillWithZeros();
2823 EvalM(xi[i], TIm_sparse, TItime+TIstep*t->c(i+c0f));
2824 }
2825 }
2826 EvalF2(xi[i], evalf, TItime+TIstep*t->c(i+c0f));
2827
2828 //for (int k=1; k<=20; k++)
2829 if (!UseSparseMass())
2830 {
2831 if (bandwidthm)
2832 {
2833 MultBW(TIm,kv[i+c0f],xh,bandwidthm);
2834 }
2835 else
2836 {
2837 Mult(TIm,kv[i+c0f],xh);
2838 }
2839 }
2840 else
2841 {
2842 Mult(TIm_sparse,kv[i+c0f],xh);
2843 }
2844 evalf -= xh; //evalf = -M_i K_i + F(u_i,v_i)
2845 f.Copy(evalf,1,1+(i-1)*sos,sos);
2846 }
2847 }
2848 if (es != 0)
2849 {
2850 evalfe.SetLen(es);
2851 for (i = 1; i <= (ns-c0f); i++)
2852 {
2853 EvalF(xi[i],evalfe,TItime+TIstep*t->c(i+c0f));
2854 evalfe-=kue[i+c0f];
2855 f.Copy(evalfe,1,1+(ns-c0f)*sos+es*(i-1),es);
2856 }
2857 }
2858 if (is != 0)
2859 {
2860 for (i = 1; i <= (ns-c0f); i++)
2861 {
2862 EvalG(xi[i],evalg,TItime+TIstep*t->c(i+c0f));
2863 f.Copy(evalg,1,1+(ns-c0f)*(sos+es)+is*(i-1),is);
2864 }
2865 }
2866 }
2867 //pure first order equations (with constraints):
2868 else if (GetSecondOrderSize() == 0)
2869 {
2870
2871 evalg.SetLen(is);
2872 evalf.SetLen(es);
2873
2874 for (i = 1; i <= ns; i++)
2875 {
2876 gv[i].SetLen(es);
2877 gv[i].Copy(x,1+es*(i-1),1,es);
2878
2879 iv[i].SetLen(is);
2880 iv[i].Copy(x,1+ns*es+is*(i-1),1,is);
2881
2882 xv[i].SetLen(es+is);
2883 xv[i].Copy(x,1+es*(i-1),1,es);
2884 xv[i].Copy(x,1+ns*es+is*(i-1),1+es,is);
2885 }
2886
2887 TIu0.SetLen(es);
2888 TIu0.Copy(TIx0,1,1,es);
2889
2890 f.SetLen(ns*(es+is));
2891
2892 for (j = 1; j <= ns; j++)
2893 {
2894 evalfs[j].SetLen(es);
2895 EvalF(xv[j], evalfs[j], TItime+TIstep*t->c(j));
2896 }
2897
2898 for (i = 1; i <= ns; i++)
2899 {
2900 fg = TIu0;
2901 fg -= gv[i];
2902 for (j = 1; j <= ns; j++)
2903 {
2904 //EvalF(xv[j], evalf, TItime+TIstep*t->c[j]);
2905 evalf = evalfs[j];
2906 evalf.Mult(TIstep * t->A(i,j));
2907 fg += evalf;
2908 }
2909 f.Copy(fg,1,1+(i-1)*es,es);
2910 }
2911
2912 if (is != 0)
2913 {
2914 for (i = 1; i <= ns; i++)
2915 {
2916 EvalG(xv[i],evalg,TItime+TIstep*t->c(i));
2917 f.Copy(evalg,1,1+ns*es+(i-1)*is,is);
2918 }
2919 }
2920 }
2921 }
2922 else
2923 {
2924 EvalG((TIx0.SubVector(1,es)).Append(x),f,TItime+TIstep);
2925 }
2926 TMStopTimer(13);
2927 }
2928
2929 //convert seconds to format days hours:min:secs
GetTString(double s)2930 mystr GetTString(double s)
2931 {
2932 int days = (int)(s/(3600.*24.));
2933 int hours = (int)((s-days*(3600*24))/3600.);
2934 int mins = (int)((s-days*(3600*24)-hours*3600)/60.);
2935 int secs = (int)((s-days*(3600*24)-hours*3600-mins*60));
2936 int millis = (int)((s-(double)((int)s))*10.);
2937
2938 mystr ts="";
2939 if (days) {ts+=mystr(days)+mystr(" days, ");};
2940 if (hours || days)
2941 {
2942 ts+=mystr(hours)+mystr(":");
2943 if (mins < 10) {ts+="0";}
2944 };
2945 ts+=mystr(mins)+mystr(":");
2946 if (secs < 10) {ts+="0";}
2947 ts+=mystr(secs)+mystr(".");
2948 ts+=mystr(millis);
2949
2950 return ts;
2951 }
2952
GetClockTime() const2953 double TimeInt::GetClockTime() const
2954 {
2955 timeb tb;
2956 tb.time = 0;
2957 tb.millitm = 0;
2958 ftime(&tb);
2959 //cout << "time=" << tb.time << ", millisec=" << tb.millitm << endl;
2960 return tb.time+(double)tb.millitm*0.001;
2961 }
2962
LoadTableaus(const mystr & tableauname)2963 void TimeInt::LoadTableaus(const mystr& tableauname)
2964 {
2965
2966
2967 //----------------------------------- read tableau
2968 CMFile tin(tableauname, TFMread);
2969
2970 int ntab, i, j, k;
2971
2972 mystr method;
2973 IRK_Tableau* tableau;
2974 tableaus.SetLen(0);
2975
2976 #ifdef COMPILE_AND
2977 #include "../ANDlib/LoadTableaus_And.h"
2978 #else
2979
2980 tin.RWInt(ntab); // #tableaus
2981 if(ntab < 1 || ntab > 10000)
2982 {
2983 uo.pUI->InstantMessageText("Could not load the tables from \"" + tableauname + "\"!! Check if working directory of WCDriver is set.");
2984 return;
2985 }
2986
2987 i = 1;
2988 while(i <= ntab)
2989 {
2990
2991 tin.RWuntilEOL(method,0);
2992
2993 if (method == mystr("#Runge-Kutta"))
2994 {
2995 tableau = new IRK_Tableau();
2996
2997 tableaus.Add(tableau);
2998
2999 i++;
3000
3001 tin.RWuntilEOL(tableau->name,0);
3002 tin.RWuntilEOL(tableau->info,0);
3003 tin.RWInt(tableau->ODE_order);
3004 //uo << "load tableau '" << tableau->name << "', order=" << tableau->ODE_order << ENDL;
3005
3006 tin.RWInt(tableau->DAE_order_y[1]);
3007 tin.RWInt(tableau->DAE_order_y[2]);
3008 tin.RWInt(tableau->DAE_order_z[1]);
3009 tin.RWInt(tableau->DAE_order_z[2]);
3010 tin.RWInt(tableau->nstages);
3011
3012 int ns=tableau->nstages;
3013 tableau->b = Vector(ns);
3014 for (j = 1; j <= ns; j++)
3015 {
3016 tin.RWDouble(tableau->b(j));
3017 }
3018
3019 tableau->c = Vector(ns);
3020 for (j = 1; j <= ns; j++)
3021 {
3022 tin.RWDouble(tableau->c(j));
3023 }
3024
3025 tableau->A = Matrix(ns, ns);
3026 for (j = 1; j <= ns; j++)
3027 {
3028 for (k = 1; k <= ns; k++)
3029 {
3030 tin.RWDouble(tableau->A(j,k));
3031 }
3032 }
3033
3034 //second order equations:
3035 tableau->A2 = tableau->A*tableau->A;
3036 //for methods which do not fulfill c1=1:
3037 tableau->Ainv = tableau->A;
3038 tableau->Ainvertable = tableau->Ainv.Invert();
3039 if (tableau->Ainvertable)
3040 {
3041 tableau->bAinv = tableau->b*tableau->Ainv;
3042 }
3043
3044 //check if tableau is implicit
3045 tableau->implicit = 0;
3046 if (tableau->c(1) != 0) {tableau->implicit = 1;}
3047 for (j = 1; j <= ns; j++)
3048 {
3049 for (k = j; k <= ns; k++)
3050 {
3051 if (tableau->A(j,k) != 0) {tableau->implicit = 1;}
3052 }
3053 }
3054 /*
3055 if (!tableau->implicit)
3056 {
3057 uo << tableau->info << "\n"
3058 << "A=" << tableau->A << "\n"
3059 << "b=" << tableau->b << "\n"
3060 << "c=" << tableau->c << "\n";
3061 }*/
3062 }
3063 }
3064 #endif
3065 uo << "loaded " << ntab << " Runge Kutta Tableaus\n";
3066 };
3067
3068
GetTableau(mystr tabname,int stages)3069 int TimeInt::GetTableau(mystr tabname, int stages)
3070 {
3071
3072 int i=1;
3073 while (i<=tableaus.Length() && (tableaus[i]->name != tabname || tableaus[i]->nstages != stages))
3074 {
3075 i++;
3076 }
3077
3078 if (i>tableaus.Length())
3079 {
3080 uo << "ERROR: Could not find an according tableau '" << tabname.c_str()
3081 << "'\n to the number of stages" << stages << " !" << ENDL;
3082 return 0;
3083 }
3084 else
3085 {
3086 return i;
3087 }
3088 }
3089
LoadTableauList(mystr tabname,TArray<int> & list,int minstage,int maxstage)3090 int TimeInt::LoadTableauList(mystr tabname, TArray<int>& list, int minstage, int maxstage)
3091 {
3092 int i;
3093 int found = 0;
3094 for (i = 1; i <= tableaus.Length(); i++)
3095 {
3096 if (tableaus(i)->name == tabname &&
3097 tableaus(i)->nstages >= minstage && tableaus(i)->nstages <= maxstage)
3098 {
3099 list.Add(i);
3100 found = 1;
3101 }
3102 }
3103 return found;
3104 }
3105
LagrangeWeight(int l,double tau,const Vector & c) const3106 double TimeInt::LagrangeWeight(int l, double tau, const Vector& c) const
3107 {
3108 double w=1;
3109 for (int i=1; i <= c.Length(); i++)
3110 {
3111 if (i!=l)
3112 {
3113 w *= (tau-c(i))/(c(l)-c(i));
3114 }
3115 }
3116 return w;
3117 }
3118
PrintTimingList()3119 void TimeInt::PrintTimingList()
3120 {
3121 TMPrintTimer();
3122 }
3123
3124
ResetComputation()3125 void TimeInt::ResetComputation()
3126 {
3127 TMResetTimer();
3128 Initialize();
3129 TIInit();
3130 //uo.pUI->CallWCDriverFunction(1); //redraw
3131 }
3132
3133
3134
3135 //print step information and draw results each step
StepPrintAndDraw(int rv)3136 void TimeInt::StepPrintAndDraw(int rv)
3137 {
3138 //calc time:
3139 double lt = GetClockTime();
3140 TIcomptime = TIV.start_clock_time + lt;
3141
3142 //do graphics if it's time for it!
3143 solset.withgraphics = GetIOption(104);
3144 //redraw frequency: 0..off, 1..draw last frame, 2..100sec, 3..20sec, 4..2sec, 5..200ms, 6..50ms, 7..20ms, 8..every 10 frames, 9..every frame
3145 if (solset.withgraphics == 1 && TItime > solset.endtime-0.1*TIminstep) {TIV.lastdraw = TItime; drawnow++;}
3146 if (solset.withgraphics == 2 && (TIcomptime - TIV.lastdraw) > 100.) {TIV.lastdraw = TIcomptime; drawnow++;}
3147 if (solset.withgraphics == 3 && (TIcomptime - TIV.lastdraw) > 20.) {TIV.lastdraw = TIcomptime; drawnow++;}
3148 if (solset.withgraphics == 4 && (TIcomptime - TIV.lastdraw) > 2.) {TIV.lastdraw = TIcomptime; drawnow++;}
3149 if (solset.withgraphics == 5 && (TIcomptime - TIV.lastdraw) > 0.2) {TIV.lastdraw = TIcomptime; drawnow++;}
3150 if (solset.withgraphics == 6 && (TIcomptime - TIV.lastdraw) > 0.05) {TIV.lastdraw = TIcomptime; drawnow++;}
3151 if (solset.withgraphics == 7 && (TIcomptime - TIV.lastdraw) > 0.02) {TIV.lastdraw = TIcomptime; drawnow++;}
3152 if (solset.withgraphics == 8 && (TIit - TIV.lastdraw) >= 10) {TIV.lastdraw = TIit; drawnow++;}
3153
3154 TIV.timetogo2 = TIV.timetogo;
3155 TIV.timetogo = TIcomptime / TItime * (solset.endtime-TItime);
3156 TIV.timetogo = 0.2*TIV.timetogo+0.8*TIV.timetogo2;
3157
3158 TIV.maxnewtonit = Maximum(GetNewtonIt(),TIV.maxnewtonit);
3159
3160 if (TItime-solset.endtime >= -0.1*TIminstep)
3161 {
3162 drawnow++;
3163 TIDrawAndStore();
3164 }
3165 if ((TIcomptime - TIV.last_showstatustext) >= 1 || //update text every GetDOption( 4) seconds
3166 ((TItime-solset.endtime)>=-0.1*TIminstep) ||
3167 (rv == 0 || StopCalculation() || TIfinished!=0))
3168 {
3169 char progress_str[64];
3170 double time_total = solset.endtime - solset.starttime;
3171 double time_left = solset.endtime - TItime;
3172
3173 double progress = 100;
3174 if (time_total != 0) progress = 100.*(time_total-time_left)/time_total;
3175
3176 char pc = '%';
3177 sprintf(progress_str, "%2.1f%c", progress, pc);
3178 uo.pUI->StatusText(progress_str);
3179
3180 #define test_progressbar_not // hack (AD) test ProgressBar
3181 #ifdef test_progressbar
3182 this->UO().pUI->CallWCDriverFunction(10,2,100); // 100 ticks
3183 this->UO().pUI->CallWCDriverFunction(10,3,(int)progress+0.5); // actual position to %value
3184
3185 ElementDataContainer edc; // text fields
3186 ElementData ed;
3187
3188 ed.SetText("Progress bar");
3189 ed.SetDataName("Caption");
3190 edc.Add(ed);
3191
3192 ed.SetText("Subroutine: StepPrintAndDraw");
3193 ed.SetDataName("Over");
3194 edc.Add(ed);
3195
3196 ed.SetText(mystr(progress) + mystr("% progress (estimate)"));
3197 ed.SetDataName("Under");
3198 edc.Add(ed);
3199
3200 this->UO().pUI->CallWCDriverFunction(10,4,0,&edc);
3201 #endif
3202
3203 TIV.last_showstatustext = TIcomptime;
3204 }
3205
3206 //print results, if it's time for it:
3207 if (SolverPrintsDetailedOutput() ||
3208 (TIcomptime - TIV.lastprintres) >= GetOptions()->LoggingOptions()->ComputationOutputEveryXSec() || //update text every GetOptions()->LoggingOptions()->ComputationOutputEveryXSec() seconds
3209 ((TItime-solset.endtime)>=-0.1*TIminstep) ||
3210 (rv == 0 || StopCalculation() || TIfinished!=0))
3211 {
3212 //char progress_str[64];
3213 double time_total = solset.endtime - solset.starttime;
3214 double time_left = solset.endtime - TItime;
3215
3216 // #ifdef gencnt
3217 // uo << "number of new calls for Vector/Matrix: n_gen_vec=" << *genvec << ", n_gen_mat=" << *genmat << "\n";
3218 // #endif
3219
3220 //double progress = 100;
3221 //if (time_total != 0) progress = 100.*(time_total-time_left)/time_total;
3222
3223 //char pc = '%';
3224 //sprintf(progress_str, "%2.1f%c", progress, pc);
3225 //uo.pUI->StatusText(progress_str);
3226
3227 TIV.lastprintres = TIcomptime;
3228
3229 if (TIV.outputlevel >=3)
3230 {
3231 //uo << "Generated vectors = " << GenVecCnt() << ", matrices = " << GenMatCnt() << ENDL;
3232
3233 SolverUO() <<
3234 ("step=")+mystr(TIit)+
3235 (", t=")+mystr(TItime)+
3236 (", tinc=")+mystr(TIstep)+
3237 //mystr(", x1=")+mystr(GetCharacteristicSol())+
3238 (", Nits=")+mystr(TIV.maxnewtonit)+
3239 (", Dits=")+mystr(log.TInonlinit)+
3240 (", Jacs=")+mystr(GetJacCount())+
3241 (", real_time=")+mystr(GetTString(TIcomptime))+
3242 (", real_time_togo=")+mystr(GetTString(TIV.timetogo))+
3243 ("\n");
3244 uo.ResetLocalMessageLevel();
3245 }
3246 //$ YV 2013-01-03: the code below was anyway inactive - this needs to be done differently in the future
3247 #if 0
3248 if (0 && contact_cnt_mastersearch!=0) //write contact information
3249 {
3250 uo << "n_gap=" << contact_cnt_gap << ", n_ms=" << contact_cnt_mastersearch;
3251 uo << ", itemlist=" << (double)contact_cnt_itemlist/(double)contact_cnt_mastersearch;
3252 uo << ", foundmaster=" << (double)contact_cnt_foundmaster/(double)contact_cnt_mastersearch;
3253 uo << ", list2=" << (double)contact_cnt_list2/(double)contact_cnt_mastersearch;
3254 uo << ", list3=" << (double)contact_cnt_list3/(double)contact_cnt_mastersearch;
3255 uo << ", list4=" << (double)contact_cnt_list4/(double)contact_cnt_mastersearch;
3256 uo << "\n";
3257 }
3258 #endif
3259 TIV.maxnewtonit = 0;
3260 }
3261 }
3262
Integrate()3263 int TimeInt::Integrate() //JG const SolverSettings& solversettings)
3264 {
3265
3266 SetSolver(&numsol); //in order to be able to use solver option right away
3267
3268 //solset = solversettings; //JG, changed because timeint and MBS now have same solversettings
3269
3270 SetComputationSolverOptions(); //copy general options to MBSSolSet(), because MBSSolSet() is faster!
3271 log.Init(); //initialize counters
3272 #ifdef gencnt
3273 (*genvec) = 0;
3274 (*genmat) = 0;
3275 #endif
3276
3277
3278 //+++++++++
3279 //==>put into log!!!!
3280 //SetNewtonIt(0);
3281 //SetNewtonItSum(0);
3282 //jaccount = 0;
3283 //changestep=0;
3284 //++++++++++
3285
3286
3287 TItime = solset.starttime;
3288 TISaveState(TIlaststep_state); //save state of end of last step (or initial step) ==> last step available
3289
3290
3291 if (lastloadresults > TItime) lastloadresults = -1e100;
3292 if (laststoredata > TItime) laststoredata = -1e100;
3293
3294 //uo << "storedata=" << solset.storedata << "\n";
3295
3296 if (solset.maxstages >= global_maxstages)
3297 {
3298 uo.pUI->InstantMessageText("Maximum number of stages (20) is succeeded!!!");
3299 }
3300
3301 //convert to old parameters:
3302 double remainigtime = solset.endtime-TItime;
3303
3304 double steps = floor(remainigtime/solset.maxstepsize+0.1*solset.minstepsize);
3305 TIbasestep = remainigtime/(double)steps;
3306 TIstep = TIbasestep;
3307
3308 if (solset.initstepsize<=solset.maxstepsize && solset.initstepsize> solset.minstepsize && FullAdaptive())
3309 {
3310 TIstep = solset.initstepsize;
3311 }
3312
3313 system_matrices_written = 0; //flag, system matrices are written at first time step
3314
3315 //numsol.DestroyOldJacs();
3316 TIm_initialized = 0;
3317 bandwidthm = 0;
3318
3319 TImaxstep = solset.maxstepsize;
3320 TIminstep = solset.minstepsize;
3321 TIstepnew = TIstep;
3322
3323 TInoincs = 1;
3324 TInonls = 1;
3325
3326 int rv = 1;
3327
3328 TIfinished = 0;
3329
3330 TIit = 0;
3331 TIrejectedsteps = 0;
3332 pCFB->ResultsUpdated(0); //initial values are also stored
3333
3334 //initialize timer variables:
3335 double lt = GetClockTime(); //temporary variable, store actual clock
3336 TIV.timetogo = 0;
3337 TIV.lastdraw = 0;
3338 TIV.lastprintres = 0;
3339 TIV.outputlevel = 3; //2
3340 TIV.maxnewtonit=0;
3341
3342 //time(<);
3343 TIV.start_clock_time=-lt;
3344
3345 steps_since_orderchange = 0;
3346 min_newtonits = NLS_MaxNewtonSteps();
3347 newjacobians_since_orderchange;
3348 last_jaccount = 0;
3349 reduce_order = 0;
3350
3351 numsol.ModifiedNewton() = NLS_ModifiedNewton();
3352 numsol.AbsoluteAccuracy() = NLS_AbsoluteAccuracy();
3353 numsol.RelativeAccuracy() = NLS_RelativeAccuracy()/sqrt(TIstepnew);
3354 numsol.NumDiffepsi() = NLS_NumDiffepsi();
3355 numsol.MaxModNewtonSteps() = NLS_MaxModNewtonSteps();
3356 numsol.MaxRestartNewtonSteps() = NLS_MaxRestartNewtonSteps();
3357 numsol.MaxFullNewtonSteps() = NLS_MaxFullNewtonSteps();
3358 numsol.TrustRegion() = NLS_TrustRegion();
3359 numsol.TrustRegionDiv() = NLS_TrustRegionDiv();
3360 numsol.SymmetricJacobian() = NLS_SymmetricJacobian();
3361 numsol.UseSparseSolver() = NLS_UseSparseSolver();
3362 numsol.SolveUndeterminedSystem() = NLS_SolveUndeterminedSystem();
3363 numsol.EstimatedConditionNumber() = NLS_EstimatedConditionNumber();
3364
3365 uo << "Use sparsesolver=" << UseSparseSolver() << "\n";
3366
3367 if (!UseSparseMass())
3368 {
3369 mlocm.SetSize(GetSecondOrderSize(),GetSecondOrderSize());
3370 mlocm.FillWithZeros();
3371 }
3372
3373 if (DoStaticComputation())
3374 {
3375 //write initial state:
3376 FirstStep();
3377 rv = StaticComputation();
3378
3379 drawnow = 1;
3380 TIDrawAndStore();
3381
3382 //write solution:
3383 FirstStep();
3384 }
3385 else if (!DoImplicitIntegration())
3386 {
3387 //write initial state:
3388 FirstStep();
3389 rv = ExplicitIntegration();
3390
3391 drawnow = 1;
3392 TIDrawAndStore();
3393
3394 //write solution:
3395 FirstStep();
3396 }
3397 else
3398 {
3399 drawnow = 0;
3400 if (solset.variable_order)
3401 {
3402 stage_tableaus.Flush();
3403 int success = LoadTableauList(solset.tableauname, stage_tableaus, solset.minstages, solset.maxstages);
3404
3405 if (!success) {uo << "Could not find tableaus '" << solset.tableauname << "'!!!" << ENDL; return 0;}
3406
3407 act_stage = 1;
3408 act_tableau = stage_tableaus(act_stage);
3409 }
3410 else
3411 {
3412 act_tableau=GetTableau(solset.tableauname, solset.maxstages);
3413 }
3414
3415 if (!act_tableau) return 0;
3416
3417 if (TIV.outputlevel > 2)
3418 uo << "Integration: " << tableaus[act_tableau]->name << ", "
3419 << tableaus[act_tableau]->info << ", ODE-order=" << tableaus[act_tableau]->ODE_order << ENDL;
3420
3421 //write solution:
3422 FirstStep();
3423
3424 while (((solset.endtime-TItime)>0.1*TIminstep) && rv != 0 && !StopCalculation() && TIfinished==0)
3425 {
3426 if (SolverPrintsDetailedOutput())
3427 {
3428 mystr str("**************** step ");
3429 str+=mystr(TIit+1);
3430 str+=mystr(" (implicit");
3431 if (FullAdaptive()) str+=mystr(", adaptive");
3432 str+=mystr(") begin\n");
3433 SolverUO() << str;
3434 }
3435
3436 if(!FullAdaptive() && RelApproxi(solset.endtime,TItime+TIstep))
3437 {
3438 TIstep = solset.endtime - TItime;
3439 }
3440
3441
3442 rv = IntegrateStep();
3443 TIit++;
3444 //uo << "Veccnt=" << GenVecCnt() << "\n";
3445 //uo << "Matcnt=" << GenMatCnt() << "\n";
3446
3447 StepPrintAndDraw(rv);
3448
3449 if (SolverPrintsDetailedOutput())
3450 {
3451 mystr str("**************** step ");
3452 str+=mystr(TIit);
3453 str+=mystr(" (implicit");
3454 if (FullAdaptive()) str+=mystr(", adaptive");
3455 str+=mystr(") end\n");
3456 SolverUO() << str;
3457 }
3458 }
3459 }
3460
3461
3462 //set new start time = actual end time (or breaking point)
3463 MBS_EDC_TreeSetDouble(TItime, "SolverOptions.start_time"); //set endtime as start time--> if start clicked several times
3464 //==> also reset initial conditions??
3465
3466
3467 if (!rv && NumSolver().GetErrorMsg().Length()!=0)
3468 {uo << "step=" << TIit-1 << ", ERROR in Newton method: " << NumSolver().GetErrorMsg().c_str() << ENDL;}
3469 else if (!rv && !DoStaticComputation()) {uo << "ERROR: Time integration not successful!!!" << ENDL;}
3470 else if (!rv && DoStaticComputation()) {uo << "ERROR: Static computation not successful!!!" << ENDL;}
3471
3472 if (TIfinished == -1) {uo << "Time integration stopped with error." << ENDL; rv = 0; }
3473
3474 return rv;
3475 }
3476
3477
IntegrateStep()3478 int TimeInt::IntegrateStep()
3479 {
3480 TIx0start = TIx0;
3481 TIk0start = TIk0;
3482 int rv;
3483
3484 if(!FullAdaptive())
3485 {
3486 rv = FullStep();
3487 }
3488 else
3489 {
3490 rv = FullAdaptiveStep();
3491 }
3492
3493 return rv;
3494 }
3495
StaticComputation()3496 int TimeInt::StaticComputation()
3497 {
3498 int rv = 1; //return value
3499 int oldmodnewton = NLS_ModifiedNewton(); // returns solver setting nls_modifiednewton
3500 if (!numsol.UseSparseSolver()) NLS_ModifiedNewton() = 1; // activates modified newton method if sparse solver is not used
3501
3502 //--------------------------------------------------------------
3503 // read system size, set initial values
3504 mystatic Vector GSxs;
3505 int ss = GetSystemSize();
3506 int sos = GetSecondOrderSize();
3507 int es = GetFirstOrderSize();
3508 int is = GetImplicitSize();
3509
3510 GSxs.SetLen(sos+es+is);
3511
3512 //TIx0 contains initial values
3513 for (int i=1; i <= sos; i++) GSxs(i) = TIx0(i);
3514 for (int i=1; i <= es; i++) GSxs(i+sos) = TIx0(i+2*sos);
3515 for (int i=1; i <= is; i++) GSxs(i+sos+es) = TIx0(i+2*sos+es);
3516
3517 //--------------------------------------------------------------
3518 //tell solver that it is a static step, time-step -1 will not happen
3519 numsol.NLSolveInfo() = -1;
3520
3521 //--------------------------------------------------------------
3522 // declare and/or initiate counters and incrememts
3523 loadfact = 0.;
3524 int successcnt = 0;
3525 int failcnt = 0;
3526 int newtonits = 0;
3527 int jaccnt = 0;
3528 int nlit = 0;
3529 int lastnewtonits = 0;
3530 int lastjaccnt = 0;
3531
3532 double lt = GetClockTime();
3533 double start_clock_time=-lt;
3534 double lastdraw = 0;
3535 double lastprintres = 0;
3536 drawnow = 0;
3537 TIit = 0;
3538
3539 #define computationsteps //$ AD 2011-08: ComputationSteps replace LoadSteps in the long run...
3540
3541 #ifndef computationsteps // must be set AFTER ApplyComputationStepSettings for correct values
3542 solset.static_initloadinc = Minimum(solset.static_initloadinc,solset.static_maxloadinc);
3543 double loadinc = solset.static_initloadinc;
3544 #endif
3545
3546 #ifdef computationsteps
3547 ParseStepEndTimes(); // extract all computation step end times from EDC
3548 DoubleCheckWithLoadSettings();
3549 double cslength = GetTMaxCompSteps(); // last step end time
3550 solset.endtime=max(cslength,solset.endtime); // could be forced to
3551 ComputationStepNumber() = 1; // begin computation in first step
3552 ApplyComputationStepSettings(ComputationStepNumber());
3553 // get correct load inc for new ComputationStep, DO NOT CHANGE value of solset.static_initloadinc any more
3554 double loadinc = Minimum(solset.static_initloadinc,solset.static_maxloadinc);
3555 #else
3556 //--------------------------------------------------------------
3557 //vary load steps from starttime to endtime(or maximal load steps):
3558 TItime = solset.starttime; // set initial artificial time to starttime (default = 0)
3559 double lslength = GetTMaxLoadStepsLength();
3560 solset.endtime=max(lslength, solset.endtime); // endtime default=1; endtime otherwise maximal number of loadsteps in example
3561 //$ YV 2011-06: according to the change in GetTMaxLoadStepsLength(), added the following test to avoid situations when endtime is nowhere specified
3562
3563 #endif
3564 if(solset.endtime <= 0)
3565 solset.endtime = 1;
3566 UO(UO_LVL_err) << "static computation, artificial time interval [" << TItime << ", " << solset.endtime << "]\n";
3567 logout.flush();
3568
3569 //--------------------------------------------------------------
3570 // while
3571 // endtime not reached
3572 // return value is 1
3573 // calculation is not stopped
3574 // time integration is not finished
3575 // do
3576 // Load iteration (load corresponds to artificial time)
3577 while (TItime < solset.endtime-1e-12 && rv == 1 && !StopCalculation() && TIfinished==0)
3578 {
3579 if (SolverPrintsDetailedOutput())
3580 {
3581 SolverUO() << mystr("**************** step ")+mystr(TIit+1)+mystr(" (static, adaptive) begin\n");
3582 }
3583
3584 //+++++++++++++++++++++++++++++
3585 // Time of last converged step, in case this step does not converge
3586 double TItime_last_converged_step = TItime;
3587
3588 //+++++++++++++++++++++++++++++
3589 // add load increment to TItime
3590
3591 #ifdef computationsteps
3592 double thisstependtime = GetEndTimeCompStep(ComputationStepNumber());
3593 // if next timevalue is higher or marginally smaller then step end time, use step end time
3594 if( TItime + loadinc + 1e-12 - thisstependtime > 0.)
3595 TItime = thisstependtime;
3596 else
3597 TItime += loadinc;
3598 #else
3599 // use next integer of TItime if the difference is already smaller than 1e-12
3600 if (floor(TItime + loadinc + 1e-12) != floor(TItime))
3601 loadinc = 1.-(TItime-floor(TItime));
3602 // utilize all integers TItime passes and do not miss them out due to a higher load increment
3603 if ( floor(TItime + loadinc) != floor(TItime))
3604 TItime=floor(TItime + loadinc);
3605 //else if ( floor(TItime + loadinc + 1e-12) != floor(TItime))
3606 // TItime=floor(TItime + loadinc);
3607 else
3608 TItime += loadinc;
3609 #endif
3610
3611 // hit endtime, do not overshoot
3612 if (TItime > solset.endtime)
3613 {
3614 TItime = solset.endtime;
3615 }
3616
3617 // obsolete - loadfactor raises from 0 to 1 in each computation step
3618 //////////// load factor is only used for relaxation of error tolerance goal; loadfact has to be <= 1
3619 //////////loadfact = TItime;
3620 //////////if (loadfact > 1) loadfact = 1;
3621
3622 // compute step time - set variable for later use (by elements, loads, ...) in Evaluate() functions
3623 ComputationStepTime() = GetCSTime(TItime);
3624 loadfact = ComputationStepTime();
3625
3626 //+++++++++++++++++++++++++++++
3627 // reset counters
3628 lastnewtonits = 0;
3629 lastjaccnt = 0;
3630
3631 //nonlinear iteration (e.g. for plastic components):
3632 int nonlinfin = 0;
3633 nlit = 0;
3634 int maxlni = 0;
3635
3636 //+++++++++++++++++++++++++++++
3637 //save start condition at iteration
3638 TISaveState(TIlaststep_state);
3639
3640
3641 //+++++++++++++++++++++++++++++
3642 StartTimeStep();
3643
3644 // AND: AP: TItemp_state is used to store plastic strains at beginning of nonlinear iteration,
3645 // after transport which occurs in StartTimerStep
3646 // otherwise: TItemp_state is not used so far
3647 TISaveState(TItemp_state);
3648 TISaveState(TIlastnonlinit_state);
3649
3650 double init_error = -1;
3651
3652 //+++++++++++++++++++++++++++++
3653 // while
3654 // nonlinear interation is not finished
3655 // return value is 1
3656 // calculation is not stopped
3657 // do
3658 // Nonlinear iteration
3659 while (!nonlinfin && rv == 1 && !StopCalculation())
3660 {
3661 //save start condition at nonlinear iteration (e.g. for error estimation)
3662 //TISaveState(TIlastnonlinit_state);
3663
3664 int sos_rs = GetSecondOrderSize_RS(); //size of resorted second order equations
3665 numsol.SetBandSize(sos_rs - reducedbandsize); //for banded-solver, which part is banded!
3666
3667 nlit++;
3668 log.TInonlinit = nlit;
3669
3670 // set initial values
3671 for (int i=1; i <= sos; i++) GSxs(i) = TIx0(i);
3672 for (int i=1; i <= es; i++) GSxs(i+sos) = TIx0(i+2*sos);
3673 for (int i=1; i <= is; i++) GSxs(i+sos+es) = TIx0(i+2*sos+es);
3674
3675 numsol.NLSolveInfo() = 1;
3676
3677 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3678 // call Newton, NLF and Jacobian modified for flag DoStaticComputation
3679 // return value is 1 if Newton method was successful
3680
3681 rv = numsol.NLSolve(GSxs);
3682
3683 // set interation counter for number of newton iterations (only maximal number is retained)
3684 int lni = numsol.GetNewtonIts();
3685 if(lni>maxlni) maxlni = lni;
3686
3687 lastnewtonits += lni;
3688 lastjaccnt += numsol.GetJacCount();
3689 if(UO().GetGlobalMessageLevel()==UO_LVL_dbg2) //$ DR 2011-09-15
3690 {
3691 UO(UO_LVL_dbg2) << "rv=" << rv << "\n";
3692 }
3693 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3694 // if Newton was successful
3695 if (rv == 1)
3696 {
3697 //.............................
3698 // set local vector for nonlinear iteration step
3699 xh.SetLen(2*sos+es+is);
3700 for (int i=1; i <= sos; i++) xh(i) = GSxs(i);
3701 for (int i=1; i <= sos; i++) xh(i+sos) = TIx0(i+sos);
3702 for (int i=1; i <= es; i++) xh(i+2*sos) = GSxs(i+sos);
3703 for (int i=1; i <= is; i++) xh(i+2*sos+es) = GSxs(i+sos+es);
3704
3705 SetStartVector(xh);
3706
3707
3708 //.............................
3709 // nonlinear step for inelastic strain
3710 //
3711 // inelastic update:
3712 // nlerror = ||yield||
3713 // inel_strain += tau * yield * direction_of_yield
3714
3715 double nlerr = PostNewtonStep(TItime);
3716
3717 //.............................
3718 if ( init_error < 0 ) init_error = nlerr;
3719 // if ( nlit%1 == 0) UO() << "step " << nlit << ", nonlinerror = " << nlerr << ", discontacc " << DiscontinuousAccuracy() << "\n";
3720
3721 //.............................
3722 // relax accuracy in iterations with small loadfactor
3723 double relaxfact = 1;
3724 if (solset.static_use_tol_relax_factor)
3725 relaxfact = Sqr(1./loadfact);
3726 double max_relaxfactor = solset.static_maxtol_relax_factor;
3727 if (relaxfact > max_relaxfactor) relaxfact = max_relaxfactor;
3728
3729 //.............................
3730 double tolgoal = DiscontinuousAccuracy();
3731
3732 if (loadfact <= 1-1e-8) // same accuracy in loadfact as in TItime <= (endtime-1e-8)!
3733 tolgoal *= relaxfact;
3734
3735 //.............................
3736 if ( nlerr <= tolgoal)
3737 {
3738 // nonlinear iteration was successful, finished
3739 nonlinfin = 1;
3740
3741 // postprocessing for nonlinear step
3742 PostprocessingStep();
3743 if (SolverPrintsDetailedOutput())
3744 {
3745 if (GetOptions()->LoggingOptions()->SolverStepSolutionVectorIncrement() && GetOptions()->LoggingOptions()->SolverStepSolutionVector())
3746 {
3747 SolverUO() << "step: solution vector = " << TIx0 << "\n";
3748 }
3749 if (GetOptions()->LoggingOptions()->SolverStepSolutionVectorIncrement())
3750 {
3751 SolverUO() << "step: increment vector = " << TIx0 - GSxs << "\n";
3752 }
3753 }
3754 }
3755 else
3756 {
3757 // print reached error_goal in percentage; for large systems each 10th iteration or for very large systems every iteration
3758 if ((ss > 2000 && (nlit % 10 == 9)) || (ss > 10000))
3759 {
3760 SolverUO() << "\rDit=" << nlit << ", discont. error reached " << tolgoal/nlerr*100. << "% of goal\n";
3761 }
3762 }
3763
3764 //******** to draw in every iteration
3765 //lastdraw = TIcomptime; drawnow++;
3766 //TIDrawAndStore();
3767
3768 //******** to enable pause and resume by click
3769 //uo.InstantMessageText("PostNewtonStep");
3770 //if(UO().GetGlobalMessageLevel()==UO_LVL_dbg1) //$ DR 2011-09-15
3771 //{
3772 // UO(UO_LVL_dbg1) << " disc. step " << nlit << ": newton_its=" << lni
3773 // << /*", disc. err="*/", nlerr=" << nlerr
3774 // << /*", tol. goal="*/", tol=" << tolgoal << "\n";
3775 //}
3776 }
3777 else
3778 {
3779 //UO(UO_LVL_dbg1) << " newton did not converge\n"; //PG no more necessary, switch on LoggingOptions.Solver.general_information
3780 }
3781
3782 if (nlit > solset.maxdiscontinuousit)
3783 {
3784 rv = 0;
3785 }
3786 }
3787 //+++++++++++++++++++++++++++++
3788 // increase counters
3789 TIit++;
3790 if ((ss > 2000 && (nlit >= 9)) || ss > 10000) UO() << "\r";
3791
3792 newtonits += lastnewtonits;
3793 jaccnt += lastjaccnt;
3794 if (nlit != 0)
3795 {
3796 lastnewtonits /= (int)sqrt((double)nlit);
3797 lastjaccnt /= (int)sqrt((double)nlit);
3798 }
3799
3800 //+++++++++++++++++++++++++++++
3801 // adapting load increment size
3802 if (!rv || lastnewtonits > 20*5 || lastjaccnt > 15*5 || nlit > 20*5) // not converged, too many iterations needed
3803 {
3804 #ifdef COMPILE_AND
3805 // AP: TIRestoreState only in case of rv=0 (i.e. in case of no convergence of time step
3806 if (!rv)
3807 #endif
3808 TIRestoreState(TIlaststep_state);
3809
3810 successcnt = -1;
3811 failcnt++;
3812 if (SolverPrintsDetailedOutput())
3813 {
3814 mystr str("");
3815 if (!rv)
3816 {
3817 if (nlit > solset.maxdiscontinuousit)
3818 {
3819 str+=mystr(" * Discontinuous.max_iterations have been reached\n");
3820 }
3821 else
3822 {
3823 str+=mystr(" * Newton did not converge\n");
3824 }
3825 }
3826 if (lastnewtonits > 15*5) str+=mystr(" * more than 75 Jacobians during this step\n");
3827 if (lastnewtonits > 20*5) str+=mystr(" * more than 100 Newton iterations during this step\n");
3828 if (nlit > 20*5) str+=mystr(" * more than 100 Discontinuous iterations during this step\n");
3829 SolverUO() << mystr("step: failcnt++, since\n")+str;
3830 }
3831
3832 if (loadinc > solset.static_minloadinc)
3833 {
3834 if (!rv) TItime = TItime_last_converged_step; // adapted artificial time to last converged step
3835
3836 loadinc /= solset.static_loadinc_down; // reduce load increment
3837 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: load increment is multiplied by ")+mystr(1/solset.static_loadinc_down)+mystr("\n");
3838
3839 if (failcnt>=2)
3840 {
3841 loadinc *= 0.25;
3842 if (SolverPrintsDetailedOutput()) SolverUO() << "step: load increment is moreover multiplied by 0.25, since failcnt > 2\n";
3843 }
3844 rv = 1;
3845 }
3846 else if (0) //0=save mode; try to overcome servere instabilities!!!! buggy
3847 {
3848 //just keep on going ...
3849 rv = 1;
3850 successcnt = 0;
3851 }
3852
3853 // hit minimal load increment, do not "under"shoot
3854 if (loadinc < solset.static_minloadinc)
3855 {
3856 loadinc = solset.static_minloadinc;
3857 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: load increment is set to minimum value of ")+mystr(solset.static_minloadinc)+mystr(", since it's been already smaller than that.\n");
3858 }
3859 }
3860 #ifndef COMPILE_AND
3861 else if (lastjaccnt <= 7 && nlit <= 4) // fast converged
3862 #else
3863 else if (lastjaccnt <= 7 && nlit <= 4*3) // AP
3864 #endif
3865 {
3866 failcnt = 0;
3867 successcnt ++;
3868 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: failcnt=0 and successcnt++, since lastjaccnt=")+mystr(lastjaccnt)+mystr("<7, and nlit=")+mystr(nlit)+mystr("<4.\n");
3869
3870 // increase load increment after solset.static_incloadinc successfull steps
3871 if (successcnt >= solset.static_incloadinc)
3872 {
3873 successcnt = 0;
3874 loadinc *= solset.static_loadinc_up;
3875 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: load increment is multiplied by ")+mystr(solset.static_loadinc_up)+mystr("\n");
3876 }
3877
3878 // hit maximal load increment, do not overshoot
3879 if (loadinc > solset.static_maxloadinc)
3880 {
3881 loadinc = solset.static_maxloadinc;
3882 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step: load increment is set to max value of ")+mystr(solset.static_maxloadinc)+mystr(", since it's been already bigger than that.\n");
3883 }
3884 }
3885 else
3886 {
3887 if (SolverPrintsDetailedOutput() && failcnt != 0) SolverUO() << mystr("step: failcnt set to 0 again.\n");
3888 failcnt = 0;
3889 }
3890
3891 //+++++++++++++++++++++++++++++
3892 TIx0draw = TIx0;
3893
3894
3895
3896 //+++++++++++++++++++++++++++++
3897 lt = GetClockTime();
3898 TIcomptime = start_clock_time + lt;
3899
3900 //+++++++++++++++++++++++++++++
3901 solset.withgraphics = GetIOption(104);
3902 //redraw frequency: 0..off, 1..draw last frame, 2..100sec, 3..20sec, 4..2sec, 5..200ms, 6..50ms, 7..20ms, 8..every 10 frames, 9..every frame
3903 if (solset.withgraphics == 1 && TItime > solset.endtime-0.1*TIminstep) {lastdraw = TItime; drawnow++;}
3904 if (solset.withgraphics == 2 && (TIcomptime - lastdraw) > 100.) {lastdraw = TIcomptime; drawnow++;}
3905 if (solset.withgraphics == 3 && (TIcomptime - lastdraw) > 20.) {lastdraw = TIcomptime; drawnow++;}
3906 if (solset.withgraphics == 4 && (TIcomptime - lastdraw) > 2.) {lastdraw = TIcomptime; drawnow++;}
3907 if (solset.withgraphics == 5 && (TIcomptime - lastdraw) > 0.2) {lastdraw = TIcomptime; drawnow++;}
3908 if (solset.withgraphics == 6 && (TIcomptime - lastdraw) > 0.05) {lastdraw = TIcomptime; drawnow++;}
3909 if (solset.withgraphics == 7 && (TIcomptime - lastdraw) > 0.02) {lastdraw = TIcomptime; drawnow++;}
3910 if (solset.withgraphics == 8 && (TIit - lastdraw) >= 10) {lastdraw = TIit; drawnow++;}
3911
3912
3913 //+++++++++++++++++++++++++++++
3914 int endflag = 0;
3915 if ((TItime >= solset.endtime-1e-8) || rv == 0 || StopCalculation() || TIfinished!=0 )
3916 {
3917 drawnow = 1;
3918 endflag = 1;
3919 #ifdef COMPILE_AND
3920 // AP: for AND, return 1 for successful computation, -1 else
3921 if (rv) TIfinished=1;
3922 else TIfinished=-1;
3923 #endif
3924 }
3925
3926 //+++++++++++++++++++++++++++++
3927 if (SolverPrintsDetailedOutput() || (TIcomptime - lastprintres) > GetOptions()->LoggingOptions()->ComputationOutputEveryXSec() || endflag) //update text every GetDOption( 4) seconds
3928 {
3929 lastprintres = TIcomptime;
3930
3931 TIV.timetogo2 = TIV.timetogo;
3932 TIV.timetogo = TIcomptime / TItime * (solset.endtime-TItime);
3933 TIV.timetogo = 0.2*TIV.timetogo+0.8*TIV.timetogo2;
3934
3935 SolverUO() <<
3936 ("step=")+mystr(TIit)+
3937 (", f=")+mystr(loadfact)+
3938 (", finc=")+mystr(loadinc)+
3939 //mystr(", x1=")+mystr(GetCharacteristicSol())+
3940 (", Nits=")+mystr(maxlni)+
3941 (", Dits=")+mystr(nlit)+
3942 (", Jacs=")+mystr(jaccnt)+
3943 (", real_time=")+mystr(GetTString(TIcomptime))+
3944 (", real_time_togo=")+mystr(GetTString(TIV.timetogo))+
3945 ("\n");
3946 }
3947
3948 if(UO().GetGlobalMessageLevel()==UO_LVL_dbg2 && SolverPrintsDetailedOutput()) //$ DR 2011-09-15
3949 {
3950 UO(UO_LVL_dbg2) << "step lastdraw = " << lastdraw << ", TIcomptime = " << TIcomptime << ", drawnow = " << drawnow << "\n";
3951 }
3952 TIDrawAndStore();
3953
3954 //+++++++++++++++++++++++++++++
3955 if (!failcnt) WriteSol();
3956
3957 //+++++++++++++++++++++++++++++
3958 EndTimeStep();
3959 #ifdef computationsteps
3960 // additional code for change of computation step here
3961 if(IsComputationStepFinished(TItime))
3962 {
3963 ComputationStepFinished();
3964
3965 ComputationStepNumber()++; // increase ComputationStepNumber by one since next TItime is in next Step
3966 ApplyComputationStepSettings(ComputationStepNumber());
3967 // get correct load inc for new ComputationStep
3968 loadinc = Minimum(solset.static_initloadinc,solset.static_maxloadinc);
3969 }
3970 #endif
3971
3972 if (SolverPrintsDetailedOutput())
3973 {
3974 SolverUO() << mystr("**************** step ")+mystr(TIit)+mystr(" (static, adaptive) end\n");
3975 }
3976 }
3977
3978 //--------------------------------------------------------------
3979 if (rv == 1 && TItime == solset.endtime)
3980 {
3981 SolverUO() << "static computation completed successfully!\n";
3982 }
3983
3984 SetNewtonItSum(newtonits);
3985 SetJacCount(jaccnt);
3986
3987 SolverUO() << newtonits << " Newton iterations and " << jaccnt << " Jacobians computed\n";
3988
3989 //--------------------------------------------------------------
3990 xh.SetLen(2*sos+es+is);
3991 for (int i=1; i <= sos; i++) xh(i) = GSxs(i);
3992 for (int i=1; i <= sos; i++) xh(i+sos) = TIx0(i+sos);
3993 for (int i=1; i <= es; i++) xh(i+2*sos) = GSxs(i+sos);
3994 for (int i=1; i <= is; i++) xh(i+2*sos+es) = GSxs(i+sos+es);
3995
3996 SetStartVector(xh);
3997
3998 if (SolverPrintsDetailedOutput())
3999 {
4000 if (GetOptions()->LoggingOptions()->SolverStepSolutionVector())
4001 {
4002 SolverUO() << "solution vector = " << TIx0 << "\n";
4003 }
4004 }
4005
4006 //--------------------------------------------------------------
4007 loadfact = 1.;
4008 TItime = solset.endtime;
4009 NLS_ModifiedNewton() = oldmodnewton;
4010
4011 //--------------------------------------------------------------
4012 logout.flush();
4013 return rv;
4014 }
4015
ExplicitIntegration()4016 int TimeInt::ExplicitIntegration()
4017 {
4018 int rv = 1;
4019
4020 if (GetImplicitSize() != 0)
4021 {
4022 uo << "ERROR: explicit integration failed: algebraic equations cannot be solved with explicit solver!" << ENDL;
4023 }
4024
4025
4026 drawnow = 0;
4027
4028 if (TIV.outputlevel > 2)
4029 uo << "explicit integration: mid-point rule, order = 1" << ENDL;
4030
4031 //write solution:
4032 FirstStep();
4033
4034 while (((solset.endtime-TItime)>0.1*TIminstep) && rv != 0 && !StopCalculation() && TIfinished==0)
4035 {
4036 if (SolverPrintsDetailedOutput())
4037 {
4038 SolverUO() << mystr("**************** step ")+mystr(TIit+1)+mystr(" (explicit, adaptive) begin\n");
4039 }
4040
4041 if(RelApproxi(solset.endtime,TItime+TIstep))
4042 {
4043 TIstep = solset.endtime - TItime;
4044 }
4045
4046 //uo << "step = " << TIit << ", time=" << TItime << ", step=" << TIstep << "\n";
4047 rv = AdaptiveExplicitStep();
4048 TIit++;
4049
4050 StepPrintAndDraw(rv);
4051
4052 if (SolverPrintsDetailedOutput())
4053 {
4054 SolverUO() << mystr("**************** step ")+mystr(TIit)+mystr(" (explicit, adaptive) end\n");
4055 }
4056 }
4057
4058 if (TIV.outputlevel >= 2)
4059 {
4060 uo << "computational time = " << TIcomptime << " seconds" << ENDL;
4061 uo << "rejected steps = " << TIrejectedsteps << ENDL;
4062 }
4063 if (TIit != 0 && TIcomptime!=0)
4064 {
4065 if (TIV.outputlevel >= 3)
4066 {
4067 uo << "timesteps per second = " << (double)TIit/TIcomptime << " steps/s" << ENDL;
4068 }
4069 }
4070 return rv;
4071 }
4072
AdaptiveExplicitStep()4073 int TimeInt::AdaptiveExplicitStep()
4074 {
4075 TISaveState(TIlaststep_state); //save state of end of last step (or initial step)
4076
4077 StartTimeStep();
4078
4079 TISaveState(TItemp_state); // AP: state after StartTimeStep(), for AND this is after transport
4080 TIstep = TIstepnew;
4081 double savestep = TIstep;
4082 log.TInewtonit = 0;
4083 double TItimeold = TItime;
4084 int rv = 0;
4085
4086 double it = 0;
4087 while (it < 15 && !rv)
4088 {
4089 it++;
4090 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("step it=")+mystr(it)+mystr(", step increment=")+mystr(TIstep)+mystr(", time=")+mystr(TItime)+mystr("\n");
4091
4092 SetStepRecommendation(1e100);
4093
4094 if (TItime+TIstep > solset.endtime) TIstep = solset.endtime - TItime;
4095
4096 rv = ExplicitStep();
4097
4098 if (!rv && it < 15)
4099 {
4100 TIRestoreState(TIlaststep_state); //set to old TIx0, reset all internal nonlinear variables
4101 if (GetStepRecommendation() < TIstep)
4102 {
4103 TIstep = GetStepRecommendation();
4104 if (it > 3)
4105 {
4106 TIstep *= 0.5;
4107 if (SolverPrintsDetailedOutput()) SolverUO() << "step increment multiplied by 0.5\n";
4108 }
4109 else if (it > 7)
4110 {
4111 TIstep *= 0.1;
4112 if (SolverPrintsDetailedOutput()) SolverUO() << "step increment multiplied by 0.1\n";
4113 }
4114 }
4115 else
4116 {
4117 TIstep *= 0.5;
4118 if (SolverPrintsDetailedOutput()) SolverUO() << "step increment multiplied by 0.5\n";
4119
4120 if (TIstep <= TIminstep)
4121 {
4122 it = 14;
4123 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("perform last step, since TIstep=")+mystr(TIstep)+mystr(" is less equal TIminstep=")+mystr(TIminstep)+mystr("\n");
4124 }
4125 }
4126
4127 if (TIstep < TIminstep)
4128 {
4129 TIstep = TIminstep;
4130 if (SolverPrintsDetailedOutput()) SolverUO() << mystr("TIstep set to TIminstep=")+mystr(TIminstep)+mystr(", since it's been already smaller than that.\n");
4131 }
4132
4133 }
4134 }
4135
4136 if (!rv)
4137 {
4138 if (!minstepwarned) uo << "ERROR: Step at minimal stepsize, step not fully converged. Further warning suppressed!" << ENDL;
4139 minstepwarned = 1;
4140 //rv = 1;
4141 }
4142
4143 FinishStep();
4144 TIstep = savestep;
4145 EndTimeStep();
4146
4147 return rv;
4148 }
4149
ExplicitStep()4150 int TimeInt::ExplicitStep()
4151 {
4152 TMStartTimer(21);
4153 int rv = 1;
4154 double corerr;
4155 TInonls = 0;
4156
4157 TIdiscontstep = 0;
4158 TISaveState(TIlastnonlinit_state);
4159
4160 rv = GeneralEStep();
4161 corerr = PostNewtonStep(TItime);
4162
4163 if (corerr == -1)
4164 {
4165 rv = 0;
4166 }
4167
4168 if (GetStepRecommendation() < TIstep && TIstep > TIminstep)
4169 {
4170 rv = 0;
4171 }
4172
4173 if (rv != 0)
4174 {
4175 PostprocessingStep();
4176 }
4177
4178 TMStopTimer(21);
4179
4180 return rv;
4181 }
4182
4183 //only for test: mass matrix
4184 Matrix expl_mass;
4185
GeneralEStep()4186 int TimeInt::GeneralEStep()
4187 {
4188 //macht einen Schritt
4189
4190 int ss = GetSystemSize();
4191 int is = GetImplicitSize();
4192 int es = GetFirstOrderSize();
4193 int sos = GetSecondOrderSize();
4194 int sos_rs = GetSecondOrderSize_RS();
4195
4196 int rv = 1;
4197
4198 int i,j;
4199 IRK_Tableau* t = tableaus[act_tableau];
4200 int ns = t->nstages;
4201
4202 int oldMinv = 0;
4203
4204 //explicit Runge Kutta!!!
4205
4206 evalf.SetLen(sos);
4207 TIu0.SetLen(sos);
4208 TIu0.Copy(TIx0,1,1,sos);
4209 TIv0.SetLen(sos);
4210 TIv0.Copy(TIx0,1+sos,1,sos);
4211 TIu0e.SetLen(es);
4212 TIu0e.Copy(TIx0,1+2*sos,1,es);
4213
4214 //build gu, gv, gue
4215 gu[1] = TIu0;
4216 gv[1] = TIv0;
4217 gue[1] = TIu0e;
4218
4219 for (i=1; i <= ns; i++)
4220 {
4221 PrecomputeEvalFunctions(); //$ PG 2012-1-15: precomputation for EvalF(), EvalF2(), EvalG(), EvalM(), and also for CqTLambda() in case of constraints
4222
4223 //evaluate right hand sides for first and second order equations
4224 kv[i].SetLen(sos);
4225 kue[i].SetLen(es);
4226 xi[i].SetLen(2*sos+es);
4227
4228 xi[i].Copy(gu[i],1,1,sos);
4229 xi[i].Copy(gv[i],1,1+sos,sos);
4230 xi[i].Copy(gue[i],1,1+2*sos,es);
4231
4232 //compute RK-f(x,t) for gu,gue and gv
4233 ku[i] = gv[i];
4234 evalfe.SetLen(es);
4235 if (es != 0)
4236 {
4237 EvalF(xi[i],kue[i],TItime+TIstep*t->c(i));
4238 }
4239
4240 if (sos != 0)
4241 {
4242 if (oldMinv)
4243 {
4244 expl_mass.SetSize(sos,sos);
4245 expl_mass.FillWithZeros();
4246 evalf.SetLen(sos);
4247 EvalM(xi[i], expl_mass, TItime+TIstep*t->c(i));
4248 EvalF2(xi[i], evalf, TItime+TIstep*t->c(i));
4249
4250 TMStartTimer(11); //solve
4251 int lrv = expl_mass.Solve(evalf,kv[i]);
4252 TMStopTimer(11); //solve
4253 if (!lrv) {uo << "Error in GeneralEStep: Mass matrix is singular!" << ENDL; return 0;}
4254 }
4255 else
4256 {
4257 EvalMinvF2(xi[i], kv[i], TItime+TIstep*t->c(i));
4258 }
4259 }
4260
4261 //compute next stage
4262 if (i < ns)
4263 {
4264 gu[i+1] = TIu0;
4265 gv[i+1] = TIv0;
4266 gue[i+1] = TIu0e;
4267 for (j = 1; j <= i; j++)
4268 {
4269 gu[i+1] += TIstep*t->A(i+1,j)*ku[j];
4270 gv[i+1] += TIstep*t->A(i+1,j)*kv[j];
4271 gue[i+1]+= TIstep*t->A(i+1,j)*kue[j];
4272 }
4273 }
4274 }
4275
4276 //compute evaluation step
4277 for (i = 1; i <= ns; i++)
4278 {
4279 TIu0 += TIstep*t->b(i)*ku[i];
4280 TIv0 += TIstep*t->b(i)*kv[i];
4281 TIu0e += TIstep*t->b(i)*kue[i];
4282 }
4283
4284 //compute new TIx0:
4285 TIx0.Copy(TIu0,1,1,sos);
4286 TIx0.Copy(TIv0,1,1+sos,sos);
4287 TIx0.Copy(TIu0e,1,1+2*sos,es);
4288
4289 return rv;
4290 }
4291
4292 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4293 //# Computation Steps with changing SolverOptions...
4294 //Time mapping
4295
4296 // returns number of the Computation Step for given global time // returns -1 it globaltime < 0 or globaltime > last step_end_time
GetCSNumber(double globaltime)4297 int TimeInt::GetCSNumber(double globaltime)
4298 {
4299 //rv : -1 if t < 0
4300 // n+1 if t > last_endtime
4301 // i [1..n} "else" - if in 0 <= t <= last_endtime
4302
4303 if(globaltime < 0.)
4304 return -1; // error - time negative !
4305
4306 // in first ComputationStep
4307 if(globaltime <= CSEndTimes(1))
4308 return 1;
4309
4310 // after last computation step endtime
4311 if(globaltime > CSEndTimes.Last()) // includes 0.0
4312 return CSEndTimes.Length()+1;
4313
4314 // most likely step for actual time
4315 int selected = ComputationStepNumber();
4316 if(selected < 1)
4317 selected = 1;
4318
4319 // in selected ComputationStep
4320 if(CSEndTimes(selected-1) < globaltime && globaltime <= CSEndTimes(selected)) // includes last_endtime
4321 return selected;
4322
4323 // in i-th ComputationStep (search array)
4324 for(int i=2; i <= CSEndTimes.Length(); i++)
4325 {
4326 if(CSEndTimes(i-1) < globaltime && globaltime <= CSEndTimes(i)) // includes last_endtime
4327 return i;
4328 }
4329
4330 // global time is larger then last ComputationStep endtime...
4331 return -1;
4332 }
4333
4334 // returns relative time in corresponding step rv(0..1] // returns 0. only for globaltime == 0 or globaltime > last step_end_time
GetCSTime(double globaltime)4335 double TimeInt::GetCSTime(double globaltime)
4336 {
4337 //rv: -1 if t < 0
4338 // 0 if t == 0
4339 // 1. if t > last_endtime
4340 // t' (0,1.] "else" t is percentage within interval
4341
4342 if(globaltime < 0.)
4343 return -1.; // error - time negative !
4344
4345 if(globaltime == 0.)
4346 return 0.; // only way to obtain "0.00000000000000000000000"
4347
4348 int stepnumber = GetCSNumber(globaltime);
4349 if(stepnumber > CSEndTimes.Length()) // stepnumber "-1" can not be rv ! (catched by "if(globaltime < 0.)")
4350 return 1.; // global time is larger then last ComputationStep endtime...
4351
4352 // time within Computation Step intervals
4353 double intervalstart = 0.0; // valid for first interval
4354 if (stepnumber > 1)
4355 intervalstart = CSEndTimes(stepnumber-1); // valid for all other intervals
4356 double intervalend = CSEndTimes(stepnumber);
4357
4358 if(globaltime >= intervalend - 1e-12)
4359 return 1.; // get a good "1.0000000000000000000000000000" at end of interval
4360
4361 double relativetime = (globaltime - intervalstart) / (intervalend - intervalstart);
4362 return relativetime; // (0 .. 1)
4363 }
4364
4365 // returns 1 if globaltime is any step_end_time
IsComputationStepFinished(double globaltime)4366 int TimeInt::IsComputationStepFinished(double globaltime)
4367 {
4368 if( GetCSTime(globaltime) == 1. && globaltime <= CSEndTimes.Last() )
4369 return 1.;
4370
4371 return 0;
4372 }
4373
4374
4375
4376
4377
4378