bndset Subroutine

private subroutine bndset(Nparm, x, Itersl, Numin, Prjslp, Cofbnd, Xkeep, Bndkp)

This subroutine sets the bounds on the coefficient changes in slnpro.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: Nparm
real(kind=wp), intent(in), dimension(Nparm + 1) :: x
integer, intent(in) :: Itersl
integer, intent(in) :: Numin
real(kind=wp), intent(in) :: Prjslp
real(kind=wp), intent(inout), dimension(Nparm) :: Cofbnd
real(kind=wp), intent(inout), dimension(Nparm + 1) :: Xkeep
real(kind=wp), intent(inout), dimension(Nparm) :: Bndkp

Called by

proc~~bndset~~CalledByGraph proc~bndset bndset proc~slpcon conmax_solver%slpcon proc~slpcon->proc~bndset proc~conmax conmax_solver%conmax proc~conmax->proc~slpcon

Source Code

    subroutine bndset(Nparm, x, Itersl, Numin, Prjslp, Cofbnd, Xkeep, Bndkp)

        implicit none

        integer, intent(in)                           :: Nparm
        real(wp), dimension(Nparm + 1), intent(in)    :: x
        integer, intent(in)                           :: Itersl
        integer, intent(in)                           :: Numin
        real(wp), intent(in)                          :: Prjslp
        real(wp), dimension(Nparm), intent(inout)     :: Cofbnd
        real(wp), dimension(Nparm + 1), intent(inout) :: Xkeep
        real(wp), dimension(Nparm), intent(inout)     :: Bndkp

        ! set initial parameters.  fact1, fact3a, fact3b, chlm1, and chlm2
        ! should be between 0.0 and 1.0, while fact2 should be > 1.0.
        real(wp), parameter :: fact1 = (one + two)/four
        real(wp), parameter :: fact2 = two
        real(wp), parameter :: fact3a = one/ten
        real(wp), parameter :: fact3b = one/(ten*ten)
        real(wp), parameter :: fact4 = two/ten
        real(wp), parameter :: chlm1 = one/ten
        real(wp), parameter :: chlm2 = (four + four)/ten
        real(wp), parameter :: tstprj = one/two - one/(ten*ten*ten)
        real(wp), parameter :: epsil = ten*ten*spcmn
        real(wp), parameter :: epsil1 = (one + one/(ten*ten*ten))*epsil
        real(wp), parameter :: bnd = two/(ten*ten) !! The initial bound on all coefficient changes.

        real(wp) :: bsave, fact3
        integer :: itight, j

        if (Numin < 1) then

            if (Itersl < 1) then

            else if (Itersl == 1) then
                ! HERE NUMIN=0 AND ITERSL=1, SO THE LAST BNDSET CALL RESULTED IN
                ! THE FIRST SUCCESSFUL PRINCIPAL ERROR NORM IMPROVEMENT,
                ! AND SO WE SAVE COFBND IN BNDKP AND X IN XKEEP.  WE WILL NOT
                ! CHANGE COFBND HERE.
                do j = 1, Nparm
                    Xkeep(j) = x(j)
                    Bndkp(j) = Cofbnd(j)
                end do
                return
            else
                ! HERE NUMIN=0 AND ITERSL >= 2, SO WE HAVE HAD AT LEAST 2 SUCCESSES,
                ! WITH THE COEFFICIENTS AND BOUNDS FOR THE LAST ONE IN X AND
                ! COFBND RESPECTIVELY, AND THE COEFFICIENTS AND BOUNDS FOR THE
                ! PREVIOUS ONE IN XKEEP AND BNDKP RESPECTIVELY.  WE WILL FORM A
                ! NEW COFBND, AND SHIFT THE OLD COFBND INTO BNDKP AND X INTO XKEEP.
                do j = 1, Nparm
                    Cofbnd_block: block
                        ! SAVE THE OLD COFBND(J) IN BSAVE.
                        bsave = Cofbnd(j)
                        ! IF AT BOTH THE LAST AND PREVIOUS SUCCESSFUL ITERATION THE CHANGES
                        ! IN A COEFFICIENT RELATIVE TO ITS BOUND WERE >= CHLM2 IN ABSOLUTE
                        ! VALUE AND IN THE SAME DIRECTION, WE LOOSEN THE BOUND BY A FACTOR
                        ! OF FACT2.  IF THE RELATIVE CHANGES WERE >= CHLM1 IN ABSOLUTE
                        ! VALUE AND IN OPPOSITE DIRECTIONS, WE TIGHTEN THE BOUND BY A FACTOR
                        ! OF FACT1 BECAUSE OF SUSPECTED OSCILLATION.  WE ALSO TIGHTEN THE
                        ! BOUND IF BOTH RELATIVE CHANGES WERE LESS THAN CHLM1 IN ABSOLUTE
                        ! VALUE IN ORDER TO PREVENT A LONG SEQUENCE OF OSCILLATIONS OF THE
                        ! SAME SMALL ORDER.  OTHERWISE WE LEAVE THE BOUND ALONE.
                        ! THE NEXT FOUR IF STATEMENTS CHECK TO SEE IF THE BOUND SHOULD BE
                        ! LOOSENED.
                        if (x(j) < chlm2*Cofbnd(j)) then
                            if (x(j) + chlm2*Cofbnd(j) <= 0) then
                                if (Xkeep(j) + chlm2*Bndkp(j) <= 0) then
                                    ! LOOSEN THE BOUND.
                                    Cofbnd(j) = fact2*Cofbnd(j)
                                    exit Cofbnd_block
                                end if
                            end if
                        else if (Xkeep(j) >= chlm2*Bndkp(j)) then
                            Cofbnd(j) = fact2*Cofbnd(j)
                            exit Cofbnd_block
                        end if
                        ! HERE THE BOUND SHOULD NOT BE LOOSENED.  THE NEXT FIVE IF
                        ! STATEMTENTS CHECK TO SEE IF IT SHOULD BE TIGHTENED.
                        if (x(j) < chlm1*Cofbnd(j)) then
                            if (x(j) + chlm1*Cofbnd(j) <= 0) then
                                if (Xkeep(j) < chlm1*Bndkp(j)) exit Cofbnd_block
                                ! HERE WE HAVE ABS(X(J)) < CHLM1*COFBND(J).
                            else if (abs(Xkeep(j)) >= chlm1*Bndkp(j)) then
                                exit Cofbnd_block
                            end if
                        else if (Xkeep(j) + chlm1*Bndkp(j) > 0) then
                            exit Cofbnd_block
                        end if
                        ! TIGHTEN THE BOUND.
                        Cofbnd(j) = fact1*Cofbnd(j)
                        ! DO NOT ALLOW THE BOUND TO DROP BELOW EPSIL.
                        if (Cofbnd(j) < epsil) Cofbnd(j) = epsil
                    end block Cofbnd_block
                    ! SAVE X(J) AND THE OLD COFBND(J).
                    Bndkp(j) = bsave
                    Xkeep(j) = x(j)
                end do
                ! IF THE LAST PROJECTION FACTOR IS SMALLER THAN .499, WE TIGHTEN THE
                ! BOUNDS BY A FACTOR OF 0.2, WITH THE RESTRICTION THAT WE DO NOT
                ! ALLOW THE BOUNDS TO DROP BELOW EPSIL.
                if (Prjslp < tstprj) then
                    do j = 1, Nparm
                        Cofbnd(j) = fact4*Cofbnd(j)
                        if (Cofbnd(j) < epsil) Cofbnd(j) = epsil
                    end do
                end if
                return
            end if

            ! HERE NUMIN=0 AND ITERSL=0, SO WE ARE IN THE FIRST BNDSET CALL SINCE THE
            ! LAST RK SUCCESS (IF ANY), SO WE SET INITIAL BOUNDS.
            Cofbnd = bnd
            return

        else if (Numin == 1) then
            ! HERE NUMIN=1 SO THE LAST BNDSET CALL RESULTED IN FAILURE TO
            ! IMPROVE THE PRINCIPAL ERROR NORM, AND WE SET FACT3=
            ! FACT3A AND TIGHTEN THE BOUNDS.
            fact3 = fact3a
        else
            ! HERE NUMIN > 1 SO THERE HAVE BEEN AT LEAST 2 SUCCESSIVE
            ! FAILURES, AND WE SET FACT3=FACT3B AND TIGHTEN THE BOUNDS.
            fact3 = fact3b
        end if

        ! TIGHTEN THE BOUNDS BY A FACTOR OF FACT3.
        itight = 1
        do j = 1, Nparm
            bsave = Cofbnd(j)
            Cofbnd(j) = fact3*bsave
            ! WE DO NOT ALLOW A BOUND TO DROP BELOW EPSIL.
            if (Cofbnd(j) < epsil) then
                ! IF THE BOUND WAS ALREADY (ESSENTIALLY) AT EPSIL, KEEP TRACK OF
                ! THIS BY NOT SETTING ITIGHT=0.
                if (bsave > epsil1) itight = 0
                Cofbnd(j) = epsil
            else
                itight = 0
            end if
        end do

        ! IF ALL THE BOUNDS WERE ALREADY (ESSENTIALLY) AT EPSIL, WE TRY
        ! RESETTING THE BOUNDS TO THEIR ORIGINAL VALUES.
        !WRITE(NWRIT,'(A)') '*****RESETTING BOUNDS TO THEIR ORIGINAL VALUES*****'
        if (itight > 0) Cofbnd = bnd

    end subroutine bndset