#include <fstream>
#include <iostream>

#include "AdvScatAbsoBodyManagerMLF.hh"
//#include "AdvPhysicalParameterDNA.hh"

/**
 * initialize struct type ScatAbosInfo variable.
 *
 * @param[inout] info AdvScatAbsoBodyManagerDNA variable
 */
void ScatAbsoInfo:: initialize() {
  this->form=undefined;
  this->rl=0.0;
  this->rs=0.0;
  this->height=0.0;
  this->atomname.clear();
  this->atomDensityRatio.clear();
  this->ratioT=0.0;
  this->temperature=0.0;
  this->gasPressure=0.0;
  this->weightPerVolume=0.0;
  this->effectiveAtomicWeight=0.0;
  this->totalDensity=0.0;
}


/////////////////////////////////////////////////////////////////////////////////////////////
// [20140414 AS start]
/**
 * A constructor
 *
 * set default atomicDataFile
 */
AdvScatAbsoBodyManagerMLF:: AdvScatAbsoBodyManagerMLF(void){
    atomicDataFileType=0;

    //atomicDataFile="/home/dnaadmin/ana/setup/database/all_nist_data.dat";
    // #[inamura 190322] put "all_nist_data.dat" into MLF/database
    atomicDataFile = "";
    const char *manyo_path_c = getenv("MANYO_PATH");
    const char *mlfsoft_path_c = getenv("MLFSOFT_PATH");
    std::string manyo_path = "";
    std::string mlfsoft_path = "";
    if (manyo_path_c != NULL){
        std::string tmp(manyo_path_c);
        manyo_path = tmp;
    }
    if (mlfsoft_path_c != NULL){
        std::string tmp(mlfsoft_path_c);
        mlfsoft_path = tmp;
    }
    std::string atomic_data_file = "";
    if (manyo_path != ""){
        char target_path_c[400];
        std::snprintf(target_path_c, sizeof(target_path_c), "%s/share/Manyo/MLF/database/all_nist_data.dat",manyo_path.c_str());
        std::fstream foAtomicData(target_path_c, std::ios::in);
        if (!(foAtomicData.fail())) atomic_data_file = (std::string)target_path_c;
        else{
            std::cout << "WARNING : AdvScatAbsoBodyManagerMLF constructer >> not found (" << (std::string)target_path_c << ") " << std::endl;
            foAtomicData.close();
        }
    }
    if ((atomic_data_file == "") && (mlfsoft_path != "")){
        char target_path_c[400];
        std::snprintf(target_path_c, sizeof(target_path_c), "%s/share/Manyo/MLF/database/all_nist_data.dat",mlfsoft_path.c_str());
        std::fstream foAtomicData(target_path_c, std::ios::in);
        if (!(foAtomicData.fail())) atomic_data_file = (std::string)target_path_c;
        else {
            std::cout << "WARNING : AdvScatAbsoBodyManagerMLF constructer >> not found (" << (std::string)target_path_c << ") " << std::endl;
            foAtomicData.close();
        }
    }
    if ((atomic_data_file == "") && (manyo_path != "")){
        char target_path_c[400];
        std::snprintf(target_path_c, sizeof(target_path_c), "%s/../../../share/Manyo/MLF/database/all_nist_data.dat",manyo_path.c_str());
        std::fstream foAtomicData(target_path_c, std::ios::in);
        if (!(foAtomicData.fail())) atomic_data_file = (std::string)target_path_c;
        else {
            std::cout << "WARNING : AdvScatAbsoBodyManagerMLF constructer >> not found (" << (std::string)target_path_c << ") " << std::endl;
            foAtomicData.close();
        }
    }
    if (atomic_data_file == ""){
        std::cerr << "WARNING :: AdvScatAbsoBodyManagerMlf::constructor >> not found atomic data file." << std::endl;
    }else{
        atomicDataFile = atomic_data_file;
        std::cout << "AdvScatAbsoBodyManagerMlf::constructor >> found atomic data file = " << atomicDataFile << std::endl;
    }
    // std::cout << "#[inamura 251008] AdvScatAbsoBodyManagerMlf constructor >> atomicDataFile = " << atomicDataFile << std::endl;
    /*
    if (manyo_path_c!=NULL){
        std::string manyo_path( manyo_path_c );
        if (manyo_path!=""){
            char target_path_c[400];
            std::snprintf( target_path_c, sizeof(target_path_c), "%s/share/Manyo/MLF/database/all_nist_data.dat",manyo_path.c_str());
            std::string atomic_data_file( target_path_c );
            atomicDataFile = atomic_data_file;
        }
    } */

    if (SearchDataBase()){
    }else{
        std::cerr << "ERROR :: AdvScatAbsoBodyManagerMLF constructure >> atomic datapath is not found " << std::endl;
    }
    //std::cout << "atomic_datapath(default) = " << atomicDataFile << std::endl; [151008 inamura]

    cohCSF=-1.0;  // [20140414 AS]
    incCSF=-1.0;  // [20140414 AS]
    absCSF=-1.0;  // [20140414 AS]
    //cohCSF=0.5; // [20140414 AS]
    //incCSF=0.5; // [20140414 AS]
    //absCSF=1.0; // [20140414 AS]
    }
/////////////////////////////////////////////////////////////////////////////////////////////
AdvScatAbsoBodyManagerMLF:: AdvScatAbsoBodyManagerMLF(std::string filepath){
    atomicDataFileType=0;
    atomicDataFile=filepath;
    if (SearchDataBase()){
    }else{
        std::cerr << "AdvScatAbsoBodyManagerMLF::AdvScatAbsoBodyManagerMLF("+filepath+") >> atomic datapath is not found " << std::endl;
    }
    std::cout << "AdvScatAbsoBodyManagerMLF::AdvScatAbsoBodyManagerMLF >> atomic_datapath = " << atomicDataFile << std::endl;

    cohCSF=-1.0;  // [20140414 AS]
    incCSF=-1.0;  // [20140414 AS]
    absCSF=-1.0;  // [20140414 AS]
    //cohCSF=0.5; // [20140414 AS]
    //incCSF=0.5; // [20140414 AS]
    //absCSF=1.0; // [20140414 AS]
    }
/////////////////////////////////////////////////////////////////////////////////////////////
bool AdvScatAbsoBodyManagerMLF:: SearchDataBase(){
    std::fstream fo(atomicDataFile.c_str(), std::ios::in);
    if(!(fo.fail())){
        fo.close();
        return true;
    }

    std::string basename("all_nist_data.dat");
    const char *home_path_c = getenv("HOME");
    char target_path_c[400];
    if (home_path_c!=NULL){
        std::string home_path( home_path_c);
        if (home_path!=""){
            std::snprintf( target_path_c, sizeof(target_path_c), "%s/ana/setup/database/%s",home_path.c_str(),basename.c_str() );
            std::fstream fo2(target_path_c, std::ios::in);
            if (!(fo2.fail())){
                atomicDataFile = target_path_c;
                fo2.close();
                return true;
            }
        }
    }

    atomicDataFile = "";
    return false;
}
/////////////////////////////////////////////////////////////////////////////////////////////
bool AdvScatAbsoBodyManagerMLF:: SetDataBaseFile(std::string filepath){
    atomicDataFile = filepath;
    return SearchDataBase();
}
/////////////////////////////////////////////////////////////////////////////////////////////
void AdvScatAbsoBodyManagerMLF:: SetAtomicDataFile(std::string filepath){
    atomicDataFileType=0;
    atomicDataFile=filepath;
    std::cout << "atomic_datapath(  new  ) = " << atomicDataFile << std::endl;
    }
/////////////////////////////////////////////////////////////////////////////////////////////
void AdvScatAbsoBodyManagerMLF:: SetSigmaCoefficient(Double Fcof, Double Finc, Double Fabs){
    cohCSF=Fcof;
    incCSF=Finc;
    absCSF=Fabs;
    }
/////////////////////////////////////////////////////////////////////////////////////////////
void AdvScatAbsoBodyManagerMLF:: SetSigmaCoefficient(ElementContainerArray qeeca, Double Finc, Double Fabs){
    cohCSF=-1.0;
    incCSF=Finc;
    absCSF=Fabs;

    UInt4 NumOfQ = qeeca.PutTableSize();
    Double sumVal=0;
    cohCSF_Qx.clear();
    cohCSF_Qy.clear();

    for(UInt4 q=0; q<NumOfQ; q++)
        {
        ElementContainer qeec=qeeca.Put(q);
        std::vector<Double> ecY=qeec.PutY();
        UInt4 NumOfHw =(UInt4)( ecY.size());
        Double val =0;
        Double qval=q;
        for(UInt4 hw=0;hw<NumOfHw;hw++)
            {
            val+=ecY.at(hw);
            }
        sumVal+=val;

        if (qeec.PutHeader().CheckKey("XRANGE")==1)
            {
            std::vector<Double> xrange;
            xrange = qeec.PutHeader().PutDoubleVector("XRANGE");
            qval=(xrange[0]+xrange[1])*0.5;
            }
        cohCSF_Qx.push_back(qval);
        cohCSF_Qy.push_back(val*qval);
        }

    UInt4 vecSize=(UInt4)(cohCSF_Qy.size());
    for(UInt4 i=0; i<vecSize; i++)
        {
        if (sumVal!=0)
            cohCSF_Qy.at(i)/=sumVal;
        else
            cohCSF_Qy.at(i)=0;
        }
    }
/////////////////////////////////////////////////////////////////////////////////////////////
Double AdvScatAbsoBodyManagerMLF:: LinearInterpolation(std::vector<Double> x,std::vector<Double> y,Double qval)
    {
    UInt4 vecSize=(UInt4)(x.size());
    if (vecSize==0)
        {
        return 0.0;
        }
    else
        {
        //inialise and allocate the gsl objects
        gsl_interp *interpolation = gsl_interp_alloc(gsl_interp_linear, vecSize);
        gsl_interp_init(interpolation, &*x.begin(), &*y.begin(), vecSize);
        gsl_interp_accel *accelerator = gsl_interp_accel_alloc();

        Double value;
        //get interpolation
        value = gsl_interp_eval(interpolation, &*x.begin(), &*y.begin(), qval, accelerator);

        gsl_interp_free(interpolation);
        gsl_interp_accel_free(accelerator);

        return value;
        }
    }
/////////////////////////////////////////////////////////////////////////////////////////////
void AdvScatAbsoBodyManagerMLF:: SetQForSigmaCoefficient(Double qval)
    {
    if ( cohCSF_Qx.empty() || cohCSF_Qy.empty()|| cohCSF_Qx.size()!=cohCSF_Qy.size() )
        {
        }
    else
        {
        cohCSF = LinearInterpolation(cohCSF_Qx,cohCSF_Qy,qval);
        }
    }
/////////////////////////////////////////////////////////////////////////////////////////////
Double AdvScatAbsoBodyManagerMLF:: GetQDepCohCSF(Double qval)
    {
    if ( cohCSF_Qx.empty() || cohCSF_Qy.empty()|| cohCSF_Qx.size()!=cohCSF_Qy.size() )
        {
        return cohCSF;
        }
    else
        {
        return LinearInterpolation(cohCSF_Qx,cohCSF_Qy,qval);
        }
    }
/////////////////////////////////////////////////////////////////////////////////////////////
std::vector<Double> AdvScatAbsoBodyManagerMLF:: GetQDepCohCSF()
    {
    return cohCSF_Qy;
    }
/////////////////////////////////////////////////////////////////////////////////////////////
std::vector<Double> AdvScatAbsoBodyManagerMLF:: GetQDepCohCSFq()
    {
    return cohCSF_Qx;
    }
/////////////////////////////////////////////////////////////////////////////////////////////
Double AdvScatAbsoBodyManagerMLF:: GetCohCSF()
    {
    return cohCSF;
    }
/////////////////////////////////////////////////////////////////////////////////////////////
Double AdvScatAbsoBodyManagerMLF:: GetIncCSF()
    {
    return incCSF;
    }
/////////////////////////////////////////////////////////////////////////////////////////////
Double AdvScatAbsoBodyManagerMLF:: GetAbsCSF()
    {
    return absCSF;
    }
/////////////////////////////////////////////////////////////////////////////////////////////
Bool AdvScatAbsoBodyManagerMLF:: SigmaCoefficientIsReady()
    {
    if (cohCSF<0 || incCSF<0 || absCSF<0)
        return false;
    else
        return true;
    }
// [20140414 AS end]
/////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////
/**
 * set value to AdvScatAbsoBodyManagerDNA variable.
 *
 * @param[in] filename scatterer and/or absorbent data file
 * @param[out] wallInfo information of wall of container
 * @param[out] bodyInfo information of scatterer and/or absorbent
 */
void AdvScatAbsoBodyManagerMLF:: SetInfoData(std::string filename, struct ScatAbsoInfo *wallInfo, struct ScatAbsoInfo *bodyInfo){

  std::fstream fo(filename.c_str(), std::ios::in);
  if(fo.fail()){
    std::cerr << "AdvScatAbsoBodyManagerMLF::SetInfoData: " << __FILE__ << ":" << __LINE__ << ": could not open file: "<< filename << std::endl;
    exit(1);
  }

  UInt4 lengthBuffer=256;
  Char *buffer=new Char[lengthBuffer];
  std::string p;
  Double v1, v2;

  Double tmpAtomicWeightWall=0.0;
  Double tmpAtomicWeightBody=0.0;

  //while(fo.getline(buffer, lengthBuffer)!=NULL){
  while(fo.getline(buffer, lengthBuffer)){
    if (strlen(buffer)>lengthBuffer) {
      std::printf("something wrong.\n");
      exit(1);
    }
    else if (strlen(buffer)==0) {
      continue;
    }
    if (strncmp(buffer, "// wall", 7)==0) {
      //while(fo.getline(buffer, lengthBuffer)!=NULL){
      while(fo.getline(buffer, lengthBuffer)){

        if (strlen(buffer)>lengthBuffer) {
          std::printf("something wrong.\n");
          exit(1);
        }
        else if (strlen(buffer)==0) {
          continue;
        }
        p=strtok(buffer, " =,");
        if (p=="atom") {
          p=strtok(NULL, " =,");
          wallInfo->atomname.push_back(p);
          v2=GetAtomicWeight(p);
          p=strtok(NULL, " =,");
          Bool wt_flag = (p=="wt%") ? true : false;
          p=strtok(NULL, " =,");
          v1=atof(p.c_str());
          if (wt_flag) {  //  ratio unit is wt% (weight percent);
              wallInfo->atomDensityRatio.push_back(v1/v2);
              tmpAtomicWeightWall+=v1;
          } else {        //  ratio unit is mol% (mol ratio)
              wallInfo->atomDensityRatio.push_back(v1);
              tmpAtomicWeightWall+=v1=v1*v2;
          }
        }
        else if (p=="form") {
          p=strtok(NULL, " =,");
          if (p.find("slab")!=std::string::npos) {
            wallInfo->form=slab;
          }
          else if (p.find("cylinder")!=std::string::npos) {
            wallInfo->form=cylinder;
          }
          else if (p.find("column")!=std::string::npos) {
            wallInfo->form=column;
          }
          else {
            std::printf("wrong wall body type :: %s\n", p.c_str());
            fflush(stdout);
            exit(1);
          }

        }
        else if (p=="r_large") {
          p=strtok(NULL, " =,");
          wallInfo->rl=atof(p.c_str())*MLF_MM2M;
        }
        else if (p=="r_small") {
          p=strtok(NULL, " =,");
          wallInfo->rs=atof(p.c_str())*MLF_MM2M;
        }
        else if (p=="height") {
          p=strtok(NULL, " =,");
          wallInfo->height=atof(p.c_str())*MLF_MM2M;
        }
        else if (p=="width") {
          p=strtok(NULL, " =,");
          wallInfo->width=atof(p.c_str())*MLF_MM2M;
        }
        else if (p=="ratio_T") {
          p=strtok(NULL, " =,");
          wallInfo->ratioT=atof(p.c_str());
        }
        else if (p=="temperature") {
          p=strtok(NULL, " =,");
          wallInfo->temperature=atof(p.c_str());
        }
        else if (p=="gas_pressure") {
          p=strtok(NULL, " =,");
          wallInfo->gasPressure=atof(p.c_str());
        }
        else if (p=="weight_per_volume") {
          p=strtok(NULL, " =,");
          wallInfo->weightPerVolume=atof(p.c_str());
        }
        else if (p=="//") {
          break;
        }
      }
      break;
    }
  }

  fo.clear();
  fo.seekg(0);

  //while(fo.getline(buffer, lengthBuffer)!=NULL){
  while(fo.getline(buffer, lengthBuffer)){
    if (strlen(buffer)>lengthBuffer) {
      std::printf("something wrong.\n");
      exit(1);
    }
    else if (strlen(buffer)==0) {
      continue;
    }
    if (strncmp(buffer, "// body", 7)==0) {
      //while (fo.getline(buffer, lengthBuffer)!=NULL){
      while (fo.getline(buffer, lengthBuffer)){
        p=strtok(buffer, " =,");
        if (p=="atom") {
          p=strtok(NULL, " =,");
          bodyInfo->atomname.push_back(p.c_str());
          v2=GetAtomicWeight(p.c_str());
          p=strtok(NULL, " =,");
          Bool wt_flag = (p=="wt%") ? true : false;
          p=strtok(NULL, " =,");
          v1=atof(p.c_str());
          if (wt_flag) {
              bodyInfo->atomDensityRatio.push_back(v1/v2);
              tmpAtomicWeightBody+=v1;
          } else {
              bodyInfo->atomDensityRatio.push_back(v1);
              tmpAtomicWeightBody+=v1=v1*v2;
          }
        }
        else if (p=="form") {
          p=strtok(NULL, " =,");
          if (p.find("slab")!=std::string::npos) {
            bodyInfo->form=slab;
          }
          else if (p.find("cylinder")!=std::string::npos) {
            bodyInfo->form=cylinder;
          }
          else if (p.find("column")!=std::string::npos) {
            bodyInfo->form=column;
          }
          else {
            std::printf("wrong detector body type :: %s\n", p.c_str());
            exit(1);
          }
        }
        else if (p=="r_large") {
          p=strtok(NULL, " =,");
          bodyInfo->rl=atof(p.c_str())*MLF_MM2M;
        }
        else if (p=="r_small") {
          p=strtok(NULL, " =,");
          bodyInfo->rs=atof(p.c_str())*MLF_MM2M;
        }
        else if (p=="height") {
          p=strtok(NULL, " =,");
          bodyInfo->height=atof(p.c_str())*MLF_MM2M;
        }
        else if (p=="width") {
          p=strtok(NULL, " =,");
          bodyInfo->width=atof(p.c_str())*MLF_MM2M;
        }
        else if (p=="ratio_T") {
          p=strtok(NULL, " =,");
          bodyInfo->ratioT=atof(p.c_str());
        }
        else if (p=="temperature") {
          p=strtok(NULL, " =,");
          bodyInfo->temperature=atof(p.c_str());
        }
        else if (p=="gas_pressure") {
          p=strtok(NULL, " =,");
          bodyInfo->gasPressure=atof(p.c_str());
        }
        else if (p=="weight_per_volume") {
          p=strtok(NULL, " =,");
          bodyInfo->weightPerVolume=atof(p.c_str());
        }
        else if (p=="//") {
          break;
        }
      }
      break;
    }
  }

  delete[] buffer;
  fo.close();

  // normalization of atomDensityRatio and set effectiveAtomicWeight for wall and body
  Double sum=0.0;
  for (UInt4 i=0; i<wallInfo->atomname.size(); i++) {
    sum+=wallInfo->atomDensityRatio[i];
  }
  for (UInt4 i=0; i<wallInfo->atomname.size(); i++) {
    wallInfo->atomDensityRatio[i]/=sum;
  }
  wallInfo->effectiveAtomicWeight=tmpAtomicWeightWall/sum;

  sum=0.0;
  for (UInt4 i=0; i<bodyInfo->atomname.size(); i++) {
    sum+=bodyInfo->atomDensityRatio[i];
  }
  for (UInt4 i=0; i<bodyInfo->atomname.size(); i++) {
    bodyInfo->atomDensityRatio[i]/=sum;
  }
  bodyInfo->effectiveAtomicWeight=tmpAtomicWeightBody/sum;
}


/**
 * get atomic weight from database file
 *
 * @param[in] atomname atom name
 * @retval atomic weight
 */
Double AdvScatAbsoBodyManagerMLF:: GetAtomicWeight(std::string atomname){
  Double atomicWeight=0.0;
  std::fstream foAtomicData(atomicDataFile.c_str(), std::ios::in);
  if(foAtomicData.fail()){
    std::cerr << "Error ScatAbsoBase::GetAtomicWeight: can't open file: "<< atomicDataFile << std::endl;
    exit(1);
  }
  std::string buffer;
  UInt4 find=0;

  //while(foAtomicData && getline(foAtomicData, buffer)!=NULL){
  while(foAtomicData && getline(foAtomicData, buffer)){
    if (buffer.size()==0) {
      continue;
    }
    if(buffer.find(atomname)!=std::string::npos){
      find=1;
      buffer.erase(0, buffer.find(atomname)+atomname.size());
      while(buffer.find(" ")==0){
        buffer.erase(buffer.begin());
      }
      buffer.erase(buffer.find(" "), buffer.size());
      atomicWeight=atof(buffer.c_str());
      break;
    }
  }
  foAtomicData.close();
  if(find==0){
    std::printf("Error AdvScatAbsoBodyManagerMLF::GetAtomicWeight: somethign wrong in atom name\n");
    std::printf("Error AdvScatAbsoBodyManagerMLF::GetAtomicWeight: atomname=%s\n", atomname.c_str());
   exit(1);
  }
  return atomicWeight;
}


/**
 * get cross section data for body and wall by use of velocity rule.
 *
 * @param[in] *wInfo pointer for struct variable wallInfo
 * @param[in] *bInfo pointer for struct variable bodyInfo
 * @param[in] energy incident energy of neutron
 * @param[out] *sigmaBA absorption cross section for body
 * @param[out] *sigmaWA absorption cross section for wall
 * @param[out] *sigmaWS scattering cross section for wall
 */
void AdvScatAbsoBodyManagerMLF:: GetSigmaFromVelocityRule(struct ScatAbsoInfo *wInfo,
                                                            struct ScatAbsoInfo *bInfo,
                                                            Double energy,
                                                            Double* sigmaBA,
                                                            Double* sigmaWA,
                                                            Double* sigmaWS){
  //velocity of neutron
  Double velocity=sqrt(2.0*energy/MLF_MASS_NEUTRON);

  // obtain sigmaBA, sigmaWA, sigmaWS which are averaged by composition atoms.
  *sigmaBA=*sigmaWA=*sigmaWS=0.0;
  // wall
  for (UInt4 i=0 ; i<wInfo->atomname.size(); i++) {
    *sigmaWA+=wInfo->atomDensityRatio[i]*GetAtomSigmaFromVelocityRule(wInfo->atomname[i], 'a', velocity);
    *sigmaWS+=wInfo->atomDensityRatio[i]*GetAtomSigmaFromVelocityRule(wInfo->atomname[i], 's', velocity);
  }
  //body
  for (UInt4 i=0 ; i<bInfo->atomname.size(); i++) {
    *sigmaBA+=bInfo->atomDensityRatio[i]*GetAtomSigmaFromVelocityRule(bInfo->atomname[i], 'a', velocity);
  }
}

/**
 * return cross section obtained by velocity rule.
 *
 * @param[in] info   pointer for struct variable AdvScatAbsoBodyManagerDNA
 * @param[in] energy incident energy of neutron
 * @param[in] state  'a': absorption, 's': scattering
 * @retval cross section for wall or body
 */
Double AdvScatAbsoBodyManagerMLF:: ReturnSigmaFromVelocityRule(struct ScatAbsoInfo *info,
                                                 Double energy,
                                                 Char state){
  Double velocity=sqrt(2.0*energy/MLF_MASS_NEUTRON);
  Double sigma=0.0;
  for (UInt4 i=0 ; i<info->atomname.size(); i++) {
    sigma+=info->atomDensityRatio[i]*GetAtomSigmaFromVelocityRule(info->atomname[i], state, velocity);
  }
  return sigma;
}


/**
 * get measured value of scattering/absorption cross section of the specified nuclide or atom
 *
 * @param[in] atomname atomic name
 * @param[in] state    'a': absorption, 's': scattering, 't': total
 * @param[in] velocity incident neutron velocity
 * @retval cross section for specified atom
 */
Double AdvScatAbsoBodyManagerMLF:: GetAtomSigmaFromVelocityRule(std::string atomname, Char state, Double velocity){
  Double sigma=0.0;
  std::string typeCS;
  typeCS=atomname+"_"+state;

//  std::printf("getatomsigma\n"); fflush(stdout);
//  std::printf("atomicDataFileType=%d\n", atomicDataFileType);fflush(stdout);

  if(atomicDataFileType==0){ //in the case of NIST data
    numData=1;
    dataCS=new Double* [numData];
    for (UInt4 i=0; i<numData; i++) {
      dataCS[i]=new Double [2];
    }
    SetSigmaDataNIST(velocity, atomname, typeCS);
//    if(state=='a') {
//      sigma=dataCS[0][1]*dataCS[0][0]/velocity*BARN2M2;
//    }
//    else {
    sigma=dataCS[0][1]*MLF_BARN2M2;
//    }
  }
  else { // in the case of data made by user
  }

   //std::printf("sigma=%e\n", sigma);fflush(stdout);
   //std::printf("velocity=%e\n", velocity);fflush(stdout);

//   std::printf("atom=%s \n", atomname);fflush(stdout);

  DeleteXsDataObject();

//  std::printf("sigma=%e, BARN2M2=%e, dataCS=%e\n", sigma, BARN2M2, dataCS[0][1]);

  return sigma;
}

/**
 * set sigma by use of database file made by NIST
 *
 * @param[in] atomname atomic name
 * @param[in] typeCS mass number, atomic name and scattering type
 */
void AdvScatAbsoBodyManagerMLF:: SetSigmaDataNIST(Double velocity, std::string atomname, std::string typeCS){
  // open database file
  std::fstream foAtomicData(atomicDataFile.c_str(), std::ios::in);
  if(foAtomicData.fail()){
    std::cerr << "AdvScatAbsoBodyManagerMLF::SetSigmaDataNist: " << __FILE__ << ":" << __LINE__ << ": " << "can't open file: "<< atomicDataFile << std::endl;
    exit(1);
  }

  // get line data of database file and analyze
  UInt4 lengthBuffer=256;
  Char *buffer=new Char[lengthBuffer];
  std::string p;
  Double cohCS, incCS, scaCS, absCS;

  // if atom data is fined in database file, "find"=1.
  // dataCS[0][0] is velocity of neutron.
  // dataCS[0][1] is cross section.
  UInt4 find=0;

  //while(foAtomicData.getline(buffer, lengthBuffer)!=NULL){
  while(foAtomicData.getline(buffer, lengthBuffer)){
    if (strlen(buffer)>lengthBuffer) {
      std::printf("something wrong.\n");
      exit(1);
    }
    else if (strlen(buffer)==0) {
      continue;
    }
    p=strtok(buffer, " ");
    if(p==atomname){
      find=1;
      p=strtok(NULL, " "); // read atomic weight
      p=strtok(NULL, " "); // read velocity
      dataCS[0][0]=atof(p.c_str());
      p=strtok(NULL, " "); // read cohCS
      cohCS=atof(p.c_str());
      p=strtok(NULL, " "); // read incCS
      incCS=atof(p.c_str());
      p=strtok(NULL, " "); // read scaCS
      scaCS=atof(p.c_str());
      p=strtok(NULL, " "); // read absCS
      absCS=atof(p.c_str());
      if(typeCS.find("_t")!=std::string::npos){

        if (SigmaCoefficientIsReady())
            {
            dataCS[0][1]=incCS*incCSF + cohCS*cohCSF + absCS*absCSF*dataCS[0][0]/velocity;
            }
        else{
            dataCS[0][1]=scaCS+absCS*dataCS[0][0]/velocity;
            }

        // debug
        //std::printf("scaCS=%e\n", scaCS);fflush(stdout);
        //std::printf("absCS=%e\n", absCS);fflush(stdout);
        //std::printf("dataCS=%e\n", dataCS[0][0]);fflush(stdout);
        //std::printf("velocity=%e\n", velocity);fflush(stdout);
        //
        break;
      }
      else if(typeCS.find("_a")!=std::string::npos){
        dataCS[0][1]=absCS*dataCS[0][0]/velocity;
        break;
      }
      else if(typeCS.find("_s")!=std::string::npos){
        dataCS[0][1]=scaCS;
        break;
      }
      else if(typeCS.find("_c")!=std::string::npos){
        dataCS[0][1]=cohCS;
        break;
      }
      else if(typeCS.find("_i")!=std::string::npos){
        dataCS[0][1]=incCS;
        break;
      }
      else {
        std::cerr << "error exit"<<std::endl;
        exit(1);
      }
    }
  }

  delete[] buffer;
  foAtomicData.close();

  // treatment in the case when atomic data is not found in database.
  if(find==0){
    std::cerr << "cannot find "<<typeCS<<" in database "<<atomicDataFile<<std::endl;
    std::cerr << "error exit"<<std::endl;
    exit(1);
  }

}

/**
 * delete dynamical variable, dataCS[][]
 *
 */
void AdvScatAbsoBodyManagerMLF:: DeleteXsDataObject(void){
  for (UInt4 i=0; i<numData; i++) {
    delete[] dataCS[i];
  }
  delete dataCS;
}

/**
 * check whether an atomic data file can be loaded correctly or not.
 *
 */
bool AdvScatAbsoBodyManagerMLF:: isFoundAtomicDataFile(){
  if (atomicDataFile == "") return false;
  else return true;
}

/**
 * check whether functions can work (initialization succeeded) or not
 */
bool AdvScatAbsoBodyManagerMLF:: isReady(){
  bool isReady = true;
  isReady = isFoundAtomicDataFile();

  return isReady;
}
