module conmod 1 contains SUBROUTINE sort_up(arr) 1 IMPLICIT NONE double precision, DIMENSION(:), INTENT(INOUT) :: arr INTEGER :: i,j,n double precision :: a n=size(arr) do j=2,n a=arr(j) do i=j-1,1,-1 if (arr(i) <= a) exit arr(i+1)=arr(i) end do arr(i+1)=a end do END SUBROUTINE sort_up SUBROUTINE sort_down(arr) IMPLICIT NONE double precision, DIMENSION(:), INTENT(INOUT) :: arr INTEGER :: i,j,n double precision :: a n=size(arr) do j=2,n a=arr(j) do i=j-1,1,-1 if (arr(i) >= a) exit arr(i+1)=arr(i) end do arr(i+1)=a end do END SUBROUTINE sort_down SUBROUTINE resort(arr,irr) 2 IMPLICIT NONE double precision, DIMENSION(:), INTENT(INOUT) :: arr double precision, DIMENSION(:), allocatable :: brr INTEGER :: k,n,irr(:) n=size(arr) allocate(brr(n)) brr=arr do k=1,n arr(k)=brr(irr(k)) end do deallocate(brr) END SUBROUTINE resort SUBROUTINE isort(arr,irr) 2 IMPLICIT NONE integer, DIMENSION(:), INTENT(INOUT) :: arr integer, DIMENSION(:), allocatable :: brr INTEGER :: k,n,irr(:) n=size(arr) allocate(brr(n)) brr=arr do k=1,n arr(k)=brr(irr(k)) end do deallocate(brr) END SUBROUTINE isort SUBROUTINE sort_up2(arr,irr) 1 IMPLICIT NONE double precision, DIMENSION(:), INTENT(INOUT) :: arr INTEGER :: i,j,k,m,n,irr(:) double precision :: a n=size(arr) do k=1,n irr(k)=k end do do j=2,n a=arr(j) m=irr(j) do i=j-1,1,-1 if (arr(i) <= a) exit arr(i+1)=arr(i) irr(i+1)=irr(i) end do arr(i+1)=a irr(i+1)=m end do END SUBROUTINE sort_up2 SUBROUTINE sort_down2(arr,irr) 1 IMPLICIT NONE double precision, DIMENSION(:), INTENT(INOUT) :: arr INTEGER :: i,j,k,m,n,irr(:) double precision :: a n=size(arr) do k=1,n irr(k)=k end do do j=2,n a=arr(j) m=irr(j) do i=j-1,1,-1 if (arr(i) >= a) exit arr(i+1)=arr(i) irr(i+1)=irr(i) end do arr(i+1)=a irr(i+1)=m end do END SUBROUTINE sort_down2 double precision function value(c,xx,yy) 16 implicit double precision (a-h,o-z) dimension c(4,4) value=& (((((c(4,4)*yy+c(3,4))*yy+c(2,4))*yy+c(1,4))*xx & +(((c(4,3)*yy+c(3,3))*yy+c(2,3))*yy+c(1,3)))*xx & +(((c(4,2)*yy+c(3,2))*yy+c(2,2))*yy+c(1,2)))*xx & +(((c(4,1)*yy+c(3,1))*yy+c(2,1))*yy+c(1,1)) return end function value double precision function dvdy(c,xx,yy) 4 implicit double precision (a-h,o-z) dimension c(4,4) dvdy=& (((((c(4,4)*3*yy+c(3,4)*2)*yy+c(2,4)))*xx & +(((c(4,3)*3*yy+c(3,3)*2)*yy+c(2,3))))*xx & +(((c(4,2)*3*yy+c(3,2)*2)*yy+c(2,2))))*xx & +(((c(4,1)*3*yy+c(3,1)*2)*yy+c(2,1))) return end function dvdy double precision function dvdx(c,xx,yy) 4 implicit double precision (a-h,o-z) dimension c(4,4) dvdx=& ((((c(4,4)*yy+c(3,4))*yy+c(2,4))*yy+c(1,4))*3*xx & +(((c(4,3)*yy+c(3,3))*yy+c(2,3))*yy+c(1,3))*2)*xx & +(((c(4,2)*yy+c(3,2))*yy+c(2,2))*yy+c(1,2)) return end function dvdx end module conmod subroutine square_con(q,xco,yco,cl,nc,ierr,idebug) 1,22 use conmod !implicit double precision (a-h,o-z) implicit none type four sequence double precision,dimension(4) :: val,d1,d2,d12 end type four type(four) q,xco,yco double precision,dimension(4) :: e,xv,yv double precision,dimension(4,4) :: c,cxco,cyco double precision,allocatable :: sr(:),vr(:),& xa(:),ya(:),va(:),xp(:,:),yp(:,:) integer, allocatable :: ia(:),is(:),mb(:),np(:),ic(:),icl(:),ih(:),icsa(:) double precision r(3),xs(300),ys(300),xout(1500),yout(1500) double precision x,y,v,vv,den,alf,fac,dx,dy,s,vx,vy,dummy,& angle,dangle,anglel,dist,arco,pi,bet,xt,yt,dyt,dxt,del integer ns,nwall,nsl,nsadl,ntodo,iout,icolor,newmt,& i,j,k,m,n,mt,nz,nk,nc,newmb,nr,iside,idesperate,icyc,ierr,& idebug double precision :: cl(nc) data xv /0.,1.,1.,0./ data yv /0.,0.,1.,1./ nz=12*nc pi=4*atan(1.) allocate(sr(3*nc),vr(3*nc),ia(3*nc),icl(3*nc)) allocate(xa(nz),ya(nz),va(nz),is(nz),mb(nz),& xp(100,nz),yp(100,nz),np(nz),ic(nz),ih(nz),icsa(nz)) call sort_up(cl) call bcucof(q%val,q%d1,q%d2,q%d12,1.d0,1.d0,c) call bcucof(xco%val,xco%d1,xco%d2,xco%d12,1.d0,1.d0,cxco) call bcucof(yco%val,yco%d1,yco%d2,yco%d12,1.d0,1.d0,cyco) call grid_box(xv,yv) call find_boundary_intersect if (nk.eq.0) then call one_color goto 2001 end if ierr=10 ntodo=nk mt=1 newmt=1 ih=0 icyc=0 do while (ntodo.gt.1) icyc=icyc+1 if (icyc.gt.nk*nk) then ierr=1 goto 2001 end if if (newmt.ne.mt) then mt=newmt else mt=mod(mt,nk)+1 newmt=mt end if m=mb(mt) write (79,'(i4,i4,f9.5,f9.5)', advance='yes') m,mt,va(m),va(mt) if (va(m).eq.va(mt).and.ih(mt).eq.0) then call start_trip do while (nwall.lt.2) fac=min(2*fac,1.d0) call get_dx_dy; if (idebug.eq.1) write (79,*) " first"; find_acceptable: do anglel=atan2(dy,dx) x=x+dx y=y+dy if (idebug.eq.1) write(79,*)'x,y=',x,y,"before improve" call improve_root call eval call get_dx_dy if (dx.eq.0) dy=ya(mt)-y if (dy.eq.0) dx=xa(mt)-x angle=atan2(dy,dx) dangle=min(abs(angle-anglel),2*pi-abs(angle-anglel)) if (dangle.lt.pi/2.and.idebug.eq.1) write(79,*) "dangle=",dangle if (dangle.lt.pi/2.) exit call jump_back if (idesperate.eq.1.and.idebug.eq.1) write(79,*) "desperate" if (idesperate.eq.1) exit end do find_acceptable ns=ns+1 xs(ns)=x ys(ns)=y if (idebug.eq.1) write (79,*) 'x,y=',x,y, " before chk" call check_boundary if (idebug.eq.1) write (79,*) 'x,y=',x,y, " after chk" if (nwall.eq.2) then if (idebug.eq.1) write (79,*) "x,y=",x,y," nwall=2" if (abs(x).lt.0.001) then x=0.; call improve_root_y; end if if (abs(1-x).lt.0.001) then x=1.; call improve_root_y; end if if (abs(y).lt.0.001) then y=0.; call improve_root_x; end if if (abs(1-y).lt.0.001) then y=1.; call improve_root_x; end if dist=sqrt((x-xa(mt))**2+(y-ya(mt))**2) if (dist.lt.0.001) then call successful_trip else !write (*,*) ' wall, but not hit' write (79,'(a,4es10.3)') ' not hit',x,xa(mt),y,ya(mt) end if end if if (ns.ge.300) then write (79,'(a)') ' no wall' !write (*,*) m,mt,x,y stop end if end do else write (79,'(a)') ' do not try' end if end do 2001 continue if (ierr.ne.0) then if (ntodo.eq.2) then i=1 do while (ih(i).eq.1.and.i.le.nk) i=i+1 end do m=i do while (ih(i).eq.1.and.i.le.nk) i=i+1 end do mt=i+1 write (*,*) 'cheating with straight line',m,mt ns=2 xs(1)=xa(m) ys(1)=ya(m) xs(2)=xa(mt) ys(2)=ya(mt) call successful_trip else call one_color end if end if deallocate(sr,vr,ia,icl) deallocate(xa,ya,va,is,mb,& xp,yp,np,ic,ih,icsa) return contains subroutine one_color 2,1 implicit none double precision qaver xout(1)=0. yout(1)=0. xout(2)=1. yout(2)=0. xout(3)=1. yout(3)=1. xout(4)=0. yout(4)=1. iout=4 icolor=1 qaver=.25*(q%val(1)+q%val(2)+q%val(3)+q%val(4)) do i=1,nc if (cl(i).lt.qaver) icolor=i+1 end do call ps_area(xout,yout,iout,icolor+2) end subroutine one_color subroutine jump_back 1,3 implicit none !write (*,'(a,i4,a,f7.3,a,f7.3)') 'saddle? ns=',ns,' x=',x,' y=',y !!!if (nsl.eq.ns) nsadl=nsadl+1 nsadl=nsadl+1 if (idebug.eq.1) write (79,*) ' nsadl=', nsadl x=xs(ns) y=ys(ns) fac=fac/4. call eval call get_dx_dy if (nsadl.gt.10) then fac=0.1 call get_dx_dy dummy=dx dx=dy dy=-dummy dx=(xa(mt)-x)*fac*abs(alf) dy=(ya(mt)-y)*fac*abs(alf) write (79,'(a,i4,a,2es11.3)',advance='yes') ' nsadl=',nsadl,' turn ',dx,dy nsadl=0 if (ns.eq.1) idesperate=1 end if nsl=ns end subroutine jump_back subroutine start_trip 1,1 implicit none x=xa(m) y=ya(m) v=va(m) ns=1 xs(ns)=x ys(ns)=y alf=.05 call eval if (idebug.eq.1) write (79,*) x,y,vv if (idebug.eq.1) write (79,*) 'alf before=',alf if (is(m).eq.4.and.vy.lt.0.) alf=-alf if (is(m).eq.2.and.vy.gt.0.) alf=-alf if (is(m).eq.1.and.vx.gt.0.) alf=-alf if (is(m).eq.3.and.vx.lt.0.) alf=-alf if (idebug.eq.1) write (79,*) 'alf after=',alf nwall=0 fac=1. nsl=-99 nsadl=0 idesperate=0 end subroutine start_trip subroutine eval 3,3 implicit none vv=value(c,x,y) vx=dvdx(c,x,y) vy=dvdy(c,x,y) end subroutine eval subroutine get_dx_dy 4 implicit none den=vx**2+vy**2 if (den.le.0.) then write (*,*) ' vx=0 and vy=0, stop' stop end if s=sqrt(den) dx=fac*alf*vy/s dy=-fac*alf*vx/s if (idebug.eq.1) write (79,'(a,4es11.4)') 'dx,dy,x,y=',dx,dy,x,y end subroutine get_dx_dy subroutine successful_trip 2,4 implicit none ih(mt)=1 ih(m)=1 x=xa(mt) y=ya(mt) xs(ns)=x ys(ns)=y ntodo=ntodo-2 iout=0 do i=1,ns iout=iout+1 xout(iout)=xs(i) yout(iout)=ys(i) end do icolor=0 if (v.lt.0.) icolor=1 call ps_line(xout,yout,iout,icolor) do i=1,np(mt) iout=iout+1 xout(iout)=xp(i,mt) yout(iout)=yp(i,mt) end do do i=1,iout ! write (*,'(a,f9.5,a,f9.5)') ' x=',xout(i),' y=',yout(i) end do icsa(m)=icshft() icolor=ic(m)+icsa(m) write (79,*) ' success, ntodo=',ntodo,' icolor=',icolor write (79,'(20i2)') (ih(i),i=1,nk) call ps_area(xout,yout,iout,icolor+2) newmt=mod(mt,nk)+1 do while (ih(newmt).eq.1.and.ntodo.ne.0) newmt=mod(newmt,nk)+1 end do newmb=mod(nk+m-2,nk)+1 do while (ih(newmb).eq.1.and.ntodo.ne.0) newmb=mod(nk+newmb-2,nk)+1 end do write (79,*) 'newmb=',newmb,' ih=',ih(newmb),'newmt=',newmt,' ih=',ih(newmt) mb(newmt)=newmb do i=ns,1,-1 np(newmt)=np(newmt)+1 xp(np(newmt),newmt)=xs(i) yp(np(newmt),newmt)=ys(i) end do if (newmt.ne.m) then do i=1,np(m) np(newmt)=np(newmt)+1 xp(np(newmt),newmt)=xp(i,m) yp(np(newmt),newmt)=yp(i,m) end do end if if (ntodo.eq.0) then ! write (*,*) ' ntodo=',ntodo iout=0 do i=1,np(newmt) !write (*,'(a,f9.5,a,f9.5)') ' xp=',xp(i,newmt),' yp=',yp(i,newmt) iout=iout+1 xout(iout)=xp(i,newmt) yout(iout)=yp(i,newmt) end do icolor=ic(newmt)+1-icsa(newmt) call ps_area(xout,yout,iout,icolor+2) ierr=0 end if write (79,'(a)') ' hit ' end subroutine successful_trip function icshft() 1,2 implicit none integer icshft vx=dvdx(c,xout(1),yout(1)) vy=dvdy(c,xout(1),yout(1)) dummy=(xout(2)-xout(1))*vy-(yout(2)-yout(1))*vx icshft=0 if (dummy.lt.0.) icshft=1 end function icshft subroutine find_boundary_intersect 1,11 implicit none nk=0 do iside=1,4 !write (*,'(es10.3)') c if (iside.eq.1) call edgey(e,c,0.d0) if (iside.eq.2) call edgex(e,c,1.d0) if (iside.eq.3) call edgey(e,c,1.d0) if (iside.eq.4) call edgex(e,c,0.d0) nr=0. do i=1,nc call real_roots(e,r,cl(i),n) ! write (*,'(3i4,4f9.5)') iside,nc,n,e !tempor do k=1,n nr=nr+1 sr(nr)=r(k) vr(nr)=cl(i) icl(nr)=i end do end do if (iside.eq.1.or.iside.eq.2) then call sort_up2(sr(1:nr),ia) call resort(vr(1:nr),ia) call isort(icl(1:nr),ia) end if if (iside.eq.3.or.iside.eq.4) then call sort_down2(sr(1:nr),ia) call resort(vr(1:nr),ia) call isort(icl(1:nr),ia) end if do i=1,nr nk=nk+1 va(nk)=vr(i) is(nk)=iside ic(nk)=icl(i) if (iside.eq.1) then xa(nk)=sr(i) ya(nk)=0. end if if (iside.eq.2) then ya(nk)=sr(i) xa(nk)=1. end if if (iside.eq.3) then xa(nk)=sr(i) ya(nk)=1. end if if (iside.eq.4) then ya(nk)=sr(i) xa(nk)=0. end if end do end do if (mod(nk,2).ne.0) then write (*,*) ' nk=',nk,'...not even...stop' end if do i=2,nk mb(i)=i-1 np(i)=0 end do mb(1)=nk np(1)=0 !tempor but OK? do i=1,nk n=is(i) if (mb(i).lt.i) then do while (n.ne.is(mb(i))) np(i)=np(i)+1 xp(np(i),i)=xv(n) yp(np(i),i)=yv(n) n=n-1 if (n.eq.0) n=4 end do else n=n+4 do while (n.ne.is(mb(i))) np(i)=np(i)+1 xp(np(i),i)=xv(mod(n-1,4)+1) yp(np(i),i)=yv(mod(n-1,4)+1) n=n-1 end do end if end do do i=1,nk write (79,'(i4,3f9.4,4i5)') i,xa(i),ya(i),va(i),is(i),mb(i),np(i),ic(i) !do j=1,np(i) !write (*,*) xp(j,i),yp(j,i) !end do end do end subroutine find_boundary_intersect subroutine check_boundary 1,5 implicit none x=xs(ns-1) y=ys(ns-1) xt=xs(ns) yt=ys(ns) dx=xt-x dy=yt-y if (xt.lt.0.or.xt.gt.1.or.yt.lt.0.or.yt.gt.1.) then nwall=nwall+1 if (xt.gt.1.) then dxt=min(1.-x,dx) dyt=dy*dxt/dx xt=x+dxt yt=y+dyt dx=dxt dy=dyt !x=xt; y=yt; call improve_root_y end if if (xt.lt.0.) then dxt=max(-x,dx) dyt=dy*dxt/dx xt=x+dxt yt=y+dyt dx=dxt dy=dyt !x=xt; y=yt; call improve_root_y end if x=xt y=yt if (yt.gt.1.) then dyt=min(1.-y,dy) dxt=dx*dyt/dy xt=x+dxt yt=y+dyt !x=xt; y=yt; call improve_root_x end if if (yt.lt.0.) then dyt=max(-y,dy) dxt=dx*dyt/dy xt=x+dxt yt=y+dyt !x=xt; y=yt; call improve_root_x end if end if x=xt y=yt call improve_root xs(ns)=x ys(ns)=y end subroutine check_boundary subroutine improve_root 2,3 implicit none do i=1,5 vv=value(c,x,y) vx=dvdx(c,x,y) vy=dvdy(c,x,y) den=vx**2+vy**2 bet=-(vv-v)/den x=x+bet*vx y=y+bet*vy end do end subroutine improve_root subroutine improve_root_x !not used 4,2 implicit none do i=1,5 vv=value(c,x,y) vx=dvdx(c,x,y) x=x-(vv-v)/vx end do end subroutine improve_root_x subroutine improve_root_y !not used 4,2 implicit none do i=1,5 vv=value(c,x,y) vy=dvdy(c,x,y) y=y-(vv-v)/vy end do end subroutine improve_root_y subroutine ps_area(x,y,n,icolor) 3,4 integer n,icolor double precision x(n),y(n) character jnum*4 write(jnum(2:4),'(i3.3)') icolor write(jnum(1:1),'(a)') 'C' write (97,'(a)') jnum write (97,'(f8.5,f8.5,a)') value(cxco,x(1),y(1)),value(cyco,x(1),y(1)),' M' do i=2,n write (97,'(f8.5,f8.5,a)') value(cxco,x(i),y(i)),value(cyco,x(i),y(i)),' L' end do write (97,*) ' P' end subroutine ps_area subroutine ps_line(x,y,n,icolor) 1,4 integer n,icolor double precision x(n),y(n) character jnum*4 write(jnum(2:4),'(i3.3)') icolor write(jnum(1:1),'(a)') 'C' write (98,'(a)') jnum write (98,'(f8.5,f8.5,a)') value(cxco,x(1),y(1)),value(cyco,x(1),y(1)),' M' do i=2,n write (98,'(f8.5,f8.5,a)') value(cxco,x(i),y(i)),value(cyco,x(i),y(i)),' L' end do write (98,*) ' S' end subroutine ps_line subroutine grid_box(x,y) 1,4 double precision x(4),y(4) double precision xq,yq,xz,yz do n=1,4 xq=x(n) yq=y(n) xz=x(mod(n,4)+1)-xq yz=y(mod(n,4)+1)-yq write (99,'(f8.5,f8.5,a)') value(cxco,xq,yq),value(cyco,xq,yq),' M' do i=1,10 write (99,'(f8.5,f8.5,a)') value(cxco,xq+.1*i*xz,yq+.1*i*yz),& value(cyco,xq+.1*i*xz,yq+.1*i*yz),' L' end do end do write (99,*) ' G' end subroutine grid_box end subroutine square_con subroutine ps_area_old(x,y,n,icolor) double precision x(n),y(n) integer n,icolor character jnum*4 write(jnum(2:4),'(i3.3)') icolor write(jnum(1:1),'(a)') 'C' write (97,'(a)') jnum write (97,'(f8.5,f8.5,a)') x(1),y(1),' M' do i=2,n write (97,'(f8.5,f8.5,a)') x(i),y(i),' L' end do write (97,*) ' P' end subroutine ps_area_old subroutine edgey(e,c,y) 2 implicit double precision (a-h,o-z) dimension e(4),c(4,4) do n=1,4 e(n)=(c(1,n)+y*(c(2,n)+y*(c(3,n)+y*c(4,n)))) end do return end subroutine edgey subroutine edgex(e,c,x) 2 implicit double precision (a-h,o-z) dimension e(4),c(4,4) do n=1,4 e(n)=(c(n,1)+x*(c(n,2)+x*(c(n,3)+x*c(n,4)))) end do return end subroutine edgex SUBROUTINE BCUCOF(Y,Y1,Y2,Y12,D1,D2,CL) 3 implicit double precision (a-h,o-z) DIMENSION Y(4),Y1(4),Y2(4),Y12(4),CL(16),X(16),WT(16,16) DATA WT/1.,0.,-3.,2.,4*0.,-3.,0.,9.,-6.,2.,0.,-6.,& 4.,8*0.,3.,0.,-9.,6.,-2.,0.,6.,-4.,10*0.,9.,-6.,& 2*0.,-6.,4.,2*0.,3.,-2.,6*0.,-9.,6.,2*0.,6.,-4.,& 4*0.,1.,0.,-3.,2.,-2.,0.,6.,-4.,1.,0.,-3.,2.,8*0.,& -1.,0.,3.,-2.,1.,0.,-3.,2.,10*0.,-3.,2.,2*0.,3.,& -2.,6*0.,3.,-2.,2*0.,-6.,4.,2*0.,3.,-2.,0.,1.,-2.,& 1.,5*0.,-3.,6.,-3.,0.,2.,-4.,2.,9*0.,3.,-6.,3.,0.,& -2.,4.,-2.,10*0.,-3.,3.,2*0.,2.,-2.,2*0.,-1.,1.,& 6*0.,3.,-3.,2*0.,-2.,2.,5*0.,1.,-2.,1.,0.,-2.,4.,& -2.,0.,1.,-2.,1.,9*0.,-1.,2.,-1.,0.,1.,-2.,1.,10*0.,& 1.,-1.,2*0.,-1.,1.,6*0.,-1.,1.,2*0.,2.,-2.,2*0.,-1.,1./ D1D2=D1*D2 DO I=1,4 X(I)=Y(I) X(I+4)=Y1(I)*D1 X(I+8)=Y2(I)*D2 X(I+12)=Y12(I)*D1D2 END DO DO I=1,16 CL(I)=& WT(I,1)*X(1)& +WT(I,2)*X(2)& +WT(I,3)*X(3)& +WT(I,4)*X(4)& +WT(I,5)*X(5)& +WT(I,6)*X(6)& +WT(I,7)*X(7)& +WT(I,8)*X(8)& +WT(I,9)*X(9)& +WT(I,10)*X(10)& +WT(I,11)*X(11)& +WT(I,12)*X(12)& +WT(I,13)*X(13)& +WT(I,14)*X(14)& +WT(I,15)*X(15)& +WT(I,16)*X(16) end do RETURN END subroutine bcucof subroutine real_roots(e,s,v,nn) 1,3 double precision :: r(6),e(4),ec(4),v,s(3) call roots(e,r,v,n) nn=0 do i=1,n if (r(2*i).eq.0.and.& r(2*i-1).ge.0.and.r(2*i-1).le.1.) then nn=nn+1 s(nn)=r(2*i-1) end if end do if (nn.gt.1) call remove_double(s,nn) do ii=1,nn-1 do i=1,nn-1 if (s(i).gt.s(i+1)) call exchange(s(i),s(i+1)) end do end do return end subroutine real_roots subroutine remove_double(s,nn) 1 double precision:: s(3) integer nn if (nn.eq.2) then if (s(2).eq.s(1)) nn=0 else if (nn.eq.3) then if (s(2).eq.s(1)) then nn=1 s(1)=s(3) else if (s(3).eq.s(1)) then s(1)=s(2) nn=1 else if (s(2).eq.s(3)) then nn=1 end if end if end subroutine remove_double subroutine exchange(a,b) 1 double precision a,b,c c=a a=b b=c return end subroutine exchange subroutine roots(e,r,v,n) 1,3 double precision :: r(6),e(4),ec(4),v ec=e r=0. n=0 ec(1)=ec(1)-v !write (*,*) 'in roots ec(4)',ec !if (sum(abs(ec(2:4))).lt.abs(ec(1))) return if (abs(ec(4)).gt.1.e-8*maxval(abs(ec))) then do n=1,4 ec(n)=ec(n)/ec(4) end do call cubik (ec,r) n=3 else if (abs(ec(3)).gt.1.e-8*maxval(abs(ec))) then call quadratic(ec,r) n=2 else if (abs(ec(2)).gt.1.e-8*maxval(abs(ec))) then call linear(ec,r) n=1 else n=0 end if end subroutine roots subroutine cubik (c,x) 1 implicit double precision (a-h,o-z) dimension c(3),x(6) ! solve x**3+c(3)*x**2+c(2)*x+c(1)=0. ! complex roots are x=x(1)+ix(2), etc. q=(c(3)**2-3*c(2))/9. r=(2*c(3)**3-9*c(3)*c(2)+27*c(1))/54. if (r**2.lt.q**3) then ! three real roots del=8*datan(1.d0)/3. sq=2*dsqrt(q) th3=dacos(r/dsqrt(q**3))/3. a3=c(3)/3. x(1)=-sq*dcos(th3)-a3 x(2)=0. x(3)=-sq*dcos(th3+del)-a3 x(4)=0. x(5)=-sq*dcos(th3-del)-a3 x(6)=0. else ! one real and two complex conjugates a=-dsign(1.d0,r)*(dabs(r)+dsqrt(r**2-q**3))**(1./3.) b=0. if(a.ne.0.) b=q/a x(1)=(a+b)-c(3)/3. x(2)=0. x(3)=-.5*(a+b)-c(3)/3. x(4)=.5*dsqrt(3.d0)*(a-b) x(5)=x(3) x(6)=-x(4) end if return end subroutine quadratic (c,x) 1 implicit double precision (a-h,o-z) dimension c(3),x(4) complex(kind(1.d0)) qq,rr ! solve c(3)*x**2+c(2)*x+c(1)=0. d=c(2)*c(2)-4*c(3)*c(1) if (d.ge.0.) then q=-0.5*(c(2)+sign(sqrt(d),c(2))) x(1)=q/c(3) x(2)=0. x(3)=c(1)/q x(4)=0. else qq=cmplx(-0.5*c(2),-0.5*sign(sqrt(-d),c(2))) rr=qq/c(3) x(1)=real(rr) x(2)=aimag(rr) rr=c(1)/qq x(3)=real(rr) x(4)=aimag(rr) end if return end subroutine quadratic subroutine linear(c,x) 1 implicit double precision (a-h,o-z) dimension c(2),x(2) x(1)=-c(1)/c(2) x(2)=0. return end subroutine linear