Example #1
0
 PlacementRef&
 operator= (PlacementRef<X> const& r)
   {
     validate(recast (r));
     id_ = recast(r);
     return *this;
   }
void Backflow_pf_wf::init(Wavefunction_data * wfdata)
{

  Backflow_pf_wf_data * dataptr;
  recast(wfdata, dataptr);
  recast(wfdata, parent);

  nmo=dataptr->bfwrapper.nmo();
  npf=dataptr->pfkeeper.npf;
  coef_eps=dataptr->pfkeeper.coef_eps;
  //nsfunc=dataptr->pfkeeper.nsfunc;
  nelectrons.Resize(2);
  nelectrons=dataptr->pfkeeper.nelectrons;

  int tote=nelectrons(0)+nelectrons(1);
  ndim=3;

  int upuppairs=dataptr->pfkeeper.npairs(0);
  int downdownpairs=dataptr->pfkeeper.npairs(1);
  int nopairs=dataptr->pfkeeper.npairs(2);
  
  npairs=upuppairs+downdownpairs+nopairs;
    
  //Properties and intermediate calculation storage.
  moVal.Resize(10,tote, dataptr->pfkeeper.totoccupation(0).GetSize());
  updatedMoVal.Resize(dataptr->pfkeeper.totoccupation(0).GetSize(),10);
  
  inverse.Resize(npf);
  pfaffVal.Resize(npf);
  mopfaff_tot.Resize(npf);
  for (int pf=0;pf<npf;pf++){
    inverse(pf).Resize(npairs, npairs);
    inverse(pf)=0;
    
    for(int e=0; e< npairs; e++){
        inverse(pf)(e,e)=1;
    }
    pfaffVal(pf)=1;
  
    mopfaff_tot(pf).Resize(npairs,npairs);
  }

  electronIsStaleVal.Resize(tote);
  electronIsStaleLap.Resize(tote);

  electronIsStaleVal=0;
  electronIsStaleLap=0;
  updateEverythingVal=1;
  updateEverythingLap=1;
  sampleAttached=0;
  dataAttached=0;
  
  coor_grad.Resize(tote,tote,ndim,ndim);
  coor_lap.Resize(tote,tote,ndim);

  gradlap.Resize(tote,5);

  jast.init(&parent->bfwrapper.jdata);
  jast.keep_ion_dep();
}
Example #3
0
 PlacementRef&
 operator= (Y const& refID)
   {
     validate (recast (refID));
     id_ = recast (refID);
     return *this;
   }
Example #4
0
void BCS_wf::init(Wavefunction_data * wfdata)
{

    BCS_wf_data * dataptr;
    recast(wfdata, dataptr);
    recast(wfdata, parent);

    //nmo=dataptr->molecorb->getNmo();
    ndet=1;
    nelectrons.Resize(2);
    nelectrons=dataptr->nelectrons;

    int tote=nelectrons(0)+nelectrons(1);
    ndim=3;

    if(nelectrons(0) != nelectrons(1)) {
        error("For BCS wave function, the number of spin up electrons must"
              " be equal to the number of spin down electrons.");
    }

    spin.Resize(tote);
    spin=dataptr->spin;

    //moVal.Resize(tote, nmo,5);
    //updatedMoVal.Resize(nmo,5);

    detVal.Resize (ndet);
    inverse.Resize(ndet);

    for(int det=0; det < ndet; det++) {
        inverse(det).Resize(nelectrons(0), nelectrons(0));
        inverse(det)=0;
        for(int e=0; e< nelectrons(0); e++) {
            inverse(det)(e,e)=1;
            inverse(det)(e,e)=1;
        }

        detVal(det)=1;
    }


    electronIsStaleVal.Resize(tote);
    electronIsStaleLap.Resize(tote);

    electronIsStaleVal=0;
    electronIsStaleLap=0;
    updateEverythingVal=1;
    updateEverythingLap=1;
    sampleAttached=0;
    dataAttached=0;

    jast.init(&parent->jastdata);

    derivatives.Resize(2*nelectrons(0),nelectrons(1),4);

    assert(jastcof==NULL);
    jastcof=new BCS_jastrow_u;

}
void Slat_Jastrow::getForceBias(Wavefunction_data * wfdata, int e,
                                Wf_return & bias)
{


  assert(bias.amp.GetDim(0) >= nfunc_);
  assert(bias.amp.GetDim(1) >= 4);
  Slat_Jastrow_data * dataptr;
  recast(wfdata, dataptr);

  assert(dataptr != NULL);


  Wf_return slat_bias(nfunc_,4);
  Wf_return jast_bias(nfunc_,4);
  slater_wf->getForceBias(dataptr->slater, e, slat_bias);
  jastrow_wf->getForceBias(dataptr->jastrow, e, jast_bias);

  for(int i=0; i< nfunc_; i++)
  {

    //cout << "value slat " << slat_bias(i,0)*exp(slat_bias(i,1) ) << endl;
    //cout << "value jast " << jast_bias(i,0)*exp(jast_bias(i,1) ) << endl;
    bias.phase(i,0)=slat_bias.phase(i,0)+jast_bias.phase(i,0);
    bias.amp(i,0)=slat_bias.amp(i,0)+jast_bias.amp(i,0);
    //cout << "force bias " << bias(0) << endl;
    for(int d=1; d<4; d++)
    {
      bias.amp(i,d)=slat_bias.amp(i,d)+jast_bias.amp(i,d);
      bias.phase(i,d)=slat_bias.phase(i,d)+jast_bias.phase(i,d);
      bias.cvals(i,d)=slat_bias.cvals(i,d)+jast_bias.cvals(i,d);
    }
  }
}
void Backflow_pf_wf::updateVal(Wavefunction_data * wfdata,
                        Sample_point * sample)
{

  assert(sampleAttached);
  assert(dataAttached);

  Backflow_pf_wf_data * pfaffdata;
  recast(wfdata, pfaffdata);

  if(updateEverythingVal){ 
    calcVal(sample);
    updateEverythingVal=0;
    electronIsStaleVal=0;
  }
  else { 
    for(int e=0; e< nelectrons(0)+nelectrons(1); e++) {
      if(electronIsStaleVal(e)) {
	calcVal(sample);
	//updateVal(e,sample);
	electronIsStaleVal=0;
      }
    }
  }
  
  assert(sampleAttached);
  assert(dataAttached);
}
Example #7
0
void BCS_wf::saveUpdate(Sample_point * sample, int e1, int e2,
                        Wavefunction_storage * wfstore)
{
    BCS_wf_storage * store;
    recast(wfstore, store);
    jast.saveUpdate(sample,e1,e2,store->jast_store);
    store->inverse=inverse;
    store->detVal=detVal;

    //
    // unpaired electrons go into extra one-body orbitals, this
    // functionality will be resurrected later
    //
    //int nmo=moVal.GetDim(1);
    //int nd=moVal.GetDim(2);
    //for(int m=0; m< nmo; m++) {
    //  for(int d=0; d< nd; d++) {
    //    store->moVal(m,d)=moVal(e,m,d);
    //  }
    //}

    // We assume the two electrons have opposite spins
    assert( spin(e1) != spin(e2) );

    int e_up, e_down;

    e_up = spin(e1) ? e2 : e1;
    e_down = spin(e1) ? e1 : e2;


    {
        int nj=derivatives.GetDim(1);
        assert(nj==nelectrons(0));
        int nd=derivatives.GetDim(2);
        for(int j=0; j< nj; j++) {
            for(int d=0; d< nd; d++) {
                store->derivatives(j,d)=derivatives(e_up,j,d);
            }
        }
        int ep=e_up+nelectrons(0);
        for(int j=0; j< nj; j++) {
            for(int d=0; d< nd; d++) {
                store->derivatives(j+nelectrons(0),d)=derivatives(ep,j,d);
            }
        }
    }
    {
        int ni=derivatives.GetDim(0);
        assert(ni==2*nelectrons(0));
        int nd=derivatives.GetDim(2);
        int rede=e_down-nelectrons(0);
        for(int i=0; i< ni; i++) {
            for(int d=0; d< nd; d++) {
                store->derivatives_2(i,d)=derivatives(i,rede,d);
            }
        }
    }

}
Example #8
0
void BCS_wf::restoreUpdate(Sample_point * sample, int e,
                           Wavefunction_storage * wfstore)
{

    BCS_wf_storage * store;
    recast(wfstore, store);

    jast.restoreUpdate(sample,e,store->jast_store);
    detVal=store->detVal;
    inverse=store->inverse;

    //
    // unpaired electrons go into extra one-body orbitals, this
    // functionality will be resurrected later
    //
    //int nmo=moVal.GetDim(1);
    //int nd=moVal.GetDim(2);
    //for(int m=0; m< nmo; m++) {
    //  for(int d=0; d< nd; d++) {
    //    moVal(e,m,d)=store->moVal(m,d);
    //  }
    //}

    if(spin(e)==0) {
        int nj=derivatives.GetDim(1);
        assert(nj==nelectrons(0));
        int nd=derivatives.GetDim(2);
        for(int j=0; j< nj; j++) {
            for(int d=0; d< nd; d++) {
                derivatives(e,j,d)=store->derivatives(j,d);
            }
        }
        int ep=e+nelectrons(0);
        for(int j=0; j< nj; j++) {
            for(int d=0; d< nd; d++) {
                derivatives(ep,j,d)=store->derivatives(j+nelectrons(0),d);
            }
        }
    }
    else {
        int ni=derivatives.GetDim(0);
        assert(ni==2*nelectrons(0));
        int nd=derivatives.GetDim(2);
        int rede=e-nelectrons(0);
        for(int i=0; i< ni; i++) {
            for(int d=0; d< nd; d++) {
                derivatives(i,rede,d)=store->derivatives(i,d);
            }
        }
    }


    electronIsStaleLap=0;
    electronIsStaleVal=0;
    updateEverythingLap=0;
    updateEverythingVal=0;

    //calcLap(sample);
}
void Backflow_pf_wf::generateStorage(Wavefunction_storage * & wfstore)
{
  wfstore=new  Backflow_pf_wf_storage;
  Backflow_pf_wf_storage * store;
  recast(wfstore, store);
  store->gradlap=gradlap;
  store->pfaffVal=pfaffVal;
}
void Slat_Jastrow::generateStorage(Wavefunction_storage * & wfstore)
{
  wfstore=new Slat_Jastrow_storage;
  Slat_Jastrow_storage * store;
  recast(wfstore, store);
  slater_wf->generateStorage(store->slat_store);
  jastrow_wf->generateStorage(store->jast_store);
}
void Slat_Jastrow::updateForceBias(Wavefunction_data * wfdata, Sample_point * sample)
{
  Slat_Jastrow_data * dataptr;
  recast(wfdata, dataptr);
  assert(dataptr != NULL);
  slater_wf->updateForceBias(dataptr->slater, sample);
  jastrow_wf->updateForceBias(dataptr->jastrow, sample);
}
void Slat_Jastrow::restoreUpdate(Sample_point * sample, int e1, int e2, Wavefunction_storage * wfstore)
{
  //cout << "restoreUpdate\n";
  Slat_Jastrow_storage * store;
  recast(wfstore, store);

  slater_wf->restoreUpdate(sample, e1, e2, store->slat_store);
  jastrow_wf->restoreUpdate(sample, e1, e2, store->jast_store);
}
void Backflow_pf_wf::saveUpdate(Sample_point * sample, int e,
                         Wavefunction_storage * wfstore)
{
  Backflow_pf_wf_storage * store;
  recast(wfstore, store);
  store->gradlap=gradlap;
  store->pfaffVal=pfaffVal;
	
}
void Slat_Jastrow::saveUpdate(Sample_point * sample, int e1, int e2, Wavefunction_storage * wfstore)
{
  Slat_Jastrow_storage * store;
  recast(wfstore, store);

  slater_wf->saveUpdate(sample, e1, e2, store->slat_store);
  jastrow_wf->saveUpdate(sample, e1, e2, store->jast_store);

}
Example #15
0
void BCS_wf::generateStorage(Wavefunction_storage * & wfstore)
{
    wfstore=new BCS_wf_storage;
    BCS_wf_storage * store;
    recast(wfstore, store);
    jast.generateStorage(store->jast_store);
    store->inverse=inverse;
    store->detVal=detVal;
    //store->moVal.Resize(moVal.GetDim(1),moVal.GetDim(2));
    store->derivatives.Resize(derivatives.GetDim(0),derivatives.GetDim(2));
    store->derivatives_2.Resize(derivatives.GetDim(0),derivatives.GetDim(2));
}
void Backflow_pf_wf::restoreUpdate(Sample_point * sample, int e,
                            Wavefunction_storage * wfstore)
{
  Backflow_pf_wf_storage * store;
  recast(wfstore, store);
  gradlap=store->gradlap;
  pfaffVal=store->pfaffVal;
	  
  electronIsStaleLap=0;
  electronIsStaleVal=0;
  updateEverythingLap=0;
  updateEverythingVal=0;
}
void Slat_Jastrow::init(Wavefunction_data * wfdata)
{
  Slat_Jastrow_data * dataptr;
  recast(wfdata, dataptr);
  dataptr->slater->generateWavefunction(slater_wf);
  dataptr->jastrow->generateWavefunction(jastrow_wf);
  if(jastrow_wf->nfunc() != slater_wf->nfunc())
  {
    error("You must put the same number of functions in the "
          "functions to be multiplied in SLAT-JASTROW.");
  }
  nfunc_=slater_wf->nfunc();
}
// JK: complex wavefunctions still behave weird, let's try to rewrite even
// this one, not touching cvals now, though
// The most important is setting is_complex, but I do differ at other places
// too.
void Slat_Jastrow::getLap(Wavefunction_data * wfdata, int e,
                          Wf_return & lap)
{
  //cout << "getLap\n";
  assert(lap.amp.GetDim(0) >= nfunc_);
  assert(lap.amp.GetDim(1) >= 5);
  Slat_Jastrow_data * dataptr;
  recast(wfdata, dataptr);
  assert(dataptr != NULL);

  Wf_return slat_lap(nfunc_,5);
  Wf_return jast_lap(nfunc_,5);

  slater_wf->getLap(dataptr->slater, e, slat_lap);
  jastrow_wf->getLap(dataptr->jastrow, e, jast_lap);

  if ( slat_lap.is_complex==1 || jast_lap.is_complex==1 )
    lap.is_complex=1;

  for(int i=0; i< nfunc_; i++)
  {

    lap.phase(i,0)=slat_lap.phase(i,0)+jast_lap.phase(i,0);
    lap.amp(i,0)=slat_lap.amp(i,0)+jast_lap.amp(i,0);
    doublevar dotproduct=0;
    dcomplex dot(0.0, 0.0);
    for(int d=1; d<4; d++)
    {
      lap.amp(i,d)=slat_lap.amp(i,d)+jast_lap.amp(i,d);
      lap.phase(i,d)=slat_lap.phase(i,d)+jast_lap.phase(i,d);
      dotproduct+=slat_lap.amp(i,d)*jast_lap.amp(i,d);

      lap.cvals(i,d)=slat_lap.cvals(i,d)+jast_lap.cvals(i,d);
      dot+=slat_lap.cvals(i,d)*jast_lap.cvals(i,d);
    }

    lap.amp(i,4)=slat_lap.amp(i,4)+jast_lap.amp(i,4)
      +2*dotproduct;
    lap.phase(i,4)=slat_lap.phase(i,4)+jast_lap.phase(i,4);

    lap.cvals(i,4)=slat_lap.cvals(i,4)+jast_lap.cvals(i,4)
      +2.0*dot;

  }
}
void Slat_Jastrow::getSymmetricVal(Wavefunction_data * wfdata,
			     int e, Wf_return & val){

  Wf_return slat_val(nfunc_, 2);
  Wf_return jast_val(nfunc_, 2);
 
  Slat_Jastrow_data * dataptr;
  recast(wfdata, dataptr);
  assert(dataptr != NULL);
  
  slater_wf->getSymmetricVal(dataptr->slater, e, slat_val);
  jastrow_wf->getSymmetricVal(dataptr->jastrow, e, jast_val);

  //cout <<"slat_val.amp(0,0) "<<slat_val.amp(0,0)<<"  jast_val.amp(0,0) "<<jast_val.amp(0,0)<<endl;

  for(int i=0; i< nfunc_; i++) {
    val.amp(i,0)=slat_val.amp(i,0)+jast_val.amp(i,0);  //add the logarithm
  }
}
void Slat_Jastrow::getVal(Wavefunction_data * wfdata,
                          int e, Wf_return & val)
{
  assert(val.amp.GetDim(0) >= nfunc_);
  Wf_return slat_val(nfunc_, 2);
  Wf_return jast_val(nfunc_, 2);
  Slat_Jastrow_data * dataptr;
  recast(wfdata, dataptr);
  assert(dataptr != NULL);
  
  slater_wf->getVal(dataptr->slater, e, slat_val);
  jastrow_wf->getVal(dataptr->jastrow, e, jast_val);

  if ( slat_val.is_complex==1 || jast_val.is_complex==1 )
    val.is_complex=1;


  for(int i=0; i< nfunc_; i++) {
    val.phase(i,0)=slat_val.phase(i,0)+jast_val.phase(i,0); 
    val.amp(i,0)=slat_val.amp(i,0)+jast_val.amp(i,0);  //add the logarithm
  }
}
Example #21
0
 static _Id const&
 bottomID ()  ///< @return marker for \em invalid reference
   {
     static lumiera_uid invalidLUID;
     return recast (&invalidLUID);
   }
int Slat_Jastrow::getParmDeriv(Wavefunction_data *  wfdata, 
			       Sample_point * sample ,
			       Parm_deriv_return & derivatives){

  //cout <<"Slat_Jastrow::getParmDeriv"<<endl;
  Slat_Jastrow_data * dataptr;
  recast(wfdata, dataptr);
  assert(dataptr != NULL);
   
  Parm_deriv_return slaterval;
  Parm_deriv_return jastval;
  slaterval.need_hessian=jastval.need_hessian=derivatives.need_hessian;
  
  int nslater=dataptr->slater->nparms();
  int njast=dataptr->jastrow->nparms();
  int nparms=derivatives.nparms_end-derivatives.nparms_start;
  if (derivatives.nparms_start<nslater){
    slaterval.nparms_start=derivatives.nparms_start;
    jastval.nparms_start=0;
    
  }
  else{
    jastval.nparms_start=derivatives.nparms_start-nslater;
    slaterval.nparms_start=nslater;
  }
  if (derivatives.nparms_end <= nslater){
    slaterval.nparms_end=derivatives.nparms_end;
    jastval.nparms_end=0;
  }
  else{
    jastval.nparms_end=derivatives.nparms_end-nslater;
    slaterval.nparms_end=nslater;
  }
  
  //cout <<slaterval.nparms_start<<" "<<slaterval.nparms_end<<"  "
  //   <<jastval.nparms_start<<" "<<jastval.nparms_end<<endl;
  

  
  //new way with usage of extend_parm_deriv; 
  //works as well, you can decrease nparms to be calculated in slater part
  //but not in jastrow part

  Parm_deriv_return retparm;
  retparm.need_hessian=derivatives.need_hessian;
  retparm.nparms_start=derivatives.nparms_start;
  retparm.nparms_end=derivatives.nparms_end;
  retparm.val_gradient.Resize(sample->electronSize(),5);
  retparm.val_gradient=0.0;
  if (slaterval.nparms_end-slaterval.nparms_start){
    slater_wf->getParmDeriv(dataptr->slater,sample, slaterval);
    //cout <<"adding slater"<<endl;
    //extend_parm_deriv(retparm,slaterval);
    retparm=slaterval;
  }
  
  if (jastval.nparms_end-jastval.nparms_start){
    if(jastval.nparms_end-jastval.nparms_start!=njast)
      error("jastval.nparms_end-jastval.nparms_start!=njast is not supported");
    jastrow_wf->getParmDeriv(dataptr->jastrow,sample, jastval);
    //cout<<"adding jastrow"<<endl;
    extend_parm_deriv(retparm,jastval);
  }
  
  derivatives=retparm;
  

  //good old way, works even for the case jastval.nparms_end-jastval.nparms_start!=njast
  /*
  if(nslater)
    slater_wf->getParmDeriv(dataptr->slater,sample, slaterval);
  if(njast)
    jastrow_wf->getParmDeriv(dataptr->jastrow,sample, jastval);
  derivatives.gradient.Resize(nparms);
    for (int i=0;i<nparms;i++){
    if(derivatives.nparms_start+i<nslater)
      derivatives.gradient(i)=slaterval.gradient(i);
    else
      derivatives.gradient(i)=jastval.gradient(i-nslater+derivatives.nparms_start);
  }
  
  if(derivatives.need_hessian){
    derivatives.hessian.Resize(nparms,nparms);
    for(int i=0;i<nparms;i++){
      for(int j=i;j<nparms;j++){
        if(i+derivatives.nparms_start<nslater)
          if (j+derivatives.nparms_start<nslater)
            derivatives.hessian(i,j)=slaterval.hessian(i,j);
          else
            derivatives.hessian(i,j)=slaterval.gradient(i)*jastval.gradient(j-nslater+derivatives.nparms_start);
        else
          derivatives.hessian(i,j)=jastval.hessian(i-nslater+derivatives.nparms_start,j-nslater+derivatives.nparms_start);
        derivatives.hessian(j,i)=derivatives.hessian(i,j);
      }
    }
  }
  */
  return 1;
}
Example #23
0
void MelaReweighterWW::setupDaughters(bool isVBF, const int& id_l1,  const int& id_l2, const int& id_n1, const int& id_n2,
                    const TLorentzVector& l1, const TLorentzVector& l2, const TLorentzVector& n1, const TLorentzVector& n2,
                    const std::vector<TLorentzVector>& associated, const std::vector<int>& idsAssociated,
                    const std::vector<TLorentzVector>& mothers, const std::vector<int>& idsMothers){
 
  _isVBF=isVBF;
  _daughters->clear();
  _daughters->push_back(SimpleParticle_t(id_l1, l1));
  _daughters->push_back(SimpleParticle_t(id_l2, l2));
  _daughters->push_back(SimpleParticle_t(id_n1, n1));
  _daughters->push_back(SimpleParticle_t(id_n2, n2));
  _associated->clear();
  for (unsigned int i = 0; i < associated.size(); ++i){
    _associated->push_back(SimpleParticle_t(idsAssociated[i], associated[i]));
  }
  _mothers->clear();
  bool hasOneGluon = false;
  for (unsigned int i = 0; i < mothers.size(); ++i){
    _mothers->push_back(SimpleParticle_t(idsMothers[i], mothers[i]));
    if (idsMothers[i] == 22)
      hasOneGluon = true;
  }

  if (_candModified != 0){
    delete _candModified;
    _candModified = 0;
  }

  _mela->resetInputEvent();
  //check charge        
  double chargeIn = 0;
  for (unsigned int i = 0; i < _mothers->size(); ++i){
    MELAParticle p(_mothers->at(i).first, _mothers->at(i).second);
    chargeIn+=p.charge();
  }
  double chargeOut = 0;
  for (unsigned int i = 0; i < _associated->size(); ++i){
    MELAParticle p(_associated->at(i).first, _associated->at(i).second);
    chargeOut+=p.charge();
  }
  bool toRecast=true;
  if (chargeIn != chargeOut){
    toRecast =  false;
    //just kill the unwanted particle
    for (unsigned int i = 0; i < _associated->size(); ++i){
      int id=_associated->at(i).first;
      bool antiParticleInInitialState=false;
      for (unsigned int j = 0; j < _mothers->size(); ++j){
        if (id==-_mothers->at(j).first){
          //cout << "Skipping " << id << endl;
          antiParticleInInitialState=true;
        }  
      }    
      if (antiParticleInInitialState)
        _associated->erase(_associated->begin()+i);
    }    
  }  

  _mela->setInputEvent(_daughters, _associated, _mothers, true); 
  if (isVBF){
    bool recasted = recast();
    if (!recasted) {
      //just remove the gluon
      for (unsigned int i = 0; i < _associated->size(); ++i){
        int id=_associated->at(i).first;
        if (id == 21)
          _associated->erase(_associated->begin()+i);
      }
      _mela->setInputEvent(_daughters, _associated, _mothers, true);  
    }
  }

}                    
Example #24
0
 PlacementRef (PlacementRef<X> const& r) ///< extended copy ctor, when type X is assignable to MX
   : id_(recast(r))
   {
     validate(id_); 
   }
Example #25
0
 explicit
 PlacementRef (Y const& refID)
   : id_(recast (refID))
   { 
     validate(id_); 
   }
Example #26
0
int main(int argc, char **argv) {
    
    /* the times recorded are: 
     start of programm, start of chain generation,
     end of chain generation, end of programm */
    double time[4];
    time[0] = time_of_day();
    
    
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    // open all neccessary files
    
    // general output file, contains basically everything which was written to the terminal
    FILE * output_file;
    output_file = fopen("output_file.dat", "w+");
    
    FILE * conv_obs_file;
    conv_obs_file = fopen("convergence_obs.dat", "w+");
    
    // pair correlation function can be weighted with potentials
    FILE * pair_correl_file;
    pair_correl_file = fopen("pair_correlation_function.dat", "w+");
    
    //------------------------------------------------------------------------------
    // all files connected to intramolecular interactions

    FILE * intra_pot_file;
    intra_pot_file = fopen("intramolecular_obs.dat", "w+");
    
    FILE * intra_boltzman_factors_hist;
    intra_boltzman_factors_hist = fopen("intramolecular_factors_hist.dat", "w+");
    
    FILE * intra_interactions_file;
    intra_interactions_file = fopen("intramolecular_interactions_hist.dat", "w+");
    
 //   FILE * intra_interactions_testfile;
 //   intra_interactions_testfile = fopen("intramolecular_interactions_testhist.dat", "w+");
    
    FILE * convergence_intraweights;
    convergence_intraweights = fopen("intramolecular_convergence_Z.dat", "w+");
    fprintf(convergence_intraweights, "### convergence_point -- sum-of-boltzman-factors \n");
    
    FILE * conv_intraobs_file;
    conv_intraobs_file = fopen("intramolecular_convergence_obs.dat", "w+");

    
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    // input and first output
    
    
    // hello message of the programm, always displayed!
    
    log_out(output_file, "\n-----------------------------------------------------------------------------------\n");
    log_out(output_file, "Roulattice version 1.1, Copyright (C) 2015 Johannes Dietschreit\n");
    log_out(output_file, "This program comes with ABSOLUTELY NO WARRANTY; for version details type '-info'.\n");
    log_out(output_file, "This is free software, and you are welcome to redistribute it\n");
    log_out(output_file, "under certain conditions; type '-license' for details.\n");
    log_out(output_file, "\tQuestions and bug reports to: [email protected]\n");
    log_out(output_file, "\tPlease include in published work based on Roulattice:\n");
    log_out(output_file, "\t\tDietschreit, J. C. B.; Diestler, D. J.; Knapp, E. W.,\n");
    log_out(output_file, "\t\tModels for Self-Avoiding Polymer Chains on the Tetrahedral Lattice.\n");
    log_out(output_file, "\t\tMacromol. Theory Simul. 2014, 23, 452-463\n");
    log_out(output_file, "-----------------------------------------------------------------------------------\n");
    
    
    
    /* get the arguments from the comand line */
    getArgs(output_file, argc, argv);
    
    
    //------------------------------------------------------------------------------------
    // for reading DCD-files
    // this has to be early in the code, because it sets the variables ARG_numberofbeads and ARG_numberofframes!
    
    // variables concerning reading dcd
    molfile_timestep_t timestep;
    void *v;
    dcdhandle *dcd;
    int natoms;
    float sizeMB =0.0, totalMB = 0.0;
    // reading the dcd-file and setting global variables accordingly
    if (ARG_typeofrun==0) {
        natoms = 0;
        v = open_dcd_read(dcdFileName, "dcd", &natoms);
        if (!v) {
            fprintf(stderr, "ERROR: open_dcd_read failed for file %s\n", dcdFileName);
            return EXIT_FAILURE;
        }
        
        dcd = (dcdhandle *)v;
        sizeMB = ((natoms * 3.0) * dcd->nsets * 4.0) / (1024.0 * 1024.0);
        totalMB += sizeMB;
        
        log_out(output_file, "Read DCD: %d atoms, %d frames, size: %6.1fMB\n", natoms, dcd->nsets, sizeMB);
        
        timestep.coords = (float *)malloc(3*sizeof(float)*natoms);
        
        ARG_numberofbeads=dcd->natoms;
        ARG_numberofframes=dcd->nsets;
    }
    //------------------------------------------------------------------------------------
    

    // print all the options to the screen so one can check whether the right thing gets computed
    print_set_options(output_file, ARG_typeofrun, ARG_flength, ARG_fflength, ARG_blength, ARG_numberofbeads, ARG_numberofframes, ARG_randomseed, ARG_bondlength, ARG_torsion, ARG_intra_potential, ARG_intra_parameter1, ARG_intra_parameter2);
    
    
    
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    // physical constants
    
    pi = acos(-1.0);
    
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    
    
    /* Initialize the most important variables */
    
    // stuff with bond lengths
    const double inv_sqrt3 = 1.0/sqrt(3.0);
    const double bondlength = ARG_bondlength;
    double recast_factor;
    if (ARG_typeofrun<40){// this recasts walk on diamond lattice
        recast_factor = inv_sqrt3*bondlength;
    }
    else {// this is for runs on simple cubic lattice
        recast_factor = bondlength;
    }
    
    // variables with atom numbers etc
    const int last_atom = ARG_numberofbeads -1;
    const unsigned int number_of_torsions = ARG_numberofbeads -3;
    // number of frag, fragfags, endfrags, fragbricks, endbricks
    unsigned int numof_frags_bricks[5] = {0};
    
    
    // fractions of the number of frames
    const unsigned long permill_frames = ARG_numberofframes / 1000; // used for convergence
    const unsigned long percent_frames = ARG_numberofframes / 100; // used for ramining time
    const unsigned long tenth_frames = ARG_numberofframes / 10; // used for error estimation
    int cent;
    int tenth;
    
    int counter; // counter which can be used at any parts of the main programm, should only be used locally in a loop
    
    
    // basic moves on the tetrahedral lattice, back and forth
    const int move[2][4][3] = {
        {
            {-1, -1, -1},
            {1, 1, -1},
            {1, -1, 1},
            {-1, 1, 1}
        },
        {
            {1, 1, 1},
            {-1, -1, 1},
            {-1, 1, -1},
            {1, -1, -1}
        }
    };
    
    // moves possible in SAW (no walking back)
    const int sawmoves[4][3] = {
        {1, 2, 3},
        {0, 2, 3},
        {0, 1, 3},
        {0, 1, 2}
    };
    
    
    //-----------------------------------------------------------------------
    // building bricks are used to put parts together which are pre-checked
    int ***building_bricks=NULL;
    
    int numberofbricks;
    
    if (ARG_typeofrun==13 || ARG_typeofrun==14 || ARG_typeofrun==23 || ARG_typeofrun==24 || ARG_typeofrun==33 || ARG_typeofrun==34){
        
        // thise generates the bricks
        building_bricks = make_bricks_saw(building_bricks, move, sawmoves, ARG_blength, &numberofbricks, ARG_strictness);
        if (NULL==building_bricks[0][0]){
            return EXIT_FAILURE;
        }
        
        log_out(output_file, "%d bricks were generated, with a length of %d \n", numberofbricks, ARG_blength);
        
    }
    
    
    
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    /* Initialize beads vector and set all values to zero */
    int **int_polymer;
    int_polymer = calloc(ARG_numberofbeads, sizeof(int *));
    
    double **double_polymer;
    double_polymer = calloc(ARG_numberofbeads, sizeof(double *));
    
    for (int dim1=0; dim1<ARG_numberofbeads;dim1++){
        
        int_polymer[dim1] = calloc(3, sizeof(int *));
        double_polymer[dim1] = calloc(3, sizeof(double *));
        
    }
    
    
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    // observables
    
    OBSERVABLE normal_obs;
    
    normal_obs.maxee = 0.0; // maximal stretch of polymer
    
    OBSERVABLE intra_obs[100];

    //-------------------------------------------------------
    // initialization of all the OBSERVABLE variables
    //-------------------------------------------------------
    
    normal_obs.err_ee2 = (double *) calloc(11, sizeof(double));
    if(NULL == normal_obs.err_ee2) {
        fprintf(stderr, "Allocation of ee2 variable failed! \n");
        return EXIT_FAILURE;
    }
    normal_obs.err_rgyr = (double *) calloc(11, sizeof(double));
    if(NULL == normal_obs.err_rgyr) {
        fprintf(stderr, "Allocation of rgyr variable failed! \n");
        return EXIT_FAILURE;
    }
    
    if (ARG_intra_potential>0) {
        for (int dim1=0; dim1<100; dim1++) {
            intra_obs[dim1].err_ee2 =(double *) calloc(11, sizeof(double));
            intra_obs[dim1].err_rgyr =(double *) calloc(11, sizeof(double));
            if(NULL == intra_obs[dim1].err_ee2 || NULL == intra_obs[dim1].err_rgyr) {
                fprintf(stderr, "Allocation of ee2 or rgyr variable (intramolecular) failed! \n");
                return EXIT_FAILURE;
            }
        }
    }
    
    
    // initializes the observables for torsional analysis (optional)
    if (ARG_torsion==1) {
        normal_obs.err_pt = (double *) calloc(11, sizeof(double));
        if(NULL == normal_obs.err_pt) {
            fprintf(stderr, "Allocation of torsion variable failed! \n");
            return EXIT_FAILURE;
        }
        
        if (ARG_intra_potential>0) {
            for (int dim1=0; dim1<100; dim1++) {
                intra_obs[dim1].pt = 0.0;
                intra_obs[dim1].err_pt = (double *) calloc(11, sizeof(double));
                if(NULL == intra_obs[dim1].err_pt) {
                    fprintf(stderr, "Allocation of torsion variable (intramolecular) failed! \n");
                    return EXIT_FAILURE;
                }
            }
        }
    }
    
    // initializes the observables for loss of solven accessible surface area analysis (optional)
    if (ARG_sasa==1){
        normal_obs.err_dsasa = (double *) calloc(11, sizeof(double));
        if(NULL == normal_obs.err_dsasa) {
            fprintf(stderr, "Allocation of D-SASA variable failed! \n");
            return EXIT_FAILURE;
        }
        
        if (ARG_intra_potential>0) {
            for (int dim1=0; dim1<100; dim1++) {
                intra_obs[dim1].dsasa = 0.0;
                intra_obs[dim1].err_dsasa = (double *) calloc(11, sizeof(double));
                if(NULL == intra_obs[dim1].err_dsasa) {
                    fprintf(stderr, "Allocation of D-SASA variable (intramolecular) failed! \n");
                    return EXIT_FAILURE;
                }
            }
        }
    }
    
    // this is needed for the pair correlation function
    double *pair_correlation_obs;
    if (ARG_pair_correlation==1) {
        pair_correlation_obs = (double*) calloc(2*ARG_numberofbeads, sizeof(double));
        if(NULL == pair_correlation_obs) {
            fprintf(stderr, "Allocation of pair_correlation_obs failed! \n");
            return EXIT_FAILURE;
        }
        
        normal_obs.pair_corr = (double *) calloc(2*ARG_numberofbeads, sizeof(double));
        if(NULL == normal_obs.pair_corr) {
            fprintf(stderr, "Allocation of pair_corr failed! \n");
            return EXIT_FAILURE;
        }
        
        if (ARG_intra_potential>0) {
            for (int dim1=0; dim1<100; dim1++) {
                intra_obs[dim1].pair_corr = (double *) calloc(2*ARG_numberofbeads, sizeof(double));
                if(NULL == intra_obs[dim1].pair_corr) {
                    fprintf(stderr, "Allocation of pair_corr (intramolecular) failed! \n");
                    return EXIT_FAILURE;
                }
            }
        }
    }
    //-------------------------
    
    
    // this will provide a measure for entropy loss calculation
    unsigned long *attempts_successes;
    double *log_attempts;
    log_attempts = (double*) calloc(11, sizeof(double));
    
    // set the number of entries in this list, it depends on the typeofrun, but not the saw-type
    // last entry is the recast number of attempts which provides a measure for the entropy loss
    
    //-------------------------------------------------------------------------------------------
    //-------------------------------------------------------------------------------------------
    // calculate variables which depend on the typeofrun
    
    
    switch (ARG_typeofrun) {
            // normal SAWX
        case 10:
        case 20:
        case 30:
            attempts_successes = calloc(2, sizeof(unsigned long));
            break;
            // fSAWX
        case 11:
        case 21:
        case 31:
            attempts_successes = calloc(5, sizeof(unsigned long));
            numof_frags_bricks[0] = (ARG_numberofbeads-1)/ARG_flength;
            break;
            // bSAWX
        case 13:
        case 23:
        case 33:
            attempts_successes = calloc(3, sizeof(unsigned long));
            numof_frags_bricks[3] = (ARG_numberofbeads-1)/ARG_blength;
            break;
            // fb_SAWX
        case 14:
        case 24:
        case 34:
            attempts_successes = calloc(5, sizeof(unsigned long));
            numof_frags_bricks[0] = (ARG_numberofbeads-1)/ARG_flength;
            numof_frags_bricks[3] = ARG_flength/ARG_blength;
            numof_frags_bricks[4] = (ARG_numberofbeads-1-ARG_flength*numof_frags_bricks[3])/ARG_blength;
            break;
            
        default:
            break;
    }
    
    
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    // intra molecular interactions
    
    
    // boltzman-factors, the intramolecular energy, the enrgy time the boltzmanfactor (entropy)
    double *intra_boltzman_factors;
    double *intra_highest_boltzmanfactor;
    double *intra_energy;
    double **intra_sum_of_boltzfactors;
    double **intra_sum_of_enrgyboltz;
    int *intra_interactions_hist;
 //   double *intra_interactions_testhist;
    
    double intra_max_factor = 0.0;
    double intra_min_factor = 0.0;
    
    // binning the energies of the intra-factors
    double intra_binmin;
    double intra_binmax;
    double intra_binwidth;
    int **intra_energybin;
    
    
    
    // these will be the parameter of the intra molecular force
    double *intra_parameter1;
    double *intra_parameter2;
    
    
    
    if (ARG_intra_potential > 0){
        switch (ARG_intra_potential) {
                // 1-10 potential well + torsional potential, given energy values
            case 1:
                intra_boltzman_factors = (double*) calloc(1, sizeof(double));
                intra_highest_boltzmanfactor = (double*) calloc(1, sizeof(double));
                intra_energy = (double*) calloc(1, sizeof(double));
                intra_sum_of_boltzfactors = (double**) calloc(1, sizeof(double));
                intra_sum_of_enrgyboltz = (double**) calloc(1, sizeof(double*));
                intra_sum_of_boltzfactors[0] = (double*) calloc(10, sizeof(double));
                intra_sum_of_enrgyboltz[0]  = (double*) calloc(10, sizeof(double));
                
                intra_parameter1 = (double*) malloc(1 * sizeof(double));
                intra_parameter2 = (double*) malloc(1 * sizeof(double));
                intra_interactions_hist = calloc(ARG_numberofbeads, sizeof(int));
 //               intra_interactions_testhist = calloc(100, sizeof(double));
                intra_parameter1[0] = ARG_intra_parameter1[0]; // nearest neighbor potential
                intra_parameter2[0] = ARG_intra_parameter2[0]; // torsion potential
                intra_binmin = -100.0;
                intra_binmax = 100.0;
                intra_binwidth = 1.0;
                intra_energybin = (int**) calloc(1, sizeof(int *));
                intra_energybin[0] = (int*) calloc(((intra_binmax-intra_binmin)/intra_binwidth), sizeof(int));
                break;
                
                // 1-10 potential well + torsional potential, given energy value range! 10x10
            case 2:
                intra_boltzman_factors = (double*) calloc(100, sizeof(double));
                intra_highest_boltzmanfactor = (double*) calloc(100, sizeof(double));
                intra_energy = (double*) calloc(100, sizeof(double));
                intra_sum_of_boltzfactors = (double**) calloc(100, sizeof(double));
                intra_sum_of_enrgyboltz = (double**) calloc(100, sizeof(double*));
                
                for (int dim1=0; dim1<100; ++dim1) {
                    intra_sum_of_boltzfactors[dim1] = (double*) calloc(10, sizeof(double));
                    intra_sum_of_enrgyboltz[dim1]  = (double*) calloc(10, sizeof(double));
                }
                
                intra_parameter1 = (double*) malloc(10 * sizeof(double));
                intra_parameter2 = (double*) malloc(10 * sizeof(double));
                intra_interactions_hist = calloc(ARG_numberofbeads, sizeof(int));
 //               intra_interactions_testhist = calloc(100, sizeof(double));
                for (int dim1=0; dim1<10; dim1++) {
                    intra_parameter1[dim1] = ARG_intra_parameter1[0]+ ARG_intra_parameter1[1]*(double)dim1; // nearest neighbor potential
                    intra_parameter2[dim1] = ARG_intra_parameter2[0]+ ARG_intra_parameter2[1]*(double)dim1; // torsion potential
                }
                intra_binmin = -100.0;
                intra_binmax = 100.0;
                intra_binwidth = 1.0;
                intra_energybin = (int**) calloc(100, sizeof(int *));
                for (int dim1=0; dim1<100; ++dim1){
                    intra_energybin[dim1] = (int*) calloc(((intra_binmax-intra_binmin)/intra_binwidth), sizeof(int));
                }
                break;
                
            default:
                fprintf(stderr, "This intramolecular potential doesn't exist! \n");
                break;
        }

    }

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

    
    
    
    
    /* start of chain generation*/
    time[1] = time_of_day();
    
    for (unsigned long frame=0; frame<ARG_numberofframes; frame++){
        
        tenth = frame/tenth_frames;
        
        switch(ARG_typeofrun){
                
            case 0:
                dcd_to_polymer(double_polymer, v, natoms, &timestep, dcd, frame, ARG_numberofbeads);
                break;
                
            case 1:
                tetra_rw(int_polymer, move, ARG_numberofbeads);
                break;
                
            case 2:
                tetra_fww(int_polymer, move, sawmoves, ARG_numberofbeads);
                break;
                
            case 10:
                tetra_saw1(int_polymer, move, sawmoves, ARG_numberofbeads, attempts_successes);
                break;
                
            case 11:
                tetra_fsaw1(int_polymer, move, sawmoves, ARG_numberofbeads, ARG_flength, attempts_successes);
                break;
                
            case 13:
                tetra_bsaw1(int_polymer, move, sawmoves, ARG_numberofbeads, ARG_blength, numberofbricks, building_bricks, attempts_successes);
                break;
                
   //         case 14: // here is something awfully wrong, can't find the mistake at the moment!
   //             tetra_fb_saw1(int_polymer, move, sawmoves, ARG_numberofbeads, ARG_blength, numberofbricks, building_bricks, ARG_flength, attempts_successes);
   //             break;
                
            case 20:
                tetra_saw2(int_polymer, move, sawmoves, ARG_numberofbeads, attempts_successes);
                break;
                
            case 21:
                tetra_fsaw2(int_polymer, move, sawmoves, ARG_numberofbeads, ARG_flength, attempts_successes);
                break;
                
            case 23:
                tetra_bsaw2(int_polymer, move, sawmoves, ARG_numberofbeads, ARG_blength, numberofbricks, building_bricks, attempts_successes);
                break;
                
            case 24:
                tetra_fb_saw2(int_polymer, move, sawmoves, ARG_numberofbeads, ARG_blength, numberofbricks, building_bricks, ARG_flength, attempts_successes);
                break;
                
            case 30:
                tetra_saw3(int_polymer, move, sawmoves, ARG_numberofbeads, attempts_successes);
                break;

            case 31:
                tetra_fsaw3(int_polymer, move, sawmoves, ARG_numberofbeads, ARG_flength, attempts_successes);
                break;
                
            case 33:
                tetra_bsaw3(int_polymer, move, sawmoves, ARG_numberofbeads, ARG_blength, numberofbricks, building_bricks, attempts_successes);
                break;
                
            case 34:
                tetra_fb_saw3(int_polymer, move, sawmoves, ARG_numberofbeads, ARG_blength, numberofbricks, building_bricks, ARG_flength, attempts_successes);
                break;

                
            default:
                log_out(output_file, "ERROR: ARG_typeofrun = %d isn't recognized by the main part of the programm!\n", ARG_typeofrun);
                usage_error();
                
        } // end of chain generaiton
        
        
        // copies the lattice polymer into an array with doubles so that the chosen bond length can be used.
        if (ARG_typeofrun>0) {
            recast(double_polymer, int_polymer, ARG_numberofbeads, &recast_factor);
        }
        
        
        //-----------------------------------------------------------------------------
        //-----------------------------------------------------------------------------
        // get most important observables
        
        // end-to-end distance^2
        normal_obs.ee2 = double_distance2(double_polymer[last_atom], double_polymer[0]);
        normal_obs.err_ee2[tenth] += normal_obs.ee2;
        // radius of gyration
        normal_obs.rgyr = radius_of_gyration(double_polymer, ARG_numberofbeads);
        normal_obs.err_rgyr[tenth] += normal_obs.rgyr;
        // pT
        if (ARG_torsion==1){
            normal_obs.pt = get_nT(double_polymer, number_of_torsions);
            normal_obs.err_pt[tenth] += normal_obs.pt;
        }
        if (ARG_sasa==1){
            //observables[4] = get_asa(double_polymer, ARG_numberofbeads, (sqrt(16.0/3.0)*bondlength/2.0));
            normal_obs.dsasa = delta_asa(double_polymer, ARG_numberofbeads, bondlength);
            normal_obs.err_dsasa[tenth] += normal_obs.dsasa;
        }
        if (ARG_pair_correlation==1) {
            if (false==pair_correlation_fct(pair_correlation_obs, double_polymer, ARG_numberofbeads)){
                return EXIT_FAILURE;
            }
            for (int pairs=0; pairs<(2*ARG_numberofbeads); pairs++) {
                normal_obs.pair_corr[pairs] += pair_correlation_obs[pairs];
            }
        }
        
        
        

        
        
        
        
        
        //-----------------------------------------------------------------------------
        //-----------------------------------------------------------------------------
        // calculate boltzman factors if intramolecular forces are switched on
        
        switch (ARG_intra_potential) {
                
            // torsion + square well potential
            case 1:
                intrapot_torsion_well(intra_boltzman_factors, intra_energy, intra_interactions_hist, intra_highest_boltzmanfactor, intra_parameter1, intra_parameter2, normal_obs.pt, number_of_torsions, int_polymer, ARG_numberofbeads);
                
                intra_sum_of_enrgyboltz[0][tenth] += (intra_boltzman_factors[0]*intra_energy[0]);
                intra_sum_of_boltzfactors[0][tenth] += intra_boltzman_factors[0];
                
                intra_obs[0].err_ee2[tenth] += normal_obs.ee2 * intra_boltzman_factors[0];
                intra_obs[0].err_rgyr[tenth] += normal_obs.rgyr * intra_boltzman_factors[0];
                intra_obs[0].err_pt[tenth] += normal_obs.pt * intra_boltzman_factors[0];
                
                intra_binenergy(intra_energy[0], intra_binmin, intra_binwidth, intra_energybin[0]);
                
                // pair correlation function
                if (ARG_pair_correlation==1){
                    for (int pairs=0; pairs<(2*ARG_numberofbeads); pairs++) {
                        intra_obs[0].pair_corr[pairs] += (pair_correlation_obs[pairs]*intra_boltzman_factors[0]);
                    }
                }
                break;
                
            // torsion + square well potential, range of energy values
            case 2:
                intrapot_torsion_well_scan(intra_boltzman_factors, intra_energy, intra_interactions_hist, intra_highest_boltzmanfactor, intra_parameter1, intra_parameter2, normal_obs.pt, number_of_torsions, int_polymer, ARG_numberofbeads);
                //intrapot_torsion_well_test(intra_boltzman_factors, intra_energy, intra_interactions_hist, intra_interactions_testhist,intra_highest_boltzmanfactor, intra_parameter1, intra_parameter2, normal_obs.pt, number_of_torsions, int_polymer, ARG_numberofbeads);
                
                for (int dim1=0; dim1<100; ++dim1) {
                    intra_sum_of_enrgyboltz[dim1][tenth] += (intra_boltzman_factors[dim1]*intra_energy[dim1]);
                    intra_sum_of_boltzfactors[dim1][tenth] += intra_boltzman_factors[dim1];
                    intra_obs[dim1].err_ee2[tenth] += normal_obs.ee2 * intra_boltzman_factors[dim1];
                    intra_obs[dim1].err_rgyr[tenth] += normal_obs.rgyr * intra_boltzman_factors[dim1];
                    intra_obs[dim1].err_pt[tenth] += normal_obs.pt * intra_boltzman_factors[dim1];
                    intra_binenergy(intra_energy[dim1], intra_binmin, intra_binwidth, intra_energybin[dim1]);
                    // pair correlation function
                    if (ARG_pair_correlation==1){
                        for (int pairs=0; pairs<(2*ARG_numberofbeads); pairs++) {
                            intra_obs[dim1].pair_corr[pairs] += (pair_correlation_obs[pairs]*intra_boltzman_factors[dim1]);
                        }
                    }
                }
                
                break;
                
            default:
                break;
                
        }// boltzman factors and energies have been determined
            // end of anything related to intramolecular potentials
        
        
        
        //--------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------
        // everything has been calculated, now is the opportunity to look at convergence
        
        if ((frame+1)%permill_frames==0) {
            // convergence of variables with equal weights
            convergence(&normal_obs, (double)number_of_torsions, (frame+1), conv_obs_file);
            
            
            switch (ARG_intra_potential) {
                    
                case 1:
                    weighted_convergence(intra_obs, 1,intra_sum_of_boltzfactors, (double)number_of_torsions, (frame+1), conv_intraobs_file);
                    weights_growth(intra_sum_of_boltzfactors, 1, (frame+1), convergence_intraweights);
                    break;
                    
                    // convergence of weighted ensemble
                case 2:
                    weighted_convergence(intra_obs, 100, intra_sum_of_boltzfactors, (double)number_of_torsions, (frame+1), conv_intraobs_file);
                    weights_growth(intra_sum_of_boltzfactors, 100, (frame+1), convergence_intraweights);
                    break;
                    
                default:
                    break;
            }
            
            
            if ((frame+1)%percent_frames==0) {
                
                cent = (frame+1)/percent_frames;
                
                log_out(output_file, "Finished %i%%\t...remaining time: %f seconds \n", (cent), ((time_of_day()-time[1])*(100-cent)/(cent)));
                
                if ((frame+1)%tenth_frames==0) {
                    // every bin after the first will also include the attempts in the previous bin!
                    log_attempts[tenth] = recalc_attempts(attempts_successes, numof_frags_bricks, numberofbricks, ARG_typeofrun);
                }
                
                
            }
        }
        
    } // end of loop over number of frames
    
    
    

    
    
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    /* Post-Process */
    time[2] = time_of_day();
    
    // Maybe there should be a function, which returns means and errors; it calls these subroutines ....
    
    log_attempts[10] = recalc_attempts(attempts_successes, numof_frags_bricks, numberofbricks, ARG_typeofrun);
    for (int dim1=9; dim1>0; --dim1) {
        log_attempts[dim1] = log( exp(log_attempts[dim1]) - exp(log_attempts[dim1-1]) );
    }
    
    // get means and errors
    normal_obs.ee2 = sqrt( average(normal_obs.err_ee2, ARG_numberofframes) );
    normal_obs.err_ee2[10] = error_sq_ten(normal_obs.ee2, normal_obs.err_ee2, ARG_numberofframes);
    normal_obs.rgyr = sqrt( average(normal_obs.err_rgyr, ARG_numberofframes) );
    normal_obs.err_rgyr[10] = error_sq_ten(normal_obs.rgyr, normal_obs.err_rgyr, ARG_numberofframes);
    normal_obs.S = (log((double)ARG_numberofframes) - log_attempts[10]);
    
    if (ARG_torsion==1) {
        normal_obs.pt = average(normal_obs.err_pt, ARG_numberofframes);
        normal_obs.err_pt[10] = error_ten(normal_obs.pt, normal_obs.err_pt, ARG_numberofframes);
    }
    if (ARG_sasa==1) {
        normal_obs.dsasa = average(normal_obs.err_dsasa, ARG_numberofframes);
        normal_obs.err_dsasa[10] = error_ten(normal_obs.dsasa, normal_obs.err_dsasa, ARG_numberofframes);
    }
    
    
    
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    /* Output */
    time[3] = time_of_day();
    
    // print the output to screen and to the output_file
    
    log_out(output_file, "\n-----------------------------------------------------------------------------------\n");
    log_out(output_file, "FINAL OUTPUT\n");
    
    log_out(output_file, "\nEntropic Considerations:\n");
    log_out(output_file, "Attempts to Compute the Ensemble: %e  \n", exp(log_attempts[10]));
    log_out(output_file, "\tDelta S / k_B (FWW -> SAWn): %f \n",  normal_obs.S);
    
    log_out(output_file, "\nChosen Observables:\n");
    log_out(output_file, "Flory Radius: %f +- %f \n", normal_obs.ee2, normal_obs.err_ee2[10]);
    log_out(output_file, "Radius of Gyration: %f +- %f \n", normal_obs.rgyr, normal_obs.err_rgyr[10]);
    if (ARG_torsion==1) {
        log_out(output_file, "Probability of trans = %f +- %f\n", (normal_obs.pt/(double)number_of_torsions), (normal_obs.err_pt[10]/(double)number_of_torsions));

    }
    if (ARG_sasa==1) {
        log_out(output_file, "Delta SASA = %f +- %f\n", normal_obs.dsasa, normal_obs.err_dsasa[10]);
    }
    if (ARG_pair_correlation==1) {
        log_out(output_file, "The pair-correlation function was written to 'pair_correlation_function.dat'.\n");
    }

    log_out(output_file, "\nThis ouput is also written to 'output_file.dat'.\n");
    log_out(output_file, "The convergence was written to 'convergence_obs.dat'.\n");
    
    
    if (ARG_intra_potential>0) {
        log_out(output_file, "\nThe Boltzmann-weighted observables can be found in 'intramolecular_obs.dat'.\n");
        log_out(output_file, "The Boltzmann-weighted convergence was written to 'intramolecular_convergence_obs.dat'.\n");
        log_out(output_file, "A histogram of the Boltzmann-factors was written to 'intramolecular_factors_hist.dat'.\n");
        log_out(output_file, "The sum of the Boltzmann-factors was written to 'intramolecular_convergence_Z.dat'.\n");
        log_out(output_file, "A histogram of the intramolecular contacts was written to 'intramolecular_interactions_hist.dat'.\n");
    }
    
    

    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    /* Output to file */
    
    // pair correlation function
    if (ARG_pair_correlation==1){
        
        if (ARG_intra_potential==0) {
            fprintf(pair_correl_file,"# r_0-r_1 pair_correlation \n");
            for (int dim1=0; dim1<(2*ARG_numberofbeads); dim1++){
                fprintf(pair_correl_file, "%i %e \n", dim1, (normal_obs.pair_corr[dim1]/(double)ARG_numberofframes));
            }
        }
        else if (ARG_intra_potential==2){
            fprintf(pair_correl_file,"# r_0-r_1 pair_correlation(unweigthed) pair_correlation(weigthed)\n");
            for (int dim1=0; dim1<(2*ARG_numberofbeads); dim1++){
                fprintf(pair_correl_file, "%i %e %e \n", dim1, (normal_obs.pair_corr[dim1]/(double)ARG_numberofframes), (intra_obs[46].pair_corr[dim1]/average(intra_sum_of_boltzfactors[46], 1)));
            }
        }
        
        
    }
    
    
    
    switch (ARG_intra_potential) {
            
        case 1:
            // prints the weighted observables to file with error estimate
            fprintf(intra_pot_file, "### 1-9 well, torsion eps, Rf, Rf_err, Rg, Rg_err, pT, pT_err, DS, DS_err, <exp(-E/kT)>/exp(-Emax/kT) \n" );

            intra_obs[0].ee2 = sqrt(weighted_average(intra_obs[0].err_ee2, intra_sum_of_boltzfactors[0]));
            intra_obs[0].err_ee2[10] = weighted_error_sq_ten(intra_obs[0].ee2, intra_obs[0].err_ee2, intra_sum_of_boltzfactors[0]);
            
            intra_obs[0].rgyr = sqrt(weighted_average(intra_obs[0].err_rgyr, intra_sum_of_boltzfactors[0]));
            intra_obs[0].err_rgyr[10] = weighted_error_sq_ten(intra_obs[0].rgyr, intra_obs[0].err_rgyr, intra_sum_of_boltzfactors[0]);
            
            intra_obs[0].pt = weighted_average(intra_obs[0].err_pt, intra_sum_of_boltzfactors[0]);
            intra_obs[0].err_pt[10] = weighted_error_ten(intra_obs[0].pt, intra_obs[0].err_pt, intra_sum_of_boltzfactors[0]);
            
            intra_obs[0].S = intra_entropy(intra_sum_of_boltzfactors[0], intra_sum_of_enrgyboltz[0], log_attempts[10]);
            intra_obs[0].err_S = intra_entropy_error_ten(intra_obs[0].S, intra_sum_of_boltzfactors[0], intra_sum_of_enrgyboltz[0], log_attempts);
            
            fprintf(intra_pot_file, "%f %f %e %e %e %e %e %e %e %e %e \n", intra_parameter1[0], intra_parameter2[0], intra_obs[0].ee2, intra_obs[0].err_ee2[10], intra_obs[0].rgyr, intra_obs[0].err_rgyr[10], (intra_obs[0].pt/(double)number_of_torsions), (intra_obs[0].err_pt[10]/(double)number_of_torsions), intra_obs[0].S, intra_obs[0].err_S, intra_loss_of_conf(intra_sum_of_boltzfactors[0], intra_highest_boltzmanfactor[0], ARG_numberofframes));

            
            // histogram over 1-9 interacitons
            fprintf(intra_interactions_file, "# number-of-nn-interactions, occurence \n");
            for (int dim1=0; dim1<ARG_numberofbeads; ++dim1) {
                fprintf(intra_interactions_file, "%i %i \n", dim1, intra_interactions_hist[dim1]);
            }
            
            // test histogram
            //      fprintf(intra_interactions_testfile, "# sperating-bonds 0_contacts 1_contacts 2_contacts\n");
            //      for (int dim1=0; dim1<98; dim1+=3) {
            //          fprintf(intra_interactions_testfile, "%i %e %e %e \n", (dim1/3+4), intra_interactions_testhist[dim1]/average(intra_sum_of_boltzfactors[46], 1), intra_interactions_testhist[dim1+1]/average(intra_sum_of_boltzfactors[46], 1), intra_interactions_testhist[dim1+2]/average(intra_sum_of_boltzfactors[46], 1));
            //     }
            
            // histogram of intra energies
            fprintf(intra_boltzman_factors_hist, "# energy, bincount-for-these-parameters");
            for (int dim1=0; dim1<((intra_binmax-intra_binmin)/intra_binwidth); ++dim1) {
                fprintf(intra_boltzman_factors_hist, "%f %i \n", (intra_binmin+(double)dim1*intra_binwidth), intra_energybin[0][dim1]);
            }
            break;
            
        case 2:
            // prints the weighted observables to file with error estimate
            fprintf(intra_pot_file, "### 1-9 well, torsion eps, Rf, Rf_err, Rg, Rg_err, pT, pT_err, DS, DS_err, <exp(-E/kT)>/exp(-Emax/kT) \n" );
            for (int dim1=0; dim1<10; dim1++) {
                for (int dim2=0; dim2<10; dim2++) {
                    
                    counter = dim1*10 + dim2;
                    
                    intra_obs[counter].ee2 = sqrt(weighted_average(intra_obs[counter].err_ee2, intra_sum_of_boltzfactors[counter]));
                    intra_obs[counter].err_ee2[10] = weighted_error_sq_ten(intra_obs[counter].ee2, intra_obs[counter].err_ee2, intra_sum_of_boltzfactors[counter]);
                    
                    intra_obs[counter].rgyr = sqrt(weighted_average(intra_obs[counter].err_rgyr, intra_sum_of_boltzfactors[counter]));
                    intra_obs[counter].err_rgyr[10] = weighted_error_sq_ten(intra_obs[counter].rgyr, intra_obs[counter].err_rgyr, intra_sum_of_boltzfactors[counter]);
                    
                    intra_obs[counter].pt = weighted_average(intra_obs[counter].err_pt, intra_sum_of_boltzfactors[counter]);
                    intra_obs[counter].err_pt[10] = weighted_error_ten(intra_obs[counter].pt, intra_obs[counter].err_pt, intra_sum_of_boltzfactors[counter]);
                    
                    intra_obs[counter].S = intra_entropy(intra_sum_of_boltzfactors[counter], intra_sum_of_enrgyboltz[counter], log_attempts[10]);
                    intra_obs[counter].err_S = intra_entropy_error_ten(intra_obs[counter].S, intra_sum_of_boltzfactors[counter], intra_sum_of_enrgyboltz[counter], log_attempts);
                    
                    fprintf(intra_pot_file, "%f %f %e %e %e %e %e %e %e %e %e \n", intra_parameter1[dim1], intra_parameter2[dim2], intra_obs[counter].ee2, intra_obs[counter].err_ee2[10], intra_obs[counter].rgyr, intra_obs[counter].err_rgyr[10], (intra_obs[counter].pt/(double)number_of_torsions), (intra_obs[counter].err_pt[10]/(double)number_of_torsions), intra_obs[counter].S, intra_obs[counter].err_S, intra_loss_of_conf(intra_sum_of_boltzfactors[counter], intra_highest_boltzmanfactor[counter], ARG_numberofframes));
                }
            }
            
            // histogram over 1-9 interacitons
            fprintf(intra_interactions_file, "# number-of-nn-interactions, occurence \n");
            for (int dim1=0; dim1<ARG_numberofbeads; ++dim1) {
                fprintf(intra_interactions_file, "%i %i \n", dim1, intra_interactions_hist[dim1]);
            }
            
            // test histogram
            //      fprintf(intra_interactions_testfile, "# sperating-bonds 0_contacts 1_contacts 2_contacts\n");
            //      for (int dim1=0; dim1<98; dim1+=3) {
            //          fprintf(intra_interactions_testfile, "%i %e %e %e \n", (dim1/3+4), intra_interactions_testhist[dim1]/average(intra_sum_of_boltzfactors[46], 1), intra_interactions_testhist[dim1+1]/average(intra_sum_of_boltzfactors[46], 1), intra_interactions_testhist[dim1+2]/average(intra_sum_of_boltzfactors[46], 1));
            //     }
            
            // histogram of intra energies
            fprintf(intra_boltzman_factors_hist, "# energy, bincount-for-these-parameters");
            for (int dim1=0; dim1<((intra_binmax-intra_binmin)/intra_binwidth); ++dim1) {
                fprintf(intra_boltzman_factors_hist, "%f ", (intra_binmin+(double)dim1*intra_binwidth));
                for (int dim2=0; dim2<100; ++dim2) {
                    fprintf(intra_boltzman_factors_hist, "%i ", intra_energybin[dim2][dim1]);
                }
                fprintf(intra_boltzman_factors_hist, "\n");
            }

            break;
            
        default:
            break;
    }


    
    
    
    
    log_out(output_file, "\nComputation of Chains:\t%f seconds \nTotal Runtime:\t\t%f seconds \n\n", (time[2]-time[1]), (time[3]-time[0]));
    log_out(output_file, "End of Programm!\n-----------------------------------------------------------------------------------\n");
    
    // make sure everything gets printed
    fflush(stdout);
    
    
    
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------------------------------------------------------------
    // close every remaining file and free remaining pointers!
    // cleaning up ;-)
    
    //close all files
    if (ARG_typeofrun==0){// dcd-file
        close_file_read(v);
    }
    
    fclose(conv_obs_file);
    fclose(pair_correl_file);
    fclose(intra_pot_file);
    fclose(intra_boltzman_factors_hist);
    fclose(convergence_intraweights);
    fclose(intra_interactions_file);
    fclose(conv_intraobs_file);
    
    // very last file to close
    fclose(output_file);
    
    
    
    //-----------------------------
    // free pointers
    
    
    // free general variables
    free(normal_obs.err_ee2);
    free(normal_obs.err_rgyr);
    
    // torsion angles
    if (ARG_torsion==1) {
        free(normal_obs.err_pt);
        if (ARG_intra_potential>0) {
            for (int dim1=0; dim1<100; dim1++) {
                free(intra_obs[dim1].err_pt);
            }
        }
    }
    
    // D-SASA
    if (ARG_sasa==1) {
        free(normal_obs.err_dsasa);
        if (ARG_intra_potential>0) {
            for (int dim1=0; dim1<100; dim1++) {
                free(intra_obs[dim1].err_dsasa);
            }
        }
    }
    
    // pair correlation function
    if (ARG_pair_correlation==1) {
        free(pair_correlation_obs);
        free(normal_obs.pair_corr);
        if (ARG_intra_potential>0) {
            for (int dim1=0; dim1<100; dim1++) {
                free(intra_obs[dim1].pair_corr);
            }
        }
    }
    
    free(attempts_successes);
    
    // free arrays which held polymer coordinates
    for (int dim1=0; dim1<ARG_numberofbeads;dim1++){
        free(int_polymer[dim1]);
        free(double_polymer[dim1]);
    }
    free(int_polymer);
    free(double_polymer);
    
    
    
    // free building blocks
    if (ARG_typeofrun==13 || ARG_typeofrun==14 || ARG_typeofrun==23 || ARG_typeofrun==24 || ARG_typeofrun==33 || ARG_typeofrun==34){
        for (int dim1=0; dim1<numberofbricks; ++dim1) {
            for (int dim2=0; dim2<ARG_blength; ++dim2) {
                free(building_bricks[dim1][dim2]);
            }
            free(building_bricks[dim1]);
        }
        free(building_bricks);
    }
    
    
    
    // free potential variables
    if (ARG_intra_potential > 0){
        switch (ARG_intra_potential) {
            case 1:
                free(intra_sum_of_boltzfactors[0]);
                break;
                
            case 2:
                for (int dim1=0; dim1<100; dim1++){
                    free(intra_sum_of_boltzfactors[dim1]);
                }
                break;

            default:
                break;
        }

        free(intra_energy);
        free(intra_boltzman_factors);
        free(intra_sum_of_boltzfactors);
        free(intra_sum_of_enrgyboltz);
        free(intra_interactions_hist);
  //      free(intra_interactions_testhist);
        free(intra_parameter1);
        free(intra_parameter2);
    }
    
    
    



    
    // end of programm
    return EXIT_SUCCESS;
}