25#include <nlohmann/json.hpp>
27#include "generated/esse/core/reusable/energy.hpp"
28#include "generated/esse/properties/non_scalar/stress_tensor.hpp"
29#include "generated/esse/properties/non_scalar/total_energy_contributions.hpp"
30#include "generated/esse/properties/scalar/fermi_energy.hpp"
31#include "generated/esse/properties/scalar/total_energy.hpp"
32#include "generated/esse/properties/structural/atomic_forces.hpp"
33#include "generated/q3/results.hpp"
46[[nodiscard]]
inline generated::Results
new_results(
const std::string& flavor) {
47 generated::Results results;
48 results.runtime_log.flavor = flavor;
49 generated::ResultsExecution& execution = results.runtime_log.
execution;
50 execution.number_of_processes = 1;
52 execution.number_of_kpoint_pools = 1;
53 execution.band_group_size = 1;
58template <
typename Record> [[nodiscard]] std::string
record_name() {
59 return nlohmann::json(Record{}.name).
template get<std::string>();
63template <
typename Record>
64[[nodiscard]] std::optional<Record>
find_record(
const generated::Results& results) {
65 const std::string name = record_name<Record>();
66 for (
const auto& record : results.properties.records) {
67 if (record.value(
"name",
"") == name) {
68 return record.template get<Record>();
75template <
typename Record>
void set_record(generated::Results& results,
const Record& record) {
76 const nlohmann::json value = record;
77 const std::string name = record_name<Record>();
78 auto& records = results.properties.records;
79 for (
auto& existing : records) {
80 if (existing.value(
"name",
"") == name) {
85 records.push_back(value);
90 return {vector.
x, vector.
y, vector.
z};
94[[nodiscard]]
inline std::vector<std::vector<double>>
to_matrix(
const Real (&matrix)[3][3]) {
95 std::vector<std::vector<double>> rows;
96 for (
const auto& row : matrix) {
97 rows.push_back({row[0], row[1], row[2]});
103[[nodiscard]]
inline generated::Energy
energy(
const std::string& name,
Real value_in_ry) {
104 return {name, generated::EnergyUnitsEnum::RY, value_in_ry};
108[[nodiscard]]
inline generated::AtomicForces
110 generated::AtomicForces forces;
111 forces.name = generated::AtomicForcesNameEnum::ATOMIC_FORCES;
112 forces.units = generated::AtomicForcesUnitsEnum::RY_A_U;
113 for (
size_t atom_index = 0; atom_index < values_in_ry_per_bohr.size(); atom_index++) {
114 forces.values.push_back(
115 {
to_vector(values_in_ry_per_bohr[atom_index]),
static_cast<int64_t
>(atom_index) + 1});
123 generated::StressTensorNameEnum::STRESS_TENSOR,
124 generated::StressTensorUnitsEnum::KBAR};
136 Real total_energy_in_ry,
139 generated::TotalEnergy{generated::TotalEnergyNameEnum::TOTAL_ENERGY,
140 generated::TotalEnergyUnitsEnum::RY,
141 total_energy_in_ry});
143 generated::TotalEnergyContributions contributions;
144 contributions.name = generated::TotalEnergyContributionsNameEnum::TOTAL_ENERGY_CONTRIBUTIONS;
145 contributions.units = generated::TotalEnergyContributionsUnitsEnum::RY;
146 contributions.eigenvalues = generated::TotalEnergyContributionsEigenvalues{
147 generated::TotalEnergyContributionsEigenvaluesNameEnum::EIGENVALUES, energies.
band_energy};
148 contributions.hartree = generated::TotalEnergyContributionsHartree{
149 generated::TotalEnergyContributionsHartreeNameEnum::HARTREE, energies.
hartree_energy};
150 contributions.exchange_correlation = generated::TotalEnergyContributionsExchangeCorrelation{
151 generated::TotalEnergyContributionsExchangeCorrelationNameEnum::EXCHANGE_CORRELATION,
153 contributions.ewald = generated::TotalEnergyContributionsEwald{
154 generated::TotalEnergyContributionsEwaldNameEnum::EWALD, energies.
ewald_energy};
155 contributions.temperature_entropy = generated::TotalEnergyContributionsTemperatureEntropy{
156 generated::TotalEnergyContributionsTemperatureEntropyNameEnum::TEMPERATURE_ENTROPY,
160 generated::ResultsEnergyContributions& terms = results.properties.energy_contributions;
176 generated::FermiEnergy{generated::FermiEnergyNameEnum::FERMI_ENERGY,
177 generated::FermiEnergyUnitsEnum::RY,
178 fermi_energy_in_ry});
187 return nlohmann::json(results).dump(4) +
"\n";
void set_record(generated::Results &results, const Record &record)
List record in the results, in place of any record of the same name.
std::optional< Record > find_record(const generated::Results &results)
The record of type Record the results list, or nothing when they list none.
generated::Results new_results(const std::string &flavor)
generated::AtomicForces atomic_forces(const std::vector< Vector3D > &values_in_ry_per_bohr)
Forces in Ry/bohr as ESSE's atomic_forces, atoms by 1-based id: the total or one contribution.
generated::Energy energy(const std::string &name, Real value_in_ry)
One of Q3's energies that ESSE has no property for, as an ESSE energy in rydberg.
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.
std::vector< std::vector< double > > to_matrix(const Real(&matrix)[3][3])
A 3x3 matrix as ESSE lists one: three rows of three.
std::string results_json_string(const generated::Results &results)
generated::StressTensor stress_tensor(const Real(&values_in_kbar)[3][3])
A stress in kbar as ESSE's stress_tensor: the total or one contribution to it.
std::vector< double > to_vector(const Vector3D &vector)
A vector as ESSE lists one: [x, y, z].
void set_energy_records(generated::Results &results, Real total_energy_in_ry, const PlanewaveKohnShamEnergies &energies)
std::string record_name()
The name every record of the generated ESSE type Record carries.
void write_json_file(const std::string &path, const nlohmann::json &document)
Real double_counting_correction
Real exchange_correlation_energy
virtual Real dispersion_energy() const
virtual Real one_center_energy_contribution() const
virtual Real hubbard_energy_contribution() const
Real smearing_entropy_contribution