TABLE OF CONTENTS
::pwtk::runPW_remedy
SYNOPSIS
proc ::pwtk::runPW_remedy {args} {
USAGE
runPW_remedy [remedy-options] [runPW-options] input ?output? The remedy-options are: -reduceconv FACTOR -nsteps NUMBER -script SCRIPT -nlevels NUMBER -remedy1st -restart For the runPW-options see the options of ::pwtk::runPW
PURPOSE
A variant of ::pwtk::runPW with a mechanism for dealing with SCF convergence problems.
OPTIONS
The remedy-options are the following:
- -script SCRIPT == how to change the pw.x input for the remedy calculation upon the SCF convergence failure
- -reduceconv FACTOR == if remedy calculation fails, further loose "conv_thr" by "FACTOR" and retry
- -nsteps NUMBER == how many ionic steps to perform in remedy calculation (note that sometimes it may help the SCF convergnece to move a bit the atoms)
- -nlevels NUMBER == number of remedy trials before aborting (default value is 5)
- -remedy1st == start immediately with the remedy mode
- -restart == run already the first calculation in restart mode, i.e., restart from previous calculation (aka rerunPW)
ARGUMENTS
- input -- filename (or headname) to which the pw.x input file will be stored. The .in (.out) suffix will be added to headname for input (output) filename.
- output -- [optional] filename to which the pw.x output will be stored
DESCRIPTION
The ::pwtk::runPW_remedy behaves like ::pwtk::runPW but if the SCF fails, it tries to remedy it by making a calculation in "remedy" mode where the pw.x input will be changed by the instructions provided with the -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 with "__remedy-N__", 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 run_extra_options variable run # query the calculation type and for non-allowed calculation, raise an error set calc [::pwtk::input::namelistGetVarValue CONTROL calculation trim] ifset calc scf switch -glob -- $calc { scf - relax - vc-relax {} default { ::pwtk::error "[procName] does not work for \"calculation = '$calc'\";\nit supports only 'scf', 'relax', and 'vc-relax' calculations" 1 } } incr remedy_level if { $remedy_level == 1 } { printTitle REMEDY "Running pw.x in \"remedy\" mode" } set remedy_options { {reduceconv.arg 1.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 {} "script to execute before runing the remedy calculation (the purpose of the script is to modify the pw.x input)"} {nlevels.arg 5 "number of remedy trials before aborting"} {remedy1st "run first in remedy mode"} {restart "run the first calculation in restart mode (e.g., restart from the scf-failed calculation"} } set args_orig $args array set opt [::cmdline::getKnownOptions args $remedy_options] set argums $args ::cmdline::getoptions argums [concat $run_options $run_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 $run_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] ifset output [outputName_ $input] set runPW runPW if { $opt(restart) } { set runPW rerunPW } # check the values of options ::pwtk::checkOTypeStrict_ -reduceconv $opt(reduceconv) {number real} "real number" ::pwtk::checkOTypeStrict_ -nsteps $opt(nsteps) {number posint} "positive integer" ::pwtk::checkOTypeStrict_ -nlevels $opt(nlevels) {number posint} "positive integer" input_pushpop { set disk_io [::pwtk::input::namelistGetVarValue CONTROL disk_io trim] if { $disk_io ne "high" || $disk_io ne "medium" } { infoMsg "temporarily setting disk_io = 'medium'" CONTROL { disk_io = 'medium' } } # BEWARE where state() is modified wrt input_pushpop set stopOnError_orig $state(stopOnError) set state(stopOnError) -1; # BEWARE: has to be -1 (see ::pwtk::checkForError) if { ! $opt(remedy1st) } { # # NORMAL mode # ::pwtk::print REMEDY-#$remedy_level "Running calculation in normal mode\n" #------------------------------------------------------------------------ eval $runPW $pw_options $input $output if { $error(type) eq {} } { ::pwtk::print REMEDY-#$remedy_level "SUCCESS: calculation converged !!!\n" } #------------------------------------------------------------------------ set runPW rerunPW set output $run(output) } if { $remedy_level > $opt(nlevels) && $error(type) == "convergence failure" } { # if there is already too many remedy trials, abort as to # prevent too many trials if { $stopOnError_orig } { ::pwtk::error "Too many trials of runPW_remedy. Aborting ..." 1 } else { ::pwtk::warning "Too many trials of runPW_remedy. Giving up ..." } } elseif { (! $opt(remedy1st) && $error(type) == "convergence failure") || $opt(remedy1st) } { # # REMEDY mode (r.m.) # # i.e.: either a convergence failure or a "remedy1st" request set head [::pwtk::trim_prefix $calc [::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" ::pwtk::print $opt(script)\n #1: try with the supplied script input_pushpop { if { [string match *relax $calc] } { # remedy mode should make only $opt(nsteps) ionic steps if { [file exists $output] } { set curr_cycles [::pwtk::grep_field "number of scf cycles" $pwo end end] } ifset curr_cycles 0 CONTROL " nstep = [expr $curr_cycles + $opt(nsteps)] " } # eval the REMEDY script eval $opt(script) if { $opt(reduceconv) <= 1.0} { # do not retry if the remedy #1 calculation fails, hence # treat the stopOnError by original (default) way set state(stopOnError) $stopOnError_orig } ::pwtk::print REMEDY-#$remedy_level "Runing the remedy calculation\n" #---remedy #1---------------- eval $runPW $pw_options $head #---------------------------- set runPW rerunPW set state(stopOnError) $stopOnError_orig if { $error(type) == "convergence failure" && $opt(reduceconv) > 1.0} { # ::pwtk::print REMEDY-#$remedy_level "The remedy calculation failed !\n" #2: try by reducing conv_thr input_pushpop { # reduce the conv_thr and make another trial; but do not go beyond conv_thr = 1e-4 set conv_thr [::pwtk::pwi::reduceConvThr $opt(reduceconv)] if { [string match *relax $calc] } { ::pwtk::print REMEDY-#$remedy_level "Temporarily setting upscale = 1.0" IONS { upscale = 1.0 } } ::pwtk::print REMEDY-#$remedy_level "Temporarily loosing the SCF conv_thr by a factor of $opt(reduceconv) * new value of conv_thr = [format %7.2e $conv_thr]\n" file copy -force $head.in $head.fail.in #---remedy #2------------------------ eval $runPW $pw_options -append $head if { $error(type) eq {} } { ::pwtk::print REMEDY-#$remedy_level "SUCCESS: calculation converged !!!\n" } #------------------------------------ }; #2 } }; #1 set state(stopOnError) $stopOnError_orig # for $stopOnError_orig == true: if we come thus far, the remedy calculation converged; # restart a "normal" calculation via the recursive call to runPW_remedy -restart # strip the -restart & -remedy1st options array set opt [::cmdline::getKnownOptions args_orig {{restart ""} {remedy1st ""}} ] #------------------------------------ eval runPW_remedy -restart $args_orig #------------------------------------ }; # REMEDY-mode (r.m.) # BEWARE no need to revert state(stopOnError) due to input_pushpop }; # input_pushpop incr remedy_level -1 }