Loading...
Searching...
No Matches
factory.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * PseudopotentialFactory — read a dataset in whichever registered format it is.
5 *
6 * This is what lets an ordinary Q3 input name any dataset file the build can
7 * read: the format is chosen from the file itself, never from its name. Every
8 * registered format (pseudopotential_format_registry.hpp) is shown the first
9 * line, and of those that recognise it, the one with the highest
10 * detection_priority() reads the file, ties going to the format registered
11 * first. Sniffing content
12 * rather than trusting a name matters because dataset files are routinely
13 * renamed per species, and a file handed to the wrong reader fails far from
14 * the cause, or worse, parses.
15 *
16 * The format readers keep their own narrower entry points (UPFReader::read for
17 * UPF), so a caller that means one format still gets that format or an error,
18 * never another format by surprise.
19 */
20
21#include <fstream>
22#include <memory>
23#include <stdexcept>
24#include <string>
25
28
29namespace q3 {
30
31/// Reads a dataset in whichever registered format its first line names.
33 public:
34 /**
35 * Read the dataset at `dataset_index` from `filename`, in the
36 * highest-ranked registered format that recognises the file's first line.
37 */
38 static std::unique_ptr<Pseudopotential> read(const std::string& filename,
39 int dataset_index = 0) {
40 std::ifstream file_stream(filename);
41 if (!file_stream.is_open())
42 throw std::runtime_error("Cannot open PP file: " + filename);
43 std::string first_line;
44 std::getline(file_stream, first_line);
45 file_stream.close();
46
47 const auto& registry = pseudopotential_format_registry();
48 const PseudopotentialFormat* chosen = nullptr;
49 for (const auto& format : registry.entries()) {
50 if (!format->recognizes(first_line))
51 continue;
52 if (chosen == nullptr || format->detection_priority() > chosen->detection_priority())
53 chosen = format.get();
54 }
55 if (chosen != nullptr)
56 return chosen->read(filename, dataset_index);
57 throw std::runtime_error(
58 "No registered pseudopotential format recognises " + filename +
59 "; the formats this build reads are: " + registry.canonical_names(", "));
60 }
61};
62
63} // namespace q3
Reads a dataset in whichever registered format its first line names.
Definition factory.hpp:32
static std::unique_ptr< Pseudopotential > read(const std::string &filename, int dataset_index=0)
Definition factory.hpp:38
One file format pseudopotential datasets are read from; see the file comment.
virtual std::unique_ptr< Pseudopotential > read(const std::string &filename, int dataset_index) const =0
virtual int detection_priority() const =0
Registry< PseudopotentialFormat > & pseudopotential_format_registry()
The registry PseudopotentialFactory::read() chooses a format from.