Lemma is an Electromagnetics API
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

kernelem1dreflspec.h 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /* This file is part of Lemma, a geophysical modelling and inversion API */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /**
  6. @file
  7. @author Trevor Irons
  8. @date 05/18/2012
  9. @version $Id: kernelem1dreflspec.h 123 2014-02-05 23:47:20Z tirons $
  10. **/
  11. #ifndef KERNELEM1DREFLSPEC_INC
  12. #define KERNELEM1DREFLSPEC_INC
  13. #include "dipolesource.h"
  14. #include "kernelem1dreflbase.h"
  15. #include "layeredearthem.h"
  16. // #include<unordered_map> // for caching results
  17. namespace Lemma {
  18. // forward declare
  19. //struct cache;
  20. // Simple container to hold reflection results
  21. struct cache {
  22. Real rho0;
  23. Real lambda[805];
  24. Real rams[805];
  25. Complex uk[805];
  26. Complex um[805];
  27. Real zh0i[805];
  28. VectorXcr Rtd[805];
  29. VectorXcr Rtu[805];
  30. VectorXcr u[805];
  31. VectorXcr cf[805];
  32. VectorXcr kk[805];
  33. const Real epsilon;
  34. //bool nc;
  35. cache( ) : epsilon (std::numeric_limits<Real>::epsilon() ) { // TODO reset to precision of Real
  36. //Rtd = VectorXcr::Zero(805);
  37. //Rtu = VectorXcr::Zero(805);
  38. }
  39. };
  40. // forward declaration for friend
  41. template<EMMODE Mode, int Ikernel, DIPOLE_LOCATION Isource, DIPOLE_LOCATION Irecv>
  42. class KernelEm1DSpec;
  43. // ===================================================================
  44. // Class: KernelEM1DReflSpec
  45. /**
  46. @class
  47. \brief Specialized version of KernelEM1DReflBase
  48. \details Through use of template specialisations, this KernelEm1D
  49. class delivers much better performance.
  50. */
  51. // ===================================================================
  52. template<EMMODE Mode, DIPOLE_LOCATION Isource, DIPOLE_LOCATION Irecv>
  53. class KernelEM1DReflSpec : public KernelEM1DReflBase {
  54. public:
  55. template<EMMODE Mode2, int Ikernel2, DIPOLE_LOCATION Isource2, DIPOLE_LOCATION Irecv2>
  56. friend class KernelEm1DSpec;
  57. friend class KernelEM1DManager;
  58. // ==================== LIFECYCLE =======================
  59. static KernelEM1DReflSpec* New() {
  60. KernelEM1DReflSpec<Mode, Isource, Irecv>* Obj =
  61. new KernelEM1DReflSpec<Mode, Isource, Irecv>("KernelEM1DReflSpec<>");
  62. Obj->AttachTo(Obj);
  63. return Obj;
  64. }
  65. void Delete() {
  66. this->DetachFrom(this);
  67. }
  68. // ==================== OPERATORS =======================
  69. // ==================== OPERATIONS =======================
  70. // ==================== ACCESS =======================
  71. // ==================== INQUIRY =======================
  72. protected:
  73. // ==================== LIFECYCLE =======================
  74. /// Default protected constructor.
  75. KernelEM1DReflSpec (const std::string& name) : KernelEM1DReflBase(name)
  76. {
  77. }
  78. /// Default protected constructor.
  79. ~KernelEM1DReflSpec () {
  80. if (this->NumberOfReferences > 0)
  81. throw DeleteObjectWithReferences( this );
  82. }
  83. void Release() {
  84. delete this;
  85. }
  86. // ==================== OPERATIONS =======================
  87. /** Computes reflection coefficients. Depending on the
  88. * specialisation, this will either be TM or TE mode.
  89. */
  90. void ComputeReflectionCoeffs(const Real &lambda);
  91. /* Computes reflection coefficients. Depending on the
  92. * specialisation, this will either be TM or TE mode. This method
  93. * stores previous results in a struct. For a given index, and
  94. * lambda, the result will be the same. Turned out to be of limited utility.
  95. */
  96. //void ComputeReflectionCoeffs(const Real &lambda, const int& idx);
  97. /** Precomputes expensive calculations that are reused by insances
  98. * of KernelEM1DSpec in the calculation of Related potentials. This
  99. * method is specialised based on template parameters
  100. */
  101. void PreComputePotentialTerms();
  102. /*
  103. * Sets the cache in CACHE to use. Somewhat expensive, avoid calling in tight loops
  104. */
  105. //void SetTCache(const Real& rho0);
  106. // ==================== DATA MEMBERS =========================
  107. private:
  108. //** Storage container for reused results */
  109. //static std::unordered_map<Real, cache> CACHE;
  110. //** Currenly used cache */
  111. //cache* tcache;
  112. //#pragma omp threadprivate(tcache)
  113. }; // ----- end of class KernelEM1DReflSpec -----
  114. //template<EMMODE Mode, DIPOLE_LOCATION Isource, DIPOLE_LOCATION Irecv>
  115. //std::unordered_map<Real, cache> KernelEM1DReflSpec<Mode, Isource, Irecv>::CACHE;
  116. //template<EMMODE Mode, DIPOLE_LOCATION Isource, DIPOLE_LOCATION Irecv>
  117. //cache* KernelEM1DReflSpec<Mode, Isource, Irecv>::tcache;
  118. ///////////////////////////////////////////////
  119. // Declarations of specialisations
  120. template<>
  121. void KernelEM1DReflSpec<TM, INAIR, INAIR>::ComputeReflectionCoeffs(const Real& lambda);
  122. template<>
  123. void KernelEM1DReflSpec<TE, INAIR, INAIR>::ComputeReflectionCoeffs(const Real& lambda);
  124. template<>
  125. void KernelEM1DReflSpec<TM, INAIR, INGROUND>::ComputeReflectionCoeffs(const Real& lambda);
  126. template<>
  127. void KernelEM1DReflSpec<TE, INAIR, INGROUND>::ComputeReflectionCoeffs(const Real& lambda);
  128. template<>
  129. void KernelEM1DReflSpec<TM, INAIR, INAIR>::PreComputePotentialTerms( );
  130. template<>
  131. void KernelEM1DReflSpec<TE, INAIR, INAIR>::PreComputePotentialTerms( );
  132. template<>
  133. void KernelEM1DReflSpec<TM, INAIR, INGROUND>::PreComputePotentialTerms( );
  134. template<>
  135. void KernelEM1DReflSpec<TE, INAIR, INGROUND>::PreComputePotentialTerms( );
  136. ///////////////////////////////////////////////
  137. // Default mode definitions
  138. /*
  139. template<EMMODE Mode, DIPOLE_LOCATION Isource, DIPOLE_LOCATION Irecv>
  140. void KernelEM1DReflSpec<Mode, Isource, Irecv>::SetTCache(const Real& rho0) {
  141. #ifdef LEMMAUSEOMP
  142. #pragma omp critical
  143. #endif
  144. {
  145. this->tcache = &this->CACHE[rho0];
  146. }
  147. }
  148. */
  149. /*
  150. template<EMMODE Mode, DIPOLE_LOCATION Isource, DIPOLE_LOCATION Irecv>
  151. void KernelEM1DReflSpec<Mode, Isource, Irecv>::ComputeReflectionCoeffs(const Real& lambda, const int& idx) {
  152. if ( (std::abs(this->tcache->lambda[idx]-lambda) <= this->tcache->epsilon) &&
  153. this->tcache->u[idx].size() > 0 && std::abs(this->kk(0) - this->tcache->kk[idx](0)) <= this->tcache->epsilon ) {
  154. //std::cout << "USING CACHED RESULTS !!!!!!" << std::endl;
  155. // load all the values we need
  156. this->u = this->tcache->u[idx];
  157. this->rams = this->tcache->rams[idx];
  158. this->cf = this->tcache->cf[idx];
  159. //this->kk = this->tcache->kk[idx];
  160. this->uk = this->tcache->uk[idx];
  161. this->um = this->tcache->um[idx];
  162. this->rtd = this->tcache->Rtd[idx];
  163. this->rtu = this->tcache->Rtu[idx];
  164. } else { // else do the work
  165. }
  166. ComputeReflectionCoeffs(lambda);
  167. //#pragma omp critical
  168. //{
  169. //std::cout << idx << "\t" << lambda << "\t" << rtd.transpose() << std::endl;
  170. //}
  171. // store the results
  172. this->tcache->u[idx] = this->u;
  173. this->tcache->cf[idx] = this->cf;
  174. this->tcache->kk[idx] = this->kk;
  175. this->tcache->uk[idx] = this->uk;
  176. this->tcache->um[idx] = this->um;
  177. this->tcache->Rtd[idx] = this->rtd;
  178. this->tcache->Rtu[idx] = this->rtu;
  179. this->tcache->zh0i[idx] = std::imag(this->zh[0]);
  180. this->tcache->lambda[idx] = lambda;
  181. this->tcache->rams[idx] = rams;
  182. }
  183. return;
  184. }
  185. */
  186. template<EMMODE Mode, DIPOLE_LOCATION Isource, DIPOLE_LOCATION Irecv>
  187. void KernelEM1DReflSpec<Mode, Isource, Irecv>::ComputeReflectionCoeffs(const Real& lambda) {
  188. static bool called = false;
  189. if (!called) {
  190. std::cout << "unspecialised Reflection function KernelEM1DReflSpec<"
  191. << Mode << ", " << Isource << ", "
  192. << Irecv << " >::ComputeReflectionCoeffs( const Real& lambda ) --> SLOW PERFORMANCE EXPECTED\n";
  193. called = true;
  194. }
  195. rams = lambda*lambda;
  196. //////////////////////////////////////////
  197. // Compute TEM stuff
  198. // This call to sqrt takes ~ 15% of execution time
  199. u = (rams-kk.array()).sqrt();
  200. uk = u(lays);
  201. um = u(layr);
  202. switch (Mode) {
  203. // TM mode
  204. case (TM):
  205. Zyu(1) = -u(0)/yh(0);
  206. Zyi = u.array() / yh.array();
  207. break;
  208. // TE mode
  209. case (TE):
  210. Zyu(1) = -u(0)/zh(0);
  211. Zyi = u.array() / zh.array();
  212. break;
  213. default:
  214. throw 11; //IllegalMode(this);
  215. }
  216. Zyd.tail<1>() = Zyi.tail<1>();
  217. for (int ilay=1; ilay<nlay-1; ++ilay) {
  218. cf(ilay) =
  219. std::exp(-(Real)(2.)*u(ilay)*LayerThickness(ilay));
  220. th(ilay) = ((Real)(1.)-cf(ilay)) / ((Real)(1.)+cf(ilay));
  221. }
  222. // Can't use blocks, b/c recursive
  223. for (int N=1; N<lays; ++N){
  224. Zyu(N+1)=Zyi(N)*(Zyu(N)-Zyi(N)*th(N)) /
  225. (Zyi(N)-Zyu(N)*th(N)) ;
  226. }
  227. int ne = nlay-2;
  228. for (int N=ne; N >=lays+1; --N) {
  229. Zyd(N) = Zyi(N)*(Zyd(N+1)+Zyi(N)*th(N)) /
  230. (Zyi(N)+Zyd(N+1)*th(N)) ;
  231. }
  232. rtd(nlay-1) = 0;
  233. if (layr < lays) {
  234. // Receiver above source layer
  235. int ls = layr;
  236. if (ls == 0) {
  237. ls = layr+1;
  238. }
  239. for (int N=ls; N<=lays; ++N) {
  240. rtu(N)= (Zyi(N)+Zyu(N)) /
  241. (Zyi(N)-Zyu(N)) ;
  242. }
  243. if (lays < nlay-1) {
  244. rtd(lays) = (Zyi(lays)-Zyd(lays+1)) /
  245. (Zyi(lays)+Zyd(lays+1)) ;
  246. }
  247. } else {
  248. // RECEIVER IN OR BELOW THE SOURCE LAYER
  249. if (lays == layr) { // Rx In source Layer
  250. if (layr == 0) {
  251. rtd(0) = (Zyu(1)+Zyd(1)) /
  252. (Zyu(1)-Zyd(1)) ;
  253. } else if (layr == nlay-1) {
  254. rtu(nlay-1) = (Zyi(nlay-1)+Zyu(nlay-1)) /
  255. (Zyi(nlay-1)-Zyu(nlay-1)) ;
  256. } else {
  257. rtu(layr) = (Zyi(layr)+Zyu(layr)) /
  258. (Zyi(layr)-Zyu(layr)) ;
  259. rtd(layr) = (Zyi(layr)-Zyd(layr+1)) /
  260. (Zyi(layr)+Zyd(layr+1)) ;
  261. }
  262. } else { // receiver below source layer
  263. if (lays == 0) {
  264. rtd(0) = (Zyu(1)+Zyd(1)) /
  265. (Zyu(1)-Zyd(1)) ;
  266. } else {
  267. rtu(lays) = (Zyi(lays)+Zyu(lays)) /
  268. (Zyi(lays)-Zyu(lays)) ;
  269. }
  270. int le = layr;
  271. if (le == nlay-1) --le;
  272. int ls = lays;
  273. if (lays == 0 ) ++ls;
  274. // TODO use blocks to vectorize maybe?
  275. // This works but gives same to slightly worse
  276. // performance as loop.
  277. // int nn = le-ls+1;
  278. // rtd.segment(ls, nn) =
  279. // (Zyi.segment(ls , nn).array() -
  280. // Zyd.segment(ls+1, nn).array()).array() /
  281. // (Zyi.segment(ls , nn).array() +
  282. // Zyd.segment(ls+1, nn).array()).array() ;
  283. for (int N=ls; N<=le; ++N) {
  284. rtd(N) = (Zyi(N)-Zyd(N+1)) /
  285. (Zyi(N)+Zyd(N+1)) ;
  286. }
  287. }
  288. } // End in or below source layer
  289. return;
  290. }
  291. template<EMMODE Mode, DIPOLE_LOCATION Isource, DIPOLE_LOCATION Irecv>
  292. void KernelEM1DReflSpec<Mode, Isource, Irecv>::PreComputePotentialTerms( ) {
  293. static bool called = false;
  294. if (!called) {
  295. std::cerr << "unspecialised function KernelEM1DReflSpec<"
  296. << Mode << ", " << Isource << ", "
  297. << Irecv << " >::PreComputePotentialTerms\n";
  298. called = true;
  299. }
  300. }
  301. } // ----- end of Lemma name -----
  302. #endif // ----- #ifndef KERNELEM1DREFLSPEC_INC -----