source: trunk/source/global/management/src/G4PhysicsVector.cc @ 1347

Last change on this file since 1347 was 1340, checked in by garnier, 14 years ago

update ti head

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