Program Listing for File Boundary.cpp

Return to documentation for file (src/module/Boundary.cpp)

#include "crpropa/module/Boundary.h"
#include "crpropa/Units.h"

#include <sstream>

namespace crpropa {

PeriodicBox::PeriodicBox() :
                origin(Vector3d(0, 0, 0)), size(Vector3d(0, 0, 0)) {
}

PeriodicBox::PeriodicBox(Vector3d o, Vector3d s) :
                origin(o), size(s) {
}

void PeriodicBox::process(Candidate *c) const {
        Vector3d pos = c->current.getPosition();
        Vector3d n = ((pos - origin) / size).floor();

        if ((n.x == 0) and (n.y == 0) and (n.z == 0))
                return; // do nothing if candidate is inside the box

        c->current.setPosition(pos - n * size);
        c->previous.setPosition(c->previous.getPosition() - n * size);
        c->source.setPosition(c->source.getPosition() - n * size);
        c->created.setPosition(c->created.getPosition() - n * size);
}

void PeriodicBox::setOrigin(Vector3d o) {
        origin = o;
}
void PeriodicBox::setSize(Vector3d s) {
        size = s;
}

std::string PeriodicBox::getDescription() const {
        std::stringstream s;
        s << "Periodic box: origin " << origin / Mpc << " Mpc, ";
        s << "size " << size / Mpc << " Mpc";
        return s.str();
}

ReflectiveBox::ReflectiveBox() :
                origin(Vector3d(0, 0, 0)), size(Vector3d(0, 0, 0)) {
}

ReflectiveBox::ReflectiveBox(Vector3d o, Vector3d s) :
                origin(o), size(s) {
}

void ReflectiveBox::process(Candidate *c) const {
        Vector3d cur = (c->current.getPosition() - origin) / size; // current position in cell units
        Vector3d n = cur.floor();

        if ((n.x == 0) and (n.y == 0) and (n.z == 0))
                return; // do nothing if candidate is inside the box

        // flip direction
        Vector3d nReflect(pow(-1, n.x), pow(-1, n.y), pow(-1, n.z));
        c->current.setDirection(c->current.getDirection() * nReflect);
        c->previous.setDirection(c->previous.getDirection() * nReflect);
        c->created.setDirection(c->created.getDirection() * nReflect);
        c->source.setDirection(c->source.getDirection() * nReflect);

        Vector3d src = (c->source.getPosition() - origin) / size; // initial position in cell units
        Vector3d cre = (c->created.getPosition() - origin) / size; // initial position in cell units
        Vector3d prv = (c->previous.getPosition() - origin) / size; // previous position in cell units

        // repeatedly translate until the current position is inside the cell
        while ((cur.x < 0) or (cur.x > 1)) {
                double t = 2 * (cur.x > 1);
                src.x = t - src.x;
                cre.x = t - cre.x;
                prv.x = t - prv.x;
                cur.x = t - cur.x;
        }
        while ((cur.y < 0) or (cur.y > 1)) {
                double t = 2 * (cur.y > 1);
                src.y = t - src.y;
                cre.y = t - cre.y;
                prv.y = t - prv.y;
                cur.y = t - cur.y;
        }
        while ((cur.z < 0) or (cur.z > 1)) {
                double t = 2 * (cur.z > 1);
                src.z = t - src.z;
                cre.z = t - cre.z;
                prv.z = t - prv.z;
                cur.z = t - cur.z;
        }

        c->current.setPosition(cur * size + origin);
        c->source.setPosition(src * size + origin);
        c->created.setPosition(cre * size + origin);
        c->previous.setPosition(prv * size + origin);
}

void ReflectiveBox::setOrigin(Vector3d o) {
        origin = o;
}
void ReflectiveBox::setSize(Vector3d s) {
        size = s;
}

std::string ReflectiveBox::getDescription() const {
        std::stringstream s;
        s << "Reflective box: origin " << origin / Mpc << " Mpc, ";
        s << "size " << size / Mpc << " Mpc";
        return s.str();
}

CubicBoundary::CubicBoundary() :
                origin(Vector3d(0, 0, 0)), size(0), limitStep(true), margin(0.1 * kpc) {
}

CubicBoundary::CubicBoundary(Vector3d o, double s) :
                origin(o), size(s), limitStep(true), margin(0.1 * kpc) {
}

void CubicBoundary::process(Candidate *c) const {
        Vector3d r = c->current.getPosition() - origin;
        double lo = r.min();
        double hi = r.max();
        if ((lo <= 0) or (hi >= size)) {
                reject(c);
        }
        if (limitStep) {
                c->limitNextStep(lo + margin);
                c->limitNextStep(size - hi + margin);
        }
}

void CubicBoundary::setOrigin(Vector3d o) {
        origin = o;
}
void CubicBoundary::setSize(double s) {
        size = s;
}
void CubicBoundary::setMargin(double m) {
        margin = m;
}
void CubicBoundary::setLimitStep(bool b) {
        limitStep = b;
}

std::string CubicBoundary::getDescription() const {
        std::stringstream s;
        s << "Cubic Boundary: origin " << origin / Mpc << " Mpc, ";
        s << "size " << size / Mpc << " Mpc, ";
        s << "Flag: '" << rejectFlagKey << "' -> '" << rejectFlagValue << "', ";
        s << "MakeInactive: " << (makeRejectedInactive ? "yes" : "no");
        if (rejectAction.valid())
                s << ", Action: " << rejectAction->getDescription();
        return s.str();
}

SphericalBoundary::SphericalBoundary() :
                center(Vector3d(0, 0, 0)), radius(0), limitStep(true), margin(0.1 * kpc) {
}

SphericalBoundary::SphericalBoundary(Vector3d c, double r) :
                center(c), radius(r), limitStep(true), margin(0.1 * kpc) {
}

void SphericalBoundary::process(Candidate *c) const {
        double d = (c->current.getPosition() - center).getR();
        if (d >= radius) {
                reject(c);
        }
        if (limitStep)
                c->limitNextStep(radius - d + margin);
}

void SphericalBoundary::setCenter(Vector3d c) {
        center = c;
}
void SphericalBoundary::setRadius(double r) {
        radius = r;
}
void SphericalBoundary::setMargin(double m) {
        margin = m;
}
void SphericalBoundary::setLimitStep(bool b) {
        limitStep = b;
}

std::string SphericalBoundary::getDescription() const {
        std::stringstream s;
        s << "Spherical Boundary: radius " << radius / Mpc << " Mpc, ";
        s << "around " << center / Mpc << " Mpc, ";
        s << "Flag: '" << rejectFlagKey << "' -> '" << rejectFlagValue << "', ";
        s << "MakeInactive: " << (makeRejectedInactive ? "yes" : "no");
        if (rejectAction.valid())
                s << ", Action: " << rejectAction->getDescription();
        return s.str();
}

EllipsoidalBoundary::EllipsoidalBoundary() :
                focalPoint1(Vector3d(0, 0, 0)), focalPoint2(Vector3d(0, 0, 0)),
                majorAxis(0), limitStep(true), margin(0.1 * kpc) {
}

EllipsoidalBoundary::EllipsoidalBoundary(Vector3d f1, Vector3d f2, double a) :
                focalPoint1(f1), focalPoint2(f2), majorAxis(a), limitStep(true),
                margin(0.1 * kpc) {
}

void EllipsoidalBoundary::process(Candidate *c) const {
        Vector3d pos = c->current.getPosition();
        double d = pos.getDistanceTo(focalPoint1) + pos.getDistanceTo(focalPoint2);
        if (d >= majorAxis) {
                reject(c);
        }
        if (limitStep)
                c->limitNextStep(majorAxis - d + margin);
}

void EllipsoidalBoundary::setFocalPoints(Vector3d f1, Vector3d f2) {
        focalPoint1 = f1;
        focalPoint2 = f2;
}
void EllipsoidalBoundary::setMajorAxis(double a) {
        majorAxis = a;
}
void EllipsoidalBoundary::setMargin(double m) {
        margin = m;
}
void EllipsoidalBoundary::setLimitStep(bool b) {
        limitStep = b;
}

std::string EllipsoidalBoundary::getDescription() const {
        std::stringstream s;
        s << "Ellipsoidal Boundary: F1 = " << focalPoint1 / Mpc << " Mpc, ";
        s << "F2 = " << focalPoint2 / Mpc << " Mpc, ";
        s << "major axis " << majorAxis / Mpc << " Mpc; ";
        s << "Flag: '" << rejectFlagKey << "' -> '" << rejectFlagValue << "', ";
        s << "MakeInactive: " << (makeRejectedInactive ? "yes" : "no");
        if (rejectAction.valid())
                s << ", Action: " << rejectAction->getDescription();
        return s.str();
}

CylindricalBoundary::CylindricalBoundary() :
  origin(Vector3d(0,0,0)), height(0), radius(0), limitStep(false), margin(0) {
}

CylindricalBoundary::CylindricalBoundary(Vector3d o, double h, double r) :
  origin(o), height(h), radius(r), limitStep(false) , margin(0){
}

void CylindricalBoundary::process(Candidate *c) const {
        Vector3d d = c->current.getPosition() - origin;
        double R2 = pow(d.x, 2.)+pow(d.y, 2.);
        double Z = fabs(d.z);
        if ( R2 < pow(radius, 2.) and Z < height/2.) {
                if(limitStep) {
                        c->limitNextStep(std::min(radius - pow(R2, 0.5), height/2. - Z) + margin);
                }
          return;
        }
        reject(c);
}

void CylindricalBoundary::setOrigin(Vector3d o) {
        origin = o;
}
void CylindricalBoundary::setHeight(double h) {
        height = h;
}
void CylindricalBoundary::setRadius(double r) {
        radius = r;
}
void CylindricalBoundary::setLimitStep(bool b) {
        limitStep = b;
}
void CylindricalBoundary::setMargin(double m) {
        margin = m;
}


std::string CylindricalBoundary::getDescription() const {
        std::stringstream s;
        s << "Cylindrical Boundary: origin = " << origin / kpc << " kpc, ";
        s << "radius = " << radius / kpc << " kpc, ";
        s << "height" << height / kpc << " kpc; ";
        s << "Flag: '" << rejectFlagKey << "' -> '" << rejectFlagValue << "', ";
        s << "MakeInactive: " << (makeRejectedInactive ? "yes" : "no");
        if (rejectAction.valid())
                s << ", Action: " << rejectAction->getDescription();
        return s.str();
}

} // namespace crpropa