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