ORANGE

The ORANGE (Oak Ridge Advanced Nested Geometry Engine) package is currently under development as the version in SCALE is ported to GPU.

Geometry creation

ORANGE geometry can be constructed from multiple geometry representations, including Geant4 HEP geometry.

CSG unit

The CSG unit is a general scene comprising arbitrary volumes made of arbitrary quadric faces. The name “unit” is derived from the KENO criticality safety code, where a unit is a reusable composable building block for arrays.

Each unit is constructed from the user defining ObjectInterface implementations and relationships, and specifying which of them are volumes. The Object interface is implemented by:

Shape

A finite (and usually convex) region of space defined by the intersection of multiple quadric surfaces. The Shape is implemented using a single IntersectRegion, which is an implementation that builds the underlying surfaces and bounding boxes. Shapes should be as simple as possible, aligned along and centered on the Z axis.

Solid

A shape that’s hollowed out and/or has a slice removed. It is equivalent to a CSG operation on two shapes of the same type and an azimuthal wedge.

PolySolid

A union of transformed solids along the Z axis, which can also be hollowed and sliced azimuthally.

Transformed

Applies a transform to another CSG object.

AnyObjects, AllObjects, and NegatedObject

Apply the CSG operations of union, intersection, and negation. The first two are implemented as templates of a JoinObjects class.

Objects are typically constructed and used as shared pointers so that they can be reused in multiple locations.

template<class T>
class Shape : public celeritas::orangeinp::ShapeBase

Shape that holds an intersect region and forwards construction args to it.

Construct as:

BoxShape s{"mybox", Real3{1, 2, 3}};
or
Shape s{"mybox", Box{{1, 2, 3}}};

See IntersectRegion.hh for a list of the regions and their construction arguments.

template<class T>
class Solid : public celeritas::orangeinp::SolidBase

A shape that is hollow, is truncated azimuthally, or both.

Examples:

// A cone with a thickness of 0.1
Solid s{"cone", Cone{{1, 2}, 10.0}, Cone{{0.9, 1.9}, 10.0}};
// A cylinder segment in z={-2.5, 2.5}, r={0.5, 0.75}, theta={-45, 45} deg
Solid s{"cyl", Cylinder{0.75, 5.0}, Cylinder{0.5, 5.0},
        {Turn{0}, Turn{0.25}};
// The east-facing quarter of a cone shape
Solid s{"cone", Cone{{1, 2}, 10.0}, {Turn{-0.125}, Turn{0.25}};

class PolyCone : public celeritas::orangeinp::PolySolidBase

A series of stacked cones or cylinders or combination of both.

class Transformed : public celeritas::orangeinp::ObjectInterface

Build a translated or transformed object.

class NegatedObject : public celeritas::orangeinp::ObjectInterface

Everywhere but the embedded object.

template<OperatorToken Op>
class JoinObjects : public celeritas::orangeinp::ObjectInterface

Join all of the given objects with an intersection or union.

std::shared_ptr<AllObjects const> celeritas::orangeinp::make_subtraction(std::string &&label, SPConstObject const &minuend, SPConstObject const &subtrahend)

Make a new object that is the second object subtracted from the first.

This just takes the intersection the first object and the negated second:

A - B <=> A & ~B

std::shared_ptr<AllObjects const> celeritas::orangeinp::make_rdv(std::string &&label, VecSenseObj &&inp)

Make a combination of possibly negated objects.

The Region Definition Vector is the SCALE way for defining media, boundaries, etc. It must not be empty.

        classDiagram
  Object <|-- Transformed
  Object <|-- Shape
  Object <|-- NegatedObject
  Object <|-- JoinObjects
  ShapeBase <|-- Shape
  class Object {
    +string_view label()*
    +NodeId build(VolumeBuilder&)*
  }
  <<Interface>> Object
  class Transformed {
    -SPConstObject obj
    -VariantTransform transform
  }
  Transformed *-- Object

  class ShapeBase {
    #IntersectRegion const& interior()*
  }
  <<Abstract>> ShapeBase

  class Shape {
    -string label;
    -IntersectRegion region;
  }
  Shape *-- IntersectRegion

  class IntersectRegion {
    +void build(IntersectSurfaceBuilder&)*
  }
  <<Interface>> IntersectRegion
  IntersectRegion <|-- Box
  IntersectRegion <|-- Sphere

  class Box {
    -Real3 halfwidths
  }
  class Sphere {
    -real_type radius
  }

  Shape <|.. BoxShape
  Shape <|.. SphereShape

  BoxShape *-- Box
  SphereShape *-- Sphere
    

CSG unit construction

The Object classes above are all factory functions for creating a CSG tree and transformed surfaces corresponding to leaf nodes. Some important aspects of this construction process are:

  • Transforming constructed surfaces based on the stack of transformations

  • Simplifying and normalizing surfaces (e.g., ensuring planes are pointing in a “positive” direction and converting arbitrary planes to axis-aligned planes)

  • Deduplicating “close” surfaces to eliminate boundary crossing errors

  • Naming constructed surfaces based on the constructing surface type

  • Constructing bounding boxes using the original and simplified surfaces, as well as additional specifications from the convex regions

  • Adding surfaces as leaf nodes to the CSG tree, and defining additional nodes based on those

  • Simplifying the CSG tree based on boundary conditions and other factors

Geant4 geometry translation

The Geant4 geometry is a hierarchy of “logical volumes” comprised of solids. Child (“daughter”) volumes are “placed” into a parent (“mother”) volume after applying a transformation (translation, rotation, reflection, or a combination), displacing the material in the parent volume. Besides this displacement, no overlap is allowed.

Solids are parametrized volumes that may be hollowed out, have slices removed, or be defined as a CSG operation on placed volumes. They are sometimes but not always convex. See the Geant4 documentation for descriptions of all the predefined solids.

A logical volume can be referenced multiple times, i.e., placed multiple times in multiple different volumes. The Geant4-ORANGE converter decomposes the graph of logical volume relationships into subgraphs that each become a CSG unit. This decomposition is currently tuned so that:

  • Volumes with no children are directly placed as “material” leaf nodes into a unit

  • Logical volumes placed in a singular location without transforms are also placed as materials with child volumes explicitly subtracted out

  • Union or poly volumes (for now!) must be placed as materials even if they are used multiple times and have daughter volumes.

Runtime interfaces

class OrangeParams : public celeritas::GeoParamsSurfaceInterface, public celeritas::ParamsDataInterface<OrangeParamsData>

Persistent model data for an ORANGE geometry.

This class initializes and manages the data used by ORANGE (surfaces, volumes) and provides a host-based interface for them.

class OrangeTrackView

Navigate through an ORANGE geometry on a single thread.

Ordering requirements:

  • initialize (through assignment) must come first

  • access (pos, dir, volume/surface/is_outside/is_on_boundary) good at any time

  • find_next_step

  • find_safety or move_internal or move_to_boundary

  • if on boundary, cross_boundary

  • at any time, set_dir , but then must do find_next_step before any move or cross action above

The main point is that find_next_step depends on the current straight-line direction, move_to_boundary and move_internal (with a step length) depends on that distance, and cross_boundary depends on being on the boundary with a knowledge of the post-boundary state.

move_internal with a position should depend on the safety distance but that’s not yet implemented.