[gpaw-users] Manipulating the SCF Loop
Tristan Maxson
tgmaxson at gmail.com
Mon Jul 14 09:47:33 CEST 2014
An issue that plagued me for a while concerning this was that the density
error is actually per valance electron so you need to multiple by the
number of valence electrons in the system when figuring the density error.
The following code worked for me to test if changing the dipole correction
during the run is valid, results unknown but the technique is useful
regardless for other settings.
class Observer:
def __init__(self):
self.iterations = 0
def __call__(self):
if rank == 0:
os.system("echo "+str(calc.scf.density_error)+" >> ELOG")
nvalence = calc.wfs.setups.nvalence - calc.input_parameters.charge
if calc.scf.density_error < (0.0001 * nvalence):
if calc.hamiltonian.poisson == correction:
calc.scf.converged = True
else:
calc.write("WithoutDipole.gpw", mode="all")
parprint("Switching to Dipole Correction")
calc.hamiltonian.poisson = correction
calc.hamiltonian.poisson.set_grid_descriptor(calc.hamiltonian.finegd)
self.iterations += 1
calc.attach(Observer(), 1)
It might make more sense from a logical standpoint to move the nvalence to
the scf class for ease of access as I have done in an attached patch file.
This would make modifying these values easier and improve clarity in code,
even if it is uncommon.
On Wed, Jul 9, 2014 at 1:58 PM, Tristan Maxson <tgmaxson at gmail.com> wrote:
> Would a way of manually running a SCF loop with a initialize, iterate,
> and finalize be something of interest to be developed?...It seems like it
> should be a fairly simple thing to break down and use and I might be
> interested in helping to develop it if it does not currently exist.
>
> Thank you for your solution, it appears to work but I agree a different
> method would probably be preferred. For clarification, do observers reset
> (for example the iterations value) by defining it as you did, when the
> calculation ends or would I have to reset it after convergence manually to
> perform the calculation again?
>
>
> On Wed, Jul 9, 2014 at 10:52 AM, Tristan Maxson <tgmaxson at gmail.com>
> wrote:
>
>> Would a way of manually running a SCF loop with a initialize, iterate,
>> and finalize be something of interest to be developed?...It seems like it
>> should be a fairly simple thing to break down and use and I might be
>> interested in helping to develop it if it does not currently exist.
>>
>> Thank you for your solution, it appears to work but I agree a different
>> method would probably be preferred. For clarification, do observers reset
>> (for example the iterations value) by defining it as you did, when the
>> calculation ends or would I have to reset it after convergence manually to
>> perform the calculation again?
>>
>>
>> On Wed, Jul 9, 2014 at 4:18 AM, Ask Hjorth Larsen <asklarsen at gmail.com>
>> wrote:
>>
>>> Hi Tristan
>>>
>>> Something like this. I haven't quite tested.
>>>
>>> calc = GPAW(convergence=dict(density=-1))
>>>
>>> class Observer:
>>> def __init__(self):
>>> self.iterations = 0
>>>
>>> def __call__(self):
>>> print 'Do something'
>>> if self.iterations > 20 and calc.scf.density_error < 1e-4:
>>> calc.scf.converged = True
>>> self.iterations += 1
>>>
>>> calc.attach(Observer(), 1)
>>>
>>>
>>> It would be nice if one could just iterate the sodding thing like this:
>>>
>>> for i in range(20):
>>> calc.iterate()
>>>
>>> and then trigger the normal SCF procedure afterwards. But that isn't
>>> possible at the moment.
>>>
>>> You could probably also call calc.set(convergence=...) from within the
>>> observer, but the set() method is prone to severe bugginess.
>>>
>>> Best regards
>>> Ask
>>>
>>> 2014-07-08 22:32 GMT+02:00 Tristan Maxson <tgmaxson at gmail.com>:
>>> > I have been doing some work which requires actively manipulating the
>>> SCF
>>> > loop between iterations and encountered a problem where the loop may
>>> end
>>> > before I desire it to.
>>> >
>>> > I am looking for some sort of "miniter" or a method of forcing another
>>> > iteration of the SCF loop from an attached observer that does not
>>> require
>>> > modifying the source if at all possible. I need the calculation to
>>> continue
>>> > as if the convergence was not reached in that iteration.
>>> >
>>> > _______________________________________________
>>> > gpaw-users mailing list
>>> > gpaw-users at listserv.fysik.dtu.dk
>>> > https://listserv.fysik.dtu.dk/mailman/listinfo/gpaw-users
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listserv.fysik.dtu.dk/pipermail/gpaw-users/attachments/20140714/2e3e6aa1/attachment.html>
-------------- next part --------------
Index: gpaw/scf.py
===================================================================
--- gpaw/scf.py (revision 11592)
+++ gpaw/scf.py (working copy)
@@ -10,12 +10,13 @@
"""
def __init__(self, eigenstates=0.1, energy=0.1, density=0.1, maxiter=100,
- fixdensity=False, niter_fixdensity=None):
- self.max_eigenstates_error = max(eigenstates, 1e-20)
- self.max_energy_error = energy
- self.max_density_error = max(density, 1e-20)
+ fixdensity=False, niter_fixdensity=None, nvalence=0):
+ self.max_eigenstates_error = max(eigenstates * nvalence, 1e-20)
+ self.max_energy_error = energy * max(nvalence, 1)
+ self.max_density_error = max(density * nvalence, 1e-20)
self.maxiter = maxiter
self.fixdensity = fixdensity
+ self.nvalence = nvalence
if niter_fixdensity is None:
niter_fixdensity = 2
Index: gpaw/paw.py
===================================================================
--- gpaw/paw.py (revision 11592)
+++ gpaw/paw.py (working copy)
@@ -504,11 +504,11 @@
if self.scf is None:
self.scf = SCFLoop(
- cc['eigenstates'] / Hartree**2 * nvalence,
- cc['energy'] / Hartree * max(nvalence, 1),
- cc['density'] * nvalence,
+ cc['eigenstates'] / Hartree**2,
+ cc['energy'] / Hartree,
+ cc['density'],
par.maxiter, par.fixdensity,
- niter_fixdensity)
+ niter_fixdensity, nvalence)
parsize_kpt = par.parallel['kpt']
parsize_domain = par.parallel['domain']
More information about the gpaw-users
mailing list