From acceda0d12ecd99fa0ea2180c26a68c62afd6531 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Fri, 19 Aug 2016 14:22:38 +0200 Subject: [PATCH 01/22] added new measurements of reweighting factors and changed concept for measurements --- meas/reweightingmeas.c | 577 ++++++++++++++++++++++++++ meas/reweightingmeas.h | 55 +++ measure.c | 492 ++++++++++++++++++++++ monomial/cloverdetratio_rwdmonomial.c | 103 +++++ monomial/cloverdetratio_rwdmonomial.h | 31 ++ 5 files changed, 1258 insertions(+) create mode 100644 meas/reweightingmeas.c create mode 100644 meas/reweightingmeas.h create mode 100644 measure.c create mode 100644 monomial/cloverdetratio_rwdmonomial.c create mode 100644 monomial/cloverdetratio_rwdmonomial.h diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c new file mode 100644 index 000000000..13c1605e1 --- /dev/null +++ b/meas/reweightingmeas.c @@ -0,0 +1,577 @@ +/*********************************************************************** + * + * Measurements of the reweighting factors by Georg Bergner 2016 + * + * Copyright (C) 2008 Carsten Urbach + * + * 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 "linalg/convert_eo_to_lexic.h" +#include "measurements.h" +#include "correlators.h" +#include "gettime.h" +#include "linalg/square_norm.h" +#include "linalg/scalar_prod_r.h" +#include "linalg/scalar_prod_i.h" +#include "linalg/diff.h" +#include "linalg/assign.h" +#include "../read_input.h" +#include "reweightingmeas.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 "../DDalphaAMG_interface.h" +#include "../boundary.h" + +/*#define CHECK_OPERATOR*/ + +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_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; +} + +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; +} + +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*/ +} + +static int invert_operator_Q(spinor * const P, spinor * const Q, + const int op_id, const int pm) { + + 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) + 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); +} + +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); +} + +static double log_determinant_estimate(const int operatorid, const int chebmax, const int estimators, const double spectmin, const double spectmax){ + +} + +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; + 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 kapparew; + int murew; +#ifdef CHECK_OPERATOR + double checkg5,check1,check2,check3,check4,check5; + double kappa_old; +#endif + /* now we bring it to normal format */ + /* here we use implicitly DUM_MATRIX and DUM_MATRIX+1 */ + spinor * lexicfield1; + spinor * lexicfield2; +#ifdef CHECK_OPERATOR + spinor * lexicfield3; + spinor * lexicfield4; +#endif + int operatorid; + int numsamples, snum, internum; + unsigned long int site; + + param = (reweighting_parameter*) measurement_list[id].parameter; + lexicfield1 = g_spinor_field[4]; + lexicfield2 = g_spinor_field[6]; +#ifdef CHECK_OPERATOR + lexicfield3=g_spinor_field[8]; + lexicfield4=g_spinor_field[10]; +#endif + 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; + 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"); + } + return; + } + + 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"); + } + } + + + kappa0 = kappa = kappainitial; + k2mu0 = k2mu = k2muinitial; + csw0 = csw = cswinitial; + rmu0 = rmu = rmuinitial; + + if (param->interpolationsteps < 1) + param->interpolationsteps = 1; + + for (internum = 0; internum < param->interpolationsteps; internum++) { + if (kapparew) { + kappa0 = kappa; + interpolate(&kappa, kappainitial, kappafinal, + param->interpolationsteps, internum); + } + 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); + } + k2mu = 2.0 * kappa * rmu; + k2mu0 = 2.0 * kappa0 * rmu0; + optr->kappa = kappa; + optr->mu = k2mu; + optr->c_sw = 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); +#ifdef CHECK_OPERATOR + for(site = 0; site < VOLUME; site++) { + _gamma5(lexicfield2[site], lexicfield1[site]); + } + checkg5=scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); /* should be zero*/ + + kappa_old=optr->kappa; + optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); /* prop=D rand*/ + mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2);/*correct normalisation*/ + mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); + convert_eo_to_lexic(lexicfield2, optr->prop0, optr->prop1); + check1 = -scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); + check2 = -scalar_prod_i(lexicfield1,lexicfield2,VOLUME, 1); + check3 = scalar_prod_r(lexicfield2,lexicfield2,VOLUME ,1); + + optr->kappa=1.0/(1.0/kappa_old+2.0); + optr->inverter(operatorid,0,0); /* to ensure that everything is updated*/ + optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); + mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2); + mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); + convert_eo_to_lexic(lexicfield3, optr->prop0, optr->prop1); + check1 += scalar_prod_r(lexicfield1,lexicfield3,VOLUME, 1); + check2 += scalar_prod_i(lexicfield1,lexicfield3,VOLUME, 1); + diff(lexicfield4,lexicfield3,lexicfield2,VOLUME); + check4=scalar_prod_r(lexicfield1,lexicfield1,VOLUME, 1); + check5=square_norm(lexicfield1,VOLUME ,1); + + optr->kappa=kappa_old; +#endif + 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); +#ifdef CHECK_OPERATOR + fprintf( ofs_full, "%e %e %e %e %e %e %e %e %e %e %e %e\n", square1, square2,prodre,prodim,prodreg5,prodimg5,checkg5,check1,check2,check3,check4,check5); +#else + /*print all raw data for cross check*/ + fprintf(ofs_full, + "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", 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); + } +#endif + 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); + + square2 = square_norm(optr->prop0, VOLUME / 2, 1); + + prodre = get_sw_reweighting(k2mu0, k2mu, kappa0, kappa, csw0, + csw); + + 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, + "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", k2mu0, + k2mu, kappa0, kappa, csw0, csw, rmu, rmu0); + fprintf(ofs_full, "%.17g %.17g %.17g\n", square1, square2, + prodre); + fprintf(ofs, "%.17g\n", square1 - square2 + prodre); + 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; +} diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h new file mode 100644 index 000000000..d973292c0 --- /dev/null +++ b/meas/reweightingmeas.h @@ -0,0 +1,55 @@ +/*********************************************************************** + * + * Measurements of the reweighting factors by Georg Bergner 2016 + * + * Copyright (C) 2008 Carsten Urbach + * + * 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 +typedef struct{ + int reweighting_operator; + int reweighting_number_sources; + int use_evenodd; + double k2mu0; + double kappa0; + int interpolationsteps; + double rmu0; + double rmu; + +} reweighting_parameter; + +inline void initialize_reweighting_parameter(void** parameter){ + reweighting_parameter* param; + if(!(*parameter)){ + (*parameter)=malloc(sizeof(reweighting_parameter)); + param=(reweighting_parameter*)(*parameter); + param->reweighting_number_sources=0; + param->reweighting_operator=0; + param->use_evenodd=0; + param->k2mu0=0.0; + param->rmu0=0.0; + param->rmu=0.0; + param->kappa0=0.0; + param->interpolationsteps=1; + } +} + +void reweighting_measurement(const int traj, const int t0, const int ieo); + +#endif diff --git a/measure.c b/measure.c new file mode 100644 index 000000000..aab5fce79 --- /dev/null +++ b/measure.c @@ -0,0 +1,492 @@ +/*********************************************************************** + * + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Carsten Urbach + * + * 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 . + * + * adaption of the invert for twisted mass QCD to contain only a few number + * of relevant measurements by Georg Bergner 2016 (still ugly) + * + * Author: Carsten Urbach, Georg Bergner + * urbach@physik.fu-berlin.de + * + *******************************************************************************/ + +#include"lime.h" +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include +#include +#include +#include +#ifdef TM_USE_MPI +#include +#endif +#ifdef TM_USE_OMP +# include +#endif +#include "global.h" +#include "git_hash.h" +#include "getopt.h" +#include "linalg_eo.h" +#include "geometry_eo.h" +#include "start.h" +/*#include "eigenvalues.h"*/ +#include "measure_gauge_action.h" +#ifdef TM_USE_MPI +#include "xchange/xchange.h" +#endif +#include +#include "source_generation.h" +#include "read_input.h" +#include "mpi_init.h" +#include "sighandler.h" +#include "boundary.h" +#include "solver/solver.h" +#include "init/init.h" +#include "smearing/stout.h" +#include "invert_eo.h" +#include "monomial/monomial.h" +#include "ranlxd.h" +#include "phmc.h" +#include "operator/D_psi.h" +#include "little_D.h" +#include "reweighting_factor.h" +#include "linalg/convert_eo_to_lexic.h" +#include "block.h" +#include "operator.h" +#include "sighandler.h" +#include "solver/generate_dfl_subspace.h" +#include "prepare_source.h" +#include +#include +#include +#include +#include "solver/dirac_operator_eigenvectors.h" +#include "source_generation.h" +#include "P_M_eta.h" +#include "operator/tm_operators.h" +#include "operator/Dov_psi.h" +#include "solver/spectral_proj.h" +#ifdef QUDA +# include "quda_interface.h" +#endif +#ifdef DDalphaAMG +# include "DDalphaAMG_interface.h" +#endif +#include "meas/measurements.h" +#include "source_generation.h" + + + +extern int nstore; +int check_geometry(); + +static void usage(); +static void process_args(int argc, char *argv[], char ** input_filename, char ** filename); +static void set_default_filenames(char ** input_filename, char ** filename); +static void invert_compute_modenumber(); + +int main(int argc, char *argv[]) +{ + FILE *parameterfile = NULL; + int j, i, ix = 0, isample = 0, op_id = 0; + char datafilename[206]; + char parameterfilename[206]; + char conf_filename[300]; + char * input_filename = NULL; + char * filename = NULL; + double plaquette_energy; + struct stout_parameters params_smear; + +#ifdef _KOJAK_INST +#pragma pomp inst init +#pragma pomp inst begin(main) +#endif + +#if (defined SSE || defined SSE2 || SSE3) + signal(SIGILL, &catch_ill_inst); +#endif + + DUM_DERI = 8; + DUM_MATRIX = DUM_DERI + 5; + NO_OF_SPINORFIELDS = DUM_MATRIX + 4; + + //4 extra fields (corresponding to DUM_MATRIX+0..5) for deg. and ND matrix mult. + NO_OF_SPINORFIELDS_32 = 6; + + verbose = 0; + g_use_clover_flag = 0; + +#ifdef TM_USE_MPI + +# ifdef TM_USE_OMP + int mpi_thread_provided; + MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &mpi_thread_provided); +# else + MPI_Init(&argc, &argv); +# endif + + MPI_Comm_rank(MPI_COMM_WORLD, &g_proc_id); +#else + g_proc_id = 0; +#endif + + process_args(argc,argv,&input_filename,&filename); + set_default_filenames(&input_filename, &filename); + + /* Read the input file */ + if( (j = read_input(input_filename)) != 0) { + fprintf(stderr, "Could not find input file: %s\nAborting...\n", input_filename); + exit(-1); + } + +#ifdef TM_USE_OMP + init_openmp(); +#endif + + /* this DBW2 stuff is not needed for the inversion ! */ + if (g_dflgcr_flag == 1) { + even_odd_flag = 0; + } + g_rgi_C1 = 0; + if (Nsave == 0) { + Nsave = 1; + } + + if (g_running_phmc) { + NO_OF_SPINORFIELDS = DUM_MATRIX + 8; + } + + tmlqcd_mpi_init(argc, argv); + + g_dbw2rand = 0; + + /* starts the single and double precision random number */ + /* generator */ + start_ranlux(rlxd_level, random_seed^nstore); + + /* we need to make sure that we don't have even_odd_flag = 1 */ + /* if any of the operators doesn't use it */ + /* in this way even/odd can still be used by other operators */ + for(j = 0; j < no_operators; j++) if(!operator_list[j].even_odd_flag) even_odd_flag = 0; + +#ifndef TM_USE_MPI + g_dbw2rand = 0; +#endif + +#ifdef _GAUGE_COPY + j = init_gauge_field(VOLUMEPLUSRAND, 1); + j += init_gauge_field_32(VOLUMEPLUSRAND, 1); +#else + j = init_gauge_field(VOLUMEPLUSRAND, 0); + j += init_gauge_field_32(VOLUMEPLUSRAND, 0); +#endif + + if (j != 0) { + fprintf(stderr, "Not enough memory for gauge_fields! Aborting...\n"); + exit(-1); + } + j = init_geometry_indices(VOLUMEPLUSRAND); + if (j != 0) { + fprintf(stderr, "Not enough memory for geometry indices! Aborting...\n"); + exit(-1); + } + if (no_monomials > 0) { + if (even_odd_flag) { + j = init_monomials(VOLUMEPLUSRAND / 2, even_odd_flag); + } + else { + j = init_monomials(VOLUMEPLUSRAND, even_odd_flag); + } + if (j != 0) { + fprintf(stderr, "Not enough memory for monomial pseudo fermion fields! Aborting...\n"); + exit(-1); + } + } + if (even_odd_flag) { + j = init_spinor_field(VOLUMEPLUSRAND / 2, NO_OF_SPINORFIELDS); + j += init_spinor_field_32(VOLUMEPLUSRAND / 2, NO_OF_SPINORFIELDS_32); + } + else { + j = init_spinor_field(VOLUMEPLUSRAND, NO_OF_SPINORFIELDS); + j += init_spinor_field_32(VOLUMEPLUSRAND, NO_OF_SPINORFIELDS_32); + } + if (j != 0) { + fprintf(stderr, "Not enough memory for spinor fields! Aborting...\n"); + exit(-1); + } + + if (g_running_phmc) { + j = init_chi_spinor_field(VOLUMEPLUSRAND / 2, 20); + if (j != 0) { + fprintf(stderr, "Not enough memory for PHMC Chi fields! Aborting...\n"); + exit(-1); + } + } + + g_mu = g_mu1; + + if (g_cart_id == 0) { + /*construct the filenames for the observables and the parameters*/ + strncpy(datafilename, filename, 200); + strcat(datafilename, ".data"); + strncpy(parameterfilename, filename, 200); + strcat(parameterfilename, ".para"); + + parameterfile = fopen(parameterfilename, "w"); + write_first_messages(parameterfile, "invert", git_hash); + fclose(parameterfile); + } + + /* define the geometry */ + geometry(); + + /* define the boundary conditions for the fermion fields */ + boundary(g_kappa); + + phmc_invmaxev = 1.; + + init_operators(); + + /* list and initialize measurements*/ + if(g_proc_id == 0) { + printf("\n"); + for(int j = 0; j < no_measurements; j++) { + printf("# measurement id %d, type = %d\n", j, measurement_list[j].type); + } + } + init_measurements(); + + /* this could be maybe moved to init_operators */ +#ifdef _USE_HALFSPINOR + j = init_dirac_halfspinor(); + if (j != 0) { + fprintf(stderr, "Not enough memory for halffield! Aborting...\n"); + exit(-1); + } + /* for mixed precision solvers, the 32 bit halfspinor field must always be there */ + j = init_dirac_halfspinor32(); + if (j != 0) + { + fprintf(stderr, "Not enough memory for 32-bit halffield! Aborting...\n"); + exit(-1); + } +# if (defined _PERSISTENT) + if (even_odd_flag) + init_xchange_halffield(); +# endif +#endif + + for (j = 0; j < Nmeas; j++) { + sprintf(conf_filename, "%s.%.4d", gauge_input_filename, nstore); + if (g_cart_id == 0) { + printf("#\n# Trying to read gauge field from file %s in %s precision.\n", + conf_filename, (gauge_precision_read_flag == 32 ? "single" : "double")); + fflush(stdout); + } + if( (i = read_gauge_field(conf_filename,g_gauge_field)) !=0) { + fprintf(stderr, "Error %d while reading gauge field from %s\n Aborting...\n", i, conf_filename); + exit(-2); + } + + + if (g_cart_id == 0) { + printf("# Finished reading gauge field.\n"); + fflush(stdout); + } +#ifdef TM_USE_MPI + xchange_gauge(g_gauge_field); +#endif + /*Convert to a 32 bit gauge field, after xchange*/ + convert_32_gauge_field(g_gauge_field_32, g_gauge_field, VOLUMEPLUSRAND); + /*compute the energy of the gauge field*/ + plaquette_energy = measure_plaquette( (const su3**) g_gauge_field); + + if (g_cart_id == 0) { + printf("# The computed plaquette value is %e.\n", plaquette_energy / (6.*VOLUME*g_nproc)); + fflush(stdout); + } + + if (use_stout_flag == 1){ + params_smear.rho = stout_rho; + params_smear.iterations = stout_no_iter; +/* if (stout_smear((su3_tuple*)(g_gauge_field[0]), ¶ms_smear, (su3_tuple*)(g_gauge_field[0])) != 0) */ +/* exit(1) ; */ + g_update_gauge_copy = 1; + plaquette_energy = measure_plaquette( (const su3**) g_gauge_field); + + if (g_cart_id == 0) { + printf("# The plaquette value after stouting is %e\n", plaquette_energy / (6.*VOLUME*g_nproc)); + fflush(stdout); + } + } + + /* if any measurements are defined in the input file, do them here */ + measurement * meas; + for(int imeas = 0; imeas < no_measurements; imeas++){ + meas = &measurement_list[imeas]; + if (g_proc_id == 0) { + fprintf(stdout, "#\n# Beginning online measurement.\n"); + } + meas->measurefunc(nstore, imeas, even_odd_flag); + } + + if (reweighting_flag == 1) { + reweighting_factor(reweighting_samples, nstore); + } + + /* Compute minimal eigenvalues, if wanted */ + if (compute_evs != 0) { + eigenvalues(&no_eigenvalues, 5000, eigenvalue_precision, + 0, compute_evs, nstore, even_odd_flag); + } + if (phmc_compute_evs != 0) { +#ifdef TM_USE_MPI + MPI_Finalize(); +#endif + return(0); + } + + /* Compute the mode number or topological susceptibility using spectral projectors, if wanted*/ + if(compute_modenumber != 0 || compute_topsus !=0){ + invert_compute_modenumber(); + } + + + + nstore += Nsave; + } + +#ifdef TM_USE_OMP + free_omp_accumulators(); +#endif + free_blocks(); + free_dfl_subspace(); + free_gauge_field(); + free_gauge_field_32(); + free_geometry_indices(); + free_spinor_field(); + free_spinor_field_32(); + free_moment_field(); + free_chi_spinor_field(); + free(filename); + free(input_filename); + free(SourceInfo.basename); + free(PropInfo.basename); +#ifdef QUDA + _endQuda(); +#endif +#ifdef TM_USE_MPI + MPI_Barrier(MPI_COMM_WORLD); + MPI_Finalize(); +#endif + return(0); +#ifdef _KOJAK_INST +#pragma pomp inst end(main) +#endif +} + +static void usage() +{ + fprintf(stdout, "Inversion for EO preconditioned Wilson twisted mass QCD\n"); + fprintf(stdout, "Version %s \n\n", PACKAGE_VERSION); + fprintf(stdout, "Please send bug reports to %s\n", PACKAGE_BUGREPORT); + fprintf(stdout, "Usage: invert [options]\n"); + fprintf(stdout, "Options: [-f input-filename]\n"); + fprintf(stdout, " [-o output-filename]\n"); + fprintf(stdout, " [-v] more verbosity\n"); + fprintf(stdout, " [-h|-? this help]\n"); + fprintf(stdout, " [-V] print version information and exit\n"); + exit(0); +} + +static void process_args(int argc, char *argv[], char ** input_filename, char ** filename) { + int c; + while ((c = getopt(argc, argv, "h?vVf:o:")) != -1) { + switch (c) { + case 'f': + *input_filename = calloc(200, sizeof(char)); + strncpy(*input_filename, optarg, 200); + break; + case 'o': + *filename = calloc(200, sizeof(char)); + strncpy(*filename, optarg, 200); + break; + case 'v': + verbose = 1; + break; + case 'V': + if(g_proc_id == 0) { + fprintf(stdout,"%s %s\n",PACKAGE_STRING,git_hash); + } + exit(0); + break; + case 'h': + case '?': + default: + if( g_proc_id == 0 ) { + usage(); + } + break; + } + } +} + +static void set_default_filenames(char ** input_filename, char ** filename) { + if( *input_filename == NULL ) { + *input_filename = calloc(13, sizeof(char)); + strcpy(*input_filename,"invert.input"); + } + + if( *filename == NULL ) { + *filename = calloc(7, sizeof(char)); + strcpy(*filename,"output"); + } +} + +static void invert_compute_modenumber() { + spinor * s_ = calloc(no_sources_z2*VOLUMEPLUSRAND+1, sizeof(spinor)); + spinor ** s = calloc(no_sources_z2, sizeof(spinor*)); + if(s_ == NULL) { + printf("Not enough memory in %s: %d",__FILE__,__LINE__); exit(42); + } + if(s == NULL) { + printf("Not enough memory in %s: %d",__FILE__,__LINE__); exit(42); + } + for(int i = 0; i < no_sources_z2; i++) { + s[i] = (spinor*)(((unsigned long int)(s_)+ALIGN_BASE)&~ALIGN_BASE)+i*VOLUMEPLUSRAND; + random_spinor_field_lexic(s[i], reproduce_randomnumber_flag,RN_Z2); + + if(g_proc_id == 0) { + printf("source %d \n", i); + } + + if(compute_modenumber != 0){ + mode_number(s[i], mstarsq); + } + + if(compute_topsus !=0) { + top_sus(s[i], mstarsq); + } + } + free(s); + free(s_); +} + diff --git a/monomial/cloverdetratio_rwdmonomial.c b/monomial/cloverdetratio_rwdmonomial.c new file mode 100644 index 000000000..a06143124 --- /dev/null +++ b/monomial/cloverdetratio_rwdmonomial.c @@ -0,0 +1,103 @@ +/*********************************************************************** + * + * Copyright (C) 2012 Carsten Urbach + * + * Adaption with a more efficient inversion by Georg Bergner 2016 + * + * 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 "su3.h" +#include "start.h" +#include "gettime.h" +#include "linalg_eo.h" +#include "deriv_Sb.h" +#include "gamma.h" +#include "operator/tm_operators.h" +#include "operator/Hopping_Matrix.h" +#include "solver/chrono_guess.h" +#include "solver/solver.h" +#include "solver/monomial_solve.h" +#include "read_input.h" +#include "operator/clovertm_operators.h" +#include "operator/clovertm_operators_32.h" +#include "operator/clover_leaf.h" +#include "monomial/monomial.h" +#include "boundary.h" +#include "cloverdetratio_rwdmonomial.h" + + +double cloverdetratio_rwaccd(const int id, hamiltonian_field_t * const hf) { + monomial * mnl = &monomial_list[id]; + int save_sloppy = g_sloppy_precision_flag; + double atime, etime; + atime = gettime(); + + + g_mu = mnl->mu2; + boundary(mnl->kappa2); + + init_sw_fields(); + sw_term( (const su3**) hf->gaugefield, mnl->kappa2, mnl->c_sw); + sw_invert(EE, mnl->mu2); + g_mu3 = 0.; + + mnl->Qsq(mnl->w_fields[1], mnl->pf); + assign(mnl->w_fields[0],mnl->pf,VOLUME/2); + + g_mu3 = 0.; + g_mu = mnl->mu; + boundary(mnl->kappa); + sw_term( (const su3**) hf->gaugefield, mnl->kappa, mnl->c_sw); + sw_invert(EE, mnl->mu); + + /*chrono_guess(mnl->pf, mnl->w_fields[1], mnl->csg_field, mnl->csg_index_array, + mnl->csg_N, mnl->csg_n, VOLUME/2, &Qtm_plus_psi);*/ + g_sloppy_precision_flag = 0; + mnl->iter0 += solve_degenerate(mnl->w_fields[0], mnl->w_fields[1], mnl->solver_params, mnl->maxiter, mnl->accprec, + g_relative_precision_flag, VOLUME/2, mnl->Qsq, mnl->solver); + + + g_sloppy_precision_flag = save_sloppy; + + /* Compute the energy contr. from second field */ + mnl->energy1 = scalar_prod_r(mnl->pf,mnl->w_fields[0], VOLUME/2, 1); + + g_mu = g_mu1; + g_mu3 = 0.; + boundary(g_kappa); + etime = gettime(); + if(g_proc_id == 0) { + if(g_debug_level > 1) { + printf("# Time for %s monomial rwacc step: %e s\n", mnl->name, etime-atime); + } + if(g_debug_level > 3) { + printf("called cloverdetratio_rwacc for id %d dH = %1.10e\n", + id, mnl->energy1 - mnl->energy0); + printf("Parameters: kappa=%e, kappa2=%e; mu=%e, mu2=%e, vprod=%e\n",mnl->kappa,mnl->kappa2,mnl->mu,mnl->mu2,mnl->energy1); + } + } + return(mnl->energy1 - mnl->energy0); +} diff --git a/monomial/cloverdetratio_rwdmonomial.h b/monomial/cloverdetratio_rwdmonomial.h new file mode 100644 index 000000000..ad13814f2 --- /dev/null +++ b/monomial/cloverdetratio_rwdmonomial.h @@ -0,0 +1,31 @@ +/*********************************************************************** + * + * Copyright (C) 2012 Carsten Urbach + * + * Adaption with a more efficient inversion by Georg Bergner 2016 + * Note that the reweighting measurement is much more efficient. + * + * 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 _CLOVERDETRATIO_RWDMONOMIAL_H +#define _CLOVERDETRATIO_RWDMONOMIAL_H + +#include "hamiltonian_field.h" + +double cloverdetratio_rwaccd(const int no, hamiltonian_field_t * const hf); + +#endif From bf00a97e750fa59e01b15fd4e15bb6b6d4fd28f0 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Fri, 19 Aug 2016 14:24:28 +0200 Subject: [PATCH 02/22] added new measurements of reweighting factors and changed concept for measurements --- .gitignore | 1 + DDalphaAMG_interface.c | 2 +- Makefile.in | 4 +-- doc/main.tex | 18 +++++----- invert.c | 2 +- meas/Makefile.in | 1 + meas/measurements.c | 17 +++++++++- meas/measurements.h | 28 ++++++++++++---- monomial/Makefile.in | 1 + monomial/monomial.c | 11 ++++++ monomial/monomial.h | 2 ++ read_input.l | 76 +++++++++++++++++++++++++++++++++++++++--- 12 files changed, 137 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index df5fa2ff6..a815af032 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ config.status hmc_tm invert offline_measurement +measure lib/ benchmark config.status diff --git a/DDalphaAMG_interface.c b/DDalphaAMG_interface.c index 84cc98c8f..c3cb3ea72 100644 --- a/DDalphaAMG_interface.c +++ b/DDalphaAMG_interface.c @@ -294,7 +294,7 @@ static int MG_solve(spinor * const phi_new, spinor * const phi_old, const double f == Qsw_psi || // Gamma5 - Schur complement with mu=0 on odd sites f == Q_plus_psi || // Gamma5 - Full operator with plus mu f == Q_minus_psi ) { // Gamma5 - Full operator with minus mu - mul_gamma5(phi_old, N); + // mul_gamma5(phi_old, N); // error in the original version DDalphaAMG_solve( new, old, precision, &mg_status ); mul_gamma5(phi_old, N); } diff --git a/Makefile.in b/Makefile.in index 6c91cbf50..fc8181c89 100644 --- a/Makefile.in +++ b/Makefile.in @@ -67,7 +67,7 @@ NOOPTMOD = test/check_xchange test/check_geometry PROGRAMS = hmc_tm benchmark invert gen_sources \ check_locallity test_lemon hopping_test LapH_ev \ - offline_measurement + offline_measurement measure ALLOBJ = ${MODULES} ${PROGRAMS} ${SMODULES} SUBDIRS = ${USESUBDIRS} @@ -76,7 +76,7 @@ SUBDIRS = ${USESUBDIRS} .SUFFIXES: # need to build modules before subdirs! -all: Makefile dep $(SUBDIRS) hmc_tm invert benchmark offline_measurement +all: Makefile dep $(SUBDIRS) hmc_tm invert benchmark offline_measurement measure $(SUBDIRS): $(MAKE) --directory=$@ diff --git a/doc/main.tex b/doc/main.tex index 6c10a8f58..40199f486 100644 --- a/doc/main.tex +++ b/doc/main.tex @@ -61,15 +61,15 @@ \section{Implementation} \myinput{components} \myinput{test} -%\myinput{eo_pre} -%\myinput{martins-trick} -%\myinput{deflation} -%\myinput{c-code} -%\myinput{integrationschemes} - -%\myinput{parallel} -%\myinput{operator} -%\myinput{online} +\myinput{eo_pre} +\myinput{martins-trick} +\myinput{deflation} +\myinput{c-code} +\myinput{integrationschemes} + +\myinput{parallel} +\myinput{operator} +\myinput{online} \section{File Formats and IO} \myinput{prop_format.tex} diff --git a/invert.c b/invert.c index 1cb6a5fac..f469ebb55 100644 --- a/invert.c +++ b/invert.c @@ -108,7 +108,7 @@ int main(int argc, char *argv[]) int j, i, ix = 0, isample = 0, op_id = 0; char datafilename[206]; char parameterfilename[206]; - char conf_filename[50]; + char conf_filename[300]; char * input_filename = NULL; char * filename = NULL; double plaquette_energy; diff --git a/meas/Makefile.in b/meas/Makefile.in index f67214295..6ed9ca8d5 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 \ energy_density gradient_flow diff --git a/meas/measurements.c b/meas/measurements.c index 06456729d..884110db9 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,7 @@ 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; no_measurements++; return(no_measurements); } @@ -79,6 +83,11 @@ 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].id = i; } return(0); @@ -87,7 +96,13 @@ return(0); void free_measurements(){ - + int i; + for(i = 0; i < no_measurements; i++) { + if(measurement_list[i].parameter){ + free(measurement_list[i].parameter); + measurement_list[i].parameter=NULL; + } + } return; } diff --git a/meas/measurements.h b/meas/measurements.h index 39921903f..a35f1b375 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 @@ -30,29 +35,38 @@ enum MEAS_TYPE { PIONNORM, POLYAKOV, ORIENTED_PLAQUETTES, - GRADIENT_FLOW + 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; - /* how it's usually called */ - char name[100]; + /* for maximal iterations in inversions for correlators */ + int max_iter; /* maximum number of slice, the source can be put if the correlator is measured in T(Z)-direction this will be set to T(LZ) by init_measurements */ int max_source_slice; + + + void* parameter; + + /* frequency of the measurement */ + int freq; + + /* how it's usually called */ + char name[100]; /* functions for the measurement */ void (*measurefunc) (const int traj, const int id, const int ieo); diff --git a/monomial/Makefile.in b/monomial/Makefile.in index e73a9ede2..6e42ec316 100644 --- a/monomial/Makefile.in +++ b/monomial/Makefile.in @@ -33,6 +33,7 @@ LIBRARIES = libmonomial libmonomial_TARGETS = nddetratio_monomial monomial det_monomial detratio_monomial \ gauge_monomial ndpoly_monomial clover_trlog_monomial cloverdet_monomial cloverdetratio_monomial \ cloverdetratio_rwmonomial \ + cloverdetratio_rwdmonomial \ clovernd_trlog_monomial poly_monomial cloverndpoly_monomial moment_energy \ ndrat_monomial ndratcor_monomial rat_monomial ratcor_monomial monitor_forces diff --git a/monomial/monomial.c b/monomial/monomial.c index 3b9d510c4..11200cea5 100644 --- a/monomial/monomial.c +++ b/monomial/monomial.c @@ -251,6 +251,17 @@ int init_monomials(const int V, const int even_odd_flag) { printf("# Initialised monomial of type CLOVERDETRATIORW, no_monomials= %d, currently only available for reweighting!\n", no_monomials); } } + else if(monomial_list[i].type == CLOVERDETRATIORWD) { + monomial_list[i].accfunction = &cloverdetratio_rwaccd; + monomial_list[i].even_odd_flag = 1; + monomial_list[i].Qsq = &Qsw_pm_psi; + monomial_list[i].Qp = &Qsw_plus_psi; + monomial_list[i].Qm = &Qsw_minus_psi; + init_swpm(VOLUME); + if(g_proc_id == 0 && g_debug_level > 1) { + printf("# Initialised monomial of type CLOVERDETRATIORWD, no_monomials= %d, currently only available for reweighting!\n", no_monomials); + } + } else if(monomial_list[i].type == DETRATIO) { monomial_list[i].hbfunction = &detratio_heatbath; monomial_list[i].accfunction = &detratio_acc; diff --git a/monomial/monomial.h b/monomial/monomial.h index c0e494b50..9da893f11 100644 --- a/monomial/monomial.h +++ b/monomial/monomial.h @@ -49,6 +49,7 @@ #define CLOVERRAT 19 #define CLOVERRATCOR 20 #define CLOVERDETRATIORW 21 +#define CLOVERDETRATIORWD 22 #define max_no_monomials 30 @@ -136,6 +137,7 @@ typedef struct { #include "monomial/cloverdet_monomial.h" #include "monomial/cloverdetratio_monomial.h" #include "monomial/cloverdetratio_rwmonomial.h" +#include "monomial/cloverdetratio_rwdmonomial.h" #include "monomial/cloverndpoly_monomial.h" #include "monomial/ndrat_monomial.h" #include "monomial/rat_monomial.h" diff --git a/read_input.l b/read_input.l index f14e9ee49..3c6531688 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" @@ -106,7 +107,7 @@ static inline void rmQuotes(char *str){ char * type; int verbose = 0; - int myverbose = 0; + int myverbose = 1; int startoption; int Ntherm; int Nmeas; @@ -265,6 +266,7 @@ static inline void rmQuotes(char *str){ %x NOSOURCESZ2 %x INITMEASUREMENT %x ONLINEMEAS +%x REWEIGHTINGMEAS %x PIONNORMMEAS %x PLOOP %x ORIENTEDPLAQUETTESMEAS @@ -673,7 +675,7 @@ static inline void rmQuotes(char *str){ {SPC}*MGSetupMu{EQL}{FLT}+ { sscanf(yytext, " %[a-zA-Z] = %lf", name, &c); mg_setup_mu=c; - if(myverbose) printf(" MGSetupMu set to %f line %d operator %d\n", mg_setup_mu, line_of_file, current_operator); + if(myverbose) printf(" MGSetupMu set to %f line %d operator %d\n", mg_cmu_factor, line_of_file, current_operator); } {SPC}*MGCoarseMuFactor{EQL}{FLT}+ { sscanf(yytext, " %[a-zA-Z] = %lf", name, &c); @@ -1232,6 +1234,11 @@ static inline void rmQuotes(char *str){ mnl->type = CLOVERDETRATIORW; strcpy((*mnl).name, "CLOVERDETRATIORW"); } + else if(strcmp(yytext, "CLOVERDETRATIORWD")==0) { + mnl->type = CLOVERDETRATIORWD; + strcpy((*mnl).name, "CLOVERDETRATIORWD"); + } + else if(strcmp(yytext, "DETRATIO")==0) { mnl->type = DETRATIO; strcpy((*mnl).name, "DETRATIO"); @@ -1335,6 +1342,7 @@ static inline void rmQuotes(char *str){ else if(mnl->type == CLOVERDET) BEGIN(CLDETMONOMIAL); else if(mnl->type == CLOVERDETRATIO) BEGIN(CLDETRATMONOMIAL); else if(mnl->type == CLOVERDETRATIORW) BEGIN(CLDETRATRWMONOMIAL); + else if(mnl->type == CLOVERDETRATIORWD) BEGIN(CLDETRATRWMONOMIAL); else BEGIN(DETMONOMIAL); } @@ -1867,6 +1875,7 @@ static inline void rmQuotes(char *str){ 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; @@ -1878,6 +1887,11 @@ static inline void rmQuotes(char *str){ 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"); @@ -1907,13 +1921,14 @@ static inline void rmQuotes(char *str){ 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); @@ -1925,7 +1940,7 @@ static inline void rmQuotes(char *str){ } } -{ +{ {SPC}*MaxSolverIterations{EQL}{DIGIT}+ { sscanf(yytext, " %[a-zA-Z] = %d", name, &a); meas->max_iter = a; @@ -1933,6 +1948,57 @@ static inline void rmQuotes(char *str){ } } +{ + {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}*Direction{EQL}[03] { sscanf(yytext, " %[a-zA-Z] = %d", name, &a); @@ -2440,7 +2506,7 @@ static inline void rmQuotes(char *str){ BEGIN(comment_caller); } -{SPC}*\n { +{SPC}*\n { line_of_file++; } <*>{SPC}*\n { From 12b43d2847b2caa5550057a6d74f660c0f6e60a2 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Tue, 13 Sep 2016 11:01:27 +0200 Subject: [PATCH 03/22] updated --- meas/reweightingmeas.c | 370 +++++++++++++++++++++++++++++++++++++---- meas/reweightingmeas.h | 18 +- measure.c | 6 +- read_input.l | 36 ++++ 4 files changed, 392 insertions(+), 38 deletions(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index 13c1605e1..7c146f832 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -45,6 +45,13 @@ #include "linalg/scalar_prod_i.h" #include "linalg/diff.h" #include "linalg/assign.h" +#include "linalg/mul_r.h" +#include "linalg/assign_mul_add_mul_r.h" +#include "linalg/mul_diff_mul_r.h" +#include "linalg/assign_mul_add_mul_add_mul_r.h" +#include "linalg/assign_add_mul_add_mul_r.h" +#include "linalg/assign_add_mul_r.h" +#include "linalg/set_even_to_zero.h" #include "../read_input.h" #include "reweightingmeas.h" #include "../operator/Hopping_Matrix.h" @@ -55,6 +62,7 @@ #include "../operator/clover_leaf.h" #include "../DDalphaAMG_interface.h" #include "../boundary.h" +#include "../global.h" /*#define CHECK_OPERATOR*/ @@ -248,11 +256,293 @@ static int invert_operator_Q(spinor * const P, spinor * const Q, 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); + (*rcurrent) = rinitial + + (thisstep + 1) * (rfinal - rinitial) / ((double) numsteps); } -static double log_determinant_estimate(const int operatorid, const int chebmax, const int estimators, const double spectmin, const double spectmax){ +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); +} +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; +} + +//#define TRIVIAL_TEST +static double log_determinant_estimate(const int operatorid, const int chebmax, + const 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) { + 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; + int k, l, n; + double x, y, ldet, prodre; + FILE * ofs; + spinor * vs1; + spinor * vs2; + spinor * u; + spinor * v0; + spinor * v1; + spinor * v2; + spinor * vt0; + spinor * vt1; + spinor * vt2; + spinor * tmp; + operator * optr; + char* filename; + char buf[100]; + n = VOLUME; + + filename = buf; + sprintf(filename, "%s%.6d", "reweightingmeas_cheb.", traj); + + vs1 = g_spinor_field[0]; + vs2 = g_spinor_field[1]; + u = g_spinor_field[2]; + v0 = g_spinor_field[4]; + v1 = g_spinor_field[6]; + v2 = g_spinor_field[8]; + vt0 = g_spinor_field[10]; + vt1 = g_spinor_field[12]; + vt2 = g_spinor_field[14]; + + optr = &operator_list[operatorid]; + if (is_schur_complement(optr->applyQsq)) { + n = VOLUME / 2; + vs1 = g_spinor_field[0]; + vs2 = g_spinor_field[1]; + u = g_spinor_field[3]; + v0 = g_spinor_field[4]; + v1 = g_spinor_field[5]; + v2 = g_spinor_field[6]; + vt0 = g_spinor_field[7]; + vt1 = g_spinor_field[8]; + vt2 = g_spinor_field[9]; + if (DUM_MATRIX < 10) { + if (g_proc_id == 0) { + fprintf(stderr, "Not enough spinor fields %d < 10 \n\n", + DUM_MATRIX); + } + return 0.0; + } + + } else { + if (DUM_MATRIX < 16) { + if (g_proc_id == 0) { + fprintf(stderr, "Not enough spinor fields %d < 16 \n\n", + DUM_MATRIX); + } + return 0.0; + } + } + + coeff = malloc(chebmax * sizeof(double)); + chebyshev_coeff(chebmax, coeff, am, bm); + if (g_proc_id == 0 && g_debug_level > 3) { + ofs = fopen("polynomialapproxtest.txt", "a"); + 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); + fprintf(ofs, "%d %g %g %g %d %g %g\n", k, x, y, fabs(y - log(x)), + chebmax, minev, maxev); + } + fclose(ofs); + } + + ldet = 0; + if (chebmax > 0) { + for (k = 0; k < estimators; k++) { + /* + * Generate estimator (may be half of it is never used) + */ + random_spinor_field_eo(vs1, reproduce_randomnumber_flag, RN_Z2); + random_spinor_field_eo(vs2, reproduce_randomnumber_flag, RN_Z2); + + assign(v0, vs1, n); + assign(vt0, vs1, n); + +#ifdef TRIVIAL_TEST + mul_r(v1,kappa1,vs1,n); +#else + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); + optr->applyQsq(v1, vs1); +#endif + /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ + assign_mul_add_mul_r(v1, vs1, 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, vs1); +#endif + /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ + assign_mul_add_mul_r(vt1, vs1, a, b, n); + + /* Makes (*R)=c1*(*S)-c2*(*U) , c1 and c2 are complex constants */ + mul_diff_mul_r(u, vt1, v1, coeff[1], coeff[1], n); + +#if 0 + for (l = 1; l + 1 < chebmax; l++) { +#ifndef TRIVIAL_TEST + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); + + optr->applyQsq(v2, v1); +#else + mul_r(v2,kappa1,v1,n); +#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; + +#ifndef TRIVIAL_TEST + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); + + optr->applyQsq(vt2, vt1); +#else + mul_r(vt2,kappa2,vt1,n); +#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; + + /* (*R) = (*R) + c1*(*S) + c2*(*U) */ + assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], + -coeff[l + 1], n); + + } + +#endif + +#ifndef TRIVIAL_TEST + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); +#endif + + for (l = 1; l + 1 < chebmax; 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; + /* (*P) = (*P) + c(*Q) c is a real constant */ + assign_add_mul_r(u, v1, -coeff[l + 1], n); + } +#ifndef TRIVIAL_TEST + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); +#endif + + for (l = 1; l + 1 < chebmax; 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; + + /* (*P) = (*P) + c(*Q) c is a real constant */ + assign_add_mul_r(u, vt1, coeff[l + 1], n); + + } + + prodre = scalar_prod_r(vs1, u, n, 1); + ldet += prodre / ((double) estimators); + if (g_proc_id == 0 && g_debug_level > 3) { + ofs = fopen("estimators.txt", "a"); + fprintf(ofs, "# Test of stochastic estimation\n"); + fprintf(ofs, "%d %g %g %g %g %g %d %d %g %g %g\n", k, kappa1, + kappa2, kappa2Mu1, kappa2Mu2, prodre, estimators, + chebmax, minev, maxev, ldet); + fclose(ofs); + } + + if (g_proc_id == 0) { + ofs = fopen(filename, "a"); + fprintf(ofs, "%d %g %g %g %g %d %g %g ", traj, kappa1, kappa2, + kappa2Mu1, kappa2Mu2, chebmax, minev, maxev); + fprintf(ofs, " %g %g\n", prodre + shift, prodre); + fclose(ofs); + } + + } /* estimator iteration*/ + } /* chebmax>0*/ + free(coeff); + return (ldet); } void reweighting_measurement(const int traj, const int id, const int ieo) { @@ -265,7 +555,7 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { char *filename_full; char buf[100]; char buf_full[100]; - double square1, square2, prodre, prodim, prodreg5, prodimg5; + 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; @@ -336,6 +626,7 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { */ k2muinitial = param->k2mu0; kappainitial = param->kappa0; + cswinitial=0; kapparew = 1; if (kappainitial == kappafinal) { kapparew = 0; @@ -366,47 +657,58 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { /* 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 (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->rmu0 != 0) { + rmuinitial = param->rmu0; + k2muinitial = 2.0 * kappainitial * rmuinitial; } - if(param->rmu!=0){ - rmufinal=param->rmu; - k2mufinal = 2.0*kappafinal*rmufinal; + 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)){ + if (murew && (g_proc_id == 0)) { printf("Mu reweighting chosen: "); - printf("mu=%e to mu=%e.\n", rmuinitial, - rmufinal); + printf("mu=%e to mu=%e.\n", rmuinitial, rmufinal); } - if(kapparew && (g_proc_id == 0)){ + if (kapparew && (g_proc_id == 0)) { printf("Kappa reweighting chosen: "); - printf("kappa=%e to kappa=%e\n", kappainitial, - kappafinal); + 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"); - } - return; + 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 (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_cheb) { + 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); + if (param->only_cheb) { + return; + } + } kappa0 = kappa = kappainitial; k2mu0 = k2mu = k2muinitial; @@ -424,7 +726,7 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } if (murew) { /* use quadratic interpolation in the case of mu*/ - rmu0=rmu; + rmu0 = rmu; tmp1 = rmuinitial * rmuinitial; tmp2 = rmufinal * rmufinal; tmp3 = rmu * rmu; @@ -437,6 +739,10 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { 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, @@ -542,8 +848,6 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { square2 = square_norm(optr->prop0, VOLUME / 2, 1); - prodre = get_sw_reweighting(k2mu0, k2mu, kappa0, kappa, csw0, - csw); if (g_mpi_time_rank == 0 && g_proc_coords[0] == 0) { ofs = fopen(filename, "a"); @@ -556,8 +860,8 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", k2mu0, k2mu, kappa0, kappa, csw0, csw, rmu, rmu0); fprintf(ofs_full, "%.17g %.17g %.17g\n", square1, square2, - prodre); - fprintf(ofs, "%.17g\n", square1 - square2 + prodre); + cswpart); + fprintf(ofs, "%.17g\n", square1 - square2 + cswpart); fclose(ofs); fclose(ofs_full); } @@ -567,6 +871,8 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { }/* loop over estimators */ } /* loop over interpolation steps*/ + + etime = gettime(); if (g_proc_id == 0 && g_debug_level > 0) { diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h index d973292c0..e46e8e820 100644 --- a/meas/reweightingmeas.h +++ b/meas/reweightingmeas.h @@ -28,9 +28,15 @@ typedef struct{ int use_evenodd; double k2mu0; double kappa0; - int interpolationsteps; double rmu0; double rmu; + double minev; + double maxev; + int interpolationsteps; + int estimatorscheb; + int cheborder; + int use_cheb; + int only_cheb; } reweighting_parameter; @@ -39,14 +45,20 @@ inline void initialize_reweighting_parameter(void** parameter){ if(!(*parameter)){ (*parameter)=malloc(sizeof(reweighting_parameter)); param=(reweighting_parameter*)(*parameter); - param->reweighting_number_sources=0; param->reweighting_operator=0; + param->reweighting_number_sources=0; param->use_evenodd=0; param->k2mu0=0.0; + param->kappa0=0.0; param->rmu0=0.0; param->rmu=0.0; - param->kappa0=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; } } diff --git a/measure.c b/measure.c index aab5fce79..aa8e1dfa2 100644 --- a/measure.c +++ b/measure.c @@ -106,7 +106,7 @@ static void invert_compute_modenumber(); int main(int argc, char *argv[]) { FILE *parameterfile = NULL; - int j, i, ix = 0, isample = 0, op_id = 0; + int j, i; char datafilename[206]; char parameterfilename[206]; char conf_filename[300]; @@ -125,8 +125,8 @@ int main(int argc, char *argv[]) #endif DUM_DERI = 8; - DUM_MATRIX = DUM_DERI + 5; - NO_OF_SPINORFIELDS = DUM_MATRIX + 4; + DUM_MATRIX = DUM_DERI + 5; /* 5 fields for doing the inversions (might be used by other opetations if no inverter used*/ + NO_OF_SPINORFIELDS = DUM_MATRIX + 4; /* Don't access these fields if you apply multiplications!*/ //4 extra fields (corresponding to DUM_MATRIX+0..5) for deg. and ND matrix mult. NO_OF_SPINORFIELDS_32 = 6; diff --git a/read_input.l b/read_input.l index 3c6531688..652feb456 100644 --- a/read_input.l +++ b/read_input.l @@ -1997,6 +1997,42 @@ static inline void rmQuotes(char *str){ ((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}*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); + } } { From 6448a5b8c87c0b7717ad5435766c0e1284a694a2 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Tue, 13 Sep 2016 16:46:51 +0200 Subject: [PATCH 04/22] added eigevalue estimation and truncated polynomial factorization --- meas/measurements.c | 12 +- meas/measurements.h | 2 + meas/reweightingmeas.c | 651 ++++++++++++++++++++++++++++++++--------- meas/reweightingmeas.h | 45 +-- read_input.l | 6 + solver/jdher.c | 2 +- 6 files changed, 554 insertions(+), 164 deletions(-) diff --git a/meas/measurements.c b/meas/measurements.c index 884110db9..3ba0a2caf 100644 --- a/meas/measurements.c +++ b/meas/measurements.c @@ -53,6 +53,7 @@ int add_measurement(const enum MEAS_TYPE meas_type) { 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); } @@ -86,6 +87,7 @@ int init_measurements(){ 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; @@ -98,9 +100,10 @@ return(0); void free_measurements(){ int i; for(i = 0; i < no_measurements; i++) { - if(measurement_list[i].parameter){ + if (measurement_list[i].parameter) { + measurement_list[i].destructor(measurement_list[i].parameter); free(measurement_list[i].parameter); - measurement_list[i].parameter=NULL; + measurement_list[i].parameter = NULL; } } return; @@ -116,5 +119,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 a35f1b375..f55a60b97 100644 --- a/meas/measurements.h +++ b/meas/measurements.h @@ -70,6 +70,7 @@ typedef struct { /* functions for the measurement */ void (*measurefunc) (const int traj, const int id, const int ieo); + void (*destructor)(void* param); } measurement; @@ -85,5 +86,6 @@ int init_measurements(); void free_measurements(); 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 index 7c146f832..3b9e03dc7 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -63,22 +63,10 @@ #include "../DDalphaAMG_interface.h" #include "../boundary.h" #include "../global.h" +#include "solver/jdher.h" /*#define CHECK_OPERATOR*/ -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_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 @@ -97,6 +85,21 @@ static int is_schur_complement(const matrix_mult f) { return 0; } +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 @@ -126,6 +129,153 @@ static void update_global_parameters(const int op_id) { }/*clover leave update*/ } +static void estimate_eigenvalues(const int operatorid, const int identifier) { +#ifdef HAVE_LAPACK + vector_list min_ev; + vector_list max_ev; + spinor * eigenvectors_ = NULL; + char filename[200]; + FILE * ofs; + double atime, etime; + int max_iterations=5000; + double prec = 1.e-5; + int maxvectors; + /********************** + * For Jacobi-Davidson + **********************/ + int verbosity = g_debug_level, converged = 0, blocksize = 1, blockwise = 0; + int solver_it_max = 50, j_max, j_min, ii; + /*int it_max = 10000;*/ + /* _Complex double *eigv_ = NULL, *eigv; */ + double decay_min = 1.7, decay_max = 1.5, + threshold_min = 1.e-3, threshold_max = 5.e-2; + double ev_max, ev_min; + + /* static int v0dim = 0; */ + int v0dim = 0; + int N = (VOLUME)/2, N2 = (VOLUMEPLUSRAND)/2; + operator * optr; + + /********************** + * General variables + **********************/ + int returncode=0; + int returncode2=0; + + + min_ev.s=2; + min_ev.el=malloc(min_ev.s*sizeof(double)); + max_ev.s=2; + max_ev.el=malloc(max_ev.s*sizeof(double)); + + optr = &operator_list[operatorid]; + + + if(!is_schur_complement(optr->applyQsq)) { + N = VOLUME; + N2 = VOLUMEPLUSRAND; + } + + evlength = N2; + if(g_proc_id == g_stdio_proc && g_debug_level >0) { + printf("Number of eigenvalues to compute = %d %d\n",min_ev.s,max_ev.s); + printf("Using Jacobi-Davidson method! \n"); + } + + + if(max_ev.s < 8){ + j_max = 15; + j_min = 8; + } + else{ + j_max = 2*max_ev.s; + j_min = max_ev.s; + } + + maxvectors=min_ev.s>max_ev.s ? min_ev.s:max_ev.s; + +#if (defined SSE || defined SSE2 || defined SSE3) + eigenvectors_ = calloc(N2*maxvectors+1, sizeof(spinor)); + eigenvectors = (spinor *)(((unsigned long int)(eigenvectors_)+ALIGN_BASE)&~ALIGN_BASE); +#else + eigenvectors_= calloc(N2*maxvectors, sizeof(spinor)); + eigenvectors = eigenvectors_; +#endif + + atime = gettime(); + + update_global_parameters(operatorid); + /* (re-) compute minimal eigenvalues */ + converged = 0; + solver_it_max = 200; + + + jdher(N*sizeof(spinor)/sizeof(_Complex double), N2*sizeof(spinor)/sizeof(_Complex double), + 50., prec,max_ev.s, j_max, j_min, + max_iterations, blocksize, blockwise, v0dim, (_Complex double*) eigenvectors, + CG, solver_it_max, + threshold_max, decay_max, verbosity, + &converged, (_Complex double*) eigenvectors, max_ev.el, + &returncode, JD_MAXIMAL, 1, + optr->applyQsq); + + max_ev.s = converged; + + if(min_ev.s < 8){ + j_max = 15; + j_min = 8; + } + else{ + j_max = 2*min_ev.s; + j_min = min_ev.s; + } + + converged = 0; + solver_it_max = 200; + + jdher(N*sizeof(spinor)/sizeof(_Complex double), N2*sizeof(spinor)/sizeof(_Complex double), + 0., prec, + min_ev.s, j_max, j_min, + max_iterations, blocksize, blockwise, v0dim, (_Complex double*) eigenvectors, + CG, solver_it_max, + threshold_min, decay_min, verbosity, + &converged, (_Complex double*) eigenvectors, min_ev.el, + &returncode2, JD_MINIMAL, 1, + optr->applyQsq); + + min_ev.s = converged; + + free(eigenvectors_); + + etime = gettime(); + if(g_proc_id == 0) { + printf("Eigenvalues computed in %e sec. gettime)\n", etime-atime); + } + + ev_min= min_ev.el[min_ev.s-1]; + ev_max= max_ev.el[max_ev.s-1]; + eigenvalues_for_cg_computed = converged; + + if(g_proc_id == 0){ + sprintf(filename,"rew_ev_estimate.%d", nstore); + ofs = fopen(filename, "a"); + for(ii = 0; ii < max_ev.s; ii++) { + fprintf(ofs, "%d %e 1\n",ii,max_ev.el[ii]); + } + for(ii = 0; ii < min_ev.s; ii++) { + fprintf(ofs, "%d %e 1\n",ii,min_ev.el[ii]); + } + fclose(ofs); + } + free(min_ev.el); + free(max_ev.el); +#else + fprintf(stderr, "lapack not available, so JD method for EV computation not available \n"); +#endif +} + + + static int invert_operator_Q(spinor * const P, spinor * const Q, const int op_id, const int pm) { @@ -303,11 +453,15 @@ static double poly_cheb(const unsigned int np, const double * const coeff, return y; } +/*Trivial test tests the function with the scaled idenetity matrix.*/ //#define TRIVIAL_TEST -static double log_determinant_estimate(const int operatorid, const int chebmax, - const int estimators, const double minev, const double maxev, +/*Convergence chesk: comparison of order n and n+1.*/ +#define CHECK_CONVERGENCE +static double 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 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; @@ -316,11 +470,17 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, const double am = t1 / 2.0; const double bm = t2 / 2.0; int k, l, n; - double x, y, ldet, prodre; + int orderstart, orderend; + int splitlength, sl; + double x, y, y1, ldet, prodre; FILE * ofs; spinor * vs1; spinor * vs2; spinor * u; +#ifdef CHECK_CONVERGENCE + spinor * unm1; + double prodrenm1, ldetnm1; +#endif spinor * v0; spinor * v1; spinor * v2; @@ -345,6 +505,9 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, vt0 = g_spinor_field[10]; vt1 = g_spinor_field[12]; vt2 = g_spinor_field[14]; +#ifdef CHECK_CONVERGENCE + unm1 = g_spinor_field[16]; +#endif optr = &operator_list[operatorid]; if (is_schur_complement(optr->applyQsq)) { @@ -358,7 +521,14 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, vt0 = g_spinor_field[7]; vt1 = g_spinor_field[8]; vt2 = g_spinor_field[9]; - if (DUM_MATRIX < 10) { +#ifdef CHECK_CONVERGENCE + unm1 = g_spinor_field[10]; +#endif +#ifdef CHECK_CONVERGENCE + if (DUM_MATRIX < 11) { +#else + if (DUM_MATRIX < 10) { +#endif if (g_proc_id == 0) { fprintf(stderr, "Not enough spinor fields %d < 10 \n\n", DUM_MATRIX); @@ -367,7 +537,11 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, } } else { - if (DUM_MATRIX < 16) { +#ifdef CHECK_CONVERGENCE + if (DUM_MATRIX < 18) { +#else + if (DUM_MATRIX < 16) { +#endif if (g_proc_id == 0) { fprintf(stderr, "Not enough spinor fields %d < 16 \n\n", DUM_MATRIX); @@ -375,9 +549,16 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, return 0.0; } } - - coeff = malloc(chebmax * sizeof(double)); - chebyshev_coeff(chebmax, coeff, am, bm); + 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) { ofs = fopen("polynomialapproxtest.txt", "a"); fprintf(ofs, @@ -385,162 +566,224 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, for (k = 0; k < 200; k++) { x = minev + (maxev - minev) * (double) k / (double) (200 - 1); y = poly_cheb(chebmax, coeff, a * x + b); - fprintf(ofs, "%d %g %g %g %d %g %g\n", k, x, y, fabs(y - log(x)), - chebmax, minev, maxev); + 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); } - ldet = 0; - if (chebmax > 0) { - for (k = 0; k < estimators; k++) { - /* - * Generate estimator (may be half of it is never used) - */ - random_spinor_field_eo(vs1, reproduce_randomnumber_flag, RN_Z2); - random_spinor_field_eo(vs2, reproduce_randomnumber_flag, RN_Z2); + /* include T_min(x) to T_(max-1) (x) */ + orderstart = 0; + orderend = chebmax; + splitlength = 1; + 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++) { + ldet = 0; + if (sl > 0) { + orderstart = orderend; + orderend = split->ord[sl]; + estimators = split->est[sl]; + } +#ifdef CHECK_CONVERGENCE + ldetnm1 = 0; +#endif + if (orderend > 0) { + for (k = 0; k < estimators; k++) { + /* + * Generate estimator (may be half of it is never used) + */ + random_spinor_field_eo(vs1, reproduce_randomnumber_flag, RN_Z2); + random_spinor_field_eo(vs2, reproduce_randomnumber_flag, RN_Z2); - assign(v0, vs1, n); - assign(vt0, vs1, n); + assign(v0, vs1, n); + assign(vt0, vs1, n); #ifdef TRIVIAL_TEST - mul_r(v1,kappa1,vs1,n); + mul_r(v1,kappa1,vs1,n); #else - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters(operatorid); - optr->applyQsq(v1, vs1); + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); + optr->applyQsq(v1, vs1); #endif - /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ - assign_mul_add_mul_r(v1, vs1, a, b, n); + /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ + assign_mul_add_mul_r(v1, vs1, a, b, n); #ifdef TRIVIAL_TEST - mul_r(vt1,kappa2,vs1,n); + mul_r(vt1,kappa2,vs1,n); #else - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); - optr->applyQsq(vt1, vs1); + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); + optr->applyQsq(vt1, vs1); #endif - /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ - assign_mul_add_mul_r(vt1, vs1, a, b, n); + /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ + assign_mul_add_mul_r(vt1, vs1, a, b, n); - /* Makes (*R)=c1*(*S)-c2*(*U) , c1 and c2 are complex constants */ - mul_diff_mul_r(u, vt1, v1, coeff[1], coeff[1], 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); +#ifdef CHECK_CONVERGENCE + if (orderend > 1) { + mul_diff_mul_r(unm1, vt1, v1, coeff[1], coeff[1], n); + } +#endif + } + + /*This part is only more efficient if not the clover term h + * as to be recompted everytime the parameters are changed.*/ #if 0 - for (l = 1; l + 1 < chebmax; l++) { + for (l = 1; l + 1 < orderend; l++) { #ifndef TRIVIAL_TEST - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters(operatorid); + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); - optr->applyQsq(v2, v1); + optr->applyQsq(v2, v1); #else - mul_r(v2,kappa1,v1,n); + mul_r(v2,kappa1,v1,n); #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) { + /* 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; #ifndef TRIVIAL_TEST - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); - optr->applyQsq(vt2, vt1); + optr->applyQsq(vt2, vt1); #else - mul_r(vt2,kappa2,vt1,n); + mul_r(vt2,kappa2,vt1,n); #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; - - /* (*R) = (*R) + c1*(*S) + c2*(*U) */ - assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], - -coeff[l + 1], n); + /* 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) { + /* (*R) = (*R) + c1*(*S) + c2*(*U) */ + assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], + -coeff[l + 1], n); + } - } + } #endif #ifndef TRIVIAL_TEST - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters(operatorid); + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); #endif - for (l = 1; l + 1 < chebmax; l++) { + for (l = 1; l + 1 < orderend; l++) { #ifdef TRIVIAL_TEST - mul_r(v2,kappa1,v1,n); + 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; - /* (*P) = (*P) + c(*Q) c is a real constant */ - assign_add_mul_r(u, v1, -coeff[l + 1], n); - } + 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); +#ifdef CHECK_CONVERGENCE + if (l + 2 < orderend) { + assign_add_mul_r(unm1, v1, -coeff[l + 1], n); + } +#endif + } + } #ifndef TRIVIAL_TEST - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); #endif - for (l = 1; l + 1 < chebmax; l++) { + for (l = 1; l + 1 < orderend; l++) { #ifdef TRIVIAL_TEST - mul_r(vt2,kappa2,vt1,n); + mul_r(vt2,kappa2,vt1,n); #else - optr->applyQsq(vt2, vt1); + 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; - - /* (*P) = (*P) + c(*Q) c is a real constant */ - assign_add_mul_r(u, vt1, coeff[l + 1], n); - - } + /* 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); +#ifdef CHECK_CONVERGENCE + if (l + 2 < orderend) { + assign_add_mul_r(unm1, vt1, coeff[l + 1], n); + } +#endif + } + } - prodre = scalar_prod_r(vs1, u, n, 1); - ldet += prodre / ((double) estimators); - if (g_proc_id == 0 && g_debug_level > 3) { - ofs = fopen("estimators.txt", "a"); - fprintf(ofs, "# Test of stochastic estimation\n"); - fprintf(ofs, "%d %g %g %g %g %g %d %d %g %g %g\n", k, kappa1, - kappa2, kappa2Mu1, kappa2Mu2, prodre, estimators, - chebmax, minev, maxev, ldet); - fclose(ofs); - } + prodre = scalar_prod_r(vs1, u, n, 1); + ldet += prodre / ((double) estimators); +#ifdef CHECK_CONVERGENCE + prodrenm1 = scalar_prod_r(vs1, unm1, n, 1); + ldetnm1 += prodrenm1 / ((double) estimators); +#endif + if (g_proc_id == 0 && g_debug_level > 3) { + ofs = fopen("estimators.txt", "a"); + fprintf(ofs, "# Test of stochastic estimation\n"); + fprintf(ofs, "%d %g %g %g %g %g %d %d %d %g %g %g ", k, + kappa1, kappa2, kappa2Mu1, kappa2Mu2, prodre, + estimators, orderstart, orderend, minev, maxev, + ldet); +#ifdef CHECK_CONVERGENCE + fprintf(ofs, " %g %g", prodrenm1, ldetnm1); +#endif + fprintf(ofs, "\n"); + fclose(ofs); + } - if (g_proc_id == 0) { - ofs = fopen(filename, "a"); - fprintf(ofs, "%d %g %g %g %g %d %g %g ", traj, kappa1, kappa2, - kappa2Mu1, kappa2Mu2, chebmax, minev, maxev); - fprintf(ofs, " %g %g\n", prodre + shift, prodre); - fclose(ofs); - } + 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 + shift, prodre); +#ifdef CHECK_CONVERGENCE + fprintf(ofs, " %.17g \n", prodrenm1 + shift); +#endif + fclose(ofs); + } - } /* estimator iteration*/ - } /* chebmax>0*/ + } /* estimator iteration*/ + } /* orderend>0*/ + } /* splitlength loop */ free(coeff); return (ldet); } @@ -626,7 +869,7 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { */ k2muinitial = param->k2mu0; kappainitial = param->kappa0; - cswinitial=0; + cswinitial = 0; kapparew = 1; if (kappainitial == kappafinal) { kapparew = 0; @@ -697,6 +940,12 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } } + cswpart = 0; + + if(param->evest){ + estimate_eigenvalues(operatorid,traj); + } + if (param->use_cheb) { if (param->use_evenodd == 1) { cswpart = get_sw_reweighting(k2muinitial, k2mufinal, kappainitial, @@ -704,7 +953,8 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } log_determinant_estimate(operatorid, param->cheborder, param->estimatorscheb, param->minev, param->maxev, kappainitial, - kappafinal, k2muinitial, k2mufinal, cswpart, traj); + kappafinal, k2muinitial, k2mufinal, cswpart, traj, + ¶m->splitlist, ¶m->coeff); if (param->only_cheb) { return; } @@ -848,7 +1098,6 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { 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"); @@ -872,7 +1121,6 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } /* loop over interpolation steps*/ - etime = gettime(); if (g_proc_id == 0 && g_debug_level > 0) { @@ -881,3 +1129,128 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } return; } + +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); + param->coeff.el = NULL; + param->coeff.s = 0; + param->splitlist.ord = NULL; + param->splitlist.est = NULL; + param->splitlist.s = 0; +} + +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]); + } + } + } else { + if (g_proc_id == 0) { + printf("File coeff.dat not present.\n"); + } + v->el = NULL; + v->s = 0; + } + +} + +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]); + } + } + } else { + if (g_proc_id == 0) { + printf("File split.dat not present.\n"); + } + list->ord = NULL; + list->est = NULL; + list->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->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; + read_coeff_from_file(¶m->coeff); + read_splitlist(¶m->splitlist); + } +} diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h index e46e8e820..62528b441 100644 --- a/meas/reweightingmeas.h +++ b/meas/reweightingmeas.h @@ -22,7 +22,23 @@ #ifndef _REWEIGHTING_MEASUREMENT_H #define _REWEIGHTING_MEASUREMENT_H +#include +#include + typedef struct{ + double* el; + unsigned int s; +} vector_list; + +typedef struct { + unsigned int * ord; + unsigned int* est; + unsigned int s; + +} split_list; + + +typedef struct { int reweighting_operator; int reweighting_number_sources; int use_evenodd; @@ -37,30 +53,15 @@ typedef struct{ int cheborder; int use_cheb; int only_cheb; - + int evest; + vector_list coeff; + split_list splitlist; } reweighting_parameter; -inline 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->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; - } -} +void free_reweighting_parameter(void* par); + + +void initialize_reweighting_parameter(void** parameter); void reweighting_measurement(const int traj, const int t0, const int ieo); diff --git a/read_input.l b/read_input.l index 652feb456..c0fd71f48 100644 --- a/read_input.l +++ b/read_input.l @@ -2003,6 +2003,12 @@ static inline void rmQuotes(char *str){ ((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); diff --git a/solver/jdher.c b/solver/jdher.c index 0d3fb5393..9dd30df25 100644 --- a/solver/jdher.c +++ b/solver/jdher.c @@ -306,7 +306,6 @@ void jdher(int n, int lda, double tau, double tol, * necessary randomly generated. * * * **************************************************************************/ - /* copy V0 to V */ _FT(zlacpy)(fupl_a, &n, &V0dim, V0, &lda, V, &lda, 1); j = V0dim; @@ -423,6 +422,7 @@ void jdher(int n, int lda, double tau, double tol, keepind[keep] = act; keep = keep + 1; } + } /* for(act = 0; act < actblksize; act ++) */ From 507f733d09de2c272a0b9407ee0ac9c1097faa6d Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Fri, 2 Dec 2016 12:43:08 +0100 Subject: [PATCH 05/22] added log estimation of reweighting --- meas/reweightingmeas.c | 545 ++++++++++++++++++++++++----------------- meas/reweightingmeas.h | 1 + measure.c | 2 +- read_input.l | 6 + 4 files changed, 328 insertions(+), 226 deletions(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index 3b9e03dc7..61becbf1d 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -65,8 +65,113 @@ #include "../global.h" #include "solver/jdher.h" +#include +#ifdef _USE_SHMEM +# include +#endif + /*#define CHECK_OPERATOR*/ +typedef struct { + spinor* buffer; + spinor** ar; + unsigned int length; +} spinor_array; + +static void set_zero(spinor * const R, const int N) { +#ifdef TM_USE_OMP +#pragma omp parallel + { +#endif + + int ix; + spinor *r; + +#ifdef TM_USE_OMP +#pragma omp for +#endif + for (ix = 0; ix < N; ++ix) { + r = (spinor *) R + ix; + + r->s0.c0 = 0.0; + r->s0.c1 = 0.0; + r->s0.c2 = 0.0; + + r->s1.c0 = 0.0; + r->s1.c1 = 0.0; + r->s1.c2 = 0.0; + + r->s2.c0 = 0.0; + r->s2.c1 = 0.0; + r->s2.c2 = 0.0; + + r->s3.c0 = 0.0; + r->s3.c1 = 0.0; + r->s3.c2 = 0.0; + } +#ifdef TM_USE_OMP +} /* OpenMP closing brace */ +#endif +} + +static int alloc_spinor_field(spinor_array* ar, int evenodd) { + int i = 0; + unsigned long int volume = VOLUMEPLUSRAND / 2; + if (evenodd == 0) { + volume = VOLUMEPLUSRAND; + } + if (ar->buffer != NULL || ar->ar != NULL || ar->length == 0) { + return (3); + } +#if (defined _USE_SHMEM && !(defined _USE_HALFSPINOR)) + if((void*)(ar->buffer = (spinor*)shmalloc((ar->length*volume+1)*sizeof(spinor))) == NULL) { + printf ("malloc errno : %d\n",errno); + errno = 0; + return(1); + } +#else + if ((void*) (ar->buffer = (spinor*) calloc(ar->length * volume + 1, + sizeof(spinor))) == NULL) { + printf("malloc errno : %d\n", errno); + errno = 0; + return (1); + } +#endif + if ((void*) (ar->ar = (spinor**) malloc(ar->length * sizeof(spinor*))) + == NULL) { + printf("malloc errno : %d\n", errno); + errno = 0; + return (2); + } +#if ( defined SSE || defined SSE2 || defined SSE3) + ar->ar = (spinor*)(((unsigned long int)(ar->buffer)+ALIGN_BASE)&~ALIGN_BASE); +#else + ar->ar[0] = ar->buffer; +#endif + + for (i = 1; i < ar->length; i++) { + ar->ar[i] = g_spinor_field[i - 1] + volume; + } + + return (0); +} + +static void free_spinor_field(spinor_array* ar) { + if (ar->buffer != NULL) { +#if (defined _USE_SHMEM && !(defined _USE_HALFSPINOR)) + shfree(ar->buffer); +#else + free(ar->buffer); +#endif + } + if (ar->ar != NULL) { + free(ar->ar); + } + ar->ar = NULL; + ar->buffer = NULL; + ar->length = 0; +} + 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 @@ -98,8 +203,6 @@ static double get_sw_reweighting(const double mu1, const double 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 @@ -131,151 +234,142 @@ static void update_global_parameters(const int op_id) { static void estimate_eigenvalues(const int operatorid, const int identifier) { #ifdef HAVE_LAPACK - vector_list min_ev; - vector_list max_ev; - spinor * eigenvectors_ = NULL; - char filename[200]; - FILE * ofs; - double atime, etime; - int max_iterations=5000; - double prec = 1.e-5; - int maxvectors; - /********************** - * For Jacobi-Davidson - **********************/ - int verbosity = g_debug_level, converged = 0, blocksize = 1, blockwise = 0; - int solver_it_max = 50, j_max, j_min, ii; - /*int it_max = 10000;*/ - /* _Complex double *eigv_ = NULL, *eigv; */ - double decay_min = 1.7, decay_max = 1.5, - threshold_min = 1.e-3, threshold_max = 5.e-2; - double ev_max, ev_min; - - /* static int v0dim = 0; */ - int v0dim = 0; - int N = (VOLUME)/2, N2 = (VOLUMEPLUSRAND)/2; - operator * optr; - - /********************** - * General variables - **********************/ - int returncode=0; - int returncode2=0; - - - min_ev.s=2; - min_ev.el=malloc(min_ev.s*sizeof(double)); - max_ev.s=2; - max_ev.el=malloc(max_ev.s*sizeof(double)); + vector_list min_ev; + vector_list max_ev; + spinor * eigenvectors_ = NULL; + char filename[200]; + FILE * ofs; + double atime, etime; + int max_iterations = 5000; + double prec = 1.e-5; + int maxvectors; + /********************** + * For Jacobi-Davidson + **********************/ + int verbosity = g_debug_level, converged = 0, blocksize = 1, blockwise = 0; + int solver_it_max = 50, j_max, j_min, ii; + /*int it_max = 10000;*/ + /* _Complex double *eigv_ = NULL, *eigv; */ + double decay_min = 1.7, decay_max = 1.5, threshold_min = 1.e-3, + threshold_max = 5.e-2; + double ev_max, ev_min; + + /* static int v0dim = 0; */ + int v0dim = 0; + int N = (VOLUME) / 2, N2 = (VOLUMEPLUSRAND) / 2; + operator * optr; - optr = &operator_list[operatorid]; + /********************** + * General variables + **********************/ + int returncode = 0; + int returncode2 = 0; + + min_ev.s = 2; + min_ev.el = malloc(min_ev.s * sizeof(double)); + max_ev.s = 2; + max_ev.el = malloc(max_ev.s * sizeof(double)); + optr = &operator_list[operatorid]; - if(!is_schur_complement(optr->applyQsq)) { - N = VOLUME; - N2 = VOLUMEPLUSRAND; - } + if (!is_schur_complement(optr->applyQsq)) { + N = VOLUME; + N2 = VOLUMEPLUSRAND; + } - evlength = N2; - if(g_proc_id == g_stdio_proc && g_debug_level >0) { - printf("Number of eigenvalues to compute = %d %d\n",min_ev.s,max_ev.s); - printf("Using Jacobi-Davidson method! \n"); - } + evlength = N2; + if (g_proc_id == g_stdio_proc && g_debug_level > 0) { + printf("Number of eigenvalues to compute = %d %d\n", min_ev.s, + max_ev.s); + printf("Using Jacobi-Davidson method! \n"); + } - if(max_ev.s < 8){ - j_max = 15; - j_min = 8; - } - else{ - j_max = 2*max_ev.s; - j_min = max_ev.s; - } + if (max_ev.s < 8) { + j_max = 15; + j_min = 8; + } else { + j_max = 2 * max_ev.s; + j_min = max_ev.s; + } - maxvectors=min_ev.s>max_ev.s ? min_ev.s:max_ev.s; + maxvectors = min_ev.s > max_ev.s ? min_ev.s : max_ev.s; #if (defined SSE || defined SSE2 || defined SSE3) - eigenvectors_ = calloc(N2*maxvectors+1, sizeof(spinor)); - eigenvectors = (spinor *)(((unsigned long int)(eigenvectors_)+ALIGN_BASE)&~ALIGN_BASE); + eigenvectors_ = calloc(N2*maxvectors+1, sizeof(spinor)); + eigenvectors = (spinor *)(((unsigned long int)(eigenvectors_)+ALIGN_BASE)&~ALIGN_BASE); #else - eigenvectors_= calloc(N2*maxvectors, sizeof(spinor)); - eigenvectors = eigenvectors_; + eigenvectors_ = calloc(N2 * maxvectors, sizeof(spinor)); + eigenvectors = eigenvectors_; #endif - atime = gettime(); + atime = gettime(); + + update_global_parameters(operatorid); - /* (re-) compute minimal eigenvalues */ - converged = 0; - solver_it_max = 200; - - - jdher(N*sizeof(spinor)/sizeof(_Complex double), N2*sizeof(spinor)/sizeof(_Complex double), - 50., prec,max_ev.s, j_max, j_min, - max_iterations, blocksize, blockwise, v0dim, (_Complex double*) eigenvectors, - CG, solver_it_max, - threshold_max, decay_max, verbosity, - &converged, (_Complex double*) eigenvectors, max_ev.el, - &returncode, JD_MAXIMAL, 1, - optr->applyQsq); - - max_ev.s = converged; - - if(min_ev.s < 8){ - j_max = 15; - j_min = 8; - } - else{ - j_max = 2*min_ev.s; - j_min = min_ev.s; - } - - converged = 0; - solver_it_max = 200; - - jdher(N*sizeof(spinor)/sizeof(_Complex double), N2*sizeof(spinor)/sizeof(_Complex double), - 0., prec, - min_ev.s, j_max, j_min, - max_iterations, blocksize, blockwise, v0dim, (_Complex double*) eigenvectors, - CG, solver_it_max, - threshold_min, decay_min, verbosity, - &converged, (_Complex double*) eigenvectors, min_ev.el, - &returncode2, JD_MINIMAL, 1, - optr->applyQsq); - - min_ev.s = converged; - - free(eigenvectors_); - - etime = gettime(); - if(g_proc_id == 0) { - printf("Eigenvalues computed in %e sec. gettime)\n", etime-atime); - } - - ev_min= min_ev.el[min_ev.s-1]; - ev_max= max_ev.el[max_ev.s-1]; - eigenvalues_for_cg_computed = converged; - - if(g_proc_id == 0){ - sprintf(filename,"rew_ev_estimate.%d", nstore); - ofs = fopen(filename, "a"); - for(ii = 0; ii < max_ev.s; ii++) { - fprintf(ofs, "%d %e 1\n",ii,max_ev.el[ii]); - } - for(ii = 0; ii < min_ev.s; ii++) { - fprintf(ofs, "%d %e 1\n",ii,min_ev.el[ii]); - } - fclose(ofs); - } - free(min_ev.el); - free(max_ev.el); + /* (re-) compute minimal eigenvalues */ + converged = 0; + solver_it_max = 200; + + jdher(N * sizeof(spinor) / sizeof(_Complex double), + N2 * sizeof(spinor) / sizeof(_Complex double), 50., prec, max_ev.s, + j_max, j_min, max_iterations, blocksize, blockwise, v0dim, + (_Complex double*) eigenvectors, CG, solver_it_max, threshold_max, + decay_max, verbosity, &converged, (_Complex double*) eigenvectors, + max_ev.el, &returncode, JD_MAXIMAL, 1, optr->applyQsq); + + max_ev.s = converged; + + if (min_ev.s < 8) { + j_max = 15; + j_min = 8; + } else { + j_max = 2 * min_ev.s; + j_min = min_ev.s; + } + + converged = 0; + solver_it_max = 200; + + jdher(N * sizeof(spinor) / sizeof(_Complex double), + N2 * sizeof(spinor) / sizeof(_Complex double), 0., prec, min_ev.s, + j_max, j_min, max_iterations, blocksize, blockwise, v0dim, + (_Complex double*) eigenvectors, CG, solver_it_max, threshold_min, + decay_min, verbosity, &converged, (_Complex double*) eigenvectors, + min_ev.el, &returncode2, JD_MINIMAL, 1, optr->applyQsq); + + min_ev.s = converged; + + free(eigenvectors_); + + etime = gettime(); + if (g_proc_id == 0) { + printf("Eigenvalues computed in %e sec. gettime)\n", etime - atime); + } + + ev_min = min_ev.el[min_ev.s - 1]; + ev_max = max_ev.el[max_ev.s - 1]; + eigenvalues_for_cg_computed = converged; + + if (g_proc_id == 0) { + sprintf(filename, "rew_ev_estimate.%d", nstore); + ofs = fopen(filename, "a"); + for (ii = 0; ii < max_ev.s; ii++) { + fprintf(ofs, "%d %e 1\n", ii, max_ev.el[ii]); + } + for (ii = 0; ii < min_ev.s; ii++) { + fprintf(ofs, "%d %e 1\n", ii, min_ev.el[ii]); + } + fclose(ofs); + } + free(min_ev.el); + free(max_ev.el); #else - fprintf(stderr, "lapack not available, so JD method for EV computation not available \n"); + fprintf(stderr, "lapack not available, so JD method for EV computation not available \n"); #endif } - - static int invert_operator_Q(spinor * const P, spinor * const Q, const int op_id, const int pm) { @@ -454,10 +548,10 @@ static double poly_cheb(const unsigned int np, const double * const coeff, } /*Trivial test tests the function with the scaled idenetity matrix.*/ -//#define TRIVIAL_TEST +/*#define TRIVIAL_TEST*/ /*Convergence chesk: comparison of order n and n+1.*/ #define CHECK_CONVERGENCE -static double log_determinant_estimate(const int operatorid, int chebmax, +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, @@ -469,17 +563,19 @@ static double log_determinant_estimate(const int operatorid, int chebmax, 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; - double x, y, y1, ldet, prodre; + spinor_array spinorarray; + static int written = 0; + double x, y, y1, prodre; FILE * ofs; - spinor * vs1; - spinor * vs2; + spinor * vs; spinor * u; #ifdef CHECK_CONVERGENCE spinor * unm1; - double prodrenm1, ldetnm1; + double prodrenm1; #endif spinor * v0; spinor * v1; @@ -491,64 +587,39 @@ static double log_determinant_estimate(const int operatorid, int chebmax, 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); - vs1 = g_spinor_field[0]; - vs2 = g_spinor_field[1]; - u = g_spinor_field[2]; - v0 = g_spinor_field[4]; - v1 = g_spinor_field[6]; - v2 = g_spinor_field[8]; - vt0 = g_spinor_field[10]; - vt1 = g_spinor_field[12]; - vt2 = g_spinor_field[14]; -#ifdef CHECK_CONVERGENCE - unm1 = g_spinor_field[16]; -#endif - optr = &operator_list[operatorid]; + + spinorarray.length = 9; if (is_schur_complement(optr->applyQsq)) { n = VOLUME / 2; - vs1 = g_spinor_field[0]; - vs2 = g_spinor_field[1]; - u = g_spinor_field[3]; - v0 = g_spinor_field[4]; - v1 = g_spinor_field[5]; - v2 = g_spinor_field[6]; - vt0 = g_spinor_field[7]; - vt1 = g_spinor_field[8]; - vt2 = g_spinor_field[9]; -#ifdef CHECK_CONVERGENCE - unm1 = g_spinor_field[10]; -#endif -#ifdef CHECK_CONVERGENCE - if (DUM_MATRIX < 11) { -#else - if (DUM_MATRIX < 10) { -#endif - if (g_proc_id == 0) { - fprintf(stderr, "Not enough spinor fields %d < 10 \n\n", - DUM_MATRIX); - } - return 0.0; - } - + 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]; #ifdef CHECK_CONVERGENCE - if (DUM_MATRIX < 18) { -#else - if (DUM_MATRIX < 16) { + unm1 = spinorarray.ar[8]; #endif - if (g_proc_id == 0) { - fprintf(stderr, "Not enough spinor fields %d < 16 \n\n", - DUM_MATRIX); - } - return 0.0; - } - } + if (coefflist->el != NULL && coefflist->s != 0) { chebmax = coefflist->s; coeff = malloc(chebmax * sizeof(double)); @@ -559,8 +630,9 @@ static double log_determinant_estimate(const int operatorid, int chebmax, coeff = malloc(chebmax * sizeof(double)); chebyshev_coeff(chebmax, coeff, am, bm); } - if (g_proc_id == 0 && g_debug_level > 3) { - ofs = fopen("polynomialapproxtest.txt", "a"); + 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++) { @@ -574,48 +646,65 @@ static double log_determinant_estimate(const int operatorid, int chebmax, 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++) { - ldet = 0; if (sl > 0) { orderstart = orderend; orderend = split->ord[sl]; estimators = split->est[sl]; + rel_shift = 0.0; } -#ifdef CHECK_CONVERGENCE - ldetnm1 = 0; -#endif + if (orderend > 0) { for (k = 0; k < estimators; k++) { + if (orderstart > 1 || orderend < 2) { + set_zero(u, n); +#ifdef CHECK_CONVERGENCE + set_zero(unm1, n); +#endif + } /* - * Generate estimator (may be half of it is never used) + * Generate estimator */ - random_spinor_field_eo(vs1, reproduce_randomnumber_flag, RN_Z2); - random_spinor_field_eo(vs2, reproduce_randomnumber_flag, RN_Z2); + 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, vs1, n); - assign(vt0, vs1, n); + 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, vs1); + optr->applyQsq(v1, vs); #endif /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ - assign_mul_add_mul_r(v1, vs1, a, b, n); + assign_mul_add_mul_r(v1, vs, a, b, n); #ifdef TRIVIAL_TEST mul_r(vt1,kappa2,vs1,n); @@ -623,10 +712,10 @@ static double log_determinant_estimate(const int operatorid, int chebmax, optr->kappa = kappa2; optr->mu = kappa2Mu2; update_global_parameters(operatorid); - optr->applyQsq(vt1, vs1); + optr->applyQsq(vt1, vs); #endif /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ - assign_mul_add_mul_r(vt1, vs1, a, b, n); + 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 */ @@ -652,7 +741,7 @@ static double log_determinant_estimate(const int operatorid, int chebmax, #else mul_r(v2,kappa1,v1,n); #endif - if(l+1>orderstart) { + if(l+1>=orderstart) { /* 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); @@ -679,7 +768,7 @@ static double log_determinant_estimate(const int operatorid, int chebmax, vt1 = vt2; vt2 = tmp; - if(l+1>orderstart) { + if(l+1>=orderstart) { /* (*R) = (*R) + c1*(*S) + c2*(*U) */ assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], -coeff[l + 1], n); @@ -709,7 +798,8 @@ static double log_determinant_estimate(const int operatorid, int chebmax, v0 = v1; v1 = v2; v2 = tmp; - if (l + 1 > orderstart) { + + if (l + 1 >= orderstart) { /* (*P) = (*P) + c(*Q) c is a real constant */ assign_add_mul_r(u, v1, -coeff[l + 1], n); #ifdef CHECK_CONVERGENCE @@ -738,7 +828,7 @@ static double log_determinant_estimate(const int operatorid, int chebmax, vt0 = vt1; vt1 = vt2; vt2 = tmp; - if (l + 1 > orderstart) { + if (l + 1 >= orderstart) { /* (*P) = (*P) + c(*Q) c is a real constant */ assign_add_mul_r(u, vt1, coeff[l + 1], n); #ifdef CHECK_CONVERGENCE @@ -749,34 +839,20 @@ static double log_determinant_estimate(const int operatorid, int chebmax, } } - prodre = scalar_prod_r(vs1, u, n, 1); - ldet += prodre / ((double) estimators); + prodre = scalar_prod_r(vs, u, n, 1); #ifdef CHECK_CONVERGENCE - prodrenm1 = scalar_prod_r(vs1, unm1, n, 1); - ldetnm1 += prodrenm1 / ((double) estimators); + prodrenm1 = scalar_prod_r(vs, unm1, n, 1); #endif - if (g_proc_id == 0 && g_debug_level > 3) { - ofs = fopen("estimators.txt", "a"); - fprintf(ofs, "# Test of stochastic estimation\n"); - fprintf(ofs, "%d %g %g %g %g %g %d %d %d %g %g %g ", k, - kappa1, kappa2, kappa2Mu1, kappa2Mu2, prodre, - estimators, orderstart, orderend, minev, maxev, - ldet); -#ifdef CHECK_CONVERGENCE - fprintf(ofs, " %g %g", prodrenm1, ldetnm1); -#endif - fprintf(ofs, "\n"); - fclose(ofs); - } 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 + shift, prodre); + fprintf(ofs, " %.17g %.17g ", prodre + rel_shift, + prodre); #ifdef CHECK_CONVERGENCE - fprintf(ofs, " %.17g \n", prodrenm1 + shift); + fprintf(ofs, " %.17g \n", prodrenm1 + rel_shift); #endif fclose(ofs); } @@ -785,7 +861,7 @@ static double log_determinant_estimate(const int operatorid, int chebmax, } /* orderend>0*/ } /* splitlength loop */ free(coeff); - return (ldet); + free_spinor_field(&spinorarray); } void reweighting_measurement(const int traj, const int id, const int ieo) { @@ -940,13 +1016,27 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } } + 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){ - estimate_eigenvalues(operatorid,traj); + if (param->evest) { + if (g_proc_id == 0) { + printf("Calculating minimal/maximal eigenvalue estimates.\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); @@ -971,8 +1061,12 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { for (internum = 0; internum < param->interpolationsteps; internum++) { if (kapparew) { kappa0 = kappa; - interpolate(&kappa, kappainitial, kappafinal, + tmp1=1.0/kappainitial; + tmp2=1.0/kappafinal; + tmp3=1.0/kappa; + interpolate(&tmp3, tmp1,tmp2, param->interpolationsteps, internum); + kappa=1.0/tmp3; } if (murew) { /* use quadratic interpolation in the case of mu*/ @@ -1249,7 +1343,8 @@ void initialize_reweighting_parameter(void** parameter) { param->splitlist.ord = NULL; param->splitlist.est = NULL; param->splitlist.s = 0; - param->evest=0; + param->evest = 0; + param->testchebconvergence = 0; read_coeff_from_file(¶m->coeff); read_splitlist(¶m->splitlist); } diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h index 62528b441..e167c60b7 100644 --- a/meas/reweightingmeas.h +++ b/meas/reweightingmeas.h @@ -48,6 +48,7 @@ typedef struct { double rmu; double minev; double maxev; + double testchebconvergence; int interpolationsteps; int estimatorscheb; int cheborder; diff --git a/measure.c b/measure.c index aa8e1dfa2..d199e8b8b 100644 --- a/measure.c +++ b/measure.c @@ -125,7 +125,7 @@ int main(int argc, char *argv[]) #endif DUM_DERI = 8; - DUM_MATRIX = DUM_DERI + 5; /* 5 fields for doing the inversions (might be used by other opetations if no inverter used*/ + DUM_MATRIX = DUM_DERI + 5; /* 5 fields for doing the inversions (might be used by other operations if no inverter used*/ NO_OF_SPINORFIELDS = DUM_MATRIX + 4; /* Don't access these fields if you apply multiplications!*/ //4 extra fields (corresponding to DUM_MATRIX+0..5) for deg. and ND matrix mult. diff --git a/read_input.l b/read_input.l index c0fd71f48..b685ab1cd 100644 --- a/read_input.l +++ b/read_input.l @@ -2039,6 +2039,12 @@ static inline void rmQuotes(char *str){ ((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); + } } { From 25f1f895eef053e164afe72f46fe36a7a7dc50db Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Fri, 19 Aug 2016 14:22:38 +0200 Subject: [PATCH 06/22] added new measurements of reweighting factors and changed concept for measurements --- meas/reweightingmeas.c | 577 ++++++++++++++++++++++++++ meas/reweightingmeas.h | 55 +++ measure.c | 492 ++++++++++++++++++++++ monomial/cloverdetratio_rwdmonomial.c | 103 +++++ monomial/cloverdetratio_rwdmonomial.h | 31 ++ 5 files changed, 1258 insertions(+) create mode 100644 meas/reweightingmeas.c create mode 100644 meas/reweightingmeas.h create mode 100644 measure.c create mode 100644 monomial/cloverdetratio_rwdmonomial.c create mode 100644 monomial/cloverdetratio_rwdmonomial.h diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c new file mode 100644 index 000000000..13c1605e1 --- /dev/null +++ b/meas/reweightingmeas.c @@ -0,0 +1,577 @@ +/*********************************************************************** + * + * Measurements of the reweighting factors by Georg Bergner 2016 + * + * Copyright (C) 2008 Carsten Urbach + * + * 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 "linalg/convert_eo_to_lexic.h" +#include "measurements.h" +#include "correlators.h" +#include "gettime.h" +#include "linalg/square_norm.h" +#include "linalg/scalar_prod_r.h" +#include "linalg/scalar_prod_i.h" +#include "linalg/diff.h" +#include "linalg/assign.h" +#include "../read_input.h" +#include "reweightingmeas.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 "../DDalphaAMG_interface.h" +#include "../boundary.h" + +/*#define CHECK_OPERATOR*/ + +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_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; +} + +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; +} + +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*/ +} + +static int invert_operator_Q(spinor * const P, spinor * const Q, + const int op_id, const int pm) { + + 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) + 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); +} + +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); +} + +static double log_determinant_estimate(const int operatorid, const int chebmax, const int estimators, const double spectmin, const double spectmax){ + +} + +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; + 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 kapparew; + int murew; +#ifdef CHECK_OPERATOR + double checkg5,check1,check2,check3,check4,check5; + double kappa_old; +#endif + /* now we bring it to normal format */ + /* here we use implicitly DUM_MATRIX and DUM_MATRIX+1 */ + spinor * lexicfield1; + spinor * lexicfield2; +#ifdef CHECK_OPERATOR + spinor * lexicfield3; + spinor * lexicfield4; +#endif + int operatorid; + int numsamples, snum, internum; + unsigned long int site; + + param = (reweighting_parameter*) measurement_list[id].parameter; + lexicfield1 = g_spinor_field[4]; + lexicfield2 = g_spinor_field[6]; +#ifdef CHECK_OPERATOR + lexicfield3=g_spinor_field[8]; + lexicfield4=g_spinor_field[10]; +#endif + 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; + 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"); + } + return; + } + + 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"); + } + } + + + kappa0 = kappa = kappainitial; + k2mu0 = k2mu = k2muinitial; + csw0 = csw = cswinitial; + rmu0 = rmu = rmuinitial; + + if (param->interpolationsteps < 1) + param->interpolationsteps = 1; + + for (internum = 0; internum < param->interpolationsteps; internum++) { + if (kapparew) { + kappa0 = kappa; + interpolate(&kappa, kappainitial, kappafinal, + param->interpolationsteps, internum); + } + 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); + } + k2mu = 2.0 * kappa * rmu; + k2mu0 = 2.0 * kappa0 * rmu0; + optr->kappa = kappa; + optr->mu = k2mu; + optr->c_sw = 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); +#ifdef CHECK_OPERATOR + for(site = 0; site < VOLUME; site++) { + _gamma5(lexicfield2[site], lexicfield1[site]); + } + checkg5=scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); /* should be zero*/ + + kappa_old=optr->kappa; + optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); /* prop=D rand*/ + mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2);/*correct normalisation*/ + mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); + convert_eo_to_lexic(lexicfield2, optr->prop0, optr->prop1); + check1 = -scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); + check2 = -scalar_prod_i(lexicfield1,lexicfield2,VOLUME, 1); + check3 = scalar_prod_r(lexicfield2,lexicfield2,VOLUME ,1); + + optr->kappa=1.0/(1.0/kappa_old+2.0); + optr->inverter(operatorid,0,0); /* to ensure that everything is updated*/ + optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); + mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2); + mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); + convert_eo_to_lexic(lexicfield3, optr->prop0, optr->prop1); + check1 += scalar_prod_r(lexicfield1,lexicfield3,VOLUME, 1); + check2 += scalar_prod_i(lexicfield1,lexicfield3,VOLUME, 1); + diff(lexicfield4,lexicfield3,lexicfield2,VOLUME); + check4=scalar_prod_r(lexicfield1,lexicfield1,VOLUME, 1); + check5=square_norm(lexicfield1,VOLUME ,1); + + optr->kappa=kappa_old; +#endif + 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); +#ifdef CHECK_OPERATOR + fprintf( ofs_full, "%e %e %e %e %e %e %e %e %e %e %e %e\n", square1, square2,prodre,prodim,prodreg5,prodimg5,checkg5,check1,check2,check3,check4,check5); +#else + /*print all raw data for cross check*/ + fprintf(ofs_full, + "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", 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); + } +#endif + 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); + + square2 = square_norm(optr->prop0, VOLUME / 2, 1); + + prodre = get_sw_reweighting(k2mu0, k2mu, kappa0, kappa, csw0, + csw); + + 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, + "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", k2mu0, + k2mu, kappa0, kappa, csw0, csw, rmu, rmu0); + fprintf(ofs_full, "%.17g %.17g %.17g\n", square1, square2, + prodre); + fprintf(ofs, "%.17g\n", square1 - square2 + prodre); + 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; +} diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h new file mode 100644 index 000000000..d973292c0 --- /dev/null +++ b/meas/reweightingmeas.h @@ -0,0 +1,55 @@ +/*********************************************************************** + * + * Measurements of the reweighting factors by Georg Bergner 2016 + * + * Copyright (C) 2008 Carsten Urbach + * + * 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 +typedef struct{ + int reweighting_operator; + int reweighting_number_sources; + int use_evenodd; + double k2mu0; + double kappa0; + int interpolationsteps; + double rmu0; + double rmu; + +} reweighting_parameter; + +inline void initialize_reweighting_parameter(void** parameter){ + reweighting_parameter* param; + if(!(*parameter)){ + (*parameter)=malloc(sizeof(reweighting_parameter)); + param=(reweighting_parameter*)(*parameter); + param->reweighting_number_sources=0; + param->reweighting_operator=0; + param->use_evenodd=0; + param->k2mu0=0.0; + param->rmu0=0.0; + param->rmu=0.0; + param->kappa0=0.0; + param->interpolationsteps=1; + } +} + +void reweighting_measurement(const int traj, const int t0, const int ieo); + +#endif diff --git a/measure.c b/measure.c new file mode 100644 index 000000000..aab5fce79 --- /dev/null +++ b/measure.c @@ -0,0 +1,492 @@ +/*********************************************************************** + * + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Carsten Urbach + * + * 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 . + * + * adaption of the invert for twisted mass QCD to contain only a few number + * of relevant measurements by Georg Bergner 2016 (still ugly) + * + * Author: Carsten Urbach, Georg Bergner + * urbach@physik.fu-berlin.de + * + *******************************************************************************/ + +#include"lime.h" +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include +#include +#include +#include +#ifdef TM_USE_MPI +#include +#endif +#ifdef TM_USE_OMP +# include +#endif +#include "global.h" +#include "git_hash.h" +#include "getopt.h" +#include "linalg_eo.h" +#include "geometry_eo.h" +#include "start.h" +/*#include "eigenvalues.h"*/ +#include "measure_gauge_action.h" +#ifdef TM_USE_MPI +#include "xchange/xchange.h" +#endif +#include +#include "source_generation.h" +#include "read_input.h" +#include "mpi_init.h" +#include "sighandler.h" +#include "boundary.h" +#include "solver/solver.h" +#include "init/init.h" +#include "smearing/stout.h" +#include "invert_eo.h" +#include "monomial/monomial.h" +#include "ranlxd.h" +#include "phmc.h" +#include "operator/D_psi.h" +#include "little_D.h" +#include "reweighting_factor.h" +#include "linalg/convert_eo_to_lexic.h" +#include "block.h" +#include "operator.h" +#include "sighandler.h" +#include "solver/generate_dfl_subspace.h" +#include "prepare_source.h" +#include +#include +#include +#include +#include "solver/dirac_operator_eigenvectors.h" +#include "source_generation.h" +#include "P_M_eta.h" +#include "operator/tm_operators.h" +#include "operator/Dov_psi.h" +#include "solver/spectral_proj.h" +#ifdef QUDA +# include "quda_interface.h" +#endif +#ifdef DDalphaAMG +# include "DDalphaAMG_interface.h" +#endif +#include "meas/measurements.h" +#include "source_generation.h" + + + +extern int nstore; +int check_geometry(); + +static void usage(); +static void process_args(int argc, char *argv[], char ** input_filename, char ** filename); +static void set_default_filenames(char ** input_filename, char ** filename); +static void invert_compute_modenumber(); + +int main(int argc, char *argv[]) +{ + FILE *parameterfile = NULL; + int j, i, ix = 0, isample = 0, op_id = 0; + char datafilename[206]; + char parameterfilename[206]; + char conf_filename[300]; + char * input_filename = NULL; + char * filename = NULL; + double plaquette_energy; + struct stout_parameters params_smear; + +#ifdef _KOJAK_INST +#pragma pomp inst init +#pragma pomp inst begin(main) +#endif + +#if (defined SSE || defined SSE2 || SSE3) + signal(SIGILL, &catch_ill_inst); +#endif + + DUM_DERI = 8; + DUM_MATRIX = DUM_DERI + 5; + NO_OF_SPINORFIELDS = DUM_MATRIX + 4; + + //4 extra fields (corresponding to DUM_MATRIX+0..5) for deg. and ND matrix mult. + NO_OF_SPINORFIELDS_32 = 6; + + verbose = 0; + g_use_clover_flag = 0; + +#ifdef TM_USE_MPI + +# ifdef TM_USE_OMP + int mpi_thread_provided; + MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &mpi_thread_provided); +# else + MPI_Init(&argc, &argv); +# endif + + MPI_Comm_rank(MPI_COMM_WORLD, &g_proc_id); +#else + g_proc_id = 0; +#endif + + process_args(argc,argv,&input_filename,&filename); + set_default_filenames(&input_filename, &filename); + + /* Read the input file */ + if( (j = read_input(input_filename)) != 0) { + fprintf(stderr, "Could not find input file: %s\nAborting...\n", input_filename); + exit(-1); + } + +#ifdef TM_USE_OMP + init_openmp(); +#endif + + /* this DBW2 stuff is not needed for the inversion ! */ + if (g_dflgcr_flag == 1) { + even_odd_flag = 0; + } + g_rgi_C1 = 0; + if (Nsave == 0) { + Nsave = 1; + } + + if (g_running_phmc) { + NO_OF_SPINORFIELDS = DUM_MATRIX + 8; + } + + tmlqcd_mpi_init(argc, argv); + + g_dbw2rand = 0; + + /* starts the single and double precision random number */ + /* generator */ + start_ranlux(rlxd_level, random_seed^nstore); + + /* we need to make sure that we don't have even_odd_flag = 1 */ + /* if any of the operators doesn't use it */ + /* in this way even/odd can still be used by other operators */ + for(j = 0; j < no_operators; j++) if(!operator_list[j].even_odd_flag) even_odd_flag = 0; + +#ifndef TM_USE_MPI + g_dbw2rand = 0; +#endif + +#ifdef _GAUGE_COPY + j = init_gauge_field(VOLUMEPLUSRAND, 1); + j += init_gauge_field_32(VOLUMEPLUSRAND, 1); +#else + j = init_gauge_field(VOLUMEPLUSRAND, 0); + j += init_gauge_field_32(VOLUMEPLUSRAND, 0); +#endif + + if (j != 0) { + fprintf(stderr, "Not enough memory for gauge_fields! Aborting...\n"); + exit(-1); + } + j = init_geometry_indices(VOLUMEPLUSRAND); + if (j != 0) { + fprintf(stderr, "Not enough memory for geometry indices! Aborting...\n"); + exit(-1); + } + if (no_monomials > 0) { + if (even_odd_flag) { + j = init_monomials(VOLUMEPLUSRAND / 2, even_odd_flag); + } + else { + j = init_monomials(VOLUMEPLUSRAND, even_odd_flag); + } + if (j != 0) { + fprintf(stderr, "Not enough memory for monomial pseudo fermion fields! Aborting...\n"); + exit(-1); + } + } + if (even_odd_flag) { + j = init_spinor_field(VOLUMEPLUSRAND / 2, NO_OF_SPINORFIELDS); + j += init_spinor_field_32(VOLUMEPLUSRAND / 2, NO_OF_SPINORFIELDS_32); + } + else { + j = init_spinor_field(VOLUMEPLUSRAND, NO_OF_SPINORFIELDS); + j += init_spinor_field_32(VOLUMEPLUSRAND, NO_OF_SPINORFIELDS_32); + } + if (j != 0) { + fprintf(stderr, "Not enough memory for spinor fields! Aborting...\n"); + exit(-1); + } + + if (g_running_phmc) { + j = init_chi_spinor_field(VOLUMEPLUSRAND / 2, 20); + if (j != 0) { + fprintf(stderr, "Not enough memory for PHMC Chi fields! Aborting...\n"); + exit(-1); + } + } + + g_mu = g_mu1; + + if (g_cart_id == 0) { + /*construct the filenames for the observables and the parameters*/ + strncpy(datafilename, filename, 200); + strcat(datafilename, ".data"); + strncpy(parameterfilename, filename, 200); + strcat(parameterfilename, ".para"); + + parameterfile = fopen(parameterfilename, "w"); + write_first_messages(parameterfile, "invert", git_hash); + fclose(parameterfile); + } + + /* define the geometry */ + geometry(); + + /* define the boundary conditions for the fermion fields */ + boundary(g_kappa); + + phmc_invmaxev = 1.; + + init_operators(); + + /* list and initialize measurements*/ + if(g_proc_id == 0) { + printf("\n"); + for(int j = 0; j < no_measurements; j++) { + printf("# measurement id %d, type = %d\n", j, measurement_list[j].type); + } + } + init_measurements(); + + /* this could be maybe moved to init_operators */ +#ifdef _USE_HALFSPINOR + j = init_dirac_halfspinor(); + if (j != 0) { + fprintf(stderr, "Not enough memory for halffield! Aborting...\n"); + exit(-1); + } + /* for mixed precision solvers, the 32 bit halfspinor field must always be there */ + j = init_dirac_halfspinor32(); + if (j != 0) + { + fprintf(stderr, "Not enough memory for 32-bit halffield! Aborting...\n"); + exit(-1); + } +# if (defined _PERSISTENT) + if (even_odd_flag) + init_xchange_halffield(); +# endif +#endif + + for (j = 0; j < Nmeas; j++) { + sprintf(conf_filename, "%s.%.4d", gauge_input_filename, nstore); + if (g_cart_id == 0) { + printf("#\n# Trying to read gauge field from file %s in %s precision.\n", + conf_filename, (gauge_precision_read_flag == 32 ? "single" : "double")); + fflush(stdout); + } + if( (i = read_gauge_field(conf_filename,g_gauge_field)) !=0) { + fprintf(stderr, "Error %d while reading gauge field from %s\n Aborting...\n", i, conf_filename); + exit(-2); + } + + + if (g_cart_id == 0) { + printf("# Finished reading gauge field.\n"); + fflush(stdout); + } +#ifdef TM_USE_MPI + xchange_gauge(g_gauge_field); +#endif + /*Convert to a 32 bit gauge field, after xchange*/ + convert_32_gauge_field(g_gauge_field_32, g_gauge_field, VOLUMEPLUSRAND); + /*compute the energy of the gauge field*/ + plaquette_energy = measure_plaquette( (const su3**) g_gauge_field); + + if (g_cart_id == 0) { + printf("# The computed plaquette value is %e.\n", plaquette_energy / (6.*VOLUME*g_nproc)); + fflush(stdout); + } + + if (use_stout_flag == 1){ + params_smear.rho = stout_rho; + params_smear.iterations = stout_no_iter; +/* if (stout_smear((su3_tuple*)(g_gauge_field[0]), ¶ms_smear, (su3_tuple*)(g_gauge_field[0])) != 0) */ +/* exit(1) ; */ + g_update_gauge_copy = 1; + plaquette_energy = measure_plaquette( (const su3**) g_gauge_field); + + if (g_cart_id == 0) { + printf("# The plaquette value after stouting is %e\n", plaquette_energy / (6.*VOLUME*g_nproc)); + fflush(stdout); + } + } + + /* if any measurements are defined in the input file, do them here */ + measurement * meas; + for(int imeas = 0; imeas < no_measurements; imeas++){ + meas = &measurement_list[imeas]; + if (g_proc_id == 0) { + fprintf(stdout, "#\n# Beginning online measurement.\n"); + } + meas->measurefunc(nstore, imeas, even_odd_flag); + } + + if (reweighting_flag == 1) { + reweighting_factor(reweighting_samples, nstore); + } + + /* Compute minimal eigenvalues, if wanted */ + if (compute_evs != 0) { + eigenvalues(&no_eigenvalues, 5000, eigenvalue_precision, + 0, compute_evs, nstore, even_odd_flag); + } + if (phmc_compute_evs != 0) { +#ifdef TM_USE_MPI + MPI_Finalize(); +#endif + return(0); + } + + /* Compute the mode number or topological susceptibility using spectral projectors, if wanted*/ + if(compute_modenumber != 0 || compute_topsus !=0){ + invert_compute_modenumber(); + } + + + + nstore += Nsave; + } + +#ifdef TM_USE_OMP + free_omp_accumulators(); +#endif + free_blocks(); + free_dfl_subspace(); + free_gauge_field(); + free_gauge_field_32(); + free_geometry_indices(); + free_spinor_field(); + free_spinor_field_32(); + free_moment_field(); + free_chi_spinor_field(); + free(filename); + free(input_filename); + free(SourceInfo.basename); + free(PropInfo.basename); +#ifdef QUDA + _endQuda(); +#endif +#ifdef TM_USE_MPI + MPI_Barrier(MPI_COMM_WORLD); + MPI_Finalize(); +#endif + return(0); +#ifdef _KOJAK_INST +#pragma pomp inst end(main) +#endif +} + +static void usage() +{ + fprintf(stdout, "Inversion for EO preconditioned Wilson twisted mass QCD\n"); + fprintf(stdout, "Version %s \n\n", PACKAGE_VERSION); + fprintf(stdout, "Please send bug reports to %s\n", PACKAGE_BUGREPORT); + fprintf(stdout, "Usage: invert [options]\n"); + fprintf(stdout, "Options: [-f input-filename]\n"); + fprintf(stdout, " [-o output-filename]\n"); + fprintf(stdout, " [-v] more verbosity\n"); + fprintf(stdout, " [-h|-? this help]\n"); + fprintf(stdout, " [-V] print version information and exit\n"); + exit(0); +} + +static void process_args(int argc, char *argv[], char ** input_filename, char ** filename) { + int c; + while ((c = getopt(argc, argv, "h?vVf:o:")) != -1) { + switch (c) { + case 'f': + *input_filename = calloc(200, sizeof(char)); + strncpy(*input_filename, optarg, 200); + break; + case 'o': + *filename = calloc(200, sizeof(char)); + strncpy(*filename, optarg, 200); + break; + case 'v': + verbose = 1; + break; + case 'V': + if(g_proc_id == 0) { + fprintf(stdout,"%s %s\n",PACKAGE_STRING,git_hash); + } + exit(0); + break; + case 'h': + case '?': + default: + if( g_proc_id == 0 ) { + usage(); + } + break; + } + } +} + +static void set_default_filenames(char ** input_filename, char ** filename) { + if( *input_filename == NULL ) { + *input_filename = calloc(13, sizeof(char)); + strcpy(*input_filename,"invert.input"); + } + + if( *filename == NULL ) { + *filename = calloc(7, sizeof(char)); + strcpy(*filename,"output"); + } +} + +static void invert_compute_modenumber() { + spinor * s_ = calloc(no_sources_z2*VOLUMEPLUSRAND+1, sizeof(spinor)); + spinor ** s = calloc(no_sources_z2, sizeof(spinor*)); + if(s_ == NULL) { + printf("Not enough memory in %s: %d",__FILE__,__LINE__); exit(42); + } + if(s == NULL) { + printf("Not enough memory in %s: %d",__FILE__,__LINE__); exit(42); + } + for(int i = 0; i < no_sources_z2; i++) { + s[i] = (spinor*)(((unsigned long int)(s_)+ALIGN_BASE)&~ALIGN_BASE)+i*VOLUMEPLUSRAND; + random_spinor_field_lexic(s[i], reproduce_randomnumber_flag,RN_Z2); + + if(g_proc_id == 0) { + printf("source %d \n", i); + } + + if(compute_modenumber != 0){ + mode_number(s[i], mstarsq); + } + + if(compute_topsus !=0) { + top_sus(s[i], mstarsq); + } + } + free(s); + free(s_); +} + diff --git a/monomial/cloverdetratio_rwdmonomial.c b/monomial/cloverdetratio_rwdmonomial.c new file mode 100644 index 000000000..a06143124 --- /dev/null +++ b/monomial/cloverdetratio_rwdmonomial.c @@ -0,0 +1,103 @@ +/*********************************************************************** + * + * Copyright (C) 2012 Carsten Urbach + * + * Adaption with a more efficient inversion by Georg Bergner 2016 + * + * 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 "su3.h" +#include "start.h" +#include "gettime.h" +#include "linalg_eo.h" +#include "deriv_Sb.h" +#include "gamma.h" +#include "operator/tm_operators.h" +#include "operator/Hopping_Matrix.h" +#include "solver/chrono_guess.h" +#include "solver/solver.h" +#include "solver/monomial_solve.h" +#include "read_input.h" +#include "operator/clovertm_operators.h" +#include "operator/clovertm_operators_32.h" +#include "operator/clover_leaf.h" +#include "monomial/monomial.h" +#include "boundary.h" +#include "cloverdetratio_rwdmonomial.h" + + +double cloverdetratio_rwaccd(const int id, hamiltonian_field_t * const hf) { + monomial * mnl = &monomial_list[id]; + int save_sloppy = g_sloppy_precision_flag; + double atime, etime; + atime = gettime(); + + + g_mu = mnl->mu2; + boundary(mnl->kappa2); + + init_sw_fields(); + sw_term( (const su3**) hf->gaugefield, mnl->kappa2, mnl->c_sw); + sw_invert(EE, mnl->mu2); + g_mu3 = 0.; + + mnl->Qsq(mnl->w_fields[1], mnl->pf); + assign(mnl->w_fields[0],mnl->pf,VOLUME/2); + + g_mu3 = 0.; + g_mu = mnl->mu; + boundary(mnl->kappa); + sw_term( (const su3**) hf->gaugefield, mnl->kappa, mnl->c_sw); + sw_invert(EE, mnl->mu); + + /*chrono_guess(mnl->pf, mnl->w_fields[1], mnl->csg_field, mnl->csg_index_array, + mnl->csg_N, mnl->csg_n, VOLUME/2, &Qtm_plus_psi);*/ + g_sloppy_precision_flag = 0; + mnl->iter0 += solve_degenerate(mnl->w_fields[0], mnl->w_fields[1], mnl->solver_params, mnl->maxiter, mnl->accprec, + g_relative_precision_flag, VOLUME/2, mnl->Qsq, mnl->solver); + + + g_sloppy_precision_flag = save_sloppy; + + /* Compute the energy contr. from second field */ + mnl->energy1 = scalar_prod_r(mnl->pf,mnl->w_fields[0], VOLUME/2, 1); + + g_mu = g_mu1; + g_mu3 = 0.; + boundary(g_kappa); + etime = gettime(); + if(g_proc_id == 0) { + if(g_debug_level > 1) { + printf("# Time for %s monomial rwacc step: %e s\n", mnl->name, etime-atime); + } + if(g_debug_level > 3) { + printf("called cloverdetratio_rwacc for id %d dH = %1.10e\n", + id, mnl->energy1 - mnl->energy0); + printf("Parameters: kappa=%e, kappa2=%e; mu=%e, mu2=%e, vprod=%e\n",mnl->kappa,mnl->kappa2,mnl->mu,mnl->mu2,mnl->energy1); + } + } + return(mnl->energy1 - mnl->energy0); +} diff --git a/monomial/cloverdetratio_rwdmonomial.h b/monomial/cloverdetratio_rwdmonomial.h new file mode 100644 index 000000000..ad13814f2 --- /dev/null +++ b/monomial/cloverdetratio_rwdmonomial.h @@ -0,0 +1,31 @@ +/*********************************************************************** + * + * Copyright (C) 2012 Carsten Urbach + * + * Adaption with a more efficient inversion by Georg Bergner 2016 + * Note that the reweighting measurement is much more efficient. + * + * 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 _CLOVERDETRATIO_RWDMONOMIAL_H +#define _CLOVERDETRATIO_RWDMONOMIAL_H + +#include "hamiltonian_field.h" + +double cloverdetratio_rwaccd(const int no, hamiltonian_field_t * const hf); + +#endif From af496d8582b8cbbfc1a0eb9c63b40aa189091919 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Fri, 19 Aug 2016 14:24:28 +0200 Subject: [PATCH 07/22] added new measurements of reweighting factors and changed concept for measurements --- .gitignore | 1 + DDalphaAMG_interface.c | 117 +++++++++-------------------------------- Makefile.in | 4 +- doc/main.tex | 18 +++---- invert.c | 2 +- meas/Makefile.in | 1 + meas/measurements.c | 17 +++++- meas/measurements.h | 27 ++++++++-- monomial/Makefile.in | 1 + monomial/monomial.c | 11 ++++ monomial/monomial.h | 2 + read_input.l | 74 ++++++++++++++++++++++++-- 12 files changed, 161 insertions(+), 114 deletions(-) diff --git a/.gitignore b/.gitignore index 600fe70fb..96ed89a9c 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ config.status hmc_tm invert offline_measurement +measure lib/ benchmark diff --git a/DDalphaAMG_interface.c b/DDalphaAMG_interface.c index 52184acb0..c3cb3ea72 100644 --- a/DDalphaAMG_interface.c +++ b/DDalphaAMG_interface.c @@ -20,66 +20,7 @@ * Interface for DDalphaAMG * *******************************************************************************/ - #include "DDalphaAMG_interface.h" - -#ifndef DDalphaAMG - -int mg_setup_iter; -int mg_coarse_setup_iter; -int mg_update_setup_iter; -int mg_omp_num_threads; -int mg_Nvec; -int mg_lvl; -int mg_blk[4]; -int mg_mixed_prec; -int mg_setup_mu_set; -double mg_setup_mu; -double mg_cmu_factor; -double mg_dtau_update; -double mg_rho_update; - -void MG_init(void) { - printf("ERROR: MG_init called but DDalphaAMG library not included.\n"); - exit(1); -} - -void MG_update_gauge(double step) { - printf("ERROR: MG_update_gauge called but DDalphaAMG library not included.\n"); - exit(1); -} - -void MG_update_mu(double mu_tmLQCD, double odd_tmLQCD) { - printf("ERROR: MG_update_mu called but DDalphaAMG library not included.\n"); - exit(1); -} - -void MG_reset(void) { - printf("ERROR: MG_reset called but DDalphaAMG library not included.\n"); - exit(1); -} - -void MG_finalize(void) { - printf("ERROR: MG_finalize called but DDalphaAMG library not included.\n"); - exit(1); -} - -int MG_solver(spinor * const phi_new, spinor * const phi_old, - const double precision, const int max_iter,const int rel_prec, - const int N, su3 **gf, matrix_mult f) { - printf("ERROR: MG_solver called but DDalphaAMG library not included.\n"); - exit(1); -} - -int MG_solver_eo(spinor * const Even_new, spinor * const Odd_new, - spinor * const Even, spinor * const Odd, - const double precision, const int max_iter, const int rel_prec, - const int N, su3 **gf, matrix_mult_full f_full) { - printf("ERROR: MG_solver_eo called but DDalphaAMG library not included.\n"); - exit(1); -} - -#else #include #include #include @@ -97,7 +38,6 @@ int MG_solver_eo(spinor * const Even_new, spinor * const Odd_new, #include "operator/clovertm_operators.h" //Enable to test the solution. It cost an application more of the operator. -//TODO: test all the operators interfaced and then undefine this flag. #define MGTEST DDalphaAMG_init mg_init; @@ -114,9 +54,7 @@ int mg_omp_num_threads=0; int mg_Nvec=24; int mg_lvl=3; int mg_blk[4] = {0, 0, 0, 0}; -int mg_mixed_prec=0; -int mg_setup_mu_set = 0; //flag that enable the use of mg_setup_mu in the setup phase -double mg_setup_mu = 0.; +double mg_setup_mu = 0./0.; //setting to NaN double mg_cmu_factor = 1.0; double mg_dtau_update = 0.0; double mg_rho_update = -1.0; @@ -192,7 +130,7 @@ static int MG_check(spinor * const phi_new, spinor * const phi_old, const int N, return 0; } - if (g_debug_level > 0 && g_proc_id == 0) + if (verbose && g_proc_id == 0) printf("MGTEST: || s - f_{tmLQC} * f_{DDalphaAMG}^{-1} * s || / ||s|| = %e / %e = %e \n", differ[0],differ[1],differ[0]/differ[1]); return 1; @@ -202,7 +140,7 @@ static int MG_check(spinor * const phi_new, spinor * const phi_old, const int N, static int MG_pre_solve( su3 **gf ) { - double dtau = fabs(mg_tau-gauge_tau); + double dtau= mg_tau-gauge_tau; // Checking if: // mg_update_setup < mg_update_setup_iter : maybe you want to do more iteration at this run // mg_dtau_update < dtau : regular condition for update of setup @@ -210,11 +148,11 @@ static int MG_pre_solve( su3 **gf ) // mg_dtau_update == 0.0 : updating at every change of configuration -> valid as well if configuration changed outside the HMC // mg_rho_update < 0.0 : parameter ignore // mg_rho_update == rho : updating only if this condition and the others are satisfied - if ( mg_do_setup == 0 && mg_update_setup < mg_update_setup_iter && ( mg_dtau_update < dtau+1e-6 || (mg_dtau_update==0.0 && mg_update_gauge==1) || - (mg_rho_update >= 0.0 && mg_rho_update == g_mu3) )) + if ( mg_do_setup == 0 && mg_update_setup < mg_update_setup_iter && ( mg_dtau_update < dtau || mg_dtau_update < -dtau || (mg_dtau_update==0.0 && mg_update_gauge==1)) && + (mg_rho_update < 0.0 || mg_rho_update == g_mu3)) mg_update_setup = mg_update_setup_iter; - if(g_debug_level > 0 && g_proc_id == 0) + if(verbose && g_proc_id == 0) printf("Tau has been increased since last MG setup update of %e\n", dtau); if (mg_initialized==0) { @@ -235,7 +173,7 @@ static int MG_pre_solve( su3 **gf ) } if (mg_do_setup==1) { - if( mg_setup_mu_set ) { + if( mg_setup_mu == mg_setup_mu ) { //is set as a NaN at the beginning, so true only if used if (g_proc_id == 0) printf("DDalphaAMG using mu=%f during setup\n", mg_setup_mu); MG_update_mu(mg_setup_mu, 0); @@ -254,7 +192,7 @@ static int MG_pre_solve( su3 **gf ) } if (mg_update_setup>0) { - if( mg_setup_mu_set ) { + if( mg_setup_mu == mg_setup_mu ) { //is set as a NaN at the beginning, so true only if used if (g_proc_id == 0) printf("DDalphaAMG using mu=%f during setup\n", mg_setup_mu); MG_update_mu(mg_setup_mu, 0); @@ -356,9 +294,9 @@ static int MG_solve(spinor * const phi_new, spinor * const phi_old, const double f == Qsw_psi || // Gamma5 - Schur complement with mu=0 on odd sites f == Q_plus_psi || // Gamma5 - Full operator with plus mu f == Q_minus_psi ) { // Gamma5 - Full operator with minus mu - mul_gamma5(old, VOLUME); + // mul_gamma5(phi_old, N); // error in the original version DDalphaAMG_solve( new, old, precision, &mg_status ); - mul_gamma5(old, VOLUME); + mul_gamma5(phi_old, N); } else if ( f == Qtm_pm_psi || // Schur complement squared f == Qsw_pm_psi ) { // Schur complement squared @@ -403,20 +341,20 @@ void MG_init() mg_init.Cart_rank=Cart_rank; mg_init.Cart_coords=Cart_coords; - mg_init.global_lattice[0]=T*g_nproc_t; - mg_init.global_lattice[1]=LZ*g_nproc_z; - mg_init.global_lattice[2]=LY*g_nproc_y; - mg_init.global_lattice[3]=LX*g_nproc_x; + mg_init.global_lattice[0]=T*N_PROC_T; + mg_init.global_lattice[1]=LZ*N_PROC_Z; + mg_init.global_lattice[2]=LY*N_PROC_Y; + mg_init.global_lattice[3]=LX*N_PROC_X; - mg_init.procs[0]=g_nproc_t; - mg_init.procs[1]=g_nproc_z; - mg_init.procs[2]=g_nproc_y; - mg_init.procs[3]=g_nproc_x; + mg_init.procs[0]=N_PROC_T; + mg_init.procs[1]=N_PROC_Z; + mg_init.procs[2]=N_PROC_Y; + mg_init.procs[3]=N_PROC_X; for(int i = 0; i<4; i++) if(mg_blk[i]==0) - mg_blk[i]=(((L/g_nproc_x)%2==0)?(((L/g_nproc_x)%4==0)?4:2): - (((L/g_nproc_x)%3==0)?3:1)); + mg_blk[i]=(((L/N_PROC_X)%2==0)?(((L/N_PROC_X)%4==0)?4:2): + (((L/N_PROC_X)%3==0)?3:1)); mg_init.block_lattice[0]=mg_blk[0]; mg_init.block_lattice[1]=mg_blk[1]; @@ -477,9 +415,9 @@ void MG_init() * Printing level: * -1: silent (errors or warnings) * 0: minimal //default - * 1: g_debug_level > 0 + * 1: verbose */ - if(g_debug_level > 0) { + if(verbose) { mg_params.print=1; } else @@ -494,10 +432,7 @@ void MG_init() mg_params.setup_iterations[1]=mg_coarse_setup_iter; // with mixed_precision = 2 the library adapt the solving precision according to the vector components - if(mg_mixed_prec) - mg_params.mixed_precision = 2; - else - mg_params.mixed_precision = 1; + mg_params.mixed_precision = 2; DDalphaAMG_update_parameters(&mg_params, &mg_status); @@ -519,7 +454,7 @@ void MG_update_mu(double mu_tmLQCD, double odd_tmLQCD) if (mu != mg_params.mu || odd_shift != mg_params.mu_odd_shift || mg_params.mu_even_shift != 0.0 ) { //Taking advantage of this function for updating printing in HMC - if(g_debug_level > 0) + if(verbose) mg_params.print=1; else mg_params.print=0; @@ -584,7 +519,7 @@ int MG_solver(spinor * const phi_new, spinor * const phi_old, DDalphaAMG_finalize(); MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); - exit(1); + exit(0); } // mg_status should have been used last time for the inversion. return mg_status.iter_count; @@ -622,5 +557,3 @@ int MG_solver_eo(spinor * const Even_new, spinor * const Odd_new, return iter_count; } - -#endif diff --git a/Makefile.in b/Makefile.in index 6c91cbf50..fc8181c89 100644 --- a/Makefile.in +++ b/Makefile.in @@ -67,7 +67,7 @@ NOOPTMOD = test/check_xchange test/check_geometry PROGRAMS = hmc_tm benchmark invert gen_sources \ check_locallity test_lemon hopping_test LapH_ev \ - offline_measurement + offline_measurement measure ALLOBJ = ${MODULES} ${PROGRAMS} ${SMODULES} SUBDIRS = ${USESUBDIRS} @@ -76,7 +76,7 @@ SUBDIRS = ${USESUBDIRS} .SUFFIXES: # need to build modules before subdirs! -all: Makefile dep $(SUBDIRS) hmc_tm invert benchmark offline_measurement +all: Makefile dep $(SUBDIRS) hmc_tm invert benchmark offline_measurement measure $(SUBDIRS): $(MAKE) --directory=$@ diff --git a/doc/main.tex b/doc/main.tex index 6c10a8f58..40199f486 100644 --- a/doc/main.tex +++ b/doc/main.tex @@ -61,15 +61,15 @@ \section{Implementation} \myinput{components} \myinput{test} -%\myinput{eo_pre} -%\myinput{martins-trick} -%\myinput{deflation} -%\myinput{c-code} -%\myinput{integrationschemes} - -%\myinput{parallel} -%\myinput{operator} -%\myinput{online} +\myinput{eo_pre} +\myinput{martins-trick} +\myinput{deflation} +\myinput{c-code} +\myinput{integrationschemes} + +\myinput{parallel} +\myinput{operator} +\myinput{online} \section{File Formats and IO} \myinput{prop_format.tex} diff --git a/invert.c b/invert.c index 847e84a17..06f1af147 100644 --- a/invert.c +++ b/invert.c @@ -108,7 +108,7 @@ int main(int argc, char *argv[]) int j, i, ix = 0, isample = 0, op_id = 0; char datafilename[206]; char parameterfilename[206]; - char conf_filename[50]; + char conf_filename[300]; char * input_filename = NULL; char * filename = NULL; double plaquette_energy; diff --git a/meas/Makefile.in b/meas/Makefile.in index f67214295..6ed9ca8d5 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 \ energy_density gradient_flow diff --git a/meas/measurements.c b/meas/measurements.c index 338ea7fea..b2e396bf0 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,7 @@ 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; no_measurements++; return(no_measurements); } @@ -80,6 +84,11 @@ 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].id = i; } return(0); @@ -88,7 +97,13 @@ return(0); void free_measurements(){ - + int i; + for(i = 0; i < no_measurements; i++) { + if(measurement_list[i].parameter){ + free(measurement_list[i].parameter); + measurement_list[i].parameter=NULL; + } + } return; } diff --git a/meas/measurements.h b/meas/measurements.h index a894137e3..3f979fef9 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 @@ -30,32 +35,44 @@ enum MEAS_TYPE { PIONNORM, POLYAKOV, ORIENTED_PLAQUETTES, - GRADIENT_FLOW + 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; + // random seed unsigned int seed; /* how it's usually called */ char name[100]; + + /* for maximal iterations in inversions for correlators */ + int max_iter; + + /* maximum number of slice, the source can be put if the correlator is measured in T(Z)-direction this will be set to T(LZ) by init_measurements */ int max_source_slice; + + + void* parameter; + + /* frequency of the measurement */ + int freq; /* functions for the measurement */ void (*measurefunc) (const int traj, const int id, const int ieo); diff --git a/monomial/Makefile.in b/monomial/Makefile.in index e73a9ede2..6e42ec316 100644 --- a/monomial/Makefile.in +++ b/monomial/Makefile.in @@ -33,6 +33,7 @@ LIBRARIES = libmonomial libmonomial_TARGETS = nddetratio_monomial monomial det_monomial detratio_monomial \ gauge_monomial ndpoly_monomial clover_trlog_monomial cloverdet_monomial cloverdetratio_monomial \ cloverdetratio_rwmonomial \ + cloverdetratio_rwdmonomial \ clovernd_trlog_monomial poly_monomial cloverndpoly_monomial moment_energy \ ndrat_monomial ndratcor_monomial rat_monomial ratcor_monomial monitor_forces diff --git a/monomial/monomial.c b/monomial/monomial.c index 3b9d510c4..11200cea5 100644 --- a/monomial/monomial.c +++ b/monomial/monomial.c @@ -251,6 +251,17 @@ int init_monomials(const int V, const int even_odd_flag) { printf("# Initialised monomial of type CLOVERDETRATIORW, no_monomials= %d, currently only available for reweighting!\n", no_monomials); } } + else if(monomial_list[i].type == CLOVERDETRATIORWD) { + monomial_list[i].accfunction = &cloverdetratio_rwaccd; + monomial_list[i].even_odd_flag = 1; + monomial_list[i].Qsq = &Qsw_pm_psi; + monomial_list[i].Qp = &Qsw_plus_psi; + monomial_list[i].Qm = &Qsw_minus_psi; + init_swpm(VOLUME); + if(g_proc_id == 0 && g_debug_level > 1) { + printf("# Initialised monomial of type CLOVERDETRATIORWD, no_monomials= %d, currently only available for reweighting!\n", no_monomials); + } + } else if(monomial_list[i].type == DETRATIO) { monomial_list[i].hbfunction = &detratio_heatbath; monomial_list[i].accfunction = &detratio_acc; diff --git a/monomial/monomial.h b/monomial/monomial.h index c0e494b50..9da893f11 100644 --- a/monomial/monomial.h +++ b/monomial/monomial.h @@ -49,6 +49,7 @@ #define CLOVERRAT 19 #define CLOVERRATCOR 20 #define CLOVERDETRATIORW 21 +#define CLOVERDETRATIORWD 22 #define max_no_monomials 30 @@ -136,6 +137,7 @@ typedef struct { #include "monomial/cloverdet_monomial.h" #include "monomial/cloverdetratio_monomial.h" #include "monomial/cloverdetratio_rwmonomial.h" +#include "monomial/cloverdetratio_rwdmonomial.h" #include "monomial/cloverndpoly_monomial.h" #include "monomial/ndrat_monomial.h" #include "monomial/rat_monomial.h" diff --git a/read_input.l b/read_input.l index e96ce991f..d3caf64b8 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" @@ -106,7 +107,7 @@ static inline void rmQuotes(char *str){ char * type; int verbose = 0; - int myverbose = 0; + int myverbose = 1; int startoption; int Ntherm; int Nmeas; @@ -265,6 +266,7 @@ static inline void rmQuotes(char *str){ %x NOSOURCESZ2 %x INITMEASUREMENT %x ONLINEMEAS +%x REWEIGHTINGMEAS %x PIONNORMMEAS %x PLOOP %x ORIENTEDPLAQUETTESMEAS @@ -1252,6 +1254,11 @@ static inline void rmQuotes(char *str){ mnl->type = CLOVERDETRATIORW; strcpy((*mnl).name, "CLOVERDETRATIORW"); } + else if(strcmp(yytext, "CLOVERDETRATIORWD")==0) { + mnl->type = CLOVERDETRATIORWD; + strcpy((*mnl).name, "CLOVERDETRATIORWD"); + } + else if(strcmp(yytext, "DETRATIO")==0) { mnl->type = DETRATIO; strcpy((*mnl).name, "DETRATIO"); @@ -1355,6 +1362,7 @@ static inline void rmQuotes(char *str){ else if(mnl->type == CLOVERDET) BEGIN(CLDETMONOMIAL); else if(mnl->type == CLOVERDETRATIO) BEGIN(CLDETRATMONOMIAL); else if(mnl->type == CLOVERDETRATIORW) BEGIN(CLDETRATRWMONOMIAL); + else if(mnl->type == CLOVERDETRATIORWD) BEGIN(CLDETRATRWMONOMIAL); else BEGIN(DETMONOMIAL); } @@ -1887,6 +1895,7 @@ static inline void rmQuotes(char *str){ 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; @@ -1898,6 +1907,11 @@ static inline void rmQuotes(char *str){ 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"); @@ -1927,13 +1941,14 @@ static inline void rmQuotes(char *str){ 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); @@ -1945,7 +1960,7 @@ static inline void rmQuotes(char *str){ } } -{ +{ {SPC}*MaxSolverIterations{EQL}{DIGIT}+ { sscanf(yytext, " %[a-zA-Z] = %d", name, &a); meas->max_iter = a; @@ -1953,6 +1968,57 @@ static inline void rmQuotes(char *str){ } } +{ + {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}*Direction{EQL}[03] { sscanf(yytext, " %[a-zA-Z] = %d", name, &a); @@ -2484,7 +2550,7 @@ static inline void rmQuotes(char *str){ BEGIN(comment_caller); } -{SPC}*\n { +{SPC}*\n { line_of_file++; } <*>{SPC}*\n { From dec5d2dd4179d517431ea63c47f7304db28d3a38 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Tue, 13 Sep 2016 11:01:27 +0200 Subject: [PATCH 08/22] updated --- meas/reweightingmeas.c | 370 +++++++++++++++++++++++++++++++++++++---- meas/reweightingmeas.h | 18 +- measure.c | 6 +- read_input.l | 36 ++++ 4 files changed, 392 insertions(+), 38 deletions(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index 13c1605e1..7c146f832 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -45,6 +45,13 @@ #include "linalg/scalar_prod_i.h" #include "linalg/diff.h" #include "linalg/assign.h" +#include "linalg/mul_r.h" +#include "linalg/assign_mul_add_mul_r.h" +#include "linalg/mul_diff_mul_r.h" +#include "linalg/assign_mul_add_mul_add_mul_r.h" +#include "linalg/assign_add_mul_add_mul_r.h" +#include "linalg/assign_add_mul_r.h" +#include "linalg/set_even_to_zero.h" #include "../read_input.h" #include "reweightingmeas.h" #include "../operator/Hopping_Matrix.h" @@ -55,6 +62,7 @@ #include "../operator/clover_leaf.h" #include "../DDalphaAMG_interface.h" #include "../boundary.h" +#include "../global.h" /*#define CHECK_OPERATOR*/ @@ -248,11 +256,293 @@ static int invert_operator_Q(spinor * const P, spinor * const Q, 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); + (*rcurrent) = rinitial + + (thisstep + 1) * (rfinal - rinitial) / ((double) numsteps); } -static double log_determinant_estimate(const int operatorid, const int chebmax, const int estimators, const double spectmin, const double spectmax){ +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); +} +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; +} + +//#define TRIVIAL_TEST +static double log_determinant_estimate(const int operatorid, const int chebmax, + const 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) { + 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; + int k, l, n; + double x, y, ldet, prodre; + FILE * ofs; + spinor * vs1; + spinor * vs2; + spinor * u; + spinor * v0; + spinor * v1; + spinor * v2; + spinor * vt0; + spinor * vt1; + spinor * vt2; + spinor * tmp; + operator * optr; + char* filename; + char buf[100]; + n = VOLUME; + + filename = buf; + sprintf(filename, "%s%.6d", "reweightingmeas_cheb.", traj); + + vs1 = g_spinor_field[0]; + vs2 = g_spinor_field[1]; + u = g_spinor_field[2]; + v0 = g_spinor_field[4]; + v1 = g_spinor_field[6]; + v2 = g_spinor_field[8]; + vt0 = g_spinor_field[10]; + vt1 = g_spinor_field[12]; + vt2 = g_spinor_field[14]; + + optr = &operator_list[operatorid]; + if (is_schur_complement(optr->applyQsq)) { + n = VOLUME / 2; + vs1 = g_spinor_field[0]; + vs2 = g_spinor_field[1]; + u = g_spinor_field[3]; + v0 = g_spinor_field[4]; + v1 = g_spinor_field[5]; + v2 = g_spinor_field[6]; + vt0 = g_spinor_field[7]; + vt1 = g_spinor_field[8]; + vt2 = g_spinor_field[9]; + if (DUM_MATRIX < 10) { + if (g_proc_id == 0) { + fprintf(stderr, "Not enough spinor fields %d < 10 \n\n", + DUM_MATRIX); + } + return 0.0; + } + + } else { + if (DUM_MATRIX < 16) { + if (g_proc_id == 0) { + fprintf(stderr, "Not enough spinor fields %d < 16 \n\n", + DUM_MATRIX); + } + return 0.0; + } + } + + coeff = malloc(chebmax * sizeof(double)); + chebyshev_coeff(chebmax, coeff, am, bm); + if (g_proc_id == 0 && g_debug_level > 3) { + ofs = fopen("polynomialapproxtest.txt", "a"); + 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); + fprintf(ofs, "%d %g %g %g %d %g %g\n", k, x, y, fabs(y - log(x)), + chebmax, minev, maxev); + } + fclose(ofs); + } + + ldet = 0; + if (chebmax > 0) { + for (k = 0; k < estimators; k++) { + /* + * Generate estimator (may be half of it is never used) + */ + random_spinor_field_eo(vs1, reproduce_randomnumber_flag, RN_Z2); + random_spinor_field_eo(vs2, reproduce_randomnumber_flag, RN_Z2); + + assign(v0, vs1, n); + assign(vt0, vs1, n); + +#ifdef TRIVIAL_TEST + mul_r(v1,kappa1,vs1,n); +#else + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); + optr->applyQsq(v1, vs1); +#endif + /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ + assign_mul_add_mul_r(v1, vs1, 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, vs1); +#endif + /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ + assign_mul_add_mul_r(vt1, vs1, a, b, n); + + /* Makes (*R)=c1*(*S)-c2*(*U) , c1 and c2 are complex constants */ + mul_diff_mul_r(u, vt1, v1, coeff[1], coeff[1], n); + +#if 0 + for (l = 1; l + 1 < chebmax; l++) { +#ifndef TRIVIAL_TEST + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); + + optr->applyQsq(v2, v1); +#else + mul_r(v2,kappa1,v1,n); +#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; + +#ifndef TRIVIAL_TEST + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); + + optr->applyQsq(vt2, vt1); +#else + mul_r(vt2,kappa2,vt1,n); +#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; + + /* (*R) = (*R) + c1*(*S) + c2*(*U) */ + assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], + -coeff[l + 1], n); + + } + +#endif + +#ifndef TRIVIAL_TEST + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); +#endif + + for (l = 1; l + 1 < chebmax; 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; + /* (*P) = (*P) + c(*Q) c is a real constant */ + assign_add_mul_r(u, v1, -coeff[l + 1], n); + } +#ifndef TRIVIAL_TEST + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); +#endif + + for (l = 1; l + 1 < chebmax; 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; + + /* (*P) = (*P) + c(*Q) c is a real constant */ + assign_add_mul_r(u, vt1, coeff[l + 1], n); + + } + + prodre = scalar_prod_r(vs1, u, n, 1); + ldet += prodre / ((double) estimators); + if (g_proc_id == 0 && g_debug_level > 3) { + ofs = fopen("estimators.txt", "a"); + fprintf(ofs, "# Test of stochastic estimation\n"); + fprintf(ofs, "%d %g %g %g %g %g %d %d %g %g %g\n", k, kappa1, + kappa2, kappa2Mu1, kappa2Mu2, prodre, estimators, + chebmax, minev, maxev, ldet); + fclose(ofs); + } + + if (g_proc_id == 0) { + ofs = fopen(filename, "a"); + fprintf(ofs, "%d %g %g %g %g %d %g %g ", traj, kappa1, kappa2, + kappa2Mu1, kappa2Mu2, chebmax, minev, maxev); + fprintf(ofs, " %g %g\n", prodre + shift, prodre); + fclose(ofs); + } + + } /* estimator iteration*/ + } /* chebmax>0*/ + free(coeff); + return (ldet); } void reweighting_measurement(const int traj, const int id, const int ieo) { @@ -265,7 +555,7 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { char *filename_full; char buf[100]; char buf_full[100]; - double square1, square2, prodre, prodim, prodreg5, prodimg5; + 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; @@ -336,6 +626,7 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { */ k2muinitial = param->k2mu0; kappainitial = param->kappa0; + cswinitial=0; kapparew = 1; if (kappainitial == kappafinal) { kapparew = 0; @@ -366,47 +657,58 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { /* 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 (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->rmu0 != 0) { + rmuinitial = param->rmu0; + k2muinitial = 2.0 * kappainitial * rmuinitial; } - if(param->rmu!=0){ - rmufinal=param->rmu; - k2mufinal = 2.0*kappafinal*rmufinal; + 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)){ + if (murew && (g_proc_id == 0)) { printf("Mu reweighting chosen: "); - printf("mu=%e to mu=%e.\n", rmuinitial, - rmufinal); + printf("mu=%e to mu=%e.\n", rmuinitial, rmufinal); } - if(kapparew && (g_proc_id == 0)){ + if (kapparew && (g_proc_id == 0)) { printf("Kappa reweighting chosen: "); - printf("kappa=%e to kappa=%e\n", kappainitial, - kappafinal); + 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"); - } - return; + 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 (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_cheb) { + 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); + if (param->only_cheb) { + return; + } + } kappa0 = kappa = kappainitial; k2mu0 = k2mu = k2muinitial; @@ -424,7 +726,7 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } if (murew) { /* use quadratic interpolation in the case of mu*/ - rmu0=rmu; + rmu0 = rmu; tmp1 = rmuinitial * rmuinitial; tmp2 = rmufinal * rmufinal; tmp3 = rmu * rmu; @@ -437,6 +739,10 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { 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, @@ -542,8 +848,6 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { square2 = square_norm(optr->prop0, VOLUME / 2, 1); - prodre = get_sw_reweighting(k2mu0, k2mu, kappa0, kappa, csw0, - csw); if (g_mpi_time_rank == 0 && g_proc_coords[0] == 0) { ofs = fopen(filename, "a"); @@ -556,8 +860,8 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", k2mu0, k2mu, kappa0, kappa, csw0, csw, rmu, rmu0); fprintf(ofs_full, "%.17g %.17g %.17g\n", square1, square2, - prodre); - fprintf(ofs, "%.17g\n", square1 - square2 + prodre); + cswpart); + fprintf(ofs, "%.17g\n", square1 - square2 + cswpart); fclose(ofs); fclose(ofs_full); } @@ -567,6 +871,8 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { }/* loop over estimators */ } /* loop over interpolation steps*/ + + etime = gettime(); if (g_proc_id == 0 && g_debug_level > 0) { diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h index d973292c0..e46e8e820 100644 --- a/meas/reweightingmeas.h +++ b/meas/reweightingmeas.h @@ -28,9 +28,15 @@ typedef struct{ int use_evenodd; double k2mu0; double kappa0; - int interpolationsteps; double rmu0; double rmu; + double minev; + double maxev; + int interpolationsteps; + int estimatorscheb; + int cheborder; + int use_cheb; + int only_cheb; } reweighting_parameter; @@ -39,14 +45,20 @@ inline void initialize_reweighting_parameter(void** parameter){ if(!(*parameter)){ (*parameter)=malloc(sizeof(reweighting_parameter)); param=(reweighting_parameter*)(*parameter); - param->reweighting_number_sources=0; param->reweighting_operator=0; + param->reweighting_number_sources=0; param->use_evenodd=0; param->k2mu0=0.0; + param->kappa0=0.0; param->rmu0=0.0; param->rmu=0.0; - param->kappa0=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; } } diff --git a/measure.c b/measure.c index aab5fce79..aa8e1dfa2 100644 --- a/measure.c +++ b/measure.c @@ -106,7 +106,7 @@ static void invert_compute_modenumber(); int main(int argc, char *argv[]) { FILE *parameterfile = NULL; - int j, i, ix = 0, isample = 0, op_id = 0; + int j, i; char datafilename[206]; char parameterfilename[206]; char conf_filename[300]; @@ -125,8 +125,8 @@ int main(int argc, char *argv[]) #endif DUM_DERI = 8; - DUM_MATRIX = DUM_DERI + 5; - NO_OF_SPINORFIELDS = DUM_MATRIX + 4; + DUM_MATRIX = DUM_DERI + 5; /* 5 fields for doing the inversions (might be used by other opetations if no inverter used*/ + NO_OF_SPINORFIELDS = DUM_MATRIX + 4; /* Don't access these fields if you apply multiplications!*/ //4 extra fields (corresponding to DUM_MATRIX+0..5) for deg. and ND matrix mult. NO_OF_SPINORFIELDS_32 = 6; diff --git a/read_input.l b/read_input.l index d3caf64b8..04faa0aa1 100644 --- a/read_input.l +++ b/read_input.l @@ -2017,6 +2017,42 @@ static inline void rmQuotes(char *str){ ((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}*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); + } } { From f43746fc5cd104ec53133ae7f880d49a4f22bff9 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Tue, 13 Sep 2016 16:46:51 +0200 Subject: [PATCH 09/22] added eigevalue estimation and truncated polynomial factorization --- meas/measurements.c | 12 +- meas/measurements.h | 2 + meas/reweightingmeas.c | 651 ++++++++++++++++++++++++++++++++--------- meas/reweightingmeas.h | 45 +-- read_input.l | 6 + solver/jdher.c | 2 +- 6 files changed, 554 insertions(+), 164 deletions(-) diff --git a/meas/measurements.c b/meas/measurements.c index b2e396bf0..86c0e86b4 100644 --- a/meas/measurements.c +++ b/meas/measurements.c @@ -53,6 +53,7 @@ int add_measurement(const enum MEAS_TYPE meas_type) { 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); } @@ -87,6 +88,7 @@ int init_measurements(){ 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; @@ -99,9 +101,10 @@ return(0); void free_measurements(){ int i; for(i = 0; i < no_measurements; i++) { - if(measurement_list[i].parameter){ + if (measurement_list[i].parameter) { + measurement_list[i].destructor(measurement_list[i].parameter); free(measurement_list[i].parameter); - measurement_list[i].parameter=NULL; + measurement_list[i].parameter = NULL; } } return; @@ -117,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 3f979fef9..1a3f66823 100644 --- a/meas/measurements.h +++ b/meas/measurements.h @@ -76,6 +76,7 @@ typedef struct { /* functions for the measurement */ void (*measurefunc) (const int traj, const int id, const int ieo); + void (*destructor)(void* param); } measurement; @@ -91,5 +92,6 @@ int init_measurements(); void free_measurements(); 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 index 7c146f832..3b9e03dc7 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -63,22 +63,10 @@ #include "../DDalphaAMG_interface.h" #include "../boundary.h" #include "../global.h" +#include "solver/jdher.h" /*#define CHECK_OPERATOR*/ -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_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 @@ -97,6 +85,21 @@ static int is_schur_complement(const matrix_mult f) { return 0; } +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 @@ -126,6 +129,153 @@ static void update_global_parameters(const int op_id) { }/*clover leave update*/ } +static void estimate_eigenvalues(const int operatorid, const int identifier) { +#ifdef HAVE_LAPACK + vector_list min_ev; + vector_list max_ev; + spinor * eigenvectors_ = NULL; + char filename[200]; + FILE * ofs; + double atime, etime; + int max_iterations=5000; + double prec = 1.e-5; + int maxvectors; + /********************** + * For Jacobi-Davidson + **********************/ + int verbosity = g_debug_level, converged = 0, blocksize = 1, blockwise = 0; + int solver_it_max = 50, j_max, j_min, ii; + /*int it_max = 10000;*/ + /* _Complex double *eigv_ = NULL, *eigv; */ + double decay_min = 1.7, decay_max = 1.5, + threshold_min = 1.e-3, threshold_max = 5.e-2; + double ev_max, ev_min; + + /* static int v0dim = 0; */ + int v0dim = 0; + int N = (VOLUME)/2, N2 = (VOLUMEPLUSRAND)/2; + operator * optr; + + /********************** + * General variables + **********************/ + int returncode=0; + int returncode2=0; + + + min_ev.s=2; + min_ev.el=malloc(min_ev.s*sizeof(double)); + max_ev.s=2; + max_ev.el=malloc(max_ev.s*sizeof(double)); + + optr = &operator_list[operatorid]; + + + if(!is_schur_complement(optr->applyQsq)) { + N = VOLUME; + N2 = VOLUMEPLUSRAND; + } + + evlength = N2; + if(g_proc_id == g_stdio_proc && g_debug_level >0) { + printf("Number of eigenvalues to compute = %d %d\n",min_ev.s,max_ev.s); + printf("Using Jacobi-Davidson method! \n"); + } + + + if(max_ev.s < 8){ + j_max = 15; + j_min = 8; + } + else{ + j_max = 2*max_ev.s; + j_min = max_ev.s; + } + + maxvectors=min_ev.s>max_ev.s ? min_ev.s:max_ev.s; + +#if (defined SSE || defined SSE2 || defined SSE3) + eigenvectors_ = calloc(N2*maxvectors+1, sizeof(spinor)); + eigenvectors = (spinor *)(((unsigned long int)(eigenvectors_)+ALIGN_BASE)&~ALIGN_BASE); +#else + eigenvectors_= calloc(N2*maxvectors, sizeof(spinor)); + eigenvectors = eigenvectors_; +#endif + + atime = gettime(); + + update_global_parameters(operatorid); + /* (re-) compute minimal eigenvalues */ + converged = 0; + solver_it_max = 200; + + + jdher(N*sizeof(spinor)/sizeof(_Complex double), N2*sizeof(spinor)/sizeof(_Complex double), + 50., prec,max_ev.s, j_max, j_min, + max_iterations, blocksize, blockwise, v0dim, (_Complex double*) eigenvectors, + CG, solver_it_max, + threshold_max, decay_max, verbosity, + &converged, (_Complex double*) eigenvectors, max_ev.el, + &returncode, JD_MAXIMAL, 1, + optr->applyQsq); + + max_ev.s = converged; + + if(min_ev.s < 8){ + j_max = 15; + j_min = 8; + } + else{ + j_max = 2*min_ev.s; + j_min = min_ev.s; + } + + converged = 0; + solver_it_max = 200; + + jdher(N*sizeof(spinor)/sizeof(_Complex double), N2*sizeof(spinor)/sizeof(_Complex double), + 0., prec, + min_ev.s, j_max, j_min, + max_iterations, blocksize, blockwise, v0dim, (_Complex double*) eigenvectors, + CG, solver_it_max, + threshold_min, decay_min, verbosity, + &converged, (_Complex double*) eigenvectors, min_ev.el, + &returncode2, JD_MINIMAL, 1, + optr->applyQsq); + + min_ev.s = converged; + + free(eigenvectors_); + + etime = gettime(); + if(g_proc_id == 0) { + printf("Eigenvalues computed in %e sec. gettime)\n", etime-atime); + } + + ev_min= min_ev.el[min_ev.s-1]; + ev_max= max_ev.el[max_ev.s-1]; + eigenvalues_for_cg_computed = converged; + + if(g_proc_id == 0){ + sprintf(filename,"rew_ev_estimate.%d", nstore); + ofs = fopen(filename, "a"); + for(ii = 0; ii < max_ev.s; ii++) { + fprintf(ofs, "%d %e 1\n",ii,max_ev.el[ii]); + } + for(ii = 0; ii < min_ev.s; ii++) { + fprintf(ofs, "%d %e 1\n",ii,min_ev.el[ii]); + } + fclose(ofs); + } + free(min_ev.el); + free(max_ev.el); +#else + fprintf(stderr, "lapack not available, so JD method for EV computation not available \n"); +#endif +} + + + static int invert_operator_Q(spinor * const P, spinor * const Q, const int op_id, const int pm) { @@ -303,11 +453,15 @@ static double poly_cheb(const unsigned int np, const double * const coeff, return y; } +/*Trivial test tests the function with the scaled idenetity matrix.*/ //#define TRIVIAL_TEST -static double log_determinant_estimate(const int operatorid, const int chebmax, - const int estimators, const double minev, const double maxev, +/*Convergence chesk: comparison of order n and n+1.*/ +#define CHECK_CONVERGENCE +static double 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 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; @@ -316,11 +470,17 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, const double am = t1 / 2.0; const double bm = t2 / 2.0; int k, l, n; - double x, y, ldet, prodre; + int orderstart, orderend; + int splitlength, sl; + double x, y, y1, ldet, prodre; FILE * ofs; spinor * vs1; spinor * vs2; spinor * u; +#ifdef CHECK_CONVERGENCE + spinor * unm1; + double prodrenm1, ldetnm1; +#endif spinor * v0; spinor * v1; spinor * v2; @@ -345,6 +505,9 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, vt0 = g_spinor_field[10]; vt1 = g_spinor_field[12]; vt2 = g_spinor_field[14]; +#ifdef CHECK_CONVERGENCE + unm1 = g_spinor_field[16]; +#endif optr = &operator_list[operatorid]; if (is_schur_complement(optr->applyQsq)) { @@ -358,7 +521,14 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, vt0 = g_spinor_field[7]; vt1 = g_spinor_field[8]; vt2 = g_spinor_field[9]; - if (DUM_MATRIX < 10) { +#ifdef CHECK_CONVERGENCE + unm1 = g_spinor_field[10]; +#endif +#ifdef CHECK_CONVERGENCE + if (DUM_MATRIX < 11) { +#else + if (DUM_MATRIX < 10) { +#endif if (g_proc_id == 0) { fprintf(stderr, "Not enough spinor fields %d < 10 \n\n", DUM_MATRIX); @@ -367,7 +537,11 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, } } else { - if (DUM_MATRIX < 16) { +#ifdef CHECK_CONVERGENCE + if (DUM_MATRIX < 18) { +#else + if (DUM_MATRIX < 16) { +#endif if (g_proc_id == 0) { fprintf(stderr, "Not enough spinor fields %d < 16 \n\n", DUM_MATRIX); @@ -375,9 +549,16 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, return 0.0; } } - - coeff = malloc(chebmax * sizeof(double)); - chebyshev_coeff(chebmax, coeff, am, bm); + 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) { ofs = fopen("polynomialapproxtest.txt", "a"); fprintf(ofs, @@ -385,162 +566,224 @@ static double log_determinant_estimate(const int operatorid, const int chebmax, for (k = 0; k < 200; k++) { x = minev + (maxev - minev) * (double) k / (double) (200 - 1); y = poly_cheb(chebmax, coeff, a * x + b); - fprintf(ofs, "%d %g %g %g %d %g %g\n", k, x, y, fabs(y - log(x)), - chebmax, minev, maxev); + 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); } - ldet = 0; - if (chebmax > 0) { - for (k = 0; k < estimators; k++) { - /* - * Generate estimator (may be half of it is never used) - */ - random_spinor_field_eo(vs1, reproduce_randomnumber_flag, RN_Z2); - random_spinor_field_eo(vs2, reproduce_randomnumber_flag, RN_Z2); + /* include T_min(x) to T_(max-1) (x) */ + orderstart = 0; + orderend = chebmax; + splitlength = 1; + 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++) { + ldet = 0; + if (sl > 0) { + orderstart = orderend; + orderend = split->ord[sl]; + estimators = split->est[sl]; + } +#ifdef CHECK_CONVERGENCE + ldetnm1 = 0; +#endif + if (orderend > 0) { + for (k = 0; k < estimators; k++) { + /* + * Generate estimator (may be half of it is never used) + */ + random_spinor_field_eo(vs1, reproduce_randomnumber_flag, RN_Z2); + random_spinor_field_eo(vs2, reproduce_randomnumber_flag, RN_Z2); - assign(v0, vs1, n); - assign(vt0, vs1, n); + assign(v0, vs1, n); + assign(vt0, vs1, n); #ifdef TRIVIAL_TEST - mul_r(v1,kappa1,vs1,n); + mul_r(v1,kappa1,vs1,n); #else - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters(operatorid); - optr->applyQsq(v1, vs1); + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); + optr->applyQsq(v1, vs1); #endif - /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ - assign_mul_add_mul_r(v1, vs1, a, b, n); + /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ + assign_mul_add_mul_r(v1, vs1, a, b, n); #ifdef TRIVIAL_TEST - mul_r(vt1,kappa2,vs1,n); + mul_r(vt1,kappa2,vs1,n); #else - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); - optr->applyQsq(vt1, vs1); + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); + optr->applyQsq(vt1, vs1); #endif - /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ - assign_mul_add_mul_r(vt1, vs1, a, b, n); + /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ + assign_mul_add_mul_r(vt1, vs1, a, b, n); - /* Makes (*R)=c1*(*S)-c2*(*U) , c1 and c2 are complex constants */ - mul_diff_mul_r(u, vt1, v1, coeff[1], coeff[1], 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); +#ifdef CHECK_CONVERGENCE + if (orderend > 1) { + mul_diff_mul_r(unm1, vt1, v1, coeff[1], coeff[1], n); + } +#endif + } + + /*This part is only more efficient if not the clover term h + * as to be recompted everytime the parameters are changed.*/ #if 0 - for (l = 1; l + 1 < chebmax; l++) { + for (l = 1; l + 1 < orderend; l++) { #ifndef TRIVIAL_TEST - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters(operatorid); + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); - optr->applyQsq(v2, v1); + optr->applyQsq(v2, v1); #else - mul_r(v2,kappa1,v1,n); + mul_r(v2,kappa1,v1,n); #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) { + /* 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; #ifndef TRIVIAL_TEST - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); - optr->applyQsq(vt2, vt1); + optr->applyQsq(vt2, vt1); #else - mul_r(vt2,kappa2,vt1,n); + mul_r(vt2,kappa2,vt1,n); #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; - - /* (*R) = (*R) + c1*(*S) + c2*(*U) */ - assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], - -coeff[l + 1], n); + /* 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) { + /* (*R) = (*R) + c1*(*S) + c2*(*U) */ + assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], + -coeff[l + 1], n); + } - } + } #endif #ifndef TRIVIAL_TEST - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters(operatorid); + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); #endif - for (l = 1; l + 1 < chebmax; l++) { + for (l = 1; l + 1 < orderend; l++) { #ifdef TRIVIAL_TEST - mul_r(v2,kappa1,v1,n); + 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; - /* (*P) = (*P) + c(*Q) c is a real constant */ - assign_add_mul_r(u, v1, -coeff[l + 1], n); - } + 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); +#ifdef CHECK_CONVERGENCE + if (l + 2 < orderend) { + assign_add_mul_r(unm1, v1, -coeff[l + 1], n); + } +#endif + } + } #ifndef TRIVIAL_TEST - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); #endif - for (l = 1; l + 1 < chebmax; l++) { + for (l = 1; l + 1 < orderend; l++) { #ifdef TRIVIAL_TEST - mul_r(vt2,kappa2,vt1,n); + mul_r(vt2,kappa2,vt1,n); #else - optr->applyQsq(vt2, vt1); + 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; - - /* (*P) = (*P) + c(*Q) c is a real constant */ - assign_add_mul_r(u, vt1, coeff[l + 1], n); - - } + /* 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); +#ifdef CHECK_CONVERGENCE + if (l + 2 < orderend) { + assign_add_mul_r(unm1, vt1, coeff[l + 1], n); + } +#endif + } + } - prodre = scalar_prod_r(vs1, u, n, 1); - ldet += prodre / ((double) estimators); - if (g_proc_id == 0 && g_debug_level > 3) { - ofs = fopen("estimators.txt", "a"); - fprintf(ofs, "# Test of stochastic estimation\n"); - fprintf(ofs, "%d %g %g %g %g %g %d %d %g %g %g\n", k, kappa1, - kappa2, kappa2Mu1, kappa2Mu2, prodre, estimators, - chebmax, minev, maxev, ldet); - fclose(ofs); - } + prodre = scalar_prod_r(vs1, u, n, 1); + ldet += prodre / ((double) estimators); +#ifdef CHECK_CONVERGENCE + prodrenm1 = scalar_prod_r(vs1, unm1, n, 1); + ldetnm1 += prodrenm1 / ((double) estimators); +#endif + if (g_proc_id == 0 && g_debug_level > 3) { + ofs = fopen("estimators.txt", "a"); + fprintf(ofs, "# Test of stochastic estimation\n"); + fprintf(ofs, "%d %g %g %g %g %g %d %d %d %g %g %g ", k, + kappa1, kappa2, kappa2Mu1, kappa2Mu2, prodre, + estimators, orderstart, orderend, minev, maxev, + ldet); +#ifdef CHECK_CONVERGENCE + fprintf(ofs, " %g %g", prodrenm1, ldetnm1); +#endif + fprintf(ofs, "\n"); + fclose(ofs); + } - if (g_proc_id == 0) { - ofs = fopen(filename, "a"); - fprintf(ofs, "%d %g %g %g %g %d %g %g ", traj, kappa1, kappa2, - kappa2Mu1, kappa2Mu2, chebmax, minev, maxev); - fprintf(ofs, " %g %g\n", prodre + shift, prodre); - fclose(ofs); - } + 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 + shift, prodre); +#ifdef CHECK_CONVERGENCE + fprintf(ofs, " %.17g \n", prodrenm1 + shift); +#endif + fclose(ofs); + } - } /* estimator iteration*/ - } /* chebmax>0*/ + } /* estimator iteration*/ + } /* orderend>0*/ + } /* splitlength loop */ free(coeff); return (ldet); } @@ -626,7 +869,7 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { */ k2muinitial = param->k2mu0; kappainitial = param->kappa0; - cswinitial=0; + cswinitial = 0; kapparew = 1; if (kappainitial == kappafinal) { kapparew = 0; @@ -697,6 +940,12 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } } + cswpart = 0; + + if(param->evest){ + estimate_eigenvalues(operatorid,traj); + } + if (param->use_cheb) { if (param->use_evenodd == 1) { cswpart = get_sw_reweighting(k2muinitial, k2mufinal, kappainitial, @@ -704,7 +953,8 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } log_determinant_estimate(operatorid, param->cheborder, param->estimatorscheb, param->minev, param->maxev, kappainitial, - kappafinal, k2muinitial, k2mufinal, cswpart, traj); + kappafinal, k2muinitial, k2mufinal, cswpart, traj, + ¶m->splitlist, ¶m->coeff); if (param->only_cheb) { return; } @@ -848,7 +1098,6 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { 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"); @@ -872,7 +1121,6 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } /* loop over interpolation steps*/ - etime = gettime(); if (g_proc_id == 0 && g_debug_level > 0) { @@ -881,3 +1129,128 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } return; } + +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); + param->coeff.el = NULL; + param->coeff.s = 0; + param->splitlist.ord = NULL; + param->splitlist.est = NULL; + param->splitlist.s = 0; +} + +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]); + } + } + } else { + if (g_proc_id == 0) { + printf("File coeff.dat not present.\n"); + } + v->el = NULL; + v->s = 0; + } + +} + +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]); + } + } + } else { + if (g_proc_id == 0) { + printf("File split.dat not present.\n"); + } + list->ord = NULL; + list->est = NULL; + list->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->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; + read_coeff_from_file(¶m->coeff); + read_splitlist(¶m->splitlist); + } +} diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h index e46e8e820..62528b441 100644 --- a/meas/reweightingmeas.h +++ b/meas/reweightingmeas.h @@ -22,7 +22,23 @@ #ifndef _REWEIGHTING_MEASUREMENT_H #define _REWEIGHTING_MEASUREMENT_H +#include +#include + typedef struct{ + double* el; + unsigned int s; +} vector_list; + +typedef struct { + unsigned int * ord; + unsigned int* est; + unsigned int s; + +} split_list; + + +typedef struct { int reweighting_operator; int reweighting_number_sources; int use_evenodd; @@ -37,30 +53,15 @@ typedef struct{ int cheborder; int use_cheb; int only_cheb; - + int evest; + vector_list coeff; + split_list splitlist; } reweighting_parameter; -inline 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->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; - } -} +void free_reweighting_parameter(void* par); + + +void initialize_reweighting_parameter(void** parameter); void reweighting_measurement(const int traj, const int t0, const int ieo); diff --git a/read_input.l b/read_input.l index 04faa0aa1..80d75113c 100644 --- a/read_input.l +++ b/read_input.l @@ -2023,6 +2023,12 @@ static inline void rmQuotes(char *str){ ((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); diff --git a/solver/jdher.c b/solver/jdher.c index 0d3fb5393..9dd30df25 100644 --- a/solver/jdher.c +++ b/solver/jdher.c @@ -306,7 +306,6 @@ void jdher(int n, int lda, double tau, double tol, * necessary randomly generated. * * * **************************************************************************/ - /* copy V0 to V */ _FT(zlacpy)(fupl_a, &n, &V0dim, V0, &lda, V, &lda, 1); j = V0dim; @@ -423,6 +422,7 @@ void jdher(int n, int lda, double tau, double tol, keepind[keep] = act; keep = keep + 1; } + } /* for(act = 0; act < actblksize; act ++) */ From 8f37f849e100163174beabb5b695450b361b7234 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Fri, 2 Dec 2016 12:43:08 +0100 Subject: [PATCH 10/22] added log estimation of reweighting --- meas/reweightingmeas.c | 545 ++++++++++++++++++++++++----------------- meas/reweightingmeas.h | 1 + measure.c | 2 +- read_input.l | 6 + 4 files changed, 328 insertions(+), 226 deletions(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index 3b9e03dc7..61becbf1d 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -65,8 +65,113 @@ #include "../global.h" #include "solver/jdher.h" +#include +#ifdef _USE_SHMEM +# include +#endif + /*#define CHECK_OPERATOR*/ +typedef struct { + spinor* buffer; + spinor** ar; + unsigned int length; +} spinor_array; + +static void set_zero(spinor * const R, const int N) { +#ifdef TM_USE_OMP +#pragma omp parallel + { +#endif + + int ix; + spinor *r; + +#ifdef TM_USE_OMP +#pragma omp for +#endif + for (ix = 0; ix < N; ++ix) { + r = (spinor *) R + ix; + + r->s0.c0 = 0.0; + r->s0.c1 = 0.0; + r->s0.c2 = 0.0; + + r->s1.c0 = 0.0; + r->s1.c1 = 0.0; + r->s1.c2 = 0.0; + + r->s2.c0 = 0.0; + r->s2.c1 = 0.0; + r->s2.c2 = 0.0; + + r->s3.c0 = 0.0; + r->s3.c1 = 0.0; + r->s3.c2 = 0.0; + } +#ifdef TM_USE_OMP +} /* OpenMP closing brace */ +#endif +} + +static int alloc_spinor_field(spinor_array* ar, int evenodd) { + int i = 0; + unsigned long int volume = VOLUMEPLUSRAND / 2; + if (evenodd == 0) { + volume = VOLUMEPLUSRAND; + } + if (ar->buffer != NULL || ar->ar != NULL || ar->length == 0) { + return (3); + } +#if (defined _USE_SHMEM && !(defined _USE_HALFSPINOR)) + if((void*)(ar->buffer = (spinor*)shmalloc((ar->length*volume+1)*sizeof(spinor))) == NULL) { + printf ("malloc errno : %d\n",errno); + errno = 0; + return(1); + } +#else + if ((void*) (ar->buffer = (spinor*) calloc(ar->length * volume + 1, + sizeof(spinor))) == NULL) { + printf("malloc errno : %d\n", errno); + errno = 0; + return (1); + } +#endif + if ((void*) (ar->ar = (spinor**) malloc(ar->length * sizeof(spinor*))) + == NULL) { + printf("malloc errno : %d\n", errno); + errno = 0; + return (2); + } +#if ( defined SSE || defined SSE2 || defined SSE3) + ar->ar = (spinor*)(((unsigned long int)(ar->buffer)+ALIGN_BASE)&~ALIGN_BASE); +#else + ar->ar[0] = ar->buffer; +#endif + + for (i = 1; i < ar->length; i++) { + ar->ar[i] = g_spinor_field[i - 1] + volume; + } + + return (0); +} + +static void free_spinor_field(spinor_array* ar) { + if (ar->buffer != NULL) { +#if (defined _USE_SHMEM && !(defined _USE_HALFSPINOR)) + shfree(ar->buffer); +#else + free(ar->buffer); +#endif + } + if (ar->ar != NULL) { + free(ar->ar); + } + ar->ar = NULL; + ar->buffer = NULL; + ar->length = 0; +} + 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 @@ -98,8 +203,6 @@ static double get_sw_reweighting(const double mu1, const double 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 @@ -131,151 +234,142 @@ static void update_global_parameters(const int op_id) { static void estimate_eigenvalues(const int operatorid, const int identifier) { #ifdef HAVE_LAPACK - vector_list min_ev; - vector_list max_ev; - spinor * eigenvectors_ = NULL; - char filename[200]; - FILE * ofs; - double atime, etime; - int max_iterations=5000; - double prec = 1.e-5; - int maxvectors; - /********************** - * For Jacobi-Davidson - **********************/ - int verbosity = g_debug_level, converged = 0, blocksize = 1, blockwise = 0; - int solver_it_max = 50, j_max, j_min, ii; - /*int it_max = 10000;*/ - /* _Complex double *eigv_ = NULL, *eigv; */ - double decay_min = 1.7, decay_max = 1.5, - threshold_min = 1.e-3, threshold_max = 5.e-2; - double ev_max, ev_min; - - /* static int v0dim = 0; */ - int v0dim = 0; - int N = (VOLUME)/2, N2 = (VOLUMEPLUSRAND)/2; - operator * optr; - - /********************** - * General variables - **********************/ - int returncode=0; - int returncode2=0; - - - min_ev.s=2; - min_ev.el=malloc(min_ev.s*sizeof(double)); - max_ev.s=2; - max_ev.el=malloc(max_ev.s*sizeof(double)); + vector_list min_ev; + vector_list max_ev; + spinor * eigenvectors_ = NULL; + char filename[200]; + FILE * ofs; + double atime, etime; + int max_iterations = 5000; + double prec = 1.e-5; + int maxvectors; + /********************** + * For Jacobi-Davidson + **********************/ + int verbosity = g_debug_level, converged = 0, blocksize = 1, blockwise = 0; + int solver_it_max = 50, j_max, j_min, ii; + /*int it_max = 10000;*/ + /* _Complex double *eigv_ = NULL, *eigv; */ + double decay_min = 1.7, decay_max = 1.5, threshold_min = 1.e-3, + threshold_max = 5.e-2; + double ev_max, ev_min; + + /* static int v0dim = 0; */ + int v0dim = 0; + int N = (VOLUME) / 2, N2 = (VOLUMEPLUSRAND) / 2; + operator * optr; - optr = &operator_list[operatorid]; + /********************** + * General variables + **********************/ + int returncode = 0; + int returncode2 = 0; + + min_ev.s = 2; + min_ev.el = malloc(min_ev.s * sizeof(double)); + max_ev.s = 2; + max_ev.el = malloc(max_ev.s * sizeof(double)); + optr = &operator_list[operatorid]; - if(!is_schur_complement(optr->applyQsq)) { - N = VOLUME; - N2 = VOLUMEPLUSRAND; - } + if (!is_schur_complement(optr->applyQsq)) { + N = VOLUME; + N2 = VOLUMEPLUSRAND; + } - evlength = N2; - if(g_proc_id == g_stdio_proc && g_debug_level >0) { - printf("Number of eigenvalues to compute = %d %d\n",min_ev.s,max_ev.s); - printf("Using Jacobi-Davidson method! \n"); - } + evlength = N2; + if (g_proc_id == g_stdio_proc && g_debug_level > 0) { + printf("Number of eigenvalues to compute = %d %d\n", min_ev.s, + max_ev.s); + printf("Using Jacobi-Davidson method! \n"); + } - if(max_ev.s < 8){ - j_max = 15; - j_min = 8; - } - else{ - j_max = 2*max_ev.s; - j_min = max_ev.s; - } + if (max_ev.s < 8) { + j_max = 15; + j_min = 8; + } else { + j_max = 2 * max_ev.s; + j_min = max_ev.s; + } - maxvectors=min_ev.s>max_ev.s ? min_ev.s:max_ev.s; + maxvectors = min_ev.s > max_ev.s ? min_ev.s : max_ev.s; #if (defined SSE || defined SSE2 || defined SSE3) - eigenvectors_ = calloc(N2*maxvectors+1, sizeof(spinor)); - eigenvectors = (spinor *)(((unsigned long int)(eigenvectors_)+ALIGN_BASE)&~ALIGN_BASE); + eigenvectors_ = calloc(N2*maxvectors+1, sizeof(spinor)); + eigenvectors = (spinor *)(((unsigned long int)(eigenvectors_)+ALIGN_BASE)&~ALIGN_BASE); #else - eigenvectors_= calloc(N2*maxvectors, sizeof(spinor)); - eigenvectors = eigenvectors_; + eigenvectors_ = calloc(N2 * maxvectors, sizeof(spinor)); + eigenvectors = eigenvectors_; #endif - atime = gettime(); + atime = gettime(); + + update_global_parameters(operatorid); - /* (re-) compute minimal eigenvalues */ - converged = 0; - solver_it_max = 200; - - - jdher(N*sizeof(spinor)/sizeof(_Complex double), N2*sizeof(spinor)/sizeof(_Complex double), - 50., prec,max_ev.s, j_max, j_min, - max_iterations, blocksize, blockwise, v0dim, (_Complex double*) eigenvectors, - CG, solver_it_max, - threshold_max, decay_max, verbosity, - &converged, (_Complex double*) eigenvectors, max_ev.el, - &returncode, JD_MAXIMAL, 1, - optr->applyQsq); - - max_ev.s = converged; - - if(min_ev.s < 8){ - j_max = 15; - j_min = 8; - } - else{ - j_max = 2*min_ev.s; - j_min = min_ev.s; - } - - converged = 0; - solver_it_max = 200; - - jdher(N*sizeof(spinor)/sizeof(_Complex double), N2*sizeof(spinor)/sizeof(_Complex double), - 0., prec, - min_ev.s, j_max, j_min, - max_iterations, blocksize, blockwise, v0dim, (_Complex double*) eigenvectors, - CG, solver_it_max, - threshold_min, decay_min, verbosity, - &converged, (_Complex double*) eigenvectors, min_ev.el, - &returncode2, JD_MINIMAL, 1, - optr->applyQsq); - - min_ev.s = converged; - - free(eigenvectors_); - - etime = gettime(); - if(g_proc_id == 0) { - printf("Eigenvalues computed in %e sec. gettime)\n", etime-atime); - } - - ev_min= min_ev.el[min_ev.s-1]; - ev_max= max_ev.el[max_ev.s-1]; - eigenvalues_for_cg_computed = converged; - - if(g_proc_id == 0){ - sprintf(filename,"rew_ev_estimate.%d", nstore); - ofs = fopen(filename, "a"); - for(ii = 0; ii < max_ev.s; ii++) { - fprintf(ofs, "%d %e 1\n",ii,max_ev.el[ii]); - } - for(ii = 0; ii < min_ev.s; ii++) { - fprintf(ofs, "%d %e 1\n",ii,min_ev.el[ii]); - } - fclose(ofs); - } - free(min_ev.el); - free(max_ev.el); + /* (re-) compute minimal eigenvalues */ + converged = 0; + solver_it_max = 200; + + jdher(N * sizeof(spinor) / sizeof(_Complex double), + N2 * sizeof(spinor) / sizeof(_Complex double), 50., prec, max_ev.s, + j_max, j_min, max_iterations, blocksize, blockwise, v0dim, + (_Complex double*) eigenvectors, CG, solver_it_max, threshold_max, + decay_max, verbosity, &converged, (_Complex double*) eigenvectors, + max_ev.el, &returncode, JD_MAXIMAL, 1, optr->applyQsq); + + max_ev.s = converged; + + if (min_ev.s < 8) { + j_max = 15; + j_min = 8; + } else { + j_max = 2 * min_ev.s; + j_min = min_ev.s; + } + + converged = 0; + solver_it_max = 200; + + jdher(N * sizeof(spinor) / sizeof(_Complex double), + N2 * sizeof(spinor) / sizeof(_Complex double), 0., prec, min_ev.s, + j_max, j_min, max_iterations, blocksize, blockwise, v0dim, + (_Complex double*) eigenvectors, CG, solver_it_max, threshold_min, + decay_min, verbosity, &converged, (_Complex double*) eigenvectors, + min_ev.el, &returncode2, JD_MINIMAL, 1, optr->applyQsq); + + min_ev.s = converged; + + free(eigenvectors_); + + etime = gettime(); + if (g_proc_id == 0) { + printf("Eigenvalues computed in %e sec. gettime)\n", etime - atime); + } + + ev_min = min_ev.el[min_ev.s - 1]; + ev_max = max_ev.el[max_ev.s - 1]; + eigenvalues_for_cg_computed = converged; + + if (g_proc_id == 0) { + sprintf(filename, "rew_ev_estimate.%d", nstore); + ofs = fopen(filename, "a"); + for (ii = 0; ii < max_ev.s; ii++) { + fprintf(ofs, "%d %e 1\n", ii, max_ev.el[ii]); + } + for (ii = 0; ii < min_ev.s; ii++) { + fprintf(ofs, "%d %e 1\n", ii, min_ev.el[ii]); + } + fclose(ofs); + } + free(min_ev.el); + free(max_ev.el); #else - fprintf(stderr, "lapack not available, so JD method for EV computation not available \n"); + fprintf(stderr, "lapack not available, so JD method for EV computation not available \n"); #endif } - - static int invert_operator_Q(spinor * const P, spinor * const Q, const int op_id, const int pm) { @@ -454,10 +548,10 @@ static double poly_cheb(const unsigned int np, const double * const coeff, } /*Trivial test tests the function with the scaled idenetity matrix.*/ -//#define TRIVIAL_TEST +/*#define TRIVIAL_TEST*/ /*Convergence chesk: comparison of order n and n+1.*/ #define CHECK_CONVERGENCE -static double log_determinant_estimate(const int operatorid, int chebmax, +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, @@ -469,17 +563,19 @@ static double log_determinant_estimate(const int operatorid, int chebmax, 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; - double x, y, y1, ldet, prodre; + spinor_array spinorarray; + static int written = 0; + double x, y, y1, prodre; FILE * ofs; - spinor * vs1; - spinor * vs2; + spinor * vs; spinor * u; #ifdef CHECK_CONVERGENCE spinor * unm1; - double prodrenm1, ldetnm1; + double prodrenm1; #endif spinor * v0; spinor * v1; @@ -491,64 +587,39 @@ static double log_determinant_estimate(const int operatorid, int chebmax, 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); - vs1 = g_spinor_field[0]; - vs2 = g_spinor_field[1]; - u = g_spinor_field[2]; - v0 = g_spinor_field[4]; - v1 = g_spinor_field[6]; - v2 = g_spinor_field[8]; - vt0 = g_spinor_field[10]; - vt1 = g_spinor_field[12]; - vt2 = g_spinor_field[14]; -#ifdef CHECK_CONVERGENCE - unm1 = g_spinor_field[16]; -#endif - optr = &operator_list[operatorid]; + + spinorarray.length = 9; if (is_schur_complement(optr->applyQsq)) { n = VOLUME / 2; - vs1 = g_spinor_field[0]; - vs2 = g_spinor_field[1]; - u = g_spinor_field[3]; - v0 = g_spinor_field[4]; - v1 = g_spinor_field[5]; - v2 = g_spinor_field[6]; - vt0 = g_spinor_field[7]; - vt1 = g_spinor_field[8]; - vt2 = g_spinor_field[9]; -#ifdef CHECK_CONVERGENCE - unm1 = g_spinor_field[10]; -#endif -#ifdef CHECK_CONVERGENCE - if (DUM_MATRIX < 11) { -#else - if (DUM_MATRIX < 10) { -#endif - if (g_proc_id == 0) { - fprintf(stderr, "Not enough spinor fields %d < 10 \n\n", - DUM_MATRIX); - } - return 0.0; - } - + 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]; #ifdef CHECK_CONVERGENCE - if (DUM_MATRIX < 18) { -#else - if (DUM_MATRIX < 16) { + unm1 = spinorarray.ar[8]; #endif - if (g_proc_id == 0) { - fprintf(stderr, "Not enough spinor fields %d < 16 \n\n", - DUM_MATRIX); - } - return 0.0; - } - } + if (coefflist->el != NULL && coefflist->s != 0) { chebmax = coefflist->s; coeff = malloc(chebmax * sizeof(double)); @@ -559,8 +630,9 @@ static double log_determinant_estimate(const int operatorid, int chebmax, coeff = malloc(chebmax * sizeof(double)); chebyshev_coeff(chebmax, coeff, am, bm); } - if (g_proc_id == 0 && g_debug_level > 3) { - ofs = fopen("polynomialapproxtest.txt", "a"); + 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++) { @@ -574,48 +646,65 @@ static double log_determinant_estimate(const int operatorid, int chebmax, 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++) { - ldet = 0; if (sl > 0) { orderstart = orderend; orderend = split->ord[sl]; estimators = split->est[sl]; + rel_shift = 0.0; } -#ifdef CHECK_CONVERGENCE - ldetnm1 = 0; -#endif + if (orderend > 0) { for (k = 0; k < estimators; k++) { + if (orderstart > 1 || orderend < 2) { + set_zero(u, n); +#ifdef CHECK_CONVERGENCE + set_zero(unm1, n); +#endif + } /* - * Generate estimator (may be half of it is never used) + * Generate estimator */ - random_spinor_field_eo(vs1, reproduce_randomnumber_flag, RN_Z2); - random_spinor_field_eo(vs2, reproduce_randomnumber_flag, RN_Z2); + 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, vs1, n); - assign(vt0, vs1, n); + 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, vs1); + optr->applyQsq(v1, vs); #endif /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ - assign_mul_add_mul_r(v1, vs1, a, b, n); + assign_mul_add_mul_r(v1, vs, a, b, n); #ifdef TRIVIAL_TEST mul_r(vt1,kappa2,vs1,n); @@ -623,10 +712,10 @@ static double log_determinant_estimate(const int operatorid, int chebmax, optr->kappa = kappa2; optr->mu = kappa2Mu2; update_global_parameters(operatorid); - optr->applyQsq(vt1, vs1); + optr->applyQsq(vt1, vs); #endif /* Makes (*R)=c1*(*R)+c2*(*S) , c1 and c2 are real constants */ - assign_mul_add_mul_r(vt1, vs1, a, b, n); + 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 */ @@ -652,7 +741,7 @@ static double log_determinant_estimate(const int operatorid, int chebmax, #else mul_r(v2,kappa1,v1,n); #endif - if(l+1>orderstart) { + if(l+1>=orderstart) { /* 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); @@ -679,7 +768,7 @@ static double log_determinant_estimate(const int operatorid, int chebmax, vt1 = vt2; vt2 = tmp; - if(l+1>orderstart) { + if(l+1>=orderstart) { /* (*R) = (*R) + c1*(*S) + c2*(*U) */ assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], -coeff[l + 1], n); @@ -709,7 +798,8 @@ static double log_determinant_estimate(const int operatorid, int chebmax, v0 = v1; v1 = v2; v2 = tmp; - if (l + 1 > orderstart) { + + if (l + 1 >= orderstart) { /* (*P) = (*P) + c(*Q) c is a real constant */ assign_add_mul_r(u, v1, -coeff[l + 1], n); #ifdef CHECK_CONVERGENCE @@ -738,7 +828,7 @@ static double log_determinant_estimate(const int operatorid, int chebmax, vt0 = vt1; vt1 = vt2; vt2 = tmp; - if (l + 1 > orderstart) { + if (l + 1 >= orderstart) { /* (*P) = (*P) + c(*Q) c is a real constant */ assign_add_mul_r(u, vt1, coeff[l + 1], n); #ifdef CHECK_CONVERGENCE @@ -749,34 +839,20 @@ static double log_determinant_estimate(const int operatorid, int chebmax, } } - prodre = scalar_prod_r(vs1, u, n, 1); - ldet += prodre / ((double) estimators); + prodre = scalar_prod_r(vs, u, n, 1); #ifdef CHECK_CONVERGENCE - prodrenm1 = scalar_prod_r(vs1, unm1, n, 1); - ldetnm1 += prodrenm1 / ((double) estimators); + prodrenm1 = scalar_prod_r(vs, unm1, n, 1); #endif - if (g_proc_id == 0 && g_debug_level > 3) { - ofs = fopen("estimators.txt", "a"); - fprintf(ofs, "# Test of stochastic estimation\n"); - fprintf(ofs, "%d %g %g %g %g %g %d %d %d %g %g %g ", k, - kappa1, kappa2, kappa2Mu1, kappa2Mu2, prodre, - estimators, orderstart, orderend, minev, maxev, - ldet); -#ifdef CHECK_CONVERGENCE - fprintf(ofs, " %g %g", prodrenm1, ldetnm1); -#endif - fprintf(ofs, "\n"); - fclose(ofs); - } 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 + shift, prodre); + fprintf(ofs, " %.17g %.17g ", prodre + rel_shift, + prodre); #ifdef CHECK_CONVERGENCE - fprintf(ofs, " %.17g \n", prodrenm1 + shift); + fprintf(ofs, " %.17g \n", prodrenm1 + rel_shift); #endif fclose(ofs); } @@ -785,7 +861,7 @@ static double log_determinant_estimate(const int operatorid, int chebmax, } /* orderend>0*/ } /* splitlength loop */ free(coeff); - return (ldet); + free_spinor_field(&spinorarray); } void reweighting_measurement(const int traj, const int id, const int ieo) { @@ -940,13 +1016,27 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { } } + 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){ - estimate_eigenvalues(operatorid,traj); + if (param->evest) { + if (g_proc_id == 0) { + printf("Calculating minimal/maximal eigenvalue estimates.\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); @@ -971,8 +1061,12 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { for (internum = 0; internum < param->interpolationsteps; internum++) { if (kapparew) { kappa0 = kappa; - interpolate(&kappa, kappainitial, kappafinal, + tmp1=1.0/kappainitial; + tmp2=1.0/kappafinal; + tmp3=1.0/kappa; + interpolate(&tmp3, tmp1,tmp2, param->interpolationsteps, internum); + kappa=1.0/tmp3; } if (murew) { /* use quadratic interpolation in the case of mu*/ @@ -1249,7 +1343,8 @@ void initialize_reweighting_parameter(void** parameter) { param->splitlist.ord = NULL; param->splitlist.est = NULL; param->splitlist.s = 0; - param->evest=0; + param->evest = 0; + param->testchebconvergence = 0; read_coeff_from_file(¶m->coeff); read_splitlist(¶m->splitlist); } diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h index 62528b441..e167c60b7 100644 --- a/meas/reweightingmeas.h +++ b/meas/reweightingmeas.h @@ -48,6 +48,7 @@ typedef struct { double rmu; double minev; double maxev; + double testchebconvergence; int interpolationsteps; int estimatorscheb; int cheborder; diff --git a/measure.c b/measure.c index aa8e1dfa2..d199e8b8b 100644 --- a/measure.c +++ b/measure.c @@ -125,7 +125,7 @@ int main(int argc, char *argv[]) #endif DUM_DERI = 8; - DUM_MATRIX = DUM_DERI + 5; /* 5 fields for doing the inversions (might be used by other opetations if no inverter used*/ + DUM_MATRIX = DUM_DERI + 5; /* 5 fields for doing the inversions (might be used by other operations if no inverter used*/ NO_OF_SPINORFIELDS = DUM_MATRIX + 4; /* Don't access these fields if you apply multiplications!*/ //4 extra fields (corresponding to DUM_MATRIX+0..5) for deg. and ND matrix mult. diff --git a/read_input.l b/read_input.l index 80d75113c..d907f60fa 100644 --- a/read_input.l +++ b/read_input.l @@ -2059,6 +2059,12 @@ static inline void rmQuotes(char *str){ ((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); + } } { From 93982ac0c86543f6b378785aae73bff4c2219a73 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Thu, 22 Dec 2016 22:14:49 +0100 Subject: [PATCH 11/22] checked DDalphaAMG interfaces --- DDalphaAMG_interface.c | 117 ++++++++++++++++++++++++++++++++--------- read_input.l | 2 +- solver/jdher.c | 2 +- 3 files changed, 94 insertions(+), 27 deletions(-) diff --git a/DDalphaAMG_interface.c b/DDalphaAMG_interface.c index c3cb3ea72..52184acb0 100644 --- a/DDalphaAMG_interface.c +++ b/DDalphaAMG_interface.c @@ -20,7 +20,66 @@ * Interface for DDalphaAMG * *******************************************************************************/ + #include "DDalphaAMG_interface.h" + +#ifndef DDalphaAMG + +int mg_setup_iter; +int mg_coarse_setup_iter; +int mg_update_setup_iter; +int mg_omp_num_threads; +int mg_Nvec; +int mg_lvl; +int mg_blk[4]; +int mg_mixed_prec; +int mg_setup_mu_set; +double mg_setup_mu; +double mg_cmu_factor; +double mg_dtau_update; +double mg_rho_update; + +void MG_init(void) { + printf("ERROR: MG_init called but DDalphaAMG library not included.\n"); + exit(1); +} + +void MG_update_gauge(double step) { + printf("ERROR: MG_update_gauge called but DDalphaAMG library not included.\n"); + exit(1); +} + +void MG_update_mu(double mu_tmLQCD, double odd_tmLQCD) { + printf("ERROR: MG_update_mu called but DDalphaAMG library not included.\n"); + exit(1); +} + +void MG_reset(void) { + printf("ERROR: MG_reset called but DDalphaAMG library not included.\n"); + exit(1); +} + +void MG_finalize(void) { + printf("ERROR: MG_finalize called but DDalphaAMG library not included.\n"); + exit(1); +} + +int MG_solver(spinor * const phi_new, spinor * const phi_old, + const double precision, const int max_iter,const int rel_prec, + const int N, su3 **gf, matrix_mult f) { + printf("ERROR: MG_solver called but DDalphaAMG library not included.\n"); + exit(1); +} + +int MG_solver_eo(spinor * const Even_new, spinor * const Odd_new, + spinor * const Even, spinor * const Odd, + const double precision, const int max_iter, const int rel_prec, + const int N, su3 **gf, matrix_mult_full f_full) { + printf("ERROR: MG_solver_eo called but DDalphaAMG library not included.\n"); + exit(1); +} + +#else #include #include #include @@ -38,6 +97,7 @@ #include "operator/clovertm_operators.h" //Enable to test the solution. It cost an application more of the operator. +//TODO: test all the operators interfaced and then undefine this flag. #define MGTEST DDalphaAMG_init mg_init; @@ -54,7 +114,9 @@ int mg_omp_num_threads=0; int mg_Nvec=24; int mg_lvl=3; int mg_blk[4] = {0, 0, 0, 0}; -double mg_setup_mu = 0./0.; //setting to NaN +int mg_mixed_prec=0; +int mg_setup_mu_set = 0; //flag that enable the use of mg_setup_mu in the setup phase +double mg_setup_mu = 0.; double mg_cmu_factor = 1.0; double mg_dtau_update = 0.0; double mg_rho_update = -1.0; @@ -130,7 +192,7 @@ static int MG_check(spinor * const phi_new, spinor * const phi_old, const int N, return 0; } - if (verbose && g_proc_id == 0) + if (g_debug_level > 0 && g_proc_id == 0) printf("MGTEST: || s - f_{tmLQC} * f_{DDalphaAMG}^{-1} * s || / ||s|| = %e / %e = %e \n", differ[0],differ[1],differ[0]/differ[1]); return 1; @@ -140,7 +202,7 @@ static int MG_check(spinor * const phi_new, spinor * const phi_old, const int N, static int MG_pre_solve( su3 **gf ) { - double dtau= mg_tau-gauge_tau; + double dtau = fabs(mg_tau-gauge_tau); // Checking if: // mg_update_setup < mg_update_setup_iter : maybe you want to do more iteration at this run // mg_dtau_update < dtau : regular condition for update of setup @@ -148,11 +210,11 @@ static int MG_pre_solve( su3 **gf ) // mg_dtau_update == 0.0 : updating at every change of configuration -> valid as well if configuration changed outside the HMC // mg_rho_update < 0.0 : parameter ignore // mg_rho_update == rho : updating only if this condition and the others are satisfied - if ( mg_do_setup == 0 && mg_update_setup < mg_update_setup_iter && ( mg_dtau_update < dtau || mg_dtau_update < -dtau || (mg_dtau_update==0.0 && mg_update_gauge==1)) && - (mg_rho_update < 0.0 || mg_rho_update == g_mu3)) + if ( mg_do_setup == 0 && mg_update_setup < mg_update_setup_iter && ( mg_dtau_update < dtau+1e-6 || (mg_dtau_update==0.0 && mg_update_gauge==1) || + (mg_rho_update >= 0.0 && mg_rho_update == g_mu3) )) mg_update_setup = mg_update_setup_iter; - if(verbose && g_proc_id == 0) + if(g_debug_level > 0 && g_proc_id == 0) printf("Tau has been increased since last MG setup update of %e\n", dtau); if (mg_initialized==0) { @@ -173,7 +235,7 @@ static int MG_pre_solve( su3 **gf ) } if (mg_do_setup==1) { - if( mg_setup_mu == mg_setup_mu ) { //is set as a NaN at the beginning, so true only if used + if( mg_setup_mu_set ) { if (g_proc_id == 0) printf("DDalphaAMG using mu=%f during setup\n", mg_setup_mu); MG_update_mu(mg_setup_mu, 0); @@ -192,7 +254,7 @@ static int MG_pre_solve( su3 **gf ) } if (mg_update_setup>0) { - if( mg_setup_mu == mg_setup_mu ) { //is set as a NaN at the beginning, so true only if used + if( mg_setup_mu_set ) { if (g_proc_id == 0) printf("DDalphaAMG using mu=%f during setup\n", mg_setup_mu); MG_update_mu(mg_setup_mu, 0); @@ -294,9 +356,9 @@ static int MG_solve(spinor * const phi_new, spinor * const phi_old, const double f == Qsw_psi || // Gamma5 - Schur complement with mu=0 on odd sites f == Q_plus_psi || // Gamma5 - Full operator with plus mu f == Q_minus_psi ) { // Gamma5 - Full operator with minus mu - // mul_gamma5(phi_old, N); // error in the original version + mul_gamma5(old, VOLUME); DDalphaAMG_solve( new, old, precision, &mg_status ); - mul_gamma5(phi_old, N); + mul_gamma5(old, VOLUME); } else if ( f == Qtm_pm_psi || // Schur complement squared f == Qsw_pm_psi ) { // Schur complement squared @@ -341,20 +403,20 @@ void MG_init() mg_init.Cart_rank=Cart_rank; mg_init.Cart_coords=Cart_coords; - mg_init.global_lattice[0]=T*N_PROC_T; - mg_init.global_lattice[1]=LZ*N_PROC_Z; - mg_init.global_lattice[2]=LY*N_PROC_Y; - mg_init.global_lattice[3]=LX*N_PROC_X; + mg_init.global_lattice[0]=T*g_nproc_t; + mg_init.global_lattice[1]=LZ*g_nproc_z; + mg_init.global_lattice[2]=LY*g_nproc_y; + mg_init.global_lattice[3]=LX*g_nproc_x; - mg_init.procs[0]=N_PROC_T; - mg_init.procs[1]=N_PROC_Z; - mg_init.procs[2]=N_PROC_Y; - mg_init.procs[3]=N_PROC_X; + mg_init.procs[0]=g_nproc_t; + mg_init.procs[1]=g_nproc_z; + mg_init.procs[2]=g_nproc_y; + mg_init.procs[3]=g_nproc_x; for(int i = 0; i<4; i++) if(mg_blk[i]==0) - mg_blk[i]=(((L/N_PROC_X)%2==0)?(((L/N_PROC_X)%4==0)?4:2): - (((L/N_PROC_X)%3==0)?3:1)); + mg_blk[i]=(((L/g_nproc_x)%2==0)?(((L/g_nproc_x)%4==0)?4:2): + (((L/g_nproc_x)%3==0)?3:1)); mg_init.block_lattice[0]=mg_blk[0]; mg_init.block_lattice[1]=mg_blk[1]; @@ -415,9 +477,9 @@ void MG_init() * Printing level: * -1: silent (errors or warnings) * 0: minimal //default - * 1: verbose + * 1: g_debug_level > 0 */ - if(verbose) { + if(g_debug_level > 0) { mg_params.print=1; } else @@ -432,7 +494,10 @@ void MG_init() mg_params.setup_iterations[1]=mg_coarse_setup_iter; // with mixed_precision = 2 the library adapt the solving precision according to the vector components - mg_params.mixed_precision = 2; + if(mg_mixed_prec) + mg_params.mixed_precision = 2; + else + mg_params.mixed_precision = 1; DDalphaAMG_update_parameters(&mg_params, &mg_status); @@ -454,7 +519,7 @@ void MG_update_mu(double mu_tmLQCD, double odd_tmLQCD) if (mu != mg_params.mu || odd_shift != mg_params.mu_odd_shift || mg_params.mu_even_shift != 0.0 ) { //Taking advantage of this function for updating printing in HMC - if(verbose) + if(g_debug_level > 0) mg_params.print=1; else mg_params.print=0; @@ -519,7 +584,7 @@ int MG_solver(spinor * const phi_new, spinor * const phi_old, DDalphaAMG_finalize(); MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); - exit(0); + exit(1); } // mg_status should have been used last time for the inversion. return mg_status.iter_count; @@ -557,3 +622,5 @@ int MG_solver_eo(spinor * const Even_new, spinor * const Odd_new, return iter_count; } + +#endif diff --git a/read_input.l b/read_input.l index d907f60fa..19cabdbb4 100644 --- a/read_input.l +++ b/read_input.l @@ -107,7 +107,7 @@ static inline void rmQuotes(char *str){ char * type; int verbose = 0; - int myverbose = 1; + int myverbose = 0; int startoption; int Ntherm; int Nmeas; diff --git a/solver/jdher.c b/solver/jdher.c index 9dd30df25..0d3fb5393 100644 --- a/solver/jdher.c +++ b/solver/jdher.c @@ -306,6 +306,7 @@ void jdher(int n, int lda, double tau, double tol, * necessary randomly generated. * * * **************************************************************************/ + /* copy V0 to V */ _FT(zlacpy)(fupl_a, &n, &V0dim, V0, &lda, V, &lda, 1); j = V0dim; @@ -422,7 +423,6 @@ void jdher(int n, int lda, double tau, double tol, keepind[keep] = act; keep = keep + 1; } - } /* for(act = 0; act < actblksize; act ++) */ From 9607fe144569fbbbf612cb5c2edaa6f81d0bd9ed Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Thu, 23 Feb 2017 16:05:15 +0100 Subject: [PATCH 12/22] corrected for new interface with kappa changes --- DDalphaAMG_interface.c | 13 + DDalphaAMG_interface.h | 1 + configure.in | 10 +- meas/reweightingmeas.c | 2457 ++++++++++++++++++++++------------------ 4 files changed, 1347 insertions(+), 1134 deletions(-) diff --git a/DDalphaAMG_interface.c b/DDalphaAMG_interface.c index 52184acb0..3904a2e79 100644 --- a/DDalphaAMG_interface.c +++ b/DDalphaAMG_interface.c @@ -531,6 +531,19 @@ void MG_update_mu(double mu_tmLQCD, double odd_tmLQCD) } } +void MG_update_kappa(double kappa) +{ + if(mg_initialized!=1){ + return; + } + DDalphaAMG_get_parameters(&mg_params); + + if (kappa!= mg_params.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/configure.in b/configure.in index 0de7058e5..7f4cbf4fd 100644 --- a/configure.in +++ b/configure.in @@ -23,11 +23,11 @@ AC_F77_LIBRARY_LDFLAGS AC_CHECK_TOOL(AR, ar, [ar]) LIBS="$LIBS $FLIBS -lm" -AC_PROG_LEX -dnl AC_PROG_LEX sets $LEX to ":" if neither lex nor flex are found! -if test "$LEX" = ":"; then - AC_MSG_ERROR([(F)LEX is required for building read_input.c. Please install it and run configure again.]) -fi +#AC_PROG_LEX +#dnl AC_PROG_LEX sets $LEX to ":" if neither lex nor flex are found! +#if test "$LEX" = ":"; then +# AC_MSG_ERROR([(F)LEX is required for building read_input.c. Please install it and run configure again.]) +#fi AC_PROG_MAKE_SET AC_PROG_RANLIB diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index 61becbf1d..e8a54ab43 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -72,1280 +72,1479 @@ /*#define CHECK_OPERATOR*/ -typedef struct { - spinor* buffer; - spinor** ar; - unsigned int length; +typedef struct +{ + spinor* buffer; + spinor** ar; + unsigned int length; } spinor_array; -static void set_zero(spinor * const R, const int N) { +static void +set_zero (spinor * const R, const int N) +{ #ifdef TM_USE_OMP #pragma omp parallel - { + { #endif - int ix; - spinor *r; + int ix; + spinor *r; #ifdef TM_USE_OMP #pragma omp for #endif - for (ix = 0; ix < N; ++ix) { - r = (spinor *) R + ix; - - r->s0.c0 = 0.0; - r->s0.c1 = 0.0; - r->s0.c2 = 0.0; - - r->s1.c0 = 0.0; - r->s1.c1 = 0.0; - r->s1.c2 = 0.0; - - r->s2.c0 = 0.0; - r->s2.c1 = 0.0; - r->s2.c2 = 0.0; - - r->s3.c0 = 0.0; - r->s3.c1 = 0.0; - r->s3.c2 = 0.0; - } + for (ix = 0; ix < N; ++ix) + { + r = (spinor *) R + ix; + + r->s0.c0 = 0.0; + r->s0.c1 = 0.0; + r->s0.c2 = 0.0; + + r->s1.c0 = 0.0; + r->s1.c1 = 0.0; + r->s1.c2 = 0.0; + + r->s2.c0 = 0.0; + r->s2.c1 = 0.0; + r->s2.c2 = 0.0; + + r->s3.c0 = 0.0; + r->s3.c1 = 0.0; + r->s3.c2 = 0.0; + } #ifdef TM_USE_OMP } /* OpenMP closing brace */ #endif } -static int alloc_spinor_field(spinor_array* ar, int evenodd) { - int i = 0; - unsigned long int volume = VOLUMEPLUSRAND / 2; - if (evenodd == 0) { - volume = VOLUMEPLUSRAND; - } - if (ar->buffer != NULL || ar->ar != NULL || ar->length == 0) { - return (3); - } +static int +alloc_spinor_field (spinor_array* ar, int evenodd) +{ + int i = 0; + unsigned long int volume = VOLUMEPLUSRAND / 2; + if (evenodd == 0) + { + volume = VOLUMEPLUSRAND; + } + if (ar->buffer != NULL || ar->ar != NULL || ar->length == 0) + { + return (3); + } #if (defined _USE_SHMEM && !(defined _USE_HALFSPINOR)) - if((void*)(ar->buffer = (spinor*)shmalloc((ar->length*volume+1)*sizeof(spinor))) == NULL) { - printf ("malloc errno : %d\n",errno); - errno = 0; - return(1); - } + if((void*)(ar->buffer = (spinor*)shmalloc((ar->length*volume+1)*sizeof(spinor))) == NULL) + { + printf ("malloc errno : %d\n",errno); + errno = 0; + return(1); + } #else - if ((void*) (ar->buffer = (spinor*) calloc(ar->length * volume + 1, - sizeof(spinor))) == NULL) { - printf("malloc errno : %d\n", errno); - errno = 0; - return (1); - } + if ((void*) (ar->buffer = (spinor*) calloc (ar->length * volume + 1, + sizeof(spinor))) == NULL) + { + printf ("malloc errno : %d\n", errno); + errno = 0; + return (1); + } #endif - if ((void*) (ar->ar = (spinor**) malloc(ar->length * sizeof(spinor*))) - == NULL) { - printf("malloc errno : %d\n", errno); - errno = 0; - return (2); - } + if ((void*) (ar->ar = (spinor**) malloc (ar->length * sizeof(spinor*))) + == NULL) + { + printf ("malloc errno : %d\n", errno); + errno = 0; + return (2); + } #if ( defined SSE || defined SSE2 || defined SSE3) - ar->ar = (spinor*)(((unsigned long int)(ar->buffer)+ALIGN_BASE)&~ALIGN_BASE); + ar->ar = (spinor*)(((unsigned long int)(ar->buffer)+ALIGN_BASE)&~ALIGN_BASE); #else - ar->ar[0] = ar->buffer; + ar->ar[0] = ar->buffer; #endif - for (i = 1; i < ar->length; i++) { - ar->ar[i] = g_spinor_field[i - 1] + volume; - } + for (i = 1; i < ar->length; i++) + { + ar->ar[i] = g_spinor_field[i - 1] + volume; + } - return (0); + return (0); } -static void free_spinor_field(spinor_array* ar) { - if (ar->buffer != NULL) { +static void +free_spinor_field (spinor_array* ar) +{ + if (ar->buffer != NULL) + { #if (defined _USE_SHMEM && !(defined _USE_HALFSPINOR)) - shfree(ar->buffer); + shfree(ar->buffer); #else - free(ar->buffer); + free (ar->buffer); #endif - } - if (ar->ar != NULL) { - free(ar->ar); - } - ar->ar = NULL; - ar->buffer = NULL; - ar->length = 0; + } + if (ar->ar != NULL) + { + free (ar->ar); + } + ar->ar = NULL; + ar->buffer = NULL; + ar->length = 0; } -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; +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; } -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 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; +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; } -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*/ +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*/ } -static void estimate_eigenvalues(const int operatorid, const int identifier) { +static void +estimate_eigenvalues (const int operatorid, const int identifier) +{ #ifdef HAVE_LAPACK - vector_list min_ev; - vector_list max_ev; - spinor * eigenvectors_ = NULL; - char filename[200]; - FILE * ofs; - double atime, etime; - int max_iterations = 5000; - double prec = 1.e-5; - int maxvectors; - /********************** - * For Jacobi-Davidson - **********************/ - int verbosity = g_debug_level, converged = 0, blocksize = 1, blockwise = 0; - int solver_it_max = 50, j_max, j_min, ii; - /*int it_max = 10000;*/ - /* _Complex double *eigv_ = NULL, *eigv; */ - double decay_min = 1.7, decay_max = 1.5, threshold_min = 1.e-3, - threshold_max = 5.e-2; - double ev_max, ev_min; - - /* static int v0dim = 0; */ - int v0dim = 0; - int N = (VOLUME) / 2, N2 = (VOLUMEPLUSRAND) / 2; - operator * optr; - - /********************** - * General variables - **********************/ - int returncode = 0; - int returncode2 = 0; - - min_ev.s = 2; - min_ev.el = malloc(min_ev.s * sizeof(double)); - max_ev.s = 2; - max_ev.el = malloc(max_ev.s * sizeof(double)); - - optr = &operator_list[operatorid]; - - if (!is_schur_complement(optr->applyQsq)) { - N = VOLUME; - N2 = VOLUMEPLUSRAND; - } - - - evlength = N2; - if (g_proc_id == g_stdio_proc && g_debug_level > 0) { - printf("Number of eigenvalues to compute = %d %d\n", min_ev.s, - max_ev.s); - printf("Using Jacobi-Davidson method! \n"); - } - - if (max_ev.s < 8) { - j_max = 15; - j_min = 8; - } else { - j_max = 2 * max_ev.s; - j_min = max_ev.s; - } - - maxvectors = min_ev.s > max_ev.s ? min_ev.s : max_ev.s; + vector_list min_ev; + vector_list max_ev; + spinor * eigenvectors_ = NULL; + char filename[200]; + FILE * ofs; + double atime, etime; + int max_iterations = 5000; + double prec = 1.e-5; + int maxvectors; + /********************** + * For Jacobi-Davidson + **********************/ + int verbosity = g_debug_level, converged = 0, blocksize = 1, blockwise = 0; + int solver_it_max = 50, j_max, j_min, ii; + /*int it_max = 10000;*/ + /* _Complex double *eigv_ = NULL, *eigv; */ + double decay_min = 1.7, decay_max = 1.5, threshold_min = 1.e-3, + threshold_max = 5.e-2; + double ev_max, ev_min; + + /* static int v0dim = 0; */ + int v0dim = 0; + int N = (VOLUME) / 2, N2 = (VOLUMEPLUSRAND) / 2; + operator * optr; + + /********************** + * General variables + **********************/ + int returncode = 0; + int returncode2 = 0; + + min_ev.s = 2; + min_ev.el = malloc(min_ev.s * sizeof(double)); + max_ev.s = 2; + max_ev.el = malloc(max_ev.s * sizeof(double)); + + optr = &operator_list[operatorid]; + + if (!is_schur_complement(optr->applyQsq)) + { + N = VOLUME; + N2 = VOLUMEPLUSRAND; + } + + evlength = N2; + if (g_proc_id == g_stdio_proc && g_debug_level > 0) + { + printf("Number of eigenvalues to compute = %d %d\n", min_ev.s, + max_ev.s); + printf("Using Jacobi-Davidson method! \n"); + } + + if (max_ev.s < 8) + { + j_max = 15; + j_min = 8; + } + else + { + j_max = 2 * max_ev.s; + j_min = max_ev.s; + } + + maxvectors = min_ev.s > max_ev.s ? min_ev.s : max_ev.s; #if (defined SSE || defined SSE2 || defined SSE3) - eigenvectors_ = calloc(N2*maxvectors+1, sizeof(spinor)); - eigenvectors = (spinor *)(((unsigned long int)(eigenvectors_)+ALIGN_BASE)&~ALIGN_BASE); + eigenvectors_ = calloc(N2*maxvectors+1, sizeof(spinor)); + eigenvectors = (spinor *)(((unsigned long int)(eigenvectors_)+ALIGN_BASE)&~ALIGN_BASE); #else - eigenvectors_ = calloc(N2 * maxvectors, sizeof(spinor)); - eigenvectors = eigenvectors_; + eigenvectors_ = calloc(N2 * maxvectors, sizeof(spinor)); + eigenvectors = eigenvectors_; #endif - atime = gettime(); - - - - update_global_parameters(operatorid); - /* (re-) compute minimal eigenvalues */ - converged = 0; - solver_it_max = 200; - - jdher(N * sizeof(spinor) / sizeof(_Complex double), - N2 * sizeof(spinor) / sizeof(_Complex double), 50., prec, max_ev.s, - j_max, j_min, max_iterations, blocksize, blockwise, v0dim, - (_Complex double*) eigenvectors, CG, solver_it_max, threshold_max, - decay_max, verbosity, &converged, (_Complex double*) eigenvectors, - max_ev.el, &returncode, JD_MAXIMAL, 1, optr->applyQsq); - - max_ev.s = converged; - - if (min_ev.s < 8) { - j_max = 15; - j_min = 8; - } else { - j_max = 2 * min_ev.s; - j_min = min_ev.s; - } - - converged = 0; - solver_it_max = 200; - - jdher(N * sizeof(spinor) / sizeof(_Complex double), - N2 * sizeof(spinor) / sizeof(_Complex double), 0., prec, min_ev.s, - j_max, j_min, max_iterations, blocksize, blockwise, v0dim, - (_Complex double*) eigenvectors, CG, solver_it_max, threshold_min, - decay_min, verbosity, &converged, (_Complex double*) eigenvectors, - min_ev.el, &returncode2, JD_MINIMAL, 1, optr->applyQsq); - - min_ev.s = converged; - - free(eigenvectors_); - - etime = gettime(); - if (g_proc_id == 0) { - printf("Eigenvalues computed in %e sec. gettime)\n", etime - atime); - } - - ev_min = min_ev.el[min_ev.s - 1]; - ev_max = max_ev.el[max_ev.s - 1]; - eigenvalues_for_cg_computed = converged; - - if (g_proc_id == 0) { - sprintf(filename, "rew_ev_estimate.%d", nstore); - ofs = fopen(filename, "a"); - for (ii = 0; ii < max_ev.s; ii++) { - fprintf(ofs, "%d %e 1\n", ii, max_ev.el[ii]); - } - for (ii = 0; ii < min_ev.s; ii++) { - fprintf(ofs, "%d %e 1\n", ii, min_ev.el[ii]); - } - fclose(ofs); - } - free(min_ev.el); - free(max_ev.el); + atime = gettime(); + + update_global_parameters(operatorid); + /* (re-) compute minimal eigenvalues */ + converged = 0; + solver_it_max = 200; + + jdher(N * sizeof(spinor) / sizeof(_Complex double), + N2 * sizeof(spinor) / sizeof(_Complex double), 50., prec, max_ev.s, + j_max, j_min, max_iterations, blocksize, blockwise, v0dim, + (_Complex double*) eigenvectors, CG, solver_it_max, threshold_max, + decay_max, verbosity, &converged, (_Complex double*) eigenvectors, + max_ev.el, &returncode, JD_MAXIMAL, 1, optr->applyQsq); + + max_ev.s = converged; + + if (min_ev.s < 8) + { + j_max = 15; + j_min = 8; + } + else + { + j_max = 2 * min_ev.s; + j_min = min_ev.s; + } + + converged = 0; + solver_it_max = 200; + + jdher(N * sizeof(spinor) / sizeof(_Complex double), + N2 * sizeof(spinor) / sizeof(_Complex double), 0., prec, min_ev.s, + j_max, j_min, max_iterations, blocksize, blockwise, v0dim, + (_Complex double*) eigenvectors, CG, solver_it_max, threshold_min, + decay_min, verbosity, &converged, (_Complex double*) eigenvectors, + min_ev.el, &returncode2, JD_MINIMAL, 1, optr->applyQsq); + + min_ev.s = converged; + + free(eigenvectors_); + + etime = gettime(); + if (g_proc_id == 0) + { + printf("Eigenvalues computed in %e sec. gettime)\n", etime - atime); + } + + ev_min = min_ev.el[min_ev.s - 1]; + ev_max = max_ev.el[max_ev.s - 1]; + eigenvalues_for_cg_computed = converged; + + if (g_proc_id == 0) + { + sprintf(filename, "rew_ev_estimate.%d", nstore); + ofs = fopen(filename, "a"); + for (ii = 0; ii < max_ev.s; ii++) + { + fprintf(ofs, "%d %e 1\n", ii, max_ev.el[ii]); + } + for (ii = 0; ii < min_ev.s; ii++) + { + fprintf(ofs, "%d %e 1\n", ii, min_ev.el[ii]); + } + fclose(ofs); + } + free(min_ev.el); + free(max_ev.el); #else - fprintf(stderr, "lapack not available, so JD method for EV computation not available \n"); + fprintf ( + stderr, + "lapack not available, so JD method for EV computation not available \n"); #endif } -static int invert_operator_Q(spinor * const P, spinor * const Q, - const int op_id, const int pm) { - - 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) { +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); + to_temporalgauge(g_gauge_field, source , P); #endif - iteration_count = linsolve_eo_gpu(P, source, max_iter, eps_sq, rel_prec, n, f); + iteration_count = linsolve_eo_gpu(P, source, max_iter, eps_sq, rel_prec, n, f); #ifdef TEMPORALGAUGE - from_temporalgauge(source, P); + 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); - } + 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) - iteration_count = MG_solver(P, source, eps_sq, max_iter,rel_prec, n , g_gauge_field, f); + 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); + 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); } -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); +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); } -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); +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); } -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; +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; } /*Trivial test tests the function with the scaled idenetity matrix.*/ /*#define TRIVIAL_TEST*/ /*Convergence chesk: comparison of order n and n+1.*/ #define CHECK_CONVERGENCE -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; +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; #ifdef CHECK_CONVERGENCE - spinor * unm1; - double prodrenm1; + spinor * unm1; + double prodrenm1; #endif - 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]; + 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]; #ifdef CHECK_CONVERGENCE - unm1 = spinorarray.ar[8]; + unm1 = spinorarray.ar[8]; #endif - 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) { - set_zero(u, n); + 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) + { + set_zero (u, n); #ifdef CHECK_CONVERGENCE - set_zero(unm1, n); + set_zero (unm1, n); #endif - } - /* - * 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); + } + /* + * 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); + 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); + 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); + /* 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); + mul_r(vt1,kappa2,vs1,n); #else - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); - optr->applyQsq(vt1, vs); + 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); + /* 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); + 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); #ifdef CHECK_CONVERGENCE - if (orderend > 1) { - mul_diff_mul_r(unm1, vt1, v1, coeff[1], coeff[1], n); - } + if (orderend > 1) + { + mul_diff_mul_r (unm1, vt1, v1, coeff[1], coeff[1], n); + } #endif - } + } - /*This part is only more efficient if not the clover term h - * as to be recompted everytime the parameters are changed.*/ + /*This part is only more efficient if not the clover term h + * as to be recompted everytime the parameters are changed.*/ #if 0 - for (l = 1; l + 1 < orderend; l++) { + for (l = 1; l + 1 < orderend; l++) + { #ifndef TRIVIAL_TEST - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters(operatorid); + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); - optr->applyQsq(v2, v1); + optr->applyQsq(v2, v1); #else - mul_r(v2,kappa1,v1,n); + mul_r(v2,kappa1,v1,n); #endif - if(l+1>=orderstart) { - /* 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) + { + /* 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; #ifndef TRIVIAL_TEST - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); - optr->applyQsq(vt2, vt1); + optr->applyQsq(vt2, vt1); #else - mul_r(vt2,kappa2,vt1,n); + mul_r(vt2,kappa2,vt1,n); #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) { - /* (*R) = (*R) + c1*(*S) + c2*(*U) */ - assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], - -coeff[l + 1], n); - } - - } + /* 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) + { + /* (*R) = (*R) + c1*(*S) + c2*(*U) */ + assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], + -coeff[l + 1], n); + } + + } #endif #ifndef TRIVIAL_TEST - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters(operatorid); + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters (operatorid); #endif - for (l = 1; l + 1 < orderend; l++) { + for (l = 1; l + 1 < orderend; l++) + { #ifdef TRIVIAL_TEST - mul_r(v2,kappa1,v1,n); + mul_r(v2,kappa1,v1,n); #else - optr->applyQsq(v2, v1); + 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); + /* 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); #ifdef CHECK_CONVERGENCE - if (l + 2 < orderend) { - assign_add_mul_r(unm1, v1, -coeff[l + 1], n); - } + if (l + 2 < orderend) + { + assign_add_mul_r (unm1, v1, -coeff[l + 1], n); + } #endif - } - } + } + } #ifndef TRIVIAL_TEST - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters (operatorid); #endif - for (l = 1; l + 1 < orderend; l++) { + for (l = 1; l + 1 < orderend; l++) + { #ifdef TRIVIAL_TEST - mul_r(vt2,kappa2,vt1,n); + mul_r(vt2,kappa2,vt1,n); #else - optr->applyQsq(vt2, vt1); + 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); + /* 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); #ifdef CHECK_CONVERGENCE - if (l + 2 < orderend) { - assign_add_mul_r(unm1, vt1, coeff[l + 1], n); - } + if (l + 2 < orderend) + { + assign_add_mul_r (unm1, vt1, coeff[l + 1], n); + } #endif - } - } + } + } - prodre = scalar_prod_r(vs, u, n, 1); + prodre = scalar_prod_r (vs, u, n, 1); #ifdef CHECK_CONVERGENCE - prodrenm1 = scalar_prod_r(vs, unm1, n, 1); + prodrenm1 = scalar_prod_r (vs, unm1, n, 1); #endif - 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); + 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); #ifdef CHECK_CONVERGENCE - fprintf(ofs, " %.17g \n", prodrenm1 + rel_shift); + fprintf (ofs, " %.17g \n", prodrenm1 + rel_shift); #endif - fclose(ofs); - } - - } /* estimator iteration*/ - } /* orderend>0*/ - } /* splitlength loop */ - free(coeff); - free_spinor_field(&spinorarray); + fclose (ofs); + } + + } /* estimator iteration*/ + } /* orderend>0*/ + } /* splitlength loop */ + free (coeff); + free_spinor_field (&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 kapparew; - int murew; +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; #ifdef CHECK_OPERATOR - double checkg5,check1,check2,check3,check4,check5; - double kappa_old; + double checkg5,check1,check2,check3,check4,check5; + double kappa_old; #endif - /* now we bring it to normal format */ - /* here we use implicitly DUM_MATRIX and DUM_MATRIX+1 */ - spinor * lexicfield1; - spinor * lexicfield2; + /* now we bring it to normal format */ + /* here we use implicitly DUM_MATRIX and DUM_MATRIX+1 */ + spinor * lexicfield1; + spinor * lexicfield2; #ifdef CHECK_OPERATOR - spinor * lexicfield3; - spinor * lexicfield4; + spinor * lexicfield3; + spinor * lexicfield4; #endif - int operatorid; - int numsamples, snum, internum; - unsigned long int site; - - param = (reweighting_parameter*) measurement_list[id].parameter; - lexicfield1 = g_spinor_field[4]; - lexicfield2 = g_spinor_field[6]; + 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]; #ifdef CHECK_OPERATOR - lexicfield3=g_spinor_field[8]; - lexicfield4=g_spinor_field[10]; + lexicfield3=g_spinor_field[8]; + lexicfield4=g_spinor_field[10]; #endif - 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.\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; - - for (internum = 0; internum < param->interpolationsteps; internum++) { - if (kapparew) { - kappa0 = kappa; - tmp1=1.0/kappainitial; - tmp2=1.0/kappafinal; - tmp3=1.0/kappa; - interpolate(&tmp3, tmp1,tmp2, - param->interpolationsteps, internum); - kappa=1.0/tmp3; - } - 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); - } - k2mu = 2.0 * kappa * rmu; - k2mu0 = 2.0 * kappa0 * rmu0; - 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); + 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.\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; + + for (internum = 0; internum < param->interpolationsteps; internum++) + { + if (kapparew) + { + kappa0 = kappa; + tmp1 = 1.0 / kappainitial; + tmp2 = 1.0 / kappafinal; + tmp3 = 1.0 / kappa; + 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; + 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); #ifdef CHECK_OPERATOR - for(site = 0; site < VOLUME; site++) { - _gamma5(lexicfield2[site], lexicfield1[site]); - } - checkg5=scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); /* should be zero*/ - - kappa_old=optr->kappa; - optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); /* prop=D rand*/ - mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2);/*correct normalisation*/ - mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); - convert_eo_to_lexic(lexicfield2, optr->prop0, optr->prop1); - check1 = -scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); - check2 = -scalar_prod_i(lexicfield1,lexicfield2,VOLUME, 1); - check3 = scalar_prod_r(lexicfield2,lexicfield2,VOLUME ,1); - - optr->kappa=1.0/(1.0/kappa_old+2.0); - optr->inverter(operatorid,0,0); /* to ensure that everything is updated*/ - optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); - mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2); - mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); - convert_eo_to_lexic(lexicfield3, optr->prop0, optr->prop1); - check1 += scalar_prod_r(lexicfield1,lexicfield3,VOLUME, 1); - check2 += scalar_prod_i(lexicfield1,lexicfield3,VOLUME, 1); - diff(lexicfield4,lexicfield3,lexicfield2,VOLUME); - check4=scalar_prod_r(lexicfield1,lexicfield1,VOLUME, 1); - check5=square_norm(lexicfield1,VOLUME ,1); - - optr->kappa=kappa_old; + for(site = 0; site < VOLUME; site++) + { + _gamma5(lexicfield2[site], lexicfield1[site]); + } + checkg5=scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); /* should be zero*/ + + kappa_old=optr->kappa; + optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); /* prop=D rand*/ + mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2);/*correct normalisation*/ + mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); + convert_eo_to_lexic(lexicfield2, optr->prop0, optr->prop1); + check1 = -scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); + check2 = -scalar_prod_i(lexicfield1,lexicfield2,VOLUME, 1); + check3 = scalar_prod_r(lexicfield2,lexicfield2,VOLUME ,1); + + optr->kappa=1.0/(1.0/kappa_old+2.0); + optr->inverter(operatorid,0,0); /* to ensure that everything is updated*/ + optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); + mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2); + mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); + convert_eo_to_lexic(lexicfield3, optr->prop0, optr->prop1); + check1 += scalar_prod_r(lexicfield1,lexicfield3,VOLUME, 1); + check2 += scalar_prod_i(lexicfield1,lexicfield3,VOLUME, 1); + diff(lexicfield4,lexicfield3,lexicfield2,VOLUME); + check4=scalar_prod_r(lexicfield1,lexicfield1,VOLUME, 1); + check5=square_norm(lexicfield1,VOLUME ,1); + + optr->kappa=kappa_old; #endif - 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); + 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); #ifdef CHECK_OPERATOR - fprintf( ofs_full, "%e %e %e %e %e %e %e %e %e %e %e %e\n", square1, square2,prodre,prodim,prodreg5,prodimg5,checkg5,check1,check2,check3,check4,check5); + fprintf( ofs_full, "%e %e %e %e %e %e %e %e %e %e %e %e\n", square1, square2,prodre,prodim,prodreg5,prodimg5,checkg5,check1,check2,check3,check4,check5); #else - /*print all raw data for cross check*/ - fprintf(ofs_full, - "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", 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); - } + /*print all raw data for cross check*/ + fprintf (ofs_full, + "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", 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); + } #endif - 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); - - 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, - "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", 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; + 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, + "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", 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; } -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); - param->coeff.el = NULL; - param->coeff.s = 0; - param->splitlist.ord = NULL; - param->splitlist.est = NULL; - param->splitlist.s = 0; +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); + param->coeff.el = NULL; + param->coeff.s = 0; + param->splitlist.ord = NULL; + param->splitlist.est = NULL; + param->splitlist.s = 0; } -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]); - } - } - } else { - if (g_proc_id == 0) { - printf("File coeff.dat not present.\n"); - } - v->el = NULL; - v->s = 0; - } +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]); + } + } + } + else + { + if (g_proc_id == 0) + { + printf ("File coeff.dat not present.\n"); + } + v->el = NULL; + v->s = 0; + } } -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]); - } - } - } 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_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]); + } + } + } + else + { + if (g_proc_id == 0) + { + printf ("File split.dat not present.\n"); + } + list->ord = NULL; + list->est = NULL; + list->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->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); - } +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->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); + } } From 449e95205eff90784680b9ac56d63b8a8a2ca887 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Thu, 2 Mar 2017 15:51:10 +0100 Subject: [PATCH 13/22] change of DDalphaAMG interface to allow for kappa change --- DDalphaAMG_interface.c | 9 ++++++--- meas/reweightingmeas.c | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/DDalphaAMG_interface.c b/DDalphaAMG_interface.c index 3904a2e79..89959b5cb 100644 --- a/DDalphaAMG_interface.c +++ b/DDalphaAMG_interface.c @@ -537,11 +537,14 @@ void MG_update_kappa(double kappa) return; } DDalphaAMG_get_parameters(&mg_params); - if (kappa!= mg_params.kappa) { - mg_params.kappa=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); - } + // DDalphaAMG_setup(&mg_status); + } } void MG_reset() { diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index e8a54ab43..2795d3100 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -578,10 +578,20 @@ invert_operator_Q (spinor * const P, spinor * const Q, const int op_id, return (iteration_count); } +//#define DEBUG_PARAMETER_CHANGE + static void interpolate (double * const rcurrent, const double rinitial, const double rfinal, const int numsteps, const int thisstep) { +#ifdef DEBUG_PARAMETER_CHANGE + if(thisstep==1){ + (*rcurrent)=100; + }else{ + (*rcurrent)=10; + } + return; +#endif (*rcurrent) = rinitial + (thisstep + 1) * (rfinal - rinitial) / ((double) numsteps); } @@ -1316,7 +1326,7 @@ reweighting_measurement (const int traj, const int id, const int ieo) #else /*print all raw data for cross check*/ fprintf (ofs_full, - "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", k2mu0, + "%.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, @@ -1374,7 +1384,7 @@ reweighting_measurement (const int traj, const int id, const int ieo) fprintf (ofs_full, "%d %d %d %d ", traj, operatorid, internum, snum); fprintf (ofs_full, - "%.6g %.6g %.6g %.6g %.6g %.6g %.6g %.6g ", k2mu0, + "%.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); From 1d63bb927c8090f173056311c508794ba740d6c0 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Wed, 19 Apr 2017 17:12:18 +0200 Subject: [PATCH 14/22] removed eigenvalue calculation (unsafe) --- meas/reweightingmeas.c | 154 +---------------------------------------- 1 file changed, 2 insertions(+), 152 deletions(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index 2795d3100..ae119e84a 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -260,156 +260,6 @@ update_global_parameters (const int op_id) }/*clover leave update*/ } -static void -estimate_eigenvalues (const int operatorid, const int identifier) -{ -#ifdef HAVE_LAPACK - vector_list min_ev; - vector_list max_ev; - spinor * eigenvectors_ = NULL; - char filename[200]; - FILE * ofs; - double atime, etime; - int max_iterations = 5000; - double prec = 1.e-5; - int maxvectors; - /********************** - * For Jacobi-Davidson - **********************/ - int verbosity = g_debug_level, converged = 0, blocksize = 1, blockwise = 0; - int solver_it_max = 50, j_max, j_min, ii; - /*int it_max = 10000;*/ - /* _Complex double *eigv_ = NULL, *eigv; */ - double decay_min = 1.7, decay_max = 1.5, threshold_min = 1.e-3, - threshold_max = 5.e-2; - double ev_max, ev_min; - - /* static int v0dim = 0; */ - int v0dim = 0; - int N = (VOLUME) / 2, N2 = (VOLUMEPLUSRAND) / 2; - operator * optr; - - /********************** - * General variables - **********************/ - int returncode = 0; - int returncode2 = 0; - - min_ev.s = 2; - min_ev.el = malloc(min_ev.s * sizeof(double)); - max_ev.s = 2; - max_ev.el = malloc(max_ev.s * sizeof(double)); - - optr = &operator_list[operatorid]; - - if (!is_schur_complement(optr->applyQsq)) - { - N = VOLUME; - N2 = VOLUMEPLUSRAND; - } - - evlength = N2; - if (g_proc_id == g_stdio_proc && g_debug_level > 0) - { - printf("Number of eigenvalues to compute = %d %d\n", min_ev.s, - max_ev.s); - printf("Using Jacobi-Davidson method! \n"); - } - - if (max_ev.s < 8) - { - j_max = 15; - j_min = 8; - } - else - { - j_max = 2 * max_ev.s; - j_min = max_ev.s; - } - - maxvectors = min_ev.s > max_ev.s ? min_ev.s : max_ev.s; - -#if (defined SSE || defined SSE2 || defined SSE3) - eigenvectors_ = calloc(N2*maxvectors+1, sizeof(spinor)); - eigenvectors = (spinor *)(((unsigned long int)(eigenvectors_)+ALIGN_BASE)&~ALIGN_BASE); -#else - eigenvectors_ = calloc(N2 * maxvectors, sizeof(spinor)); - eigenvectors = eigenvectors_; -#endif - - atime = gettime(); - - update_global_parameters(operatorid); - /* (re-) compute minimal eigenvalues */ - converged = 0; - solver_it_max = 200; - - jdher(N * sizeof(spinor) / sizeof(_Complex double), - N2 * sizeof(spinor) / sizeof(_Complex double), 50., prec, max_ev.s, - j_max, j_min, max_iterations, blocksize, blockwise, v0dim, - (_Complex double*) eigenvectors, CG, solver_it_max, threshold_max, - decay_max, verbosity, &converged, (_Complex double*) eigenvectors, - max_ev.el, &returncode, JD_MAXIMAL, 1, optr->applyQsq); - - max_ev.s = converged; - - if (min_ev.s < 8) - { - j_max = 15; - j_min = 8; - } - else - { - j_max = 2 * min_ev.s; - j_min = min_ev.s; - } - - converged = 0; - solver_it_max = 200; - - jdher(N * sizeof(spinor) / sizeof(_Complex double), - N2 * sizeof(spinor) / sizeof(_Complex double), 0., prec, min_ev.s, - j_max, j_min, max_iterations, blocksize, blockwise, v0dim, - (_Complex double*) eigenvectors, CG, solver_it_max, threshold_min, - decay_min, verbosity, &converged, (_Complex double*) eigenvectors, - min_ev.el, &returncode2, JD_MINIMAL, 1, optr->applyQsq); - - min_ev.s = converged; - - free(eigenvectors_); - - etime = gettime(); - if (g_proc_id == 0) - { - printf("Eigenvalues computed in %e sec. gettime)\n", etime - atime); - } - - ev_min = min_ev.el[min_ev.s - 1]; - ev_max = max_ev.el[max_ev.s - 1]; - eigenvalues_for_cg_computed = converged; - - if (g_proc_id == 0) - { - sprintf(filename, "rew_ev_estimate.%d", nstore); - ofs = fopen(filename, "a"); - for (ii = 0; ii < max_ev.s; ii++) - { - fprintf(ofs, "%d %e 1\n", ii, max_ev.el[ii]); - } - for (ii = 0; ii < min_ev.s; ii++) - { - fprintf(ofs, "%d %e 1\n", ii, min_ev.el[ii]); - } - fclose(ofs); - } - free(min_ev.el); - free(max_ev.el); -#else - fprintf ( - stderr, - "lapack not available, so JD method for EV computation not available \n"); -#endif -} static int invert_operator_Q (spinor * const P, spinor * const Q, const int op_id, @@ -1189,9 +1039,9 @@ reweighting_measurement (const int traj, const int id, const int ieo) { if (g_proc_id == 0) { - printf ("Calculating minimal/maximal eigenvalue estimates.\n"); + printf ("Calculating minimal/maximal eigenvalue estimates -- no longer supported!\n"); } - estimate_eigenvalues (operatorid, traj); + //estimate_eigenvalues (operatorid, traj); } if (param->use_cheb) From d7e232f5f5026b8ec7b752cf4320420d49b8cf8d Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Tue, 25 Apr 2017 14:36:56 +0200 Subject: [PATCH 15/22] reverted chenges --- configure.in | 10 +++++----- doc/main.tex | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/configure.in b/configure.in index 7f4cbf4fd..0de7058e5 100644 --- a/configure.in +++ b/configure.in @@ -23,11 +23,11 @@ AC_F77_LIBRARY_LDFLAGS AC_CHECK_TOOL(AR, ar, [ar]) LIBS="$LIBS $FLIBS -lm" -#AC_PROG_LEX -#dnl AC_PROG_LEX sets $LEX to ":" if neither lex nor flex are found! -#if test "$LEX" = ":"; then -# AC_MSG_ERROR([(F)LEX is required for building read_input.c. Please install it and run configure again.]) -#fi +AC_PROG_LEX +dnl AC_PROG_LEX sets $LEX to ":" if neither lex nor flex are found! +if test "$LEX" = ":"; then + AC_MSG_ERROR([(F)LEX is required for building read_input.c. Please install it and run configure again.]) +fi AC_PROG_MAKE_SET AC_PROG_RANLIB diff --git a/doc/main.tex b/doc/main.tex index 40199f486..1da97e7f2 100644 --- a/doc/main.tex +++ b/doc/main.tex @@ -1,4 +1,5 @@ -\documentclass[a4paper,12pt,dvips]{article} +\documentclass[a4paper,12pt]{article} +\usepackage{graphicx} %amsmath \usepackage{amssymb} \usepackage{amsmath} @@ -61,15 +62,15 @@ \section{Implementation} \myinput{components} \myinput{test} -\myinput{eo_pre} -\myinput{martins-trick} -\myinput{deflation} -\myinput{c-code} -\myinput{integrationschemes} +%\myinput{eo_pre} +%\myinput{martins-trick} +%\myinput{deflation} +%\myinput{c-code} +%\myinput{integrationschemes} -\myinput{parallel} -\myinput{operator} -\myinput{online} +%\myinput{parallel} +%\myinput{operator} +%\myinput{online} \section{File Formats and IO} \myinput{prop_format.tex} From 8cdf1fe478a3349dacf9d02f24336f2fdcd48a9b Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Tue, 25 Apr 2017 14:42:01 +0200 Subject: [PATCH 16/22] indentation issue --- meas/measurements.h | 56 +++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/meas/measurements.h b/meas/measurements.h index f0045ef74..e47f9908a 100644 --- a/meas/measurements.h +++ b/meas/measurements.h @@ -30,68 +30,64 @@ #define max_no_measurements 20 /* Give the measurement types an unambiguous ID*/ -enum MEAS_TYPE { - ONLINE, - PIONNORM, - POLYAKOV, - ORIENTED_PLAQUETTES, - GRADIENT_FLOW, - REWEIGHTING - }; +enum MEAS_TYPE +{ + ONLINE, PIONNORM, POLYAKOV, ORIENTED_PLAQUETTES, GRADIENT_FLOW, REWEIGHTING +}; - - - -typedef struct { +typedef struct +{ enum MEAS_TYPE type; int initialised; int id; - + /* for polyakov loop */ int direction; - + /* for maximal iterations in inversions for correlators */ int max_iter; - // random seed unsigned int seed; - /* maximum number of slice, the source can be put - if the correlator is measured in T(Z)-direction this will be set to - T(LZ) by init_measurements - */ + if the correlator is measured in T(Z)-direction this will be set to + T(LZ) by init_measurements + */ int max_source_slice; - void* parameter; /* frequency of the measurement */ int freq; - /* how it's usually called */ char name[100]; - + /* functions for the measurement */ - void (*measurefunc) (const int traj, const int id, const int ieo); - void (*destructor)(void* param); + 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 default_destructor(void* ptr); +void +dummy_meas (const int traj, const int id, const int ieo); +void +default_destructor (void* ptr); #endif From 6c87d09280b0037fa8aace37dc2e2bd76242d720 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Tue, 25 Apr 2017 15:25:00 +0200 Subject: [PATCH 17/22] changed includes --- meas/reweightingmeas.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index ae119e84a..5c7c42fef 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -36,30 +36,20 @@ #include "invert_eo.h" #include "solver/solver.h" #include "geometry_eo.h" -#include "linalg/convert_eo_to_lexic.h" #include "measurements.h" #include "correlators.h" #include "gettime.h" -#include "linalg/square_norm.h" -#include "linalg/scalar_prod_r.h" -#include "linalg/scalar_prod_i.h" -#include "linalg/diff.h" -#include "linalg/assign.h" -#include "linalg/mul_r.h" -#include "linalg/assign_mul_add_mul_r.h" +#include "linalg_eo.h" #include "linalg/mul_diff_mul_r.h" -#include "linalg/assign_mul_add_mul_add_mul_r.h" -#include "linalg/assign_add_mul_add_mul_r.h" -#include "linalg/assign_add_mul_r.h" -#include "linalg/set_even_to_zero.h" -#include "../read_input.h" -#include "reweightingmeas.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" From fe7a5b2a9c48de5fb16e09c261e3902ffa70e57f Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Fri, 2 Nov 2018 23:47:31 +0100 Subject: [PATCH 18/22] work on pull request --- DDalphaAMG_interface.c | 5 +- Makefile.in | 6 +- meas/measurements.h | 6 - meas/reweightingmeas.c | 1687 ++++++++++--------------- measure.c | 492 ------- monomial/Makefile.in | 1 - monomial/cloverdetratio_rwdmonomial.c | 103 -- monomial/cloverdetratio_rwdmonomial.h | 31 - monomial/monomial.c | 11 - monomial/monomial.h | 1 - read_input.l | 5 - 11 files changed, 688 insertions(+), 1660 deletions(-) delete mode 100644 measure.c delete mode 100644 monomial/cloverdetratio_rwdmonomial.c delete mode 100644 monomial/cloverdetratio_rwdmonomial.h diff --git a/DDalphaAMG_interface.c b/DDalphaAMG_interface.c index e844c5994..c677b0b1a 100644 --- a/DDalphaAMG_interface.c +++ b/DDalphaAMG_interface.c @@ -533,6 +533,10 @@ 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){ @@ -545,7 +549,6 @@ void MG_update_kappa(double kappa) } mg_params.kappa=kappa; DDalphaAMG_update_parameters(&mg_params, &mg_status); - // DDalphaAMG_setup(&mg_status); } } diff --git a/Makefile.in b/Makefile.in index 67d91b568..7a16f3ccf 100644 --- a/Makefile.in +++ b/Makefile.in @@ -74,7 +74,7 @@ NOOPTMOD = test/check_xchange test/check_geometry PROGRAMS = hmc_tm benchmark invert gen_sources \ check_locallity test_lemon hopping_test LapH_ev \ - offline_measurement measure @QPHIX_PROGRAMS@ + offline_measurement @QPHIX_PROGRAMS@ ALLOBJ = ${MODULES} ${PROGRAMS} ${SMODULES} SUBDIRS = ${USESUBDIRS} @@ -83,7 +83,7 @@ SUBDIRS = ${USESUBDIRS} .SUFFIXES: # need to build modules before subdirs! -all: Makefile dep $(SUBDIRS) hmc_tm invert benchmark offline_measurement measure @QPHIX_PROGRAMS@ +all: Makefile dep $(SUBDIRS) hmc_tm invert benchmark offline_measurement @QPHIX_PROGRAMS@ $(SUBDIRS): $(MAKE) --directory=$@ @@ -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/measurements.h b/meas/measurements.h index a12b3a3e8..7a036a6e8 100644 --- a/meas/measurements.h +++ b/meas/measurements.h @@ -50,12 +50,6 @@ typedef struct // random seed unsigned int seed; - /* maximum number of slice, the source can be put - if the correlator is measured in T(Z)-direction this will be set to - T(LZ) by init_measurements - */ - int max_source_slice; - void* parameter; /* frequency of the measurement */ diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index 5c7c42fef..b887dc213 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -60,127 +60,46 @@ # include #endif -/*#define CHECK_OPERATOR*/ -typedef struct -{ +/* + * 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; -static void -set_zero (spinor * const R, const int N) -{ -#ifdef TM_USE_OMP -#pragma omp parallel - { -#endif - - int ix; - spinor *r; - -#ifdef TM_USE_OMP -#pragma omp for -#endif - for (ix = 0; ix < N; ++ix) - { - r = (spinor *) R + ix; - - r->s0.c0 = 0.0; - r->s0.c1 = 0.0; - r->s0.c2 = 0.0; - - r->s1.c0 = 0.0; - r->s1.c1 = 0.0; - r->s1.c2 = 0.0; - - r->s2.c0 = 0.0; - r->s2.c1 = 0.0; - r->s2.c2 = 0.0; - - r->s3.c0 = 0.0; - r->s3.c1 = 0.0; - r->s3.c2 = 0.0; - } -#ifdef TM_USE_OMP -} /* OpenMP closing brace */ -#endif -} - -static int -alloc_spinor_field (spinor_array* ar, int evenodd) -{ +/* + * Allocation of the spinor field redirects to allocate_spinor_field_array. + */ +static int alloc_spinor_field(spinor_array* ar, int evenodd) { int i = 0; unsigned long int volume = VOLUMEPLUSRAND / 2; - if (evenodd == 0) - { - volume = VOLUMEPLUSRAND; - } - if (ar->buffer != NULL || ar->ar != NULL || ar->length == 0) - { - return (3); - } -#if (defined _USE_SHMEM && !(defined _USE_HALFSPINOR)) - if((void*)(ar->buffer = (spinor*)shmalloc((ar->length*volume+1)*sizeof(spinor))) == NULL) - { - printf ("malloc errno : %d\n",errno); - errno = 0; - return(1); - } -#else - if ((void*) (ar->buffer = (spinor*) calloc (ar->length * volume + 1, - sizeof(spinor))) == NULL) - { - printf ("malloc errno : %d\n", errno); - errno = 0; - return (1); - } -#endif - if ((void*) (ar->ar = (spinor**) malloc (ar->length * sizeof(spinor*))) - == NULL) - { - printf ("malloc errno : %d\n", errno); - errno = 0; - return (2); - } -#if ( defined SSE || defined SSE2 || defined SSE3) - ar->ar = (spinor*)(((unsigned long int)(ar->buffer)+ALIGN_BASE)&~ALIGN_BASE); -#else - ar->ar[0] = ar->buffer; -#endif - - for (i = 1; i < ar->length; i++) - { - ar->ar[i] = g_spinor_field[i - 1] + volume; - } - - return (0); + if (evenodd == 0) { + volume = VOLUMEPLUSRAND; + } + return (allocate_spinor_field_array(&ar->ar,&ar->buffer,volume, ar->length)); } -static void -free_spinor_field (spinor_array* ar) -{ - if (ar->buffer != NULL) - { -#if (defined _USE_SHMEM && !(defined _USE_HALFSPINOR)) - shfree(ar->buffer); -#else - free (ar->buffer); -#endif - } - if (ar->ar != NULL) - { - free (ar->ar); - } +static void free_spinor_field(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; } -static int -is_schur_complement (const matrix_mult f) -{ +/* + * 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 @@ -192,69 +111,68 @@ is_schur_complement (const matrix_mult f) 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; - } + f == Qsw_pm_psi) { // Schur complement squared + return 1; + } return 0; } -static double -get_sw_reweighting (const double mu1, const double mu2, const double kappa1, - const double kappa2, const double csw1, const double csw2) -{ +/* + * 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); + 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) -{ +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; - } + f == Qsw_pm_psi || f == Q_pm_psi) { // Full operator squared + return 1; + } return 0; } -static void -update_global_parameters (const int op_id) -{ +/* + * 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); + 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*/ + 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*/ } - -static int -invert_operator_Q (spinor * const P, spinor * const Q, const int op_id, - const int pm, int updateparameters) -{ +/* + * 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; @@ -266,240 +184,198 @@ invert_operator_Q (spinor * const P, spinor * const Q, const int op_id, matrix_mult f = optr->applyQm; int is_squared = 0; spinor * source = Q; - if (pm == 1) - { - f = optr->applyQp; - } + 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; - } + 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]; - } - } + 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); - } + 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 (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; - if (usegpu_flag) - { + // 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); + to_temporalgauge(g_gauge_field, source , P); #endif - iteration_count = linsolve_eo_gpu(P, source, max_iter, eps_sq, rel_prec, n, f); + iteration_count = linsolve_eo_gpu(P, source, max_iter, eps_sq, rel_prec, n, f); #ifdef TEMPORALGAUGE - from_temporalgauge(source, P); + 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); + 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) { - 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); + 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; - } + 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); + 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); - } + if (g_proc_id == 0) { + printf("Inversion final precision %e\n", check_prec); + } return (iteration_count); } -//#define DEBUG_PARAMETER_CHANGE - -static void -interpolate (double * const rcurrent, const double rinitial, - const double rfinal, const int numsteps, const int thisstep) -{ -#ifdef DEBUG_PARAMETER_CHANGE - if(thisstep==1){ - (*rcurrent)=100; - }else{ - (*rcurrent)=10; - } - return; -#endif +/* + * 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); } -static void -chebyshev_coeff (const unsigned int np, double * const coeff, const double a, - const double b) -{ +/* + * 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)); + 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]; - } + 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); + } + free(fxk); + free(acxk); } -static double -poly_cheb (const unsigned int np, const double * const coeff, const double x) -{ +/* + * 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; - } + 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; - } + for (j = 1; j + 1 < np; j++) { + t2 = 2.0 * x * t1 - t0; + t0 = t1; + t1 = t2; + y += coeff[j + 1] * t1; + } return y; } -/*Trivial test tests the function with the scaled idenetity matrix.*/ +/* + * 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 chesk: comparison of order n and n+1.*/ -#define CHECK_CONVERGENCE -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) -{ +/*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; @@ -517,10 +393,11 @@ log_determinant_estimate (const int operatorid, int chebmax, int estimators, FILE * ofs; spinor * vs; spinor * u; -#ifdef CHECK_CONVERGENCE + + // for convergence checks spinor * unm1; double prodrenm1; -#endif + spinor * v0; spinor * v1; spinor * v2; @@ -539,20 +416,17 @@ log_determinant_estimate (const int operatorid, int chebmax, int estimators, n = VOLUME; filename = buf; - sprintf (filename, "%s%.6d", "reweightingmeas_cheb.", traj); + 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); - } + 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]; @@ -562,288 +436,201 @@ log_determinant_estimate (const int operatorid, int chebmax, int estimators, vt0 = spinorarray.ar[5]; vt1 = spinorarray.ar[6]; vt2 = spinorarray.ar[7]; -#ifdef CHECK_CONVERGENCE + + // for convergence checks unm1 = spinorarray.ar[8]; -#endif - 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]; - } + 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); + } 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); } - 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); + 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]; + 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; } - 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); } - if (orderend > 0) - { - for (k = 0; k < estimators; k++) - { - if (orderstart > 1 || orderend < 2) - { - set_zero (u, n); -#ifdef CHECK_CONVERGENCE - set_zero (unm1, n); -#endif - } - /* - * 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); + 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); + 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); + 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); + /* 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); + 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); - -#ifdef CHECK_CONVERGENCE - if (orderend > 1) - { - mul_diff_mul_r (unm1, vt1, v1, coeff[1], coeff[1], n); - } + 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); - /*This part is only more efficient if not the clover term h - * as to be recompted everytime the parameters are changed.*/ -#if 0 - for (l = 1; l + 1 < orderend; l++) - { -#ifndef TRIVIAL_TEST - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters(operatorid); + 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); - optr->applyQsq(v2, v1); -#else - mul_r(v2,kappa1,v1,n); -#endif - if(l+1>=orderstart) - { - /* 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; + // convergence check + if (orderend > 1) { + mul_diff_mul_r(unm1, vt1, v1, coeff[1], coeff[1], n); + } -#ifndef TRIVIAL_TEST - optr->kappa = kappa2; - optr->mu = kappa2Mu2; - update_global_parameters(operatorid); - - optr->applyQsq(vt2, vt1); -#else - mul_r(vt2,kappa2,vt1,n); -#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) - { - /* (*R) = (*R) + c1*(*S) + c2*(*U) */ - assign_add_mul_add_mul_r(u, vt1, v1, coeff[l + 1], - -coeff[l + 1], n); - } - - } - -#endif + } #ifndef TRIVIAL_TEST - optr->kappa = kappa1; - optr->mu = kappa2Mu1; - update_global_parameters (operatorid); + optr->kappa = kappa1; + optr->mu = kappa2Mu1; + update_global_parameters(operatorid); #endif - for (l = 1; l + 1 < orderend; l++) - { + for (l = 1; l + 1 < orderend; l++) { #ifdef TRIVIAL_TEST - mul_r(v2,kappa1,v1,n); + mul_r(v2,kappa1,v1,n); #else - optr->applyQsq (v2, v1); + 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); -#ifdef CHECK_CONVERGENCE - if (l + 2 < orderend) - { - assign_add_mul_r (unm1, v1, -coeff[l + 1], n); - } -#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); + optr->kappa = kappa2; + optr->mu = kappa2Mu2; + update_global_parameters(operatorid); #endif - for (l = 1; l + 1 < orderend; l++) - { + for (l = 1; l + 1 < orderend; l++) { #ifdef TRIVIAL_TEST - mul_r(vt2,kappa2,vt1,n); + 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); -#ifdef CHECK_CONVERGENCE - if (l + 2 < orderend) - { - assign_add_mul_r (unm1, vt1, coeff[l + 1], n); - } + 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); -#ifdef CHECK_CONVERGENCE - prodrenm1 = scalar_prod_r (vs, unm1, n, 1); -#endif + } + } - 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); -#ifdef CHECK_CONVERGENCE - fprintf (ofs, " %.17g \n", prodrenm1 + rel_shift); -#endif - fclose (ofs); - } - - } /* estimator iteration*/ - } /* orderend>0*/ - } /* splitlength loop */ - free (coeff); - free_spinor_field (&spinorarray); + 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(&spinorarray); } -void -reweighting_measurement (const int traj, const int id, const int ieo) -{ +void reweighting_measurement(const int traj, const int id, const int ieo) { reweighting_parameter* param; double atime, etime; operator * optr; @@ -862,54 +649,41 @@ reweighting_measurement (const int traj, const int id, const int ieo) int updateinverter; int kapparew; int murew; -#ifdef CHECK_OPERATOR - double checkg5,check1,check2,check3,check4,check5; - double kappa_old; -#endif /* now we bring it to normal format */ /* here we use implicitly DUM_MATRIX and DUM_MATRIX+1 */ spinor * lexicfield1; spinor * lexicfield2; -#ifdef CHECK_OPERATOR - spinor * lexicfield3; - spinor * lexicfield4; -#endif + int operatorid; int numsamples, snum, internum; unsigned long int site; - updateinverter=0; + updateinverter = 0; param = (reweighting_parameter*) measurement_list[id].parameter; lexicfield1 = g_spinor_field[4]; lexicfield2 = g_spinor_field[6]; -#ifdef CHECK_OPERATOR - lexicfield3=g_spinor_field[8]; - lexicfield4=g_spinor_field[10]; -#endif + 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); - } + 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; + 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"); } - atime = gettime (); + return; + } + atime = gettime(); optr = &operator_list[operatorid]; optr->DownProp = 0; @@ -932,19 +706,16 @@ reweighting_measurement (const int traj, const int id, const int ieo) 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; - } + 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 @@ -952,111 +723,92 @@ reweighting_measurement (const int traj, const int id, const int ieo) 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; - } + 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 (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 (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 (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("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 (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"); - } + 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->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; - } + 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; @@ -1066,199 +818,145 @@ reweighting_measurement (const int traj, const int id, const int ieo) if (param->interpolationsteps < 1) param->interpolationsteps = 1; - for (internum = 0; internum < param->interpolationsteps; internum++) - { - if (kapparew) - { - kappa0 = kappa; - tmp1 = 1.0 / kappainitial; - tmp2 = 1.0 / kappafinal; - tmp3 = 1.0 / kappa; - interpolate (&tmp3, tmp1, tmp2, param->interpolationsteps, internum); - kappa = 1.0 / tmp3; - updateinverter=1; + for (internum = 0; internum < param->interpolationsteps; internum++) { + if (kapparew) { + kappa0 = kappa; + tmp1 = 1.0 / kappainitial; + tmp2 = 1.0 / kappafinal; + tmp3 = 1.0 / kappa; + 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; + 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]); } - 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; + 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); } - k2mu = 2.0 * kappa * rmu; - k2mu0 = 2.0 * kappa0 * rmu0; - 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); + } 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); } - 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); -#ifdef CHECK_OPERATOR - for(site = 0; site < VOLUME; site++) - { - _gamma5(lexicfield2[site], lexicfield1[site]); - } - checkg5=scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); /* should be zero*/ - - kappa_old=optr->kappa; - optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); /* prop=D rand*/ - mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2);/*correct normalisation*/ - mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); - convert_eo_to_lexic(lexicfield2, optr->prop0, optr->prop1); - check1 = -scalar_prod_r(lexicfield1,lexicfield2,VOLUME, 1); - check2 = -scalar_prod_i(lexicfield1,lexicfield2,VOLUME, 1); - check3 = scalar_prod_r(lexicfield2,lexicfield2,VOLUME ,1); - - optr->kappa=1.0/(1.0/kappa_old+2.0); - optr->inverter(operatorid,0,0); /* to ensure that everything is updated*/ - optr->applyM(optr->prop0, optr->prop1, optr->sr0, optr->sr1); - mul_r(optr->prop0, (0.5/optr->kappa), optr->prop0, VOLUME / 2); - mul_r(optr->prop1, (0.5/optr->kappa), optr->prop1, VOLUME / 2); - convert_eo_to_lexic(lexicfield3, optr->prop0, optr->prop1); - check1 += scalar_prod_r(lexicfield1,lexicfield3,VOLUME, 1); - check2 += scalar_prod_i(lexicfield1,lexicfield3,VOLUME, 1); - diff(lexicfield4,lexicfield3,lexicfield2,VOLUME); - check4=scalar_prod_r(lexicfield1,lexicfield1,VOLUME, 1); - check5=square_norm(lexicfield1,VOLUME ,1); - - optr->kappa=kappa_old; -#endif - 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); -#ifdef CHECK_OPERATOR - fprintf( ofs_full, "%e %e %e %e %e %e %e %e %e %e %e %e\n", square1, square2,prodre,prodim,prodreg5,prodimg5,checkg5,check1,check2,check3,check4,check5); -#else - /*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); - } -#endif - 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); - } + }/* 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; } -void -free_reweighting_parameter (void* par) -{ +void free_reweighting_parameter(void* par) { reweighting_parameter* param; param = (reweighting_parameter*) (par); if (param->coeff.el) - free (param->coeff.el); + free(param->coeff.el); if (param->splitlist.ord) - free (param->splitlist.ord); + free(param->splitlist.ord); if (param->splitlist.est) - free (param->splitlist.est); + free(param->splitlist.est); param->coeff.el = NULL; param->coeff.s = 0; param->splitlist.ord = NULL; @@ -1266,135 +964,112 @@ free_reweighting_parameter (void* par) param->splitlist.s = 0; } -static void -read_coeff_from_file (vector_list* v) -{ +static void read_coeff_from_file(vector_list* v) { FILE* file; unsigned int l; double dat; - file = fopen ("coeff.dat", "r"); + 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]); - } - } + if (file) { + while (fscanf(file, "%lg ", &dat) > 0) { + l++; } - else - { - if (g_proc_id == 0) - { - printf ("File coeff.dat not present.\n"); - } - v->el = NULL; - v->s = 0; + 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]); + } } + } else { + if (g_proc_id == 0) { + printf("File coeff.dat not present.\n"); + } + v->el = NULL; + v->s = 0; + } } -static void -read_splitlist (split_list* list) -{ +static void read_splitlist(split_list* list) { FILE* file; unsigned int l; int dat1, dat2; - file = fopen ("split.dat", "r"); + 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]); - } - } + if (file) { + while (fscanf(file, "%d ", &dat1) > 0 && fscanf(file, "%d ", &dat2) > 0) { + l++; } - else - { - if (g_proc_id == 0) - { - printf ("File split.dat not present.\n"); - } - list->ord = NULL; - list->est = NULL; - list->s = 0; + 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]); + } } + } else { + if (g_proc_id == 0) { + printf("File split.dat not present.\n"); + } + list->ord = NULL; + list->est = NULL; + list->s = 0; + } } -void -initialize_reweighting_parameter (void** parameter) -{ +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->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); - } + 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->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); + } } diff --git a/measure.c b/measure.c deleted file mode 100644 index d199e8b8b..000000000 --- a/measure.c +++ /dev/null @@ -1,492 +0,0 @@ -/*********************************************************************** - * - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Carsten Urbach - * - * 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 . - * - * adaption of the invert for twisted mass QCD to contain only a few number - * of relevant measurements by Georg Bergner 2016 (still ugly) - * - * Author: Carsten Urbach, Georg Bergner - * urbach@physik.fu-berlin.de - * - *******************************************************************************/ - -#include"lime.h" -#ifdef HAVE_CONFIG_H -# include -#endif -#include -#include -#include -#include -#include -#include -#ifdef TM_USE_MPI -#include -#endif -#ifdef TM_USE_OMP -# include -#endif -#include "global.h" -#include "git_hash.h" -#include "getopt.h" -#include "linalg_eo.h" -#include "geometry_eo.h" -#include "start.h" -/*#include "eigenvalues.h"*/ -#include "measure_gauge_action.h" -#ifdef TM_USE_MPI -#include "xchange/xchange.h" -#endif -#include -#include "source_generation.h" -#include "read_input.h" -#include "mpi_init.h" -#include "sighandler.h" -#include "boundary.h" -#include "solver/solver.h" -#include "init/init.h" -#include "smearing/stout.h" -#include "invert_eo.h" -#include "monomial/monomial.h" -#include "ranlxd.h" -#include "phmc.h" -#include "operator/D_psi.h" -#include "little_D.h" -#include "reweighting_factor.h" -#include "linalg/convert_eo_to_lexic.h" -#include "block.h" -#include "operator.h" -#include "sighandler.h" -#include "solver/generate_dfl_subspace.h" -#include "prepare_source.h" -#include -#include -#include -#include -#include "solver/dirac_operator_eigenvectors.h" -#include "source_generation.h" -#include "P_M_eta.h" -#include "operator/tm_operators.h" -#include "operator/Dov_psi.h" -#include "solver/spectral_proj.h" -#ifdef QUDA -# include "quda_interface.h" -#endif -#ifdef DDalphaAMG -# include "DDalphaAMG_interface.h" -#endif -#include "meas/measurements.h" -#include "source_generation.h" - - - -extern int nstore; -int check_geometry(); - -static void usage(); -static void process_args(int argc, char *argv[], char ** input_filename, char ** filename); -static void set_default_filenames(char ** input_filename, char ** filename); -static void invert_compute_modenumber(); - -int main(int argc, char *argv[]) -{ - FILE *parameterfile = NULL; - int j, i; - char datafilename[206]; - char parameterfilename[206]; - char conf_filename[300]; - char * input_filename = NULL; - char * filename = NULL; - double plaquette_energy; - struct stout_parameters params_smear; - -#ifdef _KOJAK_INST -#pragma pomp inst init -#pragma pomp inst begin(main) -#endif - -#if (defined SSE || defined SSE2 || SSE3) - signal(SIGILL, &catch_ill_inst); -#endif - - DUM_DERI = 8; - DUM_MATRIX = DUM_DERI + 5; /* 5 fields for doing the inversions (might be used by other operations if no inverter used*/ - NO_OF_SPINORFIELDS = DUM_MATRIX + 4; /* Don't access these fields if you apply multiplications!*/ - - //4 extra fields (corresponding to DUM_MATRIX+0..5) for deg. and ND matrix mult. - NO_OF_SPINORFIELDS_32 = 6; - - verbose = 0; - g_use_clover_flag = 0; - -#ifdef TM_USE_MPI - -# ifdef TM_USE_OMP - int mpi_thread_provided; - MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &mpi_thread_provided); -# else - MPI_Init(&argc, &argv); -# endif - - MPI_Comm_rank(MPI_COMM_WORLD, &g_proc_id); -#else - g_proc_id = 0; -#endif - - process_args(argc,argv,&input_filename,&filename); - set_default_filenames(&input_filename, &filename); - - /* Read the input file */ - if( (j = read_input(input_filename)) != 0) { - fprintf(stderr, "Could not find input file: %s\nAborting...\n", input_filename); - exit(-1); - } - -#ifdef TM_USE_OMP - init_openmp(); -#endif - - /* this DBW2 stuff is not needed for the inversion ! */ - if (g_dflgcr_flag == 1) { - even_odd_flag = 0; - } - g_rgi_C1 = 0; - if (Nsave == 0) { - Nsave = 1; - } - - if (g_running_phmc) { - NO_OF_SPINORFIELDS = DUM_MATRIX + 8; - } - - tmlqcd_mpi_init(argc, argv); - - g_dbw2rand = 0; - - /* starts the single and double precision random number */ - /* generator */ - start_ranlux(rlxd_level, random_seed^nstore); - - /* we need to make sure that we don't have even_odd_flag = 1 */ - /* if any of the operators doesn't use it */ - /* in this way even/odd can still be used by other operators */ - for(j = 0; j < no_operators; j++) if(!operator_list[j].even_odd_flag) even_odd_flag = 0; - -#ifndef TM_USE_MPI - g_dbw2rand = 0; -#endif - -#ifdef _GAUGE_COPY - j = init_gauge_field(VOLUMEPLUSRAND, 1); - j += init_gauge_field_32(VOLUMEPLUSRAND, 1); -#else - j = init_gauge_field(VOLUMEPLUSRAND, 0); - j += init_gauge_field_32(VOLUMEPLUSRAND, 0); -#endif - - if (j != 0) { - fprintf(stderr, "Not enough memory for gauge_fields! Aborting...\n"); - exit(-1); - } - j = init_geometry_indices(VOLUMEPLUSRAND); - if (j != 0) { - fprintf(stderr, "Not enough memory for geometry indices! Aborting...\n"); - exit(-1); - } - if (no_monomials > 0) { - if (even_odd_flag) { - j = init_monomials(VOLUMEPLUSRAND / 2, even_odd_flag); - } - else { - j = init_monomials(VOLUMEPLUSRAND, even_odd_flag); - } - if (j != 0) { - fprintf(stderr, "Not enough memory for monomial pseudo fermion fields! Aborting...\n"); - exit(-1); - } - } - if (even_odd_flag) { - j = init_spinor_field(VOLUMEPLUSRAND / 2, NO_OF_SPINORFIELDS); - j += init_spinor_field_32(VOLUMEPLUSRAND / 2, NO_OF_SPINORFIELDS_32); - } - else { - j = init_spinor_field(VOLUMEPLUSRAND, NO_OF_SPINORFIELDS); - j += init_spinor_field_32(VOLUMEPLUSRAND, NO_OF_SPINORFIELDS_32); - } - if (j != 0) { - fprintf(stderr, "Not enough memory for spinor fields! Aborting...\n"); - exit(-1); - } - - if (g_running_phmc) { - j = init_chi_spinor_field(VOLUMEPLUSRAND / 2, 20); - if (j != 0) { - fprintf(stderr, "Not enough memory for PHMC Chi fields! Aborting...\n"); - exit(-1); - } - } - - g_mu = g_mu1; - - if (g_cart_id == 0) { - /*construct the filenames for the observables and the parameters*/ - strncpy(datafilename, filename, 200); - strcat(datafilename, ".data"); - strncpy(parameterfilename, filename, 200); - strcat(parameterfilename, ".para"); - - parameterfile = fopen(parameterfilename, "w"); - write_first_messages(parameterfile, "invert", git_hash); - fclose(parameterfile); - } - - /* define the geometry */ - geometry(); - - /* define the boundary conditions for the fermion fields */ - boundary(g_kappa); - - phmc_invmaxev = 1.; - - init_operators(); - - /* list and initialize measurements*/ - if(g_proc_id == 0) { - printf("\n"); - for(int j = 0; j < no_measurements; j++) { - printf("# measurement id %d, type = %d\n", j, measurement_list[j].type); - } - } - init_measurements(); - - /* this could be maybe moved to init_operators */ -#ifdef _USE_HALFSPINOR - j = init_dirac_halfspinor(); - if (j != 0) { - fprintf(stderr, "Not enough memory for halffield! Aborting...\n"); - exit(-1); - } - /* for mixed precision solvers, the 32 bit halfspinor field must always be there */ - j = init_dirac_halfspinor32(); - if (j != 0) - { - fprintf(stderr, "Not enough memory for 32-bit halffield! Aborting...\n"); - exit(-1); - } -# if (defined _PERSISTENT) - if (even_odd_flag) - init_xchange_halffield(); -# endif -#endif - - for (j = 0; j < Nmeas; j++) { - sprintf(conf_filename, "%s.%.4d", gauge_input_filename, nstore); - if (g_cart_id == 0) { - printf("#\n# Trying to read gauge field from file %s in %s precision.\n", - conf_filename, (gauge_precision_read_flag == 32 ? "single" : "double")); - fflush(stdout); - } - if( (i = read_gauge_field(conf_filename,g_gauge_field)) !=0) { - fprintf(stderr, "Error %d while reading gauge field from %s\n Aborting...\n", i, conf_filename); - exit(-2); - } - - - if (g_cart_id == 0) { - printf("# Finished reading gauge field.\n"); - fflush(stdout); - } -#ifdef TM_USE_MPI - xchange_gauge(g_gauge_field); -#endif - /*Convert to a 32 bit gauge field, after xchange*/ - convert_32_gauge_field(g_gauge_field_32, g_gauge_field, VOLUMEPLUSRAND); - /*compute the energy of the gauge field*/ - plaquette_energy = measure_plaquette( (const su3**) g_gauge_field); - - if (g_cart_id == 0) { - printf("# The computed plaquette value is %e.\n", plaquette_energy / (6.*VOLUME*g_nproc)); - fflush(stdout); - } - - if (use_stout_flag == 1){ - params_smear.rho = stout_rho; - params_smear.iterations = stout_no_iter; -/* if (stout_smear((su3_tuple*)(g_gauge_field[0]), ¶ms_smear, (su3_tuple*)(g_gauge_field[0])) != 0) */ -/* exit(1) ; */ - g_update_gauge_copy = 1; - plaquette_energy = measure_plaquette( (const su3**) g_gauge_field); - - if (g_cart_id == 0) { - printf("# The plaquette value after stouting is %e\n", plaquette_energy / (6.*VOLUME*g_nproc)); - fflush(stdout); - } - } - - /* if any measurements are defined in the input file, do them here */ - measurement * meas; - for(int imeas = 0; imeas < no_measurements; imeas++){ - meas = &measurement_list[imeas]; - if (g_proc_id == 0) { - fprintf(stdout, "#\n# Beginning online measurement.\n"); - } - meas->measurefunc(nstore, imeas, even_odd_flag); - } - - if (reweighting_flag == 1) { - reweighting_factor(reweighting_samples, nstore); - } - - /* Compute minimal eigenvalues, if wanted */ - if (compute_evs != 0) { - eigenvalues(&no_eigenvalues, 5000, eigenvalue_precision, - 0, compute_evs, nstore, even_odd_flag); - } - if (phmc_compute_evs != 0) { -#ifdef TM_USE_MPI - MPI_Finalize(); -#endif - return(0); - } - - /* Compute the mode number or topological susceptibility using spectral projectors, if wanted*/ - if(compute_modenumber != 0 || compute_topsus !=0){ - invert_compute_modenumber(); - } - - - - nstore += Nsave; - } - -#ifdef TM_USE_OMP - free_omp_accumulators(); -#endif - free_blocks(); - free_dfl_subspace(); - free_gauge_field(); - free_gauge_field_32(); - free_geometry_indices(); - free_spinor_field(); - free_spinor_field_32(); - free_moment_field(); - free_chi_spinor_field(); - free(filename); - free(input_filename); - free(SourceInfo.basename); - free(PropInfo.basename); -#ifdef QUDA - _endQuda(); -#endif -#ifdef TM_USE_MPI - MPI_Barrier(MPI_COMM_WORLD); - MPI_Finalize(); -#endif - return(0); -#ifdef _KOJAK_INST -#pragma pomp inst end(main) -#endif -} - -static void usage() -{ - fprintf(stdout, "Inversion for EO preconditioned Wilson twisted mass QCD\n"); - fprintf(stdout, "Version %s \n\n", PACKAGE_VERSION); - fprintf(stdout, "Please send bug reports to %s\n", PACKAGE_BUGREPORT); - fprintf(stdout, "Usage: invert [options]\n"); - fprintf(stdout, "Options: [-f input-filename]\n"); - fprintf(stdout, " [-o output-filename]\n"); - fprintf(stdout, " [-v] more verbosity\n"); - fprintf(stdout, " [-h|-? this help]\n"); - fprintf(stdout, " [-V] print version information and exit\n"); - exit(0); -} - -static void process_args(int argc, char *argv[], char ** input_filename, char ** filename) { - int c; - while ((c = getopt(argc, argv, "h?vVf:o:")) != -1) { - switch (c) { - case 'f': - *input_filename = calloc(200, sizeof(char)); - strncpy(*input_filename, optarg, 200); - break; - case 'o': - *filename = calloc(200, sizeof(char)); - strncpy(*filename, optarg, 200); - break; - case 'v': - verbose = 1; - break; - case 'V': - if(g_proc_id == 0) { - fprintf(stdout,"%s %s\n",PACKAGE_STRING,git_hash); - } - exit(0); - break; - case 'h': - case '?': - default: - if( g_proc_id == 0 ) { - usage(); - } - break; - } - } -} - -static void set_default_filenames(char ** input_filename, char ** filename) { - if( *input_filename == NULL ) { - *input_filename = calloc(13, sizeof(char)); - strcpy(*input_filename,"invert.input"); - } - - if( *filename == NULL ) { - *filename = calloc(7, sizeof(char)); - strcpy(*filename,"output"); - } -} - -static void invert_compute_modenumber() { - spinor * s_ = calloc(no_sources_z2*VOLUMEPLUSRAND+1, sizeof(spinor)); - spinor ** s = calloc(no_sources_z2, sizeof(spinor*)); - if(s_ == NULL) { - printf("Not enough memory in %s: %d",__FILE__,__LINE__); exit(42); - } - if(s == NULL) { - printf("Not enough memory in %s: %d",__FILE__,__LINE__); exit(42); - } - for(int i = 0; i < no_sources_z2; i++) { - s[i] = (spinor*)(((unsigned long int)(s_)+ALIGN_BASE)&~ALIGN_BASE)+i*VOLUMEPLUSRAND; - random_spinor_field_lexic(s[i], reproduce_randomnumber_flag,RN_Z2); - - if(g_proc_id == 0) { - printf("source %d \n", i); - } - - if(compute_modenumber != 0){ - mode_number(s[i], mstarsq); - } - - if(compute_topsus !=0) { - top_sus(s[i], mstarsq); - } - } - free(s); - free(s_); -} - diff --git a/monomial/Makefile.in b/monomial/Makefile.in index 6e42ec316..e73a9ede2 100644 --- a/monomial/Makefile.in +++ b/monomial/Makefile.in @@ -33,7 +33,6 @@ LIBRARIES = libmonomial libmonomial_TARGETS = nddetratio_monomial monomial det_monomial detratio_monomial \ gauge_monomial ndpoly_monomial clover_trlog_monomial cloverdet_monomial cloverdetratio_monomial \ cloverdetratio_rwmonomial \ - cloverdetratio_rwdmonomial \ clovernd_trlog_monomial poly_monomial cloverndpoly_monomial moment_energy \ ndrat_monomial ndratcor_monomial rat_monomial ratcor_monomial monitor_forces diff --git a/monomial/cloverdetratio_rwdmonomial.c b/monomial/cloverdetratio_rwdmonomial.c deleted file mode 100644 index a06143124..000000000 --- a/monomial/cloverdetratio_rwdmonomial.c +++ /dev/null @@ -1,103 +0,0 @@ -/*********************************************************************** - * - * Copyright (C) 2012 Carsten Urbach - * - * Adaption with a more efficient inversion by Georg Bergner 2016 - * - * 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 "su3.h" -#include "start.h" -#include "gettime.h" -#include "linalg_eo.h" -#include "deriv_Sb.h" -#include "gamma.h" -#include "operator/tm_operators.h" -#include "operator/Hopping_Matrix.h" -#include "solver/chrono_guess.h" -#include "solver/solver.h" -#include "solver/monomial_solve.h" -#include "read_input.h" -#include "operator/clovertm_operators.h" -#include "operator/clovertm_operators_32.h" -#include "operator/clover_leaf.h" -#include "monomial/monomial.h" -#include "boundary.h" -#include "cloverdetratio_rwdmonomial.h" - - -double cloverdetratio_rwaccd(const int id, hamiltonian_field_t * const hf) { - monomial * mnl = &monomial_list[id]; - int save_sloppy = g_sloppy_precision_flag; - double atime, etime; - atime = gettime(); - - - g_mu = mnl->mu2; - boundary(mnl->kappa2); - - init_sw_fields(); - sw_term( (const su3**) hf->gaugefield, mnl->kappa2, mnl->c_sw); - sw_invert(EE, mnl->mu2); - g_mu3 = 0.; - - mnl->Qsq(mnl->w_fields[1], mnl->pf); - assign(mnl->w_fields[0],mnl->pf,VOLUME/2); - - g_mu3 = 0.; - g_mu = mnl->mu; - boundary(mnl->kappa); - sw_term( (const su3**) hf->gaugefield, mnl->kappa, mnl->c_sw); - sw_invert(EE, mnl->mu); - - /*chrono_guess(mnl->pf, mnl->w_fields[1], mnl->csg_field, mnl->csg_index_array, - mnl->csg_N, mnl->csg_n, VOLUME/2, &Qtm_plus_psi);*/ - g_sloppy_precision_flag = 0; - mnl->iter0 += solve_degenerate(mnl->w_fields[0], mnl->w_fields[1], mnl->solver_params, mnl->maxiter, mnl->accprec, - g_relative_precision_flag, VOLUME/2, mnl->Qsq, mnl->solver); - - - g_sloppy_precision_flag = save_sloppy; - - /* Compute the energy contr. from second field */ - mnl->energy1 = scalar_prod_r(mnl->pf,mnl->w_fields[0], VOLUME/2, 1); - - g_mu = g_mu1; - g_mu3 = 0.; - boundary(g_kappa); - etime = gettime(); - if(g_proc_id == 0) { - if(g_debug_level > 1) { - printf("# Time for %s monomial rwacc step: %e s\n", mnl->name, etime-atime); - } - if(g_debug_level > 3) { - printf("called cloverdetratio_rwacc for id %d dH = %1.10e\n", - id, mnl->energy1 - mnl->energy0); - printf("Parameters: kappa=%e, kappa2=%e; mu=%e, mu2=%e, vprod=%e\n",mnl->kappa,mnl->kappa2,mnl->mu,mnl->mu2,mnl->energy1); - } - } - return(mnl->energy1 - mnl->energy0); -} diff --git a/monomial/cloverdetratio_rwdmonomial.h b/monomial/cloverdetratio_rwdmonomial.h deleted file mode 100644 index ad13814f2..000000000 --- a/monomial/cloverdetratio_rwdmonomial.h +++ /dev/null @@ -1,31 +0,0 @@ -/*********************************************************************** - * - * Copyright (C) 2012 Carsten Urbach - * - * Adaption with a more efficient inversion by Georg Bergner 2016 - * Note that the reweighting measurement is much more efficient. - * - * 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 _CLOVERDETRATIO_RWDMONOMIAL_H -#define _CLOVERDETRATIO_RWDMONOMIAL_H - -#include "hamiltonian_field.h" - -double cloverdetratio_rwaccd(const int no, hamiltonian_field_t * const hf); - -#endif diff --git a/monomial/monomial.c b/monomial/monomial.c index 3a21a1347..ba206a934 100644 --- a/monomial/monomial.c +++ b/monomial/monomial.c @@ -258,17 +258,6 @@ int init_monomials(const int V, const int even_odd_flag) { printf("# Initialised monomial of type CLOVERDETRATIORW, no_monomials= %d, currently only available for reweighting!\n", no_monomials); } } - else if(monomial_list[i].type == CLOVERDETRATIORWD) { - monomial_list[i].accfunction = &cloverdetratio_rwaccd; - monomial_list[i].even_odd_flag = 1; - monomial_list[i].Qsq = &Qsw_pm_psi; - monomial_list[i].Qp = &Qsw_plus_psi; - monomial_list[i].Qm = &Qsw_minus_psi; - init_swpm(VOLUME); - if(g_proc_id == 0 && g_debug_level > 1) { - printf("# Initialised monomial of type CLOVERDETRATIORWD, no_monomials= %d, currently only available for reweighting!\n", no_monomials); - } - } else if(monomial_list[i].type == DETRATIO) { monomial_list[i].hbfunction = &detratio_heatbath; monomial_list[i].accfunction = &detratio_acc; diff --git a/monomial/monomial.h b/monomial/monomial.h index 7c6b6be72..c03a686f5 100644 --- a/monomial/monomial.h +++ b/monomial/monomial.h @@ -139,7 +139,6 @@ typedef struct { #include "monomial/cloverdet_monomial.h" #include "monomial/cloverdetratio_monomial.h" #include "monomial/cloverdetratio_rwmonomial.h" -#include "monomial/cloverdetratio_rwdmonomial.h" #include "monomial/cloverndpoly_monomial.h" #include "monomial/ndrat_monomial.h" #include "monomial/rat_monomial.h" diff --git a/read_input.l b/read_input.l index 61adbf256..9acafe27f 100644 --- a/read_input.l +++ b/read_input.l @@ -1605,10 +1605,6 @@ static inline double fltlist_next_token(int * const list_end){ mnl->type = CLOVERDETRATIORW; strcpy((*mnl).name, "CLOVERDETRATIORW"); } - else if(strcmp(yytext, "CLOVERDETRATIORWD")==0) { - mnl->type = CLOVERDETRATIORWD; - strcpy((*mnl).name, "CLOVERDETRATIORWD"); - } else if(strcmp(yytext, "DETRATIO")==0) { mnl->type = DETRATIO; @@ -1713,7 +1709,6 @@ static inline double fltlist_next_token(int * const list_end){ else if(mnl->type == CLOVERDET) BEGIN(CLDETMONOMIAL); else if(mnl->type == CLOVERDETRATIO) BEGIN(CLDETRATMONOMIAL); else if(mnl->type == CLOVERDETRATIORW) BEGIN(CLDETRATRWMONOMIAL); - else if(mnl->type == CLOVERDETRATIORWD) BEGIN(CLDETRATRWMONOMIAL); else BEGIN(DETMONOMIAL); } From 7c37cfe2b5077ff06c2cb4f685cd772f64bcabe6 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Sat, 3 Nov 2018 00:24:36 +0100 Subject: [PATCH 19/22] small change --- meas/reweightingmeas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index b887dc213..d410d44a3 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -2,7 +2,7 @@ * * Measurements of the reweighting factors by Georg Bergner 2016 * - * Copyright (C) 2008 Carsten Urbach + * Copyright (C) 2016 Georg Bergner * * This file is part of tmLQCD. * From b9b15a7f1fa66ba04569eeb43c81fbf36c773818 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Mon, 19 Nov 2018 21:29:56 +0100 Subject: [PATCH 20/22] added kappa.dat as optional input for intermediate kappa parameters --- meas/reweightingmeas.c | 87 +++++++++++++++++++++++++++++++++++++++--- meas/reweightingmeas.h | 31 +++++++++++++-- 2 files changed, 109 insertions(+), 9 deletions(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index d410d44a3..1a64f2970 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -53,6 +53,7 @@ #include "../DDalphaAMG_interface.h" #include "../boundary.h" #include "../global.h" +#include "../init/init_spinor_field.h" #include "solver/jdher.h" #include @@ -75,7 +76,6 @@ typedef struct { * Allocation of the spinor field redirects to allocate_spinor_field_array. */ static int alloc_spinor_field(spinor_array* ar, int evenodd) { - int i = 0; unsigned long int volume = VOLUMEPLUSRAND / 2; if (evenodd == 0) { volume = VOLUMEPLUSRAND; @@ -83,9 +83,9 @@ static int alloc_spinor_field(spinor_array* ar, int evenodd) { return (allocate_spinor_field_array(&ar->ar,&ar->buffer,volume, ar->length)); } -static void free_spinor_field(spinor_array* ar) { +static void free_spinor_field_spinor_array(spinor_array* ar) { if (ar->buffer != NULL) { - free_spinor_field_array(ar->buffer); + free_spinor_field_array(&ar->buffer); } if (ar->ar != NULL) { free(ar->ar); @@ -627,7 +627,7 @@ static void log_determinant_estimate(const int operatorid, int chebmax, } /* orderend>0*/ } /* splitlength loop */ free(coeff); - free_spinor_field(&spinorarray); + free_spinor_field_spinor_array(&spinorarray); } void reweighting_measurement(const int traj, const int id, const int ieo) { @@ -824,8 +824,15 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { tmp1 = 1.0 / kappainitial; tmp2 = 1.0 / kappafinal; tmp3 = 1.0 / kappa; - interpolate(&tmp3, tmp1, tmp2, param->interpolationsteps, internum); - kappa = 1.0 / tmp3; + if(internumkappaarray.s){ + kappa=param->kappaarray.el[internum]; + }else{ + interpolate(&tmp3, tmp1, tmp2, param->interpolationsteps, internum); + kappa = 1.0 / tmp3; + } + if (g_proc_id == 0 && g_debug_level > 0) { + printf("REWEIGHTING: kappa from %.14f to %.14f\n", kappa0,kappa); + } updateinverter = 1; } if (murew) { @@ -948,6 +955,10 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { 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); @@ -957,6 +968,10 @@ void free_reweighting_parameter(void* par) { 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; @@ -964,6 +979,11 @@ void free_reweighting_parameter(void* par) { 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; @@ -991,6 +1011,7 @@ static void read_coeff_from_file(vector_list* v) { printf("%d %lg\n", l, v->el[l]); } } + fclose(file); } else { if (g_proc_id == 0) { printf("File coeff.dat not present.\n"); @@ -1001,6 +1022,10 @@ static void read_coeff_from_file(vector_list* v) { } +/** + * + * @param list + */ static void read_splitlist(split_list* list) { FILE* file; unsigned int l; @@ -1032,6 +1057,7 @@ static void read_splitlist(split_list* list) { 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"); @@ -1043,6 +1069,49 @@ static void read_splitlist(split_list* list) { } +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)) { @@ -1053,6 +1122,8 @@ void initialize_reweighting_parameter(void** parameter) { 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; @@ -1071,5 +1142,9 @@ void initialize_reweighting_parameter(void** parameter) { param->testchebconvergence = 0; read_coeff_from_file(¶m->coeff); read_splitlist(¶m->splitlist); + read_kappalist(¶m->kappaarray); + if(param->kappaarray.s!=0){ + param->interpolationsteps=param->kappaarray.s; + } } } diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h index e167c60b7..44d532658 100644 --- a/meas/reweightingmeas.h +++ b/meas/reweightingmeas.h @@ -2,7 +2,7 @@ * * Measurements of the reweighting factors by Georg Bergner 2016 * - * Copyright (C) 2008 Carsten Urbach + * Copyright (C) 20016 Georg Bergner * * This file is part of tmLQCD. * @@ -25,11 +25,19 @@ #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; +/** + * 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; @@ -38,17 +46,21 @@ typedef struct { } 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; + double testchebconvergence; int interpolationsteps; int estimatorscheb; int cheborder; @@ -59,11 +71,24 @@ typedef struct { 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 From 4c4ae306e4d2b77f33b652b450d72c91a0abde84 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Tue, 20 Nov 2018 12:57:52 +0100 Subject: [PATCH 21/22] added kappa.dat as optional input for intermediate kappa parameters, correction --- meas/reweightingmeas.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index 1a64f2970..5b9a3bc7d 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -818,6 +818,14 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { 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; @@ -830,9 +838,6 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { interpolate(&tmp3, tmp1, tmp2, param->interpolationsteps, internum); kappa = 1.0 / tmp3; } - if (g_proc_id == 0 && g_debug_level > 0) { - printf("REWEIGHTING: kappa from %.14f to %.14f\n", kappa0,kappa); - } updateinverter = 1; } if (murew) { @@ -845,8 +850,12 @@ void reweighting_measurement(const int traj, const int id, const int ieo) { 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; @@ -1143,8 +1152,5 @@ void initialize_reweighting_parameter(void** parameter) { read_coeff_from_file(¶m->coeff); read_splitlist(¶m->splitlist); read_kappalist(¶m->kappaarray); - if(param->kappaarray.s!=0){ - param->interpolationsteps=param->kappaarray.s; - } } } From afc82c6dc9739945cd6f17c6c03742349a968512 Mon Sep 17 00:00:00 2001 From: Georg Bergner Date: Tue, 20 Nov 2018 16:13:12 +0100 Subject: [PATCH 22/22] FLTLIST input instead of separate file --- meas/reweightingmeas.c | 2 +- meas/reweightingmeas.h | 5 +++++ read_input.l | 31 +++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/meas/reweightingmeas.c b/meas/reweightingmeas.c index 5b9a3bc7d..7b1f47e54 100644 --- a/meas/reweightingmeas.c +++ b/meas/reweightingmeas.c @@ -1151,6 +1151,6 @@ void initialize_reweighting_parameter(void** parameter) { param->testchebconvergence = 0; read_coeff_from_file(¶m->coeff); read_splitlist(¶m->splitlist); - read_kappalist(¶m->kappaarray); + //read_kappalist(¶m->kappaarray); } } diff --git a/meas/reweightingmeas.h b/meas/reweightingmeas.h index 44d532658..5c57a5654 100644 --- a/meas/reweightingmeas.h +++ b/meas/reweightingmeas.h @@ -34,6 +34,11 @@ typedef struct{ 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. diff --git a/read_input.l b/read_input.l index 9acafe27f..b96f8ee18 100644 --- a/read_input.l +++ b/read_input.l @@ -267,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 @@ -2505,6 +2531,11 @@ static inline double fltlist_next_token(int * const list_end){ ((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); + } } {