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.

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