!Christen this file schurQR.f !ut here >>>>>>>>>>>>>>>>>>> ! Copyright (C) 2011 Roger Fletcher ! Current version dated 17 January 2012 ! THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC ! LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM ! CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT !***************** sparse matrix routines for manipulating L ******************* ! ********************************************************** ! Basis matrix routines for LCP solvers with sparse matrices ! ********************************************************** ! These routines form and update L-Implicit-U factors LPB=U of a matrix B ! whose columns are the normal vectors of the active constraints. In this ! method only the unit lower triangular matrix L and the diagonal of U (in ! addition to the row permutation P) is stored. B is represented in block form ! | I A_2 | where the last m1 columns (A_2 and A_1) come from the ! | 0 A_1 | general constraint normals (columns of the matrix A in bqpd) ! and the remaining unit columns come from simple bounds. The matrix A must be ! specified in sparse format and the user is referred to the file sparseA.f. ! The data structure used for L is that of a profile or skyline scheme, in ! which the nontrivial rows of L are stored as dense row spikes. The use of ! a Tarjan+spk1 ordering algorithm to control the length of these spikes has ! proved quite effective. ! In schurQR.f, the factors are updated by the Schur complement method with ! QR factors. This is based on the block factorization ! ! | B V | = | L 0 | | U V | ! | E 0 | | S I | | 0 C | ! ! where V are columns of the constraint normals [I A] that have been added to ! the active set, and E has unit rows in which the unit element marks ! columns of B that have been removed from B. C=-E.inv(B).V is the ! Schur complement matrix, which is independent of how L and U are defined, ! and its QR factors are stored. The current dimension of C is stored in the ! parameter ms of common/refactorc/mc,mxmc and the user must set a ! maximum permitted value of mc in mxmc (mxmc <= n). The current basis matrix ! is refactored if mc would exceed mxmc, or if issues of numerical stability ! arise. Typically mxmc=25 is suitable. ! Workspace ! ********* ! The user needs to supply storage for the row spikes in the LIU data ! structure of L, Also storage for matrices in the Schur complement scheme ! is required. The amount of storage required is unknown a-priori. ! Storage for schurQR.f is situated at the end of the workspace arrays ws ! and lws in bqpd. Allow as much space for ws as you can afford: the routine ! will report if there is not enough. So far 10^6 locations has proved ! adequate for problems of up to 5000 variables. ! The user is also allowed to reserve storage in ws and lws, for use in the ! user-supplied routine gdotx. This storage is situated at the start of the ! arrays ws and lws. The user specifies the amount required by ! setting the parameters kk and ll in the common block ! common/wsc/kk,ll,kkk,lll,mxws,mxlws ! Storage required by the LCP solver is also required: the amount is set by ! the LCP solver in kkk and lll. The user MUST set mxws and mxlws to be ! the total amount of real and integer workspace for the arrays ws and lws. ! Other information ! ***************** ! The methodology behind the L-Implicit-U factors and the row spike storage ! scheme for L is described in the references ! Fletcher R., Dense Factors of Sparse Matrices, in "Approximation Theory ! and Optimization. Tributes to M.J.D. Powell", (M.D. Buhmann and A. Iserles, ! eds), Cambridge University Press (1997), pp. 145-166. ! and ! Fletcher R., Block Triangular Orderings and Factors for Sparse Matrices ! in LP, in "Numerical analysis 1997" (D.F. Griffiths, D.J. Higham and ! G.A. Watson, eds.), Pitman Research Notes in Mathematics 380, (1998), ! Longman, Harlow, pp. 91-110. ! The file contains routines for solving systems with B or its transpose ! which might be of use in association with bqpd. These routines are ! documented below. ! Steepest edge coefficients e(i) are also updated in these routines subroutine start_up(n,nm,nmi,a,la,nk,e,ls,aa,ll,mode,ifail) implicit double precision (a-h,r-z), integer (i-q) dimension a(*),la(0:*),e(*),ls(*),aa(*),ll(*) common/noutc/nout common/wsc/kk,ll_,kkk,lll,mxws,mxlws common/epsc/eps,tol,emin common/schurc/ns,ns1,nt,nt1,nu,nu1,nx,nx1,np,np1,neb,neb1,nprof, & lc,lc1,li,li1,lm,lm1,lp,lp1,lq,lq1,lr,lr1,ls_,ls1,lt,lt1, & nq,nq1,nr,nr1,ny,ny1,nz,nz1,lv,lv1,le,le1 common/factorc/m1,m2,mp,mq,lastr,irow common/refactorc/mc,mxmc mxmc=min(n,mxmc) ! set storage map for sparse factors ns=n ns1=ns+1 nt=ns+n nt1=nt+1 nu=nt+n nu1=nu+1 nx=nu+n nx1=nx+1 nq=nx+n nq1=nq+1 nr=nq+mxmc**2 nr1=nr+1 ny=nr+mxmc*(mxmc+1)/2 ny1=ny+1 nz=ny+mxmc+1 nz1=nz+1 np=nz+mxmc+1 np1=np+1 nprof=mxws-kk-kkk-np ! print *,'nprof =',nprof if (nprof<=0) then write(nout,*)'not enough real workspace in ws' write(nout,*)'you give mxws as',mxws write(nout,*)'mxws must be much greater than',mxws-nprof ifail=7 return end if lc=n lc1=lc+1 li=lc+n li1=li+1 lm=li+nmi lm1=lm+1 lp=lm+n lp1=lp+1 lq=lp+n lq1=lq+1 lr=lq+n lr1=lr+1 ls_=lr+n ls1=ls_+1 lt=ls_+n lt1=lt+1 lv=lt+n lv1=lv+1 le=lv+mxmc+1 le1=le+1 lleft=mxlws-ll_-lll-le-mxmc-1 if (lleft<0) then write(nout,*)'not enough integer workspace in lws' write(nout,*)'you give mxlws as',mxlws write(nout,*)'minimum value for mxlws is',mxlws-lleft ifail=7 return end if m=nm-n mp=-1 mq=-1 ! write(nout,*)'ls',(ls(ij),ij=1,nk) if (mode==3) then if (nk<n) then ! reset ls from e do j=1,nk i=-ls(j) if (i>0)e(i)=-e(i) end do j=0 nk=nmi do i=1,nmi if (e(i)/=0.D0) then j=j+1 if (e(i)>0.D0) then ls(j)=i else ls(j)=-i e(i)=-e(i) end if else ls(nk)=i nk=nk-1 end if end do if (j/=n) then write(nout,*)'malfunction in reset sequence in start_up' stop end if end if ! reset lr, lc, li, m1 and m2 from ls do i=li+n+1,li+nm ll(i)=0 end do m1=n m2=0 do j=1,n i=abs(ls(j)) if (i>n) then ll(lc+m1)=i ll(li+i)=m1 m1=m1-1 else m2=m2+1 lii=ll(li+i) lrm2=ll(m2) call iexch(ll(lii),ll(m2)) call iexch(ll(li+i),ll(li+lrm2)) end if end do m1=n-m1 call re_order(n,nm,a,la(1),la(la(0)),ll,ll(lc1),ll(li1), & ll(lm1),ll(lp1),ll(lq1),ll(lr1),ll(ls1),ll(lt1),aa(np1), & nprof,ifail) if (ifail>=1) then ! write(nout,*)'failure in re_order (1)' if (ifail==7) return mode=2 goto 1 end if call re_factor(n,nm,a,la,ll,ll(lc1),ll(li1), & ll(lm1),ll(lp1),ll(lq1),ll(lr1),ll(ls1),ll(lt1),aa(np1), & nprof,aa,ifail) if (ifail==7) return call check_L(n,aa,ll(lp1),ifail) if (ifail==1) then mode=2 goto 1 end if call EBspace(n,ll(lp1),ll(lq1),ll(ls1),ll,aa(np1), & neb,nprof,ifail) if (ifail>0) return neb=np+neb neb1=neb+1 mc=0 do i=1,m2 ll(lm+i)=ll(i) end do do i=m2+1,n ll(lm+i)=ll(lc+i) end do return end if 1 continue if (emin==0.D0) then ! set a lower bound on e(i): setting emin=0.D0 will force emin to be recalculated: do this only if mode<3 emin=1.D0 do i=1,nmi-n emin=max(emin,ailen(n,a,la,i)) end do emin=1.D0/emin end if do i=1,n ll(i)=i ll(li+i)=i e(i)=1.D0 end do do i=n+1,nm ll(li+i)=0 e(i)=0.D0 end do nu_=0 if (mode/=0) then ! shift designated bounds to end and order the resulting rows and columns do j=1,nk i=abs(ls(j)) if (i<=n) then nn=n-nu_ nu_=nu_+1 call iexch(ls(nu_),ls(j)) ii=ll(li+i) ll(ii)=ll(nn) ll(li+ll(ii))=ii ll(nn)=i ll(li+i)=nn end if end do call order(n,nu_,nk,la,ll,ls,ll(li1),ll(lp1),ll(lq1),ll(lr1), & aa(np1),nprof,ifail) if (ifail>0) return end if call factor(n,nm,nu_,nk,a,la,e,ls,aa(ns1),aa(nt1),aa(nu1), & aa(nx1),ll,ll(lc1),ll(li1),ll(lm1),ll(lp1),ll(lq1),ll(lr1), & ll(ls1),aa(np1),nprof,aa,ifail) call EBspace(n,ll(lp1),ll(lq1),ll(ls1),ll,aa(np1), & neb,nprof,ifail) if (ifail>0) return neb=np+neb neb1=neb+1 mc=0 do i=1,m2 ll(lm+i)=ll(i) end do do i=m2+1,n ll(lm+i)=ll(lc+i) end do if (ifail>0) return 3 format(A/(15I5)) 4 format(A/(5E15.7)) ! write(nout,*)'steepest edge coefficients',(e(ij),ij=1,nm) ! emax=0.D0 ! do i=1,nm ! if (e(i)>0.D0) then ! call eptsol(n,a,la,i,a,aa(nq1),aa(nr1),aa(neb1),aa(ny1), ! * aa(ns1),aa(nu1),aa(nx1),aa,aa(np1), ! * ll,ll(lc1),ll(li1),ll(lv1),ll(le1),ll(lp1),ll(lq1),ei) ! emax=max(emax,abs(ei-e(i))) ! end if ! end do ! if (emax>=tol) ! * write(nout,*)'error in steepest edge coefficients =',emax return end subroutine refactor(n,nm,a,la,aa,ll,ifail) implicit double precision (a-h,o-z) dimension a(*),la(0:*),aa(*),ll(*) common/schurc/ns,ns1,nt,nt1,nu,nu1,nx,nx1,np,np1,neb,neb1,nprof, & lc,lc1,li,li1,lm,lm1,lp,lp1,lq,lq1,lr,lr1,ls_,ls1,lt,lt1, & nq,nq1,nr,nr1,ny,ny1,nz,nz1,lv,lv1,le,le1 common/factorc/m1,m2,mp,mq,lastr,irow common/noutc/nout ! write(nout,*)'refactor' ifail=1 return end subroutine pivot(p,q,n,nm,a,la,e,aa,ll,ifail,npv) implicit double precision (a-h,r-z), integer (i-q) dimension a(*),la(0:*),e(*),aa(*),ll(*) common/noutc/nout common/iprintc/iprint common/schurc/ns,ns1,nt,nt1,nu,nu1,nx,nx1,np,np1,neb,neb1,nprof, & lc,lc1,li,li1,lm,lm1,lp,lp1,lq,lq1,lr,lr1,ls_,ls1,lt,lt1, & nq,nq1,nr,nr1,ny,ny1,nz,nz1,lv,lv1,le,le1 common/factorc/m1,m2,mp,mq,lastr,irow common/mxm1c/mxm1 common/refactorc/mc,mxmc common/epsc/eps,tol,emin common/pqc/pc,qr,lmp ! write(nout,*)'pivot: p,q =',p,q call updateSE(p,q,n,nm,a,la,e,aa(nq1),aa(nr1),aa(neb1), & aa(ny1),aa(nz1),aa(ns1),aa(nt1),aa(nu1),aa(nx1),aa,aa(np1),ll, & ll(lc1),ll(li1),ll(lp1),ll(lq1),ll(lm1),ll(lv1),ll(le1),ifail) if (ifail==1) return if (mc==mxmc .and. pc==0 .and. qr==0) then ! reset permutations and refactorize L mc1=mc+1 ll(le+mc1)=p ll(lv+mc1)=q ! print 3,'le =',(ll(le+i),i=1,mc1) ! print 3,'lv =',(ll(lv+i),i=1,mc1) do i=1,mc1 p=ll(le+i) q=ll(lv+i) ip=ll(li+p) if (p>n) then m2=m2+1 qq=ll(lc+m2) ll(lc+ip)=qq ll(li+qq)=ip ll(li+p)=0 else ll(ip)=ll(m2) ll(li+ll(ip))=ip ll(m2)=p ll(li+p)=m2 end if if (q>n) then ll(lc+m2)=q ll(li+q)=m2 m2=m2-1 else iq=ll(li+q) ll(iq)=ll(m2) ll(li+ll(iq))=iq ll(m2)=q ll(li+q)=m2 end if end do ! print 3,'lr =',(ll(i),i=1,n) ! print 3,'lc =',(ll(lc+i),i=m2+1,n) ! print 3,'li =',(ll(li+i),i=1,nm) m1=n-m2 ! call checkperms(n,ll,ll(lc1),ll(li1)) ! mp=-1 ! mq=-1 call re_order(n,nm,a,la(1),la(la(0)),ll,ll(lc1),ll(li1), & ll(lm1),ll(lp1),ll(lq1),ll(lr1),ll(ls1),ll(lt1),aa(np1), & nprof,ifail) if (ifail>=1) then ! print *,'no traversal in re_order (3)' ifail=11 return stop end if call re_factor(n,nm,a,la,ll,ll(lc1),ll(li1), & ll(lm1),ll(lp1),ll(lq1),ll(lr1),ll(ls1),ll(lt1),aa(np1), & nprof,aa,ifail) if (ifail==7) return call EBspace(n,ll(lp1),ll(lq1),ll(ls1),ll,aa(np1), & neb,nprof,ifail) if (ifail>0) return neb=np+neb neb1=neb+1 mc=0 do i=1,m2 ll(lm+i)=ll(i) end do do i=m2+1,n ll(lm+i)=ll(lc+i) end do else call updateQR(p,q,n,a,la,aa(nq1),aa(nr1),aa(neb1),aa(nx1), & aa(ny1),aa(nz1),ll,ll(lc1),ll(li1),ll(lv1),ll(le1),ll(lm1), & ifail) if (ifail>0) return end if npv=npv+1 mp=-1 mq=-1 ! call check_L(n,aa,ll(lp1),ifail) ! print 4,'e =',(e(i),i=1,nm) ! print 3,'lm =',(ll(lm+i),i=1,n) return ! check Steepest Edge coefficients emax=0.D0 do j=1,n i=ll(lm+j) call eptsol(n,a,la,i,a,aa(nq1),aa(nr1),aa(neb1),aa(ny1), & aa(ns1),aa(nu1),aa(nx1),aa,aa(np1), & ll,ll(lc1),ll(li1),ll(lv1),ll(le1),ll(lp1),ll(lq1),ei) emax=max(emax,abs(ei-e(i))) ! if (abs(ei-e(i))>tol) then ! print *,'error in steepest edge coefficient =',i,ei,e(i) ! print 4,'s =',(aa(ns+i),i=1,n) ! if (abs(ei-e(i))>1.D-6) stop ! end if end do if (emax>tol) then print 2,'max error in steepest edge coefficients =',emax ! if (emax>1.D-2) stop end if return 2 format(A,5E15.7) 3 format(A/(15I5)) 4 format(A/(5E15.7)) 5 format((5E15.7)) end subroutine fbsub(n,jmin,jmax,a,la,q,b,x,ls,aa,ll,save) implicit double precision (a-h,r-z), integer (i-q) logical save 9 format(A/(15I5)) dimension a(*),la(*),b(*),x(*),ls(*),aa(*),ll(*) ! solves a system B.x=b ! Parameter list ! ************** ! n number of variables (as for bqpd) ! jmin,jmax now redundant ! a,la specification of QP problem data (as for bqpd) ! q an integer which, if in the range 1:n+m, specifies that the rhs vector ! b is to be column q of the matrix A of general constraint normals. ! In this case the parameter b is not referenced by fbsub. ! If q=0 then b is taken as the vector given in the parameter b. ! b(n) must be set to the r.h.s. vector b in natural order (but only if q=0) ! x(n+m) contains the solution x, set according to the index number of that ! component (in the range 1:n for a simple bound and n+1:n+m ! for a general constraint) ! ls(*) now redundant. Previously ls was an index vector, listing the ! components of x that are required. Now all the solution x is provided, ! set as described above. ! aa(*) real storage used by the basis matrix code (supply the vector ! ws(lu1) with ws as in the call of bqpd and lu1 as in common/bqpdc/...) ! ll(*) integer storage used by the basis matrix code (supply the vector ! lws(ll1) with lws as in the call of bqpd and ll1 as in common/bqpdc/...) ! save now redundant common/noutc/nout common/schurc/ns,ns1,nt,nt1,nu,nu1,nx,nx1,np,np1,neb,neb1,nprof, & lc,lc1,li,li1,lm,lm1,lp,lp1,lq,lq1,lr,lr1,ls_,ls1,lt,lt1, & nq,nq1,nr,nr1,ny,ny1,nz,nz1,lv,lv1,le,le1 common/factorc/m1,m2,mp,mq,lastr,irow ! write(nout,*)'fbsub q =',q if (q==0) then do i=1,n aa(nt+ll(li+i))=b(i) end do end if call aqsol(n,a,la,q,aa(nq1),aa(nr1),aa(neb1),aa(nz1),aa(nt1), & aa(nu1),aa(nx1),aa,aa(np1),ll,ll(lc1),ll(li1),ll(lv1), & ll(le1),ll(lp1),ll(lq1)) do j=1,n x(ll(lm+j))=aa(nt+j) end do ! print *,'x =',(x(i),i=1,18) return end subroutine ztg(n,k,rg,lv,aa,ll) implicit double precision (a-h,r-z), integer (i-q) dimension rg(*),lv(*),aa(*),ll(*) common/schurc/ns,ns1,nt,nt1,nu,nu1,nx,nx1,np,np1,neb,neb1,nprof, & lc,lc1,li,li1,lm,lm1,lp,lp1,lq,lq1,lr,lr1,ls_,ls1,lt,lt1, & nq,nq1,nr,nr1,ny,ny1,nz,nz1,lv_,lv1,le,le1 ! print *,'aa =',(aa(nu+i),i=1,18) do j=1,k rg(j)=aa(nu+ll(li+lv(j))) end do return end subroutine tfbsub(n,a,la,p,b,x,aa,ll,ep,save) implicit double precision (a-h,r-z), integer (i-q) logical save dimension a(*),la(*),b(*),x(*),aa(*),ll(*) ! solves a system Bt.x=b ! Parameter list ! ************** ! n number of variables (as for bqpd) ! a,la specification of QP problem data (as for bqpd) ! p an integer which, if in the range 1:n+m, specifies that the rhs vector ! b is a unit vector appropriate to the position of p in the current ! ordering. In this case b is not referenced by tfbsub. ! b(n+m) If p=0, this must be set to the r.h.s. vector b. Only the components ! of b need be set, according to the index number of each component (in ! the range 1:n for a simple bound and n+1:n+m for a general constraint) ! x(n) contains the solution x (in natural ordering) ! aa(*) real storage used by the basis matrix code (supply the vector ! ws(lu1) with ws as in the call of bqpd and lu1 as in common/bqpdc/...) ! ll(*) integer storage used by the basis matrix code (supply the vector ! lws(ll1) with lws as in the call of bqpd and ll1 as in common/bqpdc/...) ! ep if p>0, ep contains the L2 norm of the solution ! save now redundant common/noutc/nout common/schurc/ns,ns1,nt,nt1,nu,nu1,nx,nx1,np,np1,neb,neb1,nprof, & lc,lc1,li,li1,lm,lm1,lp,lp1,lq,lq1,lr,lr1,ls_,ls1,lt,lt1, & nq,nq1,nr,nr1,ny,ny1,nz,nz1,lv,lv1,le,le1 common/factorc/m1,m2,mp,mq,lastr,irow ! write(nout,*)'tfbsub p =',p call eptsol(n,a,la,p,b,aa(nq1),aa(nr1),aa(neb1),aa(ny1), & aa(ns1),aa(nu1),aa(nx1),aa,aa(np1),ll,ll(lc1),ll(li1), & ll(lv1),ll(le1),ll(lp1),ll(lq1),ep) do i=1,n x(ll(i))=aa(ns+i) end do ! print 4,'x =',(x(i),i=1,n) 4 format(A/(5E15.7)) return end subroutine newg common/factorc/m1,m2,mp,mq,lastr,irow mq=-1 return end !******** The following routines are internal to schurQR.f ************** subroutine check_L(n,d,p,ifail) implicit double precision (a-h,r-z), integer (i-q) dimension d(*),p(*) common/noutc/nout common/factorc/m1,nu,mp,mq,lastr,irow common/epsc/eps,tol,emin write(nout,*)'check_L' ifail=1 dmin=1.D37 do k=nu+1,n dmin=min(dmin,abs(d(k))) ! if (abs(d(k))<=tol) return end do write(nout,*)'dmin =',dmin ! len=0 ! do i=1,n ! len=len+p(i) ! end do ! write(nout,*)m1*(m1+1)/2,len+m1 ! write(nout,*)'m1 =',m1,' file length =',len,' total =',len+m1 ifail=0 return end subroutine aqsol(n,a,la,q,Q_,R,EB,z,t,u,x,d,ws, & lr,lc,li,lv,le,pp,qq) implicit double precision (a-h,r-z), integer (i-q) double precision Q_ dimension a(*),la(*),Q_(*),R(*),EB(*),z(*),t(*),u(*),x(*), & d(*),ws(*),lr(*),lc(*),li(*),lv(*),le(*),pp(*),qq(*) common/factorc/m1,m2,mp,mq,lastr,irow common/refactorc/mc,mxmc common/pqc/pc,qr,lmp ! print *,'aqsol q =',q if (q>0) then ! print *,'q,n,li(q),m2',q,n,li(q),m2 if (q<=n .and. li(q)<=m2 .or. q>n .and. li(q)>0) then ! q is in the starting active set (and hence in row qr of E) do qr=1,mc if (q==le(qr)) goto 10 end do print *,'malfunction: q not in E' stop 10 continue else ! q is a new column qr=0 end if ! form t=Bk^{-1}.aq, else form t=Bk^{-1}.t ! scatter a_q into t liq=li(q) do i=1,n t(i)=0.D0 end do if (q<=n) then t(liq)=1.D0 else call iscatter(a,la,q-n,li,t,n) end if end if ! print 4,'t=',(t(i),i=1,n) if (mc>0) then ! form u=E.B^{-1}.t and possibly z=-u if (q==0 .or. q>n .and. qr==0) then i1=1 do i=1,mc ! print 4,'EB =',(EB(j),j=i1,i1+m1-1) u(i)=scpr(0.D0,EB(i1),t(m2+1),m1) if (le(i)<=n)u(i)=u(i)+t(li(le(i))) z(i)=-u(i) i1=i1+m1 end do else if (qr>0) then do i=1,mc u(i)=0.D0 end do u(qr)=1.D0 else ! print 4,'EB =',(EB(j),j=1,m1*mc) liq=liq-m2 do i=1,mc u(i)=EB(liq) z(i)=-u(i) liq=liq+m1 end do end if ! print 4,'u=',(u(i),i=1,mc) ! form x=C^{-1}.u call Qtprod(mc,mxmc,Q_,u,x) mm=mc*(3-mc)/2+(mc-1)*mxmc call rsol(mc,mm,mxmc,R,x) ! print 4,'x=',(x(i),i=1,mc) ! accumulate t=t+V.x do i=1,mc lvi=lv(i) if (lvi<=n) then t(li(lvi))=t(li(lvi))+x(i) else call isaipy(x(i),a,la,lvi-n,t,n,lr,li) end if end do end if ! print 4,'t in natural order =',(t(li(i)),i=1,n) ! finally t:=B^{-1}.t-E'.x call aqsol0(n,a,la,0,t,u,d,ws,lr,lc,li,pp,qq) do i=1,mc lei=li(le(i)) t(lei)=t(lei)-x(i) end do ! print 4,'t in column order',(t(i),i=1,n) mq=q return 3 format(A/(15I5)) 4 format(A/(5E15.7)) end subroutine aqsol0(n,a,la,q,tn,xn,d,ws,lr,lc,li,pp,qq) implicit double precision (a-h,r-z), integer (i-q) dimension a(*),la(*),tn(*),xn(*),d(*),ws(*), & lr(*),lc(*),li(*),pp(*),qq(*) common/factorc/m1,m2,mp,mq,lastr,irow if (q>0) then do i=1,n tn(i)=0.D0 end do if (q<=n) then tn(li(q))=1.D0 else call iscatter(a,la,q-n,li,tn,n) end if end if ! print *,'tn =',(tn(i),i=1,n) do i=n,m2+1,-1 ir=lr(i) pri=pp(ir) if (pri==0) then xn(i)=tn(i)/d(i) else xn(i)=(scpr(tn(i),ws(qq(ir)+1),tn(i-pri),pri))/d(i) end if call isaipy(-xn(i),a,la,lc(i)-n,tn,n,lr,li) end do do i=m2+1,n tn(i)=xn(i) end do ! print *,'tn =',(tn(i),i=1,n) return end subroutine eptsol(n,a,la,p,b,Q_,R,EB,y,s,u,x,d,ws, & lr,lc,li,lv,le,pp,qq,ep) implicit double precision (a-h,r-z), integer (i-q) double precision Q_ dimension a(*),la(*),b(*),Q_(*),R(*),EB(*),y(*),s(*),u(*),x(*), & d(*),ws(*),lr(*),lc(*),li(*),lv(*),le(*),pp(*),qq(*) common/epsc/eps,tol,emin common/factorc/m1,m2,mp,mq,lastr,irow common/refactorc/mc,mxmc common/pqc/pc,qr,lmp ! print *,'eptsol p =',p ! column ordering is that defined by Bk = B + (V-B.E').E ! row order is same as for B if (p==0) then ! print 3,'lr =',(lr(i),i=1,m2) ! print 3,'lc =',(lc(i),i=m2+1,n) ! print 3,'le =',(le(i),i=1,mc) ! print 3,'lv =',(lv(i),i=1,mc) do i=1,mc x(i)=b(le(i)) b(le(i))=0.D0 end do call eptsol0(n,a,la,0,b,s,d,ws,lr,lc,li,pp,qq) do i=1,mc b(le(i))=x(i) if (lv(i)<=n) then x(i)=s(li(lv(i)))-b(lv(i)) else x(i)=aiscpri(n,a,la,lv(i)-n,s,-b(lv(i)),lr,li) end if end do else if (p<=n .and. li(p)<=m2 .or. p>n .and. li(p)>0) then ! p is in the starting active set (set pc=0) pc=0 lmp=li(p) else ! p is in V (pc indicates where p is in V) do pc=1,mc if (p==lv(pc)) goto 10 end do print 1,'p,pc,li(p),m1,m2 =',p,pc,li(p),m1,m2 print 3,'le =',(le(i),i=1,mc) print 3,'lv =',(lv(i),i=1,mc) print *,'malfunction: p not in V' stop 10 continue lmp=li(le(pc)) end if ! get s=Bk^{-T}.ep if (pc==0) then call eptsol0(n,a,la,p,a,s,d,ws,lr,lc,li,pp,qq) ! print 4,'s0 ordered by lr',(s(i),i=1,n) ! print 4,'s0 in natural order',(s(li(i)),i=1,n) m1mc=m1*mc do i=1,m1 EB(m1mc+i)=s(m2+i) end do ! print 1,'eptsol: p =',p ! print 4,'EB is',(s(i),i=m2+1,n) ! print 4,'EB is',(EB(i),i=1,m1mc+m1) ! form s=B^{-T}.ep and then y=-V'.s do i=1,mc if (lv(i)<=n) then x(i)=s(li(lv(i))) else x(i)=aiscpri(n,a,la,lv(i)-n,s,0.D0,lr,li) end if y(i)=-x(i) end do else ! this is pc>0: set s=0 and x=-e_pc do i=1,n s(i)=0.D0 end do do i=1,mc x(i)=0.D0 end do x(pc)=-1.D0 end if end if ! print 4,'x =',(x(i),i=1,mc) if (mc>0) then ! form u=C^{-T}.x and accumulate EB'.u into s call rtsol(mc,mm,mxmc,R,x) call Qprod(mc,mxmc,Q_,x,u) i1=1 do i=1,mc call mysaxpy(u(i),EB(i1),s(m2+1),m1) if (le(i)<=n)s(li(le(i)))=u(i) i1=i1+m1 end do end if ! print 4,'sk in natural order=',(s(li(i)),i=1,n) ! print 4,'s =',(s(i),i=1,n) mp=p if (p>0)ep=xlen(0.D0,s,n) return 1 format(A,15I5) 2 format(A,6E15.7) 3 format(A/(15I5)) 4 format(A/(5E15.7)) end subroutine eptsol0(n,a,la,p,b,sn,d,ws,lr,lc,li,pp,qq) implicit double precision (a-h,r-z), integer (i-q) dimension a(*),la(*),b(*),sn(*),d(*),ws(*), & lr(*),lc(*),li(*),pp(*),qq(*) common/epsc/eps,tol,emin common/factorc/m1,m2,mp,mq,lastr,irow if (p==0) then do i=1,m2 sn(i)=b(lr(i)) end do do i=m2+1,n sn(i)=0.D0 end do do i=m2+1,n j=lc(i) sn(i)=-aiscpri(n,a,la,j-n,sn,-b(j),lr,li)/d(i) ir=lr(i) pri=pp(ir) if (pri>0) call mysaxpy(sn(i),ws(qq(ir)+1),sn(i-pri),pri) end do else do i=1,n sn(i)=0.D0 end do pr=li(p) if (p<=n) then if (pr>m2) goto 1 sn(pr)=1.D0 do i=m2+1,n sn(i)=-aiscpri(n,a,la,lc(i)-n,sn,0.D0,lr,li)/d(i) ir=lr(i) pri=pp(ir) if (pri>0) call mysaxpy(sn(i),ws(qq(ir)+1),sn(i-pri),pri) end do else if (pr<=m2) goto 1 do i=m2+1,n bi=0.D0 if (i==pr)bi=-1.D0 sn(i)=-aiscpri(n,a,la,lc(i)-n,sn,bi,lr,li)/d(i) ir=lr(i) pri=pp(ir) if (pri>0) call mysaxpy(sn(i),ws(qq(ir)+1),sn(i-pri),pri) end do end if end if ! print *,'sn =',(sn(i),i=1,n) return 1 continue print *,'malfunction detected in eptsol0: p =',p stop end subroutine order(n,nu,nc,la,lr,ls,li,p,q,r,ws,mxws,ifail) implicit integer (c-t) double precision ws dimension la(0:*),lr(*),ls(*),li(*),p(*),q(*),r(*),ws(*) common/noutc/nout ! character star(1000,80) ! write(nout,*)'order' ! spk1 ordering on full matrix ifail=0 if (nu==n) return ! set row and column counts and row-wise data structure nn=n-nu ii=mxws/nn do j=1,nn rowj=lr(j) p(rowj)=(j-1)*ii r(rowj)=0 end do do j=nn+1,n r(lr(j))=0 end do 1 continue do i=nu+1,nc coli=abs(ls(i)) li(coli)=0 jp=la(0)+coli-n do j=la(jp),la(jp+1)-1 rowj=la(j) if (li(rowj)<=nn) then li(coli)=li(coli)+1 r(rowj)=r(rowj)+1 ij=p(rowj)+r(rowj) if (ij>mxws) then ij=mxws ifail=1 end if ws(ij)=dble(coli) end if end do end do ! check for no overlaps qrj=0 do j=1,nn rowj=lr(j) if (p(rowj)<qrj)ifail=1 qrj=p(rowj)+r(rowj) q(rowj)=qrj p(rowj)=p(rowj)+1 end do if (ifail==1 .or. qrj>mxws) then qrj=0 do j=1,nn rowj=lr(j) p(rowj)=qrj qrj=qrj+r(rowj) r(rowj)=0 end do if (qrj>mxws) then write(nout,*)'not enough space for ws in order: mxws =',mxws ifail=7 return end if ifail=0 goto 1 end if ifirstc=nu+1 ifirstr=1 2 continue ! move zero-column-count columns to lhs and find minimum column count mcc=n do i=ifirstc,nc coli=abs(ls(i)) if (li(coli)==0) then call iexch(ls(i),ls(ifirstc)) li(coli)=ifirstr-1 ifirstc=ifirstc+1 else mcc=min(mcc,li(coli)) end if end do ! write(nout,*)'ifirstc,ifirstr,mcc',ifirstc,ifirstr,mcc ! write(nout,*)'lr =',(lr(j),j=1,n) ! write(nout,*)'ls =',(ls(i),i=nu+1,nc) ! write(nout,*)'row counts =',(r(lr(j)),j=1,n) ! write(nout,*)'column counts =',(li(abs(ls(i))),i=nu+1,nc) if (ifirstc>nc) goto 4 ! apply tie-break rule tie=0 do i=ifirstc,nc coli=abs(ls(i)) if (li(coli)==mcc) then ti=0 jp=la(0)+coli-n do j=la(jp),la(jp+1)-1 rowj=la(j) if (li(rowj)>=ifirstr)ti=ti+r(rowj) end do if (ti>tie) then tie=ti mccc=coli end if end if end do ! write(nout,*)'tie,mccc',tie,mccc ! permute rows of m-c-c column to top and update column counts jp=la(0)+mccc-n do j=la(jp),la(jp+1)-1 rowj=la(j) jr=li(rowj) if (jr<ifirstr) goto 3 if (jr>nn) goto 3 lr(jr)=lr(ifirstr) li(lr(jr))=jr lr(ifirstr)=rowj li(rowj)=ifirstr ifirstr=ifirstr+1 do i=p(rowj),q(rowj) coli=int(ws(i)) li(coli)=li(coli)-1 end do 3 continue end do goto 2 4 continue ! print star diagram ! if (nc-nu>80 .or. n>1000) stop ! write(nout,*)'spk1 ordering' ! ij=li(abs(ls(nc))) ! do i=1,ij ! do j=1,nc-nu ! star(i,j)=' ' ! end do ! end do ! do j=1,nc-nu ! jp=la(0)+abs(ls(nu+j))-n ! do i=la(jp),la(jp+1)-1 ! star(li(la(i)),j)='*' ! end do ! end do ! do i=1,ij ! write(nout,*)(star(i,j),j=1,nc-nu) ! end do ! write(nout,*)'lr =',(lr(i),i=1,n) ! write(nout,*)'ls =',(ls(i),i=nu+1,nc) ! write(nout,*)'lower profile =',(li(abs(ls(i))),i=nu+1,nc) return end subroutine factor(n,nm,nu,nc,a,la,e,ls,sn,tn,un,xn,lr,lc,li, & mao,p,q,r,s,ws,mxws,d,ifail) implicit double precision (a-h,r-z), integer (i-q) integer coli,r,s,rowi,rowp,tl,tu dimension a(*),la(0:*),e(*),ls(*),sn(*),tn(*),un(*),xn(*), & lr(*),lc(*),li(*),mao(*),p(*),q(*),r(*),s(*),ws(*),d(*) ! character star(1000,80) common/factorc/m1,m2,mp,mq,lastr,irow common/iprintc/iprint common/refactorc/mc,mxmc common/epsc/eps,tol,emin common/noutc/nout parameter (thresh=1.D-1) ! factorize LPA=U when A is rectangular ! p(row) stores the number of stored elements of a natural row ! q(row) stores the base address in ws of a natural row ! r(row) stores the previous row stored in ws (or 0 if the first row in ws) ! s(row) stores the next row stored in ws (or 0 if the last row in ws) ! li(n+*) stores the lower profile of the sparse matrix ! irow stores the natural row number of the initial row stored in ws ! lastr stores the natural row number of the previous row put into ws ! write(nout,*)'factor' nup=0 lastr=0 irow=0 do i=1,n p(i)=0 end do m1=0 tl=1 do ii=nu+1,nc coli=abs(ls(ii)) ! write(nout,*)'coli =',coli tu=li(coli) do i=1,n tn(i)=0.D0 end do call iscatter(a,la,coli-n,li,tn,n) do i=m1,1,-1 rowi=lr(i) pri=p(rowi) if (pri==0) then xn(i)=tn(i)/d(i) else xn(i)=(scpr(tn(i),ws(q(rowi)+1),tn(i-pri),pri))/d(i) end if call isaipy(-xn(i),a,la,lc(i)-n,tn,n,lr,li) end do do i=1,m1 tn(i)=xn(i) end do m1p=m1+1 ! write(nout,*)'lr =',(lr(i),i=1,n) ! write(nout,*)'tn =',(tn(i),i=1,tu) ! threshold pivot selection call linf(tu-m1,tn(m1p),z,iz) if (z<=tol) then li(coli)=0 goto 2 end if zz=max(tol,z*thresh) do i=tl,tu q(lr(i))=m1p end do ! write(nout,*)'q =',(q(lr(i)),i=m1p,tu) iz=iz+m1 if (iz<tl) then z=0.D0 qri=m1p do j=m1p,tu tnj=abs(tn(j)) if (tnj>=zz) then qrj=q(lr(j)) if (qrj==qri) then if (tnj>z) then z=tnj iz=j end if else if (qrj>qri) then z=tnj iz=j qri=qrj end if end if end do end if tl=tu+1 ! write(nout,*)'zz,z,iz,m1,qri',zz,z,iz,m1,qri if (iz>m1p) then call rexch(tn(m1p),tn(iz)) call iexch(lr(m1p),lr(iz)) li(lr(m1p))=m1p li(lr(iz))=iz end if rowp=lr(m1p) ! reset q values qrp=q(rowp) do i=m1p+1,tu if (abs(tn(i))>tol) then rowi=lr(i) if (qrp<q(rowi))q(rowi)=qrp end if end do tnp=tn(m1p) do i=1,n sn(i)=0.D0 end do sn(m1p)=1.D0 do i=1,m1 sn(i)=-aiscpri(n,a,la,lc(i)-n,sn,0.D0,lr,li)/d(i) rowi=lr(i) pri=p(rowi) if (pri>0) call mysaxpy(sn(i),ws(q(rowi)+1),sn(i-pri),pri) end do ! write(nout,*)'sn =',(sn(i),i=1,m1) ! update steepest edge coefficients ep=e(rowp) e(rowp)=0.D0 eq=2.D0/ep do i=1,n un(i)=eq*sn(i) end do do i=m1,1,-1 rowi=lr(i) pri=p(rowi) if (pri==0) then xn(i)=un(i)/d(i) else xn(i)=(scpr(un(i),ws(q(rowi)+1),un(i-pri),pri))/d(i) end if call isaipy(-xn(i),a,la,lc(i)-n,un,n,lr,li) end do do i=1,m1 un(i)=xn(i) end do ! write(nout,*)'un =',(un(i),i=1,n) eq=ep/tnp do i=1,nm if (e(i)>0.D0) then j=li(i) ei=e(i) wi=tn(j)*eq awi=abs(wi) if (ei>=awi) then wi=wi/ei e(i)=max(emin,ei*sqrt(max(0.D0,1.D0+wi*(wi-un(j)/ei)))) else wi=ei/wi e(i)=max(emin,awi*sqrt(max(0.D0,1.D0+wi*(wi-un(j)/ei)))) end if end if end do e(coli)=max(emin,abs(eq)) do j=qrp,m1 if (abs(sn(j))>tol) goto 1 end do j=m1p 1 continue pri=m1p-j if (pri>0) then call newslot(rowp,pri,lastr,irow,p,q,r,s,ws,mxws,i,ifail) if (ifail>0) return p(rowp)=pri i=q(rowp) do j=j,m1 i=i+1 ws(i)=sn(j) end do end if m1=m1p ls(m1)=ls(ii) lc(m1)=coli li(coli)=m1 d(m1)=tnp 2 continue end do ! complete ls and reorder lr, lc and d do i=m1+1,n ls(i)=lr(i) end do j=n do i=1,nm if (e(i)==0.D0) then j=j+1 ls(j)=i end if end do m2=n-m1 do i=n,m2+1,-1 lc(i)=lc(i-m2) li(lc(i))=i lr(i)=lr(i-m2) li(lr(i))=i d(i)=d(i-m2) end do do i=1,m2 lr(i)=ls(m1+i) li(lr(i))=i end do ! reset mao ilast=n ii=ilast do i=ilast,m2+1,-1 mao(i)=ilast ii=min(ii,i-p(lr(i))) if (ii==i)ilast=i-1 end do ! write(nout,*)'PAQ factors: m1 =',m1 ! write(nout,4)'d =',(d(ij),ij=m2+1,n) ! do ij=m2+1,n ! rowp=lr(ij) ! if (p(rowp)/=0) then ! write(nout,*)'L(',rowp,')', ! * (ws(k),k=q(rowp)+1,q(rowp)+p(rowp)) ! end if ! end do ! print star diagram ! write(nout,*)'factored ordering: m1 =',m1 ! if (m1>80 .or. n>1000) stop ! do i=1,n ! do j=1,m1 ! star(i,j)=' ' ! end do ! end do ! do j=1,m1 ! jp=la(0)+lc(m2+j)-n ! do i=la(jp),la(jp+1)-1 ! star(li(la(i)),j)='*' ! end do ! end do ! do i=m2+1,n ! write(nout,*)(star(i,j),j=1,m1) ! end do ! write(nout,9)'ls =',(ls(j),j=1,n) ! write(nout,*)'s.e. coeffs =',(e(i),i=1,nm) ! write(nout,9)'lr =',(lr(j),j=1,n) ! write(nout,9)'lc =',(lc(j),j=m2+1,n) ! write(nout,9)'li =',(li(j),j=1,nm) ! write(nout,9)'mao =',(mao(j),j=m2+1,n) ! call checkout(n,a,la,lr,lc,li,p,q,r,s,ws,mxws,d) 4 format(A/(5E15.7)) 9 format(A/(15I5)) return end subroutine re_order(n,nm,a,la,point,lr,lc,li,mao,p,q,r,s, & t,ws,mxws,ifail) implicit double precision (a-h,u-z), integer (i-t) dimension a(*),la(*),point(0:*),lr(*),lc(*),li(*),mao(*), & p(*),q(*),r(*),s(*),t(*),ws(*) common/factorc/m1,nu,mp,mq,lastr,irow common/noutc/nout logical backtrack ! character star(1000,80) ! print star diagram ! if (n-nu>80 .or. n>1000) stop ! write(nout,*)'initial ordering' ! do i=1,n ! do j=1,n-nu ! star(i,j)=' ' ! end do ! end do ! do j=1,n-nu ! ilp=lc(nu+j)-n ! do i=point(ilp),point(ilp+1)-1 ! star(li(la(i)),j)='*' ! end do ! end do ! do i=nu+1,n ! write(nout,*)(star(i,j),j=1,n-nu) ! end do ! write(nout,*)'re_order' if (nu==n) then ifail=0 return end if m=nm-n ! transversal search do iq=nu+1,n backtrack=.false. istack=nu inode=iq nodec=lc(inode) nodec_n=nodec-n lap=point(nodec_n+1)-point(nodec_n) ! write(nout,*)'column node =',nodec,' look-ahead rows =', ! * (la(j),j=point(nodec_n),point(nodec_n)+lap-1) ! look-ahead loop 1 continue lap=lap-1 nextr=la(point(nodec_n)+lap) inext=li(nextr) if (inext>=iq) goto 4 if (lap>0) goto 1 li(nodec)=0 2 continue ! reassignment depth first search t(inode)=point(nodec_n+1)-point(nodec_n) ! write(nout,*)'column node =',nodec,' unfathomed rows =', ! * (la(j),j=point(nodec_n),point(nodec_n)+t(inode)-1) 3 continue ! examine successor nodes if (t(inode)==0) then if (istack==nu) then ifail=1 ! ifail=iq ! write(nout,*)'exit: ifail =',iq ! print *,'lc(iq) =',lc(iq) return end if istack=istack-1 backtrack=.true. if (istack==nu) then inode=iq else inode=mao(istack) end if ! write(nout,*)'backtrack to node at address =',inode nodec=lc(inode) nodec_n=nodec-n ! write(nout,*)'column node =',nodec,' unfathomed rows =', ! * (la(j),j=point(nodec_n),point(nodec_n)+t(inode)-1) goto 3 end if t(inode)=t(inode)-1 nextr=la(point(nodec_n)+t(inode)) inext=li(nextr) if (inext<=nu) goto 3 if (t(inext)>=0) goto 3 ! extend depth first search ! write(nout,*)'nextr,inext',nextr,inext inode=inext ! write(nout,*)'put node address on stack' istack=istack+1 mao(istack)=inode ! write(nout,*)'stack =',(mao(j),j=nu+1,istack) nodec=lc(inode) nodec_n=nodec-n lap=li(nodec) if (lap==0) goto 2 ! write(nout,*)'column node =',nodec,' look-ahead rows =', ! * (la(j),j=point(nodec_n),point(nodec_n)+lap-1) goto 1 4 continue ! write(nout,*)'new assignment found in row',nextr ! write(nout,*)'istack,inext,nextr',istack,inext,nextr ! if (istack>nu) write(nout,*)'stack =',(mao(j),j=nu+1,istack) li(nodec)=lap ! perform row permutation lr(inext)=lr(iq) li(lr(inext))=inext inode=iq do i=nu+1,istack inext=mao(i) lr(inode)=lr(inext) li(lr(inode))=inode inode=inext end do lr(inode)=nextr li(nextr)=inode ! write(nout,*)'lr =',(lr(j),j=nu+1,n) ! write(nout,*)'look-ahead lengths =',(li(lc(j)),j=nu+1,iq) t(iq)=-1 if (backtrack .or. istack>nu+1) then do i=nu+1,iq-1 t(i)=-1 end do end if do i=1,n if (li(i)>n) then write(nout,*)'iq =',iq stop end if end do end do ! write(nout,*)'transversal found' ! write(nout,*)'lr =',(lr(j),j=1,n) ! write(nout,*)'lc =',(lc(j),j=nu+1,n) ! print star diagram ! if (n-nu>80 .or. n>1000) stop ! write(nout,*)'transversal ordering' ! do i=1,n ! do j=1,n-nu ! star(i,j)=' ' ! end do ! end do ! do j=1,n-nu ! ilp=lc(nu+j)-n ! do i=point(ilp),point(ilp+1)-1 ! star(li(la(i)),j)='*' ! end do ! end do ! do i=nu+1,n ! write(nout,*)(star(i,j),j=1,n-nu) ! end do ! tarjan ordering do i=1,n q(i)=0 r(i)=0 end do ! reset li and pair off columns with rows do i=nu+1,n nodec=lc(i) li(nodec)=i t(lr(i))=nodec s(i)=0 end do do i=nu+1,n noder=lr(i) nodec=t(noder) lc(noder)=point(nodec-n+1)-point(nodec-n) li(nodec)=-1 end do ifath=nu istack=n+1 ! tarjan loop 10 continue istack=istack-1 inode=istack noder=lr(inode) if (lc(noder)==0) then write(nout,*)'malfunction: zero length' stop end if nodec=t(noder) 11 continue li(nodec)=lc(noder) mao(inode)=istack ! write(nout,*)'put new node',noder,' on stack' ! write(nout,*)'active part of lr =',(lr(j),j=ifath+1,n) ! write(nout,*)'ifath,istack =',ifath,istack ! write(nout,*)'column node =',nodec,' unfathomed rows =', ! * (la(j),j=point(nodec-n),point(nodec-n)+li(nodec)-1) 12 continue if (li(nodec)==0) then ! write(nout,*)'backtrack to previous nodes' 13 continue if (inode==n) goto 14 inext=inode+1 nextr=lr(inext) if (mao(inode)<mao(inext)) goto 14 inode=inext noder=nextr nodec=t(noder) if (li(nodec)==0) goto 13 ! write(nout,*)'stack =',(lr(j),j=istack,n) ! write(nout,*)'lengths =',(li(t(lr(j))),j=istack,n) ! write(nout,*)'column node =',nodec,' unfathomed rows =', ! * (la(j),j=point(nodec-n),point(nodec-n)+li(nodec)-1) goto 12 end if ! examine successors of current node li(nodec)=li(nodec)-1 nextr=la(point(nodec-n)+li(nodec)) inext=li(nextr) if (inext<=ifath) goto 12 q(nextr)=q(nextr)+1 nextc=t(nextr) ! write(nout,*)'nextc,nextr,inext',nextc,nextr,inext if (li(nextc)>=0) then mx=mao(inext) if (mao(inode)>=mx) goto 12 do j=istack,n if (mao(j)==mx) goto 12 mao(j)=mx end do write(nout,*)'malfunction' stop end if nodec=nextc noder=nextr istack=istack-1 inode=istack lr(inext)=lr(inode) li(lr(inext))=inext lr(inode)=noder li(noder)=inode goto 11 14 continue ! write(nout,*)'strong component identified' ! write(nout,*)'active part of lr =',(lr(j),j=ifath+1,n) ! write(nout,*)'ifath,istack,inode =',ifath,istack,inode,n ! shift forward strong component inext=istack-1 ir=inode-inext do j=istack,inode mao(j)=lr(j) end do do j=inext+ir,ifath+1+ir,-1 lr(j)=lr(j-ir) li(lr(j))=j end do mx=ifath+ir iq=inext-ifath ifath=ifath+1 do j=ifath,mx lr(j)=mao(j+iq) li(lr(j))=j mao(j)=mx end do istack=inode+1 ifath=mx ! write(nout,*)'active part of lr =',(lr(j),j=ifath+1,n) ! write(nout,*)'ifath,istack =',ifath,istack if (istack<=n) then inode=istack noder=lr(inode) nodec=t(noder) nodec_n=nodec-n ! write(nout,*)'column node =',nodec,' unfathomed rows =', ! * (la(j),j=point(nodec-n),point(nodec-n)+li(nodec)-1) goto 12 end if if (ifath<n) goto 10 ! end of tarjan process ! reset lc and li do i=nu+1,n lc(i)=t(lr(i)) li(lc(i))=i end do ! write(nout,*)'mao =',(mao(j),j=nu+1,n) ! write(nout,*)'q =',(q(j),j=1,n) ! write(nout,*)'lr =',(lr(j),j=1,n) ! write(nout,*)'lc =',(lc(j),j=nu+1,n) ! write(nout,*)'li =',(li(j),j=1,n+m) ! print star diagram ! if (n-nu>80 .or. n>1000) stop ! write(nout,*)'tarjan ordering' ! do i=1,n ! do j=1,n-nu ! star(i,j)=' ' ! end do ! end do ! do j=1,n-nu ! ilp=lc(nu+j)-n ! do i=point(ilp),point(ilp+1)-1 ! star(li(la(i)),j)='*' ! end do ! end do ! do i=nu+1,n ! write(nout,*)(star(i,j),j=1,n-nu) ! end do ! set up pointers for row-wise sparse structure p(1)=1 do i=1,n-1 p(i+1)=p(i)+q(i) q(i)=p(i)-1 end do if (p(n)+q(n)>mxws) then print *,'not enough space for ws in re_order' ifail=7 return end if q(n)=p(n)-1 i=nu+1 20 continue if (i==mao(i)) then t(i)=i else ! spk1 ordering on tarjan block ! set row and column counts do inode=i,mao(i) nodec=lc(inode) do j=point(nodec-n),point(nodec-n+1)-1 noder=la(j) if (li(noder)>=i) then q(noder)=q(noder)+1 ws(q(noder))=dble(nodec) s(inode)=s(inode)+1 end if end do end do ! print *,'r-c counts: i =',i,' mao(i) =',mao(i) ! print *,'q =',(q(j),j=i,mao(i)) ! print *,'s =',(s(j),j=i,mao(i)) ! find minimum-column-count column mcc=n do inode=i,mao(i) noder=lr(inode) r(noder)=q(noder)-p(noder)+1 mcc=min(mcc,s(inode)) end do ! write(nout,*)'i,mao(i),mcc',i,mao(i),mcc ! write(nout,*)'p =',(p(lr(j)),j=i,mao(i)) ! write(nout,*)'q =',(q(lr(j)),j=i,mao(i)) ! write(nout,*)'r =',(r(lr(j)),j=i,mao(i)) ! write(nout,*)'s =',(s(j),j=i,mao(i)) ! check for fully dense block if (mcc>mao(i)-i) then do inode=i,mao(i) t(inode)=mao(i) end do goto 22 end if ! determine spk1 ordering ifirstr=i ifirstc=i 21 continue ! apply tie-break rule tie=0 do inode=ifirstc,mao(i) if (s(inode)==mcc) then nodec=lc(inode)-n ti=0 do j=point(nodec),point(nodec+1)-1 noder=la(j) if (li(noder)>=ifirstr)ti=ti+r(noder) end do if (ti>tie) then tie=ti mccc=nodec end if end if end do ! write(nout,*)'tie,mccc',tie,mccc+n ! permute rows of m-c-c column to top and update column counts do j=point(mccc),point(mccc+1)-1 noder=la(j) ir=li(noder) if (ir>=ifirstr) then lr(ir)=lr(ifirstr) li(lr(ir))=ir lr(ifirstr)=noder li(noder)=ifirstr ifirstr=ifirstr+1 do ir=p(noder),q(noder) inode=li(int(ws(ir))) s(inode)=s(inode)-1 end do end if end do ! write(nout,*)'s =',(s(ij),ij=i,mao(i)) ! write(nout,*)'lr =',(lr(ij),ij=i,mao(i)) ! move zero-column-count columns to lhs and find minimum column count mcc=n do inode=ifirstc,mao(i) if (s(inode)==0) then nodec=lc(inode) lc(inode)=lc(ifirstc) li(lc(inode))=inode lc(ifirstc)=nodec li(nodec)=ifirstc s(inode)=s(ifirstc) t(ifirstc)=ifirstr-1 ifirstc=ifirstc+1 else mcc=min(mcc,s(inode)) end if end do ! write(nout,*)'lc =',(lc(ij),ij=i,mao(i)) ! write(nout,*)'ifirstc,mcc',ifirstc,mcc if (ifirstc<mao(i)) goto 21 end if 22 continue i=mao(i)+1 if (i<=n) goto 20 ! print star diagram ! if (n-nu>80 .or. n>1000) stop ! write(nout,*)'tarjan + spk1 ordering' ! do i=1,n ! do j=1,n-nu ! star(i,j)=' ' ! end do ! end do ! do j=1,n-nu ! ilp=lc(nu+j)-n ! do i=point(ilp),point(ilp+1)-1 ! star(li(la(i)),j)='*' ! end do ! end do ! do i=nu+1,n ! write(nout,*)(star(i,j),j=1,n-nu) ! end do ! write(nout,*)'lr =',(lr(j),j=nu+1,n) ! write(nout,*)'lc =',(lc(j),j=nu+1,n) ! write(nout,*)'lower profile =',(t(j),j=nu+1,n) ifail=0 return end subroutine re_factor(n,nm,a,la,lr,lc,li,mao,p,q,r,s, & t,ws,mxws,d,ifail) implicit double precision (a-h,u-z), integer (i-t) dimension a(*),la(0:*),lr(*),lc(*),li(*),mao(*), & p(*),q(*),r(*),s(*),t(*),d(*),ws(*) ! character star(1000,80) common/factorc/m1,nu,mp,mq,lastr,irow common/iprintc/iprint common/refactorc/mc,mxmc common/epsc/eps,tol,emin common/noutc/nout double precision thresh,tol parameter (thresh=1.D-1) ! factorize LPA=U ! p(row) stores the number of stored elements of a natural row ! q(row) stores the base address in ws of a natural row ! r(row) stores the previous row stored in ws (or 0 if the first row in ws) ! s(row) stores the next row stored in ws (or 0 if the last row in ws) ! t(*) stores the lower profile of the sparse matrix ! irow stores the natural row number of the initial row stored in ws ! lastr stores the natural row number of the previous row put into ws ! write(nout,*)'re_factor' nup=0 m=nm-n lastr=0 irow=0 do i=1,n p(i)=0 end do if (m1==0) return i=nu+1 1 continue if (i==mao(i)) then d(i)=aij(lr(i),lc(i)-n,a,la) if (d(i)==0.D0)d(i)=eps ! write(nout,*)'row,col,d(i) =',lr(i),lc(i),d(i) else ! write(nout,*)'lc =',(lc(j),j=i,mao(i)) do inode=i,mao(i)-1 nodec=lc(inode)-n im=inode-1 ! form L.a_q z=0. ! write(nout,*)'inode,t(inode)',inode,t(inode) do j=inode,t(inode) rowj=lr(j) prj=p(rowj) if (prj>0) then d(j)=aiscpri2(n,a,la,rowj,nodec,ws(q(rowj)+1),1.D0,im, & prj,li) else d(j)=aij(rowj,nodec,a,la) end if z=max(z,abs(d(j))) end do ! write(nout,*)'d =',(d(ij),ij=inode,t(inode)) ! threshold pivot selection zz=z*thresh z=0.D0 pri=n do j=inode,t(inode) dj=abs(d(j)) if (dj>=zz) then prj=p(lr(j)) if (prj==pri) then if (dj>z) then z=dj iz=j end if else if (prj<pri) then z=dj iz=j pri=prj end if end if end do ! write(nout,*)'zz,z,iz,pri',zz,z,iz,pri if (iz>inode) then ! pivot interchange call rexch(d(inode),d(iz)) call iexch(lr(inode),lr(iz)) li(lr(iz))=iz li(lr(inode))=inode end if if (d(inode)==0.D0)d(inode)=eps ! update L qri=q(lr(inode)) zz=-d(inode) do j=inode+1,t(inode) z=d(j)/zz rowj=lr(j) prj=p(rowj) qrj=q(rowj) ! find space available in-situ in ws if (prj==0) then len=0 else if (s(rowj)==0) then len=mxws-qrj else len=q(s(rowj))-qrj end if if (abs(z)<=tol) then ! special case of a zero multiplier if (prj==0) goto 2 len_=prj+1 if (len_>len) then call newslot(rowj,len_,lastr,irow,p,q,r,s,ws,mxws,qrj, & ifail) if (ifail>0) return qrj_=q(rowj) do k=1,prj ws(qrj_+k)=ws(qrj+k) end do ws(qrj_+len_)=z else ws(qrj+len_)=z end if p(rowj)=len_ goto 2 end if len_=max(pri,prj)+1 if (len_>len .or. pri>prj) then ! create a new slot and use saxpyz ... call newslot(rowj,len_,lastr,irow,p,q,r,s,ws,mxws,qrj, & ifail) if (ifail>0) return qrj_=q(rowj) len=prj-pri if (len>=0) then do k=1,len ws(qrj_+k)=ws(qrj+k) end do len=len+1 call saxpyz(z,ws(qri+1),ws(qrj+len),ws(qrj_+len), & len_-len) else len=-len do k=1,len ws(qrj_+k)=z*ws(qri+k) end do len=len+1 call saxpyz(z,ws(qri+len),ws(qrj+1),ws(qrj_+len), & len_-len) end if ws(qrj_+len_)=z else ! ... else saxpy in-situ if (pri>0) & call mysaxpy(z,ws(qri+1),ws(qrj+prj-pri+1),pri) ws(qrj+len_)=z end if p(rowj)=len_ ! do rj=1,n ! if (p(rj)/=0) then ! write(nout,*)'storage for row',rj,' p,q,r,s =', ! * p(rj),q(rj),r(rj),s(rj) ! end if ! end do 2 continue end do ! write(nout,*)'lr =',(lr(j),j=i,mao(i)) ! do j=i,mao(i) ! rowj=lr(j) ! if (p(rowj)/=0) then ! write(nout,*)'L(',rowj,')', ! * (ws(k),k=q(rowj)+1,q(rowj)+p(rowj)) ! end if ! end do end do inode=mao(i) noder=lr(inode) pri=p(noder) if (pri>0) then d(inode)=aiscpri2(n,a,la,noder,lc(inode)-n,ws(q(noder)+1), & 1.D0,inode-1,pri,li) else d(inode)=aij(noder,lc(inode)-n,a,la) end if if (d(inode)==0.D0)d(inode)=eps end if i=mao(i)+1 if (i<=n) goto 1 ! write(nout,*)'PAQ factors: nu =',nu ! write(nout,*)'column perm =',(lc(j),j=nu+1,n) ! write(nout,*)'row perm =',(lr(j),j=nu+1,n) ! write(nout,*)'d =',(d(ij),ij=nu+1,n) ! do j=nu+1,n ! rowj=lr(j) ! if (p(rowj)/=0) then ! write(nout,*)'L(',rowj,')', ! * (ws(k),k=q(rowj)+1,q(rowj)+p(rowj)) ! end if ! end do ! call checkout(n,a,la,lr,lc,li,p,q,r,s,ws,mxws,d) ! print star diagram ! if (m1>80 .or. n>1000) stop ! write(nout,*)'factored tarjan + spk1 ordering: nu =',nu ! do i=1,n ! do j=1,m1 ! star(i,j)=' ' ! end do ! end do ! do j=1,m1 ! jp=la(0)+lc(nu+j)-n ! do i=la(jp),la(jp+1)-1 ! star(li(la(i)),j)='*' ! end do ! end do ! do i=nu+1,n ! write(nout,*)(star(i,j),j=1,m1) ! end do ! write(nout,*)'lr =',(lr(j),j=nu+1,n) ! write(nout,*)'lc =',(lc(j),j=nu+1,n) mp=-1 mq=-1 ifail=0 return end function aiscpri2(n,a,la,rowi,coli,ws,di,im,pri,li) implicit double precision (a-h,o-z) dimension a(*),la(0:*),ws(*),li(*) integer rowi,coli,rowj,pri aiscpri2=0.D0 jp=la(0)+coli do j=la(jp),la(jp+1)-1 rowj=la(j) if (rowj==rowi) then aiscpri2=aiscpri2+di*a(j) else ir=li(rowj)-im if (ir>0) goto 1 ir=ir+pri if (ir>0)aiscpri2=aiscpri2+ws(ir)*a(j) end if 1 continue end do return end subroutine updateSE(p,q,n,nm,a,la,e,Q_,R,EB,y,z,s,t,u,x, & d,ws,lr,lc,li,pp,qq,lm,lv,le,ifail) implicit double precision (a-h,o-z) integer p,q,pc,qr,pp,qq dimension a(*),la(0:*),e(*),Q_(*),R(*),EB(*),y(*),z(*),s(*),t(*), & x(*),u(*),d(*),ws(*), & lr(*),lc(*),li(*),pp(*),qq(*),lm(*),lv(*),le(*) common/factorc/m1,m2,mp,mq,lastr,irow common/refactorc/mc,mxmc common/epsc/eps,tol,emin common/pqc/pc,qr,lmp 1 format(A,15I5) 2 format(A,6E15.7) 3 format(A/(15I5)) 4 format(A/(5E15.7)) 5 format((5E15.7)) ! print 1,'updateSE: p,q =',p,q ! print 3,'lm =',(lm(i),i=1,n) if (p/=mp) then call eptsol(n,a,la,p,a,Q_,R,EB,y,s,u,x,d,ws, & lr,lc,li,lv,le,pp,qq,ep) ! print 4,'sk in natural ordering',(s(li(i)),i=1,n) ! print 4,'sk ordered by lr',(s(i),i=1,n) else ep=e(p) end if if (q/=mq) then call aqsol(n,a,la,q,Q_,R,EB,z,t,u,x,d,ws, & lr,lc,li,lv,le,pp,qq) ! print 4,'tk =',(t(i),i=1,n) end if ! update steepest edge coefficients tp=t(lmp) eq=2.D0/ep do i=1,n u(i)=eq*s(i) end do call aqsol(n,a,la,0,Q_,R,EB,x,u,s,x,d,ws, & lr,lc,li,lv,le,pp,qq) ! print 4,'u in natural order =',(u(li(i)),i=1,n) ! print 4,'u ordered by lr =',(u(i),i=1,n) eq=ep/tp do j=1,n i=lm(j) if (e(i)==0.D0) then print *,'malfunction: e(i)=0.D0, i =',i return end if ei=e(i) wi=t(j)*eq awi=abs(wi) if (ei>=awi) then wi=wi/ei e(i)=max(emin,ei*sqrt(max(0.D0,1.D0+wi*(wi-u(j)/ei)))) else wi=ei/wi e(i)=max(emin,awi*sqrt(max(0.D0,1.D0+wi*(wi-u(j)/ei)))) end if end do e(p)=0.D0 e(q)=max(emin,abs(eq)) ! print 4,'e =',(e(i),i=1,nm) return end subroutine updateQR(p,q,n,a,la,Q_,R,EB,x,y,z, & lr,lc,li,lv,le,lm,ifail) implicit double precision (a-h,o-z) integer p,q,pc,qr dimension a(*),la(0:*),Q_(*),R(*),EB(*),x(*),y(*),z(*), & lr(*),lc(*),li(*),lv(*),le(*),lm(*) common/factorc/m1,m2,mp,mq,lastr,irow common/refactorc/mc,mxmc common/epsc/eps,tol,emin common/pqc/pc,qr,lmp 1 format(A,15I5) 2 format(A,6E15.7) 3 format(A/(15I5)) 4 format(A/(5E15.7)) 5 format((5E15.7)) ! print 1,'updateQR: p,q =',p,q,pc,qr ! print *,'mc =',mc ! x is only used for checking m1mc=m1*mc ! print 4,'EB on entry to updateQR =',(EB(i),i=1,m1mc+m1) if (pc==0) then ! p is in the starting active set if (qr==0) then ! q is a new column: extend QR case ! print *,'extend ',p,q mc1=mc+1 ! print 4,'EB for c/s p =',(EB(i),i=m1mc+1,m1mc+m1) ii=m1mc-m2 if (q<=n) then if (li(q)>m2)sum=-EB(li(q)+ii) else sum=0.D0 jp=la(0)+q-n do j=la(jp),la(jp+1)-1 i=la(j) if (i==p) then sum=sum-a(j) else if (li(i)>m2) then sum=sum-EB(li(i)+ii)*a(j) end if end do end if y(mc1)=sum if (mc==0) then Q_(1)=1.D0 R(1)=y(1) ! print 2,'R(1) =',R(1) mc=1 else ! new row and column of C ! print 2,'y =',(y(i),i=1,mc1) ! print 2,'z =',(z(i),i=1,mc) ic=mc1 mmx=mc*mxmc do i=1,mc Q_(ic)=0.D0 Q_(mmx+i)=0.D0 ic=ic+mxmc end do Q_(ic)=1.D0 ii=1 ic=1 mmx1=mmx+1 do i=1,mc call angle(R(ii),y(i),cos,sin) call rot(mc-i,R(ii+1),y(i+1),cos,sin) call rot(mc1,Q_(ic),Q_(mmx1),cos,sin) ii=ii+mxmc-i+1 ic=ic+mxmc end do z(mc1)=y(mc1) ! print 2,'z =',(z(i),i=1,mc1) ii=mc1 ic=1 do i=1,mc1 R(ii)=scpr(0.D0,Q_(ic),z,mc1) ii=ii+mxmc-i ic=ic+mxmc end do mc=mc1 end if lv(mc)=q le(mc)=p lm(lmp)=q goto 10 else ! row replacement case: p is in the starting active set and ! q is in the starting active set (and hence in row qr of E) ! print *,'row ',p,q ! print 3,'lr =',(lr(i),i=1,n) ! print 3,'lc =',(lc(i),i=m2+1,n) ! print 3,'le =',(le(i),i=1,mc) ! print 3,'lv =',(lv(i),i=1,mc) ! print 3,'lm =',(lm(i),i=1,n) mc1=mc mc=mc-1 j=mc1-qr if (mc>0) then icp=mxmc*mc+mc1 ic=icp call rexch(Q_(icp),Q_(icp-j)) ii=mc1*(3-mc1)/2+(mc1-1)*mxmc z(mc1)=R(ii) do i=mc,1,-1 ic=ic-mxmc call rexch(Q_(ic),Q_(ic-j)) call angle(Q_(icp),Q_(ic),cos,sin) call rot(mc,Q_(icp-mc),Q_(ic-mc),cos,sin) ii=ii-mxmc+i-1 z(i)=sin*R(ii) R(ii)=-cos*R(ii) call rot(mc1-i,z(i+1),R(ii+1),cos,sin) end do ic=1 icp=icp-mc do i=1,mc call angle(R(ii),y(i),cos,sin) call rot(mc1-i,R(ii+1),y(i+1),cos,sin) call rot(mc1,Q_(ic),Q_(icp),cos,sin) ii=ii+mxmc-i+1 ic=ic+mxmc end do R(ii)=y(mc1) le(qr)=le(mc1) else Q_(1)=1.D0 R(1)=y(1) end if le(mc1)=p ! j=m1*(mc1-qr) j=m1*j do i=m1mc-m1+1,m1mc EB(i-j)=EB(i) EB(i)=EB(i+m1) end do mc=mc1 end if else ! p is not in the starting active set (and hence in column pc of V) ! first remove column pc from V call ishift(lv(pc),mc-pc,1) ic=pc do i=1,pc-1 call r_shift(R(ic),mc-pc,1) ic=ic+mxmc-i end do mc1=mc mc=mc-1 ii=ic+1 iip=ii+mxmc-pc ic=(pc-1)*mxmc+1 do i=pc,mc call angle(R(ii),R(iip),cos,sin) call rot(mc-i,R(ii+1),R(iip+1),cos,sin) call r_shift(R(ii-1),mc1-i,1) ii=iip+1 iip=ii+mxmc-i-1 icp=ic+mxmc call rot(mc1,Q_(ic),Q_(icp),cos,sin) ic=icp end do if (qr==0) then ! print *,'column ',p,q ! q is a new column (column interchange case) ! print 2,'z =',(z(i),i=1,mc1) ii=mc1 ic=1 do i=1,mc1 R(ii)=scpr(0.D0,Q_(ic),z,mc1) ii=ii+mxmc-i ic=ic+mxmc end do mc=mc1 lv(mc)=q else ! q is in the starting active set and hence in row qr of E (contract QR case) ! print *,'contract',p,q icp=mxmc*mc+mc1 ic=icp j=mc1-qr call rexch(Q_(icp),Q_(icp-j)) ii=mc*(3-mc)/2+(mc-1)*mxmc do i=mc,1,-1 ic=ic-mxmc call rexch(Q_(ic),Q_(ic-j)) call angle(Q_(icp),Q_(ic),cos,sin) call rot(mc,Q_(icp-mc),Q_(ic-mc),cos,sin) y(i)=sin*R(ii) R(ii)=-cos*R(ii) call rot(mc-i,y(i+1),R(ii+1),cos,sin) ii=ii-mxmc+i-2 end do le(qr)=le(mc1) j=m1*(mc1-qr) do i=m1mc-m1+1,m1mc EB(i-j)=EB(i) end do end if end if ! reset lm (except when extending) do i=1,m2 lm(i)=lr(i) end do do i=m2+1,n lm(i)=lc(i) end do do i=1,mc lm(li(le(i)))=lv(i) end do ! print 3,'le =',(le(i),i=1,mc) ! print 3,'lv =',(lv(i),i=1,mc) ! print 3,'lm =',(lm(i),i=1,n) 10 continue ifail=0 if (mc==0) return ! print 4,'Q transpose =',(Q_(j),j=1,mc) ! do i=1,mc-1 ! print 5,(Q_(j),j=i*mxmc+1,i*mxmc+mc) ! end do ! print 4,'R =',(R(j),j=1,mc) ! ii=mxmc+1 ! do i=1,mc-1 ! print 5,(R(j),j=ii,ii+mc-i-1) ! ii=ii+mxmc-i ! end do sum=R(mc*(3-mc)/2+(mc-1)*mxmc) if (sum-sum/=0.D0 .or. sum==0.D0)ifail=1 return ! check QR factors ! print 4,'EB in check =',(EB(i),i=1,m1mc) do j=1,mc do i=1,n x(i)=0.D0 end do if (lv(j)<=n) then x(li(lv(j)))=1.D0 else call iscatter(a,la,lv(j)-n,li,x,n) end if do i=1,mc z(i)=0.D0 end do i1=j do i=1,j call mysaxpy(R(i1),Q_((i-1)*mxmc+1),z,mc) i1=i1+mxmc-i end do ! print 4,'z =',(z(i),i=1,mc) ! print 4,'x =',(x(i),i=1,n) emax=0.D0 do i=1,mc cij=-scpr(0.D0,EB((i-1)*m1+1),x(m2+1),m1) if (le(i)<=n)cij=cij-x(li(le(i))) qrij=z(i) emax=max(emax,abs(cij-qrij)) ! if (abs(cij-qrij)>tol) then ! print *,'error in C=QR: i,j =',i,j ! print *,'cij,qrij =',cij,qrij ! if (abs(cij-qrij)>1.D-6) stop ! end if end do end do if (emax>tol) print *,'max error in C=QR =',emax if (emax>tol) stop return end subroutine newslot(row,len,lastr,irow,p,q,r,s,ws,mxws,qr_, & ifail) implicit double precision (a-h,u-z), integer (i-t) parameter (igap=10) dimension p(*),q(*),r(*),s(*),ws(*) common/noutc/nout ! write(nout,*)'newslot: row =',row,' len =',len ! write(nout,*)'irow,lastr,mxws =',irow,lastr,mxws ifail=0 if (lastr==0) then if (mxws<len) then write(nout,*)'insufficient space available for profile' ifail=7 else irow=row q(row)=0 r(row)=0 s(row)=0 lastr=row end if return end if igp=igap 1 continue len_=len+igp thisr=lastr 2 continue qrow=q(thisr)+p(thisr) nextr=s(thisr) ! write(nout,*)'thisr,nextr,qrow,p(thisr),len_', ! * thisr,nextr,qrow,p(thisr),len_ if (nextr/=0) then if (q(nextr)>=qrow+len_) then ! free slot after this row goto 4 else thisr=nextr if (thisr/=lastr) goto 2 end if else if (mxws-qrow>=len_) then ! free slot at end of ws goto 4 else if (q(irow)>=len_) then ! free slot at beginning of ws qrow=0 thisr=0 nextr=irow irow=row igp=0 goto 4 end if thisr=irow if (thisr/=lastr) goto 2 end if ! no free space: try minimum value of len if (igp>0) then igp=0 goto 1 end if ! compress ws thisr=irow qrow=0 3 continue call r_shift(ws(qrow+1),p(thisr),q(thisr)-qrow) q(thisr)=qrow qrow=qrow+p(thisr) if (s(thisr)/=0) then thisr=s(thisr) goto 3 end if if (mxws<qrow+len_) then write(nout,*)'insufficient space available for profile' write(nout,*)'mxws,qrow,len_',mxws,qrow,len_ ifail=7 return end if ! insert at end of compressed file nextr=0 4 continue qr_=q(row) q(row)=qrow+igp if (p(row)>0) then if (r(row)==thisr .or. s(row)==nextr) return ! insert after row thisr and take out old row call erase(row,lastr,irow,r,s) end if lastr=row r(row)=thisr if (thisr>0)s(thisr)=row s(row)=nextr if (nextr>0)r(nextr)=row i=0 return end subroutine erase(row,lastr,irow,r,s) ! remove slot for row from the data file implicit integer (i-s) dimension r(*),s(*) common/noutc/nout ! write(nout,*)'erase: row,irow,lastr =',row,irow,lastr if (r(row)==0) then if (s(row)==0) then irow=0 lastr=0 return end if irow=s(row) r(irow)=0 else if (s(row)==0) then s(r(row))=0 else s(r(row))=s(row) r(s(row))=r(row) end if if (row==lastr)lastr=irow return end subroutine trim_(rowi,pri,qri,q,ws) ! trim leading zeros off slot for row i implicit double precision (a-h,s-z), integer (i-r) dimension q(*),ws(*) common/epsc/eps,tol,emin 1 continue qri=qri+1 pri=pri-1 if (pri==0) return if (abs(ws(qri+1))<=tol) goto 1 q(rowi)=qri return end subroutine EBspace(n,p,q,s,lr,ws,neb,nprof,ifail) implicit double precision (a-h,u-z), integer (i-t) dimension p(*),q(*),s(*),lr(*),ws(*) common/factorc/m1,m2,mp,mq,lastr,irow common/refactorc/mc,mxmc common/noutc/nout ifail=0 ! find length and last entry in file len=0 last=0 do i=m2+1,n row=lr(i) if (p(row)>0) then len=len+p(row) last=max(last,q(row)+p(row)) end if end do neb=m1*(mxmc+1) ! print *,'nprof =',nprof ! print *,'m1,len,last,neb',m1,len,last,neb if (last+neb<=nprof) then neb=last return else if (len+neb<=nprof) then ! compress the file thisr=irow qrow=0 1 continue call r_shift(ws(qrow+1),p(thisr),q(thisr)-qrow) q(thisr)=qrow qrow=qrow+p(thisr) if (s(thisr)/=0) then thisr=s(thisr) goto 1 end if neb=len return end if write(nout,*)'not enough additional space for E.B^{-1} matrix' write(nout,*)'space required is at least len+m1*(mxmc+1)' write(nout,*)'space left =',nprof-len,' len,m1 =',len,m1 ifail=7 9 format(A/(15I5)) return end subroutine checkperms(n,lr,lc,li) implicit double precision (a-h,r-z), integer (i-q) dimension lr(*),lc(*),li(*) common/factorc/m1,m2,mp,mq,lastr,irow do i=1,n if (lr(li(i))/=i) print *,'wrong perm 1' if (lr(li(i))/=i) stop if (li(lr(i))/=i) print *,'wrong perm 2' if (li(lr(i))/=i) stop end do do i=m2+1,n if (li(lc(i))/=i) print *,'wrong perm 3' if (li(lc(i))/=i) stop end do return end subroutine checkout(n,a,la,lr,lc,li,p,q,r,s,ws,mxws,d) implicit double precision (a-h,r-z), integer (i-q) integer r,s,rowj,thisr dimension a(*),la(*),lr(*),lc(*),li(*),p(*),q(*),r(*),s(*),ws(*), & d(*) common/factorc/m1,nu,mp,mq,lastr,irow common/noutc/nout common/epsc/eps,tol,emin ! check indexing do j=1,nu if (p(lr(j))/=0) then write(nout,*)'p(lr(j))/=0' goto 11 end if end do np=0 do i=nu+1,n if (p(lr(i))>0)np=np+1 end do if (irow>0) then if (r(irow)/=0) then write(nout,*)'r(irow)/=0' goto 11 end if thisr=irow 1 continue if (p(thisr)<=0) then write(nout,*)'p(thisr)<=0' goto 11 end if np=np-1 nextr=s(thisr) if (nextr==0) then if (q(thisr)+p(thisr)>mxws) then write(nout,*)'q(thisr)+p(thisr)>mxws' goto 11 end if else if (r(nextr)/=thisr) then write(nout,*)'r(nextr)/=thisr' goto 11 end if if (nextr/=s(thisr)) then write(nout,*)'nextr/=s(thisr)' goto 11 end if if (q(thisr)+p(thisr)>q(nextr)) then write(nout,*)'q(thisr)+p(thisr)>q(nextr)' goto 11 end if thisr=nextr goto 1 end if end if if (np/=0) then write(nout,*)'np/=0' goto 11 end if last=0 emax=0.D0 length=0 do inode=nu+1,n nodec=lc(inode) ! form L.a_q rowj=lr(inode) prj=p(rowj) length=length+prj if (prj<0) then write(nout,*)'prj<0' goto 11 else if (prj==0) then e=abs(aij(rowj,nodec-n,a,la)-d(inode)) else e=abs(d(inode)-aiscpri2(n,a,la,rowj,nodec-n,ws(q(rowj)+1), & 1.D0,inode-1,prj,li)) end if ! if (e>tol) write(nout,*)'error =',e, ! * ' inode,nodec,rowj =',inode,nodec,rowj emax=max(emax,e) do j=inode+1,n rowj=lr(j) prj=p(rowj) if (prj>0) then e=abs(aiscpri2(n,a,la,rowj,nodec-n,ws(q(rowj)+1),1.D0,j-1, & prj,li)) else e=abs(aij(rowj,nodec-n,a,la)) end if ! if (e>tol) write(nout,*)'error =',e, ! * ' inode,nodec,j,rowj =',inode,nodec,j,rowj emax=max(emax,e) end do end do write(nout,*)'checkout: m1 =',m1,' file length =',length if (emax>tol) write(nout,*)'error =',emax return 11 continue write(nout,*)'thisr,nextr =',thisr,nextr write(nout,*)'i,p(i),q(i),r(i),s(i): irow =',irow do i=1,n if (p(i)/=0) write(nout,*)i,p(i),q(i),r(i),s(i) end do stop end