Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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$
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 "G4PhysicsVector.hh"
57 #include <iomanip>
58 
60 
61 // --------------------------------------------------------------
62 
64  : type(T_G4PhysicsVector),
65  edgeMin(0.), edgeMax(0.), numberOfNodes(0),
66  useSpline(spline),
67  dBin(0.), baseBin(0.),
68  verboseLevel(0)
69 {
71 }
72 
73 // --------------------------------------------------------------
74 
76 {
77  delete cache; cache =0;
78 }
79 
80 // --------------------------------------------------------------
81 
83 {
85  dBin = right.dBin;
86  baseBin = right.baseBin;
87  verboseLevel = right.verboseLevel;
88 
89  DeleteData();
90  CopyData(right);
91 }
92 
93 // --------------------------------------------------------------
94 
96 {
97  if (&right==this) { return *this; }
98  dBin = right.dBin;
99  baseBin = right.baseBin;
100  verboseLevel = right.verboseLevel;
101 
102  DeleteData();
103  CopyData(right);
104  return *this;
105 }
106 
107 // --------------------------------------------------------------
108 
110 {
111  return (this == &right);
112 }
113 
114 // --------------------------------------------------------------
115 
117 {
118  return (this != &right);
119 }
120 
121 // --------------------------------------------------------------
122 
124 {
125  secDerivative.clear();
126 }
127 
128 // --------------------------------------------------------------
129 
131 {
132  type = vec.type;
133  edgeMin = vec.edgeMin;
134  edgeMax = vec.edgeMax;
136  cache->lastEnergy = vec.GetLastEnergy();
137  cache->lastValue = vec.GetLastValue();
138  cache->lastBin = vec.GetLastBin();
139  useSpline = vec.useSpline;
140 
141  size_t i;
142  dataVector.clear();
143  for(i=0; i<(vec.dataVector).size(); i++){
144  dataVector.push_back( (vec.dataVector)[i] );
145  }
146  binVector.clear();
147  for(i=0; i<(vec.binVector).size(); i++){
148  binVector.push_back( (vec.binVector)[i] );
149  }
150  secDerivative.clear();
151  for(i=0; i<(vec.secDerivative).size(); i++){
152  secDerivative.push_back( (vec.secDerivative)[i] );
153  }
154 }
155 
156 // --------------------------------------------------------------
157 
159 {
160  return binVector[binNumber];
161 }
162 
163 // --------------------------------------------------------------
164 
165 G4bool G4PhysicsVector::Store(std::ofstream& fOut, G4bool ascii)
166 {
167  // Ascii mode
168  if (ascii)
169  {
170  fOut << *this;
171  return true;
172  }
173  // Binary Mode
174 
175  // binning
176  fOut.write((char*)(&edgeMin), sizeof edgeMin);
177  fOut.write((char*)(&edgeMax), sizeof edgeMax);
178  fOut.write((char*)(&numberOfNodes), sizeof numberOfNodes);
179 
180  // contents
181  size_t size = dataVector.size();
182  fOut.write((char*)(&size), sizeof size);
183 
184  G4double* value = new G4double[2*size];
185  for(size_t i = 0; i < size; ++i)
186  {
187  value[2*i] = binVector[i];
188  value[2*i+1]= dataVector[i];
189  }
190  fOut.write((char*)(value), 2*size*(sizeof (G4double)));
191  delete [] value;
192 
193  return true;
194 }
195 
196 // --------------------------------------------------------------
197 
198 G4bool G4PhysicsVector::Retrieve(std::ifstream& fIn, G4bool ascii)
199 {
200  // clear properties;
202  cache->lastValue =0.;
203  cache->lastBin =0;
204  dataVector.clear();
205  binVector.clear();
206  secDerivative.clear();
207 
208  // retrieve in ascii mode
209  if (ascii){
210  // binning
211  fIn >> edgeMin >> edgeMax >> numberOfNodes;
212  if (fIn.fail()) { return false; }
213  // contents
214  G4int siz=0;
215  fIn >> siz;
216  if (fIn.fail()) { return false; }
217  if (siz<=0)
218  {
219 #ifdef G4VERBOSE
220  G4cerr << "G4PhysicsVector::Retrieve():";
221  G4cerr << " Invalid vector size: " << siz << G4endl;
222 #endif
223  return false;
224  }
225 
226  binVector.reserve(siz);
227  dataVector.reserve(siz);
228  G4double vBin, vData;
229 
230  for(G4int i = 0; i < siz ; i++)
231  {
232  vBin = 0.;
233  vData= 0.;
234  fIn >> vBin >> vData;
235  if (fIn.fail()) { return false; }
236  binVector.push_back(vBin);
237  dataVector.push_back(vData);
238  }
239 
240  // to remove any inconsistency
241  numberOfNodes = siz;
242  edgeMin = binVector[0];
243  edgeMax = binVector[numberOfNodes-1];
244  return true ;
245  }
246 
247  // retrieve in binary mode
248  // binning
249  fIn.read((char*)(&edgeMin), sizeof edgeMin);
250  fIn.read((char*)(&edgeMax), sizeof edgeMax);
251  fIn.read((char*)(&numberOfNodes), sizeof numberOfNodes );
252 
253  // contents
254  size_t size;
255  fIn.read((char*)(&size), sizeof size);
256 
257  G4double* value = new G4double[2*size];
258  fIn.read((char*)(value), 2*size*(sizeof(G4double)) );
259  if (G4int(fIn.gcount()) != G4int(2*size*(sizeof(G4double))) )
260  {
261  delete [] value;
262  return false;
263  }
264 
265  binVector.reserve(size);
266  dataVector.reserve(size);
267  for(size_t i = 0; i < size; ++i)
268  {
269  binVector.push_back(value[2*i]);
270  dataVector.push_back(value[2*i+1]);
271  }
272  delete [] value;
273 
274  // to remove any inconsistency
275  numberOfNodes = size;
276  edgeMin = binVector[0];
278 
279  return true;
280 }
281 
282 // --------------------------------------------------------------
283 
284 void
286 {
287  size_t n = dataVector.size();
288  size_t i;
289  if(n > 0) {
290  for(i=0; i<n; ++i) {
291  binVector[i] *= factorE;
292  dataVector[i] *= factorV;
293  }
294  }
295  // n = secDerivative.size();
296  // if(n > 0) { for(i=0; i<n; ++i) { secDerivative[i] *= factorV; } }
297  secDerivative.clear();
298 
299  edgeMin *= factorE;
300  edgeMax *= factorE;
301  cache->lastEnergy = factorE*(cache->lastEnergy);
302  cache->lastValue = factorV*(cache->lastValue);
303 }
304 
305 // --------------------------------------------------------------
306 
307 void
309  G4double endPointDerivative)
310  // A standard method of computation of second derivatives
311  // First derivatives at the first and the last point should be provided
312  // See for example W.H. Press et al. "Numerical recipes in C"
313  // Cambridge University Press, 1997.
314 {
315  if(4 > numberOfNodes) // cannot compute derivatives for less than 4 bins
316  {
318  return;
319  }
320 
321  if(!SplinePossible()) { return; }
322 
323  G4int n = numberOfNodes-1;
324 
325  G4double* u = new G4double [n];
326 
327  G4double p, sig, un;
328 
329  u[0] = (6.0/(binVector[1]-binVector[0]))
330  * ((dataVector[1]-dataVector[0])/(binVector[1]-binVector[0])
331  - firstPointDerivative);
332 
333  secDerivative[0] = - 0.5;
334 
335  // Decomposition loop for tridiagonal algorithm. secDerivative[i]
336  // and u[i] are used for temporary storage of the decomposed factors.
337 
338  for(G4int i=1; i<n; ++i)
339  {
340  sig = (binVector[i]-binVector[i-1]) / (binVector[i+1]-binVector[i-1]);
341  p = sig*(secDerivative[i-1]) + 2.0;
342  secDerivative[i] = (sig - 1.0)/p;
343  u[i] = (dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i])
344  - (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]);
345  u[i] = 6.0*u[i]/(binVector[i+1]-binVector[i-1]) - sig*u[i-1]/p;
346  }
347 
348  sig = (binVector[n-1]-binVector[n-2]) / (binVector[n]-binVector[n-2]);
349  p = sig*secDerivative[n-2] + 2.0;
350  un = (6.0/(binVector[n]-binVector[n-1]))
351  *(endPointDerivative -
352  (dataVector[n]-dataVector[n-1])/(binVector[n]-binVector[n-1])) - u[n-1]/p;
353  secDerivative[n] = un/(secDerivative[n-1] + 2.0);
354 
355  // The back-substitution loop for the triagonal algorithm of solving
356  // a linear system of equations.
357 
358  for(G4int k=n-1; k>0; --k)
359  {
360  secDerivative[k] *=
361  (secDerivative[k+1] -
362  u[k]*(binVector[k+1]-binVector[k-1])/(binVector[k+1]-binVector[k]));
363  }
364  secDerivative[0] = 0.5*(u[0] - secDerivative[1]);
365 
366  delete [] u;
367 }
368 
369 // --------------------------------------------------------------
370 
372  // Computation of second derivatives using "Not-a-knot" endpoint conditions
373  // B.I. Kvasov "Methods of shape-preserving spline approximation"
374  // World Scientific, 2000
375 {
376  if(5 > numberOfNodes) // cannot compute derivatives for less than 4 points
377  {
379  return;
380  }
381 
382  if(!SplinePossible()) { return; }
383 
384  G4int n = numberOfNodes-1;
385 
386  G4double* u = new G4double [n];
387 
388  G4double p, sig;
389 
390  u[1] = ((dataVector[2]-dataVector[1])/(binVector[2]-binVector[1]) -
391  (dataVector[1]-dataVector[0])/(binVector[1]-binVector[0]));
392  u[1] = 6.0*u[1]*(binVector[2]-binVector[1])
393  / ((binVector[2]-binVector[0])*(binVector[2]-binVector[0]));
394 
395  // Decomposition loop for tridiagonal algorithm. secDerivative[i]
396  // and u[i] are used for temporary storage of the decomposed factors.
397 
398  secDerivative[1] = (2.0*binVector[1]-binVector[0]-binVector[2])
399  / (2.0*binVector[2]-binVector[0]-binVector[1]);
400 
401  for(G4int i=2; i<n-1; ++i)
402  {
403  sig = (binVector[i]-binVector[i-1]) / (binVector[i+1]-binVector[i-1]);
404  p = sig*secDerivative[i-1] + 2.0;
405  secDerivative[i] = (sig - 1.0)/p;
406  u[i] = (dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i])
407  - (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]);
408  u[i] = (6.0*u[i]/(binVector[i+1]-binVector[i-1])) - sig*u[i-1]/p;
409  }
410 
411  sig = (binVector[n-1]-binVector[n-2]) / (binVector[n]-binVector[n-2]);
412  p = sig*secDerivative[n-3] + 2.0;
413  u[n-1] = (dataVector[n]-dataVector[n-1])/(binVector[n]-binVector[n-1])
414  - (dataVector[n-1]-dataVector[n-2])/(binVector[n-1]-binVector[n-2]);
415  u[n-1] = 6.0*sig*u[n-1]/(binVector[n]-binVector[n-2])
416  - (2.0*sig - 1.0)*u[n-2]/p;
417 
418  p = (1.0+sig) + (2.0*sig-1.0)*secDerivative[n-2];
419  secDerivative[n-1] = u[n-1]/p;
420 
421  // The back-substitution loop for the triagonal algorithm of solving
422  // a linear system of equations.
423 
424  for(G4int k=n-2; k>1; --k)
425  {
426  secDerivative[k] *=
427  (secDerivative[k+1] -
428  u[k]*(binVector[k+1]-binVector[k-1])/(binVector[k+1]-binVector[k]));
429  }
430  secDerivative[n] = (secDerivative[n-1] - (1.0-sig)*secDerivative[n-2])/sig;
431  sig = 1.0 - ((binVector[2]-binVector[1])/(binVector[2]-binVector[0]));
432  secDerivative[1] *= (secDerivative[2] - u[1]/(1.0-sig));
433  secDerivative[0] = (secDerivative[1] - sig*secDerivative[2])/(1.0-sig);
434 
435  delete [] u;
436 }
437 
438 // --------------------------------------------------------------
439 
440 void
442  // A simplified method of computation of second derivatives
443 {
444  if(!SplinePossible()) { return; }
445 
446  if(3 > numberOfNodes) // cannot compute derivatives for less than 4 bins
447  {
448  useSpline = false;
449  return;
450  }
451 
452  size_t n = numberOfNodes-1;
453 
454  for(size_t i=1; i<n; ++i)
455  {
456  secDerivative[i] =
457  3.0*((dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i]) -
458  (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]))
459  /(binVector[i+1]-binVector[i-1]);
460  }
461  secDerivative[n] = secDerivative[n-1];
463 }
464 
465 // --------------------------------------------------------------
466 
467 G4bool G4PhysicsVector::SplinePossible()
468  // Initialise second derivative array. If neighbor energy coincide
469  // or not ordered than spline cannot be applied
470 {
471  secDerivative.clear();
472  if(!useSpline) { return useSpline; }
473  secDerivative.reserve(numberOfNodes);
474  for(size_t j=0; j<numberOfNodes; ++j)
475  {
476  secDerivative.push_back(0.0);
477  if(j > 0)
478  {
479  if(binVector[j]-binVector[j-1] <= 0.) { useSpline = false; }
480  }
481  }
482  return useSpline;
483 }
484 
485 // --------------------------------------------------------------
486 
487 std::ostream& operator<<(std::ostream& out, const G4PhysicsVector& pv)
488 {
489  // binning
490  out << std::setprecision(12) << pv.edgeMin << " "
491  << pv.edgeMax << " " << pv.numberOfNodes << G4endl;
492 
493  // contents
494  out << pv.dataVector.size() << G4endl;
495  for(size_t i = 0; i < pv.dataVector.size(); i++)
496  {
497  out << pv.binVector[i] << " " << pv.dataVector[i] << G4endl;
498  }
499  out << std::setprecision(6);
500 
501  return out;
502 }
503 
504 //---------------------------------------------------------------
505 
506 void G4PhysicsVector::ComputeValue(G4double theEnergy)
507 {
508  // Use cache for speed up - check if the value 'theEnergy' lies
509  // between the last energy and low edge of of the
510  // bin of last call, then the last bin location is used.
511 
512  if( theEnergy < cache->lastEnergy
513  && theEnergy >= binVector[cache->lastBin]) {
514  cache->lastEnergy = theEnergy;
515  Interpolation(cache->lastBin);
516 
517  } else if( theEnergy <= edgeMin ) {
518  cache->lastBin = 0;
520  cache->lastValue = dataVector[0];
521 
522  } else if( theEnergy >= edgeMax ) {
523  cache->lastBin = numberOfNodes-1;
526 
527  } else {
528  cache->lastBin = FindBinLocation(theEnergy);
529  cache->lastEnergy = theEnergy;
530  Interpolation(cache->lastBin);
531  }
532 }
533