1 //#**************************************************************
2 //# filename:             UserOutput.h
3 //#
4 //# author:               Yury Vetyukov
5 //#
6 //# generated:						2003
7 //# description:
8 //# remarks:
9 //#
10 //# Copyright (c) 2003-2013 Johannes Gerstmayr, Linz Center of Mechatronics GmbH, Austrian
11 //# Center of Competence in Mechatronics GmbH, Institute of Technical Mechanics at the
12 //# Johannes Kepler Universitaet Linz, Austria. All rights reserved.
13 //#
14 //# This file is part of HotInt.
15 //# HotInt is free software: you can redistribute it and/or modify it under the terms of
16 //# the HOTINT license. See folder 'licenses' for more details.
17 //#
18 //# bug reports are welcome!!!
19 //# WWW:		www.hotint.org
20 //# email:	bug_reports@hotint.org or support@hotint.org
21 //#***************************************************************************************
22 
23 #ifndef __USER_OUTPUT_H__
24 #define __USER_OUTPUT_H__
25 
26 
27 #include "ioincludes.h"
28 
29 #include "WinCompDriverInterface.h"
30 
31 
32 #include <assert.h>
33 #include <memory.h>
34 #include <math.h>
35 
36 #include "tarray.h"    //+i2
37 #include "mystring.h"
38 #include "femath.h"
39 
40 #include "useroutputinterface.h"
41 
42 //#define ENDL "\n"
43 //const char* ENDL="\n";
44 
45 
46 
47 class UserOutput : public UserOutputInterface
48 {
49 	char buf[100];
50 	char e_buf[100];
51 	char f_buf[100];
52 
53 	int localmessagelevel;              // level of message, set by UO(UO_MSGLVL), valid until next call UO()
54 	int* globalmessagelevel;						// global message level
55 	//PG:
56 	int* globalfilemessagelevel;				// global log file message level
57 	ofstream* logfile;                  // hotint logfile
58 	double* critical_logfile_size;      // if the file size is passing a multiple of this factor, then a warning is displayed
59 	int counter_critical_logfile_size;  // counts, how often a multiple of *critical_logfile_size has been exceeded
60 
61 	int output_precision;								// output precision for the next output
62 	int* oprec_double;								  // output precision of a double
63 	int* oprec_vector;								  // output precision of a double number in vector (s)
64 	int* oprec_matrix;								  // output precision of a double number in matrix (s)
65 
66 	int* maxerrors;											// maximum number of displayed errors, linked to Solver_Options
67   int* maxwarnings;										// maximum number of displayed warningss, linked to Solver_Options
68 // counters
69 	int errorcount;
70 	int warningcount;
71 // defaults, to be linked to options or set on access
72 	int default_localmessagelevel;
73 	int default_globalmessagelevel;
74 
75 	int default_oprec;
76 	int default_oprec_double;
77 	int default_oprec_vector;
78 	int default_oprec_matrix;
79 
80 	int default_maxerror;
81 	int default_maxwarnings;
82 
83 // used to save the current localmessagelevel, in order to reset to this level later
84 	int localmessagelevel_save;
85 
86 
87 public:
88 
89 	WCDInterface::UserInterface * pUI;
90 
UserOutput()91 	UserOutput() : pUI(NULL)
92 	{
93 // reset counters
94 		errorcount = 0;
95 		warningcount = 0;
96 // defaults - valid until linked to options
97 		default_localmessagelevel = UO_LVL_all;
98 		default_globalmessagelevel = UO_LVL_all;
99 		default_oprec = 8;
100 		default_oprec_double = 8;
101 		default_oprec_vector = 8;
102 		default_oprec_matrix = 8;
103 		default_maxerror = 100;
104 		default_maxwarnings = 100;
105 
106 		localmessagelevel = default_localmessagelevel;
107 		globalmessagelevel = &default_globalmessagelevel;
108 		globalfilemessagelevel = &default_globalmessagelevel;
109 
110 		output_precision = default_oprec;
111 		oprec_double = &default_oprec_double;
112 		oprec_vector = &default_oprec_vector;
113 		oprec_matrix = &default_oprec_matrix;
114 		maxerrors = &default_maxerror;
115 		maxwarnings = &default_maxwarnings;
116 
117 		logfile = NULL;
118 		critical_logfile_size = NULL;
119 		counter_critical_logfile_size = 0;
120 	}
121 
122 // sets message level at access & until next access, increases counters
SetLocalMessageLevel(UO_MSGLVL message_level)123   void SetLocalMessageLevel(UO_MSGLVL message_level)
124 	{
125 		localmessagelevel=message_level;
126 		if (localmessagelevel==UO_LVL_err) CountError();
127 		if (localmessagelevel==UO_LVL_warn) CountWarning();
128 	}
129 // sets message level at access & until next access, increases counters
SetLocalMessageLevel(int message_level)130 	void SetLocalMessageLevel(int message_level) { SetLocalMessageLevel( (UO_MSGLVL) message_level); }
GetLocalMessageLevel()131 	int GetLocalMessageLevel() { return localmessagelevel; }
132 
133 // save the current localmessagelevel
SaveLocalMessageLevel()134 	void SaveLocalMessageLevel()
135 	{
136 		localmessagelevel_save = localmessagelevel;
137 	}
138 //reset to the saved localmessagelevel
ResetLocalMessageLevel()139 	void ResetLocalMessageLevel()
140 	{
141 		SetLocalMessageLevel(localmessagelevel_save);
142 	}
143 
GetGlobalMessageLevel()144 	int GetGlobalMessageLevel() { return *globalmessagelevel; }
GetGlobalFileMessageLevel()145 	int GetGlobalFileMessageLevel() { return *globalfilemessagelevel; }
146 
SetOutputPrec(int output_prec)147 	void SetOutputPrec(int output_prec) { output_precision = output_prec; }
148 
149 // links UserOutput to Solver_Options, to be called after UserOutput object is created
HookToSolverSettings(int * globalmessagelevel,int * globalfilemessagelevel,ofstream * logfile,double * critical_logfile_size,int * maxerrors,int * maxwarnings,int * oprec_double,int * oprec_vector,int * oprec_matrix)150 	void HookToSolverSettings(int* globalmessagelevel, int* globalfilemessagelevel, ofstream* logfile, double* critical_logfile_size,
151 		int* maxerrors, int* maxwarnings,	int* oprec_double, int* oprec_vector, int* oprec_matrix)
152 	{
153 		UserOutput::globalmessagelevel = globalmessagelevel;
154 		UserOutput::globalfilemessagelevel = globalfilemessagelevel;
155 		UserOutput::logfile = logfile;
156 		UserOutput::critical_logfile_size = critical_logfile_size;
157 		UserOutput::maxerrors = maxerrors;
158 		UserOutput::maxwarnings = maxwarnings;
159 		UserOutput::oprec_double = oprec_double;
160 		UserOutput::oprec_vector = oprec_vector;
161 		UserOutput::oprec_matrix = oprec_matrix;
162 	}
163 
MaxErrors()164 	int& MaxErrors() {return *maxerrors;}
MaxWarnings()165 	int& MaxWarnings() {return *maxwarnings;}
166 
PrintMsg()167 	int PrintMsg() // decides whether to print the message or not
168 	{
169 		if (pUI==NULL) return 0;																							// do not print in invalid UserInterface
170 		if (*globalmessagelevel < localmessagelevel) return 0;								// do not print when local message level is larger then global
171 		if ((localmessagelevel == UO_LVL_err) && ( errorcount > (*maxerrors) )) return 0;       // print no more errors
172 		if ((localmessagelevel == UO_LVL_warn) && ( warningcount > (*maxwarnings) )) return 0;  // print no more warnings
173 		return 1;
174 	}
175 //PG:
PrintMsgToLogFile()176 	int PrintMsgToLogFile() // decides whether to print the message to log file or not
177 	{
178 		if (logfile==NULL) return 0;																							// do not print in invalid UserInterface
179 		if (*globalfilemessagelevel < localmessagelevel && *globalmessagelevel < localmessagelevel) return 0;								// do not print when local message level is larger then global
180 		if ((localmessagelevel == UO_LVL_err) && ( errorcount > (*maxerrors) )) return 0;       // print no more errors
181 		if ((localmessagelevel == UO_LVL_warn) && ( warningcount > (*maxwarnings) )) return 0;  // print no more warnings
182 		return 1;
183 	}
184 
CountError()185 	void CountError() // counts errors, displays message when maxerrors is reached
186 	{
187 		errorcount++;
188 		if (errorcount == (*maxerrors)+1)
189 		{
190 			pUI->AddText("Maximum number of displayed errors reached, no more Errormessages will be displayed!\n");
191 		}
192 	}
193 
CountWarning()194 	void CountWarning() // counts warnings, displays message when maxwarnings is reached
195 	{
196 		warningcount++;
197 		if (warningcount == (*maxwarnings)+1)
198 		{
199 			pUI->AddText("Maximum number of displayed warnings reached, no more Warningmessages will be displayed!\n");
200 		}
201 	}
202 
InstantMessageText(const char * pStr)203 	virtual void InstantMessageText(const char* pStr)
204 	{
205 		pUI->InstantMessageText(pStr);
206 	}
207 /*
208 	void AddLevelTag() // On Access start line with a level tag for some
209 	{
210 		if (!PrintMsg()) return;
211 		switch (localmessagelevel)
212 		{
213 		case UO_LVL_0: break;  // no Output
214 		case UO_LVL_err: AddText("Error: "); break;  // necessary output (Errors, start/end simulation)
215 		case UO_LVL_warn: AddText("Warning: "); break;// almost necessary output (Warnings)
216 		case UO_LVL_ext: break;  // extended output (useful information)
217 		case UO_LVL_all: break;  // complete information
218 		case UO_LVL_dbg1: break; // debug level 1
219 		case UO_LVL_dbg2: break;  // debug level 2
220 		default: break;
221 		}
222 	}
223 */
224 	//PG:
225 	//void AddText(const char * pStr)
226 	//{
227 	//	if (!PrintMsg()) return;
228 	//	pUI->AddText(pStr);
229 	//}
230 	//void AddText(double x)
231 	//{
232 	//	if (!PrintMsg()) return;
233 	//	sprintf_s(buf,"%.*g",output_precision,x);
234 	//	pUI->AddText(buf);
235 	//}
236 	//void AddText(int x)
237 	//{
238 	//	if (!PrintMsg()) return;
239 	//	sprintf_s(buf,"%d",x);
240 	//	pUI->AddText(buf);
241 	//}
AddText(const char * pStr)242 	void AddText(const char * pStr)
243 	{
244 		if (PrintMsg())	pUI->AddText(pStr);
245 		if (PrintMsgToLogFile())
246 		{
247 			(*logfile) << pStr;
248 			logfile->flush();
249 
250 			// print warning, if log file is exceeding critical size
251 			if (*globalfilemessagelevel >= UO_LVL_warn || *globalmessagelevel >= UO_LVL_warn)
252 			{
253 				if (logfile->rdbuf()->pubseekoff(0,ios::end,ios::out) > (*critical_logfile_size)*(counter_critical_logfile_size + 1)*1048576.)   //critical_logfile_size is given in megabytes, while pubseekoff returns size in bytes
254 				{
255 					counter_critical_logfile_size++;
256 					int memo = localmessagelevel;
257 					localmessagelevel = UO_LVL_warn;
258 					AddText(mystr("WARNING: size of log file exceeds critical size of ") + mystr((*critical_logfile_size)*counter_critical_logfile_size) + mystr(" MB.\n"));
259 					localmessagelevel = memo;
260 				}
261 			}
262 		}
263 		return;
264 	}
AddText(double x)265 	void AddText(double x)
266 	{
267 		sprintf_s(buf,"%.*g",output_precision,x);
268 		AddText(buf);
269 	}
AddText(int x)270 	void AddText(int x)
271 	{
272 		sprintf_s(buf,"%d",x);
273 		AddText(buf);
274 	}
275 
276 	virtual UserOutputInterface & operator <<(const char * pStr)
277 	{
278 		AddText(pStr);
279 		return *this;
280 	}
281 	virtual UserOutputInterface & operator <<(int x)
282 	{
283 		sprintf_s(buf,"%d",x);
284 		AddText(buf);
285 		return *this;
286 	}
287 	virtual UserOutputInterface & operator <<(double x)
288 	{
289 		if (output_precision==-1) output_precision = *oprec_double;
290 		sprintf_s(buf,"%.*g",output_precision,x);
291 		AddText(buf);
292 		return *this;
293 	}
294 	virtual UserOutputInterface & operator <<(const Vector3D & v)
295 	{
296 		if (output_precision==-1) output_precision = *oprec_vector;
297 		mystr str;
298 		str += mystr("[");
299 		str += mystr(v.X(),output_precision);
300 		str += mystr(", ");
301 		str += mystr(v.Y(),output_precision);
302 		str += mystr(", ");
303 		str += mystr(v.Z(),output_precision);
304 		str += mystr("]");
305 		AddText(str.c_str());
306 		return *this;
307 	}
308 	virtual UserOutputInterface & operator <<(const Box3D & b)
309 	{
310 		if (output_precision==-1) output_precision = *oprec_vector;
311 		mystr str;
312 		str += mystr("[");
313 		str += mystr(b.PMin().X(),output_precision);
314 		str += mystr(", ");
315 		str += mystr(b.PMin().Y(),output_precision);
316 		str += mystr(", ");
317 		str += mystr(b.PMin().Z(),output_precision);
318 		str += mystr("] - [");
319 		str += mystr(b.PMax().X(),output_precision);
320 		str += mystr(", ");
321 		str += mystr(b.PMax().Y(),output_precision);
322 		str += mystr(", ");
323 		str += mystr(b.PMax().Z(),output_precision);
324 		str += mystr("]");
325 		AddText(str.c_str());
326 		return *this;
327 	}
328 	virtual UserOutputInterface & operator <<(const Vector2D & v)
329 	{
330 		if (output_precision==-1) output_precision = *oprec_vector;
331 		mystr str;
332 		str += mystr("[");
333 		str += mystr(v.X(),output_precision);
334 		str += mystr(", ");
335 		str += mystr(v.Y(),output_precision);
336 		str += mystr("]");
337 		AddText(str.c_str());
338 		return *this;
339 	}
340 	virtual UserOutputInterface & operator <<(const Vector & v)
341 	{
342 		if (output_precision==-1) output_precision = *oprec_vector;
343 		mystr str;
344 		if (v.GetLen()<=70)
345 		{
346 			str+=mystr("[");
347 			for (int i=1; i<v.GetLen(); i++)
348 			{
349 				str+=mystr(v(i),output_precision);
350 				str+=mystr(", ");
351 			}
352 			if (v.GetLen()!=0)
353 			{
354 				str+=mystr(v(v.GetLen()),output_precision);
355 			}
356 			str+=mystr("]");
357 		}
358 		else
359 		{
360 
361 			str+=mystr("[");
362 			for (int i=1; i<=v.GetLen(); i++)
363 			{
364 				str+=mystr(v(i),output_precision);
365 				if (i!=v.GetLen()) {str+=mystr(", ");}
366 				if (i%16==0 && i!=v.GetLen()) {str+=mystr("\n  col("); str+=mystr(i); str+=mystr( "): ");}
367 			}
368 			str+=mystr("]");
369 
370 		}
371 		AddText(str.c_str());
372 		return *this;
373 	}
374 
375 	virtual UserOutputInterface & operator <<(const IVector & v)
376 	{
377 		if (output_precision==-1) output_precision = *oprec_vector;
378 		mystr str;
379 		if (v.Length()<=70)
380 		{
381 			str+=mystr("[");
382 			for (int i=1; i<v.Length(); i++)
383 			{
384 				str+=mystr(v(i));
385 				str+=mystr(", ");
386 			}
387 			if (v.Length()!=0)
388 			{
389 				str+=mystr(v(v.Length()));
390 			}
391 			str+=mystr("]");
392 		}
393 		else
394 		{
395 			str+=mystr("[");
396 			for (int i=1; i<=v.Length(); i++)
397 			{
398 				str+=mystr(v(i));
399 				if (i!=v.Length()) {str+=mystr(", ");}
400 				if (i%16==0 && i!=v.Length()) {str+=mystr("\n  col("); str+=mystr(i); str+=mystr( "): ");}
401 			}
402 			str+=mystr("]");
403 
404 		}
405 		AddText(str.c_str());
406 		return *this;
407 	}
408 
409 	virtual UserOutputInterface & operator <<(const TArray<double> & v)
410 	{
411 		if (output_precision==-1) output_precision = *oprec_vector;
412 		mystr str;
413 		if (v.Length()<=70)
414 		{
415 			str+=mystr("[");
416 			for (int i=1; i<v.Length(); i++)
417 			{
418 				str+=mystr(v(i),output_precision);
419 				str+=mystr(", ");
420 			}
421 			if (v.Length()!=0)
422 			{
423 				str+=mystr(v(v.Length()),output_precision);
424 			}
425 			str+=mystr("]");
426 		}
427 		else
428 		{
429 
430 			str+=mystr("[");
431 			for (int i=1; i<=v.Length(); i++)
432 			{
433 				str+=mystr(v(i),output_precision);
434 				if (i!=v.Length()) {str+=mystr(", ");}
435 				if (i%16==0 && i!=v.Length()) {str+=mystr("\n  col("); str+=mystr(i); str+=mystr( "): ");}
436 			}
437 			str+=mystr("]");
438 
439 		}
440 		AddText(str.c_str());
441 		return *this;
442 	}
443 
444 
445 	virtual UserOutputInterface & operator <<(const SparseVector & v)
446 	{
447 		if (output_precision==-1) output_precision = *oprec_vector;
448 		mystr str;
449 		if (v.GetLen()<=70)
450 		{
451 			str+=mystr("[");
452 			for (int i=1; i<v.GetLen(); i++)
453 			{
454 				str+=mystr(v(i),output_precision);
455 				str+=mystr(", ");
456 			}
457 			if (v.GetLen()!=0)
458 			{
459 				str+=mystr(v(v.GetLen()),output_precision);
460 			}
461 			str+=mystr("]");
462 		} else
463 		{
464 
465 			str+=mystr("[");
466 			for (int i=1; i<=v.GetLen(); i++)
467 			{
468 				str+=mystr(v(i),output_precision);
469 				if (i!=v.GetLen()) {str+=mystr(", ");}
470 				if (i%16==0 && i!=v.GetLen()) {str+=mystr("\n  col("); str+=mystr(i); str+=mystr( "): ");}
471 			}
472 			str+=mystr("]");
473 
474 		}
475 		AddText(str.c_str());
476 		return *this;
477 	}
478 
479 	virtual UserOutputInterface & operator <<(const Matrix3D & m)
480 	{
481 		if (output_precision==-1) output_precision = *oprec_matrix;
482 		mystr str;
483 		for (int i=0; i < m.Getrows(); i++)
484 		{
485 			str+=mystr("[");
486 			for (int j=0; j < m.Getcols()-1; j++)
487 			{
488 				str+=mystr(m.Get0(i,j),output_precision);
489 				str+=", ";
490 			}
491 			str+=mystr(m.Get0(i,m.Getcols()-1),output_precision);
492 			str+="]\n";
493 		}
494 		AddText(str.c_str());
495 		return *this;
496 	}
497 
498 	virtual UserOutputInterface & operator <<(const Matrix & m)
499 	{
500 		if (output_precision==-1) output_precision = *oprec_matrix;
501 		mystr str;
502 		double max = m.MaxNorm();
503 		int i;
504 
505 		if (max==0) {max=1;}
506 		max=(int)log10(max);
507 		max=pow(10,max);
508 
509 		str+=mystr(max,output_precision);
510 		str+=mystr(" *\n");
511 
512 		for (i=1; i<=m.Getrows(); i++)
513 		{
514 			str+=mystr("[");
515 			for (int j=1; j<=m.Getcols(); j++)
516 			{
517 				char str1[32];
518 				sprintf_s(str1,"% 1.*f",output_precision,m(i,j)/max);
519 				str+=mystr(str1);
520 
521 				if (j!=m.Getcols()) {str+=mystr(",");}
522 			}
523 			str+=mystr("]\n");
524 		}
525 		AddText(str.c_str());
526 		return *this;
527 	}
528 
529 	virtual UserOutputInterface & operator <<(const SparseMatrix & m)
530 	{
531 		if (output_precision==-1) output_precision = *oprec_matrix;
532 		mystr str;
533 		double max = m.MaxNorm();
534 		int i;
535 
536 		if (max==0) {max=1;}
537 		max=(int)log10(max);
538 		max=pow(10,max);
539 
540 		str+=mystr(max); str+=mystr(" *\n");
541 
542 		for (i=1; i<=m.Getrows(); i++)
543 		{
544 			str+=mystr("[");
545 			for (int j=1; j<=m.Getcols(); j++)
546 			{
547 				char str1[32];
548 				sprintf_s(str1,"% 1.*f",output_precision,m(i,j)/max);
549 				str+=mystr(str1);
550 
551 				if (j!=m.Getcols()) {str+=mystr(",");}
552 			}
553 			str+=mystr("]\n");
554 		}
555 		AddText(str.c_str());
556 		return *this;
557 	}
558 
559 	virtual int CallWCDriverFunction(int action, int option = 0, int value = 0, ElementDataContainer* edc = NULL)
560 	{
561 		return pUI->CallWCDriverFunction(action, option, value, edc);
562 	}
563 };
564 
565 
566 #endif	// __USER_OUTPUT_H__