subroutine lagp(plag,wl,r0,dr,nl,nrange) c c predict lagged product matrix using state parameters stored c as cubic b-splines c read weights for numeric integration from a file c c faster version - assumes samples taken at half-integer lags, ranges c include 'fitter.h' include 'spline.h' include 'bfield.h' integer nl,nrange real plag(nl,nrange),taus(nl) parameter(nw=1000) integer ilag(nw) real weight(nw),dtau(nw),drange(nw) logical first real store(2*nl,2*nrange,2) data first/.true./ c c write(*,*) "dens_before: ",dens c call exit c zero out array c write(*,*) "Starting lagp" do i=1,nrange do j=1,nl plag(j,i)=0.0 end do end do c c compute all required acfs c do i=1,2*nrange ii=(i-1)/2+1 alt=r0+float(i-1)*dr*0.5 ! half integer ranges c write(*,*) "dens_before: ",dens c call exit c write(*,*) "alt: ",alt c write(*,*) "dens: ",dens c write(*,*) "te: ",te c write(*,*) "ti1: ",ti1 c write(*,*) "hf: ",hf c write(*,*) "hef: ",hef c call exit call get_spline(alt,dens,te,ti1,hf,hef) c write(*,*) "dens_after: ",dens c call exit do k=1,nion ti(k)=ti1 end do fi(2)=hf fi(3)=hef fi(1)=1.0-hf-hef do j=1,2*nl tau=float(j-1)*(dr/1.5e5)*0.5 ! half integer lags c just consider a single azimuth angle for now c call acf2(wl,tau,te,ti,fi,ven,vin,wi,nion, c & alpha_prof(ii)+1.74e-2,dens,bfld_prof(ii),rho) c store(j,i,1)=rho*dens*(100.0/alt)**2 c call acf2(wl,tau,te,ti,fi,ven,vin,wi,nion, c & alpha_prof(ii)-1.74e-2,dens,bfld_prof(ii),rho) c store(j,i,2)=rho*dens*(100.0/alt)**2 call acf2(wl,tau,te,ti,fi,ven,vin,wi,nion, & alpha_prof(ii),dens,bfld_prof(ii),rho) store(j,i,1)=rho*dens*(100.0/alt)**2 c write(*,*) "store", store(j,i,1) c call exit end do end do c construct lagged products c c write(*,*) "before weights" c write(*,*) first c write(*,*) "weight before: ",weight if(first) then open(unit=25,file='/usr/local/lib/faraday/weights.dat', & status='old') read (25,*) nwt do i=1,nwt read(25,*) weight(i),dtau(i),drange(i),ilag(i) c write(*,*) "ilag: ",ilag(i) end do c flush(25) close(25) c first=.false. end if c write(*,*) "after weights" c write(*,*) "weight(3): ",weight(3) c call exit c write(*,*) "nl: ",nl,"nrange: ",nrange,"nwt: ",nwt do i=1+nl,nrange ! don't worry about redundancy here do j=1,nwt c write(*,*) "j: ",j alt=r0+(float(i-1)+drange(j))*dr tau=abs(dtau(j)*dr/1.5e5) lag=ilag(j)+1 c write(*,*) tau k=1+2.0*(tau/(dr/1.5e5)) l=1+2.0*(alt-r0)/dr do m=1,1 ! 2 c call exit c write(*,*) i c call exit c if (i .eq. nrange) then c if (j .eq. 227) then c write(*,*) "lag: ",lag c write(*,*) "ilag: ",ilag(j) c call exit c write(*,*) "plag: ",plag(lag,i) c write(*,*) "weight: ",weight c c write(*,*) "weight: ",weight(j) c write(*,*) "store: ",store(k,l,m) c call exit c end if c end if plag(lag,i)=plag(lag,i)+weight(j)*store(k,l,m) c if (i .eq. nrange) then c write(*,*) "lag: ",lag c write(*,*) "plag: ",plag(lag,i) c write(*,*) "plag: ",plag(lag,i) c call exit c end if end do c write(*,*) "plag: ",plag(lag,i) c write(*,*) "plag: ",plag(12,72) c call exit end do c call exit c write(*,*) "plag: ",plag(12,72) end do c write(*,*) "plag: ",plag(12,72) c call exit c write(*,*) "End LAGP" return end subroutine lagp_old(plag,wl,r0,dr,nl,nrange) c c predict lagged product matrix using state parameters stored c as cubic b-splines c read weights for numeric integration from a file c c general version - samples can be anywhere c include 'fitter.h' include 'spline.h' include 'bfield.h' integer nl,nrange real plag(nl,nrange),taus(nl) parameter(nw=1000) integer ilag(nw) real weight(nw),dtau(nw),drange(nw) logical first data first/.true./ c c zero out array do i=1,nrange do j=1,nl plag(j,i)=0.0 end do end do c c construct lagged products c if(first) then open(unit=25,file='weights.dat',status='old') read (25,*) nwt do i=1,nwt read(25,*) weight(i),dtau(i),drange(i),ilag(i) end do close(25) first=.false. end if c can avoid recalculating splines and/or ACFs when parameters repeat altp=-1.0 taup=-1.0 do i=1+nl,nrange do j=1,nwt alt=r0+(float(i-1)+drange(j))*dr ii=(alt-r0)/dr+1 if(alt.ne.altp) then call get_spline(alt,dens,te,ti1,hf,hef) c write(*,*) alt,dens,te,ti1,hf,hef do k=1,nion ti(k)=ti1 end do fi(2)=hf fi(3)=hef fi(1)=1.0-hf-hef end if tau=abs(dtau(j)*dr/1.5e5) lag=ilag(j)+1 c write(*,*) i,alpha_prof(i),bfld_prof(i) if(tau.ne.taup.or.alt.ne.altp) then c two- or three- point Gauss Hermite quadrature rule c call acf2(wl,tau,te,ti,fi,ven,vin,wi,nion, c & alpha_prof(ii)+1.74e-2,dens,bfld_prof(ii),rho1) c call acf2(wl,tau,te,ti,fi,ven,vin,wi,nion, c & alpha_prof(ii)-1.74e-2,dens,bfld_prof(ii),rho2) c call acf2(wl,tau,te,ti,fi,ven,vin,wi,nion, c & alpha_prof(ii),dens,bfld_prof(ii),rho1) c call acf2(wl,tau,te,ti,fi,ven,vin,wi,nion, c & alpha_prof(ii)+1.9e-2,dens,bfld_prof(ii),rho2) c call acf2(wl,tau,te,ti,fi,ven,vin,wi,nion, c & alpha_prof(ii)-1.9e-2,dens,bfld_prof(ii),rho3) call acf2(wl,tau,te,ti,fi,ven,vin,wi,nion, & alpha_prof(ii),dens,bfld_prof(ii),rho) c rho=(rho1+rho2)/2.0 c rho=(rho2+rho3)*0.29541+rho1*1.18164)/1.77246 end if plag(lag,i)=plag(lag,i)+weight(j)*rho*dens*(100.0/alt)**2 altp=alt taup=tau end do end do return end function atanh(x) c real atanh,x c atanh=log(sqrt((1.+x)/(1.-x))) return end subroutine get_spline(alt,dens,te,ti,hf,hef) c c routines for handling cubic b-spline interpolation c gets values consistent with stored coefficients c include 'spline.h' c c bspline values from 200-1500 km in 15-km intervals c must specify five knots above ceiling c note offset ... start accessing splines above bottom two knots c c five banks of splines, for Ne, Te, Ti, H+, and He+ versus altitude c need to initialize ta somewhere c c write(*,*) "ta: ",ta c write(*,*) "bcoef(1,1): ",bcoef(1,1) c write(*,*) "nspline: ",nspline c write(*,*) "norder: ",norder c write(*,*) "alt: ",alt dens=bvalue(ta,bcoef(1,1),nspline,norder,alt,0) c write(*,*) "dens_inside_get_spline: ",dens c write(*,*) dens c call exit dens=10.0**MAX(dens,2.0) c write(*,*) dens c call exit te=bvalue(ta,bcoef(1,2),nspline,norder,alt,0) te=t0+t1*(1.0+tanh(te))/2.0 ! DLH 10/14 was 3500 c tr=bvalue(ta,bcoef(1,3),nspline,norder,alt,0) c tr=exp(tr) c ti=te/tr ti=bvalue(ta,bcoef(1,3),nspline,norder,alt,0) ti=t0+t1*(1.0+tanh(ti))/2.0 ! DLH 10/14 was 3500 hf=bvalue(ta,bcoef(1,4),nspline,norder,alt,0) hf=(1.0+tanh(hf))/2.0 hef=bvalue(ta,bcoef(1,5),nspline,norder,alt,0) hef=(1.0+tanh(hef))/2.0 return end real function bvalue ( t, bcoef, n, k, x, jderiv ) c from * a practical guide to splines * by c. de boor calls interv c calculates value at x of jderiv-th derivative of spline from b-repr. c the spline is taken to be continuous from the right, EXCEPT at the c rightmost knot, where it is taken to be continuous from the left. c c****** i n p u t ****** c t, bcoef, n, k......forms the b-representation of the spline f to c be evaluated. specifically, c t.....knot sequence, of length n+k, assumed nondecreasing. c bcoef.....b-coefficient sequence, of length n . c n.....length of bcoef and dimension of spline(k,t), c a s s u m e d positive . c k.....order of the spline . c c w a r n i n g . . . the restriction k .le. kmax (=20) is imposed c arbitrarily by the dimension statement for aj, dl, dr below, c but is n o w h e r e c h e c k e d for. c c x.....the point at which to evaluate . c jderiv.....integer giving the order of the derivative to be evaluated c a s s u m e d to be zero or positive. c c****** o u t p u t ****** c bvalue.....the value of the (jderiv)-th derivative of f at x . c c****** m e t h o d ****** c The nontrivial knot interval (t(i),t(i+1)) containing x is lo- c cated with the aid of interv . The k b-coeffs of f relevant for c this interval are then obtained from bcoef (or taken to be zero if c not explicitly available) and are then differenced jderiv times to c obtain the b-coeffs of (d**jderiv)f relevant for that interval. c Precisely, with j = jderiv, we have from x.(12) of the text that c c (d**j)f = sum ( bcoef(.,j)*b(.,k-j,t) ) c c where c / bcoef(.), , j .eq. 0 c / c bcoef(.,j) = / bcoef(.,j-1) - bcoef(.-1,j-1) c / ----------------------------- , j .gt. 0 c / (t(.+k-j) - t(.))/(k-j) c c Then, we use repeatedly the fact that c c sum ( a(.)*b(.,m,t)(x) ) = sum ( a(.,x)*b(.,m-1,t)(x) ) c with c (x - t(.))*a(.) + (t(.+m-1) - x)*a(.-1) c a(.,x) = --------------------------------------- c (x - t(.)) + (t(.+m-1) - x) c c to write (d**j)f(x) eventually as a linear combination of b-splines c of order 1 , and the coefficient for b(i,1,t)(x) must then be the c desired number (d**j)f(x). (see x.(17)-(19) of text). c parameter (kmax = 40) integer jderiv,k,n, i,ilo,imk,j,jc,jcmin,jcmax,jj,kmj,km1 * ,mflag,nmi,jdrvp1 c integer kmax C real bcoef(n),t(1),x, aj(20),dl(20),dr(20),fkmj real bcoef(n),x, aj(kmax),dl(kmax),dr(kmax),fkmj dimension t(n+k) c former fortran standard made it impossible to specify the length of t c precisely without the introduction of otherwise superfluous addition- c al arguments. bvalue = 0. if (jderiv .ge. k) go to 99 c c *** Find i s.t. 1 .le. i .lt. n+k and t(i) .lt. t(i+1) and c t(i) .le. x .lt. t(i+1) . If no such i can be found, x lies c outside the support of the spline f , hence bvalue = 0. c (The asymmetry in this choice of i makes f rightcontinuous, except c at t(n+k) where it is leftcontinuous.) call interv ( t, n+k, x, i, mflag ) if (mflag .ne. 0) go to 99 c *** if k = 1 (and jderiv = 0), bvalue = bcoef(i). km1 = k - 1 if (km1 .gt. 0) go to 1 bvalue = bcoef(i) go to 99 c c *** store the k b-spline coefficients relevant for the knot interval c (t(i),t(i+1)) in aj(1),...,aj(k) and compute dl(j) = x - t(i+1-j), c dr(j) = t(i+j) - x, j=1,...,k-1 . set any of the aj not obtainable c from input to zero. set any t.s not obtainable equal to t(1) or c to t(n+k) appropriately. 1 jcmin = 1 imk = i - k if (imk .ge. 0) go to 8 jcmin = 1 - imk do 5 j=1,i 5 dl(j) = x - t(i+1-j) do 6 j=i,km1 aj(k-j) = 0. 6 dl(j) = dl(i) go to 10 8 do 9 j=1,km1 9 dl(j) = x - t(i+1-j) c 10 jcmax = k nmi = n - i if (nmi .ge. 0) go to 18 jcmax = k + nmi do 15 j=1,jcmax 15 dr(j) = t(i+j) - x do 16 j=jcmax,km1 aj(j+1) = 0. 16 dr(j) = dr(jcmax) go to 20 18 do 19 j=1,km1 19 dr(j) = t(i+j) - x c 20 do 21 jc=jcmin,jcmax 21 aj(jc) = bcoef(imk + jc) c c *** difference the coefficients jderiv times. if (jderiv .eq. 0) go to 30 do 23 j=1,jderiv kmj = k-j fkmj = float(kmj) ilo = kmj do 23 jj=1,kmj aj(jj) = ((aj(jj+1) - aj(jj))/(dl(ilo) + dr(jj)))*fkmj 23 ilo = ilo - 1 c c *** compute value at x in (t(i),t(i+1)) of jderiv-th derivative, c given its relevant b-spline coeffs in aj(1),...,aj(k-jderiv). 30 if (jderiv .eq. km1) go to 39 jdrvp1 = jderiv + 1 do 33 j=jdrvp1,km1 kmj = k-j ilo = kmj do 33 jj=1,kmj aj(jj) = (aj(jj+1)*dl(ilo) + aj(jj)*dr(jj))/(dl(ilo)+dr(jj)) 33 ilo = ilo - 1 39 bvalue = aj(1) c 99 return end subroutine interv ( xt, lxt, x, left, mflag ) c from * a practical guide to splines * by C. de Boor computes left = max( i : xt(i) .lt. xt(lxt) .and. xt(i) .le. x ) . c c****** i n p u t ****** c xt.....a real sequence, of length lxt , assumed to be nondecreasing c lxt.....number of terms in the sequence xt . c x.....the point whose location with respect to the sequence xt is c to be determined. c c****** o u t p u t ****** c left, mflag.....both integers, whose value is c c 1 -1 if x .lt. xt(1) c i 0 if xt(i) .le. x .lt. xt(i+1) c i 0 if xt(i) .lt. x .eq. xt(i+1) .eq. xt(lxt) c i 1 if xt(i) .lt. xt(i+1) .eq. xt(lxt) .lt. x c c In particular, mflag = 0 is the 'usual' case. mflag .ne. 0 c indicates that x lies outside the CLOSED interval c xt(1) .le. y .le. xt(lxt) . The asymmetric treatment of the c intervals is due to the decision to make all pp functions cont- c inuous from the right, but, by returning mflag = 0 even if C x = xt(lxt), there is the option of having the computed pp function c continuous from the left at xt(lxt) . c c****** m e t h o d ****** c The program is designed to be efficient in the common situation that c it is called repeatedly, with x taken from an increasing or decrea- c sing sequence. This will happen, e.g., when a pp function is to be c graphed. The first guess for left is therefore taken to be the val- c ue returned at the previous call and stored in the l o c a l varia- c ble ilo . A first check ascertains that ilo .lt. lxt (this is nec- c essary since the present call may have nothing to do with the previ- c ous call). Then, if xt(ilo) .le. x .lt. xt(ilo+1), we set left = c ilo and are done after just three comparisons. c Otherwise, we repeatedly double the difference istep = ihi - ilo c while also moving ilo and ihi in the direction of x , until c xt(ilo) .le. x .lt. xt(ihi) , c after which we use bisection to get, in addition, ilo+1 = ihi . c left = ilo is then returned. c integer left,lxt,mflag, ihi,ilo,istep,middle real x,xt(lxt) data ilo /1/ save ilo ihi = ilo + 1 if (ihi .lt. lxt) go to 20 if (x .ge. xt(lxt)) go to 110 if (lxt .le. 1) go to 90 ilo = lxt - 1 ihi = lxt c 20 if (x .ge. xt(ihi)) go to 40 if (x .ge. xt(ilo)) go to 100 c c **** now x .lt. xt(ilo) . decrease ilo to capture x . istep = 1 31 ihi = ilo ilo = ihi - istep if (ilo .le. 1) go to 35 if (x .ge. xt(ilo)) go to 50 istep = istep*2 go to 31 35 ilo = 1 if (x .lt. xt(1)) go to 90 go to 50 c **** now x .ge. xt(ihi) . increase ihi to capture x . 40 istep = 1 41 ilo = ihi ihi = ilo + istep if (ihi .ge. lxt) go to 45 if (x .lt. xt(ihi)) go to 50 istep = istep*2 go to 41 45 if (x .ge. xt(lxt)) go to 110 ihi = lxt c c **** now xt(ilo) .le. x .lt. xt(ihi) . narrow the interval. 50 middle = (ilo + ihi)/2 if (middle .eq. ilo) go to 100 c note. it is assumed that middle = ilo in case ihi = ilo+1 . if (x .lt. xt(middle)) go to 53 ilo = middle go to 50 53 ihi = middle go to 50 c**** set output and return. 90 mflag = -1 left = 1 return 100 mflag = 0 left = ilo return 110 mflag = 1 if (x .eq. xt(lxt)) mflag = 0 left = lxt 111 if (left .eq. 1) return left = left - 1 if (xt(left) .lt. xt(lxt)) return go to 111 end