41 std::optional<generated::BandEdgeValenceMax> edge;
42 for (
const auto& kpoint : eigenvalues.values) {
43 for (
const auto& channel : kpoint.eigenvalues) {
44 for (
const Real energy_in_ry : channel.energies) {
45 if (energy_in_ry <= fermi_energy_in_ry && (!edge || energy_in_ry >= edge->value)) {
46 edge = generated::BandEdgeValenceMax{
47 generated::BandEdgeValenceMaxNameEnum::BAND_EDGE_VALENCE_MAX,
50 generated::BandEdgeValenceMaxUnitsEnum::RY,
62 Real fermi_energy_in_ry) {
63 std::optional<generated::BandEdgeConductionMin> edge;
64 for (
const auto& kpoint : eigenvalues.values) {
65 for (
const auto& channel : kpoint.eigenvalues) {
66 for (
const Real energy_in_ry : channel.energies) {
67 if (energy_in_ry > fermi_energy_in_ry && (!edge || energy_in_ry <= edge->value)) {
68 edge = generated::BandEdgeConductionMin{
69 generated::BandEdgeConductionMinNameEnum::BAND_EDGE_CONDUCTION_MIN,
72 generated::BandEdgeConductionMinUnitsEnum::RY,
88 constexpr Real occupation_tolerance = 1.0e-6;
89 for (
const auto& kpoint : eigenvalues.values) {
90 for (
const auto& channel : kpoint.eigenvalues) {
91 for (
const Real occupation : channel.occupations.value_or(std::vector<double>{})) {
92 if (occupation > occupation_tolerance && occupation < 1.0 - occupation_tolerance) {
105 Real conduction_in_ry,
106 const std::optional<std::vector<double>>& valence_kpoint,
107 const std::optional<std::vector<double>>& conduction_kpoint) {
108 generated::BandGapsBandGap gap;
110 gap.units = generated::BandGapsBandGapUnitsEnum::RY;
111 gap.value = conduction_in_ry - valence_in_ry;
112 gap.eigenvalue_valence = valence_in_ry;
113 gap.eigenvalue_conduction = conduction_in_ry;
114 gap.kpoint_valence = valence_kpoint;
115 gap.kpoint_conduction = conduction_kpoint;
130band_gaps(
const generated::EigenvaluesAtKpoints& eigenvalues,
Real fermi_energy_in_ry) {
137 std::optional<generated::BandGapsBandGap> direct;
138 for (
const auto& kpoint : eigenvalues.values) {
139 Real kpoint_valence_in_ry = -std::numeric_limits<Real>::infinity();
140 Real kpoint_conduction_in_ry = std::numeric_limits<Real>::infinity();
141 for (
const auto& channel : kpoint.eigenvalues) {
142 for (
const Real energy_in_ry : channel.energies) {
143 if (energy_in_ry <= fermi_energy_in_ry) {
144 kpoint_valence_in_ry = std::max(kpoint_valence_in_ry, energy_in_ry);
146 kpoint_conduction_in_ry = std::min(kpoint_conduction_in_ry, energy_in_ry);
150 const bool has_both_edges =
151 std::isfinite(kpoint_valence_in_ry) && std::isfinite(kpoint_conduction_in_ry);
152 if (has_both_edges &&
153 (!direct || kpoint_conduction_in_ry - kpoint_valence_in_ry < direct->value)) {
154 direct =
band_gap(generated::BandGapsBandGapTypeEnum::DIRECT,
155 kpoint_valence_in_ry,
156 kpoint_conduction_in_ry,
162 generated::BandGaps record;
163 record.name = generated::BandGapsNameEnum::BAND_GAPS;
165 record.values.push_back(*direct);
167 record.values.push_back(
band_gap(generated::BandGapsBandGapTypeEnum::INDIRECT,
171 conduction->kpoint));
182 const auto eigenvalues = find_record<generated::EigenvaluesAtKpoints>(results);
183 const auto fermi_energy = find_record<generated::FermiEnergy>(results);
184 if (!eigenvalues || !fermi_energy) {
193 if (
const auto gaps =
band_gaps(*eigenvalues, fermi_energy->value)) {
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< generated::BandEdgeConductionMin > band_edge_conduction_min(const generated::EigenvaluesAtKpoints &eigenvalues, Real fermi_energy_in_ry)
ESSE's band_edge_conduction_min: the lowest level above the Fermi energy, as above.
generated::BandGapsBandGap band_gap(generated::BandGapsBandGapTypeEnum type, Real valence_in_ry, Real conduction_in_ry, const std::optional< std::vector< double > > &valence_kpoint, const std::optional< std::vector< double > > &conduction_kpoint)
One ESSE band gap between two levels, with the k-points they lie at where known.