diff --git a/doc/omeas_heavy_mesons.qmd b/doc/omeas_heavy_mesons.qmd index 3b86d3bd8..41fa08823 100644 --- a/doc/omeas_heavy_mesons.qmd +++ b/doc/omeas_heavy_mesons.qmd @@ -204,11 +204,12 @@ Our correlator becomes: \, . \end{equation} -Upon a careful calculation for all values $i,j = 0,1$ we find, equivalently: +Upon a careful calculation for all values $i,j = 0,1$ we find, equivalently (using spacetime translational symmetry): \begin{equation} +\begin{split} \mathcal{C}^{h_i, h_j}_{\Gamma_1, \Gamma_2}(t, \vec{x}) -= +&= \operatorname{Tr} \left[ (S_h)_{f_i f_j} (x|0) @@ -216,7 +217,19 @@ Upon a careful calculation for all values $i,j = 0,1$ we find, equivalently: (S_u)^\dagger (x|0) \gamma_5 \Gamma_1 \right] +\\ +&= +\sum_{y,z} +\operatorname{Tr} +\left[ + (S_h)_{f_i f_j} (x+y|y) + \Gamma_2 \gamma_5 + (S_u)^\dagger (x+z|z) + \gamma_5 \Gamma_1 + \delta_{yz} +\right] \, . +\end{split} \end{equation} This is a generalized case of eq. (A9) of @PhysRevD.59.074503. @@ -269,22 +282,31 @@ Therefore, we can use spin dilutions to rephrase the correlator in a form which \end{equation} - - - - We now define our spinor propagators. If $\eta^{(\beta, \phi)}$ is the diluted source: -\begin{equation} -(D_{\ell/h})_{\alpha_1 \alpha_2} ({\psi}_{\ell/h}^{(\beta, \phi)})_{\alpha_2} -= (\eta^{(\beta, \phi)})_{\alpha_1} -\, \implies \, -(\psi_{\ell/h}^{(\beta, \phi)})^\dagger_{\alpha_1} +\begin{align} +& (D_{\ell/h})_{\alpha_1 \alpha_2} (x|y) ({\psi}_{\ell/h}^{(\beta, \phi)})_{\alpha_2} (y) += (\eta^{(\beta, \phi)})_{\alpha_1} (x) +\\ +& \, \implies \, +(\psi_{\ell/h}^{(\beta, \phi)})_{\alpha_1} (x) = -(\eta^{(\beta, \phi)})^\dagger_{\alpha_2} -(S_{\ell/h}^\dagger)_{\alpha_2 \alpha_1} -\end{equation} +(S_{\ell/h})_{\alpha_2 \alpha_1} (x | y) +\eta^{(\beta, \phi)}_{\alpha_2} (y) += +(S_{\ell/h})_{\alpha_2 \alpha_1} (x | 0) +\eta^{(\beta, \phi)}_{\alpha_2} (0) +\\ +& \, \implies \, +(\psi_{\ell/h}^{(\beta, \phi)})^{*}_{\alpha_1} (x) += +(\eta^{(\beta, \phi)})^{*}_{\alpha_2} (y) +(S_{\ell/h}^\dagger)_{\alpha_2 \alpha_1} (x | y) += +(\eta^{(\beta, \phi)})^\dagger_{\alpha_2} (0) +(S_{\ell/h}^\dagger)_{\alpha_2 \alpha_1} (x | 0) +\end{align} This means that for our matrix of correlators we have to do ${4_D \times 2_f \times 2_{h,\ell}} = 16$ inversions. @@ -319,7 +341,7 @@ Our correlator is given by the following expectation value (\Gamma_2 \gamma_5)_{\alpha_2 \alpha_3} \\ &= -\mathcal{S}^{\alpha_3 \alpha_2} (\Gamma_2 \gamma_5)_{\alpha_2 \alpha_3} +\mathcal{R}^{\alpha_3 \alpha_2} (\Gamma_2 \gamma_5)_{\alpha_2 \alpha_3} \end{split} \end{equation} @@ -329,10 +351,10 @@ More explicitly: \begin{equation} \begin{split} \Gamma_2=1 &\implies \mathcal{C}^{h_i, h_j}_{\Gamma_1, \Gamma_2}(t, \vec{x}) -= \mathcal{S}^{00}+\mathcal{S}^{11}-\mathcal{S}^{22}-\mathcal{S}^{33} += \mathcal{R}^{00}+\mathcal{R}^{11}-\mathcal{R}^{22}-\mathcal{R}^{33} \\ \Gamma_2=\gamma_5 &\implies \mathcal{C}^{h_i, h_j}_{\Gamma_1, \Gamma_2}(t, \vec{x}) -= \mathcal{S}^{00}+\mathcal{S}^{11}+\mathcal{S}^{22}+\mathcal{S}^{33} += \mathcal{R}^{00}+\mathcal{R}^{11}+\mathcal{R}^{22}+\mathcal{R}^{33} \end{split} \end{equation} @@ -343,7 +365,7 @@ More explicitly: See comments in the code: `tmLQCD/meas/correlators.c`. - +**NOTE**: test if `invert_doublet_eo_quda` works (do one inversion and check the residual) diff --git a/meas/correlators.c b/meas/correlators.c index 213a929da..c6b87a86c 100644 --- a/meas/correlators.c +++ b/meas/correlators.c @@ -308,479 +308,478 @@ void* callocMultiDimensional(int* sizes, int numDimensions, size_t elementSize) ******************************************************/ void heavy_correlators_measurement(const int traj, const int id, const int ieo, const int i1, const int i2) { - tm_stopwatch_push(&g_timers, __func__, ""); // timer for profiling + tm_stopwatch_push(&g_timers, __func__, ""); // timer for profiling - spinor phi; // dummy spinor - int i, j, t, tt, t0; // dummy indices - float tmp; // dummy variable + spinor phi; // dummy spinor + int i, j, t, tt, t0; // dummy indices + float tmp; // dummy variable - /* light-light correlators: dummy variables */ + /* light-light correlators: dummy variables */ - // array of the values of the correlator C(t) - double *Cpp = NULL, *Cpa = NULL, *Cp4 = NULL; - // result of the accumulation of MPI partial sums - double res = 0., respa = 0., resp4 = 0.; + // array of the values of the correlator C(t) + double *Cpp = NULL, *Cpa = NULL, *Cp4 = NULL; + // result of the accumulation of MPI partial sums + double res = 0., respa = 0., resp4 = 0.; #ifdef TM_USE_MPI - double mpi_res = 0., mpi_respa = 0., mpi_resp4 = 0.; - // send buffer for MPI_Gather - double *sCpp = NULL, *sCpa = NULL, *sCp4 = NULL; + double mpi_res = 0., mpi_respa = 0., mpi_resp4 = 0.; + // send buffer for MPI_Gather + double *sCpp = NULL, *sCpa = NULL, *sCp4 = NULL; #endif #ifdef TM_USE_MPI - sCpp = (double *)calloc(T, sizeof(double)); - sCpa = (double *)calloc(T, sizeof(double)); - sCp4 = (double *)calloc(T, sizeof(double)); - if (g_mpi_time_rank == 0) { - Cpp = (double *)calloc(g_nproc_t * T, sizeof(double)); - Cpa = (double *)calloc(g_nproc_t * T, sizeof(double)); - Cp4 = (double *)calloc(g_nproc_t * T, sizeof(double)); - } + sCpp = (double *)calloc(T, sizeof(double)); + sCpa = (double *)calloc(T, sizeof(double)); + sCp4 = (double *)calloc(T, sizeof(double)); + if (g_mpi_time_rank == 0) { + Cpp = (double *)calloc(g_nproc_t * T, sizeof(double)); + Cpa = (double *)calloc(g_nproc_t * T, sizeof(double)); + Cp4 = (double *)calloc(g_nproc_t * T, sizeof(double)); + } #else - Cpp = (double *)calloc(T, sizeof(double)); - Cpa = (double *)calloc(T, sizeof(double)); - Cp4 = (double *)calloc(T, sizeof(double)); + Cpp = (double *)calloc(T, sizeof(double)); + Cpa = (double *)calloc(T, sizeof(double)); + Cp4 = (double *)calloc(T, sizeof(double)); #endif - /* heavy-light correlators variables */ - double eta_Gamma[2] = {1.0, -1.0}; // sign change bilinear^\dagger, with Gamma = 1,gamma_5 + /* heavy-light correlators variables */ + double eta_Gamma[2] = {1.0, -1.0}; // sign change bilinear^\dagger, with Gamma = 1,gamma_5 - // the number of independent correlators is 16 = (2*2)_{h_1 h_2} * (2*2)_{Gamma_1 Gamma_2} - // hi: c,s - // Gamma = 1, gamma_5 - const int sizes_C_hihj_g1g2[5] = {2, 2, 2, 2, T}; - double *****C_hihj_g1g2 = - (double *****)callocMultiDimensional(sizes_C_hihj_g1g2, 5, sizeof(double)); + // the number of independent correlators is 16 = (2*2)_{h_1 h_2} * (2*2)_{Gamma_1 Gamma_2} + // hi: c,s + // Gamma = 1, gamma_5 + const int sizes_C_hihj_g1g2[5] = {2, 2, 2, 2, T}; + double *****C_hihj_g1g2 = + (double *****)callocMultiDimensional(sizes_C_hihj_g1g2, 5, sizeof(double)); - const int sizes_res_hihj_g1g2[4] = {2, 2, 2, 2}; - double ****res_hihj_g1g2 = (double ****)callocMultiDimensional(sizes_res_hihj_g1g2, 4, sizeof(double)); + const int sizes_res_hihj_g1g2[4] = {2, 2, 2, 2}; + double ****res_hihj_g1g2 = + (double ****)callocMultiDimensional(sizes_res_hihj_g1g2, 4, sizeof(double)); #ifdef TM_USE_MPI - double ****mpi_res_hihj_g1g2 = - (double ****)callocMultiDimensional(sizes_res_hihj_g1g2, 4, sizeof(double)); - // send buffer for MPI_Gather - double *****sC_hihj_g1g2 = - (double *****)callocMultiDimensional(sizes_C_hihj_g1g2, 5, sizeof(double)); + double ****mpi_res_hihj_g1g2 = + (double ****)callocMultiDimensional(sizes_res_hihj_g1g2, 4, sizeof(double)); + // send buffer for MPI_Gather + double *****sC_hihj_g1g2 = + (double *****)callocMultiDimensional(sizes_C_hihj_g1g2, 5, sizeof(double)); #endif - FILE *ofs; // output file stream - char filename[TM_OMEAS_FILENAME_LENGTH]; // file path + FILE *ofs; // output file stream + char filename[TM_OMEAS_FILENAME_LENGTH]; // file path - /* building the stochastic propagator spinors needed for the correlators */ + /* building the stochastic propagator spinors needed for the correlators */ - init_operators(); // initialize the operators in the action (if not already done) - if (no_operators < 1) { - if (g_proc_id == 0) { - // we don't want the simulation to stop, we can do the measurements offline afterwards - fprintf(stderr, - "Warning! no operators defined in input file, cannot perform online correlator " - "mesurements!\n"); - } - tm_stopwatch_pop(&g_timers, 0, 0, ""); // timer for profiling - return; + init_operators(); // initialize the operators in the action (if not already done) + if (no_operators < 1) { + if (g_proc_id == 0) { + // we don't want the simulation to stop, we can do the measurements offline afterwards + fprintf(stderr, + "Warning! no operators defined in input file, cannot perform online correlator " + "mesurements!\n"); } + tm_stopwatch_pop(&g_timers, 0, 0, ""); // timer for profiling + return; + } - // selecting the operators i1 and i2 from the list of operators initialized before - operator* optr1 = & operator_list[i1]; // light doublet - operator* optr2 = & operator_list[i2]; // heavy c,s doublet - - bool b1 = (optr1->type != TMWILSON && optr1->type != WILSON && optr1->type != CLOVER); - bool b2 = (optr2->type != DBTMWILSON && optr2->type != DBCLOVER); - if (b1 || b2) { - if (g_proc_id == 0) { - if (b1) { - fprintf( - stderr, - "Warning! optr1 should be one of the following: TMWILSON, WILSON and CLOVER\n"); - fprintf(stderr, "Cannot perform correlator online measurement!\n"); - } - if (b2) { - fprintf(stderr, - "Warning! optr2 should be one of the following: DBTMWILSON, DBCLOVER\n"); - } - fprintf(stderr, "Cannot perform correlator online measurement!\n"); - } - tm_stopwatch_pop(&g_timers, 0, 0, ""); // timer for profiling - return; + // selecting the operators i1 and i2 from the list of operators initialized before + operator* optr1 = & operator_list[i1]; // light doublet + operator* optr2 = & operator_list[i2]; // heavy c,s doublet + + bool b1 = (optr1->type != TMWILSON && optr1->type != WILSON && optr1->type != CLOVER); + bool b2 = (optr2->type != DBTMWILSON && optr2->type != DBCLOVER); + if (b1 || b2) { + if (g_proc_id == 0) { + if (b1) { + fprintf(stderr, + "Warning! optr1 should be one of the following: TMWILSON, WILSON and CLOVER\n"); + fprintf(stderr, "Cannot perform correlator online measurement!\n"); + } + if (b2) { + fprintf(stderr, "Warning! optr2 should be one of the following: DBTMWILSON, DBCLOVER\n"); + } + fprintf(stderr, "Cannot perform correlator online measurement!\n"); } + tm_stopwatch_pop(&g_timers, 0, 0, ""); // timer for profiling + return; + } - if (ranlxs_init == 0) { - rlxs_init(1, 123456); // initializing random number generator RANLUX - } + if (ranlxs_init == 0) { + rlxs_init(1, 123456); // initializing random number generator RANLUX + } - // there are three modes of operation - // 1) one single time-slice source (default) - // 2) no_samples time-slice sources on random time-slices - // 3) one sample on all time-slices - int max_samples = measurement_list[id].all_time_slices ? 1 : measurement_list[id].no_samples; - int max_time_slices = - measurement_list[id].all_time_slices ? measurement_list[id].max_source_slice : 1; - for (int sample = 0; sample < max_samples; sample++) { - for (int ts = 0; ts < max_time_slices; ts++) { - // setting output filename - if (max_samples == 1 && max_time_slices == 1) { - snprintf(filename, TM_OMEAS_FILENAME_LENGTH, "%s%06d", "heavy_mesons.", traj); - } else if (max_samples == 1 && max_time_slices > 1) { - snprintf(filename, TM_OMEAS_FILENAME_LENGTH, "%s.t%03d.%06d", "heavy_mesons", ts, - traj); - } else { - snprintf(filename, TM_OMEAS_FILENAME_LENGTH, "%s.s%03d.%06d", "heavy_mesons", - sample, traj); - } + // there are three modes of operation + // 1) one single time-slice source (default) + // 2) no_samples time-slice sources on random time-slices + // 3) one sample on all time-slices + int max_samples = measurement_list[id].all_time_slices ? 1 : measurement_list[id].no_samples; + int max_time_slices = + measurement_list[id].all_time_slices ? measurement_list[id].max_source_slice : 1; + for (int sample = 0; sample < max_samples; sample++) { + for (int ts = 0; ts < max_time_slices; ts++) { + // setting output filename + if (max_samples == 1 && max_time_slices == 1) { + snprintf(filename, TM_OMEAS_FILENAME_LENGTH, "%s%06d", "heavy_mesons.", traj); + } else if (max_samples == 1 && max_time_slices > 1) { + snprintf(filename, TM_OMEAS_FILENAME_LENGTH, "%s.t%03d.%06d", "heavy_mesons", ts, traj); + } else { + snprintf(filename, TM_OMEAS_FILENAME_LENGTH, "%s.s%03d.%06d", "heavy_mesons", sample, traj); + } - /* generate random timeslice */ - t0 = ts; - if (!measurement_list[id].all_time_slices) { - ranlxs(&tmp, 1); - t0 = (int)(measurement_list[id].max_source_slice * tmp); - } + /* generate random timeslice */ + t0 = ts; + if (!measurement_list[id].all_time_slices) { + ranlxs(&tmp, 1); + t0 = (int)(measurement_list[id].max_source_slice * tmp); + } #ifdef TM_USE_MPI - MPI_Bcast(&t0, 1, MPI_INT, 0, MPI_COMM_WORLD); // broadcast t0 to all the ranks + MPI_Bcast(&t0, 1, MPI_INT, 0, MPI_COMM_WORLD); // broadcast t0 to all the ranks #endif - if (g_debug_level > 1 && g_proc_id == 0) { - printf("# timeslice set to %d (T=%d) for online measurement\n", t0, g_nproc_t * T); - printf( - "# online measurements parameters: kappa = %.12f, mubar = %.12f, epsbar = " - "%.12f\n", - optr1->kappa, optr1->mubar, optr1->epsbar); - } + if (g_debug_level > 1 && g_proc_id == 0) { + printf("# timeslice set to %d (T=%d) for online measurement\n", t0, g_nproc_t * T); + printf( + "# online measurements parameters: kappa = %.12f, mubar = %.12f, epsbar = " + "%.12f\n", + optr1->kappa, optr1->mubar, optr1->epsbar); + } - // even-odd spinor fields for the light and heavy doublet correlators - // INDICES: source+propagator, doublet, spin dilution index, flavor projection, even-odd, flavor, position - // (+ Dirac, color) psi = (psi[(s,p)][db][beta][F][eo][f][x])[alpha][c] - // last 2 indices come from spinor struct - // Note: propagator in the sense that it is D^{-1}*source after the inversion - const int sizes_arr_eo_spinor[7] = {2, 2, 4, 2, 2, 2, VOLUME / 2}; - spinor *******arr_eo_spinor = - (spinor *******)callocMultiDimensional(sizes_arr_eo_spinor, 7, sizeof(spinor)); - - /* initalize the random sources: one source for each Dirac index beta=src_d --> spin - * dilution */ - const unsigned int seed_i = measurement_list[id].seed; // has to be same seed - for (size_t db = 0; db < 2; db++) { // doublet: light or heavy - for (size_t beta = 0; beta < 4; beta++) { // spin dilution index - for (size_t F = 0; F < 2; F++) { // flavor dilution index - for (size_t i_f = 0; i_f < 2; i_f++) { // flavor index of the doublet - // light doublet - eo_source_spinor_field_spin_diluted_oet_ts( - arr_eo_spinor[0][db][beta][F][0][i_f], arr_eo_spinor[0][db][beta][F][1][i_f], - t0, beta, sample, traj, seed_i - ); - - } - } - } + // even-odd spinor fields for the light and heavy doublet correlators + // INDICES: source+propagator, doublet, spin dilution index, flavor projection, even-odd, + // flavor, position + // (+ Dirac, color) psi = (psi[(s,p)][db][beta][F][eo][f][x])[alpha][c] + // last 2 indices come from spinor struct + // Note: propagator in the sense that it is D^{-1}*source after the inversion + const int sizes_arr_eo_spinor[7] = {2, 2, 4, 2, 2, 2, VOLUME / 2}; + spinor *******arr_eo_spinor = + (spinor *******)callocMultiDimensional(sizes_arr_eo_spinor, 7, sizeof(spinor)); + + /* initalize the random sources: one source for each Dirac index beta=src_d --> spin + * dilution */ + const unsigned int seed_i = measurement_list[id].seed; // has to be same seed + for (size_t db = 0; db < 2; db++) { // doublet: light or heavy + for (size_t beta = 0; beta < 4; beta++) { // spin dilution index + for (size_t F = 0; F < 2; F++) { // flavor dilution index + for (size_t i_f = 0; i_f < 2; i_f++) { // flavor index of the doublet + // light doublet + eo_source_spinor_field_spin_diluted_oet_ts(arr_eo_spinor[0][db][beta][F][0][i_f], + arr_eo_spinor[0][db][beta][F][1][i_f], t0, + beta, sample, traj, seed_i); } + } + } + } - // heavy doublet: for each even-odd block, I multiply by (1 + i*tau_2)/sqrt(2) - // the basis for the inversion should be the same as for the light - // --> I will multiply later by the inverse, namely at the end of the inversion - for (size_t beta = 0; beta < 4; beta++) { // spin dilution index - for (size_t F = 0; F < 2; F++) { // flavor projection index - for (size_t i_eo = 0; i_eo < 2; i_eo++) { // even-odd - // (c,s) --> [(1-i*tau_2)/sqrt(2)] * (c,s) - // stored temporarely in the propagator spinors (used as dummy) - mul_one_pm_itau2_and_div_by_sqrt2( - arr_eo_spinor[1][1][beta][F][i_eo][0], arr_eo_spinor[1][1][beta][F][i_eo][1], - arr_eo_spinor[0][1][beta][F][i_eo][0], arr_eo_spinor[0][1][beta][F][i_eo][1], +1.0, - VOLUME / 2); - - for (size_t i_f = 0; i_f < 2; i_f++) { - // assigning the result to the first components (the sources). - // The propagators will be overwritten with the inversion - assign(arr_eo_spinor[0][1][beta][F][i_eo][i_f], - arr_eo_spinor[1][1][beta][F][i_eo][i_f], VOLUME / 2); - } - } - } + // heavy doublet: for each even-odd block, I multiply by (1 + i*tau_2)/sqrt(2) + // the basis for the inversion should be the same as for the light + // --> I will multiply later by the inverse, namely at the end of the inversion + for (size_t beta = 0; beta < 4; beta++) { // spin dilution index + for (size_t F = 0; F < 2; F++) { // flavor projection index + for (size_t i_eo = 0; i_eo < 2; i_eo++) { // even-odd + // (c,s) --> [(1-i*tau_2)/sqrt(2)] * (c,s) + // stored temporarely in the propagator spinors (used as dummy) + mul_one_pm_itau2_and_div_by_sqrt2( + arr_eo_spinor[1][1][beta][F][i_eo][0], arr_eo_spinor[1][1][beta][F][i_eo][1], + arr_eo_spinor[0][1][beta][F][i_eo][0], arr_eo_spinor[0][1][beta][F][i_eo][1], +1.0, + VOLUME / 2); + + for (size_t i_f = 0; i_f < 2; i_f++) { + // assigning the result to the first components (the sources). + // The propagators will be overwritten with the inversion + assign(arr_eo_spinor[0][1][beta][F][i_eo][i_f], + arr_eo_spinor[1][1][beta][F][i_eo][i_f], VOLUME / 2); } + } + } + } - /* - assign the sources and propagator pointes for the operators - these need to be know when calling the inverter() method */ - for (size_t beta = 0; beta < 4; beta++) { // spin dilution index - /* light doublet */ + /* + assign the sources and propagator pointes for the operators + these need to be know when calling the inverter() method */ + for (size_t beta = 0; beta < 4; beta++) { // spin dilution index + /* light doublet */ - // up + // up - // sorces - optr1->sr0 = arr_eo_spinor[0][0][beta][0][0]; - optr1->sr1 = arr_eo_spinor[0][0][beta][1][0]; - // propagators - optr1->prop0 = arr_eo_spinor[1][0][beta][0][0]; - optr1->prop1 = arr_eo_spinor[1][0][beta][1][0]; + // sorces + optr1->sr0 = arr_eo_spinor[0][0][beta][0][0]; + optr1->sr1 = arr_eo_spinor[0][0][beta][1][0]; + // propagators + optr1->prop0 = arr_eo_spinor[1][0][beta][0][0]; + optr1->prop1 = arr_eo_spinor[1][0][beta][1][0]; - optr1->inverter(i1, 0, 0); // inversion for the up flavor + optr1->inverter(i1, 0, 0); // inversion for the up flavor - // PLEASE KEEP THESE LINES COMMENTED, MAY BE USEFUL IN THE FUTURE - // // inversion of the light doublet only inverts the up block (the operator is - // // diagonal in flavor) down components in flavor will be empty - // optr1->DownProp = 1; + // PLEASE KEEP THESE LINES COMMENTED, MAY BE USEFUL IN THE FUTURE + // // inversion of the light doublet only inverts the up block (the operator is + // // diagonal in flavor) down components in flavor will be empty + // optr1->DownProp = 1; - // // sources - // optr1->sr0 = arr_eo_spinor[0][0][beta][0][1]; - // optr1->sr1 = arr_eo_spinor[0][0][beta][1][1]; - // // propagator - // optr1->prop0 = arr_eo_spinor[1][0][beta][0][1]; - // optr1->prop1 = arr_eo_spinor[1][0][beta][1][1]; + // // sources + // optr1->sr0 = arr_eo_spinor[0][0][beta][0][1]; + // optr1->sr1 = arr_eo_spinor[0][0][beta][1][1]; + // // propagator + // optr1->prop0 = arr_eo_spinor[1][0][beta][0][1]; + // optr1->prop1 = arr_eo_spinor[1][0][beta][1][1]; - // optr1->inverter(i1, 0, 0); // inversion for the down + // optr1->inverter(i1, 0, 0); // inversion for the down - // optr1->DownProp = 0; // restoring to default + // optr1->DownProp = 0; // restoring to default - /* heavy doublet */ + /* heavy doublet */ - optr2->sr0 = arr_eo_spinor[0][1][beta][0][0]; - optr2->sr1 = arr_eo_spinor[0][1][beta][1][0]; - optr2->sr2 = arr_eo_spinor[0][1][beta][0][1]; - optr2->sr3 = arr_eo_spinor[0][1][beta][1][1]; + optr2->sr0 = arr_eo_spinor[0][1][beta][0][0]; + optr2->sr1 = arr_eo_spinor[0][1][beta][1][0]; + optr2->sr2 = arr_eo_spinor[0][1][beta][0][1]; + optr2->sr3 = arr_eo_spinor[0][1][beta][1][1]; - optr2->prop0 = arr_eo_spinor[1][1][beta][0][0]; - optr2->prop1 = arr_eo_spinor[1][1][beta][1][0]; - optr2->prop2 = arr_eo_spinor[1][1][beta][0][1]; - optr2->prop3 = arr_eo_spinor[1][1][beta][1][1]; + optr2->prop0 = arr_eo_spinor[1][1][beta][0][0]; + optr2->prop1 = arr_eo_spinor[1][1][beta][1][0]; + optr2->prop2 = arr_eo_spinor[1][1][beta][0][1]; + optr2->prop3 = arr_eo_spinor[1][1][beta][1][1]; - optr2->inverter(i2, 0, 0); // inversion for both flavor components - } + optr2->inverter(i2, 0, 0); // inversion for both flavor components + } - // conclude the change of basis for the heavy doublet - for (size_t beta = 0; beta < 4; beta++) { // spin dilution index - for (size_t F = 0; F < 2; F++) { // flavor projection index - for (size_t i_eo = 0; i_eo < 2; i_eo++) { // even-odd - // (c,s) --> [(1-i*tau_2)/sqrt(2)] * (c,s) - // stored temporarely in the propagator spinors (used as dummy) - mul_one_pm_itau2_and_div_by_sqrt2( - arr_eo_spinor[1][1][beta][F][i_eo][0], arr_eo_spinor[1][1][beta][F][i_eo][1], - arr_eo_spinor[0][1][beta][F][i_eo][0], arr_eo_spinor[0][1][beta][F][i_eo][1], -1.0, - VOLUME / 2); - - for (size_t i_f = 0; i_f < 2; i_f++) { - // assigning the result to the first components (the sources). - // The propagators will be overwritten with the inversion - assign(arr_eo_spinor[0][1][beta][F][i_eo][i_f], - arr_eo_spinor[1][1][beta][F][i_eo][i_f], VOLUME / 2); - } - } - } + // conclude the change of basis for the heavy doublet + for (size_t beta = 0; beta < 4; beta++) { // spin dilution index + for (size_t F = 0; F < 2; F++) { // flavor projection index + for (size_t i_eo = 0; i_eo < 2; i_eo++) { // even-odd + // (c,s) --> [(1-i*tau_2)/sqrt(2)] * (c,s) + // stored temporarely in the propagator spinors (used as dummy) + mul_one_pm_itau2_and_div_by_sqrt2( + arr_eo_spinor[1][1][beta][F][i_eo][0], arr_eo_spinor[1][1][beta][F][i_eo][1], + arr_eo_spinor[0][1][beta][F][i_eo][0], arr_eo_spinor[0][1][beta][F][i_eo][1], -1.0, + VOLUME / 2); + + for (size_t i_f = 0; i_f < 2; i_f++) { + // assigning the result to the first components (the sources). + // The propagators will be overwritten with the inversion + assign(arr_eo_spinor[0][1][beta][F][i_eo][i_f], + arr_eo_spinor[1][1][beta][F][i_eo][i_f], VOLUME / 2); } + } + } + } - // (no even-odd): source+propagator, doublet, spin dilution index, flavor proj, flavor - // index, position (+ Dirac, color) (psi[i_sp][d][beta][F][f][x])[alpha][c] - // last 3 indices come from the spinor struct - const int sizes_arr_spinor = {2, 2, 4, 2, 2, VOLUME}; - spinor ******arr_spinor = - (spinor ******)callocMultiDimensional(sizes_arr_spinor, 6, sizeof(spinor)); - - // now we switch from even-odd representation to standard - - for (size_t i_sp = 0; i_sp < 2; i_sp++) { // source or sink - for (size_t db = 0; db < 2; db++) { // doublet: light of heavy - for (size_t F = 0; F < 2; F++) { // flavor projection index - for (size_t beta = 0; beta < 4; beta++) { // spin dilution index - for (size_t i_f = 0; i_f < 2; i_f++) { - convert_eo_to_lexic(arr_spinor[i_sp][db][F][beta][i_f], + // (no even-odd): source+propagator, doublet, spin dilution index, flavor proj, flavor + // index, position (+ Dirac, color) (psi[i_sp][d][beta][F][f][x])[alpha][c] + // last 3 indices come from the spinor struct + const int sizes_arr_spinor = {2, 2, 4, 2, 2, VOLUME}; + spinor ******arr_spinor = + (spinor ******)callocMultiDimensional(sizes_arr_spinor, 6, sizeof(spinor)); + + // now we switch from even-odd representation to standard + + for (size_t i_sp = 0; i_sp < 2; i_sp++) { // source or sink + for (size_t db = 0; db < 2; db++) { // doublet: light of heavy + for (size_t F = 0; F < 2; F++) { // flavor projection index + for (size_t beta = 0; beta < 4; beta++) { // spin dilution index + for (size_t i_f = 0; i_f < 2; i_f++) { + convert_eo_to_lexic(arr_spinor[i_sp][db][F][beta][i_f], arr_eo_spinor[i_sp][db][F][beta][0][i_f], arr_eo_spinor[i_sp][db][F][beta][1][i_f]); - } - } - } } } + } + } + } + + free(arr_eo_spinor); // freeing up space: eo spinors not needed anymore + + /* + Now that I have all the propagators (all in the basis of + https://arxiv.org/pdf/1005.2042.pdf) I can build the correlators of eq. (20) + */ - free(arr_eo_spinor); // freeing up space: eo spinors not needed anymore - - /* - Now that I have all the propagators (all in the basis of - https://arxiv.org/pdf/1005.2042.pdf) I can build the correlators of eq. (20) - */ - - const int f0 = 0; // flavor index of the up - - /* now we sum only over local space for every t */ - for (t = 0; t < T; t++) { - j = g_ipt[t][0][0][0]; - - // dummy variables - res = 0.; - respa = 0.; - resp4 = 0.; - - for (i = j; i < j + LX * LY * LZ; i++) { - for (size_t beta = 0; beta < 4; beta++) { // spin dilution - spinor psi_u = arr_spinor[1][0][beta][f0][f0][i]; - - res += _spinor_prod_re(psi_u, psi_u); - _gamma0(phi, psi_u); - respa += _spinor_prod_re(psi_u, phi); - _gamma5(phi, phi); - resp4 += _spinor_prod_im(psi_u, phi); - - for (size_t F = 0; F < 2; F++) { // flavor projection - for (size_t hi = 0; hi < 2; hi++) { - for (size_t hj = 0; hj < 2; hj++) { - for (size_t g1 = 0; g1 < 2; g1++) { - for (size_t g2 = 0; g2 < 2; g2++) { - double dum = 0.0; // dummy variable - - // heavy doublet spinor propagator - phi = arr_spinor[1][1][beta][hj][hi][i]; - if (g1 == 0) { // Gamma_1 = \mathbb{1} - _gamma5(phi, phi); - } - _spinor_scalar_prod(dum, psi_u, phi); - - double sign_beta = +1; - if(g2 == 0 /* Gamma_2 == \mathbb{1} */ && beta>2){ - sign_beta = -1; - } - res_hihj_g1g2[hi][hj][g1][g2] += sign_beta*dum; - } - } + const int f0 = 0; // flavor index of the up + + /* now we sum only over local space for every t */ + for (t = 0; t < T; t++) { + j = g_ipt[t][0][0][0]; + + // dummy variables + res = 0.; + respa = 0.; + resp4 = 0.; + + for (i = j; i < j + LX * LY * LZ; i++) { + for (size_t beta = 0; beta < 4; beta++) { // spin dilution + spinor psi_u = arr_spinor[1][0][beta][f0][f0][i]; + + res += _spinor_prod_re(psi_u, psi_u); + _gamma0(phi, psi_u); + respa += _spinor_prod_re(psi_u, phi); + _gamma5(phi, phi); + resp4 += _spinor_prod_im(psi_u, phi); + + for (size_t F = 0; F < 2; F++) { // flavor projection + for (size_t hi = 0; hi < 2; hi++) { + for (size_t hj = 0; hj < 2; hj++) { + for (size_t g1 = 0; g1 < 2; g1++) { + for (size_t g2 = 0; g2 < 2; g2++) { + double dum = 0.0; // dummy variable + + // heavy doublet spinor propagator + phi = arr_spinor[1][1][beta][hj][hi][i]; + if (g1 == 0) { // Gamma_1 = \mathbb{1} + _gamma5(phi, phi); + } + _spinor_scalar_prod(dum, psi_u, phi); + + double sign_beta = +1; + if (g2 == 0 /* Gamma_2 == \mathbb{1} */ && beta > 2) { + sign_beta = -1; } + res_hihj_g1g2[hi][hj][g1][g2] += sign_beta * dum; } } } } + } + } + } #if defined TM_USE_MPI - MPI_Reduce(&res, &mpi_res, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); - res = mpi_res; - MPI_Reduce(&respa, &mpi_respa, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); - respa = mpi_respa; - MPI_Reduce(&resp4, &mpi_resp4, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); - resp4 = mpi_resp4; - sCpp[t] = +res / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / - optr1->kappa / optr1->kappa; - sCpa[t] = -respa / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / - optr1->kappa / optr1->kappa; - sCp4[t] = +resp4 / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / - optr1->kappa / optr1->kappa; + MPI_Reduce(&res, &mpi_res, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); + res = mpi_res; + MPI_Reduce(&respa, &mpi_respa, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); + respa = mpi_respa; + MPI_Reduce(&resp4, &mpi_resp4, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); + resp4 = mpi_resp4; + sCpp[t] = +res / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / + optr1->kappa / optr1->kappa; + sCpa[t] = -respa / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / + optr1->kappa / optr1->kappa; + sCp4[t] = +resp4 / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / + optr1->kappa / optr1->kappa; #else - Cpp[t] = +res / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / - optr1->kappa / optr1->kappa; - Cpa[t] = -respa / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / - optr1->kappa / optr1->kappa; - Cp4[t] = +resp4 / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / - optr1->kappa / optr1->kappa; + Cpp[t] = +res / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / optr1->kappa / + optr1->kappa; + Cpa[t] = -respa / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / + optr1->kappa / optr1->kappa; + Cp4[t] = +resp4 / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ) / 2. / + optr1->kappa / optr1->kappa; #endif - for (size_t hi = 0; hi < 2; hi++) { - for (size_t hj = 0; hj < 2; hj++) { - for (size_t g1 = 0; g1 < 2; g1++) { - for (size_t g2 = 0; g2 < 2; g2++) { + for (size_t hi = 0; hi < 2; hi++) { + for (size_t hj = 0; hj < 2; hj++) { + for (size_t g1 = 0; g1 < 2; g1++) { + for (size_t g2 = 0; g2 < 2; g2++) { #if defined TM_USE_MPI - MPI_Reduce( - &res_hihj_g1g2[hi][hj][g1][g2], &mpi_res_hihj_g1g2[hi][hj][g1][g2], 1, - MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); - res_hihj_g1g2[hi][hj][g1][g2] = mpi_res_hihj_g1g2[hi][hj][g1][g2]; - sC_hihj_g1g2[hi][hj][g1][g2][t] = -eta_Gamma[g1] * res / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ); + MPI_Reduce(&res_hihj_g1g2[hi][hj][g1][g2], &mpi_res_hihj_g1g2[hi][hj][g1][g2], 1, + MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); + res_hihj_g1g2[hi][hj][g1][g2] = mpi_res_hihj_g1g2[hi][hj][g1][g2]; + sC_hihj_g1g2[hi][hj][g1][g2][t] = + -eta_Gamma[g1] * res / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ); #else - C_hihj_g1g2[hi][hj][g1][g2][t] = -eta_Gamma[g1] * res / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ); + C_hihj_g1g2[hi][hj][g1][g2][t] = + -eta_Gamma[g1] * res / (g_nproc_x * LX) / (g_nproc_y * LY) / (g_nproc_z * LZ); #endif - } - } - } } + } + } + } - } // end loop over "t" + } // end loop over "t" #ifdef TM_USE_MPI - /* some gymnastics needed in case of parallelisation */ - if (g_mpi_time_rank == 0) { - // light correlators - MPI_Gather(sCpp, T, MPI_DOUBLE, Cpp, T, MPI_DOUBLE, 0, g_mpi_SV_slices); - MPI_Gather(sCpa, T, MPI_DOUBLE, Cpa, T, MPI_DOUBLE, 0, g_mpi_SV_slices); - MPI_Gather(sCp4, T, MPI_DOUBLE, Cp4, T, MPI_DOUBLE, 0, g_mpi_SV_slices); - - // heavy mesons - for (size_t hi = 0; hi < 2; hi++) { - for (size_t hj = 0; hj < 2; hj++) { - for (size_t g1 = 0; g1 < 2; g1++) { - for (size_t g2 = 0; g2 < 2; g2++) { - MPI_Gather(sC_hihj_g1g2[hi][hj][g1][g2], T, MPI_DOUBLE, C_hihj_g1g2[hi][hj][g1][g2], - T, MPI_DOUBLE, 0, g_mpi_SV_slices); - } - } + /* some gymnastics needed in case of parallelisation */ + if (g_mpi_time_rank == 0) { + // light correlators + MPI_Gather(sCpp, T, MPI_DOUBLE, Cpp, T, MPI_DOUBLE, 0, g_mpi_SV_slices); + MPI_Gather(sCpa, T, MPI_DOUBLE, Cpa, T, MPI_DOUBLE, 0, g_mpi_SV_slices); + MPI_Gather(sCp4, T, MPI_DOUBLE, Cp4, T, MPI_DOUBLE, 0, g_mpi_SV_slices); + + // heavy mesons + for (size_t hi = 0; hi < 2; hi++) { + for (size_t hj = 0; hj < 2; hj++) { + for (size_t g1 = 0; g1 < 2; g1++) { + for (size_t g2 = 0; g2 < 2; g2++) { + MPI_Gather(sC_hihj_g1g2[hi][hj][g1][g2], T, MPI_DOUBLE, C_hihj_g1g2[hi][hj][g1][g2], + T, MPI_DOUBLE, 0, g_mpi_SV_slices); } } } + } + } #endif - /* and write everything into a file */ - if (g_mpi_time_rank == 0 && g_proc_coords[0] == 0) { - ofs = fopen(filename, "w"); - fprintf(ofs, "1 1 0 %e %e\n", Cpp[t0], 0.); - for (t = 1; t < g_nproc_t * T / 2; t++) { - tt = (t0 + t) % (g_nproc_t * T); - fprintf(ofs, "1 1 %d %e ", t, Cpp[tt]); - tt = (t0 + g_nproc_t * T - t) % (g_nproc_t * T); - fprintf(ofs, "%e\n", Cpp[tt]); - } - tt = (t0 + g_nproc_t * T / 2) % (g_nproc_t * T); - fprintf(ofs, "1 1 %d %e %e\n", t, Cpp[tt], 0.); - - fprintf(ofs, "2 1 0 %e %e\n", Cpa[t0], 0.); - for (t = 1; t < g_nproc_t * T / 2; t++) { - tt = (t0 + t) % (g_nproc_t * T); - fprintf(ofs, "2 1 %d %e ", t, Cpa[tt]); - tt = (t0 + g_nproc_t * T - t) % (g_nproc_t * T); - fprintf(ofs, "%e\n", Cpa[tt]); - } - tt = (t0 + g_nproc_t * T / 2) % (g_nproc_t * T); - fprintf(ofs, "2 1 %d %e %e\n", t, Cpa[tt], 0.); - - fprintf(ofs, "6 1 0 %e %e\n", Cp4[t0], 0.); - for (t = 1; t < g_nproc_t * T / 2; t++) { - tt = (t0 + t) % (g_nproc_t * T); - fprintf(ofs, "6 1 %d %e ", t, Cp4[tt]); - tt = (t0 + g_nproc_t * T - t) % (g_nproc_t * T); - fprintf(ofs, "%e\n", Cp4[tt]); - } - tt = (t0 + g_nproc_t * T / 2) % (g_nproc_t * T); - fprintf(ofs, "6 1 %d %e %e\n", t, Cp4[tt], 0.); - - // heavy meson correlators - for (size_t hi = 0; hi < 2; hi++) { - for (size_t hj = 0; hj < 2; hj++) { - for (size_t g1 = 0; g1 < 2; g1++) { - for (size_t g2 = 0; g2 < 2; g2++) { - fprintf(ofs, "%d %d %d %d 0 %e %e\n", hi, hj, g1, g2, C_hihj_g1g2[hi][hj][g1][g1][t0], 0.); - for (t = 1; t < g_nproc_t * T / 2; t++) { - tt = (t0 + t) % (g_nproc_t * T); - fprintf(ofs, "%d %d %d %d %d %e ", hi, hj, g1, g2, t, C_hihj_g1g2[hi][hj][g1][g2][tt]); - tt = (t0 + g_nproc_t * T - t) % (g_nproc_t * T); - fprintf(ofs, "%e\n", C_hihj_g1g2[hi][hj][g1][g2][tt]); - } - tt = (t0 + g_nproc_t * T / 2) % (g_nproc_t * T); - fprintf(ofs, "%d %d %d %d %d %d %e %e\n", hi, hj, g1, g2, t, - C_hihj_g1g2[hi][hj][g1][g2][tt], 0.0); - } + /* and write everything into a file */ + if (g_mpi_time_rank == 0 && g_proc_coords[0] == 0) { + ofs = fopen(filename, "w"); + fprintf(ofs, "1 1 0 %e %e\n", Cpp[t0], 0.); + for (t = 1; t < g_nproc_t * T / 2; t++) { + tt = (t0 + t) % (g_nproc_t * T); + fprintf(ofs, "1 1 %d %e ", t, Cpp[tt]); + tt = (t0 + g_nproc_t * T - t) % (g_nproc_t * T); + fprintf(ofs, "%e\n", Cpp[tt]); + } + tt = (t0 + g_nproc_t * T / 2) % (g_nproc_t * T); + fprintf(ofs, "1 1 %d %e %e\n", t, Cpp[tt], 0.); + + fprintf(ofs, "2 1 0 %e %e\n", Cpa[t0], 0.); + for (t = 1; t < g_nproc_t * T / 2; t++) { + tt = (t0 + t) % (g_nproc_t * T); + fprintf(ofs, "2 1 %d %e ", t, Cpa[tt]); + tt = (t0 + g_nproc_t * T - t) % (g_nproc_t * T); + fprintf(ofs, "%e\n", Cpa[tt]); + } + tt = (t0 + g_nproc_t * T / 2) % (g_nproc_t * T); + fprintf(ofs, "2 1 %d %e %e\n", t, Cpa[tt], 0.); + + fprintf(ofs, "6 1 0 %e %e\n", Cp4[t0], 0.); + for (t = 1; t < g_nproc_t * T / 2; t++) { + tt = (t0 + t) % (g_nproc_t * T); + fprintf(ofs, "6 1 %d %e ", t, Cp4[tt]); + tt = (t0 + g_nproc_t * T - t) % (g_nproc_t * T); + fprintf(ofs, "%e\n", Cp4[tt]); + } + tt = (t0 + g_nproc_t * T / 2) % (g_nproc_t * T); + fprintf(ofs, "6 1 %d %e %e\n", t, Cp4[tt], 0.); + + // heavy meson correlators + for (size_t hi = 0; hi < 2; hi++) { + for (size_t hj = 0; hj < 2; hj++) { + for (size_t g1 = 0; g1 < 2; g1++) { + for (size_t g2 = 0; g2 < 2; g2++) { + fprintf(ofs, "%d %d %d %d 0 %e %e\n", hi, hj, g1, g2, + C_hihj_g1g2[hi][hj][g1][g1][t0], 0.); + for (t = 1; t < g_nproc_t * T / 2; t++) { + tt = (t0 + t) % (g_nproc_t * T); + fprintf(ofs, "%d %d %d %d %d %e ", hi, hj, g1, g2, t, + C_hihj_g1g2[hi][hj][g1][g2][tt]); + tt = (t0 + g_nproc_t * T - t) % (g_nproc_t * T); + fprintf(ofs, "%e\n", C_hihj_g1g2[hi][hj][g1][g2][tt]); } + tt = (t0 + g_nproc_t * T / 2) % (g_nproc_t * T); + fprintf(ofs, "%d %d %d %d %d %d %e %e\n", hi, hj, g1, g2, t, + C_hihj_g1g2[hi][hj][g1][g2][tt], 0.0); } } - fclose(ofs); } + } + fclose(ofs); + } #ifdef TM_USE_MPI - if (g_mpi_time_rank == 0) { - free(Cpp); - free(Cpa); - free(Cp4); - free(C_hihj_g1g2); - } - free(sCpp); - free(sCpa); - free(sCp4); - free(sC_hihj_g1g2); + if (g_mpi_time_rank == 0) { + free(Cpp); + free(Cpa); + free(Cp4); + free(C_hihj_g1g2); + } + free(sCpp); + free(sCpa); + free(sCp4); + free(sC_hihj_g1g2); #else - free(Cpp); - free(Cpa); - free(Cp4); - free(C_hihj_g1g2); + free(Cpp); + free(Cpa); + free(Cp4); + free(C_hihj_g1g2); #endif - } // for(max_time_slices) - } // for(max_samples) + } // for(max_time_slices) + } // for(max_samples) - tm_stopwatch_pop(&g_timers, 0, 1, ""); + tm_stopwatch_pop(&g_timers, 0, 1, ""); - return; + return; } void correlators_measurement(const int traj, const int id, const int ieo) {