Loading...
Searching...
No Matches
charge_density.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * BerkeleyGWChargeDensityFile — writes BerkeleyGW's `RHO` mean-field file.
5 *
6 * Layout (the BerkeleyGW specification, as pw2bgw.x's `write_rhog` writes it
7 * -- see header.hpp for both citations):
8 * records 1-8: BerkeleyGWCommonHeader (include_kpoint_fields=false)
9 * body: [nrecord=1][ng][gvec[3,ng]] then [nrecord=1][ng][rho[ng,ns]]
10 *
11 * rho(G) is per-spin (the specification lists the data as ng values per
12 * spin; write_rhog writes QE's G-space density one spin channel at a time --
13 * for ns=2 the actual spin-up/spin-down density after QE's own
14 * total/magnetization -> up/down conversion, not (total, magnetization)),
15 * scaled by the cell volume (write_rhog), which makes the G=0 component the
16 * number of electrons in the cell, as the specification requires. Q3's
17 * charge_density_real is per-spin already (see NormConservingPlanewaveKohnShamQuantumSystem's
18 * charge_density_real_[0]/[1] = 0.5*(total±magnetization) assembly in the
19 * pseudopotential iterator), so each spin channel is independently
20 * transformed to G-space via PlanewaveBasis::rho_r_to_g() rather than
21 * relying on SCFState::charge_density_g (which is the single spin-summed
22 * total, documented as such, and insufficient for ns=2).
23 *
24 * Unlike BerkeleyGWWavefunctionFile, RHO's on-disk layout does not depend on
25 * nspin (write_rhog writes all ng x ns values as a single record regardless of
26 * spin count -- there is no analog of WFN's layout-dependent per-band
27 * interleaving here), so this writer supports spin-polarized (ns=2) runs
28 * fully; only WFN rejects them.
29 */
30
31#include <fstream>
32#include <string>
33#include <vector>
34
35#include "io/logger.hpp"
38
39namespace q3 {
40
42 public:
43 explicit BerkeleyGWChargeDensityFile(const MeanFieldRecord& record) : record_(record) {}
44 /**
45 * These writers keep a reference to the record, so binding one to a
46 * temporary would dangle the moment the full expression ends. Deleting the
47 * rvalue overload turns that into a compile error instead of a silent
48 * read of freed memory -- callers must keep the record alive themselves,
49 * which every real call site already does.
50 */
51 explicit BerkeleyGWChargeDensityFile(const MeanFieldRecord&&) = delete;
52
53 void write_to_file(const std::string& file_path) const {
54 std::ofstream output_file(file_path, std::ios::binary);
55 if (!output_file.is_open()) {
56 log::warn("BerkeleyGWChargeDensityFile: cannot open {} for writing", file_path);
57 return;
58 }
59
60 BerkeleyGWFieldFile(record_, "RHO-Complex", record_.charge_density_g, record_.cell_volume)
61 .write(output_file);
62
63 log::info(" Wrote BerkeleyGW charge density file: {}", file_path);
64 }
65
66 private:
67 const MeanFieldRecord& record_;
68};
69
70} // namespace q3
BerkeleyGWChargeDensityFile(const MeanFieldRecord &record)
BerkeleyGWChargeDensityFile(const MeanFieldRecord &&)=delete
void write_to_file(const std::string &file_path) const
One per-spin field on the charge-density G-set, in RHO's layout; see the file comment.
Definition field.hpp:32
void write(std::ofstream &output_file) const
Writes header, G-set and field to an open stream; throws if the field is not on the G-set.
Definition field.hpp:55
void warn(spdlog::format_string_t< Args... > fmt, Args &&... args)
Definition logger.hpp:187
void info(spdlog::format_string_t< Args... > fmt, Args &&... args)
Definition logger.hpp:183
std::vector< std::vector< Complex > > charge_density_g
Definition init.hpp:148