Browse Source

More progress, octree grids are working, as are EM calculations on them. Need to add logic for kernel caluclation for a prism, and then depth layers.

master
T-bone 7 years ago
parent
commit
097ea8977d
5 changed files with 187 additions and 42 deletions
  1. 6
    0
      CMakeLists.txt
  2. 6
    0
      examples/CMakeLists.txt
  3. 3
    3
      examples/KernelV0.cpp
  4. 36
    8
      include/KernelV0.h
  5. 136
    31
      src/KernelV0.cpp

+ 6
- 0
CMakeLists.txt View File

11
 # Linking
11
 # Linking
12
 target_link_libraries(merlin "lemmacore" "fdem1d" )
12
 target_link_libraries(merlin "lemmacore" "fdem1d" )
13
 
13
 
14
+# Linking
15
+if ( LEMMA_VTK6_SUPPORT OR LEMMA_VTK7_SUPPORT ) 
16
+	target_link_libraries(merlin ${VTK_LIBRARIES})
17
+#	target_link_libraries(lemmacore "matplot")
18
+endif()
19
+
14
 # Testing
20
 # Testing
15
 if (LEMMA_ENABLE_TESTING)
21
 if (LEMMA_ENABLE_TESTING)
16
 	add_subdirectory(testing)
22
 	add_subdirectory(testing)

+ 6
- 0
examples/CMakeLists.txt View File

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

+ 3
- 3
examples/KernelV0.cpp View File

30
 		earth->SetLayerThickness( (VectorXr(1) << 10).finished() );
30
 		earth->SetLayerThickness( (VectorXr(1) << 10).finished() );
31
 
31
 
32
     // Transmitter loops
32
     // Transmitter loops
33
-    auto Tx1 = CircularLoop(60, 15, 0, 0);
34
-    auto Tx2 = CircularLoop(60, 15, 15, 0);
33
+    auto Tx1 = CircularLoop(60, 15, 50, 50);
34
+    auto Tx2 = CircularLoop(60, 15, 55, 50);
35
     //auto Tx1 = CircularLoop(60, 15, 0, 0); // was 60
35
     //auto Tx1 = CircularLoop(60, 15, 0, 0); // was 60
36
 
36
 
37
     auto Kern = KernelV0::NewSP();
37
     auto Kern = KernelV0::NewSP();
44
     // may be more natural to work with?
44
     // may be more natural to work with?
45
     std::vector<std::string> tx = {std::string("Coil 1")};
45
     std::vector<std::string> tx = {std::string("Coil 1")};
46
     std::vector<std::string> rx = {std::string("Coil 1")};
46
     std::vector<std::string> rx = {std::string("Coil 1")};
47
-    Kern->CalculateK0( tx, rx );
47
+    Kern->CalculateK0( tx, rx , false ); //, false );
48
     //Kern->CalculateK0( "Coil 1", "Coil 1" );
48
     //Kern->CalculateK0( "Coil 1", "Coil 1" );
49
 
49
 
50
 }
50
 }

+ 36
- 8
include/KernelV0.h View File

23
 #include "LemmaObject.h"
23
 #include "LemmaObject.h"
24
 #include "LayeredEarthEM.h"
24
 #include "LayeredEarthEM.h"
25
 #include "PolygonalWireAntenna.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
+#endif
26
 
33
 
27
 namespace Lemma {
34
 namespace Lemma {
28
 
35
 
123
         /**
130
         /**
124
          *   Calculates a single imaging kernel, however, phased arrays are supported
131
          *   Calculates a single imaging kernel, however, phased arrays are supported
125
          *   so that more than one transmitter and/or receiver can be specified.
132
          *   so that more than one transmitter and/or receiver can be specified.
126
-         *   @param[in]
133
+         *   @param[in] tx is the list of transmitters to use for a kernel, use the same labels as
134
+         *              used in PushCoil.
135
+         *   @param[in] rx is the list of receivers to use for a kernel, use the same labels as
136
+         *              used in PushCoil. @see PushCoil
137
+         *   @param[in] vtkOutput generates a VTK hyperoctree file as well, useful for visualization.
138
+         *              requires compilation of Lemma with VTK.
127
          */
139
          */
128
-        void CalculateK0 (const std::vector< std::string >& tx, const std::vector< std::string >& rx );
140
+        void CalculateK0 (const std::vector< std::string >& tx, const std::vector< std::string >& rx,
141
+                bool vtkOutput=false );
129
 
142
 
130
         // ====================  INQUIRY       =======================
143
         // ====================  INQUIRY       =======================
131
         /**
144
         /**
148
         /**
161
         /**
149
          *  Returns the kernel value for an input prism
162
          *  Returns the kernel value for an input prism
150
          */
163
          */
151
-        Complex f( const Vector3r& r, const Real& volume );
164
+        Complex f( const Vector3r& r, const Real& volume , const Vector3cr& Bt);
152
 
165
 
153
-        void IntegrateOnOctreeGrid( const Real& tolerance );
166
+        void IntegrateOnOctreeGrid( const Real& tolerance , bool vtkOutput=false );
154
 
167
 
155
         /**
168
         /**
156
          *  Recursive call to integrate a function on an adaptive Octree Grid.
169
          *  Recursive call to integrate a function on an adaptive Octree Grid.
165
         bool EvaluateKids(  const Vector3r& size, const int& level, const Vector3r& cpos,
178
         bool EvaluateKids(  const Vector3r& size, const int& level, const Vector3r& cpos,
166
                             const Complex& parentVal );
179
                             const Complex& parentVal );
167
 
180
 
181
+        #ifdef LEMMAUSEVTK
182
+        /**
183
+         *  Same functionality as @see EvaluateKids, but includes generation of a VTK
184
+         *  HyperOctree, which is useful for visualization.
185
+         */
186
+        bool EvaluateKids2(  const Vector3r& size, const int& level, const Vector3r& cpos,
187
+                            const Complex& parentVal, vtkHyperOctree* octree, vtkHyperOctreeCursor* curse );
188
+        #endif
189
+
168
         // ====================  DATA MEMBERS  =========================
190
         // ====================  DATA MEMBERS  =========================
169
 
191
 
170
-        Complex                                  SUM;
192
+        Complex                                   SUM;
171
 
193
 
172
-        Real                                     tol=1e-3;
194
+        Real                                      tol=1e-3;
173
 
195
 
174
-        int                                      nleaves;
196
+        int                                       nleaves;
175
 
197
 
176
-        std::shared_ptr< LayeredEarthEM >        SigmaModel = nullptr;
198
+        std::shared_ptr< LayeredEarthEM >         SigmaModel = nullptr;
177
 
199
 
178
         std::map< std::string , std::shared_ptr< PolygonalWireAntenna > >  TxRx;
200
         std::map< std::string , std::shared_ptr< PolygonalWireAntenna > >  TxRx;
179
 
201
 
202
+        std::vector< std::shared_ptr<EMEarth1D> > EMEarths;
203
+
204
+        #ifdef LEMMAUSEVTK
205
+        std::map< int, Complex  >                 LeafDict;
206
+        #endif
207
+
180
         /** ASCII string representation of the class name */
208
         /** ASCII string representation of the class name */
181
         static constexpr auto CName = "KernelV0";
209
         static constexpr auto CName = "KernelV0";
182
 
210
 

+ 136
- 31
src/KernelV0.cpp View File

19
 
19
 
20
 
20
 
21
 #include "KernelV0.h"
21
 #include "KernelV0.h"
22
-#include "EMEarth1D.h"
23
 #include "FieldPoints.h"
22
 #include "FieldPoints.h"
24
 
23
 
25
 namespace Lemma {
24
 namespace Lemma {
103
     //       Class:  KernelV0
102
     //       Class:  KernelV0
104
     //      Method:  DeSerialize
103
     //      Method:  DeSerialize
105
     //--------------------------------------------------------------------------------------
104
     //--------------------------------------------------------------------------------------
106
-    void KernelV0::CalculateK0 (const std::vector< std::string>& Tx, const std::vector<std::string >& Rx ) {
105
+    void KernelV0::CalculateK0 (const std::vector< std::string>& Tx, const std::vector<std::string >& Rx,
106
+            bool vtkOutput ) {
107
 
107
 
108
+        // All EM calculations will share same field points
109
+        auto points = FieldPoints::NewSP();
110
+            points->SetNumberOfPoints(8);
108
         for (auto tx : Tx) {
111
         for (auto tx : Tx) {
109
             // Set up EMEarth
112
             // Set up EMEarth
110
-            auto EmEarth = EMEarth1D::NewSP();
111
-                EmEarth->AttachWireAntenna(TxRx[tx]);
112
-                EmEarth->AttachLayeredEarthEM(SigmaModel);
113
-         		EmEarth->SetFieldsToCalculate(H);
113
+            EMEarths.push_back( EMEarth1D::NewSP() );
114
+                EMEarths.back()->AttachWireAntenna(TxRx[tx]);
115
+                EMEarths.back()->AttachLayeredEarthEM(SigmaModel);
116
+                EMEarths.back()->AttachFieldPoints( points );
117
+         		EMEarths.back()->SetFieldsToCalculate(H);
114
                 // TODO query for method, altough with flat antennae, this is fastest
118
                 // TODO query for method, altough with flat antennae, this is fastest
115
-                EmEarth->SetHankelTransformMethod(ANDERSON801);
116
-
117
-        IntegrateOnOctreeGrid( 1e-2 );
118
-
119
-// 		EmEarth->AttachFieldPoints(receivers);
120
-//         //EmEarth->SetHankelTransformMethod(FHTKEY101);
121
-// 	    EmEarth->CalculateWireAntennaFields();
122
-//         Vector3Xcr Rx1 = receivers->GetHfield(0);
123
-//         //receivers->ClearFields();
124
-//
125
-// 		//EmEarth->AttachWireAntenna(Tx2);
126
-// 	    EmEarth->CalculateWireAntennaFields();
127
-//         Rx1 += receivers->GetHfield(0);
128
-
119
+                EMEarths.back()->SetHankelTransformMethod(ANDERSON801);
129
         }
120
         }
121
+        IntegrateOnOctreeGrid( 1e-7, vtkOutput );
130
 
122
 
131
     }
123
     }
132
 
124
 
134
     //       Class:  KernelV0
126
     //       Class:  KernelV0
135
     //      Method:  IntegrateOnOctreeGrid
127
     //      Method:  IntegrateOnOctreeGrid
136
     //--------------------------------------------------------------------------------------
128
     //--------------------------------------------------------------------------------------
137
-    void KernelV0::IntegrateOnOctreeGrid( const Real& tolerance) {
129
+    void KernelV0::IntegrateOnOctreeGrid( const Real& tolerance, bool vtkOutput) {
138
 
130
 
139
         this->tol = tolerance;
131
         this->tol = tolerance;
140
         Vector3r                Size;
132
         Vector3r                Size;
141
             Size << 100,100,100;
133
             Size << 100,100,100;
142
-        //Vector3r                Origin;
134
+        Vector3r                Origin;
135
+            Origin << 0,0,0;
143
         Vector3r                cpos;
136
         Vector3r                cpos;
144
             cpos << 50,50,50;
137
             cpos << 50,50,50;
145
         int                     maxlevel;
138
         int                     maxlevel;
146
 
139
 
147
         SUM = 0;
140
         SUM = 0;
148
         nleaves = 0;
141
         nleaves = 0;
149
-        EvaluateKids( Size, 0, cpos, -1e2 );
142
+        if (!vtkOutput) {
143
+            EvaluateKids( Size, 0, cpos, 1e6 );
144
+        } else {
145
+        #ifdef LEMMAUSEVTK
146
+            vtkHyperOctree* oct = vtkHyperOctree::New();
147
+                oct->SetDimension(3);
148
+                oct->SetOrigin( Origin(0), Origin(1), Origin(2) );
149
+                oct->SetSize( Size(0), Size(1), Size(2) );
150
+            vtkHyperOctreeCursor* curse = oct->NewCellCursor();
151
+                curse->ToRoot();
152
+            EvaluateKids2( Size, 0, cpos, 1e6, oct, curse );
153
+            auto write = vtkXMLHyperOctreeWriter::New();
154
+                //write.SetDataModeToAscii()
155
+                write->SetInputData(oct);
156
+                write->SetFileName("octree.vto");
157
+                write->Write();
158
+                write->Delete();
159
+            curse->Delete();
160
+            oct->Delete();
161
+        #else
162
+            throw std::runtime_error("IntegrateOnOctreeGrid with vtkOutput requires Lemma with VTK support");
163
+        #endif
164
+
165
+        }
150
         std::cout << "SUM\t" << SUM << "\t" << 100*100*100 << "\t" << SUM - Complex(100.*100.*100.) <<  std::endl;
166
         std::cout << "SUM\t" << SUM << "\t" << 100*100*100 << "\t" << SUM - Complex(100.*100.*100.) <<  std::endl;
151
         std::cout << "nleaves\t" << nleaves << std::endl;
167
         std::cout << "nleaves\t" << nleaves << std::endl;
152
 
168
 
156
     //       Class:  KernelV0
172
     //       Class:  KernelV0
157
     //      Method:  f
173
     //      Method:  f
158
     //--------------------------------------------------------------------------------------
174
     //--------------------------------------------------------------------------------------
159
-    Complex KernelV0::f( const Vector3r& r, const Real& volume ) {
160
-        return Complex(volume);
175
+    Complex KernelV0::f( const Vector3r& r, const Real& volume, const Vector3cr& Bt ) {
176
+        //std::cout << volume*Bt.norm() << std::endl;
177
+        return Complex(volume*Bt.norm());
178
+        //return Complex(volume);
161
     }
179
     }
162
 
180
 
163
     //--------------------------------------------------------------------------------------
181
     //--------------------------------------------------------------------------------------
184
                         0, step[1], step[2],
202
                         0, step[1], step[2],
185
                   step[0], step[1], step[2] ).finished();
203
                   step[0], step[1], step[2] ).finished();
186
 
204
 
205
+        VectorXcr kvals(8);       // individual kernel vals
206
+        FieldPoints* cpoints = EMEarths[0]->GetFieldPoints();
207
+            cpoints->ClearFields();
208
+        for (int ichild=0; ichild<8; ++ichild) {
209
+            Vector3r cp = pos;    // Eigen complains about combining these
210
+            cp += posadd.row(ichild);
211
+            cpoints->SetLocation( ichild, cp );
212
+        }
213
+
214
+        Vector3Xcr Bt;
215
+        //Eigen::Matrix< Complex, 8, 3 > Bt;
216
+        for ( auto EMCalc : EMEarths ) {
217
+            //EMCalc->GetFieldPoints()->ClearFields();
218
+            EMCalc->CalculateWireAntennaFields();
219
+            Bt = EMCalc->GetFieldPoints()->GetHfield(0);
220
+        }
221
+
222
+        for (int ichild=0; ichild<8; ++ichild) {
223
+            Vector3r cp = pos;    // Eigen complains about combining these
224
+            cp += posadd.row(ichild);
225
+            kvals(ichild) = f(cp, vol, Bt.col(ichild));
226
+        }
227
+
228
+        Complex ksum = kvals.sum();     // Kernel sum
229
+        // Evaluate whether or not furthur splitting is needed
230
+        if ( std::abs(ksum - parentVal) > tol || level < 5 ) {
231
+            for (int ichild=0; ichild<8; ++ichild) {
232
+                Vector3r cp = pos; // Eigen complains about combining these
233
+                cp += posadd.row(ichild);
234
+                bool isleaf = EvaluateKids( size, level+1, cp, kvals(ichild) );
235
+                if (isleaf) {      // Include result in final integral
236
+                    SUM += ksum;
237
+                    nleaves += 1;
238
+                }
239
+            }
240
+            return false;  // not leaf
241
+        }
242
+        // Save here instead?
243
+        return true;       // leaf
244
+    }
245
+
246
+    #ifdef LEMMAUSEVTK
247
+    //--------------------------------------------------------------------------------------
248
+    //       Class:  KernelV0
249
+    //      Method:  EvaluateKids2 -- same as Evaluate Kids, but include VTK octree generation
250
+    //--------------------------------------------------------------------------------------
251
+    bool KernelV0::EvaluateKids2( const Vector3r& size, const int& level, const Vector3r& cpos,
252
+        const Complex& parentVal, vtkHyperOctree* oct, vtkHyperOctreeCursor* curse) {
253
+
254
+        std::cout << "\rlevel " << level << "\t" << nleaves;
255
+        std::cout.flush();
256
+
257
+        // Next level step, interested in one level below
258
+        // bitshift requires one extra, faster than, and equivalent to std::pow(2, level+1)
259
+        Vector3r step = size.array() / (Real)(1 << (level+2) );
260
+
261
+        Real vol = step(0)*step(1)*step(2);     // volume of each child
262
+
263
+        Vector3r pos =  cpos - step/2.;
264
+        Eigen::Matrix<Real, 8, 3> posadd = (Eigen::Matrix<Real, 8, 3>() <<
265
+                        0,       0,       0,
266
+                  step[0],       0,       0,
267
+                        0, step[1],       0,
268
+                  step[0], step[1],       0,
269
+                        0,       0, step[2],
270
+                  step[0],       0, step[2],
271
+                        0, step[1], step[2],
272
+                  step[0], step[1], step[2] ).finished();
273
+
187
         VectorXcr kvals(8);                     // individual kernel vals
274
         VectorXcr kvals(8);                     // individual kernel vals
275
+        FieldPoints* cpoints = EMEarths[0]->GetFieldPoints();
276
+            cpoints->ClearFields();
277
+        for (int ichild=0; ichild<8; ++ichild) {
278
+            Vector3r cp = pos;    // Eigen complains about combining these
279
+            cp += posadd.row(ichild);
280
+            cpoints->SetLocation( ichild, cp );
281
+        }
282
+
283
+        Vector3Xcr Bt;
284
+        for ( auto EMCalc : EMEarths ) {
285
+            //EMCalc->GetFieldPoints()->ClearFields();
286
+            EMCalc->CalculateWireAntennaFields();
287
+            Bt = EMCalc->GetFieldPoints()->GetHfield(0);
288
+        }
289
+
188
         for (int ichild=0; ichild<8; ++ichild) {
290
         for (int ichild=0; ichild<8; ++ichild) {
189
             Vector3r cp = pos; // Eigen complains about combining these
291
             Vector3r cp = pos; // Eigen complains about combining these
190
             cp += posadd.row(ichild);
292
             cp += posadd.row(ichild);
191
-            kvals(ichild) = f(cp, vol);
293
+            kvals(ichild) = f(cp, vol, Bt.col(ichild));
192
         }
294
         }
193
-        Complex ksum = kvals.sum();     // Kernel sum
194
 
295
 
296
+        Complex ksum = kvals.sum();     // Kernel sum
195
         // Evaluate whether or not furthur splitting is needed
297
         // Evaluate whether or not furthur splitting is needed
196
-        if ( std::abs(ksum - parentVal) > tol || level < 5 ) {
298
+        if ( std::abs(ksum - parentVal) > tol || level < 3 ) {
299
+            oct->SubdivideLeaf(curse);
197
             for (int ichild=0; ichild<8; ++ichild) {
300
             for (int ichild=0; ichild<8; ++ichild) {
301
+                curse->ToChild(ichild);
198
                 Vector3r cp = pos; // Eigen complains about combining these
302
                 Vector3r cp = pos; // Eigen complains about combining these
199
                 cp += posadd.row(ichild);
303
                 cp += posadd.row(ichild);
200
-                bool isleaf = EvaluateKids( size, level+1, pos, kvals(ichild) );
304
+                bool isleaf = EvaluateKids2( size, level+1, cp, kvals(ichild), oct, curse );
201
                 if (isleaf) {  // Include result in final integral
305
                 if (isleaf) {  // Include result in final integral
202
-//                  Id = curse.GetLeafId()     // VTK
203
-//                  LeafDict[Id] = vals[child] // VTK
306
+                    LeafDict[curse->GetLeafId()] = kvals(ichild);       // VTK
204
                     SUM += ksum;
307
                     SUM += ksum;
205
                     nleaves += 1;
308
                     nleaves += 1;
206
                 }
309
                 }
310
+                curse->ToParent();
207
             }
311
             }
208
             return false;  // not leaf
312
             return false;  // not leaf
209
         }
313
         }
210
         return true;       // leaf
314
         return true;       // leaf
211
     }
315
     }
316
+    #endif
212
 
317
 
213
 } // ----  end of namespace Lemma  ----
318
 } // ----  end of namespace Lemma  ----
214
 
319
 

Loading…
Cancel
Save