41 Real cell_dimension_1,
42 const std::vector<AtomSpecies>&
species,
43 const std::vector<Atom>&
atoms,
44 Real cell_dimension_2 = 0,
45 Real cell_dimension_3 = 0,
46 Real cell_dimension_4 = 0,
47 Real cell_dimension_5 = 0,
48 Real cell_dimension_6 = 0) {
58 for (
const auto& species_entry :
species) {
61 for (
const auto& atom_entry :
atoms) {
77 const std::vector<AtomSpecies>&
species,
78 const std::vector<Atom>&
atoms) {
82 for (
const auto& species_entry :
species) {
85 for (
const auto& atom_entry :
atoms) {
101 Real cell_dimension_1,
102 Real cell_dimension_2,
103 Real cell_dimension_3,
104 Real cell_dimension_4,
105 Real cell_dimension_5,
106 Real cell_dimension_6) {
107 lattice_parameter_ = cell_dimension_1;
136 atoms_.push_back(atom);
137 site_symmetry_classes_.clear();
144 for (std::size_t atom_index = 0;
145 atom_index < positions.size() && atom_index < atoms_.size();
147 atoms_[atom_index].position = positions[atom_index];
157 using namespace constants;
159 two_pi_over_lattice_parameter_ = two_pi / lattice_parameter_;
160 two_pi_over_lattice_parameter_squared_ =
161 two_pi_over_lattice_parameter_ * two_pi_over_lattice_parameter_;
167 cell_volume_ = std::abs(volume_fraction) * lattice_parameter_ * lattice_parameter_ *
176 reciprocal_lattice_vectors_ = lattice_inverse.
transpose();
181 return lattice_parameter_;
191 return bravais_lattice_index_;
197 return two_pi_over_lattice_parameter_;
200 return two_pi_over_lattice_parameter_squared_;
203 return lattice_vectors_;
206 return reciprocal_lattice_vectors_;
210 return static_cast<int>(atoms_.size());
213 return static_cast<int>(species_.size());
215 [[nodiscard]]
const std::vector<Atom>&
atoms()
const {
218 [[nodiscard]]
const std::vector<AtomSpecies>&
species()
const {
230 const Vector3D& fractional = atoms_[atom_index].position;
232 for (
int dimension = 0; dimension < 3; dimension++) {
233 cartesian_position[dimension] = fractional.
x * lattice_vectors_[0][dimension] +
234 fractional.
y * lattice_vectors_[1][dimension] +
235 fractional.
z * lattice_vectors_[2][dimension];
237 return cartesian_position;
254 Vector3D fractional = atoms_[atom_index_a].position - atoms_[atom_index_b].position;
255 for (
int axis = 0; axis < 3; axis++)
256 fractional[axis] -= std::round(fractional[axis]);
258 for (
int dimension = 0; dimension < 3; dimension++) {
259 cartesian_separation[dimension] = fractional.
x * lattice_vectors_[0][dimension] +
260 fractional.
y * lattice_vectors_[1][dimension] +
261 fractional.
z * lattice_vectors_[2][dimension];
263 return cartesian_separation;
270 return atoms_[atom_index].position;
274 return atoms_[atom_index].species_index;
285 return site_symmetry_classes_.empty() ? atoms_[atom_index].species_index
286 : site_symmetry_classes_[atom_index];
296 if (!classes.empty()) {
297 if (classes.size() != atoms_.size())
298 throw std::runtime_error(
"site symmetry classes: expected " +
299 std::to_string(atoms_.size()) +
" entries, got " +
300 std::to_string(classes.size()));
301 for (
size_t first = 0; first < atoms_.size(); ++first) {
302 if (classes[first] < 0)
303 throw std::runtime_error(
"site symmetry classes must be non-negative");
304 for (
size_t second = first + 1; second < atoms_.size(); ++second)
305 if (classes[first] == classes[second] &&
306 atoms_[first].species_index != atoms_[second].species_index)
307 throw std::runtime_error(
308 "site symmetry classes must not merge atoms of different species");
311 site_symmetry_classes_ = classes;
315 return !site_symmetry_classes_.empty();
318 return species_[species_index].valence_charge;
325 return lattice_vectors_ * lattice_parameter_;
332 return reciprocal_lattice_vectors_ * two_pi_over_lattice_parameter_;
339 const std::string& symbol = species_[atoms_[atom_index].species_index].symbol;
346 [[nodiscard]]
const std::string&
element(
int atom_index)
const {
347 return species_[atoms_[atom_index].species_index].symbol;
351 Real lattice_parameter_ = 0;
352 int bravais_lattice_index_ = 0;
353 Real cell_volume_ = 0;
354 Real two_pi_over_lattice_parameter_ = 0;
355 Real two_pi_over_lattice_parameter_squared_ = 0;
360 std::vector<AtomSpecies> species_;
361 std::vector<Atom> atoms_;
362 std::vector<int> site_symmetry_classes_;
int site_symmetry_class(int atom_index) const
Vector3D convert_from_crystal_to_cartesian(int atom_index) const
static Crystal from_lattice_vectors(Real lattice_parameter, const Matrix3x3 &lattice_vectors, const std::vector< AtomSpecies > &species, const std::vector< Atom > &atoms)
void set_atomic_positions(const std::vector< Vector3D > &positions)
Real two_pi_over_lattice_parameter_squared() const
int number_of_species() const
void add_atom(const Atom &atom)
int bravais_lattice_index() const
Real valence_charge(int species_index) const
static Crystal from_input_data(int bravais_lattice_index, Real cell_dimension_1, const std::vector< AtomSpecies > &species, const std::vector< Atom > &atoms, Real cell_dimension_2=0, Real cell_dimension_3=0, Real cell_dimension_4=0, Real cell_dimension_5=0, Real cell_dimension_6=0)
Real two_pi_over_lattice_parameter() const
bool has_site_symmetry_classes() const
void add_species(const AtomSpecies &species)
const Matrix3x3 & reciprocal_lattice_vectors() const
Vector3D fractional_position(int atom_index) const
const Matrix3x3 & lattice_vectors() const
const std::string & element(int atom_index) const
int species_type_index(int atom_index) const
Vector3D home_cell_separation(int atom_index_a, int atom_index_b) const
void set_from_lattice_type(int bravais_lattice_index, Real cell_dimension_1)
void compute_derived_quantities()
Matrix3x3 reciprocal_vectors_bohr() const
void set_from_lattice_type(int bravais_lattice_index, Real cell_dimension_1, Real cell_dimension_2, Real cell_dimension_3, Real cell_dimension_4, Real cell_dimension_5, Real cell_dimension_6)
int atomic_number(int atom_index) const
Matrix3x3 lattice_vectors_bohr() const
void set_site_symmetry_classes(const std::vector< int > &classes)
const std::vector< AtomSpecies > & species() const
int number_of_atoms() const
const std::vector< Atom > & atoms() const
void set_lattice(const Matrix3x3 &lattice_vectors)
Real lattice_parameter() const
static int atomic_number_by_element_symbol(const std::string &symbol)
Matrix3x3 get_lattice_vectors_from_bravais_index(int bravais_lattice_index, Real cell_dimension_1, Real cell_dimension_2=0, Real cell_dimension_3=0, Real cell_dimension_4=0, Real cell_dimension_5=0, Real cell_dimension_6=0)
3×3 matrix stored row-major: row i = mat[i]
Matrix3x3 transpose() const
Transpose.
Real determinant() const
Determinant.
Matrix3x3 inverse() const
Inverse (assumes non-singular)