+#ifndef OBS_CORRCHI_HPP
+#define OBS_CORRCHI_HPP
+
+#include "latlib/o815/o815.h"
+
+#include "latlib/writeout.h"
+
+#include "latlib/obstat.hpp"
+
+#include <iostream>
+#include <complex>
+
+#include <cmath>
+
+using namespace std;
+
+class obs_corrchi : public o815::obs {
+
+public:
+ obs_corrchi(o815 *_O815);
+
+private:
+ void _start();
+ void _meas(bool loadedobs, const int& nthmeas);
+ void _finish();
+
+ void corrCompute();
+ static complex<double> effMass(vector < complex<double> > *preCalculated, vector< complex<double> > *excludedMeas, int nmeas, void *para);
+ static void preEffMass(vector< vector < complex<double> > > *allVals, vector < complex<double> > *preCalculated, void *para);
+
+ sim *Sim;
+ obstat< complex<double>, complex<double> > oC;
+
+ int spatialV;
+
+ complex<double> *OM;
+};
+
+obs_corrchi::obs_corrchi(o815 *_O815) : o815::obs("corrchi",
+ _O815->paraQ->getParaNames() +
+ "tsep"
+ ":chi_real:chi_imag:chi_abs:chi_mass:chi_mass_err",
+ _O815, sizeof(complex<double>)*(_O815->comargs.lsize[1]/2+1) ) {
+
+ OM = (complex<double>*)(obsMem);
+
+ Sim = (sim*)O815->Sim;
+ spatialV = O815->comargs.lsize[0] * O815->comargs.lsize[0] * O815->comargs.lsize[0];
+}
+
+void obs_corrchi::_start() {
+ //*out << "OBS_test: start" << endl;
+};
+
+void obs_corrchi::_meas(bool loadedobs, const int& nthmeas) {
+ if (!loadedobs)
+ corrCompute();
+
+ oC.addMeas( OM, O815->comargs.lsize[1]/2+1 );
+};
+
+void obs_corrchi::_finish() {
+ int compid_corr[O815->comargs.lsize[1]/2];
+ int compid_effmass[O815->comargs.lsize[1]/2-1];
+
+ for (int itsep = 0; itsep < O815->comargs.lsize[1]/2; itsep++)
+ compid_corr[itsep] = oC.computeEasy(itsep);
+
+ for (int itsep = 0; itsep < O815->comargs.lsize[1]/2-1; itsep++) {
+ pair<int,int> effmasspass( itsep, O815->comargs.lsize[1]/2 );
+ compid_effmass[itsep] = oC.computeJack(obs_corrchi::preEffMass, obs_corrchi::effMass, &effmasspass);
+ }
+
+ for (int itsep = 0; itsep < O815->comargs.lsize[1]/2; itsep++) {
+ *out << O815->paraQ->getParaVals();
+ *out << "\t" << itsep;
+
+ *out << "\t" << real( oC.getMean(compid_corr[itsep]) )
+ << "\t" << imag( oC.getMean(compid_corr[itsep]) )
+ << "\t" << abs ( oC.getMean(compid_corr[itsep]) );
+
+ if ( itsep < O815->comargs.lsize[1]/2-1 )
+ *out << "\t" << real( oC.getMean(compid_effmass[itsep]) )
+ << "\t" << real( oC.getErr (compid_effmass[itsep]) );
+ else
+ *out << "\t" << NAN << "\t" << NAN;
+
+ *out << endl;
+ }
+
+ oC.reset();
+}
+
+
+void obs_corrchi::corrCompute()
+{
+ complex<double> phislice[O815->comargs.lsize[1]];
+
+ OM[O815->comargs.lsize[1]/2] = 0;
+
+ for (int it = 0; it < O815->comargs.lsize[1]; it++) {
+ phislice[it] = 0;
+
+ for (int ix = 0; ix < spatialV; ix++)
+ phislice[it] += Sim->phi[ 1*Sim->lsize4 + it*spatialV + ix ];
+
+ phislice[it] /= spatialV;
+
+ OM[O815->comargs.lsize[1]/2] += phislice[it];
+ }
+
+ for (int itsep = 0; itsep < O815->comargs.lsize[1]/2; itsep++) {
+ OM[itsep] = 0;
+
+ for (int it = 0; it < O815->comargs.lsize[1]; it++)
+ OM[itsep] += phislice[ (it+itsep)%O815->comargs.lsize[1] ] * conj( phislice[it] );
+
+ OM[itsep] /= O815->comargs.lsize[1];
+ }
+
+ OM[O815->comargs.lsize[1]/2] /= O815->comargs.lsize[1];
+}
+
+void obs_corrchi::preEffMass(vector< vector < complex<double> > > *allVals, vector < complex<double> > *preCalculated, void *para) {
+ pair<int,int> *myparas = (pair<int,int>*)para;
+
+ preCalculated->push_back(0);
+ preCalculated->push_back(0);
+ preCalculated->push_back(0);
+
+ for(vector< vector< complex<double> > >::iterator valIt = allVals->begin(); valIt != allVals->end(); ++valIt) {
+ (*preCalculated)[0] += (*valIt)[myparas->first];
+ (*preCalculated)[1] += (*valIt)[myparas->first+1];
+ (*preCalculated)[2] += (*valIt)[myparas->second];
+ }
+}
+
+complex<double> obs_corrchi::effMass(vector < complex<double> > *preCalculated, vector< complex<double> > *excludedMeas, int nmeas, void *para) {
+ pair<int,int> *myparas = (pair<int,int>*)para;
+
+ double disconnected = norm( ( (*preCalculated)[2] - (*excludedMeas)[myparas->second] ) / (complex<double>)(nmeas-1) );
+
+ return std::log( abs(
+ ( ( (*preCalculated)[0] - (*excludedMeas)[myparas->first] ) / (complex<double>)(nmeas-1) - disconnected ) /
+ ( ( (*preCalculated)[1] - (*excludedMeas)[myparas->first+1] ) / (complex<double>)(nmeas-1) - disconnected )
+ ) );
+}
+
+#endif