Core minimization routine
Iterates until the (force-)tolerance or the maximum number of iterations is reached. Also writes output files after set number of iterations
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_minimizer_mhd3d), | intent(inout) | :: | sf |
minimizer |
||
| real(kind=wp), | intent(in) | :: | abstol |
tolerance on the forces. If reached terminaters the minimization |
||
| integer, | intent(in) | :: | maxIter_in |
maximum number of iterations after which the iterations are terminated |
SUBROUTINE MinimizeMHD3D_descent(sf, abstol, maxIter_in) USE MODgvec_MHD3D_EvalFunc, ONLY: EvalAux, EvalForce, EvalEnergy USE MODgvec_Analyze, ONLY:analyze USE MODgvec_Restart, ONLY:WriteState USE MODgvec_MHD3D_visu, ONLY:WriteSFLoutfile USE MODgvec_sol_var_MHD3D, ONLY: t_sol_var_MHD3D IMPLICIT NONE REAL(wp), INTENT(IN) :: abstol !! tolerance on the forces. If reached terminaters the minimization INTEGER, INTENT(IN) :: maxIter_in !! maximum number of iterations after which the iterations are terminated !----------------------------------------------------------------------------------------------------------------------------------- ! OUTPUT VARIABLES CLASS(t_minimizer_mhd3d), INTENT(INOUT) :: sf !! minimizer !----------------------------------------------------------------------------------------------------------------------------------- ! LOCAL VARIABLES INTEGER :: maxIter !! maximum number of iterations !================================================================================================================================= ASSOCIATE(vars=>sf%vars) maxIter = vars%iter + maxIter_in DO WHILE(vars%iter.LT.maxIter) IF((vars%restart_iter))THEN CALL sf%reset() END IF !before first iteration or after restart Jac<0 IF(.NOT.vars%logger_is_initialized)THEN CALL sf%StartLogging() END IF !COMPUTE NEW SOLUTION P(1) as a prediction SELECT TYPE(vars) TYPE IS(t_gradient_descent_vars) !gradient descent, previously used for minimizerType=0 CALL vars%temp_dofs(1)%AXBY(1.0_wp,vars%dofs(0),vars%dt,vars%force(0)) !overwrites P(1), predicts solution U(1) TYPE IS(t_accelerated_gradient_descent_vars) !hirshman method !tau is damping parameter vars%tau(1:vars%ndamp-1) = vars%tau(2:vars%ndamp) !save old !ln(|F_n|^2/|F_{n-1}|^2), Fnorm=|F_X1|,|F_X2|,|F_LA| vars%tau(vars%ndamp) = MIN(0.15_wp,ABS(LOG(SUM(vars%Fnorm**2)/SUM(vars%Fnorm_old**2))))/vars%dt vars%tau_bar = 0.5_wp*vars%dt*SUM(vars%tau)/REAL(vars%ndamp,wp) !=1/2 * tauavg CALL vars%velocity(1)%AXBY(((1.0_wp-vars%tau_bar)/(1.0_wp+vars%tau_bar)),vars%velocity(0),(vars%dt/(1.0_wp+vars%tau_bar)),vars%force(0)) !velocity V(1) CALL vars%temp_dofs(1)%AXBY(1.0_wp,vars%dofs(0),vars%dt,vars%velocity(1)) !overwrites P(1), predicst solution U(1) vars%Vnorm=SQRT(vars%velocity(1)%norm_2()) END SELECT !Type vars%JacCheck=2 !no abort,if detJ<0, JacCheck=-1 vars%temp_dofs(1)%W_MHD3D=EvalEnergy(vars%temp_dofs(1),.TRUE.,vars%JacCheck) IF(vars%JacCheck.EQ.-1)THEN vars%dt=0.9_wp*vars%dt vars%nstepDecreased=vars%nStepDecreased+1 vars%nSkip_Jac=vars%nSkip_Jac+1 vars%restart_iter=.TRUE. CALL vars%dofs(0)%set_to(vars%dofs(-3)) !reset to initial state SWRITE(UNIT_stdOut,'(8X,I8,A,E11.4,A)')vars%iter,'...detJac<0, decrease stepsize to dt=',vars%dt, ' and RESTART simulation!!!!!!!' ELSE !detJ>0 vars%deltaW=vars%temp_dofs(1)%W_MHD3D-vars%dofs(0)%W_MHD3D!should be <=0, IF(vars%deltaW.LE.vars%dW_allowed*vars%W_MHD3D_0)THEN !valid step /hirshman method accept W increase! IF(ALL(vars%Fnorm.LE.abstol))THEN CALL sf%Logging(.FALSE.) SWRITE(UNIT_stdOut,'(4x,A)')'==>Iteration finished, |force| in relative tolerance' EXIT !DO LOOP END IF vars%iter=vars%iter+1 vars%t_pseudo=vars%t_pseudo+vars%dt ! for simple gradient & hirshman CALL vars%dofs(-1)%set_to(vars%dofs(0)) CALL vars%dofs(0)%set_to(vars%temp_dofs(1)) ! for hirshman method SELECT TYPE(vars) TYPE IS(t_accelerated_gradient_descent_vars) CALL vars%velocity(-1)%set_to(vars%velocity(0)) CALL vars%velocity(0)%set_to(vars%velocity(1)) END SELECT CALL EvalForce(vars%temp_dofs(1),.FALSE.,vars%JacCheck,vars%force(0)) !evalAux was already called on P(1)=U(0), so that its set false here. vars%Fnorm_old=vars%Fnorm vars%Fnorm=SQRT(vars%force(0)%norm_2()) vars%nstepDecreased=0 vars%min_dt_out=MIN(vars%min_dt_out,vars%dt) vars%max_dt_out=MAX(vars%max_dt_out,vars%dt) vars%min_dW_out=MIN(vars%min_dW_out,vars%deltaW) vars%max_dW_out=MAX(vars%max_dW_out,vars%deltaW) vars%sum_dW_out=vars%sum_dW_out+vars%deltaW IF(MOD(vars%iter,vars%logIter_ramp).EQ.0)THEN CALL sf%Logging(.NOT.((vars%logIter_ramp.GE.vars%logIter).AND.(MOD(vars%logscreen,vars%nLogScreen).EQ.0))) IF(.NOT.(vars%logIter_ramp.LT.vars%logIter))THEN !only reset for logIter vars%logscreen=vars%logscreen+1 vars%min_dt_out=1.0e+30_wp vars%max_dt_out=0.0_wp vars%min_dW_out=1.0e+30_wp vars%max_dW_out=-1.0e+30_wp vars%sum_dW_out=0.0_wp vars%nSkip_dW =0 END IF vars%logIter_ramp=MIN(vars%logIter,vars%logIter_ramp*2) END IF ELSE !not a valid step, decrease timestep and skip P(1) vars%dt=0.9_wp*vars%dt vars%nstepDecreased=vars%nStepDecreased+1 vars%nSkip_dW=vars%nSkip_dW+1 vars%restart_iter=.TRUE. SWRITE(UNIT_stdOut,'(8X,I8,A,E8.2,A,E8.1,A,E11.4)')vars%iter,'...deltaW=',vars%deltaW,'>',vars%dW_allowed,& '*W_MHD3D_0, skip step and decrease stepsize to dt=',vars%dt END IF END IF !JacCheck IF(vars%nStepDecreased.GT.130) THEN ! 0.9^130 ~10^-6 SWRITE(UNIT_stdOut,'(A,E21.11)')'Iteration stopped since timestep has been decreased by 0.9^130: ', vars%dt SWRITE(UNIT_stdOut,fmt_sep) RETURN END IF IF((MOD(vars%iter,vars%outputIter).EQ.0).AND.(vars%lastoutputIter.NE.vars%iter))THEN __PERFON('output') SWRITE(UNIT_stdOut,'(A)')'########################## OUTPUT ##################################' CALL Analyze(vars%iter, vars%dofs(0), vars%force(0)) CALL WriteState(vars%dofs(0),vars%iter) SWRITE(UNIT_stdOut,'(A)')'#####################################################################' vars%lastOutputIter=vars%iter __PERFOFF('output') END IF END DO !iter IF(vars%iter.GE.MaxIter)THEN SWRITE(UNIT_stdOut,'(A,E21.11)')"maximum iteration count exceeded" END IF SWRITE(UNIT_stdOut,'(A)') "... DONE." SWRITE(UNIT_stdOut,fmt_sep) IF(vars%lastoutputIter.NE.vars%iter)THEN CALL Analyze(MIN(vars%iter,MaxIter), vars%dofs(0), vars%force(0)) CALL WriteState(vars%dofs(0),MIN(vars%iter,MaxIter)) END IF CALL writeSFLoutfile(vars%dofs(0),MIN(vars%iter,MaxIter)) END ASSOCIATE !vars END SUBROUTINE MinimizeMHD3D_descent