Main Lemma Repository

hankeltransformhankel2.h 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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 06/26/2009
  9. @version $Id: hankeltransformhankel2.h 201 2015-01-03 00:07:47Z tirons $
  10. **/
  11. #ifndef __HANKEL2_H
  12. #define __HANKEL2_H
  13. #include "hankeltransform.h"
  14. #include "kernelem1dbase.h"
  15. #include "kernelem1dspec.h"
  16. #include "CubicSplineInterpolator.h"
  17. namespace Lemma {
  18. // ==========================================================================
  19. // Class: Hankel2
  20. /** \brief Computes the Hankel transform of orders 0 and 1 using lagged
  21. and related convolutions.
  22. \details A rewrite of work by Anderson who wrote a FORTRAN program
  23. that he released while working at the USGS.
  24. The transform evaluates an integral of the form:
  25. \f[ \int_0^\infty K(\lambda) J_I (\lambda r) ~ d \lambda
  26. \f]
  27. Where \f$ K(\lambda) \f$ is some kernel function. The value
  28. \f$ J_I \f$ is the Bessel function of order
  29. \f$I, I \in \{0,1\} \f$
  30. The kernel function is unique for each source and is computed
  31. in the class CalculateKernel. The value \f$r\f$ is the radial
  32. distance away from the centre of the grid \f$ r=\sqrt{x^2 + y^2} \f$
  33. The Hankel transform is useful as it allows a double fourier
  34. transform to be written as a single integral:
  35. \f[ \mathop {\int \!\!\! \int}_{\!\!\!\!\!-\infty}^{\,\,\infty}
  36. F(k_x^2 + k_y^2)
  37. e^{\imath (k_x x + k_y y)} dk_x \, dk_y = 2 \pi
  38. \int_0^\infty K(\lambda) J_I (\lambda r) ~ d \lambda
  39. \f]
  40. This can only be done where there is radial symmetry. Hence
  41. its application to 1D solutions here.
  42. */
  43. // ==========================================================================
  44. class Hankel2 : public HankelTransform {
  45. friend std::ostream &operator<<(std::ostream &stream, const Hankel2 &ob);
  46. public:
  47. // ==================== LIFECYCLE ==============================
  48. /**
  49. * Returns pointer to new Hankel2. Location is
  50. * initialized to (0,0,0) type and polarization are
  51. * initialized to nonworking values that will throw
  52. * exceptions if used.
  53. */
  54. static Hankel2 *New();
  55. /**
  56. * @copybrief LemmaObject::Delete()
  57. * @copydetails LemmaObject::Delete()
  58. */
  59. void Delete();
  60. // ==================== OPERATORS ==============================
  61. // ==================== OPERATIONS ==============================
  62. /// Sets the number of convolutions
  63. void SetNumConv(const int &i);
  64. /// Computes the hankel transform with arguments
  65. /// @param rho [input] rho is the hankel transform argument
  66. /// @param ntol [input] ntol is
  67. /// @param tol [input] tol is
  68. void Compute(const Real &rho, const int& ntol, const Real &tol);
  69. /// Computes the related
  70. void ComputeRelated(const Real &rho, KernelEm1DBase* Kernel);
  71. /// Computes the related
  72. void ComputeRelated(const Real &rho, std::vector< KernelEm1DBase* > KernelVec);
  73. /// Computes the related
  74. void ComputeRelated(const Real &rho, KernelEM1DManager* Manager);
  75. /// Computes the related and lagged convolutions
  76. void ComputeLaggedRelated(const Real &rho, const int& nlag, KernelEM1DManager* Manager);
  77. // ==================== ACCESS ==============================
  78. /// Returns the answer
  79. Eigen::Matrix<Complex, Eigen::Dynamic, Eigen::Dynamic> GetAnswer();
  80. /// Returns the arguments for lagged convolutions
  81. VectorXr GetArg() {return Arg;};
  82. /// Returns the value of Abscissa stepping
  83. Real GetABSER( ) { return ABSER; };
  84. /// Sets the lagged kernel index so that the proper value is returned
  85. void SetLaggedArg(const Real& rho);
  86. // ==================== INQUIRY ==============================
  87. /// Calculates Hankel Transform using filtering.
  88. /// ikk: type of kernel depending on source and receiver couple
  89. /// imode: a switch for TE(0) and TM(1) mode
  90. /// itype: order of Bessel function
  91. /// rho is argument to integral
  92. /// wavef is the propogation constant of free space
  93. /// = omega * sqrt( EP*AMU ) amu = 4 pi e-7 ep = 8.85e-12
  94. Complex Zgauss(const int &ikk, const EMMODE &imode,
  95. const int &itype, const Real &rho,
  96. const Real &wavef, KernelEm1DBase *Kernel);
  97. protected:
  98. // ==================== LIFECYCLE ==============================
  99. /** A rewrite of Anderson's Pseudo-subroutine. */
  100. inline void StoreRetreive(const int &idx, const int &lag,
  101. Complex &Zsum, const int &irel, Complex &C, const Real& rho0) {
  102. int look = idx+lag;
  103. int iq = look/801;
  104. int ir = look%801;
  105. int iroll = iq*800;
  106. if(this->Key[ir] <= iroll) {
  107. this->Key[ir] = iroll + ir;
  108. ++this->NumFun;
  109. Manager->ComputeReflectionCoeffs(this->Lambda, idx, rho0);
  110. for (unsigned int ir2=0; ir2<this->kernelVec.size(); ++ir2) {
  111. this->Zwork(ir, ir2) = this->kernelVec[ir2]->RelBesselArg(this->Lambda);
  112. }
  113. }
  114. C = this->Zwork(ir, irel) * this->FilterWeights(this->BesselOrder, idx);
  115. Zsum += C;
  116. return;
  117. }
  118. /// Default protected constructor
  119. Hankel2(const std::string& name);
  120. /// Default protected destructor
  121. ~Hankel2();
  122. /**
  123. * @copybrief LemmaObject::Release()
  124. * @copydetails LemmaObject::Release()
  125. */
  126. void Release();
  127. // ==================== OPERATIONS ==============================
  128. void DeleteSplines();
  129. // ==================== DATA MEMBERS ==============================
  130. /// The hankel transform wavenumber embedded in the integral
  131. Real Lambda;
  132. /// Number of times a kernel was evaluated
  133. int NumFun;
  134. /// Number of lagged convolutions
  135. /// must be greater or equal to 1
  136. /// It is set automatically in the @see Compute function so
  137. /// that \f$ \rho \exp\left( -.1*(\mathtt{NumConv} -1) \right) \f$
  138. /// does not underflow the exponent range
  139. int NumConv;
  140. /// Number of related kernels
  141. int NumRel;
  142. /** Bessel transform order to use */
  143. int BesselOrder;
  144. /** Lag argument */
  145. int iLag;
  146. /* Should results be cached? Useful for repeated calculations of few receiver points */
  147. // turned out to have only marginal benefits in best case, and awful consequences in many
  148. //bool cacheResults;
  149. /** Related Kernel Manager */
  150. KernelEM1DManager* Manager;
  151. /// Used as base for filter abscissa generation
  152. static const Real ABSCISSA;
  153. /// Also used in abscissa generation \f$ ABSE = \exp{.1} \f$
  154. static const Real ABSE;
  155. /// Also used in abscissa generation \f$ ABSER = 1 / \exp{.1} \f$
  156. static const Real ABSER;
  157. /// Counter for calculated
  158. int icount;
  159. /// Kernel Calculator
  160. std::vector <KernelEm1DBase*> kernelVec;
  161. /// Spines for lagged convolutions (real part)
  162. std::vector <CubicSplineInterpolator*> splineVecReal;
  163. /// Spines for lagged convolutions (imaginary part)
  164. std::vector <CubicSplineInterpolator*> splineVecImag;
  165. /// Key used internally
  166. Eigen::Matrix<int, 801, 1> Key;
  167. //int Key[801];
  168. //Eigen::Matrix<int, Eigen::Dynamic, 1> Key;
  169. /// Filter weight coefficients. Set for either \f$J_0\f$ or \f$J_1\f$
  170. /// internally by protected function SetFilterWeights.
  171. /// Fixed sized will yield better performance. (not necessarily)
  172. //Eigen::Matrix<Real, 801, 1> FilterWeights;
  173. static const Eigen::Matrix<Real, 2, 801> FilterWeights;
  174. //static const Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic> FilterWeights;
  175. /// Zwork from Anderson
  176. Eigen::Matrix<Complex, 801, Eigen::Dynamic> Zwork;
  177. //Eigen::Matrix<Complex, Eigen::Dynamic, Eigen::Dynamic> Zwork;
  178. /// Holds answer, dimensions are NumConv, and NumberRelated.
  179. Eigen::Matrix<Complex, Eigen::Dynamic, Eigen::Dynamic> Zans;
  180. /// Holds the arguments for lagged convolutions
  181. VectorXr Arg;
  182. }; // ----- end of class HankelTransform -----
  183. }
  184. #endif // __HANKEL2_h