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.

DigitalFilterIntegratorAnderson.cpp 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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 02/15/2011
  9. @version $Id: digitalfilterintegrator.cpp 87 2013-09-05 22:44:05Z tirons $
  10. **/
  11. #include "DigitalFilterIntegratorAnderson.h"
  12. namespace Lemma {
  13. // Specialisations to templated class are found here. This means that
  14. // DigitalFilterIntegratorAnderson is not strictly templated, and must be linked
  15. // with lemma for functionality.
  16. template < >
  17. inline Complex DigitalFilterIntegratorAnderson<Complex>::AbsMax(const Complex& C,
  18. const Complex& Cmax) {
  19. return Complex(std::max(std::abs(real(C)), std::real(Cmax)),
  20. std::max(std::abs(imag(C)), std::imag(Cmax)) );
  21. }
  22. template < >
  23. Real DigitalFilterIntegratorAnderson<Real>::AbsMax(const Real& C,
  24. const Real& Cmax) {
  25. return std::max(C, Cmax);
  26. }
  27. ///////////////////////////////////////////
  28. // Computes the transform y
  29. template < >
  30. void DigitalFilterIntegratorAnderson<Real>::Compute(const Real& rho,
  31. const int& ntol, const Real& tol) {
  32. Real y1 = this->ABSCISSA/rho;
  33. this->Key.setZero();
  34. // Check to make sure everything is set
  35. if (rho<=0) {
  36. throw std::runtime_error("In DigitalFilterIntegratorAnderson Argument rho < 0.");
  37. }
  38. if (this->NumConv<1) {
  39. throw std::runtime_error("In DigitalFilterIntegratorAnderson NumConv is less than 1.");
  40. }
  41. if (this->IntKernel == NULL) {
  42. throw std::runtime_error("In DigitalFilterIntegratorAnderson Unset Kernel Calculator");
  43. }
  44. Arg = VectorXr::Zero(this->NumConv);
  45. Real y = std::pow(rho*ABSER, this->NumConv-1);
  46. if (y <= 0) {
  47. std::cerr << "Exponent Underflow Error";
  48. throw std::underflow_error("Exponent underflow");
  49. }
  50. this->Work.resize(Eigen::NoChange, this->IntKernel->GetNumRel());
  51. // Main Loop
  52. int itol = 0;
  53. int none = 0;
  54. this->NumFun = 0;
  55. int idx = 0;
  56. int istore = 0;
  57. Real Sum(0.);
  58. Real Cmax(0.);
  59. Real C(0.);
  60. Ans.resize(this->NumConv, this->IntKernel->GetNumRel());
  61. Ans.setZero();
  62. // 1010 Loop
  63. for (int ilag=0; ilag < this->NumConv; ++ilag) {
  64. istore = this->NumConv - 1 - ilag;
  65. if (ilag > 0) y1 *= ABSE;
  66. Arg(istore) = ABSCISSA/y1;
  67. // 1000 Loop
  68. for (int irel=0; irel < this->IntKernel->GetNumRel(); ++irel) {
  69. //this->SetBesselOrder(this->Ckernel->GetBesselOrder(irel));
  70. none = 0;
  71. itol = ntol;
  72. Sum = Real(0);
  73. Cmax = Real(0);
  74. y = y1;
  75. // Begin right side convolution at weight 298
  76. // counting from 0
  77. idx = ilow;
  78. y *= ABSE;
  79. // Code Block 20 in Anderson
  80. do {
  81. this->StoreRetreive(idx, ilag, y, Sum, irel, C);
  82. Cmax = AbsMax(C, Cmax);
  83. ++idx;
  84. y *= ABSE;
  85. } while (idx <= ihi);
  86. //if (real(Cmax) == 0 && imag(Cmax) == 0) none = 1;
  87. if (Cmax == Real(0)) none = 1;
  88. Cmax *= tol;
  89. // Code Block 30 in Anderson
  90. do {
  91. this->StoreRetreive(idx, ilag, y, Sum, irel, C);
  92. if (std::abs(C) <= Cmax) {
  93. --itol;
  94. if (itol < 0 || idx > FilterWeights.size()-1) break;
  95. } else {
  96. itol = ntol;
  97. }
  98. ++idx;
  99. y *= ABSE;
  100. } while (idx < FilterWeights.size());
  101. itol = ntol;
  102. y = y1;
  103. // Code Block 60 in Anderson
  104. idx = ilow-1;
  105. do {
  106. this->StoreRetreive(idx, ilag, y, Sum, irel, C);
  107. if (std::abs(C) <= Cmax && none == 0) {
  108. --itol;
  109. if (itol < 0 || idx < 0) break;
  110. } else {
  111. itol = ntol;
  112. }
  113. --idx;
  114. y *= ABSER;
  115. } while (idx>=0);
  116. Ans(istore, irel) = Sum/Arg(istore);
  117. } // End of 1000 loop
  118. } // End of 1010 loop
  119. }
  120. template < >
  121. void DigitalFilterIntegratorAnderson<Complex>::Compute(const Real &rho,
  122. const int& ntol, const Real &tol) {
  123. Real y1 = this->ABSCISSA/rho;
  124. this->Key.setZero();
  125. // Check to make sure everything is set
  126. if (rho<=0) {
  127. throw std::runtime_error("In DigitalFilterIntegratorAnderson Argument rho < 0.");
  128. }
  129. if (this->NumConv<1) {
  130. throw std::runtime_error("In DigitalFilterIntegratorAnderson NumConv is less than 1.");
  131. }
  132. if (this->IntKernel == NULL) {
  133. throw std::runtime_error("In DigitalFilterIntegratorAnderson Unset Kernel Calculator");
  134. }
  135. Arg = VectorXr::Zero(this->NumConv);
  136. Real y = std::pow(rho*ABSER, this->NumConv-1);
  137. if (y <= 0) {
  138. std::cerr << "Exponent Underflow Error";
  139. throw std::underflow_error("Exponent underflow");
  140. }
  141. this->Work.resize(Eigen::NoChange, this->IntKernel->GetNumRel());
  142. // Main Loop
  143. int itol = 0;
  144. int none = 0;
  145. this->NumFun = 0;
  146. int idx = 0;
  147. int istore = 0;
  148. Complex Zsum(0.);
  149. Complex Cmax(0.);
  150. Complex C(0.);
  151. Ans.resize(this->NumConv, this->IntKernel->GetNumRel());
  152. Ans.setZero();
  153. // 1010 Loop
  154. for (int ilag=0; ilag < this->NumConv; ++ilag) {
  155. istore = this->NumConv - 1 - ilag;
  156. if (ilag > 0) y1 *= ABSE;
  157. Arg(istore) = ABSCISSA/y1;
  158. // 1000 Loop
  159. for (int irel=0; irel < this->IntKernel->GetNumRel(); ++irel) {
  160. //this->SetBesselOrder(this->Ckernel->GetBesselOrder(irel));
  161. none = 0;
  162. itol = ntol;
  163. Zsum = Complex(0);
  164. Cmax = Complex(0);
  165. y = y1;
  166. // Begin right side convolution at weight 298
  167. // counting from 0
  168. idx = ilow;
  169. y *= ABSE;
  170. // Code Block 20 in Anderson
  171. do {
  172. this->StoreRetreive(idx, ilag, y, Zsum, irel, C);
  173. Cmax = AbsMax(C, Cmax);
  174. ++idx;
  175. y *= ABSE;
  176. } while (idx <= ihi);
  177. //if (real(Cmax) == 0 && imag(Cmax) == 0) none = 1;
  178. if (Cmax == Complex(0)) none = 1;
  179. Cmax *= tol;
  180. // Code Block 30 in Anderson
  181. do {
  182. this->StoreRetreive(idx, ilag, y, Zsum, irel, C);
  183. if ( std::abs(real(C)) <= real(Cmax) &&
  184. std::abs(imag(C)) <= imag(Cmax) ) {
  185. --itol;
  186. if (itol < 0 || idx > FilterWeights.size()-1) break;
  187. } else {
  188. itol = ntol;
  189. }
  190. ++idx;
  191. y *= ABSE;
  192. } while (idx < FilterWeights.size());
  193. itol = ntol;
  194. y = y1;
  195. // Code Block 60 in Anderson
  196. idx = ilow-1;
  197. do {
  198. this->StoreRetreive(idx, ilag, y, Zsum, irel, C);
  199. if ( std::abs(real(C)) <= real(Cmax) &&
  200. std::abs(imag(C)) <= imag(Cmax) &&
  201. none == 0 ) {
  202. --itol;
  203. if (itol < 0 || idx < 0) break;
  204. } else {
  205. itol = ntol;
  206. }
  207. --idx;
  208. y *= ABSER;
  209. } while (idx>=0);
  210. Ans(istore, irel) = Zsum/Arg(istore);
  211. } // End of 1000 loop
  212. } // End of 1010 loop
  213. }
  214. } // ----- end of Lemma name -----