Browse Source

Added coupling routine

master
T-bone 7 years ago
parent
commit
7dba245aa5
9 changed files with 820 additions and 8 deletions
  1. 5
    0
      examples/CMakeLists.txt
  2. 101
    0
      examples/Coupling.cpp
  3. 7
    4
      examples/KernelV0.cpp
  4. 1
    1
      examples/plotkernel.py
  5. 258
    0
      include/Coupling.h
  6. 1
    0
      include/Merlin
  7. 1
    0
      src/CMakeLists.txt
  8. 444
    0
      src/Coupling.cpp
  9. 2
    3
      src/KernelV0.cpp

+ 5
- 0
examples/CMakeLists.txt View File

@@ -1,11 +1,16 @@
1 1
 add_executable( KernelV0 KernelV0.cpp  )
2 2
 target_link_libraries(  KernelV0  "lemmacore" "fdem1d" "merlin")
3 3
 
4
+add_executable( Coupling Coupling.cpp  )
5
+target_link_libraries(  Coupling  "lemmacore" "fdem1d" "merlin")
6
+
4 7
 # Linking
5 8
 if ( LEMMA_VTK6_SUPPORT OR LEMMA_VTK7_SUPPORT ) 
6 9
 	target_link_libraries( KernelV0 ${VTK_LIBRARIES})
10
+	target_link_libraries( Coupling ${VTK_LIBRARIES})
7 11
 endif()
8 12
 
9 13
 INSTALL_TARGETS( "/share/Merlin/"
10 14
 	KernelV0
15
+	Coupling
11 16
 )

+ 101
- 0
examples/Coupling.cpp View File

@@ -0,0 +1,101 @@
1
+/* This file is part of Lemma, a geophysical modelling and inversion API.
2
+ * More information is available at http://lemmasoftware.org
3
+ */
4
+
5
+/* This Source Code Form is subject to the terms of the Mozilla Public
6
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
7
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
+ */
9
+
10
+/**
11
+ * @file
12
+ * @date      11/11/2016 02:44:37 PM
13
+ * @version   $Id$
14
+ * @author    Trevor Irons (ti)
15
+ * @email     tirons@egi.utah.edu
16
+ * @copyright Copyright (c) 2016, University of Utah
17
+ * @copyright Copyright (c) 2016, Lemma Software, LLC
18
+ */
19
+
20
+#include <Merlin>
21
+using namespace Lemma;
22
+
23
+std::shared_ptr<PolygonalWireAntenna> CircularLoop ( int nd, Real radius, Real Offsetx, Real Offsety ) ;
24
+void MoveLoop( std::shared_ptr<PolygonalWireAntenna> Loop, int nd, Real Radius, Real Offsetx, Real Offsety );
25
+
26
+int main(int argc, char** argv) {
27
+
28
+    Real offset = atof(argv[1]);
29
+
30
+	auto earth = LayeredEarthEM::NewSP();
31
+		earth->SetNumberOfLayers(3);
32
+		earth->SetLayerConductivity( (VectorXcr(3) << Complex(0.,0), Complex(1./50.,0), Complex(1./100.)).finished() );
33
+		earth->SetLayerThickness( (VectorXr(1) << 10).finished() );
34
+        // Set mag field info
35
+        // From NOAA, Laramie WY, June 9 2016, aligned with mag. north
36
+        earth->SetMagneticFieldIncDecMag( 67, 0, 52750, NANOTESLA );
37
+
38
+    // Transmitter loops
39
+    auto Tx1 = CircularLoop(21, 15, 100, 100);
40
+    auto Tx2 = CircularLoop(21, 15, 100, 100 + offset);
41
+
42
+    auto Kern = Coupling::NewSP();
43
+        Kern->PushCoil( "Coil 1", Tx1 );
44
+        Kern->PushCoil( "Coil 2", Tx2 );
45
+        Kern->SetLayeredEarthEM( earth );
46
+
47
+        Kern->SetIntegrationSize( (Vector3r() << 200,200,200).finished() );
48
+        Kern->SetIntegrationOrigin( (Vector3r() << 0,0,2).finished() );
49
+        Kern->SetTolerance( 1e-7 ); // 1e-12
50
+
51
+    std::vector<std::string> tx = {std::string("Coil 1")};
52
+    std::vector<std::string> rx = {std::string("Coil 2")};
53
+    VectorXr Offsets = VectorXr::LinSpaced(60,0.25,60); // nbins, low, high
54
+
55
+    auto outfile = std::ofstream("coupling.dat");
56
+    for (int ii=0; ii< Offsets.size(); ++ii) {
57
+        MoveLoop(Tx2, 21, 15, 100, 100 + Offsets(ii));
58
+        Complex coupling = Kern->Calculate( tx, rx, false );
59
+        std::cout << "coupling " << coupling << std::endl;
60
+        outfile << Offsets(ii) << "\t" <<  std::real(coupling) << "\t" << std::imag(coupling) << std::endl;
61
+    }
62
+    outfile.close();
63
+}
64
+
65
+std::shared_ptr<Lemma::PolygonalWireAntenna> CircularLoop ( int nd, Real Radius, Real Offsetx, Real Offsety ) {
66
+
67
+    auto Tx1 = Lemma::PolygonalWireAntenna::NewSP();
68
+         Tx1->SetNumberOfPoints(nd);
69
+
70
+    VectorXr range = VectorXr::LinSpaced(nd, 0, 2*PI);
71
+    int ii;
72
+    for (ii=0; ii<nd; ++ii) {
73
+        Tx1->SetPoint(ii, Vector3r(Offsetx+Radius*std::cos(range(ii)), Offsety+Radius*std::sin(range(ii)),  -1e-3));
74
+    }
75
+    //Tx1->SetPoint(ii, Vector3r(Offsetx+Radius*1, Offsety,  -1e-3));
76
+
77
+    Tx1->SetCurrent(1.);
78
+    Tx1->SetNumberOfTurns(1);
79
+    Tx1->SetNumberOfFrequencies(1);
80
+    Tx1->SetFrequency(0,2246);
81
+
82
+    return Tx1;
83
+}
84
+
85
+void MoveLoop( std::shared_ptr<Lemma::PolygonalWireAntenna> Tx1, int nd, Real Radius, Real Offsetx, Real Offsety ) {
86
+
87
+    Tx1->SetNumberOfPoints(nd);
88
+
89
+    VectorXr range = VectorXr::LinSpaced(nd, 0, 2*PI);
90
+    int ii;
91
+    for (ii=0; ii<nd; ++ii) {
92
+        Tx1->SetPoint(ii, Vector3r(Offsetx+Radius*std::cos(range(ii)), Offsety+Radius*std::sin(range(ii)),  -1e-3));
93
+    }
94
+    //Tx1->SetPoint(ii, Vector3r(Offsetx+Radius*1, Offsety,  -1e-3));
95
+
96
+    Tx1->SetCurrent(1.);
97
+    Tx1->SetNumberOfTurns(1);
98
+    Tx1->SetNumberOfFrequencies(1);
99
+    Tx1->SetFrequency(0,2246);
100
+
101
+}

+ 7
- 4
examples/KernelV0.cpp View File

@@ -47,10 +47,12 @@ int main(int argc, char** argv) {
47 47
 
48 48
         Kern->SetIntegrationSize( (Vector3r() << 200,200,200).finished() );
49 49
         Kern->SetIntegrationOrigin( (Vector3r() << 0,0,0).finished() );
50
-        Kern->SetTolerance( 1e-12 );
50
+        Kern->SetTolerance( 1e-12 ); // 1e-12
51 51
 
52 52
         Kern->SetPulseDuration(0.020);
53 53
         VectorXr I(36);
54
+
55
+        // off from VC by 1.075926340216996
54 56
         // Pulses from Wyoming Red Buttes exp 0
55 57
         I << 397.4208916184016, 352.364477036168, 313.0112765842783, 278.37896394065376, 247.81424224324982,
56 58
              220.77925043190442, 196.76493264105017, 175.31662279234038, 156.0044839325404, 138.73983004230124,
@@ -63,22 +65,22 @@ int main(int argc, char** argv) {
63 65
         Kern->SetPulseCurrent( I ); // nbins, low, high
64 66
 
65 67
         //Kern->SetDepthLayerInterfaces( VectorXr::LinSpaced( 30, 3, 45.5 ) ); // nlay, low, high
66
-        VectorXr interfaces = VectorXr::LinSpaced( 31, 1, 45.5 ); // nlay, low, high
68
+        VectorXr interfaces = VectorXr::LinSpaced( 41, .5, 45.5 ); // nlay, low, high
67 69
         Real thick = .5;
68 70
         for (int ilay=1; ilay<interfaces.size(); ++ilay) {
69 71
             interfaces(ilay) = interfaces(ilay-1) + thick;
70
-            thick *= 1.1;
72
+            thick *= 1.05;
71 73
         }
72 74
         Kern->SetDepthLayerInterfaces( interfaces ); // nlay, low, high
73 75
 
74 76
     // We could, I suppose, take the earth model in here? For non-linear that
75 77
     // may be more natural to work with?
76 78
     std::vector<std::string> tx = {std::string("Coil 1"), std::string("Coil 2") };
77
-    //std::vector<std::string> tx = {std::string("Coil 1")};
78 79
     std::vector<std::string> rx = {std::string("Coil 1")};
79 80
     Kern->CalculateK0( tx, rx, false );
80 81
 
81 82
     std::ofstream dout = std::ofstream(std::string("k-")+ std::string(argv[1])+ std::string(".dat"));
83
+    //std::ofstream dout = std::ofstream(std::string("k-coincident.dat"));
82 84
         dout << interfaces.transpose() << std::endl;
83 85
         dout << I.transpose() << std::endl;
84 86
         dout << "#real\n";
@@ -88,6 +90,7 @@ int main(int argc, char** argv) {
88 90
         dout.close();
89 91
 
90 92
     std::ofstream out = std::ofstream(std::string("k-")+std::string(argv[1])+std::string(".yaml"));
93
+    //std::ofstream out = std::ofstream(std::string("k-coincident.yaml"));
91 94
     out << *Kern;
92 95
     out.close();
93 96
 }

+ 1
- 1
examples/plotkernel.py View File

@@ -22,7 +22,7 @@ ax1 =  fig.add_axes( [.100,.125,.335,.775] )
22 22
 ax2 =  fig.add_axes( [.465,.125,.335,.775] , sharex=ax1, sharey=ax1 )
23 23
 axcb = fig.add_axes( [.835,.125,.040,.775] )
24 24
 
25
-ccmap = "seismic" # RdBu
25
+ccmap = "coolwarm" # RdBu
26 26
 
27 27
 # Real plot
28 28
 ax1.pcolormesh(X, Y, K[0:nx//2].T, cmap=ccmap, vmin=-np.max(np.abs(K)), vmax=np.max(np.abs(K)))

+ 258
- 0
include/Coupling.h View File

@@ -0,0 +1,258 @@
1
+/* This file is part of Lemma, a geophysical modelling and inversion API.
2
+ * More information is available at http://lemmasoftware.org
3
+ */
4
+
5
+/* This Source Code Form is subject to the terms of the Mozilla Public
6
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
7
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
+ */
9
+
10
+/**
11
+ * @file
12
+ * @date      11/11/2016 01:47:34 PM
13
+ * @author    Trevor Irons (ti)
14
+ * @email     tirons@egi.utah.edu
15
+ * @copyright Copyright (c) 2016, University of Utah
16
+ * @copyright Copyright (c) 2016, Lemma Software, LLC
17
+ * @copyright Copyright (c) 2008, Colorado School of Mines
18
+ */
19
+#ifndef  COUPLING_INC
20
+#define  COUPLING_INC
21
+
22
+#pragma once
23
+#include "LemmaObject.h"
24
+#include "LayeredEarthEM.h"
25
+#include "PolygonalWireAntenna.h"
26
+#include "EMEarth1D.h"
27
+
28
+#ifdef LEMMAUSEVTK
29
+#include "vtkHyperOctree.h"
30
+#include "vtkHyperOctreeCursor.h"
31
+#include "vtkXMLHyperOctreeWriter.h"
32
+#include "vtkDoubleArray.h"
33
+#endif
34
+
35
+namespace Lemma {
36
+
37
+    /**
38
+     * \ingroup Merlin
39
+     * \brief
40
+     * \details
41
+     */
42
+    class Coupling : public LemmaObject {
43
+
44
+        friend std::ostream &operator<<(std::ostream &stream, const Coupling &ob);
45
+
46
+        protected:
47
+        /*
48
+         *  This key is used to lock the constructor. It is protected so that inhereted
49
+         *  classes also have the key to contruct their base class.
50
+         */
51
+        struct ctor_key {};
52
+
53
+        public:
54
+
55
+        // ====================  LIFECYCLE     =======================
56
+
57
+        /**
58
+         * Default constructor.
59
+         * @note This method is locked, and cannot be called directly.
60
+         *       The reason that the method is public is to enable the use
61
+         *       of make_shared whilst enforcing the use of shared_ptr,
62
+         *       in c++-17, this curiosity may be resolved.
63
+         * @see Coupling::NewSP
64
+         */
65
+        explicit Coupling ( const ctor_key& );
66
+
67
+        /**
68
+         * DeSerializing constructor.
69
+         * @note This method is locked, and cannot be called directly.
70
+         *       The reason that the method is public is to enable the use
71
+         *       of make_shared whilst enforcing the use of shared_ptr,
72
+         *       in c++-17, this curiosity may be resolved.
73
+         * @see Coupling::DeSerialize
74
+         */
75
+        Coupling ( const YAML::Node& node, const ctor_key& );
76
+
77
+        /**
78
+         * Default destructor.
79
+         * @note This method should never be called due to the mandated
80
+         *       use of smart pointers. It is necessary to keep the method
81
+         *       public in order to allow for the use of the more efficient
82
+         *       make_shared constructor.
83
+         */
84
+        virtual ~Coupling ();
85
+
86
+        /**
87
+         *  Uses YAML to serialize this object.
88
+         *  @return a YAML::Node
89
+         *  @see Coupling::DeSerialize
90
+         */
91
+        virtual YAML::Node Serialize() const;
92
+
93
+        /*
94
+         *  Factory method for generating concrete class.
95
+         *  @return a std::shared_ptr of type Coupling
96
+         */
97
+        static std::shared_ptr< Coupling > NewSP();
98
+
99
+        /**
100
+         *   Constructs an Coupling object from a YAML::Node.
101
+         *   @see Coupling::Serialize
102
+         */
103
+        static std::shared_ptr<Coupling> DeSerialize(const YAML::Node& node);
104
+
105
+        // ====================  OPERATORS     =======================
106
+
107
+        // ====================  OPERATIONS    =======================
108
+
109
+        /**
110
+         * @return std::shared_ptr<LayeredEarthEM>
111
+         */
112
+        inline std::shared_ptr<LayeredEarthEM> GetSigmaModel (  ) {
113
+            return SigmaModel;
114
+        }		// -----  end of method Coupling::get_SigmaModel  -----
115
+
116
+        /**
117
+         * @param[in] value the 1D-EM model used for calculations
118
+         */
119
+        inline void SetLayeredEarthEM ( std::shared_ptr< LayeredEarthEM > value ) {
120
+            SigmaModel	= value;
121
+            return ;
122
+        }		// -----  end of method Coupling::set_SigmaModel  -----
123
+
124
+        /**
125
+         *
126
+         */
127
+        inline void SetIntegrationSize ( const Vector3r& size ) {
128
+            Size = size;
129
+            return ;
130
+        }		// -----  end of method Coupling::SetIntegrationSize  -----
131
+
132
+        /**
133
+         *
134
+         */
135
+        inline void SetIntegrationOrigin ( const Vector3r& origin ) {
136
+            Origin = origin;
137
+            return ;
138
+        }		// -----  end of method Coupling::SetIntegrationOrigin  -----
139
+
140
+        /**
141
+         *   Assign transmiter coils
142
+         */
143
+        inline void PushCoil( const std::string& label, std::shared_ptr<PolygonalWireAntenna> ant ) {
144
+            TxRx[label] = ant;
145
+        }
146
+
147
+        /**
148
+         *   Calculates a single imaging kernel, however, phased arrays are supported
149
+         *   so that more than one transmitter and/or receiver can be specified.
150
+         *   @param[in] tx is the list of transmitters to use for a kernel, use the same labels as
151
+         *              used in PushCoil.
152
+         *   @param[in] rx is the list of receivers to use for a kernel, use the same labels as
153
+         *              used in PushCoil. @see PushCoil
154
+         *   @param[in] vtkOutput generates a VTK hyperoctree file as well, useful for visualization.
155
+         *              requires compilation of Lemma with VTK.
156
+         */
157
+        Complex Calculate (const std::vector< std::string >& tx, const std::vector< std::string >& rx,
158
+                bool vtkOutput=false );
159
+
160
+        /**
161
+         *  Sets the tolerance to use for making the adaptive mesh
162
+         *
163
+         */
164
+        inline void SetTolerance(const Real& ttol) {
165
+            tol = ttol;
166
+        }
167
+
168
+        inline void SetPulseDuration(const Real& taup) {
169
+            Taup = taup;
170
+        }
171
+
172
+        // ====================  INQUIRY       =======================
173
+        /**
174
+         *  Returns the name of the underlying class, similiar to Python's type
175
+         *  @return string of class name
176
+         */
177
+        virtual inline std::string GetName() const {
178
+            return CName;
179
+        }
180
+
181
+        protected:
182
+
183
+        // ====================  LIFECYCLE     =======================
184
+
185
+        /** Copy is disabled */
186
+        Coupling( const Coupling& ) = delete;
187
+
188
+        private:
189
+
190
+        /**
191
+         *  Returns the kernel value for an input prism
192
+         */
193
+        Complex f( const Vector3r& r, const Real& volume , const Vector3cr& Ht, const Vector3cr& Hr);
194
+
195
+        void IntegrateOnOctreeGrid( bool vtkOutput=false );
196
+
197
+        /**
198
+         *  Recursive call to integrate a function on an adaptive Octree Grid.
199
+         *  For efficiency's sake the octree grid is not stored, as only the
200
+         *  integral (sum) is of interest. The logic for grid refinement is based
201
+         *  on an Octree representation of the domain. If an Octree representation
202
+         *  of the kernel is desired, call alternative version @see EvaluateKids2
203
+         *  @param[in] size gives the domain size, in  metres
204
+         *  @param[in] level gives the current level of the octree grid, call with 0 initially
205
+         *  @param[in] cpos is the centre position of the parent cuboid
206
+         */
207
+        void EvaluateKids(  const Vector3r& size, const int& level, const Vector3r& cpos,
208
+                            const Complex& parentVal );
209
+
210
+        #ifdef LEMMAUSEVTK
211
+        /**
212
+         *  Same functionality as @see EvaluateKids, but includes generation of a VTK
213
+         *  HyperOctree, which is useful for visualization.
214
+         */
215
+        void EvaluateKids2(  const Vector3r& size, const int& level, const Vector3r& cpos,
216
+                            const VectorXcr& parentVal, vtkHyperOctree* octree, vtkHyperOctreeCursor* curse );
217
+
218
+        void GetPosition( vtkHyperOctreeCursor* Cursor, Real* p );
219
+        #endif
220
+
221
+        // ====================  DATA MEMBERS  =========================
222
+
223
+        int                                       ilay;
224
+        int                                       nleaves;
225
+        int                                       minLevel=4;
226
+        int                                       maxLevel=8;
227
+
228
+        Real                                      VOLSUM;
229
+        Real                                      tol=1e-11;
230
+        Real                                      Taup = .020;  // Sec
231
+
232
+        Complex                                   SUM;
233
+
234
+        Vector3r                                  Size;
235
+        Vector3r                                  Origin;
236
+
237
+        std::shared_ptr< LayeredEarthEM >         SigmaModel = nullptr;
238
+        std::shared_ptr< FieldPoints >            cpoints;
239
+
240
+        std::map< std::string , std::shared_ptr< PolygonalWireAntenna > >  TxRx;
241
+        std::map< std::string , std::shared_ptr< EMEarth1D > >             EMEarths;
242
+
243
+        #ifdef LEMMAUSEVTK
244
+        std::map< int, VectorXcr  >               LeafDict;
245
+        std::map< int, int     >                  LeafDictIdx;
246
+        std::map< int, Real     >                 LeafDictErr;
247
+        #endif
248
+
249
+        /** ASCII string representation of the class name */
250
+        static constexpr auto CName = "Coupling";
251
+
252
+    }; // -----  end of class  Coupling  -----
253
+}  // -----  end of namespace Lemma ----
254
+
255
+/* vim: set tabstop=4 expandtab */
256
+/* vim: set filetype=cpp */
257
+
258
+#endif   // ----- #ifndef COUPLING_INC  -----

+ 1
- 0
include/Merlin View File

@@ -1,4 +1,5 @@
1 1
 #include "KernelV0.h"
2
+#include "Coupling.h"
2 3
 
3 4
 /* vim: set tabstop=4 expandtab: */
4 5
 /* vim: set filetype=cpp: */

+ 1
- 0
src/CMakeLists.txt View File

@@ -1,4 +1,5 @@
1 1
 set (MERLINSOURCE
2 2
 	${CMAKE_CURRENT_SOURCE_DIR}/KernelV0.cpp
3
+	${CMAKE_CURRENT_SOURCE_DIR}/Coupling.cpp
3 4
 	PARENT_SCOPE
4 5
 )

+ 444
- 0
src/Coupling.cpp View File

@@ -0,0 +1,444 @@
1
+/* This file is part of Lemma, a geophysical modelling and inversion API.
2
+ * More information is available at http://lemmasoftware.org
3
+ */
4
+
5
+/* This Source Code Form is subject to the terms of the Mozilla Public
6
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
7
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
+ */
9
+
10
+/**
11
+ * @file
12
+ * @date      11/11/2016 01:47:25 PM
13
+ * @author    Trevor Irons (ti)
14
+ * @email     tirons@egi.utah.edu
15
+ * @copyright Copyright (c) 2016, University of Utah
16
+ * @copyright Copyright (c) 2016, Lemma Software, LLC
17
+ * @copyright Copyright (c) 2008, Colorado School of Mines
18
+ */
19
+
20
+
21
+#include "Coupling.h"
22
+#include "FieldPoints.h"
23
+
24
+namespace Lemma {
25
+
26
+    // ====================  FRIEND METHODS  =====================
27
+
28
+    std::ostream &operator << (std::ostream &stream, const Coupling &ob) {
29
+        stream << ob.Serialize()  << "\n---\n"; // End of doc ---
30
+        return stream;
31
+    }
32
+
33
+    // ====================  LIFECYCLE     =======================
34
+
35
+    //--------------------------------------------------------------------------------------
36
+    //       Class:  Coupling
37
+    //      Method:  Coupling
38
+    // Description:  constructor (locked)
39
+    //--------------------------------------------------------------------------------------
40
+    Coupling::Coupling (const ctor_key&) : LemmaObject( ) {
41
+
42
+    }  // -----  end of method Coupling::Coupling  (constructor)  -----
43
+
44
+    //--------------------------------------------------------------------------------------
45
+    //       Class:  Coupling
46
+    //      Method:  Coupling
47
+    // Description:  DeSerializing constructor (locked)
48
+    //--------------------------------------------------------------------------------------
49
+    Coupling::Coupling (const YAML::Node& node, const ctor_key&) : LemmaObject(node) {
50
+
51
+    }  // -----  end of method Coupling::Coupling  (constructor)  -----
52
+
53
+    //--------------------------------------------------------------------------------------
54
+    //       Class:  Coupling
55
+    //      Method:  NewSP()
56
+    // Description:  public constructor returing a shared_ptr
57
+    //--------------------------------------------------------------------------------------
58
+    std::shared_ptr< Coupling >  Coupling::NewSP() {
59
+        return std::make_shared< Coupling >( ctor_key() );
60
+    }
61
+
62
+    //--------------------------------------------------------------------------------------
63
+    //       Class:  Coupling
64
+    //      Method:  ~Coupling
65
+    // Description:  destructor (protected)
66
+    //--------------------------------------------------------------------------------------
67
+    Coupling::~Coupling () {
68
+
69
+    }  // -----  end of method Coupling::~Coupling  (destructor)  -----
70
+
71
+    //--------------------------------------------------------------------------------------
72
+    //       Class:  Coupling
73
+    //      Method:  Serialize
74
+    //--------------------------------------------------------------------------------------
75
+    YAML::Node  Coupling::Serialize (  ) const {
76
+        YAML::Node node = LemmaObject::Serialize();
77
+        node.SetTag( GetName() );
78
+
79
+        // Coils Transmitters & Receivers
80
+        for ( auto txm : TxRx) {
81
+            node[txm.first] = txm.second->Serialize();
82
+        }
83
+        // LayeredEarthEM
84
+        node["SigmaModel"] = SigmaModel->Serialize();
85
+
86
+        node["tol"] = tol;
87
+        node["minLevel"] = minLevel;
88
+        node["maxLevel"] = maxLevel;
89
+
90
+        return node;
91
+    }		// -----  end of method Coupling::Serialize  -----
92
+
93
+    //--------------------------------------------------------------------------------------
94
+    //       Class:  Coupling
95
+    //      Method:  DeSerialize
96
+    //--------------------------------------------------------------------------------------
97
+    std::shared_ptr<Coupling> Coupling::DeSerialize ( const YAML::Node& node  ) {
98
+        if (node.Tag() !=  "Coupling" ) {
99
+            throw  DeSerializeTypeMismatch( "Coupling", node.Tag());
100
+        }
101
+        return std::make_shared< Coupling > ( node, ctor_key() );
102
+    }		// -----  end of method Coupling::DeSerialize  -----
103
+
104
+    //--------------------------------------------------------------------------------------
105
+    //       Class:  Coupling
106
+    //      Method:  DeSerialize
107
+    //--------------------------------------------------------------------------------------
108
+    Complex Coupling::Calculate (const std::vector< std::string>& Tx, const std::vector<std::string >& Rx,
109
+            bool vtkOutput ) {
110
+        // All EM calculations will share same field points
111
+        cpoints = FieldPoints::NewSP();
112
+            cpoints->SetNumberOfPoints(8);
113
+        for (auto tx : Tx) {
114
+            // Set up EMEarth
115
+            EMEarths[tx] = EMEarth1D::NewSP();
116
+                EMEarths[tx]->AttachWireAntenna(TxRx[tx]);
117
+                EMEarths[tx]->AttachLayeredEarthEM(SigmaModel);
118
+                EMEarths[tx]->AttachFieldPoints( cpoints );
119
+         		EMEarths[tx]->SetFieldsToCalculate(H);
120
+                // TODO query for method, altough with flat antennae, this is fastest
121
+                EMEarths[tx]->SetHankelTransformMethod(ANDERSON801);
122
+                EMEarths[tx]->SetTxRxMode(TX);
123
+                TxRx[tx]->SetCurrent(1.);
124
+        }
125
+        for (auto rx : Rx) {
126
+            if (EMEarths.count(rx)) {
127
+                EMEarths[rx]->SetTxRxMode(TXRX);
128
+            } else {
129
+                EMEarths[rx] = EMEarth1D::NewSP();
130
+                    EMEarths[rx]->AttachWireAntenna(TxRx[rx]);
131
+                    EMEarths[rx]->AttachLayeredEarthEM(SigmaModel);
132
+                    EMEarths[rx]->AttachFieldPoints( cpoints );
133
+         		    EMEarths[rx]->SetFieldsToCalculate(H);
134
+                    // TODO query for method, altough with flat antennae, this is fastest
135
+                    EMEarths[rx]->SetHankelTransformMethod(ANDERSON801);
136
+                    EMEarths[rx]->SetTxRxMode(RX);
137
+                    TxRx[rx]->SetCurrent(1.);
138
+            }
139
+        }
140
+        SUM = 0;
141
+        IntegrateOnOctreeGrid( vtkOutput );
142
+        std::cout << "\nFinished KERNEL\n";
143
+        return SUM;
144
+    }
145
+
146
+    //--------------------------------------------------------------------------------------
147
+    //       Class:  Coupling
148
+    //      Method:  IntegrateOnOctreeGrid
149
+    //--------------------------------------------------------------------------------------
150
+    void Coupling::IntegrateOnOctreeGrid( bool vtkOutput) {
151
+
152
+        Vector3r cpos = Origin + Size/2.;
153
+
154
+        VOLSUM = 0;
155
+        nleaves = 0;
156
+        if (!vtkOutput) {
157
+            EvaluateKids( Size, 0, cpos, Complex(100.));
158
+        } else {
159
+        #ifdef LEMMAUSEVTK
160
+            vtkHyperOctree* oct = vtkHyperOctree::New();
161
+                oct->SetDimension(3);
162
+                oct->SetOrigin( Origin(0), Origin(1), Origin(2) );
163
+                oct->SetSize( Size(0), Size(1), Size(2) );
164
+            vtkHyperOctreeCursor* curse = oct->NewCellCursor();
165
+                curse->ToRoot();
166
+            EvaluateKids2( Size, 0, cpos, VectorXcr::Ones(PulseI.size()), oct, curse );
167
+
168
+            for (int iq=0; iq<PulseI.size(); ++iq) {
169
+
170
+            // Fill in leaf data
171
+            vtkDoubleArray* kr = vtkDoubleArray::New();
172
+                kr->SetNumberOfComponents(1);
173
+                kr->SetName("Re($K_0$)");
174
+                kr->SetNumberOfTuples( oct->GetNumberOfLeaves() );
175
+            vtkDoubleArray* ki = vtkDoubleArray::New();
176
+                ki->SetNumberOfComponents(1);
177
+                ki->SetName("Im($K_0$)");
178
+                ki->SetNumberOfTuples( oct->GetNumberOfLeaves() );
179
+            vtkDoubleArray* km = vtkDoubleArray::New();
180
+                km->SetNumberOfComponents(1);
181
+                km->SetName("mod($K_0$)");
182
+                km->SetNumberOfTuples( oct->GetNumberOfLeaves() );
183
+            vtkIntArray* kid = vtkIntArray::New();
184
+                kid->SetNumberOfComponents(1);
185
+                kid->SetName("ID");
186
+                kid->SetNumberOfTuples( oct->GetNumberOfLeaves() );
187
+            vtkIntArray* kerr = vtkIntArray::New();
188
+                kerr->SetNumberOfComponents(1);
189
+                kerr->SetName("nleaf");
190
+
191
+            //Real LeafVol(0);
192
+            for (auto leaf : LeafDict) {
193
+                kr->InsertTuple1( leaf.first, std::real(leaf.second(iq)) );
194
+                ki->InsertTuple1( leaf.first, std::imag(leaf.second(iq)) );
195
+                km->InsertTuple1( leaf.first, std::abs(leaf.second(iq)) );
196
+                kid->InsertTuple1( leaf.first, leaf.first );
197
+                //LeafVol += std::real(leaf.second);
198
+            }
199
+            //std::cout << "\n\nLeafVol=" << LeafVol << std::endl;
200
+
201
+            for (auto leaf : LeafDictIdx) {
202
+                kerr->InsertTuple1( leaf.first, leaf.second );
203
+            }
204
+
205
+            auto kri = oct->GetLeafData()->AddArray(kr);
206
+            auto kii = oct->GetLeafData()->AddArray(ki);
207
+            auto kmi = oct->GetLeafData()->AddArray(km);
208
+            auto kidi = oct->GetLeafData()->AddArray(kid);
209
+            auto keri = oct->GetLeafData()->AddArray(kerr);
210
+
211
+            auto write = vtkXMLHyperOctreeWriter::New();
212
+                //write.SetDataModeToAscii()
213
+                write->SetInputData(oct);
214
+                std::string fname = std::string("octree-") + to_string(ilay)
215
+                                  + std::string("-") + to_string(iq) + std::string(".vto");
216
+                write->SetFileName(fname.c_str());
217
+                write->Write();
218
+                write->Delete();
219
+
220
+            oct->GetLeafData()->RemoveArray( kri );
221
+            oct->GetLeafData()->RemoveArray( kii );
222
+            oct->GetLeafData()->RemoveArray( kmi );
223
+            oct->GetLeafData()->RemoveArray( kidi );
224
+            oct->GetLeafData()->RemoveArray( keri );
225
+
226
+            kerr->Delete();
227
+            kid->Delete();
228
+            kr->Delete();
229
+            ki->Delete();
230
+            km->Delete();
231
+
232
+            }
233
+
234
+            curse->Delete();
235
+            oct->Delete();
236
+        #else
237
+            throw std::runtime_error("IntegrateOnOctreeGrid with vtkOutput requires Lemma with VTK support");
238
+        #endif
239
+
240
+        }
241
+        std::cout << "\nVOLSUM=" << VOLSUM << "\tActual=" <<  Size(0)*Size(1)*Size(2)
242
+                  << "\tDifference=" << VOLSUM - (Size(0)*Size(1)*Size(2)) <<  std::endl;
243
+    }
244
+
245
+    //--------------------------------------------------------------------------------------
246
+    //       Class:  Coupling
247
+    //      Method:  f
248
+    //--------------------------------------------------------------------------------------
249
+    Complex Coupling::f( const Vector3r& r, const Real& volume, const Vector3cr& Ht, const Vector3cr& Hr ) {
250
+        return volume*Ht.dot(Hr);
251
+    }
252
+
253
+    //--------------------------------------------------------------------------------------
254
+    //       Class:  Coupling
255
+    //      Method:  EvaluateKids
256
+    //--------------------------------------------------------------------------------------
257
+    void Coupling::EvaluateKids( const Vector3r& size, const int& level, const Vector3r& cpos,
258
+        const Complex& parentVal ) {
259
+
260
+        std::cout << "\r" << (int)(1e2*VOLSUM/(Size[0]*Size[1]*Size[2])) << "\t" << nleaves;
261
+        //std::cout.flush();
262
+
263
+        // Next level step, interested in one level below
264
+        // bitshift requires one extra, faster than, and equivalent to std::pow(2, level+1)
265
+        Vector3r step  = size.array() / (Real)(1 << (level+1) );
266
+        Real vol = (step(0)*step(1)*step(2));     // volume of each child
267
+
268
+        Vector3r pos =  cpos - step/2.;
269
+        Eigen::Matrix<Real, 8, 3> posadd = (Eigen::Matrix<Real, 8, 3>() <<
270
+                        0,       0,       0,
271
+                  step[0],       0,       0,
272
+                        0, step[1],       0,
273
+                  step[0], step[1],       0,
274
+                        0,       0, step[2],
275
+                  step[0],       0, step[2],
276
+                        0, step[1], step[2],
277
+                  step[0], step[1], step[2] ).finished();
278
+
279
+        VectorXcr kvals(8);       // individual kernel vals
280
+        cpoints->ClearFields();
281
+        for (int ichild=0; ichild<8; ++ichild) {
282
+            Vector3r cp = pos;    // Eigen complains about combining these
283
+            cp += posadd.row(ichild);
284
+            cpoints->SetLocation( ichild, cp );
285
+        }
286
+
287
+        Eigen::Matrix<Complex, 3, 8> Ht = Eigen::Matrix<Complex, 3, 8>::Zero();
288
+        Eigen::Matrix<Complex, 3, 8> Hr = Eigen::Matrix<Complex, 3, 8>::Zero();
289
+        for ( auto EMCalc : EMEarths ) {
290
+            EMCalc.second->GetFieldPoints()->ClearFields();
291
+            EMCalc.second->CalculateWireAntennaFields();
292
+            switch (EMCalc.second->GetTxRxMode()) {
293
+                case TX:
294
+                    Ht += EMCalc.second->GetFieldPoints()->GetHfield(0);
295
+                    break;
296
+                case RX:
297
+                    Hr += EMCalc.second->GetFieldPoints()->GetHfield(0);
298
+                    break;
299
+                case TXRX:
300
+                    Ht += EMCalc.second->GetFieldPoints()->GetHfield(0);
301
+                    Hr += EMCalc.second->GetFieldPoints()->GetHfield(0);
302
+                    break;
303
+                default:
304
+                    break;
305
+            }
306
+        }
307
+
308
+        for (int ichild=0; ichild<8; ++ichild) {
309
+            Vector3r cp = pos;    // Eigen complains about combining these
310
+            cp += posadd.row(ichild);
311
+            kvals(ichild) = f(cp, vol, Ht.col(ichild), Hr.col(ichild));
312
+        }
313
+
314
+        Complex ksum = kvals.sum();     // Kernel sum
315
+        // Evaluate whether or not furthur splitting is needed
316
+        if ( std::abs(ksum-parentVal) > tol || level < minLevel && level < maxLevel ) {
317
+            // Not a leaf dive further in
318
+            for (int ichild=0; ichild<8; ++ichild) {
319
+                Vector3r cp = pos; // Eigen complains about combining these
320
+                cp += posadd.row(ichild);
321
+                EvaluateKids( size, level+1, cp, kvals(ichild) );
322
+            }
323
+            return; // not leaf
324
+        }
325
+        // implicit else, is a leaf
326
+        SUM += ksum;
327
+        VOLSUM  += 8.*vol;
328
+        nleaves += 1; // could say += 8 just as fairly
329
+        return;     // is leaf
330
+    }
331
+
332
+    #ifdef LEMMAUSEVTK
333
+    //--------------------------------------------------------------------------------------
334
+    //       Class:  Coupling
335
+    //      Method:  EvaluateKids2 -- same as Evaluate Kids, but include VTK octree generation
336
+    //--------------------------------------------------------------------------------------
337
+    void Coupling::EvaluateKids2( const Vector3r& size, const int& level, const Vector3r& cpos,
338
+        const Complex& parentVal, vtkHyperOctree* oct, vtkHyperOctreeCursor* curse) {
339
+
340
+        std::cout << "\r" << (int)(1e2*VOLSUM/(Size[0]*Size[1]*Size[2])) << "\t" << nleaves;
341
+        std::cout.flush();
342
+
343
+        // Next level step, interested in one level below
344
+        // bitshift requires one extra, faster than, and equivalent to std::pow(2, level+1)
345
+        Vector3r step  = size.array() / (Real)(1 << (level+1) );
346
+        Real vol = (step(0)*step(1)*step(2));         // volume of each child
347
+
348
+        Vector3r pos =  cpos - step/2.;
349
+        Eigen::Matrix<Real, 8, 3> posadd = (Eigen::Matrix<Real, 8, 3>() <<
350
+                        0,       0,       0,
351
+                  step[0],       0,       0,
352
+                        0, step[1],       0,
353
+                  step[0], step[1],       0,
354
+                        0,       0, step[2],
355
+                  step[0],       0, step[2],
356
+                        0, step[1], step[2],
357
+                  step[0], step[1], step[2] ).finished();
358
+
359
+        VectorXcr kvals(8);       // individual kernel vals
360
+        cpoints->ClearFields();
361
+        for (int ichild=0; ichild<8; ++ichild) {
362
+            Vector3r cp = pos;    // Eigen complains about combining these
363
+            cp += posadd.row(ichild);
364
+            cpoints->SetLocation( ichild, cp );
365
+        }
366
+
367
+        Eigen::Matrix<Complex, 3, 8> Ht = Eigen::Matrix<Complex, 3, 8>::Zero();
368
+        Eigen::Matrix<Complex, 3, 8> Hr = Eigen::Matrix<Complex, 3, 8>::Zero();
369
+        for ( auto EMCalc : EMEarths ) {
370
+            //EMCalc->GetFieldPoints()->ClearFields();
371
+            EMCalc.second->CalculateWireAntennaFields();
372
+            switch (EMCalc.second->GetTxRxMode()) {
373
+                case TX:
374
+                    Ht += EMCalc.second->GetFieldPoints()->GetHfield(0);
375
+                    break;
376
+                case RX:
377
+                    Hr += EMCalc.second->GetFieldPoints()->GetHfield(0);
378
+                    break;
379
+                case TXRX:
380
+                    Ht += EMCalc.second->GetFieldPoints()->GetHfield(0);
381
+                    Hr += EMCalc.second->GetFieldPoints()->GetHfield(0);
382
+                    break;
383
+                default:
384
+                    break;
385
+            }
386
+        }
387
+
388
+        for (int ichild=0; ichild<8; ++ichild) {
389
+            Vector3r cp = pos;    // Eigen complains about combining these
390
+            cp += posadd.row(ichild);
391
+            kvals(ichild) = f(cp, vol, Ht.col(ichild), Hr.col(ichild));
392
+        }
393
+
394
+        Complex ksum = kvals.sum();     // Kernel sum
395
+        // Evaluate whether or not furthur splitting is needed
396
+        if ( std::abs(ksum-parentVal) > tol || level < minLevel && level < maxLevel ) {
397
+            oct->SubdivideLeaf(curse);
398
+            for (int ichild=0; ichild<8; ++ichild) {
399
+                curse->ToChild(ichild);
400
+                Vector3r cp = pos; // Eigen complains about combining these
401
+                cp += posadd.row(ichild);
402
+                /* Test for position via alternative means */
403
+                /*
404
+                Real p[3];
405
+                GetPosition(curse, p);
406
+                if ( (Vector3r(p) - cp).norm() > 1e-8 ) {
407
+                    std::cout << "ERROR @ nleaves" << nleaves << "\n" << cp[0] << "\t" << p[0] << "\t" << cp[1] << "\t" << p[1]
408
+                              << "\t" << cp[2] << "\t" << p[2] << "\t" << vol<< std::endl;
409
+                    throw std::runtime_error("doom");
410
+                }
411
+                */
412
+                /* End of position test */
413
+                EvaluateKids2( size, level+1, cp, kvals.row(ichild), oct, curse );
414
+                curse->ToParent();
415
+            }
416
+            return;  // not a leaf
417
+        }
418
+        LeafDict[curse->GetLeafId()] = ksum/(8.*vol);
419
+        LeafDictIdx[curse->GetLeafId()] = nleaves;
420
+        Kern.row(ilay) += ksum;
421
+        VOLSUM += 8*vol;
422
+        nleaves += 1;
423
+        return;     // is a leaf
424
+    }
425
+
426
+    //--------------------------------------------------------------------------------------
427
+    //       Class:  Coupling
428
+    //      Method:  GetPosition
429
+    //--------------------------------------------------------------------------------------
430
+    void Coupling::GetPosition( vtkHyperOctreeCursor* Cursor, Real* p ) {
431
+        Real ratio=1.0/(1<<(Cursor->GetCurrentLevel()));
432
+        //step  = ((Size).array() / std::pow(2.,Cursor->GetCurrentLevel()));
433
+        p[0]=(Cursor->GetIndex(0)+.5)*ratio*this->Size[0]+this->Origin[0] ;//+ .5*step[0];
434
+        p[1]=(Cursor->GetIndex(1)+.5)*ratio*this->Size[1]+this->Origin[1] ;//+ .5*step[1];
435
+        p[2]=(Cursor->GetIndex(2)+.5)*ratio*this->Size[2]+this->Origin[2] ;//+ .5*step[2];
436
+    }
437
+
438
+    #endif
439
+
440
+} // ----  end of namespace Lemma  ----
441
+
442
+/* vim: set tabstop=4 expandtab */
443
+/* vim: set filetype=cpp */
444
+

+ 2
- 3
src/KernelV0.cpp View File

@@ -345,7 +345,7 @@ namespace Lemma {
345 345
         const VectorXcr& parentVal ) {
346 346
 
347 347
         std::cout << "\r" << (int)(1e2*VOLSUM/(Size[0]*Size[1]*Size[2])) << "\t" << nleaves;
348
-        std::cout.flush();
348
+        //std::cout.flush();
349 349
 
350 350
         // Next level step, interested in one level below
351 351
         // bitshift requires one extra, faster than, and equivalent to std::pow(2, level+1)
@@ -373,9 +373,8 @@ namespace Lemma {
373 373
 
374 374
         Eigen::Matrix<Complex, 3, 8> Ht = Eigen::Matrix<Complex, 3, 8>::Zero();
375 375
         Eigen::Matrix<Complex, 3, 8> Hr = Eigen::Matrix<Complex, 3, 8>::Zero();
376
-        //Eigen::Matrix< Complex, 8, 3 > Bt;
377 376
         for ( auto EMCalc : EMEarths ) {
378
-            //EMCalc->GetFieldPoints()->ClearFields();
377
+            EMCalc.second->GetFieldPoints()->ClearFields();
379 378
             EMCalc.second->CalculateWireAntennaFields();
380 379
             switch (EMCalc.second->GetTxRxMode()) {
381 380
                 case TX:

Loading…
Cancel
Save