Rev 139 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
cMM this is the original adapt code with one modification.cMM instead of calling the external function "functn", a fixedcMM external routine adphlp is always called, and passed a pointercMM to the external s function.cMM Michael Meyer, October 1989.subroutine adapt(ndim,a,b,minpts,maxpts,eps,relerr,* lenwrk,wrkstr,finest,ifail)c***begin prologue adaptc adaptive multidimensional integration subroutinec author: A. C. Genz, Washington State Universityc 19 March 1984c************** parameters for adapt ********************************c***** input parametersc ndim number of variables, must exceed 1, but not exceed 20c a real array of lower limits, with dimension ndimc b real array of upper limits, with dimension ndimc minpts minimum number of function evaluations to be allowed.c on the first call to adapt minpts should be set to ac non negative value (caution... minpts is altered by adapt).c It is possible to continue a calculation to greater accuracyc by calling adapt again by decreasing eps (described below)c and resetting minpts to any negative value.c minpts must not exceed maxpts.c maxpts maximum number of function evaluations to be allowed,c which must be at least rulcls, wherec rulcls = 2**ndim+2*ndim**2+6*ndim+1cc for ndim = 2 3 4 5 6 7 8 9 10 12 15 20c maxpts >= rulcls = 25 45 73 113 173 269 433 729 1285 4457 33309 1049497cc a SUGGESTED value for maxpts is 100 times the above values.cc functn externally declared user defined function to be integrated.c it must have parameters (ndim,z), where z is a real arrayc of dimension ndim.cTSL this function has been replaced by the fixed function adhlpc eps required relative accuracyc lenwrk length of array wrkstr of working storage, the routinec needs (2*ndim+3)*(1+maxpts/rulcls)/2 for lenwrk ifc maxpts function calls are used.c for guidance, if you set maxpts to 100*rulcls (see tablec above) then acceptable values for lenwrk arecc for ndim = 2 3 4 5 6 7 8 9c lenwrk = 357 561 1785 3417 6681 13209 26265 52377cc***** OUTPUT parameterscc minpts actual number of function evaluations used by adaptc wrkstr real array of working storage of dimension (lenwrk).c relerr estimated relative accuracy of finestc finest estimated value of integral ["FINal ESTimate"]c ifail : return codecc ifail=0 for normal exit, when estimated relative accuracyc relerr is less than eps with maxpts or less functionc calls made.c ifail=1 if maxpts was too small for adapt to obtain thec required relative accuracy eps.c In this case adapt returns a value of finestc with estimated relative accuracy relerr.c ifail=2 if lenwrk too small for maxpts function calls.c In this case adapt returns a value of finest withc estimated accuracy relerr using the working storagec available, but relerr will be greater than eps.c ifail=3 if ndim < 2, ndim > 20,c ifail=4 if minpts > maxpts,c ifail=5 if maxpts < rulcls or other memory problemsc (which will only be found later)c***********************************************************************c***end prologue adaptimplicit noneC-- Arguments:C double precision functnC external functninteger ndim, minpts,maxpts, lenwrk, ifaildouble precision a(ndim), b(ndim), eps, relerr, wrkstr(lenwrk),& finestC-- Local Variables:double precision center(20), width(20)double precision errmin, rgnerr, rgnval, half, zero,one,twointeger divaxo, divaxn, divflg, funcls, index1, index2,* j, k, maxcls, rgnstr, rulcls, sbrgns, sbtmpp, subrgn, subtmpdata zero/0d0/, one/1d0/, two/2d0/c Check arguments; fail w/ code '3' or '4'relerr=onefuncls=0ifail=3if(ndim.lt.2 .or. ndim.gt.20) goto 990ifail=4if(minpts.gt.maxpts) goto 990ifail=5cc***** initialisation of subroutinechalf=one/tworgnstr = 2*ndim+3errmin = zeromaxcls = 2**ndim + 2*ndim**2 + 6*ndim+1maxcls = min0(maxcls,maxpts)divaxo=0cc***** end subroutine initialisationif(minpts.lt.0) thenc on re-entry {with intact lenwrk, wrkstr(1:lenwrk)} :sbrgns=wrkstr(lenwrk-1)goto 280endifdo 30 j=1,ndimwidth(j)=(b(j)-a(j))*half30 center(j)=a(j)+width(j)finest=zerowrkstr(lenwrk)=zerodivflg=1subrgn=rgnstrsbrgns=rgnstrC-- REPEAT --- (outermost loop) -------40 call bsrl(ndim,center,width,maxcls,rulcls,* errmin,rgnerr,rgnval,divaxo,divaxn)finest=finest+rgnvalwrkstr(lenwrk)=wrkstr(lenwrk)+rgnerrfuncls = funcls + rulclscc***** place results of basic rule into partially ordered listc***** according to subregion errorif(divflg .eq. 0) thencc *** when divflg=0 start at top of list and move down list tree toc find correct position for results from first half of recentlyc divided subregion200 subtmp=2*subrgnif(subtmp.le.sbrgns) thenif(subtmp.ne.sbrgns) thensbtmpp=subtmp+rgnstrif(wrkstr(subtmp).lt.wrkstr(sbtmpp)) subtmp=sbtmppendifif(rgnerr.lt.wrkstr(subtmp)) thendo 220 k=1,rgnstrindex1=subrgn-k+1index2=subtmp-k+1wrkstr(index1)=wrkstr(index2)220 continuesubrgn=subtmpgoto 200endifendifelsecc *** when divflg=1 start at bottom right branch and move up listc tree to find correct position for results from second half ofc recently divided subregion230 subtmp=(subrgn/(rgnstr*2))*rgnstrif(subtmp.ge.rgnstr) thenif(rgnerr.gt.wrkstr(subtmp)) thendo 240 k=1,rgnstrindex1=subrgn-k+1index2=subtmp-k+1wrkstr(index1)=wrkstr(index2)240 continuesubrgn=subtmpgoto 230endifendifendifc**** store results (length= 2*ndim+3) of basic rulec in correct position in list:250 wrkstr(subrgn)=rgnerrwrkstr(subrgn-1)=rgnvalwrkstr(subrgn-2)=divaxndo 260 j=1,ndimsubtmp=subrgn-2*(j+1)wrkstr(subtmp+1)=center(j)wrkstr(subtmp)=width(j)260 continueif(divflg .eq. 0) thenc*** when divflg=0 prepare for second application of basic rulecenter(divaxo)=center(divaxo)+two*width(divaxo)sbrgns=sbrgns+rgnstrsubrgn=sbrgnsdivflg=1c*** loop back to apply basic rule to other half of subregiongo to 40endifcc***** end ordering and storage of basic rule resultsc***** make checks for possible termination of routinec270 relerr=oneif(wrkstr(lenwrk).le.zero) wrkstr(lenwrk)=zeroif(dabs(finest).ne.zero) relerr=wrkstr(lenwrk)/dabs(finest)if(relerr.gt.one) relerr=oneif(sbrgns+rgnstr .gt. lenwrk-2) ifail=2c MM: Note that rgnstr = 2*ndim+3, and lenwrkc -- lenwrk = (2*ndim + 3)* (1 + maxpts/rulcls)/2c where rulcls = 2^ndim + 2*ndim^2 + 6*ndim + 1c and maxpts increases (for each .C() call from R)if(funcls+funcls*rgnstr/sbrgns.gt.maxpts) ifail=1if(relerr.lt.eps.and.funcls.ge.minpts) ifail=0if(ifail.lt.3) goto 990cc***** prepare to use basic rule on each half of subregion with largestc error280 divflg=0subrgn=rgnstrsubtmp = 2*sbrgns/rgnstrmaxcls = maxpts/subtmperrmin = dabs(finest)*eps/dfloat(subtmp)wrkstr(lenwrk)=wrkstr(lenwrk)-wrkstr(subrgn)finest=finest-wrkstr(subrgn-1)divaxo=wrkstr(subrgn-2)do 290 j=1,ndimsubtmp=subrgn-2*(j+1)center(j)=wrkstr(subtmp+1)290 width(j)=wrkstr(subtmp)width(divaxo)=width(divaxo)*halfcenter(divaxo)=center(divaxo)-width(divaxo)cc***** loop back to apply basic rulecgoto 40cc***** termination pointc990 minpts=funclswrkstr(lenwrk-1)=sbrgnsreturnend