diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5b364d250b321b46dc3092ccf6e2c7562cc3860a..0294206175905f4c407b9926cbb15e8ebeb3f496 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,4 +46,5 @@ build_release_static: trigger_job: stage: trigger trigger: - project: tadah/tadah.mlip \ No newline at end of file + project: tadah/tadah.mlip + branch: $CI_COMMIT_REF_NAME \ No newline at end of file diff --git a/include/tadah/mlip/dataset_readers/dataset_reader_selector.h b/include/tadah/mlip/dataset_readers/dataset_reader_selector.h index 9c4808b416a9469d2b562883faa815a9f0b499bb..a09803ecc532770a28e191be52666ad02897b69a 100644 --- a/include/tadah/mlip/dataset_readers/dataset_reader_selector.h +++ b/include/tadah/mlip/dataset_readers/dataset_reader_selector.h @@ -15,11 +15,11 @@ public: /** * @brief Factory method to create specific DatasetReader objects. * - * @param type The type of the dataset reader to create. + * @param filepath File path to check the content. * @param db Reference to a StructureDB object to store parsed data. * @return A unique pointer to a DatasetReader object. */ - static std::unique_ptr<DatasetReader> get_reader(const std::string& type, StructureDB& db); + static std::unique_ptr<DatasetReader> get_reader(const std::string& filepath, StructureDB& db); /** * @brief Determines the file type based on its content. diff --git a/include/tadah/mlip/dataset_writers/castep_cell_writer.h b/include/tadah/mlip/dataset_writers/castep_cell_writer.h new file mode 100644 index 0000000000000000000000000000000000000000..90b799c4c70c0be8ad1748098765c4d9f5d50157 --- /dev/null +++ b/include/tadah/mlip/dataset_writers/castep_cell_writer.h @@ -0,0 +1,23 @@ +#ifndef CASTEP_CELL_WRITER_H +#define CASTEP_CELL_WRITER_H + +#include <tadah/mlip/structure.h> +#include <tadah/mlip/structure_db.h> +#include <tadah/mlip/dataset_writers/dataset_writer.h> + +#include <iostream> +#include <fstream> +#include <sstream> +#include <vector> +#include <stdexcept> +class CastepCellWriter : public DatasetWriter { +public: + CastepCellWriter(StructureDB& db); + + virtual void write_data(const std::string& filename, const size_t i) override; + +}; + +#endif // CASTEP_CELL_WRITER_H + + diff --git a/include/tadah/mlip/dataset_writers/dataset_writer.h b/include/tadah/mlip/dataset_writers/dataset_writer.h new file mode 100644 index 0000000000000000000000000000000000000000..91ff858df6c7f77b083a654440ed371e224525be --- /dev/null +++ b/include/tadah/mlip/dataset_writers/dataset_writer.h @@ -0,0 +1,23 @@ +#ifndef DATASET_WRITER_H +#define DATASET_WRITER_H + +#include <tadah/mlip/structure_db.h> +#include <string> +#include <vector> + +class DatasetWriter { + public: + virtual ~DatasetWriter() = default; + + virtual void write_data(const std::string& filename, const size_t i) = 0; + + DatasetWriter(StructureDB& db) : stdb(db) {}; + + virtual void set_precision(const size_t _p) { p = _p; w = p+6; }; + + protected: + StructureDB& stdb; + double p = 10; // output precision + double w = p+6; // column width +}; +#endif // DATASET_WRITER_H diff --git a/include/tadah/mlip/dataset_writers/dataset_writer_selector.h b/include/tadah/mlip/dataset_writers/dataset_writer_selector.h new file mode 100644 index 0000000000000000000000000000000000000000..7ea4f85e78bec210bd6ee9a92347e6899026734b --- /dev/null +++ b/include/tadah/mlip/dataset_writers/dataset_writer_selector.h @@ -0,0 +1,15 @@ +#ifndef DATASET_WRITER_SELECTOR_H +#define DATASET_WRITER_SELECTOR_H + +#include <tadah/mlip/structure_db.h> +#include <tadah/mlip/dataset_writers/dataset_writer.h> +#include <string> +#include <memory> + +class DatasetWriterSelector { + public: + static std::unique_ptr<DatasetWriter> get_writer(const std::string& type, StructureDB& db); + +}; + +#endif // DATASET_WRITER_SELECTOR_H diff --git a/include/tadah/mlip/dataset_writers/lammps_structure_writer.h b/include/tadah/mlip/dataset_writers/lammps_structure_writer.h new file mode 100644 index 0000000000000000000000000000000000000000..5ee539aea758bf972b33262af856c830ce241846 --- /dev/null +++ b/include/tadah/mlip/dataset_writers/lammps_structure_writer.h @@ -0,0 +1,21 @@ +#ifndef LAMMPS_STRUCTURE_WRITER_H +#define LAMMPS_STRUCTURE_WRITER_H + +#include <tadah/mlip/structure.h> +#include <tadah/mlip/structure_db.h> +#include <tadah/mlip/dataset_writers/dataset_writer.h> + +#include <iostream> +#include <fstream> +#include <sstream> +#include <vector> +#include <stdexcept> +class LammpsStructureWriter : public DatasetWriter { +public: + LammpsStructureWriter(StructureDB& db); + + virtual void write_data(const std::string& filename, const size_t i) override; + +}; + +#endif // LAMMPS_STRUCTURE_WRITER_H diff --git a/include/tadah/mlip/dataset_writers/vasp_poscar_writer.h b/include/tadah/mlip/dataset_writers/vasp_poscar_writer.h new file mode 100644 index 0000000000000000000000000000000000000000..abd58b8b38aa34b1330e0c22703ff4d24c0df9e4 --- /dev/null +++ b/include/tadah/mlip/dataset_writers/vasp_poscar_writer.h @@ -0,0 +1,21 @@ +#ifndef VASP_POSCAR_WRITER_H +#define VASP_POSCAR_WRITER_H + +#include <tadah/mlip/structure.h> +#include <tadah/mlip/structure_db.h> +#include <tadah/mlip/dataset_writers/dataset_writer.h> + +#include <iostream> +#include <fstream> +#include <sstream> +#include <vector> +#include <stdexcept> +class VaspPoscarWriter : public DatasetWriter { +public: + VaspPoscarWriter(StructureDB& db); + + virtual void write_data(const std::string& filename, const size_t i) override; + +}; + +#endif // VASP_POSCAR_WRITER_H diff --git a/src/castep_cell_writer.cpp b/src/castep_cell_writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..144da27ab7715efa0a652dfc27c88ad8745a2d94 --- /dev/null +++ b/src/castep_cell_writer.cpp @@ -0,0 +1,53 @@ +#include <tadah/mlip/structure.h> +#include <tadah/mlip/structure_db.h> +#include <tadah/mlip/dataset_writers/castep_cell_writer.h> + +CastepCellWriter::CastepCellWriter(StructureDB& db) : DatasetWriter(db) {} + +void CastepCellWriter::write_data(const std::string& filename, const size_t i) { + + if (i >= stdb.size()) { + throw std::out_of_range("Index i is out of range."); + } + + std::ofstream file(filename); + if (!file.is_open()) { + throw std::runtime_error("Could not open the file: " + filename); + } + + const Structure &st = stdb(i); + + // write label + file << "# " << st.label << std::endl; + + // write cell + file << "%BLOCK LATTICE_CART" << std::endl; + file << "ANG" << std::endl; + for (int i=0; i<3; ++i) { + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << st.cell(i,0); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << st.cell(i,1); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << st.cell(i,2); + file << std::endl; + } + file << "%ENDBLOCK LATTICE_CART" << std::endl; + + file << std::endl; + + file << "%BLOCK POSITIONS_ABS" << std::endl; + for (const auto &atom : st) { + file << std::right << std::fixed << std::setw(w) + << atom.symbol; + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << atom.position(0); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << atom.position(1); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << atom.position(2); + file << std::endl; + } + file << "%ENDBLOCK POSITIONS_ABS " << std::endl; + file.close(); +} diff --git a/src/dataset_writer_selector.cpp b/src/dataset_writer_selector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c038bedb81b2a239201601371d1b15761a39933d --- /dev/null +++ b/src/dataset_writer_selector.cpp @@ -0,0 +1,20 @@ +#include <tadah/mlip/dataset_writers/dataset_writer_selector.h> +#include <tadah/mlip/dataset_writers/castep_cell_writer.h> +#include <tadah/mlip/dataset_writers/vasp_poscar_writer.h> +#include <tadah/mlip/dataset_writers/lammps_structure_writer.h> + +// Factory method implementation +std::unique_ptr<DatasetWriter> DatasetWriterSelector::get_writer(const std::string& type, StructureDB& db) { + + if (type == "CASTEP") { + return std::make_unique<CastepCellWriter>(db); + } else if (type == "VASP") { + return std::make_unique<VaspPoscarWriter>(db); + } else if (type == "LAMMPS") { + return std::make_unique<LammpsStructureWriter>(db); + } else { + std::cerr << "Unknown type! Returning nullptr." << std::endl; + return nullptr; + } + +} diff --git a/src/lammps_structure_writer.cpp b/src/lammps_structure_writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e634f3837cb870add5d88fb12e086c10472bbd5e --- /dev/null +++ b/src/lammps_structure_writer.cpp @@ -0,0 +1,88 @@ +#include <tadah/mlip/structure.h> +#include <tadah/mlip/structure_db.h> +#include <tadah/mlip/dataset_writers/lammps_structure_writer.h> + +LammpsStructureWriter::LammpsStructureWriter(StructureDB& db) : DatasetWriter(db) {} + +void LammpsStructureWriter::write_data(const std::string& filename, const size_t i) { + + if (i >= stdb.size()) { + throw std::out_of_range("Index i is out of range."); + } + + std::ofstream file(filename); + if (!file.is_open()) { + throw std::runtime_error("Could not open the file: " + filename); + } + + const Structure &st = stdb(i); + + // compute number of atoms for a given element + const auto &elements = st.get_unique_elements(); + std::map<std::string, size_t> nelements; + std::map<std::string, size_t> type; + // Initialize the count for each element + for (const auto& element : elements) { + nelements[element.symbol] = 0; + } + // then count... + size_t t=0; + for (const auto &atom : st) { + nelements[atom.symbol]++; + if (type.find(atom.symbol) == type.end()) { + type[atom.symbol] = ++t; + } + } + + // BEGIN OF LAMMPS HEADER + file << st.label << std::endl; + file << std::endl; + file << st.natoms() << " atoms" << std::endl; + file << nelements.size() << " atom types" << std::endl; + file << std::endl; + + // General triclinic box format + std::vector<std::string> abcvec = {"avec", "bvec", "cvec"}; + for (int i=0; i<3; ++i) { + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << st.cell(i,0); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << st.cell(i,1); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << st.cell(i,2) + << " " << abcvec[i]; + file << std::endl; + } + file << " 0.0 0.0 0.0 abc origin" << std::endl; + // END LAMMPS HEADER + + // BEGIN LAMMPS BODY + file << std::endl; + file << "Masses" << std::endl; + file << std::endl; + for (const auto &t: type) { + file << t.second << " " << PeriodicTable::get_mass(t.first) << " # " << t.first << std::endl; + } + + file << std::endl; + file << "Atoms # atomic" << std::endl; + file << std::endl; + // atomic: atom-ID [int, 1-Natoms] atom-type [int, 1-Ntype] x y z + + size_t idx=1; + for (const auto &atom : st) { + file << std::right << std::fixed << std::setw(w) << idx; + file << std::right << std::fixed << std::setw(w) << type[atom.symbol]; + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << atom.position(0); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << atom.position(1); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << atom.position(2); + file << std::endl; + idx++; + } + // END LAMMPS BODY + + file.close(); +} diff --git a/src/vasp_poscar_writer.cpp b/src/vasp_poscar_writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33144181c9849ec4779e063c081dd39e8c3592f9 --- /dev/null +++ b/src/vasp_poscar_writer.cpp @@ -0,0 +1,79 @@ +#include <tadah/mlip/structure.h> +#include <tadah/mlip/structure_db.h> +#include <tadah/mlip/dataset_writers/vasp_poscar_writer.h> + +#include <fstream> + +VaspPoscarWriter::VaspPoscarWriter(StructureDB& db) : DatasetWriter(db) {} + +void VaspPoscarWriter::write_data(const std::string& filename, const size_t i) { + + if (i >= stdb.size()) { + throw std::out_of_range("Index i is out of range."); + } + + std::ofstream file(filename); + if (!file.is_open()) { + throw std::runtime_error("Could not open the file: " + filename); + } + + const Structure &st = stdb(i); + + // write scaling factor + file << st.label << std::endl; + file << "1.0" << std::endl; + + // write cell + for (int i=0; i<3; ++i) { + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << st.cell(i,0); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << st.cell(i,1); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << st.cell(i,2); + file << std::endl; + } + + + // compute number of atoms for a given element + const auto &elements = st.get_unique_elements(); + std::map<std::string, size_t> nelements; + // Initialize the count for each element + for (const auto& element : elements) { + nelements[element.symbol] = 0; + } + // then count... + for (const auto &atom : st) { + nelements[atom.symbol]++; + } + + // write elements + for (const auto& pair: nelements) { + file << pair.first << " "; + } + file << std::endl; + + // write number of every elements + for (const auto& pair: nelements) { + file << pair.second << " "; + } + file << std::endl; + + file << "Cartesian" << std::endl; + + for (const auto& pair: nelements) { + for (const auto &atom : st) { + if (pair.first == atom.symbol) { + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << atom.position(0); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << atom.position(1); + file << std::right << std::fixed << std::setw(w) + << std::setprecision(p) << atom.position(2); + file << std::endl; + } + } + } + + file.close(); +}