source: trunk/source/processes/hadronic/management/src/G4HadronicProcess.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: 27.9 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
28#include "G4Types.hh"
29
30//#include <fstream>
31//#include <sstream>
32//#include <stdlib.h>
33#include "G4HadronicProcess.hh"
34
35#include "G4HadProjectile.hh"
36#include "G4ElementVector.hh"
37#include "G4Track.hh"
38#include "G4Step.hh"
39#include "G4Element.hh"
40#include "G4ParticleChange.hh"
41#include "G4TransportationManager.hh"
42#include "G4Navigator.hh"
43#include "G4ProcessVector.hh"
44#include "G4ProcessManager.hh"
45#include "G4StableIsotopes.hh"
46#include "G4HadTmpUtil.hh"
47#include "G4NucleiProperties.hh"
48
49//VI #include "G4HadLeadBias.hh"
50#include "G4HadronicException.hh"
51//VI #include "G4HadReentrentException.hh"
52//VI #include "G4HadronicWhiteBoard.hh"
53//VI #include "G4HadSignalHandler.hh"
54#include "G4HadronicProcessStore.hh"
55
56
57/*VI
58
59namespace G4HadronicProcess_local
60{
61  extern "C" void G4HadronicProcessHandler_1(int)
62  {
63    G4HadronicWhiteBoard::Instance().Dump();
64  }
65}
66VI*/
67
68G4IsoParticleChange * G4HadronicProcess::theIsoResult = 0;
69G4IsoParticleChange * G4HadronicProcess::theOldIsoResult = 0;
70G4bool G4HadronicProcess::isoIsEnabled = true;
71
72void G4HadronicProcess::
73EnableIsotopeProductionGlobally()  {isoIsEnabled = true;}
74
75void G4HadronicProcess::
76DisableIsotopeProductionGlobally() {isoIsEnabled = false;}
77
78//////////////////////////////////////////////////////////////////
79
80G4HadronicProcess::G4HadronicProcess(const G4String& processName,
81                                     G4ProcessType aType)
82 :G4VDiscreteProcess(processName, aType)
83{
84  ModelingState = 0;
85  isoIsOnAnyway = -1;
86  theTotalResult = new G4ParticleChange();
87  theInteraction = 0;
88  theCrossSectionDataStore = new G4CrossSectionDataStore();
89  G4HadronicProcessStore::Instance()->Register(this);
90  aScaleFactor = 1;
91  xBiasOn = false;
92  G4HadronicProcess_debug_flag = false;
93  epReportLevel = 0;
94  epCheckLevels.first = DBL_MAX;
95  epCheckLevels.second = DBL_MAX;
96  levelsSetByProcess = false;
97
98  //VI   if(getenv("SwitchLeadBiasOn")) theBias.push_back(new G4HadLeadBias());
99}
100
101G4HadronicProcess::~G4HadronicProcess()
102{ 
103  G4HadronicProcessStore::Instance()->DeRegister(this);
104  delete theTotalResult;
105
106  std::for_each(theProductionModels.begin(),
107                theProductionModels.end(), G4Delete());
108  //VI  std::for_each(theBias.begin(), theBias.end(), G4Delete());
109 
110  delete theOldIsoResult; 
111  delete theIsoResult;
112  delete theCrossSectionDataStore;
113}
114
115void G4HadronicProcess::RegisterMe( G4HadronicInteraction *a )
116{ 
117  if(!a) { return; }
118  try{GetManagerPointer()->RegisterMe( a );}   
119  catch(G4HadronicException & aE)
120  {
121    G4cout << "Unrecoverable error in " << GetProcessName() 
122           << " to register " << a->GetModelName() << G4endl;
123    G4Exception("G4HadronicProcess", "007", FatalException,
124    "Could not register G4HadronicInteraction");
125  }
126  G4HadronicProcessStore::Instance()->RegisterInteraction(this, a); 
127}
128
129void G4HadronicProcess::PreparePhysicsTable(const G4ParticleDefinition& p)
130{
131  if(getenv("G4HadronicProcess_debug")) G4HadronicProcess_debug_flag = true;
132  G4HadronicProcessStore::Instance()->RegisterParticle(this, &p);
133}
134
135void G4HadronicProcess::BuildPhysicsTable(const G4ParticleDefinition& p)
136{
137  theCrossSectionDataStore->BuildPhysicsTable(p);
138  G4HadronicProcessStore::Instance()->PrintInfo(&p);
139}
140
141G4double G4HadronicProcess::
142GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *)
143{ 
144  try
145  {
146    //VI ModelingState = 1;   
147    theLastCrossSection = aScaleFactor* 
148      theCrossSectionDataStore->GetCrossSection(aTrack.GetDynamicParticle(), 
149                                                aTrack.GetMaterial());
150  }
151  catch(G4HadronicException aR)
152  { 
153    DumpState(aTrack,"GetMeanFreePath");
154    G4Exception("G4HadronicProcess", "007", FatalException,
155    "G4HadronicProcess::GetMeanFreePath failed");
156  } 
157  G4double res = DBL_MAX;
158  if( theLastCrossSection > 0.0 ) { res = 1.0/theLastCrossSection; }
159  return res;
160}
161
162G4double G4HadronicProcess::
163GetMicroscopicCrossSection(const G4DynamicParticle *aParticle, 
164                           const G4Element *anElement, 
165                           G4double aTemp )
166{
167  return
168    theCrossSectionDataStore->GetCrossSection(aParticle, anElement, aTemp);
169}
170
171G4VParticleChange *G4HadronicProcess::PostStepDoIt(
172                   const G4Track &aTrack, const G4Step &)
173{
174  // Debugging stuff
175  //VI if(G4HadronicProcess_debug_flag)
176  //VI       std::cout << "@@@@ hadronic process start "<< std::endl;
177  // G4cout << theNumberOfInteractionLengthLeft<<G4endl;
178  //VI #ifndef G4HadSignalHandler_off
179  //VI G4HadSignalHandler aHandler(G4HadronicProcess_local::G4HadronicProcessHandler_1);
180  //VI #endif
181
182  if(aTrack.GetTrackStatus() != fAlive && aTrack.GetTrackStatus() != fSuspend) {
183    if (aTrack.GetTrackStatus() == fStopAndKill ||
184        aTrack.GetTrackStatus() == fKillTrackAndSecondaries ||
185        aTrack.GetTrackStatus() == fPostponeToNextEvent) {
186      G4cout << "G4HadronicProcess: track in unusable state - "
187             << aTrack.GetTrackStatus() << G4endl;
188      G4cout << "G4HadronicProcess: returning unchanged track " << G4endl;
189      DumpState(aTrack,"PostStepDoIt");
190      G4Exception("G4HadronicProcess", "001", JustWarning, "bailing out");
191    }
192    // No warning for fStopButAlive which is a legal status here
193    theTotalResult->Clear();
194    theTotalResult->Initialize(aTrack);
195    return theTotalResult;
196  }
197
198  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
199  G4Material* aMaterial = aTrack.GetMaterial();
200  G4double originalEnergy = aParticle->GetKineticEnergy();
201  G4double kineticEnergy = originalEnergy;
202
203  /*
204  // It is not needed with standard NaN check
205  // More debugging 
206  G4Nancheck go_wild;
207  if(go_wild(originalEnergy) ||
208    go_wild(aParticle->Get4Momentum().x()) ||
209  go_wild(aParticle->Get4Momentum().y()) ||
210  go_wild(aParticle->Get4Momentum().z()) ||
211  go_wild(aParticle->Get4Momentum().t())
212  )
213  {
214    G4Exception("G4HadronicProcess", "001", JustWarning, "NaN in input energy or momentum - bailing out.");
215    theTotalResult->Clear();
216    theTotalResult->Initialize(aTrack);
217    return theTotalResult;
218  }
219  */
220
221  // Get kinetic energy per nucleon for ions
222  if(aParticle->GetDefinition()->GetBaryonNumber() > 1.5)
223          kineticEnergy/=aParticle->GetDefinition()->GetBaryonNumber();
224
225  G4Element* anElement = 0;
226  try
227  {
228    //    anElement = ChooseAandZ( aParticle, aMaterial );
229    anElement = theCrossSectionDataStore->SampleZandA(aParticle, 
230                                                      aMaterial, 
231                                                      targetNucleus);
232  }
233  catch(G4HadronicException & aR)
234  {
235    DumpState(aTrack,"SampleZandA");
236    //VI    G4cout << "Unrecoverable error for:"<<G4endl;
237    //VI G4cout << " - Particle energy[GeV] = "<< originalEnergy/GeV<<G4endl;
238    //VI G4cout << " - Material = "<<aMaterial->GetName()<<G4endl;
239    //VI G4cout << " - Particle type = "
240    //VI <<aParticle->GetDefinition()->GetParticleName()<<G4endl;
241    G4Exception("G4HadronicProcess", "007", FatalException,
242    "PostStepDoIt failed on element selection.");
243  }
244
245  try
246  {
247    theInteraction = 
248      ChooseHadronicInteraction( kineticEnergy, aMaterial, anElement );
249  }
250  catch(G4HadronicException & aE)
251  {
252    G4cout << "Target element "<<anElement->GetName()<<"  Z= " 
253           << targetNucleus.GetZ() << "  A= " << targetNucleus.GetN() << G4endl;
254    DumpState(aTrack,"ChooseHadronicInteraction");
255    //VI G4cout << " - Particle energy[GeV] = "<< originalEnergy/GeV<<G4endl;
256    //VI G4cout << " - Material = "<<aMaterial->GetName()<<G4endl;
257    //VI G4cout << " - Particle type = "
258    //VI       << aParticle->GetDefinition()->GetParticleName()<<G4endl;
259    G4Exception("G4HadronicProcess", "007", FatalException,
260    "ChooseHadronicInteraction failed.");
261  }
262
263  // Initialize the hadronic projectile from the track
264
265  G4HadProjectile thePro(aTrack);
266 
267  G4HadFinalState* result = 0;
268  G4int reentryCount = 0;
269
270  do
271  {
272    try
273    {
274      // Call the interaction
275      result = theInteraction->ApplyYourself( thePro, targetNucleus);
276      ++reentryCount;
277    }
278    /*VI
279    catch(G4HadReentrentException aR)
280    {
281      G4HadronicWhiteBoard & theBoard = G4HadronicWhiteBoard::Instance();
282      theBoard.SetProjectile(thePro);
283      theBoard.SetTargetNucleus(targetNucleus);
284      theBoard.SetProcessName(GetProcessName());
285      theBoard.SetModelName(theInteraction->GetModelName());
286
287      aR.Report(G4cout);
288      G4cout << " G4HadronicProcess re-entering the ApplyYourself call for "
289             <<G4endl;
290      G4cout << " - Particle energy[GeV] = "<< originalEnergy/GeV<<G4endl;
291      G4cout << " - Material = "<<aMaterial->GetName()<<G4endl;
292      G4cout << " - Particle type = "
293             << aParticle->GetDefinition()->GetParticleName() << G4endl;
294      result = 0; // here would still be leaking...
295      G4Exception("G4HadronicProcess", "007", FatalException,
296      "GetHadronicProcess: PostStepDoIt failed (Reentering ApplyYourself not yet supported.)"); 
297    }
298    VI*/
299    catch(G4HadronicException aR)
300    {
301      //VI G4HadronicWhiteBoard & theBoard = G4HadronicWhiteBoard::Instance();
302      //VI theBoard.SetProjectile(thePro);
303      //VI theBoard.SetTargetNucleus(targetNucleus);
304      //VI theBoard.SetProcessName(GetProcessName());
305      //VI theBoard.SetModelName(theInteraction->GetModelName());
306
307      G4cout << "Call for " << theInteraction->GetModelName() << G4endl;
308      G4cout << "Target element "<<anElement->GetName()<<"  Z= " 
309             << targetNucleus.GetZ() << "  A= " << targetNucleus.GetN() << G4endl;
310      DumpState(aTrack,"ApplyYourself");
311      //VI G4cout << " - Particle energy[GeV] = "<< originalEnergy/GeV<<G4endl;
312      //VI G4cout << " - Material = "<<aMaterial->GetName()<<G4endl;
313      //VI G4cout << " - Particle type = "
314      //VI        << aParticle->GetDefinition()->GetParticleName() << G4endl;
315      G4Exception("G4HadronicProcess", "007", FatalException,
316      "PostStepDoIt failed.");
317    }
318    if(reentryCount>100) {
319      G4cout << "Call for " << theInteraction->GetModelName() << G4endl;
320      G4cout << "Target element "<<anElement->GetName()<<"  Z= " 
321             << targetNucleus.GetZ() << "  A= " << targetNucleus.GetN() << G4endl;
322      DumpState(aTrack,"ApplyYourself");
323      G4Exception("G4HadronicProcess", "007", FatalException,
324                  "Reentering ApplyYourself too often - PostStepDoIt failed."); 
325    }
326  }
327  while(!result);
328
329  //VI if(!ModelingState && !getenv("BypassAllSafetyChecks") )
330  //VI{
331  //VI  G4cout << "ERROR IN EXECUTION -- HADRONIC PROCESS STATE NOT VALID"<<G4endl;
332  //VI  G4cout << "Result will be of undefined quality."<<G4endl;
333  //VI}
334
335  // NOT USED ?? Projectile particle has changed character during interaction
336  //VI if(result->GetStatusChange() == isAlive &&
337  //VI    thePro.GetDefinition() != aTrack.GetDefinition())
338  //VI {
339  //VI  G4DynamicParticle * aP =
340  //VI           const_cast<G4DynamicParticle *>(aTrack.GetDynamicParticle());
341  //VI   aP->SetDefinition(const_cast<G4ParticleDefinition *>(thePro.GetDefinition()));
342  //VI }
343
344  result->SetTrafoToLab(thePro.GetTrafoToLab());
345
346  /*VI
347  if(getenv("HadronicDoitLogging") )
348  {
349    G4cout << "HadronicDoitLogging "
350           << GetProcessName() <<" "
351           << aParticle->GetDefinition()->GetPDGEncoding()<<" "
352           << originalEnergy<<" "
353           << aParticle->GetMomentum()<<" "
354           << targetNucleus.GetN()<<" "
355           << targetNucleus.GetZ()<<" "
356           << G4endl;
357  }
358  VI*/
359
360  ClearNumberOfInteractionLengthLeft();
361  if(isoIsOnAnyway!=-1)
362  {
363    if(isoIsEnabled||isoIsOnAnyway)
364    {
365      result = DoIsotopeCounting(result, aTrack, targetNucleus);
366    }
367  }
368 
369  /*VI
370  G4double e=aTrack.GetKineticEnergy();
371  ModelingState = 0;
372  if(e<5*GeV)
373  {
374    for(size_t i=0; i<theBias.size(); i++)
375    {
376      result = theBias[i]->Bias(result);
377    }
378  }
379  VI*/
380  // Put hadronic final state particles into G4ParticleChange
381
382  FillTotalResult(result, aTrack);
383  //VI if(G4HadronicProcess_debug_flag)
384  //VI  std::cout << "@@@@ hadronic process end "<< std::endl;
385
386  if (epReportLevel > 0) CheckEnergyMomentumConservation(aTrack, targetNucleus);
387 
388  return theTotalResult;
389}
390
391#include <typeinfo>
392
393G4HadFinalState* 
394G4HadronicProcess::DoIsotopeCounting(G4HadFinalState * aResult,
395                                     const G4Track & aTrack,
396                                     const G4Nucleus & aNucleus)
397{
398  // get the PC from iso-production
399  delete theOldIsoResult;
400  theOldIsoResult = 0;
401  delete theIsoResult;
402  theIsoResult = new G4IsoParticleChange;
403  G4bool done = false;
404  G4IsoResult * anIsoResult = 0;
405  for(unsigned int i=0; i<theProductionModels.size(); i++)
406  {
407    anIsoResult = theProductionModels[i]->GetIsotope(aTrack, aNucleus);
408    if(anIsoResult!=0)
409    {
410      done = true;
411      break;
412    }
413  }
414
415  // If no production models active, use default iso production
416  if(!done) anIsoResult = ExtractResidualNucleus(aTrack, aNucleus, aResult); 
417
418  // Add all info explicitely and add typename from model called.
419  theIsoResult->SetIsotope(anIsoResult->GetIsotope());
420  theIsoResult->SetProductionPosition(aTrack.GetPosition());
421  theIsoResult->SetProductionTime(aTrack.GetGlobalTime());
422  theIsoResult->SetParentParticle(*aTrack.GetDynamicParticle());
423  theIsoResult->SetMotherNucleus(anIsoResult->GetMotherNucleus());
424  theIsoResult->SetProducer(typeid(*theInteraction).name());
425 
426  delete anIsoResult;
427
428  // If isotope production is enabled the GetIsotopeProductionInfo()
429  // method must be called or else a memory leak will result
430  //
431  // The following code will fix the memory leak, but remove the
432  // isotope information:
433  //
434  //  if(theIsoResult) {
435  //    delete theIsoResult;
436  //    theIsoResult = 0;
437  //  }
438 
439  return aResult;
440}
441
442G4IsoResult* 
443G4HadronicProcess::ExtractResidualNucleus(const G4Track&,
444                                          const G4Nucleus& aNucleus,
445                                          G4HadFinalState* aResult)
446{
447  G4double A = aNucleus.GetN();
448  G4double Z = aNucleus.GetZ();
449  G4double bufferA = 0;
450  G4double bufferZ = 0;
451 
452  // loop over aResult, and decrement A, Z accordingly
453  // cash the max
454  for(G4int i=0; i<aResult->GetNumberOfSecondaries(); i++)
455  {
456    G4HadSecondary* aSecTrack = aResult->GetSecondary(i);
457    if(bufferA<aSecTrack->GetParticle()->GetDefinition()->GetBaryonNumber())
458    {
459      bufferA = aSecTrack->GetParticle()->GetDefinition()->GetBaryonNumber();
460      bufferZ = aSecTrack->GetParticle()->GetDefinition()->GetPDGCharge();
461    }
462    Z-=aSecTrack->GetParticle()->GetDefinition()->GetPDGCharge();
463    A-=aSecTrack->GetParticle()->GetDefinition()->GetBaryonNumber();
464  }
465 
466  // if the fragment was part of the final state, it is
467  // assumed to be the heaviest secondary.
468  if(A<0.1)
469  {
470    A = bufferA;
471    Z = bufferZ;
472  }
473 
474  // prepare the IsoResult.
475
476  std::ostringstream ost1;
477  ost1 <<Z<<"_"<<A;
478  G4String biff = ost1.str();
479  G4IsoResult * theResult = new G4IsoResult(biff, aNucleus);
480
481  return theResult;
482}
483
484G4double G4HadronicProcess::XBiasSurvivalProbability()
485{
486  G4double result = 0;
487  G4double nLTraversed = GetTotalNumberOfInteractionLengthTraversed();
488  G4double biasedProbability = 1.-std::exp(-nLTraversed);
489  G4double realProbability = 1-std::exp(-nLTraversed/aScaleFactor);
490  result = (biasedProbability-realProbability)/biasedProbability;
491  return result;
492}
493
494G4double G4HadronicProcess::XBiasSecondaryWeight()
495{
496  G4double result = 0;
497  G4double nLTraversed = GetTotalNumberOfInteractionLengthTraversed();
498  result = 
499     1./aScaleFactor*std::exp(-nLTraversed/aScaleFactor*(1-1./aScaleFactor));
500  return result;
501}
502
503void 
504G4HadronicProcess::FillTotalResult(G4HadFinalState * aR, const G4Track & aT)
505{
506  //  G4Nancheck go_wild;
507  theTotalResult->Clear();
508  theTotalResult->ProposeLocalEnergyDeposit(0.);
509  theTotalResult->Initialize(aT);
510  theTotalResult->SetSecondaryWeightByProcess(true);
511  theTotalResult->ProposeTrackStatus(fAlive);
512  G4double rotation = CLHEP::twopi*G4UniformRand();
513  G4ThreeVector it(0., 0., 1.);
514
515  /*
516  if(xBiasOn)
517  {
518    G4cout << "BiasDebug "<<GetProcessName()<<" "
519    <<aScaleFactor<<" "
520    <<XBiasSurvivalProbability()<<" "
521    <<XBiasSecondaryWeight()<<" "
522    <<G4endl;
523  }
524  */
525  // if(GetProcessName() != "LElastic") std::cout << "Debug -1 "<<aR->GetStatusChange()<<std::endl;
526  if(aR->GetStatusChange()==stopAndKill)
527  {
528    if( xBiasOn && G4UniformRand()<XBiasSurvivalProbability() )
529    {
530      theTotalResult->ProposeParentWeight( XBiasSurvivalProbability()*aT.GetWeight() );
531    }
532    else
533    {
534      theTotalResult->ProposeTrackStatus(fStopAndKill);
535      theTotalResult->ProposeEnergy( 0.0 );
536    }
537  }
538  else if(aR->GetStatusChange()!=stopAndKill )
539  {
540    if(aR->GetStatusChange()==suspend)
541    {
542      theTotalResult->ProposeTrackStatus(fSuspend);
543      if(xBiasOn)
544      {
545        DumpState(aT,"FillTotalResult");
546        G4Exception("G4HadronicProcess", "007", FatalException,
547        "Cannot cross-section bias a process that suspends tracks.");
548      }
549    } else if (aT.GetKineticEnergy() == 0) {
550      theTotalResult->ProposeTrackStatus(fStopButAlive);
551    }
552
553    if(xBiasOn && G4UniformRand()<XBiasSurvivalProbability())
554    {
555      theTotalResult->ProposeParentWeight( XBiasSurvivalProbability()*aT.GetWeight() );
556      G4double newWeight = aR->GetWeightChange()*aT.GetWeight();
557      /*
558      if(go_wild(aR->GetEnergyChange()))
559      {
560        G4Exception("G4HadronicProcess", "007", FatalException,
561        "surviving track received NaN energy."); 
562      }
563      if(go_wild(aR->GetMomentumChange().x()) ||
564        go_wild(aR->GetMomentumChange().y()) ||
565      go_wild(aR->GetMomentumChange().z()))
566      {
567        G4Exception("G4HadronicProcess", "007", FatalException,
568        "surviving track received NaN momentum."); 
569      }
570      */
571      G4double newM=aT.GetDefinition()->GetPDGMass();
572      G4double newE=aR->GetEnergyChange() + newM;
573      G4double newP=std::sqrt(newE*newE - newM*newM);
574      G4DynamicParticle * aNew = 
575      new G4DynamicParticle(aT.GetDefinition(), newE, newP*aR->GetMomentumChange());
576      G4HadSecondary * theSec = new G4HadSecondary(aNew, newWeight);
577      aR->AddSecondary(theSec);
578    }
579    else
580    {
581      G4double newWeight = aR->GetWeightChange()*aT.GetWeight();
582      theTotalResult->ProposeParentWeight(newWeight); // This is multiplicative
583      if(aR->GetEnergyChange()>-.5) 
584      {
585        /*
586        if(go_wild(aR->GetEnergyChange()))
587        {
588          G4Exception("G4HadronicProcess", "007", FatalException,
589          "track received NaN energy."); 
590        }
591        */
592        theTotalResult->ProposeEnergy(aR->GetEnergyChange());
593      }
594      G4LorentzVector newDirection(aR->GetMomentumChange().unit(), 1.);
595      newDirection*=aR->GetTrafoToLab();
596      theTotalResult->ProposeMomentumDirection(newDirection.vect());
597    }
598  }
599  else
600  {
601    G4cout << "Call for " << theInteraction->GetModelName() << G4endl;
602    G4cout << "Target Z= " 
603           << targetNucleus.GetZ() << "  A= " << targetNucleus.GetN() << G4endl;
604    DumpState(aT,"FillTotalResult");
605    G4Exception("G4HadronicProcess", "007", FatalException,
606    "use of unsupported track-status.");
607  }
608
609  if(GetProcessName() != "hElastic" && GetProcessName() != "HadronElastic"
610     &&  theTotalResult->GetTrackStatus()==fAlive
611     && aR->GetStatusChange()==isAlive)
612    {
613    // Use for debugging:   G4double newWeight = theTotalResult->GetParentWeight();
614
615    G4double newKE = std::max(DBL_MIN, aR->GetEnergyChange());
616    G4DynamicParticle* aNew = new G4DynamicParticle(aT.GetDefinition(), 
617                                                    aR->GetMomentumChange(), 
618                                                    newKE);
619    G4HadSecondary* theSec = new G4HadSecondary(aNew, 1.0);
620    aR->AddSecondary(theSec);
621    aR->SetStatusChange(stopAndKill);
622
623    theTotalResult->ProposeTrackStatus(fStopAndKill);
624    theTotalResult->ProposeEnergy( 0.0 );
625
626  }
627  theTotalResult->ProposeLocalEnergyDeposit(aR->GetLocalEnergyDeposit());
628  theTotalResult->SetNumberOfSecondaries(aR->GetNumberOfSecondaries());
629
630  if(aR->GetStatusChange() != stopAndKill)
631  {
632    G4double newM=aT.GetDefinition()->GetPDGMass();
633    G4double newE=aR->GetEnergyChange() + newM;
634    G4double newP=std::sqrt(newE*newE - newM*newM);
635    G4ThreeVector newPV = newP*aR->GetMomentumChange();
636    G4LorentzVector newP4(newE, newPV);
637    newP4.rotate(rotation, it);
638    newP4*=aR->GetTrafoToLab();
639    theTotalResult->ProposeMomentumDirection(newP4.vect().unit());
640  }
641
642  for(G4int i=0; i<aR->GetNumberOfSecondaries(); i++)
643  {
644    G4LorentzVector theM = aR->GetSecondary(i)->GetParticle()->Get4Momentum();
645    theM.rotate(rotation, it);
646    theM*=aR->GetTrafoToLab();
647    /*
648    if(go_wild(theM.e()))
649    {
650      G4Exception("G4HadronicProcess", "007", FatalException,
651      "secondary track received NaN energy."); 
652    }
653    if(go_wild(theM.x()) ||
654      go_wild(theM.y()) ||
655    go_wild(theM.z()))
656    {
657      G4Exception("G4HadronicProcess", "007", FatalException,
658      "secondary track received NaN momentum."); 
659    }
660    */
661    aR->GetSecondary(i)->GetParticle()->Set4Momentum(theM);
662    G4double time = aR->GetSecondary(i)->GetTime();
663    if(time<0) time = aT.GetGlobalTime();
664
665    G4Track* track = new G4Track(aR->GetSecondary(i)->GetParticle(),
666                                 time,
667                                 aT.GetPosition());
668
669    G4double newWeight = aT.GetWeight()*aR->GetSecondary(i)->GetWeight();
670    //static G4double pinelcount=0;
671    if(xBiasOn) newWeight *= XBiasSecondaryWeight();
672    // G4cout << "#### ParticleDebug "
673    // <<GetProcessName()<<" "
674    // <<aR->GetSecondary(i)->GetParticle()->GetDefinition()->GetParticleName()<<" "
675    // <<aScaleFactor<<" "
676    // <<XBiasSurvivalProbability()<<" "
677    // <<XBiasSecondaryWeight()<<" "
678    // <<aT.GetWeight()<<" "
679    // <<aR->GetSecondary(i)->GetWeight()<<" "
680    // <<aR->GetSecondary(i)->GetParticle()->Get4Momentum()<<" "
681    // <<G4endl;
682    track->SetWeight(newWeight);
683    /*
684    G4double trackDeb = track->GetKineticEnergy();
685    if( (  trackDeb<0
686      || (trackDeb>aT.GetKineticEnergy()+1*GeV) ) && getenv("GHADEnergyBalanceDebug") )
687      {
688        G4cout << "Debugging hadronic processes: "<<track->GetKineticEnergy()
689        <<" "<<aT.GetKineticEnergy()
690        <<" "<<GetProcessName()
691        <<" "<<aT.GetDefinition()->GetParticleName()
692        <<G4endl;
693      }
694    */
695    track->SetTouchableHandle(aT.GetTouchableHandle());
696    theTotalResult->AddSecondary(track);
697  }
698
699  aR->Clear();
700  return;
701}
702
703G4IsoParticleChange* G4HadronicProcess::GetIsotopeProductionInfo() 
704{ 
705  G4IsoParticleChange * anIsoResult = theIsoResult;
706  if(theIsoResult) theOldIsoResult = theIsoResult;
707  theIsoResult = 0;
708  return anIsoResult;
709}
710
711void G4HadronicProcess::BiasCrossSectionByFactor(G4double aScale) 
712{
713  xBiasOn = true;
714  aScaleFactor = aScale;
715  G4String it = GetProcessName(); 
716  if( (it != "PhotonInelastic") && 
717      (it != "ElectroNuclear") && 
718      (it != "PositronNuclear") )
719    {
720      G4Exception("G4HadronicProcess::BiasCrossSectionByFactor", "007", FatalException,
721                  "Cross-section biasing available only for gamma and electro nuclear reactions.");
722    }
723  if(aScale<100)
724    {
725      G4Exception("G4HadronicProcess::BiasCrossSectionByFactor", "001", JustWarning,
726                  "Cross-section bias readjusted to be above safe limit. New value is 100");
727      aScaleFactor = 100.;
728    }
729}
730
731void 
732G4HadronicProcess::CheckEnergyMomentumConservation(const G4Track& aTrack,
733                                                   const G4Nucleus& aNucleus)
734{
735  G4double targetMass = G4NucleiProperties::GetNuclearMass(aNucleus.GetN(), aNucleus.GetZ());
736  G4LorentzVector projectile4mom = aTrack.GetDynamicParticle()->Get4Momentum();
737  G4LorentzVector target4mom(0, 0, 0, targetMass);
738  G4LorentzVector initial4mom = projectile4mom + target4mom;
739
740  G4Track* sec;
741  G4LorentzVector final4mom;
742  G4int nSec = theTotalResult->GetNumberOfSecondaries();
743  for (G4int i = 0; i < nSec; i++) {
744    sec = theTotalResult->GetSecondary(i);
745    final4mom += sec->GetDynamicParticle()->Get4Momentum();
746  }
747
748  G4LorentzVector diff = initial4mom - final4mom;
749  G4double absolute = diff.e();
750  G4double relative = absolute/aTrack.GetKineticEnergy();
751
752  G4String processName = GetProcessName();
753  G4HadronicInteraction* theModel = GetHadronicInteraction();
754  G4String modelName("none");
755  if (theModel) modelName = theModel->GetModelName();
756
757  std::pair<G4double, G4double> checkLevels = epCheckLevels;;
758  if (!levelsSetByProcess) {
759    if (theModel) checkLevels = theModel->GetEnergyMomentumCheckLevels();
760  }
761
762  G4bool relPass = false;
763  G4String relResult = "fail";
764  if (std::abs(relative) < checkLevels.first) {
765    relPass = true;
766    relResult = "pass";
767  }
768
769  G4bool absPass = false;
770  G4String absResult = "fail";
771  if (std::abs(absolute) < checkLevels.second) {
772    absPass = true;
773    absResult = "pass";
774  }
775
776  // Options for level of reporting detail:
777  //  0. off
778  //  1. report only when E/p not conserved
779  //  2. report regardless of E/p conservation
780  //  3. report only when E/p not conserved, with model names, process names, and limits
781  //  4. report regardless of E/p conservation, with model names, process names, and limits
782
783  if(epReportLevel == 4) {
784    G4cout << " Process: " << processName << " , Model: " <<  modelName << G4endl; 
785    G4cout << " relative limit " << checkLevels.first << " relative value = "
786           << relative << " " << relResult << G4endl;
787    G4cout << " absolute limit " << checkLevels.second << " absolute value = "
788           << absolute << " " << absResult << G4endl;
789
790  } else if(epReportLevel == 3) {
791    if (!absPass || !relPass) {
792      G4cout << " Process: " << processName << " , Model: " <<  modelName << G4endl; 
793      G4cout << " relative limit " << checkLevels.first << " relative value = "
794             << relative << " " << relResult << G4endl; 
795      G4cout << " absolute limit " << checkLevels.second << " absolute value = "
796             << absolute << " " << absResult << G4endl;
797    }
798
799  } else if(epReportLevel == 2) {
800    G4cout << " relative value = " << relative << " " << relPass
801           << " absolute value = " << absolute << " " << absPass << G4endl;
802
803  } else if(epReportLevel == 1) {
804    if (!absPass || !relPass) {
805      G4cout << " relative value = " << relative << " " << relPass
806             << " absolute value = " << absolute << " " << absPass << G4endl;
807    }
808  }
809}
810
811
812void G4HadronicProcess::DumpState(const G4Track& aTrack, const G4String& method)
813{
814  G4cout << "Unrecoverable error in the method " << method << " of " 
815         << GetProcessName() << G4endl;
816  G4cout << "TrackID= "<< aTrack.GetTrackID() << "  ParentID= " << aTrack.GetParentID()
817         << "  " << aTrack.GetDefinition()->GetParticleName() << G4endl;
818  G4cout << "Ekin(GeV)= " << aTrack.GetKineticEnergy()/CLHEP::GeV
819         << ";  direction= " << aTrack.GetMomentumDirection() << G4endl; 
820  G4cout << "Position(mm)= " << aTrack.GetPosition()/CLHEP::mm
821         << ";  material " << aTrack.GetMaterial()->GetName() << G4endl; 
822  G4cout << "PhysicalVolume  <" << aTrack.GetVolume()->GetName() << ">" << G4endl;
823} 
824
825/* end of file */
Note: See TracBrowser for help on using the repository browser.