24namespace upf_utilities {
27inline std::string
trim(
const std::string& input) {
28 size_t first_non_whitespace = input.find_first_not_of(
" \t\r\n");
29 if (first_non_whitespace == std::string::npos)
31 size_t last_non_whitespace = input.find_last_not_of(
" \t\r\n");
32 return input.substr(first_non_whitespace, last_non_whitespace - first_non_whitespace + 1);
61 std::string token =
trim(raw_type);
62 std::string upper_token = token;
63 for (
char& character : upper_token)
64 character =
static_cast<char>(std::toupper(
static_cast<unsigned char>(character)));
66 if (upper_token ==
"PAW")
68 if (upper_token ==
"US" || upper_token ==
"USPP")
71 if (upper_token ==
"NC" || upper_token ==
"SL")
77inline std::vector<Real>
read_reals(std::ifstream& file_stream,
int count) {
78 std::vector<Real> values;
79 values.reserve(count);
81 while (
static_cast<int>(values.size()) < count && file_stream >> value) {
82 values.push_back(value);
89inline bool find_tag(std::ifstream& file_stream,
const std::string& tag) {
91 while (std::getline(file_stream, line)) {
92 if (line.find(tag) != std::string::npos)
99inline std::string
xml_attribute(
const std::string& text,
const std::string& attribute_name) {
100 std::string patterns[] = {attribute_name +
"=\"", attribute_name +
"='"};
101 for (
auto& pattern : patterns) {
102 auto position = text.find(pattern);
103 if (position != std::string::npos) {
104 position += pattern.size();
105 char delimiter = pattern.back();
106 auto end_position = text.find(delimiter, position);
107 if (end_position != std::string::npos) {
108 return text.substr(position, end_position - position);
123 const std::string& source_description,
124 const std::string& expected_kind,
125 const std::string& found_value) {
126 std::string message =
"Malformed UPF file " + source_description +
127 ": required PP_HEADER "
129 attribute_name +
"' ";
130 if (found_value.empty()) {
131 message +=
"is missing";
133 message +=
"is not " + expected_kind +
" (found \"" + found_value +
"\")";
135 return std::runtime_error(message);
154 const std::string& attribute_name,
155 const std::string& source_description) {
160 std::size_t characters_consumed = 0;
161 int parsed_value = 0;
163 parsed_value = std::stoi(value, &characters_consumed);
164 }
catch (
const std::exception&) {
167 if (!
trim(value.substr(characters_consumed)).empty())
174 const std::string& attribute_name,
175 const std::string& source_description) {
180 std::size_t characters_consumed = 0;
181 Real parsed_value = 0.0;
183 parsed_value = std::stod(value, &characters_consumed);
184 }
catch (
const std::exception&) {
187 if (!
trim(value.substr(characters_consumed)).empty())
193inline std::vector<Real>
xml_data(
const std::string& section) {
194 std::vector<Real> values;
195 std::istringstream stream(section);
197 while (std::getline(stream, line)) {
199 if (line.find(
'<') != std::string::npos)
201 std::istringstream line_stream(line);
203 while (line_stream >> value)
204 values.push_back(value);
211 constexpr Real zero_norm_threshold = 1.0e-10;
212 for (
int wavefunction_index = 0;
214 wavefunction_index++) {
217 std::vector<Real> integrand(pseudopotential.
mesh_size);
218 for (
int radial_index = 0; radial_index < pseudopotential.
mesh_size; radial_index++) {
219 integrand[radial_index] =
220 wavefunction.radial_values[radial_index] * wavefunction.radial_values[radial_index];
224 if (norm < zero_norm_threshold) {
225 log::warn(
" WARNING: atomic wfc # {} for atom type {} has zero norm",
226 wavefunction_index + 1,
228 wavefunction.occupations = -1.0e-10;
Base class for all pseudopotential types.
std::vector< Real > radial_grid_derivative
std::vector< WavefunctionAtomic > wavefunctions_atomic
void warn(spdlog::format_string_t< Args... > fmt, Args &&... args)
void check_atomic_wavefunction_norm(Pseudopotential &pseudopotential)
Validate atomic wavefunction norms and mark zero-norm wavefunctions.
std::string trim(const std::string &input)
Remove leading and trailing whitespace from a string.
Real required_real_attribute(const std::string &text, const std::string &attribute_name, const std::string &source_description)
Read a required real-valued attribute from a UPF header tag.
std::string canonical_pseudopotential_type(const std::string &raw_type)
std::vector< Real > xml_data(const std::string §ion)
Extract numeric data from an XML section body, skipping lines that contain XML tags.
std::vector< Real > read_reals(std::ifstream &file_stream, int count)
Read a specified number of real values from a stream.
std::runtime_error malformed_attribute_error(const std::string &attribute_name, const std::string &source_description, const std::string &expected_kind, const std::string &found_value)
bool find_tag(std::ifstream &file_stream, const std::string &tag)
Advance the stream until a line containing the given tag is found.
std::string xml_attribute(const std::string &text, const std::string &attribute_name)
Extract an XML attribute value from a block of text (e.g. attr="value" or attr='value').
int required_integer_attribute(const std::string &text, const std::string &attribute_name, const std::string &source_description)
Real simpson_rule(const std::vector< Real > &function_values, const std::vector< Real > &integration_factors, int number_of_grid_points)