Browse Source

Added kiha library check, things seem to be working, need more verification and benching

enhancement_3
Trevor Irons 7 years ago
parent
commit
d8c5ce645a

+ 8
- 0
CMakeLists.txt View File

@@ -162,6 +162,14 @@ endif()
162 162
 # Lemma Configuration
163 163
 #####################
164 164
 
165
+#####################
166
+# Look for Ki Ha Lee 
167
+#####################
168
+FIND_LIBRARY( KIHA_EM1D kihaem1d ) # PATHS ${/home/tirons/local/lib}  )
169
+if ( KIHA_EM1D )
170
+	add_compile_options(-DKIHALEE_EM1D)
171
+endif()
172
+
165 173
 ####################
166 174
 # Add the c++11 flag 
167 175
 # TODO add compiler specific instructions

+ 5
- 0
Modules/FDEM1D/CMakeLists.txt View File

@@ -11,6 +11,11 @@ set_target_properties(fdem1d PROPERTIES
11 11
 # Linking
12 12
 target_link_libraries(fdem1d "lemmacore")
13 13
 
14
+if ( KIHA_EM1D )
15
+	target_link_libraries(fdem1d "kihaem1d")
16
+	target_link_libraries(fdem1d "gfortran")
17
+endif()
18
+
14 19
 # Testing
15 20
 if (LEMMA_ENABLE_TESTING)
16 21
 	add_subdirectory(testing)

+ 4
- 0
Modules/FDEM1D/examples/CMakeLists.txt View File

@@ -7,8 +7,12 @@ target_link_libraries(  FieldPoints  "lemmacore" "fdem1d")
7 7
 add_executable( PolygonalWireAntenna PolygonalWireAntenna.cpp  )
8 8
 target_link_libraries(  PolygonalWireAntenna  "lemmacore" "fdem1d")
9 9
 
10
+add_executable( EMDipEarth1D EMDipEarth1D.cpp  )
11
+target_link_libraries(  EMDipEarth1D  "lemmacore" "fdem1d")
12
+
10 13
 INSTALL_TARGETS( "/share/FEM1D/"
11 14
 	LayeredEarthEM 
12 15
 	FieldPoints
13 16
 	PolygonalWireAntenna
17
+	EMDipEarth1D
14 18
 )

Modules/FDEM1D/examples/emdipearth1d.cpp → Modules/FDEM1D/examples/EMDipEarth1D.cpp View File

@@ -30,17 +30,14 @@
30 30
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
31 31
 //
32 32
 // ===========================================================================
33
-#include "emearth1d.h"
34
-#include "dipolesource.h"
35
-#include "layeredearthem.h"
36
-#include "receiverpoints.h"
33
+#include <FDEM1D>
37 34
 
38 35
 using namespace Lemma;
39 36
 
40 37
 int main() {
41 38
 
42 39
 	// Test with a single dipole
43
-	DipoleSource *dipole = DipoleSource::New();
40
+	auto dipole = DipoleSource::NewSP();
44 41
 		dipole->SetType(GROUNDEDELECTRICDIPOLE);
45 42
 		dipole->SetPolarisation(XPOLARISATION);
46 43
 		dipole->SetNumberOfFrequencies(1);
@@ -57,13 +54,13 @@ int main() {
57 54
 	VectorXr  thick(1);
58 55
 		thick << 10;//, 10, 10;
59 56
 
60
-	LayeredEarthEM *earth = LayeredEarthEM::New();
57
+	auto earth = LayeredEarthEM::NewSP();
61 58
         earth->SetNumberOfLayers(2);
62 59
 		earth->SetLayerConductivity(sigma);
63 60
 		//earth->SetLayerThickness(thick);
64 61
 
65 62
 	// Receivers
66
-	ReceiverPoints *receivers = ReceiverPoints::New();
63
+	auto receivers = FieldPoints::NewSP();
67 64
 		Vector3r loc;
68 65
 		//Real ox = -5.1456;
69 66
 		//Real oy =  2.2350;
@@ -73,7 +70,7 @@ int main() {
73 70
 		Real dz = 2.6;
74 71
 		int  nz = 1;
75 72
 
76
-		receivers->SetNumberOfReceivers(nz);
73
+		receivers->SetNumberOfPoints(nz);
77 74
 		int ir = 0;
78 75
 		for (int iz=0; iz<nz; ++iz) {
79 76
 			loc << ox, oy, depth;
@@ -83,12 +80,12 @@ int main() {
83 80
 		}
84 81
 	//receivers->SetLocation(1, ox, oy, depth);
85 82
 
86
-	EMEarth1D *EmEarth = EMEarth1D::New();
83
+    auto EmEarth = EMEarth1D::NewSP();
87 84
         //EmEarth->SetHankelTransformMethod(DIGITALFILTERING);
88 85
         EmEarth->SetFieldsToCalculate(BOTH); // Fortran needs this
89 86
 		EmEarth->AttachDipoleSource(dipole);
90 87
 		EmEarth->AttachLayeredEarthEM(earth);
91
-		EmEarth->AttachReceiverPoints(receivers);
88
+		EmEarth->AttachFieldPoints(receivers);
92 89
 
93 90
         //dipole->SetType(ELECTRICDIPOLE);
94 91
 //         receivers->SetNumberOfReceivers(1);
@@ -105,37 +102,19 @@ int main() {
105 102
 	receivers->ClearFields();
106 103
 
107 104
     // swap tx rx posigion
105
+    /*
108 106
     receivers->SetLocation(0, dipole->GetLocation());
109 107
     dipole->SetLocation(loc);
110 108
 	EmEarth->MakeCalc3();
111 109
 	std::cout << receivers->GetEfield(0,0) << std::endl;
112
-
113 110
 	receivers->ClearFields();
111
+    */
112
+
114 113
  #ifdef KIHALEE_EM1D
115
-// 	//std::cout << "\nFORTRAN\n";
114
+    std::cout << "\nFORTRAN\n";
116 115
  	EmEarth->MakeCalc();
117 116
 // 	std::cout << receivers->GetHfield(0,0) << std::endl;
118 117
  	std::cout << receivers->GetEfield(0,0) << std::endl;
119 118
  #endif
120 119
 
121
-    dipole->Delete();
122
-    EmEarth->Delete();
123
-    receivers->Delete();
124
-    earth->Delete();
125
-
126
-// 	try {
127
-//
128
-// 	}
129
-//
130
-// 	// Catch exceptions
131
-// 	catch (NullEarth) {
132
-// 			std::cout << "Earth model not set dummy\n";
133
-// 	}
134
-//
135
-// 	catch (NullReceivers) {
136
-// 			std::cout << "Receivers not set dummy\n";
137
-// 	}
138
-
139
-	//EmEarth->TestBess();
140
-
141 120
 }

+ 1
- 1
Modules/FDEM1D/include/EMEarth1D.h View File

@@ -93,7 +93,7 @@ namespace Lemma {
93 93
 
94 94
             /// Calculates the field(s) due to an ungrounded dipole source
95 95
             /// Calls FORTRAN library em1d (em1dnew.for)
96
-#ifdef COMPILE_FORTRAN
96
+#ifdef KIHALEE_EM1D
97 97
             void MakeCalc();
98 98
 #endif
99 99
 

+ 2
- 0
Modules/FDEM1D/include/FDEM1D View File

@@ -7,6 +7,8 @@
7 7
 
8 8
 #include "DipoleSource.h"
9 9
 
10
+#include "EMEarth1D.h"
11
+
10 12
 // internal
11 13
 //#include "KernelEM1DManager.h"
12 14
 //#include "KernelEM1DSpec.h"

+ 888
- 0
Modules/FDEM1D/src/EMEarth1D.cpp View File

@@ -0,0 +1,888 @@
1
+/* This file is part of Lemma, a geophysical modelling and inversion API */
2
+
3
+/* This Source Code Form is subject to the terms of the Mozilla Public
4
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
+
7
+/**
8
+  @file
9
+  @author   Trevor Irons
10
+  @date     12/02/2009
11
+ **/
12
+
13
+#include "EMEarth1D.h"
14
+#include "FieldPoints.h"
15
+#include "WireAntenna.h"
16
+#include "PolygonalWireAntenna.h"
17
+
18
+#ifdef LEMMAUSEOMP
19
+#include "omp.h"
20
+#endif
21
+
22
+namespace Lemma {
23
+
24
+    std::ostream &operator << (std::ostream &stream, const EMEarth1D &ob) {
25
+        stream << ob.Serialize()  << "\n---\n"; // End of doc ---
26
+        return stream;
27
+    }
28
+
29
+#ifdef KIHALEE_EM1D
30
+    // Wrapper function for Fortran subroutine Em1D bi kihand
31
+    // Returns E or H fields (SLOW)
32
+    extern "C" { void em1dcall_(int &itype,   // source
33
+                            int     &ipol,    // source
34
+                            int     &nlay,    // Earth
35
+                            int     &nfreq,   // source
36
+                            int     &nfield,  // Calculator
37
+                            int     &nres,    // Receivers
38
+                            int     &jtype,   // N/A
39
+                            int     &jgamma,  // Controller
40
+                            double  &acc,     // Controller
41
+                            double  *dep,     // Earth
42
+                            std::complex<double> *sig,     // Earth
43
+                            double  *susl,    // Earth
44
+                            double  *sush,    // Earth
45
+                            double  *sustau,  // Earth
46
+                            double  *susalp,  // Earth
47
+                            double  *eprl,    // Earth
48
+                            double  *eprh,    // Earth
49
+                            double  *eprtau,  // Earth
50
+                            double  *epralp,  // Earth
51
+                            double  &finit,   // N/A
52
+                            double  &flimit,  // N/A
53
+                            double  &dlimit,  // N/A
54
+                            double  &lfinc,   // N/A
55
+                            double  &tx,      // Source
56
+                            double  &ty,      // Source
57
+                            double  &tz,      // Source
58
+                            double  *rxx,     // Receivers
59
+                            double  *rxy,     // Receivers
60
+                            double  *rxz,     // Receivers
61
+                            std::complex<double> *ex,      // Receivers
62
+                            std::complex<double> *ey,      //    |
63
+                            std::complex<double> *ez,      //    |
64
+                            std::complex<double> *hx,      //    |
65
+                            std::complex<double> *hy,      //    V
66
+                            std::complex<double> *hz );    //   ___
67
+    }
68
+#endif
69
+
70
+    // ====================  LIFECYCLE     ===================================
71
+
72
+    // TODO init large arrays here.
73
+    EMEarth1D::EMEarth1D( const ctor_key& ) : LemmaObject( ),
74
+            Dipole(nullptr), Earth(nullptr), Receivers(nullptr), Antenna(nullptr),
75
+            FieldsToCalculate(BOTH), HankelType(ANDERSON801), icalcinner(0), icalc(0)
76
+        //#ifdef HAVEBOOSTPROGRESS
77
+        //    , disp(0)
78
+        //#endif
79
+        {
80
+    }
81
+
82
+    EMEarth1D::~EMEarth1D() {
83
+    }
84
+
85
+    std::shared_ptr<EMEarth1D> EMEarth1D::NewSP() {
86
+        return std::make_shared<EMEarth1D>(ctor_key());
87
+    }
88
+
89
+    YAML::Node EMEarth1D::Serialize() const {
90
+        YAML::Node node = LemmaObject::Serialize();
91
+        node["FieldsToCalculate"] = enum2String(FieldsToCalculate);
92
+        node["HankelType"] = enum2String(HankelType);
93
+        //if (Dipole != nullptr) node["Dipole"] = Dipole->Serialize();
94
+        if (Earth != nullptr)     node["Earth"] = Earth->Serialize();
95
+        //if (Receivers != nullptr) node["Receivers"] = Receivers->Serialize(); Can be huge?
96
+        if (Antenna != nullptr)   node["Antenna"] = Antenna->Serialize();
97
+        node.SetTag( this->GetName() );
98
+        return node;
99
+    }
100
+
101
+    // ====================  ACCESS        ===================================
102
+    void EMEarth1D::AttachDipoleSource( std::shared_ptr<DipoleSource> dipoleptr) {
103
+        Dipole = dipoleptr;
104
+    }
105
+
106
+    void EMEarth1D::AttachLayeredEarthEM( std::shared_ptr<LayeredEarthEM> earthptr) {
107
+        Earth = earthptr;
108
+    }
109
+
110
+    void EMEarth1D::AttachFieldPoints( std::shared_ptr<FieldPoints> recptr) {
111
+
112
+        Receivers = recptr;
113
+        if (Receivers == nullptr) {
114
+            std::cout << "nullptr Receivers in emearth1d.cpp " << std::endl;
115
+            return;
116
+        }
117
+
118
+        // This has an implicid need to first set a source before receivers, users
119
+        // will not expect this. Fix
120
+        if (Dipole != nullptr) {
121
+            switch (FieldsToCalculate) {
122
+                case E:
123
+                    Receivers->SetNumberOfBinsE(Dipole->GetNumberOfFrequencies());
124
+                    break;
125
+                case H:
126
+                    Receivers->SetNumberOfBinsH(Dipole->GetNumberOfFrequencies());
127
+                    break;
128
+                case BOTH:
129
+                    Receivers->SetNumberOfBinsE(Dipole->GetNumberOfFrequencies());
130
+                    Receivers->SetNumberOfBinsH(Dipole->GetNumberOfFrequencies());
131
+                    break;
132
+            }
133
+        } else if (Antenna != nullptr) {
134
+            switch (FieldsToCalculate) {
135
+                case E:
136
+                    Receivers->SetNumberOfBinsE(Antenna->GetNumberOfFrequencies());
137
+                    break;
138
+                case H:
139
+                    Receivers->SetNumberOfBinsH(Antenna->GetNumberOfFrequencies());
140
+                    break;
141
+                case BOTH:
142
+                    Receivers->SetNumberOfBinsE(Antenna->GetNumberOfFrequencies());
143
+                    Receivers->SetNumberOfBinsH(Antenna->GetNumberOfFrequencies());
144
+                    break;
145
+            }
146
+        }
147
+    }
148
+
149
+    void EMEarth1D::AttachWireAntenna(std::shared_ptr<WireAntenna> antennae) {
150
+        this->Antenna = antennae;
151
+    }
152
+
153
+    void EMEarth1D::SetFieldsToCalculate(const FIELDCALCULATIONS &calc) {
154
+        FieldsToCalculate = calc;
155
+    }
156
+
157
+    void EMEarth1D::SetHankelTransformMethod( const HANKELTRANSFORMTYPE &type) {
158
+        HankelType = type;
159
+    }
160
+
161
+    void EMEarth1D::Query() {
162
+        std::cout << "EmEarth1D::Query()" << std::endl;
163
+
164
+        std::cout << "Dipole " << Dipole;
165
+        if (Dipole) std::cout << *Dipole << std::endl;
166
+
167
+        std::cout << "Earth " << Earth;
168
+        if (Earth) std::cout << *Earth << std::endl;
169
+
170
+        std::cout << "Receivers " << Earth;
171
+        if (Earth) std::cout << *Receivers << std::endl;
172
+
173
+        std::cout << "Antenna " << Earth;
174
+        if (Antenna) std::cout << *Antenna << std::endl;
175
+
176
+        std::cout << "icalc " << icalc << std::endl;
177
+
178
+        std::cout << "icalcinner " << icalcinner << std::endl;
179
+    }
180
+
181
+    // ====================  OPERATIONS    ===================================
182
+
183
+    void EMEarth1D::CalculateWireAntennaFields(bool progressbar) {
184
+
185
+        #ifdef HAVEBOOSTPROGRESS
186
+        boost::progress_display *disp;
187
+        #endif
188
+
189
+        if (Earth == nullptr) {
190
+            throw NullEarth();
191
+        }
192
+        if (Receivers == nullptr) {
193
+            throw NullReceivers();
194
+        }
195
+        if (Antenna == nullptr) {
196
+            throw NullAntenna();
197
+        }
198
+        if (Dipole != nullptr) {
199
+            throw DipoleSourceSpecifiedForWireAntennaCalc();
200
+        }
201
+
202
+        Receivers->ClearFields();
203
+
204
+        // Check to make sure Receivers are set up for all calculations
205
+        switch(FieldsToCalculate) {
206
+            case E:
207
+                if (Receivers->NumberOfBinsE != Antenna->GetNumberOfFrequencies())
208
+                    Receivers->SetNumberOfBinsE(Antenna->GetNumberOfFrequencies());
209
+                break;
210
+            case H:
211
+                if (Receivers->NumberOfBinsH != Antenna->GetNumberOfFrequencies())
212
+                    Receivers->SetNumberOfBinsH(Antenna->GetNumberOfFrequencies());
213
+                break;
214
+            case BOTH:
215
+                if (Receivers->NumberOfBinsH != Antenna->GetNumberOfFrequencies())
216
+                    Receivers->SetNumberOfBinsH(Antenna->GetNumberOfFrequencies());
217
+                if (Receivers->NumberOfBinsE != Antenna->GetNumberOfFrequencies())
218
+                    Receivers->SetNumberOfBinsE(Antenna->GetNumberOfFrequencies());
219
+                break;
220
+        }
221
+
222
+        if (Antenna->GetName() == std::string("PolygonalWireAntenna") || Antenna->GetName() == std::string("TEMTransmitter") ) {
223
+
224
+            icalc += 1;
225
+
226
+            // Check to see if they are all on a plane? If so we can do this fast
227
+            /* TODO FIX THIS ISSUES */
228
+            if (Antenna->IsHorizontallyPlanar() && HankelType == ANDERSON801) {
229
+                //std::cout << "Lag baby lag" << std::endl;
230
+                for (int ifreq=0; ifreq<Antenna->GetNumberOfFrequencies();++ifreq) {
231
+                    //std::cout << "Num Recs" <<  Receivers->GetNumberOfPoints() << std::endl;
232
+                    Real wavef = 2.*PI* Antenna->GetFrequency(ifreq);
233
+                    #ifdef LEMMAUSEOMP
234
+                    #pragma omp parallel
235
+                    {
236
+                    #endif
237
+                    auto Hankel = FHTAnderson801::NewSP();
238
+                    #ifdef LEMMAUSEOMP
239
+                    #pragma omp for schedule(static, 1)
240
+                    #endif
241
+                    for (int irec=0; irec<Receivers->GetNumberOfPoints(); ++irec) {
242
+                    //for (int irec=0; irec<2; ++irec) { // TODO FIXME BELO
243
+                        auto AntCopy = static_cast<PolygonalWireAntenna*>(Antenna.get())->ClonePA();
244
+                        SolveLaggedTxRxPair(irec, Hankel.get(), wavef, ifreq, AntCopy.get());
245
+                        //exit(0);
246
+                    }
247
+                    //Receivers->ClearFields(); // FIXME DEBUG TODO
248
+                    #ifdef LEMMAUSEOMP
249
+                    }
250
+                    #endif
251
+                }
252
+            } else
253
+            if (Receivers->GetNumberOfPoints() > Antenna->GetNumberOfFrequencies()) {
254
+
255
+                //std::cout << "freq parallel #1" << std::endl;
256
+                //** Progress display bar for long calculations */
257
+                #ifdef HAVEBOOSTPROGRESS
258
+                if (progressbar) {
259
+                    disp = new boost::progress_display( Receivers->GetNumberOfPoints()*Antenna->GetNumberOfFrequencies() );
260
+                }
261
+                #endif
262
+
263
+                // parallelise across receivers
264
+                #ifdef LEMMAUSEOMP
265
+                #pragma omp parallel
266
+                #endif
267
+                { // OpenMP Parallel Block
268
+                    // Since these antennas change we need a local copy for each
269
+                    // thread.
270
+                    auto AntCopy = static_cast<PolygonalWireAntenna*>(Antenna.get())->ClonePA();
271
+
272
+                    std::shared_ptr<HankelTransform> Hankel;
273
+                    switch (HankelType) {
274
+                        case ANDERSON801:
275
+                            Hankel = FHTAnderson801::NewSP();
276
+                            break;
277
+                        case CHAVE:
278
+                            Hankel = GQChave::NewSP();
279
+                            break;
280
+                        case FHTKEY201:
281
+                            Hankel = FHTKey201::NewSP();
282
+                            break;
283
+                        case FHTKEY101:
284
+                            Hankel = FHTKey101::NewSP();
285
+                            break;
286
+                        case FHTKEY51:
287
+                            Hankel = FHTKey51::NewSP();
288
+                            break;
289
+                        case QWEKEY:
290
+                            Hankel = QWEKey::NewSP();
291
+                            break;
292
+                        default:
293
+                            std::cerr << "Hankel transform cannot be created\n";
294
+                            exit(EXIT_FAILURE);
295
+                    }
296
+
297
+                    //for (int irec=tid; irec<Receivers->GetNumberOfPoints(); irec+=nthreads) {
298
+                    #ifdef LEMMAUSEOMP
299
+                    #pragma omp for schedule(static, 1) //nowait
300
+                    #endif
301
+                    for (int irec=0; irec<Receivers->GetNumberOfPoints(); ++irec) {
302
+                        if (!Receivers->GetMask(irec)) {
303
+                            AntCopy->ApproximateWithElectricDipoles(Receivers->GetLocation(irec));
304
+                            for (int idip=0; idip<AntCopy->GetNumberOfDipoles(); ++idip) {
305
+                                auto tDipole = AntCopy->GetDipoleSource(idip);
306
+                                //#ifdef LEMMAUSEOMP
307
+                                //#pragma omp for schedule(static, 1)
308
+                                //#endif
309
+                                for (int ifreq=0; ifreq<tDipole->GetNumberOfFrequencies();
310
+                                        ++ifreq) {
311
+                                    // Propogation constant in free space
312
+                                    Real wavef   = tDipole->GetAngularFrequency(ifreq) *
313
+                                          std::sqrt(MU0*EPSILON0);
314
+                                    SolveSingleTxRxPair(irec, Hankel.get(), wavef, ifreq, tDipole.get());
315
+                                } // freq loop
316
+                            } // dipole loop
317
+                        } // mask
318
+                        //std::cout << "Normal Path\n";
319
+                        //std::cout << Receivers->GetHfield(0, irec) << std::endl;
320
+                        //if (irec == 1) exit(0);
321
+                        #ifdef HAVEBOOSTPROGRESS
322
+                        if (progressbar) ++(*disp);
323
+                        #endif
324
+                    } // receiver loop
325
+                } // OMP_PARALLEL BLOCK
326
+            } else if (Antenna->GetNumberOfFrequencies() > 8) {
327
+                // parallel across frequencies
328
+                //std::cout << "freq parallel #2" << std::endl;
329
+                for (int irec=0; irec<Receivers->GetNumberOfPoints(); ++irec) {
330
+                    if (!Receivers->GetMask(irec)) {
331
+                        static_cast<PolygonalWireAntenna*>(Antenna.get())->ApproximateWithElectricDipoles(Receivers->GetLocation(irec));
332
+                        #ifdef LEMMAUSEOMP
333
+                        #pragma omp parallel
334
+                        #endif
335
+                        { // OpenMP Parallel Block
336
+
337
+                            std::shared_ptr<HankelTransform> Hankel;
338
+                            switch (HankelType) {
339
+                                case ANDERSON801:
340
+                                    Hankel = FHTAnderson801::NewSP();
341
+                                    break;
342
+                                case CHAVE:
343
+                                    Hankel = GQChave::NewSP();
344
+                                    break;
345
+                                case FHTKEY201:
346
+                                    Hankel = FHTKey201::NewSP();
347
+                                    break;
348
+                                case FHTKEY101:
349
+                                    Hankel = FHTKey101::NewSP();
350
+                                    break;
351
+                                case FHTKEY51:
352
+                                    Hankel = FHTKey51::NewSP();
353
+                                    break;
354
+                                case QWEKEY:
355
+                                    Hankel = QWEKey::NewSP();
356
+                                    break;
357
+                                default:
358
+                                    std::cerr << "Hankel transform cannot be created\n";
359
+                                    exit(EXIT_FAILURE);
360
+                            }
361
+                            #ifdef LEMMAUSEOMP
362
+                            #pragma omp for schedule(static, 1)
363
+                            #endif
364
+                            for (int ifreq=0; ifreq<Antenna->GetNumberOfFrequencies(); ++ifreq) {
365
+                                for (int idip=0; idip<Antenna->GetNumberOfDipoles(); ++idip) {
366
+                                    auto tDipole = Antenna->GetDipoleSource(idip);
367
+                                    // Propogation constant in free space
368
+                                    Real wavef   = tDipole->GetAngularFrequency(ifreq) *
369
+                                          std::sqrt(MU0*EPSILON0);
370
+                                    SolveSingleTxRxPair(irec, Hankel.get(), wavef, ifreq, tDipole.get());
371
+                                } // dipole loop
372
+                            } // frequency loop
373
+                        } // OMP_PARALLEL BLOCK
374
+                    } // mask loop
375
+                    #ifdef HAVEBOOSTPROGRESS
376
+                    //if (Receivers->GetNumberOfPoints() > 100) {
377
+                    //    ++ disp;
378
+                    //}
379
+                    #endif
380
+                } // receiver loop
381
+                //std::cout << "End freq parallel " << std::endl;
382
+            } // Frequency Parallel
383
+              else {
384
+                //std::cout << "parallel across #3 " << std::endl;
385
+                for (int irec=0; irec<Receivers->GetNumberOfPoints(); ++irec) {
386
+                    if (!Receivers->GetMask(irec)) {
387
+
388
+                        static_cast<PolygonalWireAntenna*>(Antenna.get())->ApproximateWithElectricDipoles(Receivers->GetLocation(irec));
389
+//                         std::cout << "Not Masked " << std::endl;
390
+//                         std::cout << "n Freqs " << Antenna->GetNumberOfFrequencies() << std::endl;
391
+//                         std::cout << "n Dipoles " << Antenna->GetNumberOfDipoles() << std::endl;
392
+//                         if ( !Antenna->GetNumberOfDipoles() ) {
393
+//                             std::cout << "NO DIPOLES!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
394
+// //                            std::cout << "rec location " << Receivers->GetLocation(irec) << std::endl;
395
+// //                        }
396
+
397
+                        #ifdef LEMMAUSEOMP
398
+                        #pragma omp parallel
399
+                        #endif
400
+                        { // OpenMP Parallel Block
401
+                            std::shared_ptr<HankelTransform> Hankel;
402
+                            switch (HankelType) {
403
+                                case ANDERSON801:
404
+                                    Hankel = FHTAnderson801::NewSP();
405
+                                    break;
406
+                                case CHAVE:
407
+                                    Hankel = GQChave::NewSP();
408
+                                    break;
409
+                                case FHTKEY201:
410
+                                    Hankel = FHTKey201::NewSP();
411
+                                    break;
412
+                                case FHTKEY101:
413
+                                    Hankel = FHTKey101::NewSP();
414
+                                    break;
415
+                                case FHTKEY51:
416
+                                    Hankel = FHTKey51::NewSP();
417
+                                    break;
418
+                                case QWEKEY:
419
+                                    Hankel = QWEKey::NewSP();
420
+                                    break;
421
+                                default:
422
+                                    std::cerr << "Hankel transform cannot be created\n";
423
+                                    exit(EXIT_FAILURE);
424
+                            }
425
+                            for (int ifreq=0; ifreq<Antenna->GetNumberOfFrequencies(); ++ifreq) {
426
+                                #ifdef LEMMAUSEOMP
427
+                                #pragma omp for schedule(static, 1)
428
+                                #endif
429
+                                for (int idip=0; idip<Antenna->GetNumberOfDipoles(); ++idip) {
430
+                                    //#pragma omp critical
431
+                                    //{
432
+                                    //cout << "idip=" << idip << "\tthread num=" << omp_get_thread_num() << '\n';
433
+                                    //}
434
+                                    auto tDipole = Antenna->GetDipoleSource(idip);
435
+                                    // Propogation constant in free space
436
+                                    Real wavef   = tDipole->GetAngularFrequency(ifreq) *
437
+                                          std::sqrt(MU0*EPSILON0);
438
+                                    SolveSingleTxRxPair(irec, Hankel.get(), wavef, ifreq, tDipole.get());
439
+                                } // dipole loop
440
+                            } // frequency loop
441
+                        } // OMP_PARALLEL BLOCK
442
+                    } // mask loop
443
+                    #ifdef HAVEBOOSTPROGRESS
444
+                    //if (Receivers->GetNumberOfPoints() > 100) {
445
+                    //    ++ disp;
446
+                    //}
447
+                    #endif
448
+                } // receiver loop
449
+           } // Polygonal parallel logic
450
+        } else {
451
+             std::cerr << "Lemma with WireAntenna class is currently broken"
452
+                  << " fix or use PolygonalWireAntenna\n" << std::endl;
453
+             exit(EXIT_FAILURE);
454
+            // TODO, getting wrong answer, curiously worKernel->GetKs() with MakeCalc, maybe
455
+            // a threading issue, use SolveSingleTxRxPair maype instead of call
456
+            // to MakeCalc3? !!!
457
+            for (int idip=0; idip<Antenna->GetNumberOfDipoles(); ++idip) {
458
+                this->Dipole = Antenna->GetDipoleSource(idip);
459
+                MakeCalc3();
460
+                //++disp;
461
+            }
462
+            this->Dipole = nullptr;
463
+        }
464
+
465
+        #ifdef HAVEBOOSTPROGRESS
466
+        if (progressbar) {
467
+            delete disp;
468
+        }
469
+        #endif
470
+    }
471
+
472
+    #ifdef KIHALEE_EM1D
473
+    void EMEarth1D::MakeCalc() {
474
+
475
+        int itype;       // 1 = elec, 2 = mag
476
+        switch (this->Dipole->GetDipoleSourceType()) {
477
+            case (GROUNDEDELECTRICDIPOLE) :
478
+                itype = 1;
479
+                break;
480
+            case (MAGNETICDIPOLE) :
481
+                itype = 2;
482
+                break;
483
+            case (UNGROUNDEDELECTRICDIPOLE) :
484
+                std::cerr << "Fortran routine cannot calculate ungrounded"
485
+                             "electric dipole\n";
486
+            default:
487
+                throw NonValidDipoleType();
488
+        }
489
+
490
+        int ipol ;
491
+        Vector3r Pol = this->Dipole->GetPolarisation();
492
+        if (std::abs(Pol[0]-1) < 1e-5) {
493
+            ipol = 1;
494
+        } else if (std::abs(Pol[1]-1) < 1e-5) {
495
+            ipol = 2;
496
+        } else if (std::abs(Pol[2]-1) < 1e-5) {
497
+            ipol = 3;
498
+        } else {
499
+            std::cerr << "Fortran routine cannot calculate arbitrary "
500
+                             "dipole polarisation, set to x, y, or z\n";
501
+        }
502
+
503
+        int nlay   =  Earth->GetNumberOfNonAirLayers();
504
+
505
+        if (nlay > MAXLAYERS) {
506
+            std::cerr << "FORTRAN CODE CAN ONLY HANDLE " << MAXLAYERS
507
+                      << " LAYERS\n";
508
+            throw  EarthModelWithMoreThanMaxLayers();
509
+        }
510
+
511
+        int nfreq  = 1;     // number of freqs
512
+
513
+        int nfield;     // field output 1 = elec, 2 = mag, 3 = both
514
+        switch (FieldsToCalculate) {
515
+            case E:
516
+                nfield = 1;
517
+                break;
518
+            case H:
519
+                nfield = 2;
520
+                break;
521
+            case BOTH:
522
+                nfield = 3;
523
+                break;
524
+            default:
525
+                throw 7;
526
+        }
527
+
528
+        int nres   = Receivers->GetNumberOfPoints();
529
+        int jtype  = 3;     // form ouf output,
530
+                            // 1 = horizontal,
531
+                            // 2 = down hole,
532
+                            // 3 = freq sounding
533
+                            // 4 = down hole logging
534
+
535
+        int jgamma = 0;     // Units 0 = MKS (H->A/m and E->V/m)
536
+                            //       1 = h->Gammas   E->V/m
537
+
538
+        double acc = 0.;    // Tolerance
539
+
540
+        // TODO, fix FORTRAN calls so these arrays can be nlay long, not
541
+        // MAXLAYERS.
542
+
543
+        // Model Parameters
544
+        double *dep    = new double[MAXLAYERS];
545
+        dep[0] = 0.;          // We always say air starts at 0
546
+        for (int ilay=1; ilay<Earth->GetNumberOfLayers(); ++ilay) {
547
+            dep[ilay] = dep[ilay-1] + Earth->GetLayerThickness(ilay);
548
+            //std::cout << "Depth " << dep[ilay] << std::endl;
549
+        }
550
+
551
+        std::complex<double> *sig = new std::complex<double> [MAXLAYERS];
552
+        for (int ilay=1; ilay<=nlay; ++ilay) {
553
+            sig[ilay-1] = (std::complex<double>)(Earth->GetLayerConductivity(ilay));
554
+        }
555
+
556
+        // TODO, pass these into Fortran call, and return Cole-Cole model
557
+        // parameters. Right now this does nothing
558
+        //std::complex<double> *sus   = new std::complex<double>[MAXLAYERS];
559
+        //std::complex<double> *epr   = new std::complex<double>[MAXLAYERS];
560
+
561
+        // Cole-Cole model stuff
562
+        double *susl   = new double[MAXLAYERS];
563
+        for (int ilay=1; ilay<=nlay; ++ilay) {
564
+            susl[ilay-1] = Earth->GetLayerLowFreqSusceptibility(ilay);
565
+        }
566
+
567
+        double *sush   = new double[MAXLAYERS];
568
+        for (int ilay=1; ilay<=nlay; ++ilay) {
569
+            sush[ilay-1] = Earth->GetLayerHighFreqSusceptibility(ilay);
570
+        }
571
+
572
+        double *sustau = new double[MAXLAYERS];
573
+        for (int ilay=1; ilay<=nlay; ++ilay) {
574
+            sustau[ilay-1] = Earth->GetLayerTauSusceptibility(ilay);
575
+        }
576
+
577
+        double *susalp = new double[MAXLAYERS];
578
+        for (int ilay=1; ilay<=nlay; ++ilay) {
579
+            susalp[ilay-1] = Earth->GetLayerBreathSusceptibility(ilay);
580
+        }
581
+
582
+        double *eprl   = new double[MAXLAYERS];
583
+        for (int ilay=1; ilay<=nlay; ++ilay) {
584
+            eprl[ilay-1] = Earth->GetLayerLowFreqPermitivity(ilay);
585
+        }
586
+
587
+        double *eprh   = new double[MAXLAYERS];
588
+        for (int ilay=1; ilay<=nlay; ++ilay) {
589
+            eprh[ilay-1] = Earth->GetLayerHighFreqPermitivity(ilay);
590
+        }
591
+
592
+        double *eprtau = new double[MAXLAYERS];
593
+        for (int ilay=1; ilay<=nlay; ++ilay) {
594
+            eprtau[ilay-1] = Earth->GetLayerTauPermitivity(ilay);
595
+        }
596
+
597
+        double *epralp = new double[MAXLAYERS];
598
+        for (int ilay=1; ilay<=nlay; ++ilay) {
599
+            epralp[ilay-1] = Earth->GetLayerBreathPermitivity(ilay);
600
+        }
601
+
602
+        // Freq stuff
603
+        double finit  = Dipole->GetFrequency(0); //(1000);   // Starting freq
604
+        double flimit = Dipole->GetFrequency(0); //(1000);   // max freq
605
+        double dlimit = Dipole->GetFrequency(0); //(1000);   // difusion limit
606
+        double lfinc(1);       // no. freq per decade
607
+
608
+        // tx location jtype != 4
609
+        double txx = Dipole->GetLocation(0); // (0.);
610
+        double txy = Dipole->GetLocation(1); // (0.);
611
+        double txz = Dipole->GetLocation(2); // (0.);
612
+
613
+        // rx position
614
+        // TODO, fix Fortran program to not waste this memory
615
+        // maybe
616
+        const int MAXREC = 15;
617
+        double *rxx = new double [MAXREC];
618
+        double *rxy = new double [MAXREC];
619
+        double *rxz = new double [MAXREC];
620
+
621
+        std::complex<double> *ex = new std::complex<double>[MAXREC];
622
+        std::complex<double> *ey = new std::complex<double>[MAXREC];
623
+        std::complex<double> *ez = new std::complex<double>[MAXREC];
624
+
625
+        std::complex<double> *hx = new std::complex<double>[MAXREC];
626
+        std::complex<double> *hy = new std::complex<double>[MAXREC];
627
+        std::complex<double> *hz = new std::complex<double>[MAXREC];
628
+
629
+        int nres2 = MAXREC;
630
+        int ii=0;
631
+
632
+        for (ii=0; ii<nres-MAXREC; ii+=MAXREC) {
633
+
634
+            for (int ir=0; ir<MAXREC; ++ir) {
635
+                //Vector3r pos = Receivers->GetLocation(ii+ir);
636
+                rxx[ir] = Receivers->GetLocation(ii+ir)[0];
637
+                rxy[ir] = Receivers->GetLocation(ii+ir)[1];
638
+                rxz[ir] = Receivers->GetLocation(ii+ir)[2];
639
+            }
640
+
641
+            em1dcall_(itype, ipol, nlay, nfreq, nfield, nres2, jtype,
642
+                  jgamma, acc, dep, sig, susl, sush, sustau, susalp,
643
+                  eprl, eprh, eprtau, epralp, finit, flimit, dlimit,
644
+                  lfinc, txx, txy, txz, rxx, rxy, rxz, ex, ey, ez,
645
+                  hx, hy, hz);
646
+
647
+            // Scale By Moment
648
+            for (int ir=0; ir<MAXREC; ++ir) {
649
+
650
+                ex[ir] *= Dipole->GetMoment();
651
+                ey[ir] *= Dipole->GetMoment();
652
+                ez[ir] *= Dipole->GetMoment();
653
+
654
+                hx[ir] *= Dipole->GetMoment();
655
+                hy[ir] *= Dipole->GetMoment();
656
+                hz[ir] *= Dipole->GetMoment();
657
+
658
+                // Append values instead of setting them
659
+                this->Receivers->AppendEfield(0, ii+ir, (Complex)(ex[ir]),
660
+                                                        (Complex)(ey[ir]),
661
+                                                        (Complex)(ez[ir]) );
662
+                this->Receivers->AppendHfield(0, ii+ir, (Complex)(hx[ir]),
663
+                                                        (Complex)(hy[ir]),
664
+                                                        (Complex)(hz[ir]) );
665
+            }
666
+        }
667
+
668
+        //ii += MAXREC;
669
+        nres2 = 0;
670
+        // Perform last positions
671
+        for (int ir=0; ir<nres-ii; ++ir) {
672
+            rxx[ir] = Receivers->GetLocation(ii+ir)[0];
673
+            rxy[ir] = Receivers->GetLocation(ii+ir)[1];
674
+            rxz[ir] = Receivers->GetLocation(ii+ir)[2];
675
+            ++nres2;
676
+        }
677
+
678
+        em1dcall_(itype, ipol, nlay, nfreq, nfield, nres2, jtype,
679
+              jgamma, acc, dep, sig, susl, sush, sustau, susalp,
680
+              eprl, eprh, eprtau, epralp, finit, flimit, dlimit,
681
+              lfinc, txx, txy, txz, rxx, rxy, rxz, ex, ey, ez,
682
+              hx, hy, hz);
683
+
684
+        // Scale By Moment
685
+        for (int ir=0; ir<nres-ii; ++ir) {
686
+
687
+            ex[ir] *= Dipole->GetMoment();
688
+            ey[ir] *= Dipole->GetMoment();
689
+            ez[ir] *= Dipole->GetMoment();
690
+
691
+            hx[ir] *= Dipole->GetMoment();
692
+            hy[ir] *= Dipole->GetMoment();
693
+            hz[ir] *= Dipole->GetMoment();
694
+
695
+            // Append values instead of setting them
696
+            this->Receivers->AppendEfield(0, ii+ir, (Complex)(ex[ir]),
697
+                                                    (Complex)(ey[ir]),
698
+                                                    (Complex)(ez[ir]) );
699
+            this->Receivers->AppendHfield(0, ii+ir, (Complex)(hx[ir]),
700
+                                                    (Complex)(hy[ir]),
701
+                                                    (Complex)(hz[ir]) );
702
+
703
+        }
704
+
705
+        delete [] sig;
706
+        delete [] dep;
707
+
708
+        //delete [] sus;
709
+        //delete [] epr;
710
+
711
+        delete [] susl;
712
+        delete [] sush;
713
+        delete [] susalp;
714
+        delete [] sustau;
715
+
716
+        delete [] eprl;
717
+        delete [] eprh;
718
+        delete [] epralp;
719
+        delete [] eprtau;
720
+
721
+        delete [] rxx;
722
+        delete [] rxy;
723
+        delete [] rxz;
724
+
725
+        delete [] ex;
726
+        delete [] ey;
727
+        delete [] ez;
728
+
729
+        delete [] hx;
730
+        delete [] hy;
731
+        delete [] hz;
732
+
733
+    }
734
+#endif
735
+
736
+
737
+    void EMEarth1D::SolveSingleTxRxPair (const int &irec, HankelTransform *Hankel, const Real &wavef, const int &ifreq,
738
+                   DipoleSource *tDipole) {
739
+        ++icalcinner;
740
+
741
+        Real rho = (Receivers->GetLocation(irec).head<2>() - tDipole->GetLocation().head<2>()).norm();
742
+
743
+        tDipole->SetKernels(ifreq, FieldsToCalculate, Receivers, irec, Earth);
744
+        Hankel->ComputeRelated( rho, tDipole->GetKernelManager() );
745
+        tDipole->UpdateFields( ifreq,  Hankel, wavef );
746
+    }
747
+
748
+    void EMEarth1D::SolveLaggedTxRxPair(const int &irec, FHTAnderson801* Hankel,
749
+                    const Real &wavef, const int &ifreq, PolygonalWireAntenna* antenna) {
750
+
751
+        antenna->ApproximateWithElectricDipoles(Receivers->GetLocation(irec));
752
+
753
+        // Determine the min and max arguments
754
+        Real rhomin = 1e9;
755
+        Real rhomax = 1e-9;
756
+        for (int idip=0; idip<antenna->GetNumberOfDipoles(); ++idip) {
757
+            auto tDipole = antenna->GetDipoleSource(idip);
758
+            Real rho = (Receivers->GetLocation(irec).head<2>() - tDipole->GetLocation().head<2>()).norm();
759
+            rhomin = std::min(rhomin, rho);
760
+            rhomax = std::max(rhomax, rho);
761
+        }
762
+        //std::cout << "rhomin\t" << rhomin << "\trhomax" << rhomax << std::endl;
763
+
764
+        // Determine number of lagged convolutions to do
765
+        // TODO, can Hankel2 adjust the lagg spacing safely?
766
+        int nlag = 1; // We need an extra for some reason for stability
767
+        Real lrho ( 1.01* rhomax );
768
+        while ( lrho > rhomin ) {
769
+            nlag += 1;
770
+            lrho *= Hankel->GetABSER();
771
+        }
772
+
773
+        //int nlag = rhomin
774
+        auto tDipole = antenna->GetDipoleSource(0);
775
+        tDipole->SetKernels(ifreq, FieldsToCalculate, Receivers, irec, Earth);
776
+
777
+        // Instead we should pass the antenna into this so that Hankel hass all the rho arguments...
778
+        Hankel->ComputeLaggedRelated( 1.01* rhomax, nlag, tDipole->GetKernelManager() );
779
+
780
+        //std::cout << Hankel->GetAnswer() << std::endl;
781
+        //std::cout << Hankel->GetArg() << std::endl;
782
+
783
+
784
+        // Sort the dipoles by rho
785
+
786
+        for (int idip=0; idip<antenna->GetNumberOfDipoles(); ++idip) {
787
+        //for (int idip=0; idip<1; ++idip) {
788
+            auto tDipole = antenna->GetDipoleSource(idip);
789
+            tDipole->SetKernels(ifreq, FieldsToCalculate, Receivers, irec, Earth);
790
+            // Pass Hankel2 a message here so it knows which one to return in Zgauss!
791
+            Real rho = (Receivers->GetLocation(irec).head<2>() - tDipole->GetLocation().head<2>()).norm();
792
+            //std::cout << " in Lagged " <<  rho << "\t" << rhomin << "\t" << rhomax << std::endl;
793
+            Hankel->SetLaggedArg( rho );
794
+            //std::cout << "out Lagged" << std::endl;
795
+            tDipole->UpdateFields( ifreq,  Hankel, wavef );
796
+        }
797
+        //std::cout << "Spline\n";
798
+        //std::cout << Receivers->GetHfield(0, irec) << std::endl;
799
+    }
800
+
801
+    //////////////////////////////////////////////////////////
802
+    // Thread safe OO Reimplimentation of KiHand's
803
+    // EM1DNEW.for programme
804
+    void EMEarth1D::MakeCalc3() {
805
+
806
+        if ( Dipole == nullptr ) throw NullDipoleSource();
807
+
808
+        if (Earth == nullptr) throw NullEarth();
809
+
810
+        if (Receivers == nullptr) throw NullReceivers();
811
+
812
+        #ifdef LEMMAUSEOMP
813
+        #pragma omp parallel
814
+        #endif
815
+        { // OpenMP Parallel Block
816
+
817
+            #ifdef LEMMAUSEOMP
818
+            int tid = omp_get_thread_num();
819
+            int nthreads = omp_get_num_threads();
820
+            #else
821
+            int tid=0;
822
+            int nthreads=1;
823
+            #endif
824
+
825
+            auto tDipole = Dipole->Clone();
826
+
827
+            std::shared_ptr<HankelTransform> Hankel;
828
+            switch (HankelType) {
829
+                case ANDERSON801:
830
+                    Hankel = FHTAnderson801::NewSP();
831
+                    break;
832
+                case CHAVE:
833
+                    Hankel = GQChave::NewSP();
834
+                    break;
835
+                case FHTKEY201:
836
+                    Hankel = FHTKey201::NewSP();
837
+                    break;
838
+                case FHTKEY101:
839
+                    Hankel = FHTKey101::NewSP();
840
+                    break;
841
+                case FHTKEY51:
842
+                    Hankel = FHTKey51::NewSP();
843
+                    break;
844
+                case QWEKEY:
845
+                    Hankel = QWEKey::NewSP();
846
+                    break;
847
+                default:
848
+                    std::cerr << "Hankel transform cannot be created\n";
849
+                    exit(EXIT_FAILURE);
850
+            }
851
+
852
+            if ( tDipole->GetNumberOfFrequencies() < Receivers->GetNumberOfPoints() ) {
853
+                for (int ifreq=0; ifreq<tDipole->GetNumberOfFrequencies(); ++ifreq) {
854
+                    // Propogation constant in free space being input to Hankel
855
+                    Real wavef   = tDipole->GetAngularFrequency(ifreq) * std::sqrt(MU0*EPSILON0);
856
+                    for (int irec=tid; irec<Receivers->GetNumberOfPoints(); irec+=nthreads) {
857
+                        SolveSingleTxRxPair(irec, Hankel.get(), wavef, ifreq, tDipole.get());
858
+                    }
859
+                }
860
+            } else {
861
+                for (int irec=0; irec<Receivers->GetNumberOfPoints(); ++irec) {
862
+                    for (int ifreq=tid; ifreq<tDipole->GetNumberOfFrequencies(); ifreq+=nthreads) {
863
+                        // Propogation constant in free space being input to Hankel
864
+                        Real wavef   = tDipole->GetAngularFrequency(ifreq) * std::sqrt(MU0*EPSILON0);
865
+                        SolveSingleTxRxPair(irec, Hankel.get(), wavef, ifreq, tDipole.get());
866
+                    }
867
+                }
868
+            }
869
+        } // OpenMP Parallel Block
870
+    }
871
+
872
+    NullReceivers::NullReceivers() :
873
+        runtime_error("nullptr RECEIVERS") {}
874
+
875
+    NullAntenna::NullAntenna() :
876
+        runtime_error("nullptr ANTENNA") {}
877
+
878
+    NullInstrument::NullInstrument(LemmaObject* ptr) :
879
+        runtime_error("nullptr INSTRUMENT") {
880
+        std::cout << "Thrown by instance of "
881
+                  << ptr->GetName() << std::endl;
882
+    }
883
+
884
+    DipoleSourceSpecifiedForWireAntennaCalc::
885
+        DipoleSourceSpecifiedForWireAntennaCalc() :
886
+        runtime_error("DIPOLE SOURCE SPECIFIED FOR WIRE ANTENNA CALC"){}
887
+
888
+} // end of Lemma Namespace

+ 1
- 1
vim/c.vim View File

@@ -17,7 +17,7 @@ syn keyword nspace Lemma YAML Eigen
17 17
 
18 18
 " Lemma types
19 19
 highlight leType ctermfg=Yellow guifg=Yellow
20
-syn keyword leType HankelTransform FHTAnderson801 FHTKey201 FHTKey101 FHTKey51 GQChave QWEKey KernelEM1D KernelEM1DSpec KernelEM1DBase KernelEM1DManager DipoleSource EarthModel LayeredEarth LayeredEarthEM TEMSurvey TEMSurveyLine TEMSurveyLineRecord TEMInductiveReceiver WireAntenna PolygonalWireAntenna TEMTransmitter TEMReceiver Instrument InstrumentTem LemmaObject FieldPoints DCIPElectrode TEMSurveyData TEMSurveyLineData TEMSurveyLineRecordData  ASCIIParser CubicSplineInterpolator RectilinearGrid GridReader RectilinearGridReader RectilinearGridVTKExporter Filter WindowFilter DEMParticle DEMGrain Data DataReader 
20
+syn keyword leType HankelTransform FHTAnderson801 FHTKey201 FHTKey101 FHTKey51 GQChave QWEKey KernelEM1D KernelEM1DSpec KernelEM1DBase KernelEM1DManager DipoleSource EarthModel LayeredEarth LayeredEarthEM TEMSurvey TEMSurveyLine TEMSurveyLineRecord TEMInductiveReceiver WireAntenna PolygonalWireAntenna TEMTransmitter TEMReceiver Instrument InstrumentTem LemmaObject FieldPoints DCIPElectrode TEMSurveyData TEMSurveyLineData TEMSurveyLineRecordData  ASCIIParser CubicSplineInterpolator RectilinearGrid GridReader RectilinearGridReader RectilinearGridVTKExporter Filter WindowFilter DEMParticle DEMGrain Data DataReader EMEarth1D 
21 21
 
22 22
 " Deprecated Lemma Types
23 23
 highlight dleType ctermfg=Blue guifg=Blue 

Loading…
Cancel
Save