cgma
volumes.cpp File Reference
#include <iostream>
#include <map>
#include <cfloat>
#include <cassert>
#include "MCNPInput.hpp"
#include "volumes.hpp"
#include "geometry.hpp"
#include "options.hpp"

Go to the source code of this file.

Classes

class  PlaneSurface
class  CylinderSurface
class  ConeSurface
class  TorusSurface
class  SphereSurface
class  EllipsoidSurface
class  BoxVolume
class  RppVolume
class  RecVolume
class  RccVolume
class  HexVolume
class  VolumeCache

Enumerations

enum  axis_t { X = 0, Y = 1, Z = 2 }

Functions

iBase_EntityHandle makeWorldSphere (iGeom_Instance &igm, double world_size)
static iBase_EntityHandle embedWithinWorld (bool positive, iGeom_Instance &igm, double world_size, iBase_EntityHandle body, bool bound_with_world)
iBase_EntityHandle applyTransform (const Transform &t, iGeom_Instance &igm, iBase_EntityHandle &e)
iBase_EntityHandle applyReverseTransform (const Transform &tx, iGeom_Instance &igm, iBase_EntityHandle &e)
static Transform axesImage (const Vector3d &v1, const Vector3d &v2, const Vector3d &v3, const Vector3d &translation=Vector3d())
static Transform imageZAxisTo (const Vector3d &v, const Vector3d &translation=Vector3d())
bool sqIsEllipsoid (const std::vector< double > &args)
SurfaceVolumemakeSurface (const SurfaceCard *card, VolumeCache *v)

Variables

static Vector3d origin (0, 0, 0)
static VolumeCache default_volume_cache

Enumeration Type Documentation

enum axis_t
Enumerator:
X 
Y 
Z 

Definition at line 164 of file volumes.cpp.

{ X=0, Y=1, Z=2 } axis_t;

Function Documentation

Definition at line 93 of file volumes.cpp.

                                                                                                            {
  
  int igm_result;
  Transform rev_t = tx.reverse();

  const Vector3d& translation = rev_t.getTranslation();
  iGeom_moveEnt( igm, e, translation.v[0], translation.v[1], translation.v[2], &igm_result);
  CHECK_IGEOM( igm_result, "applying reverse translation" );

  if( rev_t.hasInversion() ){
    iGeom_rotateEnt( igm, e, 180, 0, 0, 0, &igm_result );
    CHECK_IGEOM( igm_result, "inverting for reverse transformation" );
  }

  if( rev_t.hasRot() ){
    const Vector3d& axis = rev_t.getAxis();
    iGeom_rotateEnt( igm, e, rev_t.getTheta(), axis.v[0], axis.v[1], axis.v[2], &igm_result );
    CHECK_IGEOM( igm_result, "applying rotation" );
  }
  
  
  return e;
}

Definition at line 59 of file volumes.cpp.

                                                                                                    {
  
  int igm_result;
  if( t.hasRot()  ){
    const Vector3d& axis = t.getAxis();
    iGeom_rotateEnt( igm, e, t.getTheta(), axis.v[0], axis.v[1], axis.v[2], &igm_result );
    CHECK_IGEOM( igm_result, "applying rotation" );
  }
  
  if( t.hasInversion() ){
      //TODO: ask about the right way to do this.  Rotate seems to work, but I don't really know why...
      //iGeom_rotateEnt( igm, e, 180, 0, 0, 0, &igm_result );

    //if( !t.hasRot() ){
      iGeom_reflectEnt( igm, e, 0, 0, 0, 0, 0, 1, &igm_result );
      iGeom_reflectEnt( igm, e, 0, 0, 0, 0, 1, 0, &igm_result );
      iGeom_reflectEnt( igm, e, 0, 0, 0, 1, 0, 0, &igm_result );
      //}
      //else{
      //   const Vector3d& axis = t.getAxis();
      //   iGeom_reflectEnt( igm, e, axis.v[0], axis.v[1], axis.v[2], &igm_result );
      //   }

      CHECK_IGEOM( igm_result, "inverting for transformation" );
    }


  const Vector3d& translation = t.getTranslation();
  iGeom_moveEnt( igm, e, translation.v[0], translation.v[1], translation.v[2], &igm_result);
  CHECK_IGEOM( igm_result, "applying translation" );
  
  return e;
}
static Transform axesImage ( const Vector3d v1,
const Vector3d v2,
const Vector3d v3,
const Vector3d translation = Vector3d() 
) [static]

Definition at line 463 of file volumes.cpp.

{
  Vector3d x(1, 0, 0), y(0, 1, 0), z(0, 0, 1);
  Vector3d a1 = v1.normalize(), a2 = v2.normalize(), a3 = v3.normalize();
    
  if( OPT_DEBUG ) std::cout << "Axes image: " << a1 << " : " << a2 << " : " << a3 << std::endl;

  double rot_matrix[9] = 
    { a1.dot(x), a2.dot(x), a3.dot(x),
      a1.dot(y), a2.dot(y), a3.dot(y),
      a1.dot(z), a2.dot(z), a3.dot(z) };
  

  return Transform( rot_matrix, translation );
}
static iBase_EntityHandle embedWithinWorld ( bool  positive,
iGeom_Instance igm,
double  world_size,
iBase_EntityHandle  body,
bool  bound_with_world 
) [static]

A convenience function for SurfaceVolumes to call at the end of getHandle functions. Return the negative or positive sense of the given body, as appropriate. If bound_within_world is true, a negative-sense body will be intersected with the world sphere (a step necessary for cylinders and other infinite bodies)

Definition at line 33 of file volumes.cpp.

{
  iBase_EntityHandle final_body;
  int igm_result;

  if( !positive && !bound_with_world ){
    final_body = body;
  }
  else{
    iBase_EntityHandle world_sphere = makeWorldSphere( igm, world_size );    
    
    if( positive ){
      iGeom_subtractEnts( igm, world_sphere, body, &final_body, &igm_result);
      CHECK_IGEOM( igm_result, "making positive body" );
    }
    else{ // !positive && bound_with_world
      iGeom_intersectEnts( igm, world_sphere, body, &final_body, &igm_result);
      CHECK_IGEOM( igm_result, "making negative body" );
    }
  }
  return final_body;
}
static Transform imageZAxisTo ( const Vector3d v,
const Vector3d translation = Vector3d() 
) [static]

Definition at line 479 of file volumes.cpp.

                                                                                            {
  // approach: find two vectors perpendicular to v, then use axesImage.
  Vector3d a = v.normalize();

  Vector3d x(1, 0, 0);
  Vector3d b = x.cross( v.normalize() );
  
  if( b.length() < DBL_EPSILON ){
    // v is indistinguishable from the x axis
    b = Vector3d(0, -1, 0);
    if( OPT_DEBUG ) std::cout << "imageZAxisTo: Changing v " << std::endl;
  }

  Vector3d c = b.cross( v.normalize() );
  return axesImage( c, b, a, translation );
  

}
SurfaceVolume& makeSurface ( const SurfaceCard card,
VolumeCache v = NULL 
)

Function to create an SurfaceVolume object from a SurfaceCard. Created volumes are kept in a cache. If the v parameter is null, a default cache (static within volumes.cpp) will be used. If multiple MCNPInput instances are used in the course of a single program, then there will need to be a way to get multiple VolumeCache objects; that's not an issue right now, so I haven't coded it.

Definition at line 802 of file volumes.cpp.

                                                                    {
  
  VolumeCache& cache = default_volume_cache;
  if( v != NULL ){
    cache = *v;
  }

  
  if( cache.contains( card ) ){
    return *cache.get( card );
  }
  else{ 
    // SurfaceCard variables:  mnemonic, args, coord_xform  
    SurfaceVolume* surface;
    const std::string& mnemonic = card->getMnemonic();
    const std::vector< double >& args = card->getArgs(); 
    
    if( mnemonic == "so"){
      surface = new SphereSurface( origin, args.at(0) );
    }
    else if( mnemonic == "sx"){
      surface = new SphereSurface( Vector3d( args.at(0), 0, 0 ), args.at(1) );
    }
    else if( mnemonic == "sy"){
      surface = new SphereSurface( Vector3d( 0, args.at(0), 0 ), args.at(1) );
    }
    else if( mnemonic == "sz"){
      surface = new SphereSurface( Vector3d( 0, 0, args.at(0) ), args.at(1) );
    }
    else if( mnemonic == "s" || mnemonic == "sph" ){
      surface = new SphereSurface( Vector3d( args ), args.at(3) );
    }
    else if( mnemonic == "sq" && sqIsEllipsoid(args) ){
      surface = new EllipsoidSurface( Vector3d( args.at(7), args.at(8), args.at(9) ), Vector3d( args )* (-1/args.at(6)) );
    }
    else if( mnemonic == "p"){
      if( args.size() == 4 ){
        // plane given as ABCD coefficients (Ax+By+Cz-D=0)
        Vector3d v(args);
        surface = new PlaneSurface( v, args.at(3)/v.length() );
      }
      else if( args.size() == 9 ){
        // plane is given at three points in space
        Vector3d v1(args), v2(args,3), v3(args,6);

        // ordering of the points is arbitrary, but make sure v1 is furthest from origin.
        if( v1.length() < v2.length() ){
          std::swap( v1, v2 );
        }
        if( v1.length() < v3.length() ){
          std::swap( v1, v3 );
        }

        // the normal (up to reversal) of the plane 
        // The normal may need to be reversed to ensure that the origin
        // has negative sense, as required by MCNP
        Vector3d normal = v1.add(-v2).cross( v1.add(-v3) ).normalize();

        // If a ray started from the origin and followed the normal vector,
        // p is the point where it intersects the plane
        Vector3d p = normal.scale( v1.dot(normal) );

        // cos of the angle between v1 and normal 
        double angle = normal.dot( v1.normalize() );
        
        // invert the normal if the angle is > 90 degrees, which indicates
        // that reversal is required.
        if( angle < 0 ){
          normal   = -normal;
        }

        //std::cout << normal << " " << p.length() << " : " << angle << std::endl;
        surface = new PlaneSurface( normal, p.length() );


      }
      else{ 
        throw std::runtime_error( "P surface with unsupported number of params" );
      }

    }
    else if( mnemonic == "px"){
      surface = new PlaneSurface( Vector3d( 1, 0, 0), args.at(0) );
    }
    else if( mnemonic == "py"){
      surface = new PlaneSurface( Vector3d( 0, 1, 0), args.at(0) );
    }
    else if( mnemonic == "pz"){
      surface = new PlaneSurface( Vector3d( 0, 0, 1), args.at(0) );
    }
    else if( mnemonic == "cx" ){
      surface = new CylinderSurface( X, args.at(0) );
    }
    else if( mnemonic == "cy" ){
      surface = new CylinderSurface( Y, args.at(0) );
    }
    else if( mnemonic == "cz" ){
      surface = new CylinderSurface( Z, args.at(0) );
    }
    else if( mnemonic == "c/x"){
      surface = new CylinderSurface( X, args.at(2), args.at(0), args.at(1) );
    }
    else if( mnemonic == "c/y"){
      surface = new CylinderSurface( Y, args.at(2), args.at(0), args.at(1) );
    }
    else if( mnemonic == "c/z"){
      surface = new CylinderSurface( Z, args.at(2), args.at(0), args.at(1) );
    }
#ifdef HAVE_IGEOM_CONE
    else if( mnemonic == "kx"){
      double arg3 = ( args.size() == 3 ? args.at(2) : 0.0 );
      surface = new ConeSurface( X, args.at(1), args.at(0), arg3 );
    } 
    else if( mnemonic == "ky"){
      double arg3 = ( args.size() == 3 ? args.at(2) : 0.0 );
      surface = new ConeSurface( Y, args.at(1), args.at(0), arg3 );
    }
    else if( mnemonic == "kz"){
      double arg3 = ( args.size() == 3 ? args.at(2) : 0.0 );
      surface = new ConeSurface( Z, args.at(1), args.at(0), arg3 );
    }
    else if( mnemonic == "k/x" ){
      double arg5 = ( args.size() == 5 ? args.at(4) : 0.0 );
      surface = new ConeSurface( X, args.at(3), Vector3d(args),  arg5 );
    }
    else if( mnemonic == "k/y" ){
      double arg5 = ( args.size() == 5 ? args.at(4) : 0.0 );
      surface = new ConeSurface( Y, args.at(3), Vector3d(args),  arg5 );
    }
    else if( mnemonic == "k/z" ){
      double arg5 = ( args.size() == 5 ? args.at(4) : 0.0 );
      surface = new ConeSurface( Z, args.at(3), Vector3d(args),  arg5 );
    }
    else if( mnemonic == "trc" ){
      surface = new TrcVolume( Vector3d(args), Vector3d(args,3), args.at(6), args.at(7) );
    }
#endif /*HAVE_IGEOM_CONE */
    else if( mnemonic == "tx" ){
      surface = new TorusSurface( X, Vector3d(args), args.at(3), args.at(4), args.at(5) );
    } 
    else if( mnemonic == "ty" ){
      surface = new TorusSurface( Y, Vector3d(args), args.at(3), args.at(4), args.at(5) );
    } 
    else if( mnemonic == "tz" ){
      surface = new TorusSurface( Z, Vector3d(args), args.at(3), args.at(4), args.at(5) );
    }
    else if( mnemonic == "box" ){
      surface = new BoxVolume( Vector3d(args), Vector3d(args,3), Vector3d(args,6), Vector3d(args,9) );
    }
    else if( mnemonic == "rpp" ){
      surface = new RppVolume( Vector3d(args.at(0), args.at(2), args.at(4)), Vector3d(args.at(1), args.at(3), args.at(5)) );
    }
    else if( mnemonic == "rcc" ){
      surface = new RccVolume( Vector3d(args), Vector3d(args,3), args.at(6) );
    }
    else if( mnemonic == "rec" ){
      if( args.size() == 10 ){
        surface = new RecVolume( Vector3d( args ), Vector3d(args,3), Vector3d(args,6),  args.at(9) );
      }
      else{
        surface = new RecVolume( Vector3d( args ), Vector3d(args,3), Vector3d(args,6), Vector3d(args,9) );
      }
    }
    else if( mnemonic == "hex" || mnemonic == "rhp" ){
      if( args.size() == 9 ){
        surface = new HexVolume( Vector3d( args ), Vector3d(args,3), Vector3d(args,6) );
      }
      else{
        surface = new HexVolume( Vector3d( args ), Vector3d(args,3), Vector3d(args,6), Vector3d(args,9), Vector3d(args,12) );
      }
    }
    else if( mnemonic == "x" ) {
      switch (args.size()) {
      case 2: // plane
        surface = new PlaneSurface( Vector3d( 1, 0, 0), args.at(0) );
        break;
      case 4: // either plane, cylinder or cone
        if ( args.at(0) == args.at(2) ) // plane
          surface = new PlaneSurface( Vector3d( 1, 0, 0), args.at(0) );
        else if (args.at(1) == args.at(3)) // cylinder
          surface = new CylinderSurface( X, args.at(1) );
        else // cone
          {
            double m = (args.at(3) - args.at(1))/(args.at(2)-args.at(0));
            double apex_p = args.at(0) - args.at(1)/m;
            surface = new ConeSurface( X, m*m, apex_p, (m > 0 ? 1 : -1 ) );
          }
        break;
      default:
        throw std::runtime_error( mnemonic + " is only a supported surface with 2 or 4 arguments" );
        break;
      }
    }
    else if( mnemonic == "y" ) {
      switch (args.size()) {
      case 2: // plane
        surface = new PlaneSurface( Vector3d( 0, 1, 0), args.at(0) );
        break;
      case 4: // either plane, cylinder or cone
        if ( args.at(0) == args.at(2) ) // plane
          surface = new PlaneSurface( Vector3d( 0, 1, 0), args.at(0) );
        else if (args.at(1) == args.at(3)) // cylinder
          surface = new CylinderSurface( Y, args.at(1) );
        else // cone
          {
            double m = (args.at(3) - args.at(1))/(args.at(2)-args.at(0));
            double apex_p = args.at(0) - args.at(1)/m;
            surface = new ConeSurface( Y, m*m, apex_p, (m > 0 ? 1 : -1 ) );
          }
        break;
      default:
        throw std::runtime_error( mnemonic + " is only a supported surface with 2 or 4 arguments" );
        break;
      }
    }
    else if( mnemonic == "z" ) {
      switch (args.size()) {
      case 2: // plane
        surface = new PlaneSurface( Vector3d( 0, 0, 1), args.at(0) );
        break;
      case 4: // either plane, cylinder or cone
        if ( args.at(0) == args.at(2) ) // plane
          surface = new PlaneSurface( Vector3d( 0, 0, 1), args.at(0) );
        else if (args.at(1) == args.at(3)) // cylinder
          surface = new CylinderSurface( Z, args.at(1) );
        else // cone
          {
            double m = (args.at(3) - args.at(1))/(args.at(2)-args.at(0));
            double apex_p = args.at(0) - args.at(1)/m;
            surface = new ConeSurface( Z, m*m, apex_p, (m > 0 ? 1 : -1 ) );
          }
        break;
      default:
        throw std::runtime_error( mnemonic + " is only a supported surface with 2 or 4 arguments" );
        break;
      }
    }
    else{
      throw std::runtime_error( mnemonic + " is not a supported surface" );
    }
    
    if( card->getTransform().hasData() ){
      const Transform& transform = card->getTransform().getData();
      surface->setTransform( &transform );
    }
    
    cache.insert( card, surface );
    return *surface;
    
  }
  
  
}
iBase_EntityHandle makeWorldSphere ( iGeom_Instance igm,
double  world_size 
)

Definition at line 16 of file volumes.cpp.

                                                                            {
  iBase_EntityHandle world_sphere;
  int igm_result;
  // Note: I tried using createBrick instead of createSphere to bound the universe with a box
  // instead of a sphere.  This worked but led to a substantial increase in run times and
  // memory usage, so should be avoided.
  iGeom_createSphere( igm, world_size, &world_sphere, &igm_result);
  CHECK_IGEOM( igm_result, "making world sphere" );
  return world_sphere;
}
bool sqIsEllipsoid ( const std::vector< double > &  args)

Definition at line 785 of file volumes.cpp.

                                                    {

  bool isEllipsoid = true;
  
  if ( args.at(3)*args.at(3) + args.at(4)*args.at(4) + args.at(5)*args.at(5) != 0)
    isEllipsoid = false;

  if ( args.at(0)*args.at(1)*args.at(2)*args.at(6) >= 0 )
    isEllipsoid = false;

  return isEllipsoid;
  
}

Variable Documentation

Definition at line 800 of file volumes.cpp.

Vector3d origin(0, 0, 0) [static]
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines