Main Lemma Repository
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.

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 -----