Program Listing for File AdvectionField.cpp

Return to documentation for file (src/advectionField/AdvectionField.cpp)

#include "crpropa/advectionField/AdvectionField.h"


namespace crpropa {



void AdvectionFieldList::addField(ref_ptr<AdvectionField> field) {
        fields.push_back(field);
}

Vector3d AdvectionFieldList::getField(const Vector3d &position) const {
        Vector3d b(0.);
        for (int i = 0; i < fields.size(); i++)
                b += fields[i]->getField(position);
        return b;
}

double AdvectionFieldList::getDivergence(const Vector3d &position) const {
        double D=0.;
        // Work on default values for divergence or an error handling
        for (int i = 0; i < fields.size(); i++)
                D += fields[i]->getDivergence(position);
        return D;
}


//----------------------------------------------------------------
UniformAdvectionField::UniformAdvectionField(const Vector3d &value) :
                        value(value) {
        }

Vector3d UniformAdvectionField::getField(const Vector3d &position) const {
        return value;
        }

double UniformAdvectionField::getDivergence(const Vector3d &position) const {
        return 0.;
        }

std::string UniformAdvectionField::getDescription() const {
        std::stringstream s;
        s << "v0: " << value / km * sec << " km/s, ";
        return s.str();
}

//----------------------------------------------------------------

ConstantSphericalAdvectionField::ConstantSphericalAdvectionField(const Vector3d origin, double vWind) {
        setOrigin(origin);
        setVWind(vWind);
}

Vector3d ConstantSphericalAdvectionField::getField(const Vector3d &position) const {
        Vector3d Pos = position-origin;
        return vWind * Pos.getUnitVector();
}

double ConstantSphericalAdvectionField::getDivergence(const Vector3d &position) const {
        double R = (position-origin).getR();
        return 2*vWind/R;
}

void ConstantSphericalAdvectionField::setOrigin(const Vector3d o) {
        origin=o;
        return;
}

void ConstantSphericalAdvectionField::setVWind(double v) {
        vWind = v;
        return;
}

Vector3d ConstantSphericalAdvectionField::getOrigin() const {
        return origin;
}

double ConstantSphericalAdvectionField::getVWind() const {
        return vWind;
}

std::string ConstantSphericalAdvectionField::getDescription() const {
        std::stringstream s;
        s << "Origin: " << origin / kpc  << " kpc, ";
        s << "v0: " << vWind / km * sec << " km/s, ";
        return s.str();
}



//----------------------------------------------------------------

SphericalAdvectionField::SphericalAdvectionField(const Vector3d origin, double radius, double vMax, double tau, double alpha) {
        setOrigin(origin);
        setRadius(radius);
        setVMax(vMax);
        setTau(tau);
        setAlpha(alpha);
}

Vector3d SphericalAdvectionField::getField(const Vector3d &position) const {
        Vector3d Pos = position-origin;
        double R = Pos.getR();
        if (R>radius) {
                return Vector3d(0.);
        }
        double v_R = getV(R);
        return v_R * Pos.getUnitVector();
}

double SphericalAdvectionField::getDivergence(const Vector3d &position) const {
        double R = (position-origin).getR();
        if (R>radius) {
                return 0.;
        }
        double D = 2*vMax/R * ( 1-( 1-alpha*(pow(R, alpha)/(2*tau)) )*exp(-( pow(R, alpha)/tau )) );
        return D;
}

double SphericalAdvectionField::getV(const double &r) const {
        double f = vMax * (1-exp(-(pow(r, alpha)/tau)));
        return f;
}

void SphericalAdvectionField::setOrigin(const Vector3d o) {
        origin = o;
        return;
}

void SphericalAdvectionField::setRadius(double r) {
        radius = r;
        return;
}

void SphericalAdvectionField::setVMax(double v) {
        vMax = v;
        return;
}

void SphericalAdvectionField::setTau(double t) {
        tau = t;
        return;
}

void SphericalAdvectionField::setAlpha(double a) {
        alpha = a;
        return;
}

Vector3d SphericalAdvectionField::getOrigin() const {
        return origin;
}

double SphericalAdvectionField::getRadius() const {
        return radius;
}

double SphericalAdvectionField::getVMax() const {
        return vMax;
}

double SphericalAdvectionField::getTau() const {
        return tau;
}

double SphericalAdvectionField::getAlpha() const {
        return alpha;
}

std::string SphericalAdvectionField::getDescription() const {
        std::stringstream s;
        s << "Origin: " << origin / kpc  << " kpc, ";
        s << "Radius: " << radius / kpc  << " kpc, ";
        s << "vMax: " << vMax / km * sec << " km/s, ";
        s << "tau: " << tau << ", ";
        s << "alpha: " << alpha << "\n";
        return s.str();
}

//----------------------------------------------------------------

OneDimensionalCartesianShock::OneDimensionalCartesianShock(double compressionRatio, double vUp, double lShock){
        setComp(compressionRatio);
        setVup(vUp);
        setShockwidth(lShock);
        }

Vector3d OneDimensionalCartesianShock::getField(const Vector3d &position) const {
        double x = position.x;
        double vDown = vUp / compressionRatio;

        double a = (vUp + vDown) * 0.5;
        double b = (vUp - vDown) * 0.5;

        Vector3d v(0.);
        v.x = a - b * tanh(x / lShock);
        return v;

}

double OneDimensionalCartesianShock::getDivergence(const Vector3d &position) const {
        double x = position.x;
        double vDown = vUp / compressionRatio;

        double a = (vUp + vDown) * 0.5;
        double b = (vUp - vDown) * 0.5;
        return -b / lShock * (1 - tanh(x / lShock) * tanh(x / lShock));
}

void OneDimensionalCartesianShock::setComp(double r) {
        compressionRatio = r;
        return;
}

void OneDimensionalCartesianShock::setVup(double v) {
        vUp = v;
        return;
}
void OneDimensionalCartesianShock::setShockwidth(double w) {
        lShock = w;
        return;
}

double OneDimensionalCartesianShock::getComp() const {
        return compressionRatio;
}

double OneDimensionalCartesianShock::getVup() const {
        return vUp;
}

double OneDimensionalCartesianShock::getShockwidth() const {
        return lShock;
}

std::string OneDimensionalCartesianShock::getDescription() const {
        std::stringstream s;
        s << "Shock width: " << lShock / km  << " km, ";
        s << "Vup: " << vUp / km * sec << " km/s, ";
        s << "Compression: " << compressionRatio;
        return s.str();
}

//----------------------------------------------------------------

OneDimensionalSphericalShock::OneDimensionalSphericalShock(double rShock, double vUp, double compressionRatio, double lShock, bool coolUpstream ){
        setComp(compressionRatio);
        setVup(vUp);
        setShockwidth(lShock);
        setShockRadius(rShock);
        setCooling(coolUpstream);
        }

Vector3d OneDimensionalSphericalShock::getField(const Vector3d &position) const {
        double r = position.getR();
        Vector3d e_r = position.getUnitVector();

        double vDown = vUp / compressionRatio;
        double a = (vUp + vDown) * 0.5;
        double b = (vUp - vDown) * 0.5;

        double v;
        if (coolUpstream == true){

                if (r <= rShock)
                v = a - b * tanh((r-rShock) / lShock);
                else
                        v = (a - b * tanh((r-rShock) / lShock)) * (rShock / r) * (rShock / r);

        }
        else
                v = (a - b * tanh((r-rShock) / lShock)) * (rShock / r) * (rShock / r);

        return v * e_r;
        }

double OneDimensionalSphericalShock::getDivergence(const Vector3d &position) const {
        double r = position.getR();

        double vDown = vUp / compressionRatio;
        double a = (vUp + vDown) * 0.5;
        double b = (vUp - vDown) * 0.5;

        double c = tanh((r-rShock) / lShock);

        if (coolUpstream == true){
                if (r <= rShock)
                        return 2 * a / r - 2 * b / r * c - b / lShock * (1 - c * c);
                else
                        return -(rShock / r) * (rShock / r) * b / lShock * (1 - c * c);
        }
        else
                return -(rShock / r) * (rShock / r) *  b / lShock * (1 - c * c);

}

void OneDimensionalSphericalShock::setComp(double r) {
        compressionRatio = r;
        return;
}

void OneDimensionalSphericalShock::setVup(double v) {
        vUp = v;
        return;
}
void OneDimensionalSphericalShock::setShockwidth(double w) {
        lShock = w;
        return;
}

void OneDimensionalSphericalShock::setShockRadius(double r) {
        rShock = r;
        return;
}

void OneDimensionalSphericalShock::setCooling(bool c) {
        coolUpstream = c;
        return;
}

double OneDimensionalSphericalShock::getComp() const {
        return compressionRatio;
}

double OneDimensionalSphericalShock::getVup() const {
        return vUp;
}

double OneDimensionalSphericalShock::getShockwidth() const {
        return lShock;
}

double OneDimensionalSphericalShock::getShockRadius() const {
        return rShock;
}

bool OneDimensionalSphericalShock::getCooling() const {
        return coolUpstream;
}

std::string OneDimensionalSphericalShock::getDescription() const {
        std::stringstream s;
        s << "Shock width: " << lShock / km  << " km, ";
        s << "Shock radius: " << rShock / km  << " km, ";
        s << "Vup: " << vUp / km * sec << " km/s, ";
        s << "Comp: " << compressionRatio;

        return s.str();
}

//----------------------------------------------------------------

ObliqueAdvectionShock::ObliqueAdvectionShock(double compressionRatio, double vXUp, double vY, double lShock) {
        setComp(compressionRatio);
        setVup(vXUp);
        setVy(vY);
        setShockwidth(lShock);
        }

Vector3d ObliqueAdvectionShock::getField(const Vector3d &position) const {
        double x = position.x;
        double vXDown = vXUp / compressionRatio;

        double a = (vXUp + vXDown) * 0.5;
        double b = (vXUp - vXDown) * 0.5;

        Vector3d v(0.);
        v.x = a - b * tanh(x / lShock);
        v.y = vY;

        return v;
        }

double ObliqueAdvectionShock::getDivergence(const Vector3d &position) const {
        double x = position.x;
        double vXDown = vXUp / compressionRatio;
        // vy = const

        double a = (vXUp + vXDown) * 0.5;
        double b = (vXUp - vXDown) * 0.5;

        return -b / lShock * (1 - tanh(x / lShock) * tanh(x / lShock));
        }

void ObliqueAdvectionShock::setComp(double r) {
        compressionRatio = r;
        return;
}

void ObliqueAdvectionShock::setVup(double v) {
        vXUp = v;
        return;
}

void ObliqueAdvectionShock::setVy(double v) {
        vY = v;
        return;
}
void ObliqueAdvectionShock::setShockwidth(double w) {
        lShock = w;
        return;
}

double ObliqueAdvectionShock::getComp() const {
        return compressionRatio;
}

double ObliqueAdvectionShock::getVup() const {
        return vXUp;
}

double ObliqueAdvectionShock::getVy() const {
        return vY;
}

double ObliqueAdvectionShock::getShockwidth() const {
        return lShock;
}

std::string ObliqueAdvectionShock::getDescription() const {
        std::stringstream s;
        s << "Shock width: " << lShock / km  << " km, ";
        s << "Vx_up: " << vXUp / km * sec << " km/s, ";
        s << "Vy: " << vY / km * sec << " km/s, ";
        s << "Comp: " << compressionRatio;

        return s.str();
}

//-----------------------------------------------------------------

SphericalAdvectionShock::SphericalAdvectionShock(const Vector3d origin, double r_0, double v_0, double l) {
        setOrigin(origin);
        setR0(r_0);
        setV0(v_0);
        setLambda(l);
        setRRot(r_0);
        setAzimuthalSpeed(0.);
}


Vector3d SphericalAdvectionShock::getField(const Vector3d &pos) const {
        Vector3d R = pos-origin;
        Vector3d e_r = R.getUnitVector();
        Vector3d e_phi = R.getUnitVectorPhi();
        double r = R.getR();

        double v_r = v_0 * ( 1 + (pow(r_0/(2*r), 2.) -1 ) * g(r));
        double v_p = v_phi * (r_rot/r);

        return v_r * e_r + v_p * e_phi;
}


double SphericalAdvectionShock::getDivergence(const Vector3d &pos) const {
        double r = (pos-origin).getR();

        double d1 = 2./r*(1-g(r));
        double d2 = (pow(r_0/(2*r), 2.)-1)*g_prime(r);

        return v_0 * (d1+d2);
}


double SphericalAdvectionShock::g(double r) const {
        double a = (r-r_0)/lambda;
        return 1. / (1+exp(-a));
}

double SphericalAdvectionShock::g_prime(double r) const {
        double a = (r-r_0)/lambda;
        return 1. / (2*lambda*(1+cosh(-a)));
}

void SphericalAdvectionShock::setOrigin(const Vector3d o) {
        origin = o;
}

void SphericalAdvectionShock::setR0(double r) {
        r_0 = r;
}

void SphericalAdvectionShock::setV0(double v) {
        v_0 = v;
}

void SphericalAdvectionShock::setLambda(double l) {
        lambda = l;
}

void SphericalAdvectionShock::setRRot(double r) {
        r_rot = r;
}

void SphericalAdvectionShock::setAzimuthalSpeed(double v) {
        v_phi = v;
}

Vector3d SphericalAdvectionShock::getOrigin() const {
        return origin;
}

double SphericalAdvectionShock::getR0() const {
        return r_0;
}

double SphericalAdvectionShock::getV0() const {
        return v_0;
}

double SphericalAdvectionShock::getLambda() const {
        return lambda;
}

double SphericalAdvectionShock::getRRot() const {
        return r_rot;
}

double SphericalAdvectionShock::getAzimuthalSpeed() const {
        return v_phi;
}

std::string SphericalAdvectionShock::getDescription() const {
        std::stringstream s;
        s << "Origin: " << origin / kpc  << " kpc, ";
        s << "r0 (shock radius): " << r_0 / kpc  << " kpc, ";
        s << "r_rot (norm. azimuthal velocity): " << r_rot / kpc  << " kpc, ";
        s << "v0 (maximum radial speed): " << v_0 / km * sec << " km/s, ";
        s << "v_phi (azimuthal speed @ r_rot): " << v_phi / km * sec << " km/s, ";
        s << "lambda: " << lambda / pc << " pc";
        return s.str();
}

} // namespace crpropa