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