Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Medium.cxx

Go to the documentation of this file.
00001 // $Id: Medium.cxx,v 1.4 2001/09/04 19:26:01 atwood Exp $
00002 //
00003 //
00004 // This file is part of Gismo 2
00005 //
00006 //
00007 
00008 #ifdef __GNUG__
00009 #pragma implementation
00010 #endif
00011 
00012 #include "gismo/Medium.h"
00013 
00014 #include "gismo/Detector.h"
00015 #include "gismo/Material.h"
00016 
00017 #include "gismo/Field.h"
00018 #include "gismo/MCParticle.h"
00019 #include "facilities/error.h"
00020 
00021 #include "geometry/Box.h"
00022 #include "geometry/Ray.h"
00023 
00024 #include "geomrep/BoxRep.h"
00025 #include "geomrep/TubeRep.h"
00026 
00027 #include <typeinfo>
00028 #include <cassert>
00029 
00031 //              constructors
00032 
00033 Medium::Medium(Medium * prnt, float size)
00034    : _volume(new Box(size,size,size))
00035    , _material(0)
00036    , _detector(0)
00037    , _field(0)
00038    , _parent(prnt)
00039    , _title(0)
00040 {
00041      set_defaults();
00042 }
00043 Medium::Medium(Medium* parent, Shape* vol, const char* matName, Detector* det)
00044    :  _volume(vol)
00045    ,  _material(Material::hatch(matName))
00046    ,  _detector(det)
00047    ,  _field(0)
00048    ,  _parent(parent)
00049    ,  _title(0)
00050 {
00051         set_defaults();
00052 }
00053 
00054 Medium::Medium(const Medium & old)
00055 : _volume(&old._volume->copy())
00056 , _material(old._material)
00057 , _detector(new Detector(*old._detector))
00058 , _field(old._field)
00059 , _parent(old._parent)
00060 , _title(0)
00061 {
00062     set_defaults();
00063 }
00064 void Medium::set_defaults()
00065 {
00066 
00067    if(_parent) {
00068      // parent was specified: set appropiate attributes to be identical, then add
00069       _keCutOff = _parent->kECutOff();
00070       _maxStep = _parent->maxStep();
00071       if(!_material) _material = &_parent->material();
00072       if(!_field) _field = &(_parent->field());
00073       _parent->addMedium(this);
00074    }
00075    else {
00076         // standard defaults for tracking attributes
00077       _keCutOff   = 0.1f;
00078       _maxStep   = 100.;
00079       if(!_material) _material = Material::hatch("vacuum");
00080    }
00081    s_count ++;
00082 }
00083 
00084 
00085 Medium& Medium::setTitle(const char* newTitle)
00086 {
00087    if( _title) delete [] _title;
00088    strcpy(_title = new char[strlen(newTitle)+1], newTitle);
00089    return *this;
00090 }
00091 Medium::~Medium()
00092 {
00093    if(_title) delete [] _title;
00094    if(_volume) delete _volume;
00095    if(_detector) delete _detector;
00096     s_count--;
00097 }
00098 
00100 //               set tracking attributes: for this and all inner media
00101 
00102 Medium& Medium::setKECutOff(float keCut) {
00103   _keCutOff = keCut;
00104   return *this;
00105 }
00106 
00107 Medium& Medium::setMaxStep(float mxStep) {
00108   _maxStep = mxStep;
00109   return *this;
00110 }
00111 
00112 Medium& Medium::setField(Field* fld)
00113 {
00114   if(_parent)
00115      if(&_parent->field() != _field) delete _field;
00116   _field = fld;
00117   return *this;
00118 }
00119 
00120 const char* Medium::nameOf() const {
00121   return "Medium";
00122 }
00123 
00124 int Medium::isComposite() const {
00125   return 0;
00126 }
00127 
00129 //                manage inner media
00130 
00131 Medium& Medium::addMedium ( Medium* nextMedium)
00132 {
00133     FATAL("Non-composite Medium tried to add medium");
00134     return *nextMedium;
00135 }
00136 
00137 Medium& Medium::removeMedium (Medium* oldMedium)
00138 {
00139     FATAL("Non-composite Medium tried to remove medium");
00140     return *oldMedium;
00141 }
00142 
00144 //                       coordinate transformation
00145 GeomObject&
00146 Medium::transform(const CoordTransform& T)
00147 {
00148 
00149     if( _volume )
00150         _volume->transform(T); // could happen during initialzation
00151    if( _detector )
00152      _detector->transform(T);  // note that detector may ignore this!
00153    return *this;
00154 }
00155 
00157 //              Detector  processing methods
00158 void Medium::clear(){
00159                                 if(_detector) _detector->clear();}
00160 void Medium::generateResponse(){
00161                                 if(_detector) _detector->generateResponse();}
00162 void Medium::accept(DetectorVisitor& a){
00163                                 if(_detector) _detector->accept(a);}
00164 void Medium::writeData(std::ostream & os){
00165                                 if(_detector) _detector->writeData(os);}
00166 void Medium::readData(std::istream & is){
00167                                 if(_detector) _detector->readData(is); }
00168 void Medium::printResponse(std::ostream& os)const{
00169                                 if(_detector) _detector->printOn(os);}
00170 void Medium::createResponseView(gui::DisplayRep& v) {
00171                                 if( _detector) _detector->draw(v);}
00172 
00173 void Medium::notify() {
00174                                 if( _detector) _detector->notify();}
00175 
00177 //                    Methods used in Tracking
00178 
00179 const Medium * Medium::inside(const Point& r)const
00180 {
00181      const Medium* which = this;
00182      while (which &&  which->_volume && ! which->volume().inside(r))
00183         which = which->parent();
00184      return which;
00185 
00186 }
00187 
00188 Ray * Medium::CreateRay(const Point& r, const Vector& p, float q,float maxStep )const
00189 {
00190  /*
00191   * create a ray to extrapolate from point r, for a particle with
00192   * momentum p and charge q
00193   *
00194   * Last arg is maximum step anticipated, to allow eventual Runge-Kutta field
00195   * if zero, the particle is at rest,and the ray is only to record the
00196   * position
00197   */
00198    if( maxStep ==0 ) return new Ray(r,Vector(0,0,1));
00199    if( _field )
00200       return _field->CreateRay(r,p,q);
00201    else
00202         return new Ray(r, p);
00203 }
00204 
00205 
00206 double Medium::distanceToLeave( const Ray& r,
00207                                const Medium* & newStuff,
00208                                          double maxS ) const
00209 {
00210     assert(maxS>=0);
00211 
00212     //  Get the distance to leave our  Shape.
00213     //  If there is no intersection (looper?) the distance will be a large number
00214 
00215     if( !_volume ) {
00216         // no associated volume--means that this is the world?
00217         newStuff = this;
00218         return maxS;
00219     }
00220 
00221     double distance = volume().distanceToLeave( r,   maxS );
00222     newStuff = distance>=maxS? this : parent();
00223 
00224     if( distance == FLT_MAX) {
00225         // No solution: either trapped inside this Medium (looper) or not in Medium
00226         // so, check for geometry error
00227         const Medium *testStuff = inside(r.position());
00228         if( this != testStuff)  {
00229             std::ostrstream cerr;
00230             cerr << "Medium::distanceToLeave: geometry error at " << r.position()
00231               << "\n\ttrying to leave \"" << title() << "\""; ;
00232             if( testStuff )
00233                 cerr << "\tbut actually inside \"" <<  testStuff->title()  << "\"\n";
00234             else
00235                 cerr << " but beyond known world?\n";
00236             cerr << '\0'; WARNING(cerr.str());
00237             return distance;  // force lost here
00238         }
00239     }
00240 
00241     // Check solution against max allowed step size for this Medium
00242     if(distance > maxStep())
00243     {  distance = maxStep();
00244        newStuff = this;   // if cut back, must be still here
00245     }
00246     return distance;
00247 }
00248 
00249 double Medium::distanceToEnter( const Ray& r,
00250                                const Medium* & newStuff,
00251                                double maxDist ) const
00252 {
00253     // called by a parent CompoundMedium
00254     //  If there is no intersection the distance will return FLT_MAX
00255     //  If the Ray origin is already inside the Medium, then returns zero
00256 
00257     newStuff = this;
00258     double distance = volume().distanceToEnter( r,  maxDist );
00259 
00260     if(distance == FLT_MAX) {
00261         if( this != lastMedium &&  volume().inside(r.position(Volume::Surface_EPSILON)))
00262             distance = 0.;
00263         else
00264             newStuff = parent();
00265                 
00266     }
00267     return distance;
00268 }
00269 
00271 //                 Print and display
00272 //
00273 void Medium::printOn( std::ostream& os ) const
00274 {
00275     os << "  Medium subClass:" << nameOf() <<" - title: "<< title() <<"\n"
00276        << "             maxStep = " << maxStep()
00277        << " keCutOff = "<< kECutOff() << " \n";
00278     volume().printOn(os);
00279     if(_field)
00280             _field->printOn(os);
00281     os << " Material Name: "
00282        << _material->name() << '\n';
00283 
00284 }
00285 
00286 void Medium::createDetectorView(gui::DisplayRep& v) {
00287     const type_info& t = typeid(volume());
00288 
00289     if( t==typeid(Box) )    v.append(BoxRep(volume() ));
00290     else if (t==typeid(Tube) )v.append(TubeRep(volume() ));
00291     else {
00292 #if 0 // disable if want other volumes (like LayeredMedium::Slice) to be ignored
00293         WARNING_MACRO("no display representation was set for volume " << t.name() );
00294 #endif
00295     }
00296 }
00297 
00298 //-----------------------------------------------------------------
00299 //                  gobal statics
00300 const Medium * Medium::lastMedium = 0;
00301 unsigned Medium::s_count=0;
00302 
00303 

Generated at Wed Nov 21 12:20:26 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000