23#include "generated/esse/properties/non_scalar/eigenvalues_at_kpoints.hpp"
52inline std::string
run_scf(
const std::string& input_path,
bool write_output_files =
true) {
64 generated::Results results =
run_flavor(input);
66 if (write_output_files) {
84inline std::string
run_nscf(
const std::string& input_path,
bool write_output_files =
true) {
91 generated::Results results =
run_flavor(input);
93 if (write_output_files) {
120 patched_species_ = input_.
species;
121 pseudopotential_set_ =
136 std::string
solve(
const std::vector<std::vector<double>>& coordinates,
137 bool write_output_files =
true) {
138 for (std::size_t atom_index = 0;
139 atom_index < coordinates.size() && atom_index < input_.
atoms.size();
141 if (coordinates[atom_index].size() < 3) {
142 throw std::runtime_error(
143 "SCFSolver::solve: coordinates must have 3 components per atom.");
145 input_.
atoms[atom_index].position.x = coordinates[atom_index][0];
146 input_.
atoms[atom_index].position.y = coordinates[atom_index][1];
147 input_.
atoms[atom_index].position.z = coordinates[atom_index][2];
189 iterator->set_owned_crystal(std::move(crystal));
190 iterator->set_owned_kpoint_grid(std::move(kpoint_grid));
191 iterator->set_owned_pseudopotential_set(pseudopotential_set_.
clone());
193 if (!last_charge_density_.empty()) {
194 log::debug(
"SCFSolver solve: Injecting cached charge density.");
195 iterator->load_charge_density(last_charge_density_);
197 log::debug(
"SCFSolver solve: No cached charge density available.");
199 if (last_quantum_system_ !=
nullptr) {
200 log::debug(
"SCFSolver solve: Injecting cached quantum system.");
201 iterator->load_quantum_system(*last_quantum_system_);
203 log::debug(
"SCFSolver solve: No cached quantum system available.");
209 const bool converged = iterator->is_converged();
210 auto scf_state = iterator->result();
214 "SCFSolver solve: SCF converged. Caching charge density and quantum states.");
215 last_charge_density_ = scf_state.charge_density_real;
216 last_quantum_system_ =
217 std::make_unique<PlanewaveKohnShamQuantumSystem>(iterator->quantum_system());
220 generated::Results results =
new_results(
"self_consistent_field");
221 results.runtime_log.converged = converged;
222 results.runtime_log.self_consistent_field_iterations = iterator->iteration();
223 if (!provenance_.is_null()) {
224 results.provenance = provenance_;
232 const auto& energies = scf_state.energies();
238 results, iterator->hubbard_occupation_traces(), scf_state.hubbard_manifolds);
245 auto [stress_total, stress_contributions] =
253 const auto& eigenvalue_matrix = iterator->eigenvalues();
254 int number_of_kpoints = eigenvalue_matrix.rows();
255 int number_of_bands = eigenvalue_matrix.cols();
261 int number_of_physical_kpoints = iterator->kpoint_grid().number_of_kpoints();
263 generated::EigenvaluesAtKpoints eigenvalues;
264 eigenvalues.name = generated::EigenvaluesAtKpointsNameEnum::EIGENVALUES_AT_KPOINTS;
265 eigenvalues.units = generated::EigenvaluesAtKpointsUnitsEnum::RY;
266 for (
int kpoint_index = 0; kpoint_index < number_of_kpoints; kpoint_index++) {
267 generated::EigenvaluesAtKpointsBandEnergies channel;
268 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
269 channel.energies.push_back(eigenvalue_matrix(kpoint_index, band_index));
271 generated::EigenvaluesAtKpointsEigenvaluesAtKPoint kpoint;
273 iterator->kpoint_grid()[kpoint_index % number_of_physical_kpoints].weight;
274 kpoint.eigenvalues = {channel};
275 eigenvalues.values.push_back(kpoint);
280 if (write_output_files) {
284 std::string results_path =
294 std::vector<AtomSpecies> patched_species_;
296 nlohmann::json provenance_;
297 std::vector<std::vector<Real>> last_charge_density_;
298 std::unique_ptr<PlanewaveKohnShamQuantumSystem> last_quantum_system_;
PseudopotentialSet clone() const
Deep-clone the entire set (preserves derived types).
static void record_stress(generated::Results &results, const StressTensorTotal &total, const StressTensorContributions &contributions)
static void record_convergence(generated::Results &results, const History &history)
static void record_forces(generated::Results &results, const std::vector< Vector3D > &total_forces, const AtomicForcesContributions &contributions)
ESSE's atomic_forces record, and beside it the share of each mechanism, in Ry/bohr.
static void record_hubbard_occupations(generated::Results &results, const std::vector< std::vector< Real > > &traces, const Manifolds &manifolds)
static void record_magnetization(generated::Results &results, const std::optional< Magnetization > &magnetization)
static std::string find_spacegroup(const Crystal &crystal, Real symmetry_precision=math::tolerances::default_symmetry_precision)
SCFSolver(const std::string &input_path)
std::string solve(const std::vector< std::vector< double > > &coordinates, bool write_output_files=true)
SCFSolver(SCFSolver &&)=default
SCFSolver & operator=(SCFSolver &&)=default
SCFSolver & operator=(const SCFSolver &)=delete
SCFSolver(const SCFSolver &)=delete
std::string run_nscf(const std::string &input_path, bool write_output_files=true)
std::string run_scf(const std::string &input_path, bool write_output_files=true)
void debug(spdlog::format_string_t< Args... > fmt, Args &&... args)
void apply_verbosity(const std::string &verbosity, const std::string &explicit_log_level)
PseudopotentialSet load_pseudopotentials(std::vector< AtomSpecies > &species, const std::string &pseudopotential_directory)
Crystal build_crystal_from_input(const InputData &input, const std::vector< AtomSpecies > &species)
void set_record(generated::Results &results, const Record &record)
List record in the results, in place of any record of the same name.
generated::Results new_results(const std::string &flavor)
std::pair< StressTensorTotal, StressTensorContributions > compute_stress(const NormConservingPlanewaveKohnShamSCFState &scf_state, const std::string &nonlocal_stress_derivative_method="analytical", const std::string &dispersion_correction="none", bool disable_symmetry=false)
void set_fermi_energy(generated::Results &results, Real fermi_energy_in_ry)
ESSE's fermi_energy record, in rydberg.
void write_results_json(const generated::Results &results, const std::string &output_path)
Write the results to output_path as results.json.
InputData parse_input(const std::string &filename, const std::string &format="")
std::string results_json_string(const generated::Results &results)
void add_band_edge_records(generated::Results &results)
generated::Results run_flavor(const InputData &input)
std::unique_ptr< PlanewavePseudopotentialKohnShamSCFIterator > create_planewave_pseudopotential_iterator(KohnShamSCFIteratorConfig config)
nlohmann::json build_provenance_json(const InputData &input)
Build the provenance block for a completed run, from the input it consumed.
void set_energy_records(generated::Results &results, Real total_energy_in_ry, const PlanewaveKohnShamEnergies &energies)
KPointsGrid build_global_kpoint_grid_from_input(const InputData &input, const Crystal &crystal)
static std::pair< std::vector< Vector3D >, AtomicForcesContributions > compute_forces(const NormConservingPlanewaveKohnShamSCFState &scf_state, const std::string &dispersion_correction="none", bool disable_symmetry=false)
std::vector< Real > starting_magnetization
std::vector< std::pair< std::string, Vector3D > > band_path
std::vector< Real > atomic_starting_magnetization
Real wavefunction_energy_cutoff
std::string mixing_preconditioning
std::string exchange_correlation_functional
std::string nonlocal_stress_derivative_method
int band_path_points_per_segment
std::string diagonalization_method
Real charge_density_energy_cutoff
int methfessel_paxton_order
const PseudopotentialSet * pseudopotential_set
static ProfilingCounters & instance()
Crystal * crystal_structure
int number_of_spin_components
Real convergence_threshold