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.

GQChave.cpp 42KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166
  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 01/02/2010
  9. @version $Id: hankeltransformgaussianquadrature.cpp 200 2014-12-29 21:11:55Z tirons $
  10. **/
  11. // Description: Port of Alan Chave's gaussian quadrature algorithm, which
  12. // is public domain, code listed in published article:
  13. // Chave, A. D., 1983, Numerical integration of related Hankel transforms by
  14. // quadrature and continued fraction expansion: Geophysics, 48
  15. // 1671--1686 doi: 10.1190/1.1441448
  16. #include "GQChave.h"
  17. namespace Lemma{
  18. std::ostream &operator<<(std::ostream &stream, const GQChave &ob) {
  19. stream << ob.Serialize() << "\n";
  20. return stream;
  21. }
  22. // Initialise static members
  23. const VectorXr GQChave::WT =
  24. (VectorXr(254) << // (WT(I),I=1,20)
  25. 0.55555555555555555556e+00,0.88888888888888888889e+00,
  26. 0.26848808986833344073e+00,0.10465622602646726519e+00,
  27. 0.40139741477596222291e+00,0.45091653865847414235e+00,
  28. 0.13441525524378422036e+00,0.51603282997079739697e-01,
  29. 0.20062852937698902103e+00,0.17001719629940260339e-01,
  30. 0.92927195315124537686e-01,0.17151190913639138079e+00,
  31. 0.21915685840158749640e+00,0.22551049979820668739e+00,
  32. 0.67207754295990703540e-01,0.25807598096176653565e-01,
  33. 0.10031427861179557877e+00,0.84345657393211062463e-02,
  34. 0.46462893261757986541e-01,0.85755920049990351154e-01,
  35. // (WT(I),I=21,40)
  36. 0.10957842105592463824e+00,0.25447807915618744154e-02,
  37. 0.16446049854387810934e-01,0.35957103307129322097e-01,
  38. 0.56979509494123357412e-01,0.76879620499003531043e-01,
  39. 0.93627109981264473617e-01,0.10566989358023480974e+00,
  40. 0.11195687302095345688e+00,0.11275525672076869161e+00,
  41. 0.33603877148207730542e-01,0.12903800100351265626e-01,
  42. 0.50157139305899537414e-01,0.42176304415588548391e-02,
  43. 0.23231446639910269443e-01,0.42877960025007734493e-01,
  44. 0.54789210527962865032e-01,0.12651565562300680114e-02,
  45. 0.82230079572359296693e-02,0.17978551568128270333e-01,
  46. // (WT(I),I=41,60)
  47. 0.28489754745833548613e-01,0.38439810249455532039e-01,
  48. 0.46813554990628012403e-01,0.52834946790116519862e-01,
  49. 0.55978436510476319408e-01,0.36322148184553065969e-03,
  50. 0.25790497946856882724e-02,0.61155068221172463397e-02,
  51. 0.10498246909621321898e-01,0.15406750466559497802e-01,
  52. 0.20594233915912711149e-01,0.25869679327214746911e-01,
  53. 0.31073551111687964880e-01,0.36064432780782572640e-01,
  54. 0.40715510116944318934e-01,0.44914531653632197414e-01,
  55. 0.48564330406673198716e-01,0.51583253952048458777e-01,
  56. 0.53905499335266063927e-01,0.55481404356559363988e-01,
  57. // (WT(I),I=61,80)
  58. 0.56277699831254301273e-01,0.56377628360384717388e-01,
  59. 0.16801938574103865271e-01,0.64519000501757369228e-02,
  60. 0.25078569652949768707e-01,0.21088152457266328793e-02,
  61. 0.11615723319955134727e-01,0.21438980012503867246e-01,
  62. 0.27394605263981432516e-01,0.63260731936263354422e-03,
  63. 0.41115039786546930472e-02,0.89892757840641357233e-02,
  64. 0.14244877372916774306e-01,0.19219905124727766019e-01,
  65. 0.23406777495314006201e-01,0.26417473395058259931e-01,
  66. 0.27989218255238159704e-01,0.18073956444538835782e-03,
  67. 0.12895240826104173921e-02,0.30577534101755311361e-02,
  68. // (WT(I),I=81,100)
  69. 0.52491234548088591251e-02,0.77033752332797418482e-02,
  70. 0.10297116957956355524e-01,0.12934839663607373455e-01,
  71. 0.15536775555843982440e-01,0.18032216390391286320e-01,
  72. 0.20357755058472159467e-01,0.22457265826816098707e-01,
  73. 0.24282165203336599358e-01,0.25791626976024229388e-01,
  74. 0.26952749667633031963e-01,0.27740702178279681994e-01,
  75. 0.28138849915627150636e-01,0.50536095207862517625e-04,
  76. 0.37774664632698466027e-03,0.93836984854238150079e-03,
  77. 0.16811428654214699063e-02,0.25687649437940203731e-02,
  78. 0.35728927835172996494e-02,0.46710503721143217474e-02,
  79. // (WT(I),I=101,120)
  80. 0.58434498758356395076e-02,0.70724899954335554680e-02,
  81. 0.83428387539681577056e-02,0.96411777297025366953e-02,
  82. 0.10955733387837901648e-01,0.12275830560082770087e-01,
  83. 0.13591571009765546790e-01,0.14893641664815182035e-01,
  84. 0.16173218729577719942e-01,0.17421930159464173747e-01,
  85. 0.18631848256138790186e-01,0.19795495048097499488e-01,
  86. 0.20905851445812023852e-01,0.21956366305317824939e-01,
  87. 0.22940964229387748761e-01,0.23854052106038540080e-01,
  88. 0.24690524744487676909e-01,0.25445769965464765813e-01,
  89. 0.26115673376706097680e-01,0.26696622927450359906e-01,
  90. // (WT(I),I=121,140)
  91. 0.27185513229624791819e-01,0.27579749566481873035e-01,
  92. 0.27877251476613701609e-01,0.28076455793817246607e-01,
  93. 0.28176319033016602131e-01,0.28188814180192358694e-01,
  94. 0.84009692870519326354e-02,0.32259500250878684614e-02,
  95. 0.12539284826474884353e-01,0.10544076228633167722e-02,
  96. 0.58078616599775673635e-02,0.10719490006251933623e-01,
  97. 0.13697302631990716258e-01,0.31630366082226447689e-03,
  98. 0.20557519893273465236e-02,0.44946378920320678616e-02,
  99. 0.71224386864583871532e-02,0.96099525623638830097e-02,
  100. 0.11703388747657003101e-01,0.13208736697529129966e-01,
  101. // (WT(I),I=141,160)
  102. 0.13994609127619079852e-01,0.90372734658751149261e-04,
  103. 0.64476204130572477933e-03,0.15288767050877655684e-02,
  104. 0.26245617274044295626e-02,0.38516876166398709241e-02,
  105. 0.51485584789781777618e-02,0.64674198318036867274e-02,
  106. 0.77683877779219912200e-02,0.90161081951956431600e-02,
  107. 0.10178877529236079733e-01,0.11228632913408049354e-01,
  108. 0.12141082601668299679e-01,0.12895813488012114694e-01,
  109. 0.13476374833816515982e-01,0.13870351089139840997e-01,
  110. 0.14069424957813575318e-01,0.25157870384280661489e-04,
  111. 0.18887326450650491366e-03,0.46918492424785040975e-03,
  112. // (WT(I),I=161,180)
  113. 0.84057143271072246365e-03,0.12843824718970101768e-02,
  114. 0.17864463917586498247e-02,0.23355251860571608737e-02,
  115. 0.29217249379178197538e-02,0.35362449977167777340e-02,
  116. 0.41714193769840788528e-02,0.48205888648512683476e-02,
  117. 0.54778666939189508240e-02,0.61379152800413850435e-02,
  118. 0.67957855048827733948e-02,0.74468208324075910174e-02,
  119. 0.80866093647888599710e-02,0.87109650797320868736e-02,
  120. 0.93159241280693950932e-02,0.98977475240487497440e-02,
  121. 0.10452925722906011926e-01,0.10978183152658912470e-01,
  122. 0.11470482114693874380e-01,0.11927026053019270040e-01,
  123. // (WT(I),I=181,200)
  124. 0.12345262372243838455e-01,0.12722884982732382906e-01,
  125. 0.13057836688353048840e-01,0.13348311463725179953e-01,
  126. 0.13592756614812395910e-01,0.13789874783240936517e-01,
  127. 0.13938625738306850804e-01,0.14038227896908623303e-01,
  128. 0.14088159516508301065e-01,0.69379364324108267170e-05,
  129. 0.53275293669780613125e-04,0.13575491094922871973e-03,
  130. 0.24921240048299729402e-03,0.38974528447328229322e-03,
  131. 0.55429531493037471492e-03,0.74028280424450333046e-03,
  132. 0.94536151685852538246e-03,0.11674841174299594077e-02,
  133. 0.14049079956551446427e-02,0.16561127281544526052e-02,
  134. // (WT(I),I=201,220)
  135. 0.19197129710138724125e-02,0.21944069253638388388e-02,
  136. 0.24789582266575679307e-02,0.27721957645934509940e-02,
  137. 0.30730184347025783234e-02,0.33803979910869203823e-02,
  138. 0.36933779170256508183e-02,0.40110687240750233989e-02,
  139. 0.43326409680929828545e-02,0.46573172997568547773e-02,
  140. 0.49843645647655386012e-02,0.53130866051870565663e-02,
  141. 0.56428181013844441585e-02,0.59729195655081658049e-02,
  142. 0.63027734490857587172e-02,0.66317812429018878941e-02,
  143. 0.69593614093904229394e-02,0.72849479805538070639e-02,
  144. 0.76079896657190565832e-02,0.79279493342948491103e-02,
  145. // (WT(I),I=221,240)
  146. 0.82443037630328680306e-02,0.85565435613076896192e-02,
  147. 0.88641732094824942641e-02,0.91667111635607884067e-02,
  148. 0.94636899938300652943e-02,0.97546565363174114611e-02,
  149. 0.10039172044056840798e-01,0.10316812330947621682e-01,
  150. 0.10587167904885197931e-01,0.10849844089337314099e-01,
  151. 0.11104461134006926537e-01,0.11350654315980596602e-01,
  152. 0.11588074033043952568e-01,0.11816385890830235763e-01,
  153. 0.12035270785279562630e-01,0.12244424981611985899e-01,
  154. 0.12443560190714035263e-01,0.12632403643542078765e-01,
  155. 0.12810698163877361967e-01,0.12978202239537399286e-01,
  156. // (WT(I),I=241,254)
  157. 0.13134690091960152836e-01,0.13279951743930530650e-01,
  158. 0.13413793085110098513e-01,0.13536035934956213614e-01,
  159. 0.13646518102571291428e-01,0.13745093443001896632e-01,
  160. 0.13831631909506428676e-01,0.13906019601325461264e-01,
  161. 0.13968158806516938516e-01,0.14017968039456608810e-01,
  162. 0.14055382072649964277e-01,0.14080351962553661325e-01,
  163. 0.14092845069160408355e-01,0.14094407090096179347e-01).finished();
  164. const VectorXr GQChave::WA =
  165. (VectorXr(127) << // (WT(I),I=1,20)
  166. // (WA(I),I=1,20)
  167. 0.77459666924148337704e+00,0.96049126870802028342e+00,
  168. 0.43424374934680255800e+00,0.99383196321275502221e+00,
  169. 0.88845923287225699889e+00,0.62110294673722640294e+00,
  170. 0.22338668642896688163e+00,0.99909812496766759766e+00,
  171. 0.98153114955374010687e+00,0.92965485742974005667e+00,
  172. 0.83672593816886873550e+00,0.70249620649152707861e+00,
  173. 0.53131974364437562397e+00,0.33113539325797683309e+00,
  174. 0.11248894313318662575e+00,0.99987288812035761194e+00,
  175. 0.99720625937222195908e+00,0.98868475754742947994e+00,
  176. 0.97218287474858179658e+00,0.94634285837340290515e+00,
  177. // (WA(I),I=21,40)
  178. 0.91037115695700429250e+00,0.86390793819369047715e+00,
  179. 0.80694053195021761186e+00,0.73975604435269475868e+00,
  180. 0.66290966002478059546e+00,0.57719571005204581484e+00,
  181. 0.48361802694584102756e+00,0.38335932419873034692e+00,
  182. 0.27774982202182431507e+00,0.16823525155220746498e+00,
  183. 0.56344313046592789972e-01,0.99998243035489159858e+00,
  184. 0.99959879967191068325e+00,0.99831663531840739253e+00,
  185. 0.99572410469840718851e+00,0.99149572117810613240e+00,
  186. 0.98537149959852037111e+00,0.97714151463970571416e+00,
  187. 0.96663785155841656709e+00,0.95373000642576113641e+00,
  188. // (WA(I),I=41,60)
  189. 0.93832039777959288365e+00,0.92034002547001242073e+00,
  190. 0.89974489977694003664e+00,0.87651341448470526974e+00,
  191. 0.85064449476835027976e+00,0.82215625436498040737e+00,
  192. 0.79108493379984836143e+00,0.75748396638051363793e+00,
  193. 0.72142308537009891548e+00,0.68298743109107922809e+00,
  194. 0.64227664250975951377e+00,0.59940393024224289297e+00,
  195. 0.55449513263193254887e+00,0.50768775753371660215e+00,
  196. 0.45913001198983233287e+00,0.40897982122988867241e+00,
  197. 0.35740383783153215238e+00,0.30457644155671404334e+00,
  198. 0.25067873030348317661e+00,0.19589750271110015392e+00,
  199. // (WA(I),I=61,80)
  200. 0.14042423315256017459e+00,0.84454040083710883710e-01,
  201. 0.28184648949745694339e-01,0.99999759637974846462e+00,
  202. 0.99994399620705437576e+00,0.99976049092443204733e+00,
  203. 0.99938033802502358193e+00,0.99874561446809511470e+00,
  204. 0.99780535449595727456e+00,0.99651414591489027385e+00,
  205. 0.99483150280062100052e+00,0.99272134428278861533e+00,
  206. 0.99015137040077015918e+00,0.98709252795403406719e+00,
  207. 0.98351865757863272876e+00,0.97940628167086268381e+00,
  208. 0.97473445975240266776e+00,0.96948465950245923177e+00,
  209. 0.96364062156981213252e+00,0.95718821610986096274e+00,
  210. // (WA(I),I=81,100)
  211. 0.95011529752129487656e+00,0.94241156519108305981e+00,
  212. 0.93406843615772578800e+00,0.92507893290707565236e+00,
  213. 0.91543758715576504064e+00,0.90514035881326159519e+00,
  214. 0.89418456833555902286e+00,0.88256884024734190684e+00,
  215. 0.87029305554811390585e+00,0.85735831088623215653e+00,
  216. 0.84376688267270860104e+00,0.82952219463740140018e+00,
  217. 0.81462878765513741344e+00,0.79909229096084140180e+00,
  218. 0.78291939411828301639e+00,0.76611781930376009072e+00,
  219. 0.74869629361693660282e+00,0.73066452124218126133e+00,
  220. 0.71203315536225203459e+00,0.69281376977911470289e+00,
  221. // (WA(I),I=101,120)
  222. 0.67301883023041847920e+00,0.65266166541001749610e+00,
  223. 0.63175643771119423041e+00,0.61031811371518640016e+00,
  224. 0.58836243444766254143e+00,0.56590588542365442262e+00,
  225. 0.54296566649831149049e+00,0.51955966153745702199e+00,
  226. 0.49570640791876146017e+00,0.47142506587165887693e+00,
  227. 0.44673538766202847374e+00,0.42165768662616330006e+00,
  228. 0.39621280605761593918e+00,0.37042208795007823014e+00,
  229. 0.34430734159943802278e+00,0.31789081206847668318e+00,
  230. 0.29119514851824668196e+00,0.26424337241092676194e+00,
  231. 0.23705884558982972721e+00,0.20966523824318119477e+00,
  232. // (WA(I),I=121,127)
  233. 0.18208649675925219825e+00,0.15434681148137810869e+00,
  234. 0.12647058437230196685e+00,0.98482396598119202090e-01,
  235. 0.70406976042855179063e-01,0.42269164765363603212e-01,
  236. 0.14093886410782462614e-01).finished();
  237. /*
  238. const Real PI2 = 0.6366197723675813;
  239. const Real X01P = 0.4809651115391545e01;
  240. const Real XMAX = std::numeric_limits<Real>::max();
  241. const Real XSMALL = 0.9094947017729281e-12;
  242. const Real J0_X01 = 0.2404825557695772e01;
  243. const Real J0_X02 = 0.1043754397719454e-15;
  244. const Real J0_X11 = 0.5520078110286310e01;
  245. const Real J0_X12 = 0.8088597146146419e-16;
  246. const Real FUDGE = 6.071532166000000e-18;
  247. const Real FUDGEX = 1.734723476000000e-18;
  248. const Real TWOPI1 = 0.6283185005187988e01;
  249. const Real TWOPI2 = 0.3019915981956752e-06;
  250. const Real RTPI2 = 0.7978845608028652e0;
  251. const Real XMIN = std::numeric_limits<Real>::min();
  252. const Real J1_X01 = 0.3831705970207512e1;
  253. const Real J1_X02 = -0.5967810507509414e-15;
  254. const Real J1_X11 = 0.7015586669815619e1;
  255. const Real J1_X12 = -0.5382308663841630e-15;
  256. */
  257. GQChave::GQChave( const ctor_key& key ) : HankelTransform( key ) {
  258. //karg.resize(255, 100);
  259. //kern.resize(510, 100);
  260. Xr.resize(100);
  261. Xi.resize(100);
  262. Dr.resize(100);
  263. Di.resize(100);
  264. Sr.resize(100);
  265. Si.resize(100);
  266. Cfcor.resize(100);
  267. Cfcoi.resize(100);
  268. }
  269. GQChave::GQChave( const YAML::Node& node, const ctor_key& key ) : HankelTransform(node, key) {
  270. }
  271. /////////////////////////////////////////////////////////////
  272. GQChave::~GQChave() {
  273. }
  274. /////////////////////////////////////////////////////////////
  275. std::shared_ptr<GQChave> GQChave::NewSP() {
  276. return std::make_shared<GQChave>( ctor_key() );
  277. }
  278. //--------------------------------------------------------------------------------------
  279. // Class: GQChave
  280. // Method: DeSerialize
  281. // Description: Factory method, converts YAML node into object
  282. //--------------------------------------------------------------------------------------
  283. std::shared_ptr<GQChave> GQChave::DeSerialize( const YAML::Node& node ) {
  284. if (node.Tag() != "GQChave") {
  285. throw DeSerializeTypeMismatch( "GQChave", node.Tag());
  286. }
  287. return std::make_shared<GQChave> ( node, ctor_key() );
  288. }
  289. //--------------------------------------------------------------------------------------
  290. // Class: GQChave
  291. // Method: Serialize
  292. // Description: Converts object into Serialized version
  293. //--------------------------------------------------------------------------------------
  294. YAML::Node GQChave::Serialize() const {
  295. YAML::Node node = HankelTransform::Serialize();
  296. node.SetTag( GetName() );
  297. //node["LayerConductivity"] = LayerConductivity;
  298. return node;
  299. }
  300. /////////////////////////////////////////////////////////////
  301. //--------------------------------------------------------------------------------------
  302. // Class: GQChave
  303. // Method: GetName
  304. // Description: Class identifier
  305. //--------------------------------------------------------------------------------------
  306. inline std::string GQChave::GetName ( ) const {
  307. return CName;
  308. } // ----- end of method GQChave::GetName -----
  309. Complex GQChave::
  310. Zgauss(const int &ikk, const EMMODE &mode,
  311. const int &itype, const Real &rho, const Real &wavef,
  312. KernelEM1DBase* Kernel){
  313. // TI, TODO, change calls to Zgauss to reflect this, go and fix so we
  314. // dont subract 1 from this everywhere
  315. //Kernel->SetIk(ikk+1);
  316. //Kernel->SetMode(mode);
  317. //ik = ikk+1;
  318. //mode = imode;
  319. karg.resize(255, 100);
  320. kern.resize(510, 100);
  321. Real Besr(0);
  322. Real Besi(0);
  323. // Parameters
  324. int nl(1); // Lower limit for gauss order to start comp
  325. int nu(7); // upper limit for gauss order
  326. #ifdef LEMMA_SINGLE_PRECISION
  327. Real rerr = 1e-5; // Error, for double Kihand set to .1e-10, .1e-11
  328. Real aerr = 1e-6;
  329. #else // ----- not LEMMA_SINGLE_PRECISION -----
  330. Real rerr = 1e-11; // Error, for double Kihand set to .1e-10, .1e-11
  331. Real aerr = 1e-12;
  332. #endif // ----- not LEMMA_SINGLE_PRECISION -----
  333. int npcs(1);
  334. int inew(0);
  335. //const int NTERM = 100;
  336. //BESINT.karg.resize(255, NTERM);
  337. //BESINT.kern.resize(510, NTERM);
  338. //this->karg.setZero();
  339. //this->kern.setZero();
  340. //std::cout << "calling Besautn" << std::endl;
  341. Besautn(Besr, Besi, itype, nl, nu, rho, rerr, aerr, npcs, inew, wavef, Kernel);
  342. return Complex(Besr, Besi);
  343. }
  344. //////////////////////////////////////////////////////////////////
  345. void GQChave::
  346. Besautn(Real &besr, Real &besi,
  347. const int &besselOrder,
  348. const int &lowerGaussLimit,
  349. const int &upperGaussLimit,
  350. const Real &rho,
  351. const Real &relativeError,
  352. const Real &absError,
  353. const int& numPieces,
  354. int &inew,
  355. const Real &aorb,
  356. KernelEM1DBase* Kernel) {
  357. HighestGaussOrder = 0;
  358. NumberPartialIntegrals = 0;
  359. NumberFunctionEvals = 0;
  360. inew = 0;
  361. if (lowerGaussLimit > upperGaussLimit) {
  362. besr = 0;
  363. besi = 0;
  364. throw LowerGaussLimitGreaterThanUpperGaussLimit();
  365. }
  366. int ncntrl = 0;
  367. int nw = std::max(inew, 1);
  368. // temps
  369. Real besr_1(0);
  370. Real besi_1(0);
  371. int ierr(0);
  372. int ierr1(0);
  373. int ierr2(0);
  374. VectorXi xsum(1);
  375. //xsum.setZero(); // TODO xsum doesn't do a god damn thing
  376. int nsum(0);
  377. // Check for Rtud
  378. //std::cout << "calling Bestrn" << std::endl;
  379. Bestrn(besr_1, besi_1, besselOrder, lowerGaussLimit, rho,
  380. .1*relativeError, .1*absError,
  381. numPieces, xsum, nsum, nw, ierr, ncntrl, aorb, Kernel);
  382. if (ierr != 0 && lowerGaussLimit == 7) {
  383. HighestGaussOrder = lowerGaussLimit;
  384. return;
  385. } else {
  386. Real oldr = besr_1;
  387. Real oldi = besi_1;
  388. for (int n=lowerGaussLimit+1; n<=upperGaussLimit; ++n) {
  389. int nw2 = 2;
  390. Bestrn(besr_1, besi_1, besselOrder, n, rho, .1*relativeError,
  391. .1*absError, numPieces, xsum, nsum, nw2, ierr,
  392. ncntrl, aorb, Kernel);
  393. if (ierr != 0 && n==7) {
  394. besr_1 = oldr;
  395. besi_1 = oldi;
  396. HighestGaussOrder = n;
  397. std::cerr << "CONVERGENCE FAILED AT SMALL ARGUMNENT!\n";
  398. ierr1 = ierr + 10;
  399. break;
  400. } else if (std::abs(besr_1-oldr) <=
  401. relativeError*std::abs(besr_1)+absError &&
  402. std::abs(besi_1-oldi) <=
  403. relativeError*std::abs(besi_1)+absError) {
  404. HighestGaussOrder = n;
  405. break;
  406. } else {
  407. oldr = besr_1;
  408. oldi = besi_1;
  409. }
  410. }
  411. }
  412. inew = 0;
  413. ncntrl = 1;
  414. nw=std::max(inew, 1);
  415. Real besr_2, besi_2;
  416. //karg.setZero();
  417. //kern.setZero();
  418. HighestGaussOrder = 0;
  419. NumberPartialIntegrals = 0;
  420. NumberFunctionEvals = 0;
  421. Bestrn(besr_2, besi_2, besselOrder, lowerGaussLimit, rho,
  422. .1*relativeError, .1*absError,
  423. numPieces, xsum, nsum, nw, ierr, ncntrl, aorb, Kernel);
  424. if (ierr != 0 && lowerGaussLimit == 7) {
  425. HighestGaussOrder = lowerGaussLimit;
  426. return;
  427. } else {
  428. Real oldr = besr_2;
  429. Real oldi = besi_2;
  430. for (int n=lowerGaussLimit+1; n<=upperGaussLimit; ++n) {
  431. int nw2 = 2;
  432. Bestrn(besr_2, besi_2, besselOrder, n, rho, .1*relativeError,
  433. .1*absError, numPieces, xsum, nsum, nw2, ierr,
  434. ncntrl, aorb, Kernel);
  435. if (ierr != 0 && n==7) {
  436. besr_2 = oldr;
  437. besi_2 = oldi;
  438. HighestGaussOrder = n;
  439. std::cerr << "CONVERGENCE FAILED AT SMALL ARGUMNENT!\n";
  440. ierr2 = ierr + 20;
  441. break;
  442. } else if (std::abs(besr_2-oldr) <=
  443. relativeError*std::abs(besr_2)+absError &&
  444. std::abs(besi_2-oldi) <=
  445. relativeError*std::abs(besi_2)+absError) {
  446. HighestGaussOrder = n;
  447. break;
  448. } else {
  449. oldr = besr_2;
  450. oldi = besi_2;
  451. }
  452. }
  453. }
  454. besr = besr_1 + besr_2;
  455. besi = besi_1 + besi_2;
  456. ierr = ierr1 + ierr2;
  457. return;
  458. }
  459. /////////////////////////////////////////////////////////////
  460. void GQChave::
  461. Bestrn(Real &BESR, Real &BESI, const int &IORDER,
  462. const int& NG, const Real& rho,
  463. const Real& RERR, const Real& AERR, const int& NPCS,
  464. const VectorXi& XSUM, int& NSUM, int& NEW,
  465. int& IERR, int& NCNTRL, const Real& AORB, KernelEM1DBase* Kernel) {
  466. //std::cout << "Bestrn setZero " << NEW << std::endl;
  467. //Xr.array() = 0.;
  468. //Xi.array() = 0.;
  469. Xr.setZero();
  470. Xi.setZero();
  471. Dr.setZero();
  472. Di.setZero();
  473. Sr.setZero();
  474. Si.setZero();
  475. Cfcor.setZero();
  476. Cfcoi.setZero();
  477. Dr.setZero();
  478. Di.setZero();
  479. //std::cout << "Bestrn wat " << NEW << std::endl;
  480. Dr(0) = (Real)(-1);
  481. const int NTERM = 100;
  482. const int NSTOP = 100;
  483. int NPO;
  484. //std::cout << "Bestrn NEW " << NEW << std::endl;
  485. if (NEW == 2) {
  486. NPO = nps;
  487. } else {
  488. Nk.setZero();
  489. nps = 0;
  490. NPO=NTERM;
  491. }
  492. // Trivial?
  493. if (IORDER != 0 && rho == 0) {
  494. BESR = 0;
  495. BESI = 0;
  496. IERR = 0;
  497. return;
  498. }
  499. NumberPartialIntegrals=0;
  500. int NW = NEW;
  501. np = 0; // TI, zero based indexing
  502. int NPB = 1; // 0?
  503. int L = 0;
  504. Real B = 0.;
  505. Real A = 0.;
  506. Real SUMR = 0.;
  507. Real SUMI = 0.;
  508. Real XSUMR = 0.;
  509. Real XSUMI = 0.;
  510. Real TERMR(0), TERMI(0);
  511. // COMPUTE BESSEL TRANSFORM EXPLICITLY ON (0,XSUM(NSUM))
  512. if (NSUM > 0) {
  513. std::cerr << "NSUM GREATER THAN ZERO UNTESTED" << std::endl;
  514. Real LASTR=0.0;
  515. Real LASTI=0.0;
  516. for (int N=1; N<=NSUM; ++N) {
  517. if (NW == 2 && np > NPO) NW=1;
  518. if (np > NTERM) NW=0;
  519. A=B;
  520. B=XSUM(N);
  521. Besqud(A, B, TERMR, TERMI, NG, NW, IORDER, rho, Kernel);
  522. XSUMR += TERMR;
  523. XSUMI += TERMI;
  524. if ( (std::abs(XSUMR-LASTR) <= RERR*std::abs(XSUMR)+AERR) &&
  525. (std::abs(XSUMI-LASTI) <= RERR*std::abs(XSUMI)+AERR)) {
  526. BESR=XSUMR;
  527. BESI=XSUMI;
  528. IERR=0;
  529. nps = std::max(np, nps);
  530. return;
  531. } else {
  532. ++np;
  533. LASTR=XSUMR;
  534. LASTI=XSUMI;
  535. }
  536. }
  537. // TODO, evaluate this case triggering cerr, as well as sttement below
  538. //while ( ZeroJ(NPB,IORDER) > XSUM(NSUM*rho)) {
  539. while ( ZeroJ(NPB,IORDER) > XSUM( (int)(NSUM*rho) )) {
  540. ++NPB;
  541. }
  542. }
  543. //std::cout << "Bestrn NEW " << NEW << std::endl;
  544. // ENTRY POINT FOR PADE SUMMATION OF PARTIAL INTEGRANDS
  545. Real LASTR=0.e0;
  546. Real LASTI=0.e0;
  547. if (NCNTRL == 0) {
  548. A = 0.;
  549. B = ZeroJ(NPB,IORDER) / rho;
  550. if (B > AORB) {
  551. B = AORB;
  552. }
  553. } else {
  554. A = AORB;
  555. B = ZeroJ(NPB,IORDER)/rho;
  556. while (B <= A) {
  557. ++NPB;
  558. B = ZeroJ(NPB,IORDER)/rho;
  559. }
  560. }
  561. // CALCULATE TERMS AND SUM WITH PADECF, QUITTING WHEN CONVERGENCE IS
  562. // OBTAINED
  563. if (NCNTRL != 0) {
  564. for (int N=1; N<=NSTOP; ++N) {
  565. if (NPCS == 1) {
  566. if ((NW==2) && (np > NPO)) {
  567. NW=1;
  568. }
  569. if (np > NTERM) {
  570. NW=0;
  571. }
  572. Besqud(A,B,TERMR,TERMI,NG,NW,IORDER,rho,Kernel);
  573. ++np;
  574. } else {
  575. std::cout << "In the else conditional\n";
  576. TERMR=0.;
  577. TERMI=0.;
  578. Real XINC=(B-A)/NPCS;
  579. Real AA=A;
  580. Real BB=A+XINC;
  581. for (int I=1; I<=NPCS; ++I) {
  582. if ((NW == 2) && (np > NPO)) NW=1;
  583. if (np > NTERM) NW=0;
  584. Real TR, TI;
  585. Besqud(AA, BB, TR, TI, NG, NW, IORDER, rho, Kernel);
  586. TERMR+=TR;
  587. TERMI+=TI;
  588. AA=BB;
  589. BB=BB+XINC;
  590. ++np;
  591. }
  592. }
  593. ++NumberPartialIntegrals;
  594. Sr(L) = TERMR;
  595. Si(L) = TERMI;
  596. Padecf(SUMR,SUMI,L);
  597. if ((std::abs(SUMR-LASTR) <= RERR*std::abs(SUMR)+AERR) &&
  598. (std::abs(SUMI-LASTI) <= RERR*std::abs(SUMI)+AERR)) {
  599. BESR=XSUMR+SUMR;
  600. BESI=XSUMI+SUMI;
  601. IERR=0;
  602. nps = std::max(np-1, nps);
  603. return;
  604. } else {
  605. LASTR=SUMR;
  606. LASTI=SUMI;
  607. ++NPB;
  608. A=B;
  609. B=ZeroJ(NPB,IORDER)/rho;
  610. ++L;
  611. }
  612. }
  613. BESR=XSUMR+SUMR;
  614. BESI=XSUMI+SUMI;
  615. IERR=1;
  616. nps = std::max(np, nps);
  617. return;
  618. }
  619. // GUSSIAN QUADRATURE ONLY IN THE INTERVAL IN WHICH K_0 IS LESS THAN
  620. // LAMBDA
  621. //std::cout << "NCNTRL " << NCNTRL << " NPCS " << NPCS << std::endl;
  622. for (int N=1; N<=NSTOP; ++N) {
  623. //std::cout << "NSTOP" << NSTOP << std::endl;
  624. if (NPCS == 1) {
  625. if ((NW==2) && (np > NPO)) {
  626. NW=1;
  627. }
  628. if (np > NTERM) {
  629. NW=0;
  630. }
  631. // Problem here, A not getting initialised
  632. //std::cout << "A " << A << " B " << B << std::endl;
  633. Besqud(A, B, TERMR, TERMI, NG, NW, IORDER, rho, Kernel);
  634. ++np;
  635. } else {
  636. TERMR=0.;
  637. TERMI=0.;
  638. Real XINC=(B-A)/NPCS;
  639. Real AA=A;
  640. Real BB=A+XINC;
  641. Real TR(0), TI(0);
  642. for (int I=1; I<NPCS; ++I) {
  643. if ((NW == 2) && (np > NPO)) {
  644. NW=1;
  645. }
  646. if (np > NTERM) {
  647. NW=0;
  648. }
  649. //std::cout << "AA " << AA << " BB " << BB << std::endl;
  650. Besqud(AA, BB, TR, TI, NG, NW, IORDER, rho, Kernel);
  651. TERMR+=TR;
  652. TERMI+=TI;
  653. AA=BB;
  654. BB=BB+XINC;
  655. ++np;
  656. }
  657. }
  658. if (B >= AORB) {
  659. BESR=XSUMR+TERMR;
  660. BESI=XSUMI+TERMI;
  661. IERR=0;
  662. nps = std::max(np, nps); // TI np is zero based
  663. return;
  664. } else {
  665. XSUMR = XSUMR + TERMR;
  666. XSUMI = XSUMI + TERMI;
  667. ++NPB;
  668. A = B;
  669. B = ZeroJ(NPB,IORDER)/rho;
  670. if (B >= AORB) B = AORB;
  671. }
  672. }
  673. return;
  674. }
  675. /////////////////////////////////////////////////////////////
  676. void GQChave::
  677. Besqud(const Real &LowerLimit, const Real &UpperLimit,
  678. Real &Besr, Real &Besi, const int &npoints,
  679. const int &NEW,
  680. const int &besselOrder, const Real &rho,
  681. KernelEM1DBase* Kernel) {
  682. const int NTERM = 100;
  683. // Filter Weights
  684. Eigen::Matrix<int , 7, 1> NWA;
  685. Eigen::Matrix<int , 7, 1> NWT;
  686. Eigen::Matrix<Real, 254, 1> FUNCT;
  687. Eigen::Matrix<Real, 64, 1> FR1;
  688. Eigen::Matrix<Real, 64, 1> FI1;
  689. Eigen::Matrix<Real, 64, 1> FR2;
  690. Eigen::Matrix<Real, 64, 1> FI2;
  691. Eigen::Matrix<Real, 64, 1> BES1;
  692. Eigen::Matrix<Real, 64, 1> BES2;
  693. // Init Vals
  694. NWT << 1, 3, 7, 15, 31, 63, 127;
  695. NWA << 1, 2, 4, 8, 16, 32, 64;
  696. // CHECK FOR TRIVIAL CASE
  697. if (LowerLimit >= UpperLimit) {
  698. Besr = 0.;
  699. Besi = 0.;
  700. //std::cout << "Lower limit > Upper limit " << NEW << std::endl;
  701. //std::cout << "Lower limit " << LowerLimit << "Upper Limit " << UpperLimit <<std::endl;
  702. return;
  703. }
  704. // Temp vars for function generation
  705. Real diff(0);
  706. Real FZEROR(0);
  707. Real FZEROI(0);
  708. Real SUM(0);
  709. int KN(0);
  710. int LA(0);
  711. int LK(0);
  712. int N(0);
  713. int K;
  714. int NW;
  715. Real ACUMR;
  716. Real ACUMI;
  717. Real BESF;
  718. switch (NEW) {
  719. // CONSTRUCT FUNCT FROM SAVED KERNELS
  720. case (2):
  721. diff = (UpperLimit-LowerLimit)/2.;
  722. FZEROR = kern(0, np);
  723. FZEROI = kern(1, np);
  724. K = std::min(Nk(np)-1, npoints-1);
  725. NW=NWT(K);
  726. LK=2;
  727. for (N=0; N<2*NW; N+=2) {
  728. FUNCT(N) = kern(LK , np) +
  729. kern(LK+2, np) ;
  730. FUNCT(N+1) = kern(LK+1, np) +
  731. kern(LK+3, np) ;
  732. LK=LK+4;
  733. }
  734. if (Nk(np) >= npoints) {
  735. ACUMR = _dot(NW, WT.tail(255-NW), 1, FUNCT, 2);
  736. ACUMI = _dot(NW, WT.tail(255-NW), 1, FUNCT.tail<253>(), 2);
  737. Besr = (ACUMR+WT(2*NW)*FZEROR)*diff;
  738. Besi = (ACUMI+WT(2*NW)*FZEROI)*diff;
  739. return;
  740. } else {
  741. // COMPUTE ADDITIONAL ORDERS BEFORE TAKING DOT PRODUCT
  742. SUM= (UpperLimit+LowerLimit)/2.;
  743. KN = K +1;
  744. LA = LK/2;
  745. }
  746. break;
  747. default:
  748. // SCALE FACTORS
  749. SUM = (UpperLimit+LowerLimit) / 2.;
  750. diff = (UpperLimit-LowerLimit) / 2.;
  751. // ONE POINT GAUSS
  752. //Kernel(SUM,FZEROR,FZEROI,TEM,GEOM,PARA);
  753. Complex tba = Kernel->BesselArg(SUM);
  754. //cout.precision(16);
  755. //std::cout << "SUM " << "\t" << SUM << "\t" << tba << "\n";
  756. ++NumberFunctionEvals;
  757. BESF = Jbess(SUM*rho,besselOrder);
  758. FZEROR = BESF*std::real(tba);//FZEROR;
  759. FZEROI = BESF*std::imag(tba);//FZEROI;
  760. if (NEW == 1) {
  761. karg(0, np) = SUM;
  762. kern(0, np) = FZEROR;
  763. kern(1, np) = FZEROI;
  764. LA=1;
  765. LK=2;
  766. }
  767. N = 0; // TI was 1, 0 based index
  768. KN = 0;
  769. } // End of new switch
  770. // STEP THROUGH GAUSS ORDERS (NG = Number Gauss)
  771. for (int K=KN; K<npoints; ++K) {
  772. // COMPUTE NEW FUNCTION VALUES
  773. int NA = NWA(K) - 1; // NWA assumes 1 based indexing
  774. //std::cout << "Besqud NA=" << NA << std::endl;
  775. for (int J=0; J<NWA(K); ++J) {
  776. Real X = WA(NA)*diff;
  777. Real SUMP = SUM+X;
  778. Real SUMM = SUM-X;
  779. ++NA;
  780. //std::cout << "Calling from here\n";
  781. //Kernel(SUMP, FR1(J), FI1(J), TEM, GEOM, PARA);
  782. //Kernel(SUMM, FR2(J), FI2(J), TEM, GEOM, PARA);
  783. Complex bes1 = Kernel->BesselArg(SUMP);
  784. //std::cout << "SUMP" << "\t" << SUMP << "\t" << bes1 << "\n";
  785. Complex bes2 = Kernel->BesselArg(SUMM);
  786. //std::cout << "SUMM" << "\t" << SUMM << "\t" << bes1 << "\n";
  787. FR1(J) = std::real(bes1);
  788. FI1(J) = std::imag(bes1);
  789. FR2(J) = std::real(bes2);
  790. FI2(J) = std::imag(bes2);
  791. NumberFunctionEvals +=2;
  792. BES1(J)=Jbess(SUMP*rho, besselOrder);
  793. BES2(J)=Jbess(SUMM*rho, besselOrder);
  794. if (NEW >= 1) {
  795. karg(LA , np) = SUMP;
  796. karg(LA+1, np) = SUMM;
  797. LA += 2;
  798. }
  799. }
  800. // COMPUTE PRODUCTS OF KERNELS AND BESSEL FUNCTIONS
  801. // TODO vectorize
  802. for (int J=0; J<NWA(K); ++J) {
  803. FR1(J ) = BES1(J)*FR1(J);
  804. FI1(J ) = BES1(J)*FI1(J);
  805. FR2(J ) = BES2(J)*FR2(J);
  806. FI2(J ) = BES2(J)*FI2(J);
  807. FUNCT(N ) = FR1(J)+FR2(J);
  808. FUNCT(N+1) = FI1(J)+FI2(J);
  809. N+=2;
  810. }
  811. if (NEW >= 1) {
  812. for (int J=0; J<NWA(K); ++J) {
  813. kern(LK , np) = FR1(J);
  814. kern(LK+1, np) = FI1(J);
  815. kern(LK+2, np) = FR2(J);
  816. kern(LK+3, np) = FI2(J);
  817. LK=LK+4;
  818. }
  819. }
  820. }
  821. // COMPUTE DOT PRODUCT OF WEIGHTS WITH INTEGRAND VALUES
  822. NW=NWT(npoints-1);
  823. ACUMR = _dot(NW, WT.tail(255-NW), 1, FUNCT , 2);
  824. ACUMI = _dot(NW, WT.tail(255-NW), 1, FUNCT.tail<253>(), 2);
  825. Besr = (ACUMR+WT(2*NW-1)*FZEROR)*diff;
  826. Besi = (ACUMI+WT(2*NW-1)*FZEROI)*diff;
  827. if (np <= NTERM) Nk(np) = npoints;
  828. return;
  829. }
  830. /////////////////////////////////////////////////////////////
  831. void GQChave::
  832. Padecf(Real &SUMR, Real &SUMI, const int &N) {
  833. if (N < 2) {
  834. // INITIALIZE FOR RECURSIVE CALCULATIONS
  835. //if (N == 0) {
  836. // Xr.setZero();
  837. // Xi.setZero();
  838. //Xr = Eigen::Matrix<Real, Eigen::Dynamic, 1>::Zero(100);
  839. //Xi = Eigen::Matrix<Real, Eigen::Dynamic, 1>::Zero(100);
  840. //}
  841. Dr(N) = Sr(N);
  842. Di(N) = Si(N);
  843. Real DENOM;
  844. switch (N) {
  845. case 0:
  846. DENOM = 1;
  847. Cfcor(N) = -(-1.*Dr(N)) / DENOM;
  848. Cfcoi(N) = -(-1.*Di(N)) / DENOM;
  849. break;
  850. default:
  851. DENOM = Dr(N-1)*Dr(N-1) +
  852. Di(N-1)*Di(N-1);
  853. Cfcor(N) = -(Dr(N-1)*Dr(N) +
  854. Di(N-1)*Di(N) ) / DENOM;
  855. Cfcoi(N) = -(Dr(N-1)*Di(N ) -
  856. Dr(N )*Di(N-1) ) / DENOM;
  857. }
  858. CF(SUMR, SUMI, Cfcor, Cfcoi, N);
  859. return;
  860. } else {
  861. int L = 2*(int)((N)/2) - 1;//+1;// - 1; // - 1; // - 1;
  862. // UPDATE X VECTORS FOR RECURSIVE CALCULATION OF CF COEFFICIENTS
  863. for (int K = L; K >= 3; K-= 2) {
  864. Xr(K) = Xr(K-1)+Cfcor(N-1)*Xr(K-2) -
  865. Cfcoi(N-1)*Xi(K-2);
  866. Xi(K) = Xi(K-1)+Cfcor(N-1)*Xi(K-2) +
  867. Cfcoi(N-1)*Xr(K-2);
  868. }
  869. Xr(1) = Xr(0)+Cfcor(N-1);
  870. Xi(1) = Xi(0)+Cfcoi(N-1);
  871. // INTERCHANGE ODD AND EVEN PARTS
  872. for (int K=0; K<L; K+=2) {
  873. Real T1 = Xr(K);
  874. Real T2 = Xi(K);
  875. Xr(K) = Xr(K+1);
  876. Xi(K) = Xi(K+1);
  877. Xr(K+1) = T1;
  878. Xi(K+1) = T2;
  879. }
  880. // COMPUTE FIRST COEFFICIENTS
  881. Dr(N) = Sr(N);
  882. Di(N) = Si(N);
  883. // Dr getting fucked up here
  884. for (int K=0; K<std::max(1, L/2+1); ++K) {
  885. Dr(N) += Sr(N-K-1)*Xr(2*K) -
  886. Si(N-K-1)*Xi(2*K);
  887. Di(N) += Si(N-K-1)*Xr(2*K) +
  888. Sr(N-K-1)*Xi(2*K);
  889. }
  890. // COMPUTE NEW CF COEFFICIENT
  891. Real DENOM = Dr(N-1)*Dr(N-1) +
  892. Di(N-1)*Di(N-1);
  893. //std::cout << "DENOM " << DENOM << std::endl;
  894. Cfcor(N)=-(Dr(N )*Dr(N-1) +
  895. Di(N)*Di(N-1))/DENOM;
  896. Cfcoi(N)=-(Dr(N-1)*Di(N ) -
  897. Dr(N)*Di(N-1))/DENOM;
  898. // EVALUATE CONTINUED FRACTION
  899. CF(SUMR,SUMI,Cfcor,Cfcoi,N);
  900. return;
  901. }
  902. }
  903. /////////////////////////////////////////////////////////////
  904. void GQChave::CF(Real& RESR, Real &RESI,
  905. const VectorXr& CFCOR,
  906. const VectorXr& CFCOI,
  907. const int &N) {
  908. ////////////////////////////////////////////////
  909. // ONE Seems sort of stupid, maybe use ? instead
  910. // TODO benchmark difference
  911. //RESR = ONE(N)+CFCOR(N);
  912. RESR = (!N ? 0:1) + CFCOR(N);
  913. RESI = CFCOI(N);
  914. for (int K=N-1; K>=0; --K) {
  915. Real DENOM=RESR*RESR + RESI*RESI;
  916. Real RESRO=RESR;
  917. //RESR=ONE(K)+(RESR*CFCOR(K)+RESI*CFCOI(K))/DENOM;
  918. RESR = (!K ? 0:1) + (RESR*CFCOR(K)+RESI*CFCOI(K))/DENOM;
  919. RESI=(RESRO*CFCOI(K)-RESI*CFCOR(K))/DENOM;
  920. }
  921. return;
  922. }
  923. /////////////////////////////////////////////////////////////
  924. Real GQChave::
  925. ZeroJ(const int &nzero, const int &besselOrder) {
  926. Real ZT1 = -1.e0/8.e0;
  927. Real ZT2 = 124.e0/1536.e0;
  928. Real ZT3 = -120928.e0/491520.e0;
  929. Real ZT4 = 401743168.e0/220200960.e0;
  930. Real OT1 = 3.e0/8.e0;
  931. Real OT2 = -36.e0/1536.e0;
  932. Real OT3 = 113184.e0/491520.e0;
  933. Real OT4 = -1951209.e0/220200960.e0;
  934. Real BETA(0);
  935. switch (besselOrder) {
  936. case 0:
  937. BETA=(nzero-.25e0)*PI;
  938. return BETA-ZT1/BETA-ZT2/std::pow(BETA,3) -
  939. ZT3/std::pow(BETA,5)-ZT4/std::pow(BETA,7);
  940. case 1:
  941. BETA=(nzero+.25e0)*PI;
  942. return BETA-OT1/BETA-OT2/std::pow(BETA,3) -
  943. OT3/std::pow(BETA,5)-OT4/std::pow(BETA,7);
  944. default:
  945. throw 77;
  946. }
  947. //return 0.;
  948. }
  949. /////////////////////////////////////////////////////////////
  950. // Dot product allowing non 1 based incrementing
  951. Real GQChave::_dot(const int&n,
  952. const Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic> &X1,
  953. const int &inc1,
  954. const Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic> &X2,
  955. const int &inc2) {
  956. int k;
  957. if (inc2 > 0) {
  958. k=0;
  959. } else {
  960. k = n*std::abs(inc2);
  961. }
  962. Real dot=0.0;
  963. if (inc1 > 0) {
  964. for (int i=0; i<n; i += inc1) {
  965. dot += X1(i)*X2(k);
  966. k += inc2;
  967. }
  968. } else {
  969. for (int i=n-1; i>=0; i += inc1) {
  970. dot += X1(i)*X2(k);
  971. k += inc2;
  972. }
  973. }
  974. return dot;
  975. }
  976. /////////////////////////////////////////////////////////////
  977. //
  978. #ifdef HAVE_BOOST_SPECIAL_FUNCTIONS
  979. Real GQChave::Jbess(const Real &x, const int &IORDER) {
  980. switch (IORDER) {
  981. case 0:
  982. //return boost::math::detail::bessel_j0(X);
  983. return boost::math::cyl_bessel_j(0, x);
  984. break;
  985. case 1:
  986. //return boost::math::detail::bessel_j1(x);
  987. return boost::math::cyl_bessel_j(1, x);
  988. break;
  989. default:
  990. throw std::runtime_error("Non 0 or 1 Bessel argument specified in GQChave");
  991. }
  992. }
  993. #else
  994. Real GQChave::Jbess(const Real &x, const int &IORDER) {
  995. std::cerr << "GQChave requires boost special functions module";
  996. return 0;
  997. }
  998. #endif
  999. //////////////////////////////////////////////////////
  1000. // Exception classes
  1001. LowerGaussLimitGreaterThanUpperGaussLimit::
  1002. LowerGaussLimitGreaterThanUpperGaussLimit() :
  1003. runtime_error("LOWER GAUSS LIMIT > UPPER GAUSS LIMIT") {}
  1004. } // ----- end of Lemma name -----