ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4SBBremTable.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4SBBremTable.cc
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 // -------------------------------------------------------------------
28 //
29 // GEANT4 Class file
30 //
31 //
32 // File name: G4SBBremTable
33 //
34 // Author: Mihaly Novak
35 //
36 // Creation date: 15.07.2018
37 //
38 // Modifications:
39 //
40 // -------------------------------------------------------------------
41 //
42 #include "G4SBBremTable.hh"
43 
44 #include "G4SystemOfUnits.hh"
45 
46 #include "G4Material.hh"
47 #include "G4ProductionCutsTable.hh"
48 #include "G4MaterialCutsCouple.hh"
49 #include "Randomize.hh"
50 
51 #include "G4String.hh"
52 
53 #include "G4Log.hh"
54 #include "G4Exp.hh"
55 
56 #include "zlib.h"
57 
58 #include <iostream>
59 #include <fstream>
60 #include <sstream>
61 #include <algorithm>
62 
64  : fMaxZet(-1), fNumElEnergy(-1), fNumKappa(-1), fUsedLowEenergy(-1.),
65  fUsedHighEenergy(-1.), fLogMinElEnergy(-1.), fILDeltaElEnergy(-1.)
66 {}
67 
69 {
71 }
72 
73 void G4SBBremTable::Initialize(const G4double lowe, const G4double highe)
74 {
75  fUsedLowEenergy = lowe;
76  fUsedHighEenergy = highe;
79 // Dump();
80 }
81 
82 // run-time method that samples energy transferred to the emitted gamma photon
84  const G4double leekin,
85  const G4double gcut,
86  const G4double dielSupConst,
87  const G4int iZet,
88  const G4int matCutIndx,
89  const G4bool isElectron)
90 {
91  static const G4double kAlpha2Pi = CLHEP::twopi*CLHEP::fine_structure_const;
92  const G4double zet = (G4double)iZet;
93  const G4int izet = std::max(std::min(fMaxZet, iZet),1);
94  G4double eGamma = 0.;
95  // this should be checked in the caller
96  // if (eekin<=gcut) return kappa;
97  const G4double lElEnergy = leekin;
98  const SamplingTablePerZ* stZ = fSBSamplingTables[izet];
99  // get the gamma cut of this Z that corresponds to the current mat-cuts
100  const size_t gamCutIndx = stZ->fMatCutIndxToGamCutIndx[matCutIndx];
101  // gcut was not found: should never happen (only in verbose mode)
102  if (gamCutIndx >= stZ->fNumGammaCuts || stZ->fGammaECuts[gamCutIndx]!=gcut) {
103  G4String msg = " Gamma cut="+std::to_string(gcut) + " [MeV] was not found ";
104  msg += "in case of Z = " + std::to_string(iZet) + ". ";
105  G4Exception("G4SBBremTable::SampleEnergyTransfer()","em0X",FatalException,
106  msg.c_str());
107  }
108  const G4double lGCut = stZ->fLogGammaECuts[gamCutIndx];
109  // get the random engine
110  CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine();
111  // find lower e- energy bin
112  G4bool isCorner = false; // indicate that the lower edge e- energy < gam-gut
113  G4bool isSimply = false; // simply sampling: isCorner+lower egde is selected
114  G4int elEnergyIndx = stZ->fMaxElEnergyIndx;
115  // only if e- ekin is below the maximum value(use table at maximum otherwise)
116  if (eekin < fElEnergyVect[elEnergyIndx]) {
117  const G4double val = (lElEnergy-fLogMinElEnergy)*fILDeltaElEnergy;
118  elEnergyIndx = (G4int)val;
119  G4double pIndxH = val-elEnergyIndx;
120  // check if we are at limiting case: lower edge e- energy < gam-gut
121  if (fElEnergyVect[elEnergyIndx]<=gcut) {
122  // recompute the probability of taking the higher e- energy bin()
123  pIndxH = (lElEnergy-lGCut)/(fLElEnergyVect[elEnergyIndx+1]-lGCut);
124  isCorner = true;
125  }
126  //
127  if (rndmEngine->flat()<pIndxH) {
128  ++elEnergyIndx; // take the table at the higher e- energy bin
129  } else if (isCorner) { // take the table at the lower e- energy bin
130  // special sampling need to be done if lower edge e- energy < gam-gut:
131  // actually, we "sample" from a table "built" at the gamm-cut i.e. delta
132  isSimply = true;
133  }
134  }
135  // should never happen under normal conditions but add protection
136  if (!stZ->fTablesPerEnergy[elEnergyIndx]) {
137  return 0.;
138  }
139  // Do the photon energy sampling:
140  const STable *st = stZ->fTablesPerEnergy[elEnergyIndx];
141  const std::vector<G4double>& cVect = st->fCumCutValues;
142  const std::vector<STPoint>& pVect = st->fSTable;
143  const G4double minVal = cVect[gamCutIndx];
144 
145  // should never happen under normal conditions but add protection
146  if (minVal >= 1.) {
147  return 0.;
148  }
149  // some transfomrmtion variables used in the looop
150  const G4double lCurKappaC = lGCut - leekin;
151  const G4double lUsedKappaC = lGCut - fLElEnergyVect[elEnergyIndx];
152  // dielectric (always) and e+ correction suppressions (if the primary is e+)
153  G4double suppression = 1.;
154  G4double rndm[2];
155  // rejection loop starts here
156  do {
157  rndmEngine->flatArray(2, rndm);
158  G4double kappa = 1.0;
159  if (!isSimply) {
160  const G4double cumRV = rndm[0]*(1.-minVal)+minVal;
161  // find lower index of the values in the Cumulative Function: use linear
162  // instead of binary search because it's faster in our case
163  const G4int cumLIndx = LinSearch(pVect, fNumKappa, cumRV)-1;
164 // const G4int cumLIndx = std::lower_bound( pVect.begin(), pVect.end(), cumRV,
165 // [](const STPoint& p, const double& cumV) {
166 // return p.fCum<cumV; } ) - pVect.begin() -1;
167  const STPoint& stPL = pVect[cumLIndx];
168  const G4double pA = stPL.fParA;
169  const G4double pB = stPL.fParB;
170  const G4double cumL = stPL.fCum;
171  const G4double cumH = pVect[cumLIndx+1].fCum;
172  const G4double lKL = fLKappaVect[cumLIndx];
173  const G4double lKH = fLKappaVect[cumLIndx+1];
174  const G4double dm1 = (cumRV-cumL)/(cumH-cumL);
175  const G4double dm2 = (1.+pA+pB)*dm1;
176  const G4double dm3 = 1.+dm1*(pA+pB*dm1);
177  // kappa sampled at E_i e- energy
178  const G4double lKappa = lKL+dm2/dm3*(lKH-lKL);
179  // transform lKappa to [log(gcut/eekin),0] form [log(gcut/E_i),0]
180  kappa = G4Exp(lKappa*lCurKappaC/lUsedKappaC);
181  } else {
182 // const G4double upLimit = std::min(1.*CLHEP::eV,eekin-gcut);
183 // kappa = (gcut+rndm[0]*upLimit)/eekin;
184  kappa = 1.-rndm[0]*(1.-gcut/eekin);
185  }
186  // compute the emitted photon energy: k
187  eGamma = kappa*eekin;
188  const G4double invEGamma = 1./eGamma;
189  // compute dielectric suppression: 1/(1+[gk_p/k]^2)
190  suppression = 1./(1.+dielSupConst*invEGamma*invEGamma);
191  // add positron correction if particle is e+
192  if (!isElectron) {
193  const G4double e1 = eekin - gcut;
194  const G4double iBeta1 = (e1 + CLHEP::electron_mass_c2)
195  / std::sqrt(e1*(e1 + 2.*CLHEP::electron_mass_c2));
196  const G4double e2 = eekin - eGamma;
197  const G4double iBeta2 = (e2 + CLHEP::electron_mass_c2)
198  / std::sqrt(e2*(e2 + 2.*CLHEP::electron_mass_c2));
199  const G4double dum = kAlpha2Pi*zet*(iBeta1 - iBeta2);
200  suppression = (dum > -12.) ? suppression*G4Exp(dum) : 0.;
201  }
202  } while (rndm[1] > suppression);
203  // end of rejection loop
204  // return the sampled photon energy value k
205  return eGamma;
206 }
207 
208 
210  // claer
212  LoadSTGrid();
213  // First elements and gamma cuts data structures need to be built:
214  // loop over all material-cuts and add gamma cut to the list of elements
217  // a temporary vector to store one element
218  std::vector<size_t> vtmp(1,0);
219  size_t numMatCuts = thePCTable->GetTableSize();
220  for (size_t imc=0; imc<numMatCuts; ++imc) {
221  const G4MaterialCutsCouple *matCut = thePCTable->GetMaterialCutsCouple(imc);
222  if (!matCut->IsUsed()) {
223  continue;
224  }
225  const G4Material* mat = matCut->GetMaterial();
226  const G4ElementVector* elemVect = mat->GetElementVector();
227  const G4int indxMC = matCut->GetIndex();
228  const G4double gamCut = (*(thePCTable->GetEnergyCutsVector(0)))[indxMC];
229  const size_t numElems = elemVect->size();
230  for (size_t ielem=0; ielem<numElems; ++ielem) {
231  const G4Element *elem = (*elemVect)[ielem];
232  const G4int izet = std::max(std::min(fMaxZet, elem->GetZasInt()),1);
233  if (!fSBSamplingTables[izet]) {
234  // create data structure but do not load sampling tables yet: will be
235  // loaded after we know what are the min/max e- energies where sampling
236  // will be needed during the simulation for this Z
237  // LoadSamplingTables(izet);
238  fSBSamplingTables[izet] = new SamplingTablePerZ();
239  }
240  // add current gamma cut to the list of this element data (only if this
241  // cut value is still not tehre)
242  const std::vector<double> &cVect = fSBSamplingTables[izet]->fGammaECuts;
243  size_t indx = std::find(cVect.begin(), cVect.end(), gamCut)-cVect.begin();
244  if (indx==cVect.size()) {
245  vtmp[0] = imc;
246  fSBSamplingTables[izet]->fGamCutIndxToMatCutIndx.push_back(vtmp);
247  fSBSamplingTables[izet]->fGammaECuts.push_back(gamCut);
248  fSBSamplingTables[izet]->fLogGammaECuts.push_back(G4Log(gamCut));
249  ++fSBSamplingTables[izet]->fNumGammaCuts;
250  } else {
251  fSBSamplingTables[izet]->fGamCutIndxToMatCutIndx[indx].push_back(imc);
252  }
253  }
254  }
255 }
256 
258  const size_t numMatCuts = G4ProductionCutsTable::GetProductionCutsTable()
259  ->GetTableSize();
260  for (G4int iz=1; iz<fMaxZet+1; ++iz) {
262  if (!stZ) continue;
263  // Load-in sampling table data:
264  LoadSamplingTables(iz);
265  // init data
266  for (G4int iee=0; iee<fNumElEnergy; ++iee) {
267  if (!stZ->fTablesPerEnergy[iee])
268  continue;
269  const G4double elEnergy = fElEnergyVect[iee];
270  // 1 indicates that gamma production is not possible at this e- energy
271  stZ->fTablesPerEnergy[iee]->fCumCutValues.resize(stZ->fNumGammaCuts,1.);
272  // sort gamma cuts and other members accordingly
273  for (size_t i=0; i<stZ->fNumGammaCuts-1; ++i) {
274  for (size_t j=i+1; j<stZ->fNumGammaCuts; ++j) {
275  if (stZ->fGammaECuts[j]<stZ->fGammaECuts[i]) {
276  G4double dum0 = stZ->fGammaECuts[i];
277  G4double dum1 = stZ->fLogGammaECuts[i];
278  std::vector<size_t> dumv = stZ->fGamCutIndxToMatCutIndx[i];
279  stZ->fGammaECuts[i] = stZ->fGammaECuts[j];
280  stZ->fLogGammaECuts[i] = stZ->fLogGammaECuts[j];
282  stZ->fGammaECuts[j] = dum0;
283  stZ->fLogGammaECuts[j] = dum1;
284  stZ->fGamCutIndxToMatCutIndx[j] = dumv;
285  }
286  }
287  }
288  // set couple indices to store the corresponding gamma cut index
289  stZ->fMatCutIndxToGamCutIndx.resize(numMatCuts,-1);
290  for (size_t i=0; i<stZ->fGamCutIndxToMatCutIndx.size(); ++i) {
291  for (size_t j=0; j<stZ->fGamCutIndxToMatCutIndx[i].size(); ++j) {
293  }
294  }
295  // clear temporary vector
296  for (size_t i=0; i<stZ->fGamCutIndxToMatCutIndx.size(); ++i) {
297  stZ->fGamCutIndxToMatCutIndx[i].clear();
298  }
299  stZ->fGamCutIndxToMatCutIndx.clear();
300  // init for each gamma cut that are below the e- energy
301  for (size_t ic=0; ic<stZ->fNumGammaCuts; ++ic) {
302  const G4double gamCut = stZ->fGammaECuts[ic];
303  if (elEnergy>gamCut) {
304  // find lower kappa index; compute the 'xi' i.e. cummulative value for
305  // gamCut/elEnergy
306  const G4double cutKappa = std::max(1.e-12, gamCut/elEnergy);
307  const G4int iKLow = (cutKappa>1.e-12)
308  ? std::lower_bound(fKappaVect.begin(), fKappaVect.end(), cutKappa)
309  - fKappaVect.begin() -1
310  : 0;
311  const STPoint* stpL = &(stZ->fTablesPerEnergy[iee]->fSTable[iKLow]);
312  const STPoint* stpH = &(stZ->fTablesPerEnergy[iee]->fSTable[iKLow+1]);
313  const G4double pA = stpL->fParA;
314  const G4double pB = stpL->fParB;
315  const G4double etaL = stpL->fCum;
316  const G4double etaH = stpH->fCum;
317  const G4double alph = G4Log(cutKappa/fKappaVect[iKLow])
318  /G4Log(fKappaVect[iKLow+1]/fKappaVect[iKLow]);
319  const G4double dum = pA*(alph-1.)-1.-pB;
320  G4double val = etaL;
321  if (alph==0.) {
322  stZ->fTablesPerEnergy[iee]->fCumCutValues[ic] = val;
323  } else {
324  val = -(dum+std::sqrt(dum*dum-4.*pB*alph*alph))/(2.*pB*alph);
325  val = val*(etaH-etaL)+etaL;
326  stZ->fTablesPerEnergy[iee]->fCumCutValues[ic] = val;
327  }
328  }
329  }
330  }
331  }
332 }
333 
334 // should be called only from LoadSamplingTables(G4int) and once
336  char* path = std::getenv("G4LEDATA");
337  if (!path) {
338  G4Exception("G4SBBremTable::LoadSTGrid()","em0006",
339  FatalException, "Environment variable G4LEDATA not defined");
340  return;
341  }
342  const G4String fname = G4String(path) + "/brem_SB/SBTables/grid";
343  std::ifstream infile(fname,std::ios::in);
344  if (!infile.is_open()) {
345  G4String msgc = "Cannot open file: " + fname;
346  G4Exception("G4SBBremTable::LoadSTGrid()","em0006",
347  FatalException, msgc.c_str());
348  return;
349  }
350  // get max Z, # electron energies and # kappa values
351  infile >> fMaxZet;
352  infile >> fNumElEnergy;
353  infile >> fNumKappa;
354  // allocate space for the data and get them in:
355  // (1.) first eletron energy grid
356  fElEnergyVect.resize(fNumElEnergy);
357  fLElEnergyVect.resize(fNumElEnergy);
358  for (G4int iee=0; iee<fNumElEnergy; ++iee) {
359  G4double dum;
360  infile >> dum;
361  fElEnergyVect[iee] = dum*CLHEP::MeV;
362  fLElEnergyVect[iee] = G4Log(fElEnergyVect[iee]);
363  }
364  // (2.) then the kappa grid
365  fKappaVect.resize(fNumKappa);
366  fLKappaVect.resize(fNumKappa);
367  for (G4int ik=0; ik<fNumKappa; ++ik) {
368  infile >> fKappaVect[ik];
369  fLKappaVect[ik] = G4Log(fKappaVect[ik]);
370  }
371  // (3.) set size of the main container for sampling tables
372  fSBSamplingTables.resize(fMaxZet+1,nullptr);
373  // init electron energy grid related variables: use accurate values !!!
374 // fLogMinElEnergy = G4Log(fElEnergyVect[0]);
375 // fILDeltaElEnergy = 1./G4Log(fElEnergyVect[1]/fElEnergyVect[0]);
376  const G4double elEmin = 100.0*CLHEP::eV; //fElEnergyVect[0];
377  const G4double elEmax = 10.0*CLHEP::GeV;//fElEnergyVect[fNumElEnergy-1];
378  fLogMinElEnergy = G4Log(elEmin);
379  fILDeltaElEnergy = 1./(G4Log(elEmax/elEmin)/(fNumElEnergy-1.0));
380  // reset min/max energies if needed
383  //
384  infile.close();
385 }
386 
388  // check if grid needs to be loaded first
389  if (fMaxZet<0) {
390  LoadSTGrid();
391  }
392  // load data for a given Z only once
393  iz = std::max(std::min(fMaxZet, iz),1);
394  char* path = std::getenv("G4LEDATA");
395  if (!path) {
396  G4Exception("G4SBBremTable::LoadSamplingTables()","em0006",
397  FatalException, "Environment variable G4LEDATA not defined");
398  return;
399  }
400  const G4String fname = G4String(path) + "/brem_SB/SBTables/sTableSB_"
401  + std::to_string(iz);
402  std::istringstream infile(std::ios::in);
403  // read the compressed data file into the stream
404  ReadCompressedFile(fname, infile);
405  // the SamplingTablePerZ object was already created, set size of containers
406  // then load sampling table data for each electron energies
407  SamplingTablePerZ* zTable = fSBSamplingTables[iz];
408  //
409  // Determine min/max elektron kinetic energies and indices
410  const G4double minGammaCut = zTable->fGammaECuts[ std::min_element(
411  std::begin(zTable->fGammaECuts),std::end(zTable->fGammaECuts))
412  -std::begin(zTable->fGammaECuts)];
413  const G4double elEmin = std::max(fUsedLowEenergy, minGammaCut);
414  const G4double elEmax = fUsedHighEenergy;
415  // find low/high elecrton energy indices where tables will be needed
416  // low:
417  zTable->fMinElEnergyIndx = 0;
418  if (elEmin>=fElEnergyVect[fNumElEnergy-1]) {
419  zTable->fMinElEnergyIndx = fNumElEnergy-1;
420  } else {
421  zTable->fMinElEnergyIndx = std::lower_bound(fElEnergyVect.begin(),
422  fElEnergyVect.end(), elEmin) - fElEnergyVect.begin() -1;
423  }
424  // high:
425  zTable->fMaxElEnergyIndx = 0;
426  if (elEmax>=fElEnergyVect[fNumElEnergy-1]) {
427  zTable->fMaxElEnergyIndx = fNumElEnergy-1;
428  } else {
429  // lower + 1
430  zTable->fMaxElEnergyIndx = std::lower_bound(fElEnergyVect.begin(),
431  fElEnergyVect.end(), elEmax) - fElEnergyVect.begin();
432  }
433  // protect
434  if (zTable->fMaxElEnergyIndx<=zTable->fMinElEnergyIndx) {
435  return;
436  }
437  // load sampling tables that are needed: file is already in the stream
438  zTable->fTablesPerEnergy.resize(fNumElEnergy, nullptr);
439  for (G4int iee=0; iee<fNumElEnergy; ++iee) {
440  // go over data that are not needed
441  if (iee<zTable->fMinElEnergyIndx || iee>zTable->fMaxElEnergyIndx) {
442  for (G4int ik=0; ik<fNumKappa; ++ik) {
443  G4double dum;
444  infile >> dum; infile >> dum; infile >> dum;
445  }
446  } else { // load data that are needed
447  zTable->fTablesPerEnergy[iee] = new STable();
448  zTable->fTablesPerEnergy[iee]->fSTable.resize(fNumKappa);
449  for (G4int ik=0; ik<fNumKappa; ++ik) {
450  STPoint &stP = zTable->fTablesPerEnergy[iee]->fSTable[ik];
451  infile >> stP.fCum;
452  infile >> stP.fParA;
453  infile >> stP.fParB;
454  }
455  }
456  }
457 }
458 
459 // clean away all sampling tables and make ready to re-install
461  for (G4int iz=0; iz<fMaxZet+1; ++iz) {
462  if (fSBSamplingTables[iz]) {
463  for (G4int iee=0; iee<fNumElEnergy; ++iee) {
464  if (fSBSamplingTables[iz]->fTablesPerEnergy[iee]) {
465  fSBSamplingTables[iz]->fTablesPerEnergy[iee]->fSTable.clear();
466  fSBSamplingTables[iz]->fTablesPerEnergy[iee]->fCumCutValues.clear();
467  }
468  }
469  fSBSamplingTables[iz]->fTablesPerEnergy.clear();
470  fSBSamplingTables[iz]->fGammaECuts.clear();
471  fSBSamplingTables[iz]->fLogGammaECuts.clear();
472  fSBSamplingTables[iz]->fMatCutIndxToGamCutIndx.clear();
473  //
474  delete fSBSamplingTables[iz];
475  fSBSamplingTables[iz] = nullptr;
476  }
477  }
478  fSBSamplingTables.clear();
479  fElEnergyVect.clear();
480  fLElEnergyVect.clear();
481  fKappaVect.clear();
482  fLKappaVect.clear();
483  fMaxZet = -1;
484 }
485 
486 //void G4SBBremTable::Dump() {
487 // G4cerr<< "\n ===== Dumping ===== \n" << G4endl;
488 // for (G4int iz=0; iz<fMaxZet+1; ++iz) {
489 // if (fSBSamplingTables[iz]) {
490 // G4cerr<< " ----> There are " << fSBSamplingTables[iz]->fNumGammaCuts
491 // << " g-cut for Z = " << iz << G4endl;
492 // for (size_t ic=0; ic<fSBSamplingTables[iz]->fGammaECuts.size(); ++ic)
493 // G4cerr<< " i = " << ic << " "
494 // << fSBSamplingTables[iz]->fGammaECuts[ic] << G4endl;
495 // }
496 // }
497 //}
498 
499 // find lower bin index of value: used in acse of CDF values i.e. val in [0,1)
500 // while vector elements in [0,1]
501 G4int G4SBBremTable::LinSearch(const std::vector<STPoint>& vect,
502  const G4int size,
503  const G4double val) {
504  G4int i= 0;
505  while (i + 3 < size) {
506  if (vect [i + 0].fCum > val) return i + 0;
507  if (vect [i + 1].fCum > val) return i + 1;
508  if (vect [i + 2].fCum > val) return i + 2;
509  if (vect [i + 3].fCum > val) return i + 3;
510  i += 4;
511  }
512  while (i < size) {
513  if (vect [i].fCum > val)
514  break;
515  ++i;
516  }
517  return i;
518 }
519 
520 // uncompress one data file into the input string stream
522  std::istringstream &iss) {
523  std::string *dataString = nullptr;
524  std::string compfilename(fname+".z");
525  // create input stream with binary mode operation and positioning at the end
526  // of the file
527  std::ifstream in(compfilename, std::ios::binary | std::ios::ate);
528  if (in.good()) {
529  // get current position in the stream (was set to the end)
530  int fileSize = in.tellg();
531  // set current position being the beginning of the stream
532  in.seekg(0,std::ios::beg);
533  // create (zlib) byte buffer for the data
534  Bytef *compdata = new Bytef[fileSize];
535  while(in) {
536  in.read((char*)compdata, fileSize);
537  }
538  // create (zlib) byte buffer for the uncompressed data
539  uLongf complen = (uLongf)(fileSize*4);
540  Bytef *uncompdata = new Bytef[complen];
541  while (Z_OK!=uncompress(uncompdata, &complen, compdata, fileSize)) {
542  // increase uncompressed byte buffer
543  delete[] uncompdata;
544  complen *= 2;
545  uncompdata = new Bytef[complen];
546  }
547  // delete the compressed data buffer
548  delete [] compdata;
549  // create a string from the uncompressed data (will be deleted by the caller)
550  dataString = new std::string((char*)uncompdata, (long)complen);
551  // delete the uncompressed data buffer
552  delete [] uncompdata;
553  } else {
554  std::string msg = " Problem while trying to read "
555  + compfilename + " data file.\n";
556  G4Exception("G4SBBremTable::ReadCompressedFile","em0006",
557  FatalException,msg.c_str());
558  return;
559  }
560  // create the input string stream from the data string
561  if (dataString) {
562  iss.str(*dataString);
563  in.close();
564  delete dataString;
565  }
566 }