/*+ ARES/HADES/BORG Package -- ./libLSS/data/window3d_post.hpp Copyright (C) 2014-2020 Guilhem Lavaux Copyright (C) 2009-2020 Jens Jasche Additional contributions from: Guilhem Lavaux (2023) +*/ #ifndef __LIBLSS_DATA_WINDOW_3D_POST_HPP #define __LIBLSS_DATA_WINDOW_3D_POST_HPP #include #include #include "libLSS/mpi/generic_mpi.hpp" #include "libLSS/tools/openmp.hpp" #include #include #include #include #include "libLSS/tools/console.hpp" #include "libLSS/samplers/core/types_samplers.hpp" #include "libLSS/tools/mpi_fftw_helper.hpp" #include "libLSS/tools/fusewrapper.hpp" namespace LibLSS { namespace convolveDetails { template void buildKernel(FFTW_Manager_3d& mgr, RealArray& real_data) { constexpr double KernelCore[2] = {1, 0.5}; decltype(mgr.N0) N[3] = {mgr.N0, mgr.N1, mgr.N2}; for (int i = -1; i <= 1; i++) { size_t ri = (i < 0) ? (N[0]+i) : i; if (!mgr.on_core(ri)) continue; size_t ai = std::abs(i); for (int j = -1; j<= 1; j++) { size_t rj = (j < 0) ? (N[1]+j) : j; size_t aj = std::abs(j); for (int k = -1; k <= 1; k++) { size_t rk = (k < 0) ? (N[2]+k) : k; size_t ak = std::abs(k); real_data[ri][rj][rk] = KernelCore[ai]*KernelCore[aj]*KernelCore[ak]; } } } } } template void convolve_selection_cic(MPI_Communication *comm, SelectionArray& sel_array, T const* N) { typedef FFTW_Manager_3d DFT_Manager; typedef typename DFT_Manager::plan_type plan_type; ConsoleContext ctx("convolution of selection function"); DFT_Manager mgr(N[0], N[1], N[2], comm); Uninit_FFTW_Real_Array real_data_p(mgr.extents_real(), mgr.allocator_real); Uninit_FFTW_Complex_Array complex_data_p(mgr.extents_complex(), mgr.allocator_complex); Uninit_FFTW_Complex_Array kernel_data_p(mgr.extents_complex(), mgr.allocator_complex); auto real_data = real_data_p.get_array(); auto complex_data = complex_data_p.get_array(); auto kernel_data = kernel_data_p.get_array(); auto wc = fwrap(complex_data); auto wr = fwrap(real_data); auto kc = fwrap(kernel_data); ctx.print("Create plans"); plan_type analysis_plan = mgr.create_r2c_plan(real_data.data(), complex_data.data()); plan_type synthesis_plan = mgr.create_c2r_plan(complex_data.data(), real_data.data()); ctx.print("Kernel building"); wr = 0; convolveDetails::buildKernel(mgr, real_data); mgr.execute_r2c(analysis_plan, real_data.data(), kernel_data.data()); ctx.print("Convolve"); LibLSS::copy_array(real_data, sel_array); mgr.execute_r2c(analysis_plan, real_data.data(), complex_data.data()); wc = wc * kc * (1.0/(N[0]*N[1]*N[2])); mgr.execute_c2r(synthesis_plan, complex_data.data(), real_data.data()); auto S = fwrap(sel_array) ; // This is a mask operation, if the condition is true, then S is copied on itself (thus noop). // If the condition is false, then the value is cleared with zero. The wrapping of constant // is not trivial at the moment. S = mask((S>0)&&(wr>=0), S, fwrap(S.fautowrap(0))); ctx.print("Cleaning up"); mgr.destroy_plan(analysis_plan); mgr.destroy_plan(synthesis_plan); } } #endif