<commit_before>//=============================================================================================================
/**
* @file     main.cpp
* @author   Ruben Dörfel <ruben.doerfel@tu-ilmenau.de>;
* @version  dev
* @date     January, 2020
*
* @section  LICENSE
*
* Copyright (C) 2020, Ruben Dörfel. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief     Example for cHPI fitting on raw data with SSP. The result is written to a .txt file for comparison with MaxFilter's .pos file.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <vector>
#include <math.h>

#include <fiff/fiff.h>
#include <fiff/fiff_info.h>
#include <fiff/fiff_dig_point_set.h>
#include <fiff/fiff_cov.h>
#include <inverse/hpiFit/hpifit.h>
#include <inverse/hpiFit/hpifitdata.h>
#include <utils/ioutils.h>
#include <utils/generics/applicationlogger.h>
#include <fwd/fwd_coil_set.h>
//*************************************************************************************************************
//=============================================================================================================
// Qt INCLUDES
//=============================================================================================================

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QCommandLineParser>
#include <QDebug>
#include <QGenericMatrix>
#include <QQuaternion>
#include <QElapsedTimer>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace INVERSELIB;
using namespace FIFFLIB;
using namespace Eigen;

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

//=============================================================================================================
/**
 * The function main marks the entry point of the program.
 * By default, main has the storage class extern.
 *
 * @param [in] argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started.
 * @param [in] argv (argument vector) is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started.
 * @return the value that was set to exit() (which is 0 if exit() is called via quit()).
 */

void write_pos(const float time, QSharedPointer<FIFFLIB::FiffInfo> info, Eigen::MatrixXd& position, const QVector<double>& vGoF){
    // Write quaternions and time in position matrix. Format is the same like MaxFilter's .pos files.
    QMatrix3x3 rot;

    for(int ir = 0; ir < 3; ir++) {
        for(int ic = 0; ic < 3; ic++) {
            rot(ir,ic) = info->dev_head_t.trans(ir,ic);
        }
    }
    double GoF = std::accumulate(vGoF.begin(), vGoF.end(), .0) / vGoF.size();
    QQuaternion quatHPI = QQuaternion::fromRotationMatrix(rot);

    //qDebug() << "quatHPI.x() " << "quatHPI.y() " << "quatHPI.y() " << "trans x " << "trans y " << "trans z " << std::endl;
    //qDebug() << quatHPI.x() << quatHPI.y() << quatHPI.z() << info->dev_head_t.trans(0,3) << info->dev_head_t.trans(1,3) << info->dev_head_t.trans(2,3) << std::endl;

    position.conservativeResize(position.rows()+1, 10);
    position(position.rows()-1,0) = time;
    position(position.rows()-1,1) = quatHPI.x();
    position(position.rows()-1,2) = quatHPI.y();
    position(position.rows()-1,3) = quatHPI.z();
    position(position.rows()-1,4) = info->dev_head_t.trans(0,3);
    position(position.rows()-1,5) = info->dev_head_t.trans(1,3);
    position(position.rows()-1,6) = info->dev_head_t.trans(2,3);
    position(position.rows()-1,7) = 1-GoF;
    position(position.rows()-1,8) = GoF;
    position(position.rows()-1,9) = 0;
}

int main(int argc, char *argv[])
{
    qInstallMessageHandler(UTILSLIB::ApplicationLogger::customLogWriter);
    QElapsedTimer timer;
    QCoreApplication a(argc, argv);

    // Command Line Parser
    QCommandLineParser parser;
    parser.setApplicationDescription("hpiFit Example");
    parser.addHelpOption();
    qInfo() << "Please download the mne-cpp-test-data folder from Github (mne-tools) into mne-cpp/bin.";
    QCommandLineOption inputOption("fileIn", "The input file <in>.", "in", QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/MEG/sample/test_hpiFit_raw.fif");

    parser.addOption(inputOption);

    parser.process(a);

    // Init data loading and writing
    QFile t_fileIn(parser.value(inputOption));

    FiffRawData raw(t_fileIn);
    QSharedPointer<FiffInfo> pFiffInfo = QSharedPointer<FIFFLIB::FiffInfo>(new FiffInfo(raw.info));

    // Set up the reading parameters
    RowVectorXi picks = pFiffInfo->pick_types(true, false, false);

    MatrixXd matData;
    MatrixXd times;

    fiff_int_t from;
    fiff_int_t to;
    fiff_int_t first = raw.first_samp;
    fiff_int_t last = raw.last_samp;

    float dT_sec = 0.1;             // time between hpi fits
    float quantum_sec = 0.2f;       // read and write in 200 ms junks
    fiff_int_t quantum = ceil(quantum_sec*pFiffInfo->sfreq);

    // create time vector that specifies when to fit
//    int N = ceil((last-first)/quantum);
//    RowVectorXf time(N);
//    for(int i = 0; i < N; i++){
//        time(i) = i * dT_sec;
//    }

    // Read Quaternion File
    Eigen::MatrixXd pos;
    qInfo() << "Specify the path to your position file (.txt)";
    UTILSLIB::IOUtils::read_eigen_matrix(pos, QCoreApplication::applicationDirPath() + "/MNE-sample-data/chpi/pos/posMax_data_with_movement_chpi.txt");
    RowVectorXd time = pos.col(0);

    MatrixXd position;       // Position matrix to save quaternions etc.

    // setup informations for HPI fit (VectorView)
    QVector<int> vFreqs {166,154,161,158};
    QVector<double> vGof;
    FiffDigPointSet fittedPointSet;

    // Use SSP + SGM + calibration
    MatrixXd matProjectors = MatrixXd::Identity(pFiffInfo->chs.size(), pFiffInfo->chs.size());

    //Do a copy here because we are going to change the activity flags of the SSP's
    FiffInfo infoTemp = *(pFiffInfo.data());

    //Turn on all SSP
    for(int i = 0; i < infoTemp.projs.size(); ++i) {
        infoTemp.projs[i].active = true;
    }

    //Create the projector for all SSP's on
    infoTemp.make_projector(matProjectors);

    //set columns of matrix to zero depending on bad channels indexes
    for(qint32 j = 0; j < infoTemp.bads.size(); ++j) {
        matProjectors.col(infoTemp.ch_names.indexOf(infoTemp.bads.at(j))).setZero();
    }

    // if debugging files are necessary set bDoDebug = true;
    QString sHPIResourceDir = QCoreApplication::applicationDirPath() + "/HPIFittingDebug";
    bool bDoDebug = true;

    // read and fit
    for(int i = 0; i < time.size(); i++) {
        from = first + time(i)*pFiffInfo->sfreq;
        to = from + quantum;
        if (to > last) {
            to = last;
            qWarning() << "Block size < quantum " << quantum;
        }
        // Reading
        if(!raw.read_raw_segment(matData, times, from, to)) {
            qCritical("error during read_raw_segment");
            return -1;
        }
        qInfo() << "[done]";

        qInfo() << "HPI-Fit...";
        timer.start();
        HPIFit::fitHPI(matData,
                       matProjectors,
                       pFiffInfo->dev_head_t,
                       vFreqs,
                       vGof,
                       fittedPointSet,
                       pFiffInfo,
                       bDoDebug,
                       sHPIResourceDir);
        qInfo() << "The HPI-Fit took" << timer.elapsed() << "milliseconds";
        qInfo() << "[done]";

        write_pos(time(i),pFiffInfo,position,vGof);
    }
    UTILSLIB::IOUtils::write_eigen_matrix(position, QCoreApplication::applicationDirPath() + "/MNE-sample-data/position.txt");
}
<commit_msg>MAINT: apply coding conventions<commit_after>//=============================================================================================================
/**
* @file     main.cpp
* @author   Ruben Dörfel <ruben.doerfel@tu-ilmenau.de>;
* @version  dev
* @date     January, 2020
*
* @section  LICENSE
*
* Copyright (C) 2020, Ruben Dörfel. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief     Example for cHPI fitting on raw data with SSP. The result is written to a .txt file for comparison with MaxFilter's .pos file.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <vector>
#include <math.h>

#include <fiff/fiff.h>
#include <fiff/fiff_info.h>
#include <fiff/fiff_dig_point_set.h>
#include <fiff/fiff_cov.h>

#include <inverse/hpiFit/hpifit.h>
#include <inverse/hpiFit/hpifitdata.h>

#include <utils/ioutils.h>
#include <utils/generics/applicationlogger.h>

#include <fwd/fwd_coil_set.h>

//*************************************************************************************************************
//=============================================================================================================
// Qt INCLUDES
//=============================================================================================================

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QCommandLineParser>
#include <QDebug>
#include <QGenericMatrix>
#include <QQuaternion>
#include <QElapsedTimer>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace INVERSELIB;
using namespace FIFFLIB;
using namespace Eigen;

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

//=============================================================================================================
/**
 * The function main marks the entry point of the program.
 * By default, main has the storage class extern.
 *
 * @param [in] argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started.
 * @param [in] argv (argument vector) is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started.
 * @return the value that was set to exit() (which is 0 if exit() is called via quit()).
 */

void write_pos(const float time, QSharedPointer<FIFFLIB::FiffInfo> info, Eigen::MatrixXd& position, const QVector<double>& vGoF)
{
    // Write quaternions and time in position matrix. Format is the same like MaxFilter's .pos files.
    QMatrix3x3 rot;

    for(int ir = 0; ir < 3; ir++) {
        for(int ic = 0; ic < 3; ic++) {
            rot(ir,ic) = info->dev_head_t.trans(ir,ic);
        }
    }

    double GoF = std::accumulate(vGoF.begin(), vGoF.end(), .0) / vGoF.size();
    QQuaternion quatHPI = QQuaternion::fromRotationMatrix(rot);

    //qDebug() << "quatHPI.x() " << "quatHPI.y() " << "quatHPI.y() " << "trans x " << "trans y " << "trans z " << std::endl;
    //qDebug() << quatHPI.x() << quatHPI.y() << quatHPI.z() << info->dev_head_t.trans(0,3) << info->dev_head_t.trans(1,3) << info->dev_head_t.trans(2,3) << std::endl;

    position.conservativeResize(position.rows()+1, 10);
    position(position.rows()-1,0) = time;
    position(position.rows()-1,1) = quatHPI.x();
    position(position.rows()-1,2) = quatHPI.y();
    position(position.rows()-1,3) = quatHPI.z();
    position(position.rows()-1,4) = info->dev_head_t.trans(0,3);
    position(position.rows()-1,5) = info->dev_head_t.trans(1,3);
    position(position.rows()-1,6) = info->dev_head_t.trans(2,3);
    position(position.rows()-1,7) = 1-GoF;
    position(position.rows()-1,8) = GoF;
    position(position.rows()-1,9) = 0;
}

int main(int argc, char *argv[])
{
    qInstallMessageHandler(UTILSLIB::ApplicationLogger::customLogWriter);
    QElapsedTimer timer;
    QCoreApplication a(argc, argv);

    // Command Line Parser
    QCommandLineParser parser;
    parser.setApplicationDescription("hpiFit Example");
    parser.addHelpOption();
    qInfo() << "Please download the mne-cpp-test-data folder from Github (mne-tools) into mne-cpp/bin.";
    QCommandLineOption inputOption("fileIn", "The input file <in>.", "in", QCoreApplication::applicationDirPath() + "/MNE-sample-data/chpi/raw/data_with_movement_chpi_raw.fif");

    parser.addOption(inputOption);

    parser.process(a);

    // Init data loading and writing
    QFile t_fileIn(parser.value(inputOption));

    FiffRawData raw(t_fileIn);
    QSharedPointer<FiffInfo> pFiffInfo = QSharedPointer<FIFFLIB::FiffInfo>(new FiffInfo(raw.info));

    // Set up the reading parameters
    RowVectorXi picks = pFiffInfo->pick_types(true, false, false);

    MatrixXd matData;
    MatrixXd times;

    fiff_int_t from;
    fiff_int_t to;
    fiff_int_t first = raw.first_samp;
    fiff_int_t last = raw.last_samp;

    float dT_sec = 0.1;             // time between hpi fits
    float quantum_sec = 0.2f;       // read and write in 200 ms junks
    fiff_int_t quantum = ceil(quantum_sec*pFiffInfo->sfreq);

    // create time vector that specifies when to fit
//    int N = ceil((last-first)/quantum);
//    RowVectorXf time(N);
//    for(int i = 0; i < N; i++){
//        time(i) = i * dT_sec;
//    }

    // Read Quaternion File
    Eigen::MatrixXd pos;
    qInfo() << "Specify the path to your position file (.txt)";
    UTILSLIB::IOUtils::read_eigen_matrix(pos, QCoreApplication::applicationDirPath() + "/MNE-sample-data/chpi/pos/posMax_data_with_movement_chpi.txt");
    RowVectorXd time = pos.col(0);

    MatrixXd position;       // Position matrix to save quaternions etc.

    // setup informations for HPI fit (VectorView)
    QVector<int> vFreqs {166,154,161,158};
    QVector<double> vGof;
    FiffDigPointSet fittedPointSet;

    // Use SSP + SGM + calibration
    MatrixXd matProjectors = MatrixXd::Identity(pFiffInfo->chs.size(), pFiffInfo->chs.size());

    //Do a copy here because we are going to change the activity flags of the SSP's
    FiffInfo infoTemp = *(pFiffInfo.data());

    //Turn on all SSP
    for(int i = 0; i < infoTemp.projs.size(); ++i) {
        infoTemp.projs[i].active = true;
    }

    //Create the projector for all SSP's on
    infoTemp.make_projector(matProjectors);

    //set columns of matrix to zero depending on bad channels indexes
    for(qint32 j = 0; j < infoTemp.bads.size(); ++j) {
        matProjectors.col(infoTemp.ch_names.indexOf(infoTemp.bads.at(j))).setZero();
    }

    // if debugging files are necessary set bDoDebug = true;
    QString sHPIResourceDir = QCoreApplication::applicationDirPath() + "/HPIFittingDebug";
    bool bDoDebug = false;

    // read and fit
    for(int i = 0; i < time.size(); i++) {
        from = first + time(i)*pFiffInfo->sfreq;
        to = from + quantum;
        if (to > last) {
            to = last;
            qWarning() << "Block size < quantum " << quantum;
        }
        // Reading
        if(!raw.read_raw_segment(matData, times, from, to)) {
            qCritical("error during read_raw_segment");
            return -1;
        }
        qInfo() << "[done]";

        qInfo() << "HPI-Fit...";
        timer.start();
        HPIFit::fitHPI(matData,
                       matProjectors,
                       pFiffInfo->dev_head_t,
                       vFreqs,
                       vGof,
                       fittedPointSet,
                       pFiffInfo,
                       bDoDebug,
                       sHPIResourceDir);
        qInfo() << "The HPI-Fit took" << timer.elapsed() << "milliseconds";
        qInfo() << "[done]";

        write_pos(time(i),pFiffInfo,position,vGof);
    }
    UTILSLIB::IOUtils::write_eigen_matrix(position, QCoreApplication::applicationDirPath() + "/MNE-sample-data/position.txt");
}
<|endoftext|>


<commit_before>#include "PorousMedia.h"

template <class T>
const T& min ( const T& a, const T& b )
{
  return (a<b)?a:b;
}

template<>
Parameters valid_params<PorousMedia>()
{
  Parameters params;
  params.set<Real>("thermal_conductivity")=1.0;
  params.set<Real>("thermal_conductivity_fluid")=0.3707; //[W/(m.K)]
  params.set<Real>("thermal_conductivity_solid")=80.0;   //[W/(m.K)]
  params.set<Real>("specific_heat")=1.0;
  params.set<Real>("specific_heat_fluid")=5195;  //[J/(kg.K)]
  params.set<Real>("specific_heat_solid")=1725;
  params.set<Real>("neutron_diffusion_coefficient")=1.0;
  params.set<Real>("neutron_absorption_xs")=1.0;
  params.set<Real>("neutron_fission_xs")=1.0;
  params.set<Real>("neutron_per_fission")=1.0;
  params.set<Real>("neutron_velocity")=1.0;
  params.set<Real>("neutron_per_power")=1.0;
  params.set<Real>("heat_xfer_coefficient")=1.0;
  params.set<Real>("temp0")=1.0;
  params.set<Real>("k0")=1.0;
  params.set<Real>("k1")=0.0;
  params.set<Real>("d0")=1.0;
  params.set<Real>("d1")=0.0;
  params.set<Real>("siga0")=1.0;
  params.set<Real>("siga1")=0.0;
  params.set<Real>("sigf0")=1.0;
  params.set<Real>("sigf1")=0.0;
  params.set<Real>("fluid_resistance_coefficient")=1.0;
  params.set<Real>("gas_constant")=1.0;
  params.set<Real>("porosity")=0.5;
  // parameter of pebble-bed reactor
  params.set<Real>("vessel_cross_section")=1.0;
  params.set<Real>("pebble_diameter")=0.06;
  params.set<bool>("kta_standard")=false;
  params.set<bool>("non_dim_flag")=false;

  return params;
}

void
PorousMedia::computeProperties()
{
  for(unsigned int qp=0; qp<_qrule->n_points(); qp++)
  {
    Real  temp_diff = _solid_temp[qp]-_my_temp0;

    _thermal_conductivity[qp]          = _my_thermal_conductivity;
    _thermal_conductivity_fluid[qp]    = _my_thermal_conductivity_fluid;
    _thermal_conductivity_solid[qp]    = _my_thermal_conductivity_solid;
    _specific_heat[qp]                 = _my_specific_heat;
    _specific_heat_fluid[qp]           = _my_specific_heat_fluid;
    _specific_heat_solid[qp]           = _my_specific_heat_solid;
    _heat_xfer_coefficient[qp]         = _my_heat_xfer_coefficient;
    _fluid_resistance_coefficient[qp]  = _my_fluid_resistance_coefficient;
    _gas_constant[qp]                  = _my_gas_constant;
    _porosity[qp]                      = _my_porosity;
    _neutron_diffusion_coefficient[qp] = _my_d0+_my_d1*temp_diff;
    _neutron_absorption_xs[qp]         = _my_siga0+_my_siga1*temp_diff;
    _neutron_fission_xs[qp]            = _my_sigf0+_my_sigf1*temp_diff;
    _neutron_per_power[qp]             = _my_neutron_per_power;
    _neutron_per_fission[qp]           = _my_neutron_per_fission;
    _neutron_velocity[qp]              = _my_neutron_velocity;

//KTA standard

    if( _my_kta_standard )
    {
      /*
      //porosity
      static Real porosity_inf = 0.41;
      static Real porosity_max = 0.9;

      //dimension of the pebble bed
      static Real r_max = +0.75;
      static Real r_min = +0.07;
      static Real z_max = +0.5;
      static Real z_min = -0.5;

      Real dist_r = min( _q_point[qp](0) - r_min , r_max - _q_point[qp](0) );
      Real dist_z = min( _q_point[qp](1) - z_min , z_max - _q_point[qp](1) );

      Real C = 100;
      Real Y = min(dist_r,dist_z);

      Real _porosity[qp] = porosity_inf * (1 + (porosity_max - porosity_inf)/porosity_inf * exp(-C*Y));
      */

      //fluid thermal conductivity
      Real pre_in_bar = 1.0;
      if( _has_pre)
        pre_in_bar = _pre[qp]/1e5;

      _thermal_conductivity_fluid[qp] = 2.682e-3*(1+1.123e-3*pre_in_bar)*pow((_fluid_temp[qp]+_solid_temp[qp])/2,0.71)*(1-2e-4*pre_in_bar);

      //Solid
      Real temp_in_c = _solid_temp[qp]-273.5;
      Real kappa_pebble = 186.021-39.5408e-2*temp_in_c+4.8852e-4*pow(temp_in_c,2)-2.91e-7*pow(temp_in_c,3)+6.6e-11*pow(temp_in_c,4);
      Real b = 1.25*pow((1-_porosity[qp])/_porosity[qp],1.111);
      static Real sigma = 5.67e-8;
      static Real emissivity = 0.8;

      Real lambda = kappa_pebble/(4*sigma*pow(_solid_temp[qp],3)*_my_pebble_diameter);

      //void radiation+solid conduction
      Real a1 = (1-pow(1-_porosity[qp],0.5))*_porosity[qp];
      Real a2 = pow(1-_porosity[qp],0.5)/(2/emissivity-1);
      Real a3 = (b+1)/b;
      Real a4 = 1/(1+1/((2/emissivity-1)*lambda));
      Real lambda_r = 4*sigma*pow(_solid_temp[qp],3)*_my_pebble_diameter*(a1+a2*a3*a4);

      //gas conduction+solid conduction
      Real b1 = pow(1-_porosity[qp],0.5);
      Real ratio_lambda = _thermal_conductivity_fluid[qp]/kappa_pebble;

      Real b2 = 2*b1/(1-ratio_lambda*b);
      Real b3 = (1-ratio_lambda)*b/pow(1-ratio_lambda*b,2)*log(1/(ratio_lambda*b));
      Real b4 = (b+1)/2;
      Real b5 = (b-1)/(1-ratio_lambda*b);
      Real lambda_g = (1-b1+b2*(b3-b4-b5))*_thermal_conductivity_fluid[qp];

      //contact conduction+solid conduction
      static Real s  = 1;
      static Real sf = 1;
      Real na = 1/(pow(_my_pebble_diameter,2));
      Real nl = 1/(_my_pebble_diameter);
      static Real poisson_ratio_pebble = 0.136;
      static Real young_modules_pebble = 9e9;
      Real f = 101325.0*sf/na;
      if( _has_pre )
        f = _pre[qp]*sf/na;

      Real c1 = 3*(1-poisson_ratio_pebble*poisson_ratio_pebble)*f*0.03/4/young_modules_pebble;
      Real c2 = pow(c1,0.333);
      Real lambda_c = c2*na/nl/(0.531*s)*kappa_pebble;
      _thermal_conductivity_solid[qp] = lambda_r+lambda_g+lambda_c;

      //Fluid
      Real density = 101325/(_my_gas_constant*_fluid_temp[qp]);
      if( _has_pre)
        density = _pre[qp]/(_my_gas_constant*_fluid_temp[qp]);
      Real mom = 0;
      if( _has_xmom)
      {
        mom    = _xmom[qp]*_xmom[qp];
        if( _dim >=2 )
          mom +=_ymom[qp]*_ymom[qp];
        if( _dim == 3)
          mom +=_zmom[qp]*_zmom[qp];
        mom = pow(mom,0.5);
      }
      if( _has_rmom)
      {
        mom    = _rmom[qp]*_rmom[qp];
        if( _dim >=2 )
          mom +=_zmom[qp]*_zmom[qp];
        if( _dim == 3)
          mom +=_thetamom[qp]*_thetamom[qp];
        mom = pow(mom,0.5);
      }
      mom = mom*_porosity[qp];

      Real dyn_viscosity = 3.674e-7*pow((_fluid_temp[qp]+_solid_temp[qp])/2,0.7);
      Real reynolds      = mom*_my_pebble_diameter/dyn_viscosity;

      Real prandtl       = _specific_heat_fluid[qp]*dyn_viscosity/_thermal_conductivity_fluid[qp];

      Real nusselt = 2;
      nusselt = (7-10*_porosity[qp]+5*pow(_porosity[qp],2))*(1+0.7*pow(reynolds,0.2)*pow(prandtl,0.333))
                     +(1.33-2.4*_porosity[qp]+1.2*pow(_porosity[qp],2))*pow(reynolds,0.7)*pow(prandtl,0.333);

      Real area = 6*(1-_porosity[qp])/_my_pebble_diameter;

      _heat_xfer_coefficient[qp] = area*nusselt*_thermal_conductivity_fluid[qp]/_my_pebble_diameter;

      if( _has_rmom || _has_xmom )
      {
        Real reynolds_over_1meps = reynolds/(1-_porosity[qp]);

        Real w1 = 320*dyn_viscosity*(1-_porosity[qp])/pow(_my_pebble_diameter,2)/density/2;
        Real w2 = 0;
        if( mom >0)
          w2 = 6*mom/_my_pebble_diameter/2/density/pow(reynolds_over_1meps,0.1);
        _fluid_resistance_coefficient[qp] = w1+w2;
        //std::cout <<"w: " << _fluid_resistance_coefficient[qp] << " " << reynolds_over_1meps<< std::endl;

        /*
        _fluid_resistance_coefficient[qp] =163*dyn_viscosity*pow(1-_porosity[qp],2)/pow(_my_pebble_diameter,2)/density/pow(_porosity[qp],2);
        if( reynolds_over_1meps > 1 )
        {
          Real psi = 320/reynolds_over_1meps+6/pow(reynolds_over_1meps,0.1);
          _fluid_resistance_coefficient[qp] = psi*(1-_porosity[qp])/pow(_porosity[qp],3)/_my_pebble_diameter/2/density*mom;
        }
        */
      }
    }
  }
}
<commit_msg>trivial<commit_after>#include "PorousMedia.h"

template <class T>
const T& min ( const T& a, const T& b )
{
  return (a<b)?a:b;
}

template<>
Parameters valid_params<PorousMedia>()
{
  Parameters params;
  params.set<Real>("thermal_conductivity")=1.0;
  params.set<Real>("thermal_conductivity_fluid")=0.3707; //[W/(m.K)]
  params.set<Real>("thermal_conductivity_solid")=80.0;   //[W/(m.K)]
  params.set<Real>("specific_heat")=1.0;
  params.set<Real>("specific_heat_fluid")=5195;  //[J/(kg.K)]
  params.set<Real>("specific_heat_solid")=1725;
  params.set<Real>("neutron_diffusion_coefficient")=1.0;
  params.set<Real>("neutron_absorption_xs")=1.0;
  params.set<Real>("neutron_fission_xs")=1.0;
  params.set<Real>("neutron_per_fission")=1.0;
  params.set<Real>("neutron_velocity")=1.0;
  params.set<Real>("neutron_per_power")=1.0;
  params.set<Real>("heat_xfer_coefficient")=1.0;
  params.set<Real>("temp0")=1.0;
  params.set<Real>("k0")=1.0;
  params.set<Real>("k1")=0.0;
  params.set<Real>("d0")=1.0;
  params.set<Real>("d1")=0.0;
  params.set<Real>("siga0")=1.0;
  params.set<Real>("siga1")=0.0;
  params.set<Real>("sigf0")=1.0;
  params.set<Real>("sigf1")=0.0;
  params.set<Real>("fluid_resistance_coefficient")=1.0;
  params.set<Real>("gas_constant")=1.0;
  params.set<Real>("porosity")=0.5;
  // parameter of pebble-bed reactor
  params.set<Real>("vessel_cross_section")=1.0;
  params.set<Real>("pebble_diameter")=0.06;
  params.set<bool>("kta_standard")=false;
  params.set<bool>("non_dim_flag")=false;

  return params;
}

void
PorousMedia::computeProperties()
{
  for(unsigned int qp=0; qp<_qrule->n_points(); qp++)
  {
    Real  temp_diff = _solid_temp[qp]-_my_temp0;

    _thermal_conductivity[qp]          = _my_thermal_conductivity;
    _thermal_conductivity_fluid[qp]    = _my_thermal_conductivity_fluid;
    _thermal_conductivity_solid[qp]    = _my_thermal_conductivity_solid;
    _specific_heat[qp]                 = _my_specific_heat;
    _specific_heat_fluid[qp]           = _my_specific_heat_fluid;
    _specific_heat_solid[qp]           = _my_specific_heat_solid;
    _heat_xfer_coefficient[qp]         = _my_heat_xfer_coefficient;
    _fluid_resistance_coefficient[qp]  = _my_fluid_resistance_coefficient;
    _gas_constant[qp]                  = _my_gas_constant;
    _porosity[qp]                      = _my_porosity;
    _neutron_diffusion_coefficient[qp] = _my_d0+_my_d1*temp_diff;
    _neutron_absorption_xs[qp]         = _my_siga0+_my_siga1*temp_diff;
    _neutron_fission_xs[qp]            = _my_sigf0+_my_sigf1*temp_diff;
    _neutron_per_power[qp]             = _my_neutron_per_power;
    _neutron_per_fission[qp]           = _my_neutron_per_fission;
    _neutron_velocity[qp]              = _my_neutron_velocity;

//KTA standard

    if( _my_kta_standard )
    {
      //porosity
      /*
      static Real porosity_inf = 0.41;
      static Real porosity_max = 0.9;

      //dimension of the pebble bed
      static Real r_max = +0.75;
      static Real r_min = +0.07;
      static Real z_max = +0.5;
      static Real z_min = -0.5;

      Real dist_r = min( _q_point[qp](0) - r_min , r_max - _q_point[qp](0) );
      Real dist_z = min( _q_point[qp](1) - z_min , z_max - _q_point[qp](1) );

      Real C = 100;
      Real Y = min(dist_r,dist_z);

      Real _porosity[qp] = porosity_inf * (1 + (porosity_max - porosity_inf)/porosity_inf * exp(-C*Y));
      */

      //fluid thermal conductivity
      Real pre_in_bar = 1.0;
      if( _has_pre)
        pre_in_bar = _pre[qp]/1e5;

      _thermal_conductivity_fluid[qp] = 2.682e-3*(1+1.123e-3*pre_in_bar)*pow((_fluid_temp[qp]+_solid_temp[qp])/2,0.71)*(1-2e-4*pre_in_bar);

      //Solid
      Real temp_in_c = _solid_temp[qp]-273.5;
      Real kappa_pebble = 186.021-39.5408e-2*temp_in_c+4.8852e-4*pow(temp_in_c,2)-2.91e-7*pow(temp_in_c,3)+6.6e-11*pow(temp_in_c,4);
      Real b = 1.25*pow((1-_porosity[qp])/_porosity[qp],1.111);
      static Real sigma = 5.67e-8;
      static Real emissivity = 0.8;

      Real lambda = kappa_pebble/(4*sigma*pow(_solid_temp[qp],3)*_my_pebble_diameter);

      //void radiation+solid conduction
      Real a1 = (1-pow(1-_porosity[qp],0.5))*_porosity[qp];
      Real a2 = pow(1-_porosity[qp],0.5)/(2/emissivity-1);
      Real a3 = (b+1)/b;
      Real a4 = 1/(1+1/((2/emissivity-1)*lambda));
      Real lambda_r = 4*sigma*pow(_solid_temp[qp],3)*_my_pebble_diameter*(a1+a2*a3*a4);

      //gas conduction+solid conduction
      Real b1 = pow(1-_porosity[qp],0.5);
      Real ratio_lambda = _thermal_conductivity_fluid[qp]/kappa_pebble;

      Real b2 = 2*b1/(1-ratio_lambda*b);
      Real b3 = (1-ratio_lambda)*b/pow(1-ratio_lambda*b,2)*log(1/(ratio_lambda*b));
      Real b4 = (b+1)/2;
      Real b5 = (b-1)/(1-ratio_lambda*b);
      Real lambda_g = (1-b1+b2*(b3-b4-b5))*_thermal_conductivity_fluid[qp];

      //contact conduction+solid conduction
      static Real s  = 1;
      static Real sf = 1;
      Real na = 1/(pow(_my_pebble_diameter,2));
      Real nl = 1/(_my_pebble_diameter);
      static Real poisson_ratio_pebble = 0.136;
      static Real young_modules_pebble = 9e9;
      Real f = 101325.0*sf/na;
      if( _has_pre )
        f = _pre[qp]*sf/na;

      Real c1 = 3*(1-poisson_ratio_pebble*poisson_ratio_pebble)*f*0.03/4/young_modules_pebble;
      Real c2 = pow(c1,0.333);
      Real lambda_c = c2*na/nl/(0.531*s)*kappa_pebble;
      _thermal_conductivity_solid[qp] = lambda_r+lambda_g+lambda_c;

      //Fluid
      Real density = 101325/(_my_gas_constant*_fluid_temp[qp]);
      if( _has_pre)
        density = _pre[qp]/(_my_gas_constant*_fluid_temp[qp]);
      Real mom = 0;
      if( _has_xmom)
      {
        mom    = _xmom[qp]*_xmom[qp];
        if( _dim >=2 )
          mom +=_ymom[qp]*_ymom[qp];
        if( _dim == 3)
          mom +=_zmom[qp]*_zmom[qp];
        mom = pow(mom,0.5);
      }
      if( _has_rmom)
      {
        mom    = _rmom[qp]*_rmom[qp];
        if( _dim >=2 )
          mom +=_zmom[qp]*_zmom[qp];
        if( _dim == 3)
          mom +=_thetamom[qp]*_thetamom[qp];
        mom = pow(mom,0.5);
      }
      mom = mom*_porosity[qp];

      Real dyn_viscosity = 3.674e-7*pow((_fluid_temp[qp]+_solid_temp[qp])/2,0.7);
      Real reynolds      = mom*_my_pebble_diameter/dyn_viscosity;

      Real prandtl       = _specific_heat_fluid[qp]*dyn_viscosity/_thermal_conductivity_fluid[qp];

      Real nusselt = 2;
      nusselt = (7-10*_porosity[qp]+5*pow(_porosity[qp],2))*(1+0.7*pow(reynolds,0.2)*pow(prandtl,0.333))
                     +(1.33-2.4*_porosity[qp]+1.2*pow(_porosity[qp],2))*pow(reynolds,0.7)*pow(prandtl,0.333);

      Real area = 6*(1-_porosity[qp])/_my_pebble_diameter;

      _heat_xfer_coefficient[qp] = area*nusselt*_thermal_conductivity_fluid[qp]/_my_pebble_diameter;

      if( _has_rmom || _has_xmom )
      {
        Real reynolds_over_1meps = reynolds/(1-_porosity[qp]);

        Real w1 = 320*dyn_viscosity*(1-_porosity[qp])/pow(_my_pebble_diameter,2)/density/2;
        Real w2 = 0;
        if( mom >0)
          w2 = 6*mom/_my_pebble_diameter/2/density/pow(reynolds_over_1meps,0.1);
        _fluid_resistance_coefficient[qp] = w1+w2;
        //std::cout <<"w: " << _fluid_resistance_coefficient[qp] << " " << reynolds_over_1meps<< std::endl;

        /*
        _fluid_resistance_coefficient[qp] =163*dyn_viscosity*pow(1-_porosity[qp],2)/pow(_my_pebble_diameter,2)/density/pow(_porosity[qp],2);
        if( reynolds_over_1meps > 1 )
        {
          Real psi = 320/reynolds_over_1meps+6/pow(reynolds_over_1meps,0.1);
          _fluid_resistance_coefficient[qp] = psi*(1-_porosity[qp])/pow(_porosity[qp],3)/_my_pebble_diameter/2/density*mom;
        }
        */
      }
    }
  }
}
<|endoftext|>


<commit_before>#include "AppClass.h"
void AppClass::InitWindow(String a_sWindowName)
{
	super::InitWindow("PokemanSafari"); // Window Name

	// Set the clear color based on Microsoft's CornflowerBlue (default in XNA)
	//if this line is in Init Application it will depend on the .cfg file, if it
	//is on the InitVariables it will always force it regardless of the .cfg
	m_v4ClearColor = vector4(0.4f, 0.6f, 0.9f, 0.0f);
}

void AppClass::InitVariables(void)
{
	m_pScoreMngr = ScoreManager::GetInstance();
	m_pBOMngr = MyBOManager::GetInstance();
	m_pEntityMngr = MyEntityManager::GetInstance();

	m_pCameraMngr->SetFPS(true);
	//Create the rail camera
	railCamIndex = m_pCameraMngr->AddCamera(vector3(0.0f, 0.0f, 5.0f),
		                     vector3(0.0f, 0.0f, 0.0f),
		                     vector3(0.0f, 1.0f, 0.0f));

	m_pLightMngr->AddLight(vector3(5.5f,10.0f,10.0f));

	//Fill Paths
	FillPath();

	//Initialize positions
	m_v3PosPokeCube = vector3(0.0f, 0.0f, 0.0f);
	m_v3PosEnv = vector3(0.0f, -20.0f, 0.0f);
	m_v3PosPika = vector3(-5.0f, -20.0f, -7.0f);

	//Load Models
	m_pMeshMngr->LoadModel("PokemanSafari\\environment.obj", "Environment");
	m_pMeshMngr->LoadModel("PokemanSafari\\pokecube.obj", "Pokecube");
	m_pMeshMngr->LoadModel("PokemanSafari\\pikachu.obj", "Pikachu");

	m_pEntityMngr->AddEntity("Pokecube", PJ_POKECUBE);
	//p_pokecube_01 = new Projectile(PJ_POKECUBE, "Pokecube");
	p_pokecube_01 = (Projectile*)m_pEntityMngr->GetEntity("Pokecube");
	p_pokecube_01->SetPosition(m_v3PosPokeCube);
	p_pokecube_01->SetVelocity(vector3(0.002f, 0.0f, 0.0f));
    p_pokecube_01->SetAcceleration(vector3(0.0f, -0.002f, 0.0f));
	p_pokecube_01->SetMass(1.2f);
	//ThrowPokecube();

	c_player = new Character(CT_PLAYER, "player", 20, playerPath);

	m_pEntityMngr->AddEntity("Pikachu", CT_POKEMAN, 20, playerPath);
	//c_pika_01 = new Character(CT_POKEMAN, "Pikachu", 20, playerPath);
	c_pika_01 = (Character*)m_pEntityMngr->GetEntity("Pikachu");
	c_pika_01->SetPosition(m_v3PosPika);

}

void AppClass::ThrowPokecube()
{
	//Check if already in the air
	if (p_pokecube_01->IsAlive())
		return;

	p_pokecube_01->SetAlive(true);
	matrix4 camView = glm::transpose(m_pCameraMngr->GetViewMatrix(-1));
	vector3 pos = m_pCameraMngr->GetPosition(-1);
	pos[1] -= 0.5f; //don't go 'through' the camera
	p_pokecube_01->SetPosition(pos);
	//Set the velocity in cam z direction
	vector3 dir = -1.0f * vector3(camView[2][0], camView[2][1], camView[2][2]);
	//TODO put this inside Projectile?
	float velocityFactor = 0.5f;
	p_pokecube_01->SetVelocity(vector3(dir[0] * velocityFactor,
		                               dir[1] * velocityFactor,
									   dir[2] * velocityFactor));
}

void AppClass::UpdatePlayerCamera()
{
	//setting the camera's position to the players location
	c_player->UpdateLocation();

	if (camSelect)
	{
		//Using Rail Camera

		//lookDir = vector3(m_pCameraMngr->GetViewMatrix(-1)[0][0], m_pCameraMngr->GetViewMatrix(-1)[1][1], m_pCameraMngr->GetViewMatrix(-1)[2][2]);
		//m_pCameraMngr->SetPosition(c_player->GetLocation());

		matrix4 camView = glm::transpose(m_pCameraMngr->GetViewMatrix(-1));

		vector3 playerLoc = c_player->GetLocation();
		vector3 camZ = vector3(camView[2][0], camView[2][1], camView[2][2]);

		vector3 dif = playerLoc - m_pCameraMngr->GetPosition();
		vector3 playerTarget = camZ;
		//vector3 playerTarget =dif + vector3(0.0f, 0.0f, -1.0f);
		//if (flip)
		//{
		//	playerTarget *= -1.0f;
		///}
		//flip = !flip;
		//m_pCameraMngr->SetPosition(playerLoc);
		//m_pCameraMngr->SetTarget(playerTarget);

		vector3 playerUp = vector3(camView[1][0], camView[1][1], camView[1][2]);
		m_pCameraMngr->SetPositionTargetAndView(playerLoc, playerTarget, REAXISY, -1);
		//m_pCameraMngr->CalculateView();
		//m_pCameraMngr->CalculateProjection();
		//matrix4 temp;
		//temp = m_pCameraMngr->GetViewMatrix(-1);

		return;
	}
	//Else free camera

}

void AppClass::ToggleCamera()
{
	if (!camSelect)
	{
		m_pCameraMngr->SetActiveCamera(railCamIndex);
		camSelect = true;
	}
	else
	{
		camSelect = false;
		m_pCameraMngr->SetActiveCamera(0);
	}
}

void AppClass::Update(void)
{
	//Update the system's time
	m_pSystem->UpdateTime();
	//Update the mesh manager's time without updating for collision detection
	m_pMeshMngr->Update(false);

	//lighting
	m_pLightMngr->SetPosition(vector3(0.0f, 150.0f, 0.0f));
	m_pLightMngr->SetIntensity(8000.0f);

	//First person camera movement
	if (m_bFPC == true)
		CameraRotation();

	ArcBall();

	//Set the model matrices for both objects and Bounding Spheres
	//m_pMeshMngr->SetModelMatrix(glm::translate(m_v3O1) * ToMatrix4(m_qArcBall), "Steve");
	//m_pMeshMngr->SetModelMatrix(glm::translate(m_v3O2), "Creeper");

	m_pMeshMngr->SetModelMatrix(glm::translate(m_v3PosEnv), "Environment");
	//m_pMeshMngr->SetModelMatrix(glm::translate(m_v3PosPokeCube), "Pokecube");
	//m_pMeshMngr->SetModelMatrix(glm::translate(m_v3PosPika), "Pikachu");

	//m_pBOMngr->Update();

	p_pokecube_01->Update();
	c_pika_01->Update();

	m_pEntityMngr->UpdateCollisions();
	m_pEntityMngr->processCollisions("Pokecube");

	UpdatePlayerCamera();

	//Adds all loaded instance to the render list
	m_pMeshMngr->AddInstanceToRenderList("Environment");
	//m_pMeshMngr->AddInstanceToRenderList("Pikachu");

	//Indicate the FPS
	int nFPS = m_pSystem->GetFPS();
	//print info into the console
	//printf("x: %f            ", temp[0][0]);//print the Frames per Second
	//printf("y: %f            ", temp[1][1]);//print the Frames per Second
	//printf("z: %f            \r", temp[2][2]);//print the Frames per Second
	//Print info on the screen
	m_pScoreMngr->Update();
	//m_pMeshMngr->PrintLine(m_pSystem->GetAppName(), REYELLOW);
	m_pMeshMngr->Print("FPS:");
	m_pMeshMngr->Print(std::to_string(nFPS), RERED);
}

void AppClass::Display(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the window

	//Render the grid based on the camera's mode:
	switch (m_pCameraMngr->GetCameraMode())
	{
	//default: //Perspective
	//	m_pMeshMngr->AddGridToQueue(1.0f, REAXIS::XY); //renders the XY grid with a 100% scale
	//	break;
	//case CAMERAMODE::CAMROTHOX:
	//	m_pMeshMngr->AddGridToQueue(1.0f, REAXIS::YZ, RERED * 0.75f); //renders the YZ grid with a 100% scale
	//	break;
	//case CAMERAMODE::CAMROTHOY:
	//	m_pMeshMngr->AddGridToQueue(1.0f, REAXIS::XZ, REGREEN * 0.75f); //renders the XZ grid with a 100% scale
	//	break;
	//case CAMERAMODE::CAMROTHOZ:
	//	m_pMeshMngr->AddGridToQueue(1.0f, REAXIS::XY, REBLUE * 0.75f); //renders the XY grid with a 100% scale
	//	break;
	}

	m_pMeshMngr->Render(); //renders the render list
	m_pGLSystem->GLSwapBuffers(); //Swaps the OpenGL buffers
}

void AppClass::Release(void)
{
	super::Release(); //release the memory of the inherited fields
	m_pCameraMngr->ReleaseInstance();
}

void AppClass::FillPath(void)
{
	//Player's Path
	playerPath.push_back(vector3(10, 0, 0));
	playerPath.push_back(vector3(37, 0, 13));
	playerPath.push_back(vector3(14, 0, 45));
	playerPath.push_back(vector3(3, 0, 22));
}<commit_msg>Milestone2_Deliverable<commit_after>#include "AppClass.h"
void AppClass::InitWindow(String a_sWindowName)
{
	super::InitWindow("PokemanSafari"); // Window Name

	// Set the clear color based on Microsoft's CornflowerBlue (default in XNA)
	//if this line is in Init Application it will depend on the .cfg file, if it
	//is on the InitVariables it will always force it regardless of the .cfg
	m_v4ClearColor = vector4(0.4f, 0.6f, 0.9f, 0.0f);
}

void AppClass::InitVariables(void)
{
	m_pScoreMngr = ScoreManager::GetInstance();
	m_pBOMngr = MyBOManager::GetInstance();
	m_pEntityMngr = MyEntityManager::GetInstance();

	m_pCameraMngr->SetFPS(true);
	//Create the rail camera
	railCamIndex = m_pCameraMngr->AddCamera(vector3(0.0f, 0.0f, 5.0f),
		                     vector3(0.0f, 0.0f, 0.0f),
		                     vector3(0.0f, 1.0f, 0.0f));

	m_pLightMngr->AddLight(vector3(5.5f,10.0f,10.0f));

	//Fill Paths
	FillPath();

	//Initialize positions
	m_v3PosPokeCube = vector3(0.0f, 0.0f, 0.0f);
	m_v3PosEnv = vector3(0.0f, -20.0f, 0.0f);
	m_v3PosPika = vector3(-5.0f, -20.0f, -7.0f);

	//Load Models
	m_pMeshMngr->LoadModel("PokemanSafari\\environment.obj", "Environment");
	m_pMeshMngr->LoadModel("PokemanSafari\\pokecube.obj", "Pokecube");
	m_pMeshMngr->LoadModel("PokemanSafari\\pikachu.obj", "Pikachu");

	m_pEntityMngr->AddEntity("Pokecube", PJ_POKECUBE);
	//p_pokecube_01 = new Projectile(PJ_POKECUBE, "Pokecube");
	p_pokecube_01 = (Projectile*)m_pEntityMngr->GetEntity("Pokecube");
	p_pokecube_01->SetPosition(m_v3PosPokeCube);
	p_pokecube_01->SetVelocity(vector3(0.002f, 0.0f, 0.0f));
    p_pokecube_01->SetAcceleration(vector3(0.0f, -0.002f, 0.0f));
	p_pokecube_01->SetMass(1.2f);
	//ThrowPokecube();

	c_player = new Character(CT_PLAYER, "player", 20, playerPath);

	m_pEntityMngr->AddEntity("Pikachu", CT_POKEMAN, 20, playerPath);
	//c_pika_01 = new Character(CT_POKEMAN, "Pikachu", 20, playerPath);
	c_pika_01 = (Character*)m_pEntityMngr->GetEntity("Pikachu");
	c_pika_01->SetPosition(m_v3PosPika);

}

void AppClass::ThrowPokecube()
{
	//Check if already in the air
	if (p_pokecube_01->IsAlive())
		return;

	p_pokecube_01->SetAlive(true);
	matrix4 camView = glm::transpose(m_pCameraMngr->GetViewMatrix(-1));
	vector3 pos = m_pCameraMngr->GetPosition(-1);
	pos[1] -= 0.5f; //don't go 'through' the camera
	p_pokecube_01->SetPosition(pos);
	//Set the velocity in cam z direction
	vector3 dir = -1.0f * vector3(camView[2][0], camView[2][1], camView[2][2]);
	//TODO put this inside Projectile?
	float velocityFactor = 0.5f;
	p_pokecube_01->SetVelocity(vector3(dir[0] * velocityFactor,
		                               dir[1] * velocityFactor,
									   dir[2] * velocityFactor));
}

void AppClass::UpdatePlayerCamera()
{
	//setting the camera's position to the players location
	c_player->UpdateLocation();

	if (camSelect)
	{
		//Using Rail Camera

		//lookDir = vector3(m_pCameraMngr->GetViewMatrix(-1)[0][0], m_pCameraMngr->GetViewMatrix(-1)[1][1], m_pCameraMngr->GetViewMatrix(-1)[2][2]);
		//m_pCameraMngr->SetPosition(c_player->GetLocation());

		matrix4 camView = glm::transpose(m_pCameraMngr->GetViewMatrix(-1));

		vector3 playerLoc = c_player->GetLocation();
		vector3 camZ = vector3(camView[2][0], camView[2][1], camView[2][2]);

		vector3 dif = playerLoc - m_pCameraMngr->GetPosition();
		vector3 playerTarget = camZ;
		//vector3 playerTarget =dif + vector3(0.0f, 0.0f, -1.0f);
		//if (flip)
		//{
		//	playerTarget *= -1.0f;
		///}
		//flip = !flip;
		//m_pCameraMngr->SetPosition(playerLoc);
		//m_pCameraMngr->SetTarget(playerTarget);

		vector3 playerUp = vector3(camView[1][0], camView[1][1], camView[1][2]);
		m_pCameraMngr->SetPositionTargetAndView(playerLoc, playerTarget, REAXISY, -1);
		//m_pCameraMngr->CalculateView();
		//m_pCameraMngr->CalculateProjection();
		//matrix4 temp;
		//temp = m_pCameraMngr->GetViewMatrix(-1);

		return;
	}
	//Else free camera

}

//
void AppClass::ToggleCamera()
{
	if (!camSelect)
	{
		m_pCameraMngr->SetActiveCamera(railCamIndex);
		camSelect = true;
	}
	else
	{
		camSelect = false;
		m_pCameraMngr->SetActiveCamera(0);
	}
}

void AppClass::Update(void)
{
	//Update the system's time
	m_pSystem->UpdateTime();
	//Update the mesh manager's time without updating for collision detection
	m_pMeshMngr->Update(false);

	//lighting
	m_pLightMngr->SetPosition(vector3(0.0f, 150.0f, 0.0f));
	m_pLightMngr->SetIntensity(8000.0f);

	//First person camera movement
	if (m_bFPC == true)
		CameraRotation();

	ArcBall();

	//Set the model matrices for both objects and Bounding Spheres
	//m_pMeshMngr->SetModelMatrix(glm::translate(m_v3O1) * ToMatrix4(m_qArcBall), "Steve");
	//m_pMeshMngr->SetModelMatrix(glm::translate(m_v3O2), "Creeper");

	m_pMeshMngr->SetModelMatrix(glm::translate(m_v3PosEnv), "Environment");
	//m_pMeshMngr->SetModelMatrix(glm::translate(m_v3PosPokeCube), "Pokecube");
	//m_pMeshMngr->SetModelMatrix(glm::translate(m_v3PosPika), "Pikachu");

	//m_pBOMngr->Update();

	p_pokecube_01->Update();
	c_pika_01->Update();

	m_pEntityMngr->UpdateCollisions();
	m_pEntityMngr->processCollisions("Pokecube");

	UpdatePlayerCamera();

	//Adds all loaded instance to the render list
	m_pMeshMngr->AddInstanceToRenderList("Environment");
	//m_pMeshMngr->AddInstanceToRenderList("Pikachu");

	//Indicate the FPS
	int nFPS = m_pSystem->GetFPS();
	//print info into the console
	//printf("x: %f            ", temp[0][0]);//print the Frames per Second
	//printf("y: %f            ", temp[1][1]);//print the Frames per Second
	//printf("z: %f            \r", temp[2][2]);//print the Frames per Second
	//Print info on the screen
	m_pScoreMngr->Update();
	//m_pMeshMngr->PrintLine(m_pSystem->GetAppName(), REYELLOW);
	m_pMeshMngr->Print("FPS:");
	m_pMeshMngr->Print(std::to_string(nFPS), RERED);
}

void AppClass::Display(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the window

	//Render the grid based on the camera's mode:
	switch (m_pCameraMngr->GetCameraMode())
	{
	//default: //Perspective
	//	m_pMeshMngr->AddGridToQueue(1.0f, REAXIS::XY); //renders the XY grid with a 100% scale
	//	break;
	//case CAMERAMODE::CAMROTHOX:
	//	m_pMeshMngr->AddGridToQueue(1.0f, REAXIS::YZ, RERED * 0.75f); //renders the YZ grid with a 100% scale
	//	break;
	//case CAMERAMODE::CAMROTHOY:
	//	m_pMeshMngr->AddGridToQueue(1.0f, REAXIS::XZ, REGREEN * 0.75f); //renders the XZ grid with a 100% scale
	//	break;
	//case CAMERAMODE::CAMROTHOZ:
	//	m_pMeshMngr->AddGridToQueue(1.0f, REAXIS::XY, REBLUE * 0.75f); //renders the XY grid with a 100% scale
	//	break;
	}

	m_pMeshMngr->Render(); //renders the render list
	m_pGLSystem->GLSwapBuffers(); //Swaps the OpenGL buffers
}

void AppClass::Release(void)
{
	super::Release(); //release the memory of the inherited fields
	m_pCameraMngr->ReleaseInstance();
}

void AppClass::FillPath(void)
{
	//Player's Path
	playerPath.push_back(vector3(10, 0, 0));
	playerPath.push_back(vector3(37, 0, 13));
	playerPath.push_back(vector3(14, 0, 45));
	playerPath.push_back(vector3(3, 0, 22));
}<|endoftext|>


<commit_before>// @(#)root/meta:$
// Author: Axel Naumann 2014-05-02

/*************************************************************************
 * Copyright (C) 1995-2014, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Persistent version of a TClass.                                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TProtoClass.h"

#include "TBaseClass.h"
#include "TClass.h"
#include "TDataMember.h"
#include "TEnum.h"
#include "TInterpreter.h"
#include "TList.h"
#include "TListOfDataMembers.h"
#include "TListOfEnums.h"
#include "TRealData.h"

//______________________________________________________________________________
TProtoClass::TProtoClass(TClass* cl):
   TNamed(*cl), fBase(cl->GetListOfBases()), fData(cl->GetListOfDataMembers()),
   fEnums(cl->GetListOfEnums()), fSizeof(cl->Size()), fCanSplit(cl->fCanSplit),
   fStreamerType(cl->fStreamerType), fProperty(cl->fProperty),
   fClassProperty(cl->fClassProperty)
{
   // Initialize a TProtoClass from a TClass.
   fPRealData = new TList();

   if (!cl->GetCollectionProxy()) {
      // Build the list of RealData before we access it:
      cl->BuildRealData(0, true /*isTransient*/);
      // The data members are ordered as follows:
      // - this class's data members,
      // - foreach base: base class's data members.
      // fPRealData encodes all TProtoRealData objects with a
      // TObjString to signal a new class.
      TClass* clCurrent = cl;
      TRealData* precRd = nullptr;
      for (auto realDataObj: *cl->GetListOfRealData()) {
         TRealData *rd = (TRealData*)realDataObj;
         if (!precRd) precRd = rd;
         TClass* clRD = rd->GetDataMember()->GetClass();
         if (clRD != clCurrent) {
            clCurrent = clRD;
            TObjString *clstr = new TObjString(clRD->GetName());
            if (precRd->TestBit(TRealData::kTransient)) {
               clstr->SetBit(TRealData::kTransient);
            }
            fPRealData->AddLast(clstr);
            precRd = rd;
         }
         fPRealData->AddLast(new TProtoRealData(rd));
      }

      if (gDebug > 2) {
         for (auto dataPtr : *fPRealData) {
            const auto classType = dataPtr->IsA();
            const auto dataPtrName = dataPtr->GetName();
            if (classType == TProtoRealData::Class())
               Info("TProtoClass","Data is a protorealdata: %s", dataPtrName);
            if (classType == TObjString::Class())
               Info("TProtoClass","Data is a objectstring: %s", dataPtrName);
            if (dataPtr->TestBit(TRealData::kTransient))
               Info("TProtoClass","And is transient");
         }
      }
   }

   cl->CalculateStreamerOffset();
   fOffsetStreamer = cl->fOffsetStreamer;
}

//______________________________________________________________________________
TProtoClass::~TProtoClass()
{
   // Destructor.
   Delete();
}

//______________________________________________________________________________
void TProtoClass::Delete(Option_t* opt /*= ""*/) {
   // Delete the containers that are usually owned by their TClass.
   if (fPRealData) fPRealData->Delete(opt);
   delete fPRealData; fPRealData = 0;
   if (fBase) fBase->Delete(opt);
   delete fBase; fBase = 0;
   if (fData) fData->Delete(opt);
   delete fData; fData = 0;
   if (fEnums) fEnums->Delete(opt);
   delete fEnums; fEnums = 0;
}

//______________________________________________________________________________
Bool_t TProtoClass::FillTClass(TClass* cl) {
   // Move data from this TProtoClass into cl.
   if (cl->fRealData || cl->fBase || cl->fData || cl->fEnums
       || cl->fSizeof != -1 || cl->fCanSplit >= 0
       || cl->fProperty != (-1) ) {
      Error("FillTClass", "TClass %s already initialized!", cl->GetName());
      return kFALSE;
   }
   if (gDebug > 1) Info("FillTClass","Loading TProtoClass for %s - %s",cl->GetName(),GetName());

   if (fPRealData) {

      // A first loop to retrieve the mother classes before starting to
      // fill this TClass instance. This is done in order to avoid recursions
      // for example in presence of daughter and mother class present in two
      // dictionaries compiled in two different libraries which are not linked
      // one with each other.
      for (TObject* element: *fPRealData) {
         if (element->IsA() == TObjString::Class()) {
            if (gDebug > 1) Info("","Treating beforehand mother class %s",element->GetName());
            int autoparsingOldval=gInterpreter->SetClassAutoparsing(false);
            TClass::GetClass(element->GetName());
            gInterpreter->SetClassAutoparsing(autoparsingOldval);
         }
      }
   }

   // Copy only the TClass bits.
   // not bit 13 and below and not bit 24 and above, just Bits 14 - 23
   UInt_t newbits = TestBits(0x00ffc000);
   cl->ResetBit(0x00ffc000);
   cl->SetBit(newbits);

   cl->fName  = this->fName;
   cl->fTitle = this->fTitle;
   cl->fBase = fBase;
   cl->fData = (TListOfDataMembers*)fData;
   cl->fEnums = (TListOfEnums*)fEnums;
   cl->fRealData = new TList(); // FIXME: this should really become a THashList!

   cl->fSizeof = fSizeof;
   cl->fCanSplit = fCanSplit;
   cl->fProperty = fProperty;
   cl->fClassProperty = fClassProperty;
   cl->fStreamerType = fStreamerType;

   // Update pointers to TClass
   if (cl->fBase) {
      for (auto base: *cl->fBase) {
         ((TBaseClass*)base)->SetClass(cl);
      }
   }
   if (cl->fData) {
      for (auto dm: *cl->fData) {
         ((TDataMember*)dm)->SetClass(cl);
      }
      ((TListOfDataMembers*)cl->fData)->SetClass(cl);
   }
   if (cl->fEnums) {
      for (auto en: *cl->fEnums) {
         ((TEnum*)en)->SetClass(cl);
      }
      ((TListOfEnums*)cl->fEnums)->SetClass(cl);
   }

   TClass* currentRDClass = cl;
   if (fPRealData) {
      for (TObject* element: *fPRealData) {
         if (element->IsA() == TObjString::Class()) {
            // We now check for the TClass entry, w/o loading. Indeed we did that above.
            // If the class is not found, it means that really it was not selected and we
            // replace it with an empty placeholder with the status of kForwardDeclared.
            // Interactivity will be of course possible but if IO is attempted, a warning
            // will be issued.
            int autoparsingOldval=gInterpreter->SetClassAutoparsing(false);
            // Disable autoparsing which might be triggered by the use of ResolvedTypedef
            // and the fallback new TClass() below.
            currentRDClass = TClass::GetClass(element->GetName(), false /* Load */ );
            if (!currentRDClass && !element->TestBit(TRealData::kTransient)) {
               if (gDebug>1)
                  Info("FillTClass()",
                       "Cannot find TClass for %s; Creating an empty one in the kForwardDeclared state.",
                       element->GetName());
               currentRDClass = new TClass(element->GetName(),1,TClass::kForwardDeclared, true /*silent*/);
            }
            gInterpreter->SetClassAutoparsing(autoparsingOldval);
         } else {
            if (!currentRDClass) continue;
            TProtoRealData* prd = (TProtoRealData*)element;
            if (TRealData* rd = prd->CreateRealData(currentRDClass, cl)) {
               cl->fRealData->AddLast(rd);
            }
         }
      }
   }

   cl->SetStreamerImpl();

   fBase = 0;
   fData = 0;
   fEnums = 0;
   if (fPRealData) fPRealData->Delete();
   delete fPRealData;
   fPRealData = 0;

   return kTRUE;
}

//______________________________________________________________________________
TProtoClass::TProtoRealData::TProtoRealData(const TRealData* rd):
   TNamed(rd->GetDataMember()->GetName(), rd->GetName()),
   fOffset(rd->GetThisOffset())
{
   // Initialize this from a TRealData object.
   SetBit(kIsObject, rd->IsObject());
   SetBit(TRealData::kTransient, rd->TestBit(TRealData::kTransient));
}

//______________________________________________________________________________
TProtoClass::TProtoRealData::~TProtoRealData()
{
   // Destructor to pin vtable.
}

//______________________________________________________________________________
TRealData* TProtoClass::TProtoRealData::CreateRealData(TClass* dmClass,
                                                       TClass* parent) const
{
   // Create a TRealData from this, with its data member coming from dmClass.
   TDataMember* dm = (TDataMember*)dmClass->GetListOfDataMembers()->FindObject(GetName());
   if (!dm && dmClass->GetState()!=TClass::kForwardDeclared) {
      Error("CreateRealData",
            "Cannot find data member %s::%s for parent %s!", dmClass->GetName(),
            GetName(), parent->GetName());
      return nullptr;
   }
   TRealData* rd = new TRealData(GetTitle(), fOffset, dm);
   rd->SetIsObject(TestBit(kIsObject));
   return rd;
}
<commit_msg>Make sure that the newly created class has a filled Id map<commit_after>// @(#)root/meta:$
// Author: Axel Naumann 2014-05-02

/*************************************************************************
 * Copyright (C) 1995-2014, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Persistent version of a TClass.                                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TProtoClass.h"

#include "TBaseClass.h"
#include "TClass.h"
#include "TDataMember.h"
#include "TEnum.h"
#include "TInterpreter.h"
#include "TList.h"
#include "TListOfDataMembers.h"
#include "TListOfEnums.h"
#include "TRealData.h"

//______________________________________________________________________________
TProtoClass::TProtoClass(TClass* cl):
   TNamed(*cl), fBase(cl->GetListOfBases()), fData(cl->GetListOfDataMembers()),
   fEnums(cl->GetListOfEnums()), fSizeof(cl->Size()), fCanSplit(cl->fCanSplit),
   fStreamerType(cl->fStreamerType), fProperty(cl->fProperty),
   fClassProperty(cl->fClassProperty)
{
   // Initialize a TProtoClass from a TClass.
   fPRealData = new TList();

   if (!cl->GetCollectionProxy()) {
      // Build the list of RealData before we access it:
      cl->BuildRealData(0, true /*isTransient*/);
      // The data members are ordered as follows:
      // - this class's data members,
      // - foreach base: base class's data members.
      // fPRealData encodes all TProtoRealData objects with a
      // TObjString to signal a new class.
      TClass* clCurrent = cl;
      TRealData* precRd = nullptr;
      for (auto realDataObj: *cl->GetListOfRealData()) {
         TRealData *rd = (TRealData*)realDataObj;
         if (!precRd) precRd = rd;
         TClass* clRD = rd->GetDataMember()->GetClass();
         if (clRD != clCurrent) {
            clCurrent = clRD;
            TObjString *clstr = new TObjString(clRD->GetName());
            if (precRd->TestBit(TRealData::kTransient)) {
               clstr->SetBit(TRealData::kTransient);
            }
            fPRealData->AddLast(clstr);
            precRd = rd;
         }
         fPRealData->AddLast(new TProtoRealData(rd));
      }

      if (gDebug > 2) {
         for (auto dataPtr : *fPRealData) {
            const auto classType = dataPtr->IsA();
            const auto dataPtrName = dataPtr->GetName();
            if (classType == TProtoRealData::Class())
               Info("TProtoClass","Data is a protorealdata: %s", dataPtrName);
            if (classType == TObjString::Class())
               Info("TProtoClass","Data is a objectstring: %s", dataPtrName);
            if (dataPtr->TestBit(TRealData::kTransient))
               Info("TProtoClass","And is transient");
         }
      }
   }

   cl->CalculateStreamerOffset();
   fOffsetStreamer = cl->fOffsetStreamer;
}

//______________________________________________________________________________
TProtoClass::~TProtoClass()
{
   // Destructor.
   Delete();
}

//______________________________________________________________________________
void TProtoClass::Delete(Option_t* opt /*= ""*/) {
   // Delete the containers that are usually owned by their TClass.
   if (fPRealData) fPRealData->Delete(opt);
   delete fPRealData; fPRealData = 0;
   if (fBase) fBase->Delete(opt);
   delete fBase; fBase = 0;
   if (fData) fData->Delete(opt);
   delete fData; fData = 0;
   if (fEnums) fEnums->Delete(opt);
   delete fEnums; fEnums = 0;
}
#include <iostream>
//______________________________________________________________________________
Bool_t TProtoClass::FillTClass(TClass* cl) {
   // Move data from this TProtoClass into cl.
   if (cl->fRealData || cl->fBase || cl->fData || cl->fEnums
       || cl->fSizeof != -1 || cl->fCanSplit >= 0
       || cl->fProperty != (-1) ) {
      Error("FillTClass", "TClass %s already initialized!", cl->GetName());
      return kFALSE;
   }
   if (gDebug > 1) Info("FillTClass","Loading TProtoClass for %s - %s",cl->GetName(),GetName());

   if (fPRealData) {

      // A first loop to retrieve the mother classes before starting to
      // fill this TClass instance. This is done in order to avoid recursions
      // for example in presence of daughter and mother class present in two
      // dictionaries compiled in two different libraries which are not linked
      // one with each other.
      for (TObject* element: *fPRealData) {
         if (element->IsA() == TObjString::Class()) {
            if (gDebug > 1) Info("","Treating beforehand mother class %s",element->GetName());
            int autoparsingOldval=gInterpreter->SetClassAutoparsing(false);
            TClass::GetClass(element->GetName());
            gInterpreter->SetClassAutoparsing(autoparsingOldval);
         }
      }
   }

   // Copy only the TClass bits.
   // not bit 13 and below and not bit 24 and above, just Bits 14 - 23
   UInt_t newbits = TestBits(0x00ffc000);
   cl->ResetBit(0x00ffc000);
   cl->SetBit(newbits);

   cl->fName  = this->fName;
   cl->fTitle = this->fTitle;
   cl->fBase = fBase;
   cl->fData = (TListOfDataMembers*)fData;
   // We need to fill enums one by one to initialise the internal map which is
   // transient
   cl->fEnums = new TListOfEnums();
   for (TObject* enumAsTObj : *fEnums){
      cl->fEnums->Add((TEnum*) enumAsTObj);
   }
   cl->fRealData = new TList(); // FIXME: this should really become a THashList!

   cl->fSizeof = fSizeof;
   cl->fCanSplit = fCanSplit;
   cl->fProperty = fProperty;
   cl->fClassProperty = fClassProperty;
   cl->fStreamerType = fStreamerType;

   // Update pointers to TClass
   if (cl->fBase) {
      for (auto base: *cl->fBase) {
         ((TBaseClass*)base)->SetClass(cl);
      }
   }
   if (cl->fData) {
      for (auto dm: *cl->fData) {
         ((TDataMember*)dm)->SetClass(cl);
      }
      ((TListOfDataMembers*)cl->fData)->SetClass(cl);
   }
   if (cl->fEnums) {
      for (auto en: *cl->fEnums) {
         ((TEnum*)en)->SetClass(cl);
      }
      ((TListOfEnums*)cl->fEnums)->SetClass(cl);
   }

   TClass* currentRDClass = cl;
   if (fPRealData) {
      for (TObject* element: *fPRealData) {
         if (element->IsA() == TObjString::Class()) {
            // We now check for the TClass entry, w/o loading. Indeed we did that above.
            // If the class is not found, it means that really it was not selected and we
            // replace it with an empty placeholder with the status of kForwardDeclared.
            // Interactivity will be of course possible but if IO is attempted, a warning
            // will be issued.
            int autoparsingOldval=gInterpreter->SetClassAutoparsing(false);
            // Disable autoparsing which might be triggered by the use of ResolvedTypedef
            // and the fallback new TClass() below.
            currentRDClass = TClass::GetClass(element->GetName(), false /* Load */ );
            if (!currentRDClass && !element->TestBit(TRealData::kTransient)) {
               if (gDebug>1)
                  Info("FillTClass()",
                       "Cannot find TClass for %s; Creating an empty one in the kForwardDeclared state.",
                       element->GetName());
               currentRDClass = new TClass(element->GetName(),1,TClass::kForwardDeclared, true /*silent*/);
            }
            gInterpreter->SetClassAutoparsing(autoparsingOldval);
         } else {
            if (!currentRDClass) continue;
            TProtoRealData* prd = (TProtoRealData*)element;
            if (TRealData* rd = prd->CreateRealData(currentRDClass, cl)) {
               cl->fRealData->AddLast(rd);
            }
         }
      }
   }

   cl->SetStreamerImpl();

   fBase = 0;
   fData = 0;
   fEnums = 0;
   if (fPRealData) fPRealData->Delete();
   delete fPRealData;
   fPRealData = 0;

   return kTRUE;
}

//______________________________________________________________________________
TProtoClass::TProtoRealData::TProtoRealData(const TRealData* rd):
   TNamed(rd->GetDataMember()->GetName(), rd->GetName()),
   fOffset(rd->GetThisOffset())
{
   // Initialize this from a TRealData object.
   SetBit(kIsObject, rd->IsObject());
   SetBit(TRealData::kTransient, rd->TestBit(TRealData::kTransient));
}

//______________________________________________________________________________
TProtoClass::TProtoRealData::~TProtoRealData()
{
   // Destructor to pin vtable.
}

//______________________________________________________________________________
TRealData* TProtoClass::TProtoRealData::CreateRealData(TClass* dmClass,
                                                       TClass* parent) const
{
   // Create a TRealData from this, with its data member coming from dmClass.
   TDataMember* dm = (TDataMember*)dmClass->GetListOfDataMembers()->FindObject(GetName());
   if (!dm && dmClass->GetState()!=TClass::kForwardDeclared) {
      Error("CreateRealData",
            "Cannot find data member %s::%s for parent %s!", dmClass->GetName(),
            GetName(), parent->GetName());
      return nullptr;
   }
   TRealData* rd = new TRealData(GetTitle(), fOffset, dm);
   rd->SetIsObject(TestBit(kIsObject));
   return rd;
}
<|endoftext|>


<commit_before>//===-LTOCodeGenerator.cpp - LLVM Link Time Optimizer ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Link Time Optimization library. This library is
// intended to be used by linker to optimize code at link time.
//
//===----------------------------------------------------------------------===//

#include "LTOCodeGenerator.h"
#include "LTOModule.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Linker.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Config/config.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/system_error.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
using namespace llvm;

static cl::opt<bool> DisableInline("disable-inlining",
  cl::desc("Do not run the inliner pass"));

const char* LTOCodeGenerator::getVersionString() {
#ifdef LLVM_VERSION_INFO
  return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO;
#else
  return PACKAGE_NAME " version " PACKAGE_VERSION;
#endif
}

LTOCodeGenerator::LTOCodeGenerator()
  : _context(getGlobalContext()),
    _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL),
    _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
    _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
    _nativeObjectFile(NULL) {
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmPrinters();
}

LTOCodeGenerator::~LTOCodeGenerator() {
  delete _target;
  delete _nativeObjectFile;

  for (std::vector<char*>::iterator I = _codegenOptions.begin(),
         E = _codegenOptions.end(); I != E; ++I)
    free(*I);
}

bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) {
  bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);

  const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs();
  for (int i = 0, e = undefs.size(); i != e; ++i)
    _asmUndefinedRefs[undefs[i]] = 1;

  return ret;
}

bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug,
                                    std::string& errMsg) {
  switch (debug) {
  case LTO_DEBUG_MODEL_NONE:
    _emitDwarfDebugInfo = false;
    return false;

  case LTO_DEBUG_MODEL_DWARF:
    _emitDwarfDebugInfo = true;
    return false;
  }
  llvm_unreachable("Unknown debug format!");
}

bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model,
                                       std::string& errMsg) {
  switch (model) {
  case LTO_CODEGEN_PIC_MODEL_STATIC:
  case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
  case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
    _codeModel = model;
    return false;
  }
  llvm_unreachable("Unknown PIC model!");
}

void LTOCodeGenerator::setCpu(const char* mCpu) {
  _mCpu = mCpu;
}

void LTOCodeGenerator::addMustPreserveSymbol(const char* sym) {
  _mustPreserveSymbols[sym] = 1;
}

bool LTOCodeGenerator::writeMergedModules(const char *path,
                                          std::string &errMsg) {
  if (determineTarget(errMsg))
    return true;

  // mark which symbols can not be internalized
  applyScopeRestrictions();

  // create output file
  std::string ErrInfo;
  tool_output_file Out(path, ErrInfo,
                       raw_fd_ostream::F_Binary);
  if (!ErrInfo.empty()) {
    errMsg = "could not open bitcode file for writing: ";
    errMsg += path;
    return true;
  }

  // write bitcode to it
  WriteBitcodeToFile(_linker.getModule(), Out.os());
  Out.os().close();

  if (Out.os().has_error()) {
    errMsg = "could not write bitcode file: ";
    errMsg += path;
    Out.os().clear_error();
    return true;
  }

  Out.keep();
  return false;
}

bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) {
  // make unique temp .o file to put generated object file
  sys::PathWithStatus uniqueObjPath("lto-llvm.o");
  if ( uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg) ) {
    uniqueObjPath.eraseFromDisk();
    return true;
  }
  sys::RemoveFileOnSignal(uniqueObjPath);

  // generate object file
  bool genResult = false;
  tool_output_file objFile(uniqueObjPath.c_str(), errMsg);
  if (!errMsg.empty())
    return true;

  genResult = this->generateObjectFile(objFile.os(), errMsg);
  objFile.os().close();
  if (objFile.os().has_error()) {
    objFile.os().clear_error();
    return true;
  }

  objFile.keep();
  if ( genResult ) {
    uniqueObjPath.eraseFromDisk();
    return true;
  }

  _nativeObjectPath = uniqueObjPath.str();
  *name = _nativeObjectPath.c_str();
  return false;
}

const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) {
  const char *name;
  if (compile_to_file(&name, errMsg))
    return NULL;

  // remove old buffer if compile() called twice
  delete _nativeObjectFile;

  // read .o file into memory buffer
  OwningPtr<MemoryBuffer> BuffPtr;
  if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) {
    errMsg = ec.message();
    return NULL;
  }
  _nativeObjectFile = BuffPtr.take();

  // remove temp files
  sys::Path(_nativeObjectPath).eraseFromDisk();

  // return buffer, unless error
  if ( _nativeObjectFile == NULL )
    return NULL;
  *length = _nativeObjectFile->getBufferSize();
  return _nativeObjectFile->getBufferStart();
}

bool LTOCodeGenerator::determineTarget(std::string& errMsg) {
  if ( _target == NULL ) {
    std::string Triple = _linker.getModule()->getTargetTriple();
    if (Triple.empty())
      Triple = sys::getDefaultTargetTriple();

    // create target machine from info for merged modules
    const Target *march = TargetRegistry::lookupTarget(Triple, errMsg);
    if ( march == NULL )
      return true;

    // The relocation model is actually a static member of TargetMachine and
    // needs to be set before the TargetMachine is instantiated.
    Reloc::Model RelocModel = Reloc::Default;
    switch( _codeModel ) {
    case LTO_CODEGEN_PIC_MODEL_STATIC:
      RelocModel = Reloc::Static;
      break;
    case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
      RelocModel = Reloc::PIC_;
      break;
    case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
      RelocModel = Reloc::DynamicNoPIC;
      break;
    }

    // construct LTOModule, hand over ownership of module and target
    SubtargetFeatures Features;
    Features.getDefaultSubtargetFeatures(llvm::Triple(Triple));
    std::string FeatureStr = Features.getString();
    TargetOptions Options;
    _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, Options,
                                         RelocModel);
  }
  return false;
}

void LTOCodeGenerator::
applyRestriction(GlobalValue &GV,
                 std::vector<const char*> &mustPreserveList,
                 SmallPtrSet<GlobalValue*, 8> &asmUsed,
                 Mangler &mangler) {
  SmallString<64> Buffer;
  mangler.getNameWithPrefix(Buffer, &GV, false);

  if (GV.isDeclaration())
    return;
  if (_mustPreserveSymbols.count(Buffer))
    mustPreserveList.push_back(GV.getName().data());
  if (_asmUndefinedRefs.count(Buffer))
    asmUsed.insert(&GV);
}

static void findUsedValues(GlobalVariable *LLVMUsed,
                           SmallPtrSet<GlobalValue*, 8> &UsedValues) {
  if (LLVMUsed == 0) return;

  ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
  if (Inits == 0) return;

  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
    if (GlobalValue *GV =
        dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
      UsedValues.insert(GV);
}

void LTOCodeGenerator::applyScopeRestrictions() {
  if (_scopeRestrictionsDone) return;
  Module *mergedModule = _linker.getModule();

  // Start off with a verification pass.
  PassManager passes;
  passes.add(createVerifierPass());

  // mark which symbols can not be internalized
  MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL);
  Mangler mangler(Context, *_target->getTargetData());
  std::vector<const char*> mustPreserveList;
  SmallPtrSet<GlobalValue*, 8> asmUsed;

  for (Module::iterator f = mergedModule->begin(),
         e = mergedModule->end(); f != e; ++f)
    applyRestriction(*f, mustPreserveList, asmUsed, mangler);
  for (Module::global_iterator v = mergedModule->global_begin(),
         e = mergedModule->global_end(); v !=  e; ++v)
    applyRestriction(*v, mustPreserveList, asmUsed, mangler);
  for (Module::alias_iterator a = mergedModule->alias_begin(),
         e = mergedModule->alias_end(); a != e; ++a)
    applyRestriction(*a, mustPreserveList, asmUsed, mangler);

  GlobalVariable *LLVMCompilerUsed =
    mergedModule->getGlobalVariable("llvm.compiler.used");
  findUsedValues(LLVMCompilerUsed, asmUsed);
  if (LLVMCompilerUsed)
    LLVMCompilerUsed->eraseFromParent();

  llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
  std::vector<Constant*> asmUsed2;
  for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(),
         e = asmUsed.end(); i !=e; ++i) {
    GlobalValue *GV = *i;
    Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
    asmUsed2.push_back(c);
  }

  llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
  LLVMCompilerUsed =
    new llvm::GlobalVariable(*mergedModule, ATy, false,
                             llvm::GlobalValue::AppendingLinkage,
                             llvm::ConstantArray::get(ATy, asmUsed2),
                             "llvm.compiler.used");

  LLVMCompilerUsed->setSection("llvm.metadata");

  passes.add(createInternalizePass(mustPreserveList));

  // apply scope restrictions
  passes.run(*mergedModule);

  _scopeRestrictionsDone = true;
}

/// Optimize merged modules using various IPO passes
bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
                                          std::string &errMsg) {
  if ( this->determineTarget(errMsg) )
    return true;

  // mark which symbols can not be internalized
  this->applyScopeRestrictions();

  Module* mergedModule = _linker.getModule();

  // if options were requested, set them
  if ( !_codegenOptions.empty() )
    cl::ParseCommandLineOptions(_codegenOptions.size(),
                                const_cast<char **>(&_codegenOptions[0]));

  // Instantiate the pass manager to organize the passes.
  PassManager passes;

  // Start off with a verification pass.
  passes.add(createVerifierPass());

  // Add an appropriate TargetData instance for this module...
  passes.add(new TargetData(*_target->getTargetData()));

  PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/ false,
                                              !DisableInline);

  // Make sure everything is still good.
  passes.add(createVerifierPass());

  FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule);

  codeGenPasses->add(new TargetData(*_target->getTargetData()));

  formatted_raw_ostream Out(out);

  if (_target->addPassesToEmitFile(*codeGenPasses, Out,
                                   TargetMachine::CGFT_ObjectFile,
                                   CodeGenOpt::Aggressive)) {
    errMsg = "target file type not supported";
    return true;
  }

  // Run our queue of passes all at once now, efficiently.
  passes.run(*mergedModule);

  // Run the code generator, and write assembly file
  codeGenPasses->doInitialization();

  for (Module::iterator
         it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it)
    if (!it->isDeclaration())
      codeGenPasses->run(*it);

  codeGenPasses->doFinalization();
  delete codeGenPasses;

  return false; // success
}

/// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging
/// LTO problems.
void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) {
  for (std::pair<StringRef, StringRef> o = getToken(options);
       !o.first.empty(); o = getToken(o.second)) {
    // ParseCommandLineOptions() expects argv[0] to be program name. Lazily add
    // that.
    if ( _codegenOptions.empty() )
      _codegenOptions.push_back(strdup("libLTO"));
    _codegenOptions.push_back(strdup(o.first.str().c_str()));
  }
}
<commit_msg>Trim headers.<commit_after>//===-LTOCodeGenerator.cpp - LLVM Link Time Optimizer ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Link Time Optimization library. This library is
// intended to be used by linker to optimize code at link time.
//
//===----------------------------------------------------------------------===//

#include "LTOCodeGenerator.h"
#include "LTOModule.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Linker.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Config/config.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/system_error.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;

static cl::opt<bool> DisableInline("disable-inlining",
  cl::desc("Do not run the inliner pass"));

const char* LTOCodeGenerator::getVersionString() {
#ifdef LLVM_VERSION_INFO
  return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO;
#else
  return PACKAGE_NAME " version " PACKAGE_VERSION;
#endif
}

LTOCodeGenerator::LTOCodeGenerator()
  : _context(getGlobalContext()),
    _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL),
    _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
    _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
    _nativeObjectFile(NULL) {
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmPrinters();
}

LTOCodeGenerator::~LTOCodeGenerator() {
  delete _target;
  delete _nativeObjectFile;

  for (std::vector<char*>::iterator I = _codegenOptions.begin(),
         E = _codegenOptions.end(); I != E; ++I)
    free(*I);
}

bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) {
  bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);

  const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs();
  for (int i = 0, e = undefs.size(); i != e; ++i)
    _asmUndefinedRefs[undefs[i]] = 1;

  return ret;
}

bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug,
                                    std::string& errMsg) {
  switch (debug) {
  case LTO_DEBUG_MODEL_NONE:
    _emitDwarfDebugInfo = false;
    return false;

  case LTO_DEBUG_MODEL_DWARF:
    _emitDwarfDebugInfo = true;
    return false;
  }
  llvm_unreachable("Unknown debug format!");
}

bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model,
                                       std::string& errMsg) {
  switch (model) {
  case LTO_CODEGEN_PIC_MODEL_STATIC:
  case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
  case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
    _codeModel = model;
    return false;
  }
  llvm_unreachable("Unknown PIC model!");
}

void LTOCodeGenerator::setCpu(const char* mCpu) {
  _mCpu = mCpu;
}

void LTOCodeGenerator::addMustPreserveSymbol(const char* sym) {
  _mustPreserveSymbols[sym] = 1;
}

bool LTOCodeGenerator::writeMergedModules(const char *path,
                                          std::string &errMsg) {
  if (determineTarget(errMsg))
    return true;

  // mark which symbols can not be internalized
  applyScopeRestrictions();

  // create output file
  std::string ErrInfo;
  tool_output_file Out(path, ErrInfo,
                       raw_fd_ostream::F_Binary);
  if (!ErrInfo.empty()) {
    errMsg = "could not open bitcode file for writing: ";
    errMsg += path;
    return true;
  }

  // write bitcode to it
  WriteBitcodeToFile(_linker.getModule(), Out.os());
  Out.os().close();

  if (Out.os().has_error()) {
    errMsg = "could not write bitcode file: ";
    errMsg += path;
    Out.os().clear_error();
    return true;
  }

  Out.keep();
  return false;
}

bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) {
  // make unique temp .o file to put generated object file
  sys::PathWithStatus uniqueObjPath("lto-llvm.o");
  if ( uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg) ) {
    uniqueObjPath.eraseFromDisk();
    return true;
  }
  sys::RemoveFileOnSignal(uniqueObjPath);

  // generate object file
  bool genResult = false;
  tool_output_file objFile(uniqueObjPath.c_str(), errMsg);
  if (!errMsg.empty())
    return true;

  genResult = this->generateObjectFile(objFile.os(), errMsg);
  objFile.os().close();
  if (objFile.os().has_error()) {
    objFile.os().clear_error();
    return true;
  }

  objFile.keep();
  if ( genResult ) {
    uniqueObjPath.eraseFromDisk();
    return true;
  }

  _nativeObjectPath = uniqueObjPath.str();
  *name = _nativeObjectPath.c_str();
  return false;
}

const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) {
  const char *name;
  if (compile_to_file(&name, errMsg))
    return NULL;

  // remove old buffer if compile() called twice
  delete _nativeObjectFile;

  // read .o file into memory buffer
  OwningPtr<MemoryBuffer> BuffPtr;
  if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) {
    errMsg = ec.message();
    return NULL;
  }
  _nativeObjectFile = BuffPtr.take();

  // remove temp files
  sys::Path(_nativeObjectPath).eraseFromDisk();

  // return buffer, unless error
  if ( _nativeObjectFile == NULL )
    return NULL;
  *length = _nativeObjectFile->getBufferSize();
  return _nativeObjectFile->getBufferStart();
}

bool LTOCodeGenerator::determineTarget(std::string& errMsg) {
  if ( _target == NULL ) {
    std::string Triple = _linker.getModule()->getTargetTriple();
    if (Triple.empty())
      Triple = sys::getDefaultTargetTriple();

    // create target machine from info for merged modules
    const Target *march = TargetRegistry::lookupTarget(Triple, errMsg);
    if ( march == NULL )
      return true;

    // The relocation model is actually a static member of TargetMachine and
    // needs to be set before the TargetMachine is instantiated.
    Reloc::Model RelocModel = Reloc::Default;
    switch( _codeModel ) {
    case LTO_CODEGEN_PIC_MODEL_STATIC:
      RelocModel = Reloc::Static;
      break;
    case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
      RelocModel = Reloc::PIC_;
      break;
    case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
      RelocModel = Reloc::DynamicNoPIC;
      break;
    }

    // construct LTOModule, hand over ownership of module and target
    SubtargetFeatures Features;
    Features.getDefaultSubtargetFeatures(llvm::Triple(Triple));
    std::string FeatureStr = Features.getString();
    TargetOptions Options;
    _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, Options,
                                         RelocModel);
  }
  return false;
}

void LTOCodeGenerator::
applyRestriction(GlobalValue &GV,
                 std::vector<const char*> &mustPreserveList,
                 SmallPtrSet<GlobalValue*, 8> &asmUsed,
                 Mangler &mangler) {
  SmallString<64> Buffer;
  mangler.getNameWithPrefix(Buffer, &GV, false);

  if (GV.isDeclaration())
    return;
  if (_mustPreserveSymbols.count(Buffer))
    mustPreserveList.push_back(GV.getName().data());
  if (_asmUndefinedRefs.count(Buffer))
    asmUsed.insert(&GV);
}

static void findUsedValues(GlobalVariable *LLVMUsed,
                           SmallPtrSet<GlobalValue*, 8> &UsedValues) {
  if (LLVMUsed == 0) return;

  ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
  if (Inits == 0) return;

  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
    if (GlobalValue *GV =
        dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
      UsedValues.insert(GV);
}

void LTOCodeGenerator::applyScopeRestrictions() {
  if (_scopeRestrictionsDone) return;
  Module *mergedModule = _linker.getModule();

  // Start off with a verification pass.
  PassManager passes;
  passes.add(createVerifierPass());

  // mark which symbols can not be internalized
  MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL);
  Mangler mangler(Context, *_target->getTargetData());
  std::vector<const char*> mustPreserveList;
  SmallPtrSet<GlobalValue*, 8> asmUsed;

  for (Module::iterator f = mergedModule->begin(),
         e = mergedModule->end(); f != e; ++f)
    applyRestriction(*f, mustPreserveList, asmUsed, mangler);
  for (Module::global_iterator v = mergedModule->global_begin(),
         e = mergedModule->global_end(); v !=  e; ++v)
    applyRestriction(*v, mustPreserveList, asmUsed, mangler);
  for (Module::alias_iterator a = mergedModule->alias_begin(),
         e = mergedModule->alias_end(); a != e; ++a)
    applyRestriction(*a, mustPreserveList, asmUsed, mangler);

  GlobalVariable *LLVMCompilerUsed =
    mergedModule->getGlobalVariable("llvm.compiler.used");
  findUsedValues(LLVMCompilerUsed, asmUsed);
  if (LLVMCompilerUsed)
    LLVMCompilerUsed->eraseFromParent();

  llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
  std::vector<Constant*> asmUsed2;
  for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(),
         e = asmUsed.end(); i !=e; ++i) {
    GlobalValue *GV = *i;
    Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
    asmUsed2.push_back(c);
  }

  llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
  LLVMCompilerUsed =
    new llvm::GlobalVariable(*mergedModule, ATy, false,
                             llvm::GlobalValue::AppendingLinkage,
                             llvm::ConstantArray::get(ATy, asmUsed2),
                             "llvm.compiler.used");

  LLVMCompilerUsed->setSection("llvm.metadata");

  passes.add(createInternalizePass(mustPreserveList));

  // apply scope restrictions
  passes.run(*mergedModule);

  _scopeRestrictionsDone = true;
}

/// Optimize merged modules using various IPO passes
bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
                                          std::string &errMsg) {
  if ( this->determineTarget(errMsg) )
    return true;

  // mark which symbols can not be internalized
  this->applyScopeRestrictions();

  Module* mergedModule = _linker.getModule();

  // if options were requested, set them
  if ( !_codegenOptions.empty() )
    cl::ParseCommandLineOptions(_codegenOptions.size(),
                                const_cast<char **>(&_codegenOptions[0]));

  // Instantiate the pass manager to organize the passes.
  PassManager passes;

  // Start off with a verification pass.
  passes.add(createVerifierPass());

  // Add an appropriate TargetData instance for this module...
  passes.add(new TargetData(*_target->getTargetData()));

  PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/ false,
                                              !DisableInline);

  // Make sure everything is still good.
  passes.add(createVerifierPass());

  FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule);

  codeGenPasses->add(new TargetData(*_target->getTargetData()));

  formatted_raw_ostream Out(out);

  if (_target->addPassesToEmitFile(*codeGenPasses, Out,
                                   TargetMachine::CGFT_ObjectFile,
                                   CodeGenOpt::Aggressive)) {
    errMsg = "target file type not supported";
    return true;
  }

  // Run our queue of passes all at once now, efficiently.
  passes.run(*mergedModule);

  // Run the code generator, and write assembly file
  codeGenPasses->doInitialization();

  for (Module::iterator
         it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it)
    if (!it->isDeclaration())
      codeGenPasses->run(*it);

  codeGenPasses->doFinalization();
  delete codeGenPasses;

  return false; // success
}

/// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging
/// LTO problems.
void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) {
  for (std::pair<StringRef, StringRef> o = getToken(options);
       !o.first.empty(); o = getToken(o.second)) {
    // ParseCommandLineOptions() expects argv[0] to be program name. Lazily add
    // that.
    if ( _codegenOptions.empty() )
      _codegenOptions.push_back(strdup("libLTO"));
    _codegenOptions.push_back(strdup(o.first.str().c_str()));
  }
}
<|endoftext|>