Lemma is an Electromagnetics API
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

KernelEM1DReflSpec.cpp 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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. **/
  10. #include "KernelEM1DReflSpec.h"
  11. namespace Lemma {
  12. template<>
  13. void KernelEM1DReflSpec<TM, INAIR, INAIR>::ComputeReflectionCoeffs(const Real& lambda) {
  14. rams = lambda*lambda;
  15. u = (rams-kk.array()).sqrt(); // CRITICAL
  16. uk = u(0);
  17. um = u(0);
  18. Zyu(1) = -u(0)/yh(0);
  19. Zyi = u.array() / yh.array();
  20. Zyd.tail<1>() = Zyi.tail<1>();
  21. // Vectorise, performance benchmarks approx. the same as loop w gcc 9 -TI
  22. cf.segment(1,nlay-2) = (-2.*u.segment(1, nlay-2).array() * LayerThickness.segment(1, nlay-2).array()).exp();
  23. th.segment(1,nlay-2) = (1.-cf.segment(1, nlay-2).array()) / (1.+cf.segment(1, nlay-2).array());
  24. // for (int ilay=1; ilay<nlay-1; ++ilay) {
  25. // cf(ilay) = std::exp(-(Real)(2.)*u(ilay)*LayerThickness(ilay));
  26. // th(ilay) = ((Real)(1.)-cf(ilay)) / ((Real)(1.)+cf(ilay));
  27. // }
  28. // recursive, can't vectorize
  29. for (int N=nlay-2; N >= 1; --N) {
  30. Zyd(N) = Zyi(N)*(Zyd(N+1)+Zyi(N)*th(N)) / (Zyi(N)+Zyd(N+1)*th(N)) ;
  31. }
  32. //rtd(nlay-1) = 0;
  33. rtd(0) = (Zyu(1)+Zyd(1)) / (Zyu(1)-Zyd(1)) ;
  34. return;
  35. }
  36. template<>
  37. void KernelEM1DReflSpec<TE, INAIR, INAIR>::ComputeReflectionCoeffs(const Real& lambda) {
  38. rams = lambda*lambda;
  39. u = (rams-kk.array()).sqrt(); // CRITICAL
  40. uk = u(0);
  41. um = u(0);
  42. Zyu(1) = -u(0)/zh(0);
  43. Zyi = u.array() / zh.array();
  44. Zyd.tail<1>() = Zyi.tail<1>();
  45. // Vectorise, performance benchmarks approx. the same as loop w/ gcc 9 -TI
  46. cf.segment(1,nlay-2) = (-2.*u.segment(1, nlay-2).array() * LayerThickness.segment(1, nlay-2).array()).exp();
  47. th.segment(1,nlay-2) = (1.-cf.segment(1, nlay-2).array()) / (1.+cf.segment(1, nlay-2).array());
  48. // for (int ilay=1; ilay<nlay-1; ++ilay) {
  49. // cf(ilay) = std::exp(-(Real)(2.)*u(ilay)*LayerThickness(ilay));
  50. // th(ilay) = ((Real)(1.)-cf(ilay)) / ((Real)(1.)+cf(ilay));
  51. // }
  52. // recursive, can't vectorize
  53. for (int N=nlay-2; N >=1; --N) {
  54. Zyd(N) = Zyi(N)*(Zyd(N+1)+Zyi(N)*th(N)) / (Zyi(N)+Zyd(N+1)*th(N)) ;
  55. }
  56. //rtd(nlay-1) = 0;
  57. rtd(0) = (Zyu(1)+Zyd(1)) / (Zyu(1)-Zyd(1)) ;
  58. return;
  59. }
  60. template<>
  61. void KernelEM1DReflSpec<TM, INAIR, INGROUND>::ComputeReflectionCoeffs(const Real& lambda) {
  62. rams = lambda*lambda;
  63. u = (rams-kk.array()).sqrt();
  64. uk = u(0);
  65. um = u(layr);
  66. Zyu(1) = -u(0)/yh(0);
  67. Zyi = u.array() / yh.array();
  68. Zyd.tail<1>() = Zyi.tail<1>();
  69. for (int ilay=1; ilay<nlay-1; ++ilay) {
  70. cf(ilay) = std::exp(-(Real)(2.)*u(ilay)*LayerThickness(ilay));
  71. th(ilay) = ((Real)(1.)-cf(ilay)) / ((Real)(1.)+cf(ilay));
  72. }
  73. // Can't use blocks, b/c recursive
  74. for (int N=1; N<lays; ++N){
  75. Zyu(N+1)=Zyi(N)*(Zyu(N)-Zyi(N)*th(N)) /
  76. (Zyi(N)-Zyu(N)*th(N)) ;
  77. }
  78. int ne = nlay-2;
  79. for (int N=ne; N >=lays+1; --N) {
  80. Zyd(N) = Zyi(N)*(Zyd(N+1)+Zyi(N)*th(N)) /
  81. (Zyi(N)+Zyd(N+1)*th(N)) ;
  82. }
  83. rtd(nlay-1) = 0;
  84. rtd(0) = (Zyu(1)+Zyd(1)) / (Zyu(1)-Zyd(1)) ;
  85. int le = layr;
  86. if (le == nlay-1) --le;
  87. for (int N=1; N<=le; ++N) {
  88. rtd(N) = (Zyi(N)-Zyd(N+1)) / (Zyi(N)+Zyd(N+1)) ;
  89. }
  90. return;
  91. }
  92. template<>
  93. void KernelEM1DReflSpec<TE, INAIR, INGROUND>::ComputeReflectionCoeffs(const Real& lambda) {
  94. rams = lambda*lambda;
  95. u = (rams-kk.array()).sqrt();
  96. uk = u(0);
  97. um = u(layr);
  98. Zyu(1) = -u(0)/zh(0);
  99. Zyi = u.array() / zh.array();
  100. Zyd.tail<1>() = Zyi.tail<1>();
  101. for (int ilay=1; ilay<nlay-1; ++ilay) {
  102. cf(ilay) = std::exp(-(Real)(2.)*u(ilay)*LayerThickness(ilay));
  103. th(ilay) = ((Real)(1.)-cf(ilay)) / ((Real)(1.)+cf(ilay));
  104. }
  105. // Can't use blocks, b/c recursive
  106. for (int N=1; N<lays; ++N){
  107. Zyu(N+1)=Zyi(N)*(Zyu(N)-Zyi(N)*th(N)) /
  108. (Zyi(N)-Zyu(N)*th(N)) ;
  109. }
  110. int ne = nlay-2;
  111. for (int N=ne; N >=lays+1; --N) {
  112. Zyd(N) = Zyi(N)*(Zyd(N+1)+Zyi(N)*th(N)) /
  113. (Zyi(N)+Zyd(N+1)*th(N)) ;
  114. }
  115. rtd(nlay-1) = 0;
  116. rtd(0) = (Zyu(1)+Zyd(1)) / (Zyu(1)-Zyd(1)) ;
  117. int le = layr;
  118. if (le == nlay-1) --le;
  119. for (int N=1; N<=le; ++N) {
  120. rtd(N) = (Zyi(N)-Zyd(N+1)) / (Zyi(N)+Zyd(N+1)) ;
  121. }
  122. return;
  123. }
  124. template<>
  125. void KernelEM1DReflSpec<TM, INAIR, INAIR>::PreComputePotentialTerms( ) {
  126. relIud = 0;
  127. if (rx_z<= tx_z) relIud=1;
  128. relCon = rtd(0)*std::exp(u(0)*(rx_z+tx_z));
  129. Real adz = std::abs(rx_z - tx_z);
  130. relenukadz = std::exp(-uk*adz); // Singular source term
  131. }
  132. template<>
  133. void KernelEM1DReflSpec<TE, INAIR, INAIR>::PreComputePotentialTerms( ) {
  134. relIud = 0;
  135. if (rx_z<= tx_z) relIud=1;
  136. relCon = rtd(0)*std::exp(u(0)*(rx_z+tx_z));
  137. Real adz = std::abs(rx_z - tx_z);
  138. relenukadz = std::exp(-uk*adz); // Singular source term
  139. }
  140. template<>
  141. void KernelEM1DReflSpec<TM, INAIR, INGROUND>::PreComputePotentialTerms( ) {
  142. Complex dd = ((Real)(1.)+rtd(1)*cf(1));
  143. rel_a = ((Real)(1.) + rtd(0)) / dd;
  144. if (layr >= 2) {
  145. for (int n=2; n<=layr; ++n) {
  146. rel_a *= ((Real)(1.)+rtd(n-1));
  147. if (n < nlay-1) {
  148. rel_a /= ((Real)(1.)+rtd(n)*cf(n));
  149. }
  150. }
  151. }
  152. Complex p(0,0);
  153. for (int n=1; n<=layr; ++n) {
  154. Complex ut = u(0);
  155. if (n>1) {
  156. ut = u(n-1);
  157. }
  158. p += (u(n)-ut) * LayerDepth(n-1);
  159. }
  160. relexp_pbs1 = std::exp(uk*tx_z-um*rx_z+ p);
  161. if (layr < Earth->GetNumberOfLayers()-1) {
  162. relexp_pbs2 = std::exp(uk*tx_z-um*((Real)(2.)*LayerDepth(layr)-rx_z)+p);
  163. }
  164. }
  165. template<>
  166. void KernelEM1DReflSpec<TE, INAIR, INGROUND>::PreComputePotentialTerms( ) {
  167. Complex dd = ((Real)(1.)+rtd(1)*cf(1));
  168. rel_a = ((Real)(1.) + rtd(0)) / dd;
  169. if (layr >= 2) {
  170. for (int n=2; n<=layr; ++n) {
  171. rel_a *= ((Real)(1.)+rtd(n-1));
  172. if (n < nlay-1) {
  173. rel_a /= ((Real)(1.)+rtd(n)*cf(n));
  174. }
  175. }
  176. }
  177. Complex p(0,0);
  178. for (int n=1; n<=layr; ++n) {
  179. Complex ut = u(0);
  180. if (n>1) {
  181. ut = u(n-1);
  182. }
  183. p += (u(n)-ut) * LayerDepth(n-1);
  184. }
  185. relexp_pbs1 = std::exp(uk*tx_z-um*rx_z+ p);
  186. if (layr < Earth->GetNumberOfLayers()-1) {
  187. relexp_pbs2 = std::exp(uk*tx_z-um*((Real)(2.)*LayerDepth(layr)-rx_z)+p);
  188. }
  189. }
  190. } // ----- end of Lemma name -----