CSGSurface
This is an abstract class for any surface definition for constructive solid geometry (CSG) representations. The CSGBase framework already contains definitions for some basic surfaces (planes, spheres, and cylinders), but developers of modules or MOOSE-based application can define additional custom surfaces by deriving from this abstract CSGBase
class. General information about implementing Constructive Solid Geometry (CSG)-related methods can be found in CSGBase.
Defining a New Surface Type
Any arbitrary or custom surface can be defined by inheriting from CSGSurface
. At a minimum, the surface name and surface type, must be set, and two virtual methods that need to be defined. Additional information required by the constructor will depend on the specific surface to be defined.
Setting Coefficients
Each surface should be defined by some equation, which therefore requires the definition of coefficients or other parameters. These coefficient values should be set and be returned through the getCoefficients
method which will return a map of the coefficient strings to their values. These coefficient values are returned in the JavaScript Object Notation (JSON) file that is produced. For example, a plane is defined by the equation and so this method would return a map of the values for a
, b
, c
, and d
.
Half-space Determination
In CSG representation, knowing which half-space of the surface is positive or negative is necessary for correct construction of a cell region. To help determine the sign of these half-spaces, each surface type should have a evaluateSurfaceEquationAtPoint
method implemented that returns a floating point value, where a positive value indicates that the point lies in the positive half-space, a negative value indicates that the point lies in the negative half-space, and a value of 0 indicates that the point lies on the surface.
Setting the Surface Type
The type of surface must be set for _surface_type
in the surface constructor. It is recommended that this be done based on the class name using MooseUtils::prettyCppType<SurfaceClassName>()
so that the surface type automatically matches the class that created it.
Example
Below shows how CSGSphere
is implemented as an example.
#pragma once
#include "CSGSurface.h"
#include "libmesh/point.h"
namespace CSG
{
/**
* CSGSphere creates an internal representation of a Constructive Solid Geometry (CSG)
* sphere, represented in the form (x - x0)^2 + (y - y0)^2 + (z - z0)^2 = r^2
*/
class CSGSphere : public CSGSurface
{
public:
/**
* @brief Construct a new CSGSphere surface
*
* @param name unique name for the sphere surface
* @param center center point of sphere
* @param r radius of sphere
*/
CSGSphere(const std::string & name, const Point & center, const Real r);
/**
* @brief Construct a new CSGSphere surface
*
* @param name unique name for the sphere surface
* @param r radius of sphere
*/
CSGSphere(const std::string & name, const Real r);
/**
* Destructor
*/
virtual ~CSGSphere() = default;
/**
* @brief Get the coefficients (x0, y0, z0, r) for the equation of a sphere
* (x - x0)^2 + (y - y0)^2 + (z - z0)^2 = r^2
*
* @return map of coefficients (x0, y0, z0, and r) and their values
*/
virtual std::unordered_map<std::string, Real> getCoeffs() const override;
/**
* @brief given a point, determine its evaluation based on the equation of the sphere
*
* @param p point
* @return evaluation of point based on surface equation
*/
virtual Real evaluateSurfaceEquationAtPoint(const Point & p) const override;
protected:
// check that radius is positive
void checkRadius() const;
/// Value of x0 in equation of sphere
Real _x0;
/// Value of y0 in equation of sphere
Real _y0;
/// Value of z0 in equation of sphere
Real _z0;
/// Value of r in equation of sphere
Real _r;
};
} // namespace CSG
(moose/framework/include/csg/CSGSphere.h)
#include "CSGSphere.h"
namespace CSG
{
CSGSphere::CSGSphere(const std::string & name, const Point & center, const Real r)
: CSGSurface(name, MooseUtils::prettyCppType<CSGSphere>()),
_x0(center(0)),
_y0(center(1)),
_z0(center(2)),
_r(r)
{
checkRadius();
}
CSGSphere::CSGSphere(const std::string & name, const Real r)
: CSGSurface(name, MooseUtils::prettyCppType<CSGSphere>()), _x0(0.0), _y0(0.0), _z0(0.0), _r(r)
{
checkRadius();
}
std::unordered_map<std::string, Real>
CSGSphere::getCoeffs() const
{
std::unordered_map<std::string, Real> coeffs = {{"x0", _x0}, {"y0", _y0}, {"z0", _z0}, {"r", _r}};
return coeffs;
}
Real
CSGSphere::evaluateSurfaceEquationAtPoint(const Point & p) const
{
// Compute distance from the sphere center to determine if inside (< r^2)
// or outside (> r^2) the sphere
const Real dist_sq =
Utility::pow<2>((p(0) - _x0)) + Utility::pow<2>((p(1) - _y0)) + Utility::pow<2>((p(2) - _z0));
return dist_sq - Utility::pow<2>(_r);
}
void
CSGSphere::checkRadius() const
{
if (_r <= 0.0)
mooseError("Radius of sphere must be positive.");
}
} // namespace CSG
(moose/framework/src/csg/CSGSphere.C)