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

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