Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4tgrUtils.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4tgrUtils implementation
27//
28// Author: P.Arce, CIEMAT (November 2007)
29// --------------------------------------------------------------------
30
31#include <iomanip>
32#include <set>
33
34#include "G4tgrUtils.hh"
35
36#include "geomdefs.hh"
38#include "G4tgrParameterMgr.hh"
39#include "G4tgrMessenger.hh"
40#include "G4UnitsTable.hh"
42#include "G4UIcommand.hh"
43
44G4ThreadLocal G4tgrEvaluator* G4tgrUtils::theEvaluator = nullptr;
45
46// --------------------------------------------------------------------
48{
49 if(theEvaluator == nullptr)
50 {
51 theEvaluator = new G4tgrEvaluator;
52 }
53}
54
55// --------------------------------------------------------------------
57{
58 delete theEvaluator;
59 theEvaluator = nullptr;
60}
61
62// --------------------------------------------------------------------
64{
65 char nonCharacters[7] = { "()+-*/" };
66 for(std::size_t ii = 0; ii < 6; ++ii)
67 {
68 if(ch == nonCharacters[ii])
69 {
70 return true;
71 }
72 }
73 return false;
74}
75
76// --------------------------------------------------------------------
78{
79 G4int isnum = 1;
80 G4int numE = 0;
81 for(G4int ii = 0; ii < (G4int)str.length(); ++ii)
82 {
83 if(!isdigit(str[ii]) && (str[ii] != '.') && (str[ii] != '-') &&
84 (str[ii] != '+'))
85 {
86 //--- check for E(xponential)
87 if(str[ii] == 'E' || str[ii] == 'e')
88 {
89 if(ii == 0)
90 {
91 return 0;
92 }
93 if(numE != 0 || ii == G4int(str.length() - 1))
94 {
95 isnum = 0;
96 break;
97 }
98 numE++;
99 }
100 else
101 {
102 isnum = 0;
103 break;
104 }
105 }
106 }
107 return isnum;
108}
109
110// --------------------------------------------------------------------
112{
113 if(G4int(val) / val - 1 > precision)
114 {
115 return false;
116 }
117 else
118 {
119 return true;
120 }
121}
122
123// --------------------------------------------------------------------
124void G4tgrUtils::Dump3v(const G4ThreeVector& vec, const char* msg)
125{
126 G4cout << msg << std::setprecision(8) << vec << std::setprecision(6)
127 << G4endl;
128}
129
130// --------------------------------------------------------------------
131void G4tgrUtils::Dumprm(const G4RotationMatrix& rm, const char* msg)
132{
133 G4cout << msg << G4endl << " xx=" << rm.xx() << " yx=" << rm.yx()
134 << " zx=" << rm.zx() << G4endl << " xy=" << rm.xy()
135 << " yy=" << rm.yy() << " zy=" << rm.zy() << G4endl
136 << " xz=" << rm.xz() << " yz=" << rm.yz() << " zz=" << rm.zz()
137 << G4endl;
138}
139
140// --------------------------------------------------------------------
141void G4tgrUtils::DumpVS(const std::vector<G4String>& wl, const char* msg,
142 std::ostream& outs)
143{
144 outs << msg << G4endl;
145 for(auto ite = wl.cbegin(); ite != wl.cend(); ++ite)
146 {
147 outs << *ite << " ";
148 }
149 outs << G4endl;
150}
151
152// --------------------------------------------------------------------
153void G4tgrUtils::DumpVS(const std::vector<G4String>& wl, const char* msg)
154{
155 DumpVS(wl, msg, G4cout);
156}
157
158// --------------------------------------------------------------------
160{
161 if(str.find(':') != 0)
162 {
163 G4String ErrMessage = "Trying to subtract leading colon from a word\n" +
164 G4String("that has no leading colon: ") + str;
165 G4Exception("G4tgrUtils::SubColon()", "ParseError", FatalException,
166 ErrMessage);
167 }
168 G4String strt = str.substr(1, str.size() - 1);
169 return strt;
170}
171
172// --------------------------------------------------------------------
174{
175 //----------- first check if it is parameter
176 const char* cstr = str.c_str();
177 if(cstr[0] == '$')
178 {
179#ifdef G4VERBOSE
181 {
182 G4cout << " G4tgrUtils::GetString() - Substitute parameter: "
184 str.substr(1, str.size()))
185 << G4endl;
186 }
187#endif
189 str.substr(1, str.size()));
190 }
191 else
192 {
193 return str;
194 }
195}
196
197// --------------------------------------------------------------------
199{
200 if(!theEvaluator)
201 {
202 theEvaluator = new G4tgrEvaluator;
203 }
204#ifdef G4VERBOSE
206 {
207 G4cout << "G4tgrUtils::GetDouble() - Processing: " << str
208 << " default unit " << unitval << G4endl;
209 }
210#endif
211 if(str == "DBL_MAX")
212 {
213 return DBL_MAX;
214 }
215 else if(str == "DBL_MIN")
216 {
217 return DBL_MIN;
218 }
219 else if(str == "FLT_MAX")
220 {
221 return FLT_MAX;
222 }
223 else if(str == "FLT_MIN")
224 {
225 return FLT_MIN;
226 }
227 else if(str == "INT_MAX")
228 {
229 return INT_MAX;
230 }
231 else if(str == "INT_MIN")
232 {
233 return INT_MIN;
234 }
235 //----- Look for arithmetic symbols, (, )
236 const char* cstr = str.c_str();
237 std::set<G4int> separators;
238 separators.insert(-1);
239 G4int strlen = G4int(str.length());
240 for(G4int ii = 0; ii < strlen; ++ii)
241 {
242 char cs = cstr[ii];
243 if(cs == '*' || cs == '/' || cs == '(' || cs == ')')
244 {
245 separators.insert(ii);
246 }
247 else if(cs == '+' || cs == '-')
248 {
249 // Check if it is not an exponential
250 //
251 if((ii < 2) || ((cstr[ii - 1] != 'E') && (cstr[ii - 1] != 'e')) ||
252 !IsNumber(G4String(1,cstr[ii - 2])))
253 {
254 separators.insert(ii);
255 }
256 }
257 }
258 separators.insert(strlen);
259 std::string strnew; // build a new word with Parameters
260 // and units substituted by values
261 //----- Process words, defined as characters between two separators
262 G4int nUnits = 0;
263 std::set<G4int>::const_iterator site, site2;
264 site = separators.cbegin();
265 site2 = site;
266 ++site2;
267 for(; site2 != separators.cend(); ++site, ++site2)
268 {
269#ifdef G4VERBOSE
271 {
272 G4cout << " Loop to find word between " << *site << " " << *site2
273 << G4endl;
274 }
275#endif
276
277 if(*site != -1)
278 {
279 strnew += str.substr(*site, 1);
280 }
281
282 G4int wlen = (*site2) - (*site) - 1; // do not count contiguous separators
283 std::string word;
284 if(wlen != 0)
285 {
286 word = str.substr((*site) + 1, (*site2) - (*site) - 1);
287 }
288 else
289 {
290 //--- Check combination of separators
291 //--- Check number of parentheses
292 continue;
293 }
294
295#ifdef G4VERBOSE
297 {
298 G4cout << " Processing word: " << word << G4endl;
299 }
300#endif
301 //----------- first check if it is parameter
302 const char* cword = word.c_str();
303 if(cword[0] == '$')
304 {
306 word.substr(1, word.size()));
307 if(parstr.substr(0, 1) == "-")
308 {
309 strnew += "(";
310 }
311 strnew += parstr;
312 if(parstr.substr(0, 1) == "-")
313 {
314 strnew += ")";
315 }
316#ifdef G4VERBOSE
318 {
319 G4cout << " G4tgrutils::GetDouble() - Param found: " << word
320 << " in string " << str << " , substituted by " << parstr
321 << G4endl;
322 }
323#endif
324 }
325 else
326 {
327 //----- Get if it is a number
328 if(IsNumber(word))
329 {
330 //--- left separator cannot be ')'
331 if((*site != -1) && (cstr[*site] == ')'))
332 {
333 G4String ErrMessage =
334 "There cannot be a ')' before a number: " + word +
335 " in string: " + str;
336 G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
337 ErrMessage);
338 }
339 //--- right separator cannot be '('
340 if((*site2 != strlen) && (cstr[*site2] == '('))
341 {
342 G4String ErrMessage =
343 "There cannot be a '(' after a number: " + word +
344 " in string: " + str;
345 G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
346 ErrMessage);
347 }
348 strnew += word;
349
350 //------ If it is an string, check if it is a unit
351 }
352 else
353 {
354 //--- First character cannot be a digit
355 if(isdigit(word[0]))
356 {
357 G4String ErrMessage =
358 "String words cannot start with a digit: " + word +
359 " in string: " + str;
360 G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
361 ErrMessage);
362 }
363
364 //----- Check if it is a function
365 G4bool bWordOK = false;
366 if(G4tgrUtils::IsFunction(word))
367 {
368 //--- It must be followed by '('
369 if((*site2 == strlen) || (cstr[*site2] != '('))
370 {
371 G4String ErrMessage =
372 "There must be a '(' after a function: " + word +
373 " in string: " + str;
374 G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
375 ErrMessage);
376 }
377 strnew += word;
378 bWordOK = true;
379 //----- Check if it is a unit
380 }
381 else if(G4tgrUtils::WordIsUnit(word))
382 {
383 //--- It must be preceded by a *
384 if((*site == -1) || ((cstr[*site] != '*') && (cstr[*site] != '/')))
385 {
386 G4String ErrMess =
387 "There must be a '*' before a unit definition: " + word +
388 " in string " + str;
389 G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
390 ErrMess);
391 }
392 //--- check that it is indeed a CLHEP unit
393 if(G4UnitDefinition::GetValueOf(word) != 0.)
394 {
395 bWordOK = true;
396 nUnits++;
397 if(nUnits > 1)
398 {
399 // G4String ErrMess = "There cannot be two unit definitions: "
400 // + word + " in string " + str;
401 // G4Exception("G4tgrUtils::GetDouble()", "ParseError",
402 // FatalException, ErrMess );
403 }
404 strnew +=
406 }
407 }
408 if(!bWordOK)
409 {
410 G4String ErrMess = "String word is not a parameter, nor a unit\n" +
411 G4String("definition nor a function: ") + word +
412 G4String(" in string: ") + str;
413 G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
414 ErrMess);
415 }
416 }
417 }
418 }
419
420 G4double val = theEvaluator->evaluate(strnew.c_str());
421 if(theEvaluator->status() != HepTool::Evaluator::OK)
422 {
423 theEvaluator->print_error(theEvaluator->status());
424 G4String ErrMessage = "Evaluator error: " + strnew;
425 G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
426 ErrMessage);
427 }
428
429 if(nUnits == 0)
430 {
431 val *= unitval;
432 }
433
434#ifdef G4VERBOSE
436 {
437 G4cout << " G4tgrUtils::GetDouble() - RESULT= " << val << G4endl
438 << " from string: " << str << " converted to: " << strnew.c_str()
439 << " with unit val: " << unitval << G4endl;
440 }
441#endif
442
443 return val;
444}
445
446// --------------------------------------------------------------------
448{
449 //----- Convert it to a number (it can be a parameter)
450 G4double val = GetDouble(str);
451
452 //----- Check it is an integer
453 if(!IsInteger(val))
454 {
455 G4String ErrMessage = G4String("Trying to get the integer from a number") +
456 G4String(" which is not an integer ") + str;
457 G4Exception("G4tgrUtils::GetInt()", "ParseError", FatalException,
458 ErrMessage);
459 }
460 return G4int(val);
461}
462
463// --------------------------------------------------------------------
465{
466 G4bool val = false;
467
468 //----------- first check that it is a not number
469 if((str == "ON") || (str == "TRUE"))
470 {
471 val = true;
472 }
473 else if((str == "OFF") || (str == "FALSE"))
474 {
475 val = false;
476 }
477 else
478 {
479 G4String ErrMessage = G4String("Trying to get a float from a string") +
480 G4String(" which is not 'ON'/'OFF'/'TRUE'/'FALSE' ") +
481 str;
482 G4Exception("G4tgrUtils::GetBool()", "ParseError", FatalException,
483 ErrMessage);
484 }
485
486 return val;
487}
488
489// --------------------------------------------------------------------
490void G4tgrUtils::CheckWLsize(const std::vector<G4String>& wl,
491 unsigned int nWcheck, WLSIZEtype st,
492 const G4String& methodName)
493{
494 G4String outStr = methodName + G4String(". Line read with number of words ");
495 unsigned int wlsize = (unsigned int)wl.size();
496
497 G4bool isOK = CheckListSize(wlsize, nWcheck, st, outStr);
498
499 if(!isOK)
500 {
501 G4String chartmp = G4UIcommand::ConvertToString(G4int(nWcheck));
502 outStr += chartmp + G4String(" words");
503 DumpVS(wl, outStr.c_str());
504 G4String ErrMessage =
505 " NUMBER OF WORDS: " + G4UIcommand::ConvertToString(G4int(wlsize));
506 G4Exception("G4tgrUtils::CheckWLsize()", "ParseError", FatalException,
507 ErrMessage);
508 }
509}
510
511// --------------------------------------------------------------------
512G4bool G4tgrUtils::CheckListSize(unsigned int nWreal, unsigned int nWcheck,
513 WLSIZEtype st, G4String& outStr)
514{
515 G4bool isOK = true;
516 switch(st)
517 {
518 case WLSIZE_EQ:
519 if(nWreal != nWcheck)
520 {
521 isOK = false;
522 outStr += G4String("not equal than ");
523 }
524 break;
525 case WLSIZE_NE:
526 if(nWreal == nWcheck)
527 {
528 isOK = false;
529 outStr += G4String("equal than ");
530 }
531 break;
532 case WLSIZE_LE:
533 if(nWreal > nWcheck)
534 {
535 isOK = false;
536 outStr += G4String("greater than ");
537 }
538 break;
539 case WLSIZE_LT:
540 if(nWreal >= nWcheck)
541 {
542 isOK = false;
543 outStr += G4String("greater or equal than ");
544 }
545 break;
546 case WLSIZE_GE:
547 if(nWreal < nWcheck)
548 {
549 isOK = false;
550 outStr += G4String("less than ");
551 }
552 break;
553 case WLSIZE_GT:
554 if(nWreal <= nWcheck)
555 {
556 isOK = false;
557 outStr += G4String("less or equal than ");
558 }
559 break;
560 default:
561 G4cerr << " ERROR!! - G4tgrUtils::CheckListSize()" << G4endl
562 << " Type of WLSIZE type not found " << st << G4endl;
563 break;
564 }
565
566 return isOK;
567}
568
569// --------------------------------------------------------------------
571{
572 return !IsNumber(word);
573 if(word == "mm" || word == "cm" || word == "m" || word == "km" ||
574 word == "millimeter" || word == "centimeter" || word == "meter" ||
575 word == "kilometer" || word == "parsec" || word == "micrometer" ||
576 word == "nanometer" || word == "angstrom" || word == "fermi" ||
577 word == "nm" || word == "um" || word == "pc" || word == "radian" ||
578 word == "milliradian" || word == "degree" || word == "rad" ||
579 word == "mrad" || word == "deg" || word == "ns" || word == "becquerel" ||
580 word == "curie")
581 {
582 return true;
583 }
584 else
585 {
586 return false;
587 }
588}
589
590// --------------------------------------------------------------------
592{
593 if(word == "sin" || word == "cos" || word == "tan" || word == "asin" ||
594 word == "acos" || word == "atan" || word == "atan2" || word == "sinh" ||
595 word == "cosh" || word == "tanh" || word == "asinh" || word == "acosh" ||
596 word == "atanh" || word == "sqrt" || word == "exp" || word == "log" ||
597 word == "log10" || word == "pow")
598 {
599 return true;
600 }
601 else
602 {
603 return false;
604 }
605}
606
607// --------------------------------------------------------------------
609{
610 G4RotationMatrix rotation;
611
612 if(std::fabs(dir.mag() - 1.) >
614 {
615 G4String WarMessage = "Direction cosines have been normalized to one.\n" +
616 G4String("They were normalized to ") +
618 G4Exception("G4tgrUtils::GetRotationFromDirection()", "WrongArgument",
619 JustWarning, WarMessage);
620 dir /= dir.mag();
621 }
622 G4double angx = -std::asin(dir.y());
623
624 // There are always two solutions angx, angy and PI-angx,
625 // PI+angy, choose first
626 //
627 G4double angy;
628 if(dir.y() == 1.)
629 {
630 angy = 0.;
631 }
632 else if(dir.y() == 0.)
633 {
634 angy = 0.;
635 }
636 else
637 {
638 angy = std::asin(dir.x() / std::sqrt(1 - dir.y() * dir.y()));
639 }
640
641 // choose between angy and PI-angy
642 if(dir.z() * std::cos(angx) * std::cos(angy) < 0)
643 {
644 angy = pi - angy;
645 }
646 rotation.rotateX(angx);
647 rotation.rotateY(angy);
648
649 return rotation;
650}
651
652// --------------------------------------------------------------------
654 const G4String& word2)
655{
656 G4bool bEqual = true;
657 std::vector<std::pair<size_t, size_t>> stringPairs;
658 // start of substring, number of characters
659
660 //--- Get string limits between asterisks in word1
661
662 std::size_t cStart = 0;
663 for(;;)
664 {
665 size_t cAster = word1.find("*", cStart);
666 if(cAster != std::string::npos)
667 {
668 if(cAster == cStart)
669 {
670 if(cAster != 0)
671 {
672 G4Exception("G4tgrUtils::AreWordsEquivalent()",
673 "A word has two asterisks together, please correct it",
674 FatalException, ("Offending word is: " + word1).c_str());
675 }
676 else
677 {
678 // word1 == *
679 if(word1.size() == 1)
680 {
681 return true;
682 }
683 }
684 }
685 if(cAster != cStart)
686 {
687 stringPairs.push_back(
688 std::pair<size_t, size_t>(cStart, cAster - cStart));
689 }
690 cStart = cAster + 1;
691 }
692 else
693 {
694 if(cStart == 0)
695 {
696 //--- If there is no asterisk check if they are the same
697 return word1 == word2;
698 }
699 break;
700 }
701 }
702
703 //---- Add characters after last asterisk as string pair
704 if(cStart <= word1.length())
705 {
706 if(word1.length() != cStart)
707 {
708 stringPairs.push_back(
709 std::pair<size_t, size_t>(cStart, word1.length() - cStart));
710 }
711 }
712
713 //--- If there are not asterisk, simple comparison
714 if(stringPairs.size() == 0)
715 {
716 if(word1 == word2)
717 {
718 return true;
719 }
720 else
721 {
722 return false;
723 }
724 }
725
726 //--- Find substrings in word2, in same order as in word1
727 cStart = 0;
728 for(std::size_t ii = 0; ii < stringPairs.size(); ++ii)
729 {
730 std::pair<size_t, size_t> spair = stringPairs[ii];
731 size_t sFound = word2.find(word1.substr(spair.first, spair.second), cStart);
732 if(sFound == std::string::npos)
733 {
734 bEqual = false;
735 break;
736 }
737 else
738 {
739 //---- If there is no asterisk before first character,
740 // the fisrt string pair found has to start at the first character
741 if(spair.first == 0 && sFound != 0)
742 {
743 bEqual = false;
744 break;
745 //---- If there is no asterisk after last character,
746 // the last string pair found has to end at the last character
747 }
748 else if((spair.first + spair.second - 1 == word1.length()) &&
749 (sFound + spair.second - 1 != word2.length()))
750 {
751 bEqual = false;
752 break;
753 }
754 cStart += spair.second;
755 }
756 }
757
758 return bEqual;
759}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
WLSIZEtype
Definition G4tgrUtils.hh:46
@ WLSIZE_NE
Definition G4tgrUtils.hh:48
@ WLSIZE_EQ
Definition G4tgrUtils.hh:47
@ WLSIZE_GE
Definition G4tgrUtils.hh:51
@ WLSIZE_LT
Definition G4tgrUtils.hh:50
@ WLSIZE_LE
Definition G4tgrUtils.hh:49
@ WLSIZE_GT
Definition G4tgrUtils.hh:52
double z() const
double x() const
double y() const
double mag() const
double zz() const
double yz() const
double zx() const
double yx() const
double zy() const
double xx() const
HepRotation & rotateX(double delta)
Definition Rotation.cc:61
double yy() const
double xz() const
HepRotation & rotateY(double delta)
Definition Rotation.cc:74
double xy() const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
static G4String ConvertToString(G4bool boolVal)
static G4double GetValueOf(const G4String &)
void print_error(G4int status) const
static G4int GetVerboseLevel()
G4String FindParameter(const G4String &name, G4bool exists=true)
static G4tgrParameterMgr * GetInstance()
static G4bool IsNumber(const G4String &str)
Definition G4tgrUtils.cc:77
static G4String GetString(const G4String &str)
static G4bool IsSeparator(char)
Definition G4tgrUtils.cc:63
static void CheckWLsize(const std::vector< G4String > &wl, unsigned int nWCheck, WLSIZEtype st, const G4String &methodName)
static void DumpVS(const std::vector< G4String > &wl, const char *msg)
static G4bool IsInteger(const G4double val, const G4double precision=1.e-6)
static G4bool GetBool(const G4String &str)
static void Dumprm(const G4RotationMatrix &rm, const char *msg)
static G4bool CheckListSize(unsigned int nWreal, unsigned int nWcheck, WLSIZEtype st, G4String &outstr)
static void Dump3v(const G4ThreeVector &vec, const char *msg)
static G4bool IsFunction(const G4String &word)
static G4int GetInt(const G4String &str)
static G4double GetDouble(const G4String &str, G4double unitval=1.)
static G4RotationMatrix GetRotationFromDirection(G4ThreeVector dir)
static G4String SubColon(const G4String &str)
static G4bool WordIsUnit(const G4String &word)
static G4bool AreWordsEquivalent(const G4String &word1, const G4String &word2)
double evaluate(const char *expression)
Definition Evaluator.cc:616
int status() const
Definition Evaluator.cc:636
#define INT_MIN
Definition templates.hh:94
#define FLT_MAX
Definition templates.hh:78
#define FLT_MIN
Definition templates.hh:70
#define INT_MAX
Definition templates.hh:90
#define DBL_MIN
Definition templates.hh:54
#define DBL_MAX
Definition templates.hh:62
#define G4ThreadLocal
Definition tls.hh:77