Mercurial > octave
diff libcruft/npsol/lsadd.f @ 2329:30c606bec7a8
[project @ 1996-07-19 01:29:05 by jwe]
Initial revision
author | jwe |
---|---|
date | Fri, 19 Jul 1996 01:29:55 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcruft/npsol/lsadd.f Fri Jul 19 01:29:55 1996 +0000 @@ -0,0 +1,301 @@ +*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +* File LSSUBS FORTRAN +* +* LSADD LSADDS LSBNDS LSCHOL LSCORE LSCRSH LSDEL +* LSDFLT LSFEAS LSFILE LSGETP LSGSET LSKEY LSLOC +* LSMOVE LSMULS LSOPTN LSPRT LSSETX LSSOL +*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + SUBROUTINE LSADD ( UNITQ, + $ INFORM, IFIX, IADD, JADD, + $ NACTIV, NZ, NFREE, NRANK, NRES, NGQ, + $ N, NROWA, NQ, NROWR, NROWT, + $ KX, CONDMX, + $ A, R, T, RES, GQ, ZY, WRK1, WRK2 ) + + IMPLICIT DOUBLE PRECISION(A-H,O-Z) + LOGICAL UNITQ + INTEGER KX(N) + DOUBLE PRECISION A(NROWA,*), R(NROWR,*), T(NROWT,*), + $ RES(N,*), GQ(N,*), ZY(NQ,*) + DOUBLE PRECISION WRK1(N), WRK2(N) +************************************************************************ +* LSADD updates the factorization, A(free) * (Z Y) = (0 T), when a +* constraint is added to the working set. If NRANK .gt. 0, the +* factorization ( R ) = PWQ is also updated, where W is the +* ( 0 ) +* least squares matrix, R is upper-triangular, and P is an +* orthogonal matrix. The matrices W and P are not stored. +* +* There are three separate cases to consider (although each case +* shares code with another)... +* +* (1) A free variable becomes fixed on one of its bounds when there +* are already some general constraints in the working set. +* +* (2) A free variable becomes fixed on one of its bounds when there +* are only bound constraints in the working set. +* +* (3) A general constraint (corresponding to row IADD of A) is +* added to the working set. +* +* In cases (1) and (2), we assume that KX(IFIX) = JADD. +* In all cases, JADD is the index of the constraint being added. +* +* If there are no general constraints in the working set, the +* matrix Q = (Z Y) is the identity and will not be touched. +* +* If NRES .GT. 0, the row transformations are applied to the rows of +* the (N by NRES) matrix RES. +* If NGQ .GT. 0, the column transformations are applied to the +* columns of the (NGQ by N) matrix GQ'. +* +* Systems Optimization Laboratory, Stanford University. +* Original version written 31-October--1984. +* This version of LSADD dated 29-December-1985. +************************************************************************ + COMMON /SOL1CM/ NOUT + COMMON /SOL4CM/ EPSPT3, EPSPT5, EPSPT8, EPSPT9 + COMMON /SOL5CM/ ASIZE, DTMAX, DTMIN + + LOGICAL LSDBG + PARAMETER (LDBG = 5) + COMMON /LSDEBG/ ILSDBG(LDBG), LSDBG + + LOGICAL BOUND , OVERFL + EXTERNAL DDOT , DDIV , DNRM2 + INTRINSIC MAX , MIN + PARAMETER (ZERO = 0.0D+0, ONE = 1.0D+0) + +* If the condition estimator of the updated factors is greater than +* CONDBD, a warning message is printed. + + CONDBD = ONE / EPSPT9 + + OVERFL = .FALSE. + BOUND = JADD .LE. N + IF (BOUND) THEN +* =============================================================== +* A simple bound has entered the working set. IADD is not used. +* =============================================================== + IF (LSDBG .AND. ILSDBG(1) .GT. 0) + $ WRITE (NOUT, 1010) NACTIV, NZ, NFREE, IFIX, JADD, UNITQ + NANEW = NACTIV + + IF (UNITQ) THEN + +* Q is not stored, but KX defines an ordering of the columns +* of the identity matrix that implicitly define Q. +* Reorder KX so that variable IFIX is moved to position +* NFREE+1 and variables IFIX+1,...,NFREE+1 are moved one +* position to the left. + + CALL DLOAD ( NFREE, (ZERO), WRK1, 1 ) + WRK1(IFIX) = ONE + + DO 100 I = IFIX, NFREE-1 + KX(I) = KX(I+1) + 100 CONTINUE + ELSE +* ------------------------------------------------------------ +* Q is stored explicitly. +* ------------------------------------------------------------ +* Set WRK1 = the (IFIX)-th row of Q. +* Move the (NFREE)-th row of Q to position IFIX. + + CALL DCOPY ( NFREE, ZY(IFIX,1), NQ, WRK1, 1 ) + IF (IFIX .LT. NFREE) THEN + CALL DCOPY ( NFREE, ZY(NFREE,1), NQ, ZY(IFIX,1), NQ ) + KX(IFIX) = KX(NFREE) + END IF + END IF + KX(NFREE) = JADD + ELSE +* =============================================================== +* A general constraint has entered the working set. +* IFIX is not used. +* =============================================================== + IF (LSDBG .AND. ILSDBG(1) .GT. 0) + $ WRITE (NOUT, 1020) NACTIV, NZ, NFREE, IADD, JADD, UNITQ + + NANEW = NACTIV + 1 + +* Transform the incoming row of A by Q'. + + CALL DCOPY ( N, A(IADD,1), NROWA, WRK1, 1 ) + CALL CMQMUL( 8, N, NZ, NFREE, NQ, UNITQ, KX, WRK1, ZY, WRK2) + +* Check that the incoming row is not dependent upon those +* already in the working set. + + DTNEW = DNRM2 ( NZ, WRK1, 1 ) + IF (NACTIV .EQ. 0) THEN + +* This is the only general constraint in the working set. + + COND = DDIV ( ASIZE, DTNEW, OVERFL ) + TDTMAX = DTNEW + TDTMIN = DTNEW + ELSE + +* There are already some general constraints in the working +* set. Update the estimate of the condition number. + + TDTMAX = MAX( DTNEW, DTMAX ) + TDTMIN = MIN( DTNEW, DTMIN ) + COND = DDIV ( TDTMAX, TDTMIN, OVERFL ) + END IF + + IF (COND .GT. CONDMX .OR. OVERFL) GO TO 900 + + IF (UNITQ) THEN + +* This is the first general constraint to be added. +* Set Q = I. + + DO 200 J = 1, NFREE + CALL DLOAD ( NFREE, (ZERO), ZY(1,J), 1 ) + ZY(J,J) = ONE + 200 CONTINUE + UNITQ = .FALSE. + END IF + END IF + + NZERO = NZ - 1 + IF (BOUND) NZERO = NFREE - 1 + +* ------------------------------------------------------------------ +* Use a sequence of 2*2 column transformations to reduce the +* first NZERO elements of WRK1 to zero. This affects ZY, except +* when UNITQ is true. The transformations may also be applied +* to R, T and GQ'. +* ------------------------------------------------------------------ + LROWR = N + NELM = 1 + IROWT = NACTIV + + DO 300 K = 1, NZERO + +* Compute the transformation that reduces WRK1(K) to zero, +* then apply it to the relevant columns of Z and GQ'. + + CALL DROT3G( WRK1(K+1), WRK1(K), CS, SN ) + IF (.NOT. UNITQ) + $ CALL DROT3 ( NFREE, ZY(1,K+1), 1, ZY(1,K), 1, CS, SN ) + IF (NGQ .GT. 0) + $ CALL DROT3 ( NGQ , GQ(K+1,1), N, GQ(K,1), N, CS, SN ) + + IF (K .GE. NZ .AND. NACTIV .GT. 0) THEN + +* Apply the rotation to T. + + T(IROWT,K) = ZERO + CALL DROT3 ( NELM, T(IROWT,K+1), 1, T(IROWT,K), 1, CS, SN ) + NELM = NELM + 1 + IROWT = IROWT - 1 + END IF + + IF (NRANK .GT. 0) THEN + +* Apply the same transformation to the columns of R. +* This generates a subdiagonal element in R that must be +* eliminated by a row rotation. + + IF (K .LT. NRANK) R(K+1,K) = ZERO + LCOL = MIN( K+1, NRANK ) + + CALL DROT3 ( LCOL, R(1,K+1), 1, R(1,K), 1, CS, SN ) + IF (K .LT. NRANK) THEN + CALL DROT3G( R(K,K), R(K+1,K), CS, SN ) + LROWR = LROWR - 1 + CALL DROT3 ( LROWR, R(K,K+1) , NROWR, + $ R(K+1,K+1), NROWR, CS, SN ) + + IF (NRES .GT. 0) + $ CALL DROT3 ( NRES, RES(K,1) , N , + $ RES(K+1,1), N , CS, SN ) + END IF + END IF + 300 CONTINUE + + IF (BOUND) THEN + +* The last row and column of ZY has been transformed to plus +* or minus the unit vector E(NFREE). We can reconstitute the +* columns of GQ and R corresponding to the new fixed variable. + + IF (WRK1(NFREE) .LT. ZERO) THEN + NFMIN = MIN( NRANK, NFREE ) + IF (NFMIN .GT. 0) CALL DSCAL ( NFMIN, -ONE, R(1,NFREE) , 1 ) + IF (NGQ .GT. 0) CALL DSCAL ( NGQ , -ONE, GQ(NFREE,1), N ) + END IF + +* --------------------------------------------------------------- +* The diagonals of T have been altered. Recompute the +* largest and smallest values. +* --------------------------------------------------------------- + IF (NACTIV .GT. 0) THEN + CALL DCOND( NACTIV, T(NACTIV,NZ), NROWT-1, TDTMAX, TDTMIN ) + COND = DDIV ( TDTMAX, TDTMIN, OVERFL ) + END IF + ELSE +* --------------------------------------------------------------- +* General constraint. Install the new row of T. +* --------------------------------------------------------------- + CALL DCOPY ( NANEW, WRK1(NZ), 1, T(NANEW,NZ), NROWT ) + END IF + +* ================================================================== +* Prepare to exit. Check the magnitude of the condition estimator. +* ================================================================== + 900 IF (NANEW .GT. 0) THEN + IF (COND .LT. CONDMX .AND. .NOT. OVERFL) THEN + +* The factorization has been successfully updated. + + INFORM = 0 + DTMAX = TDTMAX + DTMIN = TDTMIN + IF (COND .GE. CONDBD) WRITE (NOUT, 2000) JADD + ELSE + +* The proposed working set appears to be linearly dependent. + + INFORM = 1 + IF (LSDBG .AND. ILSDBG(1) .GT. 0) THEN + WRITE( NOUT, 3000 ) + IF (BOUND) THEN + WRITE (NOUT, 3010) ASIZE, DTMAX, DTMIN + ELSE + IF (NACTIV .GT. 0) THEN + WRITE (NOUT, 3020) ASIZE, DTMAX, DTMIN, DTNEW + ELSE + WRITE (NOUT, 3030) ASIZE, DTNEW + END IF + END IF + END IF + END IF + END IF + + RETURN + + 1010 FORMAT(/ ' //LSADD // Simple bound added.' + $ / ' //LSADD // NACTIV NZ NFREE IFIX JADD UNITQ' + $ / ' //LSADD // ', 5I6, L6 ) + 1020 FORMAT(/ ' //LSADD // General constraint added. ' + $ / ' //LSADD // NACTIV NZ NFREE IADD JADD UNITQ' + $ / ' //LSADD // ', 5I6, L6 ) + 2000 FORMAT(/ ' XXX Serious ill-conditioning in the working set', + $ ' after adding constraint ', I5 + $ / ' XXX Overflow may occur in subsequent iterations.'//) + 3000 FORMAT(/ ' //LSADD // Dependent constraint rejected.' ) + 3010 FORMAT(/ ' //LSADD // ASIZE DTMAX DTMIN ' + $ / ' //LSADD //', 1P3E10.2 ) + 3020 FORMAT(/ ' //LSADD // ASIZE DTMAX DTMIN DTNEW' + $ / ' //LSADD //', 1P4E10.2 ) + 3030 FORMAT(/ ' //LSADD // ASIZE DTNEW' + $ / ' //LSADD //', 1P2E10.2 ) + +* End of LSADD . + + END