Program Listing for File YRECIO.cpp

Return to documentation for file (/home/kpenev/projects/git/poet/poet_src/StellarEvolution/YRECIO.cpp)

#define BUILDING_LIBRARY
#include "YRECIO.h"
#include <string>
#include <sstream>
#include <algorithm>

const std::streamsize max_line_length=1000;

EvolutionIterator::EvolutionIterator(const EvolutionIterator &orig) :
    mass_iter(orig.mass_iter), age_iter(orig.age_iter),
    radius_iter(orig.radius_iter), luminosity_iter(orig.luminosity_iter),
    rad_mass_iter(orig.rad_mass_iter),
    core_boundary_iter(orig.core_boundary_iter),
    conv_inertia_iter(orig.conv_inertia_iter),
    rad_inertia_iter(orig.rad_inertia_iter) {}

EvolutionIterator &EvolutionIterator::operator=(const EvolutionIterator &rhs)
{
    mass_iter=rhs.mass_iter;
    age_iter=rhs.age_iter;
    radius_iter=rhs.radius_iter;
    luminosity_iter=rhs.luminosity_iter;
    rad_mass_iter=rhs.rad_mass_iter;
    core_boundary_iter=rhs.core_boundary_iter;
    conv_inertia_iter=rhs.conv_inertia_iter;
    rad_inertia_iter=rhs.rad_inertia_iter;
    return *this;
}

EvolutionIterator &EvolutionIterator::operator++()
{
    ++mass_iter; ++age_iter; ++radius_iter; ++luminosity_iter;
    ++rad_mass_iter; ++core_boundary_iter; ++conv_inertia_iter;
    ++rad_inertia_iter;
    return *this;
}

EvolutionIterator EvolutionIterator::operator++(int)
{
    EvolutionIterator result(*this); ++(*this); return result;
}

bool EvolutionIterator::operator==(const EvolutionIterator &rhs)
{
    return mass_iter==rhs.mass_iter;
}

YRECHeader::YRECHeader(std::ifstream &track, const std::string &filename)
{
    const std::string mass_word="Mtot/Msun", age_word="Age(Gyr)",
          radius_word="log(R/Rsun)", log_luminosity_word="log(L/Lsun)",
          env_mass_word="m_envp/M", env_radius_word1="r_envp/M",
          env_radius_word2="r_envp/R", Irad_word="I_rad", Iconv_word="I_env";
    char word[max_line_length+1];
    char line_characters[max_line_length+1];
    while(track.get()=='#') {
        track.getline(line_characters, max_line_length);
        if(!track.good())
            throw Error::IO(filename, "while reading header.");
        std::istringstream line(line_characters);
        assert(line.good());
        for(int word_index=0; !line.eof(); word_index++) {
            assert(line.good());
            line >> word;
            if(word==mass_word) {
                std::string error_msg="failed to read track mass: ";
                if(!line.good())
                    throw Error::IO(filename, error_msg +
                            (line.eof() ? "end of line before =" :
                             "read error before ="));
                line >> word;
                if(!line.good()) throw Error::IO(filename, error_msg +
                        (line.eof() ? "end of line after =" :
                         "read error at ="));
                line >> track_mass;
                if(!line.good()) throw Error::IO(filename, error_msg +
                        (line.eof() ? "end of line before value" :
                        "error parsing value"));
            }
            if(word==age_word) age_col=word_index;
            else if(word==radius_word) radius_col=word_index;
            else if(word==log_luminosity_word) log_luminosity_col=word_index;
            else if(word==env_mass_word)
                envelope_mass_col=word_index;
            else if(word==env_radius_word1 || word==env_radius_word2)
                rad_conv_boundary_col=word_index;
            else if(word==Irad_word) rad_inertia_col=word_index;
            else if(word==Iconv_word) conv_inertia_col=word_index;
        }
    }
    track.unget();
}

void YRECEvolution::read_model_file(const std::string &filename)
{
    std::cerr << "Reading: " << filename << std::endl;
    std::ifstream file(filename.c_str());
    YRECHeader header(file, filename);
    mass_list.push_back(header.get_mass());
    int required_columns=std::max(header.get_age_col(),
            header.get_radius_col());
    required_columns=std::max(required_columns,
            header.get_log_luminosity_col());
    required_columns=std::max(required_columns,
            header.get_envelope_mass_col());
    required_columns=std::max(required_columns,
            header.get_core_boundary_col());
    required_columns=std::max(required_columns,
            header.get_rad_inertia_col());
    required_columns=std::max(required_columns,
            header.get_conv_inertia_col());
    char line_characters[max_line_length+1];
    std::list<double> track_ages, track_radii, track_luminosities,
        track_rad_masses, track_core_boundaries, track_conv_inertias,
        track_rad_inertias;
    double inertia_norm=AstroConst::solar_mass*std::pow(
            AstroConst::solar_radius, 2)*1e7;
    for(int line_number=0; !file.eof(); line_number++) {
        std::cerr << "Reading line " << line_number << "\r";
        std::cerr.flush();
        std::ostringstream error_message;
        error_message << "while reading data line " << line_number;
        if(!file.good()) throw Error::IO(filename, error_message.str());
        file.getline(line_characters, max_line_length);
        if(file.gcount()==0) continue;
        std::istringstream line(line_characters);
        int column=0;
        for(; !line.eof(); column++) {
            double value;
            line >> value;
            if(column==header.get_age_col()) track_ages.push_back(value);
            else if(column==header.get_radius_col())
                track_radii.push_back(std::pow(10.0, value));
            else if(column==header.get_log_luminosity_col())
                track_luminosities.push_back(std::pow(10.0, value));
            else if(column==header.get_envelope_mass_col())
                track_rad_masses.push_back(value*header.get_mass());
            else if(column==header.get_core_boundary_col())
                track_core_boundaries.push_back(value*track_radii.back());
            else if(column==header.get_rad_inertia_col())
                track_rad_inertias.push_back(value/inertia_norm);
            else if(column==header.get_conv_inertia_col())
                track_conv_inertias.push_back(value/inertia_norm);
        }
        if(column<=required_columns)
            throw Error::IO(filename, error_message.str());
    }
    ages.push_back(list_to_valarray(track_ages));
    radii.push_back(list_to_valarray(track_radii));
    luminosities.push_back(list_to_valarray(track_luminosities));
    rad_masses.push_back(list_to_valarray(track_rad_masses));
    core_boundaries.push_back(list_to_valarray(track_core_boundaries));
    rad_inertias.push_back(list_to_valarray(track_rad_inertias));
    conv_inertias.push_back(list_to_valarray(track_conv_inertias));
}

EvolutionIterator YRECEvolution::begin()
{
    EvolutionIterator result;
    result.mass_iter=mass_list.begin();
    result.age_iter=ages.begin();
    result.radius_iter=radii.begin();
    result.luminosity_iter=luminosities.begin();
    result.rad_mass_iter=rad_masses.begin();
    result.core_boundary_iter=core_boundaries.begin();
    result.conv_inertia_iter=conv_inertias.begin();
    result.rad_inertia_iter=rad_inertias.begin();
    return result;
}

EvolutionIterator YRECEvolution::end()
{
    EvolutionIterator result;
    result.mass_iter=mass_list.end();
    result.age_iter=ages.end();
    result.radius_iter=radii.end();
    result.luminosity_iter=luminosities.end();
    result.rad_mass_iter=rad_masses.end();
    result.core_boundary_iter=core_boundaries.end();
    result.conv_inertia_iter=conv_inertias.end();
    result.rad_inertia_iter=rad_inertias.end();
    return result;
}

void YRECEvolution::move(EvolutionIterator &dest, EvolutionIterator &source)
{
    mass_list.splice(dest.mass_iter, mass_list, source.mass_iter);
    ages.splice(dest.age_iter, ages, source.age_iter);
    radii.splice(dest.radius_iter, radii, source.radius_iter);
    luminosities.splice(dest.luminosity_iter, luminosities,
            source.luminosity_iter);
    rad_masses.splice(dest.rad_mass_iter, rad_masses, source.rad_mass_iter);
    core_boundaries.splice(dest.core_boundary_iter, core_boundaries,
            source.core_boundary_iter);
    conv_inertias.splice(dest.conv_inertia_iter, conv_inertias,
            source.conv_inertia_iter);
    rad_inertias.splice(dest.rad_inertia_iter, rad_inertias,
            source.rad_inertia_iter);
}

void YRECEvolution::sort_masses()
{
    EvolutionIterator iter=begin(), stop_iter=end();
    double largest_sorted=*iter.mass_iter;
    while(iter!=stop_iter) {
        while(*iter.mass_iter>=largest_sorted && iter!=stop_iter) {
            largest_sorted=*iter.mass_iter;
            ++iter;
        }
        if(iter==stop_iter) break;
        EvolutionIterator dest=begin();
        while(*(dest.mass_iter)<=*iter.mass_iter) {++dest;}
        EvolutionIterator source=iter++;
        move(dest, source);
    }
}

YRECEvolution::YRECEvolution(const std::string &model_directory,
                             double smooth_radius,
                             double smooth_conv_inertia,
                             double smooth_rad_inertia,
                             double smooth_rad_mass,
                             double smooth_core_env_boundary,
                             int radius_nodes,
                             int conv_inertia_nodes,
                             int rad_inertia_nodes,
                             int rad_mass_nodes,
                             int core_env_boundary_nodes)
{
    DIR *dirstream=opendir(model_directory.c_str());
    std::string join;
    if(model_directory[model_directory.size()-1]=='/') join="";
    else join="/";
    if(dirstream==NULL) throw Error::PathNotFound(
        "in YRECEvolution constructor.", model_directory);
    struct dirent *entry;
    while((entry=readdir(dirstream))) {
        std::string fname(entry->d_name);
        if(fname[0]!='.' && fname.substr(fname.size()-6)==".track")
            read_model_file(model_directory+join+entry->d_name);
    }
    if(closedir(dirstream)) throw Error::Runtime(
        "Failed to close directory stream tied to "+model_directory+
        " in YRECEvolution constructor.");
    sort_masses();
    std::valarray<double> masses = list_to_valarray(mass_list);
    interpolate_from(masses,
                     ages,
                     radii,
                     conv_inertias,
                     rad_inertias,
                     rad_masses,
                     core_boundaries,
                     smooth_radius,
                     smooth_conv_inertia,
                     smooth_rad_inertia,
                     smooth_rad_mass,
                     smooth_core_env_boundary,
                     radius_nodes,
                     conv_inertia_nodes,
                     rad_inertia_nodes,
                     rad_mass_nodes,
                     core_env_boundary_nodes,
                     luminosities,
                     NaN,
                     0);
}