Quantum 3xplorer (Q3)
An AI-native quantum simulation engine
Loading...
Searching...
No Matches
pair.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * PlanewaveFFTPair — charge-density and wavefunction FFT grids sized together.
5 */
6
12#include <memory>
13
14namespace q3 {
15
17 public:
18 /**
19 * @param use_exact_wavefunction_grid false (default) sizes the wavefunction grid for
20 * 2 x ecutwfc; true sizes it exactly, for 4 x ecutwfc, as pw.x does. See
21 * InputData::use_exact_wavefunction_grid.
22 */
23 void initialize(const FFTGridFactory& fft_grid_factory,
24 const Crystal& crystal_structure,
25 Real energy_cutoff_charge_density,
26 Real energy_cutoff_wavefunction,
27 bool use_measured_fft_planning = true,
28 bool use_exact_wavefunction_grid = false) {
29 Real two_pi_over_lattice_parameter_squared =
30 crystal_structure.two_pi_over_lattice_parameter_squared();
31 const Matrix3x3& reciprocal_lattice = crystal_structure.reciprocal_lattice_vectors();
32 const Matrix3x3& direct_lattice = crystal_structure.lattice_vectors();
33
34 int fft_factors[3];
35 FFTGridSizer::compute_fft_factors(crystal_structure, fft_factors);
36
37 int grid_dimension_rho_1, grid_dimension_rho_2, grid_dimension_rho_3;
38 FFTGridSizer::calculate_grid_dimensions(energy_cutoff_charge_density,
39 two_pi_over_lattice_parameter_squared,
40 direct_lattice,
41 reciprocal_lattice,
42 grid_dimension_rho_1,
43 grid_dimension_rho_2,
44 grid_dimension_rho_3,
45 fft_factors);
46 /**
47 * Rho grid uses FFTW_MEASURE by default (use_measured_fft_planning=true);
48 * pass false for bit-reproducible FFTW_ESTIMATE planning (see
49 * InputData::use_deterministic_fft_planning).
50 */
51 fft_rho_ = fft_grid_factory.create_fft_grid();
52 fft_rho_->init(grid_dimension_rho_1,
53 grid_dimension_rho_2,
54 grid_dimension_rho_3,
55 use_measured_fft_planning);
56
57 /**
58 * The smooth (wavefunction) FFT grid carries two products, V(r)ψ(r) and |ψ(r)|². A
59 * wavefunction holds plane waves out to G_max = sqrt(ecutwfc), so |ψ|² reaches 2 G_max,
60 * and a grid that holds the sphere of radius 2 G_max -- a 4 x ecutwfc cutoff -- takes
61 * both products without aliasing: |ψ|² fits whole, and any component of Vψ that wraps
62 * around lands outside the wavefunction sphere, where it is discarded. That is the
63 * exact grid, and the one pw.x builds; enlarging it changes nothing.
64 *
65 * The default grid holds only √2 G_max (2 x ecutwfc). Parts of |ψ|² and of Vψ wrap onto
66 * components that are kept, so it is faster but approximate: harmless where the
67 * wavefunctions have little weight near the cutoff, and up to mRy off pw.x on a hard
68 * deck at a low cutoff -- 9.5 mRy on a Ni/CO slab at 20 Ry. The exact grid costs 1.4x to
69 * 2.3x the solver time on the silicon and copper examples, depending on the thread count.
70 *
71 * Either is capped at the dense grid, which already holds everything the density can
72 * carry.
73 */
74 Real wavefunction_grid_cutoff_factor = use_exact_wavefunction_grid ? 4.0 : 2.0;
75 Real smooth_cutoff = std::min(wavefunction_grid_cutoff_factor * energy_cutoff_wavefunction,
76 energy_cutoff_charge_density);
77 int grid_dimension_wave_1, grid_dimension_wave_2, grid_dimension_wave_3;
79 two_pi_over_lattice_parameter_squared,
80 direct_lattice,
81 reciprocal_lattice,
82 grid_dimension_wave_1,
83 grid_dimension_wave_2,
84 grid_dimension_wave_3,
85 fft_factors);
86 // Wave grid uses FFTW_MEASURE by default; see the rho grid comment above.
87 fft_wave_ = fft_grid_factory.create_fft_grid();
88 fft_wave_->init(grid_dimension_wave_1,
89 grid_dimension_wave_2,
90 grid_dimension_wave_3,
91 use_measured_fft_planning);
92
93 /**
94 * Serial wave grid for band-distributed parallelism (task groups).
95 * Every rank gets a full-sized serial grid so each can do independent
96 * FFTs for its assigned bands without MPI collective calls.
97 */
98 fft_wave_serial_ = std::make_unique<SerialFFTGrid>();
99 fft_wave_serial_->init(grid_dimension_wave_1,
100 grid_dimension_wave_2,
101 grid_dimension_wave_3,
102 use_measured_fft_planning);
103 }
104
105 [[nodiscard]] FFTGrid& fft_rho() {
106 return *fft_rho_;
107 }
108 [[nodiscard]] const FFTGrid& fft_rho() const {
109 return *fft_rho_;
110 }
111 [[nodiscard]] FFTGrid& fft_wave() {
112 return *fft_wave_;
113 }
114 [[nodiscard]] const FFTGrid& fft_wave() const {
115 return *fft_wave_;
116 }
117 /**
118 * Serial (non-MPI) wave FFT grid for band-distributed parallelism.
119 * Identical dimensions to fft_wave() but runs locally on each rank.
120 */
121 [[nodiscard]] const SerialFFTGrid& fft_wave_serial() const {
122 return *fft_wave_serial_;
123 }
124
125 private:
126 std::unique_ptr<FFTGrid> fft_rho_;
127 std::unique_ptr<FFTGrid> fft_wave_;
128 std::unique_ptr<SerialFFTGrid> fft_wave_serial_;
129};
130
131} // namespace q3
Real two_pi_over_lattice_parameter_squared() const
Definition crystal.hpp:199
const Matrix3x3 & reciprocal_lattice_vectors() const
Definition crystal.hpp:205
const Matrix3x3 & lattice_vectors() const
Definition crystal.hpp:202
virtual std::unique_ptr< FFTGrid > create_fft_grid() const =0
static void compute_fft_factors(const Crystal &crystal_structure, int fft_factors[3])
static void calculate_grid_dimensions(Real energy_cutoff, Real two_pi_over_lattice_parameter_squared, const Matrix3x3 &direct_lattice, const Matrix3x3 &reciprocal_lattice, int &grid_dimension_1, int &grid_dimension_2, int &grid_dimension_3, const int fft_factors[3]=nullptr)
const FFTGrid & fft_wave() const
Definition pair.hpp:114
const SerialFFTGrid & fft_wave_serial() const
Definition pair.hpp:121
FFTGrid & fft_wave()
Definition pair.hpp:111
FFTGrid & fft_rho()
Definition pair.hpp:105
void initialize(const FFTGridFactory &fft_grid_factory, const Crystal &crystal_structure, Real energy_cutoff_charge_density, Real energy_cutoff_wavefunction, bool use_measured_fft_planning=true, bool use_exact_wavefunction_grid=false)
Definition pair.hpp:23
const FFTGrid & fft_rho() const
Definition pair.hpp:108
double Real
3×3 matrix stored row-major: row i = mat[i]