Quantum 3xplorer (Q3)
An AI-native quantum simulation engine
Loading...
Searching...
No Matches
set.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * PseudopotentialSet — polymorphic container for pseudopotential_set.
5 *
6 * Stores unique_ptrs internally but exposes const Pseudopotential& via
7 * operator[], so all existing `.field` access patterns work unchanged.
8 * This avoids changing 20+ function signatures from .field to ->field.
9 */
10
11#include <cassert>
12#include <memory>
13#include <stdexcept>
14#include <string>
15#include <vector>
16
20
21namespace q3 {
22
23/**
24 * Polymorphic container for pseudopotentials.
25 *
26 * Stores unique_ptrs internally but exposes const Pseudopotential& via
27 * operator[], so all existing `.field` access patterns work unchanged.
28 */
30 public:
35
36 PseudopotentialSet() = default;
37
38 /// Move a unique_ptr into the set.
39 void push_back(std::unique_ptr<Pseudopotential> pseudopotential) {
40 pseudopotentials_.push_back(std::move(pseudopotential));
41 }
42
43 /// Access by index (const reference).
44 [[nodiscard]] const Pseudopotential& operator[](int index) const {
45 assert(index >= 0 && index < static_cast<int>(pseudopotentials_.size()));
46 return *pseudopotentials_[index];
47 }
48
49 /// Access by index (mutable reference).
51 assert(index >= 0 && index < static_cast<int>(pseudopotentials_.size()));
52 return *pseudopotentials_[index];
53 }
54
55 /**
56 * Access as ultrasoft pseudopotential.
57 *
58 * A PAW dataset also satisfies this cast — it extends the ultrasoft class
59 * because it carries the same augmentation apparatus — so the check below
60 * tests the storage layout, not the pseudopotential kind. Use
61 * pseudopotential_type_enum() to distinguish the two.
62 */
63 [[nodiscard]] const UltrasoftPseudopotential& as_ultrasoft(int index) const {
64 assert(index >= 0 && index < static_cast<int>(pseudopotentials_.size()));
65 const auto* result =
66 dynamic_cast<const UltrasoftPseudopotential*>(pseudopotentials_[index].get());
67 if (result == nullptr) {
68 throw std::logic_error(
69 "as_ultrasoft(" + std::to_string(index) + "): species '" +
70 pseudopotentials_[index]->element +
71 "' carries no augmentation, so there is no ultrasoft form to return. A cell "
72 "mixing norm-conserving species with ultrasoft or PAW ones reaches this when a "
73 "caller asks for the augmented form per species without gating on the species. "
74 "This was an assert, which a release build compiles out -- so the null it "
75 "guarded was dereferenced instead of reported.");
76 }
77 return *result;
78 }
79
80 /// Access as PAW pseudopotential.
81 [[nodiscard]] const PawPseudopotential& as_paw(int index) const {
82 assert(index >= 0 && index < static_cast<int>(pseudopotentials_.size()));
83 const auto* result =
84 dynamic_cast<const PawPseudopotential*>(pseudopotentials_[index].get());
85 if (result == nullptr) {
86 throw std::logic_error(
87 "as_paw(" + std::to_string(index) + "): species '" +
88 pseudopotentials_[index]->element +
89 "' is not a PAW dataset, so there is no one-center form to return. A cell mixing "
90 "PAW species with norm-conserving or ultrasoft ones reaches this when a caller "
91 "asks for the one-center form per species without gating on the species. This "
92 "was an assert, which a release build compiles out -- so the null it guarded was "
93 "dereferenced instead of reported.");
94 }
95 return *result;
96 }
97
98 [[nodiscard]] int size() const {
99 return static_cast<int>(pseudopotentials_.size());
100 }
101
102 [[nodiscard]] bool empty() const {
103 return pseudopotentials_.empty();
104 }
105
106 /**
107 * Check whether any pseudopotential in this set is of the given type.
108 */
109 [[nodiscard]] bool has_pseudopotential_type(PseudopotentialType target_type) const {
110 for (int index = 0; index < size(); ++index) {
111 if ((*this)[index].pseudopotential_type_enum() == target_type) {
112 return true;
113 }
114 }
115 return false;
116 }
117
118 /**
119 * Whether any species needs the augmentation machinery.
120 *
121 * The question the plane-wave side actually asks — it wants to know
122 * whether to build Q(G) tables, an S-operator and a per-step D matrix, and
123 * both ultrasoft and PAW datasets answer yes. Asking it by capability
124 * rather than by `== ultrasoft` is what lets a PAW dataset reach that
125 * machinery at all: PAW is a layered extension of ultrasoft here, so a
126 * type equality test silently routes it down the norm-conserving path
127 * where its augmentation charges are simply dropped.
128 */
129 [[nodiscard]] bool has_augmentation_charges() const {
130 for (int index = 0; index < size(); ++index) {
131 if ((*this)[index].has_augmentation_charges()) {
132 return true;
133 }
134 }
135 return false;
136 }
137
138 /// Deep-clone the entire set (preserves derived types).
139 [[nodiscard]] PseudopotentialSet clone() const {
140 PseudopotentialSet result;
141 for (const auto& pseudopotential : pseudopotentials_) {
142 result.push_back(pseudopotential->clone());
143 }
144 return result;
145 }
146
147 private:
148 std::vector<std::unique_ptr<Pseudopotential>> pseudopotentials_;
149};
150
151} // namespace q3
PAW pseudopotential — extends ultrasoft with one-center (on-site) data.
Definition init.hpp:33
PseudopotentialSet & operator=(PseudopotentialSet &&)=default
bool has_pseudopotential_type(PseudopotentialType target_type) const
Definition set.hpp:109
const UltrasoftPseudopotential & as_ultrasoft(int index) const
Definition set.hpp:63
PseudopotentialSet()=default
Pseudopotential & operator[](int index)
Access by index (mutable reference).
Definition set.hpp:50
void push_back(std::unique_ptr< Pseudopotential > pseudopotential)
Move a unique_ptr into the set.
Definition set.hpp:39
PseudopotentialSet clone() const
Deep-clone the entire set (preserves derived types).
Definition set.hpp:139
const PawPseudopotential & as_paw(int index) const
Access as PAW pseudopotential.
Definition set.hpp:81
PseudopotentialSet(const PseudopotentialSet &)=delete
const Pseudopotential & operator[](int index) const
Access by index (const reference).
Definition set.hpp:44
PseudopotentialSet & operator=(const PseudopotentialSet &)=delete
PseudopotentialSet(PseudopotentialSet &&)=default
bool empty() const
Definition set.hpp:102
int size() const
Definition set.hpp:98
bool has_augmentation_charges() const
Definition set.hpp:129
Base class for all pseudopotential types.
Definition init.hpp:35
Ultrasoft pseudopotential — extends base with augmentation data.
Definition init.hpp:27
PseudopotentialType
Pseudopotential type classification.
Definition init.hpp:27