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
 # Lemma Configuration
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
 # Add the c++11 flag 
174
 # Add the c++11 flag 
167
 # TODO add compiler specific instructions
175
 # TODO add compiler specific instructions

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

11
 # Linking
11
 # Linking
12
 target_link_libraries(fdem1d "lemmacore")
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
 # Testing
19
 # Testing
15
 if (LEMMA_ENABLE_TESTING)
20
 if (LEMMA_ENABLE_TESTING)
16
 	add_subdirectory(testing)
21
 	add_subdirectory(testing)

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

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

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

30
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
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
 using namespace Lemma;
35
 using namespace Lemma;
39
 
36
 
40
 int main() {
37
 int main() {
41
 
38
 
42
 	// Test with a single dipole
39
 	// Test with a single dipole
43
-	DipoleSource *dipole = DipoleSource::New();
40
+	auto dipole = DipoleSource::NewSP();
44
 		dipole->SetType(GROUNDEDELECTRICDIPOLE);
41
 		dipole->SetType(GROUNDEDELECTRICDIPOLE);
45
 		dipole->SetPolarisation(XPOLARISATION);
42
 		dipole->SetPolarisation(XPOLARISATION);
46
 		dipole->SetNumberOfFrequencies(1);
43
 		dipole->SetNumberOfFrequencies(1);
57
 	VectorXr  thick(1);
54
 	VectorXr  thick(1);
58
 		thick << 10;//, 10, 10;
55
 		thick << 10;//, 10, 10;
59
 
56
 
60
-	LayeredEarthEM *earth = LayeredEarthEM::New();
57
+	auto earth = LayeredEarthEM::NewSP();
61
         earth->SetNumberOfLayers(2);
58
         earth->SetNumberOfLayers(2);
62
 		earth->SetLayerConductivity(sigma);
59
 		earth->SetLayerConductivity(sigma);
63
 		//earth->SetLayerThickness(thick);
60
 		//earth->SetLayerThickness(thick);
64
 
61
 
65
 	// Receivers
62
 	// Receivers
66
-	ReceiverPoints *receivers = ReceiverPoints::New();
63
+	auto receivers = FieldPoints::NewSP();
67
 		Vector3r loc;
64
 		Vector3r loc;
68
 		//Real ox = -5.1456;
65
 		//Real ox = -5.1456;
69
 		//Real oy =  2.2350;
66
 		//Real oy =  2.2350;
73
 		Real dz = 2.6;
70
 		Real dz = 2.6;
74
 		int  nz = 1;
71
 		int  nz = 1;
75
 
72
 
76
-		receivers->SetNumberOfReceivers(nz);
73
+		receivers->SetNumberOfPoints(nz);
77
 		int ir = 0;
74
 		int ir = 0;
78
 		for (int iz=0; iz<nz; ++iz) {
75
 		for (int iz=0; iz<nz; ++iz) {
79
 			loc << ox, oy, depth;
76
 			loc << ox, oy, depth;
83
 		}
80
 		}
84
 	//receivers->SetLocation(1, ox, oy, depth);
81
 	//receivers->SetLocation(1, ox, oy, depth);
85
 
82
 
86
-	EMEarth1D *EmEarth = EMEarth1D::New();
83
+    auto EmEarth = EMEarth1D::NewSP();
87
         //EmEarth->SetHankelTransformMethod(DIGITALFILTERING);
84
         //EmEarth->SetHankelTransformMethod(DIGITALFILTERING);
88
         EmEarth->SetFieldsToCalculate(BOTH); // Fortran needs this
85
         EmEarth->SetFieldsToCalculate(BOTH); // Fortran needs this
89
 		EmEarth->AttachDipoleSource(dipole);
86
 		EmEarth->AttachDipoleSource(dipole);
90
 		EmEarth->AttachLayeredEarthEM(earth);
87
 		EmEarth->AttachLayeredEarthEM(earth);
91
-		EmEarth->AttachReceiverPoints(receivers);
88
+		EmEarth->AttachFieldPoints(receivers);
92
 
89
 
93
         //dipole->SetType(ELECTRICDIPOLE);
90
         //dipole->SetType(ELECTRICDIPOLE);
94
 //         receivers->SetNumberOfReceivers(1);
91
 //         receivers->SetNumberOfReceivers(1);
105
 	receivers->ClearFields();
102
 	receivers->ClearFields();
106
 
103
 
107
     // swap tx rx posigion
104
     // swap tx rx posigion
105
+    /*
108
     receivers->SetLocation(0, dipole->GetLocation());
106
     receivers->SetLocation(0, dipole->GetLocation());
109
     dipole->SetLocation(loc);
107
     dipole->SetLocation(loc);
110
 	EmEarth->MakeCalc3();
108
 	EmEarth->MakeCalc3();
111
 	std::cout << receivers->GetEfield(0,0) << std::endl;
109
 	std::cout << receivers->GetEfield(0,0) << std::endl;
112
-
113
 	receivers->ClearFields();
110
 	receivers->ClearFields();
111
+    */
112
+
114
  #ifdef KIHALEE_EM1D
113
  #ifdef KIHALEE_EM1D
115
-// 	//std::cout << "\nFORTRAN\n";
114
+    std::cout << "\nFORTRAN\n";
116
  	EmEarth->MakeCalc();
115
  	EmEarth->MakeCalc();
117
 // 	std::cout << receivers->GetHfield(0,0) << std::endl;
116
 // 	std::cout << receivers->GetHfield(0,0) << std::endl;
118
  	std::cout << receivers->GetEfield(0,0) << std::endl;
117
  	std::cout << receivers->GetEfield(0,0) << std::endl;
119
  #endif
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
 
93
 
94
             /// Calculates the field(s) due to an ungrounded dipole source
94
             /// Calculates the field(s) due to an ungrounded dipole source
95
             /// Calls FORTRAN library em1d (em1dnew.for)
95
             /// Calls FORTRAN library em1d (em1dnew.for)
96
-#ifdef COMPILE_FORTRAN
96
+#ifdef KIHALEE_EM1D
97
             void MakeCalc();
97
             void MakeCalc();
98
 #endif
98
 #endif
99
 
99
 

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

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

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

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
 
17
 
18
 " Lemma types
18
 " Lemma types
19
 highlight leType ctermfg=Yellow guifg=Yellow
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
 " Deprecated Lemma Types
22
 " Deprecated Lemma Types
23
 highlight dleType ctermfg=Blue guifg=Blue 
23
 highlight dleType ctermfg=Blue guifg=Blue 

Loading…
Cancel
Save