70 throw std::runtime_error(
71 "BerkeleyGWWavefunctionFile: spin-polarized (nspin>1) WFN export is not yet "
72 "supported. pw2bgw writes each band as a single record with all spins' "
73 "coefficients concatenated (G fastest, spin slower) rather than one record per "
74 "(k,spin,band); implementing that interleaving without a BerkeleyGW/QE reference "
75 "to validate against was judged too risky to guess at silently. Use "
76 "number_of_spin_components: 1, or omit mean_field_export, for a spin-polarized "
80 std::ofstream output_file(file_path, std::ios::binary);
81 if (!output_file.is_open()) {
82 log::warn(
"BerkeleyGWWavefunctionFile: cannot open {} for writing", file_path);
87 header.
write(output_file);
93 write_occupied_band_bounds_records(output_file);
94 write_eigenvalues_record(output_file);
95 write_occupations_record(output_file);
97 write_body(output_file, record_writer);
99 log::info(
" Wrote BerkeleyGW wavefunction file: {}", file_path);
120 static constexpr Real occupied_band_occupation_threshold = 0.5;
123 void write_occupied_band_bounds_records(std::ofstream& output_file)
const {
127 int total_kpoint_states = number_of_kpoints * number_of_spin_components;
129 std::vector<int32_t> lowest_occupied_band(total_kpoint_states, 0);
130 std::vector<int32_t> highest_occupied_band(total_kpoint_states, 0);
132 for (
int state_index = 0; state_index < total_kpoint_states; state_index++) {
133 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
135 if (occupation > occupied_band_occupation_threshold) {
136 if (lowest_occupied_band[state_index] == 0) {
137 lowest_occupied_band[state_index] = band_index + 1;
139 highest_occupied_band[state_index] = band_index + 1;
146 lowest_occupied_band.data(),
147 static_cast<int32_t
>(lowest_occupied_band.size() *
sizeof(int32_t)));
150 highest_occupied_band.data(),
151 static_cast<int32_t
>(highest_occupied_band.size() *
sizeof(int32_t)));
164 void write_eigenvalues_record(std::ofstream& output_file)
const {
165 write_band_major_matrix_record(output_file, [
this](
int state_index,
int band_index) {
171 void write_occupations_record(std::ofstream& output_file)
const {
172 write_band_major_matrix_record(output_file, [
this](
int state_index,
int band_index) {
173 return record_.
occupations[state_index][band_index];
177 template <
typename ValueFunction>
178 void write_band_major_matrix_record(std::ofstream& output_file, ValueFunction value_of)
const {
182 int total_kpoint_states = number_of_kpoints * number_of_spin_components;
184 std::vector<double> values(
static_cast<size_t>(number_of_bands) * total_kpoint_states);
185 for (
int state_index = 0; state_index < total_kpoint_states; state_index++) {
186 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
187 values[
static_cast<size_t>(state_index) * number_of_bands + band_index] =
188 value_of(state_index, band_index);
192 output_file, values.data(),
static_cast<int32_t
>(values.size() *
sizeof(
double)));
206 void write_body(std::ofstream& output_file,
const BerkeleyGWRecordWriter& record_writer)
const {
210 for (
int kpoint_index = 0; kpoint_index < number_of_kpoints; kpoint_index++) {
211 record_writer.write_kpoint_gvectors(output_file, kpoint_index);
214 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
215 int kpoint_state_index = kpoint_index;
216 record_writer.write_complex_block(
218 number_of_plane_waves,
219 record_.
band_source->coefficients(kpoint_state_index, band_index),
220 number_of_plane_waves);