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

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