source: trunk/source/processes/hadronic/models/radioactive_decay/src/G4NuclearDecayChannel.cc@ 1036

Last change on this file since 1036 was 962, checked in by garnier, 17 years ago

update processes

File size: 25.2 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// MODULES: G4NuclearDecayChannel.cc
29//
30// Version: 0.b.4
31// Date: 14/04/00
32// Author: F Lei & P R Truscott
33// Organisation: DERA UK
34// Customer: ESA/ESTEC, NOORDWIJK
35// Contract: 12115/96/JG/NL Work Order No. 3
36//
37// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38//
39// CHANGE HISTORY
40// --------------
41//
42// 29 February 2000, P R Truscott, DERA UK
43// 0.b.3 release.
44//
45// 18 October 2002, F Lei
46// modified link metheds in DecayIt() to G4PhotoEvaporation() in order to
47// use the new Internal Coversion feature.
48// 13 April 2000, F Lei, DERA UK
49// Changes made are:
50// 1) Use PhotonEvaporation instead of DiscreteGammaDeexcitation
51// 2) verbose control
52//
53// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54///////////////////////////////////////////////////////////////////////////////
55//
56#include "G4NuclearLevelManager.hh"
57#include "G4NuclearLevelStore.hh"
58#include "G4NuclearDecayChannel.hh"
59#include "G4DynamicParticle.hh"
60#include "G4DecayProducts.hh"
61#include "G4DecayTable.hh"
62#include "G4PhysicsLogVector.hh"
63#include "G4ParticleChangeForRadDecay.hh"
64#include "G4IonTable.hh"
65
66#include "G4BetaFermiFunction.hh"
67#include "G4PhotonEvaporation.hh"
68#include "G4AtomicTransitionManager.hh"
69#include "G4AtomicShell.hh"
70#include "G4AtomicDeexcitation.hh"
71
72const G4double G4NuclearDecayChannel:: pTolerance = 0.001;
73const G4double G4NuclearDecayChannel:: levelTolerance = 2.0*keV;
74//const G4bool G4NuclearDecayChannel:: FermiOn = true;
75
76///////////////////////////////////////////////////////////////////////////////
77//
78//
79// Constructor for one decay product (the nucleus).
80//
81G4NuclearDecayChannel::G4NuclearDecayChannel
82 (const G4RadioactiveDecayMode &theMode,
83 G4int Verbose,
84 const G4ParticleDefinition *theParentNucleus,
85 G4double theBR,
86 G4double theQtransition,
87 G4int A,
88 G4int Z,
89 G4double theDaughterExcitation) :
90 G4GeneralPhaseSpaceDecay(Verbose), decayMode(theMode)
91{
92#ifdef G4VERBOSE
93 if (GetVerboseLevel()>1)
94 {G4cout <<"G4NuclearDecayChannel constructor for " <<G4int(theMode) <<G4endl;}
95#endif
96 SetParent(theParentNucleus);
97 FillParent();
98 parent_mass = theParentNucleus->GetPDGMass();
99 SetBR (theBR);
100 SetNumberOfDaughters (1);
101 FillDaughterNucleus (0, A, Z, theDaughterExcitation);
102 Qtransition = theQtransition;
103}
104///////////////////////////////////////////////////////////////////////////////
105//
106//
107// Constructor for a daughter nucleus and one other particle.
108//
109G4NuclearDecayChannel::G4NuclearDecayChannel
110 (const G4RadioactiveDecayMode &theMode,
111 G4int Verbose,
112 const G4ParticleDefinition *theParentNucleus,
113 G4double theBR,
114 G4double theQtransition,
115 G4int A,
116 G4int Z,
117 G4double theDaughterExcitation,
118 const G4String theDaughterName1) :
119 G4GeneralPhaseSpaceDecay(Verbose), decayMode(theMode)
120{
121#ifdef G4VERBOSE
122 if (GetVerboseLevel()>1)
123 {G4cout <<"G4NuclearDecayChannel constructor for " <<G4int(theMode) <<G4endl;}
124#endif
125 SetParent (theParentNucleus);
126 FillParent();
127 parent_mass = theParentNucleus->GetPDGMass();
128 SetBR (theBR);
129 SetNumberOfDaughters (2);
130 SetDaughter(0, theDaughterName1);
131 FillDaughterNucleus (1, A, Z, theDaughterExcitation);
132 Qtransition = theQtransition;
133}
134///////////////////////////////////////////////////////////////////////////////
135//
136//
137// Constructor for a daughter nucleus and two other particles.
138//
139G4NuclearDecayChannel::G4NuclearDecayChannel
140 (const G4RadioactiveDecayMode &theMode,
141 G4int Verbose,
142 const G4ParticleDefinition *theParentNucleus,
143 G4double theBR,
144 G4double theFFN,
145 G4bool betaS,
146 CLHEP::RandGeneral* randBeta,
147 G4double theQtransition,
148 G4int A,
149 G4int Z,
150 G4double theDaughterExcitation,
151 const G4String theDaughterName1,
152 const G4String theDaughterName2) :
153 G4GeneralPhaseSpaceDecay(Verbose), decayMode(theMode)
154 //,BetaSimple(betaS),
155 // RandomEnergy(randBeta), Qtransition(theQtransition),FermiFN(theFFN)
156{
157#ifdef G4VERBOSE
158 if (GetVerboseLevel()>1)
159 {G4cout <<"G4NuclearDecayChannel constructor for " <<G4int(theMode) <<G4endl;}
160#endif
161 SetParent (theParentNucleus);
162 FillParent();
163 parent_mass = theParentNucleus->GetPDGMass();
164 SetBR (theBR);
165 SetNumberOfDaughters (3);
166 SetDaughter(0, theDaughterName1);
167 SetDaughter(2, theDaughterName2);
168 FillDaughterNucleus(1, A, Z, theDaughterExcitation);
169 BetaSimple = betaS;
170 RandomEnergy = randBeta;
171 Qtransition = theQtransition;
172 FermiFN = theFFN;
173}
174
175////////////////////////////////////////////////////////////////////////////////
176//
177//
178//
179//
180#include "G4HadTmpUtil.hh"
181
182void G4NuclearDecayChannel::FillDaughterNucleus (G4int index, G4int A, G4int Z,
183 G4double theDaughterExcitation)
184{
185 //
186 //
187 // Determine if the proposed daughter nucleus has a sensible A, Z and excitation
188 // energy.
189 //
190 if (A<1 || Z<0 || theDaughterExcitation <0.0)
191 {
192 G4cerr <<"Error in G4NuclearDecayChannel::FillDaughterNucleus";
193 G4cerr <<"Inappropriate values of daughter A, Z or excitation" <<G4endl;
194 G4cerr <<"A = " <<A <<" and Z = " <<Z;
195 G4cerr <<" Ex = " <<theDaughterExcitation*MeV <<"MeV" <<G4endl;
196 G4Exception(__FILE__, G4inttostring(__LINE__), FatalException, "G4NuclearDecayChannel::FillDaughterNucleus");
197 }
198 //
199 //
200 // Save A and Z to local variables. Find the GROUND STATE of the daughter
201 // nucleus and save this, as an ion, in the array of daughters.
202 //
203 daughterA = A;
204 daughterZ = Z;
205 if (Z == 1 && A == 1) {
206 daughterNucleus = G4Proton::Definition();
207 } else if (Z == 0 && A == 1) {
208 daughterNucleus = G4Neutron::Definition();
209 } else {
210 G4IonTable *theIonTable =
211 (G4IonTable*)(G4ParticleTable::GetParticleTable()->GetIonTable());
212 daughterNucleus = theIonTable->GetIon(daughterZ, daughterA, theDaughterExcitation*MeV);
213 }
214 daughterExcitation = theDaughterExcitation;
215 SetDaughter(index, daughterNucleus);
216}
217
218///////////////////////////////////////////////////////////////////////////////
219//
220//
221//
222//
223G4DecayProducts *G4NuclearDecayChannel::DecayIt (G4double theParentMass)
224{
225 //
226 //
227 // Load-up the details of the parent and daughter particles if they have not
228 // been defined properly.
229 //
230 if (parent == 0) FillParent();
231 if (daughters == 0) FillDaughters();
232 //
233 //
234 // We want to ensure that the difference between the total
235 // parent and daughter masses equals the energy liberated by the transition.
236 //
237 theParentMass = 0.0;
238 for( G4int index=0; index < numberOfDaughters; index++)
239 {theParentMass += daughters[index]->GetPDGMass();}
240 theParentMass += Qtransition ;
241 // bug fix for beta+ decay (flei 25/09/01)
242 if (decayMode == 2) theParentMass -= 2*0.511 * MeV;
243 //
244#ifdef G4VERBOSE
245 if (GetVerboseLevel()>1) {
246 G4cout << "G4NuclearDecayChannel::DecayIt "<< G4endl;
247 G4cout << "the decay mass = " << theParentMass << G4endl;
248 }
249#endif
250
251 SetParentMass (theParentMass);
252
253 //
254 //
255 // Define a product vector.
256 //
257 G4DecayProducts *products = 0;
258 //
259 //
260 // Depending upon the number of daughters, select the appropriate decay
261 // kinematics scheme.
262 //
263 switch (numberOfDaughters)
264 {
265 case 0:
266 G4cerr << "G4NuclearDecayChannel::DecayIt ";
267 G4cerr << " daughters not defined " <<G4endl;
268 break;
269 case 1:
270 products = OneBodyDecayIt();
271 break;
272 case 2:
273 products = TwoBodyDecayIt();
274 break;
275 case 3:
276 products = BetaDecayIt();
277 break;
278 default:
279 G4cerr <<"Error in G4NuclearDecayChannel::DecayIt" <<G4endl;
280 G4cerr <<"Number of daughters in decay = " <<numberOfDaughters <<G4endl;
281 G4Exception(__FILE__, G4inttostring(__LINE__), FatalException, "G4NuclearDecayChannel::DecayIt");
282 }
283 if (products == 0) {
284 G4cerr << "G4NuclearDecayChannel::DecayIt ";
285 G4cerr << *parent_name << " can not decay " << G4endl;
286 DumpInfo();
287 }
288 //
289 // If the decay is to an excited state of the daughter nuclide, we need
290 // to apply the photo-evaporation process.
291 //
292 // needed to hold the shell idex after ICM
293 G4int shellIndex = -1;
294 //
295 if (daughterExcitation > 0.0)
296 {
297 //
298 // Pop the daughter nucleus off the product vector - we need to retain
299 // the momentum of this particle.
300 //
301 dynamicDaughter = products->PopProducts();
302 G4LorentzVector daughterMomentum = dynamicDaughter->Get4Momentum();
303 G4ThreeVector const daughterMomentum1(static_cast<const G4LorentzVector> (daughterMomentum));
304 //
305 //
306 // Now define a G4Fragment with the correct A, Z and excitation, and declare and
307 // initialise a G4PhotonEvaporation object.
308 //
309 G4Fragment nucleus(daughterA, daughterZ, daughterMomentum);
310 G4PhotonEvaporation* deexcitation = new G4PhotonEvaporation;
311 deexcitation->SetVerboseLevel(GetVerboseLevel());
312 // switch on/off internal electron conversion
313 deexcitation->SetICM(true);
314 // set the maximum life-time for a level that will be treated. Level with life-time longer than this
315 // will be outputed as meta-stable isotope
316 //
317 deexcitation->SetMaxHalfLife(1e-6*second);
318 // but in IT mode, we need to force the transition
319 if (decayMode == 0) {
320 deexcitation->RDMForced(true);
321 } else {
322 deexcitation->RDMForced(false);
323 }
324 //
325 // Get the gammas by deexciting the nucleus.
326 //
327 G4FragmentVector* gammas = deexcitation->BreakItUp(nucleus);
328 // in the case of BreakItUp(nucleus), the returned G4FragmentVector contains the residual nuclide
329 // as its last entry.
330 G4int nGammas=gammas->size()-1;
331 //
332 // Go through each gamma/e- and add it to the decay product. The angular distribution
333 // of the gammas is isotropic, and the residual nucleus is assumed not to have suffered
334 // any recoil as a result of this de-excitation.
335 //
336 for (G4int ig=0; ig<nGammas; ig++)
337 {
338 G4DynamicParticle *theGammaRay = new
339 G4DynamicParticle (gammas->operator[](ig)->GetParticleDefinition(),
340 gammas->operator[](ig)->GetMomentum());
341 theGammaRay -> SetProperTime(gammas->operator[](ig)->GetCreationTime());
342 products->PushProducts (theGammaRay);
343 }
344 //
345 // now the nucleus
346 G4double finalDaughterExcitation = gammas->operator[](nGammas)->GetExcitationEnergy();
347 // f.lei (03/01/03) this is needed to fix the crach in test18
348 if (finalDaughterExcitation <= 1.0*keV) finalDaughterExcitation = 0 ;
349
350 // f.lei (07/03/05) added the delete to fix bug#711
351 if (dynamicDaughter) delete dynamicDaughter;
352
353 G4IonTable *theIonTable = (G4IonTable*)(G4ParticleTable::GetParticleTable()->GetIonTable());
354 dynamicDaughter = new G4DynamicParticle
355 (theIonTable->GetIon(daughterZ,daughterA,finalDaughterExcitation),
356 daughterMomentum1);
357 products->PushProducts (dynamicDaughter);
358 // retrive the ICM shell index
359 shellIndex = deexcitation->GetVacantShellNumber();
360
361 //
362 // Delete/reset variables associated with the gammas.
363 //
364 while (!gammas->empty()) {
365 delete *(gammas->end()-1);
366 gammas->pop_back();
367 }
368 // gammas->clearAndDestroy();
369 delete gammas;
370 delete deexcitation;
371 }
372 //
373 // now we have to take care of the EC product which have to go through the ARM
374 //
375 G4int eShell = -1;
376 if (decayMode == 3 || decayMode == 4 || decayMode == 5) {
377 switch (decayMode)
378 {
379 case KshellEC:
380 //
381 {
382 eShell = 0; // --> 0 from 1 (f.lei 30/4/2008)
383 }
384 break;
385 case LshellEC:
386 //
387 {
388 eShell = G4int(G4UniformRand()*3)+1;
389 }
390 break;
391 case MshellEC:
392 //
393 {
394 eShell = G4int(G4UniformRand()*5)+4;
395 }
396 break;
397 case ERROR:
398 default:
399 G4Exception("G4NuclearDecayChannel::DecayIt()", "601",
400 FatalException, "Error in decay mode selection");
401 }
402 }
403 // now deal with the IT case where ICM may have been applied
404 //
405 if (decayMode == 0) {
406 eShell = shellIndex;
407 }
408 // now apply ARM if there is a vaccancy
409 //
410 if (eShell != -1) {
411 G4int aZ = daughterZ;
412 if (aZ > 5 && aZ < 100) { // only applies to 5< Z <100
413 // Retrieve the corresponding identifier and binding energy of the selected shell
414 const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
415 const G4AtomicShell* shell = transitionManager->Shell(aZ, eShell);
416 G4double bindingEnergy = shell->BindingEnergy();
417 G4int shellId = shell->ShellId();
418
419 G4AtomicDeexcitation* atomDeex = new G4AtomicDeexcitation();
420 //the default is no Auger electron generation.
421 // Switch it on/off here!
422 atomDeex->ActivateAugerElectronProduction(true);
423 std::vector<G4DynamicParticle*>* armProducts = atomDeex->GenerateParticles(aZ,shellId);
424
425 // pop up the daughter before insertion;
426 // f.lei (30/04/2008) check if the total kinetic energy is less than
427 // the shell binding energy; if true add the difference to the daughter to conserve the energy
428 dynamicDaughter = products->PopProducts();
429 G4double tARMEnergy = 0.0;
430 for (size_t i = 0; i < armProducts->size(); i++) {
431 products->PushProducts ((*armProducts)[i]);
432 tARMEnergy += (*armProducts)[i]->GetKineticEnergy();
433 }
434 if ((bindingEnergy - tARMEnergy) > 0.1*keV){
435 G4double dEnergy = dynamicDaughter->GetKineticEnergy() + (bindingEnergy - tARMEnergy);
436 dynamicDaughter->SetKineticEnergy(dEnergy);
437 }
438 products->PushProducts(dynamicDaughter);
439
440#ifdef G4VERBOSE
441 if (GetVerboseLevel()>0)
442 {
443 G4cout <<"G4NuclearDecayChannel::Selected shell number for ARM = " <<shellId <<G4endl;
444 G4cout <<"G4NuclearDecayChannel::ARM products = " <<armProducts->size()<<G4endl;
445 G4cout <<" The binding energy = " << bindingEnergy << G4endl;
446 G4cout <<" Total ARM particle kinetic energy = " << tARMEnergy << G4endl;
447 }
448#endif
449
450 delete armProducts;
451 delete atomDeex;
452 }
453 }
454
455 return products;
456}
457////////////////////////////////////////////////////////////////////////////////
458//
459
460G4DecayProducts *G4NuclearDecayChannel::BetaDecayIt()
461
462{
463 if (GetVerboseLevel()>1) G4cout << "G4Decay::BetaDecayIt()"<<G4endl;
464
465 //daughters'mass
466 G4double daughtermass[3];
467 G4double sumofdaughtermass = 0.0;
468 G4double pmass = GetParentMass();
469 for (G4int index=0; index<3; index++)
470 {
471 daughtermass[index] = daughters[index]->GetPDGMass();
472 sumofdaughtermass += daughtermass[index];
473 }
474
475 //create parent G4DynamicParticle at rest
476 G4ParticleMomentum dummy;
477 G4DynamicParticle * parentparticle = new G4DynamicParticle( parent, dummy, 0.0);
478
479 //create G4Decayproducts
480 G4DecayProducts *products = new G4DecayProducts(*parentparticle);
481 delete parentparticle;
482
483 G4double Q = pmass - sumofdaughtermass;
484
485 // 09/11/2004 flei
486 // All Beta decays are now treated with the improved 3 body decay algorithm. No more slow/fast modes
487 /*
488 if (BetaSimple == true) {
489
490 // Use the histogramed distribution to generate the beta energy
491 G4double daughtermomentum[2];
492 G4double daughterenergy[2];
493 daughterenergy[0] = RandomEnergy->shoot() * Q;
494 daughtermomentum[0] = std::sqrt(daughterenergy[0]*daughterenergy[0] +
495 2.0*daughterenergy[0] * daughtermass[0]);
496 // the recoil neuleus is asummed to have a maximum energy of Q/daughterA/1000.
497 daughterenergy[1] = G4UniformRand() * Q/(1000.*daughterA);
498 G4double recoilmomentumsquared = daughterenergy[1]*daughterenergy[1] +
499 2.0*daughterenergy[1] * daughtermass[1];
500 if (recoilmomentumsquared < 0.0) recoilmomentumsquared = 0.0;
501 daughtermomentum[1] = std::sqrt(recoilmomentumsquared);
502 //
503 //create daughter G4DynamicParticle
504 G4double costheta, sintheta, phi, sinphi, cosphi;
505 // G4double costhetan, sinthetan, phin, sinphin, cosphin;
506 costheta = 2.*G4UniformRand()-1.0;
507 sintheta = std::sqrt((1.0-costheta)*(1.0+costheta));
508 phi = twopi*G4UniformRand()*rad;
509 sinphi = std::sin(phi);
510 cosphi = std::cos(phi);
511 G4ParticleMomentum direction0(sintheta*cosphi,sintheta*sinphi,costheta);
512 G4DynamicParticle * daughterparticle
513 = new G4DynamicParticle( daughters[0], direction0*daughtermomentum[0]);
514 products->PushProducts(daughterparticle);
515 // The two products are independent in directions
516 costheta = 2.*G4UniformRand()-1.0;
517 sintheta = std::sqrt((1.0-costheta)*(1.0+costheta));
518 phi = twopi*G4UniformRand()*rad;
519 sinphi = std::sin(phi);
520 cosphi = std::cos(phi);
521 G4ParticleMomentum direction1(sintheta*cosphi,sintheta*sinphi,costheta);
522 daughterparticle
523 = new G4DynamicParticle( daughters[1], direction1*daughtermomentum[1]);
524 products->PushProducts(daughterparticle);
525
526 // the neutrino is igored in this case
527
528 } else {
529 */
530 /* original slow method
531 //calculate daughter momentum
532 // Generate two
533 G4double rd1, rd2;
534 G4double daughtermomentum[3];
535 G4double daughterenergy[3];
536 G4double momentummax=0.0, momentumsum = 0.0;
537 G4double fermif;
538 G4BetaFermiFunction* aBetaFermiFunction;
539 if (decayMode == 1) {
540 // beta-decay
541 aBetaFermiFunction = new G4BetaFermiFunction (daughterA, daughterZ);
542 } else {
543 // beta+decay
544 aBetaFermiFunction = new G4BetaFermiFunction (daughterA, -daughterZ);
545 }
546 if (GetVerboseLevel()>1) {
547 G4cout<< " Q = " <<Q<<G4endl;
548 G4cout<< " daughterA = " <<daughterA<<G4endl;
549 G4cout<< " daughterZ = " <<daughterZ<<G4endl;
550 G4cout<< " decayMode = " <<static_cast<G4int>(decayMode) << G4endl;
551 G4cout<< " FermiFN = " <<FermiFN<<G4endl;
552 }
553 do
554 {
555 rd1 = G4UniformRand();
556 rd2 = G4UniformRand();
557
558 momentummax = 0.0;
559 momentumsum = 0.0;
560
561 // daughter 0
562
563 // energy = rd2*(pmass - sumofdaughtermass);
564 daughtermomentum[0] = std::sqrt(rd2) * std::sqrt((Q + 2.0*daughtermass[0])*Q);
565 daughterenergy[0] = std::sqrt(daughtermomentum[0]*daughtermomentum[0] +
566 daughtermass[0] * daughtermass[0]) - daughtermass[0];
567 if ( daughtermomentum[0] >momentummax )momentummax = daughtermomentum[0];
568 momentumsum += daughtermomentum[0];
569
570 // daughter 2
571 // energy = (1.-rd1)*(pmass - sumofdaughtermass);
572 daughtermomentum[2] = std::sqrt(rd1)*std::sqrt((Q + 2.0*daughtermass[2])*Q);
573 daughterenergy[2] = std::sqrt(daughtermomentum[2]*daughtermomentum[2] +
574 daughtermass[2] * daughtermass[2]) - daughtermass[2];
575 if ( daughtermomentum[2] >momentummax )momentummax = daughtermomentum[2];
576 momentumsum += daughtermomentum[2];
577
578 // daughter 1
579
580 daughterenergy[1] = Q - daughterenergy[0] - daughterenergy[2];
581 if (daughterenergy[1] > 0.0) {
582 daughtermomentum[1] = std::sqrt(daughterenergy[1]*daughterenergy[1] +
583 2.0*daughterenergy[1] * daughtermass[1]);
584 if ( daughtermomentum[1] >momentummax ) momentummax =
585 daughtermomentum[1];
586 momentumsum += daughtermomentum[1];
587 } else {
588 momentummax = momentumsum = Q;
589 }
590 // beta particles is sampled with no coulomb effects applied above. Now
591 // apply the Fermi function using rejection method.
592 daughterenergy[0] = daughterenergy[0]*MeV/0.511;
593 fermif = aBetaFermiFunction->GetFF(daughterenergy[0])/FermiFN;
594 // fermif: normalised Fermi factor
595 if (G4UniformRand() > fermif) momentummax = momentumsum = Q;
596 // rejection method
597 } while (momentummax > momentumsum - momentummax );
598 delete aBetaFermiFunction;
599
600 // output message
601 if (GetVerboseLevel()>1) {
602 G4cout <<" daughter 0:" <<daughtermomentum[0]/GeV <<"[GeV/c]" <<G4endl;
603 G4cout <<" daughter 1:" <<daughtermomentum[1]/GeV <<"[GeV/c]" <<G4endl;
604 G4cout <<" daughter 2:" <<daughtermomentum[2]/GeV <<"[GeV/c]" <<G4endl;
605 G4cout <<" momentum sum:" <<momentumsum/GeV <<"[GeV/c]" <<G4endl;
606 }
607 */
608 // faster method as suggested by Dirk Kruecker of FZ-Julich
609 G4double daughtermomentum[3];
610 G4double daughterenergy[3];
611 // Use the histogramed distribution to generate the beta energy
612 daughterenergy[0] = RandomEnergy->shoot() * Q;
613 daughtermomentum[0] = std::sqrt(daughterenergy[0]*daughterenergy[0] +
614 2.0*daughterenergy[0] * daughtermass[0]);
615
616 //neutrino energy distribution is flat within the kinematical limits
617 G4double rd = 2*G4UniformRand()-1;
618 // limits
619 G4double Mme=pmass-daughtermass[0];
620 G4double K=0.5-daughtermass[1]*daughtermass[1]/(2*Mme*Mme-4*pmass*daughterenergy[0]);
621
622 daughterenergy[2]=K*(Mme-daughterenergy[0]+rd*daughtermomentum[0]);
623 daughtermomentum[2] = daughterenergy[2] ;
624
625 // the recoil neuleus
626 daughterenergy[1] = Q-daughterenergy[0]-daughterenergy[2];
627 G4double recoilmomentumsquared = daughterenergy[1]*daughterenergy[1] +
628 2.0*daughterenergy[1] * daughtermass[1];
629 if (recoilmomentumsquared < 0.0) recoilmomentumsquared = 0.0;
630 daughtermomentum[1] = std::sqrt(recoilmomentumsquared);
631
632 // output message
633 if (GetVerboseLevel()>1) {
634 G4cout <<" daughter 0:" <<daughtermomentum[0]/GeV <<"[GeV/c]" <<G4endl;
635 G4cout <<" daughter 1:" <<daughtermomentum[1]/GeV <<"[GeV/c]" <<G4endl;
636 G4cout <<" daughter 2:" <<daughtermomentum[2]/GeV <<"[GeV/c]" <<G4endl;
637 }
638 //create daughter G4DynamicParticle
639 G4double costheta, sintheta, phi, sinphi, cosphi;
640 G4double costhetan, sinthetan, phin, sinphin, cosphin;
641 costheta = 2.*G4UniformRand()-1.0;
642 sintheta = std::sqrt((1.0-costheta)*(1.0+costheta));
643 phi = twopi*G4UniformRand()*rad;
644 sinphi = std::sin(phi);
645 cosphi = std::cos(phi);
646 G4ParticleMomentum direction0(sintheta*cosphi,sintheta*sinphi,costheta);
647 G4DynamicParticle * daughterparticle
648 = new G4DynamicParticle( daughters[0], direction0*daughtermomentum[0]);
649 products->PushProducts(daughterparticle);
650
651 costhetan = (daughtermomentum[1]*daughtermomentum[1]-
652 daughtermomentum[2]*daughtermomentum[2]-
653 daughtermomentum[0]*daughtermomentum[0])/
654 (2.0*daughtermomentum[2]*daughtermomentum[0]);
655 // added the following test to avoid rounding erros. A problem
656 // reported bye Ben Morgan of Uni.Warwick
657 if (costhetan > 1.) costhetan = 1.;
658 if (costhetan < -1.) costhetan = -1.;
659 sinthetan = std::sqrt((1.0-costhetan)*(1.0+costhetan));
660 phin = twopi*G4UniformRand()*rad;
661 sinphin = std::sin(phin);
662 cosphin = std::cos(phin);
663 G4ParticleMomentum direction2;
664 direction2.setX( sinthetan*cosphin*costheta*cosphi -
665 sinthetan*sinphin*sinphi + costhetan*sintheta*cosphi);
666 direction2.setY( sinthetan*cosphin*costheta*sinphi +
667 sinthetan*sinphin*cosphi + costhetan*sintheta*sinphi);
668 direction2.setZ( -sinthetan*cosphin*sintheta +
669 costhetan*costheta);
670 daughterparticle = new G4DynamicParticle
671 ( daughters[2], direction2*(daughtermomentum[2]/direction2.mag()));
672 products->PushProducts(daughterparticle);
673
674 daughterparticle =
675 new G4DynamicParticle (daughters[1],
676 (direction0*daughtermomentum[0] +
677 direction2*(daughtermomentum[2]/direction2.mag()))*(-1.0));
678 products->PushProducts(daughterparticle);
679 // }
680 // delete daughterparticle;
681
682 if (GetVerboseLevel()>1) {
683 G4cout << "G4NuclearDecayChannel::BetaDecayIt ";
684 G4cout << " create decay products in rest frame " <<G4endl;
685 products->DumpInfo();
686 }
687 return products;
688}
Note: See TracBrowser for help on using the repository browser.