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(&lt);
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