From babc61f537fd1ede1dda1bbf1dc7d8a82f343c89 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Sat, 18 Apr 2026 09:31:50 +0200 Subject: [PATCH 01/46] compilation from y6 add new files and upate make --- compile/compile_me.mk | 10 ++++++++ compile/goals.mk | 11 +++++++++ compile/targets.mk | 12 ++++++++++ services/make.inc | 55 ++++++++++++++++++++----------------------- 4 files changed, 59 insertions(+), 29 deletions(-) create mode 100644 compile/compile_me.mk create mode 100644 compile/goals.mk create mode 100644 compile/targets.mk diff --git a/compile/compile_me.mk b/compile/compile_me.mk new file mode 100644 index 00000000..3c3a6fbf --- /dev/null +++ b/compile/compile_me.mk @@ -0,0 +1,10 @@ +# +# License-Identifier: GPL +# +# Copyright (C) 2025 The Yambo Team +# +# Authors (see AUTHORS file for details): AM MN +# +# LetzElPhC ep plugin - yambo build system stub +# Integration handled via SERVICES_LIBS in libraries.mk +# diff --git a/compile/goals.mk b/compile/goals.mk new file mode 100644 index 00000000..706aa3c7 --- /dev/null +++ b/compile/goals.mk @@ -0,0 +1,11 @@ +# +# License-Identifier: GPL +# +# Copyright (C) 2025 The Yambo Team +# +# Authors (see AUTHORS file for details): AM MN +# +# Co-Authors (see AUTHORS file for details): RR +# LetzElPhC ep plugin - yambo build system stub +# Integration handled via SERVICES_LIBS in libraries.mk +# diff --git a/compile/targets.mk b/compile/targets.mk new file mode 100644 index 00000000..8e75d98b --- /dev/null +++ b/compile/targets.mk @@ -0,0 +1,12 @@ +# +# License-Identifier: GPL +# +# Copyright (C) 2025 The Yambo Team +# +# Authors (see AUTHORS file for details): AM MN +# +# +# Co-Authors (see AUTHORS file for details): RR +# LetzElPhC ep plugin - yambo build system stub +# Integration handled via SERVICES_LIBS in libraries.mk +# diff --git a/services/make.inc b/services/make.inc index 368d2924..9fd90f36 100644 --- a/services/make.inc +++ b/services/make.inc @@ -1,38 +1,35 @@ -CC := mpicc +# Library paths and compiler are taken directly from yambo's configure output +# (config/setup, two levels above this plugin directory). +# Run `bash yambo_build_rr.sh` (or your configure script) before `make` here. +YAMBO_ROOT := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/../../..) +include $(YAMBO_ROOT)/config/setup -### if you are using yambo <= 5.1.2, you need to add "-DYAMBO_LT_5_1" to cflags -### add -DCOMPILE_ELPH_DOUBLE if you want to compile the code in double precession to cflags -#CFLAGS := -O3 -Wall -Wextra -march=native -fopenmp -#LD_FLAGS := -fopenmp +CC := $(cc) -##Debug flags, incase of testing always turn on the address sanitizer ! (clang is recommanded for this) -CFLAGS := -g -Wall -Wextra # -fsanitize=address,undefined -fno-omit-frame-pointer # for mkl add -LD_FLAGS := -g # -fsanitize=address,undefined -Wl,-no_compact_unwind +### if you are using yambo <= 5.1.2, add -DYAMBO_LT_5_1 to CFLAGS +### add -DCOMPILE_ELPH_DOUBLE to compile in double precision +CFLAGS := -O2 -Wall -Wextra +LD_FLAGS := +OPENMP_FLAGS := +#-DELPH_OMP_PARALLEL_BUILD ## uncomment for openmp build -OPENMP_FLAGS := -#-DELPH_OMP_PARALLEL_BUILD ## uncomment for openmp build +# FFTW: yambo's lfft/ifft cover fftw3; add fftw3f (single-precision) needed by LetzElPhC +FFTW_INC := $(ifft) +FFTW3_LIB := $(lfft) -lfftw3f -FFTW_INC := -I${YAMBO_EXT_LIBS}/gfortran/mpifort/include/ -FFTW3_LIB := -L${YAMBO_EXT_LIBS}/gfortran/mpifort/lib -lfftw3f -lfftw3 -#FFTW_INC := -I/opt/homebrew/include -#FFTW3_LIB := -L/opt/homebrew/lib -lfftw3_threads -lfftw3f -lfftw3f_omp -lfftw3_omp -lfftw3 +BLAS_LIB := $(lblas) -#BLAS_LIB := -L/opt/homebrew/opt/openblas/lib -lopenblas -BLAS_LIB := -L${YAMBO_EXT_LIBS}/gfortran/mpifort/lib -lopenblas +# NetCDF: yambo's lnetcdf/inetcdf point to the parallel-enabled build (nc_open_par) +NETCDF_INC := $(inetcdf) +NETCDF_LIB := $(lnetcdf) -NETCDF_INC := -I${YAMBO_EXT_LIBS}/gfortran/mpifort/v4/parallel/include -NETCDF_LIB := -L${YAMBO_EXT_LIBS}/gfortran/mpifort/v4/parallel/lib -lnetcdf -HDF5_LIB := -L${YAMBO_EXT_LIBS}/gfortran/mpifort/v4/parallel/lib -lhdf5_hl -lhdf5 -lz -#NETCDF_INC := -I/Users/murali/softwares/core/include -#NETCDF_LIB := -L/Users/murali/softwares/core/lib -lnetcdf -#HDF5_LIB := -L/opt/homebrew/lib -lhdf5 +# HDF5: yambo links -lhdf5_fortran; LetzElPhC needs the C high-level API (-lhdf5_hl). +# Extract the -L flags from yambo's hdf5 config and substitute C-appropriate libraries. +HDF5_LIB := $(filter -L%,$(lhdf5)) -lhdf5_hl -lhdf5 -lz +INC_DIRS := +LIBS := -INC_DIRS := -LIBS := - -#### Notes Extra CFLAGS -### add -DCOMPILE_ELPH_DOUBLE if you want to compile the code in double precession -### if you are using yambo <= 5.1.2, you need to add "-DYAMBO_LT_5_1" to cflags -### for openmp use -DELPH_OMP_PARALLEL_BUILD in CFLAGS and set -fopenmp in LD_FLAGS and CFLAGS +#### Notes / Extra CFLAGS +### for openmp: add -DELPH_OMP_PARALLEL_BUILD to CFLAGS and -fopenmp to LD_FLAGS and CFLAGS From 7a5e260c30e5afe2e3e8f0d35eb128c81843adca Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Sun, 19 Apr 2026 19:18:33 +0200 Subject: [PATCH 02/46] allow double and single fftw --- services/elph/.objects | 2 +- services/elph/ep_f2c_bridge.c | 20 ++++++++++++++++++++ services/make.inc | 9 ++++++--- 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 services/elph/ep_f2c_bridge.c diff --git a/services/elph/.objects b/services/elph/.objects index dae7f16b..81fa9f60 100644 --- a/services/elph/.objects +++ b/services/elph/.objects @@ -1 +1 @@ -objs = set_kernel.o elph_driver.o compute_elph_matq.o compute_dmats.o +objs = set_kernel.o elph_driver.o compute_elph_matq.o compute_dmats.o ep_f2c_bridge.o diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c new file mode 100644 index 00000000..e5c8d76e --- /dev/null +++ b/services/elph/ep_f2c_bridge.c @@ -0,0 +1,20 @@ +/* + * License-Identifier: GPL + * + * Copyright (C) 2025 The Yambo Team + * + * Authors (see AUTHORS file for details): RR AM + * + * Thin bridge: called from Fortran via ISO_C_BINDING. + * Converts a Fortran MPI communicator handle (MPI_Fint) to a C MPI_Comm + * and forwards the call to LetzElPhC's elph_driver(). + */ + +#include "elph.h" /* already pulls in common/dtypes.h and elphC.h */ +#include + +void elph_driver_f2c(const char* input_file, int dft_code, MPI_Fint f_comm) +{ + MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + elph_driver(input_file, (enum ELPH_dft_code)dft_code, c_comm); +} diff --git a/services/make.inc b/services/make.inc index 9fd90f36..4e7bf6da 100644 --- a/services/make.inc +++ b/services/make.inc @@ -1,21 +1,24 @@ # Library paths and compiler are taken directly from yambo's configure output # (config/setup, two levels above this plugin directory). -# Run `bash yambo_build_rr.sh` (or your configure script) before `make` here. YAMBO_ROOT := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/../../..) include $(YAMBO_ROOT)/config/setup CC := $(cc) -### if you are using yambo <= 5.1.2, add -DYAMBO_LT_5_1 to CFLAGS ### add -DCOMPILE_ELPH_DOUBLE to compile in double precision CFLAGS := -O2 -Wall -Wextra LD_FLAGS := OPENMP_FLAGS := #-DELPH_OMP_PARALLEL_BUILD ## uncomment for openmp build -# FFTW: yambo's lfft/ifft cover fftw3; add fftw3f (single-precision) needed by LetzElPhC +# FFTW: yambo's lfft/ifft cover fftw3 (double); LetzElPhC defaults to single precision (fftw3f). +# Set -DCOMPILE_ELPH_DOUBLE in CFLAGS above to switch LetzElPhC to double precision. FFTW_INC := $(ifft) +ifeq (,$(findstring -DCOMPILE_ELPH_DOUBLE,$(CFLAGS))) FFTW3_LIB := $(lfft) -lfftw3f +else +FFTW3_LIB := $(lfft) -lfftw3 +endif BLAS_LIB := $(lblas) From e846abb4371f80be5daffd7516558a7ffedf28d1 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Thu, 30 Apr 2026 14:54:40 +0200 Subject: [PATCH 03/46] changes for elph plugin echo --- compile/compile_me.mk | 2 ++ compile/headers_and_libs.mk | 14 ++++++++++++++ compile/help.mk | 16 ++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 compile/headers_and_libs.mk create mode 100644 compile/help.mk diff --git a/compile/compile_me.mk b/compile/compile_me.mk index 3c3a6fbf..8e75d98b 100644 --- a/compile/compile_me.mk +++ b/compile/compile_me.mk @@ -5,6 +5,8 @@ # # Authors (see AUTHORS file for details): AM MN # +# +# Co-Authors (see AUTHORS file for details): RR # LetzElPhC ep plugin - yambo build system stub # Integration handled via SERVICES_LIBS in libraries.mk # diff --git a/compile/headers_and_libs.mk b/compile/headers_and_libs.mk new file mode 100644 index 00000000..d6c32c0b --- /dev/null +++ b/compile/headers_and_libs.mk @@ -0,0 +1,14 @@ +# +# License-Identifier: GPL +# +# Copyright (C) 2025 The Yambo Team +# +# Authors (see AUTHORS file for details): RR AM +# +# LetzElPhC ep plugin - extra include paths for the vendored C source. +# C files under plugins/ep/services//*.c use relative includes +# like "common/dtypes.h", so the plugin services root must be on the +# include path. +# +iheaders += $(IFLAG)$(srcdir)/plugins/ep/services +include_headers += $(IFLAG)$(srcdir)/plugins/ep/services diff --git a/compile/help.mk b/compile/help.mk new file mode 100644 index 00000000..3a7ee157 --- /dev/null +++ b/compile/help.mk @@ -0,0 +1,16 @@ +# +# License-Identifier: GPL +# +# Copyright (C) 2025 The Yambo Team +# +# Authors (see AUTHORS file for details): RR AM +# +# Help blurb for the ep (LetzElPhC) plugin, called from +# compile/global/functions/help.mk when plugins/ep.pulled is present. +# +define ep_help + $(ECHO) " ep plugin = LetzElPhC electron-phonon coupling plugin";\ + $(ECHO) " Trigger: yambo -collisions ep";\ + $(ECHO) " Source: plugins/ep/services/, integration: packages/el-ph/";\ + $(ECHO) +endef From 4c6501990219f070ab134e5e26b26edf1e2b6abd Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Tue, 5 May 2026 11:22:52 +0200 Subject: [PATCH 04/46] ignore tests --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 11ec0f59..c4e78f0b 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ controllers/options/options_driver.c controllers/defaults/DEFAULTS_driver.F services/controllers/SERVICES_setup.F services/units/UNITS_defaults.F +tests/ From 82ee49cc5b2814b86e1af66f08a16213caa87c88 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Tue, 5 May 2026 11:25:27 +0200 Subject: [PATCH 05/46] update to write ndb.electron-phonon db in y6 --- services/elph/compute_elph_matq.c | 25 +++- services/elph/elph.h | 19 ++- services/elph/elph_driver.c | 186 +++++++++++++++++++++++++++++- services/elph/ep_f2c_bridge.c | 12 ++ 4 files changed, 235 insertions(+), 7 deletions(-) diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index 82b72650..a9af8bf1 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -24,7 +24,8 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, const int varid_elph, const int ncid_dmat, const int varid_dmat, const bool non_loc, const bool kminusq, - const struct ELPH_MPI_Comms* Comm) + const struct ELPH_MPI_Comms* Comm, + elph_fill_fn fill_fn) { /* dVscf -> (nmodes,nmag,Nx,Ny,Nz) @@ -146,8 +147,15 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, int nc_err; if (Comm->commK_rank == 0) { - if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, countp, - elph_kq_mn))) + if (fill_fn != NULL) + { + fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, + (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, + (int)lattice->nspin, (int)nbnds, + (int)lattice->start_band); + } + else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, + countp, elph_kq_mn))) { ERR(nc_err); } @@ -209,8 +217,15 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, startp[0] = qpos_star; startp[1] = idx_Sk; // Write it for Sq and Sk point - if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, countp, - gSq_buff))) + if (fill_fn != NULL) + { + fill_fn((int)startp[0], (int)startp[1], gSq_buff, + (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, + (int)lattice->nspin, (int)nbnds, + (int)lattice->start_band); + } + else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, + countp, gSq_buff))) { ERR(nc_err); } diff --git a/services/elph/elph.h b/services/elph/elph.h index d0513c5d..045d00e2 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -5,9 +5,25 @@ #include "common/dtypes.h" #include "elphC.h" +/* + * Per-(iq_BZ, ik_BZ) fill callback for yambo COLL integration. + * Called once per BZ (q,k) pair on commK_rank==0 processes. + * iq_BZ, ik_BZ : 0-based BZ indices + * data : ELPH_cmplx buffer, C row-major (nmodes, nspin, nbnds, nbnds) + * nq..nb_start : full-BZ dimensions (constant across calls); nb_start is 1-based + */ +typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, + const void* data, + int nq, int nk, int nmodes, int nspin, + int nbnds, int nb_start); + void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, MPI_Comm comm_world); +/* Callback-enabled variant: skips ndb.elph; calls fill_fn per (q,k) instead. */ +void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn); + void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, struct Pseudo* pseudo, struct Phonon* phonon, const ND_int iqpt, ELPH_cmplx* eigVec, @@ -15,7 +31,8 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, const int varid_elph, const int ncid_dmat, const int varid_dmat, const bool non_loc, const bool kminusq, - const struct ELPH_MPI_Comms* Comm); + const struct ELPH_MPI_Comms* Comm, + elph_fill_fn fill_fn); void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, const struct Lattice* lattice, diff --git a/services/elph/elph_driver.c b/services/elph/elph_driver.c index e09baeff..3a9993a3 100644 --- a/services/elph/elph_driver.c +++ b/services/elph/elph_driver.c @@ -303,7 +303,7 @@ void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, eigVec, dVscf, ncid_elph, varid_elph, ncid_dmat, varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms); + input_data->kminusq, mpi_comms, NULL); } free(eig_Sq); @@ -374,3 +374,187 @@ void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, // done with the calculation print_info_msg(World_rank_tmp, "********** Program ended **********"); } + +/* + * Callback-enabled driver: identical flow to elph_driver but writes gkkp + * data via fill_fn(iq_BZ, ik_BZ, data, ...) instead of ndb.elph. + * ndb.Dmats is still created and used internally for BZ symmetry expansion. + * Eigenvectors / frequencies are NOT written (yambo reads them elsewhere). + */ +void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn) +{ + struct elph_usr_input* input_data; + init_ELPH_clocks(); + + read_elph_input_file(ELPH_input_file, &input_data, comm_world); + + struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); + init_kernel(kernel); + set_kernel(input_data->kernel_str, kernel); + + struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); + CHECK_ALLOC(mpi_comms); + + create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, + mpi_comms); + + print_ELPH_logo(mpi_comms->commW_rank, stdout); + print_info_msg(mpi_comms->commW_rank, + "********** Program started **********"); + print_input_info(input_data->save_dir, input_data->ph_save_dir, + input_data->kernel_str, input_data->kminusq, dft_code, + mpi_comms); + + struct Lattice* lattice = malloc(sizeof(struct Lattice)); + CHECK_ALLOC(lattice); + init_lattice_type(lattice); + + struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); + CHECK_ALLOC(pseudo); + init_Pseudo_type(pseudo); + + struct Phonon* phonon = malloc(sizeof(struct Phonon)); + CHECK_ALLOC(phonon); + init_phonon_type(phonon); + + struct WFC* wfcs; + + read_and_alloc_save_data(input_data->save_dir, mpi_comms, + input_data->start_bnd, input_data->end_bnd, &wfcs, + input_data->ph_save_dir, lattice, pseudo, phonon, + dft_code); + + print_lattice_info(mpi_comms, lattice); + print_phonon_info(mpi_comms, phonon); + + print_info_msg(mpi_comms->commW_rank, ""); + print_info_msg(mpi_comms->commW_rank, + "=== Computing Dmats for phonon symmetries ==="); + compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, + phonon->ph_syms, mpi_comms); + + ND_int nmodes = lattice->nmodes; + ND_int nfft_loc = + lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; + + ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); + CHECK_ALLOC(eigVec); + + ELPH_cmplx* dVscf = + malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); + CHECK_ALLOC(dVscf); + + ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); + CHECK_ALLOC(omega_ph); + + int ncid_dmat, nc_err; + int varid_dmat; + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, + MPI_INFO_NULL, &ncid_dmat))) + { + ERR(nc_err); + } + + if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) + { + ERR(nc_err); + } + + size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; + if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, + Dmat_counts, NULL))) + { + ERR(nc_err); + } + } + + print_info_msg(mpi_comms->commW_rank, + "=== Computing Electron-phonon matrix elements ==="); + print_info_msg(mpi_comms->commW_rank, ""); + + for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) + { + print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", + (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); + + ND_int iqpt_iBZg = iqpt + phonon->nq_shift; + + if (dft_code == DFT_CODE_QE) + { + ELPH_cmplx* dvscf_read = NULL; + if (kernel->screening == ELPH_DFPT_SCREENING) + { + dvscf_read = dVscf; + } + else + { + ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; + for (ND_int ix = 0; ix < dvscf_num; ++ix) + { + dVscf[ix] = 0.0; + } + } + get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, + eigVec, dvscf_read, omega_ph, mpi_comms); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + + ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); + CHECK_ALLOC(Vlocr); + dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, + mpi_comms->commK); + + if (dft_code == DFT_CODE_QE) + { + add_dvscf_qe(dVscf, Vlocr, lattice); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + free(Vlocr); + + compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, + eigVec, dVscf, 0, 0, ncid_dmat, + varid_dmat, kernel->non_loc, + input_data->kminusq, mpi_comms, fill_fn); + } + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_close(ncid_dmat))) + { + ERR(nc_err); + } + } + + free(omega_ph); + free(eigVec); + free(dVscf); + + int World_rank_tmp = mpi_comms->commW_rank; + + free(kernel); + free_elph_usr_input(input_data); + free_save_data(wfcs, lattice, pseudo, phonon); + free(lattice); + free(pseudo); + free(phonon); + free_parallel_comms(mpi_comms); + free(mpi_comms); + fftw_fun(cleanup)(); + + if (0 == World_rank_tmp) + { + print_ELPH_clock_summary(); + } + cleanup_ELPH_clocks(); + print_info_msg(World_rank_tmp, "********** Program ended **********"); +} diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index e5c8d76e..c59217ab 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -18,3 +18,15 @@ void elph_driver_f2c(const char* input_file, int dft_code, MPI_Fint f_comm) MPI_Comm c_comm = MPI_Comm_f2c(f_comm); elph_driver(input_file, (enum ELPH_dft_code)dft_code, c_comm); } + +/* + * Callback-enabled bridge: fill_fn_ptr is a Fortran procedure pointer + * (passed as a C function pointer via ISO_C_BINDING's c_funloc). + */ +void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, + void* fill_fn_ptr) +{ + MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + elph_driver_cb(input_file, (enum ELPH_dft_code)dft_code, c_comm, + (elph_fill_fn)fill_fn_ptr); +} From 21295a62792b9e2c13cd4eab7f249cd9bedfcd3e Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Mon, 11 May 2026 22:01:44 +0200 Subject: [PATCH 06/46] add option make lelphc make cleean_lelphc --- compile/goals.mk | 8 +++----- compile/targets.mk | 17 +++++++++++------ services/make.inc | 3 ++- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/compile/goals.mk b/compile/goals.mk index 706aa3c7..9fa43d29 100644 --- a/compile/goals.mk +++ b/compile/goals.mk @@ -3,9 +3,7 @@ # # Copyright (C) 2025 The Yambo Team # -# Authors (see AUTHORS file for details): AM MN -# -# Co-Authors (see AUTHORS file for details): RR -# LetzElPhC ep plugin - yambo build system stub -# Integration handled via SERVICES_LIBS in libraries.mk +# Authors (see AUTHORS file for details): AM MN RR # + +.PHONY: lelphc clean_lelphc diff --git a/compile/targets.mk b/compile/targets.mk index 8e75d98b..5e3a0ea2 100644 --- a/compile/targets.mk +++ b/compile/targets.mk @@ -3,10 +3,15 @@ # # Copyright (C) 2025 The Yambo Team # -# Authors (see AUTHORS file for details): AM MN -# -# -# Co-Authors (see AUTHORS file for details): RR -# LetzElPhC ep plugin - yambo build system stub -# Integration handled via SERVICES_LIBS in libraries.mk +# Authors (see AUTHORS file for details): AM MN RR # +# Build the standalone lelphc binary from LetzElPhC C source. +# Requires yambo to have been configured first (config/setup must exist). +# Usage: make lelphc -> builds plugins/ep/services/lelphc +# make clean_lelphc -> cleans the standalone build + +lelphc: + $(MAKE) -C $(srcdir)/plugins/ep/services + +clean_lelphc: + -$(MAKE) -C $(srcdir)/plugins/ep/services clean diff --git a/services/make.inc b/services/make.inc index 4e7bf6da..3358ebea 100644 --- a/services/make.inc +++ b/services/make.inc @@ -15,7 +15,8 @@ OPENMP_FLAGS := # Set -DCOMPILE_ELPH_DOUBLE in CFLAGS above to switch LetzElPhC to double precision. FFTW_INC := $(ifft) ifeq (,$(findstring -DCOMPILE_ELPH_DOUBLE,$(CFLAGS))) -FFTW3_LIB := $(lfft) -lfftw3f +# lfft from yambo already contains -lfftw3f; strip before appending to avoid duplicate +FFTW3_LIB := $(filter-out -lfftw3f,$(lfft)) -lfftw3f else FFTW3_LIB := $(lfft) -lfftw3 endif From 5030ea74080803cb7fb1a106168f0795d50846ad Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Tue, 12 May 2026 09:09:20 +0200 Subject: [PATCH 07/46] WIP: write dvqG to yambo db --- services/Makefile | 94 +++-- services/compute_dmats.c | 131 ++++++ services/compute_elph_matq.c | 249 +++++++++++ services/dvG_utils.c | 141 +++++++ services/dvG_utils.h | 31 ++ services/elph.h | 66 +++ services/elph/dvG_utils.c | 141 +++++++ services/elph/dvG_utils.h | 31 ++ services/elph/elph.h | 21 + services/elph/elph_driver.c | 202 +++++++++ services/elph/ep_f2c_bridge.c | 13 + services/elph_driver.c | 762 ++++++++++++++++++++++++++++++++++ services/ep_f2c_bridge.c | 45 ++ services/set_kernel.c | 52 +++ 14 files changed, 1934 insertions(+), 45 deletions(-) create mode 100644 services/compute_dmats.c create mode 100644 services/compute_elph_matq.c create mode 100644 services/dvG_utils.c create mode 100644 services/dvG_utils.h create mode 100644 services/elph.h create mode 100644 services/elph/dvG_utils.c create mode 100644 services/elph/dvG_utils.h create mode 100644 services/elph_driver.c create mode 100644 services/ep_f2c_bridge.c create mode 100644 services/set_kernel.c diff --git a/services/Makefile b/services/Makefile index 53edd6b4..2e7a13bd 100644 --- a/services/Makefile +++ b/services/Makefile @@ -1,45 +1,49 @@ -include make.inc - -TARGET := lelphc - -#### make start here - -SUBDIR = nonloc io/ezxml parser/inih io \ - io/qe common dvloc elph wfc \ - symmetries fft common/cwalk \ - preprocessor interpolation \ - common/ELPH_hash_map phonon \ - common/kdtree parser - -.SUFFIXES : - -INCS = $(wildcard *.h $(foreach fd, $(SUBDIR), $(fd)/*.h)) -SRCS = $(wildcard *.c $(foreach fd, $(SUBDIR), $(fd)/*.c)) -OBJS = $(addprefix ./, $(SRCS:c=o)) - -INC_DIRS += -I. $(FFTW_INC) $(NETCDF_INC) -LIBS += $(FFTW3_LIB) $(BLAS_LIB) $(NETCDF_LIB) $(HDF5_LIB) -lm - - -PHONY := $(TARGET) -$(TARGET): $(OBJS) - $(CC) -o ./$@ $(OBJS) $(LIBS) $(LD_FLAGS) - -%.o: %.c $(INCS) make.inc - $(CC) $(CFLAGS) -c $< $(INC_DIRS) $(OPENMP_FLAGS) -o $@ - - -PHONY += clean -clean: - rm ./$(TARGET) $(OBJS) - -PHONY += echoes -echoes: - @echo "INC files: $(INCS)" - @echo "SRC files: $(SRCS)" - @echo "OBJ files: $(OBJS)" - @echo "LIB files: $(LIBS)" - @echo "INC DIR: $(INC_DIRS)" - - -.PHONY = $(PHONY) +# +# License-Identifier: GPL +# +# Copyright (C) 2016 The Yambo Team +# +# Authors (see AUTHORS file for details): HM +# +# VARIABLES (static and dynamical) +# +include dyn_variables.mk +include $(compdir)/compile/local/static_variables.mk +include $(compdir)/compile/local/defs.mk +include $(compdir)/compile/defs.mk +# +# SETUP +# +include $(compdir)/config/setup +# +# Module dependencies +# +-include local_modules.dep +# +# Include directories (headers) +# +include $(compdir)/compile/headers.mk +# +# Libraries +# +include $(compdir)/compile/libraries.mk +ifneq "$(wildcard $(compdir)/plugins/plugins.pulled)" "" + include $(compdir)/plugins/*/compile/headers_and_libs.mk +endif +# +# OBJECTS +# +include objects.mk +# +# OPERATIONS +# +include $(compdir)/compile/local/operations.mk +# +# RULES +# +include $(compdir)/compile/local/rules.mk +# +# FUNCTIONS +# +include $(compdir)/compile/local/functions.mk +# diff --git a/services/compute_dmats.c b/services/compute_dmats.c new file mode 100644 index 00000000..2880e8ee --- /dev/null +++ b/services/compute_dmats.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include + +#include "common/dtypes.h" +#include "common/error.h" +#include "common/parallel.h" +#include "common/progess_bar.h" +#include "elph.h" +#include "elphC.h" +#include "io/io.h" +#include "symmetries/symmetries.h" + +/* + * This function contain the wrapper functions to compute and + * write or read dmat functions to file) + */ + +void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, + const struct Lattice* lattice, + const ND_int nph_sym, + const struct symmetry* sym_data, + const struct ELPH_MPI_Comms* Comm) +{ + ND_int nk_totalBZ = lattice->nkpts_BZ; + ELPH_cmplx* Dkmn_rep_ptr = NULL; + + int ncid, varid, nc_err; + + size_t startp[6] = {0, 0, 0, 0, 0, 0}; + size_t countp[6] = {1, 1, lattice->nspin, lattice->nbnds, lattice->nbnds, + 2}; + + ND_int nk_chunk_size = NC4_DEFAULT_CHUCK_KB * 1024; // now this is in bytes + // scale with complex number size to get the number of elements + nk_chunk_size /= + (sizeof(ELPH_cmplx) * lattice->nspin * lattice->nbnds * lattice->nbnds); + // chuck the varaible elph_mat with atmost default size + if (nk_chunk_size == 0) + { + nk_chunk_size = 1; + } + else if (nk_chunk_size > nk_totalBZ) + { + nk_chunk_size = nk_totalBZ; + } + + if (Comm->commK_rank == 0) + { + // we overwrite any existing file + if ((nc_err = nc_create_par(file_name, NC_NETCDF4 | NC_CLOBBER, + Comm->commR, MPI_INFO_NULL, &ncid))) + { + fprintf(stderr, "Error creating Dmat file"); + ERR(nc_err); + } + // set no fill mode (to avoid writting twice) + if ((nc_err = ncsetfill(ncid, NC_NOFILL))) + { + fprintf(stderr, "Error setting nc_fill to dmat file."); + ERR(nc_err); + } + + def_ncVar(ncid, &varid, 6, ELPH_NC4_IO_FLOAT, + (ND_int[]){nph_sym, nk_totalBZ, lattice->nspin, + lattice->nbnds, lattice->nbnds, 2}, + "Dmats", + (char*[]){"nsym_ph", "nkpts", "nspin", "Rk_band", "k_band", + "re_im"}, + (size_t[]){1, nk_chunk_size, lattice->nspin, lattice->nbnds, + lattice->nbnds, 2}); + + // Make the access INDEPENDENT as not all can call the put_var function + // simultaneously + if ((nc_err = nc_var_par_access(ncid, varid, NC_INDEPENDENT))) + { + ERR(nc_err); + } + + Dkmn_rep_ptr = calloc(lattice->nspin * lattice->nbnds * lattice->nbnds, + sizeof(ELPH_cmplx)); + CHECK_ALLOC(Dkmn_rep_ptr); + } + + // for computation of Dmats, we use all the nodes + // ("nsym", "nk", "nspin", "nbndb", "nbnda") + ND_int dmat_shift; + ND_int ndmats = + distribute_to_grps(nph_sym * nk_totalBZ, Comm->nqpools * Comm->nkpools, + Comm->commW_rank / Comm->commK_size, &dmat_shift); + + // start the progress bar for dmats + struct progress_bar pbar[1]; + start_progressbar(pbar, Comm->commW_rank, ndmats); + + for (ND_int idmat = 0; idmat < ndmats; ++idmat) + { + ND_int isym = (idmat + dmat_shift) / nk_totalBZ; + ND_int ikBZ = (idmat + dmat_shift) % nk_totalBZ; + + startp[0] = isym; + startp[1] = ikBZ; + + // compute the dmats + electronic_reps(wfcs, lattice, sym_data[isym].Rmat, sym_data[isym].tau, + sym_data[isym].time_rev, ikBZ, Dkmn_rep_ptr, Comm); + + if (Comm->commK_rank == 0) + { + // write data to file + if ((nc_err = + nc_put_vara(ncid, varid, startp, countp, Dkmn_rep_ptr))) + { + ERR(nc_err); + } + } + + // update the progress bar + print_progressbar(pbar); + } + if (Comm->commK_rank == 0) + { + free(Dkmn_rep_ptr); + + if ((nc_err = nc_close(ncid))) + { + ERR(nc_err); + } + } +} diff --git a/services/compute_elph_matq.c b/services/compute_elph_matq.c new file mode 100644 index 00000000..a9af8bf1 --- /dev/null +++ b/services/compute_elph_matq.c @@ -0,0 +1,249 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "common/dtypes.h" +#include "common/error.h" +#include "common/numerical_func.h" +#include "common/parallel.h" +#include "common/progess_bar.h" +#include "dvloc/dvloc.h" +#include "elph.h" +#include "elphC.h" +#include "nonloc/Vnonloc.h" +#include "symmetries/symmetries.h" + +void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, + struct Pseudo* pseudo, struct Phonon* phonon, + const ND_int iqpt, ELPH_cmplx* eigVec, + ELPH_cmplx* dVscfq, const int ncid_elph, + const int varid_elph, const int ncid_dmat, + const int varid_dmat, const bool non_loc, + const bool kminusq, + const struct ELPH_MPI_Comms* Comm, + elph_fill_fn fill_fn) +{ + /* + dVscf -> (nmodes,nmag,Nx,Ny,Nz) + ((k, nmodes, nspin, nbands, nbands)) + */ + /* distribute k points */ + int mpi_error; + const ND_int nk_totalBZ = lattice->nkpts_BZ; + + const ELPH_float* qpt = phonon->qpts_iBZ + iqpt * 3; + + ND_int qpos = 0; // positon of this iBZ qpoint in full q point list + for (ND_int i = 0; i < iqpt; ++i) + { + qpos += phonon->nqstar[i]; + } + + // sanity check + if (phonon->qmap[2 * qpos] != iqpt || phonon->qmap[2 * qpos + 1] != 0) + { + error_msg("Qpoint in iBZ cannot be traced in phonon qmap"); + } + + ND_int kshift; + ND_int nk_this_pool = + distribute_to_grps(nk_totalBZ, Comm->nkpools, + Comm->commQ_rank / Comm->commK_size, &kshift); + + if (nk_this_pool < 1) + { + error_msg( + "There are no kpoints in some cpus, Make sure nkpool < # of " + "kpoints in full BZ."); + } + /* get the k point indices and symmetries */ + int* kmap = lattice->kmap; + int* KplusQidxs = malloc(nk_totalBZ * sizeof(int)); + CHECK_ALLOC(KplusQidxs); + + ELPH_float qpt_tmp[3]; + memcpy(qpt_tmp, qpt, sizeof(ELPH_float) * 3); + // incase if we want yambo convention + if (kminusq) + { + for (int xi = 0; xi < 3; ++xi) + { + qpt_tmp[xi] = -qpt_tmp[xi]; + } + } + get_KplusQ_idxs(nk_totalBZ, lattice->kpt_fullBZ_crys, qpt_tmp, KplusQidxs); + + ND_int nbnds = lattice->nbnds; + ND_int nmodes = lattice->nmodes; + + ELPH_cmplx* elph_kq_mn = NULL; + if (Comm->commK_rank == 0) + { + elph_kq_mn = + calloc(nbnds * nbnds * lattice->nspin * nmodes, sizeof(ELPH_cmplx)); + CHECK_ALLOC(elph_kq_mn); + } + //// (nu, nspin, mk, nk+q) + /* Now Compute elph-matrix elements for each kpoint */ + + size_t startp[7] = {0, 0, 0, 0, 0, 0, 0}; + size_t countp[7] = {1, 1, nmodes, lattice->nspin, nbnds, nbnds, 2}; + + ELPH_cmplx* gSq_buff = NULL; + ELPH_cmplx* D_mat_l = NULL; + ELPH_cmplx* D_mat_r = NULL; + + if (Comm->commK_rank == 0) + { + gSq_buff = + calloc(nbnds * nbnds * lattice->nspin * nmodes, sizeof(ELPH_cmplx)); + CHECK_ALLOC(gSq_buff); + + D_mat_l = calloc(nbnds * nbnds * lattice->nspin, sizeof(ELPH_cmplx)); + CHECK_ALLOC(D_mat_l); + + D_mat_r = calloc(nbnds * nbnds * lattice->nspin, sizeof(ELPH_cmplx)); + CHECK_ALLOC(D_mat_r); + } + + // start the progress bar + struct progress_bar pbar[1]; + start_progressbar(pbar, Comm->commW_rank, nk_this_pool); + // compute electron-phonon matrix elements for each kpoint + for (ND_int ii = 0; ii < nk_this_pool; ++ii) + { + /* compute the global k index */ + ND_int i = kshift + ii; + + int idx_k = i; + int idx_kq = KplusQidxs[i]; + + if (kminusq) + { + swap_ints(&idx_k, &idx_kq); + } + + int ik = kmap[2 * idx_k]; + int ksym = kmap[2 * idx_k + 1]; + + int ikq = kmap[2 * idx_kq]; + int kqsym = kmap[2 * idx_kq + 1]; + + elphLocal(qpt, wfcs, lattice, ikq, ik, kqsym, ksym, dVscfq, Comm, + elph_kq_mn); + /* add the non local part elements */ + // WARNING : non local must be added after elphLocal else U.B + if (non_loc) + { + add_elphNonLocal(wfcs, lattice, pseudo, ikq, ik, kqsym, ksym, + eigVec, elph_kq_mn, Comm); + } + startp[0] = qpos; + startp[1] = i; + int nc_err; + if (Comm->commK_rank == 0) + { + if (fill_fn != NULL) + { + fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, + (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, + (int)lattice->nspin, (int)nbnds, + (int)lattice->start_band); + } + else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, + countp, elph_kq_mn))) + { + ERR(nc_err); + } + } + + // expand the el-ph matrix elements in full BZ + const ELPH_float* kpt_BZ = lattice->kpt_fullBZ + 3 * i; + + // only master node does this + if (Comm->commK_rank == 0) + { + for (ND_int istar = 1; istar < phonon->nqstar[iqpt]; ++istar) + { + ND_int qpos_star = qpos + istar; + // get the symmetry + int istar_symm = phonon->qmap[2 * qpos_star + 1]; + + size_t D_mat_sp[6] = {istar_symm, idx_kq, 0, 0, 0, 0}; + size_t D_mat_cp[6] = { + 1, 1, lattice->nspin, lattice->nbnds, lattice->nbnds, 2}; + // read D_mats //const int ncid_dmat, const int varid_dmat, + if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, D_mat_sp, + D_mat_cp, D_mat_l))) + { // k + q + ERR(nc_err); + } + + D_mat_sp[1] = idx_k; + if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, D_mat_sp, + D_mat_cp, D_mat_r))) + { // k + ERR(nc_err); + } + + // gSq_buff + elph_q_rotate(D_mat_l, elph_kq_mn, D_mat_r, lattice, + phonon->ph_syms[istar_symm].time_rev, gSq_buff); + + ELPH_float Sk_crys[3]; + ELPH_float Sk_cart[3]; + + MatVec3f(phonon->ph_syms[istar_symm].Rmat, kpt_BZ, false, + Sk_cart); + // convert to crsytal units + MatVec3f(lattice->alat_vec, Sk_cart, true, Sk_crys); + + // now get the indices of S*k + + ND_int idx_Sk = find_kidx_in_list( + lattice->nkpts_BZ, lattice->kpt_fullBZ_crys, Sk_crys); + + if (idx_Sk < 0) + { + error_msg( + "Unable to to find S*k index " + "This is due to incommenserate k and q grids."); + } + + startp[0] = qpos_star; + startp[1] = idx_Sk; + // Write it for Sq and Sk point + if (fill_fn != NULL) + { + fill_fn((int)startp[0], (int)startp[1], gSq_buff, + (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, + (int)lattice->nspin, (int)nbnds, + (int)lattice->start_band); + } + else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, + countp, gSq_buff))) + { + ERR(nc_err); + } + } + } + mpi_error = MPI_Barrier(Comm->commK); + MPI_error_msg(mpi_error); + // update the progress bar + print_progressbar(pbar); + } + // free wfc buffers + if (Comm->commK_rank == 0) + { + free(elph_kq_mn); + free(gSq_buff); + free(D_mat_l); + free(D_mat_r); + } + + free(KplusQidxs); +} diff --git a/services/dvG_utils.c b/services/dvG_utils.c new file mode 100644 index 00000000..1db548ce --- /dev/null +++ b/services/dvG_utils.c @@ -0,0 +1,141 @@ +/* + * License-Identifier: GPL + * + * Copyright (C) 2025 The Yambo Team + * + * Authors (see AUTHORS file for details): RR AM + * + * Gather distributed dVscf z-slabs to commK rank 0 and apply a forward 3D + * FFT, producing dV_q^nu(G) ready for the elph_dvG_fill_fn callback. + */ + +#include "dvG_utils.h" +#include "fft/fft.h" +#include "common/error.h" +#include +#include + +ELPH_cmplx* gather_dVscf_and_fft(const ELPH_cmplx* dVscf, + const struct Lattice* lattice, + MPI_Comm commK) +{ + ND_int nmodes = lattice->nmodes; + ND_int nmag = lattice->nmag; + ND_int Nx = lattice->fft_dims[0]; + ND_int Ny = lattice->fft_dims[1]; + ND_int Nz = lattice->fft_dims[2]; + ND_int Nz_loc = lattice->nfftz_loc; + ND_int shift = lattice->nfftz_loc_shift; + ND_int Nxy = Nx * Ny; + ND_int NmodMag = nmodes * nmag; + + int commK_rank, commK_size; + MPI_Comm_rank(commK, &commK_rank); + MPI_Comm_size(commK, &commK_size); + + /* Collect per-rank Nz_loc and shifts. */ + int* all_Nz_loc = malloc(commK_size * sizeof(int)); + int* all_shifts = malloc(commK_size * sizeof(int)); + CHECK_ALLOC(all_Nz_loc); + CHECK_ALLOC(all_shifts); + int my_Nz_loc = (int)Nz_loc; + int my_shift = (int)shift; + MPI_Allgather(&my_Nz_loc, 1, MPI_INT, all_Nz_loc, 1, MPI_INT, commK); + MPI_Allgather(&my_shift, 1, MPI_INT, all_shifts, 1, MPI_INT, commK); + + /* + * Pack local slab: rearrange from + * dVscf[nmodes][nmag][Nx][Ny][Nz_loc] (C row-major) + * to + * packed[Nz_loc][nmodes][nmag][Nx][Ny] + * so that the z-extent is the leading dimension for contiguous Gatherv. + */ + ND_int local_count = Nz_loc * NmodMag * Nxy; + ELPH_cmplx* packed = malloc(local_count * sizeof(ELPH_cmplx)); + CHECK_ALLOC(packed); + + for (ND_int iv = 0; iv < nmodes; ++iv) + for (ND_int is = 0; is < nmag; ++is) + for (ND_int ix = 0; ix < Nx; ++ix) + for (ND_int iy = 0; iy < Ny; ++iy) + for (ND_int iz = 0; iz < Nz_loc; ++iz) + { + packed[iz * NmodMag*Nxy + iv * nmag*Nxy + is * Nxy + ix * Ny + iy] = + dVscf[iv * nmag*Nxy*Nz_loc + is * Nxy*Nz_loc + + ix * Ny*Nz_loc + iy * Nz_loc + iz]; + } + + /* Build Gatherv send/recv counts and displacements (only on rank 0). */ + int* sendcounts = NULL; + int* displs = NULL; + ELPH_cmplx* gathered = NULL; + ND_int NmodMagNxy = NmodMag * Nxy; + + if (commK_rank == 0) + { + sendcounts = malloc(commK_size * sizeof(int)); + displs = malloc(commK_size * sizeof(int)); + CHECK_ALLOC(sendcounts); + CHECK_ALLOC(displs); + for (int r = 0; r < commK_size; ++r) + { + sendcounts[r] = all_Nz_loc[r] * (int)NmodMagNxy; + displs[r] = all_shifts[r] * (int)NmodMagNxy; + } + gathered = malloc((size_t)Nz * NmodMag * Nxy * sizeof(ELPH_cmplx)); + CHECK_ALLOC(gathered); + } + + MPI_Gatherv(packed, (int)local_count, ELPH_MPI_cmplx, + gathered, sendcounts, displs, ELPH_MPI_cmplx, + 0, commK); + + free(packed); + free(all_Nz_loc); + free(all_shifts); + if (commK_rank == 0) + { + free(sendcounts); + free(displs); + } + + if (commK_rank != 0) + return NULL; + + /* + * Transpose gathered[Nz][nmodes][nmag][Nx][Ny] back to + * dVG[nmodes][nmag][Nx][Ny][Nz]. + */ + ELPH_cmplx* dVG = malloc((size_t)NmodMag * Nxy * Nz * sizeof(ELPH_cmplx)); + CHECK_ALLOC(dVG); + + for (ND_int iz = 0; iz < Nz; ++iz) + for (ND_int iv = 0; iv < nmodes; ++iv) + for (ND_int is = 0; is < nmag; ++is) + for (ND_int ix = 0; ix < Nx; ++ix) + for (ND_int iy = 0; iy < Ny; ++iy) + { + dVG[iv * nmag*Nxy*Nz + is * Nxy*Nz + ix * Ny*Nz + iy * Nz + iz] = + gathered[iz * NmodMagNxy + iv * nmag*Nxy + is * Nxy + ix * Ny + iy]; + } + free(gathered); + + /* + * Forward 3D FFT for each (mode, spin) slice. + * fftw plan_dft_3d uses row-major [n0][n1][n2] = [Nx][Ny][Nz]. + */ + ND_int slice_sz = Nxy * Nz; + for (ND_int iv = 0; iv < nmodes; ++iv) + for (ND_int is = 0; is < nmag; ++is) + { + ELPH_cmplx* sl = dVG + (iv * nmag + is) * slice_sz; + fftw_generic_plan plan = fftw_fun(plan_dft_3d)( + (int)Nx, (int)Ny, (int)Nz, + sl, sl, + FFTW_FORWARD, FFTW_ESTIMATE); + fftw_fun(execute)(plan); + fftw_fun(destroy_plan)(plan); + } + + return dVG; +} diff --git a/services/dvG_utils.h b/services/dvG_utils.h new file mode 100644 index 00000000..fc4029e4 --- /dev/null +++ b/services/dvG_utils.h @@ -0,0 +1,31 @@ +#pragma once +/* + * License-Identifier: GPL + * + * Copyright (C) 2025 The Yambo Team + * + * Authors (see AUTHORS file for details): RR AM + * + * Helpers for gathering the distributed dVscf real-space potential and + * transforming it to reciprocal space so that the elph_dvG_fill_fn callback + * can be invoked from commK rank 0. + */ + +#include "common/dtypes.h" +#include "elph.h" +#include + +/* + * Gather z-slabs of dVscf from all commK ranks onto rank 0, perform a + * forward 3D FFT for each (mode, spin) slice, and return the result. + * + * dVscf layout (C row-major, distributed): + * (nmodes, nmag, fft_dims[0], fft_dims[1], nfftz_loc) + * + * Return value (only meaningful on commK rank 0; NULL on other ranks): + * malloc'd buffer of shape (nmodes, nmag, Nx, Ny, Nz) in G-space (complex). + * Caller must free(). + */ +ELPH_cmplx* gather_dVscf_and_fft(const ELPH_cmplx* dVscf, + const struct Lattice* lattice, + MPI_Comm commK); diff --git a/services/elph.h b/services/elph.h new file mode 100644 index 00000000..22caf6c7 --- /dev/null +++ b/services/elph.h @@ -0,0 +1,66 @@ +#pragma once +#include +#include + +#include "common/dtypes.h" +#include "elphC.h" + +/* + * Per-(iq_BZ, ik_BZ) fill callback for yambo COLL integration. + * Called once per BZ (q,k) pair on commK_rank==0 processes. + * iq_BZ, ik_BZ : 0-based BZ indices + * data : ELPH_cmplx buffer, C row-major (nmodes, nspin, nbnds, nbnds) + * nq..nb_start : full-BZ dimensions (constant across calls); nb_start is 1-based + */ +typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, + const void* data, + int nq, int nk, int nmodes, int nspin, + int nbnds, int nb_start); + +/* + * Callback for dV_q^nu(G) in reciprocal space, called once per iBZ q-point + * from commK rank 0. + * iq_iBZ : 0-based global iBZ q-point index + * dVG : C row-major (nmodes, nmag, nfft_x, nfft_y, nfft_z) after forward FFT + * nq_iBZ : total number of iBZ q-points + */ +typedef void (*elph_dvG_fill_fn)(int iq_iBZ, + const void* dVG, + int nq_iBZ, int nmodes, int nmag, + int nfft_x, int nfft_y, int nfft_z); + +void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world); + +/* Callback-enabled variant: skips ndb.elph; calls fill_fn per (q,k) instead. */ +void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn); + +/* + * Extended callback variant: like elph_driver_cb plus calls dvG_fill_fn once per + * iBZ q-point with the full dV_q^nu(G) potential in reciprocal space. + * Either callback may be NULL to skip that output. + */ +void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn, + elph_dvG_fill_fn dvG_fill_fn); + +void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, + struct Pseudo* pseudo, struct Phonon* phonon, + const ND_int iqpt, ELPH_cmplx* eigVec, + ELPH_cmplx* dVscfq, const int ncid_elph, + const int varid_elph, const int ncid_dmat, + const int varid_dmat, const bool non_loc, + const bool kminusq, + const struct ELPH_MPI_Comms* Comm, + elph_fill_fn fill_fn); + +void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, + const struct Lattice* lattice, + const ND_int nph_sym, + const struct symmetry* sym_data, + const struct ELPH_MPI_Comms* Comm); + +void init_kernel(struct kernel_info* kernel); + +void set_kernel(const char* kernel_str, struct kernel_info* kernel); diff --git a/services/elph/dvG_utils.c b/services/elph/dvG_utils.c new file mode 100644 index 00000000..1db548ce --- /dev/null +++ b/services/elph/dvG_utils.c @@ -0,0 +1,141 @@ +/* + * License-Identifier: GPL + * + * Copyright (C) 2025 The Yambo Team + * + * Authors (see AUTHORS file for details): RR AM + * + * Gather distributed dVscf z-slabs to commK rank 0 and apply a forward 3D + * FFT, producing dV_q^nu(G) ready for the elph_dvG_fill_fn callback. + */ + +#include "dvG_utils.h" +#include "fft/fft.h" +#include "common/error.h" +#include +#include + +ELPH_cmplx* gather_dVscf_and_fft(const ELPH_cmplx* dVscf, + const struct Lattice* lattice, + MPI_Comm commK) +{ + ND_int nmodes = lattice->nmodes; + ND_int nmag = lattice->nmag; + ND_int Nx = lattice->fft_dims[0]; + ND_int Ny = lattice->fft_dims[1]; + ND_int Nz = lattice->fft_dims[2]; + ND_int Nz_loc = lattice->nfftz_loc; + ND_int shift = lattice->nfftz_loc_shift; + ND_int Nxy = Nx * Ny; + ND_int NmodMag = nmodes * nmag; + + int commK_rank, commK_size; + MPI_Comm_rank(commK, &commK_rank); + MPI_Comm_size(commK, &commK_size); + + /* Collect per-rank Nz_loc and shifts. */ + int* all_Nz_loc = malloc(commK_size * sizeof(int)); + int* all_shifts = malloc(commK_size * sizeof(int)); + CHECK_ALLOC(all_Nz_loc); + CHECK_ALLOC(all_shifts); + int my_Nz_loc = (int)Nz_loc; + int my_shift = (int)shift; + MPI_Allgather(&my_Nz_loc, 1, MPI_INT, all_Nz_loc, 1, MPI_INT, commK); + MPI_Allgather(&my_shift, 1, MPI_INT, all_shifts, 1, MPI_INT, commK); + + /* + * Pack local slab: rearrange from + * dVscf[nmodes][nmag][Nx][Ny][Nz_loc] (C row-major) + * to + * packed[Nz_loc][nmodes][nmag][Nx][Ny] + * so that the z-extent is the leading dimension for contiguous Gatherv. + */ + ND_int local_count = Nz_loc * NmodMag * Nxy; + ELPH_cmplx* packed = malloc(local_count * sizeof(ELPH_cmplx)); + CHECK_ALLOC(packed); + + for (ND_int iv = 0; iv < nmodes; ++iv) + for (ND_int is = 0; is < nmag; ++is) + for (ND_int ix = 0; ix < Nx; ++ix) + for (ND_int iy = 0; iy < Ny; ++iy) + for (ND_int iz = 0; iz < Nz_loc; ++iz) + { + packed[iz * NmodMag*Nxy + iv * nmag*Nxy + is * Nxy + ix * Ny + iy] = + dVscf[iv * nmag*Nxy*Nz_loc + is * Nxy*Nz_loc + + ix * Ny*Nz_loc + iy * Nz_loc + iz]; + } + + /* Build Gatherv send/recv counts and displacements (only on rank 0). */ + int* sendcounts = NULL; + int* displs = NULL; + ELPH_cmplx* gathered = NULL; + ND_int NmodMagNxy = NmodMag * Nxy; + + if (commK_rank == 0) + { + sendcounts = malloc(commK_size * sizeof(int)); + displs = malloc(commK_size * sizeof(int)); + CHECK_ALLOC(sendcounts); + CHECK_ALLOC(displs); + for (int r = 0; r < commK_size; ++r) + { + sendcounts[r] = all_Nz_loc[r] * (int)NmodMagNxy; + displs[r] = all_shifts[r] * (int)NmodMagNxy; + } + gathered = malloc((size_t)Nz * NmodMag * Nxy * sizeof(ELPH_cmplx)); + CHECK_ALLOC(gathered); + } + + MPI_Gatherv(packed, (int)local_count, ELPH_MPI_cmplx, + gathered, sendcounts, displs, ELPH_MPI_cmplx, + 0, commK); + + free(packed); + free(all_Nz_loc); + free(all_shifts); + if (commK_rank == 0) + { + free(sendcounts); + free(displs); + } + + if (commK_rank != 0) + return NULL; + + /* + * Transpose gathered[Nz][nmodes][nmag][Nx][Ny] back to + * dVG[nmodes][nmag][Nx][Ny][Nz]. + */ + ELPH_cmplx* dVG = malloc((size_t)NmodMag * Nxy * Nz * sizeof(ELPH_cmplx)); + CHECK_ALLOC(dVG); + + for (ND_int iz = 0; iz < Nz; ++iz) + for (ND_int iv = 0; iv < nmodes; ++iv) + for (ND_int is = 0; is < nmag; ++is) + for (ND_int ix = 0; ix < Nx; ++ix) + for (ND_int iy = 0; iy < Ny; ++iy) + { + dVG[iv * nmag*Nxy*Nz + is * Nxy*Nz + ix * Ny*Nz + iy * Nz + iz] = + gathered[iz * NmodMagNxy + iv * nmag*Nxy + is * Nxy + ix * Ny + iy]; + } + free(gathered); + + /* + * Forward 3D FFT for each (mode, spin) slice. + * fftw plan_dft_3d uses row-major [n0][n1][n2] = [Nx][Ny][Nz]. + */ + ND_int slice_sz = Nxy * Nz; + for (ND_int iv = 0; iv < nmodes; ++iv) + for (ND_int is = 0; is < nmag; ++is) + { + ELPH_cmplx* sl = dVG + (iv * nmag + is) * slice_sz; + fftw_generic_plan plan = fftw_fun(plan_dft_3d)( + (int)Nx, (int)Ny, (int)Nz, + sl, sl, + FFTW_FORWARD, FFTW_ESTIMATE); + fftw_fun(execute)(plan); + fftw_fun(destroy_plan)(plan); + } + + return dVG; +} diff --git a/services/elph/dvG_utils.h b/services/elph/dvG_utils.h new file mode 100644 index 00000000..fc4029e4 --- /dev/null +++ b/services/elph/dvG_utils.h @@ -0,0 +1,31 @@ +#pragma once +/* + * License-Identifier: GPL + * + * Copyright (C) 2025 The Yambo Team + * + * Authors (see AUTHORS file for details): RR AM + * + * Helpers for gathering the distributed dVscf real-space potential and + * transforming it to reciprocal space so that the elph_dvG_fill_fn callback + * can be invoked from commK rank 0. + */ + +#include "common/dtypes.h" +#include "elph.h" +#include + +/* + * Gather z-slabs of dVscf from all commK ranks onto rank 0, perform a + * forward 3D FFT for each (mode, spin) slice, and return the result. + * + * dVscf layout (C row-major, distributed): + * (nmodes, nmag, fft_dims[0], fft_dims[1], nfftz_loc) + * + * Return value (only meaningful on commK rank 0; NULL on other ranks): + * malloc'd buffer of shape (nmodes, nmag, Nx, Ny, Nz) in G-space (complex). + * Caller must free(). + */ +ELPH_cmplx* gather_dVscf_and_fft(const ELPH_cmplx* dVscf, + const struct Lattice* lattice, + MPI_Comm commK); diff --git a/services/elph/elph.h b/services/elph/elph.h index 045d00e2..22caf6c7 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -17,6 +17,18 @@ typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, int nq, int nk, int nmodes, int nspin, int nbnds, int nb_start); +/* + * Callback for dV_q^nu(G) in reciprocal space, called once per iBZ q-point + * from commK rank 0. + * iq_iBZ : 0-based global iBZ q-point index + * dVG : C row-major (nmodes, nmag, nfft_x, nfft_y, nfft_z) after forward FFT + * nq_iBZ : total number of iBZ q-points + */ +typedef void (*elph_dvG_fill_fn)(int iq_iBZ, + const void* dVG, + int nq_iBZ, int nmodes, int nmag, + int nfft_x, int nfft_y, int nfft_z); + void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, MPI_Comm comm_world); @@ -24,6 +36,15 @@ void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, MPI_Comm comm_world, elph_fill_fn fill_fn); +/* + * Extended callback variant: like elph_driver_cb plus calls dvG_fill_fn once per + * iBZ q-point with the full dV_q^nu(G) potential in reciprocal space. + * Either callback may be NULL to skip that output. + */ +void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn, + elph_dvG_fill_fn dvG_fill_fn); + void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, struct Pseudo* pseudo, struct Phonon* phonon, const ND_int iqpt, ELPH_cmplx* eigVec, diff --git a/services/elph/elph_driver.c b/services/elph/elph_driver.c index 3a9993a3..44a41679 100644 --- a/services/elph/elph_driver.c +++ b/services/elph/elph_driver.c @@ -17,6 +17,7 @@ THe starting point for the entire code #include "common/parallel.h" #include "common/print_info.h" #include "dvloc/dvloc.h" +#include "dvG_utils.h" #include "elph.h" #include "elphC.h" #include "fft/fft.h" @@ -558,3 +559,204 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, cleanup_ELPH_clocks(); print_info_msg(World_rank_tmp, "********** Program ended **********"); } + +/* + * Extended callback variant: like elph_driver_cb plus dvG_fill_fn called + * once per iBZ q-point from commK rank 0 with dV_q^nu(G) in G-space. + * Either callback may be NULL to skip that output. + */ +void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn, + elph_dvG_fill_fn dvG_fill_fn) +{ + struct elph_usr_input* input_data; + init_ELPH_clocks(); + + read_elph_input_file(ELPH_input_file, &input_data, comm_world); + + struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); + init_kernel(kernel); + set_kernel(input_data->kernel_str, kernel); + + struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); + CHECK_ALLOC(mpi_comms); + + create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, + mpi_comms); + + print_ELPH_logo(mpi_comms->commW_rank, stdout); + print_info_msg(mpi_comms->commW_rank, + "********** Program started **********"); + print_input_info(input_data->save_dir, input_data->ph_save_dir, + input_data->kernel_str, input_data->kminusq, dft_code, + mpi_comms); + + struct Lattice* lattice = malloc(sizeof(struct Lattice)); + CHECK_ALLOC(lattice); + init_lattice_type(lattice); + + struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); + CHECK_ALLOC(pseudo); + init_Pseudo_type(pseudo); + + struct Phonon* phonon = malloc(sizeof(struct Phonon)); + CHECK_ALLOC(phonon); + init_phonon_type(phonon); + + struct WFC* wfcs; + + read_and_alloc_save_data(input_data->save_dir, mpi_comms, + input_data->start_bnd, input_data->end_bnd, &wfcs, + input_data->ph_save_dir, lattice, pseudo, phonon, + dft_code); + + print_lattice_info(mpi_comms, lattice); + print_phonon_info(mpi_comms, phonon); + + print_info_msg(mpi_comms->commW_rank, ""); + print_info_msg(mpi_comms->commW_rank, + "=== Computing Dmats for phonon symmetries ==="); + compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, + phonon->ph_syms, mpi_comms); + + ND_int nmodes = lattice->nmodes; + ND_int nfft_loc = + lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; + + ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); + CHECK_ALLOC(eigVec); + + ELPH_cmplx* dVscf = + malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); + CHECK_ALLOC(dVscf); + + ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); + CHECK_ALLOC(omega_ph); + + int ncid_dmat, nc_err; + int varid_dmat; + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, + MPI_INFO_NULL, &ncid_dmat))) + { + ERR(nc_err); + } + + if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) + { + ERR(nc_err); + } + + size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; + if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, + Dmat_counts, NULL))) + { + ERR(nc_err); + } + } + + print_info_msg(mpi_comms->commW_rank, + "=== Computing Electron-phonon matrix elements ==="); + print_info_msg(mpi_comms->commW_rank, ""); + + for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) + { + print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", + (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); + + ND_int iqpt_iBZg = iqpt + phonon->nq_shift; + + if (dft_code == DFT_CODE_QE) + { + ELPH_cmplx* dvscf_read = NULL; + if (kernel->screening == ELPH_DFPT_SCREENING) + { + dvscf_read = dVscf; + } + else + { + ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; + for (ND_int ix = 0; ix < dvscf_num; ++ix) + { + dVscf[ix] = 0.0; + } + } + get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, + eigVec, dvscf_read, omega_ph, mpi_comms); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + + ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); + CHECK_ALLOC(Vlocr); + dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, + mpi_comms->commK); + + if (dft_code == DFT_CODE_QE) + { + add_dvscf_qe(dVscf, Vlocr, lattice); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + free(Vlocr); + + /* dvG callback: gather dVscf z-slabs to rank 0, FFT, call handler. */ + if (dvG_fill_fn != NULL) + { + ELPH_cmplx* dVG = gather_dVscf_and_fft(dVscf, lattice, + mpi_comms->commK); + if (mpi_comms->commK_rank == 0) + { + dvG_fill_fn((int)iqpt_iBZg, (const void*)dVG, + (int)phonon->nq_iBZ, + (int)nmodes, (int)lattice->nmag, + (int)lattice->fft_dims[0], + (int)lattice->fft_dims[1], + (int)lattice->fft_dims[2]); + free(dVG); + } + } + + compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, + eigVec, dVscf, 0, 0, ncid_dmat, + varid_dmat, kernel->non_loc, + input_data->kminusq, mpi_comms, fill_fn); + } + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_close(ncid_dmat))) + { + ERR(nc_err); + } + } + + free(omega_ph); + free(eigVec); + free(dVscf); + + int World_rank_tmp = mpi_comms->commW_rank; + + free(kernel); + free_elph_usr_input(input_data); + free_save_data(wfcs, lattice, pseudo, phonon); + free(lattice); + free(pseudo); + free(phonon); + free_parallel_comms(mpi_comms); + free(mpi_comms); + fftw_fun(cleanup)(); + + if (0 == World_rank_tmp) + { + print_ELPH_clock_summary(); + } + cleanup_ELPH_clocks(); + print_info_msg(World_rank_tmp, "********** Program ended **********"); +} diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index c59217ab..7861fb90 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -30,3 +30,16 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, elph_driver_cb(input_file, (enum ELPH_dft_code)dft_code, c_comm, (elph_fill_fn)fill_fn_ptr); } + +/* + * Extended callback bridge: gkkp fill_fn + dvG fill callback. + * Either pointer may be NULL (pass c_null_funptr from Fortran) to skip that output. + */ +void elph_driver_cb2_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, + void* fill_fn_ptr, void* dvG_fill_fn_ptr) +{ + MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + elph_driver_cb2(input_file, (enum ELPH_dft_code)dft_code, c_comm, + (elph_fill_fn)fill_fn_ptr, + (elph_dvG_fill_fn)dvG_fill_fn_ptr); +} diff --git a/services/elph_driver.c b/services/elph_driver.c new file mode 100644 index 00000000..44a41679 --- /dev/null +++ b/services/elph_driver.c @@ -0,0 +1,762 @@ +/* +THe starting point for the entire code +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/ELPH_timers.h" +#include "common/dtypes.h" +#include "common/error.h" +#include "common/init_dtypes.h" +#include "common/parallel.h" +#include "common/print_info.h" +#include "dvloc/dvloc.h" +#include "dvG_utils.h" +#include "elph.h" +#include "elphC.h" +#include "fft/fft.h" +#include "io/io.h" +#include "io/qe/qe_io.h" +#include "parser/parser.h" +#include "symmetries/symmetries.h" + +void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world) +{ + struct elph_usr_input* input_data; + // start the clocks + init_ELPH_clocks(); + // + // read the input file + read_elph_input_file(ELPH_input_file, &input_data, comm_world); + // Note input parameters are broadcasted internally + // All the parameters in input_data must be available for all cpus in + // comm_world + + struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); + // initate the kernel with default + init_kernel(kernel); + // set the kernel + set_kernel(input_data->kernel_str, kernel); + + struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); + CHECK_ALLOC(mpi_comms); + + create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, + mpi_comms); + + // print logo and stated message + print_ELPH_logo(mpi_comms->commW_rank, stdout); + print_info_msg(mpi_comms->commW_rank, + "********** Program started **********"); + print_input_info(input_data->save_dir, input_data->ph_save_dir, + input_data->kernel_str, input_data->kminusq, dft_code, + mpi_comms); + + struct Lattice* lattice = malloc(sizeof(struct Lattice)); + CHECK_ALLOC(lattice); + init_lattice_type(lattice); + + struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); + CHECK_ALLOC(pseudo); + init_Pseudo_type(pseudo); + + struct Phonon* phonon = malloc(sizeof(struct Phonon)); + CHECK_ALLOC(phonon); + init_phonon_type(phonon); + + struct WFC* wfcs; + + // read the SAVE data and phonon related data. + read_and_alloc_save_data(input_data->save_dir, mpi_comms, + input_data->start_bnd, input_data->end_bnd, &wfcs, + input_data->ph_save_dir, lattice, pseudo, phonon, + dft_code); + + // print info about lattice and phonons + print_lattice_info(mpi_comms, lattice); + print_phonon_info(mpi_comms, phonon); + //======= Now start the real computation ========= + // a) COmpute the D_mats and store them in the netcdf file + // ============= Dmats ===================== + print_info_msg(mpi_comms->commW_rank, ""); + print_info_msg(mpi_comms->commW_rank, + "=== Computing Dmats for phonon symmetries ==="); + compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, + phonon->ph_syms, mpi_comms); + // b) Compute elph + // ============= ELPH iBZ computation ============= + ND_int nmodes = lattice->nmodes; + ND_int nfft_loc = + lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; + + ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); + //(nmodes,nmodes) // buffer to store eigen vectors + CHECK_ALLOC(eigVec); + + ELPH_cmplx* dVscf = + malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); + // (nmodes,nmag,Nx,Ny,Nz) // bufffer to store dVscf + CHECK_ALLOC(dVscf); + + ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); + // buffer for storing phonon freq + CHECK_ALLOC(omega_ph); + + int ncid_elph, ncid_dmat, nc_err; + int varid_eig, varid_elph, varid_omega, varid_dmat; + // Define netcdf variables + if (mpi_comms->commK_rank == 0) + { + // open Dmat file + if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, + MPI_INFO_NULL, &ncid_dmat))) + { + ERR(nc_err); + } + + // get dmat var id for dmats + if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) + { + ERR(nc_err); + } + + size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; + // Make a no-op call to nc_get_vara to avoid deadlocks in some + // suitiations. This happens when a procces doesnot make atleast + // single read call (for ex when qpool = qiBZ) + if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, + Dmat_counts, NULL))) + { + ERR(nc_err); + } + + // create elph file. Note: we overwrite any existing file + if ((nc_err = + nc_create_par("ndb.elph", NC_NETCDF4 | NC_CLOBBER, + mpi_comms->commR, MPI_INFO_NULL, &ncid_elph))) + { + fprintf(stderr, "Error creating ndb.elph file."); + ERR(nc_err); + } + + // set no fill mode (to avoid writting twice) + if ((nc_err = ncsetfill(ncid_elph, NC_NOFILL))) + { + fprintf(stderr, "Error setting nc_fill to ndb.elph file."); + ERR(nc_err); + } + + def_ncVar(ncid_elph, &varid_eig, 5, ELPH_NC4_IO_FLOAT, + (ND_int[]){phonon->nq_BZ, nmodes, nmodes / 3, 3, 2}, + "POLARIZATION_VECTORS", + (char*[]){"nq", "nmodes", "atom", "pol", "re_im"}, NULL); + + def_ncVar(ncid_elph, &varid_omega, 2, ELPH_NC4_IO_FLOAT, + (ND_int[]){phonon->nq_BZ, nmodes}, "FREQ", + (char*[]){"nq", "nmodes"}, NULL); + + ND_int nk_chunk_size = + NC4_DEFAULT_CHUCK_KB * 1024; // now this is in bytes + // scale with complex number size to get the number of elements + nk_chunk_size /= (sizeof(ELPH_cmplx) * nmodes * lattice->nspin * + lattice->nbnds * lattice->nbnds); + // chuck the varaible elph_mat with atmost default size + if (nk_chunk_size == 0) + { + nk_chunk_size = 1; + } + else if (nk_chunk_size > lattice->nkpts_BZ) + { + nk_chunk_size = lattice->nkpts_BZ; + } + + def_ncVar(ncid_elph, &varid_elph, 7, ELPH_NC4_IO_FLOAT, + (ND_int[]){phonon->nq_BZ, lattice->nkpts_BZ, nmodes, + lattice->nspin, lattice->nbnds, lattice->nbnds, 2}, + "elph_mat", + (char*[]){"nq", "nk", "nmodes", "nspin", "initial_band", + "final_band_PH_abs", "re_im"}, + (size_t[]){1, nk_chunk_size, nmodes, lattice->nspin, + lattice->nbnds, lattice->nbnds, 2}); + } + + ELPH_cmplx* eig_Sq = NULL; + + if (mpi_comms->commQ_rank == 0) + { + eig_Sq = calloc(nmodes * nmodes, sizeof(ELPH_cmplx)); + CHECK_ALLOC(eig_Sq); + } + + print_info_msg(mpi_comms->commW_rank, + "=== Computing Electron-phonon matrix elements ==="); + print_info_msg(mpi_comms->commW_rank, ""); + for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) + { + print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", + (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); + + ND_int iqpt_iBZg = iqpt + phonon->nq_shift; + // read dynamical matrix and dvscf for the iBZ qpt + if (dft_code == DFT_CODE_QE) + { + ELPH_cmplx* dvscf_read = NULL; + if (kernel->screening == ELPH_DFPT_SCREENING) + { + dvscf_read = dVscf; + } + else + { + // zero out the buffer. This is must ! + ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; + for (ND_int ix = 0; ix < dvscf_num; ++ix) + { + dVscf[ix] = 0.0; + } + } + // + get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, + eigVec, dvscf_read, omega_ph, mpi_comms); + // qe dvscf only contains dV_Ha + dV_xc, we need to add the local + // part of pseudo + } + else + { + error_msg("Currently only quantum espresso supported"); + } + // local part + ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); + // buffer to store local part of the pseudo potential + CHECK_ALLOC(Vlocr); + // + // compute the local part of the bare + dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, + mpi_comms->commK); + + if (dft_code == DFT_CODE_QE) + { + add_dvscf_qe(dVscf, Vlocr, + lattice); // add bare local to induce part + } + else + { + error_msg("Currently only quantum espresso supported"); + } + + free(Vlocr); + // free the local part buffer + ND_int qpos = 0; // positon of this iBZ qpoint in full q point list + for (ND_int i = 0; i < iqpt_iBZg; ++i) + { + qpos += phonon->nqstar[i]; + } + // write eigen vectors and frequencies + if (mpi_comms->commQ_rank == 0) + { + size_t startp[5] = {qpos, 0, 0, 0, 0}; + size_t countp[5] = {1, nmodes, nmodes / 3, 3, 2}; + if ((nc_err = + nc_put_vara(ncid_elph, varid_eig, startp, countp, eigVec))) + { + ERR(nc_err); + } + + if ((nc_err = nc_put_vara(ncid_elph, varid_omega, startp, countp, + omega_ph))) + { + ERR(nc_err); + } + // write down the rotate eigen vectors; + for (ND_int istar = 1; istar < phonon->nqstar[iqpt_iBZg]; ++istar) + { + ND_int qpos_star = qpos + istar; + + struct symmetry* sym_rot = + phonon->ph_syms + phonon->qmap[2 * qpos_star + 1]; + + rotate_eig_vecs(sym_rot, lattice, + phonon->qpts_iBZ + iqpt_iBZg * 3, eigVec, + eig_Sq); + // + startp[0] = qpos_star; + if ((nc_err = nc_put_vara(ncid_elph, varid_eig, startp, countp, + eig_Sq))) + { + ERR(nc_err); + } + + if ((nc_err = nc_put_vara(ncid_elph, varid_omega, startp, + countp, omega_ph))) + { + ERR(nc_err); + } + // + } + } + // Now compute and write the electron-phonon matrix elements + compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, + eigVec, dVscf, ncid_elph, varid_elph, ncid_dmat, + varid_dmat, kernel->non_loc, + input_data->kminusq, mpi_comms, NULL); + } + + free(eig_Sq); + + if (mpi_comms->commK_rank == 0) + { + // close files + if ((nc_err = nc_close(ncid_elph))) + { + ERR(nc_err); + } + + if ((nc_err = nc_close(ncid_dmat))) + { + ERR(nc_err); + } + } + + // finally write some basic info to ndb.elph file (only master node writes + // it) + + if (mpi_comms->commW_rank == 0) + { + if ((nc_err = nc_open("ndb.elph", NC_WRITE, &ncid_elph))) + { + ERR(nc_err); + } + + char convention_str[32]; + strcpy(convention_str, "standard"); + if (input_data->kminusq) + { + strcpy(convention_str, "yambo"); + } + write_basic_data(ncid_elph, lattice, phonon, input_data->kernel_str, + convention_str); + + if ((nc_err = nc_close(ncid_elph))) + { + ERR(nc_err); + } + } + + int World_rank_tmp = mpi_comms->commW_rank; + // ELPH_cmplx Ry2Ha = pow(2,-1.5); + free(omega_ph); + free(eigVec); + free(dVscf); + + // cleanup + free(kernel); + free_elph_usr_input(input_data); + free_save_data(wfcs, lattice, pseudo, phonon); + free(lattice); + free(pseudo); + free(phonon); + free_parallel_comms(mpi_comms); + free(mpi_comms); + fftw_fun(cleanup)(); + + // print the clocks + if (0 == World_rank_tmp) + { + print_ELPH_clock_summary(); + } + // cleanup the clocks + cleanup_ELPH_clocks(); + // done with the calculation + print_info_msg(World_rank_tmp, "********** Program ended **********"); +} + +/* + * Callback-enabled driver: identical flow to elph_driver but writes gkkp + * data via fill_fn(iq_BZ, ik_BZ, data, ...) instead of ndb.elph. + * ndb.Dmats is still created and used internally for BZ symmetry expansion. + * Eigenvectors / frequencies are NOT written (yambo reads them elsewhere). + */ +void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn) +{ + struct elph_usr_input* input_data; + init_ELPH_clocks(); + + read_elph_input_file(ELPH_input_file, &input_data, comm_world); + + struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); + init_kernel(kernel); + set_kernel(input_data->kernel_str, kernel); + + struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); + CHECK_ALLOC(mpi_comms); + + create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, + mpi_comms); + + print_ELPH_logo(mpi_comms->commW_rank, stdout); + print_info_msg(mpi_comms->commW_rank, + "********** Program started **********"); + print_input_info(input_data->save_dir, input_data->ph_save_dir, + input_data->kernel_str, input_data->kminusq, dft_code, + mpi_comms); + + struct Lattice* lattice = malloc(sizeof(struct Lattice)); + CHECK_ALLOC(lattice); + init_lattice_type(lattice); + + struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); + CHECK_ALLOC(pseudo); + init_Pseudo_type(pseudo); + + struct Phonon* phonon = malloc(sizeof(struct Phonon)); + CHECK_ALLOC(phonon); + init_phonon_type(phonon); + + struct WFC* wfcs; + + read_and_alloc_save_data(input_data->save_dir, mpi_comms, + input_data->start_bnd, input_data->end_bnd, &wfcs, + input_data->ph_save_dir, lattice, pseudo, phonon, + dft_code); + + print_lattice_info(mpi_comms, lattice); + print_phonon_info(mpi_comms, phonon); + + print_info_msg(mpi_comms->commW_rank, ""); + print_info_msg(mpi_comms->commW_rank, + "=== Computing Dmats for phonon symmetries ==="); + compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, + phonon->ph_syms, mpi_comms); + + ND_int nmodes = lattice->nmodes; + ND_int nfft_loc = + lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; + + ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); + CHECK_ALLOC(eigVec); + + ELPH_cmplx* dVscf = + malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); + CHECK_ALLOC(dVscf); + + ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); + CHECK_ALLOC(omega_ph); + + int ncid_dmat, nc_err; + int varid_dmat; + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, + MPI_INFO_NULL, &ncid_dmat))) + { + ERR(nc_err); + } + + if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) + { + ERR(nc_err); + } + + size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; + if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, + Dmat_counts, NULL))) + { + ERR(nc_err); + } + } + + print_info_msg(mpi_comms->commW_rank, + "=== Computing Electron-phonon matrix elements ==="); + print_info_msg(mpi_comms->commW_rank, ""); + + for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) + { + print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", + (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); + + ND_int iqpt_iBZg = iqpt + phonon->nq_shift; + + if (dft_code == DFT_CODE_QE) + { + ELPH_cmplx* dvscf_read = NULL; + if (kernel->screening == ELPH_DFPT_SCREENING) + { + dvscf_read = dVscf; + } + else + { + ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; + for (ND_int ix = 0; ix < dvscf_num; ++ix) + { + dVscf[ix] = 0.0; + } + } + get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, + eigVec, dvscf_read, omega_ph, mpi_comms); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + + ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); + CHECK_ALLOC(Vlocr); + dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, + mpi_comms->commK); + + if (dft_code == DFT_CODE_QE) + { + add_dvscf_qe(dVscf, Vlocr, lattice); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + free(Vlocr); + + compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, + eigVec, dVscf, 0, 0, ncid_dmat, + varid_dmat, kernel->non_loc, + input_data->kminusq, mpi_comms, fill_fn); + } + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_close(ncid_dmat))) + { + ERR(nc_err); + } + } + + free(omega_ph); + free(eigVec); + free(dVscf); + + int World_rank_tmp = mpi_comms->commW_rank; + + free(kernel); + free_elph_usr_input(input_data); + free_save_data(wfcs, lattice, pseudo, phonon); + free(lattice); + free(pseudo); + free(phonon); + free_parallel_comms(mpi_comms); + free(mpi_comms); + fftw_fun(cleanup)(); + + if (0 == World_rank_tmp) + { + print_ELPH_clock_summary(); + } + cleanup_ELPH_clocks(); + print_info_msg(World_rank_tmp, "********** Program ended **********"); +} + +/* + * Extended callback variant: like elph_driver_cb plus dvG_fill_fn called + * once per iBZ q-point from commK rank 0 with dV_q^nu(G) in G-space. + * Either callback may be NULL to skip that output. + */ +void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn, + elph_dvG_fill_fn dvG_fill_fn) +{ + struct elph_usr_input* input_data; + init_ELPH_clocks(); + + read_elph_input_file(ELPH_input_file, &input_data, comm_world); + + struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); + init_kernel(kernel); + set_kernel(input_data->kernel_str, kernel); + + struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); + CHECK_ALLOC(mpi_comms); + + create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, + mpi_comms); + + print_ELPH_logo(mpi_comms->commW_rank, stdout); + print_info_msg(mpi_comms->commW_rank, + "********** Program started **********"); + print_input_info(input_data->save_dir, input_data->ph_save_dir, + input_data->kernel_str, input_data->kminusq, dft_code, + mpi_comms); + + struct Lattice* lattice = malloc(sizeof(struct Lattice)); + CHECK_ALLOC(lattice); + init_lattice_type(lattice); + + struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); + CHECK_ALLOC(pseudo); + init_Pseudo_type(pseudo); + + struct Phonon* phonon = malloc(sizeof(struct Phonon)); + CHECK_ALLOC(phonon); + init_phonon_type(phonon); + + struct WFC* wfcs; + + read_and_alloc_save_data(input_data->save_dir, mpi_comms, + input_data->start_bnd, input_data->end_bnd, &wfcs, + input_data->ph_save_dir, lattice, pseudo, phonon, + dft_code); + + print_lattice_info(mpi_comms, lattice); + print_phonon_info(mpi_comms, phonon); + + print_info_msg(mpi_comms->commW_rank, ""); + print_info_msg(mpi_comms->commW_rank, + "=== Computing Dmats for phonon symmetries ==="); + compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, + phonon->ph_syms, mpi_comms); + + ND_int nmodes = lattice->nmodes; + ND_int nfft_loc = + lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; + + ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); + CHECK_ALLOC(eigVec); + + ELPH_cmplx* dVscf = + malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); + CHECK_ALLOC(dVscf); + + ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); + CHECK_ALLOC(omega_ph); + + int ncid_dmat, nc_err; + int varid_dmat; + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, + MPI_INFO_NULL, &ncid_dmat))) + { + ERR(nc_err); + } + + if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) + { + ERR(nc_err); + } + + size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; + if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, + Dmat_counts, NULL))) + { + ERR(nc_err); + } + } + + print_info_msg(mpi_comms->commW_rank, + "=== Computing Electron-phonon matrix elements ==="); + print_info_msg(mpi_comms->commW_rank, ""); + + for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) + { + print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", + (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); + + ND_int iqpt_iBZg = iqpt + phonon->nq_shift; + + if (dft_code == DFT_CODE_QE) + { + ELPH_cmplx* dvscf_read = NULL; + if (kernel->screening == ELPH_DFPT_SCREENING) + { + dvscf_read = dVscf; + } + else + { + ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; + for (ND_int ix = 0; ix < dvscf_num; ++ix) + { + dVscf[ix] = 0.0; + } + } + get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, + eigVec, dvscf_read, omega_ph, mpi_comms); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + + ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); + CHECK_ALLOC(Vlocr); + dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, + mpi_comms->commK); + + if (dft_code == DFT_CODE_QE) + { + add_dvscf_qe(dVscf, Vlocr, lattice); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + free(Vlocr); + + /* dvG callback: gather dVscf z-slabs to rank 0, FFT, call handler. */ + if (dvG_fill_fn != NULL) + { + ELPH_cmplx* dVG = gather_dVscf_and_fft(dVscf, lattice, + mpi_comms->commK); + if (mpi_comms->commK_rank == 0) + { + dvG_fill_fn((int)iqpt_iBZg, (const void*)dVG, + (int)phonon->nq_iBZ, + (int)nmodes, (int)lattice->nmag, + (int)lattice->fft_dims[0], + (int)lattice->fft_dims[1], + (int)lattice->fft_dims[2]); + free(dVG); + } + } + + compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, + eigVec, dVscf, 0, 0, ncid_dmat, + varid_dmat, kernel->non_loc, + input_data->kminusq, mpi_comms, fill_fn); + } + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_close(ncid_dmat))) + { + ERR(nc_err); + } + } + + free(omega_ph); + free(eigVec); + free(dVscf); + + int World_rank_tmp = mpi_comms->commW_rank; + + free(kernel); + free_elph_usr_input(input_data); + free_save_data(wfcs, lattice, pseudo, phonon); + free(lattice); + free(pseudo); + free(phonon); + free_parallel_comms(mpi_comms); + free(mpi_comms); + fftw_fun(cleanup)(); + + if (0 == World_rank_tmp) + { + print_ELPH_clock_summary(); + } + cleanup_ELPH_clocks(); + print_info_msg(World_rank_tmp, "********** Program ended **********"); +} diff --git a/services/ep_f2c_bridge.c b/services/ep_f2c_bridge.c new file mode 100644 index 00000000..7861fb90 --- /dev/null +++ b/services/ep_f2c_bridge.c @@ -0,0 +1,45 @@ +/* + * License-Identifier: GPL + * + * Copyright (C) 2025 The Yambo Team + * + * Authors (see AUTHORS file for details): RR AM + * + * Thin bridge: called from Fortran via ISO_C_BINDING. + * Converts a Fortran MPI communicator handle (MPI_Fint) to a C MPI_Comm + * and forwards the call to LetzElPhC's elph_driver(). + */ + +#include "elph.h" /* already pulls in common/dtypes.h and elphC.h */ +#include + +void elph_driver_f2c(const char* input_file, int dft_code, MPI_Fint f_comm) +{ + MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + elph_driver(input_file, (enum ELPH_dft_code)dft_code, c_comm); +} + +/* + * Callback-enabled bridge: fill_fn_ptr is a Fortran procedure pointer + * (passed as a C function pointer via ISO_C_BINDING's c_funloc). + */ +void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, + void* fill_fn_ptr) +{ + MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + elph_driver_cb(input_file, (enum ELPH_dft_code)dft_code, c_comm, + (elph_fill_fn)fill_fn_ptr); +} + +/* + * Extended callback bridge: gkkp fill_fn + dvG fill callback. + * Either pointer may be NULL (pass c_null_funptr from Fortran) to skip that output. + */ +void elph_driver_cb2_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, + void* fill_fn_ptr, void* dvG_fill_fn_ptr) +{ + MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + elph_driver_cb2(input_file, (enum ELPH_dft_code)dft_code, c_comm, + (elph_fill_fn)fill_fn_ptr, + (elph_dvG_fill_fn)dvG_fill_fn_ptr); +} diff --git a/services/set_kernel.c b/services/set_kernel.c new file mode 100644 index 00000000..1970d14c --- /dev/null +++ b/services/set_kernel.c @@ -0,0 +1,52 @@ +#include +#include +#include + +#include "common/dtypes.h" +#include "common/error.h" +#include "common/string_func.h" +#include "elph.h" + +void init_kernel(struct kernel_info* kernel) +{ + strcpy(kernel->name_str, "dfpt"); + kernel->bare_loc = true; + kernel->non_loc = true; + kernel->screening = ELPH_DFPT_SCREENING; +} + +void set_kernel(const char* kernel_str, struct kernel_info* kernel) +{ + size_t name_str_size = sizeof(kernel->name_str) - 1; + kernel->name_str[name_str_size] = '\0'; + strlcpy_custom(kernel->name_str, kernel_str, name_str_size); + + if (!strcmp(kernel_str, "dfpt")) + { + kernel->bare_loc = true; + kernel->non_loc = true; + kernel->screening = ELPH_DFPT_SCREENING; + } + else if (!strcmp(kernel_str, "dfpt_local")) + { + kernel->bare_loc = true; + kernel->non_loc = false; + kernel->screening = ELPH_DFPT_SCREENING; + } + else if (!strcmp(kernel_str, "bare")) + { + kernel->bare_loc = true; + kernel->non_loc = true; + kernel->screening = ELPH_NO_SCREENING; + } + else if (!strcmp(kernel_str, "bare_local")) + { + kernel->bare_loc = true; + kernel->non_loc = false; + kernel->screening = ELPH_NO_SCREENING; + } + else + { + error_msg("invalid value for kernel in the input file"); + } +} From 1be853aada22b803190d79a15c91cc43a09453fe Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Sun, 17 May 2026 19:05:30 +0200 Subject: [PATCH 08/46] update --- services/Makefile | 94 ++++++++++++++++++++---------------------- services/elph/.objects | 2 +- 2 files changed, 46 insertions(+), 50 deletions(-) diff --git a/services/Makefile b/services/Makefile index 2e7a13bd..53edd6b4 100644 --- a/services/Makefile +++ b/services/Makefile @@ -1,49 +1,45 @@ -# -# License-Identifier: GPL -# -# Copyright (C) 2016 The Yambo Team -# -# Authors (see AUTHORS file for details): HM -# -# VARIABLES (static and dynamical) -# -include dyn_variables.mk -include $(compdir)/compile/local/static_variables.mk -include $(compdir)/compile/local/defs.mk -include $(compdir)/compile/defs.mk -# -# SETUP -# -include $(compdir)/config/setup -# -# Module dependencies -# --include local_modules.dep -# -# Include directories (headers) -# -include $(compdir)/compile/headers.mk -# -# Libraries -# -include $(compdir)/compile/libraries.mk -ifneq "$(wildcard $(compdir)/plugins/plugins.pulled)" "" - include $(compdir)/plugins/*/compile/headers_and_libs.mk -endif -# -# OBJECTS -# -include objects.mk -# -# OPERATIONS -# -include $(compdir)/compile/local/operations.mk -# -# RULES -# -include $(compdir)/compile/local/rules.mk -# -# FUNCTIONS -# -include $(compdir)/compile/local/functions.mk -# +include make.inc + +TARGET := lelphc + +#### make start here + +SUBDIR = nonloc io/ezxml parser/inih io \ + io/qe common dvloc elph wfc \ + symmetries fft common/cwalk \ + preprocessor interpolation \ + common/ELPH_hash_map phonon \ + common/kdtree parser + +.SUFFIXES : + +INCS = $(wildcard *.h $(foreach fd, $(SUBDIR), $(fd)/*.h)) +SRCS = $(wildcard *.c $(foreach fd, $(SUBDIR), $(fd)/*.c)) +OBJS = $(addprefix ./, $(SRCS:c=o)) + +INC_DIRS += -I. $(FFTW_INC) $(NETCDF_INC) +LIBS += $(FFTW3_LIB) $(BLAS_LIB) $(NETCDF_LIB) $(HDF5_LIB) -lm + + +PHONY := $(TARGET) +$(TARGET): $(OBJS) + $(CC) -o ./$@ $(OBJS) $(LIBS) $(LD_FLAGS) + +%.o: %.c $(INCS) make.inc + $(CC) $(CFLAGS) -c $< $(INC_DIRS) $(OPENMP_FLAGS) -o $@ + + +PHONY += clean +clean: + rm ./$(TARGET) $(OBJS) + +PHONY += echoes +echoes: + @echo "INC files: $(INCS)" + @echo "SRC files: $(SRCS)" + @echo "OBJ files: $(OBJS)" + @echo "LIB files: $(LIBS)" + @echo "INC DIR: $(INC_DIRS)" + + +.PHONY = $(PHONY) diff --git a/services/elph/.objects b/services/elph/.objects index 81fa9f60..5d4205ff 100644 --- a/services/elph/.objects +++ b/services/elph/.objects @@ -1 +1 @@ -objs = set_kernel.o elph_driver.o compute_elph_matq.o compute_dmats.o ep_f2c_bridge.o +objs = set_kernel.o elph_driver.o compute_elph_matq.o compute_dmats.o ep_f2c_bridge.o dvG_utils.o From cbe07098b63317e2adeaee046e107883297e78f7 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Wed, 20 May 2026 17:41:26 +0200 Subject: [PATCH 09/46] rm duplicated files --- services/compute_dmats.c | 131 ------ services/compute_elph_matq.c | 249 ------------ services/dvG_utils.c | 141 ------- services/dvG_utils.h | 31 -- services/elph.h | 66 --- services/elph_driver.c | 762 ----------------------------------- services/ep_f2c_bridge.c | 45 --- services/set_kernel.c | 52 --- 8 files changed, 1477 deletions(-) delete mode 100644 services/compute_dmats.c delete mode 100644 services/compute_elph_matq.c delete mode 100644 services/dvG_utils.c delete mode 100644 services/dvG_utils.h delete mode 100644 services/elph.h delete mode 100644 services/elph_driver.c delete mode 100644 services/ep_f2c_bridge.c delete mode 100644 services/set_kernel.c diff --git a/services/compute_dmats.c b/services/compute_dmats.c deleted file mode 100644 index 2880e8ee..00000000 --- a/services/compute_dmats.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include -#include - -#include "common/dtypes.h" -#include "common/error.h" -#include "common/parallel.h" -#include "common/progess_bar.h" -#include "elph.h" -#include "elphC.h" -#include "io/io.h" -#include "symmetries/symmetries.h" - -/* - * This function contain the wrapper functions to compute and - * write or read dmat functions to file) - */ - -void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, - const struct Lattice* lattice, - const ND_int nph_sym, - const struct symmetry* sym_data, - const struct ELPH_MPI_Comms* Comm) -{ - ND_int nk_totalBZ = lattice->nkpts_BZ; - ELPH_cmplx* Dkmn_rep_ptr = NULL; - - int ncid, varid, nc_err; - - size_t startp[6] = {0, 0, 0, 0, 0, 0}; - size_t countp[6] = {1, 1, lattice->nspin, lattice->nbnds, lattice->nbnds, - 2}; - - ND_int nk_chunk_size = NC4_DEFAULT_CHUCK_KB * 1024; // now this is in bytes - // scale with complex number size to get the number of elements - nk_chunk_size /= - (sizeof(ELPH_cmplx) * lattice->nspin * lattice->nbnds * lattice->nbnds); - // chuck the varaible elph_mat with atmost default size - if (nk_chunk_size == 0) - { - nk_chunk_size = 1; - } - else if (nk_chunk_size > nk_totalBZ) - { - nk_chunk_size = nk_totalBZ; - } - - if (Comm->commK_rank == 0) - { - // we overwrite any existing file - if ((nc_err = nc_create_par(file_name, NC_NETCDF4 | NC_CLOBBER, - Comm->commR, MPI_INFO_NULL, &ncid))) - { - fprintf(stderr, "Error creating Dmat file"); - ERR(nc_err); - } - // set no fill mode (to avoid writting twice) - if ((nc_err = ncsetfill(ncid, NC_NOFILL))) - { - fprintf(stderr, "Error setting nc_fill to dmat file."); - ERR(nc_err); - } - - def_ncVar(ncid, &varid, 6, ELPH_NC4_IO_FLOAT, - (ND_int[]){nph_sym, nk_totalBZ, lattice->nspin, - lattice->nbnds, lattice->nbnds, 2}, - "Dmats", - (char*[]){"nsym_ph", "nkpts", "nspin", "Rk_band", "k_band", - "re_im"}, - (size_t[]){1, nk_chunk_size, lattice->nspin, lattice->nbnds, - lattice->nbnds, 2}); - - // Make the access INDEPENDENT as not all can call the put_var function - // simultaneously - if ((nc_err = nc_var_par_access(ncid, varid, NC_INDEPENDENT))) - { - ERR(nc_err); - } - - Dkmn_rep_ptr = calloc(lattice->nspin * lattice->nbnds * lattice->nbnds, - sizeof(ELPH_cmplx)); - CHECK_ALLOC(Dkmn_rep_ptr); - } - - // for computation of Dmats, we use all the nodes - // ("nsym", "nk", "nspin", "nbndb", "nbnda") - ND_int dmat_shift; - ND_int ndmats = - distribute_to_grps(nph_sym * nk_totalBZ, Comm->nqpools * Comm->nkpools, - Comm->commW_rank / Comm->commK_size, &dmat_shift); - - // start the progress bar for dmats - struct progress_bar pbar[1]; - start_progressbar(pbar, Comm->commW_rank, ndmats); - - for (ND_int idmat = 0; idmat < ndmats; ++idmat) - { - ND_int isym = (idmat + dmat_shift) / nk_totalBZ; - ND_int ikBZ = (idmat + dmat_shift) % nk_totalBZ; - - startp[0] = isym; - startp[1] = ikBZ; - - // compute the dmats - electronic_reps(wfcs, lattice, sym_data[isym].Rmat, sym_data[isym].tau, - sym_data[isym].time_rev, ikBZ, Dkmn_rep_ptr, Comm); - - if (Comm->commK_rank == 0) - { - // write data to file - if ((nc_err = - nc_put_vara(ncid, varid, startp, countp, Dkmn_rep_ptr))) - { - ERR(nc_err); - } - } - - // update the progress bar - print_progressbar(pbar); - } - if (Comm->commK_rank == 0) - { - free(Dkmn_rep_ptr); - - if ((nc_err = nc_close(ncid))) - { - ERR(nc_err); - } - } -} diff --git a/services/compute_elph_matq.c b/services/compute_elph_matq.c deleted file mode 100644 index a9af8bf1..00000000 --- a/services/compute_elph_matq.c +++ /dev/null @@ -1,249 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "common/dtypes.h" -#include "common/error.h" -#include "common/numerical_func.h" -#include "common/parallel.h" -#include "common/progess_bar.h" -#include "dvloc/dvloc.h" -#include "elph.h" -#include "elphC.h" -#include "nonloc/Vnonloc.h" -#include "symmetries/symmetries.h" - -void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, - struct Pseudo* pseudo, struct Phonon* phonon, - const ND_int iqpt, ELPH_cmplx* eigVec, - ELPH_cmplx* dVscfq, const int ncid_elph, - const int varid_elph, const int ncid_dmat, - const int varid_dmat, const bool non_loc, - const bool kminusq, - const struct ELPH_MPI_Comms* Comm, - elph_fill_fn fill_fn) -{ - /* - dVscf -> (nmodes,nmag,Nx,Ny,Nz) - ((k, nmodes, nspin, nbands, nbands)) - */ - /* distribute k points */ - int mpi_error; - const ND_int nk_totalBZ = lattice->nkpts_BZ; - - const ELPH_float* qpt = phonon->qpts_iBZ + iqpt * 3; - - ND_int qpos = 0; // positon of this iBZ qpoint in full q point list - for (ND_int i = 0; i < iqpt; ++i) - { - qpos += phonon->nqstar[i]; - } - - // sanity check - if (phonon->qmap[2 * qpos] != iqpt || phonon->qmap[2 * qpos + 1] != 0) - { - error_msg("Qpoint in iBZ cannot be traced in phonon qmap"); - } - - ND_int kshift; - ND_int nk_this_pool = - distribute_to_grps(nk_totalBZ, Comm->nkpools, - Comm->commQ_rank / Comm->commK_size, &kshift); - - if (nk_this_pool < 1) - { - error_msg( - "There are no kpoints in some cpus, Make sure nkpool < # of " - "kpoints in full BZ."); - } - /* get the k point indices and symmetries */ - int* kmap = lattice->kmap; - int* KplusQidxs = malloc(nk_totalBZ * sizeof(int)); - CHECK_ALLOC(KplusQidxs); - - ELPH_float qpt_tmp[3]; - memcpy(qpt_tmp, qpt, sizeof(ELPH_float) * 3); - // incase if we want yambo convention - if (kminusq) - { - for (int xi = 0; xi < 3; ++xi) - { - qpt_tmp[xi] = -qpt_tmp[xi]; - } - } - get_KplusQ_idxs(nk_totalBZ, lattice->kpt_fullBZ_crys, qpt_tmp, KplusQidxs); - - ND_int nbnds = lattice->nbnds; - ND_int nmodes = lattice->nmodes; - - ELPH_cmplx* elph_kq_mn = NULL; - if (Comm->commK_rank == 0) - { - elph_kq_mn = - calloc(nbnds * nbnds * lattice->nspin * nmodes, sizeof(ELPH_cmplx)); - CHECK_ALLOC(elph_kq_mn); - } - //// (nu, nspin, mk, nk+q) - /* Now Compute elph-matrix elements for each kpoint */ - - size_t startp[7] = {0, 0, 0, 0, 0, 0, 0}; - size_t countp[7] = {1, 1, nmodes, lattice->nspin, nbnds, nbnds, 2}; - - ELPH_cmplx* gSq_buff = NULL; - ELPH_cmplx* D_mat_l = NULL; - ELPH_cmplx* D_mat_r = NULL; - - if (Comm->commK_rank == 0) - { - gSq_buff = - calloc(nbnds * nbnds * lattice->nspin * nmodes, sizeof(ELPH_cmplx)); - CHECK_ALLOC(gSq_buff); - - D_mat_l = calloc(nbnds * nbnds * lattice->nspin, sizeof(ELPH_cmplx)); - CHECK_ALLOC(D_mat_l); - - D_mat_r = calloc(nbnds * nbnds * lattice->nspin, sizeof(ELPH_cmplx)); - CHECK_ALLOC(D_mat_r); - } - - // start the progress bar - struct progress_bar pbar[1]; - start_progressbar(pbar, Comm->commW_rank, nk_this_pool); - // compute electron-phonon matrix elements for each kpoint - for (ND_int ii = 0; ii < nk_this_pool; ++ii) - { - /* compute the global k index */ - ND_int i = kshift + ii; - - int idx_k = i; - int idx_kq = KplusQidxs[i]; - - if (kminusq) - { - swap_ints(&idx_k, &idx_kq); - } - - int ik = kmap[2 * idx_k]; - int ksym = kmap[2 * idx_k + 1]; - - int ikq = kmap[2 * idx_kq]; - int kqsym = kmap[2 * idx_kq + 1]; - - elphLocal(qpt, wfcs, lattice, ikq, ik, kqsym, ksym, dVscfq, Comm, - elph_kq_mn); - /* add the non local part elements */ - // WARNING : non local must be added after elphLocal else U.B - if (non_loc) - { - add_elphNonLocal(wfcs, lattice, pseudo, ikq, ik, kqsym, ksym, - eigVec, elph_kq_mn, Comm); - } - startp[0] = qpos; - startp[1] = i; - int nc_err; - if (Comm->commK_rank == 0) - { - if (fill_fn != NULL) - { - fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, - (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, - (int)lattice->nspin, (int)nbnds, - (int)lattice->start_band); - } - else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, - countp, elph_kq_mn))) - { - ERR(nc_err); - } - } - - // expand the el-ph matrix elements in full BZ - const ELPH_float* kpt_BZ = lattice->kpt_fullBZ + 3 * i; - - // only master node does this - if (Comm->commK_rank == 0) - { - for (ND_int istar = 1; istar < phonon->nqstar[iqpt]; ++istar) - { - ND_int qpos_star = qpos + istar; - // get the symmetry - int istar_symm = phonon->qmap[2 * qpos_star + 1]; - - size_t D_mat_sp[6] = {istar_symm, idx_kq, 0, 0, 0, 0}; - size_t D_mat_cp[6] = { - 1, 1, lattice->nspin, lattice->nbnds, lattice->nbnds, 2}; - // read D_mats //const int ncid_dmat, const int varid_dmat, - if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, D_mat_sp, - D_mat_cp, D_mat_l))) - { // k + q - ERR(nc_err); - } - - D_mat_sp[1] = idx_k; - if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, D_mat_sp, - D_mat_cp, D_mat_r))) - { // k - ERR(nc_err); - } - - // gSq_buff - elph_q_rotate(D_mat_l, elph_kq_mn, D_mat_r, lattice, - phonon->ph_syms[istar_symm].time_rev, gSq_buff); - - ELPH_float Sk_crys[3]; - ELPH_float Sk_cart[3]; - - MatVec3f(phonon->ph_syms[istar_symm].Rmat, kpt_BZ, false, - Sk_cart); - // convert to crsytal units - MatVec3f(lattice->alat_vec, Sk_cart, true, Sk_crys); - - // now get the indices of S*k - - ND_int idx_Sk = find_kidx_in_list( - lattice->nkpts_BZ, lattice->kpt_fullBZ_crys, Sk_crys); - - if (idx_Sk < 0) - { - error_msg( - "Unable to to find S*k index " - "This is due to incommenserate k and q grids."); - } - - startp[0] = qpos_star; - startp[1] = idx_Sk; - // Write it for Sq and Sk point - if (fill_fn != NULL) - { - fill_fn((int)startp[0], (int)startp[1], gSq_buff, - (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, - (int)lattice->nspin, (int)nbnds, - (int)lattice->start_band); - } - else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, - countp, gSq_buff))) - { - ERR(nc_err); - } - } - } - mpi_error = MPI_Barrier(Comm->commK); - MPI_error_msg(mpi_error); - // update the progress bar - print_progressbar(pbar); - } - // free wfc buffers - if (Comm->commK_rank == 0) - { - free(elph_kq_mn); - free(gSq_buff); - free(D_mat_l); - free(D_mat_r); - } - - free(KplusQidxs); -} diff --git a/services/dvG_utils.c b/services/dvG_utils.c deleted file mode 100644 index 1db548ce..00000000 --- a/services/dvG_utils.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * License-Identifier: GPL - * - * Copyright (C) 2025 The Yambo Team - * - * Authors (see AUTHORS file for details): RR AM - * - * Gather distributed dVscf z-slabs to commK rank 0 and apply a forward 3D - * FFT, producing dV_q^nu(G) ready for the elph_dvG_fill_fn callback. - */ - -#include "dvG_utils.h" -#include "fft/fft.h" -#include "common/error.h" -#include -#include - -ELPH_cmplx* gather_dVscf_and_fft(const ELPH_cmplx* dVscf, - const struct Lattice* lattice, - MPI_Comm commK) -{ - ND_int nmodes = lattice->nmodes; - ND_int nmag = lattice->nmag; - ND_int Nx = lattice->fft_dims[0]; - ND_int Ny = lattice->fft_dims[1]; - ND_int Nz = lattice->fft_dims[2]; - ND_int Nz_loc = lattice->nfftz_loc; - ND_int shift = lattice->nfftz_loc_shift; - ND_int Nxy = Nx * Ny; - ND_int NmodMag = nmodes * nmag; - - int commK_rank, commK_size; - MPI_Comm_rank(commK, &commK_rank); - MPI_Comm_size(commK, &commK_size); - - /* Collect per-rank Nz_loc and shifts. */ - int* all_Nz_loc = malloc(commK_size * sizeof(int)); - int* all_shifts = malloc(commK_size * sizeof(int)); - CHECK_ALLOC(all_Nz_loc); - CHECK_ALLOC(all_shifts); - int my_Nz_loc = (int)Nz_loc; - int my_shift = (int)shift; - MPI_Allgather(&my_Nz_loc, 1, MPI_INT, all_Nz_loc, 1, MPI_INT, commK); - MPI_Allgather(&my_shift, 1, MPI_INT, all_shifts, 1, MPI_INT, commK); - - /* - * Pack local slab: rearrange from - * dVscf[nmodes][nmag][Nx][Ny][Nz_loc] (C row-major) - * to - * packed[Nz_loc][nmodes][nmag][Nx][Ny] - * so that the z-extent is the leading dimension for contiguous Gatherv. - */ - ND_int local_count = Nz_loc * NmodMag * Nxy; - ELPH_cmplx* packed = malloc(local_count * sizeof(ELPH_cmplx)); - CHECK_ALLOC(packed); - - for (ND_int iv = 0; iv < nmodes; ++iv) - for (ND_int is = 0; is < nmag; ++is) - for (ND_int ix = 0; ix < Nx; ++ix) - for (ND_int iy = 0; iy < Ny; ++iy) - for (ND_int iz = 0; iz < Nz_loc; ++iz) - { - packed[iz * NmodMag*Nxy + iv * nmag*Nxy + is * Nxy + ix * Ny + iy] = - dVscf[iv * nmag*Nxy*Nz_loc + is * Nxy*Nz_loc - + ix * Ny*Nz_loc + iy * Nz_loc + iz]; - } - - /* Build Gatherv send/recv counts and displacements (only on rank 0). */ - int* sendcounts = NULL; - int* displs = NULL; - ELPH_cmplx* gathered = NULL; - ND_int NmodMagNxy = NmodMag * Nxy; - - if (commK_rank == 0) - { - sendcounts = malloc(commK_size * sizeof(int)); - displs = malloc(commK_size * sizeof(int)); - CHECK_ALLOC(sendcounts); - CHECK_ALLOC(displs); - for (int r = 0; r < commK_size; ++r) - { - sendcounts[r] = all_Nz_loc[r] * (int)NmodMagNxy; - displs[r] = all_shifts[r] * (int)NmodMagNxy; - } - gathered = malloc((size_t)Nz * NmodMag * Nxy * sizeof(ELPH_cmplx)); - CHECK_ALLOC(gathered); - } - - MPI_Gatherv(packed, (int)local_count, ELPH_MPI_cmplx, - gathered, sendcounts, displs, ELPH_MPI_cmplx, - 0, commK); - - free(packed); - free(all_Nz_loc); - free(all_shifts); - if (commK_rank == 0) - { - free(sendcounts); - free(displs); - } - - if (commK_rank != 0) - return NULL; - - /* - * Transpose gathered[Nz][nmodes][nmag][Nx][Ny] back to - * dVG[nmodes][nmag][Nx][Ny][Nz]. - */ - ELPH_cmplx* dVG = malloc((size_t)NmodMag * Nxy * Nz * sizeof(ELPH_cmplx)); - CHECK_ALLOC(dVG); - - for (ND_int iz = 0; iz < Nz; ++iz) - for (ND_int iv = 0; iv < nmodes; ++iv) - for (ND_int is = 0; is < nmag; ++is) - for (ND_int ix = 0; ix < Nx; ++ix) - for (ND_int iy = 0; iy < Ny; ++iy) - { - dVG[iv * nmag*Nxy*Nz + is * Nxy*Nz + ix * Ny*Nz + iy * Nz + iz] = - gathered[iz * NmodMagNxy + iv * nmag*Nxy + is * Nxy + ix * Ny + iy]; - } - free(gathered); - - /* - * Forward 3D FFT for each (mode, spin) slice. - * fftw plan_dft_3d uses row-major [n0][n1][n2] = [Nx][Ny][Nz]. - */ - ND_int slice_sz = Nxy * Nz; - for (ND_int iv = 0; iv < nmodes; ++iv) - for (ND_int is = 0; is < nmag; ++is) - { - ELPH_cmplx* sl = dVG + (iv * nmag + is) * slice_sz; - fftw_generic_plan plan = fftw_fun(plan_dft_3d)( - (int)Nx, (int)Ny, (int)Nz, - sl, sl, - FFTW_FORWARD, FFTW_ESTIMATE); - fftw_fun(execute)(plan); - fftw_fun(destroy_plan)(plan); - } - - return dVG; -} diff --git a/services/dvG_utils.h b/services/dvG_utils.h deleted file mode 100644 index fc4029e4..00000000 --- a/services/dvG_utils.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -/* - * License-Identifier: GPL - * - * Copyright (C) 2025 The Yambo Team - * - * Authors (see AUTHORS file for details): RR AM - * - * Helpers for gathering the distributed dVscf real-space potential and - * transforming it to reciprocal space so that the elph_dvG_fill_fn callback - * can be invoked from commK rank 0. - */ - -#include "common/dtypes.h" -#include "elph.h" -#include - -/* - * Gather z-slabs of dVscf from all commK ranks onto rank 0, perform a - * forward 3D FFT for each (mode, spin) slice, and return the result. - * - * dVscf layout (C row-major, distributed): - * (nmodes, nmag, fft_dims[0], fft_dims[1], nfftz_loc) - * - * Return value (only meaningful on commK rank 0; NULL on other ranks): - * malloc'd buffer of shape (nmodes, nmag, Nx, Ny, Nz) in G-space (complex). - * Caller must free(). - */ -ELPH_cmplx* gather_dVscf_and_fft(const ELPH_cmplx* dVscf, - const struct Lattice* lattice, - MPI_Comm commK); diff --git a/services/elph.h b/services/elph.h deleted file mode 100644 index 22caf6c7..00000000 --- a/services/elph.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include -#include - -#include "common/dtypes.h" -#include "elphC.h" - -/* - * Per-(iq_BZ, ik_BZ) fill callback for yambo COLL integration. - * Called once per BZ (q,k) pair on commK_rank==0 processes. - * iq_BZ, ik_BZ : 0-based BZ indices - * data : ELPH_cmplx buffer, C row-major (nmodes, nspin, nbnds, nbnds) - * nq..nb_start : full-BZ dimensions (constant across calls); nb_start is 1-based - */ -typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, - const void* data, - int nq, int nk, int nmodes, int nspin, - int nbnds, int nb_start); - -/* - * Callback for dV_q^nu(G) in reciprocal space, called once per iBZ q-point - * from commK rank 0. - * iq_iBZ : 0-based global iBZ q-point index - * dVG : C row-major (nmodes, nmag, nfft_x, nfft_y, nfft_z) after forward FFT - * nq_iBZ : total number of iBZ q-points - */ -typedef void (*elph_dvG_fill_fn)(int iq_iBZ, - const void* dVG, - int nq_iBZ, int nmodes, int nmag, - int nfft_x, int nfft_y, int nfft_z); - -void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world); - -/* Callback-enabled variant: skips ndb.elph; calls fill_fn per (q,k) instead. */ -void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn fill_fn); - -/* - * Extended callback variant: like elph_driver_cb plus calls dvG_fill_fn once per - * iBZ q-point with the full dV_q^nu(G) potential in reciprocal space. - * Either callback may be NULL to skip that output. - */ -void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn fill_fn, - elph_dvG_fill_fn dvG_fill_fn); - -void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, - struct Pseudo* pseudo, struct Phonon* phonon, - const ND_int iqpt, ELPH_cmplx* eigVec, - ELPH_cmplx* dVscfq, const int ncid_elph, - const int varid_elph, const int ncid_dmat, - const int varid_dmat, const bool non_loc, - const bool kminusq, - const struct ELPH_MPI_Comms* Comm, - elph_fill_fn fill_fn); - -void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, - const struct Lattice* lattice, - const ND_int nph_sym, - const struct symmetry* sym_data, - const struct ELPH_MPI_Comms* Comm); - -void init_kernel(struct kernel_info* kernel); - -void set_kernel(const char* kernel_str, struct kernel_info* kernel); diff --git a/services/elph_driver.c b/services/elph_driver.c deleted file mode 100644 index 44a41679..00000000 --- a/services/elph_driver.c +++ /dev/null @@ -1,762 +0,0 @@ -/* -THe starting point for the entire code -*/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common/ELPH_timers.h" -#include "common/dtypes.h" -#include "common/error.h" -#include "common/init_dtypes.h" -#include "common/parallel.h" -#include "common/print_info.h" -#include "dvloc/dvloc.h" -#include "dvG_utils.h" -#include "elph.h" -#include "elphC.h" -#include "fft/fft.h" -#include "io/io.h" -#include "io/qe/qe_io.h" -#include "parser/parser.h" -#include "symmetries/symmetries.h" - -void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world) -{ - struct elph_usr_input* input_data; - // start the clocks - init_ELPH_clocks(); - // - // read the input file - read_elph_input_file(ELPH_input_file, &input_data, comm_world); - // Note input parameters are broadcasted internally - // All the parameters in input_data must be available for all cpus in - // comm_world - - struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); - // initate the kernel with default - init_kernel(kernel); - // set the kernel - set_kernel(input_data->kernel_str, kernel); - - struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); - CHECK_ALLOC(mpi_comms); - - create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, - mpi_comms); - - // print logo and stated message - print_ELPH_logo(mpi_comms->commW_rank, stdout); - print_info_msg(mpi_comms->commW_rank, - "********** Program started **********"); - print_input_info(input_data->save_dir, input_data->ph_save_dir, - input_data->kernel_str, input_data->kminusq, dft_code, - mpi_comms); - - struct Lattice* lattice = malloc(sizeof(struct Lattice)); - CHECK_ALLOC(lattice); - init_lattice_type(lattice); - - struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); - CHECK_ALLOC(pseudo); - init_Pseudo_type(pseudo); - - struct Phonon* phonon = malloc(sizeof(struct Phonon)); - CHECK_ALLOC(phonon); - init_phonon_type(phonon); - - struct WFC* wfcs; - - // read the SAVE data and phonon related data. - read_and_alloc_save_data(input_data->save_dir, mpi_comms, - input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon, - dft_code); - - // print info about lattice and phonons - print_lattice_info(mpi_comms, lattice); - print_phonon_info(mpi_comms, phonon); - //======= Now start the real computation ========= - // a) COmpute the D_mats and store them in the netcdf file - // ============= Dmats ===================== - print_info_msg(mpi_comms->commW_rank, ""); - print_info_msg(mpi_comms->commW_rank, - "=== Computing Dmats for phonon symmetries ==="); - compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, - phonon->ph_syms, mpi_comms); - // b) Compute elph - // ============= ELPH iBZ computation ============= - ND_int nmodes = lattice->nmodes; - ND_int nfft_loc = - lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; - - ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); - //(nmodes,nmodes) // buffer to store eigen vectors - CHECK_ALLOC(eigVec); - - ELPH_cmplx* dVscf = - malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); - // (nmodes,nmag,Nx,Ny,Nz) // bufffer to store dVscf - CHECK_ALLOC(dVscf); - - ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); - // buffer for storing phonon freq - CHECK_ALLOC(omega_ph); - - int ncid_elph, ncid_dmat, nc_err; - int varid_eig, varid_elph, varid_omega, varid_dmat; - // Define netcdf variables - if (mpi_comms->commK_rank == 0) - { - // open Dmat file - if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, - MPI_INFO_NULL, &ncid_dmat))) - { - ERR(nc_err); - } - - // get dmat var id for dmats - if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) - { - ERR(nc_err); - } - - size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; - // Make a no-op call to nc_get_vara to avoid deadlocks in some - // suitiations. This happens when a procces doesnot make atleast - // single read call (for ex when qpool = qiBZ) - if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, - Dmat_counts, NULL))) - { - ERR(nc_err); - } - - // create elph file. Note: we overwrite any existing file - if ((nc_err = - nc_create_par("ndb.elph", NC_NETCDF4 | NC_CLOBBER, - mpi_comms->commR, MPI_INFO_NULL, &ncid_elph))) - { - fprintf(stderr, "Error creating ndb.elph file."); - ERR(nc_err); - } - - // set no fill mode (to avoid writting twice) - if ((nc_err = ncsetfill(ncid_elph, NC_NOFILL))) - { - fprintf(stderr, "Error setting nc_fill to ndb.elph file."); - ERR(nc_err); - } - - def_ncVar(ncid_elph, &varid_eig, 5, ELPH_NC4_IO_FLOAT, - (ND_int[]){phonon->nq_BZ, nmodes, nmodes / 3, 3, 2}, - "POLARIZATION_VECTORS", - (char*[]){"nq", "nmodes", "atom", "pol", "re_im"}, NULL); - - def_ncVar(ncid_elph, &varid_omega, 2, ELPH_NC4_IO_FLOAT, - (ND_int[]){phonon->nq_BZ, nmodes}, "FREQ", - (char*[]){"nq", "nmodes"}, NULL); - - ND_int nk_chunk_size = - NC4_DEFAULT_CHUCK_KB * 1024; // now this is in bytes - // scale with complex number size to get the number of elements - nk_chunk_size /= (sizeof(ELPH_cmplx) * nmodes * lattice->nspin * - lattice->nbnds * lattice->nbnds); - // chuck the varaible elph_mat with atmost default size - if (nk_chunk_size == 0) - { - nk_chunk_size = 1; - } - else if (nk_chunk_size > lattice->nkpts_BZ) - { - nk_chunk_size = lattice->nkpts_BZ; - } - - def_ncVar(ncid_elph, &varid_elph, 7, ELPH_NC4_IO_FLOAT, - (ND_int[]){phonon->nq_BZ, lattice->nkpts_BZ, nmodes, - lattice->nspin, lattice->nbnds, lattice->nbnds, 2}, - "elph_mat", - (char*[]){"nq", "nk", "nmodes", "nspin", "initial_band", - "final_band_PH_abs", "re_im"}, - (size_t[]){1, nk_chunk_size, nmodes, lattice->nspin, - lattice->nbnds, lattice->nbnds, 2}); - } - - ELPH_cmplx* eig_Sq = NULL; - - if (mpi_comms->commQ_rank == 0) - { - eig_Sq = calloc(nmodes * nmodes, sizeof(ELPH_cmplx)); - CHECK_ALLOC(eig_Sq); - } - - print_info_msg(mpi_comms->commW_rank, - "=== Computing Electron-phonon matrix elements ==="); - print_info_msg(mpi_comms->commW_rank, ""); - for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) - { - print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", - (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); - - ND_int iqpt_iBZg = iqpt + phonon->nq_shift; - // read dynamical matrix and dvscf for the iBZ qpt - if (dft_code == DFT_CODE_QE) - { - ELPH_cmplx* dvscf_read = NULL; - if (kernel->screening == ELPH_DFPT_SCREENING) - { - dvscf_read = dVscf; - } - else - { - // zero out the buffer. This is must ! - ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; - for (ND_int ix = 0; ix < dvscf_num; ++ix) - { - dVscf[ix] = 0.0; - } - } - // - get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, - eigVec, dvscf_read, omega_ph, mpi_comms); - // qe dvscf only contains dV_Ha + dV_xc, we need to add the local - // part of pseudo - } - else - { - error_msg("Currently only quantum espresso supported"); - } - // local part - ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); - // buffer to store local part of the pseudo potential - CHECK_ALLOC(Vlocr); - // - // compute the local part of the bare - dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, - mpi_comms->commK); - - if (dft_code == DFT_CODE_QE) - { - add_dvscf_qe(dVscf, Vlocr, - lattice); // add bare local to induce part - } - else - { - error_msg("Currently only quantum espresso supported"); - } - - free(Vlocr); - // free the local part buffer - ND_int qpos = 0; // positon of this iBZ qpoint in full q point list - for (ND_int i = 0; i < iqpt_iBZg; ++i) - { - qpos += phonon->nqstar[i]; - } - // write eigen vectors and frequencies - if (mpi_comms->commQ_rank == 0) - { - size_t startp[5] = {qpos, 0, 0, 0, 0}; - size_t countp[5] = {1, nmodes, nmodes / 3, 3, 2}; - if ((nc_err = - nc_put_vara(ncid_elph, varid_eig, startp, countp, eigVec))) - { - ERR(nc_err); - } - - if ((nc_err = nc_put_vara(ncid_elph, varid_omega, startp, countp, - omega_ph))) - { - ERR(nc_err); - } - // write down the rotate eigen vectors; - for (ND_int istar = 1; istar < phonon->nqstar[iqpt_iBZg]; ++istar) - { - ND_int qpos_star = qpos + istar; - - struct symmetry* sym_rot = - phonon->ph_syms + phonon->qmap[2 * qpos_star + 1]; - - rotate_eig_vecs(sym_rot, lattice, - phonon->qpts_iBZ + iqpt_iBZg * 3, eigVec, - eig_Sq); - // - startp[0] = qpos_star; - if ((nc_err = nc_put_vara(ncid_elph, varid_eig, startp, countp, - eig_Sq))) - { - ERR(nc_err); - } - - if ((nc_err = nc_put_vara(ncid_elph, varid_omega, startp, - countp, omega_ph))) - { - ERR(nc_err); - } - // - } - } - // Now compute and write the electron-phonon matrix elements - compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, - eigVec, dVscf, ncid_elph, varid_elph, ncid_dmat, - varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, NULL); - } - - free(eig_Sq); - - if (mpi_comms->commK_rank == 0) - { - // close files - if ((nc_err = nc_close(ncid_elph))) - { - ERR(nc_err); - } - - if ((nc_err = nc_close(ncid_dmat))) - { - ERR(nc_err); - } - } - - // finally write some basic info to ndb.elph file (only master node writes - // it) - - if (mpi_comms->commW_rank == 0) - { - if ((nc_err = nc_open("ndb.elph", NC_WRITE, &ncid_elph))) - { - ERR(nc_err); - } - - char convention_str[32]; - strcpy(convention_str, "standard"); - if (input_data->kminusq) - { - strcpy(convention_str, "yambo"); - } - write_basic_data(ncid_elph, lattice, phonon, input_data->kernel_str, - convention_str); - - if ((nc_err = nc_close(ncid_elph))) - { - ERR(nc_err); - } - } - - int World_rank_tmp = mpi_comms->commW_rank; - // ELPH_cmplx Ry2Ha = pow(2,-1.5); - free(omega_ph); - free(eigVec); - free(dVscf); - - // cleanup - free(kernel); - free_elph_usr_input(input_data); - free_save_data(wfcs, lattice, pseudo, phonon); - free(lattice); - free(pseudo); - free(phonon); - free_parallel_comms(mpi_comms); - free(mpi_comms); - fftw_fun(cleanup)(); - - // print the clocks - if (0 == World_rank_tmp) - { - print_ELPH_clock_summary(); - } - // cleanup the clocks - cleanup_ELPH_clocks(); - // done with the calculation - print_info_msg(World_rank_tmp, "********** Program ended **********"); -} - -/* - * Callback-enabled driver: identical flow to elph_driver but writes gkkp - * data via fill_fn(iq_BZ, ik_BZ, data, ...) instead of ndb.elph. - * ndb.Dmats is still created and used internally for BZ symmetry expansion. - * Eigenvectors / frequencies are NOT written (yambo reads them elsewhere). - */ -void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn fill_fn) -{ - struct elph_usr_input* input_data; - init_ELPH_clocks(); - - read_elph_input_file(ELPH_input_file, &input_data, comm_world); - - struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); - init_kernel(kernel); - set_kernel(input_data->kernel_str, kernel); - - struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); - CHECK_ALLOC(mpi_comms); - - create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, - mpi_comms); - - print_ELPH_logo(mpi_comms->commW_rank, stdout); - print_info_msg(mpi_comms->commW_rank, - "********** Program started **********"); - print_input_info(input_data->save_dir, input_data->ph_save_dir, - input_data->kernel_str, input_data->kminusq, dft_code, - mpi_comms); - - struct Lattice* lattice = malloc(sizeof(struct Lattice)); - CHECK_ALLOC(lattice); - init_lattice_type(lattice); - - struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); - CHECK_ALLOC(pseudo); - init_Pseudo_type(pseudo); - - struct Phonon* phonon = malloc(sizeof(struct Phonon)); - CHECK_ALLOC(phonon); - init_phonon_type(phonon); - - struct WFC* wfcs; - - read_and_alloc_save_data(input_data->save_dir, mpi_comms, - input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon, - dft_code); - - print_lattice_info(mpi_comms, lattice); - print_phonon_info(mpi_comms, phonon); - - print_info_msg(mpi_comms->commW_rank, ""); - print_info_msg(mpi_comms->commW_rank, - "=== Computing Dmats for phonon symmetries ==="); - compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, - phonon->ph_syms, mpi_comms); - - ND_int nmodes = lattice->nmodes; - ND_int nfft_loc = - lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; - - ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); - CHECK_ALLOC(eigVec); - - ELPH_cmplx* dVscf = - malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); - CHECK_ALLOC(dVscf); - - ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); - CHECK_ALLOC(omega_ph); - - int ncid_dmat, nc_err; - int varid_dmat; - - if (mpi_comms->commK_rank == 0) - { - if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, - MPI_INFO_NULL, &ncid_dmat))) - { - ERR(nc_err); - } - - if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) - { - ERR(nc_err); - } - - size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; - if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, - Dmat_counts, NULL))) - { - ERR(nc_err); - } - } - - print_info_msg(mpi_comms->commW_rank, - "=== Computing Electron-phonon matrix elements ==="); - print_info_msg(mpi_comms->commW_rank, ""); - - for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) - { - print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", - (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); - - ND_int iqpt_iBZg = iqpt + phonon->nq_shift; - - if (dft_code == DFT_CODE_QE) - { - ELPH_cmplx* dvscf_read = NULL; - if (kernel->screening == ELPH_DFPT_SCREENING) - { - dvscf_read = dVscf; - } - else - { - ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; - for (ND_int ix = 0; ix < dvscf_num; ++ix) - { - dVscf[ix] = 0.0; - } - } - get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, - eigVec, dvscf_read, omega_ph, mpi_comms); - } - else - { - error_msg("Currently only quantum espresso supported"); - } - - ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); - CHECK_ALLOC(Vlocr); - dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, - mpi_comms->commK); - - if (dft_code == DFT_CODE_QE) - { - add_dvscf_qe(dVscf, Vlocr, lattice); - } - else - { - error_msg("Currently only quantum espresso supported"); - } - free(Vlocr); - - compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, - eigVec, dVscf, 0, 0, ncid_dmat, - varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, fill_fn); - } - - if (mpi_comms->commK_rank == 0) - { - if ((nc_err = nc_close(ncid_dmat))) - { - ERR(nc_err); - } - } - - free(omega_ph); - free(eigVec); - free(dVscf); - - int World_rank_tmp = mpi_comms->commW_rank; - - free(kernel); - free_elph_usr_input(input_data); - free_save_data(wfcs, lattice, pseudo, phonon); - free(lattice); - free(pseudo); - free(phonon); - free_parallel_comms(mpi_comms); - free(mpi_comms); - fftw_fun(cleanup)(); - - if (0 == World_rank_tmp) - { - print_ELPH_clock_summary(); - } - cleanup_ELPH_clocks(); - print_info_msg(World_rank_tmp, "********** Program ended **********"); -} - -/* - * Extended callback variant: like elph_driver_cb plus dvG_fill_fn called - * once per iBZ q-point from commK rank 0 with dV_q^nu(G) in G-space. - * Either callback may be NULL to skip that output. - */ -void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn fill_fn, - elph_dvG_fill_fn dvG_fill_fn) -{ - struct elph_usr_input* input_data; - init_ELPH_clocks(); - - read_elph_input_file(ELPH_input_file, &input_data, comm_world); - - struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); - init_kernel(kernel); - set_kernel(input_data->kernel_str, kernel); - - struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); - CHECK_ALLOC(mpi_comms); - - create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, - mpi_comms); - - print_ELPH_logo(mpi_comms->commW_rank, stdout); - print_info_msg(mpi_comms->commW_rank, - "********** Program started **********"); - print_input_info(input_data->save_dir, input_data->ph_save_dir, - input_data->kernel_str, input_data->kminusq, dft_code, - mpi_comms); - - struct Lattice* lattice = malloc(sizeof(struct Lattice)); - CHECK_ALLOC(lattice); - init_lattice_type(lattice); - - struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); - CHECK_ALLOC(pseudo); - init_Pseudo_type(pseudo); - - struct Phonon* phonon = malloc(sizeof(struct Phonon)); - CHECK_ALLOC(phonon); - init_phonon_type(phonon); - - struct WFC* wfcs; - - read_and_alloc_save_data(input_data->save_dir, mpi_comms, - input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon, - dft_code); - - print_lattice_info(mpi_comms, lattice); - print_phonon_info(mpi_comms, phonon); - - print_info_msg(mpi_comms->commW_rank, ""); - print_info_msg(mpi_comms->commW_rank, - "=== Computing Dmats for phonon symmetries ==="); - compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, - phonon->ph_syms, mpi_comms); - - ND_int nmodes = lattice->nmodes; - ND_int nfft_loc = - lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; - - ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); - CHECK_ALLOC(eigVec); - - ELPH_cmplx* dVscf = - malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); - CHECK_ALLOC(dVscf); - - ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); - CHECK_ALLOC(omega_ph); - - int ncid_dmat, nc_err; - int varid_dmat; - - if (mpi_comms->commK_rank == 0) - { - if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, - MPI_INFO_NULL, &ncid_dmat))) - { - ERR(nc_err); - } - - if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) - { - ERR(nc_err); - } - - size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; - if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, - Dmat_counts, NULL))) - { - ERR(nc_err); - } - } - - print_info_msg(mpi_comms->commW_rank, - "=== Computing Electron-phonon matrix elements ==="); - print_info_msg(mpi_comms->commW_rank, ""); - - for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) - { - print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", - (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); - - ND_int iqpt_iBZg = iqpt + phonon->nq_shift; - - if (dft_code == DFT_CODE_QE) - { - ELPH_cmplx* dvscf_read = NULL; - if (kernel->screening == ELPH_DFPT_SCREENING) - { - dvscf_read = dVscf; - } - else - { - ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; - for (ND_int ix = 0; ix < dvscf_num; ++ix) - { - dVscf[ix] = 0.0; - } - } - get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, - eigVec, dvscf_read, omega_ph, mpi_comms); - } - else - { - error_msg("Currently only quantum espresso supported"); - } - - ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); - CHECK_ALLOC(Vlocr); - dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, - mpi_comms->commK); - - if (dft_code == DFT_CODE_QE) - { - add_dvscf_qe(dVscf, Vlocr, lattice); - } - else - { - error_msg("Currently only quantum espresso supported"); - } - free(Vlocr); - - /* dvG callback: gather dVscf z-slabs to rank 0, FFT, call handler. */ - if (dvG_fill_fn != NULL) - { - ELPH_cmplx* dVG = gather_dVscf_and_fft(dVscf, lattice, - mpi_comms->commK); - if (mpi_comms->commK_rank == 0) - { - dvG_fill_fn((int)iqpt_iBZg, (const void*)dVG, - (int)phonon->nq_iBZ, - (int)nmodes, (int)lattice->nmag, - (int)lattice->fft_dims[0], - (int)lattice->fft_dims[1], - (int)lattice->fft_dims[2]); - free(dVG); - } - } - - compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, - eigVec, dVscf, 0, 0, ncid_dmat, - varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, fill_fn); - } - - if (mpi_comms->commK_rank == 0) - { - if ((nc_err = nc_close(ncid_dmat))) - { - ERR(nc_err); - } - } - - free(omega_ph); - free(eigVec); - free(dVscf); - - int World_rank_tmp = mpi_comms->commW_rank; - - free(kernel); - free_elph_usr_input(input_data); - free_save_data(wfcs, lattice, pseudo, phonon); - free(lattice); - free(pseudo); - free(phonon); - free_parallel_comms(mpi_comms); - free(mpi_comms); - fftw_fun(cleanup)(); - - if (0 == World_rank_tmp) - { - print_ELPH_clock_summary(); - } - cleanup_ELPH_clocks(); - print_info_msg(World_rank_tmp, "********** Program ended **********"); -} diff --git a/services/ep_f2c_bridge.c b/services/ep_f2c_bridge.c deleted file mode 100644 index 7861fb90..00000000 --- a/services/ep_f2c_bridge.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * License-Identifier: GPL - * - * Copyright (C) 2025 The Yambo Team - * - * Authors (see AUTHORS file for details): RR AM - * - * Thin bridge: called from Fortran via ISO_C_BINDING. - * Converts a Fortran MPI communicator handle (MPI_Fint) to a C MPI_Comm - * and forwards the call to LetzElPhC's elph_driver(). - */ - -#include "elph.h" /* already pulls in common/dtypes.h and elphC.h */ -#include - -void elph_driver_f2c(const char* input_file, int dft_code, MPI_Fint f_comm) -{ - MPI_Comm c_comm = MPI_Comm_f2c(f_comm); - elph_driver(input_file, (enum ELPH_dft_code)dft_code, c_comm); -} - -/* - * Callback-enabled bridge: fill_fn_ptr is a Fortran procedure pointer - * (passed as a C function pointer via ISO_C_BINDING's c_funloc). - */ -void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, - void* fill_fn_ptr) -{ - MPI_Comm c_comm = MPI_Comm_f2c(f_comm); - elph_driver_cb(input_file, (enum ELPH_dft_code)dft_code, c_comm, - (elph_fill_fn)fill_fn_ptr); -} - -/* - * Extended callback bridge: gkkp fill_fn + dvG fill callback. - * Either pointer may be NULL (pass c_null_funptr from Fortran) to skip that output. - */ -void elph_driver_cb2_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, - void* fill_fn_ptr, void* dvG_fill_fn_ptr) -{ - MPI_Comm c_comm = MPI_Comm_f2c(f_comm); - elph_driver_cb2(input_file, (enum ELPH_dft_code)dft_code, c_comm, - (elph_fill_fn)fill_fn_ptr, - (elph_dvG_fill_fn)dvG_fill_fn_ptr); -} diff --git a/services/set_kernel.c b/services/set_kernel.c deleted file mode 100644 index 1970d14c..00000000 --- a/services/set_kernel.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include - -#include "common/dtypes.h" -#include "common/error.h" -#include "common/string_func.h" -#include "elph.h" - -void init_kernel(struct kernel_info* kernel) -{ - strcpy(kernel->name_str, "dfpt"); - kernel->bare_loc = true; - kernel->non_loc = true; - kernel->screening = ELPH_DFPT_SCREENING; -} - -void set_kernel(const char* kernel_str, struct kernel_info* kernel) -{ - size_t name_str_size = sizeof(kernel->name_str) - 1; - kernel->name_str[name_str_size] = '\0'; - strlcpy_custom(kernel->name_str, kernel_str, name_str_size); - - if (!strcmp(kernel_str, "dfpt")) - { - kernel->bare_loc = true; - kernel->non_loc = true; - kernel->screening = ELPH_DFPT_SCREENING; - } - else if (!strcmp(kernel_str, "dfpt_local")) - { - kernel->bare_loc = true; - kernel->non_loc = false; - kernel->screening = ELPH_DFPT_SCREENING; - } - else if (!strcmp(kernel_str, "bare")) - { - kernel->bare_loc = true; - kernel->non_loc = true; - kernel->screening = ELPH_NO_SCREENING; - } - else if (!strcmp(kernel_str, "bare_local")) - { - kernel->bare_loc = true; - kernel->non_loc = false; - kernel->screening = ELPH_NO_SCREENING; - } - else - { - error_msg("invalid value for kernel in the input file"); - } -} From 650716af5ff3a873c21c45e34aba1b9823ca3b34 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Wed, 20 May 2026 17:42:55 +0200 Subject: [PATCH 10/46] changes in fallback --- services/elph.h | 8 +++++--- services/elph/elph_driver.c | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/services/elph.h b/services/elph.h index 22caf6c7..30350216 100644 --- a/services/elph.h +++ b/services/elph.h @@ -20,12 +20,14 @@ typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, /* * Callback for dV_q^nu(G) in reciprocal space, called once per iBZ q-point * from commK rank 0. - * iq_iBZ : 0-based global iBZ q-point index - * dVG : C row-major (nmodes, nmag, nfft_x, nfft_y, nfft_z) after forward FFT - * nq_iBZ : total number of iBZ q-points + * iq_iBZ : 0-based global iBZ q-point index + * dVG : C row-major (nmodes, nmag, nfft_x, nfft_y, nfft_z) after forward FFT + * ph_freqs : phonon frequencies omega_ph[nmodes] in Hartree (ELPH_float*) + * nq_iBZ : total number of iBZ q-points */ typedef void (*elph_dvG_fill_fn)(int iq_iBZ, const void* dVG, + const void* ph_freqs, int nq_iBZ, int nmodes, int nmag, int nfft_x, int nfft_y, int nfft_z); diff --git a/services/elph/elph_driver.c b/services/elph/elph_driver.c index 44a41679..5df597fc 100644 --- a/services/elph/elph_driver.c +++ b/services/elph/elph_driver.c @@ -714,6 +714,7 @@ void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, if (mpi_comms->commK_rank == 0) { dvG_fill_fn((int)iqpt_iBZg, (const void*)dVG, + (const void*)omega_ph, (int)phonon->nq_iBZ, (int)nmodes, (int)lattice->nmag, (int)lattice->fft_dims[0], From ebf3d5e18f4e0485b5f77efa517c01e07c44ffe7 Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Tue, 26 May 2026 13:06:17 +0200 Subject: [PATCH 11/46] More elements to connect to the main --- compile/headers_and_libs.mk | 4 ++-- compile/libraries.mk | 6 +++--- info/compilation.info | 7 +++++++ info/intro.info | 8 ++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 info/compilation.info create mode 100644 info/intro.info diff --git a/compile/headers_and_libs.mk b/compile/headers_and_libs.mk index d6c32c0b..cc110c9d 100644 --- a/compile/headers_and_libs.mk +++ b/compile/headers_and_libs.mk @@ -10,5 +10,5 @@ # like "common/dtypes.h", so the plugin services root must be on the # include path. # -iheaders += $(IFLAG)$(srcdir)/plugins/ep/services -include_headers += $(IFLAG)$(srcdir)/plugins/ep/services +iheaders += $(IFLAG)$(srcdir)/plugins/letz/services +include_headers += $(IFLAG)$(srcdir)/plugins/letz/services diff --git a/compile/libraries.mk b/compile/libraries.mk index bc64ef5c..b2ff0dac 100644 --- a/compile/libraries.mk +++ b/compile/libraries.mk @@ -9,8 +9,8 @@ ifeq ($(wildcard compile/global/defs.mk),compile/global/defs.mk) include compile/defs.mk endif # -EP_S1= [Sep,nonloc] [Sep,io/ezxml] [Sep,parser/inih] [Sep,io] -EP_S2= [Sep,io/qe] [Sep,common] [Sep,dvloc] [Sep,elph] [Sep,wfc] [Sep,symmetries] [Sep,fft] -EP_S3= [Sep,common/cwalk] [Sep,preprocessor] [Sep,interpolation] [Sep,common/ELPH_hash_map] [Sep,phonon] [Sep,common/kdtree] [Sep,parser] +EP_S1= [Sletz,nonloc] [Sletz,io/ezxml] [Sletz,parser/inih] [Sletz,io] +EP_S2= [Sletz,io/qe] [Sletz,common] [Sletz,dvloc] [Sletz,elph] [Sletz,wfc] [Sletz,symmetries] [Sletz,fft] +EP_S3= [Sletz,common/cwalk] [Sletz,preprocessor] [Sletz,interpolation] [Sletz,common/ELPH_hash_map] [Sletz,phonon] [Sletz,common/kdtree] [Sletz,parser] # SERVICES_LIBS += ${EP_S1} ${EP_S2} ${EP_S3} diff --git a/info/compilation.info b/info/compilation.info new file mode 100644 index 00000000..f82a95c8 --- /dev/null +++ b/info/compilation.info @@ -0,0 +1,7 @@ +# +# License-Identifier: GPL +# +# Copyright (C) 2026 The Yambo Team +# +# Authors (see AUTHORS file for details): AM RR +# diff --git a/info/intro.info b/info/intro.info new file mode 100644 index 00000000..211a647b --- /dev/null +++ b/info/intro.info @@ -0,0 +1,8 @@ +# +# License-Identifier: GPL +# +# Copyright (C) 2026 The Yambo Team +# +# Authors (see AUTHORS file for details): AM RR +# + [letz-plugin] This plugin connects Yambo with the LetzElPhC code From f374bed9c6efca5070da390420254da0337b83a8 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Tue, 26 May 2026 21:59:48 +0200 Subject: [PATCH 12/46] change for compilation and linking order --- compile/headers_and_libs.mk | 3 +-- compile/libraries.mk | 4 +++- compile/targets.mk | 11 +---------- services/elph/compute_elph_matq.c | 11 ++++++++--- services/elph/elph.h | 14 +++++++++----- services/elph/elph_driver.c | 8 +++++--- 6 files changed, 27 insertions(+), 24 deletions(-) diff --git a/compile/headers_and_libs.mk b/compile/headers_and_libs.mk index d6c32c0b..edcff51c 100644 --- a/compile/headers_and_libs.mk +++ b/compile/headers_and_libs.mk @@ -10,5 +10,4 @@ # like "common/dtypes.h", so the plugin services root must be on the # include path. # -iheaders += $(IFLAG)$(srcdir)/plugins/ep/services -include_headers += $(IFLAG)$(srcdir)/plugins/ep/services +# ep plugin is superseded by letz; include paths defined in letz/compile/headers_and_libs.mk diff --git a/compile/libraries.mk b/compile/libraries.mk index bc64ef5c..d115f94f 100644 --- a/compile/libraries.mk +++ b/compile/libraries.mk @@ -13,4 +13,6 @@ EP_S1= [Sep,nonloc] [Sep,io/ezxml] [Sep,parser/inih] [Sep,io] EP_S2= [Sep,io/qe] [Sep,common] [Sep,dvloc] [Sep,elph] [Sep,wfc] [Sep,symmetries] [Sep,fft] EP_S3= [Sep,common/cwalk] [Sep,preprocessor] [Sep,interpolation] [Sep,common/ELPH_hash_map] [Sep,phonon] [Sep,common/kdtree] [Sep,parser] # -SERVICES_LIBS += ${EP_S1} ${EP_S2} ${EP_S3} +ifneq (,$(filter yambo_ep ypp_ep,$(MAKECMDGOALS))) + SERVICES_LIBS += ${EP_S1} ${EP_S2} ${EP_S3} +endif diff --git a/compile/targets.mk b/compile/targets.mk index 5e3a0ea2..68a8772e 100644 --- a/compile/targets.mk +++ b/compile/targets.mk @@ -5,13 +5,4 @@ # # Authors (see AUTHORS file for details): AM MN RR # -# Build the standalone lelphc binary from LetzElPhC C source. -# Requires yambo to have been configured first (config/setup must exist). -# Usage: make lelphc -> builds plugins/ep/services/lelphc -# make clean_lelphc -> cleans the standalone build - -lelphc: - $(MAKE) -C $(srcdir)/plugins/ep/services - -clean_lelphc: - -$(MAKE) -C $(srcdir)/plugins/ep/services clean +# lelphc/clean_lelphc targets defined in plugins/letz/compile/targets.mk diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index a9af8bf1..1cb8e118 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -25,7 +25,8 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, const int varid_dmat, const bool non_loc, const bool kminusq, const struct ELPH_MPI_Comms* Comm, - elph_fill_fn fill_fn) + elph_fill_fn fill_fn, + const ND_int iqpt_iBZ) { /* dVscf -> (nmodes,nmag,Nx,Ny,Nz) @@ -152,7 +153,9 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, (int)lattice->nspin, (int)nbnds, - (int)lattice->start_band); + (int)lattice->start_band, + (int)iqpt_iBZ, + (const void*)(phonon->qpts_BZ + 3 * startp[0])); } else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, countp, elph_kq_mn))) @@ -222,7 +225,9 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, fill_fn((int)startp[0], (int)startp[1], gSq_buff, (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, (int)lattice->nspin, (int)nbnds, - (int)lattice->start_band); + (int)lattice->start_band, + (int)iqpt_iBZ, + (const void*)(phonon->qpts_BZ + 3 * startp[0])); } else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, countp, gSq_buff))) diff --git a/services/elph/elph.h b/services/elph/elph.h index 30350216..980071c0 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -8,14 +8,17 @@ /* * Per-(iq_BZ, ik_BZ) fill callback for yambo COLL integration. * Called once per BZ (q,k) pair on commK_rank==0 processes. - * iq_BZ, ik_BZ : 0-based BZ indices - * data : ELPH_cmplx buffer, C row-major (nmodes, nspin, nbnds, nbnds) - * nq..nb_start : full-BZ dimensions (constant across calls); nb_start is 1-based + * iq_BZ, ik_BZ : 0-based BZ indices + * data : ELPH_cmplx buffer, C row-major (nmodes, nspin, nbnds, nbnds) + * nq..nb_start : full-BZ dimensions (constant across calls); nb_start is 1-based + * iq_iBZ : 0-based iBZ q-point index for this iq_BZ star + * qpt_BZ_crys : crystal-coordinate q-point for iq_BZ (ELPH_float[3]) */ typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, const void* data, int nq, int nk, int nmodes, int nspin, - int nbnds, int nb_start); + int nbnds, int nb_start, + int iq_iBZ, const void* qpt_BZ_crys); /* * Callback for dV_q^nu(G) in reciprocal space, called once per iBZ q-point @@ -55,7 +58,8 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, const int varid_dmat, const bool non_loc, const bool kminusq, const struct ELPH_MPI_Comms* Comm, - elph_fill_fn fill_fn); + elph_fill_fn fill_fn, + const ND_int iqpt_iBZ); void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, const struct Lattice* lattice, diff --git a/services/elph/elph_driver.c b/services/elph/elph_driver.c index 5df597fc..dfa1d210 100644 --- a/services/elph/elph_driver.c +++ b/services/elph/elph_driver.c @@ -304,7 +304,7 @@ void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, eigVec, dVscf, ncid_elph, varid_elph, ncid_dmat, varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, NULL); + input_data->kminusq, mpi_comms, NULL, iqpt_iBZg); } free(eig_Sq); @@ -525,7 +525,8 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, eigVec, dVscf, 0, 0, ncid_dmat, varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, fill_fn); + input_data->kminusq, mpi_comms, fill_fn, + iqpt_iBZg); } if (mpi_comms->commK_rank == 0) @@ -727,7 +728,8 @@ void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, eigVec, dVscf, 0, 0, ncid_dmat, varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, fill_fn); + input_data->kminusq, mpi_comms, fill_fn, + iqpt_iBZg); } if (mpi_comms->commK_rank == 0) From 693bc3f489e854babebf7695e68c8ac3248b8734 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Tue, 26 May 2026 22:02:47 +0200 Subject: [PATCH 13/46] introduce new order --- compile/libraries.mk | 28 ++++++++++++++++++++++++---- services/Makefile | 15 +++++++++------ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/compile/libraries.mk b/compile/libraries.mk index b2ff0dac..67aa87f0 100644 --- a/compile/libraries.mk +++ b/compile/libraries.mk @@ -9,8 +9,28 @@ ifeq ($(wildcard compile/global/defs.mk),compile/global/defs.mk) include compile/defs.mk endif # -EP_S1= [Sletz,nonloc] [Sletz,io/ezxml] [Sletz,parser/inih] [Sletz,io] -EP_S2= [Sletz,io/qe] [Sletz,common] [Sletz,dvloc] [Sletz,elph] [Sletz,wfc] [Sletz,symmetries] [Sletz,fft] -EP_S3= [Sletz,common/cwalk] [Sletz,preprocessor] [Sletz,interpolation] [Sletz,common/ELPH_hash_map] [Sletz,phonon] [Sletz,common/kdtree] [Sletz,parser] +# Library link order is INTRINSIC to LetzElPhC's dependency. +# Static linker is left-to-right: symbol-users before symbol-providers. # -SERVICES_LIBS += ${EP_S1} ${EP_S2} ${EP_S3} +# Dependency tiers (each tier depends only on equal/lower tiers): +# T5 drivers : interpolation, elph +# T4 QE I/O : io/qe +# T3 main I/O : io +# T2 kernels+pp : dvloc, nonloc, symmetries, preprocessor +# T1 primitives : wfc, fft, phonon, parser +# T0 base+vendors : common, common/cwalk, common/ELPH_hash_map, common/kdtree, +# io/ezxml, parser/inih +# +# elph (T5) hosts the Fortran-to-C ABI boundary (ep_f2c_bridge.c): +# elph_driver_f2c / elph_driver_cb_f2c / elph_driver_cb2_f2c +# These are the ONLY entry points yambo_ep calls into LetzElPhC. +# +EP_S1= [Sletz,interpolation] [Sletz,elph] +EP_S2= [Sletz,io/qe] +EP_S3= [Sletz,io] +EP_S4= [Sletz,dvloc] [Sletz,nonloc] [Sletz,symmetries] [Sletz,preprocessor] +EP_S5= [Sletz,wfc] [Sletz,fft] [Sletz,phonon] [Sletz,parser] +EP_S6= [Sletz,common] [Sletz,common/cwalk] [Sletz,common/ELPH_hash_map] \ + [Sletz,common/kdtree] [Sletz,io/ezxml] [Sletz,parser/inih] +# +SERVICES_LIBS += ${EP_S1} ${EP_S2} ${EP_S3} ${EP_S4} ${EP_S5} ${EP_S6} diff --git a/services/Makefile b/services/Makefile index 53edd6b4..2382396e 100644 --- a/services/Makefile +++ b/services/Makefile @@ -4,12 +4,15 @@ TARGET := lelphc #### make start here -SUBDIR = nonloc io/ezxml parser/inih io \ - io/qe common dvloc elph wfc \ - symmetries fft common/cwalk \ - preprocessor interpolation \ - common/ELPH_hash_map phonon \ - common/kdtree parser +# SUBDIR order mirrors the link-tier (T0 base → T5 drivers). +# For library use, compile/libraries.mk enforces the same tier ordering. +SUBDIR = common common/cwalk common/ELPH_hash_map common/kdtree \ + io/ezxml parser/inih \ + wfc fft phonon parser \ + dvloc nonloc symmetries preprocessor \ + io \ + io/qe \ + elph interpolation .SUFFIXES : From 8abf218cad6b6cb5685f24e5ceab14543e1740ed Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Tue, 26 May 2026 22:17:41 +0200 Subject: [PATCH 14/46] revert changes --- compile/headers_and_libs.mk | 3 ++- compile/targets.mk | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/compile/headers_and_libs.mk b/compile/headers_and_libs.mk index edcff51c..cc110c9d 100644 --- a/compile/headers_and_libs.mk +++ b/compile/headers_and_libs.mk @@ -10,4 +10,5 @@ # like "common/dtypes.h", so the plugin services root must be on the # include path. # -# ep plugin is superseded by letz; include paths defined in letz/compile/headers_and_libs.mk +iheaders += $(IFLAG)$(srcdir)/plugins/letz/services +include_headers += $(IFLAG)$(srcdir)/plugins/letz/services diff --git a/compile/targets.mk b/compile/targets.mk index 68a8772e..5868b9c9 100644 --- a/compile/targets.mk +++ b/compile/targets.mk @@ -5,4 +5,8 @@ # # Authors (see AUTHORS file for details): AM MN RR # -# lelphc/clean_lelphc targets defined in plugins/letz/compile/targets.mk +lelphc: + $(MAKE) -C $(srcdir)/plugins/letz/services + +clean_lelphc: + -$(MAKE) -C $(srcdir)/plugins/letz/services clean From e1876d1e378769f76aa03657d9998f0c9e899745 Mon Sep 17 00:00:00 2001 From: marini Date: Wed, 27 May 2026 15:44:22 +0200 Subject: [PATCH 15/46] MODIFIED * compile/headers_and_libs.mk compile/libraries.mk Changes: - Libraries order fixed Patch sent by: marini --- compile/headers_and_libs.mk | 1 + compile/libraries.mk | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compile/headers_and_libs.mk b/compile/headers_and_libs.mk index cc110c9d..b5d57158 100644 --- a/compile/headers_and_libs.mk +++ b/compile/headers_and_libs.mk @@ -12,3 +12,4 @@ # iheaders += $(IFLAG)$(srcdir)/plugins/letz/services include_headers += $(IFLAG)$(srcdir)/plugins/letz/services +llibs += -lcblas diff --git a/compile/libraries.mk b/compile/libraries.mk index 0db735c3..70af37c9 100644 --- a/compile/libraries.mk +++ b/compile/libraries.mk @@ -25,13 +25,12 @@ endif # elph_driver_f2c / elph_driver_cb_f2c / elph_driver_cb2_f2c # These are the ONLY entry points yambo_ep calls into LetzElPhC. # -EP_S1= [Sletz,interpolation] [Sletz,elph] -EP_S2= [Sletz,io/qe] -EP_S3= [Sletz,io] -EP_S4= [Sletz,dvloc] [Sletz,nonloc] [Sletz,symmetries] [Sletz,preprocessor] -EP_S5= [Sletz,wfc] [Sletz,fft] [Sletz,phonon] [Sletz,parser] -EP_S6= [Sletz,common] [Sletz,common/cwalk] [Sletz,common/ELPH_hash_map] \ - [Sletz,common/kdtree] [Sletz,io/ezxml] [Sletz,parser/inih] +EP_S1= [Sletz,interpolation] +EP_S2= [Sletz,io/qe] [Sletz,common/ELPH_hash_map] [Sletz,common] [Sletz,symmetries] [Sletz,nonloc] +EP_S3= [Sletz,dvloc] [Sletz,io] [Sletz,io/ezxml] +EP_S4= [Sletz,wfc] [Sletz,fft] [Sletz,dvloc] [Sletz,common/cwalk] [Sletz,preprocessor] +EP_S5= [Sletz,phonon] [Sletz,parser/inih] [Sletz,parser] +EP_S6= [Sletz,common/kdtree] [Sletz,elph] # ifneq (,$(filter yambo_ep ypp_ep,$(MAKECMDGOALS))) SERVICES_LIBS += ${EP_S1} ${EP_S2} ${EP_S3} ${EP_S4} ${EP_S5} ${EP_S6} From b10b2fd1cbcd4b0129a9cd0c18c233425f9ce0db Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Thu, 28 May 2026 08:31:01 +0200 Subject: [PATCH 16/46] remove circularly dependency between common and nonloc due to free_Pseudos --- services/common/free_dtypes.c | 32 +------------------ services/common/free_dtypes.h | 3 +- services/interpolation/interpolation_driver.c | 1 + services/nonloc/fcoeff.c | 29 +++++++++++++++++ services/nonloc/fcoeff.h | 1 + 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/services/common/free_dtypes.c b/services/common/free_dtypes.c index 3b6fc66e..c12c0f56 100644 --- a/services/common/free_dtypes.c +++ b/services/common/free_dtypes.c @@ -5,7 +5,6 @@ #include "dtypes.h" #include "elphC.h" -#include "nonloc/fcoeff.h" void free_wfc_type(struct WFC* Wfc) { @@ -109,33 +108,4 @@ void free_local_pseudo_type(struct local_pseudo* lpseudo) lpseudo->rab_grid = NULL; return; -} - -void free_Pseudo_type(struct Pseudo* pseudo) -{ - if (!pseudo) - { - return; - } - - free_f_Coeff(pseudo); - free(pseudo->fCoeff); - free_Vloc_table_type(pseudo->vloc_table); - free(pseudo->Fsign); - free(pseudo->PP_table); - - if (pseudo->loc_pseudo) - { - for (ND_int itype = 0; itype < pseudo->ntype; ++itype) - { - free_local_pseudo_type(pseudo->loc_pseudo + itype); - } - } - free(pseudo->loc_pseudo); - - pseudo->loc_pseudo = NULL; - pseudo->PP_table = NULL; - pseudo->Fsign = NULL; - pseudo->fCoeff = NULL; - return; -} +} \ No newline at end of file diff --git a/services/common/free_dtypes.h b/services/common/free_dtypes.h index 3549574f..a1eab0a1 100644 --- a/services/common/free_dtypes.h +++ b/services/common/free_dtypes.h @@ -6,5 +6,4 @@ void free_lattice_type(struct Lattice* lattice); void free_phonon_type(struct Phonon* phonon); void free_Vloc_table_type(struct Vloc_table* vloc_tab); void free_local_pseudo_type(struct local_pseudo* lpseudo); -void free_Pseudo_type(struct Pseudo* pseudo); -void free_wfc_type(struct WFC* wfc); +void free_wfc_type(struct WFC* wfc); \ No newline at end of file diff --git a/services/interpolation/interpolation_driver.c b/services/interpolation/interpolation_driver.c index e5b3eae3..35347746 100644 --- a/services/interpolation/interpolation_driver.c +++ b/services/interpolation/interpolation_driver.c @@ -19,6 +19,7 @@ #include "common/print_info.h" #include "common/progess_bar.h" #include "dvloc/dvloc.h" +#include "nonloc/fcoeff.h" #include "elphC.h" #include "interpolation.h" #include "interpolation_utilities.h" diff --git a/services/nonloc/fcoeff.c b/services/nonloc/fcoeff.c index 18ef289f..72582c40 100644 --- a/services/nonloc/fcoeff.c +++ b/services/nonloc/fcoeff.c @@ -14,6 +14,7 @@ These routines contain functions related the pseudo potentials. #include "common/constants.h" #include "common/dtypes.h" #include "common/error.h" +#include "common/free_dtypes.h" #include "elphC.h" /** Static declarations*/ @@ -281,3 +282,31 @@ static ELPH_float CGCoeff(bool jp1, bool spin_down, int l, int twomj) } } } + +void free_Pseudo_type(struct Pseudo* pseudo) +{ + if (!pseudo) + { + return; + } + + free_f_Coeff(pseudo); + free(pseudo->fCoeff); + free_Vloc_table_type(pseudo->vloc_table); + free(pseudo->Fsign); + free(pseudo->PP_table); + + if (pseudo->loc_pseudo) + { + for (ND_int itype = 0; itype < pseudo->ntype; ++itype) + { + free_local_pseudo_type(pseudo->loc_pseudo + itype); + } + } + free(pseudo->loc_pseudo); + + pseudo->loc_pseudo = NULL; + pseudo->PP_table = NULL; + pseudo->Fsign = NULL; + pseudo->fCoeff = NULL; +} diff --git a/services/nonloc/fcoeff.h b/services/nonloc/fcoeff.h index 5745ff1e..707cfb29 100644 --- a/services/nonloc/fcoeff.h +++ b/services/nonloc/fcoeff.h @@ -3,3 +3,4 @@ void alloc_and_Compute_f_Coeff(struct Lattice* lattice, struct Pseudo* pseudo); void free_f_Coeff(struct Pseudo* pseudo); +void free_Pseudo_type(struct Pseudo* pseudo); From fdb81fafe06bbc9d48ff41c7f25f7aba46dfa526 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Thu, 28 May 2026 08:41:04 +0200 Subject: [PATCH 17/46] fix cycle dep between io and io/qe --- services/elph/elph_driver.c | 36 ++++++++++++++++++++++++++++++------ services/io/get_save_data.c | 15 +-------------- services/io/io.h | 3 +-- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/services/elph/elph_driver.c b/services/elph/elph_driver.c index dfa1d210..0adae188 100644 --- a/services/elph/elph_driver.c +++ b/services/elph/elph_driver.c @@ -74,10 +74,18 @@ void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, struct WFC* wfcs; // read the SAVE data and phonon related data. + if (dft_code == DFT_CODE_QE) + { + get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, + mpi_comms); + } + else + { + error_msg("Only QE supported"); + } read_and_alloc_save_data(input_data->save_dir, mpi_comms, input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon, - dft_code); + input_data->ph_save_dir, lattice, pseudo, phonon); // print info about lattice and phonons print_lattice_info(mpi_comms, lattice); @@ -421,10 +429,18 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, struct WFC* wfcs; + if (dft_code == DFT_CODE_QE) + { + get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, + mpi_comms); + } + else + { + error_msg("Only QE supported"); + } read_and_alloc_save_data(input_data->save_dir, mpi_comms, input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon, - dft_code); + input_data->ph_save_dir, lattice, pseudo, phonon); print_lattice_info(mpi_comms, lattice); print_phonon_info(mpi_comms, phonon); @@ -606,10 +622,18 @@ void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, struct WFC* wfcs; + if (dft_code == DFT_CODE_QE) + { + get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, + mpi_comms); + } + else + { + error_msg("Only QE supported"); + } read_and_alloc_save_data(input_data->save_dir, mpi_comms, input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon, - dft_code); + input_data->ph_save_dir, lattice, pseudo, phonon); print_lattice_info(mpi_comms, lattice); print_phonon_info(mpi_comms, phonon); diff --git a/services/io/get_save_data.c b/services/io/get_save_data.c index 699b8554..94dab8bd 100644 --- a/services/io/get_save_data.c +++ b/services/io/get_save_data.c @@ -22,7 +22,6 @@ #include "dvloc/dvloc.h" #include "elphC.h" #include "io.h" -#include "io/qe/qe_io.h" #include "mpi_bcast.h" #include "nonloc/fcoeff.h" #include "symmetries/symmetries.h" @@ -54,8 +53,7 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, ND_int start_band, ND_int end_band, struct WFC** wfcs, char* ph_save_dir, struct Lattice* lattice, struct Pseudo* pseudo, - struct Phonon* phonon, - enum ELPH_dft_code dft_code) + struct Phonon* phonon) { /* This function allocates and reads data from SAVE dir. The following data is read : wfcs(in iBZ), lattice and pseudo @@ -75,18 +73,7 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, int mpi_error; - // first get the basic dft/dfpt data from dft code (code specific) before - // anything char* pp_head = "ns.kb_pp_pwscf"; // Change this accordingly - if (dft_code == DFT_CODE_QE) - { - // char* pp_head = "ns.kb_pp_pwscf"; - get_data_from_qe(lattice, phonon, pseudo, ph_save_dir, NULL, Comm); - } - else - { - error_msg("Only QE supported"); - } lattice->nfftz_loc = get_mpi_local_size_idx( lattice->fft_dims[2], &(lattice->nfftz_loc_shift), Comm->commK); diff --git a/services/io/io.h b/services/io/io.h index 0214d72b..f6185e35 100644 --- a/services/io/io.h +++ b/services/io/io.h @@ -15,8 +15,7 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, ND_int start_band, ND_int end_band, struct WFC** wfcs, char* ph_save_dir, struct Lattice* lattice, struct Pseudo* pseudo, - struct Phonon* phonon, - enum ELPH_dft_code dft_code); + struct Phonon* phonon); void free_save_data(struct WFC* wfcs, struct Lattice* lattice, struct Pseudo* pseudo, struct Phonon* phonon); From e48989c472772ea84915e5305b92b9f2d8802e66 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Thu, 28 May 2026 08:44:55 +0200 Subject: [PATCH 18/46] update lib order --- compile/libraries.mk | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/compile/libraries.mk b/compile/libraries.mk index 70af37c9..c58c16ca 100644 --- a/compile/libraries.mk +++ b/compile/libraries.mk @@ -16,21 +16,23 @@ endif # T5 drivers : interpolation, elph # T4 QE I/O : io/qe # T3 main I/O : io -# T2 kernels+pp : dvloc, nonloc, symmetries, preprocessor -# T1 primitives : wfc, fft, phonon, parser -# T0 base+vendors : common, common/cwalk, common/ELPH_hash_map, common/kdtree, -# io/ezxml, parser/inih +# T2 kernels+pp : dvloc, symmetries, nonloc, preprocessor +# T1 primitives : fft, parser, phonon, wfc +# T0 base+vendors : common, common/kdtree, io/ezxml, common/ELPH_hash_map, +# parser/inih, common/cwalk # # elph (T5) hosts the Fortran-to-C ABI boundary (ep_f2c_bridge.c): # elph_driver_f2c / elph_driver_cb_f2c / elph_driver_cb2_f2c # These are the ONLY entry points yambo_ep calls into LetzElPhC. # -EP_S1= [Sletz,interpolation] -EP_S2= [Sletz,io/qe] [Sletz,common/ELPH_hash_map] [Sletz,common] [Sletz,symmetries] [Sletz,nonloc] -EP_S3= [Sletz,dvloc] [Sletz,io] [Sletz,io/ezxml] -EP_S4= [Sletz,wfc] [Sletz,fft] [Sletz,dvloc] [Sletz,common/cwalk] [Sletz,preprocessor] -EP_S5= [Sletz,phonon] [Sletz,parser/inih] [Sletz,parser] -EP_S6= [Sletz,common/kdtree] [Sletz,elph] +# Order generated by check_dep.py topological sort (most-dependent first). +# +EP_S1= [Sletz,interpolation] [Sletz,elph] +EP_S2= [Sletz,io/qe] +EP_S3= [Sletz,io] +EP_S4= [Sletz,dvloc] [Sletz,symmetries] [Sletz,nonloc] [Sletz,preprocessor] +EP_S5= [Sletz,fft] [Sletz,parser] [Sletz,phonon] [Sletz,wfc] +EP_S6= [Sletz,common] [Sletz,common/kdtree] [Sletz,io/ezxml] [Sletz,common/ELPH_hash_map] [Sletz,parser/inih] [Sletz,common/cwalk] # ifneq (,$(filter yambo_ep ypp_ep,$(MAKECMDGOALS))) SERVICES_LIBS += ${EP_S1} ${EP_S2} ${EP_S3} ${EP_S4} ${EP_S5} ${EP_S6} From 863c1126f64435b0ec2ce818e8947de0b9bd434c Mon Sep 17 00:00:00 2001 From: marini Date: Fri, 29 May 2026 11:24:35 +0200 Subject: [PATCH 19/46] MODIFIED * compile/libraries.mk Patch sent by: marini --- compile/libraries.mk | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compile/libraries.mk b/compile/libraries.mk index c58c16ca..6361cec5 100644 --- a/compile/libraries.mk +++ b/compile/libraries.mk @@ -27,12 +27,12 @@ endif # # Order generated by check_dep.py topological sort (most-dependent first). # -EP_S1= [Sletz,interpolation] [Sletz,elph] -EP_S2= [Sletz,io/qe] -EP_S3= [Sletz,io] -EP_S4= [Sletz,dvloc] [Sletz,symmetries] [Sletz,nonloc] [Sletz,preprocessor] -EP_S5= [Sletz,fft] [Sletz,parser] [Sletz,phonon] [Sletz,wfc] -EP_S6= [Sletz,common] [Sletz,common/kdtree] [Sletz,io/ezxml] [Sletz,common/ELPH_hash_map] [Sletz,parser/inih] [Sletz,common/cwalk] +EP_S1= [Sletz,interpolation] +EP_S2= [Sletz,io/qe] [Sletz,common/ELPH_hash_map] [Sletz,common] [Sletz,symmetries] [Sletz,nonloc] +EP_S3= [Sletz,dvloc] [Sletz,io] [Sletz,io/ezxml] +EP_S4= [Sletz,wfc] [Sletz,fft] [Sletz,dvloc] [Sletz,common/cwalk] [Sletz,preprocessor] +EP_S5= [Sletz,phonon] [Sletz,parser/inih] [Sletz,parser] +EP_S6= [Sletz,common/kdtree] [Sletz,elph] # ifneq (,$(filter yambo_ep ypp_ep,$(MAKECMDGOALS))) SERVICES_LIBS += ${EP_S1} ${EP_S2} ${EP_S3} ${EP_S4} ${EP_S5} ${EP_S6} From 31f8ea17d1f8c9f0c89a295fd1e77175183a1ab8 Mon Sep 17 00:00:00 2001 From: marini Date: Fri, 29 May 2026 13:03:47 +0200 Subject: [PATCH 20/46] MODIFIED * compile/libraries.mk Patch sent by: marini --- compile/libraries.mk | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compile/libraries.mk b/compile/libraries.mk index 6361cec5..3e5115dd 100644 --- a/compile/libraries.mk +++ b/compile/libraries.mk @@ -13,12 +13,12 @@ endif # Static linker is left-to-right: symbol-users before symbol-providers. # # Dependency tiers (each tier depends only on equal/lower tiers): -# T5 drivers : interpolation, elph -# T4 QE I/O : io/qe -# T3 main I/O : io -# T2 kernels+pp : dvloc, symmetries, nonloc, preprocessor -# T1 primitives : fft, parser, phonon, wfc -# T0 base+vendors : common, common/kdtree, io/ezxml, common/ELPH_hash_map, +# T6 drivers : interpolation, elph +# T5 QE I/O : io/qe +# T4 main I/O : io +# T3 kernels+pp : dvloc, symmetries, nonloc, preprocessor +# T2 primitives : fft, parser, phonon, wfc +# T1 base+vendors : common, common/kdtree, io/ezxml, common/ELPH_hash_map, # parser/inih, common/cwalk # # elph (T5) hosts the Fortran-to-C ABI boundary (ep_f2c_bridge.c): @@ -31,7 +31,7 @@ EP_S1= [Sletz,interpolation] EP_S2= [Sletz,io/qe] [Sletz,common/ELPH_hash_map] [Sletz,common] [Sletz,symmetries] [Sletz,nonloc] EP_S3= [Sletz,dvloc] [Sletz,io] [Sletz,io/ezxml] EP_S4= [Sletz,wfc] [Sletz,fft] [Sletz,dvloc] [Sletz,common/cwalk] [Sletz,preprocessor] -EP_S5= [Sletz,phonon] [Sletz,parser/inih] [Sletz,parser] +EP_S5= [Sletz,phonon] [Sletz,parser/inih] [Sletz,parser] EP_S6= [Sletz,common/kdtree] [Sletz,elph] # ifneq (,$(filter yambo_ep ypp_ep,$(MAKECMDGOALS))) From bb6189db4840e836af2661abbf983e63cb418b88 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Fri, 29 May 2026 14:46:56 +0200 Subject: [PATCH 21/46] allow write file in y6 --- services/common/print_info.c | 13 +++++++++--- services/common/print_info.h | 3 +++ services/elph/elph_driver.c | 6 +++--- services/elph/ep_f2c_bridge.c | 37 ++++++++++++++++++++++++++++++++--- 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/services/common/print_info.c b/services/common/print_info.c index bfdd0549..8e825a32 100644 --- a/services/common/print_info.c +++ b/services/common/print_info.c @@ -12,18 +12,25 @@ #include "dtypes.h" +static FILE* elph_log_fp = NULL; + +void elph_set_log_file(FILE* fp) { elph_log_fp = fp; } + +FILE* elph_get_log_file(void) { return elph_log_fp ? elph_log_fp : stdout; } + void print_info_msg(int mpi_rank, const char* fmt, ...) { if (mpi_rank) { return; } + FILE* out = elph_get_log_file(); va_list args; va_start(args, fmt); - vfprintf(stdout, fmt, args); + vfprintf(out, fmt, args); va_end(args); - fprintf(stdout, "\n"); - fflush(stdout); + fprintf(out, "\n"); + fflush(out); } void print_input_info(const char* save_dir, const char* ph_save_dir, diff --git a/services/common/print_info.h b/services/common/print_info.h index 85a25b24..804aaae6 100644 --- a/services/common/print_info.h +++ b/services/common/print_info.h @@ -8,6 +8,9 @@ void print_ELPH_logo(int mpi_rank, FILE* output); void print_info_msg(int mpi_rank, const char* fmt, ...); +void elph_set_log_file(FILE* fp); +FILE* elph_get_log_file(void); + void print_input_info(const char* save_dir, const char* ph_save_dir, const char* kernel, const bool kminusq, const enum ELPH_dft_code dft_code, diff --git a/services/elph/elph_driver.c b/services/elph/elph_driver.c index 0adae188..d1e3373e 100644 --- a/services/elph/elph_driver.c +++ b/services/elph/elph_driver.c @@ -52,7 +52,7 @@ void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, mpi_comms); // print logo and stated message - print_ELPH_logo(mpi_comms->commW_rank, stdout); + print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); print_info_msg(mpi_comms->commW_rank, "********** Program started **********"); print_input_info(input_data->save_dir, input_data->ph_save_dir, @@ -408,7 +408,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, mpi_comms); - print_ELPH_logo(mpi_comms->commW_rank, stdout); + print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); print_info_msg(mpi_comms->commW_rank, "********** Program started **********"); print_input_info(input_data->save_dir, input_data->ph_save_dir, @@ -601,7 +601,7 @@ void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, mpi_comms); - print_ELPH_logo(mpi_comms->commW_rank, stdout); + print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); print_info_msg(mpi_comms->commW_rank, "********** Program started **********"); print_input_info(input_data->save_dir, input_data->ph_save_dir, diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index 7861fb90..219b5e95 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -11,12 +11,38 @@ */ #include "elph.h" /* already pulls in common/dtypes.h and elphC.h */ +#include "common/print_info.h" #include +#include -void elph_driver_f2c(const char* input_file, int dft_code, MPI_Fint f_comm) +static void open_letz_log(MPI_Comm comm, const char* log_path) +{ + int rank; + MPI_Comm_rank(comm, &rank); + if (rank == 0 && log_path != NULL && log_path[0] != '\0') + { + FILE* fp = fopen(log_path, "w"); + if (fp) elph_set_log_file(fp); + } +} + +static void close_letz_log(void) +{ + FILE* fp = elph_get_log_file(); + if (fp != NULL) + { + fclose(fp); + elph_set_log_file(NULL); + } +} + +void elph_driver_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, + const char* log_path) { MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + open_letz_log(c_comm, log_path); elph_driver(input_file, (enum ELPH_dft_code)dft_code, c_comm); + close_letz_log(); } /* @@ -24,11 +50,13 @@ void elph_driver_f2c(const char* input_file, int dft_code, MPI_Fint f_comm) * (passed as a C function pointer via ISO_C_BINDING's c_funloc). */ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, - void* fill_fn_ptr) + void* fill_fn_ptr, const char* log_path) { MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + open_letz_log(c_comm, log_path); elph_driver_cb(input_file, (enum ELPH_dft_code)dft_code, c_comm, (elph_fill_fn)fill_fn_ptr); + close_letz_log(); } /* @@ -36,10 +64,13 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, * Either pointer may be NULL (pass c_null_funptr from Fortran) to skip that output. */ void elph_driver_cb2_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, - void* fill_fn_ptr, void* dvG_fill_fn_ptr) + void* fill_fn_ptr, void* dvG_fill_fn_ptr, + const char* log_path) { MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + open_letz_log(c_comm, log_path); elph_driver_cb2(input_file, (enum ELPH_dft_code)dft_code, c_comm, (elph_fill_fn)fill_fn_ptr, (elph_dvG_fill_fn)dvG_fill_fn_ptr); + close_letz_log(); } From 59111850fca940468dd72b30bd8a3a21ae722e58 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Fri, 29 May 2026 21:01:56 +0200 Subject: [PATCH 22/46] trick to avoid writing to stdout --- services/elph/ep_f2c_bridge.c | 42 ++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index 219b5e95..0ebbc3a2 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -8,12 +8,24 @@ * Thin bridge: called from Fortran via ISO_C_BINDING. * Converts a Fortran MPI communicator handle (MPI_Fint) to a C MPI_Comm * and forwards the call to LetzElPhC's elph_driver(). + * */ #include "elph.h" /* already pulls in common/dtypes.h and elphC.h */ #include "common/print_info.h" #include #include +#include +#include + +/* Fortran bind(C) callbacks — linked from the ep packages library. */ +extern void elph_coll_fill_gkkp(int, int, const void*, int, int, int, int, int, int, int, const void*); +extern void elph_coll_fill_dvg(int, const void*, const void*, int, int, int, int, int, int); + +/* + * Redirect stdout to the log file for the duration of the LetzElPhC call. + */ +static int saved_stdout_fd = -1; static void open_letz_log(MPI_Comm comm, const char* log_path) { @@ -22,7 +34,13 @@ static void open_letz_log(MPI_Comm comm, const char* log_path) if (rank == 0 && log_path != NULL && log_path[0] != '\0') { FILE* fp = fopen(log_path, "w"); - if (fp) elph_set_log_file(fp); + if (fp) + { + elph_set_log_file(fp); + fflush(stdout); + saved_stdout_fd = dup(STDOUT_FILENO); + dup2(fileno(fp), STDOUT_FILENO); + } } } @@ -31,6 +49,13 @@ static void close_letz_log(void) FILE* fp = elph_get_log_file(); if (fp != NULL) { + fflush(fp); + if (saved_stdout_fd >= 0) + { + dup2(saved_stdout_fd, STDOUT_FILENO); + close(saved_stdout_fd); + saved_stdout_fd = -1; + } fclose(fp); elph_set_log_file(NULL); } @@ -46,8 +71,8 @@ void elph_driver_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, } /* - * Callback-enabled bridge: fill_fn_ptr is a Fortran procedure pointer - * (passed as a C function pointer via ISO_C_BINDING's c_funloc). + * Callback-enabled bridge: fill_fn_ptr argument is kept for API compatibility + * but ignored — elph_coll_fill_gkkp is resolved directly by the linker. */ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, void* fill_fn_ptr, const char* log_path) @@ -55,13 +80,14 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, MPI_Comm c_comm = MPI_Comm_f2c(f_comm); open_letz_log(c_comm, log_path); elph_driver_cb(input_file, (enum ELPH_dft_code)dft_code, c_comm, - (elph_fill_fn)fill_fn_ptr); + (elph_fill_fn)elph_coll_fill_gkkp); close_letz_log(); } /* - * Extended callback bridge: gkkp fill_fn + dvG fill callback. - * Either pointer may be NULL (pass c_null_funptr from Fortran) to skip that output. + * Extended callback bridge: fill_fn_ptr and dvG_fill_fn_ptr are kept for API + * compatibility but ignored — callbacks resolved directly by the linker to + * avoid the arm64 gfortran procedure-descriptor segfault. */ void elph_driver_cb2_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, void* fill_fn_ptr, void* dvG_fill_fn_ptr, @@ -70,7 +96,7 @@ void elph_driver_cb2_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, MPI_Comm c_comm = MPI_Comm_f2c(f_comm); open_letz_log(c_comm, log_path); elph_driver_cb2(input_file, (enum ELPH_dft_code)dft_code, c_comm, - (elph_fill_fn)fill_fn_ptr, - (elph_dvG_fill_fn)dvG_fill_fn_ptr); + (elph_fill_fn)elph_coll_fill_gkkp, + (elph_dvG_fill_fn)elph_coll_fill_dvg); close_letz_log(); } From 70dc17b389a080916b3ff21cf80129f153c5f286 Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Thu, 11 Jun 2026 13:55:57 +0200 Subject: [PATCH 23/46] MODIFIED * services/elph/elph_driver.c services/io/qe/get_dvscf_dyn_qe.c services/main_elphC.c services/preprocessor/pp_ph_save.c services/preprocessor/preprocessor.h Changes: - Making letz able to read PH from a different directory Patch sent by: Andrea Marini --- services/elph/elph_driver.c | 16 +++++++--- services/io/qe/get_dvscf_dyn_qe.c | 2 +- services/main_elphC.c | 2 +- services/preprocessor/pp_ph_save.c | 45 ++++++++++++++++++---------- services/preprocessor/preprocessor.h | 2 +- 5 files changed, 44 insertions(+), 23 deletions(-) diff --git a/services/elph/elph_driver.c b/services/elph/elph_driver.c index d1e3373e..babfd0a6 100644 --- a/services/elph/elph_driver.c +++ b/services/elph/elph_driver.c @@ -25,6 +25,7 @@ THe starting point for the entire code #include "io/qe/qe_io.h" #include "parser/parser.h" #include "symmetries/symmetries.h" +#include "common/string_func.h" void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, MPI_Comm comm_world) @@ -441,6 +442,9 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, read_and_alloc_save_data(input_data->save_dir, mpi_comms, input_data->start_bnd, input_data->end_bnd, &wfcs, input_data->ph_save_dir, lattice, pseudo, phonon); + char DM_name[100]; + strlcpy_custom(DM_name, input_data->ph_save_dir,100); + strlcat(DM_name,"/ndb.Dmats", 100); print_lattice_info(mpi_comms, lattice); print_phonon_info(mpi_comms, phonon); @@ -448,7 +452,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, print_info_msg(mpi_comms->commW_rank, ""); print_info_msg(mpi_comms->commW_rank, "=== Computing Dmats for phonon symmetries ==="); - compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, + compute_and_write_dmats(DM_name, wfcs, lattice, phonon->nph_sym, phonon->ph_syms, mpi_comms); ND_int nmodes = lattice->nmodes; @@ -470,7 +474,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, if (mpi_comms->commK_rank == 0) { - if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, + if ((nc_err = nc_open_par(DM_name, NC_NOWRITE, mpi_comms->commR, MPI_INFO_NULL, &ncid_dmat))) { ERR(nc_err); @@ -635,13 +639,17 @@ void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, input_data->start_bnd, input_data->end_bnd, &wfcs, input_data->ph_save_dir, lattice, pseudo, phonon); + char DM_name[100]; + strlcpy_custom(DM_name, input_data->ph_save_dir,100); + strlcat(DM_name,"/ndb.Dmats", 100); + print_lattice_info(mpi_comms, lattice); print_phonon_info(mpi_comms, phonon); print_info_msg(mpi_comms->commW_rank, ""); print_info_msg(mpi_comms->commW_rank, "=== Computing Dmats for phonon symmetries ==="); - compute_and_write_dmats("ndb.Dmats", wfcs, lattice, phonon->nph_sym, + compute_and_write_dmats(DM_name, wfcs, lattice, phonon->nph_sym, phonon->ph_syms, mpi_comms); ND_int nmodes = lattice->nmodes; @@ -663,7 +671,7 @@ void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, if (mpi_comms->commK_rank == 0) { - if ((nc_err = nc_open_par("ndb.Dmats", NC_NOWRITE, mpi_comms->commR, + if ((nc_err = nc_open_par(DM_name, NC_NOWRITE, mpi_comms->commR, MPI_INFO_NULL, &ncid_dmat))) { ERR(nc_err); diff --git a/services/io/qe/get_dvscf_dyn_qe.c b/services/io/qe/get_dvscf_dyn_qe.c index ec3776f9..1d6c8bfc 100644 --- a/services/io/qe/get_dvscf_dyn_qe.c +++ b/services/io/qe/get_dvscf_dyn_qe.c @@ -34,7 +34,7 @@ void get_dvscf_dyn_qe(const char* ph_save_dir, struct Lattice* lattice, pat_vecs = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); CHECK_ALLOC(pat_vecs); } - + // Note : It is very important to note that we must read eigenvectors by a // single cpu and then broadcast to all others. This is because // small numerical accuracies can lead different diff --git a/services/main_elphC.c b/services/main_elphC.c index 27f4fbf2..ab6186ec 100644 --- a/services/main_elphC.c +++ b/services/main_elphC.c @@ -76,7 +76,7 @@ int main(int argc, char* argv[]) { if (calc_info->code == DFT_CODE_QE) { - create_ph_save_dir_pp_qe(calc_info->input_file); + create_ph_save_dir_pp_qe(calc_info->input_file,calc_info->ph_save_dir); } } } diff --git a/services/preprocessor/pp_ph_save.c b/services/preprocessor/pp_ph_save.c index 6aa2a35e..5a4b87a0 100644 --- a/services/preprocessor/pp_ph_save.c +++ b/services/preprocessor/pp_ph_save.c @@ -21,15 +21,16 @@ This file contains functions which are os dependent. static ND_int find_nqpools(const char* out_dir, char* buffer_tmp, ND_int buffer_size); -void create_ph_save_dir_pp_qe(const char* inp_file) +void create_ph_save_dir_pp_qe(const char* inp_file,const char* ph_path ) { // parse the input file // open the qe ph.x input file char PH_SAVE_DIR_NAME[ELPH_MAX_ENV_SIZE]; - // check if env exits for ph_save char* env_var_tmp = getenv("ELPH_PH_SAVE_DIR"); +/* + // check if env exits for ph_save if (env_var_tmp && strlen(env_var_tmp) > 0) { if (strlen(env_var_tmp) > (ELPH_MAX_ENV_SIZE - 1)) @@ -46,6 +47,15 @@ void create_ph_save_dir_pp_qe(const char* inp_file) strlcpy_custom(PH_SAVE_DIR_NAME, PH_SAVE_DIR_NAME_DEFAULT, ELPH_MAX_ENV_SIZE); } +*/ + + strlcpy_custom(PH_SAVE_DIR_NAME, ph_path,ELPH_MAX_ENV_SIZE); + strlcat(PH_SAVE_DIR_NAME, "/", ELPH_MAX_ENV_SIZE); + strlcat(PH_SAVE_DIR_NAME, PH_SAVE_DIR_NAME_DEFAULT, ELPH_MAX_ENV_SIZE); + + char ph_workdir_tmp[ELPH_MAX_ENV_SIZE]; + strlcpy_custom(ph_workdir_tmp, ph_path,ELPH_MAX_ENV_SIZE); + // FILE* fp = fopen(inp_file, "r"); if (fp == NULL) @@ -85,6 +95,8 @@ void create_ph_save_dir_pp_qe(const char* inp_file) { strcpy(out_dir, "./"); } + strlcat(ph_workdir_tmp,"/",ELPH_MAX_ENV_SIZE); + strlcat(ph_workdir_tmp,out_dir,ELPH_MAX_ENV_SIZE); strcpy(dyn_prefix, "matdyn"); strcpy(dvscf_prefix, ""); @@ -281,6 +293,7 @@ void create_ph_save_dir_pp_qe(const char* inp_file) // from now we use read buffer as file_name_buf // now create the ph_save directory + if (ELPH_mkdir(PH_SAVE_DIR_NAME)) { if (errno != EEXIST) @@ -356,7 +369,7 @@ void create_ph_save_dir_pp_qe(const char* inp_file) // 3) copy dyn files - snprintf(src_file_tmp, PH_X_INP_READ_BUF_SIZE, "%s0", dyn_prefix); + snprintf(src_file_tmp, PH_X_INP_READ_BUF_SIZE, "%s/%s0",ph_path,dyn_prefix); // first copy the dyn0 file cwk_path_join_multiple((const char*[]){PH_SAVE_DIR_NAME, "dyn0", NULL}, dest_file_tmp, PH_X_INP_READ_BUF_SIZE); @@ -396,13 +409,11 @@ void create_ph_save_dir_pp_qe(const char* inp_file) { if (xml_dyn_prefix) { - snprintf(src_file_tmp, PH_X_INP_READ_BUF_SIZE, "%s%d.xml", - dyn_prefix, idyn + 1); + snprintf(src_file_tmp, PH_X_INP_READ_BUF_SIZE, "%s/%s%d.xml",ph_path,dyn_prefix, idyn + 1); } else { - snprintf(src_file_tmp, PH_X_INP_READ_BUF_SIZE, "%s%d", dyn_prefix, - idyn + 1); + snprintf(src_file_tmp, PH_X_INP_READ_BUF_SIZE, "%s/%s%d", ph_path, dyn_prefix,idyn + 1); } char dyn_tmp_str[32]; @@ -419,8 +430,7 @@ void create_ph_save_dir_pp_qe(const char* inp_file) } // Find the number of qpools used in ph.x calculation - ND_int ph_x_qpools = - find_nqpools(out_dir, tmp_file_buf, PH_X_INP_READ_BUF_SIZE); + ND_int ph_x_qpools = find_nqpools(ph_workdir_tmp, tmp_file_buf, PH_X_INP_READ_BUF_SIZE); // 3) copy dvscf files for (int idyn = 0; idyn < ndyn; ++idyn) @@ -450,7 +460,7 @@ void create_ph_save_dir_pp_qe(const char* inp_file) scf_prefix, dvscf_prefix, dvscf_tmp_str); cwk_path_join_multiple( - (const char*[]){out_dir, ph0_tmp, dest_file_tmp, + (const char*[]){ph_path,out_dir, ph0_tmp, dest_file_tmp, tmp_file_buf, NULL}, src_file_tmp, PH_X_INP_READ_BUF_SIZE); } @@ -460,7 +470,7 @@ void create_ph_save_dir_pp_qe(const char* inp_file) scf_prefix, dvscf_prefix, dvscf_tmp_str); cwk_path_join_multiple( - (const char*[]){out_dir, ph0_tmp, tmp_file_buf, NULL}, + (const char*[]){ph_path,out_dir, ph0_tmp, tmp_file_buf, NULL}, src_file_tmp, PH_X_INP_READ_BUF_SIZE); } @@ -472,9 +482,9 @@ void create_ph_save_dir_pp_qe(const char* inp_file) (const char*[]){PH_SAVE_DIR_NAME, tmp_file_buf, NULL}, dest_file_tmp, PH_X_INP_READ_BUF_SIZE); - if (0 == copy_files(src_file_tmp, dest_file_tmp)) + if (0 != copy_files(src_file_tmp, dest_file_tmp)) { - break; + printf("Warning : Error copying file %s.\n", src_file_tmp); } } } @@ -487,14 +497,17 @@ void create_ph_save_dir_pp_qe(const char* inp_file) { char dyn_tmp_str[32]; - snprintf(dest_file_tmp, PH_X_INP_READ_BUF_SIZE, "%s.phsave", - scf_prefix); + snprintf(src_file_tmp, PH_X_INP_READ_BUF_SIZE, "%s/%s/_ph0/%s.phsave",ph_path,out_dir,scf_prefix); snprintf(dyn_tmp_str, 32, "patterns.%d.xml", idyn + 1); + strlcat(src_file_tmp,"/",PH_X_INP_READ_BUF_SIZE); + strlcat(src_file_tmp,dyn_tmp_str,PH_X_INP_READ_BUF_SIZE); +/* cwk_path_join_multiple( (const char*[]){out_dir, "_ph0", dest_file_tmp, dyn_tmp_str, NULL}, src_file_tmp, PH_X_INP_READ_BUF_SIZE); +*/ cwk_path_join_multiple( (const char*[]){PH_SAVE_DIR_NAME, dyn_tmp_str, NULL}, dest_file_tmp, PH_X_INP_READ_BUF_SIZE); @@ -509,7 +522,7 @@ void create_ph_save_dir_pp_qe(const char* inp_file) snprintf(dest_file_tmp, PH_X_INP_READ_BUF_SIZE, "%s.phsave", scf_prefix); cwk_path_join_multiple( - (const char*[]){out_dir, "_ph0", dest_file_tmp, "tensors.xml", NULL}, + (const char*[]){ph_path,out_dir, "_ph0", dest_file_tmp, "tensors.xml", NULL}, src_file_tmp, PH_X_INP_READ_BUF_SIZE); cwk_path_join_multiple( diff --git a/services/preprocessor/preprocessor.h b/services/preprocessor/preprocessor.h index ea2adc0f..8d4302be 100644 --- a/services/preprocessor/preprocessor.h +++ b/services/preprocessor/preprocessor.h @@ -9,7 +9,7 @@ void ELPH_cli_parser(int argc, char* argv[], struct calc_details* calc_info); -void create_ph_save_dir_pp_qe(const char* inp_file); +void create_ph_save_dir_pp_qe(const char* inp_file,const char* ph_path); void ELPH_print_version(void); void ELPH_print_help(void); From 8b791a9971e9276d49ff2f0f265a2d617f470703 Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Thu, 11 Jun 2026 18:00:13 +0200 Subject: [PATCH 24/46] MODIFIED * compile/compile_me.mk services/elph/.objects services/elph/elph_driver.c services/io/get_save_data.c services/main_elphC.c services/parser/parser.h services/preprocessor/pp_ph_save.c services/preprocessor/preprocessor.h NEW * services/elph/elph_driver_cb.c services/elph/elph_driver_cb2.c Additions: - Adde _Y6_LETZ pre-compilation flag to perform Yambo specific operations Changes: - Yambo-specific drivers created Patch sent by: Andrea Marini --- compile/compile_me.mk | 8 +- services/elph/.objects | 3 +- services/elph/elph_driver.c | 411 --------------------------- services/elph/elph_driver_cb.c | 226 +++++++++++++++ services/elph/elph_driver_cb2.c | 243 ++++++++++++++++ services/io/get_save_data.c | 4 + services/main_elphC.c | 2 +- services/parser/parser.h | 4 +- services/preprocessor/pp_ph_save.c | 13 +- services/preprocessor/preprocessor.h | 6 +- 10 files changed, 497 insertions(+), 423 deletions(-) create mode 100644 services/elph/elph_driver_cb.c create mode 100644 services/elph/elph_driver_cb2.c diff --git a/compile/compile_me.mk b/compile/compile_me.mk index 8e75d98b..d209e66a 100644 --- a/compile/compile_me.mk +++ b/compile/compile_me.mk @@ -3,10 +3,12 @@ # # Copyright (C) 2025 The Yambo Team # -# Authors (see AUTHORS file for details): AM MN +# Authors (see AUTHORS file for details): MN # -# -# Co-Authors (see AUTHORS file for details): RR +# Co-Authors (see AUTHORS file for details): RR AM # LetzElPhC ep plugin - yambo build system stub # Integration handled via SERVICES_LIBS in libraries.mk # +ifneq (,$(findstring yambo_ep,$(MAKECMDGOALS))) + Y_PRECMP= -D_Y6_LETZ +endif diff --git a/services/elph/.objects b/services/elph/.objects index 5d4205ff..6eadfd85 100644 --- a/services/elph/.objects +++ b/services/elph/.objects @@ -1 +1,2 @@ -objs = set_kernel.o elph_driver.o compute_elph_matq.o compute_dmats.o ep_f2c_bridge.o dvG_utils.o +objs = elph_driver_cb.o set_kernel.o elph_driver.o ep_f2c_bridge.o dvG_utils.o compute_elph_matq.o compute_dmats.o \ + elph_driver_cb2.o diff --git a/services/elph/elph_driver.c b/services/elph/elph_driver.c index babfd0a6..fb82cac8 100644 --- a/services/elph/elph_driver.c +++ b/services/elph/elph_driver.c @@ -384,414 +384,3 @@ void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, // done with the calculation print_info_msg(World_rank_tmp, "********** Program ended **********"); } - -/* - * Callback-enabled driver: identical flow to elph_driver but writes gkkp - * data via fill_fn(iq_BZ, ik_BZ, data, ...) instead of ndb.elph. - * ndb.Dmats is still created and used internally for BZ symmetry expansion. - * Eigenvectors / frequencies are NOT written (yambo reads them elsewhere). - */ -void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn fill_fn) -{ - struct elph_usr_input* input_data; - init_ELPH_clocks(); - - read_elph_input_file(ELPH_input_file, &input_data, comm_world); - - struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); - init_kernel(kernel); - set_kernel(input_data->kernel_str, kernel); - - struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); - CHECK_ALLOC(mpi_comms); - - create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, - mpi_comms); - - print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); - print_info_msg(mpi_comms->commW_rank, - "********** Program started **********"); - print_input_info(input_data->save_dir, input_data->ph_save_dir, - input_data->kernel_str, input_data->kminusq, dft_code, - mpi_comms); - - struct Lattice* lattice = malloc(sizeof(struct Lattice)); - CHECK_ALLOC(lattice); - init_lattice_type(lattice); - - struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); - CHECK_ALLOC(pseudo); - init_Pseudo_type(pseudo); - - struct Phonon* phonon = malloc(sizeof(struct Phonon)); - CHECK_ALLOC(phonon); - init_phonon_type(phonon); - - struct WFC* wfcs; - - if (dft_code == DFT_CODE_QE) - { - get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, - mpi_comms); - } - else - { - error_msg("Only QE supported"); - } - read_and_alloc_save_data(input_data->save_dir, mpi_comms, - input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon); - char DM_name[100]; - strlcpy_custom(DM_name, input_data->ph_save_dir,100); - strlcat(DM_name,"/ndb.Dmats", 100); - - print_lattice_info(mpi_comms, lattice); - print_phonon_info(mpi_comms, phonon); - - print_info_msg(mpi_comms->commW_rank, ""); - print_info_msg(mpi_comms->commW_rank, - "=== Computing Dmats for phonon symmetries ==="); - compute_and_write_dmats(DM_name, wfcs, lattice, phonon->nph_sym, - phonon->ph_syms, mpi_comms); - - ND_int nmodes = lattice->nmodes; - ND_int nfft_loc = - lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; - - ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); - CHECK_ALLOC(eigVec); - - ELPH_cmplx* dVscf = - malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); - CHECK_ALLOC(dVscf); - - ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); - CHECK_ALLOC(omega_ph); - - int ncid_dmat, nc_err; - int varid_dmat; - - if (mpi_comms->commK_rank == 0) - { - if ((nc_err = nc_open_par(DM_name, NC_NOWRITE, mpi_comms->commR, - MPI_INFO_NULL, &ncid_dmat))) - { - ERR(nc_err); - } - - if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) - { - ERR(nc_err); - } - - size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; - if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, - Dmat_counts, NULL))) - { - ERR(nc_err); - } - } - - print_info_msg(mpi_comms->commW_rank, - "=== Computing Electron-phonon matrix elements ==="); - print_info_msg(mpi_comms->commW_rank, ""); - - for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) - { - print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", - (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); - - ND_int iqpt_iBZg = iqpt + phonon->nq_shift; - - if (dft_code == DFT_CODE_QE) - { - ELPH_cmplx* dvscf_read = NULL; - if (kernel->screening == ELPH_DFPT_SCREENING) - { - dvscf_read = dVscf; - } - else - { - ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; - for (ND_int ix = 0; ix < dvscf_num; ++ix) - { - dVscf[ix] = 0.0; - } - } - get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, - eigVec, dvscf_read, omega_ph, mpi_comms); - } - else - { - error_msg("Currently only quantum espresso supported"); - } - - ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); - CHECK_ALLOC(Vlocr); - dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, - mpi_comms->commK); - - if (dft_code == DFT_CODE_QE) - { - add_dvscf_qe(dVscf, Vlocr, lattice); - } - else - { - error_msg("Currently only quantum espresso supported"); - } - free(Vlocr); - - compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, - eigVec, dVscf, 0, 0, ncid_dmat, - varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, fill_fn, - iqpt_iBZg); - } - - if (mpi_comms->commK_rank == 0) - { - if ((nc_err = nc_close(ncid_dmat))) - { - ERR(nc_err); - } - } - - free(omega_ph); - free(eigVec); - free(dVscf); - - int World_rank_tmp = mpi_comms->commW_rank; - - free(kernel); - free_elph_usr_input(input_data); - free_save_data(wfcs, lattice, pseudo, phonon); - free(lattice); - free(pseudo); - free(phonon); - free_parallel_comms(mpi_comms); - free(mpi_comms); - fftw_fun(cleanup)(); - - if (0 == World_rank_tmp) - { - print_ELPH_clock_summary(); - } - cleanup_ELPH_clocks(); - print_info_msg(World_rank_tmp, "********** Program ended **********"); -} - -/* - * Extended callback variant: like elph_driver_cb plus dvG_fill_fn called - * once per iBZ q-point from commK rank 0 with dV_q^nu(G) in G-space. - * Either callback may be NULL to skip that output. - */ -void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn fill_fn, - elph_dvG_fill_fn dvG_fill_fn) -{ - struct elph_usr_input* input_data; - init_ELPH_clocks(); - - read_elph_input_file(ELPH_input_file, &input_data, comm_world); - - struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); - init_kernel(kernel); - set_kernel(input_data->kernel_str, kernel); - - struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); - CHECK_ALLOC(mpi_comms); - - create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, - mpi_comms); - - print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); - print_info_msg(mpi_comms->commW_rank, - "********** Program started **********"); - print_input_info(input_data->save_dir, input_data->ph_save_dir, - input_data->kernel_str, input_data->kminusq, dft_code, - mpi_comms); - - struct Lattice* lattice = malloc(sizeof(struct Lattice)); - CHECK_ALLOC(lattice); - init_lattice_type(lattice); - - struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); - CHECK_ALLOC(pseudo); - init_Pseudo_type(pseudo); - - struct Phonon* phonon = malloc(sizeof(struct Phonon)); - CHECK_ALLOC(phonon); - init_phonon_type(phonon); - - struct WFC* wfcs; - - if (dft_code == DFT_CODE_QE) - { - get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, - mpi_comms); - } - else - { - error_msg("Only QE supported"); - } - read_and_alloc_save_data(input_data->save_dir, mpi_comms, - input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon); - - char DM_name[100]; - strlcpy_custom(DM_name, input_data->ph_save_dir,100); - strlcat(DM_name,"/ndb.Dmats", 100); - - print_lattice_info(mpi_comms, lattice); - print_phonon_info(mpi_comms, phonon); - - print_info_msg(mpi_comms->commW_rank, ""); - print_info_msg(mpi_comms->commW_rank, - "=== Computing Dmats for phonon symmetries ==="); - compute_and_write_dmats(DM_name, wfcs, lattice, phonon->nph_sym, - phonon->ph_syms, mpi_comms); - - ND_int nmodes = lattice->nmodes; - ND_int nfft_loc = - lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; - - ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); - CHECK_ALLOC(eigVec); - - ELPH_cmplx* dVscf = - malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); - CHECK_ALLOC(dVscf); - - ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); - CHECK_ALLOC(omega_ph); - - int ncid_dmat, nc_err; - int varid_dmat; - - if (mpi_comms->commK_rank == 0) - { - if ((nc_err = nc_open_par(DM_name, NC_NOWRITE, mpi_comms->commR, - MPI_INFO_NULL, &ncid_dmat))) - { - ERR(nc_err); - } - - if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) - { - ERR(nc_err); - } - - size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; - if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, - Dmat_counts, NULL))) - { - ERR(nc_err); - } - } - - print_info_msg(mpi_comms->commW_rank, - "=== Computing Electron-phonon matrix elements ==="); - print_info_msg(mpi_comms->commW_rank, ""); - - for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) - { - print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", - (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); - - ND_int iqpt_iBZg = iqpt + phonon->nq_shift; - - if (dft_code == DFT_CODE_QE) - { - ELPH_cmplx* dvscf_read = NULL; - if (kernel->screening == ELPH_DFPT_SCREENING) - { - dvscf_read = dVscf; - } - else - { - ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; - for (ND_int ix = 0; ix < dvscf_num; ++ix) - { - dVscf[ix] = 0.0; - } - } - get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, - eigVec, dvscf_read, omega_ph, mpi_comms); - } - else - { - error_msg("Currently only quantum espresso supported"); - } - - ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); - CHECK_ALLOC(Vlocr); - dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, - mpi_comms->commK); - - if (dft_code == DFT_CODE_QE) - { - add_dvscf_qe(dVscf, Vlocr, lattice); - } - else - { - error_msg("Currently only quantum espresso supported"); - } - free(Vlocr); - - /* dvG callback: gather dVscf z-slabs to rank 0, FFT, call handler. */ - if (dvG_fill_fn != NULL) - { - ELPH_cmplx* dVG = gather_dVscf_and_fft(dVscf, lattice, - mpi_comms->commK); - if (mpi_comms->commK_rank == 0) - { - dvG_fill_fn((int)iqpt_iBZg, (const void*)dVG, - (const void*)omega_ph, - (int)phonon->nq_iBZ, - (int)nmodes, (int)lattice->nmag, - (int)lattice->fft_dims[0], - (int)lattice->fft_dims[1], - (int)lattice->fft_dims[2]); - free(dVG); - } - } - - compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, - eigVec, dVscf, 0, 0, ncid_dmat, - varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, fill_fn, - iqpt_iBZg); - } - - if (mpi_comms->commK_rank == 0) - { - if ((nc_err = nc_close(ncid_dmat))) - { - ERR(nc_err); - } - } - - free(omega_ph); - free(eigVec); - free(dVscf); - - int World_rank_tmp = mpi_comms->commW_rank; - - free(kernel); - free_elph_usr_input(input_data); - free_save_data(wfcs, lattice, pseudo, phonon); - free(lattice); - free(pseudo); - free(phonon); - free_parallel_comms(mpi_comms); - free(mpi_comms); - fftw_fun(cleanup)(); - - if (0 == World_rank_tmp) - { - print_ELPH_clock_summary(); - } - cleanup_ELPH_clocks(); - print_info_msg(World_rank_tmp, "********** Program ended **********"); -} diff --git a/services/elph/elph_driver_cb.c b/services/elph/elph_driver_cb.c new file mode 100644 index 00000000..a28f71c0 --- /dev/null +++ b/services/elph/elph_driver_cb.c @@ -0,0 +1,226 @@ +/* + Yambo calling point +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/ELPH_timers.h" +#include "common/dtypes.h" +#include "common/error.h" +#include "common/init_dtypes.h" +#include "common/parallel.h" +#include "common/print_info.h" +#include "dvloc/dvloc.h" +#include "dvG_utils.h" +#include "elph.h" +#include "elphC.h" +#include "fft/fft.h" +#include "io/io.h" +#include "io/qe/qe_io.h" +#include "parser/parser.h" +#include "symmetries/symmetries.h" +#include "common/string_func.h" + +/* + * Callback-enabled driver: identical flow to elph_driver but writes gkkp + * data via fill_fn(iq_BZ, ik_BZ, data, ...) instead of ndb.elph. + * ndb.Dmats is still created and used internally for BZ symmetry expansion. + * Eigenvectors / frequencies are NOT written (yambo reads them elsewhere). + */ +void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn) +{ + struct elph_usr_input* input_data; + init_ELPH_clocks(); + + read_elph_input_file(ELPH_input_file, &input_data, comm_world); + + struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); + init_kernel(kernel); + set_kernel(input_data->kernel_str, kernel); + + struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); + CHECK_ALLOC(mpi_comms); + + create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, + mpi_comms); + + print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); + print_info_msg(mpi_comms->commW_rank, + "********** Program started **********"); + print_input_info(input_data->save_dir, input_data->ph_save_dir, + input_data->kernel_str, input_data->kminusq, dft_code, + mpi_comms); + + struct Lattice* lattice = malloc(sizeof(struct Lattice)); + CHECK_ALLOC(lattice); + init_lattice_type(lattice); + + struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); + CHECK_ALLOC(pseudo); + init_Pseudo_type(pseudo); + + struct Phonon* phonon = malloc(sizeof(struct Phonon)); + CHECK_ALLOC(phonon); + init_phonon_type(phonon); + + struct WFC* wfcs; + + if (dft_code == DFT_CODE_QE) + { + get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, + mpi_comms); + } + else + { + error_msg("Only QE supported"); + } + read_and_alloc_save_data(input_data->save_dir, mpi_comms, + input_data->start_bnd, input_data->end_bnd, &wfcs, + input_data->ph_save_dir, lattice, pseudo, phonon); + char DM_name[100]; + strlcpy_custom(DM_name, input_data->ph_save_dir,100); + strlcat(DM_name,"/ndb.Dmats", 100); + + print_lattice_info(mpi_comms, lattice); + print_phonon_info(mpi_comms, phonon); + + print_info_msg(mpi_comms->commW_rank, ""); + print_info_msg(mpi_comms->commW_rank, + "=== Computing Dmats for phonon symmetries ==="); + compute_and_write_dmats(DM_name, wfcs, lattice, phonon->nph_sym, + phonon->ph_syms, mpi_comms); + + ND_int nmodes = lattice->nmodes; + ND_int nfft_loc = + lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; + + ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); + CHECK_ALLOC(eigVec); + + ELPH_cmplx* dVscf = + malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); + CHECK_ALLOC(dVscf); + + ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); + CHECK_ALLOC(omega_ph); + + int ncid_dmat, nc_err; + int varid_dmat; + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_open_par(DM_name, NC_NOWRITE, mpi_comms->commR, + MPI_INFO_NULL, &ncid_dmat))) + { + ERR(nc_err); + } + + if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) + { + ERR(nc_err); + } + + size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; + if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, + Dmat_counts, NULL))) + { + ERR(nc_err); + } + } + + print_info_msg(mpi_comms->commW_rank, + "=== Computing Electron-phonon matrix elements ==="); + print_info_msg(mpi_comms->commW_rank, ""); + + for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) + { + print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", + (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); + + ND_int iqpt_iBZg = iqpt + phonon->nq_shift; + + if (dft_code == DFT_CODE_QE) + { + ELPH_cmplx* dvscf_read = NULL; + if (kernel->screening == ELPH_DFPT_SCREENING) + { + dvscf_read = dVscf; + } + else + { + ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; + for (ND_int ix = 0; ix < dvscf_num; ++ix) + { + dVscf[ix] = 0.0; + } + } + get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, + eigVec, dvscf_read, omega_ph, mpi_comms); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + + ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); + CHECK_ALLOC(Vlocr); + dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, + mpi_comms->commK); + + if (dft_code == DFT_CODE_QE) + { + add_dvscf_qe(dVscf, Vlocr, lattice); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + free(Vlocr); + + compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, + eigVec, dVscf, 0, 0, ncid_dmat, + varid_dmat, kernel->non_loc, + input_data->kminusq, mpi_comms, fill_fn, + iqpt_iBZg); + } + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_close(ncid_dmat))) + { + ERR(nc_err); + } + } + + free(omega_ph); + free(eigVec); + free(dVscf); + + int World_rank_tmp = mpi_comms->commW_rank; + + free(kernel); + free_elph_usr_input(input_data); + free_save_data(wfcs, lattice, pseudo, phonon); + free(lattice); + free(pseudo); + free(phonon); + free_parallel_comms(mpi_comms); + free(mpi_comms); + fftw_fun(cleanup)(); + + if (0 == World_rank_tmp) + { + print_ELPH_clock_summary(); + } + cleanup_ELPH_clocks(); + print_info_msg(World_rank_tmp, "********** Program ended **********"); +} + + diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c new file mode 100644 index 00000000..bdc4d4ac --- /dev/null +++ b/services/elph/elph_driver_cb2.c @@ -0,0 +1,243 @@ +/* + Yambo calling point +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/ELPH_timers.h" +#include "common/dtypes.h" +#include "common/error.h" +#include "common/init_dtypes.h" +#include "common/parallel.h" +#include "common/print_info.h" +#include "dvloc/dvloc.h" +#include "dvG_utils.h" +#include "elph.h" +#include "elphC.h" +#include "fft/fft.h" +#include "io/io.h" +#include "io/qe/qe_io.h" +#include "parser/parser.h" +#include "symmetries/symmetries.h" +#include "common/string_func.h" +/* + * Extended callback variant: like elph_driver_cb plus dvG_fill_fn called + * once per iBZ q-point from commK rank 0 with dV_q^nu(G) in G-space. + * Either callback may be NULL to skip that output. + */ +void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, + MPI_Comm comm_world, elph_fill_fn fill_fn, + elph_dvG_fill_fn dvG_fill_fn) +{ + struct elph_usr_input* input_data; + init_ELPH_clocks(); + + read_elph_input_file(ELPH_input_file, &input_data, comm_world); + + struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); + init_kernel(kernel); + set_kernel(input_data->kernel_str, kernel); + + struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); + CHECK_ALLOC(mpi_comms); + + create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, + mpi_comms); + + print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); + print_info_msg(mpi_comms->commW_rank, + "********** Program started **********"); + print_input_info(input_data->save_dir, input_data->ph_save_dir, + input_data->kernel_str, input_data->kminusq, dft_code, + mpi_comms); + + struct Lattice* lattice = malloc(sizeof(struct Lattice)); + CHECK_ALLOC(lattice); + init_lattice_type(lattice); + + struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); + CHECK_ALLOC(pseudo); + init_Pseudo_type(pseudo); + + struct Phonon* phonon = malloc(sizeof(struct Phonon)); + CHECK_ALLOC(phonon); + init_phonon_type(phonon); + + struct WFC* wfcs; + + if (dft_code == DFT_CODE_QE) + { + get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, + mpi_comms); + } + else + { + error_msg("Only QE supported"); + } + read_and_alloc_save_data(input_data->save_dir, mpi_comms, + input_data->start_bnd, input_data->end_bnd, &wfcs, + input_data->ph_save_dir, lattice, pseudo, phonon); + + char DM_name[100]; + strlcpy_custom(DM_name, input_data->ph_save_dir,100); + strlcat(DM_name,"/ndb.Dmats", 100); + + print_lattice_info(mpi_comms, lattice); + print_phonon_info(mpi_comms, phonon); + + print_info_msg(mpi_comms->commW_rank, ""); + print_info_msg(mpi_comms->commW_rank, + "=== Computing Dmats for phonon symmetries ==="); + compute_and_write_dmats(DM_name, wfcs, lattice, phonon->nph_sym, + phonon->ph_syms, mpi_comms); + + ND_int nmodes = lattice->nmodes; + ND_int nfft_loc = + lattice->fft_dims[0] * lattice->fft_dims[1] * lattice->nfftz_loc; + + ELPH_cmplx* eigVec = malloc(sizeof(ELPH_cmplx) * nmodes * nmodes); + CHECK_ALLOC(eigVec); + + ELPH_cmplx* dVscf = + malloc(sizeof(ELPH_cmplx) * nmodes * lattice->nmag * nfft_loc); + CHECK_ALLOC(dVscf); + + ELPH_float* omega_ph = malloc(sizeof(ELPH_float) * nmodes); + CHECK_ALLOC(omega_ph); + + int ncid_dmat, nc_err; + int varid_dmat; + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_open_par(DM_name, NC_NOWRITE, mpi_comms->commR, + MPI_INFO_NULL, &ncid_dmat))) + { + ERR(nc_err); + } + + if ((nc_err = nc_inq_varid(ncid_dmat, "Dmats", &varid_dmat))) + { + ERR(nc_err); + } + + size_t Dmat_counts[6] = {0, 0, 0, 0, 0, 0}; + if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, Dmat_counts, + Dmat_counts, NULL))) + { + ERR(nc_err); + } + } + + print_info_msg(mpi_comms->commW_rank, + "=== Computing Electron-phonon matrix elements ==="); + print_info_msg(mpi_comms->commW_rank, ""); + + for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) + { + print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", + (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); + + ND_int iqpt_iBZg = iqpt + phonon->nq_shift; + + if (dft_code == DFT_CODE_QE) + { + ELPH_cmplx* dvscf_read = NULL; + if (kernel->screening == ELPH_DFPT_SCREENING) + { + dvscf_read = dVscf; + } + else + { + ND_int dvscf_num = nmodes * lattice->nmag * nfft_loc; + for (ND_int ix = 0; ix < dvscf_num; ++ix) + { + dVscf[ix] = 0.0; + } + } + get_dvscf_dyn_qe(input_data->ph_save_dir, lattice, iqpt_iBZg, + eigVec, dvscf_read, omega_ph, mpi_comms); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + + ELPH_cmplx* Vlocr = malloc(sizeof(ELPH_cmplx) * nmodes * nfft_loc); + CHECK_ALLOC(Vlocr); + dVlocq(phonon->qpts_iBZ + iqpt_iBZg * 3, lattice, pseudo, eigVec, Vlocr, + mpi_comms->commK); + + if (dft_code == DFT_CODE_QE) + { + add_dvscf_qe(dVscf, Vlocr, lattice); + } + else + { + error_msg("Currently only quantum espresso supported"); + } + free(Vlocr); + + /* dvG callback: gather dVscf z-slabs to rank 0, FFT, call handler. */ + if (dvG_fill_fn != NULL) + { + ELPH_cmplx* dVG = gather_dVscf_and_fft(dVscf, lattice, + mpi_comms->commK); + if (mpi_comms->commK_rank == 0) + { + dvG_fill_fn((int)iqpt_iBZg, (const void*)dVG, + (const void*)omega_ph, + (int)phonon->nq_iBZ, + (int)nmodes, (int)lattice->nmag, + (int)lattice->fft_dims[0], + (int)lattice->fft_dims[1], + (int)lattice->fft_dims[2]); + free(dVG); + } + } + + compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, + eigVec, dVscf, 0, 0, ncid_dmat, + varid_dmat, kernel->non_loc, + input_data->kminusq, mpi_comms, fill_fn, + iqpt_iBZg); + } + + if (mpi_comms->commK_rank == 0) + { + if ((nc_err = nc_close(ncid_dmat))) + { + ERR(nc_err); + } + } + + free(omega_ph); + free(eigVec); + free(dVscf); + + int World_rank_tmp = mpi_comms->commW_rank; + + free(kernel); + free_elph_usr_input(input_data); + free_save_data(wfcs, lattice, pseudo, phonon); + free(lattice); + free(pseudo); + free(phonon); + free_parallel_comms(mpi_comms); + free(mpi_comms); + fftw_fun(cleanup)(); + + if (0 == World_rank_tmp) + { + print_ELPH_clock_summary(); + } + cleanup_ELPH_clocks(); + print_info_msg(World_rank_tmp, "********** Program ended **********"); +} + diff --git a/services/io/get_save_data.c b/services/io/get_save_data.c index 94dab8bd..a05a2581 100644 --- a/services/io/get_save_data.c +++ b/services/io/get_save_data.c @@ -197,6 +197,7 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, if (start_band < 1 || end_band < 1) { +#if !defined _Y6_LETZ if (Comm->commW_rank == 0) { fprintf(stderr, @@ -204,12 +205,14 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, "matrix elements for all bands, " "Bands index belong to [1,nbnds] \n"); } +#endif start_band = 1; end_band = lattice->total_bands; } if (start_band > lattice->total_bands || end_band > lattice->total_bands || start_band >= end_band) { +#if !defined _Y6_LETZ if (Comm->commW_rank == 0) { fprintf( @@ -217,6 +220,7 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, "Warning : invalid bands used in calculation. computing matrix " "elements for all bands \n"); } +#endif start_band = 1; end_band = lattice->total_bands; } diff --git a/services/main_elphC.c b/services/main_elphC.c index ab6186ec..325c6126 100644 --- a/services/main_elphC.c +++ b/services/main_elphC.c @@ -76,7 +76,7 @@ int main(int argc, char* argv[]) { if (calc_info->code == DFT_CODE_QE) { - create_ph_save_dir_pp_qe(calc_info->input_file,calc_info->ph_save_dir); + create_ph_save_dir_pp_qe(calc_info->input_file,calc_info->ph_save_dir,"./"); } } } diff --git a/services/parser/parser.h b/services/parser/parser.h index ab3f85ff..4f4fad65 100644 --- a/services/parser/parser.h +++ b/services/parser/parser.h @@ -14,7 +14,9 @@ struct elph_usr_input int start_bnd; // starting band int end_bnd; // last band char* save_dir; // save dir - char* ph_save_dir; // ph_save directory + char* scf_path; // SCF run directory + char* ph_path; // ph run directory + char* ph_save_dir; // ph_path/ph_save directory char* kernel_str; // level of screening to include bool kminusq; // true if convention is "yambo" else false }; diff --git a/services/preprocessor/pp_ph_save.c b/services/preprocessor/pp_ph_save.c index 5a4b87a0..3cc8006d 100644 --- a/services/preprocessor/pp_ph_save.c +++ b/services/preprocessor/pp_ph_save.c @@ -18,10 +18,13 @@ This file contains functions which are os dependent. #include "io/ezxml/ezxml.h" #include "preprocessor.h" -static ND_int find_nqpools(const char* out_dir, char* buffer_tmp, - ND_int buffer_size); +static ND_int find_nqpools(const char* out_dir, char* buffer_tmp,ND_int buffer_size); -void create_ph_save_dir_pp_qe(const char* inp_file,const char* ph_path ) +#if defined _Y6_LETZ +void create_ph_save_dir_pp_qe(const char* inp_file,char* ph_path,char* scf_path ) +#else +void create_ph_save_dir_pp_qe(const char* inp_file,const char* ph_path, const char* scf_path ) +#endif { // parse the input file // open the qe ph.x input file @@ -307,7 +310,7 @@ void create_ph_save_dir_pp_qe(const char* inp_file,const char* ph_path ) snprintf(prefix_dir, 100, "%s.save", scf_prefix); cwk_path_join_multiple( - (const char*[]){out_dir, prefix_dir, "data-file-schema.xml", NULL}, + (const char*[]){scf_path,out_dir, prefix_dir, "data-file-schema.xml", NULL}, src_file_tmp, PH_X_INP_READ_BUF_SIZE); cwk_path_join_multiple( @@ -353,7 +356,7 @@ void create_ph_save_dir_pp_qe(const char* inp_file,const char* ph_path ) char* tmp_str = pseudo_file_xml->txt; cwk_path_join_multiple( - (const char*[]){out_dir, prefix_dir, tmp_str, NULL}, src_file_tmp, + (const char*[]){scf_path,out_dir, prefix_dir, tmp_str, NULL}, src_file_tmp, PH_X_INP_READ_BUF_SIZE); cwk_path_join_multiple((const char*[]){PH_SAVE_DIR_NAME, tmp_str, NULL}, diff --git a/services/preprocessor/preprocessor.h b/services/preprocessor/preprocessor.h index 8d4302be..0c2b077e 100644 --- a/services/preprocessor/preprocessor.h +++ b/services/preprocessor/preprocessor.h @@ -9,7 +9,11 @@ void ELPH_cli_parser(int argc, char* argv[], struct calc_details* calc_info); -void create_ph_save_dir_pp_qe(const char* inp_file,const char* ph_path); +#if defined _Y6_LETZ +void create_ph_save_dir_pp_qe(const char* inp_file,char* ph_path,char* scf_path); +#else +void create_ph_save_dir_pp_qe(const char* inp_file,const char* ph_path, const char* scf_path); +#endif void ELPH_print_version(void); void ELPH_print_help(void); From fd3c5e11970e09fdc542715be579b64a8f5dcdcc Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Fri, 12 Jun 2026 09:11:06 +0200 Subject: [PATCH 25/46] MODIFIED * services/elph/elph.h services/elph/elph_driver_cb2.c services/elph/ep_f2c_bridge.c Changes: - Letz input file passed via struct instead that by reading the external file Patch sent by: Andrea Marini --- services/elph/elph.h | 3 ++- services/elph/elph_driver_cb2.c | 8 ++++---- services/elph/ep_f2c_bridge.c | 11 +++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/services/elph/elph.h b/services/elph/elph.h index 980071c0..c125588f 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -2,6 +2,7 @@ #include #include +#include "parser/parser.h" #include "common/dtypes.h" #include "elphC.h" @@ -46,7 +47,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, * iBZ q-point with the full dV_q^nu(G) potential in reciprocal space. * Either callback may be NULL to skip that output. */ -void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, +void elph_driver_cb2(struct elph_usr_input* input_data, enum ELPH_dft_code dft_code, MPI_Comm comm_world, elph_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn); diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index bdc4d4ac..f2b84dae 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -31,14 +31,14 @@ * once per iBZ q-point from commK rank 0 with dV_q^nu(G) in G-space. * Either callback may be NULL to skip that output. */ -void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, +void elph_driver_cb2(struct elph_usr_input* input_data,enum ELPH_dft_code dft_code, MPI_Comm comm_world, elph_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn) { - struct elph_usr_input* input_data; + /*struct elph_usr_input* input_data;*/ init_ELPH_clocks(); - read_elph_input_file(ELPH_input_file, &input_data, comm_world); + /* read_elph_input_file(ELPH_input_file, &input_data, comm_world);*/ struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); init_kernel(kernel); @@ -224,7 +224,7 @@ void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, int World_rank_tmp = mpi_comms->commW_rank; free(kernel); - free_elph_usr_input(input_data); + /*free_elph_usr_input(input_data);*/ free_save_data(wfcs, lattice, pseudo, phonon); free(lattice); free(pseudo); diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index 0ebbc3a2..c992236d 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -17,6 +17,7 @@ #include #include #include +#include "parser/parser.h" /* Fortran bind(C) callbacks — linked from the ep packages library. */ extern void elph_coll_fill_gkkp(int, int, const void*, int, int, int, int, int, int, int, const void*); @@ -89,13 +90,15 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, * compatibility but ignored — callbacks resolved directly by the linker to * avoid the arm64 gfortran procedure-descriptor segfault. */ -void elph_driver_cb2_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, - void* fill_fn_ptr, void* dvG_fill_fn_ptr, - const char* log_path) +void elph_driver_cb2_f2c(struct elph_usr_input* input_data, int dft_code, MPI_Fint f_comm, + void* fill_fn_ptr, void* dvG_fill_fn_ptr, + const char* log_path) { + printf("\n f2c %s\n",input_data->save_dir); + printf("\n f2c %s\n",input_data->scf_path); MPI_Comm c_comm = MPI_Comm_f2c(f_comm); open_letz_log(c_comm, log_path); - elph_driver_cb2(input_file, (enum ELPH_dft_code)dft_code, c_comm, + elph_driver_cb2(input_data,(enum ELPH_dft_code)dft_code, c_comm, (elph_fill_fn)elph_coll_fill_gkkp, (elph_dvG_fill_fn)elph_coll_fill_dvg); close_letz_log(); From f2eefe27e3dfb17cd9665d53e5fb1cdc333fff0f Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Fri, 12 Jun 2026 13:38:33 +0200 Subject: [PATCH 26/46] MODIFIED * services/common/dtypes.h services/elph/elph.h services/elph/elph_driver_cb2.c services/elph/ep_f2c_bridge.c Additions: - Added Y6_data structure Patch sent by: Andrea Marini --- services/common/dtypes.h | 17 +++++++++++++++++ services/elph/elph.h | 2 +- services/elph/elph_driver_cb2.c | 17 ++++++++++++++++- services/elph/ep_f2c_bridge.c | 7 +++---- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/services/common/dtypes.h b/services/common/dtypes.h index 4010569e..3eefc275 100644 --- a/services/common/dtypes.h +++ b/services/common/dtypes.h @@ -77,6 +77,23 @@ enum asr_kind ASR_ALL_HUANG }; +// Pieces of Lattice and Phonon to be passed to Yambo// +struct Y6_info +{ + int natom; + int nsym; + int timerev; + int nspin; + int nspinor; + int total_bands; + int start_band; + int end_band; + int nbnds; + int lattice_dim; + int nmag; + int nmodes; +}; + struct Lattice { // type which contains all information about the crystal structure diff --git a/services/elph/elph.h b/services/elph/elph.h index c125588f..76f028da 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -47,7 +47,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, * iBZ q-point with the full dV_q^nu(G) potential in reciprocal space. * Either callback may be NULL to skip that output. */ -void elph_driver_cb2(struct elph_usr_input* input_data, enum ELPH_dft_code dft_code, +void elph_driver_cb2(struct elph_usr_input* input_data, struct Y6_info* y6_data, enum ELPH_dft_code dft_code, MPI_Comm comm_world, elph_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn); diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index f2b84dae..49223a30 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -31,7 +31,7 @@ * once per iBZ q-point from commK rank 0 with dV_q^nu(G) in G-space. * Either callback may be NULL to skip that output. */ -void elph_driver_cb2(struct elph_usr_input* input_data,enum ELPH_dft_code dft_code, +void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,enum ELPH_dft_code dft_code, MPI_Comm comm_world, elph_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn) { @@ -216,6 +216,21 @@ void elph_driver_cb2(struct elph_usr_input* input_data,enum ELPH_dft_code dft_co ERR(nc_err); } } + // Filling Y6 info// + y6_data->natom=lattice->natom; + y6_data->nsym=lattice->nsym; + y6_data->timerev=lattice->timerev; + y6_data->nspin=lattice->nspin; + y6_data->nspinor=lattice->nspinor; + y6_data->total_bands=lattice->total_bands; + y6_data->start_band=lattice->start_band; + y6_data->end_band=lattice->end_band; + y6_data->nbnds=lattice->nbnds; + y6_data->lattice_dim=lattice->dimension; + y6_data->nmag=lattice->nmag; + y6_data->nmodes=lattice->nmodes; + printf("MAG %i",lattice->nmag); + printf("MODES %i",lattice->nmodes); free(omega_ph); free(eigVec); diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index c992236d..78c45e06 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -90,15 +90,14 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, * compatibility but ignored — callbacks resolved directly by the linker to * avoid the arm64 gfortran procedure-descriptor segfault. */ -void elph_driver_cb2_f2c(struct elph_usr_input* input_data, int dft_code, MPI_Fint f_comm, +void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_data, + int dft_code, MPI_Fint f_comm, void* fill_fn_ptr, void* dvG_fill_fn_ptr, const char* log_path) { - printf("\n f2c %s\n",input_data->save_dir); - printf("\n f2c %s\n",input_data->scf_path); MPI_Comm c_comm = MPI_Comm_f2c(f_comm); open_letz_log(c_comm, log_path); - elph_driver_cb2(input_data,(enum ELPH_dft_code)dft_code, c_comm, + elph_driver_cb2(input_data,y6_data,(enum ELPH_dft_code)dft_code, c_comm, (elph_fill_fn)elph_coll_fill_gkkp, (elph_dvG_fill_fn)elph_coll_fill_dvg); close_letz_log(); From 44448fe47e059a7affd97d71af7e1e12d8b0ac61 Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Fri, 12 Jun 2026 18:10:13 +0200 Subject: [PATCH 27/46] MODIFIED * services/elph/elph.h services/elph/elph_driver_cb2.c services/elph/ep_f2c_bridge.c Patch sent by: Andrea Marini --- services/elph/elph.h | 2 +- services/elph/elph_driver_cb2.c | 22 +++++++++++++++------- services/elph/ep_f2c_bridge.c | 4 ++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/services/elph/elph.h b/services/elph/elph.h index 76f028da..124b35a9 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -49,7 +49,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, */ void elph_driver_cb2(struct elph_usr_input* input_data, struct Y6_info* y6_data, enum ELPH_dft_code dft_code, MPI_Comm comm_world, elph_fill_fn fill_fn, - elph_dvG_fill_fn dvG_fill_fn); + elph_dvG_fill_fn dvG_fill_fn,int i_control); void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, struct Pseudo* pseudo, struct Phonon* phonon, diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index 49223a30..1ab787cc 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -33,7 +33,7 @@ */ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,enum ELPH_dft_code dft_code, MPI_Comm comm_world, elph_fill_fn fill_fn, - elph_dvG_fill_fn dvG_fill_fn) + elph_dvG_fill_fn dvG_fill_fn,int i_control) { /*struct elph_usr_input* input_data;*/ init_ELPH_clocks(); @@ -50,12 +50,15 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, mpi_comms); - print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); - print_info_msg(mpi_comms->commW_rank, - "********** Program started **********"); - print_input_info(input_data->save_dir, input_data->ph_save_dir, - input_data->kernel_str, input_data->kminusq, dft_code, - mpi_comms); + if (i_control == 0 ) + { + print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); + print_info_msg(mpi_comms->commW_rank, + "********** Program started **********"); + print_input_info(input_data->save_dir, input_data->ph_save_dir, + input_data->kernel_str, input_data->kminusq, dft_code, + mpi_comms); + } struct Lattice* lattice = malloc(sizeof(struct Lattice)); CHECK_ALLOC(lattice); @@ -80,10 +83,15 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e { error_msg("Only QE supported"); } + if (i_control< 0 ) + { + return; + } read_and_alloc_save_data(input_data->save_dir, mpi_comms, input_data->start_bnd, input_data->end_bnd, &wfcs, input_data->ph_save_dir, lattice, pseudo, phonon); + char DM_name[100]; strlcpy_custom(DM_name, input_data->ph_save_dir,100); strlcat(DM_name,"/ndb.Dmats", 100); diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index 78c45e06..c499a3e6 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -93,12 +93,12 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_data, int dft_code, MPI_Fint f_comm, void* fill_fn_ptr, void* dvG_fill_fn_ptr, - const char* log_path) + const char* log_path, int i_control) { MPI_Comm c_comm = MPI_Comm_f2c(f_comm); open_letz_log(c_comm, log_path); elph_driver_cb2(input_data,y6_data,(enum ELPH_dft_code)dft_code, c_comm, (elph_fill_fn)elph_coll_fill_gkkp, - (elph_dvG_fill_fn)elph_coll_fill_dvg); + (elph_dvG_fill_fn)elph_coll_fill_dvg,i_control); close_letz_log(); } From 0ab2d9b66097906df092544f78e4360974466549 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Sat, 13 Jun 2026 11:07:26 +0200 Subject: [PATCH 28/46] support query-only mode (i_control<0): populate y6_data early, skip gkkp/dvG --- services/elph/elph_driver_cb2.c | 39 +++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index 1ab787cc..9b9b0e79 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -83,8 +83,31 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e { error_msg("Only QE supported"); } + + /* Populate y6_data (elphC_info in Fortran) with lattice/phonon metadata. + This happens early so query-only mode (i_control < 0) can return with + nmodes, natom, nsym, etc. already set for Fortran-side allocation. */ + y6_data->natom=lattice->natom; + y6_data->nsym=lattice->nsym; + y6_data->timerev=lattice->timerev; + y6_data->nspin=lattice->nspin; + y6_data->nspinor=lattice->nspinor; + y6_data->total_bands=lattice->total_bands; + y6_data->start_band=lattice->start_band; + y6_data->end_band=lattice->end_band; + y6_data->nbnds=lattice->nbnds; + y6_data->lattice_dim=lattice->dimension; + y6_data->nmag=lattice->nmag; + y6_data->nmodes=lattice->nmodes; + if (i_control< 0 ) { + /* Query-only mode: return with y6_data populated, skip gkkp/dvG computation. */ + free(lattice); + free(pseudo); + free(phonon); + free_parallel_comms(mpi_comms); + free(mpi_comms); return; } read_and_alloc_save_data(input_data->save_dir, mpi_comms, @@ -224,22 +247,6 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e ERR(nc_err); } } - // Filling Y6 info// - y6_data->natom=lattice->natom; - y6_data->nsym=lattice->nsym; - y6_data->timerev=lattice->timerev; - y6_data->nspin=lattice->nspin; - y6_data->nspinor=lattice->nspinor; - y6_data->total_bands=lattice->total_bands; - y6_data->start_band=lattice->start_band; - y6_data->end_band=lattice->end_band; - y6_data->nbnds=lattice->nbnds; - y6_data->lattice_dim=lattice->dimension; - y6_data->nmag=lattice->nmag; - y6_data->nmodes=lattice->nmodes; - printf("MAG %i",lattice->nmag); - printf("MODES %i",lattice->nmodes); - free(omega_ph); free(eigVec); free(dVscf); From 3b18f605345ade558dce777eb257f2d83fe49eb4 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Sat, 13 Jun 2026 12:57:57 +0200 Subject: [PATCH 29/46] changes for PAR --- services/common/dtypes.h | 2 ++ services/elph/elph_driver_cb2.c | 5 ++++- services/elph/ep_f2c_bridge.c | 10 +++++++--- services/preprocessor/cli.c | 1 + 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/services/common/dtypes.h b/services/common/dtypes.h index 3eefc275..795c3187 100644 --- a/services/common/dtypes.h +++ b/services/common/dtypes.h @@ -56,6 +56,8 @@ struct calc_details // name of the input file. // can be elph input or DFT-Phonon input // base on calc_type + char ph_save_dir[512]; + // phonon save directory path for QE preprocessor }; struct symmetry diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index 9b9b0e79..f2c6baa3 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -30,10 +30,12 @@ * Extended callback variant: like elph_driver_cb plus dvG_fill_fn called * once per iBZ q-point from commK rank 0 with dV_q^nu(G) in G-space. * Either callback may be NULL to skip that output. + * comm_q, comm_k: Y6 PAR communicators for q,k distribution (nqpool/nkpool derived from these). */ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,enum ELPH_dft_code dft_code, MPI_Comm comm_world, elph_fill_fn fill_fn, - elph_dvG_fill_fn dvG_fill_fn,int i_control) + elph_dvG_fill_fn dvG_fill_fn,int i_control, + MPI_Comm comm_q, MPI_Comm comm_k) { /*struct elph_usr_input* input_data;*/ init_ELPH_clocks(); @@ -47,6 +49,7 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e struct ELPH_MPI_Comms* mpi_comms = malloc(sizeof(struct ELPH_MPI_Comms)); CHECK_ALLOC(mpi_comms); + /* Create parallel communicators using Y6 scheme communicators for pool distribution */ create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, mpi_comms); diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index c499a3e6..c2762842 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -89,16 +89,20 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, * Extended callback bridge: fill_fn_ptr and dvG_fill_fn_ptr are kept for API * compatibility but ignored — callbacks resolved directly by the linker to * avoid the arm64 gfortran procedure-descriptor segfault. + * Communicators (f_comm_q, f_comm_k) passed from Y6 PAR schemes for MPI distribution. */ -void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_data, +void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_data, int dft_code, MPI_Fint f_comm, void* fill_fn_ptr, void* dvG_fill_fn_ptr, - const char* log_path, int i_control) + const char* log_path, int i_control, + MPI_Fint f_comm_q, MPI_Fint f_comm_k) { MPI_Comm c_comm = MPI_Comm_f2c(f_comm); + MPI_Comm c_comm_q = MPI_Comm_f2c(f_comm_q); + MPI_Comm c_comm_k = MPI_Comm_f2c(f_comm_k); open_letz_log(c_comm, log_path); elph_driver_cb2(input_data,y6_data,(enum ELPH_dft_code)dft_code, c_comm, (elph_fill_fn)elph_coll_fill_gkkp, - (elph_dvG_fill_fn)elph_coll_fill_dvg,i_control); + (elph_dvG_fill_fn)elph_coll_fill_dvg,i_control,c_comm_q,c_comm_k); close_letz_log(); } diff --git a/services/preprocessor/cli.c b/services/preprocessor/cli.c index 091eec45..25a5ba70 100644 --- a/services/preprocessor/cli.c +++ b/services/preprocessor/cli.c @@ -17,6 +17,7 @@ void ELPH_cli_parser(int argc, char* argv[], struct calc_details* calc_info) calc_info->calc = CALC_ELPH; calc_info->code = DFT_CODE_QE; strcpy(calc_info->input_file, ""); + strcpy(calc_info->ph_save_dir, "ph_save"); /* * Here are the options * --help (help) From e8ea52ab4e8df98ca30c615beda6a451a5942683 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Sat, 13 Jun 2026 13:05:07 +0200 Subject: [PATCH 30/46] comp error --- services/elph/elph.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/elph/elph.h b/services/elph/elph.h index 124b35a9..3fd36a50 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -46,10 +46,12 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, * Extended callback variant: like elph_driver_cb plus calls dvG_fill_fn once per * iBZ q-point with the full dV_q^nu(G) potential in reciprocal space. * Either callback may be NULL to skip that output. + * comm_q, comm_k: Y6 PAR communicators for q,k distribution. */ void elph_driver_cb2(struct elph_usr_input* input_data, struct Y6_info* y6_data, enum ELPH_dft_code dft_code, MPI_Comm comm_world, elph_fill_fn fill_fn, - elph_dvG_fill_fn dvG_fill_fn,int i_control); + elph_dvG_fill_fn dvG_fill_fn,int i_control, + MPI_Comm comm_q, MPI_Comm comm_k); void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, struct Pseudo* pseudo, struct Phonon* phonon, From 5e7b365a21446b76c5df138284229de2b3292601 Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Mon, 15 Jun 2026 18:24:04 +0200 Subject: [PATCH 31/46] MODIFIED * services/common/dtypes.h services/common/parallel.c services/elph/elph.h services/elph/elph_driver_cb2.c services/elph/ep_f2c_bridge.c NEW * services/elph/yambo.h Additions: - Added y6_work structure with distributed K and Q Patch sent by: Andrea Marini --- services/common/dtypes.h | 17 ----------------- services/common/parallel.c | 1 + services/elph/elph.h | 7 ++++--- services/elph/elph_driver_cb2.c | 34 ++++++++++++++++++++++----------- services/elph/ep_f2c_bridge.c | 25 +++++++++++++++++------- services/elph/yambo.h | 31 ++++++++++++++++++++++++++++++ 6 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 services/elph/yambo.h diff --git a/services/common/dtypes.h b/services/common/dtypes.h index 795c3187..d9b9de44 100644 --- a/services/common/dtypes.h +++ b/services/common/dtypes.h @@ -79,23 +79,6 @@ enum asr_kind ASR_ALL_HUANG }; -// Pieces of Lattice and Phonon to be passed to Yambo// -struct Y6_info -{ - int natom; - int nsym; - int timerev; - int nspin; - int nspinor; - int total_bands; - int start_band; - int end_band; - int nbnds; - int lattice_dim; - int nmag; - int nmodes; -}; - struct Lattice { // type which contains all information about the crystal structure diff --git a/services/common/parallel.c b/services/common/parallel.c index d4a62402..9306a76b 100644 --- a/services/common/parallel.c +++ b/services/common/parallel.c @@ -9,6 +9,7 @@ This file contains function which distributes cpus #include "dtypes.h" #include "elphC.h" #include "error.h" +#include /*get block size and starting idx of dimension that is distrbuted amoung cpus*/ ND_int get_mpi_local_size_idx(const ND_int n, ND_int* start_idx, MPI_Comm Comm) diff --git a/services/elph/elph.h b/services/elph/elph.h index 3fd36a50..622d5137 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -5,6 +5,7 @@ #include "parser/parser.h" #include "common/dtypes.h" #include "elphC.h" +#include "yambo.h" /* * Per-(iq_BZ, ik_BZ) fill callback for yambo COLL integration. @@ -48,10 +49,10 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, * Either callback may be NULL to skip that output. * comm_q, comm_k: Y6 PAR communicators for q,k distribution. */ -void elph_driver_cb2(struct elph_usr_input* input_data, struct Y6_info* y6_data, enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn fill_fn, +void elph_driver_cb2(struct elph_usr_input* input_data, struct Y6_info* y6_data, struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, + elph_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn,int i_control, - MPI_Comm comm_q, MPI_Comm comm_k); + MPI_Comm comm_world ); void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, struct Pseudo* pseudo, struct Phonon* phonon, diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index f2c6baa3..d17a5f75 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -18,6 +18,7 @@ #include "common/print_info.h" #include "dvloc/dvloc.h" #include "dvG_utils.h" +#include "yambo.h" #include "elph.h" #include "elphC.h" #include "fft/fft.h" @@ -32,16 +33,14 @@ * Either callback may be NULL to skip that output. * comm_q, comm_k: Y6 PAR communicators for q,k distribution (nqpool/nkpool derived from these). */ -void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn fill_fn, +void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, + elph_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn,int i_control, - MPI_Comm comm_q, MPI_Comm comm_k) + MPI_Comm comm_world) { /*struct elph_usr_input* input_data;*/ init_ELPH_clocks(); - /* read_elph_input_file(ELPH_input_file, &input_data, comm_world);*/ - struct kernel_info* kernel = malloc(sizeof(struct kernel_info)); init_kernel(kernel); set_kernel(input_data->kernel_str, kernel); @@ -53,6 +52,18 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, mpi_comms); + /* + fprintf(stderr,"\n"); + for (int i = 0; i < y6_work->NK; i++) { + fprintf(stderr," R %i K %i\n ",mpi_comms->commW_rank, y6_work->K[i]); + } + fprintf(stderr,"\n"); + for (int i = 0; i < y6_work->NQ; i++) { + fprintf(stderr," R %i Q %i\n ",mpi_comms->commW_rank, y6_work->Q[i]); + } + fprintf(stderr,"\n"); + */ + if (i_control == 0 ) { print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); @@ -109,8 +120,8 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e free(lattice); free(pseudo); free(phonon); - free_parallel_comms(mpi_comms); - free(mpi_comms); + //free_parallel_comms(mpi_comms); + //free(mpi_comms); return; } read_and_alloc_save_data(input_data->save_dir, mpi_comms, @@ -173,12 +184,13 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e "=== Computing Electron-phonon matrix elements ==="); print_info_msg(mpi_comms->commW_rank, ""); - for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) + for (ND_int iqpt = 0; iqpt < y6_work->NQ; ++iqpt) { print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); - ND_int iqpt_iBZg = iqpt + phonon->nq_shift; + //ND_int iqpt_iBZg = iqpt + phonon->nq_shift; + ND_int iqpt_iBZg = y6_work->Q[iqpt]; if (dft_code == DFT_CODE_QE) { @@ -262,8 +274,8 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e free(lattice); free(pseudo); free(phonon); - free_parallel_comms(mpi_comms); - free(mpi_comms); + //free_parallel_comms(mpi_comms); + //free(mpi_comms); fftw_fun(cleanup)(); if (0 == World_rank_tmp) diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index c2762842..d55fa825 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -13,7 +13,9 @@ #include "elph.h" /* already pulls in common/dtypes.h and elphC.h */ #include "common/print_info.h" +#include #include +#include #include #include #include @@ -92,17 +94,26 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, * Communicators (f_comm_q, f_comm_k) passed from Y6 PAR schemes for MPI distribution. */ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_data, - int dft_code, MPI_Fint f_comm, - void* fill_fn_ptr, void* dvG_fill_fn_ptr, + int dft_code, void* fill_fn_ptr, void* dvG_fill_fn_ptr, const char* log_path, int i_control, - MPI_Fint f_comm_q, MPI_Fint f_comm_k) + int NQ_todo, int* Q_todo, int NK_todo , int* K_todo,MPI_Fint f_comm) { MPI_Comm c_comm = MPI_Comm_f2c(f_comm); - MPI_Comm c_comm_q = MPI_Comm_f2c(f_comm_q); - MPI_Comm c_comm_k = MPI_Comm_f2c(f_comm_k); open_letz_log(c_comm, log_path); - elph_driver_cb2(input_data,y6_data,(enum ELPH_dft_code)dft_code, c_comm, + + struct Y6_parallel_work* y6_work = malloc(sizeof(struct Y6_parallel_work)); + + y6_work->Q = malloc(NQ_todo * sizeof(int)); + y6_work->NQ = NQ_todo-1; + y6_work->Q = Q_todo; + + y6_work->K = malloc(NK_todo * sizeof(int)); + y6_work->NK = NK_todo-1; + y6_work->K = K_todo; + + elph_driver_cb2(input_data,y6_data,y6_work,(enum ELPH_dft_code)dft_code, (elph_fill_fn)elph_coll_fill_gkkp, - (elph_dvG_fill_fn)elph_coll_fill_dvg,i_control,c_comm_q,c_comm_k); + (elph_dvG_fill_fn)elph_coll_fill_dvg,i_control,c_comm); + close_letz_log(); } diff --git a/services/elph/yambo.h b/services/elph/yambo.h new file mode 100644 index 00000000..86c43d92 --- /dev/null +++ b/services/elph/yambo.h @@ -0,0 +1,31 @@ +/* +This file contains Yambo specific data-structures used in the Code. +*/ +#pragma once +#include + +struct Y6_parallel_work +{ + int *Q; + int NQ; + int *K; + int NK; +}; + +// Pieces of Lattice and Phonon to be passed to Yambo// +struct Y6_info +{ + int natom; + int nsym; + int timerev; + int nspin; + int nspinor; + int total_bands; + int start_band; + int end_band; + int nbnds; + int lattice_dim; + int nmag; + int nmodes; +}; + From b3e508b3b741fa5b633cdab06db87170e80c4685 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Mon, 15 Jun 2026 20:41:15 +0200 Subject: [PATCH 32/46] reading of nsym and nspin --- services/elph/elph_driver_cb2.c | 51 ++++++++----- services/io/get_save_data.c | 131 +++++++++++++++++++++++++++----- services/io/io.h | 3 + 3 files changed, 150 insertions(+), 35 deletions(-) diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index f2c6baa3..5737e049 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -87,9 +87,40 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e error_msg("Only QE supported"); } - /* Populate y6_data (elphC_info in Fortran) with lattice/phonon metadata. - This happens early so query-only mode (i_control < 0) can return with - nmodes, natom, nsym, etc. already set for Fortran-side allocation. */ + if (i_control < 0) + { + /* Query-only mode: read dimensions only, skip matrix computation. + read_lattice_dimensions populates nspin, nsym, etc. from SAVE netCDF. */ + read_lattice_dimensions(input_data->save_dir, mpi_comms, lattice, phonon); + + /* Populate y6_data (elphC_info in Fortran) with metadata. */ + y6_data->natom=lattice->natom; + y6_data->nsym=lattice->nsym; + y6_data->timerev=lattice->timerev; + y6_data->nspin=lattice->nspin; + y6_data->nspinor=lattice->nspinor; + y6_data->total_bands=lattice->total_bands; + y6_data->start_band=lattice->start_band; + y6_data->end_band=lattice->end_band; + y6_data->nbnds=lattice->nbnds; + y6_data->lattice_dim=lattice->dimension; + y6_data->nmag=lattice->nmag; + y6_data->nmodes=lattice->nmodes; + + /* Return after metadata population; skip gkkp/dvG computation. */ + free(lattice); + free(pseudo); + free(phonon); + free_parallel_comms(mpi_comms); + free(mpi_comms); + return; + } + + read_and_alloc_save_data(input_data->save_dir, mpi_comms, + input_data->start_bnd, input_data->end_bnd, &wfcs, + input_data->ph_save_dir, lattice, pseudo, phonon); + + /* Populate y6_data (elphC_info in Fortran) with lattice/phonon metadata. */ y6_data->natom=lattice->natom; y6_data->nsym=lattice->nsym; y6_data->timerev=lattice->timerev; @@ -103,20 +134,6 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data,e y6_data->nmag=lattice->nmag; y6_data->nmodes=lattice->nmodes; - if (i_control< 0 ) - { - /* Query-only mode: return with y6_data populated, skip gkkp/dvG computation. */ - free(lattice); - free(pseudo); - free(phonon); - free_parallel_comms(mpi_comms); - free(mpi_comms); - return; - } - read_and_alloc_save_data(input_data->save_dir, mpi_comms, - input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon); - char DM_name[100]; strlcpy_custom(DM_name, input_data->ph_save_dir,100); diff --git a/services/io/get_save_data.c b/services/io/get_save_data.c index a05a2581..f389c293 100644 --- a/services/io/get_save_data.c +++ b/services/io/get_save_data.c @@ -48,6 +48,115 @@ static void get_wfc_from_save(ND_int spin_stride_len, ND_int ik, ND_int nkiBZ, static inline ND_int get_wf_io_pool(ND_int ik, ND_int q, ND_int r); +/* Read lattice dimensions (nspin, nsym, etc.) from SAVE netCDF files.*/ +void read_lattice_dimensions(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, + struct Lattice* lattice, struct Phonon* phonon) +{ + int mpi_error; + int nsELid, nsWFid, nsLATid, tempid, retval; + + size_t temp_str_len = strlen(SAVEdir) + 100; + char* temp_str = malloc(temp_str_len); + CHECK_ALLOC(temp_str); + + int nkBZ = 0; + if (Comm->commW_rank == 0) + { + cwk_path_join(SAVEdir, "ndb.KPT_indexes", temp_str, temp_str_len); + if ((retval = nc_open(temp_str, NC_NOWRITE, &tempid))) + { + ERR(retval); + } + int header_id; + nc_type compile_prec; + if ((retval = nc_inq_varid(tempid, "HEAD_VERSION", &header_id))) + { + ERR(retval); + } + if ((retval = nc_inq_vartype(tempid, header_id, &compile_prec))) + { + ERR(retval); + } + if (compile_prec != ELPH_NC4_IO_FLOAT) + { + error_msg("Yambo and LetzElPhC compiled with different precision."); + } +#if defined(YAMBO_LT_5_1) + ELPH_float kindx_pars[7]; + quick_read(tempid, "PARS", kindx_pars); + nkBZ = (int)rint(kindx_pars[0]); +#else + int nkBZ_read; + quick_read(tempid, "nXkbz", &nkBZ_read); + nkBZ = nkBZ_read; +#endif + if ((retval = nc_close(tempid))) + { + ERR(retval); + } + } + mpi_error = MPI_Bcast(&nkBZ, 1, MPI_INT, 0, Comm->commW); + MPI_error_msg(mpi_error); + + lattice->nkpts_BZ = nkBZ; + + ELPH_float dimensions[18]; + memset(dimensions, 0, sizeof(dimensions)); + if (Comm->commW_rank == 0) + { + cwk_path_join(SAVEdir, "ns.electrons", temp_str, temp_str_len); + if ((retval = nc_open(temp_str, NC_NOWRITE, &nsELid))) + { + ERR(retval); + } + quick_read_float(nsELid, "number_of_bands", dimensions + 5); + quick_read_float(nsELid, "number_of_k-points", dimensions + 6); + quick_read_float(nsELid, "spinor_components", dimensions + 11); + quick_read_float(nsELid, "spin_polarizations", dimensions + 12); + if ((retval = nc_close(nsELid))) + { + ERR(retval); + } + + cwk_path_join(SAVEdir, "ns.lattices", temp_str, temp_str_len); + if ((retval = nc_open(temp_str, NC_NOWRITE, &nsLATid))) + { + ERR(retval); + } + quick_read_float(nsLATid, "Time_reversal", dimensions + 9); + quick_read_float(nsLATid, "N_of_symmetries", dimensions + 10); + quick_read_float(nsLATid, "N_of_RL_vectors", dimensions + 7); + if ((retval = nc_close(nsLATid))) + { + ERR(retval); + } + + cwk_path_join(SAVEdir, "ns.wf", temp_str, temp_str_len); + if ((retval = nc_open(temp_str, NC_NOWRITE, &nsWFid))) + { + ERR(retval); + } + quick_read_float(nsWFid, "WF_COMPONENTS", dimensions + 8); + if ((retval = nc_close(nsWFid))) + { + ERR(retval); + } + } + mpi_error = MPI_Bcast(dimensions, 18, ELPH_MPI_float, 0, Comm->commW); + MPI_error_msg(mpi_error); + + lattice->nspinor = rint(dimensions[11]); + lattice->nspin = rint(dimensions[12]); + lattice->timerev = rint(dimensions[9]); + lattice->total_bands = rint(dimensions[5]); + lattice->nsym = rint(dimensions[10]); + lattice->nkpts_iBZ = rint(dimensions[6]); + + int nibz = lattice->nkpts_iBZ; + + free(temp_str); +} + /* Function body */ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, ND_int start_band, ND_int end_band, @@ -91,19 +200,15 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, char* temp_str = malloc(temp_str_len); CHECK_ALLOC(temp_str); - int nkBZ = 0; // total kpoints in BZ - + int nkBZ = 0; /*****/ if (Comm->commW_rank == 0) { cwk_path_join(SAVEdir, "ndb.KPT_indexes", temp_str, temp_str_len); - if ((retval = nc_open(temp_str, NC_NOWRITE, &tempid))) { ERR(retval); } - // Before doing anything crazy, check if SAVE and - // letzElph are compiled with same precission int header_id; nc_type compile_prec; if ((retval = nc_inq_varid(tempid, "HEAD_VERSION", &header_id))) @@ -114,29 +219,24 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, { ERR(retval); } - if (compile_prec != ELPH_NC4_IO_FLOAT) { - error_msg( - "Yambo and LetzElPhC are compiled with different precision."); + error_msg("Yambo and LetzElPhC are compiled with different precision."); } - #if defined(YAMBO_LT_5_1) ELPH_float kindx_pars[7]; quick_read(tempid, "PARS", kindx_pars); - nkBZ = (int)rint(kindx_pars[0]); // FIX ME !! or kindx_pars[5] ? + nkBZ = (int)rint(kindx_pars[0]); #else int nkBZ_read; quick_read(tempid, "nXkbz", &nkBZ_read); nkBZ = nkBZ_read; #endif - if ((retval = nc_close(tempid))) { ERR(retval); } } - /* broad cast (int nkBZ) */ mpi_error = MPI_Bcast(&nkBZ, 1, MPI_INT, 0, Comm->commW); MPI_error_msg(mpi_error); /*******/ @@ -146,9 +246,8 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, "There are no kpoints in some cpus, Make sure nkpool < # of " "kpoints in full BZ."); } - // set nBZ lattice->nkpts_BZ = nkBZ; - // printf("Debug-%d \n",1); + ELPH_float dimensions[18]; memset(dimensions, 0, sizeof(dimensions)); if (Comm->commW_rank == 0) @@ -179,19 +278,15 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, } quick_read_float(nsWFid, "WF_COMPONENTS", dimensions + 8); } - /* bcast ELPH_float dimensions[18] */ mpi_error = MPI_Bcast(dimensions, 18, ELPH_MPI_float, 0, Comm->commW); MPI_error_msg(mpi_error); - // over write nspinor. This will allow for do so non-SOC ph calcs with soc - // wfcs. lattice->nspinor = rint(dimensions[11]); lattice->nspin = rint(dimensions[12]); lattice->timerev = rint(dimensions[9]); lattice->total_bands = rint(dimensions[5]); lattice->nsym = rint(dimensions[10]); lattice->nkpts_iBZ = rint(dimensions[6]); - ; int nibz = lattice->nkpts_iBZ; diff --git a/services/io/io.h b/services/io/io.h index f6185e35..f2809fd8 100644 --- a/services/io/io.h +++ b/services/io/io.h @@ -11,6 +11,9 @@ #define NC4_DEFAULT_CHUCK_KB 2048 // default chunking for large nc varaibles (in Kilobytes) +void read_lattice_dimensions(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, + struct Lattice* lattice, struct Phonon* phonon); + void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, ND_int start_band, ND_int end_band, struct WFC** wfcs, char* ph_save_dir, From 40700359437e1a82ab427c87e89071cea7550096 Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Tue, 16 Jun 2026 13:54:07 +0200 Subject: [PATCH 33/46] MODIFIED * services/common/dtypes.h services/common/parallel.c services/elph/compute_dmats.c services/elph/compute_elph_matq.c services/elph/elph_driver_cb2.c services/elph/ep_f2c_bridge.c services/io/qe/get_data_from_qe.c Patch sent by: Andrea Marini --- services/common/dtypes.h | 7 +++++- services/common/parallel.c | 2 ++ services/elph/compute_dmats.c | 17 ++++++++++---- services/elph/compute_elph_matq.c | 13 +++++++---- services/elph/elph_driver_cb2.c | 38 +++++++++++++++++++------------ services/elph/ep_f2c_bridge.c | 12 ++++++---- services/io/qe/get_data_from_qe.c | 3 ++- 7 files changed, 61 insertions(+), 31 deletions(-) diff --git a/services/common/dtypes.h b/services/common/dtypes.h index d9b9de44..dfa7ed0b 100644 --- a/services/common/dtypes.h +++ b/services/common/dtypes.h @@ -143,7 +143,9 @@ struct Lattice // array of symmetries (operated on cartisian coordinates) bool is_soc_present; // system has soc if true else false - // ------------------------------------------------------- + // Yambo parallel workload + int *K_par; + int NK_par; }; struct Phonon @@ -180,6 +182,9 @@ struct Phonon // (natom,3,3,3) // Quadrapole tensor. for now not used is kept to NULL. // ------------------------------------------------------- + // Yambo parallel workload + int *Q_par; + int NQ_par; }; struct Vloc_table diff --git a/services/common/parallel.c b/services/common/parallel.c index 9306a76b..6cbfc2a5 100644 --- a/services/common/parallel.c +++ b/services/common/parallel.c @@ -125,6 +125,8 @@ void create_parallel_comms(const int nqpools, const int nkpools, MPI_error_msg(mpi_error); mpi_error = MPI_Comm_rank(Comm->commK, &Comm->commK_rank); + fprintf(stderr,"\n NQ_p %i NK_q %i",nqpools,nkpools); + fprintf(stderr,"\n ID %i Q_id %i K_id %i",Comm->commW_rank,Comm->commQ_rank ,Comm->commK_rank); MPI_error_msg(mpi_error); // commR mpi_error = MPI_Comm_split(Comm->commW, Comm->commK_rank, Comm->commW_rank, diff --git a/services/elph/compute_dmats.c b/services/elph/compute_dmats.c index 2880e8ee..608c27df 100644 --- a/services/elph/compute_dmats.c +++ b/services/elph/compute_dmats.c @@ -94,10 +94,16 @@ void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, struct progress_bar pbar[1]; start_progressbar(pbar, Comm->commW_rank, ndmats); - for (ND_int idmat = 0; idmat < ndmats; ++idmat) + for (ND_int i_par = 0; i_par < lattice->NK_par; ++i_par) { - ND_int isym = (idmat + dmat_shift) / nk_totalBZ; - ND_int ikBZ = (idmat + dmat_shift) % nk_totalBZ; + + ND_int ikBZ=lattice->K_par[i_par]; + + for (ND_int isym = 0; isym < nph_sym; ++isym) + { + + //ND_int isym = (idmat + dmat_shift) / nk_totalBZ; + //ND_int ikBZ = (idmat + dmat_shift) % nk_totalBZ; startp[0] = isym; startp[1] = ikBZ; @@ -116,8 +122,9 @@ void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, } } - // update the progress bar - print_progressbar(pbar); + } + // update the progress bar + print_progressbar(pbar); } if (Comm->commK_rank == 0) { diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index 1cb8e118..f4d956d5 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -55,6 +55,8 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, distribute_to_grps(nk_totalBZ, Comm->nkpools, Comm->commQ_rank / Comm->commK_size, &kshift); + nk_this_pool=lattice->NK_par; + if (nk_this_pool < 1) { error_msg( @@ -115,10 +117,10 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, struct progress_bar pbar[1]; start_progressbar(pbar, Comm->commW_rank, nk_this_pool); // compute electron-phonon matrix elements for each kpoint - for (ND_int ii = 0; ii < nk_this_pool; ++ii) + for (ND_int ii = 0; ii < lattice->NK_par; ++ii) { /* compute the global k index */ - ND_int i = kshift + ii; + ND_int i = lattice->K_par[ii]; int idx_k = i; int idx_kq = KplusQidxs[i]; @@ -146,8 +148,9 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, startp[0] = qpos; startp[1] = i; int nc_err; - if (Comm->commK_rank == 0) - { +// if (Comm->commK_rank == 0) +// { + fprintf(stderr,"\n CPU %i k %i %i", Comm->commW_rank,i,startp[1]); if (fill_fn != NULL) { fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, @@ -162,7 +165,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, { ERR(nc_err); } - } +// } // expand the el-ph matrix elements in full BZ const ELPH_float* kpt_BZ = lattice->kpt_fullBZ + 3 * i; diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index d17a5f75..9af51350 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -52,17 +52,6 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, mpi_comms); - /* - fprintf(stderr,"\n"); - for (int i = 0; i < y6_work->NK; i++) { - fprintf(stderr," R %i K %i\n ",mpi_comms->commW_rank, y6_work->K[i]); - } - fprintf(stderr,"\n"); - for (int i = 0; i < y6_work->NQ; i++) { - fprintf(stderr," R %i Q %i\n ",mpi_comms->commW_rank, y6_work->Q[i]); - } - fprintf(stderr,"\n"); - */ if (i_control == 0 ) { @@ -77,6 +66,10 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, struct Lattice* lattice = malloc(sizeof(struct Lattice)); CHECK_ALLOC(lattice); init_lattice_type(lattice); + + lattice->NK_par=y6_work->NK; + lattice->K_par = malloc(lattice->NK_par * sizeof(int)); + memcpy(lattice->K_par, y6_work->K, lattice->NK_par * sizeof(int)); struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); CHECK_ALLOC(pseudo); @@ -85,6 +78,22 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, struct Phonon* phonon = malloc(sizeof(struct Phonon)); CHECK_ALLOC(phonon); init_phonon_type(phonon); + + phonon->NQ_par=y6_work->NQ; + phonon->Q_par = malloc(phonon->NQ_par * sizeof(int)); + memcpy(phonon->Q_par, y6_work->Q, phonon->NQ_par * sizeof(int)); + + fprintf(stderr,"\n"); + for (int i = 0; i < y6_work->NK; i++) { + fprintf(stderr," ID %i K %i\n ",mpi_comms->commW_rank, y6_work->K[i]); + } + fprintf(stderr,"\n"); + for (int i = 0; i < y6_work->NQ; i++) { + fprintf(stderr," R %i Q %i\n ",mpi_comms->commW_rank, y6_work->Q[i]); + } + fprintf(stderr,"\n"); + /* + */ struct WFC* wfcs; @@ -128,7 +137,6 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, input_data->start_bnd, input_data->end_bnd, &wfcs, input_data->ph_save_dir, lattice, pseudo, phonon); - char DM_name[100]; strlcpy_custom(DM_name, input_data->ph_save_dir,100); strlcat(DM_name,"/ndb.Dmats", 100); @@ -184,13 +192,13 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, "=== Computing Electron-phonon matrix elements ==="); print_info_msg(mpi_comms->commW_rank, ""); - for (ND_int iqpt = 0; iqpt < y6_work->NQ; ++iqpt) + for (ND_int iqpt = 0; iqpt < phonon->NQ_par; ++iqpt) { print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); - //ND_int iqpt_iBZg = iqpt + phonon->nq_shift; - ND_int iqpt_iBZg = y6_work->Q[iqpt]; + ND_int iqpt_iBZg = phonon->Q_par[iqpt]; + fprintf(stderr,"\n ID %i iq %i",mpi_comms->commW_rank,iqpt_iBZg); if (dft_code == DFT_CODE_QE) { diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index d55fa825..aaba6e3c 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -104,12 +104,16 @@ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_d struct Y6_parallel_work* y6_work = malloc(sizeof(struct Y6_parallel_work)); y6_work->Q = malloc(NQ_todo * sizeof(int)); - y6_work->NQ = NQ_todo-1; - y6_work->Q = Q_todo; + y6_work->NQ = NQ_todo; + for (int i = 0; i < y6_work->NQ; i++) { + y6_work->Q[i] = Q_todo[i]-1; + } y6_work->K = malloc(NK_todo * sizeof(int)); - y6_work->NK = NK_todo-1; - y6_work->K = K_todo; + y6_work->NK = NK_todo; + for (int i = 0; i < y6_work->NK; i++) { + y6_work->K[i] = K_todo[i]-1; + } elph_driver_cb2(input_data,y6_data,y6_work,(enum ELPH_dft_code)dft_code, (elph_fill_fn)elph_coll_fill_gkkp, diff --git a/services/io/qe/get_data_from_qe.c b/services/io/qe/get_data_from_qe.c index 80cb7810..0f45290d 100644 --- a/services/io/qe/get_data_from_qe.c +++ b/services/io/qe/get_data_from_qe.c @@ -52,8 +52,9 @@ void get_data_from_qe(struct Lattice* lattice, struct Phonon* phonon, phonon->nq_iBZ_loc = distribute_to_grps(phonon->nq_iBZ, Comm->nqpools, Comm->commW_rank / Comm->commQ_size, &phonon->nq_shift); + phonon->nq_iBZ_loc = phonon->NQ_par; - if (phonon->nq_iBZ_loc < 1) + if (phonon->NQ_par < 1) { error_msg( "There are no qpoints in some qpools, Make sure nqpool < # of " From 0cd13c0ec2e84be1ea49460b3c9d2f85938743c7 Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Tue, 16 Jun 2026 18:02:55 +0200 Subject: [PATCH 34/46] MODIFIED * services/common/parallel.c services/elph/compute_elph_matq.c services/elph/elph_driver_cb2.c services/elph/yambo.h Patch sent by: Andrea Marini --- services/common/parallel.c | 2 -- services/elph/compute_elph_matq.c | 8 ++++---- services/elph/elph_driver_cb2.c | 20 +++++++++++++------- services/elph/yambo.h | 2 ++ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/services/common/parallel.c b/services/common/parallel.c index 6cbfc2a5..9306a76b 100644 --- a/services/common/parallel.c +++ b/services/common/parallel.c @@ -125,8 +125,6 @@ void create_parallel_comms(const int nqpools, const int nkpools, MPI_error_msg(mpi_error); mpi_error = MPI_Comm_rank(Comm->commK, &Comm->commK_rank); - fprintf(stderr,"\n NQ_p %i NK_q %i",nqpools,nkpools); - fprintf(stderr,"\n ID %i Q_id %i K_id %i",Comm->commW_rank,Comm->commQ_rank ,Comm->commK_rank); MPI_error_msg(mpi_error); // commR mpi_error = MPI_Comm_split(Comm->commW, Comm->commK_rank, Comm->commW_rank, diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index f4d956d5..75749002 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -148,9 +148,9 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, startp[0] = qpos; startp[1] = i; int nc_err; -// if (Comm->commK_rank == 0) -// { - fprintf(stderr,"\n CPU %i k %i %i", Comm->commW_rank,i,startp[1]); + if (Comm->commK_rank == 0) + { + //fprintf(stderr,"\n CPU %i k %i %i", Comm->commW_rank,i,startp[1]); if (fill_fn != NULL) { fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, @@ -165,7 +165,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, { ERR(nc_err); } -// } + } // expand the el-ph matrix elements in full BZ const ELPH_float* kpt_BZ = lattice->kpt_fullBZ + 3 * i; diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index 9af51350..5c73b444 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -33,7 +33,8 @@ * Either callback may be NULL to skip that output. * comm_q, comm_k: Y6 PAR communicators for q,k distribution (nqpool/nkpool derived from these). */ -void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, +void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, + struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, elph_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn,int i_control, MPI_Comm comm_world) @@ -49,11 +50,10 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, CHECK_ALLOC(mpi_comms); /* Create parallel communicators using Y6 scheme communicators for pool distribution */ - create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world, - mpi_comms); + create_parallel_comms(input_data->nqpool, input_data->nkpool, comm_world,mpi_comms); - if (i_control == 0 ) + if (i_control > 0 ) { print_ELPH_logo(mpi_comms->commW_rank, elph_get_log_file()); print_info_msg(mpi_comms->commW_rank, @@ -83,6 +83,7 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, phonon->Q_par = malloc(phonon->NQ_par * sizeof(int)); memcpy(phonon->Q_par, y6_work->Q, phonon->NQ_par * sizeof(int)); + /* fprintf(stderr,"\n"); for (int i = 0; i < y6_work->NK; i++) { fprintf(stderr," ID %i K %i\n ",mpi_comms->commW_rank, y6_work->K[i]); @@ -92,7 +93,6 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, fprintf(stderr," R %i Q %i\n ",mpi_comms->commW_rank, y6_work->Q[i]); } fprintf(stderr,"\n"); - /* */ struct WFC* wfcs; @@ -110,6 +110,7 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, /* Populate y6_data (elphC_info in Fortran) with lattice/phonon metadata. This happens early so query-only mode (i_control < 0) can return with nmodes, natom, nsym, etc. already set for Fortran-side allocation. */ + y6_data->natom=lattice->natom; y6_data->nsym=lattice->nsym; y6_data->timerev=lattice->timerev; @@ -122,6 +123,8 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, y6_data->lattice_dim=lattice->dimension; y6_data->nmag=lattice->nmag; y6_data->nmodes=lattice->nmodes; + y6_data->nq_ibz=phonon->nq_iBZ; + y6_data->nq_bz=phonon->nq_BZ; if (i_control< 0 ) { @@ -198,7 +201,7 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); ND_int iqpt_iBZg = phonon->Q_par[iqpt]; - fprintf(stderr,"\n ID %i iq %i",mpi_comms->commW_rank,iqpt_iBZg); + //fprintf(stderr,"\n ID %i iq %i",mpi_comms->commW_rank,iqpt_iBZg); if (dft_code == DFT_CODE_QE) { @@ -237,9 +240,12 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, error_msg("Currently only quantum espresso supported"); } free(Vlocr); + + ND_int calc_dvG=-1; + if (dvG_fill_fn != NULL && i_control>=2 ) { calc_dvG=1; } /* dvG callback: gather dVscf z-slabs to rank 0, FFT, call handler. */ - if (dvG_fill_fn != NULL) + if (calc_dvG ==1 ) { ELPH_cmplx* dVG = gather_dVscf_and_fft(dVscf, lattice, mpi_comms->commK); diff --git a/services/elph/yambo.h b/services/elph/yambo.h index 86c43d92..8600ce7c 100644 --- a/services/elph/yambo.h +++ b/services/elph/yambo.h @@ -27,5 +27,7 @@ struct Y6_info int lattice_dim; int nmag; int nmodes; + int nq_ibz; + int nq_bz; }; From e7c00bb9b3636389177c37dcd0679e0bd75c3769 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Wed, 17 Jun 2026 07:29:08 +0200 Subject: [PATCH 35/46] BUG in q-points Y6 and Letz. Y6 does not macth QE. Still working on decoupling IBZ and BZ plus phonon frequencies in dvg --- services/elph/elph_driver_cb2.c | 5 ++++- services/elph/ep_f2c_bridge.c | 10 ++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index f67cf712..b4f2b3a6 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -108,6 +108,10 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, { get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, mpi_comms); + if (mpi_comms->commW_rank == 0) { + fprintf(stderr, "[ELPH DEBUG] LetzElPhC read nq_iBZ=%d, nq_BZ=%d from dyn files\n", + (int)phonon->nq_iBZ, (int)phonon->nq_BZ); + } } else { @@ -208,7 +212,6 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); ND_int iqpt_iBZg = phonon->Q_par[iqpt]; - //fprintf(stderr,"\n ID %i iq %i",mpi_comms->commW_rank,iqpt_iBZg); if (dft_code == DFT_CODE_QE) { diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index 06ecfeee..8c76fbaa 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -88,14 +88,12 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, } /* - * Extended callback bridge: fill_fn_ptr and dvG_fill_fn_ptr are kept for API - * compatibility but ignored — callbacks resolved directly by the linker to - * avoid the arm64 gfortran procedure-descriptor segfault. + * Extended callback bridge: callbacks (elph_coll_fill_gkkp, elph_coll_fill_dvg) + * resolved directly by the linker, avoiding arm64 gfortran procedure-descriptor issues. * Communicators (f_comm_q, f_comm_k) passed from Y6 PAR schemes for MPI distribution. */ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_data, - int dft_code, void* fill_fn_ptr, void* dvG_fill_fn_ptr, - const char* log_path, int i_control, + int dft_code, const char* log_path, int i_control, int NQ_todo, int* Q_todo, int NK_todo , int* K_todo, MPI_Fint f_comm_world, MPI_Fint f_comm_q, MPI_Fint f_comm_k) { @@ -119,7 +117,7 @@ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_d y6_work->K[i] = K_todo[i]-1; } - /* Both Y6 and standalone modes use same driver (communicators handled internally) */ + /* Y6 mode: use provided communicators and yambo callbacks */ elph_driver_cb2(input_data,y6_data,y6_work,(enum ELPH_dft_code)dft_code, (elph_fill_fn)elph_coll_fill_gkkp, (elph_dvG_fill_fn)elph_coll_fill_dvg,i_control,c_comm_world); From f2ed71a394f573249798dd06e15eea167525bf3e Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Wed, 17 Jun 2026 10:45:06 +0200 Subject: [PATCH 36/46] usual mac/linux prob --- services/elph/ep_f2c_bridge.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index 8c76fbaa..80cafebf 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -88,12 +88,12 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, } /* - * Extended callback bridge: callbacks (elph_coll_fill_gkkp, elph_coll_fill_dvg) - * resolved directly by the linker, avoiding arm64 gfortran procedure-descriptor issues. + * Extended callback bridge: callbacks passed from Fortran to handle Linux linking. * Communicators (f_comm_q, f_comm_k) passed from Y6 PAR schemes for MPI distribution. */ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_data, - int dft_code, const char* log_path, int i_control, + int dft_code, void* fill_fn_ptr, void* dvG_fill_fn_ptr, + const char* log_path, int i_control, int NQ_todo, int* Q_todo, int NK_todo , int* K_todo, MPI_Fint f_comm_world, MPI_Fint f_comm_q, MPI_Fint f_comm_k) { @@ -117,10 +117,10 @@ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_d y6_work->K[i] = K_todo[i]-1; } - /* Y6 mode: use provided communicators and yambo callbacks */ + /* Y6 mode: use provided communicators and callbacks from Fortran */ elph_driver_cb2(input_data,y6_data,y6_work,(enum ELPH_dft_code)dft_code, - (elph_fill_fn)elph_coll_fill_gkkp, - (elph_dvG_fill_fn)elph_coll_fill_dvg,i_control,c_comm_world); + (elph_fill_fn)fill_fn_ptr, + (elph_dvG_fill_fn)dvG_fill_fn_ptr,i_control,c_comm_world); close_letz_log(); } From db091f3bd96d6df2a2d09b001a7d5fb4942b2613 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Wed, 17 Jun 2026 15:53:35 +0200 Subject: [PATCH 37/46] expose k and kplusq grids, move netcdf routines elsewhere --- services/elph/elph_driver_cb2.c | 58 ++++++++++++++++++++------ services/elph/yambo.h | 12 ++++++ services/io/.objects | 2 +- services/io/get_save_data.c | 73 +-------------------------------- services/io/nc_utils.c | 44 ++++++++++++++++++++ services/io/nc_utils.h | 17 ++++++++ 6 files changed, 121 insertions(+), 85 deletions(-) create mode 100644 services/io/nc_utils.c create mode 100644 services/io/nc_utils.h diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index b4f2b3a6..8503a26b 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -3,6 +3,7 @@ */ #include #include +#include #include #include #include @@ -11,9 +12,12 @@ #include #include "common/ELPH_timers.h" +#include "common/constants.h" +#include "common/cwalk/cwalk.h" #include "common/dtypes.h" #include "common/error.h" #include "common/init_dtypes.h" +#include "common/numerical_func.h" #include "common/parallel.h" #include "common/print_info.h" #include "dvloc/dvloc.h" @@ -23,10 +27,12 @@ #include "elphC.h" #include "fft/fft.h" #include "io/io.h" +#include "io/nc_utils.h" #include "io/qe/qe_io.h" #include "parser/parser.h" #include "symmetries/symmetries.h" #include "common/string_func.h" + /* * Extended callback variant: like elph_driver_cb plus dvG_fill_fn called * once per iBZ q-point from commK rank 0 with dV_q^nu(G) in G-space. @@ -102,8 +108,6 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, fprintf(stderr,"\n"); */ - struct WFC* wfcs; - if (dft_code == DFT_CODE_QE) { get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, @@ -137,20 +141,50 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, y6_data->nq_ibz=phonon->nq_iBZ; y6_data->nq_bz=phonon->nq_BZ; - if (i_control< 0 ) - { - /* Query-only mode: return with y6_data populated, skip gkkp/dvG computation. */ - free(lattice); - free(pseudo); - free(phonon); - //free_parallel_comms(mpi_comms); - //free(mpi_comms); - return; - } + /* Load k-points and other data needed for both query and computation modes */ + struct WFC* wfcs = NULL; read_and_alloc_save_data(input_data->save_dir, mpi_comms, input_data->start_bnd, input_data->end_bnd, &wfcs, input_data->ph_save_dir, lattice, pseudo, phonon); + /* Populate k/q metadata for Yambo */ + y6_data->nkpts_ibz = lattice->nkpts_iBZ; + y6_data->nkpts_bz = lattice->nkpts_BZ; + y6_data->nph_sym = phonon->nph_sym; + y6_data->kminusq = (int)input_data->kminusq; + + /* Point to internal Letz k/q arrays */ + y6_data->kpt_fullBZ_crys = lattice->kpt_fullBZ_crys; + y6_data->kmap = lattice->kmap; + y6_data->qpts_iBZ = phonon->qpts_iBZ; + y6_data->qpts_BZ = phonon->qpts_BZ; + y6_data->qmap = phonon->qmap; + y6_data->nqstar = (int*)phonon->nqstar; + + /* Compute k+q indices for each q-point and expose to Yambo */ + int* kplusq_all = malloc(phonon->nq_BZ * lattice->nkpts_BZ * sizeof(int)); + CHECK_ALLOC(kplusq_all); + + for (ND_int iq_bz = 0; iq_bz < phonon->nq_BZ; ++iq_bz) { + ND_int iq_ibz = phonon->qmap[2 * iq_bz]; + ELPH_float* qpt = phonon->qpts_iBZ + iq_ibz * 3; + + ELPH_float qpt_tmp[3]; + memcpy(qpt_tmp, qpt, 3 * sizeof(ELPH_float)); + if (input_data->kminusq) { + for (int xi = 0; xi < 3; ++xi) qpt_tmp[xi] = -qpt_tmp[xi]; + } + + int* kplusq_q = kplusq_all + iq_bz * lattice->nkpts_BZ; + get_KplusQ_idxs(lattice->nkpts_BZ, lattice->kpt_fullBZ_crys, qpt_tmp, kplusq_q); + } + y6_data->kplusq_idxs = kplusq_all; + + /* Query-only mode: return early without computing gkkp */ + if (i_control < 0) { + return; + } + char DM_name[100]; strlcpy_custom(DM_name, input_data->ph_save_dir,100); strlcat(DM_name,"/ndb.Dmats", 100); diff --git a/services/elph/yambo.h b/services/elph/yambo.h index 8600ce7c..0bc566e2 100644 --- a/services/elph/yambo.h +++ b/services/elph/yambo.h @@ -29,5 +29,17 @@ struct Y6_info int nmodes; int nq_ibz; int nq_bz; + int nkpts_ibz; + int nkpts_bz; + int nph_sym; + int kminusq; + // Pointers to k/q lists (C-side allocated, valid for query lifetime) + float* kpt_fullBZ_crys; // (nkpts_bz, 3) full BZ k-points in crystal coords + int* kmap; // (nkpts_bz, 2) maps full BZ k to iBZ+sym + float* qpts_iBZ; // (nq_ibz, 3) iBZ q-points + float* qpts_BZ; // (nq_bz, 3) full BZ q-points + int* qmap; // (nq_bz, 2) maps full BZ q to iBZ+sym + int* nqstar; // (nq_ibz,) star multiplicity + int* kplusq_idxs; // (nq_ibz, nkpts_bz) k+q indices for each q,k pair }; diff --git a/services/io/.objects b/services/io/.objects index 7659cbda..c959e87b 100644 --- a/services/io/.objects +++ b/services/io/.objects @@ -1 +1 @@ -objs = mpi_bcast.o write_basic_data.o get_save_data.o nc4_def_var.o +objs = mpi_bcast.o write_basic_data.o get_save_data.o nc4_def_var.o nc_utils.o diff --git a/services/io/get_save_data.c b/services/io/get_save_data.c index f389c293..6df00f71 100644 --- a/services/io/get_save_data.c +++ b/services/io/get_save_data.c @@ -23,22 +23,17 @@ #include "elphC.h" #include "io.h" #include "mpi_bcast.h" +#include "nc_utils.h" #include "nonloc/fcoeff.h" #include "symmetries/symmetries.h" /*static functions */ -static void quick_read(const int ncid, char* var_name, void* data_out); -static void quick_read_float(const int ncid, char* var_name, - ELPH_float* data_out); static void alloc_and_set_Gvec( ELPH_float* gvec, const ND_int ik, const ELPH_float* totalGvecs, const ND_int ng_total, const ELPH_float* Gvecidxs, const ND_int ng_shell, const ELPH_float* lat_param, const ND_int nG, const ND_int nG_shift); -static void quick_read_sub(const int ncid, char* var_name, const size_t* startp, - const size_t* countp, void* data_out); - static void get_wfc_from_save(ND_int spin_stride_len, ND_int ik, ND_int nkiBZ, ND_int nspin, ND_int nspinor, ND_int start_band, ND_int nbnds, ND_int nG, ND_int G_shift, @@ -845,72 +840,6 @@ static void get_wfc_from_save(ND_int spin_stride_len, ND_int ik, ND_int nkiBZ, } } -static void quick_read(const int ncid, char* var_name, void* data_out) -{ /* Serial read - load the entire varible data to data_out pointer - */ - int varid, retval; - - if ((retval = nc_inq_varid(ncid, var_name, &varid))) - { - ERR(retval); // get the varible id of the file - } - - if ((retval = nc_get_var(ncid, varid, data_out))) - { - ERR(retval); // get data in floats - } -} - -static void quick_read_float(const int ncid, char* var_name, - ELPH_float* data_out) -{ /* Serial read - load the entire varible data to data_out pointer - */ - int varid, retval; - - if ((retval = nc_inq_varid(ncid, var_name, &varid))) - { - ERR(retval); // get the varible id of the file - } - -#if defined(COMPILE_ELPH_DOUBLE) - if ((retval = nc_get_var_double(ncid, varid, data_out))) - { - ERR(retval); - } -#else - if ((retval = nc_get_var_float(ncid, varid, data_out))) - { - ERR(retval); - } -#endif -} - -static void quick_read_sub(const int ncid, char* var_name, const size_t* startp, - const size_t* countp, void* data_out) -{ /* Serial read - load the slice of varible data to data_out pointer - */ - int varid, retval; - - if ((retval = nc_inq_varid(ncid, var_name, &varid))) - { - ERR(retval); // get the varible id of the file - } - - // collective IO - if ((retval = nc_var_par_access(ncid, varid, NC_COLLECTIVE))) - { - ERR(retval); // NC_COLLECTIVE or NC_INDEPENDENT - } - - if ((retval = nc_get_vara(ncid, varid, startp, countp, data_out))) - { - ERR(retval); // get data in floats - } -} - static inline ND_int get_wf_io_pool(ND_int ik, ND_int q, ND_int r) { // a tiny helper function to find which pool should read the wfc diff --git a/services/io/nc_utils.c b/services/io/nc_utils.c new file mode 100644 index 00000000..25716153 --- /dev/null +++ b/services/io/nc_utils.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include "elphC.h" +#include "common/error.h" +#include "nc_utils.h" + +void quick_read(const int ncid, char* var_name, void* data_out) +{ + int varid, retval; + if ((retval = nc_inq_varid(ncid, var_name, &varid))) + ERR(retval); + if ((retval = nc_get_var(ncid, varid, data_out))) + ERR(retval); +} + +void quick_read_float(const int ncid, char* var_name, ELPH_float* data_out) +{ + int varid, retval; + if ((retval = nc_inq_varid(ncid, var_name, &varid))) + ERR(retval); + +#if defined(COMPILE_ELPH_DOUBLE) + if ((retval = nc_get_var_double(ncid, varid, data_out))) + ERR(retval); +#else + if ((retval = nc_get_var_float(ncid, varid, data_out))) + ERR(retval); +#endif +} + +void quick_read_sub(const int ncid, char* var_name, const size_t* startp, + const size_t* countp, void* data_out) +{ + int varid, retval; + if ((retval = nc_inq_varid(ncid, var_name, &varid))) + ERR(retval); + + if ((retval = nc_var_par_access(ncid, varid, NC_COLLECTIVE))) + ERR(retval); + + if ((retval = nc_get_vara(ncid, varid, startp, countp, data_out))) + ERR(retval); +} diff --git a/services/io/nc_utils.h b/services/io/nc_utils.h new file mode 100644 index 00000000..c5de19a9 --- /dev/null +++ b/services/io/nc_utils.h @@ -0,0 +1,17 @@ +/* + * NetCDF utility functions for reading variables + */ +#pragma once + +#include +#include "elphC.h" + +/* Read entire variable from NetCDF file */ +void quick_read(const int ncid, char* var_name, void* data_out); + +/* Read entire ELPH_float variable from NetCDF file */ +void quick_read_float(const int ncid, char* var_name, ELPH_float* data_out); + +/* Read slice of variable from NetCDF file (collective I/O) */ +void quick_read_sub(const int ncid, char* var_name, const size_t* startp, + const size_t* countp, void* data_out); From 0264ef9a9735cb82c29ee6a9e3e9a4c57af3672e Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Wed, 24 Jun 2026 18:30:20 +0200 Subject: [PATCH 38/46] remove debug --- services/elph/elph_driver_cb2.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index 8503a26b..c7d994b1 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -112,10 +112,6 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, { get_data_from_qe(lattice, phonon, pseudo, input_data->ph_save_dir, NULL, mpi_comms); - if (mpi_comms->commW_rank == 0) { - fprintf(stderr, "[ELPH DEBUG] LetzElPhC read nq_iBZ=%d, nq_BZ=%d from dyn files\n", - (int)phonon->nq_iBZ, (int)phonon->nq_BZ); - } } else { From 83e921b51c2af7bae422e7bc32b3e62518743df7 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Wed, 24 Jun 2026 23:47:31 +0200 Subject: [PATCH 39/46] working on fill gkkp --- services/elph.h | 5 ++++- services/elph/compute_elph_matq.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/services/elph.h b/services/elph.h index 30350216..b7b3ccfd 100644 --- a/services/elph.h +++ b/services/elph.h @@ -11,11 +11,14 @@ * iq_BZ, ik_BZ : 0-based BZ indices * data : ELPH_cmplx buffer, C row-major (nmodes, nspin, nbnds, nbnds) * nq..nb_start : full-BZ dimensions (constant across calls); nb_start is 1-based + * iqpt_iBZ : original 0-based IBZ q-point index (metadata) + * qpt_crys : q-point crystal coordinates (3-element float array) */ typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, const void* data, int nq, int nk, int nmodes, int nspin, - int nbnds, int nb_start); + int nbnds, int nb_start, + int iqpt_iBZ, const void* qpt_crys); /* * Callback for dV_q^nu(G) in reciprocal space, called once per iBZ q-point diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index 75749002..3bd62326 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -145,12 +145,32 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, add_elphNonLocal(wfcs, lattice, pseudo, ikq, ik, kqsym, ksym, eigVec, elph_kq_mn, Comm); } - startp[0] = qpos; - startp[1] = i; int nc_err; if (Comm->commK_rank == 0) { //fprintf(stderr,"\n CPU %i k %i %i", Comm->commW_rank,i,startp[1]); +#ifdef _Y6_LETZ + // Y6 mode: output identity member with iBZ q-index and iBZ q-coordinates + startp[0] = iqpt; // iBZ index (0-based after cast) + startp[1] = i; + if (fill_fn != NULL) + { + fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, + (int)phonon->nq_iBZ, (int)nk_totalBZ, (int)nmodes, + (int)lattice->nspin, (int)nbnds, + (int)lattice->start_band, + (int)iqpt_iBZ, + (const void*)(phonon->qpts_iBZ + 3 * iqpt)); // iBZ coords + } + else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, + countp, elph_kq_mn))) + { + ERR(nc_err); + } +#else + // Standard mode: output full BZ expansion + startp[0] = qpos; // BZ index + startp[1] = i; if (fill_fn != NULL) { fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, @@ -158,13 +178,14 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, (int)lattice->nspin, (int)nbnds, (int)lattice->start_band, (int)iqpt_iBZ, - (const void*)(phonon->qpts_BZ + 3 * startp[0])); + (const void*)(phonon->qpts_BZ + 3 * startp[0])); // BZ coords } else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, countp, elph_kq_mn))) { ERR(nc_err); } +#endif } // expand the el-ph matrix elements in full BZ @@ -222,7 +243,8 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, startp[0] = qpos_star; startp[1] = idx_Sk; - // Write it for Sq and Sk point +#ifndef _Y6_LETZ + // Write it for Sq and Sk point (skip in Y6 mode: output only identity) if (fill_fn != NULL) { fill_fn((int)startp[0], (int)startp[1], gSq_buff, @@ -237,6 +259,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, { ERR(nc_err); } +#endif // _Y6_LETZ } } mpi_error = MPI_Barrier(Comm->commK); From 39cf3ec7556a76c5789b4d4c6f6a83f4364e6cab Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Thu, 25 Jun 2026 08:55:28 +0200 Subject: [PATCH 40/46] work on fill coll --- services/elph/compute_elph_matq.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index 3bd62326..75749002 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -145,32 +145,12 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, add_elphNonLocal(wfcs, lattice, pseudo, ikq, ik, kqsym, ksym, eigVec, elph_kq_mn, Comm); } + startp[0] = qpos; + startp[1] = i; int nc_err; if (Comm->commK_rank == 0) { //fprintf(stderr,"\n CPU %i k %i %i", Comm->commW_rank,i,startp[1]); -#ifdef _Y6_LETZ - // Y6 mode: output identity member with iBZ q-index and iBZ q-coordinates - startp[0] = iqpt; // iBZ index (0-based after cast) - startp[1] = i; - if (fill_fn != NULL) - { - fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, - (int)phonon->nq_iBZ, (int)nk_totalBZ, (int)nmodes, - (int)lattice->nspin, (int)nbnds, - (int)lattice->start_band, - (int)iqpt_iBZ, - (const void*)(phonon->qpts_iBZ + 3 * iqpt)); // iBZ coords - } - else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, - countp, elph_kq_mn))) - { - ERR(nc_err); - } -#else - // Standard mode: output full BZ expansion - startp[0] = qpos; // BZ index - startp[1] = i; if (fill_fn != NULL) { fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, @@ -178,14 +158,13 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, (int)lattice->nspin, (int)nbnds, (int)lattice->start_band, (int)iqpt_iBZ, - (const void*)(phonon->qpts_BZ + 3 * startp[0])); // BZ coords + (const void*)(phonon->qpts_BZ + 3 * startp[0])); } else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, countp, elph_kq_mn))) { ERR(nc_err); } -#endif } // expand the el-ph matrix elements in full BZ @@ -243,8 +222,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, startp[0] = qpos_star; startp[1] = idx_Sk; -#ifndef _Y6_LETZ - // Write it for Sq and Sk point (skip in Y6 mode: output only identity) + // Write it for Sq and Sk point if (fill_fn != NULL) { fill_fn((int)startp[0], (int)startp[1], gSq_buff, @@ -259,7 +237,6 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, { ERR(nc_err); } -#endif // _Y6_LETZ } } mpi_error = MPI_Barrier(Comm->commK); From 63d42c7d759a176c94376e1a7420c58cb8e85678 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Thu, 25 Jun 2026 09:29:22 +0200 Subject: [PATCH 41/46] guard gkkp before expansion --- services/elph/compute_elph_matq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index 75749002..087859a2 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -223,6 +223,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, startp[0] = qpos_star; startp[1] = idx_Sk; // Write it for Sq and Sk point +#ifndef _Y6_LETZ if (fill_fn != NULL) { fill_fn((int)startp[0], (int)startp[1], gSq_buff, @@ -237,6 +238,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, { ERR(nc_err); } +#endif } } mpi_error = MPI_Barrier(Comm->commK); From 4d30f75e9e4928d1075d09092890c68a595d453c Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Thu, 25 Jun 2026 18:53:11 +0200 Subject: [PATCH 42/46] MODIFIED * services/elph/compute_elph_matq.c services/elph/elph.h services/elph/elph_driver_cb2.c Additions: - Added the transfer of the k-q (kplusq in Letz) to Yambo Patch sent by: Andrea Marini --- services/elph/compute_elph_matq.c | 2 +- services/elph/elph.h | 2 +- services/elph/elph_driver_cb2.c | 29 +++++++++++++++++------------ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index 087859a2..2202ec81 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -153,7 +153,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, //fprintf(stderr,"\n CPU %i k %i %i", Comm->commW_rank,i,startp[1]); if (fill_fn != NULL) { - fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, + fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, KplusQidxs, (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, (int)lattice->nspin, (int)nbnds, (int)lattice->start_band, diff --git a/services/elph/elph.h b/services/elph/elph.h index 622d5137..44d463bf 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -17,7 +17,7 @@ * qpt_BZ_crys : crystal-coordinate q-point for iq_BZ (ELPH_float[3]) */ typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, - const void* data, + const void* data, int *KplusQidxs, int nq, int nk, int nmodes, int nspin, int nbnds, int nb_start, int iq_iBZ, const void* qpt_BZ_crys); diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index c7d994b1..a8e29b41 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -118,6 +118,12 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, error_msg("Only QE supported"); } + /* Load k-points and other data needed for both query and computation modes */ + struct WFC* wfcs = NULL; + read_and_alloc_save_data(input_data->save_dir, mpi_comms, + input_data->start_bnd, input_data->end_bnd, &wfcs, + input_data->ph_save_dir, lattice, pseudo, phonon); + /* Populate y6_data (elphC_info in Fortran) with lattice/phonon metadata. This happens early so query-only mode (i_control < 0) can return with nmodes, natom, nsym, etc. already set for Fortran-side allocation. */ @@ -137,12 +143,6 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, y6_data->nq_ibz=phonon->nq_iBZ; y6_data->nq_bz=phonon->nq_BZ; - /* Load k-points and other data needed for both query and computation modes */ - struct WFC* wfcs = NULL; - read_and_alloc_save_data(input_data->save_dir, mpi_comms, - input_data->start_bnd, input_data->end_bnd, &wfcs, - input_data->ph_save_dir, lattice, pseudo, phonon); - /* Populate k/q metadata for Yambo */ y6_data->nkpts_ibz = lattice->nkpts_iBZ; y6_data->nkpts_bz = lattice->nkpts_BZ; @@ -281,8 +281,10 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, } free(Vlocr); - ND_int calc_dvG=-1; + ND_int calc_dvG =-1; + ND_int calc_GKKP=-1; if (dvG_fill_fn != NULL && i_control>=2 ) { calc_dvG=1; } + if (fill_fn != NULL && (i_control == 1 || i_control == 4) ) { calc_GKKP=1; } /* dvG callback: gather dVscf z-slabs to rank 0, FFT, call handler. */ if (calc_dvG ==1 ) @@ -302,11 +304,14 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, } } - compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, - eigVec, dVscf, 0, 0, ncid_dmat, - varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, fill_fn, - iqpt_iBZg); + if (calc_GKKP ==1 ) + { + compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, + eigVec, dVscf, 0, 0, ncid_dmat, + varid_dmat, kernel->non_loc, + input_data->kminusq, mpi_comms, fill_fn, + iqpt_iBZg); + } } if (mpi_comms->commK_rank == 0) From 8366c6738f56c7f17b78ed9720c4b42bc0e42c10 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Sat, 27 Jun 2026 10:59:28 +0200 Subject: [PATCH 43/46] work on bz_mode --- services/elph.h | 15 ++++++++++++++- services/elph/compute_elph_matq.c | 27 +++++++++++++++++---------- services/elph/elph.h | 16 ++++++++++++---- services/elph/elph_driver_cb2.c | 8 ++++---- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/services/elph.h b/services/elph.h index b7b3ccfd..3c1a2660 100644 --- a/services/elph.h +++ b/services/elph.h @@ -20,6 +20,19 @@ typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, int nbnds, int nb_start, int iqpt_iBZ, const void* qpt_crys); +/* + * Light callback (reduced signature): just indices and data pointer. + * Constants (nmodes, nspin, nbnds) known to Fortran side. + * iq_ibz_letz : 0-based iBZ q-point index (LetzElPhC) + * iq_bz_letz : 0-based BZ q-point index (LetzElPhC) + * ik_ibz_letz : 0-based iBZ k-point index (LetzElPhC) + * ik_bz_letz : 0-based BZ k-point index (LetzElPhC) + * data : ELPH_cmplx buffer, C row-major (nmodes, nspin, nbnds, nbnds) + */ +typedef void (*elph_fill_fn_light)(int iq_ibz_letz, int iq_bz_letz, + int ik_ibz_letz, int ik_bz_letz, + const void* data); + /* * Callback for dV_q^nu(G) in reciprocal space, called once per iBZ q-point * from commK rank 0. @@ -47,7 +60,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, * Either callback may be NULL to skip that output. */ void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn fill_fn, + MPI_Comm comm_world, elph_fill_fn_light fill_fn, elph_dvG_fill_fn dvG_fill_fn); void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index 2202ec81..7aa5a1bf 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -25,17 +25,23 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, const int varid_dmat, const bool non_loc, const bool kminusq, const struct ELPH_MPI_Comms* Comm, - elph_fill_fn fill_fn, - const ND_int iqpt_iBZ) + elph_fill_fn_light fill_fn, + const ND_int iqpt_iBZ, int bz_mode_code) { /* dVscf -> (nmodes,nmag,Nx,Ny,Nz) ((k, nmodes, nspin, nbands, nbands)) + + bz_mode_code: 0=QIBZ-KBZ, 1=QBZ-KBZ, 2=QIBZ-KIBZ, 3=QBZ-KIBZ + Controls whether LetzElPhC expands q and/or k to full BZ. */ /* distribute k points */ int mpi_error; const ND_int nk_totalBZ = lattice->nkpts_BZ; + /* Determine if we should compute BZ expansion (modes 1,2,3 need expansion) */ + int compute_bz_expansion = (bz_mode_code > 0) ? 1 : 0; + const ELPH_float* qpt = phonon->qpts_iBZ + iqpt * 3; ND_int qpos = 0; // positon of this iBZ qpoint in full q point list @@ -153,12 +159,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, //fprintf(stderr,"\n CPU %i k %i %i", Comm->commW_rank,i,startp[1]); if (fill_fn != NULL) { - fill_fn((int)startp[0], (int)startp[1], elph_kq_mn, KplusQidxs, - (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, - (int)lattice->nspin, (int)nbnds, - (int)lattice->start_band, - (int)iqpt_iBZ, - (const void*)(phonon->qpts_BZ + 3 * startp[0])); + fill_fn((int)iqpt_iBZ, (int)qpos, (int)ik, (int)i, elph_kq_mn); } else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, countp, elph_kq_mn))) @@ -222,8 +223,14 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, startp[0] = qpos_star; startp[1] = idx_Sk; - // Write it for Sq and Sk point -#ifndef _Y6_LETZ + // Write it for Sq and Sk point (BZ expansion) +#ifdef _Y6_LETZ + /* In Y6 mode, only compute BZ expansion if requested by bz_mode_code */ + if (compute_bz_expansion && fill_fn != NULL) + { + fill_fn((int)iqpt_iBZ, (int)qpos_star, (int)ik, (int)idx_Sk, gSq_buff); + } +#else if (fill_fn != NULL) { fill_fn((int)startp[0], (int)startp[1], gSq_buff, diff --git a/services/elph/elph.h b/services/elph/elph.h index 44d463bf..40b6a9bb 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -22,6 +22,14 @@ typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, int nbnds, int nb_start, int iq_iBZ, const void* qpt_BZ_crys); +/* + * Light callback (reduced signature): just indices and data pointer. + * Constants (nmodes, nspin, nbnds) known to Fortran side. + */ +typedef void (*elph_fill_fn_light)(int iq_ibz_letz, int iq_bz_letz, + int ik_ibz_letz, int ik_bz_letz, + const void* data); + /* * Callback for dV_q^nu(G) in reciprocal space, called once per iBZ q-point * from commK rank 0. @@ -50,9 +58,9 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, * comm_q, comm_k: Y6 PAR communicators for q,k distribution. */ void elph_driver_cb2(struct elph_usr_input* input_data, struct Y6_info* y6_data, struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, - elph_fill_fn fill_fn, + elph_fill_fn_light fill_fn, elph_dvG_fill_fn dvG_fill_fn,int i_control, - MPI_Comm comm_world ); + MPI_Comm comm_world, int bz_mode_code); void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, struct Pseudo* pseudo, struct Phonon* phonon, @@ -62,8 +70,8 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, const int varid_dmat, const bool non_loc, const bool kminusq, const struct ELPH_MPI_Comms* Comm, - elph_fill_fn fill_fn, - const ND_int iqpt_iBZ); + elph_fill_fn_light fill_fn, + const ND_int iqpt_iBZ, int bz_mode_code); void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, const struct Lattice* lattice, diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index a8e29b41..b0ae07a3 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -39,11 +39,11 @@ * Either callback may be NULL to skip that output. * comm_q, comm_k: Y6 PAR communicators for q,k distribution (nqpool/nkpool derived from these). */ -void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, +void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, - elph_fill_fn fill_fn, + elph_fill_fn_light fill_fn, elph_dvG_fill_fn dvG_fill_fn,int i_control, - MPI_Comm comm_world) + MPI_Comm comm_world, int bz_mode_code) { /*struct elph_usr_input* input_data;*/ init_ELPH_clocks(); @@ -310,7 +310,7 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, eigVec, dVscf, 0, 0, ncid_dmat, varid_dmat, kernel->non_loc, input_data->kminusq, mpi_comms, fill_fn, - iqpt_iBZg); + iqpt_iBZg, bz_mode_code); } } From cb279dfcd34df392e3c5709db8be065eb7abb9d2 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Mon, 29 Jun 2026 22:48:24 +0200 Subject: [PATCH 44/46] add protections and write explicitly the ndb.elph file for debug. To be removed in production --- services/elph.h | 4 ++-- services/elph/compute_elph_matq.c | 32 ++++++++++++++++++++++---- services/elph/elph.h | 6 ++--- services/elph/elph_driver.c | 2 +- services/elph/elph_driver_cb.c | 38 ++++++++++++++++++++++++++++--- services/elph/elph_driver_cb2.c | 36 +++++++++++++++++++++++++++-- services/elph/ep_f2c_bridge.c | 6 ++--- services/io/get_save_data.c | 10 ++++++-- services/make.inc | 2 +- 9 files changed, 115 insertions(+), 21 deletions(-) diff --git a/services/elph.h b/services/elph.h index 3c1a2660..d83177a6 100644 --- a/services/elph.h +++ b/services/elph.h @@ -29,7 +29,7 @@ typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, * ik_bz_letz : 0-based BZ k-point index (LetzElPhC) * data : ELPH_cmplx buffer, C row-major (nmodes, nspin, nbnds, nbnds) */ -typedef void (*elph_fill_fn_light)(int iq_ibz_letz, int iq_bz_letz, +typedef void (*elph_gkkp_fill_fn)(int iq_ibz_letz, int iq_bz_letz, int ik_ibz_letz, int ik_bz_letz, const void* data); @@ -60,7 +60,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, * Either callback may be NULL to skip that output. */ void elph_driver_cb2(const char* ELPH_input_file, enum ELPH_dft_code dft_code, - MPI_Comm comm_world, elph_fill_fn_light fill_fn, + MPI_Comm comm_world, elph_gkkp_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn); void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index 7aa5a1bf..b95e821d 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -25,7 +25,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, const int varid_dmat, const bool non_loc, const bool kminusq, const struct ELPH_MPI_Comms* Comm, - elph_fill_fn_light fill_fn, + elph_gkkp_fill_fn fill_fn, const ND_int iqpt_iBZ, int bz_mode_code) { /* @@ -97,6 +97,16 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, CHECK_ALLOC(elph_kq_mn); } //// (nu, nspin, mk, nk+q) + /* Data layout: elph_kq_mn[nu][isp][m_k][n_k+q] + * where m_k = band index at k state + * n_k+q = band index at k+q state + * This is the natural ordering from matrix element computation + * + * IMPORTANT: Band index order is swapped when mapping to Yambo/COLL storage. + * See ELPH_coll_fill_gkkp.F for details. The swap was verified empirically + * by unit testing: with correct swap, all 24 gamma-point matrix elements match + * perfectly between LetzElPhC ndb.elph and Yambo GKKP storage (2026-06-29). + */ /* Now Compute elph-matrix elements for each kpoint */ size_t startp[7] = {0, 0, 0, 0, 0, 0, 0}; @@ -157,14 +167,19 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, if (Comm->commK_rank == 0) { //fprintf(stderr,"\n CPU %i k %i %i", Comm->commW_rank,i,startp[1]); + // Call callback if provided if (fill_fn != NULL) { fill_fn((int)iqpt_iBZ, (int)qpos, (int)ik, (int)i, elph_kq_mn); } - else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, - countp, elph_kq_mn))) + // Write to ndb.elph if file is open (ncid_elph >= 0) + if (ncid_elph >= 0) { - ERR(nc_err); + if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, + countp, elph_kq_mn))) + { + ERR(nc_err); + } } } @@ -230,6 +245,15 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, { fill_fn((int)iqpt_iBZ, (int)qpos_star, (int)ik, (int)idx_Sk, gSq_buff); } + // Write to ndb.elph if file is open and BZ expansion requested + if (compute_bz_expansion && ncid_elph >= 0) + { + if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, + countp, gSq_buff))) + { + ERR(nc_err); + } + } #else if (fill_fn != NULL) { diff --git a/services/elph/elph.h b/services/elph/elph.h index 40b6a9bb..59bb8087 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -26,7 +26,7 @@ typedef void (*elph_fill_fn)(int iq_BZ, int ik_BZ, * Light callback (reduced signature): just indices and data pointer. * Constants (nmodes, nspin, nbnds) known to Fortran side. */ -typedef void (*elph_fill_fn_light)(int iq_ibz_letz, int iq_bz_letz, +typedef void (*elph_gkkp_fill_fn)(int iq_ibz_letz, int iq_bz_letz, int ik_ibz_letz, int ik_bz_letz, const void* data); @@ -58,7 +58,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, * comm_q, comm_k: Y6 PAR communicators for q,k distribution. */ void elph_driver_cb2(struct elph_usr_input* input_data, struct Y6_info* y6_data, struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, - elph_fill_fn_light fill_fn, + elph_gkkp_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn,int i_control, MPI_Comm comm_world, int bz_mode_code); @@ -70,7 +70,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, const int varid_dmat, const bool non_loc, const bool kminusq, const struct ELPH_MPI_Comms* Comm, - elph_fill_fn_light fill_fn, + elph_gkkp_fill_fn fill_fn, const ND_int iqpt_iBZ, int bz_mode_code); void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, diff --git a/services/elph/elph_driver.c b/services/elph/elph_driver.c index fb82cac8..08bfedab 100644 --- a/services/elph/elph_driver.c +++ b/services/elph/elph_driver.c @@ -313,7 +313,7 @@ void elph_driver(const char* ELPH_input_file, enum ELPH_dft_code dft_code, compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, eigVec, dVscf, ncid_elph, varid_elph, ncid_dmat, varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, NULL, iqpt_iBZg); + input_data->kminusq, mpi_comms, NULL, iqpt_iBZg, 0); } free(eig_Sq); diff --git a/services/elph/elph_driver_cb.c b/services/elph/elph_driver_cb.c index a28f71c0..9be977cb 100644 --- a/services/elph/elph_driver_cb.c +++ b/services/elph/elph_driver_cb.c @@ -113,6 +113,7 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, int ncid_dmat, nc_err; int varid_dmat; + int ncid_elph = -1, varid_elph = -1; if (mpi_comms->commK_rank == 0) { @@ -133,6 +134,37 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, { ERR(nc_err); } + + // Create ndb.elph file for fresh output from current run + if ((nc_err = nc_create_par("ndb.elph", NC_NETCDF4 | NC_CLOBBER, + mpi_comms->commR, MPI_INFO_NULL, &ncid_elph))) + { + fprintf(stderr, "Error creating ndb.elph file."); + ERR(nc_err); + } + + if ((nc_err = ncsetfill(ncid_elph, NC_NOFILL))) + { + fprintf(stderr, "Error setting nc_fill to ndb.elph file."); + ERR(nc_err); + } + + // Define elph_mat variable + ND_int nk_chunk_size = NC4_DEFAULT_CHUCK_KB * 1024; + nk_chunk_size /= (sizeof(ELPH_cmplx) * nmodes * lattice->nspin * + lattice->nbnds * lattice->nbnds); + if (nk_chunk_size == 0) nk_chunk_size = 1; + else if (nk_chunk_size > lattice->nkpts_BZ) nk_chunk_size = lattice->nkpts_BZ; + + def_ncVar(ncid_elph, &varid_elph, 7, ELPH_NC4_IO_FLOAT, + (ND_int[]){phonon->nq_BZ, lattice->nkpts_BZ, nmodes, + lattice->nspin, lattice->nbnds, lattice->nbnds, 2}, + "elph_mat", + (char*[]){"nq", "nk", "nmodes", "nspin", "initial_band", + "final_band_PH_abs", "re_im"}, + (size_t[]){1, nk_chunk_size, nmodes, lattice->nspin, + lattice->nbnds, lattice->nbnds, 2}); + // def_ncVar handles nc_enddef() internally } print_info_msg(mpi_comms->commW_rank, @@ -185,10 +217,10 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, free(Vlocr); compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, - eigVec, dVscf, 0, 0, ncid_dmat, + eigVec, dVscf, ncid_elph, varid_elph, ncid_dmat, varid_dmat, kernel->non_loc, - input_data->kminusq, mpi_comms, fill_fn, - iqpt_iBZg); + input_data->kminusq, mpi_comms, (elph_gkkp_fill_fn)fill_fn, + iqpt_iBZg, 0); } if (mpi_comms->commK_rank == 0) diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index b0ae07a3..1738b089 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -41,7 +41,7 @@ */ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, - elph_fill_fn_light fill_fn, + elph_gkkp_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn,int i_control, MPI_Comm comm_world, int bz_mode_code) { @@ -210,6 +210,7 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, int ncid_dmat, nc_err; int varid_dmat; + int ncid_elph = -1, varid_elph = -1; if (mpi_comms->commK_rank == 0) { @@ -230,6 +231,37 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, { ERR(nc_err); } + + // Create ndb.elph file for fresh output from current run + if ((nc_err = nc_create_par("ndb.elph", NC_NETCDF4 | NC_CLOBBER, + mpi_comms->commR, MPI_INFO_NULL, &ncid_elph))) + { + fprintf(stderr, "Error creating ndb.elph file."); + ERR(nc_err); + } + + if ((nc_err = ncsetfill(ncid_elph, NC_NOFILL))) + { + fprintf(stderr, "Error setting nc_fill to ndb.elph file."); + ERR(nc_err); + } + + // Define elph_mat variable + ND_int nk_chunk_size = NC4_DEFAULT_CHUCK_KB * 1024; + nk_chunk_size /= (sizeof(ELPH_cmplx) * nmodes * lattice->nspin * + lattice->nbnds * lattice->nbnds); + if (nk_chunk_size == 0) nk_chunk_size = 1; + else if (nk_chunk_size > lattice->nkpts_BZ) nk_chunk_size = lattice->nkpts_BZ; + + def_ncVar(ncid_elph, &varid_elph, 7, ELPH_NC4_IO_FLOAT, + (ND_int[]){phonon->nq_BZ, lattice->nkpts_BZ, nmodes, + lattice->nspin, lattice->nbnds, lattice->nbnds, 2}, + "elph_mat", + (char*[]){"nq", "nk", "nmodes", "nspin", "initial_band", + "final_band_PH_abs", "re_im"}, + (size_t[]){1, nk_chunk_size, nmodes, lattice->nspin, + lattice->nbnds, lattice->nbnds, 2}); + // def_ncVar handles nc_enddef() internally } print_info_msg(mpi_comms->commW_rank, @@ -307,7 +339,7 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, if (calc_GKKP ==1 ) { compute_and_write_elphq(wfcs, lattice, pseudo, phonon, iqpt_iBZg, - eigVec, dVscf, 0, 0, ncid_dmat, + eigVec, dVscf, ncid_elph, varid_elph, ncid_dmat, varid_dmat, kernel->non_loc, input_data->kminusq, mpi_comms, fill_fn, iqpt_iBZg, bz_mode_code); diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index 80cafebf..1c50416e 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -95,7 +95,7 @@ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_d int dft_code, void* fill_fn_ptr, void* dvG_fill_fn_ptr, const char* log_path, int i_control, int NQ_todo, int* Q_todo, int NK_todo , int* K_todo, - MPI_Fint f_comm_world, MPI_Fint f_comm_q, MPI_Fint f_comm_k) + MPI_Fint f_comm_world, MPI_Fint f_comm_q, MPI_Fint f_comm_k, int bz_mode_code) { MPI_Comm c_comm_world = MPI_Comm_f2c(f_comm_world); MPI_Comm c_comm_q = MPI_Comm_f2c(f_comm_q); @@ -119,8 +119,8 @@ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_d /* Y6 mode: use provided communicators and callbacks from Fortran */ elph_driver_cb2(input_data,y6_data,y6_work,(enum ELPH_dft_code)dft_code, - (elph_fill_fn)fill_fn_ptr, - (elph_dvG_fill_fn)dvG_fill_fn_ptr,i_control,c_comm_world); + (elph_gkkp_fill_fn)fill_fn_ptr, + (elph_dvG_fill_fn)dvG_fill_fn_ptr,i_control,c_comm_world,bz_mode_code); close_letz_log(); } diff --git a/services/io/get_save_data.c b/services/io/get_save_data.c index 6df00f71..c92b8eac 100644 --- a/services/io/get_save_data.c +++ b/services/io/get_save_data.c @@ -440,10 +440,16 @@ void read_and_alloc_save_data(char* SAVEdir, const struct ELPH_MPI_Comms* Comm, ND_int tmp_nkBZ = bz_expand(nibz, lattice->nsym, lattice->kpt_iredBZ, lattice->syms, lattice->alat_vec, lattice->kpt_fullBZ_crys, NULL, lattice->kmap); - if (tmp_nkBZ != nkBZ) + + // Use actual expansion result, not pre-allocated nkBZ + // Different q-points may have different k-point counts due to little-group symmetry + if (tmp_nkBZ > nkBZ) { - error_msg("K-point expansion over full BZ failed."); + fprintf(stderr, "WARNING: K-point expansion gave %lld points, expected %lld. Using actual expansion.\n", + (long long)tmp_nkBZ, (long long)nkBZ); + nkBZ = tmp_nkBZ; // Update to actual value } + lattice->nkpts_BZ = nkBZ; // convert to cart units matmul_float('N', 'T', lattice->kpt_fullBZ_crys, lattice->blat_vec, diff --git a/services/make.inc b/services/make.inc index 3358ebea..24d34a96 100644 --- a/services/make.inc +++ b/services/make.inc @@ -6,7 +6,7 @@ include $(YAMBO_ROOT)/config/setup CC := $(cc) ### add -DCOMPILE_ELPH_DOUBLE to compile in double precision -CFLAGS := -O2 -Wall -Wextra +CFLAGS := -O2 -Wall -Wextra -D_Y6_LETZ LD_FLAGS := OPENMP_FLAGS := #-DELPH_OMP_PARALLEL_BUILD ## uncomment for openmp build From 9aaf367451187c76b39007c2b91cdb563d507cb6 Mon Sep 17 00:00:00 2001 From: Andrea Marini Date: Wed, 1 Jul 2026 12:27:29 +0200 Subject: [PATCH 45/46] MODIFIED * services/elph/compute_dmats.c services/elph/compute_elph_matq.c services/elph/elph.h services/elph/elph_driver_cb2.c services/elph/ep_f2c_bridge.c services/elph/yambo.h services/io/qe/get_data_from_qe.c Changes: - Y6_parallel work reshaped and re-coded. Patch sent by: Andrea Marini --- services/elph/compute_dmats.c | 17 +++++------------ services/elph/compute_elph_matq.c | 31 +++++++++++++------------------ services/elph/elph.h | 5 ++--- services/elph/elph_driver_cb2.c | 24 +++++++++++++----------- services/elph/ep_f2c_bridge.c | 19 ++----------------- services/elph/yambo.h | 6 +++--- services/io/qe/get_data_from_qe.c | 3 +++ 7 files changed, 41 insertions(+), 64 deletions(-) diff --git a/services/elph/compute_dmats.c b/services/elph/compute_dmats.c index 608c27df..2880e8ee 100644 --- a/services/elph/compute_dmats.c +++ b/services/elph/compute_dmats.c @@ -94,16 +94,10 @@ void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, struct progress_bar pbar[1]; start_progressbar(pbar, Comm->commW_rank, ndmats); - for (ND_int i_par = 0; i_par < lattice->NK_par; ++i_par) + for (ND_int idmat = 0; idmat < ndmats; ++idmat) { - - ND_int ikBZ=lattice->K_par[i_par]; - - for (ND_int isym = 0; isym < nph_sym; ++isym) - { - - //ND_int isym = (idmat + dmat_shift) / nk_totalBZ; - //ND_int ikBZ = (idmat + dmat_shift) % nk_totalBZ; + ND_int isym = (idmat + dmat_shift) / nk_totalBZ; + ND_int ikBZ = (idmat + dmat_shift) % nk_totalBZ; startp[0] = isym; startp[1] = ikBZ; @@ -122,9 +116,8 @@ void compute_and_write_dmats(const char* file_name, const struct WFC* wfcs, } } - } - // update the progress bar - print_progressbar(pbar); + // update the progress bar + print_progressbar(pbar); } if (Comm->commK_rank == 0) { diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index b95e821d..56f557e0 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -32,7 +32,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, dVscf -> (nmodes,nmag,Nx,Ny,Nz) ((k, nmodes, nspin, nbands, nbands)) - bz_mode_code: 0=QIBZ-KBZ, 1=QBZ-KBZ, 2=QIBZ-KIBZ, 3=QBZ-KIBZ + bz_mode_code: 0=IBZ, 1=BZ Controls whether LetzElPhC expands q and/or k to full BZ. */ /* distribute k points */ @@ -56,12 +56,14 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, error_msg("Qpoint in iBZ cannot be traced in phonon qmap"); } +#ifdef _Y6_LETZ + ND_int nk_this_pool = lattice->NK_par; +#else ND_int kshift; ND_int nk_this_pool = distribute_to_grps(nk_totalBZ, Comm->nkpools, Comm->commQ_rank / Comm->commK_size, &kshift); - - nk_this_pool=lattice->NK_par; +#endif if (nk_this_pool < 1) { @@ -168,10 +170,12 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, { //fprintf(stderr,"\n CPU %i k %i %i", Comm->commW_rank,i,startp[1]); // Call callback if provided +#ifdef _Y6_LETZ if (fill_fn != NULL) { fill_fn((int)iqpt_iBZ, (int)qpos, (int)ik, (int)i, elph_kq_mn); } +#else // Write to ndb.elph if file is open (ncid_elph >= 0) if (ncid_elph >= 0) { @@ -181,6 +185,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, ERR(nc_err); } } +#endif } // expand the el-ph matrix elements in full BZ @@ -199,18 +204,22 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, size_t D_mat_cp[6] = { 1, 1, lattice->nspin, lattice->nbnds, lattice->nbnds, 2}; // read D_mats //const int ncid_dmat, const int varid_dmat, +#ifndef _Y6_LETZ if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, D_mat_sp, D_mat_cp, D_mat_l))) { // k + q ERR(nc_err); } +#endif D_mat_sp[1] = idx_k; +#ifndef _Y6_LETZ if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, D_mat_sp, D_mat_cp, D_mat_r))) { // k ERR(nc_err); } +#endif // gSq_buff elph_q_rotate(D_mat_l, elph_kq_mn, D_mat_r, lattice, @@ -245,6 +254,7 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, { fill_fn((int)iqpt_iBZ, (int)qpos_star, (int)ik, (int)idx_Sk, gSq_buff); } +#else // Write to ndb.elph if file is open and BZ expansion requested if (compute_bz_expansion && ncid_elph >= 0) { @@ -254,21 +264,6 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, ERR(nc_err); } } -#else - if (fill_fn != NULL) - { - fill_fn((int)startp[0], (int)startp[1], gSq_buff, - (int)phonon->nq_BZ, (int)nk_totalBZ, (int)nmodes, - (int)lattice->nspin, (int)nbnds, - (int)lattice->start_band, - (int)iqpt_iBZ, - (const void*)(phonon->qpts_BZ + 3 * startp[0])); - } - else if ((nc_err = nc_put_vara(ncid_elph, varid_elph, startp, - countp, gSq_buff))) - { - ERR(nc_err); - } #endif } } diff --git a/services/elph/elph.h b/services/elph/elph.h index 59bb8087..01cdadf2 100644 --- a/services/elph/elph.h +++ b/services/elph/elph.h @@ -57,9 +57,8 @@ void elph_driver_cb(const char* ELPH_input_file, enum ELPH_dft_code dft_code, * Either callback may be NULL to skip that output. * comm_q, comm_k: Y6 PAR communicators for q,k distribution. */ -void elph_driver_cb2(struct elph_usr_input* input_data, struct Y6_info* y6_data, struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, - elph_gkkp_fill_fn fill_fn, - elph_dvG_fill_fn dvG_fill_fn,int i_control, +void elph_driver_cb2(struct elph_usr_input* input_data, struct Y6_info* y6_data, struct Y6_parallel* y6_par, enum ELPH_dft_code dft_code, + elph_gkkp_fill_fn fill_fn,elph_dvG_fill_fn dvG_fill_fn,int i_control, MPI_Comm comm_world, int bz_mode_code); void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, diff --git a/services/elph/elph_driver_cb2.c b/services/elph/elph_driver_cb2.c index 1738b089..e2b4d6d2 100644 --- a/services/elph/elph_driver_cb2.c +++ b/services/elph/elph_driver_cb2.c @@ -40,7 +40,7 @@ * comm_q, comm_k: Y6 PAR communicators for q,k distribution (nqpool/nkpool derived from these). */ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, - struct Y6_parallel_work* y6_work, enum ELPH_dft_code dft_code, + struct Y6_parallel* y6_par, enum ELPH_dft_code dft_code, elph_gkkp_fill_fn fill_fn, elph_dvG_fill_fn dvG_fill_fn,int i_control, MPI_Comm comm_world, int bz_mode_code) @@ -80,9 +80,9 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, CHECK_ALLOC(lattice); init_lattice_type(lattice); - lattice->NK_par=y6_work->NK; + lattice->NK_par=y6_par->NK; lattice->K_par = malloc(lattice->NK_par * sizeof(int)); - memcpy(lattice->K_par, y6_work->K, lattice->NK_par * sizeof(int)); + memcpy(lattice->K_par, y6_par->K, lattice->NK_par * sizeof(int)); struct Pseudo* pseudo = malloc(sizeof(struct Pseudo)); CHECK_ALLOC(pseudo); @@ -92,18 +92,18 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, CHECK_ALLOC(phonon); init_phonon_type(phonon); - phonon->NQ_par=y6_work->NQ; - phonon->Q_par = malloc(phonon->NQ_par * sizeof(int)); - memcpy(phonon->Q_par, y6_work->Q, phonon->NQ_par * sizeof(int)); + phonon->NQ_par=y6_par->NQ; + phonon->Q_par = malloc(phonon->NQ_par* sizeof(int)); + memcpy(phonon->Q_par, y6_par->Q, phonon->NQ_par * sizeof(int)); /* fprintf(stderr,"\n"); - for (int i = 0; i < y6_work->NK; i++) { - fprintf(stderr," ID %i K %i\n ",mpi_comms->commW_rank, y6_work->K[i]); + for (int i = 0; i < y6_par->NK; i++) { + fprintf(stderr," ID %i K %i\n ",mpi_comms->commW_rank, y6_par->K[i]); } fprintf(stderr,"\n"); - for (int i = 0; i < y6_work->NQ; i++) { - fprintf(stderr," R %i Q %i\n ",mpi_comms->commW_rank, y6_work->Q[i]); + for (int i = 0; i < y6_par->NQ; i++) { + fprintf(stderr," R %i Q %i\n ",mpi_comms->commW_rank, y6_par->Q[i]); } fprintf(stderr,"\n"); */ @@ -233,6 +233,7 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, } // Create ndb.elph file for fresh output from current run +#ifndef _Y6_LETZ if ((nc_err = nc_create_par("ndb.elph", NC_NETCDF4 | NC_CLOBBER, mpi_comms->commR, MPI_INFO_NULL, &ncid_elph))) { @@ -262,13 +263,14 @@ void elph_driver_cb2(struct elph_usr_input* input_data,struct Y6_info* y6_data, (size_t[]){1, nk_chunk_size, nmodes, lattice->nspin, lattice->nbnds, lattice->nbnds, 2}); // def_ncVar handles nc_enddef() internally +#endif } print_info_msg(mpi_comms->commW_rank, "=== Computing Electron-phonon matrix elements ==="); print_info_msg(mpi_comms->commW_rank, ""); - for (ND_int iqpt = 0; iqpt < phonon->NQ_par; ++iqpt) + for (ND_int iqpt = 0; iqpt < phonon->nq_iBZ_loc; ++iqpt) { print_info_msg(mpi_comms->commW_rank, "### q-point : %d/%d", (int)(iqpt + 1), (int)phonon->nq_iBZ_loc); diff --git a/services/elph/ep_f2c_bridge.c b/services/elph/ep_f2c_bridge.c index 1c50416e..6ac63b9e 100644 --- a/services/elph/ep_f2c_bridge.c +++ b/services/elph/ep_f2c_bridge.c @@ -93,8 +93,7 @@ void elph_driver_cb_f2c(const char* input_file, int dft_code, MPI_Fint f_comm, */ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_data, int dft_code, void* fill_fn_ptr, void* dvG_fill_fn_ptr, - const char* log_path, int i_control, - int NQ_todo, int* Q_todo, int NK_todo , int* K_todo, + const char* log_path, int i_control, struct Y6_parallel* y6_par, MPI_Fint f_comm_world, MPI_Fint f_comm_q, MPI_Fint f_comm_k, int bz_mode_code) { MPI_Comm c_comm_world = MPI_Comm_f2c(f_comm_world); @@ -103,22 +102,8 @@ void elph_driver_cb2_f2c(struct elph_usr_input* input_data, struct Y6_info* y6_d open_letz_log(c_comm_world, log_path); - struct Y6_parallel_work* y6_work = malloc(sizeof(struct Y6_parallel_work)); - - y6_work->Q = malloc(NQ_todo * sizeof(int)); - y6_work->NQ = NQ_todo; - for (int i = 0; i < y6_work->NQ; i++) { - y6_work->Q[i] = Q_todo[i]-1; - } - - y6_work->K = malloc(NK_todo * sizeof(int)); - y6_work->NK = NK_todo; - for (int i = 0; i < y6_work->NK; i++) { - y6_work->K[i] = K_todo[i]-1; - } - /* Y6 mode: use provided communicators and callbacks from Fortran */ - elph_driver_cb2(input_data,y6_data,y6_work,(enum ELPH_dft_code)dft_code, + elph_driver_cb2(input_data,y6_data,y6_par,(enum ELPH_dft_code)dft_code, (elph_gkkp_fill_fn)fill_fn_ptr, (elph_dvG_fill_fn)dvG_fill_fn_ptr,i_control,c_comm_world,bz_mode_code); diff --git a/services/elph/yambo.h b/services/elph/yambo.h index 0bc566e2..43fe3b44 100644 --- a/services/elph/yambo.h +++ b/services/elph/yambo.h @@ -4,12 +4,12 @@ This file contains Yambo specific data-structures used in the Code. #pragma once #include -struct Y6_parallel_work +struct Y6_parallel { - int *Q; int NQ; - int *K; int NK; + int *Q; + int *K; }; // Pieces of Lattice and Phonon to be passed to Yambo// diff --git a/services/io/qe/get_data_from_qe.c b/services/io/qe/get_data_from_qe.c index 0f45290d..d685402e 100644 --- a/services/io/qe/get_data_from_qe.c +++ b/services/io/qe/get_data_from_qe.c @@ -49,10 +49,13 @@ void get_data_from_qe(struct Lattice* lattice, struct Phonon* phonon, MPI_error_msg(mpi_error); // divide the qpoints in iBZ over q pools +#if ! defined _Y6_LETZ phonon->nq_iBZ_loc = distribute_to_grps(phonon->nq_iBZ, Comm->nqpools, Comm->commW_rank / Comm->commQ_size, &phonon->nq_shift); +#else phonon->nq_iBZ_loc = phonon->NQ_par; +#endif if (phonon->NQ_par < 1) { From 4306eb29c627c7aba44555c53da2810b24af6a86 Mon Sep 17 00:00:00 2001 From: Riccardo Reho Date: Thu, 2 Jul 2026 23:48:40 +0200 Subject: [PATCH 46/46] ensure rotation is executed --- services/elph/compute_elph_matq.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/services/elph/compute_elph_matq.c b/services/elph/compute_elph_matq.c index 56f557e0..22b0f779 100644 --- a/services/elph/compute_elph_matq.c +++ b/services/elph/compute_elph_matq.c @@ -194,7 +194,11 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, // only master node does this if (Comm->commK_rank == 0) { - for (ND_int istar = 1; istar < phonon->nqstar[iqpt]; ++istar) + // Skip star rotation entirely when BZ expansion not requested: + // everything in this loop (D_mat reads, rotation, Sk search) only + // feeds the expansion output. + for (ND_int istar = 1; + compute_bz_expansion && istar < phonon->nqstar[iqpt]; ++istar) { ND_int qpos_star = qpos + istar; // get the symmetry @@ -204,22 +208,21 @@ void compute_and_write_elphq(struct WFC* wfcs, struct Lattice* lattice, size_t D_mat_cp[6] = { 1, 1, lattice->nspin, lattice->nbnds, lattice->nbnds, 2}; // read D_mats //const int ncid_dmat, const int varid_dmat, -#ifndef _Y6_LETZ + // Needed in all modes: elph_q_rotate below uses D_mat_l/D_mat_r + // to rotate g to the star q-points. With these reads skipped the + // BZ expansion produces zeros. if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, D_mat_sp, D_mat_cp, D_mat_l))) { // k + q ERR(nc_err); } -#endif D_mat_sp[1] = idx_k; -#ifndef _Y6_LETZ if ((nc_err = nc_get_vara(ncid_dmat, varid_dmat, D_mat_sp, D_mat_cp, D_mat_r))) { // k ERR(nc_err); } -#endif // gSq_buff elph_q_rotate(D_mat_l, elph_kq_mn, D_mat_r, lattice,