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

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

update geant4-09-04-beta-cand-01 interfaces-V09-03-09 vis-V09-03-08

File size: 15.5 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.46 2010/05/28 05:13:43 kurasige Exp $
28// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
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    size_t size=0;
208    fIn >> size;
209    if (fIn.fail())  { return false; }
210
211    binVector.reserve(size);
212    dataVector.reserve(size);
213    G4double vBin, vData;
214
215    for(size_t i = 0; i < size ; i++)
216    {
217      vBin = 0.;
218      vData= 0.;
219      fIn >> vBin >> vData;
220      if (fIn.fail())  { return false; }
221      binVector.push_back(vBin);
222      dataVector.push_back(vData);
223    }
224    return true ;
225  }
226
227  // retrieve in binary mode
228  // binning
229  fIn.read((char*)(&edgeMin), sizeof edgeMin);
230  fIn.read((char*)(&edgeMax), sizeof edgeMax);
231  fIn.read((char*)(&numberOfNodes), sizeof numberOfNodes ); 
232 
233  // contents
234  size_t size;
235  fIn.read((char*)(&size), sizeof size); 
236 
237  G4double* value = new G4double[2*size];
238  fIn.read((char*)(value),  2*size*(sizeof(G4double)) );
239  if (G4int(fIn.gcount()) != G4int(2*size*(sizeof(G4double))) )
240  {
241    delete [] value;
242    return false;
243  }
244
245  binVector.reserve(size);
246  dataVector.reserve(size);
247  for(size_t i = 0; i < size; ++i)
248  {
249    binVector.push_back(value[2*i]);
250    dataVector.push_back(value[2*i+1]);
251  }
252  delete [] value;
253  return true;
254}
255
256// --------------------------------------------------------------
257
258void 
259G4PhysicsVector::ScaleVector(G4double factorE, G4double factorV)
260{
261  size_t n = dataVector.size();
262  size_t i;
263  if(n > 0) { 
264    for(i=0; i<n; ++i) {
265      binVector[i]  *= factorE;
266      dataVector[i] *= factorV;
267    } 
268  }
269  n = secDerivative.size();
270  if(n > 0) { for(i=0; i<n; ++i) { secDerivative[i] *= factorV; } }
271
272  edgeMin *= factorE;
273  edgeMax *= factorE;
274  cache->lastEnergy = factorE*(cache->lastEnergy);
275  cache->lastValue  = factorV*(cache->lastValue);
276}
277
278// --------------------------------------------------------------
279
280void 
281G4PhysicsVector::ComputeSecondDerivatives(G4double firstPointDerivative, 
282                                          G4double endPointDerivative)
283  //  A standard method of computation of second derivatives
284  //  First derivatives at the first and the last point should be provided
285  //  See for example W.H. Press et al. "Numerical reciptes and C"
286  //  Cambridge University Press, 1997.
287{
288  if(4 > numberOfNodes)   // cannot compute derivatives for less than 4 bins
289  {
290    ComputeSecDerivatives();
291    return;
292  }
293
294  if(!SplinePossible()) { return; }
295
296  G4int n = numberOfNodes-1;
297
298  G4double* u = new G4double [n];
299 
300  G4double p, sig, un;
301
302  u[0] = (6.0/(binVector[1]-binVector[0]))
303    * ((dataVector[1]-dataVector[0])/(binVector[1]-binVector[0])
304       - firstPointDerivative);
305 
306  secDerivative[0] = - 0.5;
307
308  // Decomposition loop for tridiagonal algorithm. secDerivative[i]
309  // and u[i] are used for temporary storage of the decomposed factors.
310
311  for(G4int i=1; i<n; ++i)
312  {
313    sig = (binVector[i]-binVector[i-1]) / (binVector[i+1]-binVector[i-1]);
314    p = sig*(secDerivative[i-1]) + 2.0;
315    secDerivative[i] = (sig - 1.0)/p;
316    u[i] = (dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i])
317         - (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]);
318    u[i] = 6.0*u[i]/(binVector[i+1]-binVector[i-1]) - sig*u[i-1]/p;
319  }
320
321  sig = (binVector[n-1]-binVector[n-2]) / (binVector[n]-binVector[n-2]);
322  p = sig*secDerivative[n-2] + 2.0;
323  un = (6.0/(binVector[n]-binVector[n-1]))
324    *(endPointDerivative - 
325      (dataVector[n]-dataVector[n-1])/(binVector[n]-binVector[n-1])) - u[n-1]/p;
326  secDerivative[n] = un/(secDerivative[n-1] + 2.0);
327
328  // The back-substitution loop for the triagonal algorithm of solving
329  // a linear system of equations.
330   
331  for(G4int k=n-1; k>0; --k)
332  {
333    secDerivative[k] *= 
334      (secDerivative[k+1] - 
335       u[k]*(binVector[k+1]-binVector[k-1])/(binVector[k+1]-binVector[k]));
336  }
337  secDerivative[0] = 0.5*(u[0] - secDerivative[1]);
338
339  delete [] u;
340}
341
342// --------------------------------------------------------------
343
344void G4PhysicsVector::FillSecondDerivatives()
345  // Computation of second derivatives using "Not-a-knot" endpoint conditions
346  // B.I. Kvasov "Methods of shape-preserving spline approximation"
347  // World Scientific, 2000
348{ 
349  if(5 > numberOfNodes)  // cannot compute derivatives for less than 4 points
350  {
351    ComputeSecDerivatives();
352    return;
353  }
354
355  if(!SplinePossible()) { return; }
356 
357  G4int n = numberOfNodes-1;
358
359  //G4cout << "G4PhysicsVector::FillSecondDerivatives() n= " << n << G4endl;
360  // G4cout << *this << G4endl;
361
362  G4double* u = new G4double [n];
363 
364  G4double p, sig;
365
366  u[1] = ((dataVector[2]-dataVector[1])/(binVector[2]-binVector[1]) -
367          (dataVector[1]-dataVector[0])/(binVector[1]-binVector[0]));
368  u[1] = 6.0*u[1]*(binVector[2]-binVector[1])
369    / ((binVector[2]-binVector[0])*(binVector[2]-binVector[0]));
370 
371  // Decomposition loop for tridiagonal algorithm. secDerivative[i]
372  // and u[i] are used for temporary storage of the decomposed factors.
373
374  secDerivative[1] = (2.0*binVector[1]-binVector[0]-binVector[2])
375    / (2.0*binVector[2]-binVector[0]-binVector[1]);
376
377  for(G4int i=2; i<n-1; ++i)
378  {
379    sig = (binVector[i]-binVector[i-1]) / (binVector[i+1]-binVector[i-1]);
380    p = sig*secDerivative[i-1] + 2.0;
381    secDerivative[i] = (sig - 1.0)/p;
382    u[i] = (dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i])
383         - (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]);
384    u[i] = (6.0*u[i]/(binVector[i+1]-binVector[i-1])) - sig*u[i-1]/p;
385  }
386
387  sig = (binVector[n-1]-binVector[n-2]) / (binVector[n]-binVector[n-2]);
388  p = sig*secDerivative[n-3] + 2.0;
389  u[n-1] = (dataVector[n]-dataVector[n-1])/(binVector[n]-binVector[n-1])
390    - (dataVector[n-1]-dataVector[n-2])/(binVector[n-1]-binVector[n-2]);
391  u[n-1] = 6.0*sig*u[n-1]/(binVector[n]-binVector[n-2])
392    - (2.0*sig - 1.0)*u[n-2]/p; 
393
394  p = (1.0+sig) + (2.0*sig-1.0)*secDerivative[n-2];
395  secDerivative[n-1] = u[n-1]/p;
396
397  // The back-substitution loop for the triagonal algorithm of solving
398  // a linear system of equations.
399   
400  for(G4int k=n-2; k>1; --k)
401  {
402    secDerivative[k] *= 
403      (secDerivative[k+1] - 
404       u[k]*(binVector[k+1]-binVector[k-1])/(binVector[k+1]-binVector[k]));
405  }
406  secDerivative[n] = (secDerivative[n-1] - (1.0-sig)*secDerivative[n-2])/sig;
407  sig = 1.0 - ((binVector[2]-binVector[1])/(binVector[2]-binVector[0]));
408  secDerivative[1] *= (secDerivative[2] - u[1]/(1.0-sig));
409  secDerivative[0]  = (secDerivative[1] - sig*secDerivative[2])/(1.0-sig);
410
411  delete [] u;
412}
413
414// --------------------------------------------------------------
415
416void 
417G4PhysicsVector::ComputeSecDerivatives()
418  //  A simplified method of computation of second derivatives
419{
420  if(!SplinePossible())  { return; }
421
422  if(3 > numberOfNodes)  // cannot compute derivatives for less than 4 bins
423  {
424    useSpline = false;
425    return;
426  }
427
428  size_t n = numberOfNodes-1;
429
430  for(size_t i=1; i<n; ++i)
431  {
432    secDerivative[i] =
433      3.0*((dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i]) -
434           (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]))
435      /(binVector[i+1]-binVector[i-1]);
436  }
437  secDerivative[n] = secDerivative[n-1];
438  secDerivative[0] = secDerivative[1];
439}
440
441// --------------------------------------------------------------
442
443G4bool G4PhysicsVector::SplinePossible()
444  // Initialise second derivative array. If neighbor energy coincide
445  // or not ordered than spline cannot be applied
446{
447  if(!useSpline) return useSpline;
448  secDerivative.clear();
449  secDerivative.reserve(numberOfNodes);
450  for(size_t j=0; j<numberOfNodes; ++j)
451  {
452    secDerivative.push_back(0.0);
453    if(j > 0)
454    {
455      if(binVector[j]-binVector[j-1] <= 0.)  { useSpline = false; }
456    }
457  } 
458  return useSpline;
459}
460   
461// --------------------------------------------------------------
462
463std::ostream& operator<<(std::ostream& out, const G4PhysicsVector& pv)
464{
465  // binning
466  out << std::setprecision(12) << pv.edgeMin;
467  out <<" " << pv.edgeMax <<" "  << pv.numberOfNodes << G4endl; 
468
469  // contents
470  out << pv.dataVector.size() << G4endl; 
471  for(size_t i = 0; i < pv.dataVector.size(); i++)
472  {
473    out << std::setprecision(12) << pv.binVector[i] << "  "
474        << pv.dataVector[i] << G4endl;
475  }
476  return out;
477}
478
479//---------------------------------------------------------------
480
481G4double G4PhysicsVector::Value(G4double theEnergy) 
482{
483  // Use cache for speed up - check if the value 'theEnergy' is same as the
484  // last call. If it is same, then use the last bin location. Also the
485  // value 'theEnergy' lies between the last energy and low edge of of the
486  // bin of last call, then the last bin location is used.
487
488  if( theEnergy == cache->lastEnergy ) {
489
490  } else if( theEnergy < cache->lastEnergy
491        &&   theEnergy >= binVector[cache->lastBin]) {
492     cache->lastEnergy = theEnergy;
493     Interpolation(cache->lastBin);
494
495  } else if( theEnergy <= edgeMin ) {
496     cache->lastBin = 0;
497     cache->lastEnergy = edgeMin;
498     cache->lastValue  = dataVector[0];
499
500  } else if( theEnergy >= edgeMax ){
501     cache->lastBin = numberOfNodes-1;
502     cache->lastEnergy = edgeMax;
503     cache->lastValue  = dataVector[cache->lastBin];
504
505  } else {
506     cache->lastBin = FindBinLocation(theEnergy); 
507     cache->lastEnergy = theEnergy;
508     Interpolation(cache->lastBin);
509  }
510  return cache->lastValue;       
511}
512
Note: See TracBrowser for help on using the repository browser.