diff --git a/.gitignore b/.gitignore
index 3ed2d47d1..4a9a3bfbc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,5 +18,6 @@ tags
hmc_tm
invert
offline_measurement
+measure
lib/
benchmark
diff --git a/DDalphaAMG_interface.c b/DDalphaAMG_interface.c
index 4b24928fc..c677b0b1a 100644
--- a/DDalphaAMG_interface.c
+++ b/DDalphaAMG_interface.c
@@ -533,6 +533,25 @@ void MG_update_mu(double mu_tmLQCD, double odd_tmLQCD)
}
}
+/*
+ * This extra interface has been required for the reweighting measurements.
+ * The update of the parameters was not taken into account properly.
+ */
+void MG_update_kappa(double kappa)
+{
+ if(mg_initialized!=1){
+ return;
+ }
+ DDalphaAMG_get_parameters(&mg_params);
+ if (kappa!= mg_params.kappa) {
+ if (g_proc_id == 0) {
+ printf("MG WARNING: setting kappa from %.14f to %.14f general kappa %.14f\n",mg_params.kappa,kappa,g_kappa);
+ }
+ mg_params.kappa=kappa;
+ DDalphaAMG_update_parameters(&mg_params, &mg_status);
+ }
+}
+
void MG_reset() {
if(mg_do_setup == 0)
diff --git a/DDalphaAMG_interface.h b/DDalphaAMG_interface.h
index 144e96b4c..9b717f87e 100644
--- a/DDalphaAMG_interface.h
+++ b/DDalphaAMG_interface.h
@@ -44,6 +44,7 @@ extern double mg_rho_update;
void MG_init(void);
void MG_update_gauge(double step);
void MG_update_mu(double mu_tmLQCD, double odd_tmLQCD);
+void MG_update_kappa(double kappa);
void MG_reset(void);
void MG_finalize(void);
diff --git a/Makefile.in b/Makefile.in
index fe98465e4..7a16f3ccf 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -124,7 +124,7 @@ ${addsuffix .o, ${SMODULES}}: %.o: ${srcdir}/%.c %.d Makefile $(abs_top_builddir
# C++ modules
$(addsuffix .o,${CXXMODULES}): %.o: ${srcdir}/%.cpp %.d Makefile $(abs_top_builddir)/config.h
${CXXCOMPILE} -c $<
-
+
${addsuffix .o, ${PROGRAMS}}: %.o: ${srcdir}/%.c %.d Makefile $(abs_top_builddir)/config.h ${top_srcdir}/git_hash.h
${COMPILE} ${OPTARGS} -c $<
diff --git a/meas/Makefile.in b/meas/Makefile.in
index 3b2ccaccb..521e257ee 100644
--- a/meas/Makefile.in
+++ b/meas/Makefile.in
@@ -34,6 +34,7 @@ LIBRARIES = libmeas
libmeas_TARGETS = measurements \
oriented_plaquettes \
correlators \
+ reweightingmeas \
pion_norm \
polyakov_loop \
measure_clover_field_strength_observables \
diff --git a/meas/measurements.c b/meas/measurements.c
index 338ea7fea..86c0e86b4 100644
--- a/meas/measurements.c
+++ b/meas/measurements.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 2008 Carsten Urbach
* 2009 Florian Burger
+ * 2016 Georg Bergner
*
* This file is part of tmLQCD.
*
@@ -35,8 +36,10 @@
#include "polyakov_loop.h"
#include "oriented_plaquettes.h"
#include "gradient_flow.h"
+#include "reweightingmeas.h"
#include "measurements.h"
+
measurement measurement_list[max_no_measurements];
int no_measurements = 0;
@@ -49,6 +52,8 @@ int add_measurement(const enum MEAS_TYPE meas_type) {
measurement_list[no_measurements].measurefunc = &dummy_meas;
measurement_list[no_measurements].type = meas_type;
measurement_list[no_measurements].initialised = 1;
+ measurement_list[no_measurements].parameter=(void *)NULL;
+ measurement_list[no_measurements].destructor = &default_destructor;
no_measurements++;
return(no_measurements);
}
@@ -80,6 +85,12 @@ int init_measurements(){
measurement_list[i].measurefunc = &gradient_flow_measurement;
}
+ if(measurement_list[i].type == REWEIGHTING) {
+ measurement_list[i].measurefunc = &reweighting_measurement;
+ initialize_reweighting_parameter(&measurement_list[i].parameter);
+ measurement_list[i].destructor = &free_reweighting_parameter;
+ }
+
measurement_list[i].id = i;
}
return(0);
@@ -88,7 +99,14 @@ return(0);
void free_measurements(){
-
+ int i;
+ for(i = 0; i < no_measurements; i++) {
+ if (measurement_list[i].parameter) {
+ measurement_list[i].destructor(measurement_list[i].parameter);
+ free(measurement_list[i].parameter);
+ measurement_list[i].parameter = NULL;
+ }
+ }
return;
}
@@ -102,5 +120,10 @@ void dummy_meas(const int traj, const int id, const int ieo) {
}
+void default_destructor(void* ptr) {
+
+}
+
+
diff --git a/meas/measurements.h b/meas/measurements.h
index 73e695a17..7a036a6e8 100644
--- a/meas/measurements.h
+++ b/meas/measurements.h
@@ -4,6 +4,8 @@
*
* Adapted from monomial.h by Florian Burger 2009/12/16
*
+ * More flexible handling of measurements parameters by Georg Bergner 2016
+ *
* This file is part of tmLQCD.
*
* tmLQCD is free software: you can redistribute it and/or modify
@@ -18,6 +20,9 @@
*
* You should have received a copy of the GNU General Public License
* along with tmLQCD. If not, see .
+ *
+ *
+ *
***********************************************************************/
#ifndef _MEASUREMENTS_H
#define _MEASUREMENTS_H
@@ -25,29 +30,31 @@
#define max_no_measurements 20
/* Give the measurement types an unambiguous ID*/
-enum MEAS_TYPE {
- ONLINE,
- PIONNORM,
- POLYAKOV,
- ORIENTED_PLAQUETTES,
- GRADIENT_FLOW
- };
-
-typedef struct {
+enum MEAS_TYPE
+{
+ ONLINE, PIONNORM, POLYAKOV, ORIENTED_PLAQUETTES, GRADIENT_FLOW, REWEIGHTING
+};
+
+typedef struct
+{
enum MEAS_TYPE type;
int initialised;
int id;
-
- /* frequency of the measurement */
- int freq;
- /* for maximal iterations in inversions for correlators */
- int max_iter;
+
/* for polyakov loop */
int direction;
+ /* for maximal iterations in inversions for correlators */
+ int max_iter;
+
// random seed
unsigned int seed;
+ void* parameter;
+
+ /* frequency of the measurement */
+ int freq;
+
/* how it's usually called */
char name[100];
@@ -67,21 +74,29 @@ typedef struct {
double gf_tmax;
/* functions for the measurement */
- void (*measurefunc) (const int traj, const int id, const int ieo);
+ void
+ (*measurefunc) (const int traj, const int id, const int ieo);
+ void
+ (*destructor) (void* param);
} measurement;
-
/* list of all monomials */
extern measurement measurement_list[max_no_measurements];
extern int no_measurements;
/* add a new measurement to the list of measurements */
-int add_measurement(const enum MEAS_TYPE);
+int
+add_measurement (const enum MEAS_TYPE);
/* initialise all measurements in the list */
-int init_measurements();
+int
+init_measurements ();
/* free space again */
-void free_measurements();
+void
+free_measurements ();
-void dummy_meas(const int traj, const int id, const int ieo);
+void
+dummy_meas (const int traj, const int id, const int ieo);
+void
+default_destructor (void* ptr);
#endif
diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c
new file mode 100644
index 000000000..7b1f47e54
--- /dev/null
+++ b/meas/reweightingmeas.c
@@ -0,0 +1,1156 @@
+/***********************************************************************
+ *
+ * Measurements of the reweighting factors by Georg Bergner 2016
+ *
+ * Copyright (C) 2016 Georg Bergner
+ *
+ * This file is part of tmLQCD.
+ *
+ * tmLQCD is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * tmLQCD is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with tmLQCD. If not, see .
+ ***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+#include
+#include
+#include
+#include
+#include "global.h"
+#include "start.h"
+#include "ranlxs.h"
+#include "su3spinor.h"
+#include "source_generation.h"
+#include "operator.h"
+#include "invert_eo.h"
+#include "solver/solver.h"
+#include "geometry_eo.h"
+#include "measurements.h"
+#include "correlators.h"
+#include "gettime.h"
+#include "linalg_eo.h"
+#include "linalg/mul_diff_mul_r.h"
+#include "../operator/Hopping_Matrix.h"
+#include "../operator/tm_operators.h"
+#include "../operator/clovertm_operators.h"
+#include "../operator/tm_operators_32.h"
+#include "../operator/clovertm_operators_32.h"
+#include "../operator/clover_leaf.h"
+#include "../read_input.h"
+#include "reweightingmeas.h"
+#include "../operator.h"
+#include "../DDalphaAMG_interface.h"
+#include "../boundary.h"
+#include "../global.h"
+#include "../init/init_spinor_field.h"
+#include "solver/jdher.h"
+
+#include
+#ifdef _USE_SHMEM
+# include
+#endif
+
+
+/*
+ * This struct provides an array of spinor fields.
+ * This is easier to handle than the pointer of pointer of pointers used in other parts of the code.
+ */
+typedef struct {
+ spinor* buffer;
+ spinor** ar;
+ unsigned int length;
+} spinor_array;
+
+/*
+ * Allocation of the spinor field redirects to allocate_spinor_field_array.
+ */
+static int alloc_spinor_field(spinor_array* ar, int evenodd) {
+ unsigned long int volume = VOLUMEPLUSRAND / 2;
+ if (evenodd == 0) {
+ volume = VOLUMEPLUSRAND;
+ }
+ return (allocate_spinor_field_array(&ar->ar,&ar->buffer,volume, ar->length));
+}
+
+static void free_spinor_field_spinor_array(spinor_array* ar) {
+ if (ar->buffer != NULL) {
+ free_spinor_field_array(&ar->buffer);
+ }
+ if (ar->ar != NULL) {
+ free(ar->ar);
+ }
+ ar->ar = NULL;
+ ar->buffer = NULL;
+ ar->length = 0;
+}
+
+/*
+ * The generic inverter requires different functions depending on
+ * preconditioned or unpreconditioned matrix.
+ */
+static int is_schur_complement(const matrix_mult f) {
+ if (f == Msw_psi || // Schur complement with mu=0 on odd sites
+ f == Qsw_psi || // Gamma5 - Schur complement with mu=0 on odd sites
+ f == Mtm_plus_psi || // Schur complement with plus mu
+ f == Msw_plus_psi || // Schur complement with plus mu
+ f == Qtm_plus_psi || // Gamma5 - Schur complement with plus mu
+ f == Qsw_plus_psi || // Gamma5 - Schur complement with plus mu
+ f == Mtm_minus_psi || // Schur complement with minus mu
+ f == Msw_minus_psi || // Schur complement with minus mu
+ f == Qtm_minus_psi || // Gamma5 - Schur complement with minus mu
+ f == Qsw_minus_psi || // Gamma5 - Schur complement with minus mu
+ f == Qtm_pm_psi || // Schur complement squared
+ f == Qsw_pm_psi) { // Schur complement squared
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * This is the part of the reweighting that comes from the csw term.
+ */
+static double get_sw_reweighting(const double mu1, const double mu2,
+ const double kappa1, const double kappa2, const double csw1,
+ const double csw2) {
+ double ret;
+ sw_term((const su3**) g_gauge_field, kappa1, csw1);
+ ret = -sw_trace(0, mu1);
+ if (kappa1 != kappa2 || csw1 != csw2) {
+ sw_term((const su3**) g_gauge_field, kappa2, csw2);
+ }
+ ret += sw_trace(0, mu2);
+ return (ret);
+}
+
+static int is_sym_pos_definite(const matrix_mult f) {
+ if (f == Qtm_pm_psi || // Schur complement squared
+ f == Qsw_pm_psi || f == Q_pm_psi) { // Full operator squared
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Change of parameters requires in some cases update of the csw part.
+ */
+static void update_global_parameters(const int op_id) {
+ operator * optr = &operator_list[op_id];
+ g_kappa = optr->kappa;
+ boundary(g_kappa);
+ g_mu = optr->mu;
+ g_c_sw = optr->c_sw;
+ if (optr->type == CLOVER) {
+ if (g_cart_id == 0 && g_debug_level > 1) {
+ printf("#\n# csw = %e, computing clover leafs\n", g_c_sw);
+ }
+ init_sw_fields(VOLUME);
+
+ sw_term((const su3**) g_gauge_field, optr->kappa, optr->c_sw);
+ /* this must be EE here! */
+ /* to match clover_inv in Qsw_psi */
+ sw_invert(EE, optr->mu);
+ /* now copy double sw and sw_inv fields to 32bit versions */
+ copy_32_sw_fields();
+ }/*clover leave update*/
+}
+
+/*
+ * Generic inversion routine. The one in operator.c (op_invert) is not appropriate for
+ * this purpose since it is designed for the propagator measurements.
+ * The solve_degenerate (solver/monomial_solve.c) does not offer the DDalphaAMG functionality
+ * for non-quadratic operator.
+ */
+static int invert_operator_Q(spinor * const P, spinor * const Q,
+ const int op_id, const int pm, int updateparameters) {
+
+ operator * optr = &operator_list[op_id];
+ int iteration_count = 0;
+ int use_solver = optr->solver;
+ int rel_prec = optr->rel_prec;
+ double eps_sq = optr->eps_sq;
+ double check_prec;
+ int max_iter = optr->maxiter;
+ matrix_mult f = optr->applyQm;
+ int is_squared = 0;
+ spinor * source = Q;
+ if (pm == 1) {
+ f = optr->applyQp;
+ }
+ solver_params_t solver_params = optr->solver_params;
+ int n = VOLUME;
+ if (is_schur_complement(f)) {
+ n = VOLUME / 2;
+ }
+
+ optr->iterations = 0;
+ optr->reached_prec = -1.;
+ update_global_parameters(op_id);
+
+ if (use_solver == MIXEDCG || use_solver == RGMIXEDCG || use_solver == CG) {
+ if (!is_sym_pos_definite(f)) {
+ f = optr->applyQsq;
+ is_squared = 1;
+ if (pm == 0) {
+ optr->applyQp(g_spinor_field[DUM_DERI], Q);
+ source = g_spinor_field[DUM_DERI];
+ }
+ }
+ }
+
+ /*check initial precision since some inverters fail if already converged*/
+ f(g_spinor_field[DUM_DERI + 2], P);
+ diff(g_spinor_field[DUM_DERI + 2], g_spinor_field[DUM_DERI + 2], source, n);
+ check_prec = square_norm(g_spinor_field[DUM_DERI + 2], VOLUME, 1);
+ if (g_proc_id == 0) {
+ printf("Inversion initial precision %e\n", check_prec);
+ }
+ if (check_prec < 1e-24) {
+ return (0);
+ }
+
+ if (use_solver == MIXEDCG || use_solver == RGMIXEDCG) {
+ // the default mixed solver is rg_mixed_cg_her
+ int
+ (*msolver_fp)(spinor * const, spinor * const, solver_params_t, const int,
+ double, const int, const int, matrix_mult,
+ matrix_mult32) = rg_mixed_cg_her;
+
+ // but it might be necessary at some point to use the old version
+ if (use_solver == MIXEDCG) {
+ msolver_fp = mixed_cg_her;
+ }
+
+ if (usegpu_flag) {
+#ifdef HAVE_GPU
+#ifdef TEMPORALGAUGE
+ to_temporalgauge(g_gauge_field, source , P);
+#endif
+ iteration_count = linsolve_eo_gpu(P, source, max_iter, eps_sq, rel_prec, n, f);
+#ifdef TEMPORALGAUGE
+ from_temporalgauge(source, P);
+#endif
+#endif
+ return (iteration_count);
+ } else {
+ if (f == Qtm_pm_psi) {
+ iteration_count = msolver_fp(P, source, solver_params, max_iter, eps_sq,
+ rel_prec, n, f, &Qtm_pm_psi_32);
+ return (iteration_count);
+ } else if (f == Q_pm_psi) {
+ iteration_count = msolver_fp(P, source, solver_params, max_iter, eps_sq,
+ rel_prec, n, f, &Q_pm_psi_32);
+ return (iteration_count);
+ } else if (f == Qsw_pm_psi) {
+ copy_32_sw_fields();
+ iteration_count = msolver_fp(P, source, solver_params, max_iter, eps_sq,
+ rel_prec, n, f, &Qsw_pm_psi_32);
+ return (iteration_count);
+ } else {
+ if (g_proc_id == 0)
+ printf(
+ "Warning: 32 bit matrix not available. Falling back to CG in 64 bit\n");
+ use_solver = CG;
+ }
+ }
+ }
+ if (use_solver == CG) {
+ iteration_count = cg_her(P, source, max_iter, eps_sq, rel_prec, n, f);
+ } else if (use_solver == BICGSTAB) {
+ iteration_count = bicgstab_complex(P, source, max_iter, eps_sq, rel_prec, n,
+ f);
+ }
+#ifdef DDalphaAMG
+ else if (use_solver == MG)
+ {
+ if (updateparameters == 1)
+ {
+ MG_update_kappa (g_kappa);
+ }
+ iteration_count = MG_solver (P, source, eps_sq, max_iter, rel_prec, n,
+ g_gauge_field, f);
+ }
+#endif
+ else {
+ if (g_proc_id == 0)
+ printf("Error: solver not allowed for degenerate solve. Aborting...\n");
+ return -1;
+ }
+ if (is_squared) {
+ f = optr->applyQm;
+ if (pm == 1) {
+ optr->applyQm(g_spinor_field[DUM_DERI], P);
+ assign(P, g_spinor_field[DUM_DERI], n);
+ f = optr->applyQp;
+ }
+ }
+ /*check precision*/
+ f(g_spinor_field[DUM_DERI], P);
+ diff(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI], Q, n);
+ check_prec = square_norm(g_spinor_field[DUM_DERI], VOLUME, 1);
+ optr->reached_prec = check_prec;
+ optr->iterations = iteration_count;
+ if (g_proc_id == 0) {
+ printf("Inversion final precision %e\n", check_prec);
+ }
+ return (iteration_count);
+}
+
+/*
+ * Interpolation for the factorized version of the reweighting factors.
+ */
+static void interpolate(double * const rcurrent, const double rinitial,
+ const double rfinal, const int numsteps, const int thisstep) {
+ (*rcurrent) = rinitial
+ + (thisstep + 1) * (rfinal - rinitial) / ((double) numsteps);
+}
+
+/*
+ * Alternative calculation of reweighting factors using Chebyshev polynomial approximations.
+ */
+static void chebyshev_coeff(const unsigned int np, double * const coeff,
+ const double a, const double b) {
+ double * fxk;
+ double * acxk;
+ fxk = malloc(np * sizeof(double));
+ acxk = malloc(np * sizeof(double));
+ int n, k;
+ double fakt;
+ for (n = 0; n < np; n++) {
+ acxk[n] = (3.14159265358979323846) * ((double) n + 0.5) / ((double) np);
+ fxk[n] = log(a * cos(acxk[n]) + b);
+ }
+ for (k = 0; k < np; k++) {
+ coeff[k] = 0;
+ fakt = (k == 0) ? 1.0 / (double) np : 2.0 / (double) np;
+ for (n = 0; n < np; n++) {
+ coeff[k] += fakt * cos(k * acxk[n]) * fxk[n];
+ }
+ }
+ free(fxk);
+ free(acxk);
+}
+
+/*
+ * Alternative calculation of reweighting factors using Chebyshev polynomial approximations.
+ */
+static double poly_cheb(const unsigned int np, const double * const coeff,
+ const double x) {
+ double y, t1, t0, t2;
+ int j;
+ y = coeff[0];
+ if (np < 1) {
+ return y;
+ }
+ t0 = 1.0;
+ t1 = x;
+ y += coeff[1] * t1;
+ for (j = 1; j + 1 < np; j++) {
+ t2 = 2.0 * x * t1 - t0;
+ t0 = t1;
+ t1 = t2;
+ y += coeff[j + 1] * t1;
+ }
+ return y;
+}
+
+/*
+ * Alternative calculation of reweighting factors using Chebyshev polynomial approximations.
+ * Main part: log determinant estimation.
+ */
+/*Trivial test tests the function with the scaled identity matrix.*/
+/*#define TRIVIAL_TEST*/
+/*Convergence checks: comparison of order n and n+1.*/
+static void log_determinant_estimate(const int operatorid, int chebmax,
+ int estimators, const double minev, const double maxev, const double kappa1,
+ const double kappa2, const double kappa2Mu1, const double kappa2Mu2,
+ const double shift, const int traj, const split_list * const split,
+ const vector_list * const coefflist) {
+ double * coeff;
+ const double t1 = maxev - minev;
+ const double t2 = maxev + minev;
+ const double a = 2.0 / t1;
+ const double b = -t2 / t1;
+ const double am = t1 / 2.0;
+ const double bm = t2 / 2.0;
+ double rel_shift;
+ int k, l, n;
+ int orderstart, orderend;
+ int splitlength, sl;
+ spinor_array spinorarray;
+ static int written = 0;
+ double x, y, y1, prodre;
+ FILE * ofs;
+ spinor * vs;
+ spinor * u;
+
+ // for convergence checks
+ spinor * unm1;
+ double prodrenm1;
+
+ spinor * v0;
+ spinor * v1;
+ spinor * v2;
+ spinor * vt0;
+ spinor * vt1;
+ spinor * vt2;
+ spinor * tmp;
+ operator * optr;
+ char* filename;
+ char buf[100];
+
+ spinorarray.ar = NULL;
+ spinorarray.buffer = NULL;
+ spinorarray.length = 0;
+
+ n = VOLUME;
+
+ filename = buf;
+ sprintf(filename, "%s%.6d", "reweightingmeas_cheb.", traj);
+
+ optr = &operator_list[operatorid];
+
+ spinorarray.length = 9;
+ if (is_schur_complement(optr->applyQsq)) {
+ n = VOLUME / 2;
+ alloc_spinor_field(&spinorarray, 1);
+ } else {
+ alloc_spinor_field(&spinorarray, 0);
+ }
+
+ vs = spinorarray.ar[0];
+ u = spinorarray.ar[1];
+ v0 = spinorarray.ar[2];
+ v1 = spinorarray.ar[3];
+ v2 = spinorarray.ar[4];
+ vt0 = spinorarray.ar[5];
+ vt1 = spinorarray.ar[6];
+ vt2 = spinorarray.ar[7];
+
+ // for convergence checks
+ unm1 = spinorarray.ar[8];
+
+ if (coefflist->el != NULL && coefflist->s != 0) {
+ chebmax = coefflist->s;
+ coeff = malloc(chebmax * sizeof(double));
+ for (k = 0; k < chebmax; k++) {
+ coeff[k] = coefflist->el[k];
+ }
+ } else {
+ coeff = malloc(chebmax * sizeof(double));
+ chebyshev_coeff(chebmax, coeff, am, bm);
+ }
+ if (g_proc_id == 0 && g_debug_level > 3 && written == 0) {
+ written = 1;
+ ofs = fopen("polynomialapproxtest.txt", "w");
+ fprintf(ofs,
+ "# Test of the Chebyshev approximation of the log(x) function: index x y |y-log(x)| chebyshevorder minx, maxx\n");
+ for (k = 0; k < 200; k++) {
+ x = minev + (maxev - minev) * (double) k / (double) (200 - 1);
+ y = poly_cheb(chebmax, coeff, a * x + b);
+ y1 = NAN;
+ if (chebmax > 0) {
+ y1 = poly_cheb(chebmax - 1, coeff, a * x + b);
+ }
+ fprintf(ofs, "%d %g %g %g %g %g %d %g %g\n", k, x, y, y1,
+ fabs(y - log(x)), fabs(y1 - log(x)), chebmax, minev, maxev);
+ }
+ fclose(ofs);
+ ofs = fopen("coeff_out.txt", "w");
+ for (k = 0; k < chebmax; k++) {
+ fprintf(ofs, "%g\n", coeff[k]);
+ }
+ fclose(ofs);
+ }
+
+ /* include T_min(x) to T_(max-1) (x) */
+ orderstart = 0;
+ orderend = chebmax;
+ splitlength = 1;
+ rel_shift = shift;
+ if (split->est != NULL && split->ord != NULL && split->s != 0) {
+ splitlength = split->s;
+ orderend = split->ord[0];
+ estimators = split->est[0];
+ }
+ for (sl = 0; sl < splitlength; sl++) {
+ if (sl > 0) {
+ orderstart = orderend;
+ orderend = split->ord[sl];
+ estimators = split->est[sl];
+ rel_shift = 0.0;
+ }
+
+ if (orderend > 0) {
+ for (k = 0; k < estimators; k++) {
+ if (orderstart > 1 || orderend < 2) {
+ zero_spinor_field(u, n);
+ // convergence check
+ zero_spinor_field(unm1, n);
+
+ }
+ /*
+ * Generate estimator
+ */
+ if (n == VOLUME / 2) {
+ random_spinor_field_eo(vs, reproduce_randomnumber_flag, RN_Z2);
+ } else {
+ random_spinor_field_lexic(vs, reproduce_randomnumber_flag, RN_Z2);
+ }
+
+ assign(v0, vs, n);
+ assign(vt0, vs, n);
+
+#ifdef TRIVIAL_TEST
+ prodre = scalar_prod_r(vs1, vs1, n, 1);
+ printf("Test noise /Volume= %g, Volume=%d\n",prodre/(double)n,n);
+ mul_r(v1,kappa1,vs1,n);
+#else
+ optr->kappa = kappa1;
+ optr->mu = kappa2Mu1;
+ update_global_parameters(operatorid);
+ optr->applyQsq(v1, vs);
+#endif
+ /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */
+ assign_mul_add_mul_r(v1, vs, a, b, n);
+
+#ifdef TRIVIAL_TEST
+ mul_r(vt1,kappa2,vs1,n);
+#else
+ optr->kappa = kappa2;
+ optr->mu = kappa2Mu2;
+ update_global_parameters(operatorid);
+ optr->applyQsq(vt1, vs);
+#endif
+ /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */
+ assign_mul_add_mul_r(vt1, vs, a, b, n);
+
+ if (orderstart < 2) {
+ /* Makes (*R)=c1*(*S)-c2*(*U) , c1 and c2 are complex constants */
+ mul_diff_mul_r(u, vt1, v1, coeff[1], coeff[1], n);
+
+ // convergence check
+ if (orderend > 1) {
+ mul_diff_mul_r(unm1, vt1, v1, coeff[1], coeff[1], n);
+ }
+
+ }
+
+#ifndef TRIVIAL_TEST
+ optr->kappa = kappa1;
+ optr->mu = kappa2Mu1;
+ update_global_parameters(operatorid);
+#endif
+
+ for (l = 1; l + 1 < orderend; l++) {
+#ifdef TRIVIAL_TEST
+ mul_r(v2,kappa1,v1,n);
+#else
+ optr->applyQsq(v2, v1);
+#endif
+
+ /* Makes (*R) = c1*(*R) + c2*(*S) + c3*(*U) */
+ assign_mul_add_mul_add_mul_r(v2, v1, v0, 2.0 * a, 2.0 * b, -1.0, n);
+ tmp = v0;
+ v0 = v1;
+ v1 = v2;
+ v2 = tmp;
+
+ if (l + 1 >= orderstart) {
+ /* (*P) = (*P) + c(*Q) c is a real constant */
+ assign_add_mul_r(u, v1, -coeff[l + 1], n);
+
+ // convergence checks
+ if (l + 2 < orderend) {
+ assign_add_mul_r(unm1, v1, -coeff[l + 1], n);
+ }
+
+ }
+ }
+#ifndef TRIVIAL_TEST
+ optr->kappa = kappa2;
+ optr->mu = kappa2Mu2;
+ update_global_parameters(operatorid);
+#endif
+
+ for (l = 1; l + 1 < orderend; l++) {
+#ifdef TRIVIAL_TEST
+ mul_r(vt2,kappa2,vt1,n);
+#else
+ optr->applyQsq(vt2, vt1);
+#endif
+ /* Makes (*R) = c1*(*R) + c2*(*S) + c3*(*U) */
+ assign_mul_add_mul_add_mul_r(vt2, vt1, vt0, 2.0 * a, 2.0 * b, -1.0,
+ n);
+ tmp = vt0;
+ vt0 = vt1;
+ vt1 = vt2;
+ vt2 = tmp;
+ if (l + 1 >= orderstart) {
+ /* (*P) = (*P) + c(*Q) c is a real constant */
+ assign_add_mul_r(u, vt1, coeff[l + 1], n);
+
+ // convergence checks
+ if (l + 2 < orderend) {
+ assign_add_mul_r(unm1, vt1, coeff[l + 1], n);
+ }
+
+ }
+ }
+
+ prodre = scalar_prod_r(vs, u, n, 1);
+ // convergence checks
+ prodrenm1 = scalar_prod_r(vs, unm1, n, 1);
+
+ if (g_proc_id == 0) {
+ ofs = fopen(filename, "a");
+ fprintf(ofs, "%d %d %g %g %g %g %d %d %g %g ", traj, sl, kappa1,
+ kappa2, kappa2Mu1, kappa2Mu2, orderend, orderstart, minev, maxev);
+ fprintf(ofs, " %.17g %.17g ", prodre + rel_shift, prodre);
+ // convergence checks
+ fprintf(ofs, " %.17g \n", prodrenm1 + rel_shift);
+
+ fclose(ofs);
+ }
+
+ } /* estimator iteration*/
+ } /* orderend>0*/
+ } /* splitlength loop */
+ free(coeff);
+ free_spinor_field_spinor_array(&spinorarray);
+}
+
+void reweighting_measurement(const int traj, const int id, const int ieo) {
+ reweighting_parameter* param;
+ double atime, etime;
+ operator * optr;
+ FILE *ofs;
+ FILE *ofs_full;
+ char *filename;
+ char *filename_full;
+ char buf[100];
+ char buf_full[100];
+ double square1, square2, prodre, prodim, prodreg5, prodimg5, cswpart;
+ double kappa0, kappa, k2mu0, k2mu, csw0, csw;
+ double kappafinal, k2mufinal, cswfinal, rmufinal;
+ double kappainitial, k2muinitial, cswinitial, rmuinitial;
+ double mdiff, rmu, rmu0;
+ double tmp1, tmp2, tmp3;
+ int updateinverter;
+ int kapparew;
+ int murew;
+ /* now we bring it to normal format */
+ /* here we use implicitly DUM_MATRIX and DUM_MATRIX+1 */
+ spinor * lexicfield1;
+ spinor * lexicfield2;
+
+ int operatorid;
+ int numsamples, snum, internum;
+ unsigned long int site;
+
+ updateinverter = 0;
+ param = (reweighting_parameter*) measurement_list[id].parameter;
+ lexicfield1 = g_spinor_field[4];
+ lexicfield2 = g_spinor_field[6];
+
+ operatorid = param->reweighting_operator;
+ numsamples = param->reweighting_number_sources;
+ filename = buf;
+ filename_full = buf_full;
+ sprintf(filename, "%s%.6d", "reweightingmeas.", traj);
+ sprintf(filename_full, "%s%.6d", "reweightingmeas_full_data.", traj);
+ if (g_proc_id == 0) {
+ fprintf(stdout, "Reweighting measurement %d with %d samples.\n", id,
+ numsamples);
+ }
+
+ init_operators();
+ if (no_operators < operatorid) {
+ if (g_proc_id == 0) {
+ fprintf(
+ stderr,
+ "Warning! Number of operators smaller than the given number for the reweighting operator, unable to perform measurement!\n");
+ }
+ return;
+ }
+ atime = gettime();
+
+ optr = &operator_list[operatorid];
+ optr->DownProp = 0;
+ optr->sr0 = g_spinor_field[0];
+ optr->sr1 = g_spinor_field[1];
+ optr->prop0 = g_spinor_field[2];
+ optr->prop1 = g_spinor_field[3];
+
+ /* now checking parameters
+ * The target values are obtained from the operator*/
+
+ kappafinal = optr->kappa;
+ k2mufinal = optr->mu;
+ cswfinal = optr->c_sw;
+
+ /* the initial values are obtained
+ * from the parameter
+ */
+ k2muinitial = param->k2mu0;
+ kappainitial = param->kappa0;
+ cswinitial = 0;
+ kapparew = 1;
+ if (kappainitial == kappafinal) {
+ kapparew = 0;
+ }
+ if (kappainitial == 0.0) {
+ kappainitial = kappafinal;
+ kapparew = 0;
+ }
+ if (cswinitial == 0.0) {
+ cswinitial = cswfinal;
+ }
+ /* be careful:
+ * in the mu reweighting it is the parameter Mu and not 2KappaMu that
+ * counts
+ */
+ rmufinal = k2mufinal / 2.0 / kappafinal;
+ rmuinitial = k2muinitial / 2.0 / kappainitial;
+ murew = 1;
+ if (k2muinitial == 0.0) {
+ rmuinitial = rmufinal;
+ k2muinitial = 2.0 * kappainitial * rmuinitial;
+ murew = 0;
+ }
+ if (fabs(rmuinitial - rmufinal) < 1e-14) {
+ murew = 0;
+ }
+
+ /* second option:
+ * determine mu and mu0 explicitly in the
+ */
+ if (g_proc_id == 0 && (param->rmu != 0 || param->rmu0 != 0)) {
+ printf(
+ "WARNING: measurement uses custom mu values mu=%e, mu0=%e instead of the parameters of the operator.\n",
+ param->rmu, param->rmu0);
+ }
+ if (param->rmu0 != 0) {
+ rmuinitial = param->rmu0;
+ k2muinitial = 2.0 * kappainitial * rmuinitial;
+ }
+ if (param->rmu != 0) {
+ rmufinal = param->rmu;
+ k2mufinal = 2.0 * kappafinal * rmufinal;
+ }
+ if (fabs(rmuinitial - rmufinal) > 1e-14) {
+ murew = 1;
+ }
+
+ if (murew && (g_proc_id == 0)) {
+ printf("Mu reweighting chosen: ");
+ printf("mu=%e to mu=%e.\n", rmuinitial, rmufinal);
+ }
+
+ if (kapparew && (g_proc_id == 0)) {
+ printf("Kappa reweighting chosen: ");
+ printf("kappa=%e to kappa=%e\n", kappainitial, kappafinal);
+ }
+
+ if (!murew && !kapparew) {
+ if (g_proc_id == 0) {
+ printf("ERROR: no mu or kappa reweighting.\n");
+ }
+ }
+
+ if (murew && kapparew) {
+ if (g_proc_id == 0) {
+ printf(
+ "WARNING: Mu AND Kappa reweighting chosen. If unprecond version, the rawdata has to be combined by hand!\n");
+ }
+ }
+
+ if (param->use_evenodd && !is_schur_complement(optr->applyQsq)
+ && g_proc_id == 0) {
+ printf(
+ "WARNING: If you want to use the preconditioned version the operator should be even-odd preconditioned.\n");
+ }
+
+ cswpart = 0;
+
+ if (param->evest) {
+ if (g_proc_id == 0) {
+ printf(
+ "Calculating minimal/maximal eigenvalue estimates -- no longer supported!\n");
+ }
+ //estimate_eigenvalues (operatorid, traj);
+ }
+
+ if (param->use_cheb) {
+ if (is_schur_complement(optr->applyQsq) && !param->use_evenodd
+ && g_proc_id == 0) {
+ printf(
+ "WARNING: If you want to use Chebyshev approximation without preconditioning you have to switch it of in the operator as well.\n");
+ }
+ if (param->use_evenodd == 1) {
+ cswpart = get_sw_reweighting(k2muinitial, k2mufinal, kappainitial,
+ kappafinal, cswinitial, cswfinal);
+ }
+ log_determinant_estimate(operatorid, param->cheborder,
+ param->estimatorscheb, param->minev, param->maxev, kappainitial,
+ kappafinal, k2muinitial, k2mufinal, cswpart, traj, ¶m->splitlist,
+ ¶m->coeff);
+ if (param->only_cheb) {
+ return;
+ }
+ }
+
+ kappa0 = kappa = kappainitial;
+ k2mu0 = k2mu = k2muinitial;
+ csw0 = csw = cswinitial;
+ rmu0 = rmu = rmuinitial;
+
+ if (param->interpolationsteps < 1)
+ param->interpolationsteps = 1;
+
+ if(param->kappaarray.s!=0){
+ param->interpolationsteps=param->kappaarray.s;
+ }
+
+ if (g_proc_id == 0 && g_debug_level > 0) {
+ printf("REWEIGHTING: interpolation steps %d\n",param->interpolationsteps);
+ }
+
+ for (internum = 0; internum < param->interpolationsteps; internum++) {
+ if (kapparew) {
+ kappa0 = kappa;
+ tmp1 = 1.0 / kappainitial;
+ tmp2 = 1.0 / kappafinal;
+ tmp3 = 1.0 / kappa;
+ if(internumkappaarray.s){
+ kappa=param->kappaarray.el[internum];
+ }else{
+ interpolate(&tmp3, tmp1, tmp2, param->interpolationsteps, internum);
+ kappa = 1.0 / tmp3;
+ }
+ updateinverter = 1;
+ }
+ if (murew) {
+ /* use quadratic interpolation in the case of mu*/
+ rmu0 = rmu;
+ tmp1 = rmuinitial * rmuinitial;
+ tmp2 = rmufinal * rmufinal;
+ tmp3 = rmu * rmu;
+ interpolate(&tmp3, tmp1, tmp2, param->interpolationsteps, internum);
+ rmu = sqrt(tmp3);
+ updateinverter = 1;
+ }
+
+ k2mu = 2.0 * kappa * rmu;
+ k2mu0 = 2.0 * kappa0 * rmu0;
+ if (g_proc_id == 0 && g_debug_level > 0) {
+ printf("REWEIGHTING: kappa from %.14f to %.14f, mu %.16f to %.16f, 2kappamu %.16f to %.16f\n", kappa0,kappa,rmu,rmu0,k2mu0,k2mu);
+ }
+ optr->kappa = kappa;
+ optr->mu = k2mu;
+ optr->c_sw = csw;
+
+ if (param->use_evenodd == 1) {
+ cswpart = get_sw_reweighting(k2mu0, k2mu, kappa0, kappa, csw0, csw);
+ }
+
+ for (snum = 0; snum < numsamples; snum++) {
+ if (param->use_evenodd == 0) {
+ random_spinor_field_eo(optr->sr0, reproduce_randomnumber_flag,
+ RN_GAUSS);
+ random_spinor_field_eo(optr->sr1, reproduce_randomnumber_flag,
+ RN_GAUSS);
+ convert_eo_to_lexic(lexicfield1, optr->sr0, optr->sr1);
+ square1 = square_norm(lexicfield1, VOLUME, 1);
+ // we don't want to do inversion twice for this purpose here
+ // op_id = 0, index_start = 0, write_prop = 0
+ optr->inverter(operatorid, 0, 0);
+ convert_eo_to_lexic(lexicfield2, optr->prop0, optr->prop1);
+ square2 = square_norm(lexicfield2, VOLUME, 1);
+ prodre = scalar_prod_r(lexicfield1, lexicfield2, VOLUME, 1);
+ prodim = scalar_prod_i(lexicfield1, lexicfield2, VOLUME, 1);
+ for (site = 0; site < VOLUME; site++) {
+ _gamma5(lexicfield2[site], lexicfield2[site]);
+ }
+ prodreg5 = scalar_prod_r(lexicfield1, lexicfield2, VOLUME, 1);
+ prodimg5 = scalar_prod_i(lexicfield1, lexicfield2, VOLUME, 1);
+
+ if (g_mpi_time_rank == 0 && g_proc_coords[0] == 0) {
+ ofs = fopen(filename, "a");
+ ofs_full = fopen(filename_full, "a");
+ fprintf(ofs, "%d %d %d %d ", traj, operatorid, internum, snum);
+ fprintf(ofs_full, "%d %d %d %d ", traj, operatorid, internum, snum);
+
+ /*print all raw data for cross check*/
+ fprintf(ofs_full,
+ "%.17g %.17g %.17g %.17g %.17g %.17g %.17g %.17g ", k2mu0, k2mu,
+ kappa0, kappa, csw0, csw, rmu0, rmu);
+ fprintf(ofs_full, "%.17g %.17g %.17g %.17g %.17g %.17g\n", square1,
+ square2, prodre, prodim, prodreg5, prodimg5);
+ /*print two and one flavour reweighting log factors*/
+ if (murew) { /* ignoring rounding errors*/
+ fprintf(ofs, "%.17g %.17g %.17g\n",
+ (rmu * rmu - rmu0 * rmu0) * square2, (rmu - rmu0) * prodreg5,
+ (rmu - rmu0) * prodimg5);
+ }
+ if (kapparew) {
+ mdiff = 0.5 / kappa - 0.5 / kappa0;
+ fprintf(ofs, "%.17g %.17g %.17g\n",
+ 2.0 * mdiff * prodre + mdiff * mdiff * square2, mdiff * prodre,
+ mdiff * prodim);
+ }
+ fclose(ofs);
+ fclose(ofs_full);
+ }
+ } else { /* end not even odd*/
+ set_even_to_zero(optr->sr0);
+ set_even_to_zero(optr->prop0);
+ random_spinor_field_eo(lexicfield1, reproduce_randomnumber_flag,
+ RN_GAUSS);
+ square1 = square_norm(lexicfield1, VOLUME / 2, 1);
+
+ optr->kappa = kappa0;
+ optr->mu = k2mu0;
+ update_global_parameters(operatorid);
+
+ optr->applyQm(optr->sr0, lexicfield1);
+ assign(optr->prop0, lexicfield1, VOLUME / 2);
+
+ optr->kappa = kappa;
+ optr->mu = k2mu;
+ /* done in inverter: update_global_parameters(operatorid);*/
+
+ invert_operator_Q(optr->prop0, optr->sr0, operatorid, 0,
+ updateinverter);
+ updateinverter = 0;
+
+ square2 = square_norm(optr->prop0, VOLUME / 2, 1);
+
+ if (g_mpi_time_rank == 0 && g_proc_coords[0] == 0) {
+ ofs = fopen(filename, "a");
+ ofs_full = fopen(filename_full, "a");
+ fprintf(ofs, "%d %d %d %d ", traj, operatorid, internum, snum);
+ fprintf(ofs_full, "%d %d %d %d ", traj, operatorid, internum, snum);
+ fprintf(ofs_full,
+ "%.17g %.17g %.17g %.17g %.17g %.17g %.17g %.17g ", k2mu0, k2mu,
+ kappa0, kappa, csw0, csw, rmu, rmu0);
+ fprintf(ofs_full, "%.17g %.17g %.17g\n", square1, square2, cswpart);
+ fprintf(ofs, "%.17g\n", square1 - square2 + cswpart);
+ fclose(ofs);
+ fclose(ofs_full);
+ }
+
+ }/* end even odd*/
+
+ }/* loop over estimators */
+
+ } /* loop over interpolation steps*/
+
+ etime = gettime();
+
+ if (g_proc_id == 0 && g_debug_level > 0) {
+ printf("REWEIGHTING: measurement done int t/s = %1.4e\n", etime - atime);
+ }
+ return;
+}
+
+/**
+ * Destructor for the parameter, frees allocated memory.
+ * @param par reweighting parameter.
+ */
+void free_reweighting_parameter(void* par) {
+ reweighting_parameter* param;
+ param = (reweighting_parameter*) (par);
+ if (param->coeff.el)
+ free(param->coeff.el);
+ if (param->splitlist.ord)
+ free(param->splitlist.ord);
+ if (param->splitlist.est)
+ free(param->splitlist.est);
+ if(param->kappaarray.el)
+ free(param->kappaarray.el);
+ param->kappaarray.el=NULL;
+ param->kappaarray.s=0;
+ param->coeff.el = NULL;
+ param->coeff.s = 0;
+ param->splitlist.ord = NULL;
+ param->splitlist.est = NULL;
+ param->splitlist.s = 0;
+}
+
+/**
+ * Coefficients provided for the Chebyshev approximation of log(x).
+ * Values are read from coeff.dat.
+ * @param v (output) value
+ */
+static void read_coeff_from_file(vector_list* v) {
+ FILE* file;
+ unsigned int l;
+ double dat;
+
+ file = fopen("coeff.dat", "r");
+ l = 0;
+ dat = 0;
+
+ if (file) {
+ while (fscanf(file, "%lg ", &dat) > 0) {
+ l++;
+ }
+ v->s = l;
+ v->el = malloc(l * sizeof(double));
+ file = freopen("coeff.dat", "r", file);
+ l = 0;
+ while (fscanf(file, "%lg ", &dat) > 0) {
+ v->el[l++] = dat;
+ }
+ if (g_debug_level > 3) {
+ printf(
+ "The following coefficients have been read from file coeff.dat:\n");
+ for (l = 0; l < v->s; l++) {
+ printf("%d %lg\n", l, v->el[l]);
+ }
+ }
+ fclose(file);
+ } else {
+ if (g_proc_id == 0) {
+ printf("File coeff.dat not present.\n");
+ }
+ v->el = NULL;
+ v->s = 0;
+ }
+
+}
+
+/**
+ *
+ * @param list
+ */
+static void read_splitlist(split_list* list) {
+ FILE* file;
+ unsigned int l;
+ int dat1, dat2;
+
+ file = fopen("split.dat", "r");
+ l = 0;
+ dat1 = dat2 = 0;
+
+ if (file) {
+ while (fscanf(file, "%d ", &dat1) > 0 && fscanf(file, "%d ", &dat2) > 0) {
+ l++;
+ }
+ list->s = l;
+ list->ord = malloc(l * sizeof(unsigned int));
+ list->est = malloc(l * sizeof(unsigned int));
+
+ file = freopen("split.dat", "r", file);
+ l = 0;
+ while (fscanf(file, "%d ", &dat1) > 0 && fscanf(file, "%d ", &dat2) > 0) {
+ list->ord[l] = dat1;
+ list->est[l] = dat2;
+ l++;
+ }
+ if (g_debug_level > 3) {
+ printf(
+ "The following factor splits have been read from file split.dat:\n");
+ for (l = 0; l < list->s; l++) {
+ printf("%d %d %d\n", l, list->ord[l], list->est[l]);
+ }
+ }
+ fclose(file);
+ } else {
+ if (g_proc_id == 0) {
+ printf("File split.dat not present.\n");
+ }
+ list->ord = NULL;
+ list->est = NULL;
+ list->s = 0;
+ }
+
+}
+
+static void read_kappalist(vector_list* kappaarray) {
+ FILE* file;
+ unsigned int l;
+ double dat;
+
+ file = fopen("kappa.dat", "r");
+ l = 0;
+ dat = 0;
+
+ if (file) {
+ while (fscanf(file, "%lg ", &dat) > 0) {
+ l++;
+ }
+ if(l==0){
+ fclose(file);
+ return;
+ }
+ kappaarray->s=l;
+ kappaarray->el = malloc(l * sizeof(double));
+
+ file = freopen("kappa.dat", "r", file);
+ l = 0;
+ while (fscanf(file, "%lg ", &dat) > 0) {
+ kappaarray->el[l++] = dat;
+ }
+ if (g_debug_level > 3) {
+ printf(
+ "The following kappa value have been obtained from kappa.dat:\n");
+ for (l = 0; l < kappaarray->s; l++) {
+ printf("%d %lg\n", l, kappaarray->el[l]);
+ }
+ }
+ fclose(file);
+ } else {
+ if (g_proc_id == 0) {
+ printf("File kappa.dat not present.\n");
+ }
+ kappaarray->el = NULL;
+ kappaarray->s = 0;
+ }
+
+}
+
+void initialize_reweighting_parameter(void** parameter) {
+ reweighting_parameter* param;
+ if (!(*parameter)) {
+ (*parameter) = malloc(sizeof(reweighting_parameter));
+ param = (reweighting_parameter*) (*parameter);
+ param->reweighting_operator = 0;
+ param->reweighting_number_sources = 0;
+ param->use_evenodd = 0;
+ param->k2mu0 = 0.0;
+ param->kappa0 = 0.0;
+ param->kappaarray.el= NULL;
+ param->kappaarray.s=0;
+ param->rmu0 = 0.0;
+ param->rmu = 0.0;
+ param->minev = 1e-7;
+ param->maxev = 20.0;
+ param->interpolationsteps = 1;
+ param->estimatorscheb = 0;
+ param->cheborder = 0;
+ param->use_cheb = 0;
+ param->only_cheb = 0;
+ param->coeff.el = NULL;
+ param->coeff.s = 0;
+ param->splitlist.ord = NULL;
+ param->splitlist.est = NULL;
+ param->splitlist.s = 0;
+ param->evest = 0;
+ param->testchebconvergence = 0;
+ read_coeff_from_file(¶m->coeff);
+ read_splitlist(¶m->splitlist);
+ //read_kappalist(¶m->kappaarray);
+ }
+}
diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h
new file mode 100644
index 000000000..5c57a5654
--- /dev/null
+++ b/meas/reweightingmeas.h
@@ -0,0 +1,99 @@
+/***********************************************************************
+ *
+ * Measurements of the reweighting factors by Georg Bergner 2016
+ *
+ * Copyright (C) 20016 Georg Bergner
+ *
+ * This file is part of tmLQCD.
+ *
+ * tmLQCD is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * tmLQCD is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with tmLQCD. If not, see .
+ ***********************************************************************/
+
+#ifndef _REWEIGHTING_MEASUREMENT_H
+#define _REWEIGHTING_MEASUREMENT_H
+#include
+#include
+
+/**
+ * This struct collects data for the Chebyshev reweighting factor measurements.
+ * These are the coefficients for the log(x) approximation provided from outside.
+ */
+typedef struct{
+ double* el;
+ unsigned int s;
+} vector_list;
+
+inline void allocate(vector_list* v, const unsigned int length){
+ v->s=length;
+ v->el = malloc(length * sizeof(double));
+}
+
+/**
+ * This struct collects data for the Chebyshev reweighting factor measurements.
+ * The split_list allows to combine different approximations.
+ */
+typedef struct {
+ unsigned int * ord;
+ unsigned int* est;
+ unsigned int s;
+
+} split_list;
+
+
+/**
+ * Parameters for the reweighting factor measurements.
+ */
+typedef struct {
+ int reweighting_operator;
+ int reweighting_number_sources;
+ int use_evenodd;
+ double k2mu0;
+ double kappa0;
+ vector_list kappaarray;
+ double rmu0;
+ double rmu;
+ double minev;
+ double maxev;
+ double testchebconvergence;
+ int interpolationsteps;
+ int estimatorscheb;
+ int cheborder;
+ int use_cheb;
+ int only_cheb;
+ int evest;
+ vector_list coeff;
+ split_list splitlist;
+} reweighting_parameter;
+
+/**
+ * Destructor for parameter.
+ * @param par
+ */
+void free_reweighting_parameter(void* par);
+
+/**
+ * Constructor for parameter.
+ * @param parameter
+ */
+void initialize_reweighting_parameter(void** parameter);
+
+/**
+ * main measurement.
+ * @param traj
+ * @param t0
+ * @param ieo
+ */
+void reweighting_measurement(const int traj, const int t0, const int ieo);
+
+#endif
diff --git a/monomial/monomial.h b/monomial/monomial.h
index c2321956f..c03a686f5 100644
--- a/monomial/monomial.h
+++ b/monomial/monomial.h
@@ -50,6 +50,7 @@
#define CLOVERRAT 19
#define CLOVERRATCOR 20
#define CLOVERDETRATIORW 21
+#define CLOVERDETRATIORWD 22
#define max_no_monomials 30
diff --git a/read_input.l b/read_input.l
index 16c34fc2e..b96f8ee18 100644
--- a/read_input.l
+++ b/read_input.l
@@ -59,6 +59,7 @@ EQL {SPC}*={SPC}*
#include"monomial/monomial.h"
#include"solver/solver_types.h"
#include"meas/measurements.h"
+#include"meas/reweightingmeas.h"
#include"integrator.h"
#include"operator.h"
#include"phmc.h"
@@ -266,6 +267,32 @@ static inline double fltlist_next_token(int * const list_end){
}
}
+ static inline void parse_double_vector(const char * const input,vector_list* vector){
+ char paramname[100];
+ char* inputcopy;
+ int list_end = 0;
+ int l=0;
+ double value = 0;
+ inputcopy=strdup(input);
+ fltlist_tokenize(inputcopy, paramname, 100);
+ value = (double)fltlist_next_token(&list_end);
+ while( list_end != 1 ){
+ l++;
+ value = (double)fltlist_next_token(&list_end);
+ }
+ free(inputcopy);
+ allocate(vector,l);
+ fltlist_tokenize(input, paramname, 100);
+ value = (double)fltlist_next_token(&list_end);
+ l=0;
+ while( list_end != 1 ){
+ vector->el[l]=value;
+ l++;
+ value = (double)fltlist_next_token(&list_end);
+ }
+ }
+
+
%}
%option never-interactive
@@ -339,6 +366,7 @@ static inline double fltlist_next_token(int * const list_end){
%x NOSOURCESZ2
%x INITMEASUREMENT
%x ONLINEMEAS
+%x REWEIGHTINGMEAS
%x PIONNORMMEAS
%x PLOOP
%x ORIENTEDPLAQUETTESMEAS
@@ -1603,6 +1631,7 @@ static inline double fltlist_next_token(int * const list_end){
mnl->type = CLOVERDETRATIORW;
strcpy((*mnl).name, "CLOVERDETRATIORW");
}
+
else if(strcmp(yytext, "DETRATIO")==0) {
mnl->type = DETRATIO;
strcpy((*mnl).name, "DETRATIO");
@@ -2311,6 +2340,7 @@ static inline double fltlist_next_token(int * const list_end){
if(myverbose) printf("initialising measurements line %d\n", line_of_file);
current_measurement++;
meas = &measurement_list[current_measurement];
+ meas->parameter=(void*)NULL;
meas->id = current_measurement;
meas->direction = 0;
meas->max_iter = 15000;
@@ -2322,6 +2352,11 @@ static inline double fltlist_next_token(int * const list_end){
meas->type = PIONNORM;
strcpy((*meas).name, "PIONNORM");
}
+ else if(strcmp(yytext, "REWEIGHTINGMEAS")==0) {
+ meas->type = REWEIGHTING;
+ initialize_reweighting_parameter(&meas->parameter);
+ strcpy((*meas).name, "REWEIGHTINGMEAS");
+ }
else if(strcmp(yytext, "POLYAKOVLOOP")==0) {
meas->type = POLYAKOV;
strcpy((*meas).name, "POLYAKOV");
@@ -2358,13 +2393,14 @@ static inline double fltlist_next_token(int * const list_end){
if(myverbose) printf("measurement has id %d\n", current_measurement);
if(meas->type == ONLINE) BEGIN(ONLINEMEAS);
+ else if(meas->type == REWEIGHTING) BEGIN(REWEIGHTINGMEAS);
else if(meas->type == PIONNORM) BEGIN(PIONNORMMEAS);
else if(meas->type == POLYAKOV) BEGIN(PLOOP);
else if(meas->type == ORIENTED_PLAQUETTES) BEGIN(ORIENTEDPLAQUETTESMEAS);
else if(meas->type == GRADIENT_FLOW) BEGIN(GRADIENTFLOWMEAS);
}
-{
+{
^EndMeasurement{SPC}* {
if(myverbose) printf("Measurement with id %d parsed in line %d\n\n", meas->id, line_of_file);
BEGIN(0);
@@ -2376,7 +2412,7 @@ static inline double fltlist_next_token(int * const list_end){
}
}
-{
+{
{SPC}*MaxSolverIterations{EQL}{DIGIT}+ {
sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
meas->max_iter = a;
@@ -2397,6 +2433,111 @@ static inline double fltlist_next_token(int * const list_end){
}
}
+
+{
+ {SPC}*Operator{EQL}{DIGIT}+ {
+ sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->reweighting_operator = a;
+ if(myverbose) printf(" ReweightingOperator set to %d line %d measurement id=%d\n", a, line_of_file, meas->id);
+ }
+ {SPC}*Samples{EQL}{DIGIT}+ {
+ sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->reweighting_number_sources = a;
+ if(myverbose) printf(" ReweightingSamples set to %d line %d measurement id=%d\n", a, line_of_file, meas->id);
+ }
+ {SPC}*InterpolationSteps{EQL}{DIGIT}+ {
+ sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->interpolationsteps = a;
+ if(myverbose) printf(" ReweightingSamples set to %d line %d measurement id=%d\n", a, line_of_file, meas->id);
+ }
+ {SPC}*UseEvenOdd{EQL}{DIGIT}+ {
+ sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->use_evenodd = a;
+ if(myverbose) printf(" UseEvenOdd set to %d line %d measurement id=%d\n", a, line_of_file, meas->id);
+ }
+ {SPC}*2KappaMu0{EQL}{FLT} {
+ sscanf(yytext, " %[20a-zA-Z] = %lf", name, &c);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->k2mu0 = c;
+ if(myverbose) printf("Reweighting 2KappaMu0 set to %e line %d\n", c, line_of_file);
+ }
+ {SPC}*Mu{EQL}{FLT} {
+ sscanf(yytext, " %[a-zA-Z] = %lf", name, &c);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->rmu = c;
+ if(myverbose) printf("Reweighting Mu set to %e line %d\n", c, line_of_file);
+ }
+ {SPC}*Mu0{EQL}{FLT} {
+ sscanf(yytext, " %[0a-zA-Z] = %lf", name, &c);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->rmu0 = c;
+ if(myverbose) printf("Reweighting Mu0 set to %e line %d\n", c, line_of_file);
+ }
+ {SPC}*Kappa0{EQL}{FLT} {
+ sscanf(yytext, " %[20a-zA-Z] = %lf", name, &c);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->kappa0 = c;
+ if(myverbose) printf("Reweighting Kappa0 set to %e line %d\n", c, line_of_file);
+ }
+ {SPC}*UseCheb{EQL}{DIGIT}+ {
+ sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->use_cheb = a;
+ if(myverbose) printf(" UseCheb set to %d line %d measurement id=%d\n", a, line_of_file, meas->id);
+ }
+ {SPC}*EvEst{EQL}{DIGIT}+ {
+ sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->evest = a;
+ if(myverbose) printf(" EvEst set to %d line %d measurement id=%d\n", a, line_of_file, meas->id);
+ }
+ {SPC}*UseChebOnly{EQL}{DIGIT}+ {
+ sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->only_cheb = a;
+ if(myverbose) printf(" UseChebOnly set to %d line %d measurement id=%d\n", a, line_of_file, meas->id);
+ }
+ {SPC}*ChebOrder{EQL}{DIGIT}+ {
+ sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->cheborder = a;
+ if(myverbose) printf(" ChebOrder set to %d line %d measurement id=%d\n", a, line_of_file, meas->id);
+ }
+ {SPC}*ChebEst{EQL}{DIGIT}+ {
+ sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->estimatorscheb = a;
+ if(myverbose) printf(" ChebEst set to %d line %d measurement id=%d\n", a, line_of_file, meas->id);
+ }
+ {SPC}*MinEv{EQL}{FLT} {
+ sscanf(yytext, " %[20a-zA-Z] = %lf", name, &c);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->minev = c;
+ if(myverbose) printf("Reweighting MinEv set to %e line %d\n", c, line_of_file);
+ }
+ {SPC}*MaxEv{EQL}{FLT} {
+ sscanf(yytext, " %[20a-zA-Z] = %lf", name, &c);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->maxev = c;
+ if(myverbose) printf("Reweighting MaxEv set to %e line %d\n", c, line_of_file);
+ }
+ {SPC}*ChebConvLimit{EQL}{FLT} {
+ sscanf(yytext, " %[a-zA-Z] = %lf", name, &c);
+ initialize_reweighting_parameter(&meas->parameter);
+ ((reweighting_parameter*)meas->parameter)->testchebconvergence = c;
+ if(myverbose) printf("Reweighting ChebConvLimit set to %e line %d\n", c, line_of_file);
+ }
+ {SPC}*KappaSteps{EQL}{FLTLIST} {
+ initialize_reweighting_parameter(&meas->parameter);
+ parse_double_vector(yytext,&((reweighting_parameter*)meas->parameter)->kappaarray);
+ if(myverbose) printf("Reweighting KappaSteps %d line %d\n", ((reweighting_parameter*)meas->parameter)->kappaarray.s, line_of_file);
+ }
+}
+
{
{SPC}*StepSize{EQL}{FLT} {
sscanf(yytext, " %[2a-zA-Z] = %lf", name, &c);
@@ -2410,6 +2551,7 @@ static inline double fltlist_next_token(int * const list_end){
}
}
+
{
{SPC}*Direction{EQL}[03] {
sscanf(yytext, " %[a-zA-Z] = %d", name, &a);
@@ -2941,7 +3083,7 @@ static inline double fltlist_next_token(int * const list_end){
BEGIN(comment_caller);
}
-{SPC}*\n {
+{SPC}*\n {
line_of_file++;
}
<*>{SPC}*\n {