00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 #include "G4EmModelManager.hh"
00079 #include "G4SystemOfUnits.hh"
00080 #include "G4PhysicsTable.hh"
00081 #include "G4PhysicsVector.hh"
00082
00083
00084
00085 G4RegionModels::G4RegionModels(G4int nMod, std::vector<G4int>& indx,
00086 G4DataVector& lowE, const G4Region* reg)
00087 {
00088 nModelsForRegion = nMod;
00089 theListOfModelIndexes = new G4int [nModelsForRegion];
00090 lowKineticEnergy = new G4double [nModelsForRegion+1];
00091 for (G4int i=0; i<nModelsForRegion; ++i) {
00092 theListOfModelIndexes[i] = indx[i];
00093 lowKineticEnergy[i] = lowE[i];
00094 }
00095 lowKineticEnergy[nModelsForRegion] = lowE[nModelsForRegion];
00096 theRegion = reg;
00097 }
00098
00099
00100
00101 G4RegionModels::~G4RegionModels()
00102 {
00103 delete [] theListOfModelIndexes;
00104 delete [] lowKineticEnergy;
00105 }
00106
00107
00108
00109 #include "G4Step.hh"
00110 #include "G4ParticleDefinition.hh"
00111 #include "G4PhysicsVector.hh"
00112 #include "G4Gamma.hh"
00113 #include "G4Positron.hh"
00114 #include "G4MaterialCutsCouple.hh"
00115 #include "G4ProductionCutsTable.hh"
00116 #include "G4RegionStore.hh"
00117 #include "G4Gamma.hh"
00118 #include "G4Positron.hh"
00119 #include "G4UnitsTable.hh"
00120 #include "G4DataVector.hh"
00121
00122
00123
00124 G4EmModelManager::G4EmModelManager():
00125 nEmModels(0),
00126 nRegions(0),
00127 particle(0),
00128 verboseLevel(0)
00129 {
00130 maxSubCutInRange = 0.7*mm;
00131 models.reserve(4);
00132 flucModels.reserve(4);
00133 regions.reserve(4);
00134 orderOfModels.reserve(4);
00135 isUsed.reserve(4);
00136 severalModels = true;
00137 fluoFlag = false;
00138 currRegionModel = 0;
00139 currModel = 0;
00140 theCuts = 0;
00141 theSubCuts = 0;
00142 }
00143
00144
00145
00146 G4EmModelManager::~G4EmModelManager()
00147 {
00148 verboseLevel = 0;
00149 Clear();
00150 delete theSubCuts;
00151 }
00152
00153
00154
00155 void G4EmModelManager::Clear()
00156 {
00157 if(1 < verboseLevel) {
00158 G4cout << "G4EmModelManager::Clear()" << G4endl;
00159 }
00160 size_t n = setOfRegionModels.size();
00161 if(n > 0) {
00162 for(size_t i=0; i<n; ++i) {
00163 delete setOfRegionModels[i];
00164 setOfRegionModels[i] = 0;
00165 }
00166 }
00167 }
00168
00169
00170
00171 void G4EmModelManager::AddEmModel(G4int num, G4VEmModel* p,
00172 G4VEmFluctuationModel* fm, const G4Region* r)
00173 {
00174 if(!p) {
00175 G4cout << "G4EmModelManager::AddEmModel WARNING: no model defined."
00176 << G4endl;
00177 return;
00178 }
00179 models.push_back(p);
00180 flucModels.push_back(fm);
00181 regions.push_back(r);
00182 orderOfModels.push_back(num);
00183 isUsed.push_back(0);
00184 p->DefineForRegion(r);
00185 ++nEmModels;
00186 }
00187
00188
00189
00190 void G4EmModelManager::UpdateEmModel(const G4String& nam,
00191 G4double emin, G4double emax)
00192 {
00193 if (nEmModels > 0) {
00194 for(G4int i=0; i<nEmModels; ++i) {
00195 if(nam == models[i]->GetName()) {
00196 models[i]->SetLowEnergyLimit(emin);
00197 models[i]->SetHighEnergyLimit(emax);
00198 break;
00199 }
00200 }
00201 }
00202 G4cout << "G4EmModelManager::UpdateEmModel WARNING: no model <"
00203 << nam << "> is found out"
00204 << G4endl;
00205 }
00206
00207
00208
00209 G4VEmModel* G4EmModelManager::GetModel(G4int i, G4bool ver)
00210 {
00211 G4VEmModel* model = 0;
00212 if(i >= 0 && i < nEmModels) { model = models[i]; }
00213 else if(verboseLevel > 0 && ver) {
00214 G4cout << "G4EmModelManager::GetModel WARNING: "
00215 << "index " << i << " is wrong Nmodels= "
00216 << nEmModels;
00217 if(particle) G4cout << " for " << particle->GetParticleName();
00218 G4cout<< G4endl;
00219 }
00220 return model;
00221 }
00222
00223
00224
00225 const G4DataVector*
00226 G4EmModelManager::Initialise(const G4ParticleDefinition* p,
00227 const G4ParticleDefinition* secondaryParticle,
00228 G4double minSubRange,
00229 G4int val)
00230 {
00231 verboseLevel = val;
00232 G4String partname = p->GetParticleName();
00233 if(1 < verboseLevel) {
00234 G4cout << "G4EmModelManager::Initialise() for "
00235 << partname << G4endl;
00236 }
00237
00238 if(nEmModels < 1) {
00239 G4ExceptionDescription ed;
00240 ed << "No models found out for " << p->GetParticleName()
00241 << " !" << G4endl;
00242 G4Exception("G4EmModelManager::Initialise","em0002",
00243 FatalException, ed);
00244 }
00245
00246 particle = p;
00247 Clear();
00248
00249 G4RegionStore* regionStore = G4RegionStore::GetInstance();
00250 const G4Region* world =
00251 regionStore->GetRegion("DefaultRegionForTheWorld", false);
00252
00253
00254 nRegions = 1;
00255 std::vector<const G4Region*> setr;
00256 setr.push_back(world);
00257 G4bool isWorld = false;
00258
00259 for (G4int ii=0; ii<nEmModels; ++ii) {
00260 const G4Region* r = regions[ii];
00261 if ( r == 0 || r == world) {
00262 isWorld = true;
00263 regions[ii] = world;
00264 } else {
00265 G4bool newRegion = true;
00266 if (nRegions>1) {
00267 for (G4int j=1; j<nRegions; ++j) {
00268 if ( r == setr[j] ) newRegion = false;
00269 }
00270 }
00271 if (newRegion) {
00272 setr.push_back(r);
00273 nRegions++;
00274 }
00275 }
00276 }
00277
00278 if(!isWorld) {
00279 G4ExceptionDescription ed;
00280 ed << "No models defined for the World volume for " << p->GetParticleName()
00281 << " !" << G4endl;
00282 G4Exception("G4EmModelManager::Initialise","em0002",
00283 FatalException, ed);
00284 }
00285
00286 G4ProductionCutsTable* theCoupleTable=
00287 G4ProductionCutsTable::GetProductionCutsTable();
00288 size_t numOfCouples = theCoupleTable->GetTableSize();
00289
00290
00291 if(nRegions > 1 && nEmModels > 1) {
00292 if(numOfCouples > idxOfRegionModels.size()) {
00293 idxOfRegionModels.resize(numOfCouples);
00294 }
00295 }
00296 size_t nr = 1;
00297 if(nEmModels > 1) { nr = nRegions; }
00298 if(nr > setOfRegionModels.size()) { setOfRegionModels.resize(nr); }
00299
00300 std::vector<G4int> modelAtRegion(nEmModels);
00301 std::vector<G4int> modelOrd(nEmModels);
00302 G4DataVector eLow(nEmModels+1);
00303 G4DataVector eHigh(nEmModels);
00304
00305
00306 for (G4int reg=0; reg<nRegions; ++reg) {
00307 const G4Region* region = setr[reg];
00308 G4int n = 0;
00309
00310 for (G4int ii=0; ii<nEmModels; ++ii) {
00311
00312 G4VEmModel* model = models[ii];
00313 if ( region == regions[ii] ) {
00314
00315 G4double tmin = model->LowEnergyLimit();
00316 G4double tmax = model->HighEnergyLimit();
00317 G4int ord = orderOfModels[ii];
00318 G4bool push = true;
00319 G4bool insert = false;
00320 G4int idx = n;
00321
00322 if(1 < verboseLevel) {
00323 G4cout << "Model #" << ii
00324 << " <" << model->GetName() << "> for region <";
00325 if (region) G4cout << region->GetName();
00326 G4cout << "> "
00327 << " tmin(MeV)= " << tmin/MeV
00328 << "; tmax(MeV)= " << tmax/MeV
00329 << "; order= " << ord
00330 << G4endl;
00331 }
00332
00333 if(n > 0) {
00334
00335
00336 tmin = std::min(tmin, eHigh[n-1]);
00337 tmax = std::max(tmax, eLow[0]);
00338
00339
00340
00341 if( tmax - tmin <= eV) push = false;
00342
00343 else if (tmax == eLow[0]) {
00344 push = false;
00345 insert = true;
00346 idx = 0;
00347
00348 } else if(tmin < eHigh[n-1]) {
00349
00350 for(G4int k=0; k<n; ++k) {
00351
00352 if(ord >= modelOrd[k]) {
00353 if(tmin < eHigh[k] && tmin >= eLow[k]) tmin = eHigh[k];
00354 if(tmax <= eHigh[k] && tmax > eLow[k]) tmax = eLow[k];
00355 if(tmax > eHigh[k] && tmin < eLow[k]) {
00356 if(tmax - eHigh[k] > eLow[k] - tmin) tmin = eHigh[k];
00357 else tmax = eLow[k];
00358 }
00359 if( tmax - tmin <= eV) {
00360 push = false;
00361 break;
00362 }
00363 }
00364 }
00365
00366
00367 if(push) {
00368 if (tmax == eLow[0]) {
00369 push = false;
00370 insert = true;
00371 idx = 0;
00372
00373 } else if(tmin < eHigh[n-1]) {
00374
00375 if(tmin > eLow[n-1] && tmax >= eHigh[n-1]) {
00376 eHigh[n-1] = tmin;
00377
00378 } else if(tmin <= eLow[0] && tmax < eHigh[0]) {
00379 eLow[0] = tmax;
00380 push = false;
00381 insert = true;
00382 idx = 0;
00383 } else {
00384
00385 for(G4int k=0; k<n; ++k) {
00386 if(tmin <= eLow[k] && tmax >= eHigh[k]) {
00387 push = false;
00388 modelAtRegion[k] = ii;
00389 modelOrd[k] = ord;
00390 isUsed[ii] = 1;
00391 }
00392 }
00393 }
00394 }
00395 }
00396 }
00397 }
00398 if(insert) {
00399 for(G4int k=n-1; k>=idx; --k) {
00400 modelAtRegion[k+1] = modelAtRegion[k];
00401 modelOrd[k+1] = modelOrd[k];
00402 eLow[k+1] = eLow[k];
00403 eHigh[k+1] = eHigh[k];
00404 }
00405 }
00406
00407
00408 if (push || insert) {
00409 ++n;
00410 modelAtRegion[idx] = ii;
00411 modelOrd[idx] = ord;
00412 eLow[idx] = tmin;
00413 eHigh[idx] = tmax;
00414 isUsed[ii] = 1;
00415 }
00416 }
00417 }
00418 eLow[0] = 0.0;
00419 eLow[n] = eHigh[n-1];
00420
00421 if(1 < verboseLevel) {
00422 G4cout << "New G4RegionModels set with " << n << " models for region <";
00423 if (region) G4cout << region->GetName();
00424 G4cout << "> Elow(MeV)= ";
00425 for(G4int ii=0; ii<=n; ++ii) {G4cout << eLow[ii]/MeV << " ";}
00426 G4cout << G4endl;
00427 }
00428 G4RegionModels* rm = new G4RegionModels(n, modelAtRegion, eLow, region);
00429 setOfRegionModels[reg] = rm;
00430 if(1 == nEmModels) { break; }
00431 }
00432
00433 currRegionModel = setOfRegionModels[0];
00434
00435
00436 size_t idx = 1;
00437 if(secondaryParticle) {
00438 if( secondaryParticle == G4Gamma::Gamma() ) { idx = 0; }
00439 else if( secondaryParticle == G4Positron::Positron()) { idx = 2; }
00440 }
00441
00442
00443 theCuts = static_cast<const G4DataVector*>(theCoupleTable->GetEnergyCutsVector(idx));
00444
00445 if(minSubRange < 1.0) {
00446 if( !theSubCuts ) { theSubCuts = new G4DataVector(); }
00447 theSubCuts->resize(numOfCouples,DBL_MAX);
00448 }
00449 for(size_t i=0; i<numOfCouples; ++i) {
00450
00451 const G4MaterialCutsCouple* couple =
00452 theCoupleTable->GetMaterialCutsCouple(i);
00453 const G4Material* material = couple->GetMaterial();
00454 const G4ProductionCuts* pcuts = couple->GetProductionCuts();
00455
00456 G4int reg = 0;
00457 if(nRegions > 1 && nEmModels > 1) {
00458 reg = nRegions;
00459 do {--reg;} while (reg>0 && pcuts != (setr[reg]->GetProductionCuts()));
00460 idxOfRegionModels[i] = reg;
00461 }
00462 if(1 < verboseLevel) {
00463 G4cout << "G4EmModelManager::Initialise() for "
00464 << material->GetName()
00465 << " indexOfCouple= " << i
00466 << " indexOfRegion= " << reg
00467 << G4endl;
00468 }
00469
00470 G4double cut = (*theCuts)[i];
00471 if(secondaryParticle) {
00472
00473
00474 if( cut < DBL_MAX && minSubRange < 1.0) {
00475 G4double subcut = minSubRange*cut;
00476 G4double rcut = std::min(minSubRange*pcuts->GetProductionCut(idx),
00477 maxSubCutInRange);
00478 G4double tcutmax =
00479 theCoupleTable->ConvertRangeToEnergy(secondaryParticle,material,rcut);
00480 if(tcutmax < subcut) { subcut = tcutmax; }
00481 (*theSubCuts)[i] = subcut;
00482 }
00483 }
00484 }
00485
00486
00487 G4int nn = 0;
00488 severalModels = true;
00489 for(G4int jj=0; jj<nEmModels; ++jj) {
00490 if(1 == isUsed[jj]) {
00491 ++nn;
00492 currModel = models[jj];
00493 currModel->Initialise(particle, *theCuts);
00494 if(flucModels[jj]) { flucModels[jj]->InitialiseMe(particle); }
00495 }
00496 }
00497 if(1 == nn) { severalModels = false; }
00498
00499 if(1 < verboseLevel) {
00500 G4cout << "G4EmModelManager for " << particle->GetParticleName()
00501 << " is initialised; nRegions= " << nRegions
00502 << G4endl;
00503 }
00504
00505 return theCuts;
00506 }
00507
00508
00509
00510 void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
00511 const G4MaterialCutsCouple* couple,
00512 G4EmTableType tType)
00513 {
00514 size_t i = couple->GetIndex();
00515 G4double cut = (*theCuts)[i];
00516 G4double emin = 0.0;
00517
00518 if(fTotal == tType) { cut = DBL_MAX; }
00519 else if(fSubRestricted == tType) {
00520 emin = cut;
00521 if(theSubCuts) { emin = (*theSubCuts)[i]; }
00522 }
00523
00524 if(1 < verboseLevel) {
00525 G4cout << "G4EmModelManager::FillDEDXVector() for "
00526 << couple->GetMaterial()->GetName()
00527 << " cut(MeV)= " << cut
00528 << " emin(MeV)= " << emin
00529 << " Type " << tType
00530 << " for " << particle->GetParticleName()
00531 << G4endl;
00532 }
00533
00534 G4int reg = 0;
00535 if(nRegions > 1 && nEmModels > 1) { reg = idxOfRegionModels[i]; }
00536 const G4RegionModels* regModels = setOfRegionModels[reg];
00537 G4int nmod = regModels->NumberOfModels();
00538
00539
00540
00541
00542 size_t totBinsLoss = aVector->GetVectorLength();
00543 G4double del = 0.0;
00544 G4int k0 = 0;
00545
00546 for(size_t j=0; j<totBinsLoss; ++j) {
00547
00548 G4double e = aVector->Energy(j);
00549
00550
00551 G4int k = 0;
00552 if (nmod > 1) {
00553 k = nmod;
00554 do {--k;} while (k>0 && e <= regModels->LowEdgeEnergy(k));
00555
00556 if(k > 0 && k != k0) {
00557 k0 = k;
00558 G4double elow = regModels->LowEdgeEnergy(k);
00559 G4double dedx1 = ComputeDEDX(models[regModels->ModelIndex(k-1)],
00560 couple,elow,cut,emin);
00561 G4double dedx2 = ComputeDEDX(models[regModels->ModelIndex(k)],
00562 couple,elow,cut,emin);
00563 del = 0.0;
00564 if(dedx2 > 0.0) { del = (dedx1/dedx2 - 1.0)*elow; }
00565
00566
00567 }
00568 }
00569 G4double dedx =
00570 ComputeDEDX(models[regModels->ModelIndex(k)],couple,e,cut,emin);
00571 dedx *= (1.0 + del/e);
00572
00573 if(2 < verboseLevel) {
00574 G4cout << "Material= " << couple->GetMaterial()->GetName()
00575 << " E(MeV)= " << e/MeV
00576 << " dEdx(MeV/mm)= " << dedx*mm/MeV
00577 << " del= " << del*mm/MeV<< " k= " << k
00578 << " modelIdx= " << regModels->ModelIndex(k)
00579 << G4endl;
00580 }
00581 if(dedx < 0.0) { dedx = 0.0; }
00582 aVector->PutValue(j, dedx);
00583 }
00584 }
00585
00586
00587
00588 void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
00589 const G4MaterialCutsCouple* couple,
00590 G4bool startFromNull,
00591 G4EmTableType tType)
00592 {
00593 size_t i = couple->GetIndex();
00594 G4double cut = (*theCuts)[i];
00595 G4double tmax = DBL_MAX;
00596 if (fSubRestricted == tType) {
00597 tmax = cut;
00598 if(theSubCuts) { cut = (*theSubCuts)[i]; }
00599 }
00600
00601 G4int reg = 0;
00602 if(nRegions > 1 && nEmModels > 1) { reg = idxOfRegionModels[i]; }
00603 const G4RegionModels* regModels = setOfRegionModels[reg];
00604 G4int nmod = regModels->NumberOfModels();
00605 if(1 < verboseLevel) {
00606 G4cout << "G4EmModelManager::FillLambdaVector() for "
00607 << particle->GetParticleName()
00608 << " in " << couple->GetMaterial()->GetName()
00609 << " Ecut(MeV)= " << cut
00610 << " Emax(MeV)= " << tmax
00611 << " Type " << tType
00612 << " nmod= " << nmod
00613 << G4endl;
00614 }
00615
00616
00617 size_t totBinsLambda = aVector->GetVectorLength();
00618 G4double del = 0.0;
00619 G4int k0 = 0;
00620 G4int k = 0;
00621 G4VEmModel* mod = models[regModels->ModelIndex(0)];
00622 for(size_t j=0; j<totBinsLambda; ++j) {
00623
00624 G4double e = aVector->Energy(j);
00625
00626
00627 if (nmod > 1) {
00628 k = nmod;
00629 do {--k;} while (k>0 && e <= regModels->LowEdgeEnergy(k));
00630 if(k > 0 && k != k0) {
00631 k0 = k;
00632 G4double elow = regModels->LowEdgeEnergy(k);
00633 G4VEmModel* mod1 = models[regModels->ModelIndex(k-1)];
00634 G4double xs1 = mod1->CrossSection(couple,particle,elow,cut,tmax);
00635 mod = models[regModels->ModelIndex(k)];
00636 G4double xs2 = mod->CrossSection(couple,particle,elow,cut,tmax);
00637 del = 0.0;
00638 if(xs2 > 0.0) { del = (xs1/xs2 - 1.0)*elow; }
00639
00640
00641 }
00642 }
00643 G4double cross = mod->CrossSection(couple,particle,e,cut,tmax);
00644 cross *= (1.0 + del/e);
00645 if(fIsCrossSectionPrim == tType) { cross *= e; }
00646
00647 if(j==0 && startFromNull) { cross = 0.0; }
00648
00649 if(2 < verboseLevel) {
00650 G4cout << "FillLambdaVector: " << j << ". e(MeV)= " << e/MeV
00651 << " cross(1/mm)= " << cross*mm
00652 << " del= " << del*mm << " k= " << k
00653 << " modelIdx= " << regModels->ModelIndex(k)
00654 << G4endl;
00655 }
00656 if(cross < 0.0) { cross = 0.0; }
00657 aVector->PutValue(j, cross);
00658 }
00659 }
00660
00661
00662
00663 void G4EmModelManager::DumpModelList(G4int verb)
00664 {
00665 if(verb == 0) { return; }
00666 for(G4int i=0; i<nRegions; ++i) {
00667 G4RegionModels* r = setOfRegionModels[i];
00668 const G4Region* reg = r->Region();
00669 G4int n = r->NumberOfModels();
00670 if(n > 0) {
00671 G4cout << " ===== EM models for the G4Region " << reg->GetName()
00672 << " ======" << G4endl;;
00673 for(G4int j=0; j<n; ++j) {
00674 G4VEmModel* model = models[r->ModelIndex(j)];
00675 G4double emin =
00676 std::max(r->LowEdgeEnergy(j),model->LowEnergyActivationLimit());
00677 G4double emax =
00678 std::min(r->LowEdgeEnergy(j+1),model->HighEnergyActivationLimit());
00679 G4cout << std::setw(20);
00680 G4cout << model->GetName() << " : Emin= "
00681 << std::setw(8) << G4BestUnit(emin,"Energy")
00682 << " Emax= "
00683 << std::setw(8) << G4BestUnit(emax,"Energy");
00684 G4PhysicsTable* table = model->GetCrossSectionTable();
00685 if(table) {
00686 size_t kk = table->size();
00687 for(size_t k=0; k<kk; ++k) {
00688 G4PhysicsVector* v = (*table)[k];
00689 if(v) {
00690 G4int nn = v->GetVectorLength() - 1;
00691 G4cout << " Table with " << nn << " bins Emin= "
00692 << std::setw(6) << G4BestUnit(v->Energy(0),"Energy")
00693 << " Emax= "
00694 << std::setw(6) << G4BestUnit(v->Energy(nn),"Energy");
00695 break;
00696 }
00697 }
00698 }
00699 G4VEmAngularDistribution* an = model->GetAngularDistribution();
00700 if(an) { G4cout << " " << an->GetName(); }
00701 if(fluoFlag && model->DeexcitationFlag()) { G4cout << " FluoActive"; }
00702 G4cout << G4endl;
00703 }
00704 }
00705 if(1 == nEmModels) { break; }
00706 }
00707 }
00708
00709