Program Listing for File MagneticLens.cpp

Return to documentation for file (src/magneticLens/MagneticLens.cpp)

//----------------------------------------------------------------------
// This file is part of PARSEC (http://physik.rwth-aachen.de/parsec)
// a parametrized simulation engine for cosmic rays.
//
// Copyright (C) 2011  Martin Erdmann, Peter Schiffer, Tobias Winchen
//                     RWTH Aachen University, Germany
// Contact: winchen@physik.rwth-aachen.de
//
//  This program 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.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program. If not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------

#include "crpropa/magneticLens/MagneticLens.h"

#include "crpropa/Random.h"
#include "crpropa/Units.h"

// needed for memcpy in gcc 4.3.2
#include <cstring>

namespace crpropa
{

void MagneticLens::loadLens(const string &filename)
{
        ifstream infile(filename.c_str());
        if (!infile)
        {
                throw std::runtime_error("Can't read file: " + filename);
        }
        string line;

        string prefix;
        int sp = filename.find_last_of("/");
        if (sp >= 0)
        {
                prefix = filename.substr(0, sp);
                prefix.append("/");
        }
        string mfdatfile;
        double emin, emax;

        int lineCounter = 0;
        while (!infile.eof())
        {
                getline(infile, line);
                lineCounter++;
                if (line.find('#') == string::npos)
                {
                        stringstream ss;
                        ss << line;
                        ss >> mfdatfile >> emin >> emax;
                        if (ss.fail())
                        {
                                cerr << "WARNING! Cannot read line " << lineCounter << " of file " << filename << " :\n [" << lineCounter << " ]: " << line << " \n";
                                cerr << " ... Skipping line and continue\n";
                        }
                        else
                        {
                                this->loadLensPart(prefix + mfdatfile, pow(10, emin) * eV, pow(10, emax) * eV);
                        }
                }
        }
}

bool MagneticLens::transformCosmicRay(double rigidity, double& phi,
                double& theta)
{
        uint32_t c = _pixelization->direction2Pix(phi, theta);
        LensPart *lenspart = getLensPart(rigidity);
        if (!lenspart)
        {
                std::cerr << "Warning. Trying to transform cosmic ray with rigidity " << rigidity / eV << " eV which is not covered by this lens!.\n";
                std::cerr << " This lens covers the range " << _minimumRigidity /eV << " eV - " << _maximumRigidity << " eV.\n";
                return false;
        }

        ModelVectorType v = lenspart->getMatrix().col(c);

        uint32_t r;

        // the random number to compare with
        double rn = Random::instance().rand();

        ModelVectorType::InnerIterator i(v);
  double cpv = 0;
  while (i)
  {
                cpv += i.value();
                if (rn < cpv)
                {
                        _pixelization->pix2Direction(i.index(), phi, theta);
                        return true;
    }
    else
    {
                        ++i;
    }
   }
  return false;
}

bool MagneticLens::transformCosmicRay(double rigidity, Vector3d &p){

                        double galacticLongitude = atan2(-p.y, -p.x);
                        double galacticLatitude =       M_PI / 2 - acos(-p.z/ sqrt(p.x*p.x + p.y*p.y + p.z*p.z));
                        bool result = transformCosmicRay(rigidity, galacticLongitude, galacticLatitude);

                        p.x = -1 * cos(galacticLongitude) * sin(M_PI / 2 - galacticLatitude);
                        p.y = -1 * sin(galacticLongitude) * sin(M_PI / 2 - galacticLatitude);
                        p.z = -1. * cos(M_PI / 2 - galacticLatitude);

                        return result;
}

void MagneticLens::loadLensPart(const string &filename, double rigidityMin,
                double rigidityMax)
{
        updateRigidityBounds(rigidityMin, rigidityMax);

        LensPart *p = new LensPart(filename, rigidityMin, rigidityMax);
        p->loadMatrixFromFile();
        _checkMatrix(p->getMatrix());

        _lensParts.push_back(p);
}

void MagneticLens::_checkMatrix(const ModelMatrixType &M)
{
        if (M.rows() != M.cols())
        {
                throw std::runtime_error("Not a square Matrix!");
        }

        if (_pixelization)
        {
                if (_pixelization->nPix() != M.cols())
                {
                        std::cerr << "*** ERROR ***" << endl;
                        std::cerr << "  Pixelization: " << _pixelization->nPix() << endl;
                        std::cerr << "  Matrix Size : " << M.cols() << endl;
                        throw std::runtime_error("Matrix doesn't fit into Lense");
                }
        }
        else
        {
                uint32_t morder = Pixelization::pix2Order(M.cols());
                if (morder == 0)
                {
                        throw std::runtime_error(
                                        "Matrix size doesn't match healpix scheme!");
                }
                _pixelization = new Pixelization(morder);
        }
}

void MagneticLens::updateRigidityBounds(double rigidityMin, double rigidityMax)
{
        if (rigidityMin >= rigidityMax)
        {
                throw std::runtime_error("rigidityMin >= rigidityMax");
        }
        if (rigidityMin < _minimumRigidity)
        {
                _minimumRigidity = rigidityMin;
        }

        if (_maximumRigidity < rigidityMin)
        {
                _maximumRigidity = rigidityMax;
        }
}

void MagneticLens::setLensPart(const ModelMatrixType &M, double rigidityMin,
                double rigidityMax)
{
        updateRigidityBounds(rigidityMin, rigidityMax);
        LensPart *p = new LensPart("Direct Input", rigidityMin, rigidityMax);

        p->setMatrix(M);

        _checkMatrix(p->getMatrix());
        _lensParts.push_back(p);
}

LensPart* MagneticLens::getLensPart(double rigidity) const
{
        const_LensPartIter i = _lensParts.begin();
        while (i != _lensParts.end())
        {
                if (((*i)->getMinimumRigidity() < rigidity / eV)
                                && ((*i)->getMaximumRigidity() >= rigidity / eV))
                {
                        return (*i);
                }
                ++i;
        }
        return NULL;
}

bool MagneticLens::rigidityCovered(double rigidity) const
{
        if (getLensPart(rigidity))
                return true;
        else
                return false;
}


void MagneticLens::normalizeMatrixColumns()
{
        for (LensPartIter iter = _lensParts.begin(); iter != _lensParts.end();
                        ++iter)
        {
                normalizeColumns((*iter)->getMatrix());
        }
}


void MagneticLens::normalizeLens()
{
        // get maximum of sums of columns, and normalize each matrix to that
        double norm = 0;
        for (LensPartIter iter = _lensParts.begin(); iter != _lensParts.end();
                        ++iter)
        {
                if ((*iter)->getMaximumOfSumsOfColumns() > norm)
                {
                        norm = (*iter)->getMaximumOfSumsOfColumns();
                }
        }
        for (LensPartIter iter = _lensParts.begin(); iter != _lensParts.end();
                        ++iter)
        {
                normalizeMatrix((*iter)->getMatrix(), norm);
        }
  _norm = norm;
}

void MagneticLens::normalizeLensparts()
{
        for (LensPartIter iter = _lensParts.begin(); iter != _lensParts.end();
                        ++iter)
        {
                double norm = (*iter)->getMaximumOfSumsOfColumns();
                normalizeMatrix((*iter)->getMatrix(), norm);
        }
}

void MagneticLens::transformModelVector(double* model, double rigidity) const
{
        LensPart* lenspart = getLensPart(rigidity);

        if (!lenspart)
        {
                std::cerr << "Warning. Trying to transform vector with rigidity " << rigidity / eV << "eV which is not covered by this lens!.\n" << std::endl;
                return;
        }

        prod_up(lenspart->getMatrix(), model);

}



} // namespace parsec