From 44eb922e27cf7904fefe7ec4af1da58d6e4edef1 Mon Sep 17 00:00:00 2001
From: Walter Van Herck <w.van.herck@fz-juelich.de>
Date: Mon, 12 Jun 2017 18:07:48 +0200
Subject: [PATCH] Add initialization step (formal) for B fields in
 MainComputation

---
 Core/Computation/MainComputation.cpp | 19 ++++++++++++-------
 Core/Computation/MainComputation.h   |  5 ++++-
 Core/Multilayer/MultiLayer.cpp       |  5 +++++
 Core/Multilayer/MultiLayer.h         |  3 +++
 auto/Wrap/libBornAgainCore.py        |  5 +++++
 auto/Wrap/libBornAgainCore_wrap.cpp  | 22 ++++++++++++++++++++++
 6 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/Core/Computation/MainComputation.cpp b/Core/Computation/MainComputation.cpp
index 09e88f9e96c..900f5abc271 100644
--- a/Core/Computation/MainComputation.cpp
+++ b/Core/Computation/MainComputation.cpp
@@ -102,7 +102,7 @@ IFresnelMap* MainComputation::createFresnelMap()
             return new MatrixFresnelMap();
 }
 
-std::unique_ptr<MultiLayer> MainComputation::getAveragedMultilayer()
+std::unique_ptr<MultiLayer> MainComputation::getAveragedMultilayer() const
 {
     std::map<size_t, std::vector<HomogeneousRegion>> region_map;
     for (auto& comp: m_computation_terms) {
@@ -125,14 +125,19 @@ std::unique_ptr<MultiLayer> MainComputation::getAveragedMultilayer()
     return P_result;
 }
 
+std::unique_ptr<MultiLayer> MainComputation::getMultilayerForFresnel() const
+{
+    std::unique_ptr<MultiLayer> P_result = m_sim_options.useAvgMaterials()
+                                           ? getAveragedMultilayer()
+                                           : std::unique_ptr<MultiLayer>(mP_multi_layer->clone());
+    P_result->initBFields();
+    return P_result;
+}
+
 void MainComputation::initFresnelMap()
 {
-    if (m_sim_options.useAvgMaterials()) {
-        auto avg_multilayer = getAveragedMultilayer();
-        mP_fresnel_map->setMultilayer(*avg_multilayer);
-    }
-    else
-        mP_fresnel_map->setMultilayer(*mP_multi_layer);
+    auto multilayer = getMultilayerForFresnel();
+    mP_fresnel_map->setMultilayer(*multilayer);
 }
 
 bool MainComputation::checkRegions(const std::vector<HomogeneousRegion>& regions) const
diff --git a/Core/Computation/MainComputation.h b/Core/Computation/MainComputation.h
index 6fed2fb5d13..373b3e2dc4c 100644
--- a/Core/Computation/MainComputation.h
+++ b/Core/Computation/MainComputation.h
@@ -57,7 +57,10 @@ private:
     void runProtected();
     IFresnelMap* createFresnelMap();
     // creates a multilayer that contains averaged materials, for use in Fresnel calculations
-    std::unique_ptr<MultiLayer> getAveragedMultilayer();
+    std::unique_ptr<MultiLayer> getAveragedMultilayer() const;
+    // creates a multilayer for use in Fresnel calculations; if needed, it calculates average
+    // materials and precalculates the magnetic B fields
+    std::unique_ptr<MultiLayer> getMultilayerForFresnel() const;
     // sets the correct layer materials for the Fresnel map to use
     void initFresnelMap();
     bool checkRegions(const std::vector<HomogeneousRegion>& regions) const;
diff --git a/Core/Multilayer/MultiLayer.cpp b/Core/Multilayer/MultiLayer.cpp
index fc9a456bd8c..b6bb7a7f6ff 100644
--- a/Core/Multilayer/MultiLayer.cpp
+++ b/Core/Multilayer/MultiLayer.cpp
@@ -181,6 +181,11 @@ bool MultiLayer::containsMagneticMaterial() const
     return false;
 }
 
+void MultiLayer::initBFields()
+{
+    return;
+}
+
 bool MultiLayer::hasRoughness() const
 {
     for (auto p_interface: m_interfaces)
diff --git a/Core/Multilayer/MultiLayer.h b/Core/Multilayer/MultiLayer.h
index 593f05d8b7b..2303f5fbd0c 100644
--- a/Core/Multilayer/MultiLayer.h
+++ b/Core/Multilayer/MultiLayer.h
@@ -130,6 +130,9 @@ public:
 
     bool containsMagneticMaterial() const;
 
+    //! precalculate the magnetic B fields in each layer
+    void initBFields();
+
     bool hasRoughness() const;
 
     size_t totalNofLayouts() const;
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index 80971776f6f..cf2de9b7e76 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -22717,6 +22717,11 @@ class MultiLayer(ISample):
         return _libBornAgainCore.MultiLayer_containsMagneticMaterial(self)
 
 
+    def initBFields(self):
+        """initBFields(MultiLayer self)"""
+        return _libBornAgainCore.MultiLayer_initBFields(self)
+
+
     def hasRoughness(self):
         """
         hasRoughness(MultiLayer self) -> bool
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index ee5f42d1525..dedc1efcdd4 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -95717,6 +95717,27 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_MultiLayer_initBFields(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MultiLayer *arg1 = (MultiLayer *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:MultiLayer_initBFields",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_MultiLayer, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MultiLayer_initBFields" "', argument " "1"" of type '" "MultiLayer *""'"); 
+  }
+  arg1 = reinterpret_cast< MultiLayer * >(argp1);
+  (arg1)->initBFields();
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_MultiLayer_hasRoughness(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   MultiLayer *arg1 = (MultiLayer *) 0 ;
@@ -120386,6 +120407,7 @@ static PyMethodDef SwigMethods[] = {
 		"bool MultiLayer::containsMagneticMaterial() const \n"
 		"\n"
 		""},
+	 { (char *)"MultiLayer_initBFields", _wrap_MultiLayer_initBFields, METH_VARARGS, (char *)"MultiLayer_initBFields(MultiLayer self)"},
 	 { (char *)"MultiLayer_hasRoughness", _wrap_MultiLayer_hasRoughness, METH_VARARGS, (char *)"\n"
 		"MultiLayer_hasRoughness(MultiLayer self) -> bool\n"
 		"\n"
-- 
GitLab