TABLE OF CONTENTS


::pwtk::runPW_remedy

SYNOPSIS

proc ::pwtk::runPW_remedy {args} {

USAGE

runPW_remedy [remedy-options] [runPW-options] input ?output?

Remedy-options are:

     -restart
     -remedy1st
     -reduceconv <factor>
     -nsteps <value>
     -script <script>
     -max_thr <value>
     -nlevels <number>

RunPW-options are options of ::pwtk::runPW

PURPOSE

An ehanced version of ::pwtk::runPW with an automatic mechanism for dealing with SCF convergence problems.

OPTIONS

Remedy options are the following:

ARGUMENTS

DESCRIPTION

The ::pwtk::runPW_remedy behaves like ::pwtk::runPW with the exeption that if the SCF convergence fails, it will try to remedy it by making a calculation in "remedy" mode where the pw.x input will be changed by the instructions provided with -script option. If the SCF converges with the remedy calculation then the calculation is restarted in normal mode. If even the remedy calculation fails and -reduceconv option was specified then another remedy calculation is performed with the reduced conv_thr threshold.

The names of the I/O files of remedy calculations are prefixed by "__remedy-N__" string, where N is the sequential number of a given remedy calculation.

EXAMPLE

::pwtk::runPW_remedy -script {

       CONTROL { calculation = 'scf' }
       SYSTEM { degauss = 0.05 }
       ::pwtk::pwi::disableDipoleCorr

} relax.in

SOURCE

    variable error
    variable state
    variable remedy_level
    variable run_options
    variable runPW_extra_options
    variable run

    if { [remote_mode_] } {
        ::pwtk::warning "::pwtk::runPW_remedy may not run as expected in remote mode"
    }
    
    incr remedy_level

    if { $remedy_level == 1 } {
        printTitle REMEDY "Running pw.x in \"remedy\" mode"
    }
    
    set args_orig $args
    
    set extra_options {
        {restart     0   "run already the first calculation in restart mode, i.e., restart from scf-failed calculation"}
        {remedy1st   0   "run first in remedy mode"}
        {reduceconv.arg  0   "reduce the conv_thr if remedy calculation fails and make another trial"}
        {nsteps.arg      2   "how many ionic steps to run in remedy mode"}
        {script.arg  ::pwtk::pwi::disableDipoleCorr "script to execute before runing the remedy calculation (the purpose of the script is to modify the pw.x input)"}
        {loose_thr.arg   1d-4  "the loosest acceptable conv_thr"}
        {nlevels.arg     5     "number of remedy trials before aborting"}
    }

    array set opt [::cmdline::getKnownOptions args $extra_options]    
    set argums $args
    #
    ::cmdline::getoptions argums [concat $run_options $runPW_extra_options] "\n\nUsage: ::pwtk::runPW_remedy \[options\] input ?output?\n\nOptions are:"
    #
    set argums_len [llength $argums]
    set args_len   [llength $args]
    if { $argums_len < 1 || $argums_len > 2 } {
        ::pwtk::error [::cmdline::usage [concat $run_options $runPW_extra_options] "\n\nUsage: ::pwtk::runPW_remedy \[options\] input ?output?"] 1
    } else {
        set pw_options [lrange $args 0 [expr $args_len - $argums_len - 1]]
    }

    set input  [lindex $argums 0]
    set output [lindex $argums 1]   
    if { $output == {} } {
        set output [outputName_ $input]
    }
    
    set runPW runPW
    if { $opt(restart) } {
        set runPW rerunPW
    }
        
    set stopOnError_orig $state(stopOnError)
    set state(stopOnError) -1

    if { ! $opt(remedy1st) } {
        #
        # NORMAL mode
        #
        ::pwtk::print REMEDY-#$remedy_level "Running calculation in normal mode in \$PWD directory:\n  [pwd]"
        ::pwtk::print REMEDY-#$remedy_level "  * current value of stopOnError = $state(stopOnError)\n"
        #-------------------------------------
        eval $runPW $pw_options $input $output
        #-------------------------------------
        set runPW rerunPW
        set output $run(output)
    }
    
    if { (! $opt(remedy1st) && $error(type) == "convergence failure") || $opt(remedy1st) } {
        #
        # REMEDY mode
        #
        
        set head [regsub "^relax.|^vc-relax.|^scf." [::pwtk::headname $input] {}]
        set head __remedy-${remedy_level}__.$head

        ::pwtk::print REMEDY-#$remedy_level "Trying to remedy SCF convergence problems using the following instructions:\n  $opt(script)"

        input_push; #1

        # remedy mode should make only $opt(nsteps) ionic steps
        runPW_remedy_fewSteps_ $output $opt(nsteps)

        # eval the REMEDY script
        eval $opt(script)
        #-----------------------
        
        if { $opt(reduceconv) <= 0.0} {
            # do not retry if the remedy calculation fails, hence
            # treat the stopOnError by original (default) way
            set state(stopOnError) $stopOnError_orig
        }

        ::pwtk::print REMEDY-#$remedy_level "Runing the remedy calculation ..."
        ::pwtk::print REMEDY-#$remedy_level "  * current value of stopOnError = $state(stopOnError)\n"
        #----------------------------
        eval $runPW $pw_options $head 
        #----------------------------
        set runPW rerunPW
        set state(stopOnError) $stopOnError_orig        

        if { $error(type) == "convergence failure" && $opt(reduceconv) > 0.0} {
            # reduce the conv_thr and make another trial; but do not go beyond conv_thr = 1e-4

            set conv_thr_old [f2c_number [::pwtk::input::namelistGetVarValue ELECTRONS conv_thr]]
            
            ::pwtk::print REMEDY-#$remedy_level "Apparently the remedy calculation failed !\n"

            input_push; #2

            ::pwtk::pwi::reduceConvThr $opt(reduceconv)
            IONS { upscale = 1.0 }

            set conv_thr [f2c_number [::pwtk::input::namelistGetVarValue ELECTRONS conv_thr]]
            
            if { $conv_thr <= $opt(loose_thr) } {
                ::pwtk::print REMEDY-#$remedy_level "Temporarily reducing the SCF conv_thr and setting upscale = 1.0 ..."          
                ::pwtk::print REMEDY-#$remedy_level "  * previous value of conv_thr = [format %7.2e $conv_thr_old]"
                ::pwtk::print REMEDY-#$remedy_level "  *  reduced value of conv_thr = [format %7.2e $conv_thr]"
                ::pwtk::print REMEDY-#$remedy_level "  * current value of stopOnError = $state(stopOnError)\n"
                #
                file copy -force $head.in $head.fail.in
                #------------------------------------
                eval $runPW $pw_options -append $head
                #------------------------------------
            } else {
                ::pwtk::print REMEDY-#$remedy_level "The SCF conv_thr is too low to be reduced further. Aborting."         
                ::pwtk::print REMEDY-#$remedy_level "  * current value of non reduced conv_thr = [format %7.2e $conv_thr_old]"
                ::pwtk::print REMEDY-#$remedy_level "  * reduced value of conv_thr would be $conv_thr, which is lower then $opt(loose_thr)\n"
            }
            input_pop; #2
        }
        
        input_pop; #1

        # if we come thus far, the remedy calculation converged;
        # now restart a (normal) calculation via runPW_remedy

        set state(stopOnError) $stopOnError_orig
        
        # N.B.: use a maximum of $opt(nlevels) trials of runPW_remedy as to prevent too many trials
        
        if { $remedy_level < $opt(nlevels) } {

            # strip the restart & remedy1st options 
            set ignored_options {
                {restart   0  "ignored option"}
                {remedy1st 0  "ignored option"}
            }    
            array set opt [::cmdline::getKnownOptions args_orig $ignored_options]
            
            ::pwtk::print REMEDY-#$remedy_level "Reverting back to normal calculation mode."
            ::pwtk::print REMEDY-#$remedy_level "  * current value of stopOnError = $state(stopOnError)\n"
            
            eval runPW_remedy -restart $args_orig
        } else {
            # too many levels - give up
            
            if { $stopOnError_orig } {
                ::pwtk::error "Too many trials of runPW_remedy tricks. Aborting ..."
            } else {
                ::pwtk::warning "Too many trials of runPW_remedy tricks. Giving up ..."
            }
        }
    }; # remedy-mode

    set state(stopOnError) $stopOnError_orig
    
    ::pwtk::print REMEDY-#$remedy_level "Leaving runPW_remedy #$remedy_level"
    if { $remedy_level == 1 } { ::pwtk::print "" }
    
    incr remedy_level -1
}