From 0df3883571fbe90592052b47543f4948daa70e6b Mon Sep 17 00:00:00 2001
From: Walter Van Herck <w.van.herck@fz-juelich.de>
Date: Thu, 27 Sep 2018 16:13:31 +0200
Subject: [PATCH] Create factory function for hexagonal close packed lattice

---
 Core/Lattice/Lattice.cpp                      |  18 ++-
 Core/Lattice/Lattice.h                        |   6 +-
 Core/Lattice/LatticeUtils.cpp                 |  12 +-
 Core/Lattice/LatticeUtils.h                   |   2 +
 .../MesoCrystalPerformanceBuilder.cpp         |   2 +-
 .../Functional/Python/PyCore/mesocrystal1.py  |   2 +-
 Tests/UnitTests/Core/Sample/CrystalTest.h     |   2 +-
 Tests/UnitTests/Core/Sample/LatticeTest.h     |   6 +-
 Tests/UnitTests/Core/Sample/MesoCrystalTest.h |   2 +-
 auto/Wrap/libBornAgainCore.py                 |  38 ++++--
 auto/Wrap/libBornAgainCore_wrap.cpp           | 111 +++++++++++++++++-
 11 files changed, 178 insertions(+), 23 deletions(-)

diff --git a/Core/Lattice/Lattice.cpp b/Core/Lattice/Lattice.cpp
index d69811b3c8a..73a5dc34973 100644
--- a/Core/Lattice/Lattice.cpp
+++ b/Core/Lattice/Lattice.cpp
@@ -143,6 +143,14 @@ std::vector<kvector_t> Lattice::reciprocalLatticeVectorsWithinRadius(
         input_vector, nearest_coords, radius, m_ra, m_rb, m_rc, m_a, m_b, m_c);
 }
 
+Lattice Lattice::createCubicLattice(double a)
+{
+    kvector_t a1(a, 0.0, 0.0);
+    kvector_t a2(0.0, a, 0.0);
+    kvector_t a3(0.0, 0.0, a);
+    return Lattice(a1, a2, a3);
+}
+
 Lattice Lattice::createFCCLattice(double a)
 {
     double b = a/2.0;
@@ -152,7 +160,7 @@ Lattice Lattice::createFCCLattice(double a)
     return Lattice(a1, a2, a3);
 }
 
-Lattice Lattice::createTrigonalLattice(double a, double c)
+Lattice Lattice::createHexagonalLattice(double a, double c)
 {
     kvector_t a1(a, 0.0, 0.0);
     kvector_t a2(-a/2.0, std::sqrt(3.0)*a/2.0, 0);
@@ -160,6 +168,14 @@ Lattice Lattice::createTrigonalLattice(double a, double c)
     return Lattice(a1, a2, a3);
 }
 
+Lattice Lattice::createHCPLattice(double a, double c)
+{
+    kvector_t a1(a, 0.0, 0.0);
+    kvector_t a2(-a/2.0, std::sqrt(3.0)*a/2.0, 0);
+    kvector_t a3(a/2.0, a/std::sqrt(3.0)/2.0, c/2.0);
+    return Lattice(a1, a2, a3);
+}
+
 void Lattice::onChange()
 {
     m_cache_ok = false;
diff --git a/Core/Lattice/Lattice.h b/Core/Lattice/Lattice.h
index 099f31fa034..f409672c485 100644
--- a/Core/Lattice/Lattice.h
+++ b/Core/Lattice/Lattice.h
@@ -75,9 +75,13 @@ public:
     //! Sets a selection rule for the reciprocal vectors
     void setSelectionRule(const ISelectionRule& p_selection_rule);
 
+    static Lattice createCubicLattice(double a);
+
     static Lattice createFCCLattice(double a);
 
-    static Lattice createTrigonalLattice(double a, double c);
+    static Lattice createHexagonalLattice(double a, double c);
+
+    static Lattice createHCPLattice(double a, double c);
 
     void onChange() override;
 
diff --git a/Core/Lattice/LatticeUtils.cpp b/Core/Lattice/LatticeUtils.cpp
index b14147a0fac..18f388420eb 100644
--- a/Core/Lattice/LatticeUtils.cpp
+++ b/Core/Lattice/LatticeUtils.cpp
@@ -18,10 +18,20 @@
 Lattice LatticeUtils::CreateFCCLattice(double lattice_constant,
                                        const ILatticeOrientation& orientation)
 {
-    Lattice prim_cubic( {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} );
+    Lattice prim_cubic = Lattice::createCubicLattice(1.0);
     std::unique_ptr<ILatticeOrientation> P_orientation(orientation.clone());
     P_orientation->usePrimitiveLattice(prim_cubic);
     auto rotation = P_orientation->transformationMatrix();
     Lattice fcc = Lattice::createFCCLattice(lattice_constant);
     return fcc.createTransformedLattice(rotation);
 }
+
+Lattice LatticeUtils::CreateHCPLattice(double a, double c, const ILatticeOrientation &orientation)
+{
+    Lattice prim_hexagonal = Lattice::createHexagonalLattice(1.0, c/a);
+    std::unique_ptr<ILatticeOrientation> P_orientation(orientation.clone());
+    P_orientation->usePrimitiveLattice(prim_hexagonal);
+    auto rotation = P_orientation->transformationMatrix();
+    Lattice hcp = Lattice::createHCPLattice(a, c);
+    return hcp.createTransformedLattice(rotation);
+}
diff --git a/Core/Lattice/LatticeUtils.h b/Core/Lattice/LatticeUtils.h
index b908c4bb5a7..74e48a57c9b 100644
--- a/Core/Lattice/LatticeUtils.h
+++ b/Core/Lattice/LatticeUtils.h
@@ -24,6 +24,8 @@ namespace LatticeUtils
 {
 BA_CORE_API_ Lattice CreateFCCLattice(double lattice_constant,
                                       const ILatticeOrientation& orientation);
+BA_CORE_API_ Lattice CreateHCPLattice(double a, double c,
+                                      const ILatticeOrientation& orientation);
 }  // namespace LatticeUtils
 
 #endif // LATTICEUTILS_H
diff --git a/Tests/Functional/Core/CoreSpecial/MesoCrystalPerformanceBuilder.cpp b/Tests/Functional/Core/CoreSpecial/MesoCrystalPerformanceBuilder.cpp
index 8d52b94dc21..bd62c3c099c 100644
--- a/Tests/Functional/Core/CoreSpecial/MesoCrystalPerformanceBuilder.cpp
+++ b/Tests/Functional/Core/CoreSpecial/MesoCrystalPerformanceBuilder.cpp
@@ -136,7 +136,7 @@ namespace
 
 Lattice createLattice(double a, double c)
 {
-    Lattice result = Lattice::createTrigonalLattice(a, c);
+    Lattice result = Lattice::createHexagonalLattice(a, c);
     result.setSelectionRule(SimpleSelectionRule(-1, 1, 1, 3));
     return result;
 }
diff --git a/Tests/Functional/Python/PyCore/mesocrystal1.py b/Tests/Functional/Python/PyCore/mesocrystal1.py
index 9a7fc15556c..9f42a1e2863 100644
--- a/Tests/Functional/Python/PyCore/mesocrystal1.py
+++ b/Tests/Functional/Python/PyCore/mesocrystal1.py
@@ -123,7 +123,7 @@ class MySampleBuilder(IMultiLayerBuilder):
     # create lattice
     # -------------------------------------------------------------------------
     def createLattice(self, stacking_radius_a, stacking_radius_c):
-        lattice = Lattice.createTrigonalLattice(stacking_radius_a*2.0, stacking_radius_c*2.0*2.3)
+        lattice = Lattice.createHexagonalLattice(stacking_radius_a*2.0, stacking_radius_c*2.0*2.3)
         p_result = Lattice(lattice)
         selection_rule = SimpleSelectionRule(-1, 1, 1, 3)
         p_result.setSelectionRule( selection_rule )
diff --git a/Tests/UnitTests/Core/Sample/CrystalTest.h b/Tests/UnitTests/Core/Sample/CrystalTest.h
index 5e22f442c0e..dbc87108a57 100644
--- a/Tests/UnitTests/Core/Sample/CrystalTest.h
+++ b/Tests/UnitTests/Core/Sample/CrystalTest.h
@@ -14,7 +14,7 @@ CrystalTest::~CrystalTest() = default;
 
 TEST_F(CrystalTest, getChildren)
 {
-    Lattice lattice = Lattice::createTrigonalLattice(1.0, 2.0);
+    Lattice lattice = Lattice::createHexagonalLattice(1.0, 2.0);
     ParticleComposition composition;
     Crystal crystal(composition, lattice);
 
diff --git a/Tests/UnitTests/Core/Sample/LatticeTest.h b/Tests/UnitTests/Core/Sample/LatticeTest.h
index cc962327b72..e7ba1fdff5c 100644
--- a/Tests/UnitTests/Core/Sample/LatticeTest.h
+++ b/Tests/UnitTests/Core/Sample/LatticeTest.h
@@ -163,10 +163,10 @@ TEST_F(LatticeTest, FCCLatticeTest)
     EXPECT_EQ(fcc3, l1.getBasisVectorC());
 }
 
-// tests trigonal lattice creation
-TEST_F(LatticeTest, TrigonalLatticeTest)
+// tests hexagonal lattice creation
+TEST_F(LatticeTest, HexagonalLatticeTest)
 {
-    Lattice l1 = Lattice::createTrigonalLattice(1, 4);
+    Lattice l1 = Lattice::createHexagonalLattice(1, 4);
 
     kvector_t tri1(1, 0.0, 0.0);
     kvector_t tri2(-1 / 2.0, std::sqrt(3.0) * 1 / 2.0, 0);
diff --git a/Tests/UnitTests/Core/Sample/MesoCrystalTest.h b/Tests/UnitTests/Core/Sample/MesoCrystalTest.h
index 8d678f0cf97..c367d146b8a 100644
--- a/Tests/UnitTests/Core/Sample/MesoCrystalTest.h
+++ b/Tests/UnitTests/Core/Sample/MesoCrystalTest.h
@@ -16,7 +16,7 @@ MesoCrystalTest::~MesoCrystalTest() = default;
 
 TEST_F(MesoCrystalTest, getChildren)
 {
-    Lattice lattice = Lattice::createTrigonalLattice(1.0, 2.0);
+    Lattice lattice = Lattice::createHexagonalLattice(1.0, 2.0);
     ParticleComposition composition;
     Crystal crystal(composition, lattice);
     MesoCrystal meso(crystal, FormFactorFullSphere(1.0));
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index 65fa2a3444f..144f5323d88 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -24519,17 +24519,29 @@ class Lattice(INode):
         return _libBornAgainCore.Lattice_setSelectionRule(self, p_selection_rule)
 
 
+    def createCubicLattice(a):
+        """createCubicLattice(double a) -> Lattice"""
+        return _libBornAgainCore.Lattice_createCubicLattice(a)
+
+    createCubicLattice = staticmethod(createCubicLattice)
+
     def createFCCLattice(a):
         """createFCCLattice(double a) -> Lattice"""
         return _libBornAgainCore.Lattice_createFCCLattice(a)
 
     createFCCLattice = staticmethod(createFCCLattice)
 
-    def createTrigonalLattice(a, c):
-        """createTrigonalLattice(double a, double c) -> Lattice"""
-        return _libBornAgainCore.Lattice_createTrigonalLattice(a, c)
+    def createHexagonalLattice(a, c):
+        """createHexagonalLattice(double a, double c) -> Lattice"""
+        return _libBornAgainCore.Lattice_createHexagonalLattice(a, c)
+
+    createHexagonalLattice = staticmethod(createHexagonalLattice)
+
+    def createHCPLattice(a, c):
+        """createHCPLattice(double a, double c) -> Lattice"""
+        return _libBornAgainCore.Lattice_createHCPLattice(a, c)
 
-    createTrigonalLattice = staticmethod(createTrigonalLattice)
+    createHCPLattice = staticmethod(createHCPLattice)
 
     def onChange(self):
         """
@@ -24545,13 +24557,21 @@ class Lattice(INode):
 Lattice_swigregister = _libBornAgainCore.Lattice_swigregister
 Lattice_swigregister(Lattice)
 
+def Lattice_createCubicLattice(a):
+    """Lattice_createCubicLattice(double a) -> Lattice"""
+    return _libBornAgainCore.Lattice_createCubicLattice(a)
+
 def Lattice_createFCCLattice(a):
     """Lattice_createFCCLattice(double a) -> Lattice"""
     return _libBornAgainCore.Lattice_createFCCLattice(a)
 
-def Lattice_createTrigonalLattice(a, c):
-    """Lattice_createTrigonalLattice(double a, double c) -> Lattice"""
-    return _libBornAgainCore.Lattice_createTrigonalLattice(a, c)
+def Lattice_createHexagonalLattice(a, c):
+    """Lattice_createHexagonalLattice(double a, double c) -> Lattice"""
+    return _libBornAgainCore.Lattice_createHexagonalLattice(a, c)
+
+def Lattice_createHCPLattice(a, c):
+    """Lattice_createHCPLattice(double a, double c) -> Lattice"""
+    return _libBornAgainCore.Lattice_createHCPLattice(a, c)
 
 
 def CreateFCCLattice(lattice_constant, orientation):
@@ -24562,6 +24582,10 @@ def CreateFCCLattice(lattice_constant, orientation):
 
     """
     return _libBornAgainCore.CreateFCCLattice(lattice_constant, orientation)
+
+def CreateHCPLattice(a, c, orientation):
+    """CreateHCPLattice(double a, double c, ILatticeOrientation orientation) -> Lattice"""
+    return _libBornAgainCore.CreateHCPLattice(a, c, orientation)
 class Lattice1DParameters(_object):
     """
 
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index 836d5d27a8b..89fce75173d 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -104793,6 +104793,28 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Lattice_createCubicLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  double arg1 ;
+  double val1 ;
+  int ecode1 = 0 ;
+  PyObject * obj0 = 0 ;
+  SwigValueWrapper< Lattice > result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Lattice_createCubicLattice",&obj0)) SWIG_fail;
+  ecode1 = SWIG_AsVal_double(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createCubicLattice" "', argument " "1"" of type '" "double""'");
+  } 
+  arg1 = static_cast< double >(val1);
+  result = Lattice::createCubicLattice(arg1);
+  resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Lattice_createFCCLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   double arg1 ;
@@ -104815,7 +104837,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Lattice_createTrigonalLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Lattice_createHexagonalLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   double arg1 ;
   double arg2 ;
@@ -104827,18 +104849,49 @@ SWIGINTERN PyObject *_wrap_Lattice_createTrigonalLattice(PyObject *SWIGUNUSEDPAR
   PyObject * obj1 = 0 ;
   SwigValueWrapper< Lattice > result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Lattice_createTrigonalLattice",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Lattice_createHexagonalLattice",&obj0,&obj1)) SWIG_fail;
   ecode1 = SWIG_AsVal_double(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createTrigonalLattice" "', argument " "1"" of type '" "double""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createHexagonalLattice" "', argument " "1"" of type '" "double""'");
   } 
   arg1 = static_cast< double >(val1);
   ecode2 = SWIG_AsVal_double(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice_createTrigonalLattice" "', argument " "2"" of type '" "double""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice_createHexagonalLattice" "', argument " "2"" of type '" "double""'");
   } 
   arg2 = static_cast< double >(val2);
-  result = Lattice::createTrigonalLattice(arg1,arg2);
+  result = Lattice::createHexagonalLattice(arg1,arg2);
+  resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Lattice_createHCPLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  double arg1 ;
+  double arg2 ;
+  double val1 ;
+  int ecode1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  SwigValueWrapper< Lattice > result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Lattice_createHCPLattice",&obj0,&obj1)) SWIG_fail;
+  ecode1 = SWIG_AsVal_double(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createHCPLattice" "', argument " "1"" of type '" "double""'");
+  } 
+  arg1 = static_cast< double >(val1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice_createHCPLattice" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  result = Lattice::createHCPLattice(arg1,arg2);
   resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
@@ -104908,6 +104961,49 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_CreateHCPLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  double arg1 ;
+  double arg2 ;
+  ILatticeOrientation *arg3 = 0 ;
+  double val1 ;
+  int ecode1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  SwigValueWrapper< Lattice > result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:CreateHCPLattice",&obj0,&obj1,&obj2)) SWIG_fail;
+  ecode1 = SWIG_AsVal_double(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "CreateHCPLattice" "', argument " "1"" of type '" "double""'");
+  } 
+  arg1 = static_cast< double >(val1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "CreateHCPLattice" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_ILatticeOrientation,  0  | 0);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CreateHCPLattice" "', argument " "3"" of type '" "ILatticeOrientation const &""'"); 
+  }
+  if (!argp3) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "CreateHCPLattice" "', argument " "3"" of type '" "ILatticeOrientation const &""'"); 
+  }
+  arg3 = reinterpret_cast< ILatticeOrientation * >(argp3);
+  result = LatticeUtils::CreateHCPLattice(arg1,arg2,(ILatticeOrientation const &)*arg3);
+  resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_new_Lattice1DParameters__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Lattice1DParameters *result = 0 ;
@@ -136813,8 +136909,10 @@ static PyMethodDef SwigMethods[] = {
 		"Sets a selection rule for the reciprocal vectors. \n"
 		"\n"
 		""},
+	 { (char *)"Lattice_createCubicLattice", _wrap_Lattice_createCubicLattice, METH_VARARGS, (char *)"Lattice_createCubicLattice(double a) -> Lattice"},
 	 { (char *)"Lattice_createFCCLattice", _wrap_Lattice_createFCCLattice, METH_VARARGS, (char *)"Lattice_createFCCLattice(double a) -> Lattice"},
-	 { (char *)"Lattice_createTrigonalLattice", _wrap_Lattice_createTrigonalLattice, METH_VARARGS, (char *)"Lattice_createTrigonalLattice(double a, double c) -> Lattice"},
+	 { (char *)"Lattice_createHexagonalLattice", _wrap_Lattice_createHexagonalLattice, METH_VARARGS, (char *)"Lattice_createHexagonalLattice(double a, double c) -> Lattice"},
+	 { (char *)"Lattice_createHCPLattice", _wrap_Lattice_createHCPLattice, METH_VARARGS, (char *)"Lattice_createHCPLattice(double a, double c) -> Lattice"},
 	 { (char *)"Lattice_onChange", _wrap_Lattice_onChange, METH_VARARGS, (char *)"\n"
 		"Lattice_onChange(Lattice self)\n"
 		"\n"
@@ -136830,6 +136928,7 @@ static PyMethodDef SwigMethods[] = {
 		"Lattice LatticeUtils::CreateFCCLattice(double lattice_constant, const ILatticeOrientation &orientation)\n"
 		"\n"
 		""},
+	 { (char *)"CreateHCPLattice", _wrap_CreateHCPLattice, METH_VARARGS, (char *)"CreateHCPLattice(double a, double c, ILatticeOrientation orientation) -> Lattice"},
 	 { (char *)"new_Lattice1DParameters", _wrap_new_Lattice1DParameters, METH_VARARGS, (char *)"\n"
 		"Lattice1DParameters()\n"
 		"new_Lattice1DParameters(double length, double xi) -> Lattice1DParameters\n"
-- 
GitLab