Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4SPSPosDistribution.cc
Go to the documentation of this file.
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// MODULE: G4SPSPosDistribution.cc
29//
30// Version: 1.0
31// Date: 5/02/04
32// Author: Fan Lei
33// Organisation: QinetiQ ltd.
34// Customer: ESA/ESTEC
35//
36///////////////////////////////////////////////////////////////////////////////
37//
38// CHANGE HISTORY
39// --------------
40//
41//
42// Version 1.0, 05/02/2004, Fan Lei, Created.
43// Based on the G4GeneralParticleSource class in Geant4 v6.0
44//
45///////////////////////////////////////////////////////////////////////////////
46//
47
49
51#include "Randomize.hh"
53#include "G4VPhysicalVolume.hh"
55
57 : posRndm(0)
58{
59
60 // Initialise all variables
61 // Position distribution Variables
62
63 SourcePosType = "Point";
64 Shape = "NULL";
65 halfx = 0.;
66 halfy = 0.;
67 halfz = 0.;
68 Radius = 0.;
69 Radius0 = 0.;
70 SR = 0.;
71 SX = 0.;
72 SY = 0.;
73 ParAlpha = 0.;
74 ParTheta = 0.;
75 ParPhi = 0.;
76 CentreCoords = G4ThreeVector(0., 0., 0.);
77 Rotx = CLHEP::HepXHat;
78 Roty = CLHEP::HepYHat;
79 Rotz = CLHEP::HepZHat;
80 Confine = false; //If true confines source distribution to VolName
81 VolName = "NULL";
82 SideRefVec1 = CLHEP::HepXHat; // x-axis
83 SideRefVec2 = CLHEP::HepYHat; // y-axis
84 SideRefVec3 = CLHEP::HepZHat; // z-axis
85 verbosityLevel = 0 ;
88}
89
91{
92}
93
95{
96 SourcePosType = PosType;
97}
98
100{
101 Shape = shapeType;
102}
103
105{
106 CentreCoords = coordsOfCentre;
107}
108
110{
111 // This should be x'
112 Rotx = posrot1;
113 if(verbosityLevel == 2)
114 {
115 G4cout << "Vector x' " << Rotx << G4endl;
116 }
117 GenerateRotationMatrices();
118}
119
121{
122 // This is a vector in the plane x'y' but need not
123 // be y'
124 Roty = posrot2;
125 if(verbosityLevel == 2)
126 {
127 G4cout << "The vector in the x'-y' plane " << Roty << G4endl;
128 }
129 GenerateRotationMatrices();
130}
131
133{
134 halfx = xhalf;
135}
136
138{
139 halfy = yhalf;
140}
141
143{
144 halfz = zhalf;
145}
146
148{
149 Radius = rds;
150}
151
153{
154 Radius0 = rds;
155}
156
158{
159 SX = SY = r;
160 SR = r;
161}
162
164{
165 SX = r;
166}
167
169{
170 SY = r;
171}
172
174{
175 ParAlpha = paralp;
176}
177
179{
180 ParTheta = parthe;
181}
182
184{
185 ParPhi = parphi;
186}
187
188void G4SPSPosDistribution::GenerateRotationMatrices()
189{
190 // This takes in 2 vectors, x' and one in the plane x'-y',
191 // and from these takes a cross product to calculate z'.
192 // Then a cross product is taken between x' and z' to give
193 // y'.
194 Rotx = Rotx.unit(); // x'
195 Roty = Roty.unit(); // vector in x'y' plane
196 Rotz = Rotx.cross(Roty); // z'
197 Rotz = Rotz.unit();
198 Roty = Rotz.cross(Rotx); // y'
199 Roty = Roty.unit();
200 if(verbosityLevel == 2)
201 {
202 G4cout << "The new axes, x', y', z' " << Rotx << " " << Roty << " " << Rotz << G4endl;
203 }
204}
205
207{
208 VolName = Vname;
209 if(verbosityLevel == 2)
210 G4cout << VolName << G4endl;
211 G4VPhysicalVolume *tempPV = NULL;
212 G4PhysicalVolumeStore *PVStore = 0;
213 G4String theRequiredVolumeName = VolName;
215 G4int i = 0;
216 G4bool found = false;
217 if(verbosityLevel == 2)
218 G4cout << PVStore->size() << G4endl;
219 while (!found && i<G4int(PVStore->size())) {
220 tempPV = (*PVStore)[i];
221 found = tempPV->GetName() == theRequiredVolumeName;
222 if(verbosityLevel == 2)
223 G4cout << i << " " << " " << tempPV->GetName() << " " << theRequiredVolumeName << " " << found << G4endl;
224 if (!found)
225 {i++;}
226 }
227 // found = true then the volume exists else it doesnt.
228 if(found == true)
229 {
230 if(verbosityLevel >= 1)
231 G4cout << "Volume " << VolName << " exists" << G4endl;
232 Confine = true;
233 }
234 else
235 {
236 G4cout << " **** Error: Volume does not exist **** " << G4endl;
237 G4cout << " Ignoring confine condition" << G4endl;
238 Confine = false;
239 VolName = "NULL";
240 }
241
242}
243
244void G4SPSPosDistribution::GeneratePointSource()
245{
246 // Generates Points given the point source.
247 if(SourcePosType == "Point")
248 particle_position = CentreCoords;
249 else
250 if(verbosityLevel >= 1)
251 G4cout << "Error SourcePosType is not set to Point" << G4endl;
252}
253
254void G4SPSPosDistribution::GeneratePointsInBeam()
255{
256 G4double x, y, z;
257
258 G4ThreeVector RandPos;
259 G4double tempx, tempy, tempz;
260 z = 0.;
261
262 // Private Method to create points in a plane
263 if(Shape == "Circle")
264 {
265 x = Radius + 100.;
266 y = Radius + 100.;
267 while(std::sqrt((x*x) + (y*y)) > Radius)
268 {
269 x = posRndm->GenRandX();
270 y = posRndm->GenRandY();
271
272 x = (x*2.*Radius) - Radius;
273 y = (y*2.*Radius) - Radius;
274 }
275 x += G4RandGauss::shoot(0.0,SX) ;
276 y += G4RandGauss::shoot(0.0,SY) ;
277 }
278 else
279 {
280 // all other cases default to Rectangle case
281 x = posRndm->GenRandX();
282 y = posRndm->GenRandY();
283 x = (x*2.*halfx) - halfx;
284 y = (y*2.*halfy) - halfy;
285 x += G4RandGauss::shoot(0.0,SX);
286 y += G4RandGauss::shoot(0.0,SY);
287 }
288 // Apply Rotation Matrix
289 // x * Rotx, y * Roty and z * Rotz
290 if(verbosityLevel >= 2)
291 {
292 G4cout << "Raw position " << x << "," << y << "," << z << G4endl;
293 }
294 tempx = (x * Rotx.x()) + (y * Roty.x()) + (z * Rotz.x());
295 tempy = (x * Rotx.y()) + (y * Roty.y()) + (z * Rotz.y());
296 tempz = (x * Rotx.z()) + (y * Roty.z()) + (z * Rotz.z());
297
298 RandPos.setX(tempx);
299 RandPos.setY(tempy);
300 RandPos.setZ(tempz);
301
302 // Translate
303 particle_position = CentreCoords + RandPos;
304 if(verbosityLevel >= 1)
305 {
306 if(verbosityLevel >= 2)
307 {
308 G4cout << "Rotated Position " << RandPos << G4endl;
309 }
310 G4cout << "Rotated and Translated position " << particle_position << G4endl;
311 }
312}
313
314void G4SPSPosDistribution::GeneratePointsInPlane()
315{
316 G4double x, y, z;
317 G4double expression;
318 G4ThreeVector RandPos;
319 G4double tempx, tempy, tempz;
320 x = y = z = 0.;
321
322 if(SourcePosType != "Plane" && verbosityLevel >= 1)
323 G4cout << "Error: SourcePosType is not Plane" << G4endl;
324
325 // Private Method to create points in a plane
326 if(Shape == "Circle")
327 {
328 x = Radius + 100.;
329 y = Radius + 100.;
330 while(std::sqrt((x*x) + (y*y)) > Radius)
331 {
332 x = posRndm->GenRandX();
333 y = posRndm->GenRandY();
334
335 x = (x*2.*Radius) - Radius;
336 y = (y*2.*Radius) - Radius;
337 }
338 }
339 else if(Shape == "Annulus")
340 {
341 x = Radius + 100.;
342 y = Radius + 100.;
343 while(std::sqrt((x*x) + (y*y)) > Radius || std::sqrt((x*x) + (y*y)) < Radius0 )
344 {
345 x = posRndm->GenRandX();
346 y = posRndm->GenRandY();
347
348 x = (x*2.*Radius) - Radius;
349 y = (y*2.*Radius) - Radius;
350 }
351 }
352 else if(Shape == "Ellipse")
353 {
354 expression = 20.;
355 while(expression > 1.)
356 {
357 x = posRndm->GenRandX();
358 y = posRndm->GenRandY();
359
360 x = (x*2.*halfx) - halfx;
361 y = (y*2.*halfy) - halfy;
362
363 expression = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
364 }
365 }
366 else if(Shape == "Square")
367 {
368 x = posRndm->GenRandX();
369 y = posRndm->GenRandY();
370 x = (x*2.*halfx) - halfx;
371 y = (y*2.*halfy) - halfy;
372 }
373 else if(Shape == "Rectangle")
374 {
375 x = posRndm->GenRandX();
376 y = posRndm->GenRandY();
377 x = (x*2.*halfx) - halfx;
378 y = (y*2.*halfy) - halfy;
379 }
380 else
381 G4cout << "Shape not one of the plane types" << G4endl;
382
383 // Apply Rotation Matrix
384 // x * Rotx, y * Roty and z * Rotz
385 if(verbosityLevel == 2)
386 {
387 G4cout << "Raw position " << x << "," << y << "," << z << G4endl;
388 }
389 tempx = (x * Rotx.x()) + (y * Roty.x()) + (z * Rotz.x());
390 tempy = (x * Rotx.y()) + (y * Roty.y()) + (z * Rotz.y());
391 tempz = (x * Rotx.z()) + (y * Roty.z()) + (z * Rotz.z());
392
393 RandPos.setX(tempx);
394 RandPos.setY(tempy);
395 RandPos.setZ(tempz);
396
397 // Translate
398 particle_position = CentreCoords + RandPos;
399 if(verbosityLevel >= 1)
400 {
401 if(verbosityLevel == 2)
402 {
403 G4cout << "Rotated Position " << RandPos << G4endl;
404 }
405 G4cout << "Rotated and Translated position " << particle_position << G4endl;
406 }
407
408 // For Cosine-Law make SideRefVecs = to Rotation matrix vectors
409 SideRefVec1 = Rotx;
410 SideRefVec2 = Roty;
411 SideRefVec3 = Rotz;
412 // If rotation matrix z' point to origin then invert the matrix
413 // So that SideRefVecs point away.
414 if((CentreCoords.x() > 0. && Rotz.x() < 0.)
415 || (CentreCoords.x() < 0. && Rotz.x() > 0.)
416 || (CentreCoords.y() > 0. && Rotz.y() < 0.)
417 || (CentreCoords.y() < 0. && Rotz.y() > 0.)
418 || (CentreCoords.z() > 0. && Rotz.z() < 0.)
419 || (CentreCoords.z() < 0. && Rotz.z() > 0.))
420 {
421 // Invert y and z.
422 SideRefVec2 = -SideRefVec2;
423 SideRefVec3 = -SideRefVec3;
424 }
425 if(verbosityLevel == 2)
426 {
427 G4cout << "Reference vectors for cosine-law " << SideRefVec1 << " " << SideRefVec2 << " " << SideRefVec3 << G4endl;
428 }
429}
430
431void G4SPSPosDistribution::GeneratePointsOnSurface()
432{
433 //Private method to create points on a surface
434 G4double theta, phi;
435 G4double x, y, z;
436 x = y = z = 0.;
437 G4ThreeVector RandPos;
438 // G4double tempx, tempy, tempz;
439
440 if(SourcePosType != "Surface" && verbosityLevel >= 1)
441 G4cout << "Error SourcePosType not Surface" << G4endl;
442
443 if(Shape == "Sphere")
444 {
445 // G4double tantheta;
446 theta = posRndm->GenRandPosTheta();
447 phi = posRndm->GenRandPosPhi();
448 theta = std::acos(1. - 2.*theta); // theta isotropic
449 phi = phi * 2. * pi;
450 // tantheta = std::tan(theta);
451
452 x = Radius * std::sin(theta) * std::cos(phi);
453 y = Radius * std::sin(theta) * std::sin(phi);
454 z = Radius * std::cos(theta);
455
456 RandPos.setX(x);
457 RandPos.setY(y);
458 RandPos.setZ(z);
459
460 // Cosine-law (not a good idea to use this here)
461 G4ThreeVector zdash(x,y,z);
462 zdash = zdash.unit();
463 G4ThreeVector xdash = Rotz.cross(zdash);
464 G4ThreeVector ydash = xdash.cross(zdash);
465 SideRefVec1 = xdash.unit();
466 SideRefVec2 = ydash.unit();
467 SideRefVec3 = zdash.unit();
468 }
469 else if(Shape == "Ellipsoid")
470 {
471 G4double minphi, maxphi, middlephi;
472 G4double answer, constant;
473
474 constant = pi/(halfx*halfx) + pi/(halfy*halfy) +
475 twopi/(halfz*halfz);
476
477 // simplified approach
478 theta = posRndm->GenRandPosTheta();
479 phi = posRndm->GenRandPosPhi();
480
481 theta = std::acos(1. - 2.*theta);
482 minphi = 0.;
483 maxphi = twopi;
484 while(maxphi-minphi > 0.)
485 {
486 middlephi = (maxphi+minphi)/2.;
487 answer = (1./(halfx*halfx))*(middlephi/2. + std::sin(2*middlephi)/4.)
488 + (1./(halfy*halfy))*(middlephi/2. - std::sin(2*middlephi)/4.)
489 + middlephi/(halfz*halfz);
490 answer = answer/constant;
491 if(answer > phi) maxphi = middlephi;
492 if(answer < phi) minphi = middlephi;
493 if(std::fabs(answer-phi) <= 0.00001)
494 {
495 minphi = maxphi +1;
496 phi = middlephi;
497 }
498 }
499
500 x = std::sin(theta)*std::cos(phi);
501 y = std::sin(theta)*std::sin(phi);
502 z = std::cos(theta);
503 // x,y and z form a unit vector. Put this onto the ellipse.
504 G4double lhs;
505 // solve for x
506 G4double numYinX = y/x;
507 G4double numZinX = z/x;
508 G4double tempxvar;
509 tempxvar= 1./(halfx*halfx)+(numYinX*numYinX)/(halfy*halfy)
510 + (numZinX*numZinX)/(halfz*halfz);
511
512 tempxvar = 1./tempxvar;
513 G4double coordx = std::sqrt(tempxvar);
514
515 //solve for y
516 G4double numXinY = x/y;
517 G4double numZinY = z/y;
518 G4double tempyvar;
519 tempyvar=(numXinY*numXinY)/(halfx*halfx)+1./(halfy*halfy)
520 +(numZinY*numZinY)/(halfz*halfz);
521 tempyvar = 1./tempyvar;
522 G4double coordy = std::sqrt(tempyvar);
523
524 //solve for z
525 G4double numXinZ = x/z;
526 G4double numYinZ = y/z;
527 G4double tempzvar;
528 tempzvar=(numXinZ*numXinZ)/(halfx*halfx)
529 +(numYinZ*numYinZ)/(halfy*halfy)+1./(halfz*halfz);
530 tempzvar = 1./tempzvar;
531 G4double coordz = std::sqrt(tempzvar);
532
533 lhs = std::sqrt((coordx*coordx)/(halfx*halfx) +
534 (coordy*coordy)/(halfy*halfy) +
535 (coordz*coordz)/(halfz*halfz));
536
537 if(std::fabs(lhs-1.) > 0.001 && verbosityLevel >= 1)
538 G4cout << "Error: theta, phi not really on ellipsoid" << G4endl;
539
540 // coordx, coordy and coordz are all positive
541 G4double TestRandVar = G4UniformRand();
542 if(TestRandVar > 0.5)
543 {
544 coordx = -coordx;
545 }
546 TestRandVar = G4UniformRand();
547 if(TestRandVar > 0.5)
548 {
549 coordy = -coordy;
550 }
551 TestRandVar = G4UniformRand();
552 if(TestRandVar > 0.5)
553 {
554 coordz = -coordz;
555 }
556
557 RandPos.setX(coordx);
558 RandPos.setY(coordy);
559 RandPos.setZ(coordz);
560
561 // Cosine-law (not a good idea to use this here)
562 G4ThreeVector zdash(coordx,coordy,coordz);
563 zdash = zdash.unit();
564 G4ThreeVector xdash = Rotz.cross(zdash);
565 G4ThreeVector ydash = xdash.cross(zdash);
566 SideRefVec1 = xdash.unit();
567 SideRefVec2 = ydash.unit();
568 SideRefVec3 = zdash.unit();
569 }
570 else if(Shape == "Cylinder")
571 {
572 G4double AreaTop, AreaBot, AreaLat;
573 G4double AreaTotal, prob1, prob2, prob3;
574 G4double testrand;
575
576 // User giver Radius and z-half length
577 // Calculate surface areas, maybe move this to
578 // a different routine.
579
580 AreaTop = pi * Radius * Radius;
581 AreaBot = AreaTop;
582 AreaLat = 2. * pi * Radius * 2. * halfz;
583 AreaTotal = AreaTop + AreaBot + AreaLat;
584
585 prob1 = AreaTop / AreaTotal;
586 prob2 = AreaBot / AreaTotal;
587 prob3 = 1.00 - prob1 - prob2;
588 if(std::fabs(prob3 - (AreaLat/AreaTotal)) >= 0.001)
589 {
590 if(verbosityLevel >= 1)
591 G4cout << AreaLat/AreaTotal << " " << prob3<<G4endl;
592 G4cout << "Error in prob3" << G4endl;
593 }
594
595 // Decide surface to calculate point on.
596
597 testrand = G4UniformRand();
598 if(testrand <= prob1)
599 {
600 //Point on Top surface
601 z = halfz;
602 x = Radius + 100.;
603 y = Radius + 100.;
604 while(((x*x)+(y*y)) > (Radius*Radius))
605 {
606 x = posRndm->GenRandX();
607 y = posRndm->GenRandY();
608
609 x = x * 2. * Radius;
610 y = y * 2. * Radius;
611 x = x - Radius;
612 y = y - Radius;
613 }
614 // Cosine law
615 SideRefVec1 = Rotx;
616 SideRefVec2 = Roty;
617 SideRefVec3 = Rotz;
618 }
619 else if((testrand > prob1) && (testrand <= (prob1 + prob2)))
620 {
621 //Point on Bottom surface
622 z = -halfz;
623 x = Radius + 100.;
624 y = Radius + 100.;
625 while(((x*x)+(y*y)) > (Radius*Radius))
626 {
627 x = posRndm->GenRandX();
628 y = posRndm->GenRandY();
629
630 x = x * 2. * Radius;
631 y = y * 2. * Radius;
632 x = x - Radius;
633 y = y - Radius;
634 }
635 // Cosine law
636 SideRefVec1 = Rotx;
637 SideRefVec2 = -Roty;
638 SideRefVec3 = -Rotz;
639 }
640 else if(testrand > (prob1+prob2))
641 {
642 G4double rand;
643 //Point on Lateral Surface
644
645 rand = posRndm->GenRandPosPhi();
646 rand = rand * 2. * pi;
647
648 x = Radius * std::cos(rand);
649 y = Radius * std::sin(rand);
650
651 z = posRndm->GenRandZ();
652
653 z = z * 2. * halfz;
654 z = z - halfz;
655
656 // Cosine law
657 G4ThreeVector zdash(x,y,0.);
658 zdash = zdash.unit();
659 G4ThreeVector xdash = Rotz.cross(zdash);
660 G4ThreeVector ydash = xdash.cross(zdash);
661 SideRefVec1 = xdash.unit();
662 SideRefVec2 = ydash.unit();
663 SideRefVec3 = zdash.unit();
664 }
665 else
666 G4cout << "Error: testrand " << testrand << G4endl;
667
668 RandPos.setX(x);
669 RandPos.setY(y);
670 RandPos.setZ(z);
671
672 }
673 else if(Shape == "Para")
674 {
675 G4double testrand;
676 //Right Parallelepiped.
677 // User gives x,y,z half lengths and ParAlpha
678 // ParTheta and ParPhi
679 // +x = <1, -x >1 & <2, +y >2 & <3, -y >3 &<4
680 // +z >4 & < 5, -z >5 &<6.
681 testrand = G4UniformRand();
682 G4double AreaX = halfy * halfz * 4.;
683 G4double AreaY = halfx * halfz * 4.;
684 G4double AreaZ = halfx * halfy * 4.;
685 G4double AreaTotal = 2*(AreaX + AreaY + AreaZ);
686 G4double Probs[6];
687 Probs[0] = AreaX/AreaTotal;
688 Probs[1] = Probs[0] + AreaX/AreaTotal;
689 Probs[2] = Probs[1] + AreaY/AreaTotal;
690 Probs[3] = Probs[2] + AreaY/AreaTotal;
691 Probs[4] = Probs[3] + AreaZ/AreaTotal;
692 Probs[5] = Probs[4] + AreaZ/AreaTotal;
693
694 x = posRndm->GenRandX();
695 y = posRndm->GenRandY();
696 z = posRndm->GenRandZ();
697
698 x = x * halfx * 2.;
699 x = x - halfx;
700 y = y * halfy * 2.;
701 y = y - halfy;
702 z = z * halfz * 2.;
703 z = z - halfz;
704 // Pick a side first
705 if(testrand < Probs[0])
706 {
707 // side is +x
708 x = halfx + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
709 y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
710 // z = z;
711 // Cosine-law
712 G4ThreeVector xdash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
713 halfz*std::tan(ParTheta)*std::sin(ParPhi),
714 halfz/std::cos(ParPhi));
715 G4ThreeVector ydash(halfy*std::tan(ParAlpha), -halfy, 0.0);
716 xdash = xdash.unit();
717 ydash = ydash.unit();
718 G4ThreeVector zdash = xdash.cross(ydash);
719 SideRefVec1 = xdash.unit();
720 SideRefVec2 = ydash.unit();
721 SideRefVec3 = zdash.unit();
722 }
723 else if(testrand >= Probs[0] && testrand < Probs[1])
724 {
725 // side is -x
726 x = -halfx + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
727 y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
728 // z = z;
729 // Cosine-law
730 G4ThreeVector xdash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
731 halfz*std::tan(ParTheta)*std::sin(ParPhi),
732 halfz/std::cos(ParPhi));
733 G4ThreeVector ydash(halfy*std::tan(ParAlpha), halfy, 0.0);
734 xdash = xdash.unit();
735 ydash = ydash.unit();
736 G4ThreeVector zdash = xdash.cross(ydash);
737 SideRefVec1 = xdash.unit();
738 SideRefVec2 = ydash.unit();
739 SideRefVec3 = zdash.unit();
740 }
741 else if(testrand >= Probs[1] && testrand < Probs[2])
742 {
743 // side is +y
744 x = x + z*std::tan(ParTheta)*std::cos(ParPhi) + halfy*std::tan(ParAlpha);
745 y = halfy + z*std::tan(ParTheta)*std::sin(ParPhi);
746 // z = z;
747 // Cosine-law
748 G4ThreeVector ydash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
749 halfz*std::tan(ParTheta)*std::sin(ParPhi),
750 halfz/std::cos(ParPhi));
751 ydash = ydash.unit();
752 G4ThreeVector xdash = Roty.cross(ydash);
753 G4ThreeVector zdash = xdash.cross(ydash);
754 SideRefVec1 = xdash.unit();
755 SideRefVec2 = -ydash.unit();
756 SideRefVec3 = -zdash.unit();
757 }
758 else if(testrand >= Probs[2] && testrand < Probs[3])
759 {
760 // side is -y
761 x = x + z*std::tan(ParTheta)*std::cos(ParPhi) - halfy*std::tan(ParAlpha);
762 y = -halfy + z*std::tan(ParTheta)*std::sin(ParPhi);
763 // z = z;
764 // Cosine-law
765 G4ThreeVector ydash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
766 halfz*std::tan(ParTheta)*std::sin(ParPhi),
767 halfz/std::cos(ParPhi));
768 ydash = ydash.unit();
769 G4ThreeVector xdash = Roty.cross(ydash);
770 G4ThreeVector zdash = xdash.cross(ydash);
771 SideRefVec1 = xdash.unit();
772 SideRefVec2 = ydash.unit();
773 SideRefVec3 = zdash.unit();
774 }
775 else if(testrand >= Probs[3] && testrand < Probs[4])
776 {
777 // side is +z
778 z = halfz;
779 y = y + halfz*std::sin(ParPhi)*std::tan(ParTheta);
780 x = x + halfz*std::cos(ParPhi)*std::tan(ParTheta) + y*std::tan(ParAlpha);
781 // Cosine-law
782 SideRefVec1 = Rotx;
783 SideRefVec2 = Roty;
784 SideRefVec3 = Rotz;
785 }
786 else if(testrand >= Probs[4] && testrand < Probs[5])
787 {
788 // side is -z
789 z = -halfz;
790 y = y - halfz*std::sin(ParPhi)*std::tan(ParTheta);
791 x = x - halfz*std::cos(ParPhi)*std::tan(ParTheta) + y*std::tan(ParAlpha);
792 // Cosine-law
793 SideRefVec1 = Rotx;
794 SideRefVec2 = -Roty;
795 SideRefVec3 = -Rotz;
796 }
797 else
798 {
799 G4cout << "Error: testrand out of range" << G4endl;
800 if(verbosityLevel >= 1)
801 G4cout << "testrand=" << testrand << " Probs[5]=" << Probs[5] <<G4endl;
802 }
803
804 RandPos.setX(x);
805 RandPos.setY(y);
806 RandPos.setZ(z);
807 }
808
809 // Apply Rotation Matrix
810 // x * Rotx, y * Roty and z * Rotz
811 if(verbosityLevel == 2)
812 G4cout << "Raw position " << RandPos << G4endl;
813
814 x=(RandPos.x()*Rotx.x())+(RandPos.y()*Roty.x())+(RandPos.z()*Rotz.x());
815 y=(RandPos.x()*Rotx.y())+(RandPos.y()*Roty.y())+(RandPos.z()*Rotz.y());
816 z=(RandPos.x()*Rotx.z())+(RandPos.y()*Roty.z())+(RandPos.z()*Rotz.z());
817
818 RandPos.setX(x);
819 RandPos.setY(y);
820 RandPos.setZ(z);
821
822 // Translate
823 particle_position = CentreCoords + RandPos;
824
825 if(verbosityLevel >= 1)
826 {
827 if(verbosityLevel == 2)
828 G4cout << "Rotated position " << RandPos << G4endl;
829 G4cout << "Rotated and translated position " << particle_position << G4endl;
830 }
831 if(verbosityLevel == 2)
832 {
833 G4cout << "Reference vectors for cosine-law " << SideRefVec1 << " " << SideRefVec2 << " " << SideRefVec3 << G4endl;
834 }
835}
836
837void G4SPSPosDistribution::GeneratePointsInVolume()
838{
839 G4ThreeVector RandPos;
840 G4double tempx, tempy, tempz;
841 G4double x, y, z;
842 x = y = z = 0.;
843 if(SourcePosType != "Volume" && verbosityLevel >= 1)
844 G4cout << "Error SourcePosType not Volume" << G4endl;
845 //Private method to create points in a volume
846 if(Shape == "Sphere")
847 {
848 x = Radius*2.;
849 y = Radius*2.;
850 z = Radius*2.;
851 while(((x*x)+(y*y)+(z*z)) > (Radius*Radius))
852 {
853 x = posRndm->GenRandX();
854 y = posRndm->GenRandY();
855 z = posRndm->GenRandZ();
856
857 x = (x*2.*Radius) - Radius;
858 y = (y*2.*Radius) - Radius;
859 z = (z*2.*Radius) - Radius;
860 }
861 }
862 else if(Shape == "Ellipsoid")
863 {
864 G4double temp;
865 temp = 100.;
866 while(temp > 1.)
867 {
868 x = posRndm->GenRandX();
869 y = posRndm->GenRandY();
870 z = posRndm->GenRandZ();
871
872 x = (x*2.*halfx) - halfx;
873 y = (y*2.*halfy) - halfy;
874 z = (z*2.*halfz) - halfz;
875
876 temp = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy))
877 + ((z*z)/(halfz*halfz));
878 }
879 }
880 else if(Shape == "Cylinder")
881 {
882 x = Radius*2.;
883 y = Radius*2.;
884 while(((x*x)+(y*y)) > (Radius*Radius))
885 {
886 x = posRndm->GenRandX();
887 y = posRndm->GenRandY();
888 z = posRndm->GenRandZ();
889
890 x = (x*2.*Radius) - Radius;
891 y = (y*2.*Radius) - Radius;
892 z = (z*2.*halfz) - halfz;
893 }
894 }
895 else if(Shape == "Para")
896 {
897 x = posRndm->GenRandX();
898 y = posRndm->GenRandY();
899 z = posRndm->GenRandZ();
900 x = (x*2.*halfx) - halfx;
901 y = (y*2.*halfy) - halfy;
902 z = (z*2.*halfz) - halfz;
903 x = x + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
904 y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
905 // z = z;
906 }
907 else
908 G4cout << "Error: Volume Shape Doesnt Exist" << G4endl;
909
910 RandPos.setX(x);
911 RandPos.setY(y);
912 RandPos.setZ(z);
913
914 // Apply Rotation Matrix
915 // x * Rotx, y * Roty and z * Rotz
916 tempx = (x * Rotx.x()) + (y * Roty.x()) + (z * Rotz.x());
917 tempy = (x * Rotx.y()) + (y * Roty.y()) + (z * Rotz.y());
918 tempz = (x * Rotx.z()) + (y * Roty.z()) + (z * Rotz.z());
919
920 RandPos.setX(tempx);
921 RandPos.setY(tempy);
922 RandPos.setZ(tempz);
923
924 // Translate
925 particle_position = CentreCoords + RandPos;
926
927 if(verbosityLevel == 2)
928 {
929 G4cout << "Raw position " << x << "," << y << "," << z << G4endl;
930 G4cout << "Rotated position " << RandPos << G4endl;
931 }
932 if(verbosityLevel >= 1)
933 G4cout << "Rotated and translated position " << particle_position << G4endl;
934
935 // Cosine-law (not a good idea to use this here)
936 G4ThreeVector zdash(tempx,tempy,tempz);
937 zdash = zdash.unit();
938 G4ThreeVector xdash = Rotz.cross(zdash);
939 G4ThreeVector ydash = xdash.cross(zdash);
940 SideRefVec1 = xdash.unit();
941 SideRefVec2 = ydash.unit();
942 SideRefVec3 = zdash.unit();
943
944 if(verbosityLevel == 2)
945 {
946 G4cout << "Reference vectors for cosine-law " << SideRefVec1 << " " << SideRefVec2 << " " << SideRefVec3 << G4endl;
947 }
948}
949
950G4bool G4SPSPosDistribution::IsSourceConfined()
951{
952 // Method to check point is within the volume specified
953 if(Confine == false)
954 G4cout << "Error: Confine is false" << G4endl;
955 G4ThreeVector null(0.,0.,0.);
956 G4ThreeVector *ptr;
957 ptr = &null;
958
959 // Check particle_position is within VolName, if so true,
960 // else false
961 G4VPhysicalVolume *theVolume;
962 theVolume=gNavigator->LocateGlobalPointAndSetup(particle_position,ptr,true);
963 G4String theVolName = theVolume->GetName();
964 if(theVolName == VolName)
965 {
966 if(verbosityLevel >= 1)
967 G4cout << "Particle is in volume " << VolName << G4endl;
968 return(true);
969 }
970 else
971 return(false);
972}
973
975{
976 //
977 G4bool srcconf = false;
978 G4int LoopCount = 0;
979 while(srcconf == false)
980 {
981 if(SourcePosType == "Point")
982 GeneratePointSource();
983 else if(SourcePosType == "Beam")
984 GeneratePointsInBeam();
985 else if(SourcePosType == "Plane")
986 GeneratePointsInPlane();
987 else if(SourcePosType == "Surface")
988 GeneratePointsOnSurface();
989 else if(SourcePosType == "Volume")
990 GeneratePointsInVolume();
991 else
992 {
993 G4cout << "Error: SourcePosType undefined" << G4endl;
994 G4cout << "Generating point source" << G4endl;
995 GeneratePointSource();
996 }
997 if(Confine == true)
998 {
999 srcconf = IsSourceConfined();
1000 // if source in confined srcconf = true terminating the loop
1001 // if source isnt confined srcconf = false and loop continues
1002 }
1003 else if(Confine == false)
1004 srcconf = true; // terminate loop
1005 LoopCount++;
1006 if(LoopCount == 100000)
1007 {
1008 G4cout << "*************************************" << G4endl;
1009 G4cout << "LoopCount = 100000" << G4endl;
1010 G4cout << "Either the source distribution >> confinement" << G4endl;
1011 G4cout << "or any confining volume may not overlap with" << G4endl;
1012 G4cout << "the source distribution or any confining volumes" << G4endl;
1013 G4cout << "may not exist"<< G4endl;
1014 G4cout << "If you have set confine then this will be ignored" <<G4endl;
1015 G4cout << "for this event." << G4endl;
1016 G4cout << "*************************************" << G4endl;
1017 srcconf = true; //Avoids an infinite loop
1018 }
1019 }
1020 return particle_position;
1021}
1022
1023
1024
1025
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
double z() const
Hep3Vector unit() const
double x() const
void setY(double)
double y() const
Hep3Vector cross(const Hep3Vector &) const
void setZ(double)
void setX(double)
virtual G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=0, const G4bool pRelativeSearch=true, const G4bool ignoreDirection=true)
Definition: G4Navigator.cc:116
static G4PhysicalVolumeStore * GetInstance()
void ConfineSourceToVolume(G4String)
void SetCentreCoords(G4ThreeVector)
void SetPosRot2(G4ThreeVector)
void SetPosRot1(G4ThreeVector)
static G4TransportationManager * GetTransportationManager()
G4Navigator * GetNavigatorForTracking() const
const G4String & GetName() const
DLL_API const Hep3Vector HepZHat
Definition: ThreeVector.h:424
DLL_API const Hep3Vector HepXHat
DLL_API const Hep3Vector HepYHat
Definition: ThreeVector.h:424
const G4double pi