From 026b8ac1950798d32d0836457a2eb44ccd30595e Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Wed, 31 Aug 2022 10:35:09 +0200
Subject: [PATCH] + Ellipsoids, overlooked

---
 Sample/HardParticle/EllipsoidalCylinder.cpp | 23 +++++++--
 Sample/HardParticle/EllipsoidalCylinder.h   |  8 +--
 Sample/HardParticle/HemiEllipsoid.cpp       | 23 +++++++--
 Sample/HardParticle/HemiEllipsoid.h         | 10 ++--
 auto/Wrap/doxygenSample.i                   |  6 +++
 auto/Wrap/libBornAgainSample.py             | 16 ++++++
 auto/Wrap/libBornAgainSample_wrap.cpp       | 56 +++++++++++++++++++++
 7 files changed, 129 insertions(+), 13 deletions(-)

diff --git a/Sample/HardParticle/EllipsoidalCylinder.cpp b/Sample/HardParticle/EllipsoidalCylinder.cpp
index 53cadfd6660..f3cb6380749 100644
--- a/Sample/HardParticle/EllipsoidalCylinder.cpp
+++ b/Sample/HardParticle/EllipsoidalCylinder.cpp
@@ -16,6 +16,7 @@
 #include "Base/Math/Bessel.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
+#include "Base/Util/Assert.h"
 #include "Sample/Shapes/DoubleEllipse.h"
 
 EllipsoidalCylinder::EllipsoidalCylinder(const std::vector<double> P)
@@ -24,9 +25,7 @@ EllipsoidalCylinder::EllipsoidalCylinder(const std::vector<double> P)
     , m_radius_y(m_P[1])
     , m_height(m_P[2])
 {
-    checkNodeArgs();
-    m_shape3D =
-        std::make_unique<DoubleEllipseZ>(m_radius_x, m_radius_y, m_height, m_radius_x, m_radius_y);
+    validateOrThrow();
 }
 
 EllipsoidalCylinder::EllipsoidalCylinder(double radius_x, double radius_y, double height)
@@ -36,11 +35,13 @@ EllipsoidalCylinder::EllipsoidalCylinder(double radius_x, double radius_y, doubl
 
 double EllipsoidalCylinder::radialExtension() const
 {
+    ASSERT(m_validated);
     return (m_radius_x + m_radius_y) / 2.0;
 }
 
 complex_t EllipsoidalCylinder::formfactor_at_bottom(C3 q) const
 {
+    ASSERT(m_validated);
     complex_t qxRa = q.x() * m_radius_x;
     complex_t qyRb = q.y() * m_radius_y;
     complex_t qzHdiv2 = m_height / 2 * q.z();
@@ -51,3 +52,19 @@ complex_t EllipsoidalCylinder::formfactor_at_bottom(C3 q) const
 
     return M_TWOPI * m_radius_x * m_radius_y * m_height * Fz * J1_gamma_div_gamma;
 }
+
+std::string EllipsoidalCylinder::validate() const
+{
+    std::vector<std::string> errs;
+    requestGt0(errs, m_radius_x, "radius_x");
+    requestGt0(errs, m_radius_y, "radius_y");
+    requestGt0(errs, m_height, "height");
+    if (!errs.empty())
+        return jointError("Cylinder", errs);
+
+    m_shape3D =
+        std::make_unique<DoubleEllipseZ>(m_radius_x, m_radius_y, m_height, m_radius_x, m_radius_y);
+
+    m_validated = true;
+    return "";
+}
diff --git a/Sample/HardParticle/EllipsoidalCylinder.h b/Sample/HardParticle/EllipsoidalCylinder.h
index d307daa9175..07085c3bdb1 100644
--- a/Sample/HardParticle/EllipsoidalCylinder.h
+++ b/Sample/HardParticle/EllipsoidalCylinder.h
@@ -33,9 +33,9 @@ public:
     std::string className() const final { return "EllipsoidalCylinder"; }
     std::vector<ParaMeta> parDefs() const final
     {
-        return {{"RadiusX", "nm", "radius in x direction", 0, +INF, 0},
-                {"RadiusY", "nm", "radius in y direction", 0, +INF, 0},
-                {"Height", "nm", "height", 0, +INF, 0}};
+        return {{"RadiusX", "nm"},
+                {"RadiusY", "nm"},
+                {"Height", "nm"}};
     }
 
     double radiusX() const { return m_radius_x; }
@@ -46,6 +46,8 @@ public:
 
     complex_t formfactor_at_bottom(C3 q) const override;
 
+    std::string validate() const final;
+
 private:
     const double& m_radius_x;
     const double& m_radius_y;
diff --git a/Sample/HardParticle/HemiEllipsoid.cpp b/Sample/HardParticle/HemiEllipsoid.cpp
index 5db4767b06c..925fe68279f 100644
--- a/Sample/HardParticle/HemiEllipsoid.cpp
+++ b/Sample/HardParticle/HemiEllipsoid.cpp
@@ -16,6 +16,7 @@
 #include "Base/Math/Bessel.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/IntegratorGK.h"
+#include "Base/Util/Assert.h"
 #include "Sample/Shapes/TruncatedEllipsoidNet.h"
 #include <limits>
 
@@ -25,9 +26,7 @@ HemiEllipsoid::HemiEllipsoid(const std::vector<double> P)
     , m_radius_y(m_P[1])
     , m_height(m_P[2])
 {
-    checkNodeArgs();
-    m_shape3D =
-        std::make_unique<TruncatedEllipsoidNet>(m_radius_x, m_radius_x, m_height, m_height, 0.0);
+    validateOrThrow();
 }
 
 HemiEllipsoid::HemiEllipsoid(double radius_x, double radius_y, double height)
@@ -37,11 +36,13 @@ HemiEllipsoid::HemiEllipsoid(double radius_x, double radius_y, double height)
 
 double HemiEllipsoid::radialExtension() const
 {
+    ASSERT(m_validated);
     return (m_radius_x + m_radius_y) / 2.0;
 }
 
 complex_t HemiEllipsoid::formfactor_at_bottom(C3 q) const
 {
+    ASSERT(m_validated);
     double R = m_radius_x;
     double W = m_radius_y;
     double H = m_height;
@@ -69,3 +70,19 @@ complex_t HemiEllipsoid::formfactor_at_bottom(C3 q) const
                },
                0., H);
 }
+
+std::string HemiEllipsoid::validate() const
+{
+    std::vector<std::string> errs;
+    requestGt0(errs, m_radius_x, "radius_x");
+    requestGt0(errs, m_radius_y, "radius_y");
+    requestGt0(errs, m_height, "height");
+    if (!errs.empty())
+        return jointError("HemiEllipsoid", errs);
+
+    m_shape3D =
+        std::make_unique<TruncatedEllipsoidNet>(m_radius_x, m_radius_x, m_height, m_height, 0.0);
+
+    m_validated = true;
+    return "";
+}
diff --git a/Sample/HardParticle/HemiEllipsoid.h b/Sample/HardParticle/HemiEllipsoid.h
index 9603203edca..5cdf01f2dc0 100644
--- a/Sample/HardParticle/HemiEllipsoid.h
+++ b/Sample/HardParticle/HemiEllipsoid.h
@@ -35,9 +35,9 @@ public:
     std::string className() const final { return "HemiEllipsoid"; }
     std::vector<ParaMeta> parDefs() const final
     {
-        return {{"RadiusX", "nm", "radius in x direction", 0, +INF, 0},
-                {"RadiusY", "nm", "radius in y direction", 0, +INF, 0},
-                {"Height", "nm", "height = radius in z direction", 0, +INF, 0}};
+        return {{"RadiusX", "nm"},
+                {"RadiusY", "nm"},
+                {"Height", "nm"}};
     }
 
     double height() const { return m_height; }
@@ -48,10 +48,12 @@ public:
 
     complex_t formfactor_at_bottom(C3 q) const override;
 
+    std::string validate() const final;
+
 private:
     const double& m_radius_x;
     const double& m_radius_y;
-    const double& m_height;
+    const double& m_height; //!< radius in +z direction
 #endif // USER_API
 };
 
diff --git a/auto/Wrap/doxygenSample.i b/auto/Wrap/doxygenSample.i
index 2dbe87295fc..ef3cae34be3 100644
--- a/auto/Wrap/doxygenSample.i
+++ b/auto/Wrap/doxygenSample.i
@@ -720,6 +720,9 @@ Returns the (approximate in some cases) radial size of the particle of this form
 %feature("docstring")  EllipsoidalCylinder::formfactor_at_bottom "complex_t EllipsoidalCylinder::formfactor_at_bottom(C3 q) const override
 EllipsoidalCylinder::formfactor_at_bottom";
 
+%feature("docstring")  EllipsoidalCylinder::validate "std::string EllipsoidalCylinder::validate() const final
+EllipsoidalCylinder::validate";
+
 
 // File: classFormFactorComponents.xml
 %feature("docstring") FormFactorComponents "
@@ -883,6 +886,9 @@ Returns the (approximate in some cases) radial size of the particle of this form
 %feature("docstring")  HemiEllipsoid::formfactor_at_bottom "complex_t HemiEllipsoid::formfactor_at_bottom(C3 q) const override
 HemiEllipsoid::formfactor_at_bottom";
 
+%feature("docstring")  HemiEllipsoid::validate "std::string HemiEllipsoid::validate() const final
+HemiEllipsoid::validate";
+
 
 // File: classHexagonalLattice2D.xml
 %feature("docstring") HexagonalLattice2D "
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index 94c851abe6e..058b6c34eb2 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -8369,6 +8369,14 @@ class EllipsoidalCylinder(IFormFactor):
         EllipsoidalCylinder::formfactor_at_bottom
         """
         return _libBornAgainSample.EllipsoidalCylinder_formfactor_at_bottom(self, q)
+
+    def validate(self):
+        r"""
+        validate(EllipsoidalCylinder self) -> std::string
+        std::string EllipsoidalCylinder::validate() const final
+        EllipsoidalCylinder::validate
+        """
+        return _libBornAgainSample.EllipsoidalCylinder_validate(self)
     __swig_destroy__ = _libBornAgainSample.delete_EllipsoidalCylinder
 
 # Register EllipsoidalCylinder in _libBornAgainSample:
@@ -8661,6 +8669,14 @@ class HemiEllipsoid(IFormFactor):
         """
         return _libBornAgainSample.HemiEllipsoid_formfactor_at_bottom(self, q)
 
+    def validate(self):
+        r"""
+        validate(HemiEllipsoid self) -> std::string
+        std::string HemiEllipsoid::validate() const final
+        HemiEllipsoid::validate
+        """
+        return _libBornAgainSample.HemiEllipsoid_validate(self)
+
 # Register HemiEllipsoid in _libBornAgainSample:
 _libBornAgainSample.HemiEllipsoid_swigregister(HemiEllipsoid)
 
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index 49b9d163212..94d8bc7d217 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -51687,6 +51687,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_EllipsoidalCylinder_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  EllipsoidalCylinder *arg1 = (EllipsoidalCylinder *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_EllipsoidalCylinder, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "EllipsoidalCylinder_validate" "', argument " "1"" of type '" "EllipsoidalCylinder const *""'"); 
+  }
+  arg1 = reinterpret_cast< EllipsoidalCylinder * >(argp1);
+  result = ((EllipsoidalCylinder const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_EllipsoidalCylinder(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   EllipsoidalCylinder *arg1 = (EllipsoidalCylinder *) 0 ;
@@ -52816,6 +52839,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_HemiEllipsoid_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  HemiEllipsoid *arg1 = (HemiEllipsoid *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_HemiEllipsoid, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "HemiEllipsoid_validate" "', argument " "1"" of type '" "HemiEllipsoid const *""'"); 
+  }
+  arg1 = reinterpret_cast< HemiEllipsoid * >(argp1);
+  result = ((HemiEllipsoid const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *HemiEllipsoid_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
@@ -65165,6 +65211,11 @@ static PyMethodDef SwigMethods[] = {
 		"complex_t EllipsoidalCylinder::formfactor_at_bottom(C3 q) const override\n"
 		"EllipsoidalCylinder::formfactor_at_bottom\n"
 		""},
+	 { "EllipsoidalCylinder_validate", _wrap_EllipsoidalCylinder_validate, METH_O, "\n"
+		"EllipsoidalCylinder_validate(EllipsoidalCylinder self) -> std::string\n"
+		"std::string EllipsoidalCylinder::validate() const final\n"
+		"EllipsoidalCylinder::validate\n"
+		""},
 	 { "delete_EllipsoidalCylinder", _wrap_delete_EllipsoidalCylinder, METH_O, "delete_EllipsoidalCylinder(EllipsoidalCylinder self)"},
 	 { "EllipsoidalCylinder_swigregister", EllipsoidalCylinder_swigregister, METH_O, NULL},
 	 { "EllipsoidalCylinder_swiginit", EllipsoidalCylinder_swiginit, METH_VARARGS, NULL},
@@ -65334,6 +65385,11 @@ static PyMethodDef SwigMethods[] = {
 		"complex_t HemiEllipsoid::formfactor_at_bottom(C3 q) const override\n"
 		"HemiEllipsoid::formfactor_at_bottom\n"
 		""},
+	 { "HemiEllipsoid_validate", _wrap_HemiEllipsoid_validate, METH_O, "\n"
+		"HemiEllipsoid_validate(HemiEllipsoid self) -> std::string\n"
+		"std::string HemiEllipsoid::validate() const final\n"
+		"HemiEllipsoid::validate\n"
+		""},
 	 { "HemiEllipsoid_swigregister", HemiEllipsoid_swigregister, METH_O, NULL},
 	 { "HemiEllipsoid_swiginit", HemiEllipsoid_swiginit, METH_VARARGS, NULL},
 	 { "new_HollowSphere", _wrap_new_HollowSphere, METH_VARARGS, "\n"
-- 
GitLab