Geant4  10.01.p01
G4PhysicsVector.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: G4PhysicsVector.cc 83009 2014-07-24 14:51:29Z gcosmo $
28 //
29 //
30 // --------------------------------------------------------------
31 // GEANT 4 class implementation file
32 //
33 // G4PhysicsVector.cc
34 //
35 // History:
36 // 02 Dec. 1995, G.Cosmo : Structure created based on object model
37 // 03 Mar. 1996, K.Amako : Implemented the 1st version
38 // 01 Jul. 1996, K.Amako : Hidden bin from the user introduced
39 // 12 Nov. 1998, K.Amako : A bug in GetVectorLength() fixed
40 // 11 Nov. 2000, H.Kurashige : use STL vector for dataVector and binVector
41 // 18 Jan. 2001, H.Kurashige : removed ptrNextTable
42 // 09 Mar. 2001, H.Kurashige : added G4PhysicsVector type
43 // 05 Sep. 2008, V.Ivanchenko : added protections for zero-length vector
44 // 11 May 2009, A.Bagulya : added new implementation of methods
45 // ComputeSecondDerivatives - first derivatives at edge points
46 // should be provided by a user
47 // FillSecondDerivatives - default computation base on "not-a-knot"
48 // algorithm
49 // 19 Jun. 2009, V.Ivanchenko : removed hidden bin
50 // 17 Nov. 2009, H.Kurashige : use pointer for DataVector
51 // 04 May 2010 H.Kurashige : use G4PhyscisVectorCache
52 // 28 May 2010 H.Kurashige : Stop using pointers to G4PVDataVector
53 // 16 Aug. 2011 H.Kurashige : Add dBin, baseBin and verboseLevel
54 // --------------------------------------------------------------
55 
56 #include <iomanip>
57 #include "G4PhysicsVector.hh"
58 
59 //G4ThreadLocal G4Allocator<G4PhysicsVector> *fpPVAllocator = 0;
60 
61 // --------------------------------------------------------------
62 
64  : type(T_G4PhysicsVector),
65  edgeMin(0.), edgeMax(0.), numberOfNodes(0),
66  useSpline(false),
67  dBin(0.), baseBin(0.),
68  verboseLevel(0)
69 {
70  // if (!fpPVAllocator) fpPVAllocator = new G4Allocator<G4PhysicsVector>;
71 }
72 
73 // --------------------------------------------------------------
74 
76 {
77 }
78 
79 // --------------------------------------------------------------
80 
82 {
83  dBin = right.dBin;
84  baseBin = right.baseBin;
85  verboseLevel = right.verboseLevel;
86 
87  DeleteData();
88  CopyData(right);
89 }
90 
91 // --------------------------------------------------------------
92 
94 {
95  if (&right==this) { return *this; }
96  dBin = right.dBin;
97  baseBin = right.baseBin;
98  verboseLevel = right.verboseLevel;
99 
100  DeleteData();
101  CopyData(right);
102  return *this;
103 }
104 
105 // --------------------------------------------------------------
106 
108 {
109  return (this == &right);
110 }
111 
112 // --------------------------------------------------------------
113 
115 {
116  return (this != &right);
117 }
118 
119 // --------------------------------------------------------------
120 
122 {
123  useSpline = false;
124  secDerivative.clear();
125 }
126 
127 // --------------------------------------------------------------
128 
130 {
131  type = vec.type;
132  edgeMin = vec.edgeMin;
133  edgeMax = vec.edgeMax;
135  useSpline = vec.useSpline;
136 
137  size_t i;
138  dataVector.resize(numberOfNodes);
139  for(i=0; i<numberOfNodes; ++i) {
140  dataVector[i] = (vec.dataVector)[i];
141  }
142  binVector.resize(numberOfNodes);
143  for(i=0; i<numberOfNodes; ++i) {
144  binVector[i] = (vec.binVector)[i];
145  }
146  if(0 < (vec.secDerivative).size()) {
147  secDerivative.resize(numberOfNodes);
148  for(i=0; i<numberOfNodes; ++i){
149  secDerivative[i] = (vec.secDerivative)[i];
150  }
151  }
152 }
153 
154 // --------------------------------------------------------------
155 
157 {
158  return binVector[binNumber];
159 }
160 
161 // --------------------------------------------------------------
162 
163 G4bool G4PhysicsVector::Store(std::ofstream& fOut, G4bool ascii)
164 {
165  // Ascii mode
166  if (ascii)
167  {
168  fOut << *this;
169  return true;
170  }
171  // Binary Mode
172 
173  // binning
174  fOut.write((char*)(&edgeMin), sizeof edgeMin);
175  fOut.write((char*)(&edgeMax), sizeof edgeMax);
176  fOut.write((char*)(&numberOfNodes), sizeof numberOfNodes);
177 
178  // contents
179  size_t size = dataVector.size();
180  fOut.write((char*)(&size), sizeof size);
181 
182  G4double* value = new G4double[2*size];
183  for(size_t i = 0; i < size; ++i)
184  {
185  value[2*i] = binVector[i];
186  value[2*i+1]= dataVector[i];
187  }
188  fOut.write((char*)(value), 2*size*(sizeof (G4double)));
189  delete [] value;
190 
191  return true;
192 }
193 
194 // --------------------------------------------------------------
195 
196 G4bool G4PhysicsVector::Retrieve(std::ifstream& fIn, G4bool ascii)
197 {
198  // clear properties;
199  dataVector.clear();
200  binVector.clear();
201  secDerivative.clear();
202 
203  // retrieve in ascii mode
204  if (ascii){
205  // binning
206  fIn >> edgeMin >> edgeMax >> numberOfNodes;
207  if (fIn.fail()) { return false; }
208  // contents
209  G4int siz=0;
210  fIn >> siz;
211  if (fIn.fail()) { return false; }
212  if (siz<=0)
213  {
214 #ifdef G4VERBOSE
215  G4cerr << "G4PhysicsVector::Retrieve():";
216  G4cerr << " Invalid vector size: " << siz << G4endl;
217 #endif
218  return false;
219  }
220 
221  binVector.reserve(siz);
222  dataVector.reserve(siz);
223  G4double vBin, vData;
224 
225  for(G4int i = 0; i < siz ; i++)
226  {
227  vBin = 0.;
228  vData= 0.;
229  fIn >> vBin >> vData;
230  if (fIn.fail()) { return false; }
231  binVector.push_back(vBin);
232  dataVector.push_back(vData);
233  }
234 
235  // to remove any inconsistency
236  numberOfNodes = siz;
237  edgeMin = binVector[0];
238  edgeMax = binVector[numberOfNodes-1];
239  return true ;
240  }
241 
242  // retrieve in binary mode
243  // binning
244  fIn.read((char*)(&edgeMin), sizeof edgeMin);
245  fIn.read((char*)(&edgeMax), sizeof edgeMax);
246  fIn.read((char*)(&numberOfNodes), sizeof numberOfNodes );
247 
248  // contents
249  size_t size;
250  fIn.read((char*)(&size), sizeof size);
251 
252  G4double* value = new G4double[2*size];
253  fIn.read((char*)(value), 2*size*(sizeof(G4double)) );
254  if (G4int(fIn.gcount()) != G4int(2*size*(sizeof(G4double))) )
255  {
256  delete [] value;
257  return false;
258  }
259 
260  binVector.reserve(size);
261  dataVector.reserve(size);
262  for(size_t i = 0; i < size; ++i)
263  {
264  binVector.push_back(value[2*i]);
265  dataVector.push_back(value[2*i+1]);
266  }
267  delete [] value;
268 
269  // to remove any inconsistency
270  numberOfNodes = size;
271  edgeMin = binVector[0];
273 
274  return true;
275 }
276 
277 // --------------------------------------------------------------
278 
279 void
281 {
282  size_t n = dataVector.size();
283  size_t i;
284  if(n > 0) {
285  for(i=0; i<n; ++i) {
286  binVector[i] *= factorE;
287  dataVector[i] *= factorV;
288  }
289  }
290  // n = secDerivative.size();
291  // if(n > 0) { for(i=0; i<n; ++i) { secDerivative[i] *= factorV; } }
292  secDerivative.clear();
293 
294  edgeMin *= factorE;
295  edgeMax *= factorE;
296 }
297 
298 // --------------------------------------------------------------
299 
300 void
302  G4double endPointDerivative)
303  // A standard method of computation of second derivatives
304  // First derivatives at the first and the last point should be provided
305  // See for example W.H. Press et al. "Numerical recipes in C"
306  // Cambridge University Press, 1997.
307 {
308  if(4 > numberOfNodes) // cannot compute derivatives for less than 4 bins
309  {
311  return;
312  }
313 
314  if(!SplinePossible()) { return; }
315 
316  useSpline = true;
317 
318  G4int n = numberOfNodes-1;
319 
320  G4double* u = new G4double [n];
321 
322  G4double p, sig, un;
323 
324  u[0] = (6.0/(binVector[1]-binVector[0]))
325  * ((dataVector[1]-dataVector[0])/(binVector[1]-binVector[0])
326  - firstPointDerivative);
327 
328  secDerivative[0] = - 0.5;
329 
330  // Decomposition loop for tridiagonal algorithm. secDerivative[i]
331  // and u[i] are used for temporary storage of the decomposed factors.
332 
333  for(G4int i=1; i<n; ++i)
334  {
335  sig = (binVector[i]-binVector[i-1]) / (binVector[i+1]-binVector[i-1]);
336  p = sig*(secDerivative[i-1]) + 2.0;
337  secDerivative[i] = (sig - 1.0)/p;
338  u[i] = (dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i])
339  - (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]);
340  u[i] = 6.0*u[i]/(binVector[i+1]-binVector[i-1]) - sig*u[i-1]/p;
341  }
342 
343  sig = (binVector[n-1]-binVector[n-2]) / (binVector[n]-binVector[n-2]);
344  p = sig*secDerivative[n-2] + 2.0;
345  un = (6.0/(binVector[n]-binVector[n-1]))
346  *(endPointDerivative -
347  (dataVector[n]-dataVector[n-1])/(binVector[n]-binVector[n-1])) - u[n-1]/p;
348  secDerivative[n] = un/(secDerivative[n-1] + 2.0);
349 
350  // The back-substitution loop for the triagonal algorithm of solving
351  // a linear system of equations.
352 
353  for(G4int k=n-1; k>0; --k)
354  {
355  secDerivative[k] *=
356  (secDerivative[k+1] -
357  u[k]*(binVector[k+1]-binVector[k-1])/(binVector[k+1]-binVector[k]));
358  }
359  secDerivative[0] = 0.5*(u[0] - secDerivative[1]);
360 
361  delete [] u;
362 }
363 
364 // --------------------------------------------------------------
365 
367  // Computation of second derivatives using "Not-a-knot" endpoint conditions
368  // B.I. Kvasov "Methods of shape-preserving spline approximation"
369  // World Scientific, 2000
370 {
371  if(5 > numberOfNodes) // cannot compute derivatives for less than 4 points
372  {
374  return;
375  }
376 
377  if(!SplinePossible()) { return; }
378 
379  useSpline = true;
380 
381  G4int n = numberOfNodes-1;
382 
383  G4double* u = new G4double [n];
384 
385  G4double p, sig;
386 
387  u[1] = ((dataVector[2]-dataVector[1])/(binVector[2]-binVector[1]) -
388  (dataVector[1]-dataVector[0])/(binVector[1]-binVector[0]));
389  u[1] = 6.0*u[1]*(binVector[2]-binVector[1])
390  / ((binVector[2]-binVector[0])*(binVector[2]-binVector[0]));
391 
392  // Decomposition loop for tridiagonal algorithm. secDerivative[i]
393  // and u[i] are used for temporary storage of the decomposed factors.
394 
395  secDerivative[1] = (2.0*binVector[1]-binVector[0]-binVector[2])
396  / (2.0*binVector[2]-binVector[0]-binVector[1]);
397 
398  for(G4int i=2; i<n-1; ++i)
399  {
400  sig = (binVector[i]-binVector[i-1]) / (binVector[i+1]-binVector[i-1]);
401  p = sig*secDerivative[i-1] + 2.0;
402  secDerivative[i] = (sig - 1.0)/p;
403  u[i] = (dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i])
404  - (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]);
405  u[i] = (6.0*u[i]/(binVector[i+1]-binVector[i-1])) - sig*u[i-1]/p;
406  }
407 
408  sig = (binVector[n-1]-binVector[n-2]) / (binVector[n]-binVector[n-2]);
409  p = sig*secDerivative[n-3] + 2.0;
410  u[n-1] = (dataVector[n]-dataVector[n-1])/(binVector[n]-binVector[n-1])
411  - (dataVector[n-1]-dataVector[n-2])/(binVector[n-1]-binVector[n-2]);
412  u[n-1] = 6.0*sig*u[n-1]/(binVector[n]-binVector[n-2])
413  - (2.0*sig - 1.0)*u[n-2]/p;
414 
415  p = (1.0+sig) + (2.0*sig-1.0)*secDerivative[n-2];
416  secDerivative[n-1] = u[n-1]/p;
417 
418  // The back-substitution loop for the triagonal algorithm of solving
419  // a linear system of equations.
420 
421  for(G4int k=n-2; k>1; --k)
422  {
423  secDerivative[k] *=
424  (secDerivative[k+1] -
425  u[k]*(binVector[k+1]-binVector[k-1])/(binVector[k+1]-binVector[k]));
426  }
427  secDerivative[n] = (secDerivative[n-1] - (1.0-sig)*secDerivative[n-2])/sig;
428  sig = 1.0 - ((binVector[2]-binVector[1])/(binVector[2]-binVector[0]));
429  secDerivative[1] *= (secDerivative[2] - u[1]/(1.0-sig));
430  secDerivative[0] = (secDerivative[1] - sig*secDerivative[2])/(1.0-sig);
431 
432  delete [] u;
433 }
434 
435 // --------------------------------------------------------------
436 
437 void
439  // A simplified method of computation of second derivatives
440 {
441  if(3 > numberOfNodes) // cannot compute derivatives for less than 4 bins
442  {
443  useSpline = false;
444  return;
445  }
446 
447  if(!SplinePossible()) { return; }
448 
449  useSpline = true;
450 
451  size_t n = numberOfNodes-1;
452 
453  for(size_t i=1; i<n; ++i)
454  {
455  secDerivative[i] =
456  3.0*((dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i]) -
457  (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]))
458  /(binVector[i+1]-binVector[i-1]);
459  }
460  secDerivative[n] = secDerivative[n-1];
462 }
463 
464 // --------------------------------------------------------------
465 
467  // Initialise second derivative array. If neighbor energy coincide
468  // or not ordered than spline cannot be applied
469 {
470  G4bool result = true;
471  for(size_t j=1; j<numberOfNodes; ++j)
472  {
473  if(binVector[j] <= binVector[j-1]) {
474  result = false;
475  useSpline = false;
476  secDerivative.clear();
477  break;
478  }
479  }
480  secDerivative.resize(numberOfNodes,0.0);
481  return result;
482 }
483 
484 // --------------------------------------------------------------
485 
486 std::ostream& operator<<(std::ostream& out, const G4PhysicsVector& pv)
487 {
488  // binning
489  out << std::setprecision(12) << pv.edgeMin << " "
490  << pv.edgeMax << " " << pv.numberOfNodes << G4endl;
491 
492  // contents
493  out << pv.dataVector.size() << G4endl;
494  for(size_t i = 0; i < pv.dataVector.size(); i++)
495  {
496  out << pv.binVector[i] << " " << pv.dataVector[i] << G4endl;
497  }
498  out << std::setprecision(6);
499 
500  return out;
501 }
502 
503 //---------------------------------------------------------------
504 
505 G4double G4PhysicsVector::Value(G4double theEnergy, size_t& lastIdx) const
506 {
507  G4double y;
508  if(theEnergy <= edgeMin) {
509  lastIdx = 0;
510  y = dataVector[0];
511  } else if(theEnergy >= edgeMax) {
512  lastIdx = numberOfNodes-1;
513  y = dataVector[lastIdx];
514  } else {
515  lastIdx = FindBin(theEnergy, lastIdx);
516  y = Interpolation(lastIdx, theEnergy);
517  }
518  return y;
519 }
520 
521 //---------------------------------------------------------------
522 
524 {
525  if(1 >= numberOfNodes) { return 0.0; }
526  size_t n1 = 0;
527  size_t n2 = numberOfNodes/2;
528  size_t n3 = numberOfNodes - 1;
529  G4double y = rand*dataVector[n3];
530  while (n1 + 1 != n3)
531  {
532  if (y > dataVector[n2])
533  { n1 = n2; }
534  else
535  { n3 = n2; }
536  n2 = (n3 + n1 + 1)/2;
537  }
538  G4double res = binVector[n1];
539  G4double del = dataVector[n3] - dataVector[n1];
540  if(del > 0.0) {
541  res += (y - dataVector[n1])*(binVector[n3] - res)/del;
542  }
543  return res;
544 }
545 
546 //---------------------------------------------------------------
G4PVDataVector dataVector
G4double FindLinearEnergy(G4double rand) const
G4double Interpolation(size_t idx, G4double energy) const
void CopyData(const G4PhysicsVector &vec)
G4PhysicsVector(G4bool spline=false)
void ComputeSecondDerivatives(G4double firstPointDerivative, G4double endPointDerivative)
G4double GetLowEdgeEnergy(size_t binNumber) const
int G4int
Definition: G4Types.hh:78
void FillSecondDerivatives()
G4PVDataVector binVector
G4int operator!=(const G4PhysicsVector &right) const
std::ostream & operator<<(std::ostream &out, const G4PhysicsVector &pv)
G4int operator==(const G4PhysicsVector &right) const
bool G4bool
Definition: G4Types.hh:79
G4PhysicsVectorType type
G4PVDataVector secDerivative
virtual void ScaleVector(G4double factorE, G4double factorV)
size_t FindBin(G4double energy, size_t idx) const
const G4int n
G4double Value(G4double theEnergy, size_t &lastidx) const
virtual G4bool Store(std::ofstream &fOut, G4bool ascii=false)
virtual G4bool Retrieve(std::ifstream &fIn, G4bool ascii=false)
#define G4endl
Definition: G4ios.hh:61
double G4double
Definition: G4Types.hh:76
void ComputeSecDerivatives()
virtual ~G4PhysicsVector()
G4PhysicsVector & operator=(const G4PhysicsVector &)
G4GLOB_DLL std::ostream G4cerr