00001
00002
00003 #include "flux/FluxSource.h"
00004
00005 #include "dom/DOM_Element.hpp"
00006 #include "dom/DOM_NodeList.hpp"
00007 #include "xml/Dom.h"
00008
00009 #include "SpectrumFactoryTable.h"
00010
00011 #include "flux/SimpleSpectrum.h"
00012
00013 #include "facilities/error.h"
00014
00015 #include "CLHEP/Random/RandFlat.h"
00016
00017 #include "geometry/CoordTransform.h"
00018 #include "geometry/Ray.h"
00019 #include "geometry/Box.h"
00020
00021
00022 double FluxSource::s_backoff;
00023 double FluxSource::s_radius=1.0;
00024
00025
00026 #include <algorithm>
00027 #include <list>
00028 using std::min;
00029 using std::max;
00030
00031
00032 FluxSource::FluxSource(Spectrum* aSpec, double aFlux)
00033 : EventSource(aFlux), m_spectrum(0),
00034 m_maxEnergy(100.),
00035 _minCos(-0.4f), _maxCos(1.0f), _minPhi(0.0f), _maxPhi(2*M_PI),
00036 m_rmin(0), m_rmax(1), _phi(0.0f), _theta(0.0f), m_pointtype(NOPOINT),
00037 m_launch(NONE), illumBox(0)
00038 {
00039 s_backoff = 0.;
00040 spectrum(aSpec);
00041 useSpectrumDirection();
00042 setAcceptance();
00043 }
00044
00045 FluxSource::FluxSource(const DOM_Element& xelem )
00046 : EventSource (xelem), m_spectrum(0),
00047 m_maxEnergy(100.),
00048 _minCos(-0.4f), _maxCos(1.0f), _minPhi(0.0f), _maxPhi(2*M_PI),
00049 m_rmin(0), m_rmax(1), _phi(0.0f), _theta(0.0f), m_pointtype(NOPOINT), m_launch(NONE), illumBox(0)
00050 {
00051 static double d2r = M_PI/180.;
00052
00053 Spectrum* s = 0;
00054 std::string class_name;
00055 std::string source_params;
00056
00057 DOM_Element spec = xml::Dom::findFirstChildByName(xelem, "spectrum");
00058
00059
00060 if (spec == DOM_Element()) {
00061
00062
00063 class_name = xelem.getAttribute("name").transcode();
00064 useSpectrumDirection();
00065
00066 } else {
00067
00068
00069 DOM_NodeList children = spec.getChildNodes();
00070
00071
00072 DOM_Node childNode = children.item(0);
00073 DOM_Element specType;
00074
00075 if (childNode.getNodeType() == DOM_Node::ELEMENT_NODE) {
00076 specType = (DOM_Element &) childNode;
00077 }
00078 else specType = xml::Dom::getSiblingElement(childNode);
00079
00080 DOMString typeTagName = specType.getTagName();
00081 std::string spectrum_name = spec.getAttribute("name").transcode();
00082
00083 if (typeTagName.equals("particle")) s = new SimpleSpectrum(specType);
00084 else if (typeTagName.equals("SpectrumClass")) {
00085
00086 class_name = specType.getAttribute("name").transcode();
00087 source_params= specType.getAttribute("params").transcode();
00088 }
00089 else {
00090
00091 class_name = typeTagName.transcode();
00092 }
00093
00094 DOM_Element angles = xml::Dom::getSiblingElement(specType);
00095
00096 DOMString anglesTag = angles.getTagName();
00097
00098 if (anglesTag.equals("solid_angle") ) {
00099 setLaunch(atof(angles.getAttribute("theta").transcode()) * d2r,
00100 atof(angles.getAttribute("phi").transcode()) *d2r);
00101 setCosThetaRange(atof(angles.getAttribute("mincos").transcode()),
00102 atof(angles.getAttribute("maxcos").transcode()) );
00103 }
00104 else if (anglesTag.equals("direction") ) {
00105 setLaunch(atof(angles.getAttribute("theta").transcode()) * d2r,
00106 atof(angles.getAttribute("phi").transcode()) *d2r);
00107 }
00108 else if (anglesTag.equals("use_spectrum") ) {
00109 useSpectrumDirection();
00110 }
00111 else if(anglesTag.equals("galactic_dir")){
00112 m_galb=atof(angles.getAttribute("b").transcode());
00113 m_gall=atof(angles.getAttribute("l").transcode());
00114 getGalacticDir(atof(angles.getAttribute("l").transcode()),
00115 atof(angles.getAttribute("b").transcode()) );
00116 m_launch=GALACTIC;
00117 }
00118 else {
00119 FATAL_MACRO("Unknown angle specification in Flux::Flux \""
00120 << anglesTag.transcode() << "\"" );
00121 }
00122
00123
00124 DOM_Element launch = xml::Dom::getSiblingElement(angles);
00125 if(launch !=DOM_Element()) {
00126
00127 DOMString launchTag = launch.getTagName();
00128
00129 if(launchTag.equals("launch_point")){
00130 m_pointtype=SINGLE;
00131 LaunchType templaunch=m_launch;
00132
00133 setLaunch(launchDir(),
00134 Point(atof(launch.getAttribute("x").transcode()),
00135 atof(launch.getAttribute("y").transcode()),
00136 atof(launch.getAttribute("z").transcode()) ) );
00137 m_launch=templaunch;
00138
00139 }else if(launchTag.equals("patch")){
00140
00141 m_pointtype = PATCH;
00142 LaunchType templaunch=m_launch;
00143
00144
00145
00146 setLaunch( (-launchDir()).theta(), (-launchDir()).phi(),
00147 atof(launch.getAttribute("xmax").transcode()),
00148 atof(launch.getAttribute("xmin").transcode()),
00149 atof(launch.getAttribute("ymax").transcode()),
00150 atof(launch.getAttribute("ymin").transcode()),
00151 atof(launch.getAttribute("zmax").transcode()),
00152 atof(launch.getAttribute("zmin").transcode())
00153 );
00154
00155 m_launch=templaunch;
00156
00157
00158 }else {
00159 FATAL_MACRO("Unknown launch specification in Flux::Flux \""
00160 << launchTag.transcode() << "\"" );
00161 }
00162 }
00163
00164
00165 }
00166 if( s==0) {
00167
00168 s = SpectrumFactoryTable::instance()->instantiate(class_name, source_params);
00169
00170 if(s==0){
00171 FATAL_MACRO("Unknown Spectrum: "<< class_name);
00172 std::cerr << "List of known Spectrum classes:\n" ;
00173 std::list<std::string>list= SpectrumFactoryTable::instance()->spectrumList();
00174 for( std::list<std::string>::iterator i = list.begin(); i!=list.end(); ++i)
00175 std::cerr << "\t" << *i << std::endl;
00176
00177 return;
00178 }
00179 }
00180
00181
00182 FluxSource::spectrum(s);
00183
00184 s_backoff = 0.;
00185 setAcceptance();
00186
00187 }
00188
00189
00190 FluxSource::~FluxSource()
00191 {
00192 delete m_spectrum;
00193 if(illumBox) delete illumBox;
00194 }
00195
00196 inline static double sqr(double x) {return x*x; }
00197
00198
00199 void
00200 FluxSource::setAcceptance()
00201 {
00202 s_radius = sqrt(totalArea() / M_PI ) * 100;
00203 if(!s_backoff) s_backoff = s_radius;
00204
00205 switch (m_launch) {
00206
00207 case NONE:
00208 EventSource::solidAngle( (_maxCos - _minCos)*(_maxPhi - _minPhi) );
00209 break;
00210 case DIRECTION:
00211 case POINT:
00212 case GALACTIC:
00213 case SPECTRUM:
00214
00215 EventSource::solidAngle( m_spectrum==0? 1.0 : m_spectrum->solidAngle());
00216 break;
00217 case SURFACE:
00218 EventSource::solidAngle( (_maxCos - _minCos) * (_maxPhi - _minPhi) );
00219 if (_maxCos == _minCos) EventSource::solidAngle(1.);
00220 break;
00221 case PATCHFIXED:
00222 EventSource::solidAngle(1.0);
00223 break;
00224 }
00225 }
00226
00227 void FluxSource::spectrum(Spectrum* s, double emax)
00228 {
00229 if (emax > 0) {
00230 setMaxEnergy(emax);
00231
00232 std::cerr << "exercising obsolete function fraction" << std::endl;
00233 }
00234
00235 m_spectrum = s;
00236
00237 }
00238
00239 FluxSource* FluxSource::event()
00240 {
00241 computeLaunch();
00242 return this;
00243
00244 }
00245
00246 void FluxSource::randomLaunchPoint()
00247 {
00248 HepRotation r_pln;
00249
00250 double ly = m_launchDir.y(), lx = m_launchDir.x();
00251 if( lx !=0 || ly !=0 )r_pln.rotate(acos(m_launchDir.z()),
00252 Vector(-ly, lx, 0.));
00253
00254
00255
00256 double azimuth = RandFlat::shoot( 2*M_PI );
00257 double rad = s_radius*(sqrt(RandFlat::shoot()));
00258
00259
00260
00261
00262
00263
00264 Vector posLaunch(rad*cos(azimuth), rad*sin(azimuth), 0.);
00265
00266
00267 CoordTransform t(r_pln, Vector(0,0,0) );
00268 t.transformVector(posLaunch);
00269
00270
00271 m_launchPoint = (Point&)posLaunch - m_launchDir*s_backoff;
00272 }
00273
00274
00275
00276 double FluxSource::flux() const
00277 {
00278 return enabled() ? std::max(m_spectrum->flux(), EventSource::flux()) : 0;
00279 }
00280
00281 #if 1
00282 double FluxSource::solidAngle() const
00283 {
00284
00285 return EventSource::solidAngle();
00286 }
00287 #endif
00288
00289 void FluxSource::computeLaunch ()
00290 {
00291
00292
00293
00294 const double fudge=1.001;
00295 double kinetic_energy;
00296 do {
00297
00298
00299 kinetic_energy = spectrum()->energySrc( HepRandom::getTheEngine() );
00300 } while (kinetic_energy > m_maxEnergy* fudge);
00301
00302
00303
00304 switch (m_launch) {
00305 case SPECTRUM:
00306 {
00307
00308
00309 std::pair<float,float> direction = spectrum()->dir(kinetic_energy,HepRandom::getTheEngine());
00310 double costh = direction.first;
00311 double sinth = sqrt(1.-costh*costh);
00312 double phi = direction.second;
00313 Vector v(cos(phi)*sinth, sin(phi)*sinth, costh);
00314 m_launchDir = -v;
00315
00316
00317
00318
00319 if (_theta != 0.0) m_launchDir.rotateX(_theta).rotateZ(_phi);
00320
00321
00322
00323
00324 break;
00325 }
00326 case GALACTIC:
00327 {
00328
00329
00330 getGalacticDir(m_gall, m_galb);
00331 break;
00332 }
00333 case SURFACE:
00334 {
00335 getSurfacePosDir();
00336 break;
00337 }
00338 case PATCHFIXED: {
00339
00340
00341 if (_theta == 0.0) {
00342
00343 double xInc = patchXmin + patchWidX * RandFlat::shoot();
00344 double yInc = patchYmin + patchWidY * RandFlat::shoot();
00345 double zInc = patchTop;
00346 m_launchPoint = Point(xInc, yInc, zInc);
00347 } else {
00348 double dist = FLT_MAX;
00349 const double distToSearch = 500.;
00350 do {
00351 randomLaunchPoint();
00352
00353 Ray trialRay(m_launchPoint, m_launchDir);
00354 dist = illumBox->distanceToEnter(trialRay, distToSearch);
00355
00356 if (dist < FLT_MAX) m_launchPoint = trialRay.position(dist);
00357
00358
00359 } while (dist >= FLT_MAX);
00360 }
00361 break;
00362 }
00363 case NONE:
00364 {
00365 double costh = -RandFlat::shoot(_minCos, _maxCos);
00366 double sinth = sqrt(1.-costh*costh);
00367 double phi = RandFlat::shoot(_minPhi, _maxPhi);
00368
00369
00370
00371 m_launchDir = Vector(cos(phi)*sinth, sin(phi)*sinth, costh);
00372
00373
00374 if (_theta != 0.0) m_launchDir.rotateX(_theta).rotateZ(_phi);
00375 }
00376
00377 case DIRECTION:
00378 {
00379
00380 }
00381
00382 case POINT:
00383
00384 break;
00385
00386 }
00387
00388 m_energy = kinetic_energy;
00389
00390
00391
00392 switch (m_pointtype) {
00393 case NOPOINT:
00394 {
00395 randomLaunchPoint();
00396 break;
00397 }
00398
00399 case SINGLE:
00400 {
00401 break;
00402 }
00403 case PATCH:
00404 {
00405
00406
00407 if (_theta == 0.0) {
00408
00409 double xInc = patchXmin + patchWidX * RandFlat::shoot();
00410 double yInc = patchYmin + patchWidY * RandFlat::shoot();
00411 double zInc = patchTop;
00412 m_launchPoint = Point(xInc, yInc, zInc);
00413 } else {
00414 double dist = FLT_MAX;
00415 const double distToSearch = 500.;
00416 do {
00417 randomLaunchPoint();
00418
00419 Ray trialRay(m_launchPoint, m_launchDir);
00420 dist = illumBox->distanceToEnter(trialRay, distToSearch);
00421
00422 if (dist < FLT_MAX) m_launchPoint = trialRay.position(dist);
00423
00424
00425 } while (dist >= FLT_MAX);
00426 }
00427 break;
00428 }
00429 }
00430
00431
00432 }
00433
00434 std::string FluxSource::fullTitle () const
00435 {
00436 return title();
00437 }
00438
00439 std::string FluxSource::displayTitle () const
00440 {
00441 std::strstream s;
00442 s << EventSource::displayTitle() << '(' << m_spectrum->title() ;
00443 s << ')' << '\0';
00444 std::string t(s.str());
00445 s.freeze(false);
00446 return t;
00447 }
00448
00449 int FluxSource::eventNumber()const
00450 {
00451 return 0;
00452 }
00453
00454 void FluxSource::setCosThetaRange(double minc, double maxc)
00455 {
00456
00457 _minCos = min(minc,maxc);
00458 _maxCos = max(minc,maxc);
00459 if(_minCos==_maxCos) {
00460 if(_minCos!=-1) _minCos-=0.001; else _maxCos +=0.001;
00461 }
00462 m_launch = NONE;
00463 setAcceptance();
00464 }
00465
00466 void FluxSource::setPhiRange(double min_phi, double max_phi)
00467 {
00468
00469 _minPhi = min_phi;
00470 _maxPhi = max_phi;
00471 m_launch = NONE;
00472 setAcceptance();
00473 }
00474 void FluxSource::setLaunch(const Vector& dir, const Point& pos)
00475 {
00476
00477 m_launchDir = dir;
00478 m_launchPoint = pos;
00479 m_launch = POINT;
00480 }
00481 void FluxSource::useSpectrumDirection()
00482 {
00483 m_launch = SPECTRUM;
00484 }
00485
00486
00487 void FluxSource::setLaunch(double theta, double phi)
00488 {
00489 std::cout << "setting launch" << std::endl;
00490 _theta = theta;
00491 _phi = phi;
00492 Vector dir(sin(_theta)*cos(_phi),sin(_theta)*sin(_phi),cos(_theta));
00493 setLaunch(-dir);
00494 }
00495
00496 void FluxSource::setLaunch(const Vector& dir)
00497 {
00498
00499 m_launchDir = dir.unit();
00500 m_launch = DIRECTION;
00501 _theta = (-dir).theta();
00502 _phi = (-dir).phi();
00503 setAcceptance();
00504 }
00505
00506 void FluxSource::setLaunch(double theta, double phi, double xMax,
00507 double xMin, double yMax, double yMin,
00508 double zTop, double zBot) {
00509
00510
00511
00512
00513 double epsilon = 1e-5;
00514
00515 if (zTop < zBot) {
00516 WARNING_MACRO("zTop < zBot -- SWAPPING");
00517 std::swap(zTop, zBot);
00518 }
00519
00520 patchTop = zTop;
00521 patchBottom = zBot;
00522 patchHeight = fabs(zTop - zBot);
00523 if(patchHeight < epsilon) patchHeight = 0.0;
00524
00525 if (xMax < xMin) {
00526 WARNING_MACRO("patchXmax < patchXmin in Flux -- SWAPPING");
00527 std::swap(xMax, xMin);
00528 }
00529
00530 if( yMax < yMin) {
00531 WARNING_MACRO("patchYmax < patchYmin in Flux -- SWAPPING");
00532 std::swap(yMax, yMin);
00533 }
00534
00535 patchXmax = xMax;
00536 patchXmin = xMin;
00537 patchYmax = yMax;
00538 patchYmin = yMin;
00539
00540 patchWidX = fabs(patchXmax - patchXmin);
00541 patchWidY = fabs(patchYmax - patchYmin);
00542 if(patchWidX < epsilon) patchWidX = 0.0;
00543 if(patchWidY < epsilon) patchWidY = 0.0;
00544
00545 if( (patchHeight == 0.0) && ( (patchWidX == 0.0) || (patchWidY == 0.0) ) ) {
00546 FATAL_MACRO("zero area illumination\n");
00547 }
00548 if( (patchWidX == 0.0) && (patchWidY == 0) ) {
00549 FATAL_MACRO("zero area illumination!\n");
00550 }
00551
00552
00553 if ((theta == 0.0) && (patchHeight != 0.0)) {
00554 WARNING("on-axis, but zTop != zBot, setting zBot = zTop\n");
00555 patchHeight = 0.0;
00556 patchBottom = patchTop;
00557 }
00558
00559
00560
00561 if (patchHeight <= 0.0) patchHeight = 0.0001;
00562 if (patchWidX <= 0.0) patchWidX = 0.0001;
00563 if (patchWidY <= 0.0) patchWidY = 0.0001;
00564
00565
00566
00567 illumBox = new Box(patchWidX, patchWidY, patchHeight);
00568 Vector center((xMax + xMin)/2., (yMax+yMin)/2., (zBot+zTop)/2.);
00569 illumBox->move(center);
00570
00571
00572 _theta = theta;
00573 _phi = phi;
00574 Vector dir(sin(_theta)*cos(_phi),sin(_theta)*sin(_phi),cos(_theta));
00575
00576 m_launchDir = (-dir).unit();
00577 m_launch = PATCHFIXED;
00578
00579 setAcceptance();
00580 }
00581
00582 void FluxSource::setLaunch(double xMax, double xMin, double yMax, double yMin,
00583 double zTop, double zBot, bool fan)
00584 {
00585
00586
00587
00588
00589
00590
00591
00592
00593 double epsilon = 1e-5;
00594
00595 sidePatch = false;
00596 fanBeam = false;
00597 double thMax = acos(_minCos);
00598 double thMin = acos(_maxCos);
00599
00600 if (zTop < zBot) {
00601 WARNING_MACRO("zTop < zBot -- SWAPPING");
00602 std::swap(zTop, zBot);
00603 }
00604
00605 patchTop = zTop;
00606 patchBottom = zBot;
00607 patchHeight = fabs(zTop - zBot);
00608 if(patchHeight < epsilon) patchHeight = 0.0;
00609
00610 if (xMax < xMin) {
00611 WARNING_MACRO("patchXmax < patchXmin in Flux -- SWAPPING");
00612 std::swap(xMax, xMin);
00613 }
00614
00615 if( yMax < yMin) {
00616 WARNING_MACRO("patchYmax < patchYmin in Flux -- SWAPPING");
00617 std::swap(yMax, yMin);
00618 }
00619
00620 patchXmax = xMax;
00621 patchXmin = xMin;
00622 patchYmax = yMax;
00623 patchYmin = yMin;
00624
00625 patchWidX = fabs(patchXmax - patchXmin);
00626 patchWidY = fabs(patchYmax - patchYmin);
00627 if(patchWidX < epsilon) patchWidX = 0.0;
00628 if(patchWidY < epsilon) patchWidY = 0.0;
00629
00630
00631 double aTop, aBot, aSide0, aSide1, aSide2, aSide3;
00632
00633
00634 if( (patchWidX == 0.0) || (patchWidY == 0.0) ) {
00635
00636 if( (patchHeight == 0.0) || ((patchWidX == 0.0) && (patchWidY == 0.0)) ) {
00637 FATAL_MACRO("zero area illumination\n");
00638 }
00639
00640
00641 sidePatch = true;
00642
00643 fanBeam = fan;
00644
00645 if( patchWidY == 0.0) {
00646
00647 double tempY = patchYmax;
00648 patchWidY = patchWidX;
00649 patchYmax = patchXmax;
00650 patchYmin = patchXmin;
00651 patchWidX = 0.0;
00652 patchXmin = tempY;
00653 patchXmax = tempY;
00654 }
00655
00656
00657 aSide0 = patchHeight * patchWidY;
00658 aSide1 = 0.0;
00659 aSide2 = 0.0;
00660 aSide3 = 0.0;
00661 aTop = 0.0;
00662 aBot = 0.0;
00663
00664 } else {
00665
00666 aTop = patchWidX * patchWidY;
00667 aBot = patchWidX * patchWidY;
00668 aSide0 = patchHeight * patchWidY;
00669 aSide1 = patchHeight * patchWidX;
00670 aSide2 = patchHeight * patchWidY;
00671 aSide3 = patchHeight * patchWidX;
00672 }
00673
00674
00675 if( (sidePatch == true) && (fanBeam == false) ) {
00676
00677
00678 } else if ((sidePatch == true) &&
00679 ((_minPhi < (-M_PI/2.) * (1.+epsilon) ) ||
00680 (_maxPhi > (M_PI/2.) * (1.+epsilon) ) ) )
00681 {
00682
00683 _minPhi = -M_PI/2.;
00684 _maxPhi = M_PI/2.;
00685
00686 } else if (sidePatch == false) {
00687
00688 _minPhi = -M_PI;
00689 _maxPhi = M_PI;
00690 }
00691
00692
00693 double aSideTot = aSide0 + aSide1 + aSide2 + aSide3;
00694
00695 patchRange = (_minCos < 0 ? -1 : 1) * _minCos * _minCos -
00696 (_maxCos < 0 ? -1 : 1) * _maxCos * _maxCos;
00697
00698 patchOffset = (_maxCos < 0 ? -1 : 1) * _maxCos * _maxCos;
00699
00700
00701
00702 float wBot = 0.0, wTop = 0.0;
00703
00704 if (sidePatch == true) {
00705
00706 wBot = 0.0;
00707 wTop = 0.0;
00708
00709 } else {
00710
00711
00712 if ( (thMax <= M_PI / 2.) && (thMin < M_PI / 2.) ) {
00713
00714 wBot = 0.0;
00715 wTop = _maxCos * _maxCos - _minCos * _minCos;
00716
00717 if((thMax == 0) && (thMin == 0) ) wTop = 1.0;
00718
00719 } else if ( (thMax > M_PI / 2.) && (thMin < M_PI / 2.) ) {
00720
00721 wBot = _minCos * _minCos;
00722 wTop = _maxCos * _maxCos;
00723
00724 } else {
00725 wBot = _minCos * _minCos - _maxCos * _maxCos;
00726 wTop = 0.0;
00727 if ( (thMax == M_PI) && (thMin == M_PI) ) wBot = 1.0;
00728 }
00729 }
00730
00731
00732
00733
00734
00735 float wSide;
00736
00737 if(sidePatch == true) {
00738 wSide = 1.0;
00739 } else {
00740 wSide = ( (thMax - thMin) - 0.5 * ( sin(2. * thMax) - sin(2. * thMin) ) )
00741 / M_PI;
00742 }
00743
00744 Fratio = wSide * aSideTot / (wSide * aSideTot + wTop * aTop + wBot * aBot);
00745
00746
00747
00748
00749
00750 m_launch = SURFACE;
00751 setAcceptance();
00752 }
00753
00754 void FluxSource::getSurfacePosDir() {
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777 double xInc, yInc, zInc;
00778 double cosTh, sinTh, phi;
00779 int sideNum;
00780 if (RandFlat::shoot() < Fratio) {
00781 double cosE, sinE;
00782
00783 if ( (sidePatch == true) && (fanBeam == false) ) {
00784
00785
00786
00787 double randNum = RandFlat::shoot() * patchRange + patchOffset;
00788 cosE = ( (randNum < 0) ? -1 : 1) * sqrt( fabs (randNum) );
00789 sinE = sqrt( 1 - cosE * cosE);
00790
00791
00792 double Xi = RandFlat::shoot(0., 2*M_PI);
00793
00794 cosTh = sinE * sin(Xi);
00795 sinTh = sqrt(1 - cosTh * cosTh);
00796
00797 double anySidePhi = (Xi < 0 ? -1 : 1) * acos(cosE / sinTh);
00798 phi = anySidePhi;
00799
00800
00801 sideNum = 0;
00802
00803 } else {
00804
00805
00806 bool PhiDONE;
00807 do {
00808 PhiDONE = false;
00809 cosE = sqrt(RandFlat::shoot());
00810
00811
00812
00813 sinE = sqrt( 1 - cosE * cosE);
00814
00815 double Xi = RandFlat::shoot(-M_PI, M_PI);
00816 cosTh = sinE * sin(Xi);
00817 sinTh = sqrt(1 - cosTh * cosTh);
00818
00819 double rand = RandFlat::shoot(-1, 1);
00820
00821 double anySidePhi = (rand < 0 ? -1 : 1) * acos(cosE / sinTh);
00822
00823 sideNum = int(4 * RandFlat::shoot());
00824 if(sidePatch == true) sideNum = 0;
00825 phi = anySidePhi + (M_PI / 2.) * sideNum;
00826
00827 if(fanBeam == true) {
00828 if ( (phi >= _minPhi) && (phi <= _maxPhi) ) PhiDONE = true;
00829 } else {
00830 PhiDONE = true;
00831 }
00832
00833 } while( (cosTh > _maxCos) || (cosTh < _minCos) || (!PhiDONE) );
00834
00835 }
00836
00837 zInc = patchBottom + patchHeight * RandFlat::shoot();
00838
00839 if ( (sideNum % 2) == 0) {
00840 if(sideNum == 0) {
00841 xInc = patchXmax;
00842 } else {
00843 xInc = patchXmin;
00844 }
00845 yInc = patchYmin + patchWidY * RandFlat::shoot();
00846 } else {
00847 xInc = patchXmin + patchWidX * RandFlat::shoot();
00848 if (sideNum == 1) {
00849 yInc = patchYmax;
00850 } else {
00851 yInc = patchYmin;
00852 }
00853 }
00854 } else {
00855
00856
00857
00858 phi = RandFlat::shoot(_minPhi, _maxPhi);
00859 double ranN = RandFlat::shoot() * patchRange + patchOffset;
00860 cosTh = (ranN > 0 ? 1 : -1) * sqrt( fabs ( ranN ) );
00861 sinTh = sqrt( 1 - cosTh * cosTh );
00862
00863 if (cosTh > 0.) {
00864 zInc = patchTop;
00865 }
00866 else {
00867 zInc = patchBottom;
00868 }
00869 xInc = patchXmin + patchWidX * RandFlat::shoot();
00870 yInc = patchYmin + patchWidY * RandFlat::shoot();
00871 }
00872
00873 Point IncPoint(xInc, yInc, zInc);
00874 m_launchPoint = IncPoint;
00875 m_launchDir = Vector( -(cos(phi) * sinTh), -(sin(phi) * sinTh), -(cosTh));
00876 }
00877
00878 void FluxSource::getGalacticDir(double l,double b){
00879
00880
00881 std::pair<double,double> v;
00882 v=GPS::instance()->galToGlast(std::make_pair<double,double>(l,b));
00883
00884
00885 double theta=v.first;
00886 double phi=v.second;
00887
00888 setLaunch(theta,phi);
00889 }
00890
00891
00892 std::string FluxSource::title () const
00893 {
00894 std::strstream t;
00895 t << m_spectrum->title() << ", ";
00896 switch (m_launch) {
00897 case NONE:
00898 t << "range(" << _minCos << ',' << _maxCos << "), ";
00899 if( theta() == 0) break;
00900 case DIRECTION:
00901 t << "angle(" << theta()*180/M_PI << ','
00902 << phi()*180/M_PI << "), ";
00903 break;
00904 case POINT:
00905 t << "launch(" << m_launchDir << m_launchPoint << "), ";
00906 break;
00907 case SURFACE:
00908 t << "box(" << patchXmin << ',' << patchXmax << ',' << patchYmin << ','
00909 << patchYmax << ',' << patchTop << ',' << patchBottom << ") theta("
00910 << _minCos << ',' << _maxCos << "), phi(" << _minPhi << ','
00911 << _maxPhi << "), ";
00912 break;
00913 case SPECTRUM:
00914 break;
00915 case GALACTIC:
00916 break;
00917 case PATCHFIXED:
00918 t << "box(" << patchXmin << ',' << patchXmax << ',' << patchYmin
00919 << ',' << patchYmax << ',' << patchTop << ',' << patchBottom
00920 << ") theta(" << _theta << "), phi(" << _phi << "), ";
00921 }
00922 t << "flux("<< flux() << ")" << '\0';
00923 std::string s(t.str());
00924 #ifdef WIN32
00925 t.freeze(false);
00926 #endif
00927 return s;
00928 }
00929
00930
00931 void FluxSource::refLaunch(LaunchType launch) {m_launch=launch;}
00932 void FluxSource::refPoint(PointType point) {m_pointtype=point;}
00933
00934