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,6 +11,12 @@ set_target_properties(merlin PROPERTIES
11 11
 # Linking
12 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 20
 # Testing
15 21
 if (LEMMA_ENABLE_TESTING)
16 22
 	add_subdirectory(testing)

+ 6
- 0
examples/CMakeLists.txt View File

@@ -1,6 +1,12 @@
1 1
 add_executable( KernelV0 KernelV0.cpp  )
2 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 10
 INSTALL_TARGETS( "/share/Merlin/"
5 11
 	KernelV0
6 12
 )

+ 3
- 3
examples/KernelV0.cpp View File

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

+ 36
- 8
include/KernelV0.h View File

@@ -23,6 +23,13 @@
23 23
 #include "LemmaObject.h"
24 24
 #include "LayeredEarthEM.h"
25 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 34
 namespace Lemma {
28 35
 
@@ -123,9 +130,15 @@ namespace Lemma {
123 130
         /**
124 131
          *   Calculates a single imaging kernel, however, phased arrays are supported
125 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 143
         // ====================  INQUIRY       =======================
131 144
         /**
@@ -148,9 +161,9 @@ namespace Lemma {
148 161
         /**
149 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 169
          *  Recursive call to integrate a function on an adaptive Octree Grid.
@@ -165,18 +178,33 @@ namespace Lemma {
165 178
         bool EvaluateKids(  const Vector3r& size, const int& level, const Vector3r& cpos,
166 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 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 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 208
         /** ASCII string representation of the class name */
181 209
         static constexpr auto CName = "KernelV0";
182 210
 

+ 136
- 31
src/KernelV0.cpp View File

@@ -19,7 +19,6 @@
19 19
 
20 20
 
21 21
 #include "KernelV0.h"
22
-#include "EMEarth1D.h"
23 22
 #include "FieldPoints.h"
24 23
 
25 24
 namespace Lemma {
@@ -103,30 +102,23 @@ namespace Lemma {
103 102
     //       Class:  KernelV0
104 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 111
         for (auto tx : Tx) {
109 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 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,19 +126,43 @@ namespace Lemma {
134 126
     //       Class:  KernelV0
135 127
     //      Method:  IntegrateOnOctreeGrid
136 128
     //--------------------------------------------------------------------------------------
137
-    void KernelV0::IntegrateOnOctreeGrid( const Real& tolerance) {
129
+    void KernelV0::IntegrateOnOctreeGrid( const Real& tolerance, bool vtkOutput) {
138 130
 
139 131
         this->tol = tolerance;
140 132
         Vector3r                Size;
141 133
             Size << 100,100,100;
142
-        //Vector3r                Origin;
134
+        Vector3r                Origin;
135
+            Origin << 0,0,0;
143 136
         Vector3r                cpos;
144 137
             cpos << 50,50,50;
145 138
         int                     maxlevel;
146 139
 
147 140
         SUM = 0;
148 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 166
         std::cout << "SUM\t" << SUM << "\t" << 100*100*100 << "\t" << SUM - Complex(100.*100.*100.) <<  std::endl;
151 167
         std::cout << "nleaves\t" << nleaves << std::endl;
152 168
 
@@ -156,8 +172,10 @@ namespace Lemma {
156 172
     //       Class:  KernelV0
157 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,31 +202,118 @@ namespace Lemma {
184 202
                         0, step[1], step[2],
185 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 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 290
         for (int ichild=0; ichild<8; ++ichild) {
189 291
             Vector3r cp = pos; // Eigen complains about combining these
190 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 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 300
             for (int ichild=0; ichild<8; ++ichild) {
301
+                curse->ToChild(ichild);
198 302
                 Vector3r cp = pos; // Eigen complains about combining these
199 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 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 307
                     SUM += ksum;
205 308
                     nleaves += 1;
206 309
                 }
310
+                curse->ToParent();
207 311
             }
208 312
             return false;  // not leaf
209 313
         }
210 314
         return true;       // leaf
211 315
     }
316
+    #endif
212 317
 
213 318
 } // ----  end of namespace Lemma  ----
214 319
 

Loading…
Cancel
Save