subroutine dvnlsd is a nonlinear system solver, which uses functional iteration or a chord (modified newton) method. for the chord method direct linear algebraic system solvers are used. subroutine dvnlsd then handles the corrector phase of this integration package.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(dvode_t), | intent(inout) | :: | me | |||
real(kind=wp), | intent(inout) | :: | y(*) |
the dependent variable, a vector of length n |
||
real(kind=wp), | intent(inout) | :: | yh(ldyh,*) |
the nordsieck (taylor) array, ldyh by lmax, input and output. on input, it contains predicted values. |
||
integer, | intent(in) | :: | ldyh |
a constant >= n, the first dimension of yh |
||
real(kind=wp) | :: | vsav(*) |
unused work array. |
|||
real(kind=wp) | :: | savf(*) |
a work array of length n. |
|||
real(kind=wp), | intent(in) | :: | ewt(*) |
an error weight vector of length n |
||
real(kind=wp), | intent(inout) | :: | acor(*) |
a work array of length n, used for the accumulated corrections to the predicted y vector. |
||
integer, | intent(inout) | :: | iwm(*) |
integer work array associated with matrix operations in chord iteration (miter /= 0). |
||
real(kind=wp), | intent(inout) | :: | wm(*) |
real work array associated with matrix operations in chord iteration (miter /= 0). |
||
integer, | intent(inout) | :: | nflag |
input/output flag, with values and meanings as follows:
|
subroutine dvnlsd(me,y,yh,ldyh,vsav,savf,ewt,acor,iwm,wm,nflag) class(dvode_t),intent(inout) :: me real(wp),intent(inout) :: y(*) !! the dependent variable, a vector of length n integer,intent(in) :: ldyh !! a constant >= n, the first dimension of yh real(wp),intent(inout) :: yh(ldyh,*) !! the nordsieck (taylor) array, ldyh by lmax, input !! and output. on input, it contains predicted values. real(wp) :: vsav(*) !! unused work array. real(wp) :: savf(*) !! a work array of length n. real(wp),intent(in) :: ewt(*) !! an error weight vector of length n real(wp),intent(inout) :: acor(*) !! a work array of length n, used for the accumulated !! corrections to the predicted y vector. real(wp),intent(inout) :: wm(*) !! real work array associated with matrix !! operations in chord iteration (miter /= 0). integer,intent(inout) :: iwm(*) !! integer work array associated with matrix !! operations in chord iteration (miter /= 0). integer,intent(inout) :: nflag !! input/output flag, with values and meanings as follows: !! !! * **input:** !! * 0 first call for this time step. !! * -1 convergence failure in previous call to dvnlsd. !! * -2 error test failure in dvstep. !! !! * **output:** !! * 0 successful completion of nonlinear solver. !! * -1 convergence failure or singular matrix. !! * -2 unrecoverable error in matrix preprocessing (cannot occur here). !! * -3 unrecoverable error in solution (cannot occur here). real(wp) :: cscale , dcon , del , delp integer :: i , ierpj , iersl , m integer,parameter :: maxcor = 3 integer,parameter :: msbp = 20 real(wp),parameter :: ccmax = 0.3_wp real(wp),parameter :: crdown = 0.3_wp real(wp),parameter :: rdiv = 2.0_wp real(wp),parameter :: one = 1.0_wp real(wp),parameter :: two = 2.0_wp !----------------------------------------------------------------------- ! on the first step, on a change of method order, or after a ! nonlinear convergence failure with nflag = -2, set ipup = miter ! to force a jacobian update when miter /= 0. !----------------------------------------------------------------------- if ( me%dat%jstart==0 ) me%dat%nslp = 0 if ( nflag==0 ) me%dat%icf = 0 if ( nflag==-2 ) me%dat%ipup = me%dat%miter if ( (me%dat%jstart==0) .or. (me%dat%jstart==-1) ) me%dat%ipup = me%dat%miter ! if this is functional iteration, set crate == 1 and drop to 220 if ( me%dat%miter==0 ) then me%dat%crate = one else !----------------------------------------------------------------------- ! rc is the ratio of new to old values of the coefficient h/el(2)=h/l1. ! when rc differs from 1 by more than ccmax, ipup is set to miter ! to force dvjac to be called, if a jacobian is involved. ! in any case, dvjac is called at least every msbp steps. !----------------------------------------------------------------------- me%dat%drc = abs(me%dat%rc-one) if ( me%dat%drc>ccmax .or. me%dat%nst>=me%dat%nslp+msbp ) me%dat%ipup = me%dat%miter end if corrector : do !----------------------------------------------------------------------- ! up to maxcor corrector iterations are taken. a convergence test is ! made on the r.m.s. norm of each correction, weighted by the error ! weight vector ewt. the sum of the corrections is accumulated in the ! vector acor(i). the yh array is not altered in the corrector loop. !----------------------------------------------------------------------- m = 0 delp = zero call dcopy(me%dat%n,yh(1,1),1,y,1) call me%f(me%dat%n,me%dat%tn,y(1:me%dat%n),savf(1:me%dat%n)) me%dat%nfe = me%dat%nfe + 1 if ( me%dat%ipup>0 ) then !----------------------------------------------------------------------- ! if indicated, the matrix p = i - h*rl1*j is reevaluated and ! preprocessed before starting the corrector iteration. ipup is set ! to 0 as an indicator that this has been done. !----------------------------------------------------------------------- call me%dvjac(y,yh,ldyh,ewt,acor,savf,wm,iwm,ierpj) me%dat%ipup = 0 me%dat%rc = one me%dat%drc = zero me%dat%crate = one me%dat%nslp = me%dat%nst ! if matrix is singular, take error return to force cut in step size. -- if ( ierpj/=0 ) exit corrector endif do i = 1 , me%dat%n acor(i) = zero enddo do ! this is a looping point for the corrector iteration. ----------------- if ( me%dat%miter/=0 ) then !----------------------------------------------------------------------- ! in the case of the chord method, compute the corrector error, ! and solve the linear system with that as right-hand side and ! p as coefficient matrix. the correction is scaled by the factor ! 2/(1+rc) to account for changes in h*rl1 since the last dvjac call. !----------------------------------------------------------------------- do i = 1 , me%dat%n y(i) = (me%dat%rl1*me%dat%h)*savf(i) - (me%dat%rl1*yh(i,2)+acor(i)) enddo call me%dvsol(wm,iwm,y,iersl) me%dat%nni = me%dat%nni + 1 if ( iersl>0 ) exit if ( me%dat%meth==2 .and. me%dat%rc/=one ) then cscale = two/(one+me%dat%rc) call dscal(me%dat%n,cscale,y,1) endif del = me%dvnorm(me%dat%n,y(1:me%dat%n),ewt(1:me%dat%n)) call daxpy(me%dat%n,one,y,1,acor,1) do i = 1 , me%dat%n y(i) = yh(i,1) + acor(i) enddo else !----------------------------------------------------------------------- ! in the case of functional iteration, update y directly from ! the result of the last function evaluation. !----------------------------------------------------------------------- do i = 1 , me%dat%n savf(i) = me%dat%rl1*(me%dat%h*savf(i)-yh(i,2)) enddo do i = 1 , me%dat%n y(i) = savf(i) - acor(i) enddo del = me%dvnorm(me%dat%n,y(1:me%dat%n),ewt(1:me%dat%n)) do i = 1 , me%dat%n y(i) = yh(i,1) + savf(i) enddo call dcopy(me%dat%n,savf,1,acor,1) endif !----------------------------------------------------------------------- ! test for convergence. if m > 0, an estimate of the convergence ! rate constant is stored in crate, and this is used in the test. !----------------------------------------------------------------------- if ( m/=0 ) me%dat%crate = max(crdown*me%dat%crate,del/delp) dcon = del*min(one,me%dat%crate)/me%dat%tq(4) if ( dcon<=one ) then ! return for successful step. ------------------------------------------ nflag = 0 me%dat%jcur = 0 me%dat%icf = 0 if ( m==0 ) me%dat%acnrm = del if ( m>0 ) me%dat%acnrm = me%dvnorm(me%dat%n,acor(1:me%dat%n),ewt(1:me%dat%n)) return else m = m + 1 if ( m/=maxcor ) then if ( m<2 .or. del<=rdiv*delp ) then delp = del call me%f(me%dat%n,me%dat%tn,y(1:me%dat%n),savf(1:me%dat%n)) me%dat%nfe = me%dat%nfe + 1 cycle endif endif exit endif end do if ( me%dat%miter/=0 .and. me%dat%jcur/=1 ) then me%dat%icf = 1 me%dat%ipup = me%dat%miter else exit corrector endif end do corrector nflag = -1 me%dat%icf = 2 me%dat%ipup = me%dat%miter end subroutine dvnlsd