From 00fe58b57bdc3375651e8912dfbca43667749edd Mon Sep 17 00:00:00 2001
From: mkirsz <s1351949@sms.ed.ac.uk>
Date: Mon, 25 Nov 2024 18:09:14 +0000
Subject: [PATCH] Helper methods for comparison

---
 include/tadah/mlip/atom.h      |  6 ++++++
 include/tadah/mlip/structure.h | 15 +++++++++++++-
 src/atom.cpp                   | 36 ++++++++++++++++++++--------------
 src/structure.cpp              | 17 ++++++++++++++++
 4 files changed, 58 insertions(+), 16 deletions(-)

diff --git a/include/tadah/mlip/atom.h b/include/tadah/mlip/atom.h
index 4a6fd87..04d82a4 100644
--- a/include/tadah/mlip/atom.h
+++ b/include/tadah/mlip/atom.h
@@ -79,5 +79,11 @@ struct Atom: public Element {
      */
     bool operator==(const Atom &) const;
 
+    /** Return true if both atoms have the same position and type.
+     *
+     * This method compares chemical type and position only
+     */
+    bool is_the_same(const Atom &, double thr=1e-6) const;
+
 };
 #endif
diff --git a/include/tadah/mlip/structure.h b/include/tadah/mlip/structure.h
index 1fa835b..9648e65 100644
--- a/include/tadah/mlip/structure.h
+++ b/include/tadah/mlip/structure.h
@@ -251,10 +251,23 @@ struct Structure {
    * This operator compares cell, stress tensor, number of atoms,
    * eweight, fweight and sweight, all atom positions and forces.
    *
-   * It does NOT compare labels/
+   * Assumes atoms have the same order.
+   *
+   * It does NOT compare labels.
    */
   bool operator==(const Structure& st) const;
 
+  /** Return true if both structures are the same.
+   *
+   * This method compares cell vectors, number of atoms,
+   * species and atomic coordinates
+   *
+   * Order ot atoms does not matter.
+   *
+   * It does NOT compare energies, stresses, forces and labels.
+   */
+  bool is_the_same(const Structure& st, double thr=1e-6) const;
+
   // move iterator forward to the next structure
   // return number of atoms in the structure
   // return 0 if there is no more structures
diff --git a/src/atom.cpp b/src/atom.cpp
index a84be1e..164a6c4 100644
--- a/src/atom.cpp
+++ b/src/atom.cpp
@@ -5,25 +5,31 @@
 Atom::Atom() {}
 
 Atom::Atom(const Element &element,
-        const double px, const double py, const double pz,
-        const double fx, const double fy, const double fz):
-    Element(element),
-    position(px,py,pz),
-    force(fx,fy,fz)
+           const double px, const double py, const double pz,
+           const double fx, const double fy, const double fz):
+  Element(element),
+  position(px,py,pz),
+  force(fx,fy,fz)
 {}
 
 std::ostream& operator<<(std::ostream& os, const Atom& atom)
 {
-    os     << (Element&)atom;
-    os     << "Coordinates:  " << std::left << atom.position << std::endl;
-    os     << "Force:        " << std::left << atom.force << std::endl;
-    return os;
+  os     << (Element&)atom;
+  os     << "Coordinates:  " << std::left << atom.position << std::endl;
+  os     << "Force:        " << std::left << atom.force << std::endl;
+  return os;
 }
 bool Atom::operator==(const Atom &a) const {
-    double EPSILON = std::numeric_limits<double>::epsilon();
-    return 
-        position.isApprox(a.position, EPSILON)
-        && force.isApprox(a.force, EPSILON)
-        && Element::operator==(a)
-        ;
+  double EPSILON = std::numeric_limits<double>::epsilon();
+  return 
+  position.isApprox(a.position, EPSILON)
+  && force.isApprox(a.force, EPSILON)
+  && Element::operator==(a)
+  ;
+}
+bool Atom::is_the_same(const Atom &a, double thr) const {
+  return 
+  position.isApprox(a.position, thr)
+  && Element::operator==(a)
+  ;
 }
diff --git a/src/structure.cpp b/src/structure.cpp
index 4aa0675..f5c6748 100644
--- a/src/structure.cpp
+++ b/src/structure.cpp
@@ -192,6 +192,23 @@ bool Structure::operator==(const Structure& st) const
   }
   return result;
 }
+bool Structure::is_the_same(const Structure& st, double thr) const
+{
+  bool result =
+    cell.isApprox(st.cell, thr)
+    && natoms()==st.natoms();
+  if (!result) return result;
+
+  size_t count=0;;
+  for (size_t i=0;i<natoms();++i) {
+    for (size_t j=i;j<natoms();++j) {
+      result = atoms[i].is_the_same(st.atoms[j], thr);
+      if (result) count++;
+    }
+  }
+
+  return count==natoms() ? true : false;
+}
 int Structure::next_structure(std::ifstream &ifs) {
   std::string line;
   std::getline(ifs,line);
-- 
GitLab