source: trunk/source/processes/hadronic/models/util/src/G4GeneralPhaseSpaceDecay.cc@ 1347

Last change on this file since 1347 was 819, checked in by garnier, 17 years ago

import all except CVS

File size: 20.1 KB
RevLine 
[819]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// $Id: G4GeneralSpaceDecay.cc,v 1.0 1998/05/21
29// ----------------------------------------------------------------
30// GEANT 4 class header file
31//
32// History: first implementation, A. Feliciello, 21st May 1998
33//
34// Note: this class is a generalization of the
35// G4PhaseSpaceDecayChannel one
36// ----------------------------------------------------------------
37
38#include "G4ParticleDefinition.hh"
39#include "G4DecayProducts.hh"
40#include "G4VDecayChannel.hh"
41#include "G4GeneralPhaseSpaceDecay.hh"
42#include "Randomize.hh"
43#include "G4LorentzVector.hh"
44#include "G4LorentzRotation.hh"
45#include "G4ios.hh"
46
47
48G4GeneralPhaseSpaceDecay::G4GeneralPhaseSpaceDecay(G4int Verbose) :
49 G4VDecayChannel("Phase Space", Verbose),
50 theDaughterMasses(0)
51{
52 if (GetVerboseLevel()>1) G4cout << "G4GeneralPhaseSpaceDecay:: constructor " << G4endl;
53}
54
55G4GeneralPhaseSpaceDecay::G4GeneralPhaseSpaceDecay(const G4String& theParentName,
56 G4double theBR,
57 G4int theNumberOfDaughters,
58 const G4String& theDaughterName1,
59 const G4String& theDaughterName2,
60 const G4String& theDaughterName3) :
61 G4VDecayChannel("Phase Space",
62 theParentName,theBR,
63 theNumberOfDaughters,
64 theDaughterName1,
65 theDaughterName2,
66 theDaughterName3),
67 theDaughterMasses(0)
68{
69 if (GetVerboseLevel()>1) G4cout << "G4GeneralPhaseSpaceDecay:: constructor " << G4endl;
70
71 // Set the parent particle (resonance) mass to the (default) PDG vale
72 if (parent != NULL)
73 {
74 parentmass = parent->GetPDGMass();
75 }
76}
77
78G4GeneralPhaseSpaceDecay::G4GeneralPhaseSpaceDecay(const G4String& theParentName,
79 G4double theParentMass,
80 G4double theBR,
81 G4int theNumberOfDaughters,
82 const G4String& theDaughterName1,
83 const G4String& theDaughterName2,
84 const G4String& theDaughterName3) :
85 G4VDecayChannel("Phase Space",
86 theParentName,theBR,
87 theNumberOfDaughters,
88 theDaughterName1,
89 theDaughterName2,
90 theDaughterName3),
91 parentmass(theParentMass),
92 theDaughterMasses(0)
93{
94 if (GetVerboseLevel()>1) G4cout << "G4GeneralPhaseSpaceDecay:: constructor " << G4endl;
95}
96
97G4GeneralPhaseSpaceDecay::G4GeneralPhaseSpaceDecay(const G4String& theParentName,
98 G4double theParentMass,
99 G4double theBR,
100 G4int theNumberOfDaughters,
101 const G4String& theDaughterName1,
102 const G4String& theDaughterName2,
103 const G4String& theDaughterName3,
104 const G4double *masses) :
105 G4VDecayChannel("Phase Space",
106 theParentName,theBR,
107 theNumberOfDaughters,
108 theDaughterName1,
109 theDaughterName2,
110 theDaughterName3),
111 parentmass(theParentMass),
112 theDaughterMasses(masses)
113{
114 if (GetVerboseLevel()>1) G4cout << "G4GeneralPhaseSpaceDecay:: constructor " << G4endl;
115}
116
117G4GeneralPhaseSpaceDecay::~G4GeneralPhaseSpaceDecay()
118{
119}
120
121G4DecayProducts *G4GeneralPhaseSpaceDecay::DecayIt(G4double)
122{
123 if (GetVerboseLevel()>1) G4cout << "G4GeneralPhaseSpaceDecay::DecayIt ";
124 G4DecayProducts * products = NULL;
125
126 if (parent == NULL) FillParent();
127 if (daughters == NULL) FillDaughters();
128
129 switch (numberOfDaughters){
130 case 0:
131 if (GetVerboseLevel()>0) {
132 G4cout << "G4GeneralPhaseSpaceDecay::DecayIt ";
133 G4cout << " daughters not defined " <<G4endl;
134 }
135 break;
136 case 1:
137 products = OneBodyDecayIt();
138 break;
139 case 2:
140 products = TwoBodyDecayIt();
141 break;
142 case 3:
143 products = ThreeBodyDecayIt();
144 break;
145 default:
146 products = ManyBodyDecayIt();
147 break;
148 }
149 if ((products == NULL) && (GetVerboseLevel()>0)) {
150 G4cout << "G4GeneralPhaseSpaceDecay::DecayIt ";
151 G4cout << *parent_name << " can not decay " << G4endl;
152 DumpInfo();
153 }
154 return products;
155}
156
157G4DecayProducts *G4GeneralPhaseSpaceDecay::OneBodyDecayIt()
158{
159 if (GetVerboseLevel()>1) G4cout << "G4GeneralPhaseSpaceDecay::OneBodyDecayIt()"<<G4endl;
160
161// G4double daughtermass = daughters[0]->GetPDGMass();
162
163 //create parent G4DynamicParticle at rest
164 G4ParticleMomentum dummy;
165 G4DynamicParticle * parentparticle = new G4DynamicParticle(parent, dummy, 0.0);
166
167 //create G4Decayproducts
168 G4DecayProducts *products = new G4DecayProducts(*parentparticle);
169 delete parentparticle;
170
171 //create daughter G4DynamicParticle at rest
172 G4DynamicParticle * daughterparticle = new G4DynamicParticle(daughters[0], dummy, 0.0);
173 products->PushProducts(daughterparticle);
174
175 if (GetVerboseLevel()>1)
176 {
177 G4cout << "G4GeneralPhaseSpaceDecay::OneBodyDecayIt ";
178 G4cout << " create decay products in rest frame " <<G4endl;
179 products->DumpInfo();
180 }
181 return products;
182}
183
184G4DecayProducts *G4GeneralPhaseSpaceDecay::TwoBodyDecayIt()
185{
186 if (GetVerboseLevel()>1) G4cout << "G4GeneralPhaseSpaceDecay::TwoBodyDecayIt()"<<G4endl;
187
188 //daughters'mass
189 G4double daughtermass[2];
190 G4double daughtermomentum;
191 if ( theDaughterMasses )
192 {
193 daughtermass[0]= *(theDaughterMasses);
194 daughtermass[1] = *(theDaughterMasses+1);
195 } else {
196 daughtermass[0] = daughters[0]->GetPDGMass();
197 daughtermass[1] = daughters[1]->GetPDGMass();
198 }
199
200// G4double sumofdaughtermass = daughtermass[0] + daughtermass[1];
201
202 //create parent G4DynamicParticle at rest
203 G4ParticleMomentum dummy;
204 G4DynamicParticle * parentparticle = new G4DynamicParticle( parent, dummy, 0.0);
205
206 //create G4Decayproducts @@GF why dummy parentparticle?
207 G4DecayProducts *products = new G4DecayProducts(*parentparticle);
208 delete parentparticle;
209
210 //calculate daughter momentum
211 daughtermomentum = Pmx(parentmass,daughtermass[0],daughtermass[1]);
212 G4double costheta = 2.*G4UniformRand()-1.0;
213 G4double sintheta = std::sqrt((1.0 - costheta)*(1.0 + costheta));
214 G4double phi = twopi*G4UniformRand()*rad;
215 G4ParticleMomentum direction(sintheta*std::cos(phi),sintheta*std::sin(phi),costheta);
216
217 //create daughter G4DynamicParticle
218 G4double Etotal= std::sqrt(daughtermass[0]*daughtermass[0] + daughtermomentum*daughtermomentum);
219 G4DynamicParticle * daughterparticle = new G4DynamicParticle( daughters[0],Etotal, direction*daughtermomentum);
220 products->PushProducts(daughterparticle);
221 Etotal= std::sqrt(daughtermass[1]*daughtermass[1] + daughtermomentum*daughtermomentum);
222 daughterparticle = new G4DynamicParticle( daughters[1],Etotal, direction*(-1.0*daughtermomentum));
223 products->PushProducts(daughterparticle);
224
225 if (GetVerboseLevel()>1)
226 {
227 G4cout << "G4GeneralPhaseSpaceDecay::TwoBodyDecayIt ";
228 G4cout << " create decay products in rest frame " <<G4endl;
229 products->DumpInfo();
230 }
231 return products;
232}
233
234G4DecayProducts *G4GeneralPhaseSpaceDecay::ThreeBodyDecayIt()
235// algorism of this code is originally written in GDECA3 of GEANT3
236{
237 if (GetVerboseLevel()>1) G4cout << "G4GeneralPhaseSpaceDecay::ThreeBodyDecayIt()"<<G4endl;
238
239 //daughters'mass
240 G4double daughtermass[3];
241 G4double sumofdaughtermass = 0.0;
242 for (G4int index=0; index<3; index++)
243 {
244 if ( theDaughterMasses )
245 {
246 daughtermass[index]= *(theDaughterMasses+index);
247 } else {
248 daughtermass[index] = daughters[index]->GetPDGMass();
249 }
250 sumofdaughtermass += daughtermass[index];
251 }
252
253 //create parent G4DynamicParticle at rest
254 G4ParticleMomentum dummy;
255 G4DynamicParticle * parentparticle = new G4DynamicParticle( parent, dummy, 0.0);
256
257 //create G4Decayproducts
258 G4DecayProducts *products = new G4DecayProducts(*parentparticle);
259 delete parentparticle;
260
261 //calculate daughter momentum
262 // Generate two
263 G4double rd1, rd2, rd;
264 G4double daughtermomentum[3];
265 G4double momentummax=0.0, momentumsum = 0.0;
266 G4double energy;
267
268 do
269 {
270 rd1 = G4UniformRand();
271 rd2 = G4UniformRand();
272 if (rd2 > rd1)
273 {
274 rd = rd1;
275 rd1 = rd2;
276 rd2 = rd;
277 }
278 momentummax = 0.0;
279 momentumsum = 0.0;
280 // daughter 0
281
282 energy = rd2*(parentmass - sumofdaughtermass);
283 daughtermomentum[0] = std::sqrt(energy*energy + 2.0*energy* daughtermass[0]);
284 if ( daughtermomentum[0] >momentummax )momentummax = daughtermomentum[0];
285 momentumsum += daughtermomentum[0];
286
287 // daughter 1
288 energy = (1.-rd1)*(parentmass - sumofdaughtermass);
289 daughtermomentum[1] = std::sqrt(energy*energy + 2.0*energy* daughtermass[1]);
290 if ( daughtermomentum[1] >momentummax )momentummax = daughtermomentum[1];
291 momentumsum += daughtermomentum[1];
292
293 // daughter 2
294 energy = (rd1-rd2)*(parentmass - sumofdaughtermass);
295 daughtermomentum[2] = std::sqrt(energy*energy + 2.0*energy* daughtermass[2]);
296 if ( daughtermomentum[2] >momentummax )momentummax = daughtermomentum[2];
297 momentumsum += daughtermomentum[2];
298 } while (momentummax > momentumsum - momentummax );
299
300 // output message
301 if (GetVerboseLevel()>1) {
302 G4cout << " daughter 0:" << daughtermomentum[0]/GeV << "[GeV/c]" <<G4endl;
303 G4cout << " daughter 1:" << daughtermomentum[1]/GeV << "[GeV/c]" <<G4endl;
304 G4cout << " daughter 2:" << daughtermomentum[2]/GeV << "[GeV/c]" <<G4endl;
305 G4cout << " momentum sum:" << momentumsum/GeV << "[GeV/c]" <<G4endl;
306 }
307
308 //create daughter G4DynamicParticle
309 G4double costheta, sintheta, phi, sinphi, cosphi;
310 G4double costhetan, sinthetan, phin, sinphin, cosphin;
311 costheta = 2.*G4UniformRand()-1.0;
312 sintheta = std::sqrt((1.0-costheta)*(1.0+costheta));
313 phi = twopi*G4UniformRand()*rad;
314 sinphi = std::sin(phi);
315 cosphi = std::cos(phi);
316 G4ParticleMomentum direction0(sintheta*cosphi,sintheta*sinphi,costheta);
317 G4double Etotal=std::sqrt( daughtermass[0]*daughtermass[0] + daughtermomentum[0]*daughtermomentum[0]);
318 G4DynamicParticle * daughterparticle
319 = new G4DynamicParticle( daughters[0], Etotal, direction0*daughtermomentum[0]);
320 products->PushProducts(daughterparticle);
321
322 costhetan = (daughtermomentum[1]*daughtermomentum[1]-daughtermomentum[2]*daughtermomentum[2]-daughtermomentum[0]*daughtermomentum[0])/(2.0*daughtermomentum[2]*daughtermomentum[0]);
323 sinthetan = std::sqrt((1.0-costhetan)*(1.0+costhetan));
324 phin = twopi*G4UniformRand()*rad;
325 sinphin = std::sin(phin);
326 cosphin = std::cos(phin);
327 G4ParticleMomentum direction2;
328 direction2.setX( sinthetan*cosphin*costheta*cosphi - sinthetan*sinphin*sinphi + costhetan*sintheta*cosphi);
329 direction2.setY( sinthetan*cosphin*costheta*sinphi + sinthetan*sinphin*cosphi + costhetan*sintheta*sinphi);
330 direction2.setZ( -sinthetan*cosphin*sintheta + costhetan*costheta);
331 Etotal=std::sqrt( daughtermass[2]*daughtermass[2] + daughtermomentum[2]*daughtermomentum[2]/direction2.mag2());
332 daughterparticle = new G4DynamicParticle( daughters[2],Etotal, direction2*(daughtermomentum[2]/direction2.mag()));
333 products->PushProducts(daughterparticle);
334 G4ThreeVector mom=(direction0*daughtermomentum[0] + direction2*(daughtermomentum[2]/direction2.mag()))*(-1.0);
335 Etotal= std::sqrt( daughtermass[1]*daughtermass[1] + mom.mag2() );
336 daughterparticle =
337 new G4DynamicParticle(daughters[1], Etotal, mom);
338 products->PushProducts(daughterparticle);
339
340 if (GetVerboseLevel()>1) {
341 G4cout << "G4GeneralPhaseSpaceDecay::ThreeBodyDecayIt ";
342 G4cout << " create decay products in rest frame " <<G4endl;
343 products->DumpInfo();
344 }
345 return products;
346}
347
348G4DecayProducts *G4GeneralPhaseSpaceDecay::ManyBodyDecayIt()
349// algorism of this code is originally written in FORTRAN by M.Asai
350//*****************************************************************
351// NBODY
352// N-body phase space Monte-Carlo generator
353// Makoto Asai
354// Hiroshima Institute of Technology
355// (asai@kekvax.kek.jp)
356// Revised release : 19/Apr/1995
357//
358{
359 //return value
360 G4DecayProducts *products;
361
362 if (GetVerboseLevel()>1) G4cout << "G4GeneralPhaseSpaceDecay::ManyBodyDecayIt()"<<G4endl;
363
364 //daughters'mass
365 G4double *daughtermass = new G4double[numberOfDaughters];
366 G4double sumofdaughtermass = 0.0;
367 for (G4int index=0; index<numberOfDaughters; index++){
368 daughtermass[index] = daughters[index]->GetPDGMass();
369 sumofdaughtermass += daughtermass[index];
370 }
371
372 //Calculate daughter momentum
373 G4double *daughtermomentum = new G4double[numberOfDaughters];
374 G4ParticleMomentum direction;
375 G4DynamicParticle **daughterparticle;
376 G4double *sm = new G4double[numberOfDaughters];
377 G4double tmas;
378 G4double weight = 1.0;
379 G4int numberOfTry = 0;
380 G4int index1, index2;
381
382 do {
383 //Generate rundom number in descending order
384 G4double temp;
385 G4double *rd = new G4double[numberOfDaughters];
386 rd[0] = 1.0;
387 for(index1 =1; index1 < numberOfDaughters -1; index1++)
388 rd[index1] = G4UniformRand();
389 rd[ numberOfDaughters -1] = 0.0;
390 for(index1 =1; index1 < numberOfDaughters -1; index1++) {
391 for(index2 = index1+1; index2 < numberOfDaughters; index2++) {
392 if (rd[index1] < rd[index2]){
393 temp = rd[index1];
394 rd[index1] = rd[index2];
395 rd[index2] = temp;
396 }
397 }
398 }
399
400 //calcurate virtual mass
401 tmas = parentmass - sumofdaughtermass;
402 temp = sumofdaughtermass;
403 for(index1 =0; index1 < numberOfDaughters; index1++) {
404 sm[index1] = rd[index1]*tmas + temp;
405 temp -= daughtermass[index1];
406 if (GetVerboseLevel()>1) {
407 G4cout << index1 << " rundom number:" << rd[index1];
408 G4cout << " virtual mass:" << sm[index1]/GeV << "[GeV/c/c]" <<G4endl;
409 }
410 }
411 delete [] rd;
412
413 //Calculate daughter momentum
414 weight = 1.0;
415 index1 =numberOfDaughters-1;
416 daughtermomentum[index1]= Pmx( sm[index1-1],daughtermass[index1-1],sm[index1]);
417 if (GetVerboseLevel()>1) {
418 G4cout << " daughter " << index1 << ":" << *daughters_name[index1];
419 G4cout << " momentum:" << daughtermomentum[index1]/GeV << "[GeV/c]" <<G4endl;
420 }
421 for(index1 =numberOfDaughters-2; index1>=0; index1--) {
422 // calculate
423 daughtermomentum[index1]= Pmx( sm[index1],daughtermass[index1], sm[index1 +1]);
424 if(daughtermomentum[index1] < 0.0) {
425 // !!! illegal momentum !!!
426 if (GetVerboseLevel()>0) {
427 G4cout << "G4GeneralPhaseSpaceDecay::ManyBodyDecayIt ";
428 G4cout << " can not calculate daughter momentum " <<G4endl;
429 G4cout << " parent:" << *parent_name;
430 G4cout << " mass:" << parentmass/GeV << "[GeV/c/c]" <<G4endl;
431 G4cout << " daughter " << index1 << ":" << *daughters_name[index1];
432 G4cout << " mass:" << daughtermass[index1]/GeV << "[GeV/c/c]" ;
433 G4cout << " mass:" << daughtermomentum[index1]/GeV << "[GeV/c]" <<G4endl;
434 }
435 delete [] sm;
436 delete [] daughtermass;
437 delete [] daughtermomentum;
438 return NULL; // Error detection
439
440 } else {
441 // calculate weight of this events
442 weight *= daughtermomentum[index1]/sm[index1];
443 if (GetVerboseLevel()>1) {
444 G4cout << " daughter " << index1 << ":" << *daughters_name[index1];
445 G4cout << " momentum:" << daughtermomentum[index1]/GeV << "[GeV/c]" <<G4endl;
446 }
447 }
448 }
449 if (GetVerboseLevel()>1) {
450 G4cout << " weight: " << weight <<G4endl;
451 }
452
453 // exit if number of Try exceeds 100
454 if (numberOfTry++ >100) {
455 if (GetVerboseLevel()>0) {
456 G4cout << "G4GeneralPhaseSpaceDecay::ManyBodyDecayIt: ";
457 G4cout << " can not determine Decay Kinematics " << G4endl;
458 }
459 delete [] sm;
460 delete [] daughtermass;
461 delete [] daughtermomentum;
462 return NULL; // Error detection
463 }
464 } while ( weight > G4UniformRand());
465 if (GetVerboseLevel()>1) {
466 G4cout << "Start calulation of daughters momentum vector "<<G4endl;
467 }
468
469 G4double costheta, sintheta, phi;
470 G4double beta;
471 daughterparticle = new G4DynamicParticle*[numberOfDaughters];
472
473 index1 = numberOfDaughters -2;
474 costheta = 2.*G4UniformRand()-1.0;
475 sintheta = std::sqrt((1.0-costheta)*(1.0+costheta));
476 phi = twopi*G4UniformRand()*rad;
477 direction.setZ(costheta);
478 direction.setY(sintheta*std::sin(phi));
479 direction.setX(sintheta*std::cos(phi));
480 daughterparticle[index1] = new G4DynamicParticle( daughters[index1], direction*daughtermomentum[index1] );
481 daughterparticle[index1+1] = new G4DynamicParticle( daughters[index1+1], direction*(-1.0*daughtermomentum[index1]) );
482
483 for (index1 = numberOfDaughters -3; index1 >= 0; index1--) {
484 //calculate momentum direction
485 costheta = 2.*G4UniformRand()-1.0;
486 sintheta = std::sqrt((1.0-costheta)*(1.0+costheta));
487 phi = twopi*G4UniformRand()*rad;
488 direction.setZ(costheta);
489 direction.setY(sintheta*std::sin(phi));
490 direction.setX(sintheta*std::cos(phi));
491
492 // boost already created particles
493 beta = daughtermomentum[index1];
494 beta /= std::sqrt( daughtermomentum[index1]*daughtermomentum[index1] + sm[index1+1]*sm[index1+1] );
495 for (G4int index2 = index1+1; index2<numberOfDaughters; index2++) {
496 G4LorentzVector p4;
497 // make G4LorentzVector for secondaries
498 p4 = daughterparticle[index2]->Get4Momentum();
499
500 // boost secondaries to new frame
501 p4.boost( direction.x()*beta, direction.y()*beta, direction.z()*beta);
502
503 // change energy/momentum
504 daughterparticle[index2]->Set4Momentum(p4);
505 }
506 //create daughter G4DynamicParticle
507 daughterparticle[index1]= new G4DynamicParticle( daughters[index1], direction*(-1.0*daughtermomentum[index1]));
508 }
509
510 //create G4Decayproducts
511 G4DynamicParticle *parentparticle;
512 direction.setX(1.0); direction.setY(0.0); direction.setZ(0.0);
513 parentparticle = new G4DynamicParticle( parent, direction, 0.0);
514 products = new G4DecayProducts(*parentparticle);
515 delete parentparticle;
516 for (index1 = 0; index1<numberOfDaughters; index1++) {
517 products->PushProducts(daughterparticle[index1]);
518 }
519 if (GetVerboseLevel()>1) {
520 G4cout << "G4GeneralPhaseSpaceDecay::ManyBodyDecayIt ";
521 G4cout << " create decay products in rest frame " << G4endl;
522 products->DumpInfo();
523 }
524
525 delete [] daughterparticle;
526 delete [] daughtermomentum;
527 delete [] daughtermass;
528 delete [] sm;
529
530 return products;
531}
532
533
534
535
536
Note: See TracBrowser for help on using the repository browser.