Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4PhysicsVector class implementation << 27 // 26 // 28 // Authors: << 27 // $Id: G4PhysicsVector.cc 74256 2013-10-02 14:24:02Z gcosmo $ 29 // - 02 Dec. 1995, G.Cosmo: Structure created << 28 // 30 // - 03 Mar. 1996, K.Amako: Implemented the 1s << 29 // 31 // Revisions: << 30 // -------------------------------------------------------------- 32 // - 11 Nov. 2000, H.Kurashige: Use STL vector << 31 // GEANT 4 class implementation file 33 // ------------------------------------------- << 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 // -------------------------------------------------------------- 34 55 35 #include "G4PhysicsVector.hh" << 36 #include <iomanip> 56 #include <iomanip> >> 57 #include "G4PhysicsVector.hh" >> 58 >> 59 G4ThreadLocal G4Allocator<G4PhysicsVector> *fpPVAllocator = 0; 37 60 38 // ------------------------------------------- 61 // -------------------------------------------------------------- 39 G4PhysicsVector::G4PhysicsVector(G4bool val) << 40 : useSpline(val) << 41 {} << 42 62 43 // ------------------------------------------- << 63 G4PhysicsVector::G4PhysicsVector(G4bool) 44 void G4PhysicsVector::Initialise() << 64 : type(T_G4PhysicsVector), >> 65 edgeMin(0.), edgeMax(0.), numberOfNodes(0), >> 66 useSpline(false), >> 67 dBin(0.), baseBin(0.), >> 68 verboseLevel(0) 45 { 69 { 46 if (1 < numberOfNodes) << 70 if (!fpPVAllocator) fpPVAllocator = new G4Allocator<G4PhysicsVector>; 47 { << 71 // g4pow = G4Pow::GetInstance(); 48 idxmax = numberOfNodes - 2; << 72 } 49 edgeMin = binVector[0]; << 73 50 edgeMax = binVector[idxmax + 1]; << 74 // -------------------------------------------------------------- >> 75 >> 76 G4PhysicsVector::~G4PhysicsVector() >> 77 { >> 78 } >> 79 >> 80 // -------------------------------------------------------------- >> 81 >> 82 G4PhysicsVector::G4PhysicsVector(const G4PhysicsVector& right) >> 83 { >> 84 // g4pow = G4Pow::GetInstance(); >> 85 >> 86 dBin = right.dBin; >> 87 baseBin = right.baseBin; >> 88 verboseLevel = right.verboseLevel; >> 89 >> 90 DeleteData(); >> 91 CopyData(right); >> 92 } >> 93 >> 94 // -------------------------------------------------------------- >> 95 >> 96 G4PhysicsVector& G4PhysicsVector::operator=(const G4PhysicsVector& right) >> 97 { >> 98 if (&right==this) { return *this; } >> 99 dBin = right.dBin; >> 100 baseBin = right.baseBin; >> 101 verboseLevel = right.verboseLevel; >> 102 >> 103 DeleteData(); >> 104 CopyData(right); >> 105 return *this; >> 106 } >> 107 >> 108 // -------------------------------------------------------------- >> 109 >> 110 G4int G4PhysicsVector::operator==(const G4PhysicsVector &right) const >> 111 { >> 112 return (this == &right); >> 113 } >> 114 >> 115 // -------------------------------------------------------------- >> 116 >> 117 G4int G4PhysicsVector::operator!=(const G4PhysicsVector &right) const >> 118 { >> 119 return (this != &right); >> 120 } >> 121 >> 122 // -------------------------------------------------------------- >> 123 >> 124 void G4PhysicsVector::DeleteData() >> 125 { >> 126 useSpline = false; >> 127 secDerivative.clear(); >> 128 } >> 129 >> 130 // -------------------------------------------------------------- >> 131 >> 132 void G4PhysicsVector::CopyData(const G4PhysicsVector& vec) >> 133 { >> 134 type = vec.type; >> 135 edgeMin = vec.edgeMin; >> 136 edgeMax = vec.edgeMax; >> 137 numberOfNodes = vec.numberOfNodes; >> 138 useSpline = vec.useSpline; >> 139 >> 140 size_t i; >> 141 dataVector.clear(); >> 142 for(i=0; i<(vec.dataVector).size(); i++){ >> 143 dataVector.push_back( (vec.dataVector)[i] ); >> 144 } >> 145 binVector.clear(); >> 146 for(i=0; i<(vec.binVector).size(); i++){ >> 147 binVector.push_back( (vec.binVector)[i] ); >> 148 } >> 149 secDerivative.clear(); >> 150 for(i=0; i<(vec.secDerivative).size(); i++){ >> 151 secDerivative.push_back( (vec.secDerivative)[i] ); 51 } 152 } 52 } 153 } 53 154 54 // ------------------------------------------- 155 // -------------------------------------------------------------- 55 G4bool G4PhysicsVector::Store(std::ofstream& f << 156 >> 157 G4double G4PhysicsVector::GetLowEdgeEnergy(size_t binNumber) const >> 158 { >> 159 return binVector[binNumber]; >> 160 } >> 161 >> 162 // -------------------------------------------------------------- >> 163 >> 164 G4bool G4PhysicsVector::Store(std::ofstream& fOut, G4bool ascii) 56 { 165 { 57 // Ascii mode 166 // Ascii mode 58 if (ascii) 167 if (ascii) 59 { 168 { 60 fOut << *this; 169 fOut << *this; 61 return true; 170 return true; 62 } << 171 } 63 // Binary Mode 172 // Binary Mode 64 173 65 // binning 174 // binning 66 fOut.write((char*) (&edgeMin), sizeof edgeMi << 175 fOut.write((char*)(&edgeMin), sizeof edgeMin); 67 fOut.write((char*) (&edgeMax), sizeof edgeMa << 176 fOut.write((char*)(&edgeMax), sizeof edgeMax); 68 fOut.write((char*) (&numberOfNodes), sizeof << 177 fOut.write((char*)(&numberOfNodes), sizeof numberOfNodes); 69 178 70 // contents 179 // contents 71 std::size_t size = dataVector.size(); << 180 size_t size = dataVector.size(); 72 fOut.write((char*) (&size), sizeof size); << 181 fOut.write((char*)(&size), sizeof size); 73 182 74 auto value = new G4double[2 * size]; << 183 G4double* value = new G4double[2*size]; 75 for (std::size_t i = 0; i < size; ++i) << 184 for(size_t i = 0; i < size; ++i) 76 { 185 { 77 value[2 * i] = binVector[i]; << 186 value[2*i] = binVector[i]; 78 value[2 * i + 1] = dataVector[i]; << 187 value[2*i+1]= dataVector[i]; 79 } 188 } 80 fOut.write((char*) (value), 2 * size * (size << 189 fOut.write((char*)(value), 2*size*(sizeof (G4double))); 81 delete[] value; << 190 delete [] value; 82 191 83 return true; 192 return true; 84 } 193 } 85 194 86 // ------------------------------------------- 195 // -------------------------------------------------------------- >> 196 87 G4bool G4PhysicsVector::Retrieve(std::ifstream 197 G4bool G4PhysicsVector::Retrieve(std::ifstream& fIn, G4bool ascii) 88 { 198 { 89 // clear properties; 199 // clear properties; 90 dataVector.clear(); 200 dataVector.clear(); 91 binVector.clear(); 201 binVector.clear(); 92 secDerivative.clear(); 202 secDerivative.clear(); 93 203 94 // retrieve in ascii mode 204 // retrieve in ascii mode 95 if (ascii) << 205 if (ascii){ 96 { << 97 // binning 206 // binning 98 fIn >> edgeMin >> edgeMax >> numberOfNodes << 207 fIn >> edgeMin >> edgeMax >> numberOfNodes; 99 if (fIn.fail() || numberOfNodes < 2) << 208 if (fIn.fail()) { return false; } 100 { << 101 return false; << 102 } << 103 // contents 209 // contents 104 G4int siz0 = 0; << 210 G4int siz=0; 105 fIn >> siz0; << 211 fIn >> siz; 106 if (siz0 < 2) { return false; } << 212 if (fIn.fail()) { return false; } 107 auto siz = static_cast<std::size_t>(siz0); << 213 if (siz<=0) 108 if (fIn.fail() || siz != numberOfNodes) << 109 { 214 { >> 215 #ifdef G4VERBOSE >> 216 G4cerr << "G4PhysicsVector::Retrieve():"; >> 217 G4cerr << " Invalid vector size: " << siz << G4endl; >> 218 #endif 110 return false; 219 return false; 111 } 220 } 112 221 113 binVector.reserve(siz); 222 binVector.reserve(siz); 114 dataVector.reserve(siz); 223 dataVector.reserve(siz); 115 G4double vBin, vData; 224 G4double vBin, vData; 116 225 117 for (std::size_t i = 0; i < siz; ++i) << 226 for(G4int i = 0; i < siz ; i++) 118 { 227 { 119 vBin = 0.; << 228 vBin = 0.; 120 vData = 0.; << 229 vData= 0.; 121 fIn >> vBin >> vData; 230 fIn >> vBin >> vData; 122 if (fIn.fail()) << 231 if (fIn.fail()) { return false; } 123 { << 124 return false; << 125 } << 126 binVector.push_back(vBin); 232 binVector.push_back(vBin); 127 dataVector.push_back(vData); 233 dataVector.push_back(vData); 128 } 234 } 129 Initialise(); << 235 130 return true; << 236 // to remove any inconsistency >> 237 numberOfNodes = siz; >> 238 edgeMin = binVector[0]; >> 239 edgeMax = binVector[numberOfNodes-1]; >> 240 return true ; 131 } 241 } 132 242 133 // retrieve in binary mode 243 // retrieve in binary mode 134 // binning 244 // binning 135 fIn.read((char*) (&edgeMin), sizeof edgeMin) << 245 fIn.read((char*)(&edgeMin), sizeof edgeMin); 136 fIn.read((char*) (&edgeMax), sizeof edgeMax) << 246 fIn.read((char*)(&edgeMax), sizeof edgeMax); 137 fIn.read((char*) (&numberOfNodes), sizeof nu << 247 fIn.read((char*)(&numberOfNodes), sizeof numberOfNodes ); 138 << 248 139 // contents 249 // contents 140 std::size_t size; << 250 size_t size; 141 fIn.read((char*) (&size), sizeof size); << 251 fIn.read((char*)(&size), sizeof size); 142 << 252 143 auto value = new G4double[2 * size]; << 253 G4double* value = new G4double[2*size]; 144 fIn.read((char*) (value), 2 * size * (sizeof << 254 fIn.read((char*)(value), 2*size*(sizeof(G4double)) ); 145 if (static_cast<G4int>(fIn.gcount()) != stat << 255 if (G4int(fIn.gcount()) != G4int(2*size*(sizeof(G4double))) ) 146 { 256 { 147 delete[] value; << 257 delete [] value; 148 return false; 258 return false; 149 } 259 } 150 260 151 binVector.reserve(size); 261 binVector.reserve(size); 152 dataVector.reserve(size); 262 dataVector.reserve(size); 153 for (std::size_t i = 0; i < size; ++i) << 263 for(size_t i = 0; i < size; ++i) 154 { 264 { 155 binVector.push_back(value[2 * i]); << 265 binVector.push_back(value[2*i]); 156 dataVector.push_back(value[2 * i + 1]); << 266 dataVector.push_back(value[2*i+1]); 157 } 267 } 158 delete[] value; << 268 delete [] value; >> 269 >> 270 // to remove any inconsistency >> 271 numberOfNodes = size; >> 272 edgeMin = binVector[0]; >> 273 edgeMax = binVector[numberOfNodes-1]; 159 274 160 Initialise(); << 161 return true; 275 return true; 162 } 276 } 163 277 164 // ------------------------------------------- 278 // -------------------------------------------------------------- 165 void G4PhysicsVector::DumpValues(G4double unit << 166 { << 167 for (std::size_t i = 0; i < numberOfNodes; + << 168 { << 169 G4cout << binVector[i] / unitE << " " << << 170 << G4endl; << 171 } << 172 } << 173 279 174 // ------------------------------------------- << 280 void 175 std::size_t G4PhysicsVector::FindBin(const G4d << 281 G4PhysicsVector::ScaleVector(G4double factorE, G4double factorV) 176 std::size << 177 { 282 { 178 if (idx + 1 < numberOfNodes && << 283 size_t n = dataVector.size(); 179 energy >= binVector[idx] && energy <= bi << 284 size_t i; 180 { << 285 if(n > 0) { 181 return idx; << 286 for(i=0; i<n; ++i) { 182 } << 287 binVector[i] *= factorE; 183 if (energy <= binVector[1]) << 288 dataVector[i] *= factorV; 184 { << 289 } 185 return 0; << 186 } << 187 if (energy >= binVector[idxmax]) << 188 { << 189 return idxmax; << 190 } 290 } 191 return GetBin(energy); << 291 // n = secDerivative.size(); 192 } << 292 // if(n > 0) { for(i=0; i<n; ++i) { secDerivative[i] *= factorV; } } >> 293 secDerivative.clear(); 193 294 194 // ------------------------------------------- << 295 edgeMin *= factorE; 195 void G4PhysicsVector::ScaleVector(const G4doub << 296 edgeMax *= factorE; 196 const G4doub << 197 { << 198 for (std::size_t i = 0; i < numberOfNodes; + << 199 { << 200 binVector[i] *= factorE; << 201 dataVector[i] *= factorV; << 202 } << 203 Initialise(); << 204 } 297 } 205 298 206 // ------------------------------------------- << 299 // -------------------------------------------------------------- 207 void G4PhysicsVector::FillSecondDerivatives(co << 300 208 const G4double dir1, << 301 void 209 const G4double dir2) << 302 G4PhysicsVector::ComputeSecondDerivatives(G4double firstPointDerivative, >> 303 G4double endPointDerivative) >> 304 // A standard method of computation of second derivatives >> 305 // First derivatives at the first and the last point should be provided >> 306 // See for example W.H. Press et al. "Numerical recipes in C" >> 307 // Cambridge University Press, 1997. 210 { 308 { 211 if (!useSpline) { return; } << 309 if(4 > numberOfNodes) // cannot compute derivatives for less than 4 bins 212 // cannot compute derivatives for less than << 213 const std::size_t nmin = (stype == G4SplineT << 214 if (nmin > numberOfNodes) << 215 { 310 { 216 if (0 < verboseLevel) << 311 ComputeSecDerivatives(); 217 { << 218 G4cout << "### G4PhysicsVector: spline c << 219 << numberOfNodes << " points - spline d << 220 << G4endl; << 221 DumpValues(); << 222 } << 223 useSpline = false; << 224 return; 312 return; 225 } 313 } 226 // check energies of free vector << 227 if (type == T_G4PhysicsFreeVector) << 228 { << 229 for (std::size_t i=0; i<=idxmax; ++i) << 230 { << 231 if (binVector[i + 1] <= binVector[i]) << 232 { << 233 if (0 < verboseLevel) << 234 { << 235 G4cout << "### G4PhysicsVector: spline can << 236 << " E[" << i << "]=" << binVector[i] << 237 << " >= E[" << i+1 << "]=" << binVector[i << 238 << G4endl; << 239 DumpValues(); << 240 } << 241 useSpline = false; << 242 return; << 243 } << 244 } << 245 } << 246 314 247 // spline is possible << 315 if(!SplinePossible()) { return; } 248 Initialise(); << 249 secDerivative.resize(numberOfNodes); << 250 316 251 if (1 < verboseLevel) << 317 useSpline = true; 252 { << 253 G4cout << "### G4PhysicsVector:: FillSecon << 254 << numberOfNodes << G4endl; << 255 DumpValues(); << 256 } << 257 318 258 switch(stype) << 319 G4int n = numberOfNodes-1; 259 { << 260 case G4SplineType::Base: << 261 ComputeSecDerivative1(); << 262 break; << 263 320 264 case G4SplineType::FixedEdges: << 321 G4double* u = new G4double [n]; 265 ComputeSecDerivative2(dir1, dir2); << 322 266 break; << 323 G4double p, sig, un; 267 324 268 default: << 325 u[0] = (6.0/(binVector[1]-binVector[0])) 269 ComputeSecDerivative0(); << 326 * ((dataVector[1]-dataVector[0])/(binVector[1]-binVector[0]) 270 } << 327 - firstPointDerivative); 271 } << 328 >> 329 secDerivative[0] = - 0.5; 272 330 273 // ------------------------------------------- << 331 // Decomposition loop for tridiagonal algorithm. secDerivative[i] 274 void G4PhysicsVector::ComputeSecDerivative0() << 332 // and u[i] are used for temporary storage of the decomposed factors. 275 // A simplified method of computation of seco << 333 276 { << 334 for(G4int i=1; i<n; ++i) 277 std::size_t n = numberOfNodes - 1; << 335 { >> 336 sig = (binVector[i]-binVector[i-1]) / (binVector[i+1]-binVector[i-1]); >> 337 p = sig*(secDerivative[i-1]) + 2.0; >> 338 secDerivative[i] = (sig - 1.0)/p; >> 339 u[i] = (dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i]) >> 340 - (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]); >> 341 u[i] = 6.0*u[i]/(binVector[i+1]-binVector[i-1]) - sig*u[i-1]/p; >> 342 } >> 343 >> 344 sig = (binVector[n-1]-binVector[n-2]) / (binVector[n]-binVector[n-2]); >> 345 p = sig*secDerivative[n-2] + 2.0; >> 346 un = (6.0/(binVector[n]-binVector[n-1])) >> 347 *(endPointDerivative - >> 348 (dataVector[n]-dataVector[n-1])/(binVector[n]-binVector[n-1])) - u[n-1]/p; >> 349 secDerivative[n] = un/(secDerivative[n-1] + 2.0); 278 350 279 for (std::size_t i = 1; i < n; ++i) << 351 // The back-substitution loop for the triagonal algorithm of solving >> 352 // a linear system of equations. >> 353 >> 354 for(G4int k=n-1; k>0; --k) 280 { 355 { 281 secDerivative[i] = 3.0 * << 356 secDerivative[k] *= 282 ((dataVector[i + 1] - dataVector[i]) / ( << 357 (secDerivative[k+1] - 283 (dataVector[i] - dataVector[i - 1]) / << 358 u[k]*(binVector[k+1]-binVector[k-1])/(binVector[k+1]-binVector[k])); 284 (binVector[i] - binVector[i - 1])) / << 285 (binVector[i + 1] - binVector[i - 1]); << 286 } 359 } 287 secDerivative[n] = secDerivative[n - 1]; << 360 secDerivative[0] = 0.5*(u[0] - secDerivative[1]); 288 secDerivative[0] = secDerivative[1]; << 361 >> 362 delete [] u; 289 } 363 } 290 364 291 // ------------------------------------------- 365 // -------------------------------------------------------------- 292 void G4PhysicsVector::ComputeSecDerivative1() << 366 293 // Computation of second derivatives using "No << 367 void G4PhysicsVector::FillSecondDerivatives() 294 // B.I. Kvasov "Methods of shape-preserving sp << 368 // Computation of second derivatives using "Not-a-knot" endpoint conditions 295 // World Scientific, 2000 << 369 // B.I. Kvasov "Methods of shape-preserving spline approximation" >> 370 // World Scientific, 2000 296 { 371 { 297 std::size_t n = numberOfNodes - 1; << 372 if(5 > numberOfNodes) // cannot compute derivatives for less than 4 points 298 auto u = new G4double[n]; << 373 { 299 G4double p, sig; << 374 ComputeSecDerivatives(); >> 375 return; >> 376 } >> 377 >> 378 if(!SplinePossible()) { return; } 300 379 301 u[1] = ((dataVector[2] - dataVector[1]) / (b << 380 useSpline = true; 302 (dataVector[1] - dataVector[0]) / (b << 381 303 u[1] = 6.0 * u[1] * (binVector[2] - binVecto << 382 G4int n = numberOfNodes-1; 304 ((binVector[2] - binVector[0]) * (bin << 383 >> 384 G4double* u = new G4double [n]; >> 385 >> 386 G4double p, sig; 305 387 >> 388 u[1] = ((dataVector[2]-dataVector[1])/(binVector[2]-binVector[1]) - >> 389 (dataVector[1]-dataVector[0])/(binVector[1]-binVector[0])); >> 390 u[1] = 6.0*u[1]*(binVector[2]-binVector[1]) >> 391 / ((binVector[2]-binVector[0])*(binVector[2]-binVector[0])); >> 392 306 // Decomposition loop for tridiagonal algori 393 // Decomposition loop for tridiagonal algorithm. secDerivative[i] 307 // and u[i] are used for temporary storage o 394 // and u[i] are used for temporary storage of the decomposed factors. 308 395 309 secDerivative[1] = (2.0 * binVector[1] - bin << 396 secDerivative[1] = (2.0*binVector[1]-binVector[0]-binVector[2]) 310 (2.0 * binVector[2] - bin << 397 / (2.0*binVector[2]-binVector[0]-binVector[1]); 311 398 312 for(std::size_t i = 2; i < n - 1; ++i) << 399 for(G4int i=2; i<n-1; ++i) 313 { 400 { 314 sig = << 401 sig = (binVector[i]-binVector[i-1]) / (binVector[i+1]-binVector[i-1]); 315 (binVector[i] - binVector[i - 1]) / (bin << 402 p = sig*secDerivative[i-1] + 2.0; 316 p = sig * secDerivative[i - << 403 secDerivative[i] = (sig - 1.0)/p; 317 secDerivative[i] = (sig - 1.0) / p; << 404 u[i] = (dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i]) 318 u[i] = << 405 - (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1]); 319 (dataVector[i + 1] - dataVector[i]) / (b << 406 u[i] = (6.0*u[i]/(binVector[i+1]-binVector[i-1])) - sig*u[i-1]/p; 320 (dataVector[i] - dataVector[i - 1]) / (b << 407 } 321 u[i] = << 408 322 (6.0 * u[i] / (binVector[i + 1] - binVec << 409 sig = (binVector[n-1]-binVector[n-2]) / (binVector[n]-binVector[n-2]); 323 } << 410 p = sig*secDerivative[n-3] + 2.0; 324 << 411 u[n-1] = (dataVector[n]-dataVector[n-1])/(binVector[n]-binVector[n-1]) 325 sig = << 412 - (dataVector[n-1]-dataVector[n-2])/(binVector[n-1]-binVector[n-2]); 326 (binVector[n - 1] - binVector[n - 2]) / (b << 413 u[n-1] = 6.0*sig*u[n-1]/(binVector[n]-binVector[n-2]) 327 p = sig * secDerivative[n - 3] + 2.0; << 414 - (2.0*sig - 1.0)*u[n-2]/p; 328 u[n - 1] = << 329 (dataVector[n] - dataVector[n - 1]) / (bin << 330 (dataVector[n - 1] - dataVector[n - 2]) / << 331 (binVector[n - 1] - binVector[n - 2]); << 332 u[n - 1] = 6.0 * sig * u[n - 1] / (binVector << 333 (2.0 * sig - 1.0) * u[n - 2] / p; << 334 415 335 p = (1.0 + sig) + (2.0 * sig - 1.0) * secDer << 416 p = (1.0+sig) + (2.0*sig-1.0)*secDerivative[n-2]; 336 secDerivative[n - 1] = u[n - 1] / p; << 417 secDerivative[n-1] = u[n-1]/p; 337 418 338 // The back-substitution loop for the triago 419 // The back-substitution loop for the triagonal algorithm of solving 339 // a linear system of equations. 420 // a linear system of equations. 340 << 421 341 for (std::size_t k = n - 2; k > 1; --k) << 422 for(G4int k=n-2; k>1; --k) 342 { 423 { 343 secDerivative[k] *= << 424 secDerivative[k] *= 344 (secDerivative[k + 1] - u[k] * (binVecto << 425 (secDerivative[k+1] - 345 (binVector[k + << 426 u[k]*(binVector[k+1]-binVector[k-1])/(binVector[k+1]-binVector[k])); 346 } << 427 } 347 secDerivative[n] = << 428 secDerivative[n] = (secDerivative[n-1] - (1.0-sig)*secDerivative[n-2])/sig; 348 (secDerivative[n - 1] - (1.0 - sig) * secD << 429 sig = 1.0 - ((binVector[2]-binVector[1])/(binVector[2]-binVector[0])); 349 sig = 1.0 - ((binVector[2] - binVector[1]) / << 430 secDerivative[1] *= (secDerivative[2] - u[1]/(1.0-sig)); 350 secDerivative[1] *= (secDerivative[2] - u[1] << 431 secDerivative[0] = (secDerivative[1] - sig*secDerivative[2])/(1.0-sig); 351 secDerivative[0] = (secDerivative[1] - sig * << 352 432 353 delete[] u; << 433 delete [] u; 354 } 434 } 355 435 356 // ------------------------------------------- 436 // -------------------------------------------------------------- 357 void G4PhysicsVector::ComputeSecDerivative2(G4 << 437 358 G4 << 438 void 359 // A standard method of computation of second << 439 G4PhysicsVector::ComputeSecDerivatives() 360 // First derivatives at the first and the last << 440 // A simplified method of computation of second derivatives 361 // See for example W.H. Press et al. "Numerica << 362 // Cambridge University Press, 1997. << 363 { 441 { 364 std::size_t n = numberOfNodes - 1; << 442 if(3 > numberOfNodes) // cannot compute derivatives for less than 4 bins 365 auto u = new G4double[n]; << 443 { 366 G4double p, sig, un; << 444 useSpline = false; >> 445 return; >> 446 } 367 447 368 u[0] = (6.0 / (binVector[1] - binVector[0])) << 448 if(!SplinePossible()) { return; } 369 ((dataVector[1] - dataVector[0]) / (b << 370 firstPointDerivative); << 371 449 372 secDerivative[0] = -0.5; << 450 useSpline = true; 373 451 374 // Decomposition loop for tridiagonal algori << 452 size_t n = numberOfNodes-1; 375 // and u[i] are used for temporary storage o << 376 453 377 for (std::size_t i = 1; i < n; ++i) << 454 for(size_t i=1; i<n; ++i) 378 { 455 { 379 sig = << 456 secDerivative[i] = 380 (binVector[i] - binVector[i - 1]) / (bin << 457 3.0*((dataVector[i+1]-dataVector[i])/(binVector[i+1]-binVector[i]) - 381 p = sig * (secDerivative[i << 458 (dataVector[i]-dataVector[i-1])/(binVector[i]-binVector[i-1])) 382 secDerivative[i] = (sig - 1.0) / p; << 459 /(binVector[i+1]-binVector[i-1]); 383 u[i] = << 460 } 384 (dataVector[i + 1] - dataVector[i]) / (b << 461 secDerivative[n] = secDerivative[n-1]; 385 (dataVector[i] - dataVector[i - 1]) / (b << 462 secDerivative[0] = secDerivative[1]; 386 u[i] = << 463 } 387 6.0 * u[i] / (binVector[i + 1] - binVect << 388 } << 389 << 390 sig = << 391 (binVector[n - 1] - binVector[n - 2]) / (b << 392 p = sig * secDerivative[n - 2] + 2.0; << 393 un = (6.0 / (binVector[n] - binVector[n - 1] << 394 (endPointDerivative - (dataVector[n] << 395 (binVector[n] << 396 u[n - 1] / p; << 397 secDerivative[n] = un / (secDerivative[n - 1 << 398 464 399 // The back-substitution loop for the triago << 465 // -------------------------------------------------------------- 400 // a linear system of equations. << 401 466 402 for (std::size_t k = n - 1; k > 0; --k) << 467 G4bool G4PhysicsVector::SplinePossible() >> 468 // Initialise second derivative array. If neighbor energy coincide >> 469 // or not ordered than spline cannot be applied >> 470 { >> 471 G4bool result = true; >> 472 secDerivative.clear(); >> 473 secDerivative.reserve(numberOfNodes); >> 474 for(size_t j=0; j<numberOfNodes; ++j) 403 { 475 { 404 secDerivative[k] *= << 476 secDerivative.push_back(0.0); 405 (secDerivative[k + 1] - u[k] * (binVecto << 477 if(j > 0) 406 (binVector[k + << 478 { 407 } << 479 if(binVector[j]-binVector[j-1] <= 0.) { 408 secDerivative[0] = 0.5 * (u[0] - secDerivati << 480 result = false; 409 << 481 secDerivative.clear(); 410 delete[] u; << 482 break; >> 483 } >> 484 } >> 485 } >> 486 return result; 411 } 487 } 412 << 488 413 // ------------------------------------------- 489 // -------------------------------------------------------------- >> 490 414 std::ostream& operator<<(std::ostream& out, co 491 std::ostream& operator<<(std::ostream& out, const G4PhysicsVector& pv) 415 { 492 { 416 // binning 493 // binning 417 G4long prec = out.precision(); << 494 out << std::setprecision(12) << pv.edgeMin << " " 418 out << std::setprecision(12) << pv.edgeMin < << 495 << pv.edgeMax << " " << pv.numberOfNodes << G4endl; 419 << pv.numberOfNodes << G4endl; << 420 496 421 // contents 497 // contents 422 out << pv.dataVector.size() << G4endl; << 498 out << pv.dataVector.size() << G4endl; 423 for (std::size_t i = 0; i < pv.dataVector.si << 499 for(size_t i = 0; i < pv.dataVector.size(); i++) 424 { 500 { 425 out << pv.binVector[i] << " " << pv.dataV 501 out << pv.binVector[i] << " " << pv.dataVector[i] << G4endl; 426 } 502 } 427 out.precision(prec); << 503 out << std::setprecision(6); 428 504 429 return out; 505 return out; 430 } 506 } 431 507 432 //-------------------------------------------- 508 //--------------------------------------------------------------- 433 G4double G4PhysicsVector::GetEnergy(const G4do << 509 >> 510 G4double >> 511 G4PhysicsVector::Value(G4double theEnergy, size_t& lastIdx) const 434 { 512 { 435 if (0 == numberOfNodes) << 513 G4double y; 436 { << 514 if(theEnergy <= edgeMin) { 437 return 0.0; << 515 lastIdx = 0; 438 } << 516 y = dataVector[0]; 439 if (1 == numberOfNodes || val <= dataVector[ << 517 } else if(theEnergy >= edgeMax) { 440 { << 518 lastIdx = numberOfNodes-1; 441 return edgeMin; << 519 y = dataVector[lastIdx]; 442 } << 520 } else { 443 if (val >= dataVector[numberOfNodes - 1]) << 521 lastIdx = FindBin(theEnergy, lastIdx); 444 { << 522 y = Interpolation(lastIdx, theEnergy); 445 return edgeMax; << 446 } << 447 std::size_t bin = std::lower_bound(dataVecto << 448 - dataVector.cbegin() - 1; << 449 if (bin > idxmax) { bin = idxmax; } << 450 G4double res = binVector[bin]; << 451 G4double del = dataVector[bin + 1] - dataVec << 452 if (del > 0.0) << 453 { << 454 res += (val - dataVector[bin]) * (binVecto << 455 } 523 } 456 return res; << 524 return y; 457 } 525 } 458 526 459 //-------------------------------------------- 527 //--------------------------------------------------------------- 460 void G4PhysicsVector::PrintPutValueError(std:: << 528 461 G4dou << 529 G4double G4PhysicsVector::FindLinearEnergy(G4double rand) const 462 const << 530 { 463 { << 531 if(1 >= numberOfNodes) { return 0.0; } 464 G4ExceptionDescription ed; << 532 size_t n1 = 0; 465 ed << "Vector type: " << type << " length= " << 533 size_t n2 = numberOfNodes/2; 466 << "; an attempt to put data at index= " << 534 size_t n3 = numberOfNodes - 1; 467 << " value= " << val << " in " << text; << 535 G4double y = rand*dataVector[n3]; 468 G4Exception("G4PhysicsVector:", "gl0005", << 536 while (n1 + 1 != n3) 469 FatalException, ed, "Wrong opera << 537 { >> 538 if (y > dataVector[n2]) >> 539 { n1 = n2; } >> 540 else >> 541 { n3 = n2; } >> 542 n2 = (n3 + n1 + 1)/2; >> 543 } >> 544 G4double res = binVector[n1]; >> 545 G4double del = dataVector[n3] - dataVector[n1]; >> 546 if(del > 0.0) { >> 547 res += (y - dataVector[n1])*(binVector[n3] - res)/del; >> 548 } >> 549 return res; 470 } 550 } 471 551 472 //-------------------------------------------- 552 //--------------------------------------------------------------- 473 553