subroutine fit_userfun(name, ufun) ! ---------------------------------- include 'fit.inc' character*(*) name external ufun real ufun integer sys_adrr_rriii usernp=0 npd=0 usertit=name userfun = sys_adrr_rriii(ufun) end subroutine fit_userpar(name) ! ---------------------------- include 'fit.inc' character*(*) name integer i if (npd .ne. 0) 1 stop 'per-dataset parameters must be defined at end!' usernp=usernp+1 if (usernp .gt. maxext) stop 'too many user parameters' i=index(name,':') userpar(usernp)=name(i+1:) if (i .gt. 1) then call str_upcase(usersho(usernp),name(1:i-1)) else usersho(usernp)=' ' endif usercct(usernp)=cinfo end subroutine fit_userpdp(name) ! ---------------------------- include 'fit.inc' character*(*) name integer i npd=npd+1 if (npd .gt. maxpd .or. npd+usernp .gt. maxext) 1 stop 'too many per-dataset parameters' userpar(usernp+npd)=name do i=1,maxset pdpar(npd, i)=none enddo c usercct(usernp+npd)=cinfo ! not yet implemented end subroutine fit_usercinfo(calcinfo) ! ---------------------------------- include 'fit.inc' integer calcinfo cinfo=calcinfo end subroutine fit_ncurves(ncur) ! ---------------------------- include 'fit.inc' integer ncur integer i nset=ncur if (nset .le. 0) then do i=1,npkt nset=max(nset,iset(i)) enddo endif end subroutine fit_user1st include 'fit.inc' real dum real sys_rfun_rriii integer calcinfo,i calcinfo=0 do i=1,nu if (u(i) .ne. pold(i)) then calcinfo=ior(calcinfo, usercct(i)) endif enddo dum=sys_rfun_rriii(userfun, 0.0, u, nu, 1, calcinfo) end integer function fit_userini(jfifu) include 'fit.inc' integer i,jfifu real dum, xx real sys_rfun_rriii do i=1,nu pold(i)=1.234e-35 enddo xx=-float(jfifu) dum=sys_rfun_rriii(userfun, xx, u, nu, -1, 0) fit_userini=nint(xx) if (fit_userini .lt. 0) fit_userini=0 end subroutine fit_check_range include 'fit.inc' real xmin, xmax real xmin0/-1./,xmax0/1.0/ integer i if (ififu .ne. 7) RETURN xmin0=xval(nxmin) xmax0=xmin0 do i=nxmin,nxmax if (xval(i) .lt. xmin0) xmin0=xval(i) if (xval(i) .gt. xmax0) xmax0=xval(i) enddo return entry fit_put_xrange(xmin, xmax) xmin0=min(xmin,xmax) xmax0=max(xmin,xmax) RETURN entry fit_limit_xrange(xmin, xmax) xmin0=max(xmin0,min(xmin,xmax)) xmax0=min(xmax0,max(xmin,xmax)) RETURN entry fit_get_xrange(xmin, xmax) xmin=xmin0 xmax=xmax0 end subroutine fit_fixit(i) include 'fit.inc' integer i lcode(i)=0 end subroutine fit_delta(xd,sd) include 'fit.inc' real sd,xd logical read integer nd,nr real xdi(maxpeak), sdi(maxpeak) logical disable/.true./ save nd,nr,xdi,sdi,disable if (sd .eq. 0 .or. disable) RETURN if (nd .ge. maxpeak) then print *,'too many delta peaks' RETURN endif nd=nd+1 xdi(nd)=xd sdi(nd)=sd return entry fit_init_delta(read) if (read) then nr=0 else nd=0 endif disable=read return entry fit_get_delta(xd,sd) if (nr .ge. nd) then sd=0 xd=0 else nr=nr+1 sd=sdi(nr) xd=xdi(nr) endif end subroutine fit_confun(name, ufun) ! --------------------------------- include 'fit.inc' include 'fit_user.inc' character*(*) name external ufun, fit_cfun real ufun real fit_cfun integer sys_adrr_rriii data xbase/0.0/ data show/.false./ data ecnt/0/ call fit_userfun(name, ufun) confun=userfun userfun = sys_adrr_rriii(fit_cfun) call fit_userpar('GW:GaussWid') call fit_userpar('XS:CalcStep') end subroutine fit_xbase(x_base) ! ---------------------------- real x_base include 'fit_user.inc' xbase=x_base end real function fit_cfun(x,p,n,mode,cinfo) ! ---------------------------------------- implicit none real x ! x-value integer n ! number of parameters real p(*) ! parameters integer mode ! mode ! 0: x-dependent part, 1: x-independent part, -1: par. independent part integer cinfo ! calculation information (not used here) include 'fit_user.inc' integer maxt, maxg, ng, imaxg, m_f, m_i, m_t, m_x real pn, gn parameter (m_f=0, m_i=1, m_t=2, m_x=3) ! m_f: call function directly ! m_i: initialize function ! m_t: transform x -> t ! m_x: transform t -> x parameter (pn=2.0) ! step size of larger gaussian = fwhm/pn parameter (gn=2.0) ! total width = gn*fwhm parameter (imaxg=128) ! maximal fwhm (in steps) integer i,j,k,m real ts ! t-step real t ! transformed x real ta, tb ! limits of t-space real gw ! total gaussian width (in t-space) real wg ! total peak weight real sum ! summing variable integer kstp ! step for folding integer mfold ! number of folding steps real wd ! individual peak width real t0 ! base for integration real lasty ! last value for integr. real xa, xb ! x-range real xs ! x-step at xbase real q ! ratio between fwhm's of peaks for folding steps real stp ! real step real xd, sd ! delta peak parameters real x0, x1, x2, qq, td, xsi parameter (maxt=10000) ! maximal number of points real y(0:maxt),yf(0:maxt) ! array before and after folding parameter (maxg=100) ! maximal number of points per gaussian (> gn*5) real gs(0:maxg) ! precalculated gaussian save y,ta,tb,xa,xb,gw,kstp external sys_rfun_rriii, voigt, spline3, spline4 real sys_rfun_rriii, voigt, spline3, spline4 if (mode .eq. 0) then if (gw .eq. 0) then fit_cfun=sys_rfun_rriii(confun,x,p,n,m_f,cinfo) RETURN endif if (x .lt. xa .or. x .gt. xb) then fit_cfun=sys_rfun_rriii(confun,x,p,n,m_f,cinfo) ecnt=ecnt+1 show=.true. else t=sys_rfun_rriii(confun,x,p,n,m_t,cinfo)/ts t=(t-ta)/istp i=nint(t-0.5) if (i .le. 1) then fit_cfun=spline3(t, y(0), y(1), y(2)) elseif (i .ge. npy-1) then fit_cfun=spline3(npy-t, y(npy), y(npy-1), y(npy-2)) else fit_cfun=spline4(t-i, y(i-1), y(i), y(i+1), y(i+2)) endif endif else if (mode .gt. 0) then show=.true. call fit_init_delta(.false.) if (p(1) .eq. 0.0) then fit_cfun=sys_rfun_rriii(confun,x,p,n,m_f,cinfo) RETURN endif call fit_get_xrange(xa,xb) fit_cfun=sys_rfun_rriii(confun,x,p,n,m_i,cinfo) call fit_init_delta(.true.) ta=sys_rfun_rriii(confun,xa,p,n,m_t,cinfo) tb=sys_rfun_rriii(confun,xb,p,n,m_t,cinfo) xs=p(2) if (xs .eq. 0) xs=p(1)/10 if (xbase-max(p(1),xs) .lt. xa .or. 1 xbase+max(p(1),xs) .gt. xb) then qq=(tb-ta)/(xb-xa) ts=abs(xs*qq) gw=abs(p(1)*qq)/ts else ts=abs(sys_rfun_rriii(confun,xbase+xs,p,n,m_t,cinfo) 1 -sys_rfun_rriii(confun,xbase-xs,p,n,m_t,cinfo)) if (ts .eq. 0) ts=1.0 gw=abs(sys_rfun_rriii(confun,xbase+p(1)/2,p,n,m_t,cinfo) 1 -sys_rfun_rriii(confun,xbase-p(1)/2,p,n,m_t,cinfo))/ts endif ta=int((ta/ts-gn*gw)) tb=int((tb/ts+gn*gw)+1) npy=nint(tb-ta) istp=max(int(gw/imaxg+1), (npy+maxt-1)/maxt) npy=npy/istp t0=ta-0.5*istp x0=sys_rfun_rriii(confun,t0*ts,p,n,m_x,cinfo) lasty=sys_rfun_rriii(confun,x0,p,n,m_f,cinfo) k=0 do i=0,npy x1=sys_rfun_rriii(confun,(t0+i*istp)*ts,p,n,m_x,cinfo) ! simpson integral over interval (x0...x1) xsi=(x1-x0)/istp x2=x1-xsi/2 sum=lasty do j=1,istp lasty=sys_rfun_rriii(confun,x0+j*xsi,p,n,m_f,cinfo) sum=sum+4*sys_rfun_rriii(confun,x2+j*xsi,p,n,m_f,cinfo) 1 +2*lasty enddo x0=x1 y(i)=(sum-lasty)/6/istp k=k+istp enddo call fit_get_delta(xd, sd) do while (sd .ne. 0) td=sys_rfun_rriii(confun,xd,p,n,m_t,cinfo)/ts sd=sd/abs( 1 sys_rfun_rriii(confun,(td+0.5*istp)*ts,p,n,m_x,cinfo) 1 -sys_rfun_rriii(confun,(td-0.5*istp)*ts,p,n,m_x,cinfo) ) if (td .ge. ta .and. td .le. tb) then t=(td-ta)/istp i=nint(t-0.4999) if (i .ge. npy) i=npy-1 y(i)=y(i)+sd*(i+1-t) y(i+1)=y(i+1)+sd*(t-i) endif call fit_get_delta(xd, sd) enddo if (gw .le. istp) RETURN mfold=max(1,nint(log(gw/pn/istp))) sum=0 q=max(1.1,(gw/pn/istp)**(1.0/mfold)) qq=1/(q*q) qq=sqrt((1-qq**mfold)/(1-qq)) ! sqrt of sum of squared widths divided by gw wd=gw/istp/q**(mfold-1)/qq icnt=0 stp=1.0 do m=1,mfold kstp=int(stp) stp=stp*q ng=min(maxg,int(gn*wd/kstp+0.9)) icnt=icnt+(2*ng+1)*(npy+1)-(ng-1)*ng+1 do i=0,ng gs(i)=voigt(float(i), wd/kstp, 0.0) enddo do i=0,npy wg=0 sum=0 k=i do j=0,min(ng,i/kstp) sum=sum+gs(j)*y(k) wg=wg+gs(j) k=k-kstp enddo k=i+kstp do j=1,min(ng,(npy-i)/kstp) sum=sum+gs(j)*y(k) wg=wg+gs(j) k=k+kstp enddo yf(i)=sum/wg enddo do i=ng*kstp,npy-ng*kstp y(i)=yf(i) enddo wd=wd*q enddo else fit_cfun=sys_rfun_rriii(confun,x,p,n,mode,cinfo) call fit_fixit(2) endif end subroutine fit_confun_print include 'fit_user.inc' if (show) then print * print '(i10,a,i9,a)' 1 , npy*istp*2+1, ' fn. calls, fold. multiplications: ',icnt if (ecnt .gt. 0) then print *,ecnt,' outside range calls counted' ecnt=0 endif show=.false. endif end real function spline4(x, y1, y2, y3, y4) ! spline interpolation. ! the result is valid for values x between 0 and 1 (x-coord of y2 and y3) real x, y1, y2, y3, y4 real ss, sl, sr ss=y3-y2 ! median slope sl=(y3-y1)/2 ! slope at point 2 sr=(y4-y2)/2 ! slope at point 3 spline4=y2+x*ss ! linear interpol. 1 + (sl-ss)*x*(x-1)**2 ! correction for left slope 1 - (sr-ss)*(1-x)*x**2 ! correction for right slope end real function spline3(x, y1, y2, y3) ! spline interpolation. ! the result is valid for values x between 0 and 1 (x-coord of y1 and y2) ! or, as an extrapolation to the left of x1 real x, y1, y2, y3 real sl, sr, s1 s1=y2-y1 sr=(y3-y1)/2 ! interpolate slope at point 2 sl=2*sr-s1 ! extrapolate slope at point 1 spline3=y1+x*s1 ! linear interpol. 1 + (sl-s1)*x*(x-1)**2 ! correction for left slope 1 - (sr-s1)*(1-x)*x**2 ! correction for right slope end