//
// Implementation of the BoundaryGeometry class
//
// Copyright (c) 200x - 2020, Achim Gsell,
// Paul Scherrer Institut, Villigen PSI, Switzerland
// All rights reserved.
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see .
//
/**
\brief class BoundaryGeometry
A GEOMETRY definition is used by most physics commands to define the
particle charge and the reference momentum, together with some other
data.
i.e:
G1: Geometry, FILE="input.h5"
G2: Geometry, L=1.0, A=0.0025, B=0.0001
:TODO: update above section
*/
#ifndef _OPAL_BOUNDARY_GEOMETRY_H
#define _OPAL_BOUNDARY_GEOMETRY_H
class OpalBeamline;
class ElementBase;
#include
#include
#include
#include
#include "AbstractObjects/Definition.h"
#include "Attributes/Attributes.h"
#include "Structure/SecondaryEmissionPhysics.h"
#include "Utilities/Util.h"
#include
extern Inform* gmsg;
class BoundaryGeometry : public Definition {
public:
BoundaryGeometry();
virtual ~BoundaryGeometry();
virtual bool canReplaceBy (
Object* object);
virtual BoundaryGeometry* clone (
const std::string& name);
// Check the GEOMETRY data.
virtual void execute ();
// Find named GEOMETRY.
static BoundaryGeometry* find (
const std::string& name);
// Update the GEOMETRY data.
virtual void update ();
void updateElement (
ElementBase* element);
void initialize ();
int partInside (
const Vector_t& r,
const Vector_t& v,
const double dt,
Vector_t& intecoords,
int& triId);
Inform& printInfo (
Inform& os) const;
void writeGeomToVtk (std::string fn);
inline std::string getFilename() const {
return Attributes::getString(itsAttr[FGEOM]);
}
inline std::string getTopology() const {
return Util::toUpper(Attributes::getString(itsAttr[TOPO]));
}
inline double getA() {
return (double)Attributes::getReal(itsAttr[A]);
}
inline double getB() {
return (double)Attributes::getReal(itsAttr[B]);
}
inline double getC() {
return (double)Attributes::getReal(itsAttr[C]);
}
inline double getS() {
return (double)Attributes::getReal(itsAttr[S]);
}
inline double getLength() {
return (double)Attributes::getReal(itsAttr[LENGTH]);
}
inline double getL1() {
return (double)Attributes::getReal(itsAttr[L1]);
}
inline double getL2() {
return (double)Attributes::getReal(itsAttr[L2]);
}
/**
Return number of boundary faces.
*/
inline size_t getNumBFaces () {
return Triangles_m.size();
}
/**
Return the hr_m.
*/
inline Vector_t gethr () {
return voxelMesh_m.sizeOfVoxel;
}
/**
Return the nr_m.
*/
inline Vektor getnr () {
return voxelMesh_m.nr_m;
}
/**
Return the mincoords_m.
*/
inline Vector_t getmincoords () {
return minExtent_m;
}
/**
Return the maxcoords_m.
*/
inline Vector_t getmaxcoords () {
return maxExtent_m;
}
inline bool getInsidePoint (Vector_t& pt) {
if (haveInsidePoint_m == false) {
return false;
}
pt = insidePoint_m;
return true;
}
bool findInsidePoint (void);
inline bool isOutsideApperture(Vector_t x) {
if (hasApperture()) {
for (size_t i = 0; i < apert_m.size(); i += 3) {
if ((apert_m[i] <= x(2)) && (x(2) < apert_m[i+1])) {
// yes we are inside the interval
const double r = apert_m[i+2] * apert_m[i+2];
return ((x(0)*x(0)) + (x(1)*x(1))) > r;
}
}
}
return false;
}
int intersectRayBoundary (
const Vector_t& P,
const Vector_t& v,
Vector_t& I);
int fastIsInside (
const Vector_t& reference_pt, // [in] a reference point
const Vector_t& P // [in] point to test
);
enum DebugFlags {
debug_isInside = 0x0001,
debug_fastIsInside = 0x0002,
debug_intersectRayBoundary = 0x0004,
debug_intersectLineSegmentBoundary = 0x0008,
debug_intersectTinyLineSegmentBoundary = 0x0010,
debug_PartInside = 0x0020,
};
inline void enableDebug(enum DebugFlags flags) {
debugFlags_m |= flags;
}
inline void disableDebug(enum DebugFlags flags) {
debugFlags_m &= ~flags;
}
private:
bool isInside (
const Vector_t& P // [in] point to test
);
int intersectTriangleVoxel (
const int triangle_id,
const int i,
const int j,
const int k);
int intersectTinyLineSegmentBoundary (
const Vector_t&,
const Vector_t&,
Vector_t&,
int&
);
int intersectLineSegmentBoundary (
const Vector_t& P0,
const Vector_t& P1,
Vector_t& intersection_pt,
int& triangle_id
);
std::string h5FileName_m; // H5hut filename
std::vector Points_m; // geometry point coordinates
std::vector> Triangles_m; // boundary faces defined via point IDs
// please note: 4 is correct, historical reasons!
std::vector TriNormals_m; // oriented normal vector of triangles
std::vector TriAreas_m; // area of triangles
Vector_t minExtent_m; // minimum of geometry coordinate.
Vector_t maxExtent_m; // maximum of geometry coordinate.
struct {
Vector_t minExtent;
Vector_t maxExtent;
Vector_t sizeOfVoxel;
Vektor nr_m; // number of intervals of geometry in X,Y,Z direction
std::unordered_map
std::unordered_set> ids; // intersecting triangles
} voxelMesh_m;
int debugFlags_m;
bool haveInsidePoint_m;
Vector_t insidePoint_m; // attribute INSIDEPOINT
/*
An additional structure to hold apperture information
to prevent that particles go past the geometry. The user
can specify n trippel with the form: (zmin, zmax, r)
*/
std::vector apert_m;
gsl_rng *randGen_m; //
IpplTimings::TimerRef Tinitialize_m; // initialize geometry
IpplTimings::TimerRef TisInside_m;
IpplTimings::TimerRef TfastIsInside_m;
IpplTimings::TimerRef TRayTrace_m; // ray tracing
IpplTimings::TimerRef TPartInside_m; // particle inside
BoundaryGeometry(const BoundaryGeometry&);
void operator= (const BoundaryGeometry&);
// Clone constructor.
BoundaryGeometry(const std::string& name, BoundaryGeometry* parent);
inline bool hasApperture() {
return (apert_m.size() != 0);
}
inline const Vector_t& getPoint (const int triangle_id, const int vertex_id) {
assert (1 <= vertex_id && vertex_id <=3);
return Points_m[Triangles_m[triangle_id][vertex_id]];
}
enum INTERSECTION_TESTS {
SEGMENT,
RAY,
LINE
};
int intersectLineTriangle (
const enum INTERSECTION_TESTS kind,
const Vector_t& P0,
const Vector_t& P1,
const int triangle_id,
Vector_t& I);
inline int mapVoxelIndices2ID (const int i, const int j, const int k);
inline Vector_t mapIndices2Voxel (const int, const int, const int);
inline Vector_t mapPoint2Voxel (const Vector_t&);
inline void computeMeshVoxelization (void);
enum {
FGEOM, // file holding the geometry
LENGTH, // length of elliptic tube or boxcorner
S, // start of the geometry
L1, // in case of BOXCORNER first part of geometry with hight B
L2, // in case of BOXCORNER second part of geometry with hight B-C
A, // major semi-axis of elliptic tube
B, // minor semi-axis of ellitpic tube
C, // in case of BOXCORNER hight of corner
TOPO, // BOX, BOXCORNER, ELLIPTIC if FGEOM is selected topo is over-written
ZSHIFT, // Shift in z direction
XYZSCALE, // Multiplicative scaling factor for coordinates
XSCALE, // Multiplicative scaling factor for x-coordinates
YSCALE, // Multiplicative scaling factor for y-coordinates
ZSCALE, // Multiplicative scaling factor for z-coordinates
APERTURE, // in addition to the geometry
INSIDEPOINT,
SIZE
};
};
inline Inform &operator<< (Inform& os, const BoundaryGeometry& b) {
return b.printInfo (os);
}
#endif
// vi: set et ts=4 sw=4 sts=4:
// Local Variables:
// mode:c
// c-basic-offset: 4
// indent-tabs-mode: nil
// require-final-newline: nil
// End: