Geant4  10.03
G4MaterialPropertiesTable.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 // $Id: G4MaterialPropertiesTable.cc 99765 2016-10-05 08:49:47Z gcosmo $
28 //
29 //
31 // G4MaterialPropertiesTable Implementation
33 //
34 // File: G4MaterialPropertiesTable.cc
35 // Version: 1.0
36 // Created: 1996-02-08
37 // Author: Juliet Armstrong
38 // Updated: 2005-05-12 add SetGROUPVEL(), courtesy of
39 // Horton-Smith (bug report #741), by P. Gumplinger
40 // 2002-11-05 add named material constants by P. Gumplinger
41 // 1999-11-05 Migration from G4RWTPtrHashDictionary to STL
42 // by John Allison
43 // 1997-03-26 by Peter Gumplinger
44 // > cosmetics (only)
45 // mail: gum@triumf.ca
46 //
48 
49 #include "globals.hh"
51 #include "G4PhysicalConstants.hh"
52 #include "G4Log.hh"
53 
55 // Constructors
57 
59 {
60 }
61 
63 // Destructor
65 
67 {
68  MPTiterator i;
69  for (i = MPT.begin(); i != MPT.end(); ++i)
70  {
71  G4cout << (*i).second << G4endl;
72  delete (*i).second;
73  }
74  MPT.clear();
75  MPTC.clear();
76 }
77 
79 // Methods
81 
83 {
84  // Returns the constant material property corresponding to a key
85 
86  MPTCiterator j;
87  j = MPTC.find(G4String(key));
88  if ( j != MPTC.end() ) return j->second;
89  G4cout << "key: " << G4String(key) << G4endl;
90  G4Exception("G4MaterialPropertiesTable::GetConstProperty()","mat202",
91  FatalException, "Constant Material Property not found.");
92  return 0.;
93 }
94 
96 {
97  // Returns true if a const property 'key' exists
98 
99  MPTCiterator j;
100  j = MPTC.find(G4String(key));
101  if ( j != MPTC.end() ) return true;
102  return false;
103 }
104 
107 {
108  // Returns a Material Property Vector corresponding to a key
109 
110  //Important Note for MT. adotti 17 Feb 2016
111  //In previous implementation the following line was at the bottom of the
112  //function causing a rare race-condition.
113  //Moving this line here from the bottom solves the problem because:
114  //1- Map is accessed only via operator[] (to insert) and find() (to search),
115  // and these are thread safe if done on separate elements.
116  // See notes on data-races at:
117  // http://www.cplusplus.com/reference/map/map/operator%5B%5D/
118  // http://www.cplusplus.com/reference/map/map/find/
119  //2- So we have a data race if two threads access the same element (GROUPVEL)
120  // one in read and one in write mode. This was happening with the line
121  // at the bottom of the code, one thread in SetGROUPVEL(),
122  // and the other here
123  //3- SetGROUPVEL() is protected by a mutex that ensures that only
124  // one thread at the time will execute its code
125  //4- The if() statement guarantees that only if two threads are searching
126  // the same problematic key (GROUPVEL) the mutex will be used.
127  // Different keys do not lock (good for performances)
128  //5- As soon as a thread acquires the mutex in SetGROUPVEL it checks again
129  // if the map has GROUPVEL key, if so returns immediately.
130  // This "double check" allows to execute the heavy code to calculate
131  // group velocity only once even if two threads enter SetGROUPVEL together
132  if (G4String(key) == "GROUPVEL") return SetGROUPVEL();
133 
134  MPTiterator i;
135  i = MPT.find(G4String(key));
136  if ( i != MPT.end() ) return i->second;
137  return nullptr;
138 }
139 
141  G4double aPhotonEnergy,
142  G4double aPropertyValue)
143 {
144  // Allows to add an entry pair directly to the Material Property Vector
145  // given a key
146 
147  G4MaterialPropertyVector *targetVector=MPT [G4String(key)];
148  if (targetVector != nullptr)
149  {
150  targetVector->InsertValues(aPhotonEnergy, aPropertyValue);
151  }
152  else
153  {
154  G4Exception("G4MaterialPropertiesTable::AddEntry()", "mat203",
155  FatalException, "Material Property Vector not found.");
156  }
157 }
158 
160 {
161  MPTiterator i;
162  for (i = MPT.begin(); i != MPT.end(); ++i)
163  {
164  G4cout << (*i).first << G4endl;
165  if ( (*i).second != 0 )
166  {
167  (*i).second->DumpValues();
168  }
169  else
170  {
171  G4Exception("G4MaterialPropertiesTable::DumpTable()", "mat204",
172  JustWarning, "NULL Material Property Vector Pointer.");
173  }
174  }
175  MPTCiterator j;
176  for (j = MPTC.begin(); j != MPTC.end(); ++j)
177  {
178  G4cout << j->first << G4endl;
179  if ( j->second != 0 )
180  {
181  G4cout << j->second << G4endl;
182  }
183  else
184  {
185  G4Exception("G4MaterialPropertiesTable::DumpTable()", "mat202",
186  JustWarning, "No Material Constant Property.");
187  }
188  }
189 }
190 
191 #ifdef G4MULTITHREADED
192 #include "G4AutoLock.hh"
193 namespace {
194  G4Mutex materialPropertyTableMutex = G4MUTEX_INITIALIZER;
195 }
196 #endif
197 
199 {
200 #ifdef G4MULTITHREADED
201  G4AutoLock mptm(&materialPropertyTableMutex);
202 #endif
203 
204  // check if "GROUPVEL" already exists
205  MPTiterator itr;
206  itr = MPT.find("GROUPVEL");
207  if(itr != MPT.end()) return itr->second;
208 
209  // fetch RINDEX data, give up if unavailable
210  //
211  G4MaterialPropertyVector *rindex = this->GetProperty("RINDEX");
212  if (rindex==0) { return 0; }
213 
214  // RINDEX exists but has no entries, give up
215  //
216  if ( rindex->GetVectorLength() == 0 ) { return 0; }
217 
218  // add GROUPVEL vector
219  //
221 
222  // fill GROUPVEL vector using RINDEX values
223  // rindex built-in "iterator" was advanced to first entry above
224  //
225  G4double E0 = rindex->Energy(0);
226  G4double n0 = (*rindex)[0];
227 
228  if (E0 <= 0.)
229  {
230  G4Exception("G4MaterialPropertiesTable::SetGROUPVEL()", "mat205",
231  FatalException, "Optical Photon Energy <= 0");
232  }
233 
234  if ( rindex->GetVectorLength() >= 2 )
235  {
236  // good, we have at least two entries in RINDEX
237  // get next energy/value pair
238 
239  G4double E1 = rindex->Energy(1);
240  G4double n1 = (*rindex)[1];
241 
242  if (E1 <= 0.)
243  {
244  G4Exception("G4MaterialPropertiesTable::SetGROUPVEL()", "mat205",
245  FatalException, "Optical Photon Energy <= 0");
246  }
247 
248  G4double vg;
249 
250  // add entry at first photon energy
251  //
252  vg = c_light/(n0+(n1-n0)/G4Log(E1/E0));
253 
254  // allow only for 'normal dispersion' -> dn/d(logE) > 0
255  //
256  if((vg<0) || (vg>c_light/n0)) { vg = c_light/n0; }
257 
258  groupvel->InsertValues( E0, vg );
259 
260  // add entries at midpoints between remaining photon energies
261  //
262 
263  for (size_t i = 2; i < rindex->GetVectorLength(); i++)
264  {
265  vg = c_light/( 0.5*(n0+n1)+(n1-n0)/G4Log(E1/E0));
266 
267  // allow only for 'normal dispersion' -> dn/d(logE) > 0
268  //
269  if((vg<0) || (vg>c_light/(0.5*(n0+n1)))) { vg = c_light/(0.5*(n0+n1)); }
270  groupvel->InsertValues( 0.5*(E0+E1), vg );
271 
272  // get next energy/value pair, or exit loop
273  //
274  E0 = E1;
275  n0 = n1;
276  E1 = rindex->Energy(i);
277  n1 = (*rindex)[i];
278 
279  if (E1 <= 0.)
280  {
281  G4Exception("G4MaterialPropertiesTable::SetGROUPVEL()", "mat205",
282  FatalException, "Optical Photon Energy <= 0");
283  }
284  }
285 
286  // add entry at last photon energy
287  //
288  vg = c_light/(n1+(n1-n0)/G4Log(E1/E0));
289 
290  // allow only for 'normal dispersion' -> dn/d(logE) > 0
291  //
292  if((vg<0) || (vg>c_light/n1)) { vg = c_light/n1; }
293  groupvel->InsertValues( E1, vg );
294  }
295  else // only one entry in RINDEX -- weird!
296  {
297  groupvel->InsertValues( E0, c_light/n0 );
298  }
299 
300  this->AddProperty( "GROUPVEL", groupvel );
301 
302  return groupvel;
303 }
void AddEntry(const char *key, G4double aPhotonEnergy, G4double aPropertyValue)
void InsertValues(G4double energy, G4double value)
G4MaterialPropertyVector * SetGROUPVEL()
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:175
G4MaterialPropertyVector * AddProperty(const char *key, G4double *PhotonEnergies, G4double *PropertyValues, G4int NumEntries)
G4GLOB_DLL std::ostream G4cout
G4PhysicsOrderedFreeVector G4MaterialPropertyVector
std::map< G4String, G4double, std::less< G4String > > MPTC
bool G4bool
Definition: G4Types.hh:79
std::map< G4String, G4MaterialPropertyVector *, std::less< G4String > >::const_iterator MPTiterator
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4double G4Log(G4double x)
Definition: G4Log.hh:230
G4bool ConstPropertyExists(const char *key) const
G4int G4Mutex
Definition: G4Threading.hh:173
std::map< G4String, G4double, std::less< G4String > >::const_iterator MPTCiterator
#define G4endl
Definition: G4ios.hh:61
std::map< G4String, G4MaterialPropertyVector *, std::less< G4String > > MPT
double G4double
Definition: G4Types.hh:76
G4MaterialPropertyVector * GetProperty(const char *key)
G4double GetConstProperty(const char *key) const