Statistiques
| Révision :

root / ase / calculators / jacapo / jacapo.py @ 8

Historique | Voir | Annoter | Télécharger (140,74 ko)

1 1 tkerber
'''
2 1 tkerber
python module for ASE2-free and Numeric-free dacapo
3 1 tkerber

4 1 tkerber
U{John Kitchin<mailto:jkitchin@andrew.cmu.edu>} December 25, 2008
5 1 tkerber

6 1 tkerber
This module supports numpy directly.
7 1 tkerber

8 1 tkerber
* ScientificPython2.8 is required
9 1 tkerber

10 1 tkerber
 - this is the first version to use numpy by default.
11 1 tkerber

12 1 tkerber
see https://wiki.fysik.dtu.dk/stuff/nc/ for dacapo netcdf variable
13 1 tkerber
documentation
14 1 tkerber
'''
15 1 tkerber
16 1 tkerber
__docformat__ = 'restructuredtext'
17 1 tkerber
18 1 tkerber
import exceptions, glob, os, pickle, string
19 1 tkerber
from Scientific.IO.NetCDF import NetCDFFile as netCDF
20 1 tkerber
import numpy as np
21 1 tkerber
import subprocess as sp
22 1 tkerber
23 1 tkerber
import validate
24 1 tkerber
import changed
25 1 tkerber
26 1 tkerber
import logging
27 1 tkerber
log = logging.getLogger('Jacapo')
28 1 tkerber
29 1 tkerber
handler = logging.StreamHandler()
30 1 tkerber
formatter = logging.Formatter('''\
31 1 tkerber
%(levelname)-10s function: %(funcName)s lineno: %(lineno)-4d \
32 1 tkerber
%(message)s''')
33 1 tkerber
handler.setFormatter(formatter)
34 1 tkerber
log.addHandler(handler)
35 1 tkerber
36 1 tkerber
37 1 tkerber
class DacapoRunning(exceptions.Exception):
38 1 tkerber
    """Raised when ncfile.status = 'running'"""
39 1 tkerber
    pass
40 1 tkerber
41 1 tkerber
class DacapoAborted(exceptions.Exception):
42 1 tkerber
    """Raised when ncfile.status = 'aborted'"""
43 1 tkerber
    pass
44 1 tkerber
45 1 tkerber
class DacapoInput(exceptions.Exception):
46 1 tkerber
    ''' raised for bad input variables'''
47 1 tkerber
    pass
48 1 tkerber
49 1 tkerber
class DacapoAbnormalTermination(exceptions.Exception):
50 1 tkerber
    """Raised when text file does not end correctly"""
51 1 tkerber
    pass
52 1 tkerber
53 1 tkerber
def read(ncfile):
54 1 tkerber
    '''return atoms and calculator from ncfile
55 1 tkerber

56 1 tkerber
    >>> atoms, calc = read('co.nc')
57 1 tkerber
    '''
58 1 tkerber
    calc = Jacapo(ncfile)
59 1 tkerber
    atoms = calc.get_atoms() #this returns a copy
60 1 tkerber
    return (atoms, calc)
61 1 tkerber
62 1 tkerber
class Jacapo:
63 1 tkerber
    '''
64 1 tkerber
    Python interface to the Fortran DACAPO code
65 1 tkerber
    '''
66 1 tkerber
67 1 tkerber
    __name__ = 'Jacapo'
68 1 tkerber
    __version__ = 0.4
69 1 tkerber
70 1 tkerber
    #dictionary of valid input variables and default settings
71 1 tkerber
    default_input = {'atoms':None,
72 1 tkerber
                     'pw':350,
73 1 tkerber
                     'dw':350,
74 1 tkerber
                     'xc':'PW91',
75 1 tkerber
                     'nbands':None,
76 1 tkerber
                     'ft':0.1,
77 1 tkerber
                     'kpts':(1,1,1),
78 1 tkerber
                     'spinpol':False,
79 1 tkerber
                     'fixmagmom':None,
80 1 tkerber
                     'symmetry':False,
81 1 tkerber
                     'calculate_stress':False,
82 1 tkerber
                     'dipole':{'status':False,
83 1 tkerber
                               'mixpar':0.2,
84 1 tkerber
                               'initval':0.0,
85 1 tkerber
                               'adddipfield':0.0,
86 1 tkerber
                               'position':None},
87 1 tkerber
                     'status':'new',
88 1 tkerber
                     'pseudopotentials':None,
89 1 tkerber
                     'extracharge':None,
90 1 tkerber
                     'extpot':None,
91 1 tkerber
                     'fftgrid':None,
92 1 tkerber
                     'ascii_debug':'Off',
93 1 tkerber
                     'ncoutput':{'wf':'Yes',
94 1 tkerber
                                 'cd':'Yes',
95 1 tkerber
                                 'efp':'Yes',
96 1 tkerber
                                 'esp':'Yes'},
97 1 tkerber
                     'ados':None,
98 1 tkerber
                     'decoupling':None,
99 1 tkerber
                     'external_dipole':None,
100 1 tkerber
                     'convergence':{'energy':0.00001,
101 1 tkerber
                                    'density':0.0001,
102 1 tkerber
                                    'occupation':0.001,
103 1 tkerber
                                    'maxsteps':None,
104 1 tkerber
                                    'maxtime':None},
105 1 tkerber
                     'charge_mixing':{'method':'Pulay',
106 1 tkerber
                                      'mixinghistory':10,
107 1 tkerber
                                      'mixingcoeff':0.1,
108 1 tkerber
                                      'precondition':'No',
109 1 tkerber
                                      'updatecharge':'Yes'},
110 1 tkerber
                     'electronic_minimization':{'method':'eigsolve',
111 1 tkerber
                                                'diagsperband':2},
112 1 tkerber
                     'occupationstatistics':'FermiDirac',
113 1 tkerber
                     'fftgrid':{'soft':None,
114 1 tkerber
                                'hard':None},
115 1 tkerber
                     'mdos':None,
116 1 tkerber
                     'psp':None
117 1 tkerber
                   }
118 1 tkerber
119 1 tkerber
    def __init__(self,
120 1 tkerber
                 nc='out.nc',
121 1 tkerber
                 outnc=None,
122 1 tkerber
                 debug=logging.WARN,
123 1 tkerber
                 stay_alive=False,
124 1 tkerber
                 **kwargs):
125 1 tkerber
        '''
126 1 tkerber
        Initialize the Jacapo calculator
127 1 tkerber

128 1 tkerber
        :Parameters:
129 1 tkerber

130 1 tkerber
          nc : string
131 1 tkerber
           output netcdf file, or input file if nc already exists
132 1 tkerber

133 1 tkerber
          outnc : string
134 1 tkerber
           output file. by default equal to nc
135 1 tkerber

136 1 tkerber
          debug : integer
137 1 tkerber
           logging debug level.
138 1 tkerber

139 1 tkerber
        Valid kwargs:
140 1 tkerber

141 1 tkerber
          atoms : ASE.Atoms instance
142 1 tkerber
            atoms is an ase.Atoms object that will be attached
143 1 tkerber
            to this calculator.
144 1 tkerber

145 1 tkerber
          pw : integer
146 1 tkerber
            sets planewave cutoff
147 1 tkerber

148 1 tkerber
          dw : integer
149 1 tkerber
            sets density cutoff
150 1 tkerber

151 1 tkerber
          kpts : iterable
152 1 tkerber
            set chadi-cohen, monkhorst-pack kpt grid,
153 1 tkerber
            e.g. kpts = (2,2,1) or explicit list of kpts
154 1 tkerber

155 1 tkerber
          spinpol : Boolean
156 1 tkerber
            sets whether spin-polarization is used or not.
157 1 tkerber

158 1 tkerber
          fixmagmom : float
159 1 tkerber
            set the magnetic moment of the unit cell. only used
160 1 tkerber
            in spin polarize calculations
161 1 tkerber

162 1 tkerber
          ft : float
163 1 tkerber
            set the Fermi temperature used in occupation smearing
164 1 tkerber

165 1 tkerber
          xc : string
166 1 tkerber
            set the exchange-correlation functional.
167 1 tkerber
            one of ['PZ','VWN','PW91','PBE','RPBE','revPBE'],
168 1 tkerber

169 1 tkerber
          dipole
170 1 tkerber
            boolean
171 1 tkerber
            turn the dipole correction on (True) or off (False)
172 1 tkerber

173 1 tkerber
            or:
174 1 tkerber
            dictionary of parameters to fine-tune behavior
175 1 tkerber
            {'status':False,
176 1 tkerber
            'mixpar':0.2,
177 1 tkerber
            'initval':0.0,
178 1 tkerber
            'adddipfield':0.0,
179 1 tkerber
            'position':None}
180 1 tkerber

181 1 tkerber
          nbands : integer
182 1 tkerber
            set the number of bands
183 1 tkerber

184 1 tkerber
          symmetry : Boolean
185 1 tkerber
            Turn symmetry reduction on (True) or off (False)
186 1 tkerber

187 1 tkerber
          stress : Boolean
188 1 tkerber
            Turn stress calculation on (True) or off (False)
189 1 tkerber

190 1 tkerber
          debug : level for logging
191 1 tkerber
            could be something like
192 1 tkerber
            logging.DEBUG or an integer 0-50. The higher the integer,
193 1 tkerber
            the less information you see set debug level (0 = off, 10 =
194 1 tkerber
            extreme)
195 1 tkerber

196 1 tkerber
        Modification of the nc file only occurs at calculate time if needed
197 1 tkerber

198 1 tkerber
        >>> calc = Jacapo('CO.nc')
199 1 tkerber

200 1 tkerber
        reads the calculator from CO.nc if it exists or
201 1 tkerber
        minimally initializes CO.nc with dimensions if it does not exist.
202 1 tkerber

203 1 tkerber
        >>> calc = Jacapo('CO.nc', pw=300)
204 1 tkerber

205 1 tkerber
        reads the calculator from CO.nc or initializes it if
206 1 tkerber
        it does not exist and changes the planewave cutoff energy to
207 1 tkerber
        300eV
208 1 tkerber

209 1 tkerber
         >>> atoms = Jacapo.read_atoms('CO.nc')
210 1 tkerber

211 1 tkerber
        returns the atoms in the netcdffile CO.nc, with the calculator
212 1 tkerber
        attached to it.
213 1 tkerber

214 1 tkerber
        >>> atoms, calc = read('CO.nc')
215 1 tkerber

216 1 tkerber
        '''
217 1 tkerber
        self.debug = debug
218 1 tkerber
        log.setLevel(debug)
219 1 tkerber
220 1 tkerber
        self.pars = Jacapo.default_input.copy()
221 1 tkerber
        self.pars_uptodate = {}
222 1 tkerber
223 1 tkerber
        log.debug(self.pars)
224 1 tkerber
225 1 tkerber
        for key in self.pars:
226 1 tkerber
            self.pars_uptodate[key] = False
227 1 tkerber
228 1 tkerber
        self.kwargs = kwargs
229 1 tkerber
        self.set_psp_database()
230 1 tkerber
231 1 tkerber
        self.set_nc(nc)
232 1 tkerber
        #assume not ready at init, rely on code later to change this
233 1 tkerber
        self.ready = False
234 1 tkerber
235 1 tkerber
        # need to set a default value for stay_alive
236 1 tkerber
        self.stay_alive = stay_alive
237 1 tkerber
238 1 tkerber
        # Jacapo('out.nc') should return a calculator with atoms in
239 1 tkerber
        # out.nc attached or initialize out.nc
240 1 tkerber
        if os.path.exists(nc):
241 1 tkerber
242 1 tkerber
            # for correct updating, we need to set the correct frame number
243 1 tkerber
            # before setting atoms or calculator
244 1 tkerber
245 1 tkerber
            self._set_frame_number()
246 1 tkerber
247 1 tkerber
            self.atoms = self.read_only_atoms(nc)
248 1 tkerber
249 1 tkerber
            #if atoms object is passed to
250 1 tkerber
            #__init__ we assume the user wants the atoms object
251 1 tkerber
            # updated to the current state in the file.
252 1 tkerber
            if 'atoms' in kwargs:
253 1 tkerber
                log.debug('Updating the atoms in kwargs')
254 1 tkerber
255 1 tkerber
                atoms = kwargs['atoms']
256 1 tkerber
                atoms.set_cell(self.atoms.get_cell())
257 1 tkerber
                atoms.set_positions(self.atoms.get_positions())
258 1 tkerber
                atoms.calc = self
259 1 tkerber
260 1 tkerber
            #update the parameter list from the ncfile
261 1 tkerber
            self.update_input_parameters()
262 1 tkerber
263 1 tkerber
            self.ready = True
264 1 tkerber
265 1 tkerber
        #change output file if needed
266 1 tkerber
        if outnc:
267 1 tkerber
            self.set_nc(outnc)
268 1 tkerber
269 1 tkerber
        if len(kwargs) > 0:
270 1 tkerber
271 1 tkerber
            if 'stress' in kwargs:
272 1 tkerber
                raise DacapoInput, '''\
273 1 tkerber
                stress keyword is deprecated.
274 1 tkerber
                you must use calculate_stress instead'''
275 1 tkerber
276 1 tkerber
            #make sure to set calculator on atoms if it was in kwargs
277 1 tkerber
            #and do this first, since some parameters need info from atoms
278 1 tkerber
            if 'atoms' in kwargs:
279 1 tkerber
                #we need to set_atoms here so the atoms are written to
280 1 tkerber
                #the ncfile
281 1 tkerber
                self.set_atoms(kwargs['atoms'])
282 1 tkerber
                kwargs['atoms'].calc = self
283 1 tkerber
                del kwargs['atoms'] #so we don't call it in the next
284 1 tkerber
                                    #line. we don't want to do that
285 1 tkerber
                                    #because it will update the _frame
286 1 tkerber
                                    #counter, and that should not be
287 1 tkerber
                                    #done here.
288 1 tkerber
289 1 tkerber
            self.set(**kwargs) #if nothing changes, nothing will be done
290 1 tkerber
291 1 tkerber
    def set(self, **kwargs):
292 1 tkerber
        '''set a parameter
293 1 tkerber

294 1 tkerber
        parameter is stored in dictionary that is processed later if a
295 1 tkerber
        calculation is need.
296 1 tkerber
        '''
297 1 tkerber
        for key in kwargs:
298 1 tkerber
            if key not in self.default_input:
299 1 tkerber
                raise DacapoInput, '%s is not valid input' % key
300 1 tkerber
301 1 tkerber
            if kwargs[key] is None:
302 1 tkerber
                continue
303 1 tkerber
304 1 tkerber
            #now check for valid input
305 1 tkerber
            validf = 'validate.valid_%s' % key
306 1 tkerber
            valid = eval('%s(kwargs[key])' % validf)
307 1 tkerber
            if not valid:
308 1 tkerber
                s = 'Warning invalid input detected for key "%s" %s'
309 1 tkerber
                log.warn(s % (key,
310 1 tkerber
                              kwargs[key]))
311 1 tkerber
                raise DacapoInput, s % (key, kwargs[key])
312 1 tkerber
313 1 tkerber
            #now see if key has changed
314 1 tkerber
            if key in self.pars:
315 1 tkerber
                changef = 'changed.%s_changed' % key
316 1 tkerber
                if os.path.exists(self.get_nc()):
317 1 tkerber
                    notchanged = not eval('%s(self,kwargs[key])' % changef)
318 1 tkerber
                else:
319 1 tkerber
                    notchanged = False
320 1 tkerber
                log.debug('%s notchanged = %s' % (key, notchanged))
321 1 tkerber
322 1 tkerber
                if notchanged:
323 1 tkerber
                    continue
324 1 tkerber
325 1 tkerber
            log.debug('setting: %s. self.ready = False ' % key)
326 1 tkerber
327 1 tkerber
            self.pars[key] = kwargs[key]
328 1 tkerber
            self.pars_uptodate[key] = False
329 1 tkerber
            self.ready = False
330 1 tkerber
            log.debug('exiting set function')
331 1 tkerber
332 1 tkerber
    def write_input(self):
333 1 tkerber
        '''write out input parameters as needed
334 1 tkerber

335 1 tkerber
        you must define a self._set_keyword function that does all the
336 1 tkerber
        actual writing.
337 1 tkerber
        '''
338 1 tkerber
        log.debug('Writing input variables out')
339 1 tkerber
        log.debug(self.pars)
340 1 tkerber
341 1 tkerber
        if 'DACAPO_READONLY' in os.environ:
342 1 tkerber
            raise Exception, 'DACAPO_READONLY set and you tried to write!'
343 1 tkerber
344 1 tkerber
        if self.ready:
345 1 tkerber
            return
346 1 tkerber
        # Only write out changed parameters. this function does not do
347 1 tkerber
        # the writing, that is done for each variable in private
348 1 tkerber
        # functions.
349 1 tkerber
        for key in self.pars:
350 1 tkerber
            if self.pars_uptodate[key] is False:
351 1 tkerber
                setf = 'set_%s' % key
352 1 tkerber
353 1 tkerber
                if self.pars[key] is None:
354 1 tkerber
                    continue
355 1 tkerber
356 1 tkerber
                log.debug('trying to call: %s' % setf)
357 1 tkerber
                log.debug('self.%s(self.pars[key])' % setf)
358 1 tkerber
                log.debug('key = %s' % str(self.pars[key]))
359 1 tkerber
360 1 tkerber
                if isinstance(self.pars[key], dict):
361 1 tkerber
                    eval('self.%s(**self.pars[key])' % setf)
362 1 tkerber
                else:
363 1 tkerber
                    eval('self.%s(self.pars[key])' % setf)
364 1 tkerber
365 1 tkerber
                self.pars_uptodate[key] = True #update the changed flag
366 1 tkerber
367 1 tkerber
                log.debug('wrote %s: %s' % (key, str(self.pars[key])))
368 1 tkerber
369 1 tkerber
        #set Jacapo version
370 1 tkerber
        ncf = netCDF(self.get_nc(), 'a')
371 1 tkerber
        ncf.Jacapo_version = Jacapo.__version__
372 1 tkerber
        ncf.sync()
373 1 tkerber
        ncf.close()
374 1 tkerber
375 1 tkerber
    def update_input_parameters(self):
376 1 tkerber
        '''read in all the input parameters from the netcdfile'''
377 1 tkerber
378 1 tkerber
        log.debug('Updating parameters')
379 1 tkerber
380 1 tkerber
        for key in self.default_input:
381 1 tkerber
            getf = 'self.get_%s()' % key
382 1 tkerber
            log.debug('getting key: %s' % key)
383 1 tkerber
            self.pars[key] = eval(getf)
384 1 tkerber
            self.pars_uptodate[key] = True
385 1 tkerber
        return self.pars
386 1 tkerber
387 1 tkerber
    def initnc(self, ncfile=None):
388 1 tkerber
        '''create an ncfile with minimal dimensions in it
389 1 tkerber

390 1 tkerber
        this makes sure the dimensions needed for other set functions
391 1 tkerber
        exist when needed.'''
392 1 tkerber
393 1 tkerber
        if ncfile is None:
394 1 tkerber
            ncfile = self.get_nc()
395 1 tkerber
        else:
396 1 tkerber
            self.set_nc(ncfile)
397 1 tkerber
398 1 tkerber
        log.debug('initializing %s' % ncfile)
399 1 tkerber
400 1 tkerber
        base = os.path.split(ncfile)[0]
401 1 tkerber
        if base is not '' and not os.path.isdir(base):
402 1 tkerber
            os.makedirs(base)
403 1 tkerber
404 1 tkerber
        ncf = netCDF(ncfile, 'w')
405 1 tkerber
        #first, we define some dimensions we always need
406 1 tkerber
        #unlimited
407 1 tkerber
        ncf.createDimension('number_ionic_steps', None)
408 1 tkerber
        ncf.createDimension('dim1', 1)
409 1 tkerber
        ncf.createDimension('dim2', 2)
410 1 tkerber
        ncf.createDimension('dim3', 3)
411 1 tkerber
        ncf.createDimension('dim4', 4)
412 1 tkerber
        ncf.createDimension('dim5', 5)
413 1 tkerber
        ncf.createDimension('dim6', 6)
414 1 tkerber
        ncf.createDimension('dim7', 7)
415 1 tkerber
        ncf.createDimension('dim20', 20) #for longer strings
416 1 tkerber
        ncf.status  = 'new'
417 1 tkerber
        ncf.history = 'Dacapo'
418 1 tkerber
        ncf.jacapo_version = Jacapo.__version__
419 1 tkerber
        ncf.close()
420 1 tkerber
421 1 tkerber
        self.ready = False
422 1 tkerber
        self._frame = 0
423 1 tkerber
424 1 tkerber
    def __del__(self):
425 1 tkerber
        '''If calculator is deleted try to stop dacapo program
426 1 tkerber
        '''
427 1 tkerber
428 1 tkerber
        if hasattr(self, '_dacapo'):
429 1 tkerber
            if self._dacapo.poll()==None:
430 1 tkerber
                self.execute_external_dynamics(stopprogram=True)
431 1 tkerber
        #and clean up after Dacapo
432 1 tkerber
        if os.path.exists('stop'):
433 1 tkerber
            os.remove('stop')
434 1 tkerber
        #remove slave files
435 1 tkerber
        txt = self.get_txt()
436 1 tkerber
        if txt is not None:
437 1 tkerber
            slv = txt + '.slave*'
438 1 tkerber
            for slvf in glob.glob(slv):
439 1 tkerber
                os.remove(slvf)
440 1 tkerber
441 1 tkerber
    def __str__(self):
442 1 tkerber
        '''
443 1 tkerber
        pretty-print the calculator and atoms.
444 1 tkerber

445 1 tkerber
        we read everything directly from the ncfile to prevent
446 1 tkerber
        triggering any calculations
447 1 tkerber
        '''
448 1 tkerber
        s = []
449 1 tkerber
        if self.nc is None:
450 1 tkerber
            return 'No netcdf file attached to this calculator'
451 1 tkerber
        if not os.path.exists(self.nc):
452 1 tkerber
            return 'ncfile does not exist yet'
453 1 tkerber
454 1 tkerber
        nc = netCDF(self.nc, 'r')
455 1 tkerber
        s.append('  ---------------------------------')
456 1 tkerber
        s.append('  Dacapo calculation from %s' % self.nc)
457 1 tkerber
        if hasattr(nc, 'status'):
458 1 tkerber
            s.append('  status = %s' % nc.status)
459 1 tkerber
        if hasattr(nc, 'version'):
460 1 tkerber
            s.append('  version = %s' % nc.version)
461 1 tkerber
        if hasattr(nc, 'Jacapo_version'):
462 1 tkerber
            s.append('  Jacapo version = %s' % nc.Jacapo_version[0])
463 1 tkerber
464 1 tkerber
        energy = nc.variables.get('TotalEnergy', None)
465 1 tkerber
466 1 tkerber
        if energy and energy[:][-1] < 1E36: # missing values get
467 1 tkerber
                                              # returned at 9.3E36
468 1 tkerber
            s.append('  Energy = %1.6f eV' % energy[:][-1])
469 1 tkerber
        else:
470 1 tkerber
            s.append('  Energy = None')
471 1 tkerber
472 1 tkerber
        s.append('')
473 1 tkerber
474 1 tkerber
        atoms = self.get_atoms()
475 1 tkerber
476 1 tkerber
        if atoms is None:
477 1 tkerber
            s.append('  no atoms defined')
478 1 tkerber
        else:
479 1 tkerber
            uc = atoms.get_cell()
480 1 tkerber
            #a, b, c = uc
481 1 tkerber
            s.append("  Unit Cell vectors (angstroms)")
482 1 tkerber
            s.append("         x        y       z   length")
483 1 tkerber
484 1 tkerber
            for i, v in enumerate(uc):
485 1 tkerber
                L = (np.sum(v**2))**0.5 #vector length
486 1 tkerber
                s.append("  a%i [% 1.4f % 1.4f % 1.4f] %1.2f" % (i,
487 1 tkerber
                                                                 v[0],
488 1 tkerber
                                                                 v[1],
489 1 tkerber
                                                                 v[2],
490 1 tkerber
                                                                 L))
491 1 tkerber
492 1 tkerber
            stress = nc.variables.get('TotalStress', None)
493 1 tkerber
            if stress is not None:
494 1 tkerber
                stress = np.take(stress[:].ravel(), [0, 4, 8, 5, 2, 1])
495 1 tkerber
                s.append('  Stress: xx,   yy,    zz,    yz,    xz,    xy')
496 1 tkerber
                s1 = '       % 1.3f % 1.3f % 1.3f % 1.3f % 1.3f % 1.3f'
497 1 tkerber
                s.append(s1 % tuple(stress))
498 1 tkerber
            else:
499 1 tkerber
                s.append('  No stress calculated.')
500 1 tkerber
            s.append('  Volume = %1.2f A^3' % atoms.get_volume())
501 1 tkerber
            s.append('')
502 1 tkerber
503 1 tkerber
            z = "  Atom,  sym, position (in x,y,z),     tag, rmsForce and psp"
504 1 tkerber
            s.append(z)
505 1 tkerber
506 1 tkerber
            #this is just the ncvariable
507 1 tkerber
            forces = nc.variables.get('DynamicAtomForces', None)
508 1 tkerber
509 1 tkerber
            for i, atom in enumerate(atoms):
510 1 tkerber
                sym = atom.get_symbol()
511 1 tkerber
                pos = atom.get_position()
512 1 tkerber
                tag = atom.get_tag()
513 1 tkerber
                if forces is not None and (forces[:][-1][i] < 1E36).all():
514 1 tkerber
                    f = forces[:][-1][i]
515 1 tkerber
                    # Lars Grabow: this seems to work right for some
516 1 tkerber
                    # reason, but I would expect this to be the right
517 1 tkerber
                    # index order f=forces[-1][i][:]
518 1 tkerber
                    # frame,atom,direction
519 1 tkerber
                    rmsforce = (np.sum(f**2))**0.5
520 1 tkerber
                else:
521 1 tkerber
                    rmsforce = None
522 1 tkerber
523 1 tkerber
                st = "  %2i   %3.12s  " % (i, sym)
524 1 tkerber
                st += "[% 7.3f%7.3f% 7.3f] " % tuple(pos)
525 1 tkerber
                st += " %2s  " % tag
526 1 tkerber
                if rmsforce is not None:
527 1 tkerber
                    st += " %4.3f " % rmsforce
528 1 tkerber
                else:
529 1 tkerber
                    st += ' None '
530 1 tkerber
                st += " %s"  % (self.get_psp(sym))
531 1 tkerber
                s.append(st)
532 1 tkerber
533 1 tkerber
        s.append('')
534 1 tkerber
        s.append('  Details:')
535 1 tkerber
        xc = self.get_xc()
536 1 tkerber
        if xc is not None:
537 1 tkerber
            s.append('  XCfunctional        = %s' % self.get_xc())
538 1 tkerber
        else:
539 1 tkerber
            s.append('  XCfunctional        = Not defined')
540 1 tkerber
        s.append('  Planewavecutoff     = %i eV' % int(self.get_pw()))
541 1 tkerber
        dw = self.get_dw()
542 1 tkerber
        if dw:
543 1 tkerber
            s.append('  Densitywavecutoff   = %i eV' % int(self.get_dw()))
544 1 tkerber
        else:
545 1 tkerber
            s.append('  Densitywavecutoff   = None')
546 1 tkerber
        ft = self.get_ft()
547 1 tkerber
        if ft is not None:
548 1 tkerber
            s.append('  FermiTemperature    = %f kT' % ft)
549 1 tkerber
        else:
550 1 tkerber
            s.append('  FermiTemperature    = not defined')
551 1 tkerber
        nelectrons = self.get_valence()
552 1 tkerber
        if nelectrons is not None:
553 1 tkerber
            s.append('  Number of electrons = %1.1f'  % nelectrons)
554 1 tkerber
        else:
555 1 tkerber
            s.append('  Number of electrons = None')
556 1 tkerber
        s.append('  Number of bands     = %s'  % self.get_nbands())
557 1 tkerber
        s.append('  Kpoint grid         = %s' % str(self.get_kpts_type()))
558 1 tkerber
        s.append('  Spin-polarized      = %s' % self.get_spin_polarized())
559 1 tkerber
        s.append('  Dipole correction   = %s' % self.get_dipole())
560 1 tkerber
        s.append('  Symmetry            = %s' % self.get_symmetry())
561 1 tkerber
        s.append('  Constraints         = %s' % str(atoms._get_constraints()))
562 1 tkerber
        s.append('  ---------------------------------')
563 1 tkerber
        nc.close()
564 1 tkerber
        return string.join(s, '\n')
565 1 tkerber
566 1 tkerber
    #todo figure out other xc psp databases
567 1 tkerber
    def set_psp_database(self, xc=None):
568 1 tkerber
        '''
569 1 tkerber
        get the xc-dependent psp database
570 1 tkerber

571 1 tkerber
        :Parameters:
572 1 tkerber

573 1 tkerber
         xc : string
574 1 tkerber
           one of 'PW91', 'PBE', 'revPBE', 'RPBE', 'PZ'
575 1 tkerber

576 1 tkerber

577 1 tkerber
        not all the databases are complete, and that means
578 1 tkerber
        some psp do not exist.
579 1 tkerber

580 1 tkerber
        note: this function is not supported fully. only pw91 is
581 1 tkerber
        imported now. Changing the xc at this point results in loading
582 1 tkerber
        a nearly empty database, and I have not thought about how to
583 1 tkerber
        resolve that
584 1 tkerber
        '''
585 1 tkerber
586 1 tkerber
        if xc == 'PW91' or xc is None:
587 1 tkerber
            from pw91_psp import defaultpseudopotentials
588 1 tkerber
        else:
589 1 tkerber
            log.warn('PW91 pseudopotentials are being used!')
590 1 tkerber
            #todo build other xc psp databases
591 1 tkerber
            from pw91_psp import defaultpseudopotentials
592 1 tkerber
593 1 tkerber
        self.psp = defaultpseudopotentials
594 1 tkerber
595 1 tkerber
    def _set_frame_number(self, frame=None):
596 1 tkerber
        'set framenumber in the netcdf file'
597 1 tkerber
598 1 tkerber
        if frame is None:
599 1 tkerber
            nc = netCDF(self.nc, 'r')
600 1 tkerber
            if 'TotalEnergy' in nc.variables:
601 1 tkerber
                frame = nc.variables['TotalEnergy'].shape[0]
602 1 tkerber
                # make sure the last energy is reasonable. Sometime
603 1 tkerber
                # the field is empty if the calculation ran out of
604 1 tkerber
                # walltime for example. Empty values get returned as
605 1 tkerber
                # 9.6E36.  Dacapos energies should always be negative,
606 1 tkerber
                # so if the energy is > 1E36, there is definitely
607 1 tkerber
                # something wrong and a restart is required.
608 1 tkerber
                if nc.variables.get('TotalEnergy', None)[-1] > 1E36:
609 1 tkerber
                    log.warn("Total energy > 1E36. NC file is incomplete. \
610 1 tkerber
                    calc.restart required")
611 1 tkerber
                    self.restart()
612 1 tkerber
            else:
613 1 tkerber
                frame = 1
614 1 tkerber
            nc.close()
615 1 tkerber
            log.info("Current frame number is: %i" % (frame-1))
616 1 tkerber
        self._frame = frame-1  #netCDF starts counting with 1
617 1 tkerber
618 1 tkerber
    def _increment_frame(self):
619 1 tkerber
        'increment the framenumber'
620 1 tkerber
621 1 tkerber
        log.debug('incrementing frame')
622 1 tkerber
        self._frame += 1
623 1 tkerber
624 1 tkerber
    def set_pw(self, pw):
625 1 tkerber
        '''set the planewave cutoff.
626 1 tkerber

627 1 tkerber
        :Parameters:
628 1 tkerber

629 1 tkerber
         pw : integer
630 1 tkerber
           the planewave cutoff in eV
631 1 tkerber

632 1 tkerber
        this function checks to make sure the density wave cutoff is
633 1 tkerber
        greater than or equal to the planewave cutoff.'''
634 1 tkerber
635 1 tkerber
        nc = netCDF(self.nc, 'a')
636 1 tkerber
        if 'PlaneWaveCutoff' in nc.variables:
637 1 tkerber
            vpw = nc.variables['PlaneWaveCutoff']
638 1 tkerber
            vpw.assignValue(pw)
639 1 tkerber
        else:
640 1 tkerber
            vpw = nc.createVariable('PlaneWaveCutoff', 'd', ('dim1',))
641 1 tkerber
            vpw.assignValue(pw)
642 1 tkerber
643 1 tkerber
        if 'Density_WaveCutoff' in nc.variables:
644 1 tkerber
            vdw = nc.variables['Density_WaveCutoff']
645 1 tkerber
            dw = vdw.getValue()
646 1 tkerber
            if pw > dw:
647 1 tkerber
                vdw.assignValue(pw) #make them equal
648 1 tkerber
        else:
649 1 tkerber
            vdw = nc.createVariable('Density_WaveCutoff', 'd', ('dim1',))
650 1 tkerber
            vdw.assignValue(pw)
651 1 tkerber
        nc.close()
652 1 tkerber
        self.restart() #nc dimension change for number_plane_Wave dimension
653 1 tkerber
        self.set_status('new')
654 1 tkerber
        self.ready = False
655 1 tkerber
656 1 tkerber
    def set_dw(self, dw):
657 1 tkerber
        '''set the density wave cutoff energy.
658 1 tkerber

659 1 tkerber
        :Parameters:
660 1 tkerber

661 1 tkerber
          dw : integer
662 1 tkerber
            the density wave cutoff
663 1 tkerber

664 1 tkerber
        The function checks to make sure it is not less than the
665 1 tkerber
        planewave cutoff.
666 1 tkerber

667 1 tkerber
        Density_WaveCutoff describes the kinetic energy neccesary to
668 1 tkerber
        represent a wavefunction associated with the total density,
669 1 tkerber
        i.e. G-vectors for which $\vert G\vert^2$ $<$
670 1 tkerber
        4*Density_WaveCutoff will be used to describe the total
671 1 tkerber
        density (including augmentation charge and partial core
672 1 tkerber
        density). If Density_WaveCutoff is equal to PlaneWaveCutoff
673 1 tkerber
        this implies that the total density is as soft as the
674 1 tkerber
        wavefunctions described by the kinetic energy cutoff
675 1 tkerber
        PlaneWaveCutoff. If a value of Density_WaveCutoff is specified
676 1 tkerber
        (must be larger than or equal to PlaneWaveCutoff) the program
677 1 tkerber
        will run using two grids, one for representing the
678 1 tkerber
        wavefunction density (softgrid_dim) and one representing the
679 1 tkerber
        total density (hardgrid_dim). If the density can be
680 1 tkerber
        reprensented on the same grid as the wavefunction density
681 1 tkerber
        Density_WaveCutoff can be chosen equal to PlaneWaveCutoff
682 1 tkerber
        (default).
683 1 tkerber
        '''
684 1 tkerber
685 1 tkerber
        pw = self.get_pw()
686 1 tkerber
        if pw > dw:
687 1 tkerber
            log.warn('Planewave cutoff %i is greater \
688 1 tkerber
than density cutoff %i' % (pw, dw))
689 1 tkerber
690 1 tkerber
        ncf = netCDF(self.nc, 'a')
691 1 tkerber
        if 'Density_WaveCutoff' in ncf.variables:
692 1 tkerber
            vdw = ncf.variables['Density_WaveCutoff']
693 1 tkerber
            vdw.assignValue(dw)
694 1 tkerber
        else:
695 1 tkerber
            vdw = ncf.createVariable('Density_WaveCutoff', 'i', ('dim1',))
696 1 tkerber
            vdw.assignValue(dw)
697 1 tkerber
        ncf.close()
698 1 tkerber
        self.restart() #nc dimension change
699 1 tkerber
        self.set_status('new')
700 1 tkerber
        self.ready = False
701 1 tkerber
702 1 tkerber
    def set_xc(self, xc):
703 1 tkerber
        '''Set the self-consistent exchange-correlation functional
704 1 tkerber

705 1 tkerber
        :Parameters:
706 1 tkerber

707 1 tkerber
         xc : string
708 1 tkerber
           Must be one of 'PZ', 'VWN', 'PW91', 'PBE', 'revPBE', 'RPBE'
709 1 tkerber

710 1 tkerber
        Selects which density functional to use for
711 1 tkerber
        exchange-correlation when performing electronic minimization
712 1 tkerber
        (the electronic energy is minimized with respect to this
713 1 tkerber
        selected functional) Notice that the electronic energy is also
714 1 tkerber
        evaluated non-selfconsistently by DACAPO for other
715 1 tkerber
        exchange-correlation functionals Recognized options :
716 1 tkerber

717 1 tkerber
        * "PZ" (Perdew Zunger LDA-parametrization)
718 1 tkerber
        * "VWN" (Vosko Wilk Nusair LDA-parametrization)
719 1 tkerber
        * "PW91" (Perdew Wang 91 GGA-parametrization)
720 1 tkerber
        * "PBE" (Perdew Burke Ernzerhof GGA-parametrization)
721 1 tkerber
        * "revPBE" (revised PBE/1 GGA-parametrization)
722 1 tkerber
        * "RPBE" (revised PBE/2 GGA-parametrization)
723 1 tkerber

724 1 tkerber
        option "PZ" is not allowed for spin polarized
725 1 tkerber
        calculation; use "VWN" instead.
726 1 tkerber
        '''
727 1 tkerber
        nc = netCDF(self.nc, 'a')
728 1 tkerber
        v = 'ExcFunctional'
729 1 tkerber
        if v in nc.variables:
730 1 tkerber
            nc.variables[v][:] = np.array('%7s' % xc, 'c')
731 1 tkerber
        else:
732 1 tkerber
            vxc = nc.createVariable('ExcFunctional', 'c', ('dim7',))
733 1 tkerber
            vxc[:] = np.array('%7s' % xc, 'c')
734 1 tkerber
        nc.close()
735 1 tkerber
        self.set_status('new')
736 1 tkerber
        self.ready = False
737 1 tkerber
738 1 tkerber
    def set_nbands(self, nbands=None):
739 1 tkerber
        '''Set the number of bands. a few unoccupied bands are
740 1 tkerber
        recommended.
741 1 tkerber

742 1 tkerber
        :Parameters:
743 1 tkerber

744 1 tkerber
          nbands : integer
745 1 tkerber
            the number of bands.
746 1 tkerber

747 1 tkerber
        if nbands = None the function returns with nothing done. At
748 1 tkerber
        calculate time, if there are still no bands, they will be set
749 1 tkerber
        by:
750 1 tkerber

751 1 tkerber
        the number of bands is calculated as
752 1 tkerber
        $nbands=nvalence*0.65 + 4$
753 1 tkerber
        '''
754 1 tkerber
        if nbands is None:
755 1 tkerber
            return
756 1 tkerber
757 1 tkerber
        self.delete_ncattdimvar(self.nc,
758 1 tkerber
                                ncdims=['number_of_bands'],
759 1 tkerber
                                ncvars=[])
760 1 tkerber
761 1 tkerber
        nc = netCDF(self.nc, 'a')
762 1 tkerber
        v = 'ElectronicBands'
763 1 tkerber
        if v in nc.variables:
764 1 tkerber
            vnb = nc.variables[v]
765 1 tkerber
        else:
766 1 tkerber
            vnb = nc.createVariable('ElectronicBands', 'c', ('dim1',))
767 1 tkerber
768 1 tkerber
        vnb.NumberOfBands = nbands
769 1 tkerber
        nc.sync()
770 1 tkerber
        nc.close()
771 1 tkerber
        self.set_status('new')
772 1 tkerber
        self.ready = False
773 1 tkerber
774 1 tkerber
    def set_kpts(self, kpts):
775 1 tkerber
        '''
776 1 tkerber
        set the kpt grid.
777 1 tkerber

778 1 tkerber
        Parameters:
779 1 tkerber

780 1 tkerber
        kpts: (n1,n2,n3) or [k1,k2,k3,...] or one of these
781 1 tkerber
        chadi-cohen sets:
782 1 tkerber

783 1 tkerber
        * cc6_1x1
784 1 tkerber
        * cc12_2x3
785 1 tkerber
        * cc18_sq3xsq3
786 1 tkerber
        * cc18_1x1
787 1 tkerber
        * cc54_sq3xsq3
788 1 tkerber
        * cc54_1x1
789 1 tkerber
        * cc162_sq3xsq3
790 1 tkerber
        * cc162_1x1
791 1 tkerber

792 1 tkerber
        (n1,n2,n3) creates an n1 x n2 x n3 monkhorst-pack grid,
793 1 tkerber
        [k1,k2,k3,...] creates a kpt-grid based on the kpoints
794 1 tkerber
        defined in k1,k2,k3,...
795 1 tkerber

796 1 tkerber
        There is also a possibility to have Dacapo (fortran) create
797 1 tkerber
        the Kpoints in chadi-cohen or monkhorst-pack form. To do this
798 1 tkerber
        you need to set the KpointSetup.gridtype attribute, and
799 1 tkerber
        KpointSetup.
800 1 tkerber

801 1 tkerber
        KpointSetup = [3,0,0]
802 1 tkerber
        KpointSetup.gridtype = 'ChadiCohen'
803 1 tkerber

804 1 tkerber
        KpointSetup(1)         Chadi-Cohen k-point set
805 1 tkerber
        1         6 k-points 1x1
806 1 tkerber
        2         18-kpoints sqrt(3)*sqrt(3)
807 1 tkerber
        3         18-kpoints 1x1
808 1 tkerber
        4         54-kpoints sqrt(3)*sqrt(3)
809 1 tkerber
        5         54-kpoints 1x1
810 1 tkerber
        6         162-kpoints 1x1
811 1 tkerber
        7         12-kpoints 2x3
812 1 tkerber
        8         162-kpoints 3xsqrt 3
813 1 tkerber

814 1 tkerber
        or
815 1 tkerber
        KpointSetup = [4,4,4]
816 1 tkerber
        KpointSetup.gridtype = 'MonkhorstPack'
817 1 tkerber
        we do not use this functionality.
818 1 tkerber
        '''
819 1 tkerber
820 1 tkerber
        #chadi-cohen
821 1 tkerber
        if isinstance(kpts, str):
822 1 tkerber
            exec('from ase.dft.kpoints import %s' % kpts)
823 1 tkerber
            listofkpts = eval(kpts)
824 1 tkerber
            gridtype = kpts #stored in ncfile
825 1 tkerber
            #uc = self.get_atoms().get_cell()
826 1 tkerber
            #listofkpts = np.dot(ccgrid,np.linalg.inv(uc.T))
827 1 tkerber
828 1 tkerber
        #monkhorst-pack grid
829 1 tkerber
        if np.array(kpts).shape == (3,):
830 1 tkerber
            from ase.dft.kpoints import monkhorst_pack
831 1 tkerber
            N1, N2, N3 = kpts
832 1 tkerber
            listofkpts = monkhorst_pack((N1, N2, N3))
833 1 tkerber
            gridtype = 'Monkhorst-Pack %s' % str(tuple(kpts))
834 1 tkerber
835 1 tkerber
        #user-defined list is provided
836 1 tkerber
        if len(np.array(kpts).shape) == 2:
837 1 tkerber
            listofkpts = kpts
838 1 tkerber
            gridtype = 'user_defined_%i_kpts' % len(kpts)  #stored in ncfile
839 1 tkerber
840 1 tkerber
        nbzkpts = len(listofkpts)
841 1 tkerber
842 1 tkerber
        #we need to get dimensions stored temporarily so
843 1 tkerber
        #we can delete all dimensions and variables associated with
844 1 tkerber
        #kpoints before we save them back out.
845 1 tkerber
        nc2 = netCDF(self.nc, 'r')
846 1 tkerber
        ncdims = nc2.dimensions
847 1 tkerber
        nc2.close()
848 1 tkerber
849 1 tkerber
        if 'number_BZ_kpoints' in ncdims:
850 1 tkerber
            self.delete_ncattdimvar(self.nc,
851 1 tkerber
                                    ncdims=['number_plane_waves',
852 1 tkerber
                                            'number_BZ_kpoints',
853 1 tkerber
                                            'number_IBZ_kpoints'])
854 1 tkerber
855 1 tkerber
        # now define dim and var
856 1 tkerber
        nc = netCDF(self.nc, 'a')
857 1 tkerber
        nc.createDimension('number_BZ_kpoints', nbzkpts)
858 1 tkerber
        bv = nc.createVariable('BZKpoints', 'd', ('number_BZ_kpoints',
859 1 tkerber
                                                  'dim3'))
860 1 tkerber
861 1 tkerber
        bv[:] = listofkpts
862 1 tkerber
        bv.gridtype = gridtype
863 1 tkerber
        nc.sync()
864 1 tkerber
        nc.close()
865 1 tkerber
866 1 tkerber
        log.debug('kpts = %s' % str(self.get_kpts()))
867 1 tkerber
868 1 tkerber
        self.set_status('new')
869 1 tkerber
        self.ready = False
870 1 tkerber
871 1 tkerber
    def atoms_are_equal(self, atoms):
872 1 tkerber
        '''
873 1 tkerber
        comparison of atoms to self.atoms using tolerances to account
874 1 tkerber
        for float/double differences and float math.
875 1 tkerber
        '''
876 1 tkerber
877 1 tkerber
        TOL = 1.0e-6 #angstroms
878 1 tkerber
879 1 tkerber
        a = self.atoms.arrays
880 1 tkerber
        b = atoms.arrays
881 1 tkerber
882 1 tkerber
        #match number of atoms in cell
883 1 tkerber
        lenmatch = len(atoms) == len(self.atoms)
884 1 tkerber
        if lenmatch is not True:
885 1 tkerber
            return False #the next two comparisons fail in this case.
886 1 tkerber
887 1 tkerber
        #match positions in cell
888 1 tkerber
        posmatch = (abs(a['positions'] - b['positions']) <= TOL).all()
889 1 tkerber
        #match cell
890 1 tkerber
        cellmatch = (abs(self.atoms.get_cell()
891 1 tkerber
                         - atoms.get_cell()) <= TOL).all()
892 1 tkerber
893 1 tkerber
        if lenmatch and posmatch and cellmatch:
894 1 tkerber
            return True
895 1 tkerber
        else:
896 1 tkerber
            return False
897 1 tkerber
898 1 tkerber
    def set_atoms(self, atoms):
899 1 tkerber
        '''attach an atoms to the calculator and update the ncfile
900 1 tkerber

901 1 tkerber
        :Parameters:
902 1 tkerber

903 1 tkerber
          atoms
904 1 tkerber
            ASE.Atoms instance
905 1 tkerber

906 1 tkerber
        '''
907 1 tkerber
908 1 tkerber
        log.debug('setting atoms to: %s' % str(atoms))
909 1 tkerber
910 1 tkerber
        if hasattr(self, 'atoms') and self.atoms is not None:
911 1 tkerber
            #return if the atoms are the same. no change needs to be made
912 1 tkerber
            if self.atoms_are_equal(atoms):
913 1 tkerber
                log.debug('No change to atoms in set_atoms, returning')
914 1 tkerber
                return
915 1 tkerber
916 1 tkerber
            # some atoms already exist. Test if new atoms are
917 1 tkerber
            # different from old atoms.
918 1 tkerber
            # this is redundant
919 1 tkerber
            if atoms != self.atoms:
920 1 tkerber
                # the new atoms are different from the old ones. Start
921 1 tkerber
                # a new frame.
922 1 tkerber
                log.debug('atoms != self.atoms, incrementing')
923 1 tkerber
                self._increment_frame()
924 1 tkerber
925 1 tkerber
        self.atoms = atoms.copy()
926 1 tkerber
        self.ready = False
927 1 tkerber
        log.debug('self.atoms = %s' % str(self.atoms))
928 1 tkerber
929 1 tkerber
    def set_ft(self, ft):
930 1 tkerber
        '''set the Fermi temperature for occupation smearing
931 1 tkerber

932 1 tkerber
        :Parameters:
933 1 tkerber

934 1 tkerber
          ft : float
935 1 tkerber
            Fermi temperature in kT (eV)
936 1 tkerber

937 1 tkerber
        Electronic temperature, corresponding to gaussian occupation
938 1 tkerber
        statistics. Device used to stabilize the convergence towards
939 1 tkerber
        the electronic ground state. Higher values stabilizes the
940 1 tkerber
        convergence. Values in the range 0.1-1.0 eV are recommended,
941 1 tkerber
        depending on the complexity of the Fermi surface (low values
942 1 tkerber
        for d-metals and narrow gap semiconducters, higher for free
943 1 tkerber
        electron-like metals).
944 1 tkerber
        '''
945 1 tkerber
946 1 tkerber
        nc = netCDF(self.nc, 'a')
947 1 tkerber
        v = 'ElectronicBands'
948 1 tkerber
        if v in nc.variables:
949 1 tkerber
            vnb = nc.variables[v]
950 1 tkerber
        else:
951 1 tkerber
            vnb = nc.createVariable('ElectronicBands', 'c', ('dim1',))
952 1 tkerber
953 1 tkerber
        vnb.OccupationStatistics_FermiTemperature = ft
954 1 tkerber
        nc.sync()
955 1 tkerber
        nc.close()
956 1 tkerber
        self.set_status('new')
957 1 tkerber
        self.ready = False
958 1 tkerber
959 1 tkerber
    def set_status(self, status):
960 1 tkerber
        '''set the status flag in the netcdf file
961 1 tkerber

962 1 tkerber
        :Parameters:
963 1 tkerber

964 1 tkerber
          status : string
965 1 tkerber
            status flag, e.g. 'new', 'finished'
966 1 tkerber
        '''
967 1 tkerber
968 1 tkerber
        nc = netCDF(self.nc, 'a')
969 1 tkerber
        nc.status = status
970 1 tkerber
        nc.sync()
971 1 tkerber
        nc.close()
972 1 tkerber
        log.debug('set status to %s' % status)
973 1 tkerber
974 1 tkerber
    def get_spinpol(self):
975 1 tkerber
        'Returns the spin polarization setting, either True or False'
976 1 tkerber
977 1 tkerber
        nc = netCDF(self.nc, 'r')
978 1 tkerber
        v = 'ElectronicBands'
979 1 tkerber
        if v in nc.variables:
980 1 tkerber
            vnb = nc.variables[v]
981 1 tkerber
            if hasattr(vnb, 'SpinPolarization'):
982 1 tkerber
                spinpol = vnb.SpinPolarization
983 1 tkerber
            else:
984 1 tkerber
                spinpol = 1
985 1 tkerber
        else:
986 1 tkerber
            spinpol = 1
987 1 tkerber
988 1 tkerber
        nc.close()
989 1 tkerber
        if spinpol == 1:
990 1 tkerber
            return False
991 1 tkerber
        else:
992 1 tkerber
            return True
993 1 tkerber
994 1 tkerber
    def set_spinpol(self, spinpol=False):
995 1 tkerber
        '''set Spin polarization.
996 1 tkerber

997 1 tkerber
        :Parameters:
998 1 tkerber

999 1 tkerber
         spinpol : Boolean
1000 1 tkerber
           set_spinpol(True)  spin-polarized.
1001 1 tkerber
           set_spinpol(False) no spin polarization, default
1002 1 tkerber

1003 1 tkerber
        Specify whether to perform a spin polarized or unpolarized
1004 1 tkerber
        calculation.
1005 1 tkerber
        '''
1006 1 tkerber
1007 1 tkerber
        nc = netCDF(self.nc, 'a')
1008 1 tkerber
        v = 'ElectronicBands'
1009 1 tkerber
        if v in nc.variables:
1010 1 tkerber
            vnb = nc.variables[v]
1011 1 tkerber
        else:
1012 1 tkerber
            vnb = nc.createVariable('ElectronicBands', 'c', ('dim1',))
1013 1 tkerber
1014 1 tkerber
        if spinpol is True:
1015 1 tkerber
            vnb.SpinPolarization = 2
1016 1 tkerber
        else:
1017 1 tkerber
            vnb.SpinPolarization = 1
1018 1 tkerber
1019 1 tkerber
        nc.sync()
1020 1 tkerber
        nc.close()
1021 1 tkerber
        self.set_status('new')
1022 1 tkerber
        self.ready = False
1023 1 tkerber
1024 1 tkerber
    def set_fixmagmom(self, fixmagmom=None):
1025 1 tkerber
        '''set a fixed magnetic moment for a spin polarized calculation
1026 1 tkerber

1027 1 tkerber
        :Parameters:
1028 1 tkerber

1029 1 tkerber
          fixmagmom : float
1030 1 tkerber
            the magnetic moment of the cell in Bohr magnetons
1031 1 tkerber
        '''
1032 1 tkerber
1033 1 tkerber
        if fixmagmom is None:
1034 1 tkerber
            return
1035 1 tkerber
1036 1 tkerber
        nc = netCDF(self.nc,'a')
1037 1 tkerber
        v = 'ElectronicBands'
1038 1 tkerber
        if v in nc.variables:
1039 1 tkerber
            vnb = nc.variables[v]
1040 1 tkerber
        else:
1041 1 tkerber
            vnb = nc.createVariable('ElectronicBands', 'c', ('dim1',))
1042 1 tkerber
1043 1 tkerber
        vnb.SpinPolarization = 2 #You must want spin-polarized
1044 1 tkerber
        vnb.FixedMagneticMoment = fixmagmom
1045 1 tkerber
        nc.sync()
1046 1 tkerber
        nc.close()
1047 1 tkerber
        self.set_status('new')
1048 1 tkerber
        self.ready = False
1049 1 tkerber
1050 1 tkerber
    def get_fixmagmom(self):
1051 1 tkerber
        'returns the value of FixedMagneticMoment'
1052 1 tkerber
1053 1 tkerber
        nc = netCDF(self.nc,'r')
1054 1 tkerber
        if 'ElectronicBands' in nc.variables:
1055 1 tkerber
            v = nc.variables['ElectronicBands']
1056 1 tkerber
            if hasattr(v,'FixedMagneticMoment'):
1057 1 tkerber
                fixmagmom = v.FixedMagneticMoment
1058 1 tkerber
            else:
1059 1 tkerber
                fixmagmom = None
1060 1 tkerber
        else:
1061 1 tkerber
            fixmagmom = None
1062 1 tkerber
        nc.close()
1063 1 tkerber
        return fixmagmom
1064 1 tkerber
1065 1 tkerber
    def set_calculate_stress(self, stress=True):
1066 1 tkerber
        '''Turn on stress calculation
1067 1 tkerber

1068 1 tkerber
        :Parameters:
1069 1 tkerber

1070 1 tkerber
          stress : boolean
1071 1 tkerber
            set_calculate_stress(True) calculates stress
1072 1 tkerber
            set_calculate_stress(False) do not calculate stress
1073 1 tkerber
        '''
1074 1 tkerber
1075 1 tkerber
        nc = netCDF(self.get_nc(),'a')
1076 1 tkerber
        vs = 'NetCDFOutputControl'
1077 1 tkerber
        if vs in nc.variables:
1078 1 tkerber
            v = nc.variables[vs]
1079 1 tkerber
        else:
1080 1 tkerber
            v = nc.createVariable('NetCDFOutputControl', 'c', ('dim1',))
1081 1 tkerber
1082 1 tkerber
        if stress is True:
1083 1 tkerber
            v.PrintTotalStress = 'Yes'
1084 1 tkerber
        else:
1085 1 tkerber
            v.PrintTotalStress = 'No'
1086 1 tkerber
        nc.sync()
1087 1 tkerber
        nc.close()
1088 1 tkerber
        self.set_status('new')
1089 1 tkerber
        self.ready = False
1090 1 tkerber
1091 1 tkerber
    def set_nc(self, nc='out.nc'):
1092 1 tkerber
        '''
1093 1 tkerber
        set filename for the netcdf and text output for this calculation
1094 1 tkerber

1095 1 tkerber
        :Parameters:
1096 1 tkerber

1097 1 tkerber
          nc : string
1098 1 tkerber
            filename for netcdf file
1099 1 tkerber

1100 1 tkerber
        if the ncfile attached to the calculator is changing, the old
1101 1 tkerber
        file will be copied to the new file if it doesn not exist so
1102 1 tkerber
        that all the calculator details are preserved. Otherwise, the
1103 1 tkerber

1104 1 tkerber
        if the ncfile does not exist, it will get initialized.
1105 1 tkerber

1106 1 tkerber
        the text file will have the same basename as the ncfile, but
1107 1 tkerber
        with a .txt extension.
1108 1 tkerber
        '''
1109 1 tkerber
1110 1 tkerber
        #the first time this is called, there may be no self.nc defined
1111 1 tkerber
        if not hasattr(self, 'nc'):
1112 1 tkerber
            self.nc = nc
1113 1 tkerber
1114 1 tkerber
        #check if the name is changing and if so, copy the old ncfile
1115 1 tkerber
        #to the new one.  This is necessary to ensure all the
1116 1 tkerber
        #calculator details are copied over. if the file already
1117 1 tkerber
        #exists we use the contents of the existing file
1118 1 tkerber
        if nc != self.nc and not os.path.exists(nc):
1119 1 tkerber
            log.debug('copying %s to %s' % (self.nc, nc))
1120 1 tkerber
            #import shutil
1121 1 tkerber
            #shutil.copy(self.nc,nc)
1122 1 tkerber
            base = os.path.split(nc)[0]
1123 1 tkerber
            if not os.path.isdir(base) and base is not '':
1124 1 tkerber
                os.makedirs(base)
1125 1 tkerber
            status = os.system('cp %s %s' % (self.nc, nc))
1126 1 tkerber
            if status != 0:
1127 1 tkerber
                raise Exception, 'Copying ncfile failed.'
1128 1 tkerber
            self.nc = nc
1129 1 tkerber
1130 1 tkerber
        elif os.path.exists(nc):
1131 1 tkerber
            self._set_frame_number()
1132 1 tkerber
            self.set_psp_database()
1133 1 tkerber
            self.atoms = self.read_only_atoms(nc)
1134 1 tkerber
            self.nc = nc
1135 1 tkerber
            self.update_input_parameters()
1136 1 tkerber
1137 1 tkerber
        #I always want the text file set based on the ncfile
1138 1 tkerber
        #and I never want to set this myself.
1139 1 tkerber
        base = os.path.splitext(self.nc)[0]
1140 1 tkerber
        self.txt = base + '.txt'
1141 1 tkerber
1142 1 tkerber
    def set_psp(self,
1143 1 tkerber
                sym=None,
1144 1 tkerber
                z=None,
1145 1 tkerber
                psp=None):
1146 1 tkerber
        '''
1147 1 tkerber
        set the pseudopotential file for a species or an atomic number.
1148 1 tkerber

1149 1 tkerber
        :Parameters:
1150 1 tkerber

1151 1 tkerber
         sym : string
1152 1 tkerber
           chemical symbol of the species
1153 1 tkerber

1154 1 tkerber
          z : integer
1155 1 tkerber
            the atomic number of the species
1156 1 tkerber

1157 1 tkerber
          psp : string
1158 1 tkerber
            filename of the pseudopotential
1159 1 tkerber

1160 1 tkerber

1161 1 tkerber
        you can only set sym or z.
1162 1 tkerber

1163 1 tkerber
        examples::
1164 1 tkerber

1165 1 tkerber
          set_psp('N',psp='pspfile')
1166 1 tkerber
          set_psp(z=6,psp='pspfile')
1167 1 tkerber
        '''
1168 1 tkerber
        log.debug(str([sym, z, psp]))
1169 1 tkerber
        if (sym, z, psp) == (None, None, None):
1170 1 tkerber
            return
1171 1 tkerber
1172 1 tkerber
        if (sym is None and z is not None):
1173 1 tkerber
            from ase.data import chemical_symbols
1174 1 tkerber
            sym = chemical_symbols[z]
1175 1 tkerber
        elif (sym is not None and z is None):
1176 1 tkerber
            pass
1177 1 tkerber
        else:
1178 1 tkerber
            raise Exception, 'You can only specify Z or sym!'
1179 1 tkerber
1180 1 tkerber
        if not hasattr(self, 'psp'):
1181 1 tkerber
            self.set_psp_database()
1182 1 tkerber
1183 1 tkerber
        #only make change if needed
1184 1 tkerber
        if sym not in self.psp:
1185 1 tkerber
            self.psp[sym] = psp
1186 1 tkerber
            self.ready = False
1187 1 tkerber
            self.set_status('new')
1188 1 tkerber
        elif self.psp[sym] != psp:
1189 1 tkerber
            self.psp[sym] = psp
1190 1 tkerber
            self.ready = False
1191 1 tkerber
            self.set_status('new')
1192 1 tkerber
1193 1 tkerber
        if not self.ready:
1194 1 tkerber
            #now we update the netcdf file
1195 1 tkerber
            ncf = netCDF(self.nc, 'a')
1196 1 tkerber
            vn = 'AtomProperty_%s' % sym
1197 1 tkerber
            if vn not in ncf.variables:
1198 1 tkerber
                p = ncf.createVariable(vn, 'c', ('dim20',))
1199 1 tkerber
            else:
1200 1 tkerber
                p = ncf.variables[vn]
1201 1 tkerber
1202 1 tkerber
            ppath = self.get_psp(sym=sym)
1203 1 tkerber
            p.PspotFile = ppath
1204 1 tkerber
            ncf.close()
1205 1 tkerber
1206 1 tkerber
    def get_pseudopotentials(self):
1207 1 tkerber
        'get pseudopotentials set for atoms attached to calculator'
1208 1 tkerber
1209 1 tkerber
        if self.atoms is None:
1210 1 tkerber
            return None
1211 1 tkerber
1212 1 tkerber
        psp = {}
1213 1 tkerber
        for atom in self.atoms:
1214 1 tkerber
            psp[atom.symbol] = self.psp[atom.symbol]
1215 1 tkerber
        return psp
1216 1 tkerber
1217 1 tkerber
    def get_symmetry(self):
1218 1 tkerber
        '''return the type of symmetry used'''
1219 1 tkerber
1220 1 tkerber
        nc = netCDF(self.nc, 'r')
1221 1 tkerber
        if 'UseSymmetry' in nc.variables:
1222 1 tkerber
            sym = string.join(nc.variables['UseSymmetry'][:],'').strip()
1223 1 tkerber
        else:
1224 1 tkerber
            sym = None
1225 1 tkerber
        nc.close()
1226 1 tkerber
        if sym in ['Off', None]:
1227 1 tkerber
            return False
1228 1 tkerber
        elif sym == 'Maximum':
1229 1 tkerber
            return True
1230 1 tkerber
        else:
1231 1 tkerber
            raise Exception, 'Type of symmetry not recognized: %s' % sym
1232 1 tkerber
1233 1 tkerber
    def set_symmetry(self, val=False):
1234 1 tkerber
        '''set how symmetry is used to reduce k-points
1235 1 tkerber

1236 1 tkerber
        :Parameters:
1237 1 tkerber

1238 1 tkerber
         val : Boolean
1239 1 tkerber
           set_sym(True) Maximum symmetry is used
1240 1 tkerber
           set_sym(False) No symmetry is used
1241 1 tkerber

1242 1 tkerber
        This variable controls the if and how DACAPO should attempt
1243 1 tkerber
        using symmetry in the calculation. Imposing symmetry generally
1244 1 tkerber
        speeds up the calculation and reduces numerical noise to some
1245 1 tkerber
        extent. Symmetry should always be applied to the maximum
1246 1 tkerber
        extent, when ions are not moved. When relaxing ions, however,
1247 1 tkerber
        the symmetry of the equilibrium state may be lower than the
1248 1 tkerber
        initial state. Such an equilibrium state with lower symmetry
1249 1 tkerber
        is missed, if symmetry is imposed. Molecular dynamics-like
1250 1 tkerber
        algorithms for ionic propagation will generally not break the
1251 1 tkerber
        symmetry of the initial state, but some algorithms, like the
1252 1 tkerber
        BFGS may break the symmetry of the initial state. Recognized
1253 1 tkerber
        options:
1254 1 tkerber

1255 1 tkerber
        "Off": No symmetry will be imposed, apart from time inversion
1256 1 tkerber
        symmetry in recipical space. This is utilized to reduce the
1257 1 tkerber
        k-point sampling set for Brillouin zone integration and has no
1258 1 tkerber
        influence on the ionic forces/motion.
1259 1 tkerber

1260 1 tkerber
        "Maximum": DACAPO will look for symmetry in the supplied
1261 1 tkerber
        atomic structure and extract the highest possible symmetry
1262 1 tkerber
        group. During the calculation, DACAPO will impose the found
1263 1 tkerber
        spatial symmetry on ionic forces and electronic structure,
1264 1 tkerber
        i.e. the symmetry will be conserved during the calculation.
1265 1 tkerber
        '''
1266 1 tkerber
1267 1 tkerber
        if val:
1268 1 tkerber
            symval = 'Maximum'
1269 1 tkerber
        else:
1270 1 tkerber
            symval = 'Off'
1271 1 tkerber
1272 1 tkerber
        ncf = netCDF(self.get_nc(), 'a')
1273 1 tkerber
        if 'UseSymmetry' not in ncf.variables:
1274 1 tkerber
            sym = ncf.createVariable('UseSymmetry', 'c', ('dim7',))
1275 1 tkerber
        else:
1276 1 tkerber
            sym = ncf.variables['UseSymmetry']
1277 1 tkerber
1278 1 tkerber
        sym[:] = np.array('%7s' % symval, 'c')
1279 1 tkerber
        ncf.sync()
1280 1 tkerber
        ncf.close()
1281 1 tkerber
        self.set_status('new')
1282 1 tkerber
        self.ready = False
1283 1 tkerber
1284 1 tkerber
    def set_extracharge(self, val):
1285 1 tkerber
        '''add extra charge to unit cell
1286 1 tkerber

1287 1 tkerber
        :Parameters:
1288 1 tkerber

1289 1 tkerber
          val : float
1290 1 tkerber
            extra electrons to add or subtract from the unit cell
1291 1 tkerber

1292 1 tkerber
        Fixed extra charge in the unit cell (i.e. deviation from
1293 1 tkerber
        charge neutrality). This assumes a compensating, positive
1294 1 tkerber
        constant backgound charge (jellium) to forge overall charge
1295 1 tkerber
        neutrality.
1296 1 tkerber
        '''
1297 1 tkerber
1298 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1299 1 tkerber
        if 'ExtraCharge' in nc.variables:
1300 1 tkerber
            v = nc.variables['ExtraCharge']
1301 1 tkerber
        else:
1302 1 tkerber
            v = nc.createVariable('ExtraCharge', 'd', ('dim1',))
1303 1 tkerber
1304 1 tkerber
        v.assignValue(val)
1305 1 tkerber
        nc.sync()
1306 1 tkerber
        nc.close()
1307 1 tkerber
1308 1 tkerber
    def get_extracharge(self):
1309 1 tkerber
        'Return the extra charge set in teh calculator'
1310 1 tkerber
1311 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
1312 1 tkerber
        if 'ExtraCharge' in nc.variables:
1313 1 tkerber
            v = nc.variables['ExtraCharge']
1314 1 tkerber
            exchg = v.getValue()
1315 1 tkerber
        else:
1316 1 tkerber
            exchg = None
1317 1 tkerber
        nc.close()
1318 1 tkerber
        return exchg
1319 1 tkerber
1320 1 tkerber
    def get_extpot(self):
1321 1 tkerber
        'return the external potential set in teh calculator'
1322 1 tkerber
1323 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1324 1 tkerber
        if 'ExternalPotential' in nc.variables:
1325 1 tkerber
            v = nc.variables['ExternalPotential']
1326 1 tkerber
            extpot = v[:]
1327 1 tkerber
        else:
1328 1 tkerber
            extpot = None
1329 1 tkerber
1330 1 tkerber
        nc.close()
1331 1 tkerber
        return extpot
1332 1 tkerber
1333 1 tkerber
    def set_extpot(self, potgrid):
1334 1 tkerber
        '''add external potential of value
1335 1 tkerber

1336 1 tkerber
        see this link before using this
1337 1 tkerber
        https://listserv.fysik.dtu.dk/pipermail/campos/2003-August/000657.html
1338 1 tkerber

1339 1 tkerber
        :Parameters:
1340 1 tkerber

1341 1 tkerber
          potgrid : np.array with shape (nx,ny,nz)
1342 1 tkerber
            the shape must be the same as the fft soft grid
1343 1 tkerber
            the value of the potential to add
1344 1 tkerber

1345 1 tkerber

1346 1 tkerber
        you have to know both of the fft grid dimensions ahead of time!
1347 1 tkerber
        if you know what you are doing, you can set the fft_grid you want
1348 1 tkerber
        before hand with:
1349 1 tkerber
        calc.set_fftgrid((n1,n2,n3))
1350 1 tkerber
        '''
1351 1 tkerber
1352 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1353 1 tkerber
        if 'ExternalPotential' in nc.variables:
1354 1 tkerber
            v = nc.variables['ExternalPotential']
1355 1 tkerber
        else:
1356 1 tkerber
            # I assume here you have the dimensions of potgrid correct
1357 1 tkerber
            # and that the soft and hard grids are the same.
1358 1 tkerber
            # if softgrid is defined, Dacapo requires hardgrid to be
1359 1 tkerber
            # defined too.
1360 1 tkerber
            s1, s2, s3 = potgrid.shape
1361 1 tkerber
            if 'softgrid_dim1' not in nc.dimensions:
1362 1 tkerber
                nc.createDimension('softgrid_dim1', s1)
1363 1 tkerber
                nc.createDimension('softgrid_dim2', s2)
1364 1 tkerber
                nc.createDimension('softgrid_dim3', s3)
1365 1 tkerber
                nc.createDimension('hardgrid_dim1', s1)
1366 1 tkerber
                nc.createDimension('hardgrid_dim2', s2)
1367 1 tkerber
                nc.createDimension('hardgrid_dim3', s3)
1368 1 tkerber
1369 1 tkerber
            v = nc.createVariable('ExternalPotential',
1370 1 tkerber
                                  'd',
1371 1 tkerber
                                  ('softgrid_dim1',
1372 1 tkerber
                                   'softgrid_dim2',
1373 1 tkerber
                                   'softgrid_dim3',))
1374 1 tkerber
        v[:] = potgrid
1375 1 tkerber
        nc.sync()
1376 1 tkerber
        nc.close()
1377 1 tkerber
        self.set_status('new')
1378 1 tkerber
        self.ready = False
1379 1 tkerber
1380 1 tkerber
    def set_fftgrid(self, soft=None, hard=None):
1381 1 tkerber
        '''
1382 1 tkerber
        sets the dimensions of the FFT grid to be used
1383 1 tkerber

1384 1 tkerber
        :Parameters:
1385 1 tkerber

1386 1 tkerber
          soft : (n1,n2,n3) integers
1387 1 tkerber
            make a n1 x n2 x n3 grid
1388 1 tkerber

1389 1 tkerber
          hard : (n1,n2,n3) integers
1390 1 tkerber
            make a n1 x n2 x n3 grid
1391 1 tkerber

1392 1 tkerber

1393 1 tkerber
        >>> calc.set_fftgrid(soft=[42,44,46])
1394 1 tkerber
        sets the soft and hard grid dimensions to 42,44,46
1395 1 tkerber

1396 1 tkerber
        >>> calc.set_fftgrid(soft=[42,44,46],hard=[80,84,88])
1397 1 tkerber
        sets the soft grid dimensions to 42,44,46 and the hard
1398 1 tkerber
        grid dimensions to 80,84,88
1399 1 tkerber

1400 1 tkerber
        These are the fast FFt grid numbers listed in fftdimensions.F
1401 1 tkerber

1402 1 tkerber
        data list_of_fft /2,  4,  6,  8, 10, 12, 14, 16, 18, 20, &
1403 1 tkerber
        22,24, 28, 30,32, 36, 40, 42, 44, 48, &
1404 1 tkerber
        56,60, 64, 66, 70, 72, 80, 84, 88, 90, &
1405 1 tkerber
        96,108,110,112,120,126,128,132,140,144,154, &
1406 1 tkerber
        160,168,176,180,192,198,200, &
1407 1 tkerber
        216,240,264,270,280,288,324,352,360,378,384,400,432, &
1408 1 tkerber
        450,480,540,576,640/
1409 1 tkerber

1410 1 tkerber
        otherwise you will get some errors from mis-dimensioned variables.
1411 1 tkerber

1412 1 tkerber
        this is usually automatically set by Dacapo.
1413 1 tkerber
        '''
1414 1 tkerber
1415 1 tkerber
        if soft is not None:
1416 1 tkerber
            self.delete_ncattdimvar(self.nc,
1417 1 tkerber
                                    ncdims=['softgrid_dim1',
1418 1 tkerber
                                            'softgrid_dim2',
1419 1 tkerber
                                            'softgrid_dim3'
1420 1 tkerber
                                            ],
1421 1 tkerber
                                    ncvars=[])
1422 1 tkerber
1423 1 tkerber
1424 1 tkerber
            nc = netCDF(self.get_nc(), 'a')
1425 1 tkerber
            nc.createDimension('softgrid_dim1', soft[0])
1426 1 tkerber
            nc.createDimension('softgrid_dim2', soft[1])
1427 1 tkerber
            nc.createDimension('softgrid_dim3', soft[2])
1428 1 tkerber
            nc.sync()
1429 1 tkerber
            nc.close()
1430 1 tkerber
1431 1 tkerber
            if hard is None:
1432 1 tkerber
                hard = soft
1433 1 tkerber
1434 1 tkerber
        if hard is not None:
1435 1 tkerber
            self.delete_ncattdimvar(self.nc,
1436 1 tkerber
                                    ncdims=['hardgrid_dim1',
1437 1 tkerber
                                            'hardgrid_dim2',
1438 1 tkerber
                                            'hardgrid_dim3'
1439 1 tkerber
                                            ],
1440 1 tkerber
                                    ncvars=[])
1441 1 tkerber
            nc = netCDF(self.get_nc(),'a')
1442 1 tkerber
            nc.createDimension('hardgrid_dim1', hard[0])
1443 1 tkerber
            nc.createDimension('hardgrid_dim2', hard[1])
1444 1 tkerber
            nc.createDimension('hardgrid_dim3', hard[2])
1445 1 tkerber
            nc.sync()
1446 1 tkerber
            nc.close()
1447 1 tkerber
1448 1 tkerber
        self.set_status('new')
1449 1 tkerber
        self.ready = False
1450 1 tkerber
1451 1 tkerber
    def get_ascii_debug(self):
1452 1 tkerber
        'Return the debug settings in Dacapo'
1453 1 tkerber
1454 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
1455 1 tkerber
        if 'PrintDebugInfo' in nc.variables:
1456 1 tkerber
            v = nc.variables['PrintDebugInfo']
1457 1 tkerber
            debug = string.join(v[:], '')
1458 1 tkerber
        else:
1459 1 tkerber
            debug = None
1460 1 tkerber
        nc.close()
1461 1 tkerber
        return debug
1462 1 tkerber
1463 1 tkerber
    def set_ascii_debug(self, level):
1464 1 tkerber
        '''set the debug level for Dacapo
1465 1 tkerber

1466 1 tkerber
        :Parameters:
1467 1 tkerber

1468 1 tkerber
          level : string
1469 1 tkerber
            one of 'Off', 'MediumLevel', 'HighLevel'
1470 1 tkerber
        '''
1471 1 tkerber
1472 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1473 1 tkerber
        if 'PrintDebugInfo' in nc.variables:
1474 1 tkerber
            v = nc.variables['PrintDebugInfo']
1475 1 tkerber
        else:
1476 1 tkerber
            if 'dim20' not in nc.dimensions:
1477 1 tkerber
                nc.createDimension('dim20', 20)
1478 1 tkerber
            v = nc.createVariable('PrintDebugInfo', 'c', ('dim20',))
1479 1 tkerber
1480 1 tkerber
        v[:] = np.array('%20s' % level, dtype='c')
1481 1 tkerber
        nc.sync()
1482 1 tkerber
        nc.close()
1483 1 tkerber
        self.set_status('new')
1484 1 tkerber
        self.ready = False
1485 1 tkerber
1486 1 tkerber
    def get_ncoutput(self):
1487 1 tkerber
        'returns the control variables for the ncfile'
1488 1 tkerber
1489 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1490 1 tkerber
        if 'NetCDFOutputControl' in nc.variables:
1491 1 tkerber
            v = nc.variables['NetCDFOutputControl']
1492 1 tkerber
            ncoutput = {}
1493 1 tkerber
            if hasattr(v, 'PrintWaveFunction'):
1494 1 tkerber
                ncoutput['wf'] = v.PrintWaveFunction
1495 1 tkerber
            if hasattr(v, 'PrintChargeDensity'):
1496 1 tkerber
                ncoutput['cd'] = v.PrintChargeDensity
1497 1 tkerber
            if hasattr(v, 'PrintEffPotential'):
1498 1 tkerber
                ncoutput['efp'] = v.PrintEffPotential
1499 1 tkerber
            if hasattr(v, 'PrintElsPotential'):
1500 1 tkerber
                ncoutput['esp'] = v.PrintElsPotential
1501 1 tkerber
        else:
1502 1 tkerber
            ncoutput = None
1503 1 tkerber
        nc.close()
1504 1 tkerber
        return ncoutput
1505 1 tkerber
1506 1 tkerber
    def set_ncoutput(self,
1507 1 tkerber
                     wf=None,
1508 1 tkerber
                     cd=None,
1509 1 tkerber
                     efp=None,
1510 1 tkerber
                     esp=None):
1511 1 tkerber
        '''set the output of large variables in the netcdf output file
1512 1 tkerber

1513 1 tkerber
        :Parameters:
1514 1 tkerber

1515 1 tkerber
          wf : string
1516 1 tkerber
            controls output of wavefunction. values can
1517 1 tkerber
            be 'Yes' or 'No'
1518 1 tkerber

1519 1 tkerber
          cd : string
1520 1 tkerber
            controls output of charge density. values can
1521 1 tkerber
            be 'Yes' or 'No'
1522 1 tkerber

1523 1 tkerber
          efp : string
1524 1 tkerber
            controls output of effective potential. values can
1525 1 tkerber
            be 'Yes' or 'No'
1526 1 tkerber

1527 1 tkerber
          esp : string
1528 1 tkerber
            controls output of electrostatic potential. values can
1529 1 tkerber
            be 'Yes' or 'No'
1530 1 tkerber
        '''
1531 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1532 1 tkerber
        if 'NetCDFOutputControl' in nc.variables:
1533 1 tkerber
            v = nc.variables['NetCDFOutputControl']
1534 1 tkerber
        else:
1535 1 tkerber
            v = nc.createVariable('NetCDFOutputControl', 'c', ())
1536 1 tkerber
1537 1 tkerber
        if wf is not None:
1538 1 tkerber
            v.PrintWaveFunction = wf
1539 1 tkerber
        if cd is not None:
1540 1 tkerber
            v.PrintChargeDensity = cd
1541 1 tkerber
        if efp is not None:
1542 1 tkerber
            v.PrintEffPotential = efp
1543 1 tkerber
        if esp is not None:
1544 1 tkerber
            v.PrintElsPotential = esp
1545 1 tkerber
1546 1 tkerber
        nc.sync()
1547 1 tkerber
        nc.close()
1548 1 tkerber
        self.set_status('new')
1549 1 tkerber
        self.ready = False
1550 1 tkerber
1551 1 tkerber
    def get_ados(self, **kwargs):
1552 1 tkerber
        '''
1553 1 tkerber
        attempt at maintaining backward compatibility with get_ados
1554 1 tkerber
        returning data
1555 1 tkerber

1556 1 tkerber
        Now when we call calc.get_ados() it will return settings,
1557 1 tkerber

1558 1 tkerber
        and calc.get_ados(atoms=[],...) should return data
1559 1 tkerber

1560 1 tkerber
        '''
1561 1 tkerber
1562 1 tkerber
        if len(kwargs) != 0:
1563 1 tkerber
            return self.get_ados_data(**kwargs)
1564 1 tkerber
1565 1 tkerber
        nc = netCDF(self.get_nc(),'r')
1566 1 tkerber
        if 'PrintAtomProjectedDOS' in nc.variables:
1567 1 tkerber
            v = nc.variables['PrintAtomProjectedDOS']
1568 1 tkerber
            ados = {}
1569 1 tkerber
            if hasattr(v, 'EnergyWindow'):
1570 1 tkerber
                ados['energywindow'] = v.EnergyWindow
1571 1 tkerber
            if hasattr(v, 'EnergyWidth'):
1572 1 tkerber
                ados['energywidth'] = v.EnergyWidth
1573 1 tkerber
            if hasattr(v, 'NumberEnergyPoints'):
1574 1 tkerber
                ados['npoints'] = v.NumberEnergyPoints
1575 1 tkerber
            if hasattr(v, 'CutoffRadius'):
1576 1 tkerber
                ados['cutoff'] = v.CutoffRadius
1577 1 tkerber
        else:
1578 1 tkerber
            ados = None
1579 1 tkerber
1580 1 tkerber
        nc.close()
1581 1 tkerber
        return ados
1582 1 tkerber
1583 1 tkerber
    def set_ados(self,
1584 1 tkerber
                 energywindow=(-15,5),
1585 1 tkerber
                 energywidth=0.2,
1586 1 tkerber
                 npoints=250,
1587 1 tkerber
                 cutoff=1.0):
1588 1 tkerber
        '''
1589 1 tkerber
        setup calculation of atom-projected density of states
1590 1 tkerber

1591 1 tkerber
        :Parameters:
1592 1 tkerber

1593 1 tkerber
          energywindow : (float, float)
1594 1 tkerber
            sets (emin,emax) in eV referenced to the Fermi level
1595 1 tkerber

1596 1 tkerber
          energywidth : float
1597 1 tkerber
            the gaussian used in smearing
1598 1 tkerber

1599 1 tkerber
          npoints : integer
1600 1 tkerber
            the number of points to sample the DOS at
1601 1 tkerber

1602 1 tkerber
          cutoff : float
1603 1 tkerber
            the cutoff radius in angstroms for the integration.
1604 1 tkerber
        '''
1605 1 tkerber
1606 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1607 1 tkerber
        if 'PrintAtomProjectedDOS' in nc.variables:
1608 1 tkerber
            v = nc.variables['PrintAtomProjectedDOS']
1609 1 tkerber
        else:
1610 1 tkerber
            v = nc.createVariable('PrintAtomProjectedDOS', 'c', ())
1611 1 tkerber
1612 1 tkerber
        v.EnergyWindow = energywindow
1613 1 tkerber
        v.EnergyWidth  = energywidth
1614 1 tkerber
        v.NumberEnergyPoints = npoints
1615 1 tkerber
        v.CutoffRadius = cutoff
1616 1 tkerber
1617 1 tkerber
        nc.sync()
1618 1 tkerber
        nc.close()
1619 1 tkerber
        self.set_status('new')
1620 1 tkerber
        self.ready = False
1621 1 tkerber
1622 1 tkerber
    def get_mdos(self):
1623 1 tkerber
        'return multicentered projected dos parameters'
1624 1 tkerber
        nc = netCDF(self.get_nc(),'r')
1625 1 tkerber
1626 1 tkerber
        mdos = {}
1627 1 tkerber
1628 1 tkerber
        if 'MultiCenterProjectedDOS' in nc.variables:
1629 1 tkerber
            v = nc.variables['MultiCenterProjectedDOS']
1630 1 tkerber
            mdos['energywindow'] = v.EnergyWindow
1631 1 tkerber
            mdos['energywidth'] = v.EnergyWidth
1632 1 tkerber
            mdos['numberenergypoints'] = v.NumberEnergyPoints
1633 1 tkerber
            mdos['cutoffradius'] = v.CutoffRadius
1634 1 tkerber
            mdos['mcenters'] = eval(v.mcenters)
1635 1 tkerber
1636 1 tkerber
        nc.close()
1637 1 tkerber
1638 1 tkerber
        return mdos
1639 1 tkerber
1640 1 tkerber
    def get_mdos_data(self,
1641 1 tkerber
                      spin=0,
1642 1 tkerber
                      cutoffradius='infinite'):
1643 1 tkerber
        '''returns data from multicentered projection
1644 1 tkerber

1645 1 tkerber

1646 1 tkerber
        returns (mdos, rotmat)
1647 1 tkerber

1648 1 tkerber
        the rotation matrices are retrieved from the text file. I am
1649 1 tkerber
        not sure what you would do with these, but there was a note
1650 1 tkerber
        about them in the old documentation so I put the code to
1651 1 tkerber
        retrieve them here. the syntax for the return value is:
1652 1 tkerber
        rotmat[atom#][label] returns the rotation matrix for the
1653 1 tkerber
        center on the atom# for label. I do not not know what the
1654 1 tkerber
        label refers to.
1655 1 tkerber
        '''
1656 1 tkerber
1657 1 tkerber
        if self.calculation_required():
1658 1 tkerber
            self.calculate()
1659 1 tkerber
1660 1 tkerber
        nc = netCDF(self.get_nc(),'r')
1661 1 tkerber
        icut = 1 #short
1662 1 tkerber
        if cutoffradius == "infinite":
1663 1 tkerber
            icut = 0
1664 1 tkerber
1665 1 tkerber
        #var = nc.variables['MultiCenterProjectedDOS']
1666 1 tkerber
        integrated = nc.variables['MultiCenterProjectedDOS_IntegratedDOS'][:]
1667 1 tkerber
        tz = 'MultiCenterProjectedDOS_EnergyResolvedDOS'
1668 1 tkerber
        energyresolved = nc.variables[tz][:]
1669 1 tkerber
        energygrid = nc.variables['MultiCenterProjectedDOS_EnergyGrid'][:]
1670 1 tkerber
1671 1 tkerber
        number_of_multicenters  = integrated.shape[0]
1672 1 tkerber
        #number_of_cutoff = integrated.shape[1]
1673 1 tkerber
        #number_of_spin = integrated.shape[2]
1674 1 tkerber
1675 1 tkerber
        multicenterprojections = []
1676 1 tkerber
        for multicenter in range(number_of_multicenters):
1677 1 tkerber
            #orbitals = var[multicenter]
1678 1 tkerber
            energyresolveddata = energyresolved[multicenter, icut, spin, :]
1679 1 tkerber
            #integrateddata     = integrated[multicenter, icut, spin]
1680 1 tkerber
            multicenterprojections.append([energygrid, energyresolveddata])
1681 1 tkerber
1682 1 tkerber
        log.info('Found %d multicenters' % len(multicenterprojections))
1683 1 tkerber
        nc.close()
1684 1 tkerber
1685 1 tkerber
        #now parse the text file for the rotation matrices
1686 1 tkerber
        rot_mat_lines = []
1687 1 tkerber
        txt = self.get_txt()
1688 1 tkerber
        if os.path.exists(txt):
1689 1 tkerber
            f = open(txt,'r')
1690 1 tkerber
            for line in f:
1691 1 tkerber
                if 'MUL: Rmatrix' in line:
1692 1 tkerber
                    rot_mat_lines.append(line)
1693 1 tkerber
            f.close()
1694 1 tkerber
1695 1 tkerber
            rotmat = []
1696 1 tkerber
            for line in rot_mat_lines:
1697 1 tkerber
                fields = line.split()
1698 1 tkerber
                novl = int(fields[2])
1699 1 tkerber
                ncen = int(fields[3])
1700 1 tkerber
                row = [float(x) for x in fields[4:]]
1701 1 tkerber
1702 1 tkerber
                try:
1703 1 tkerber
                    rotmat[novl-1][ncen-1].append(row)
1704 1 tkerber
                except IndexError:
1705 1 tkerber
                    try:
1706 1 tkerber
                        rotmat[novl-1].append([])
1707 1 tkerber
                        rotmat[novl-1][ncen-1].append(row)
1708 1 tkerber
                    except IndexError:
1709 1 tkerber
                        rotmat.append([])
1710 1 tkerber
                        rotmat[novl-1].append([])
1711 1 tkerber
                    rotmat[novl-1][ncen-1].append(row)
1712 1 tkerber
        else:
1713 1 tkerber
            rotmat = None
1714 1 tkerber
1715 1 tkerber
        return (multicenterprojections, rotmat)
1716 1 tkerber
1717 1 tkerber
    def set_mdos(self,
1718 1 tkerber
                 mcenters=None,
1719 1 tkerber
                 energywindow=(-15,5),
1720 1 tkerber
                 energywidth=0.2,
1721 1 tkerber
                 numberenergypoints=250,
1722 1 tkerber
                 cutoffradius=1.0):
1723 1 tkerber
        '''Setup multicentered projected DOS.
1724 1 tkerber

1725 1 tkerber
        mcenters
1726 1 tkerber
           a list of tuples containing (atom#,l,m,weight)
1727 1 tkerber
           (0,0,0,1.0) specifies (atom 0, l=0, m=0, weight=1.0) an s orbital
1728 1 tkerber
           on atom 0
1729 1 tkerber

1730 1 tkerber
           (1,1,1,1.0) specifies (atom 1, l=1, m=1, weight=1.0) a p orbital
1731 1 tkerber
           with m = +1 on atom 0
1732 1 tkerber

1733 1 tkerber
           l=0 s-orbital
1734 1 tkerber
           l=1 p-orbital
1735 1 tkerber
           l=2 d-orbital
1736 1 tkerber

1737 1 tkerber
           m in range of ( -l ... 0 ... +l )
1738 1 tkerber

1739 1 tkerber
           The direction cosines for which the spherical harmonics are
1740 1 tkerber
           set up are using the next different atom in the list
1741 1 tkerber
           (cyclic) as direction pointer, so the z-direction is chosen
1742 1 tkerber
           along the direction to this next atom. At the moment the
1743 1 tkerber
           rotation matrices is only given in the text file, you can
1744 1 tkerber
           use grep'MUL: Rmatrix' out_o2.txt to get this information.
1745 1 tkerber

1746 1 tkerber
        adapated from old MultiCenterProjectedDOS.py
1747 1 tkerber
        '''
1748 1 tkerber
        if mcenters is None:
1749 1 tkerber
            return
1750 1 tkerber
1751 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1752 1 tkerber
1753 1 tkerber
        _listofmcenters_ = mcenters
1754 1 tkerber
1755 1 tkerber
        # get number of multi centers
1756 1 tkerber
        ncenters = len(_listofmcenters_)
1757 1 tkerber
        # get max number of orbitals any center
1758 1 tkerber
        max_orbitals = max(map(len, _listofmcenters_))
1759 1 tkerber
1760 1 tkerber
        mmatrix = np.zeros([ncenters, max_orbitals, 4], np.float)
1761 1 tkerber
        ncenter = 0
1762 1 tkerber
        for multicenter in _listofmcenters_:
1763 1 tkerber
            norbital = 0
1764 1 tkerber
            for orbital in multicenter:
1765 1 tkerber
                mmatrix[ncenter, norbital] = orbital
1766 1 tkerber
                norbital = norbital + 1
1767 1 tkerber
1768 1 tkerber
            # signal that this multicenter contains less than
1769 1 tkerber
            # max_orbital orbitals
1770 1 tkerber
            if len(multicenter) < max_orbitals:
1771 1 tkerber
                mmatrix[ncenter, len(multicenter):max_orbitals] = (-1.0, 0,
1772 1 tkerber
                                                                   0, 0)
1773 1 tkerber
1774 1 tkerber
            ncenter = ncenter + 1
1775 1 tkerber
1776 1 tkerber
        nc.createDimension('max_orbitals', max_orbitals)
1777 1 tkerber
        nc.createDimension('number_of_multicenters', ncenters)
1778 1 tkerber
1779 1 tkerber
        if 'MultiCenterProjectedDOS' in nc.variables:
1780 1 tkerber
            v = nc.variables['MultiCenterProjectedDOS']
1781 1 tkerber
        else:
1782 1 tkerber
            v = nc.createVariable('MultiCenterProjectedDOS',
1783 1 tkerber
                                  'd',
1784 1 tkerber
                                  ('number_of_multicenters',
1785 1 tkerber
                                   'max_orbitals',
1786 1 tkerber
                                   'dim4'))
1787 1 tkerber
1788 1 tkerber
        v.EnergyWindow = energywindow
1789 1 tkerber
        v.EnergyWidth = energywidth
1790 1 tkerber
        v.NumberEnergyPoints = numberenergypoints
1791 1 tkerber
        v.CutoffRadius = cutoffradius
1792 1 tkerber
1793 1 tkerber
        #this is kind of hacky, but it is needed for get_mdos so you
1794 1 tkerber
        #can tell if the input is changed.
1795 1 tkerber
        v.mcenters = str(mcenters)
1796 1 tkerber
1797 1 tkerber
        v[:] = mmatrix
1798 1 tkerber
1799 1 tkerber
        nc.sync()
1800 1 tkerber
        nc.close()
1801 1 tkerber
1802 1 tkerber
    def set_debug(self, debug):
1803 1 tkerber
        '''
1804 1 tkerber
        set debug level for python logging
1805 1 tkerber

1806 1 tkerber
        debug should be an integer from 0-100 or one of the logging
1807 1 tkerber
        constants like logging.DEBUG, logging.WARN, etc...
1808 1 tkerber

1809 1 tkerber
        '''
1810 1 tkerber
1811 1 tkerber
        self.debug = debug
1812 1 tkerber
        log.setLevel(debug)
1813 1 tkerber
1814 1 tkerber
    def get_debug(self):
1815 1 tkerber
        'Return the python logging level'
1816 1 tkerber
1817 1 tkerber
        return self.debug
1818 1 tkerber
1819 1 tkerber
    def get_decoupling(self):
1820 1 tkerber
        'return the electrostatic decoupling parameters'
1821 1 tkerber
1822 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
1823 1 tkerber
        if 'Decoupling' in nc.variables:
1824 1 tkerber
            v = nc.variables['Decoupling']
1825 1 tkerber
            decoupling = {}
1826 1 tkerber
            if hasattr(v,'NumberOfGaussians'):
1827 1 tkerber
                decoupling['ngaussians'] = v.NumberOfGaussians
1828 1 tkerber
            if hasattr(v,'ECutoff'):
1829 1 tkerber
                decoupling['ecutoff'] = v.ECutoff
1830 1 tkerber
            if hasattr(v,'WidthOfGaussian'):
1831 1 tkerber
                decoupling['gausswidth'] = v.WidthOfGaussian
1832 1 tkerber
        else:
1833 1 tkerber
            decoupling = None
1834 1 tkerber
        nc.close()
1835 1 tkerber
        return decoupling
1836 1 tkerber
1837 1 tkerber
    def set_decoupling(self,
1838 1 tkerber
                       ngaussians=3,
1839 1 tkerber
                       ecutoff=100,
1840 1 tkerber
                       gausswidth=0.35):
1841 1 tkerber
        '''
1842 1 tkerber
        Decoupling activates the three dimensional electrostatic
1843 1 tkerber
        decoupling. Based on paper by Peter E. Bloechl: JCP 103
1844 1 tkerber
        page7422 (1995).
1845 1 tkerber

1846 1 tkerber
        :Parameters:
1847 1 tkerber

1848 1 tkerber
          ngaussians : int
1849 1 tkerber
            The number of gaussian functions per atom
1850 1 tkerber
            used for constructing the model charge of the system
1851 1 tkerber

1852 1 tkerber
          ecutoff : int
1853 1 tkerber
            The cut off energy (eV) of system charge density in
1854 1 tkerber
            g-space used when mapping constructing the model change of
1855 1 tkerber
            the system, i.e. only charge density components below
1856 1 tkerber
            ECutoff enters when constructing the model change.
1857 1 tkerber

1858 1 tkerber
          gausswidth : float
1859 1 tkerber
            The width of the Gaussians defined by
1860 1 tkerber
            $widthofgaussian*1.5^(n-1)$  $n$=(1 to numberofgaussians)
1861 1 tkerber

1862 1 tkerber
        '''
1863 1 tkerber
1864 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1865 1 tkerber
        if 'Decoupling' in nc.variables:
1866 1 tkerber
            v = nc.variables['Decoupling']
1867 1 tkerber
        else:
1868 1 tkerber
            v = nc.createVariable('Decoupling', 'c', ())
1869 1 tkerber
1870 1 tkerber
        v.NumberOfGaussians = ngaussians
1871 1 tkerber
        v.ECutoff = ecutoff
1872 1 tkerber
        v.WidthOfGaussian = gausswidth
1873 1 tkerber
1874 1 tkerber
        nc.sync()
1875 1 tkerber
        nc.close()
1876 1 tkerber
        self.set_status('new')
1877 1 tkerber
        self.ready = False
1878 1 tkerber
1879 1 tkerber
    def set_external_dipole(self,
1880 1 tkerber
                            value,
1881 1 tkerber
                            position=None):
1882 1 tkerber
        '''
1883 1 tkerber
        Externally imposed dipole potential. This option overwrites
1884 1 tkerber
        DipoleCorrection if set.
1885 1 tkerber

1886 1 tkerber
        :Parameters:
1887 1 tkerber

1888 1 tkerber
          value : float
1889 1 tkerber
            units of volts
1890 1 tkerber

1891 1 tkerber
          position : float
1892 1 tkerber
            scaled coordinates along third unit cell direction.
1893 1 tkerber
            if None, the compensation dipole layer plane in the
1894 1 tkerber
            vacuum position farthest from any other atoms on both
1895 1 tkerber
            sides of the slab. Do not set to 0.0.
1896 1 tkerber
        '''
1897 1 tkerber
1898 1 tkerber
        var = 'ExternalDipolePotential'
1899 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
1900 1 tkerber
        if var in nc.variables:
1901 1 tkerber
            v = nc.variables[var]
1902 1 tkerber
        else:
1903 1 tkerber
            v = nc.createVariable('ExternalDipolePotential', 'd', ())
1904 1 tkerber
1905 1 tkerber
        v.assignValue(value)
1906 1 tkerber
        if position is not None:
1907 1 tkerber
            v.DipoleLayerPosition = position
1908 1 tkerber
1909 1 tkerber
        nc.sync()
1910 1 tkerber
        nc.close()
1911 1 tkerber
        self.set_status('new')
1912 1 tkerber
        self.ready = False
1913 1 tkerber
1914 1 tkerber
    def get_external_dipole(self):
1915 1 tkerber
        'return the External dipole settings'
1916 1 tkerber
1917 1 tkerber
        var = 'ExternalDipolePotential'
1918 1 tkerber
        nc = netCDF(self.get_nc(),'r')
1919 1 tkerber
        if var in nc.variables:
1920 1 tkerber
            v = nc.variables[var]
1921 1 tkerber
            value = v.getValue()
1922 1 tkerber
            if hasattr(v, 'DipoleLayerPosition'):
1923 1 tkerber
                position = v.DipoleLayerPosition
1924 1 tkerber
            else:
1925 1 tkerber
                position = None
1926 1 tkerber
1927 1 tkerber
            ed = {'value':value, 'position':position}
1928 1 tkerber
        else:
1929 1 tkerber
            ed = None
1930 1 tkerber
        nc.close()
1931 1 tkerber
        return ed
1932 1 tkerber
1933 1 tkerber
    def set_dipole(self,
1934 1 tkerber
                   status=True,
1935 1 tkerber
                   mixpar=0.2,
1936 1 tkerber
                   initval=0.0,
1937 1 tkerber
                   adddipfield=0.0,
1938 1 tkerber
                   position=None):
1939 1 tkerber
        '''turn on and set dipole correction scheme
1940 1 tkerber

1941 1 tkerber
        :Parameters:
1942 1 tkerber

1943 1 tkerber
          status : Boolean
1944 1 tkerber
            True turns dipole on. False turns Dipole off
1945 1 tkerber

1946 1 tkerber
          mixpar : float
1947 1 tkerber
            Mixing Parameter for the the dipole correction field
1948 1 tkerber
            during the electronic minimization process. If instabilities
1949 1 tkerber
            occur during electronic minimization, this value may be
1950 1 tkerber
            decreased.
1951 1 tkerber

1952 1 tkerber
          initval : float
1953 1 tkerber
            initial value to start at
1954 1 tkerber

1955 1 tkerber
          adddipfield : float
1956 1 tkerber
            additional dipole field to add
1957 1 tkerber
            units : V/ang
1958 1 tkerber
            External additive, constant electrostatic field along
1959 1 tkerber
            third unit cell vector, corresponding to an external
1960 1 tkerber
            dipole layer. The field discontinuity follows the position
1961 1 tkerber
            of the dynamical dipole correction, i.e. if
1962 1 tkerber
            DipoleCorrection:DipoleLayerPosition is set, the field
1963 1 tkerber
            discontinuity is at this value, otherwise it is at the
1964 1 tkerber
            vacuum position farthest from any other atoms on both
1965 1 tkerber
            sides of the slab.
1966 1 tkerber

1967 1 tkerber
          position : float
1968 1 tkerber
            scaled coordinates along third unit cell direction.
1969 1 tkerber
            If this attribute is set, DACAPO will position the
1970 1 tkerber
            compensation dipole layer plane in at the provided value.
1971 1 tkerber
            If this attribute is not set, DACAPO will put the compensation
1972 1 tkerber
            dipole layer plane in the vacuum position farthest from any
1973 1 tkerber
            other atoms on both sides of the slab. Do not set this to
1974 1 tkerber
            0.0
1975 1 tkerber

1976 1 tkerber

1977 1 tkerber
        calling set_dipole() sets all default values.
1978 1 tkerber

1979 1 tkerber
        '''
1980 1 tkerber
        if status == False:
1981 1 tkerber
            self.delete_ncattdimvar(self.nc, ncvars=['DipoleCorrection'])
1982 1 tkerber
            return
1983 1 tkerber
1984 1 tkerber
        ncf = netCDF(self.get_nc(), 'a')
1985 1 tkerber
        if 'DipoleCorrection' not in ncf.variables:
1986 1 tkerber
            dip = ncf.createVariable('DipoleCorrection', 'c', ())
1987 1 tkerber
        else:
1988 1 tkerber
            dip = ncf.variables['DipoleCorrection']
1989 1 tkerber
        dip.MixingParameter = mixpar
1990 1 tkerber
        dip.InitialValue = initval
1991 1 tkerber
        dip.AdditiveDipoleField = adddipfield
1992 1 tkerber
1993 1 tkerber
        if position is not None:
1994 1 tkerber
            dip.DipoleLayerPosition = position
1995 1 tkerber
1996 1 tkerber
        ncf.sync()
1997 1 tkerber
        ncf.close()
1998 1 tkerber
        self.set_status('new')
1999 1 tkerber
        self.ready = False
2000 1 tkerber
2001 1 tkerber
    def set_stay_alive(self, value):
2002 1 tkerber
        'set the stay alive setting'
2003 1 tkerber
2004 1 tkerber
        self.delete_ncattdimvar(self.nc,
2005 1 tkerber
                                ncvars=['Dynamics'])
2006 1 tkerber
2007 1 tkerber
        if value in [True, False]:
2008 1 tkerber
            self.stay_alive = value
2009 1 tkerber
            #self._dacapo_is_running = False
2010 1 tkerber
        else:
2011 1 tkerber
            log.debug("stay_alive must be boolean. Value was not changed.")
2012 1 tkerber
2013 1 tkerber
    def get_stay_alive(self):
2014 1 tkerber
        'return the stay alive settings'
2015 1 tkerber
2016 1 tkerber
        return self.stay_alive
2017 1 tkerber
2018 1 tkerber
    def get_fftgrid(self):
2019 1 tkerber
        'return soft and hard fft grids'
2020 1 tkerber
2021 1 tkerber
        nc = netCDF(self.nc, 'r')
2022 1 tkerber
        soft = []
2023 1 tkerber
        hard = []
2024 1 tkerber
        for d in [1, 2, 3]:
2025 1 tkerber
            sd = 'softgrid_dim%i' % d
2026 1 tkerber
            hd = 'hardgrid_dim%i' % d
2027 1 tkerber
            if sd in nc.dimensions:
2028 1 tkerber
                soft.append(nc.dimensions[sd])
2029 1 tkerber
                hard.append(nc.dimensions[hd])
2030 1 tkerber
        nc.close()
2031 1 tkerber
        return ({'soft':soft,
2032 1 tkerber
                 'hard':hard})
2033 1 tkerber
2034 1 tkerber
    def get_kpts_type(self):
2035 1 tkerber
        'return the kpt grid type'
2036 1 tkerber
2037 1 tkerber
        nc = netCDF(self.nc, 'r')
2038 1 tkerber
2039 1 tkerber
        if 'BZKpoints' in nc.variables:
2040 1 tkerber
            bv = nc.variables['BZKpoints']
2041 1 tkerber
            if hasattr(bv, 'gridtype'):
2042 1 tkerber
                kpts_type = bv.gridtype #string saved in jacapo
2043 1 tkerber
            else:
2044 1 tkerber
                #no grid attribute, this ncfile was created pre-jacapo
2045 1 tkerber
                kpts_type = 'pre-Jacapo: %i kpts' % len(bv[:])
2046 1 tkerber
        else:
2047 1 tkerber
            kpts_type = 'BZKpoints not defined. [[0,0,0]] used by default.'
2048 1 tkerber
2049 1 tkerber
        nc.close()
2050 1 tkerber
        return kpts_type
2051 1 tkerber
2052 1 tkerber
    def get_kpts(self):
2053 1 tkerber
        'return the BZ kpts'
2054 1 tkerber
        nc = netCDF(self.nc, 'r')
2055 1 tkerber
2056 1 tkerber
        if 'BZKpoints' in nc.variables:
2057 1 tkerber
            bv = nc.variables['BZKpoints']
2058 1 tkerber
            kpts = bv[:]
2059 1 tkerber
        else:
2060 1 tkerber
            kpts = ([0, 0, 0]) #default Gamma point used in Dacapo when
2061 1 tkerber
                             #BZKpoints not defined
2062 1 tkerber
2063 1 tkerber
        nc.close()
2064 1 tkerber
        return kpts
2065 1 tkerber
2066 1 tkerber
    def get_nbands(self):
2067 1 tkerber
        'return the number of bands used in the calculation'
2068 1 tkerber
        nc = netCDF(self.nc, 'r')
2069 1 tkerber
2070 1 tkerber
        if 'ElectronicBands' in nc.variables:
2071 1 tkerber
            v = nc.variables['ElectronicBands']
2072 1 tkerber
            if hasattr(v, 'NumberOfBands'):
2073 1 tkerber
                nbands = v.NumberOfBands[0]
2074 1 tkerber
            else:
2075 1 tkerber
                nbands = None
2076 1 tkerber
        else:
2077 1 tkerber
            nbands = None
2078 1 tkerber
2079 1 tkerber
        nc.close()
2080 1 tkerber
        return nbands
2081 1 tkerber
2082 1 tkerber
    def get_ft(self):
2083 1 tkerber
        'return the FermiTemperature used in the calculation'
2084 1 tkerber
        nc = netCDF(self.nc, 'r')
2085 1 tkerber
2086 1 tkerber
        if 'ElectronicBands' in nc.variables:
2087 1 tkerber
            v = nc.variables['ElectronicBands']
2088 1 tkerber
            if hasattr(v, 'OccupationStatistics_FermiTemperature'):
2089 1 tkerber
                ft = v.OccupationStatistics_FermiTemperature
2090 1 tkerber
            else:
2091 1 tkerber
                ft = None
2092 1 tkerber
        else:
2093 1 tkerber
            ft = None
2094 1 tkerber
        nc.close()
2095 1 tkerber
        return ft
2096 1 tkerber
2097 1 tkerber
    def get_dipole(self):
2098 1 tkerber
        'return dictionary of parameters if the DipoleCorrection was used'
2099 1 tkerber
2100 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
2101 1 tkerber
        pars = {}
2102 1 tkerber
        if 'DipoleCorrection' in nc.variables:
2103 1 tkerber
            v = nc.variables['DipoleCorrection']
2104 1 tkerber
            pars['status'] = True
2105 1 tkerber
            if hasattr(v, 'MixingParameter'):
2106 1 tkerber
                pars['mixpar'] = v.MixingParameter
2107 1 tkerber
            if hasattr(v, 'InitialValue'):
2108 1 tkerber
                pars['initval'] = v.InitialValue
2109 1 tkerber
            if hasattr(v, 'AdditiveDipoleField'):
2110 1 tkerber
                pars['adddipfield'] = v.AdditiveDipoleField
2111 1 tkerber
            if hasattr(v, 'DipoleLayerPosition'):
2112 1 tkerber
                pars['position'] = v.DipoleLayerPosition
2113 1 tkerber
2114 1 tkerber
        else:
2115 1 tkerber
            pars = False
2116 1 tkerber
        nc.close()
2117 1 tkerber
        return pars
2118 1 tkerber
2119 1 tkerber
    def get_pw(self):
2120 1 tkerber
        'return the planewave cutoff used'
2121 1 tkerber
2122 1 tkerber
        ncf = netCDF(self.nc, 'r')
2123 1 tkerber
        if 'PlaneWaveCutoff' in ncf.variables:
2124 1 tkerber
            pw = ncf.variables['PlaneWaveCutoff'].getValue()
2125 1 tkerber
        else:
2126 1 tkerber
            pw = None
2127 1 tkerber
        ncf.close()
2128 1 tkerber
2129 1 tkerber
        if isinstance(pw, int) or isinstance(pw, float):
2130 1 tkerber
            return pw
2131 1 tkerber
        elif pw is None:
2132 1 tkerber
            return None
2133 1 tkerber
        else:
2134 1 tkerber
            return pw[0]
2135 1 tkerber
2136 1 tkerber
    def get_dw(self):
2137 1 tkerber
        'return the density wave cutoff'
2138 1 tkerber
2139 1 tkerber
        ncf = netCDF(self.nc, 'r')
2140 1 tkerber
        if 'Density_WaveCutoff' in ncf.variables:
2141 1 tkerber
            dw = ncf.variables['Density_WaveCutoff'].getValue()
2142 1 tkerber
        else:
2143 1 tkerber
            dw = None
2144 1 tkerber
        ncf.close()
2145 1 tkerber
2146 1 tkerber
        #some old calculations apparently store ints, while newer ones
2147 1 tkerber
        #are lists
2148 1 tkerber
        if isinstance(dw, int) or isinstance(dw, float):
2149 1 tkerber
            return dw
2150 1 tkerber
        else:
2151 1 tkerber
            if dw is None:
2152 1 tkerber
                return None
2153 1 tkerber
            else:
2154 1 tkerber
                return dw[0]
2155 1 tkerber
2156 1 tkerber
    def get_xc(self):
2157 1 tkerber
        '''return the self-consistent exchange-correlation functional used
2158 1 tkerber

2159 1 tkerber
        returns a string'''
2160 1 tkerber
2161 1 tkerber
        nc = netCDF(self.nc, 'r')
2162 1 tkerber
        v = 'ExcFunctional'
2163 1 tkerber
        if v in nc.variables:
2164 1 tkerber
            xc = nc.variables[v][:].tostring().strip()
2165 1 tkerber
        else:
2166 1 tkerber
            xc = None
2167 1 tkerber
2168 1 tkerber
        nc.close()
2169 1 tkerber
        return xc
2170 1 tkerber
2171 1 tkerber
    def get_potential_energy(self,
2172 1 tkerber
                             atoms=None,
2173 1 tkerber
                             force_consistent=False):
2174 1 tkerber
        '''
2175 1 tkerber
        return the potential energy.
2176 1 tkerber
        '''
2177 1 tkerber
2178 1 tkerber
        if self.calculation_required(atoms):
2179 1 tkerber
            log.debug('calculation required for energy')
2180 1 tkerber
            self.calculate()
2181 1 tkerber
        else:
2182 1 tkerber
            log.debug('no calculation required for energy')
2183 1 tkerber
2184 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
2185 1 tkerber
        try:
2186 1 tkerber
            if force_consistent:
2187 1 tkerber
                e = nc.variables['TotalFreeEnergy'][-1]
2188 1 tkerber
            else:
2189 1 tkerber
                e = nc.variables['TotalEnergy'][-1]
2190 1 tkerber
            nc.close()
2191 1 tkerber
            return e
2192 1 tkerber
        except (TypeError, KeyError):
2193 1 tkerber
            raise RuntimeError('Error in calculating the total energy\n' +
2194 1 tkerber
                               'Check ascii out file for error messages')
2195 1 tkerber
2196 1 tkerber
    def get_forces(self, atoms=None):
2197 1 tkerber
        """Calculate atomic forces"""
2198 1 tkerber
2199 1 tkerber
        if atoms is None:
2200 1 tkerber
            atoms = self.atoms
2201 1 tkerber
        if self.calculation_required(atoms):
2202 1 tkerber
            self.calculate()
2203 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
2204 1 tkerber
        forces = nc.variables['DynamicAtomForces'][-1]
2205 1 tkerber
        nc.close()
2206 1 tkerber
        return forces
2207 1 tkerber
2208 1 tkerber
    def get_atoms(self):
2209 1 tkerber
        'return the atoms attached to a calculator()'
2210 1 tkerber
2211 1 tkerber
        if hasattr(self, 'atoms'):
2212 1 tkerber
            if self.atoms is None:
2213 1 tkerber
                return None
2214 1 tkerber
            atoms = self.atoms.copy()
2215 1 tkerber
            #it is not obvious the copy of atoms should have teh same
2216 1 tkerber
            #calculator
2217 1 tkerber
            atoms.set_calculator(self)
2218 1 tkerber
        else:
2219 1 tkerber
            atoms = None
2220 1 tkerber
        return atoms
2221 1 tkerber
2222 1 tkerber
    def get_nc(self):
2223 1 tkerber
        'return the ncfile used for output'
2224 1 tkerber
2225 1 tkerber
        return self.nc
2226 1 tkerber
2227 1 tkerber
    def get_txt(self):
2228 1 tkerber
        'return the txt file used for output'
2229 1 tkerber
2230 1 tkerber
        if hasattr(self,'txt'):
2231 1 tkerber
            return self.txt
2232 1 tkerber
        else:
2233 1 tkerber
            return None
2234 1 tkerber
2235 1 tkerber
    def get_psp(self, sym=None, z=None):
2236 1 tkerber
        '''get the pseudopotential filename from the psp database
2237 1 tkerber

2238 1 tkerber
        :Parameters:
2239 1 tkerber

2240 1 tkerber
          sym : string
2241 1 tkerber
            the chemical symbol of the species
2242 1 tkerber

2243 1 tkerber
          z : integer
2244 1 tkerber
            the atomic number of the species
2245 1 tkerber

2246 1 tkerber

2247 1 tkerber
        you can only specify sym or z. Returns the pseudopotential
2248 1 tkerber
        filename, not the full path.
2249 1 tkerber
        '''
2250 1 tkerber
2251 1 tkerber
        if (sym is None and z is not None):
2252 1 tkerber
            from ase.data import chemical_symbols
2253 1 tkerber
            sym = chemical_symbols[z]
2254 1 tkerber
        elif (sym is not None and z is None):
2255 1 tkerber
            pass
2256 1 tkerber
        else:
2257 1 tkerber
            raise Exception, 'You can only specify Z or sym!'
2258 1 tkerber
        psp = self.psp[sym]
2259 1 tkerber
        return psp
2260 1 tkerber
2261 1 tkerber
    def get_spin_polarized(self):
2262 1 tkerber
        'Return True if calculate is spin-polarized or False if not'
2263 1 tkerber
2264 1 tkerber
        #self.calculate() #causes recursion error with get_magnetic_moments
2265 1 tkerber
        nc = netCDF(self.nc, 'r')
2266 1 tkerber
        if 'ElectronicBands' in nc.variables:
2267 1 tkerber
            v = nc.variables['ElectronicBands']
2268 1 tkerber
            if hasattr(v, 'SpinPolarization'):
2269 1 tkerber
                if v.SpinPolarization == 1:
2270 1 tkerber
                    spinpol = False
2271 1 tkerber
                elif v.SpinPolarization == 2:
2272 1 tkerber
                    spinpol = True
2273 1 tkerber
            else:
2274 1 tkerber
                spinpol = False
2275 1 tkerber
        else:
2276 1 tkerber
            spinpol = 'Not defined'
2277 1 tkerber
2278 1 tkerber
        nc.close()
2279 1 tkerber
        return spinpol
2280 1 tkerber
2281 1 tkerber
    def get_magnetic_moments(self, atoms=None):
2282 1 tkerber
        '''return magnetic moments on each atom after the calculation is
2283 1 tkerber
        run'''
2284 1 tkerber
2285 1 tkerber
        if self.calculation_required(atoms):
2286 1 tkerber
            self.calculate()
2287 1 tkerber
        nc = netCDF(self.nc, 'r')
2288 1 tkerber
        if 'InitialAtomicMagneticMoment' in nc.variables:
2289 1 tkerber
            mom = nc.variables['InitialAtomicMagneticMoment'][:]
2290 1 tkerber
        else:
2291 1 tkerber
            mom = [0.0]*len(self.atoms)
2292 1 tkerber
2293 1 tkerber
        nc.close()
2294 1 tkerber
        return mom
2295 1 tkerber
2296 1 tkerber
    def get_status(self):
2297 1 tkerber
        '''get status of calculation from ncfile. usually one of:
2298 1 tkerber
        'new',
2299 1 tkerber
        'aborted'
2300 1 tkerber
        'running'
2301 1 tkerber
        'finished'
2302 1 tkerber
        None
2303 1 tkerber
        '''
2304 1 tkerber
2305 1 tkerber
        nc = netCDF(self.nc, 'r')
2306 1 tkerber
        if hasattr(nc, 'status'):
2307 1 tkerber
            status = nc.status
2308 1 tkerber
        else:
2309 1 tkerber
            status = None
2310 1 tkerber
        nc.close()
2311 1 tkerber
        return status
2312 1 tkerber
2313 1 tkerber
    def get_calculate_stress(self):
2314 1 tkerber
        'return whether stress is calculated or not'
2315 1 tkerber
2316 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
2317 1 tkerber
        if 'TotalStress' in nc.variables:
2318 1 tkerber
            calcstress = True
2319 1 tkerber
        else:
2320 1 tkerber
            calcstress = False
2321 1 tkerber
        nc.close()
2322 1 tkerber
        return calcstress
2323 1 tkerber
2324 1 tkerber
    def get_stress(self, atoms=None):
2325 1 tkerber
        '''get stress on the atoms.
2326 1 tkerber

2327 1 tkerber
        you should have set up the calculation
2328 1 tkerber
        to calculate stress first.
2329 1 tkerber

2330 1 tkerber
        returns [sxx, syy, szz, syz, sxz, sxy]'''
2331 1 tkerber
2332 1 tkerber
        if self.calculation_required(atoms):
2333 1 tkerber
            self.calculate()
2334 1 tkerber
2335 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
2336 1 tkerber
        if 'TotalStress' in nc.variables:
2337 1 tkerber
            stress = nc.variables['TotalStress'][:]
2338 1 tkerber
            #ase expects the 6-element form
2339 1 tkerber
            stress = np.take(stress.ravel(), [0, 4, 8, 5, 2, 1])
2340 1 tkerber
        else:
2341 1 tkerber
            #stress will not be here if you did not set it up by
2342 1 tkerber
            #calling set_stress() or in the __init__
2343 1 tkerber
            stress = None
2344 1 tkerber
2345 1 tkerber
        nc.close()
2346 1 tkerber
2347 1 tkerber
        return stress
2348 1 tkerber
2349 1 tkerber
    def get_psp_valence(self, psp):
2350 1 tkerber
        '''
2351 1 tkerber
        get the psp valence charge on an atom from the pspfile.
2352 1 tkerber
        '''
2353 1 tkerber
2354 1 tkerber
        from struct import unpack
2355 1 tkerber
        dacapopath = os.environ.get('DACAPOPATH')
2356 1 tkerber
2357 1 tkerber
        if os.path.exists(psp):
2358 1 tkerber
            #the pspfile may be in the current directory
2359 1 tkerber
            #or defined by an absolute path
2360 1 tkerber
            fullpsp = psp
2361 1 tkerber
        else:
2362 1 tkerber
            #or, it is in the default psp path
2363 1 tkerber
            fullpsp = os.path.join(dacapopath, psp)
2364 1 tkerber
2365 1 tkerber
        if os.path.exists(fullpsp.strip()):
2366 1 tkerber
            f = open(fullpsp)
2367 1 tkerber
            # read past version numbers and text information
2368 1 tkerber
            buf = f.read(64)
2369 1 tkerber
            # read number valence electrons
2370 1 tkerber
            buf = f.read(8)
2371 1 tkerber
            fmt = ">d"
2372 1 tkerber
            nvalence = unpack(fmt, buf)[0]
2373 1 tkerber
            f.close()
2374 1 tkerber
2375 1 tkerber
        else:
2376 1 tkerber
            raise Exception, "%s does not exist" % fullpsp
2377 1 tkerber
2378 1 tkerber
        return nvalence
2379 1 tkerber
2380 1 tkerber
    def get_psp_nuclear_charge(self, psp):
2381 1 tkerber
        '''
2382 1 tkerber
        get the nuclear charge of the atom from teh psp-file.
2383 1 tkerber

2384 1 tkerber
        This is not the same as the atomic number, nor is it
2385 1 tkerber
        necessarily the negative of the number of valence electrons,
2386 1 tkerber
        since a psp may be an ion. this function is needed to compute
2387 1 tkerber
        centers of ion charge for the dipole moment calculation.
2388 1 tkerber

2389 1 tkerber
        We read in the valence ion configuration from the psp file and
2390 1 tkerber
        add up the charges in each shell.
2391 1 tkerber
        '''
2392 1 tkerber
2393 1 tkerber
        from struct import unpack
2394 1 tkerber
        dacapopath = os.environ.get('DACAPOPATH')
2395 1 tkerber
2396 1 tkerber
        if os.path.exists(psp):
2397 1 tkerber
            #the pspfile may be in the current directory
2398 1 tkerber
            #or defined by an absolute path
2399 1 tkerber
            fullpsp = psp
2400 1 tkerber
2401 1 tkerber
        else:
2402 1 tkerber
            #or, it is in the default psp path
2403 1 tkerber
            fullpsp = os.path.join(dacapopath, psp)
2404 1 tkerber
2405 1 tkerber
        if os.path.exists(fullpsp.strip()):
2406 1 tkerber
            f = open(fullpsp)
2407 1 tkerber
            unpack('>i', f.read(4))[0]
2408 1 tkerber
            for i in range(3):
2409 1 tkerber
                f.read(4)
2410 1 tkerber
            for i in range(3):
2411 1 tkerber
                f.read(4)
2412 1 tkerber
            f.read(8)
2413 1 tkerber
            f.read(20)
2414 1 tkerber
            f.read(8)
2415 1 tkerber
            f.read(8)
2416 1 tkerber
            f.read(8)
2417 1 tkerber
            nvalps = unpack('>i', f.read(4))[0]
2418 1 tkerber
            f.read(4)
2419 1 tkerber
            f.read(8)
2420 1 tkerber
            f.read(8)
2421 1 tkerber
            wwnlps = []
2422 1 tkerber
            for i in range(nvalps):
2423 1 tkerber
                f.read(4)
2424 1 tkerber
                wwnlps.append(unpack('>d', f.read(8))[0])
2425 1 tkerber
                f.read(8)
2426 1 tkerber
            f.close()
2427 1 tkerber
2428 1 tkerber
        else:
2429 1 tkerber
            raise Exception, "%s does not exist" % fullpsp
2430 1 tkerber
2431 1 tkerber
        return np.array(wwnlps).sum()
2432 1 tkerber
2433 1 tkerber
    def get_valence(self, atoms=None):
2434 1 tkerber
        '''return the total number of valence electrons for the
2435 1 tkerber
        atoms. valence electrons are read directly from the
2436 1 tkerber
        pseudopotentials.
2437 1 tkerber

2438 1 tkerber
        the psp filenames are stored in the ncfile. They may be just
2439 1 tkerber
        the name of the file, in which case the psp may exist in the
2440 1 tkerber
        same directory as the ncfile, or in $DACAPOPATH, or the psp
2441 1 tkerber
        may be defined by an absolute or relative path. This function
2442 1 tkerber
        deals with all these possibilities.
2443 1 tkerber
        '''
2444 1 tkerber
2445 1 tkerber
        from struct import unpack
2446 1 tkerber
2447 1 tkerber
        #do not use get_atoms() or recursion occurs
2448 1 tkerber
        if atoms is None:
2449 1 tkerber
            if hasattr(self, 'atoms'):
2450 1 tkerber
                atoms = self.atoms
2451 1 tkerber
            else:
2452 1 tkerber
                return None
2453 1 tkerber
2454 1 tkerber
        dacapopath = os.environ.get('DACAPOPATH')
2455 1 tkerber
        totval = 0.0
2456 1 tkerber
        for sym in atoms.get_chemical_symbols():
2457 1 tkerber
            psp = self.get_psp(sym)
2458 1 tkerber
2459 1 tkerber
            if os.path.exists(psp):
2460 1 tkerber
                #the pspfile may be in the current directory
2461 1 tkerber
                #or defined by an absolute path
2462 1 tkerber
                fullpsp = psp
2463 1 tkerber
2464 1 tkerber
            #let's also see if we can construct an absolute path to a
2465 1 tkerber
            #local or relative path psp.
2466 1 tkerber
            abs_path_to_nc = os.path.abspath(self.get_nc())
2467 1 tkerber
            base = os.path.split(abs_path_to_nc)[0]
2468 1 tkerber
            possible_path_to_psp = os.path.join(base, psp)
2469 1 tkerber
            if os.path.exists(possible_path_to_psp):
2470 1 tkerber
                fullpsp = possible_path_to_psp
2471 1 tkerber
2472 1 tkerber
            else:
2473 1 tkerber
                #or, it is in the default psp path
2474 1 tkerber
                fullpsp = os.path.join(dacapopath, psp)
2475 1 tkerber
            if os.path.exists(fullpsp.strip()):
2476 1 tkerber
                f = open(fullpsp)
2477 1 tkerber
                # read past version numbers and text information
2478 1 tkerber
                buf = f.read(64)
2479 1 tkerber
                # read number valence electrons
2480 1 tkerber
                buf = f.read(8)
2481 1 tkerber
                fmt = ">d"
2482 1 tkerber
                nvalence = unpack(fmt, buf)[0]
2483 1 tkerber
                f.close()
2484 1 tkerber
                totval += float(nvalence)
2485 1 tkerber
            else:
2486 1 tkerber
                raise Exception, "%s does not exist" % fullpsp
2487 1 tkerber
2488 1 tkerber
        return totval
2489 1 tkerber
2490 1 tkerber
    def calculation_required(self, atoms=None, quantities=None):
2491 1 tkerber
        '''
2492 1 tkerber
        determines if a calculation is needed.
2493 1 tkerber

2494 1 tkerber
        return True if a calculation is needed to get up to date data.
2495 1 tkerber
        return False if no calculation is needed.
2496 1 tkerber

2497 1 tkerber
        quantities is here because of the ase interface.
2498 1 tkerber
        '''
2499 1 tkerber
2500 1 tkerber
        # first, compare if the atoms is the same as the stored atoms
2501 1 tkerber
        # if anything has changed, we need to run a calculation
2502 1 tkerber
        log.debug('running calculation_required')
2503 1 tkerber
2504 1 tkerber
        if self.nc is None:
2505 1 tkerber
            raise Exception, 'No output ncfile specified!'
2506 1 tkerber
2507 1 tkerber
        if atoms is not None:
2508 1 tkerber
            if not self.atoms_are_equal(atoms):
2509 1 tkerber
                log.debug('found that atoms != self.atoms')
2510 1 tkerber
                tol = 1.0e-6 #tolerance that the unit cell is the same
2511 1 tkerber
                new = atoms.get_cell()
2512 1 tkerber
                old = self.atoms.get_cell()
2513 1 tkerber
                #float comparison of equality
2514 1 tkerber
                if not np.all(abs(old-new) < tol):
2515 1 tkerber
                    #this often changes the number of planewaves
2516 1 tkerber
                    #which requires a complete restart
2517 1 tkerber
                    log.debug('restart required! because cell changed')
2518 1 tkerber
                    self.restart()
2519 1 tkerber
                else:
2520 1 tkerber
                    log.debug('Unitcells apparently the same')
2521 1 tkerber
2522 1 tkerber
                self.set_atoms(atoms) #we have to update the atoms in any case
2523 1 tkerber
                return True
2524 1 tkerber
2525 1 tkerber
        #if we make it past the atoms check, we look in the
2526 1 tkerber
        #nc file. if parameters have been changed the status
2527 1 tkerber
        #will tell us if a calculation is needed
2528 1 tkerber
2529 1 tkerber
        #past this point, atoms was None or equal, so there is nothing to
2530 1 tkerber
        #update in the calculator
2531 1 tkerber
2532 1 tkerber
        log.debug('atoms tested equal')
2533 1 tkerber
        if os.path.exists(self.nc):
2534 1 tkerber
            nc = netCDF(self.nc, 'r')
2535 1 tkerber
            if hasattr(nc, 'status'):
2536 1 tkerber
                if nc.status == 'finished' and self.ready:
2537 1 tkerber
                    nc.close()
2538 1 tkerber
                    return False
2539 1 tkerber
                elif nc.status == 'running':
2540 1 tkerber
                    nc.close()
2541 1 tkerber
                    raise DacapoRunning('Dacapo is Running')
2542 1 tkerber
                elif nc.status == 'aborted':
2543 1 tkerber
                    nc.close()
2544 1 tkerber
                    raise DacapoAborted('Dacapo aborted. see txt file!')
2545 1 tkerber
                else:
2546 1 tkerber
                    log.debug('ncfile exists, but is not ready')
2547 1 tkerber
                    nc.close()
2548 1 tkerber
                    return True
2549 1 tkerber
            else:
2550 1 tkerber
                #legacy calculations do not have a status flag in them.
2551 1 tkerber
                #let us guess that if the TotalEnergy is there
2552 1 tkerber
                #no calculation needs to be run?
2553 1 tkerber
                if 'TotalEnergy' in nc.variables:
2554 1 tkerber
                    runflag = False
2555 1 tkerber
                else:
2556 1 tkerber
                    runflag = True
2557 1 tkerber
                nc.close()
2558 1 tkerber
                log.debug('Legacy calculation')
2559 1 tkerber
                return runflag #if no status run calculation
2560 1 tkerber
            nc.close()
2561 1 tkerber
2562 1 tkerber
        #default, a calculation is required
2563 1 tkerber
        return True
2564 1 tkerber
2565 1 tkerber
    def get_scratch(self):
2566 1 tkerber
        '''finds an appropriate scratch directory for the calculation'''
2567 1 tkerber
2568 1 tkerber
        import getpass
2569 1 tkerber
        username = getpass.getuser()
2570 1 tkerber
2571 1 tkerber
        scratch_dirs = []
2572 1 tkerber
        if os.environ.has_key('SCRATCH'):
2573 1 tkerber
            scratch_dirs.append(os.environ['SCRATCH'])
2574 1 tkerber
        if os.environ.has_key('SCR'):
2575 1 tkerber
            scratch_dirs.append(os.environ['SCR'])
2576 1 tkerber
        scratch_dirs.append('/scratch/'+username)
2577 1 tkerber
        scratch_dirs.append('/scratch/')
2578 1 tkerber
        scratch_dirs.append(os.curdir)
2579 1 tkerber
        for scratch_dir in scratch_dirs:
2580 1 tkerber
            if os.access(scratch_dir, os.W_OK):
2581 1 tkerber
                return scratch_dir
2582 1 tkerber
        raise IOError, "No suitable scratch directory and no write access \
2583 1 tkerber
        to current dir."
2584 1 tkerber
2585 1 tkerber
    def calculate(self):
2586 1 tkerber
        '''run a calculation.
2587 1 tkerber

2588 1 tkerber
        you have to be a little careful with code in here. Use the
2589 1 tkerber
        calculation_required function to tell if a calculation is
2590 1 tkerber
        required. It is assumed here that if you call this, you mean
2591 1 tkerber
        it.'''
2592 1 tkerber
2593 1 tkerber
        #provide a way to make no calculation get run
2594 1 tkerber
        if os.environ.get('DACAPO_DRYRUN', None) is not None:
2595 1 tkerber
            raise Exception, '$DACAPO_DRYRUN detected, and a calculation \
2596 1 tkerber
            attempted'
2597 1 tkerber
2598 1 tkerber
        if not self.ready:
2599 1 tkerber
            log.debug('Calculator is not ready.')
2600 1 tkerber
            if not os.path.exists(self.get_nc()):
2601 1 tkerber
                self.initnc()
2602 1 tkerber
2603 1 tkerber
            log.debug('writing atoms out')
2604 1 tkerber
            log.debug(self.atoms)
2605 1 tkerber
2606 1 tkerber
            self.write_nc() #write atoms to ncfile
2607 1 tkerber
2608 1 tkerber
            log.debug('writing input out')
2609 1 tkerber
            self.write_input() #make sure input is uptodate
2610 1 tkerber
2611 1 tkerber
2612 1 tkerber
            #check that the bands get set
2613 1 tkerber
            if self.get_nbands() is None:
2614 1 tkerber
                nelectrons = self.get_valence()
2615 1 tkerber
                nbands = int(nelectrons * 0.65 + 4)
2616 1 tkerber
                self.set_nbands(nbands)
2617 1 tkerber
2618 1 tkerber
        log.debug('running a calculation')
2619 1 tkerber
2620 1 tkerber
        nc = self.get_nc()
2621 1 tkerber
        txt = self.get_txt()
2622 1 tkerber
        scratch = self.get_scratch()
2623 1 tkerber
2624 1 tkerber
        if self.stay_alive:
2625 1 tkerber
            self.execute_external_dynamics(nc, txt)
2626 1 tkerber
            self.ready = True
2627 1 tkerber
            self.set_status('finished')
2628 1 tkerber
        else:
2629 1 tkerber
            cmd = 'dacapo.run  %(innc)s -out %(txt)s -scratch %(scratch)s'
2630 1 tkerber
            cmd = cmd % {'innc':nc,
2631 1 tkerber
                         'txt':txt,
2632 1 tkerber
                         'scratch':scratch}
2633 1 tkerber
2634 1 tkerber
            log.debug(cmd)
2635 1 tkerber
            # using subprocess instead of commands subprocess is more
2636 1 tkerber
            # flexible and works better for stay_alive
2637 1 tkerber
            self._dacapo = sp.Popen(cmd,
2638 1 tkerber
                                    stdout=sp.PIPE,
2639 1 tkerber
                                    stderr=sp.PIPE,
2640 1 tkerber
                                    shell=True)
2641 1 tkerber
            status = self._dacapo.wait()
2642 1 tkerber
            [stdout, stderr] = self._dacapo.communicate()
2643 1 tkerber
            output = stdout+stderr
2644 1 tkerber
2645 1 tkerber
            if status is 0: #that means it ended fine!
2646 1 tkerber
                self.ready = True
2647 1 tkerber
                self.set_status('finished')
2648 1 tkerber
            else:
2649 1 tkerber
                log.debug('Status was not 0')
2650 1 tkerber
                log.debug(output)
2651 1 tkerber
                self.ready = False
2652 1 tkerber
            # directory cleanup has been moved to self.__del__()
2653 1 tkerber
            del self._dacapo
2654 1 tkerber
2655 1 tkerber
            #Sometimes dacapo dies or is killed abnormally, and in this
2656 1 tkerber
            #case an exception should be raised to prevent a geometry
2657 1 tkerber
            #optimization from continuing for example. The best way to
2658 1 tkerber
            #detect this right now is actually to check the end of the
2659 1 tkerber
            #text file to make sure it ends with the right line. The
2660 1 tkerber
            #line differs if the job was run in parallel or in serial.
2661 1 tkerber
            f = open(txt, 'r')
2662 1 tkerber
            lines = f.readlines()
2663 1 tkerber
            f.close()
2664 1 tkerber
2665 1 tkerber
            if 'PAR: msexit halting Master' in lines[-1]:
2666 1 tkerber
                pass #standard parallel end
2667 1 tkerber
            elif ('TIM' in lines[-2]
2668 1 tkerber
                  and 'clexit: exiting the program' in lines[-1]):
2669 1 tkerber
                pass #standard serial end
2670 1 tkerber
            else:
2671 1 tkerber
                # text file does not end as expected, print the last
2672 1 tkerber
                # 10 lines and raise exception
2673 1 tkerber
                log.debug(string.join(lines[-10:-1], ''))
2674 1 tkerber
                s = 'Dacapo output txtfile (%s) did not end normally.'
2675 1 tkerber
                raise DacapoAbnormalTermination(s % txt)
2676 1 tkerber
2677 1 tkerber
    def execute_external_dynamics(self,
2678 1 tkerber
                                  nc=None,
2679 1 tkerber
                                  txt=None,
2680 1 tkerber
                                  stoppfile='stop',
2681 1 tkerber
                                  stopprogram=None):
2682 1 tkerber
        '''
2683 1 tkerber
        Implementation of the stay alive functionality with socket
2684 1 tkerber
        communication between dacapo and python.  Known limitations:
2685 1 tkerber
        It is not possible to start 2 independent Dacapo calculators
2686 1 tkerber
        from the same python process, since the python PID is used as
2687 1 tkerber
        identifier for the script[PID].py file.
2688 1 tkerber
        '''
2689 1 tkerber
2690 1 tkerber
        from socket import socket, AF_INET, SOCK_STREAM, timeout
2691 1 tkerber
        import tempfile
2692 1 tkerber
2693 1 tkerber
        if hasattr(self, "_dacapo"):
2694 1 tkerber
            msg = "Starting External Dynamics while Dacapo is runnning: %s"
2695 1 tkerber
            msg = msg % str(self._dacapo.poll())
2696 1 tkerber
            log.debug(msg)
2697 1 tkerber
        else:
2698 1 tkerber
            log.debug("No dacapo instance has been started yet")
2699 1 tkerber
        log.debug("Stopprogram: %s" % stopprogram)
2700 1 tkerber
2701 1 tkerber
        if not nc:
2702 1 tkerber
            nc = self.get_nc()
2703 1 tkerber
        if not txt:
2704 1 tkerber
            txt = self.get_txt()
2705 1 tkerber
        tempfile.tempdir = os.curdir
2706 1 tkerber
2707 1 tkerber
        if stopprogram:
2708 1 tkerber
            # write stop file
2709 1 tkerber
            stfile = open(stoppfile, 'w')
2710 1 tkerber
            stfile.write('1 \n')
2711 1 tkerber
            stfile.close()
2712 1 tkerber
2713 1 tkerber
            # signal to dacapo that positions are ready
2714 1 tkerber
            # let dacapo continue, it is up to the python mainloop
2715 1 tkerber
            # to allow dacapo enough time to finish properly.
2716 1 tkerber
            self._client.send('ok too proceed')
2717 1 tkerber
2718 1 tkerber
            # Wait for dacapo to acknowledge that netcdf file has
2719 1 tkerber
            # been updated, and analysis part of the code has been
2720 1 tkerber
            # terminated. Dacapo sends a signal at the end of call
2721 1 tkerber
            # clexit().
2722 1 tkerber
            log.info("waiting for dacapo to exit...")
2723 1 tkerber
            self.s.settimeout(1200.0) # if dacapo exits with an
2724 1 tkerber
                                       # error, self.s.accept()
2725 1 tkerber
                                       # should time out,
2726 1 tkerber
                                      # but we need to give it
2727 1 tkerber
                                      # enough time to write the
2728 1 tkerber
                                      # wave function to the nc
2729 1 tkerber
                                      # file.
2730 1 tkerber
            try:
2731 1 tkerber
                self._client, self._addr = self.s.accept() # Last
2732 1 tkerber
                                                          # mumble
2733 1 tkerber
                                                          # before
2734 1 tkerber
                                                          # Dacapo
2735 1 tkerber
                                                          # dies.
2736 1 tkerber
                os.system("sleep 5") # 5 seconds of silence
2737 1 tkerber
                                                         # mourning
2738 1 tkerber
                                                         # dacapo.
2739 1 tkerber
            except timeout:
2740 1 tkerber
                print '''Socket connection timed out.'''
2741 1 tkerber
                print '''This usually means Dacapo crashed.'''
2742 1 tkerber
2743 1 tkerber
            # close the socket s
2744 1 tkerber
            self.s.close()
2745 1 tkerber
            self._client.close()
2746 1 tkerber
2747 1 tkerber
            # remove the script???? file
2748 1 tkerber
            ncfile = netCDF(nc, 'r')
2749 1 tkerber
            vdyn = ncfile.variables['Dynamics']
2750 1 tkerber
            os.system('rm -f '+vdyn.ExternalIonMotion_script)
2751 1 tkerber
            ncfile.close()
2752 1 tkerber
            os.system('rm -f '+stoppfile)
2753 1 tkerber
2754 1 tkerber
            if self._dacapo.poll()==None:  # dacapo is still not dead!
2755 1 tkerber
                # but this should do it!
2756 1 tkerber
                sp.Popen("kill -9 "+str(self._dacapo.pid), shell=True)
2757 1 tkerber
                #if Dacapo dies for example because of too few
2758 1 tkerber
                #bands, subprocess never returns an exitcode.
2759 1 tkerber
                #very strange, but at least the program is
2760 1 tkerber
                #terminated.  print self._dacapo.returncode
2761 1 tkerber
            del self._dacapo
2762 1 tkerber
            return
2763 1 tkerber
2764 1 tkerber
        if hasattr(self, '_dacapo') and self._dacapo.poll()==None:
2765 1 tkerber
            # returns  None if  dacapo is running self._dacapo_is_running:
2766 1 tkerber
2767 1 tkerber
            # calculation_required already updated the positions in
2768 1 tkerber
            # the nc file
2769 1 tkerber
            self._client.send('ok too proceed')
2770 1 tkerber
2771 1 tkerber
        else:
2772 1 tkerber
2773 1 tkerber
            # get process pid that will be used as communication
2774 1 tkerber
            # channel
2775 1 tkerber
            pid = os.getpid()
2776 1 tkerber
2777 1 tkerber
            # setup communication channel to dacapo
2778 1 tkerber
            from sys    import version
2779 1 tkerber
            from string import split
2780 1 tkerber
            effpid = (pid)%(2**16-1025)+1025 # This translate pid
2781 1 tkerber
                                               # [0;99999] to a number
2782 1 tkerber
                                               # in [1025;65535] (the
2783 1 tkerber
                                               # allowed socket
2784 1 tkerber
                                               # numbers)
2785 1 tkerber
2786 1 tkerber
            self.s = socket(AF_INET, SOCK_STREAM)
2787 1 tkerber
            foundafreesocket = 0
2788 1 tkerber
            while not foundafreesocket:
2789 1 tkerber
                try:
2790 1 tkerber
                    if split(version)[0] > "2":     # new interface
2791 1 tkerber
                        self.s.bind(("", effpid))
2792 1 tkerber
                    else:                           # old interface
2793 1 tkerber
                        self.s.bind("", effpid)
2794 1 tkerber
                    foundafreesocket = 1
2795 1 tkerber
                except:
2796 1 tkerber
                    effpid = effpid + 1
2797 1 tkerber
2798 1 tkerber
            # write script file that will be used by dacapo
2799 1 tkerber
            scriptname = 'script%s.py' % str(pid)
2800 1 tkerber
            scriptfile = open(scriptname, 'w')
2801 1 tkerber
            scriptfile.write(
2802 1 tkerber
"""#!/usr/bin/env python
2803 1 tkerber
from socket import *
2804 1 tkerber
from sys    import version
2805 1 tkerber
from string import split
2806 1 tkerber
s = socket(AF_INET,SOCK_STREAM)
2807 1 tkerber
# tell python that dacapo has finished
2808 1 tkerber
if split(version)[0] > "2":     # new interface
2809 1 tkerber
     s.connect(("",%(effpid)s))
2810 1 tkerber
else:                           # old interface
2811 1 tkerber
     s.connect("",%(effpid)s)
2812 1 tkerber
# wait for python main loop
2813 1 tkerber
s.recv(14)
2814 1 tkerber
""" % {'effpid':str(effpid)})
2815 1 tkerber
            scriptfile.close()
2816 1 tkerber
            os.system('chmod +x ' + scriptname)
2817 1 tkerber
2818 1 tkerber
            # setup dynamics as external and set the script name
2819 1 tkerber
            ncfile = netCDF(nc, 'a')
2820 1 tkerber
            if 'Dynamics' not in ncfile.variables:
2821 1 tkerber
                vdyn = ncfile.createVariable('Dynamics', 'c', ())
2822 1 tkerber
            else:
2823 1 tkerber
                vdyn = ncfile.variables['Dynamics']
2824 1 tkerber
            vdyn.Type = "ExternalIonMotion"
2825 1 tkerber
            vdyn.ExternalIonMotion_script = './'+ scriptname
2826 1 tkerber
            ncfile.close()
2827 1 tkerber
2828 1 tkerber
            # dacapo is not running start dacapo non blocking
2829 1 tkerber
            scratch_in_nc = tempfile.mktemp()
2830 1 tkerber
            os.system('mv '+nc+' '+scratch_in_nc)
2831 1 tkerber
            os.system('rm -f '+stoppfile)
2832 1 tkerber
            scratch = self.get_scratch()
2833 1 tkerber
            cmd = 'dacapo.run'
2834 1 tkerber
            cmd += ' %(innc)s %(outnc)s -out %(txt)s -scratch %(scratch)s'
2835 1 tkerber
            cmd = cmd % {'innc':scratch_in_nc,
2836 1 tkerber
                         'outnc':nc,
2837 1 tkerber
                         'txt':txt,
2838 1 tkerber
                         'scratch':scratch}
2839 1 tkerber
2840 1 tkerber
            log.debug(cmd)
2841 1 tkerber
            self._dacapo = sp.Popen(cmd,
2842 1 tkerber
                                    stdout=sp.PIPE,
2843 1 tkerber
                                    stderr=sp.PIPE,
2844 1 tkerber
                                    shell=True)
2845 1 tkerber
2846 1 tkerber
            self.s.listen(1)
2847 1 tkerber
2848 1 tkerber
        # wait for dacapo
2849 1 tkerber
        self._client, self._addr = self.s.accept()
2850 1 tkerber
2851 1 tkerber
    def write_nc(self, nc=None, atoms=None):
2852 1 tkerber
        '''
2853 1 tkerber
        write out atoms to a netcdffile.
2854 1 tkerber

2855 1 tkerber
        This does not write out the calculation parameters!
2856 1 tkerber

2857 1 tkerber
        :Parameters:
2858 1 tkerber

2859 1 tkerber
          nc : string
2860 1 tkerber
            ncfilename to write to. this file will get clobbered
2861 1 tkerber
            if it already exists.
2862 1 tkerber

2863 1 tkerber
          atoms : ASE.Atoms
2864 1 tkerber
            atoms to write. if None use the attached atoms
2865 1 tkerber
            if no atoms are attached only the calculator is
2866 1 tkerber
            written out.
2867 1 tkerber

2868 1 tkerber
        the ncfile is always opened in 'a' mode.
2869 1 tkerber

2870 1 tkerber
        note: it is good practice to use the atoms argument to make
2871 1 tkerber
        sure that the geometry you mean gets written! Otherwise, the
2872 1 tkerber
        atoms in the calculator is used, which may be different than
2873 1 tkerber
        the external copy of the atoms.
2874 1 tkerber

2875 1 tkerber
        '''
2876 1 tkerber
2877 1 tkerber
        log.debug('writing atoms to ncfile')
2878 1 tkerber
        #no filename was provided to function, use the current ncfile
2879 1 tkerber
        if nc is None:
2880 1 tkerber
            nc = self.get_nc()
2881 1 tkerber
2882 1 tkerber
        if nc != self.nc:
2883 1 tkerber
            #this means we are writing a new file, and we should copy
2884 1 tkerber
            #the old file to it first.  this makes sure the old
2885 1 tkerber
            #calculator settings are preserved
2886 1 tkerber
            new = nc
2887 1 tkerber
            old = self.nc
2888 1 tkerber
            log.debug('Copying old ncfile to new ncfile')
2889 1 tkerber
            log.debug('cp %s %s' % (old, new))
2890 1 tkerber
            os.system('cp %s %s' % (old, new))
2891 1 tkerber
2892 1 tkerber
        if atoms is None:
2893 1 tkerber
            atoms = self.get_atoms()
2894 1 tkerber
2895 1 tkerber
        log.debug('self.atoms = %s' % str(self.atoms))
2896 1 tkerber
        log.debug('atoms = %s' % str(atoms))
2897 1 tkerber
2898 1 tkerber
        if atoms is not None: #there may still be no atoms attached
2899 1 tkerber
            log.debug('about to write to %s' % nc)
2900 1 tkerber
            ncf = netCDF(nc, 'a')
2901 1 tkerber
2902 1 tkerber
            if 'number_of_dynamic_atoms' not in ncf.dimensions:
2903 1 tkerber
                ncf.createDimension('number_of_dynamic_atoms',
2904 1 tkerber
                                    len(atoms))
2905 1 tkerber
            else:
2906 1 tkerber
                # number of atoms is already a dimension, but we might
2907 1 tkerber
                # be setting new atoms here
2908 1 tkerber
                # check for same atom symbols (implicitly includes
2909 1 tkerber
                # a length check)
2910 1 tkerber
                symbols = np.array(['%2s' % s for s in
2911 1 tkerber
                                    atoms.get_chemical_symbols()], dtype='c')
2912 1 tkerber
                ncsym = ncf.variables['DynamicAtomSpecies'][:]
2913 1 tkerber
                if (symbols.size != ncsym.size) or (np.any(ncsym != symbols)):
2914 1 tkerber
                    # the number of atoms or their order has changed.
2915 1 tkerber
                    # Treat this as a new calculation and reset
2916 1 tkerber
                    # number_of_ionic_steps and
2917 1 tkerber
                    # number_of_dynamic_atoms.
2918 1 tkerber
                    ncf.close() #nc file must be closed for
2919 1 tkerber
                                 #delete_ncattdimvar to work correctly
2920 1 tkerber
                    self.delete_ncattdimvar(nc, ncattrs=[],
2921 1 tkerber
                                            ncdims=['number_of_dynamic_atoms',
2922 1 tkerber
                                                    'number_ionic_steps'])
2923 1 tkerber
                    ncf = netCDF(nc, 'a')
2924 1 tkerber
                    ncf.createDimension('number_of_dynamic_atoms',
2925 1 tkerber
                                                  len(atoms))
2926 1 tkerber
                    ncf.createDimension('number_ionic_steps', None)
2927 1 tkerber
                    self._set_frame_number(0)
2928 1 tkerber
                    ncf.close() #nc file must be closed for restart to
2929 1 tkerber
                                #work correctly
2930 1 tkerber
                    self.restart()
2931 1 tkerber
                    ncf = netCDF(nc, 'a')
2932 1 tkerber
2933 1 tkerber
            #now, create variables
2934 1 tkerber
            if 'DynamicAtomSpecies' not in ncf.variables:
2935 1 tkerber
                sym = ncf.createVariable('DynamicAtomSpecies',
2936 1 tkerber
                                         'c',
2937 1 tkerber
                                         ('number_of_dynamic_atoms',
2938 1 tkerber
                                          'dim2',))
2939 1 tkerber
            else:
2940 1 tkerber
                sym = ncf.variables['DynamicAtomSpecies']
2941 1 tkerber
2942 1 tkerber
            #note explicit array casting was required here
2943 1 tkerber
            symbols = atoms.get_chemical_symbols()
2944 1 tkerber
            sym[:] = np.array(['%2s' % s for s in symbols], dtype='c')
2945 1 tkerber
2946 1 tkerber
            if 'DynamicAtomPositions' not in ncf.variables:
2947 1 tkerber
                pos = ncf.createVariable('DynamicAtomPositions',
2948 1 tkerber
                                         'd',
2949 1 tkerber
                                         ('number_ionic_steps',
2950 1 tkerber
                                          'number_of_dynamic_atoms',
2951 1 tkerber
                                          'dim3'))
2952 1 tkerber
            else:
2953 1 tkerber
                pos = ncf.variables['DynamicAtomPositions']
2954 1 tkerber
2955 1 tkerber
            spos = atoms.get_scaled_positions()
2956 1 tkerber
            if pos.typecode() == 'f':
2957 1 tkerber
                spos = np.array(spos, dtype=np.float32)
2958 1 tkerber
            pos[self._frame, :] = spos
2959 1 tkerber
2960 1 tkerber
            if 'UnitCell' not in ncf.variables:
2961 1 tkerber
                uc = ncf.createVariable('UnitCell', 'd',
2962 1 tkerber
                                        ('number_ionic_steps',
2963 1 tkerber
                                         'dim3', 'dim3'))
2964 1 tkerber
            else:
2965 1 tkerber
                uc = ncf.variables['UnitCell']
2966 1 tkerber
2967 1 tkerber
            cell = atoms.get_cell()
2968 1 tkerber
            if uc.typecode() == 'f':
2969 1 tkerber
                cell = np.array(cell, dtype=np.float32)
2970 1 tkerber
2971 1 tkerber
            uc[self._frame, :] = cell
2972 1 tkerber
2973 1 tkerber
            if 'AtomTags' not in ncf.variables:
2974 1 tkerber
                tags = ncf.createVariable('AtomTags', 'i',
2975 1 tkerber
                                          ('number_of_dynamic_atoms',))
2976 1 tkerber
            else:
2977 1 tkerber
                tags = ncf.variables['AtomTags']
2978 1 tkerber
2979 1 tkerber
            tags[:] = np.array(atoms.get_tags(), np.int32)
2980 1 tkerber
2981 1 tkerber
            if 'InitialAtomicMagneticMoment' not in ncf.variables:
2982 1 tkerber
                mom = ncf.createVariable('InitialAtomicMagneticMoment',
2983 1 tkerber
                                         'd',
2984 1 tkerber
                                         ('number_of_dynamic_atoms',))
2985 1 tkerber
            else:
2986 1 tkerber
                mom = ncf.variables['InitialAtomicMagneticMoment']
2987 1 tkerber
2988 1 tkerber
            #explain why we have to use get_initial_magnetic_moments()
2989 1 tkerber
            moms = atoms.get_initial_magnetic_moments()
2990 1 tkerber
            if mom.typecode() == 'f':
2991 1 tkerber
                moms = np.array(moms, dtype=np.float32)
2992 1 tkerber
            mom[:] = moms
2993 1 tkerber
2994 1 tkerber
            #finally the atom pseudopotentials
2995 1 tkerber
            for sym in atoms.get_chemical_symbols():
2996 1 tkerber
                vn = 'AtomProperty_%s' % sym
2997 1 tkerber
                if vn not in ncf.variables:
2998 1 tkerber
                    p = ncf.createVariable(vn, 'c', ('dim20',))
2999 1 tkerber
                else:
3000 1 tkerber
                    p = ncf.variables[vn]
3001 1 tkerber
3002 1 tkerber
                ppath = self.get_psp(sym=sym)
3003 1 tkerber
                p.PspotFile = ppath
3004 1 tkerber
3005 1 tkerber
            ncf.sync()
3006 1 tkerber
            ncf.close()
3007 1 tkerber
3008 1 tkerber
            #store constraints if they exist
3009 1 tkerber
            constraints = atoms._get_constraints()
3010 1 tkerber
            if constraints != []:
3011 1 tkerber
                nc = netCDF(self.get_nc(), 'a')
3012 1 tkerber
                if 'constraints' not in nc.variables:
3013 1 tkerber
                    if 'dim1' not in nc.dimensions:
3014 1 tkerber
                        nc.createDimension('dim1', 1)
3015 1 tkerber
                    c = nc.createVariable('constraints', 'c', ('dim1',))
3016 1 tkerber
                else:
3017 1 tkerber
                    c = nc.variables['constraints']
3018 1 tkerber
                #we store the pickle string as an attribute of a
3019 1 tkerber
                #netcdf variable because that way we do not have to
3020 1 tkerber
                #know how long the string is.  with a character
3021 1 tkerber
                #variable you have to specify the dimension of the
3022 1 tkerber
                #string ahead of time.
3023 1 tkerber
                c.data = pickle.dumps(constraints)
3024 1 tkerber
                nc.close()
3025 1 tkerber
            else:
3026 1 tkerber
                # getting here means there where no constraints on the
3027 1 tkerber
                # atoms just written we should check if there are any
3028 1 tkerber
                # old constraints left in the ncfile
3029 1 tkerber
                # from a previous atoms, and delete them if so
3030 1 tkerber
                delete_constraints = False
3031 1 tkerber
                nc = netCDF(self.get_nc())
3032 1 tkerber
                if 'constraints' in nc.variables:
3033 1 tkerber
                    delete_constraints = True
3034 1 tkerber
                nc.close()
3035 1 tkerber
3036 1 tkerber
                if delete_constraints:
3037 1 tkerber
                    log.debug('deleting old constraints')
3038 1 tkerber
                    self.delete_ncattdimvar(self.nc,
3039 1 tkerber
                                            ncvars=['constraints'])
3040 1 tkerber
3041 1 tkerber
    def read_atoms(filename):
3042 1 tkerber
        '''read atoms and calculator from an existing netcdf file.
3043 1 tkerber

3044 1 tkerber
        :Parameters:
3045 1 tkerber

3046 1 tkerber
          filename : string
3047 1 tkerber
            name of file to read from.
3048 1 tkerber

3049 1 tkerber
        static method
3050 1 tkerber

3051 1 tkerber
        example::
3052 1 tkerber

3053 1 tkerber
          >>> atoms = Jacapo.read_atoms(ncfile)
3054 1 tkerber
          >>> calc = atoms.get_calculator()
3055 1 tkerber

3056 1 tkerber
        this method is here for legacy purposes. I used to use it alot.
3057 1 tkerber
        '''
3058 1 tkerber
3059 1 tkerber
        calc = Jacapo(filename)
3060 1 tkerber
        atoms = calc.get_atoms()
3061 1 tkerber
        return atoms
3062 1 tkerber
3063 1 tkerber
    read_atoms = staticmethod(read_atoms)
3064 1 tkerber
3065 1 tkerber
    def read_only_atoms(self, ncfile):
3066 1 tkerber
        '''read only the atoms from an existing netcdf file. Used to
3067 1 tkerber
        initialize a calculator from a ncfilename.
3068 1 tkerber

3069 1 tkerber
        :Parameters:
3070 1 tkerber

3071 1 tkerber
          ncfile : string
3072 1 tkerber
            name of file to read from.
3073 1 tkerber

3074 1 tkerber
        return ASE.Atoms with no calculator attached or None if no
3075 1 tkerber
        atoms found
3076 1 tkerber
        '''
3077 1 tkerber
3078 1 tkerber
        from ase import Atoms
3079 1 tkerber
3080 1 tkerber
        nc = netCDF(ncfile, 'r')
3081 1 tkerber
        #some ncfiles do not have atoms in them
3082 1 tkerber
        if 'UnitCell' not in nc.variables:
3083 1 tkerber
            log.debug('no unit cell found in ncfile')
3084 1 tkerber
            nc.close()
3085 1 tkerber
            return None
3086 1 tkerber
3087 1 tkerber
        cell = nc.variables['UnitCell'][:][-1]
3088 1 tkerber
        sym = nc.variables['DynamicAtomSpecies'][:]
3089 1 tkerber
        symbols = [x.tostring().strip() for x in sym]
3090 1 tkerber
        spos = nc.variables['DynamicAtomPositions'][:][-1]
3091 1 tkerber
3092 1 tkerber
        pos = np.dot(spos, cell)
3093 1 tkerber
3094 1 tkerber
        atoms = Atoms(symbols=symbols,
3095 1 tkerber
                      positions=pos,
3096 1 tkerber
                      cell=cell)
3097 1 tkerber
3098 1 tkerber
        if 'AtomTags' in nc.variables:
3099 1 tkerber
            tags = nc.variables['AtomTags'][:]
3100 1 tkerber
            atoms.set_tags(tags)
3101 1 tkerber
3102 1 tkerber
        if 'InitialAtomicMagneticMoment' in nc.variables:
3103 1 tkerber
            mom = nc.variables['InitialAtomicMagneticMoment'][:]
3104 1 tkerber
            atoms.set_initial_magnetic_moments(mom)
3105 1 tkerber
3106 1 tkerber
        #update psp database
3107 1 tkerber
        for sym in symbols:
3108 1 tkerber
            vn = 'AtomProperty_%s' % sym
3109 1 tkerber
            if vn in nc.variables:
3110 1 tkerber
                var = nc.variables[vn]
3111 1 tkerber
                pspfile = var.PspotFile
3112 1 tkerber
                self.psp[sym] = pspfile
3113 1 tkerber
3114 1 tkerber
        #get constraints if they exist
3115 1 tkerber
        c = nc.variables.get('constraints', None)
3116 1 tkerber
        if c is not None:
3117 1 tkerber
            constraints = pickle.loads(c.data)
3118 1 tkerber
            atoms.set_constraint(constraints)
3119 1 tkerber
3120 1 tkerber
        nc.close()
3121 1 tkerber
3122 1 tkerber
        return atoms
3123 1 tkerber
3124 1 tkerber
    def delete_ncattdimvar(self, ncf, ncattrs=None, ncdims=None, ncvars=None):
3125 1 tkerber
        '''
3126 1 tkerber
        helper function to delete attributes,
3127 1 tkerber
        dimensions and variables in a netcdffile
3128 1 tkerber

3129 1 tkerber
        this functionality is not implemented for some reason in
3130 1 tkerber
        netcdf, so the only way to do this is to copy all the
3131 1 tkerber
        attributes, dimensions, and variables to a new file, excluding
3132 1 tkerber
        the ones you want to delete and then rename the new file.
3133 1 tkerber

3134 1 tkerber
        if you delete a dimension, all variables with that dimension
3135 1 tkerber
        are also deleted.
3136 1 tkerber
        '''
3137 1 tkerber
3138 1 tkerber
        if ncattrs is None:
3139 1 tkerber
            ncattrs = []
3140 1 tkerber
        if ncdims is None:
3141 1 tkerber
            ncdims = []
3142 1 tkerber
        if ncvars is None:
3143 1 tkerber
            ncvars = []
3144 1 tkerber
3145 1 tkerber
        log.debug('beginning: going to delete dims: %s' % str(ncdims))
3146 1 tkerber
        log.debug('beginning: going to delete vars: %s' % str(ncvars))
3147 1 tkerber
3148 1 tkerber
        oldnc = netCDF(ncf, 'r')
3149 1 tkerber
3150 1 tkerber
        #h,tempnc = tempfile.mkstemp(dir='.',suffix='.nc')
3151 1 tkerber
        tempnc = ncf+'.temp'
3152 1 tkerber
3153 1 tkerber
        newnc = netCDF(tempnc, 'w')
3154 1 tkerber
3155 1 tkerber
        for attr in dir(oldnc):
3156 1 tkerber
            if attr in ['close', 'createDimension',
3157 1 tkerber
                        'createVariable', 'flush', 'sync']:
3158 1 tkerber
                continue
3159 1 tkerber
            if attr in ncattrs:
3160 1 tkerber
                continue #do not copy this attribute
3161 1 tkerber
            setattr(newnc, attr, getattr(oldnc, attr))
3162 1 tkerber
3163 1 tkerber
        #copy dimensions
3164 1 tkerber
        for dim in oldnc.dimensions:
3165 1 tkerber
            if dim in ncdims:
3166 1 tkerber
                log.debug('deleting %s of %s' % (dim, str(ncdims)))
3167 1 tkerber
                continue #do not copy this dimension
3168 1 tkerber
            size = oldnc.dimensions[dim]
3169 1 tkerber
3170 1 tkerber
            newnc.createDimension(dim, size)
3171 1 tkerber
3172 1 tkerber
        # we need to delete all variables that depended on a deleted dimension
3173 1 tkerber
        for v in oldnc.variables:
3174 1 tkerber
            dims1 = oldnc.variables[v].dimensions
3175 1 tkerber
            for dim in ncdims:
3176 1 tkerber
                if dim in dims1:
3177 1 tkerber
                    s = 'deleting "%s" because it depends on dim "%s"'
3178 1 tkerber
                    log.debug(s %(v, dim))
3179 1 tkerber
                    ncvars.append(v)
3180 1 tkerber
3181 1 tkerber
        #copy variables, except the ones to delete
3182 1 tkerber
        for v in oldnc.variables:
3183 1 tkerber
            if v in ncvars:
3184 1 tkerber
                log.debug('vars to delete: %s ' % ncvars)
3185 1 tkerber
                log.debug('deleting ncvar: %s' % v)
3186 1 tkerber
                continue #we do not copy this v over
3187 1 tkerber
3188 1 tkerber
            ncvar = oldnc.variables[v]
3189 1 tkerber
            tcode = ncvar.typecode()
3190 1 tkerber
            #char typecodes do not come out right apparently
3191 1 tkerber
            if tcode == " ":
3192 1 tkerber
                tcode = 'c'
3193 1 tkerber
3194 1 tkerber
            ncvar2 = newnc.createVariable(v, tcode, ncvar.dimensions)
3195 1 tkerber
            try:
3196 1 tkerber
                ncvar2[:] = ncvar[:]
3197 1 tkerber
            except TypeError:
3198 1 tkerber
                #this exception occurs for scalar variables
3199 1 tkerber
                #use getValue and assignValue instead
3200 1 tkerber
                ncvar2.assignValue(ncvar.getValue())
3201 1 tkerber
3202 1 tkerber
            #and variable attributes
3203 1 tkerber
            #print dir(ncvar)
3204 1 tkerber
            for att in dir(ncvar):
3205 1 tkerber
                if att in ['assignValue', 'getValue', 'typecode']:
3206 1 tkerber
                    continue
3207 1 tkerber
                setattr(ncvar2, att, getattr(ncvar, att))
3208 1 tkerber
3209 1 tkerber
        oldnc.close()
3210 1 tkerber
        newnc.close()
3211 1 tkerber
3212 1 tkerber
        s = 'looking for .nfs files before copying: %s'
3213 1 tkerber
        log.debug(s % glob.glob('.nfs*'))
3214 1 tkerber
3215 1 tkerber
        #ack!!! this makes .nfsxxx files!!!
3216 1 tkerber
        #os.close(h) #this avoids the stupid .nfsxxx file
3217 1 tkerber
        #import shutil
3218 1 tkerber
        #shutil.move(tempnc,ncf)
3219 1 tkerber
3220 1 tkerber
        #this seems to avoid making the .nfs files
3221 1 tkerber
        os.system('cp %s %s' % (tempnc, ncf))
3222 1 tkerber
        os.system('rm %s' % tempnc)
3223 1 tkerber
3224 1 tkerber
        s = 'looking for .nfs files after copying: %s'
3225 1 tkerber
        log.debug(s %  glob.glob('.nfs*'))
3226 1 tkerber
3227 1 tkerber
    def restart(self):
3228 1 tkerber
        '''
3229 1 tkerber
        Restart the calculator by deleting nc dimensions that will
3230 1 tkerber
        be rewritten on the next calculation. This is sometimes required
3231 1 tkerber
        when certain dimensions change related to unitcell size changes
3232 1 tkerber
        planewave/densitywave cutoffs and kpt changes. These can cause
3233 1 tkerber
        fortran netcdf errors if the data does not match the pre-defined
3234 1 tkerber
        dimension sizes.
3235 1 tkerber

3236 1 tkerber
        also delete all the output from previous calculation.
3237 1 tkerber
        '''
3238 1 tkerber
3239 1 tkerber
        log.debug('restarting!')
3240 1 tkerber
3241 1 tkerber
        ncdims = ['number_plane_waves',
3242 1 tkerber
                  'number_IBZ_kpoints',
3243 1 tkerber
                  'softgrid_dim1',
3244 1 tkerber
                  'softgrid_dim2',
3245 1 tkerber
                  'softgrid_dim3',
3246 1 tkerber
                  'hardgrid_dim1',
3247 1 tkerber
                  'hardgrid_dim2',
3248 1 tkerber
                  'hardgrid_dim3',
3249 1 tkerber
                  'max_projectors_per_atom',
3250 1 tkerber
                  'atomdos_energygrid_size',
3251 1 tkerber
                  'atomdos_angular_channels',
3252 1 tkerber
                  'atomdos_radial_orbs']
3253 1 tkerber
3254 1 tkerber
        ncvars = ['TotalEnergy',
3255 1 tkerber
                  'TotalFreeEnergy',
3256 1 tkerber
                  'EvaluateTotalEnergy',
3257 1 tkerber
                  'DynamicAtomForces',
3258 1 tkerber
                  'FermiLevel',
3259 1 tkerber
                  'EnsembleXCEnergies',
3260 1 tkerber
                  'AtomProjectedDOS_IntegratedDOS',
3261 1 tkerber
                  'AtomProjectedDOS_OrdinalMap',
3262 1 tkerber
                  'NumberPlaneWavesKpoint',
3263 1 tkerber
                  'AtomProjectedDOS_EnergyResolvedDOS',
3264 1 tkerber
                  'AtomProjectedDOS_EnergyGrid',
3265 1 tkerber
                  'EvaluateCorrelationEnergy',
3266 1 tkerber
                  'DynamicAtomVelocities',
3267 1 tkerber
                  'KpointWeight',
3268 1 tkerber
                  'EvaluateExchangeEnergy',
3269 1 tkerber
                  'EffectivePotential',
3270 1 tkerber
                  'TotalStress',
3271 1 tkerber
                  'ChargeDensity',
3272 1 tkerber
                  'WaveFunction',
3273 1 tkerber
                  'WaveFunctionFFTindex',
3274 1 tkerber
                  'NumberOfNLProjectors',
3275 1 tkerber
                  'NLProjectorPsi',
3276 1 tkerber
                  'TypeNLProjector1',
3277 1 tkerber
                  'NumberofNLProjectors',
3278 1 tkerber
                  'PartialCoreDensity',
3279 1 tkerber
                  'ChargeDensity',
3280 1 tkerber
                  'ElectrostaticPotential',
3281 1 tkerber
                  'StructureFactor',
3282 1 tkerber
                  'EigenValues',
3283 1 tkerber
                  'OccupationNumbers']
3284 1 tkerber
3285 1 tkerber
        self.delete_ncattdimvar(self.nc,
3286 1 tkerber
                                ncattrs=[],
3287 1 tkerber
                                ncdims=ncdims,
3288 1 tkerber
                                ncvars=ncvars)
3289 1 tkerber
3290 1 tkerber
        self.set_status('new')
3291 1 tkerber
        self.ready = False
3292 1 tkerber
3293 1 tkerber
    def get_convergence(self):
3294 1 tkerber
        'return convergence settings for Dacapo'
3295 1 tkerber
3296 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3297 1 tkerber
        vname = 'ConvergenceControl'
3298 1 tkerber
        if vname in nc.variables:
3299 1 tkerber
            v = nc.variables[vname]
3300 1 tkerber
            convergence = {}
3301 1 tkerber
            if hasattr(v, 'AbsoluteEnergyConvergence'):
3302 1 tkerber
                convergence['energy'] = v.AbsoluteEnergyConvergence[0]
3303 1 tkerber
            if hasattr(v, 'DensityConvergence'):
3304 1 tkerber
                convergence['density'] = v.DensityConvergence[0]
3305 1 tkerber
            if hasattr(v, 'OccupationConvergence'):
3306 1 tkerber
                convergence['occupation'] = v.OccupationConvergence[0]
3307 1 tkerber
            if hasattr(v, 'MaxNumberOfSteps'):
3308 1 tkerber
                convergence['maxsteps'] = v.MaxNumberOfSteps[0]
3309 1 tkerber
            if hasattr(v, 'CPUTimeLimit'):
3310 1 tkerber
                convergence['cputime'] = v.CPUTimeLimit[0]
3311 1 tkerber
        else:
3312 1 tkerber
            convergence = None
3313 1 tkerber
3314 1 tkerber
        nc.close()
3315 1 tkerber
        return convergence
3316 1 tkerber
3317 1 tkerber
    def set_convergence(self,
3318 1 tkerber
                        energy=0.00001,
3319 1 tkerber
                        density=0.0001,
3320 1 tkerber
                        occupation=0.001,
3321 1 tkerber
                        maxsteps=None,
3322 1 tkerber
                        maxtime=None
3323 1 tkerber
                        ):
3324 1 tkerber
        '''set convergence criteria for stopping the dacapo calculator.
3325 1 tkerber

3326 1 tkerber
        :Parameters:
3327 1 tkerber

3328 1 tkerber
          energy : float
3329 1 tkerber
            set total energy change (eV) required for stopping
3330 1 tkerber

3331 1 tkerber
          density : float
3332 1 tkerber
            set density change required for stopping
3333 1 tkerber

3334 1 tkerber
          occupation : float
3335 1 tkerber
            set occupation change required for stopping
3336 1 tkerber

3337 1 tkerber
          maxsteps : integer
3338 1 tkerber
            specify maximum number of steps to take
3339 1 tkerber

3340 1 tkerber
          maxtime : integer
3341 1 tkerber
            specify maximum number of hours to run.
3342 1 tkerber

3343 1 tkerber
        Autopilot not supported here.
3344 1 tkerber
        '''
3345 1 tkerber
3346 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
3347 1 tkerber
        vname = 'ConvergenceControl'
3348 1 tkerber
        if vname in nc.variables:
3349 1 tkerber
            v = nc.variables[vname]
3350 1 tkerber
        else:
3351 1 tkerber
            v = nc.createVariable(vname, 'c', ('dim1',))
3352 1 tkerber
3353 1 tkerber
        if energy is not None:
3354 1 tkerber
            v.AbsoluteEnergyConvergence = energy
3355 1 tkerber
        if density is not None:
3356 1 tkerber
            v.DensityConvergence = density
3357 1 tkerber
        if occupation is not None:
3358 1 tkerber
            v.OccupationConvergence = occupation
3359 1 tkerber
        if maxsteps is not None:
3360 1 tkerber
            v.MaxNumberOfSteps = maxsteps
3361 1 tkerber
        if maxtime is not None:
3362 1 tkerber
            v.CPUTimeLimit = maxtime
3363 1 tkerber
3364 1 tkerber
        nc.sync()
3365 1 tkerber
        nc.close()
3366 1 tkerber
3367 1 tkerber
    def get_charge_mixing(self):
3368 1 tkerber
        'return charge mixing parameters'
3369 1 tkerber
3370 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3371 1 tkerber
        vname = 'ChargeMixing'
3372 1 tkerber
        if vname in nc.variables:
3373 1 tkerber
            v = nc.variables[vname]
3374 1 tkerber
            charge_mixing = {}
3375 1 tkerber
            if hasattr(v, 'Method'):
3376 1 tkerber
                charge_mixing['method'] = v.Method
3377 1 tkerber
            if hasattr(v, 'UpdateCharge'):
3378 1 tkerber
                charge_mixing['updatecharge'] = v.UpdateCharge
3379 1 tkerber
            if hasattr(v, 'Pulay_MixingHistory'):
3380 1 tkerber
                charge_mixing['mixinghistory'] = v.Pulay_MixingHistory[0]
3381 1 tkerber
            if hasattr(v, 'Pulay_DensityMixingCoeff'):
3382 1 tkerber
                charge_mixing['mixingcoeff'] = v.Pulay_DensityMixingCoeff[0]
3383 1 tkerber
            if hasattr(v, 'Pulay_KerkerPrecondition'):
3384 1 tkerber
                charge_mixing['precondition'] = v.Pulay_KerkerPrecondition
3385 1 tkerber
        else:
3386 1 tkerber
            charge_mixing = None
3387 1 tkerber
3388 1 tkerber
        nc.close()
3389 1 tkerber
        return charge_mixing
3390 1 tkerber
3391 1 tkerber
    def set_charge_mixing(self,
3392 1 tkerber
                          method='Pulay',
3393 1 tkerber
                          mixinghistory=10,
3394 1 tkerber
                          mixingcoeff=0.1,
3395 1 tkerber
                          precondition='No',
3396 1 tkerber
                          updatecharge='Yes'):
3397 1 tkerber
        '''set density mixing method and parameters
3398 1 tkerber

3399 1 tkerber
        :Parameters:
3400 1 tkerber

3401 1 tkerber
          method : string
3402 1 tkerber
            'Pulay' for Pulay mixing. only one supported now
3403 1 tkerber

3404 1 tkerber
          mixinghistory : integer
3405 1 tkerber
            number of iterations to mix
3406 1 tkerber
            Number of charge residual vectors stored for generating
3407 1 tkerber
            the Pulay estimate on the self-consistent charge density,
3408 1 tkerber
            see Sec. 4.2 in Kresse/Furthmuller:
3409 1 tkerber
            Comp. Mat. Sci. 6 (1996) p34ff
3410 1 tkerber

3411 1 tkerber
          mixingcoeff : float
3412 1 tkerber
            Mixing coefficient for Pulay charge mixing, corresponding
3413 1 tkerber
            to A in G$^1$ in Sec. 4.2 in Kresse/Furthmuller:
3414 1 tkerber
            Comp. Mat. Sci. 6 (1996) p34ff
3415 1 tkerber

3416 1 tkerber
          precondition : string
3417 1 tkerber
            'Yes' or 'No'
3418 1 tkerber

3419 1 tkerber
            * "Yes" : Kerker preconditiong is used,
3420 1 tkerber
               i.e. q$_0$ is different from zero, see eq. 82
3421 1 tkerber
               in Kresse/Furthmuller: Comp. Mat. Sci. 6 (1996).
3422 1 tkerber
               The value of q$_0$ is fix to give a damping of 20
3423 1 tkerber
               of the lowest q vector.
3424 1 tkerber

3425 1 tkerber
            * "No" : q$_0$ is zero and mixing is linear (default).
3426 1 tkerber

3427 1 tkerber
          updatecharge : string
3428 1 tkerber
            'Yes' or 'No'
3429 1 tkerber

3430 1 tkerber
            * "Yes" : Perform charge mixing according to
3431 1 tkerber
               ChargeMixing:Method setting
3432 1 tkerber

3433 1 tkerber
            * "No" : Freeze charge to initial value.
3434 1 tkerber
               This setting is useful when evaluating the Harris-Foulkes
3435 1 tkerber
               density functional
3436 1 tkerber

3437 1 tkerber
        '''
3438 1 tkerber
3439 1 tkerber
        if method == 'Pulay':
3440 1 tkerber
            nc = netCDF(self.get_nc(), 'a')
3441 1 tkerber
            vname = 'ChargeMixing'
3442 1 tkerber
            if vname in nc.variables:
3443 1 tkerber
                v = nc.variables[vname]
3444 1 tkerber
            else:
3445 1 tkerber
                v = nc.createVariable(vname, 'c', ('dim1',))
3446 1 tkerber
3447 1 tkerber
            v.Method = 'Pulay'
3448 1 tkerber
            v.UpdateCharge = updatecharge
3449 1 tkerber
            v.Pulay_MixingHistory = mixinghistory
3450 1 tkerber
            v.Pulay_DensityMixingCoeff = mixingcoeff
3451 1 tkerber
            v.Pulay_KerkerPrecondition = precondition
3452 1 tkerber
3453 1 tkerber
            nc.sync()
3454 1 tkerber
            nc.close()
3455 1 tkerber
3456 1 tkerber
        self.ready = False
3457 1 tkerber
3458 1 tkerber
    def set_electronic_minimization(self,
3459 1 tkerber
                                    method='eigsolve',
3460 1 tkerber
                                    diagsperband=2):
3461 1 tkerber
        '''set the eigensolver method
3462 1 tkerber

3463 1 tkerber
        Selector for which subroutine to use for electronic
3464 1 tkerber
        minimization
3465 1 tkerber

3466 1 tkerber
        Recognized options : "resmin", "eigsolve" and "rmm-diis".
3467 1 tkerber

3468 1 tkerber
        * "resmin" : Power method (Lennart Bengtson), can only handle
3469 1 tkerber
           k-point parallization.
3470 1 tkerber

3471 1 tkerber
        * "eigsolve : Block Davidson algorithm
3472 1 tkerber
           (Claus Bendtsen et al).
3473 1 tkerber

3474 1 tkerber
        * "rmm-diis : Residual minimization
3475 1 tkerber
           method (RMM), using DIIS (direct inversion in the iterate
3476 1 tkerber
           subspace) The implementaion follows closely the algorithm
3477 1 tkerber
           outlined in Kresse and Furthmuller, Comp. Mat. Sci, III.G/III.H
3478 1 tkerber

3479 1 tkerber
        :Parameters:
3480 1 tkerber

3481 1 tkerber
          method : string
3482 1 tkerber
            should be 'resmin', 'eigsolve' or 'rmm-diis'
3483 1 tkerber

3484 1 tkerber
          diagsperband : int
3485 1 tkerber
            The number of diagonalizations per band for
3486 1 tkerber
            electronic minimization algorithms (maps onto internal
3487 1 tkerber
            variable ndiapb). Applies for both
3488 1 tkerber
            ElectronicMinimization:Method = "resmin" and "eigsolve".
3489 1 tkerber
            default value = 2
3490 1 tkerber
        '''
3491 1 tkerber
3492 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
3493 1 tkerber
3494 1 tkerber
        vname = 'ElectronicMinimization'
3495 1 tkerber
        if vname in nc.variables:
3496 1 tkerber
            v = nc.variables[vname]
3497 1 tkerber
        else:
3498 1 tkerber
            log.debug('Creating ElectronicMinimization')
3499 1 tkerber
            v = nc.createVariable(vname, 'c', ('dim1',))
3500 1 tkerber
3501 1 tkerber
        log.debug('setting method for ElectronicMinimization: % s' % method)
3502 1 tkerber
        v.Method = method
3503 1 tkerber
        log.debug('setting DiagonalizationsBand for ElectronicMinimization')
3504 1 tkerber
        if diagsperband is not None:
3505 1 tkerber
            v.DiagonalizationsPerBand = diagsperband
3506 1 tkerber
3507 1 tkerber
        log.debug('synchronizing ncfile')
3508 1 tkerber
        nc.sync()
3509 1 tkerber
3510 1 tkerber
        nc.close()
3511 1 tkerber
3512 1 tkerber
    def get_electronic_minimization(self):
3513 1 tkerber
        '''get method and diagonalizations per band for electronic
3514 1 tkerber
        minimization algorithms'''
3515 1 tkerber
3516 1 tkerber
        log.debug('getting electronic minimization parameters')
3517 1 tkerber
3518 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
3519 1 tkerber
        vname = 'ElectronicMinimization'
3520 1 tkerber
        if vname in nc.variables:
3521 1 tkerber
            v = nc.variables[vname]
3522 1 tkerber
            method = v.Method
3523 1 tkerber
            if hasattr(v, 'DiagonalizationsPerBand'):
3524 1 tkerber
                diagsperband = v.DiagonalizationsPerBand[0]
3525 1 tkerber
            else:
3526 1 tkerber
                diagsperband = None
3527 1 tkerber
        else:
3528 1 tkerber
            method = None
3529 1 tkerber
            diagsperband = None
3530 1 tkerber
        nc.close()
3531 1 tkerber
        return {'method':method,
3532 1 tkerber
                'diagsperband':diagsperband}
3533 1 tkerber
3534 1 tkerber
    def get_occupationstatistics(self):
3535 1 tkerber
        'return occupation statistics method'
3536 1 tkerber
3537 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3538 1 tkerber
        if 'ElectronicBands' in nc.variables:
3539 1 tkerber
            v = nc.variables['ElectronicBands']
3540 1 tkerber
            if hasattr(v, 'OccupationStatistics'):
3541 1 tkerber
                occstat = v.OccupationStatistics
3542 1 tkerber
            else:
3543 1 tkerber
                occstat = None
3544 1 tkerber
        else:
3545 1 tkerber
            occstat = None
3546 1 tkerber
        nc.close()
3547 1 tkerber
        return occstat
3548 1 tkerber
3549 1 tkerber
    def set_occupationstatistics(self, method):
3550 1 tkerber
        '''
3551 1 tkerber
        set the method used for smearing the occupations.
3552 1 tkerber

3553 1 tkerber
        :Parameters:
3554 1 tkerber

3555 1 tkerber
          method : string
3556 1 tkerber
            one of 'FermiDirac' or 'MethfesselPaxton'
3557 1 tkerber
            Currently, the Methfessel-Paxton scheme (PRB 40, 3616 (1989).)
3558 1 tkerber
            is implemented to 1th order (which is recommemded by most authors).
3559 1 tkerber
            'FermiDirac' is the default
3560 1 tkerber
        '''
3561 1 tkerber
3562 1 tkerber
        nc = netCDF(self.get_nc(), 'a')
3563 1 tkerber
        if 'ElectronicBands' in nc.variables:
3564 1 tkerber
            v = nc.variables['ElectronicBands']
3565 1 tkerber
            v.OccupationStatistics = method
3566 1 tkerber
3567 1 tkerber
        nc.sync()
3568 1 tkerber
        nc.close()
3569 1 tkerber
3570 1 tkerber
    def get_fermi_level(self):
3571 1 tkerber
        'return Fermi level'
3572 1 tkerber
3573 1 tkerber
        if self.calculation_required():
3574 1 tkerber
            self.calculate()
3575 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3576 1 tkerber
        ef = nc.variables['FermiLevel'][-1]
3577 1 tkerber
        nc.close()
3578 1 tkerber
        return ef
3579 1 tkerber
3580 1 tkerber
    def get_occupation_numbers(self, kpt=0, spin=0):
3581 1 tkerber
        '''return occupancies of eigenstates for a kpt and spin
3582 1 tkerber

3583 1 tkerber
        :Parameters:
3584 1 tkerber

3585 1 tkerber
          kpt : integer
3586 1 tkerber
            index of the IBZ kpoint you want the occupation of
3587 1 tkerber

3588 1 tkerber
          spin : integer
3589 1 tkerber
            0 or 1
3590 1 tkerber
        '''
3591 1 tkerber
3592 1 tkerber
        if self.calculation_required():
3593 1 tkerber
            self.calculate()
3594 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3595 1 tkerber
        occ = nc.variables['OccupationNumbers'][:][-1][kpt, spin]
3596 1 tkerber
        nc.close()
3597 1 tkerber
        return occ
3598 1 tkerber
3599 1 tkerber
    def get_xc_energies(self, *functional):
3600 1 tkerber
        """
3601 1 tkerber
        Get energies for different functionals self-consistent and
3602 1 tkerber
        non-self-consistent.
3603 1 tkerber

3604 1 tkerber
        :Parameters:
3605 1 tkerber

3606 1 tkerber
          functional : strings
3607 1 tkerber
            some set of 'PZ','VWN','PW91','PBE','revPBE', 'RPBE'
3608 1 tkerber

3609 1 tkerber
        This function returns the self-consistent energy and/or
3610 1 tkerber
        energies associated with various functionals.
3611 1 tkerber
        The functionals are currently PZ,VWN,PW91,PBE,revPBE, RPBE.
3612 1 tkerber
        The different energies may be useful for calculating improved
3613 1 tkerber
        adsorption energies as in B. Hammer, L.B. Hansen and
3614 1 tkerber
        J.K. Norskov, Phys. Rev. B 59,7413.
3615 1 tkerber
        Examples:
3616 1 tkerber
        get_xcenergies() #returns all the energies
3617 1 tkerber
        get_xcenergies('PBE') # returns the PBE total energy
3618 1 tkerber
        get_xcenergies('PW91','PBE','revPBE') # returns a
3619 1 tkerber
        # list of energies in the order asked for
3620 1 tkerber
        """
3621 1 tkerber
3622 1 tkerber
        if self.calculation_required():
3623 1 tkerber
            self.calculate()
3624 1 tkerber
3625 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3626 1 tkerber
3627 1 tkerber
        funcenergies = nc.variables['EvaluateTotalEnergy'][:][-1]
3628 1 tkerber
        xcfuncs = nc.variables['EvalFunctionalOfDensity_XC'][:]
3629 1 tkerber
3630 1 tkerber
        nc.close()
3631 1 tkerber
3632 1 tkerber
        xcfuncs = [xc.tostring().strip() for xc in xcfuncs]
3633 1 tkerber
        edict = dict(zip(xcfuncs, funcenergies))
3634 1 tkerber
3635 1 tkerber
        if len(functional) == 0:
3636 1 tkerber
            #get all energies by default
3637 1 tkerber
            functional = xcfuncs
3638 1 tkerber
3639 1 tkerber
        return [edict[xc] for xc in functional]
3640 1 tkerber
3641 1 tkerber
    # break of compatibility
3642 1 tkerber
    def get_ados_data(self,
3643 1 tkerber
                      atoms,
3644 1 tkerber
                      orbitals,
3645 1 tkerber
                      cutoff,
3646 1 tkerber
                      spin):
3647 1 tkerber
        '''get atom projected data
3648 1 tkerber

3649 1 tkerber
        :Parameters:
3650 1 tkerber

3651 1 tkerber
          atoms
3652 1 tkerber
              list of atom indices (integers)
3653 1 tkerber

3654 1 tkerber
          orbitals
3655 1 tkerber
              list of strings
3656 1 tkerber
              ['s','p','d'],
3657 1 tkerber
              ['px','py','pz']
3658 1 tkerber
              ['d_zz', 'dxx-yy', 'd_xy', 'd_xz', 'd_yz']
3659 1 tkerber

3660 1 tkerber
          cutoff : string
3661 1 tkerber
            cutoff radius you want the results for 'short' or 'infinite'
3662 1 tkerber

3663 1 tkerber
          spin
3664 1 tkerber
            : list of integers
3665 1 tkerber
            spin you want the results for
3666 1 tkerber
            [0] or [1] or [0,1] for both
3667 1 tkerber

3668 1 tkerber
        returns (egrid, ados)
3669 1 tkerber
        egrid has the fermi level at 0 eV
3670 1 tkerber
        '''
3671 1 tkerber
3672 1 tkerber
        if self.calculation_required():
3673 1 tkerber
            self.calculate()
3674 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3675 1 tkerber
        omapvar = nc.variables['AtomProjectedDOS_OrdinalMap']
3676 1 tkerber
        omap = omapvar[:] #indices
3677 1 tkerber
        c = omapvar.AngularChannels
3678 1 tkerber
        channels = [x.strip() for x in c.split(',')] #channel names
3679 1 tkerber
        #this has dimensions(nprojections, nspins, npoints)
3680 1 tkerber
        ados = nc.variables['AtomProjectedDOS_EnergyResolvedDOS'][:]
3681 1 tkerber
        #this is the energy grid for all the atoms
3682 1 tkerber
        egrid = nc.variables['AtomProjectedDOS_EnergyGrid'][:]
3683 1 tkerber
        nc.close()
3684 1 tkerber
3685 1 tkerber
        #it is apparently not necessary to normalize the egrid to
3686 1 tkerber
        #the Fermi level. the data is already for ef = 0.
3687 1 tkerber
3688 1 tkerber
        #get list of orbitals, replace 'p' and 'd' in needed
3689 1 tkerber
        orbs = []
3690 1 tkerber
        for o in orbitals:
3691 1 tkerber
            if o == 'p':
3692 1 tkerber
                orbs += ['p_x', 'p_y', 'p_z']
3693 1 tkerber
            elif o == 'd':
3694 1 tkerber
                orbs += ['d_zz', 'dxx-yy', 'd_xy', 'd_xz', 'd_yz']
3695 1 tkerber
            else:
3696 1 tkerber
                orbs += [o]
3697 1 tkerber
3698 1 tkerber
        orbinds = [channels.index(x) for x in orbs]
3699 1 tkerber
3700 1 tkerber
        cutdict = {'infinite':0,
3701 1 tkerber
                   'short':1}
3702 1 tkerber
3703 1 tkerber
        icut = cutdict[cutoff]
3704 1 tkerber
3705 1 tkerber
        ydata = np.zeros(len(egrid), np.float)
3706 1 tkerber
3707 1 tkerber
        for atomind in atoms:
3708 1 tkerber
            for oi in orbinds:
3709 1 tkerber
                ind = omap[atomind, icut, oi]
3710 1 tkerber
3711 1 tkerber
                for si in spin:
3712 1 tkerber
                    ydata += ados[ind, si]
3713 1 tkerber
3714 1 tkerber
        return (egrid, ydata)
3715 1 tkerber
3716 1 tkerber
    def get_all_eigenvalues(self, spin=0):
3717 1 tkerber
        '''return all the eigenvalues at all the kpoints for a spin.
3718 1 tkerber

3719 1 tkerber
        :Parameters:
3720 1 tkerber

3721 1 tkerber
          spin : integer
3722 1 tkerber
            which spin the eigenvalues are for'''
3723 1 tkerber
3724 1 tkerber
        if self.calculation_required():
3725 1 tkerber
            self.calculate()
3726 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3727 1 tkerber
        ev = nc.variables['EigenValues'][:][-1][:, spin]
3728 1 tkerber
        nc.close()
3729 1 tkerber
        return ev
3730 1 tkerber
3731 1 tkerber
    def get_eigenvalues(self, kpt=0, spin=0):
3732 1 tkerber
        '''return the eigenvalues for a kpt and spin
3733 1 tkerber

3734 1 tkerber
        :Parameters:
3735 1 tkerber

3736 1 tkerber
          kpt : integer
3737 1 tkerber
            index of the IBZ kpoint
3738 1 tkerber

3739 1 tkerber
          spin : integer
3740 1 tkerber
            which spin the eigenvalues are for'''
3741 1 tkerber
3742 1 tkerber
        if self.calculation_required():
3743 1 tkerber
            self.calculate()
3744 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3745 1 tkerber
        ev = nc.variables['EigenValues'][:][-1][kpt, spin]
3746 1 tkerber
        nc.close()
3747 1 tkerber
        return ev
3748 1 tkerber
3749 1 tkerber
    def get_k_point_weights(self):
3750 1 tkerber
        'return the weights on the IBZ kpoints'
3751 1 tkerber
3752 1 tkerber
        if self.calculation_required():
3753 1 tkerber
            self.calculate()
3754 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3755 1 tkerber
        kw = nc.variables['KpointWeight'][:]
3756 1 tkerber
        nc.close()
3757 1 tkerber
        return kw
3758 1 tkerber
3759 1 tkerber
    def get_magnetic_moment(self):
3760 1 tkerber
        'calculates the magnetic moment (Bohr-magnetons) of the supercell'
3761 1 tkerber
3762 1 tkerber
        if not self.get_spin_polarized():
3763 1 tkerber
            return None
3764 1 tkerber
3765 1 tkerber
        if self.calculation_required():
3766 1 tkerber
            self.calculate()
3767 1 tkerber
3768 1 tkerber
        nibzk = len(self.get_ibz_kpoints())
3769 1 tkerber
        ibzkw = self.get_k_point_weights()
3770 1 tkerber
        spinup, spindn = 0.0, 0.0
3771 1 tkerber
3772 1 tkerber
        for k in range(nibzk):
3773 1 tkerber
3774 1 tkerber
            spinup += self.get_occupation_numbers(k, 0).sum()*ibzkw[k]
3775 1 tkerber
            spindn += self.get_occupation_numbers(k, 1).sum()*ibzkw[k]
3776 1 tkerber
3777 1 tkerber
        return (spinup - spindn)
3778 1 tkerber
3779 1 tkerber
    def get_number_of_spins(self):
3780 1 tkerber
        'if spin-polarized returns 2, if not returns 1'
3781 1 tkerber
3782 1 tkerber
        if self.calculation_required():
3783 1 tkerber
            self.calculate()
3784 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3785 1 tkerber
        spv = nc.variables['ElectronicBands']
3786 1 tkerber
        nc.close()
3787 1 tkerber
3788 1 tkerber
        if hasattr(spv, 'SpinPolarization'):
3789 1 tkerber
            return spv.SpinPolarization
3790 1 tkerber
        else:
3791 1 tkerber
            return 1
3792 1 tkerber
3793 1 tkerber
    def get_ibz_kpoints(self):
3794 1 tkerber
        'return list of kpoints in the irreducible brillouin zone'
3795 1 tkerber
3796 1 tkerber
        if self.calculation_required():
3797 1 tkerber
            self.calculate()
3798 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3799 1 tkerber
        ibz = nc.variables['IBZKpoints'][:]
3800 1 tkerber
        nc.close()
3801 1 tkerber
        return ibz
3802 1 tkerber
3803 1 tkerber
    get_ibz_k_points = get_ibz_kpoints
3804 1 tkerber
3805 1 tkerber
    def get_bz_k_points(self):
3806 1 tkerber
        'return list of kpoints in the Brillouin zone'
3807 1 tkerber
3808 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3809 1 tkerber
        if 'BZKpoints' in nc.variables:
3810 1 tkerber
            bz = nc.variables['BZKpoints'][:]
3811 1 tkerber
        else:
3812 1 tkerber
            bz = None
3813 1 tkerber
        nc.close()
3814 1 tkerber
        return bz
3815 1 tkerber
3816 1 tkerber
    def get_effective_potential(self, spin=1):
3817 1 tkerber
        '''
3818 1 tkerber
        returns the realspace local effective potential for the spin.
3819 1 tkerber
        the units of the potential are eV
3820 1 tkerber

3821 1 tkerber
        :Parameters:
3822 1 tkerber

3823 1 tkerber
          spin : integer
3824 1 tkerber
             specify which spin you want, 0 or 1
3825 1 tkerber

3826 1 tkerber
        '''
3827 1 tkerber
3828 1 tkerber
        if self.calculation_required():
3829 1 tkerber
            self.calculate()
3830 1 tkerber
3831 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3832 1 tkerber
        efp = np.transpose(nc.variables['EffectivePotential'][:][spin])
3833 1 tkerber
        nc.close()
3834 1 tkerber
        fftgrids = self.get_fftgrid()
3835 1 tkerber
        hardgrid = fftgrids['hard']
3836 1 tkerber
        x, y, z = self.get_ucgrid(hardgrid)
3837 1 tkerber
        return (x, y, z, efp)
3838 1 tkerber
3839 1 tkerber
    def get_electrostatic_potential(self, spin=0):
3840 1 tkerber
        '''get electrostatic potential
3841 1 tkerber

3842 1 tkerber
        Netcdf documentation::
3843 1 tkerber

3844 1 tkerber
          double ElectrostaticPotential(number_of_spin,
3845 1 tkerber
                                        hardgrid_dim3,
3846 1 tkerber
                                        hardgrid_dim2,
3847 1 tkerber
                                        hardgrid_dim1) ;
3848 1 tkerber
                 ElectrostaticPotential:
3849 1 tkerber
                     Description = "realspace local effective potential" ;
3850 1 tkerber
                     unit = "eV" ;
3851 1 tkerber

3852 1 tkerber
        '''
3853 1 tkerber
3854 1 tkerber
        if self.calculation_required():
3855 1 tkerber
            self.calculate()
3856 1 tkerber
3857 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3858 1 tkerber
        esp = np.transpose(nc.variables['ElectrostaticPotential'][:][spin])
3859 1 tkerber
        nc.close()
3860 1 tkerber
        fftgrids = self.get_fftgrid()
3861 1 tkerber
3862 1 tkerber
        x, y, z = self.get_ucgrid(fftgrids['hard'])
3863 1 tkerber
3864 1 tkerber
        return (x, y, z, esp)
3865 1 tkerber
3866 1 tkerber
    def get_charge_density(self, spin=0):
3867 1 tkerber
        '''
3868 1 tkerber
        return x,y,z,charge density data
3869 1 tkerber

3870 1 tkerber
        x,y,z are grids sampling the unit cell
3871 1 tkerber
        cd is the charge density data
3872 1 tkerber

3873 1 tkerber
        netcdf documentation::
3874 1 tkerber

3875 1 tkerber
          ChargeDensity(number_of_spin,
3876 1 tkerber
                        hardgrid_dim3,
3877 1 tkerber
                        hardgrid_dim2,
3878 1 tkerber
                        hardgrid_dim1)
3879 1 tkerber
          ChargeDensity:Description = "realspace charge density" ;
3880 1 tkerber
                  ChargeDensity:unit = "-e/A^3" ;
3881 1 tkerber

3882 1 tkerber
        '''
3883 1 tkerber
3884 1 tkerber
        if self.calculation_required():
3885 1 tkerber
            self.calculate()
3886 1 tkerber
3887 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
3888 1 tkerber
3889 1 tkerber
        cd = np.transpose(nc.variables['ChargeDensity'][:][spin])
3890 1 tkerber
3891 1 tkerber
        #I am not completely sure why this has to be done
3892 1 tkerber
        #it does give units of electrons/ang**3
3893 1 tkerber
        vol = self.get_atoms().get_volume()
3894 1 tkerber
        cd /= vol
3895 1 tkerber
        nc.close()
3896 1 tkerber
        grids = self.get_fftgrid()
3897 1 tkerber
3898 1 tkerber
        x, y, z = self.get_ucgrid(grids['hard'])
3899 1 tkerber
        return x, y, z, cd
3900 1 tkerber
3901 1 tkerber
    def get_ucgrid(self, dims):
3902 1 tkerber
        '''Return X,Y,Z grids for uniform sampling of the unit cell
3903 1 tkerber

3904 1 tkerber
        dims = (n0,n1,n2)
3905 1 tkerber

3906 1 tkerber
        n0 points along unitcell vector 0
3907 1 tkerber
        n1 points along unitcell vector 1
3908 1 tkerber
        n2 points along unitcell vector 2
3909 1 tkerber
        '''
3910 1 tkerber
3911 1 tkerber
        n0, n1, n2 = dims
3912 1 tkerber
3913 1 tkerber
        s0 = 1.0/n0
3914 1 tkerber
        s1 = 1.0/n1
3915 1 tkerber
        s2 = 1.0/n2
3916 1 tkerber
3917 1 tkerber
        X, Y, Z = np.mgrid[0.0:1.0:s0,
3918 1 tkerber
                          0.0:1.0:s1,
3919 1 tkerber
                          0.0:1.0:s2]
3920 1 tkerber
3921 1 tkerber
        C = np.column_stack([X.ravel(),
3922 1 tkerber
                             Y.ravel(),
3923 1 tkerber
                             Z.ravel()])
3924 1 tkerber
3925 1 tkerber
        atoms = self.get_atoms()
3926 1 tkerber
        uc = atoms.get_cell()
3927 1 tkerber
        real = np.dot(C, uc)
3928 1 tkerber
3929 1 tkerber
        #now convert arrays back to unitcell shape
3930 1 tkerber
        RX = np.reshape(real[:, 0], (n0, n1, n2))
3931 1 tkerber
        RY = np.reshape(real[:, 1], (n0, n1, n2))
3932 1 tkerber
        RZ = np.reshape(real[:, 2], (n0, n1, n2))
3933 1 tkerber
        return (RX, RY, RZ)
3934 1 tkerber
3935 1 tkerber
    def get_number_of_grid_points(self):
3936 1 tkerber
        'return soft fft grid'
3937 1 tkerber
3938 1 tkerber
        # needed by ase.dft.wannier
3939 1 tkerber
        fftgrids = self.get_fftgrid()
3940 1 tkerber
        return np.array(fftgrids['soft'])
3941 1 tkerber
3942 1 tkerber
    def get_wannier_localization_matrix(self, nbands, dirG, kpoint,
3943 1 tkerber
                                        nextkpoint, G_I, spin):
3944 1 tkerber
        'return wannier localization  matrix'
3945 1 tkerber
3946 1 tkerber
        if self.calculation_required():
3947 1 tkerber
            self.calculate()
3948 1 tkerber
3949 1 tkerber
        if not hasattr(self, 'wannier'):
3950 1 tkerber
            from utils.wannier import Wannier
3951 1 tkerber
            self.wannier = Wannier(self)
3952 1 tkerber
            self.wannier.set_bands(nbands)
3953 1 tkerber
            self.wannier.set_spin(spin)
3954 1 tkerber
        locmat = self.wannier.get_zi_bloch_matrix(dirG,
3955 1 tkerber
                                                  kpoint,
3956 1 tkerber
                                                  nextkpoint,
3957 1 tkerber
                                                  G_I)
3958 1 tkerber
        return locmat
3959 1 tkerber
3960 1 tkerber
    def initial_wannier(self,
3961 1 tkerber
                        initialwannier,
3962 1 tkerber
                        kpointgrid,
3963 1 tkerber
                        fixedstates,
3964 1 tkerber
                        edf,
3965 1 tkerber
                        spin):
3966 1 tkerber
        'return initial wannier'
3967 1 tkerber
3968 1 tkerber
        if self.calculation_required():
3969 1 tkerber
            self.calculate()
3970 1 tkerber
3971 1 tkerber
        if not hasattr(self, 'wannier'):
3972 1 tkerber
            from utils.wannier import Wannier
3973 1 tkerber
            self.wannier = Wannier(self)
3974 1 tkerber
3975 1 tkerber
        self.wannier.set_data(initialwannier)
3976 1 tkerber
        self.wannier.set_k_point_grid(kpointgrid)
3977 1 tkerber
        self.wannier.set_spin(spin)
3978 1 tkerber
3979 1 tkerber
        waves = [[self.get_reciprocal_bloch_function(band=band,
3980 1 tkerber
                                                     kpt=kpt,
3981 1 tkerber
                                                     spin=spin)
3982 1 tkerber
                  for band in range(self.get_nbands())]
3983 1 tkerber
                  for kpt in range(len(self.get_ibz_k_points()))]
3984 1 tkerber
3985 1 tkerber
        self.wannier.setup_m_matrix(waves, self.get_bz_k_points())
3986 1 tkerber
3987 1 tkerber
        #lfn is too keep line length below 78 characters
3988 1 tkerber
        lfn = self.wannier.get_list_of_coefficients_and_rotation_matrices
3989 1 tkerber
        c, U = lfn((self.get_nbands(), fixedstates, edf))
3990 1 tkerber
3991 1 tkerber
        U = np.array(U)
3992 1 tkerber
        for k in range(len(c)):
3993 1 tkerber
            c[k] = np.array(c[k])
3994 1 tkerber
        return c, U
3995 1 tkerber
3996 1 tkerber
    def get_dipole_moment(self,atoms=None):
3997 1 tkerber
        '''
3998 1 tkerber
        return dipole moment of unit cell
3999 1 tkerber

4000 1 tkerber
        Defined by the vector connecting the center of electron charge
4001 1 tkerber
        density to the center of nuclear charge density.
4002 1 tkerber

4003 1 tkerber
        Units = eV*angstrom
4004 1 tkerber

4005 1 tkerber
        1 Debye = 0.208194 eV*angstrom
4006 1 tkerber

4007 1 tkerber
        '''
4008 1 tkerber
        if self.calculation_required():
4009 1 tkerber
            self.calculate()
4010 1 tkerber
4011 1 tkerber
        if atoms is None:
4012 1 tkerber
            atoms = self.get_atoms()
4013 1 tkerber
4014 1 tkerber
        #center of electron charge density
4015 1 tkerber
        x, y, z, cd = self.get_charge_density()
4016 1 tkerber
4017 1 tkerber
        n1, n2, n3 = cd.shape
4018 1 tkerber
        nelements = n1*n2*n3
4019 1 tkerber
        voxel_volume = atoms.get_volume()/nelements
4020 1 tkerber
        total_electron_charge = -cd.sum()*voxel_volume
4021 1 tkerber
4022 1 tkerber
4023 1 tkerber
        electron_density_center = np.array([(cd*x).sum(),
4024 1 tkerber
                                            (cd*y).sum(),
4025 1 tkerber
                                            (cd*z).sum()])
4026 1 tkerber
        electron_density_center *= voxel_volume
4027 1 tkerber
        electron_density_center /= total_electron_charge
4028 1 tkerber
4029 1 tkerber
        electron_dipole_moment = electron_density_center*total_electron_charge
4030 1 tkerber
        electron_dipole_moment *= -1.0 #we need the - here so the two
4031 1 tkerber
                                        #negatives don't cancel
4032 1 tkerber
        # now the ion charge center
4033 1 tkerber
        psps = self.get_pseudopotentials()
4034 1 tkerber
        ion_charge_center = np.array([0.0, 0.0, 0.0])
4035 1 tkerber
        total_ion_charge = 0.0
4036 1 tkerber
        for atom in atoms:
4037 1 tkerber
            Z = self.get_psp_nuclear_charge(psps[atom.symbol])
4038 1 tkerber
            total_ion_charge += Z
4039 1 tkerber
            pos = atom.get_position()
4040 1 tkerber
            ion_charge_center += Z*pos
4041 1 tkerber
4042 1 tkerber
        ion_charge_center /= total_ion_charge
4043 1 tkerber
        ion_dipole_moment = ion_charge_center*total_ion_charge
4044 1 tkerber
4045 1 tkerber
        dipole_vector = (ion_dipole_moment + electron_dipole_moment)
4046 1 tkerber
        return dipole_vector
4047 1 tkerber
4048 1 tkerber
4049 1 tkerber
    def get_reciprocal_bloch_function(self, band=0, kpt=0, spin=0):
4050 1 tkerber
        '''return the reciprocal bloch function. Need for Jacapo
4051 1 tkerber
        Wannier class.'''
4052 1 tkerber
4053 1 tkerber
        if self.calculation_required():
4054 1 tkerber
            self.calculate()
4055 1 tkerber
4056 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
4057 1 tkerber
4058 1 tkerber
        # read reciprocal bloch function
4059 1 tkerber
        npw = nc.variables['NumberPlaneWavesKpoint'][:]
4060 1 tkerber
        bf = nc.variables['WaveFunction'][kpt, spin, band]
4061 1 tkerber
        wflist = np.zeros(npw[kpt], np.complex)
4062 1 tkerber
        wflist.real = bf[0:npw[kpt], 1]
4063 1 tkerber
        wflist.imag = bf[0:npw[kpt], 0]
4064 1 tkerber
4065 1 tkerber
        nc.close()
4066 1 tkerber
4067 1 tkerber
        return wflist
4068 1 tkerber
4069 1 tkerber
    def get_reciprocal_fft_index(self, kpt=0):
4070 1 tkerber
        '''return the Wave Function FFT Index'''
4071 1 tkerber
4072 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
4073 1 tkerber
        recind = nc.variables['WaveFunctionFFTindex'][kpt, :, :]
4074 1 tkerber
        nc.close()
4075 1 tkerber
        return recind
4076 1 tkerber
4077 1 tkerber
    def get_ensemble_coefficients(self):
4078 1 tkerber
        'returns exchange correlation ensemble coefficients'
4079 1 tkerber
4080 1 tkerber
        # adapted from ASE/dacapo.py
4081 1 tkerber
        # def GetEnsembleCoefficients(self):
4082 1 tkerber
        #     self.Calculate()
4083 1 tkerber
        #     E = self.GetPotentialEnergy()
4084 1 tkerber
        #     xc = self.GetNetCDFEntry('EnsembleXCEnergies')
4085 1 tkerber
        #     Exc = xc[0]
4086 1 tkerber
        #     exc_c = self.GetNetCDFEntry('EvaluateCorrelationEnergy')
4087 1 tkerber
        #     exc_e =  self.GetNetCDFEntry('EvaluateExchangeEnergy')
4088 1 tkerber
        #     exc = exc_c + exc_e
4089 1 tkerber
        #     if self.GetXCFunctional() == 'RPBE':
4090 1 tkerber
        #             Exc = exc[-1][-1]
4091 1 tkerber
        #
4092 1 tkerber
        #     E0 = xc[1]       # Fx = 0
4093 1 tkerber
        #
4094 1 tkerber
        #     diff0 = xc[2] # - Exc
4095 1 tkerber
        #     diff1 = xc[3] # - Exc
4096 1 tkerber
        #     diff2 = xc[4] # - Exc
4097 1 tkerber
        #     coefs = (E + E0 - Exc,diff0-E0 ,diff1-E0,diff2-E0)
4098 1 tkerber
        #     print 'ensemble: (%.9f, %.9f, %.9f, %.9f)'% coefs
4099 1 tkerber
        #     return num.array(coefs)
4100 1 tkerber
        if self.calculation_required():
4101 1 tkerber
            self.calculate()
4102 1 tkerber
4103 1 tkerber
        E = self.get_potential_energy()
4104 1 tkerber
        nc = netCDF(self.get_nc(), 'r')
4105 1 tkerber
        if 'EnsembleXCEnergies' in nc.variables:
4106 1 tkerber
            v = nc.variables['EnsembleXCEnergies']
4107 1 tkerber
            xc = v[:]
4108 1 tkerber
4109 1 tkerber
        EXC = xc[0]
4110 1 tkerber
4111 1 tkerber
        if 'EvaluateCorrelationEnergy' in nc.variables:
4112 1 tkerber
            v = nc.variables['EvaluateCorrelationEnergy']
4113 1 tkerber
            exc_c = v[:]
4114 1 tkerber
4115 1 tkerber
        if 'EvaluateExchangeEnergy' in nc.variables:
4116 1 tkerber
            v = nc.variables['EvaluateExchangeEnergy']
4117 1 tkerber
            exc_e = v[:]
4118 1 tkerber
4119 1 tkerber
        exc = exc_c + exc_e
4120 1 tkerber
4121 1 tkerber
        if self.get_xc == 'RPBE':
4122 1 tkerber
            EXC = exc[-1][-1]
4123 1 tkerber
4124 1 tkerber
        E0 = xc[1]    # Fx = 0
4125 1 tkerber
4126 1 tkerber
        diff0 = xc[2] # - Exc
4127 1 tkerber
        diff1 = xc[3] # - Exc
4128 1 tkerber
        diff2 = xc[4] # - Exc
4129 1 tkerber
        coefs = (E + E0 - EXC, diff0-E0, diff1-E0, diff2-E0)
4130 1 tkerber
        log.info('ensemble: (%.9f, %.9f, %.9f, %.9f)'% coefs)
4131 1 tkerber
        return np.array(coefs)
4132 1 tkerber
4133 1 tkerber
    def get_pseudo_wave_function(self, band=0, kpt=0, spin=0, pad=True):
4134 1 tkerber
4135 1 tkerber
        '''return the pseudo wavefunction'''
4136 1 tkerber
4137 1 tkerber
        # pad=True does nothing here.
4138 1 tkerber
        if self.calculation_required():
4139 1 tkerber
            self.calculate()
4140 1 tkerber
4141 1 tkerber
        ibz = self.get_ibz_kpoints()
4142 1 tkerber
4143 1 tkerber
        #get the reciprocal bloch function
4144 1 tkerber
        wflist = self.get_reciprocal_bloch_function(band=band,
4145 1 tkerber
                                                    kpt=kpt,
4146 1 tkerber
                                                    spin=spin)
4147 1 tkerber
        # wflist == Reciprocal Bloch Function
4148 1 tkerber
4149 1 tkerber
        recind = self. get_reciprocal_fft_index(kpt)
4150 1 tkerber
        grids = self.get_fftgrid()
4151 1 tkerber
        softgrid = grids['soft']
4152 1 tkerber
4153 1 tkerber
        # GetReciprocalBlochFunctionGrid
4154 1 tkerber
        wfrec = np.zeros((softgrid), np.complex)
4155 1 tkerber
4156 1 tkerber
        for i in xrange(len(wflist)):
4157 1 tkerber
            wfrec[recind[0, i]-1,
4158 1 tkerber
                  recind[1, i]-1,
4159 1 tkerber
                  recind[2, i]-1] = wflist[i]
4160 1 tkerber
4161 1 tkerber
        # calculate Bloch Function
4162 1 tkerber
        wf = wfrec.copy()
4163 1 tkerber
        dim = wf.shape
4164 1 tkerber
        for i in range(len(dim)):
4165 1 tkerber
            wf = np.fft.fft(wf, dim[i], axis=i)
4166 1 tkerber
4167 1 tkerber
        #now the phase function to get the bloch phase
4168 1 tkerber
        basis = self.get_atoms().get_cell()
4169 1 tkerber
        kpoint = np.dot(ibz[kpt], basis) #coordinates of relevant
4170 1 tkerber
                                         #kpoint in cartesian
4171 1 tkerber
                                         #coordinates
4172 1 tkerber
        def phasefunction(coor):
4173 1 tkerber
            'return phasefunction'
4174 1 tkerber
            pf = np.exp(1.0j*np.dot(kpoint, coor))
4175 1 tkerber
            return pf
4176 1 tkerber
4177 1 tkerber
        # Calculating the Bloch phase at the origin (0,0,0) of the grid
4178 1 tkerber
        origin = np.array([0., 0., 0.])
4179 1 tkerber
        blochphase = phasefunction(origin)
4180 1 tkerber
        spatialshape = wf.shape[-len(basis):]
4181 1 tkerber
        gridunitvectors = np.array(map(lambda unitvector,
4182 1 tkerber
                                       shape:unitvector/shape,
4183 1 tkerber
                                       basis,
4184 1 tkerber
                                       spatialshape))
4185 1 tkerber
4186 1 tkerber
        for dim in range(len(spatialshape)):
4187 1 tkerber
            # Multiplying with the phase at the origin
4188 1 tkerber
            deltaphase = phasefunction(gridunitvectors[dim])
4189 1 tkerber
            # and calculating phase difference between each point
4190 1 tkerber
            newphase = np.fromfunction(lambda i, phase=deltaphase:phase**i,
4191 1 tkerber
                                     (spatialshape[dim],))
4192 1 tkerber
            blochphase = np.multiply.outer(blochphase, newphase)
4193 1 tkerber
4194 1 tkerber
        return blochphase*wf
4195 1 tkerber
4196 1 tkerber
    def get_wave_function(self, band=0, kpt=0, spin=0):
4197 1 tkerber
        '''return the wave function. This is the pseudo wave function
4198 1 tkerber
        divided by volume.'''
4199 1 tkerber
4200 1 tkerber
        pwf = self.get_pseudo_wave_function(band=band,
4201 1 tkerber
                                            kpt=kpt,
4202 1 tkerber
                                            spin=spin,
4203 1 tkerber
                                            pad=True)
4204 1 tkerber
        vol = self.get_atoms().get_volume()
4205 1 tkerber
        fftgrids = self.get_fftgrid()
4206 1 tkerber
        softgrid = fftgrids['soft']
4207 1 tkerber
4208 1 tkerber
        x, y, z = self.get_ucgrid((softgrid))
4209 1 tkerber
4210 1 tkerber
        return x, y, z, pwf/np.sqrt(vol)
4211 1 tkerber
4212 1 tkerber
    def strip(self):
4213 1 tkerber
        '''remove all large memory nc variables not needed for
4214 1 tkerber
        anything I use very often.
4215 1 tkerber
        '''
4216 1 tkerber
        self.delete_ncattdimvar(self.nc,
4217 1 tkerber
                                ncdims=['max_projectors_per_atom'],
4218 1 tkerber
                                ncvars=['WaveFunction',
4219 1 tkerber
                                        'WaveFunctionFFTindex',
4220 1 tkerber
                                        'NumberOfNLProjectors',
4221 1 tkerber
                                        'NLProjectorPsi',
4222 1 tkerber
                                        'TypeNLProjector1',
4223 1 tkerber
                                        'NumberofNLProjectors',
4224 1 tkerber
                                        'PartialCoreDensity',
4225 1 tkerber
                                        'ChargeDensity',
4226 1 tkerber
                                        'ElectrostaticPotential',
4227 1 tkerber
                                        'StructureFactor'])
4228 1 tkerber
4229 1 tkerber
# shortcut function names
4230 1 tkerber
Jacapo.get_cd = Jacapo.get_charge_density
4231 1 tkerber
Jacapo.get_wf = Jacapo.get_wave_function
4232 1 tkerber
Jacapo.get_esp = Jacapo.get_electrostatic_potential
4233 1 tkerber
Jacapo.get_occ = Jacapo.get_occupation_numbers
4234 1 tkerber
Jacapo.get_ef = Jacapo.get_fermi_level
4235 1 tkerber
Jacapo.get_number_of_bands = Jacapo.get_nbands
4236 1 tkerber
Jacapo.set_pseudopotentials = Jacapo.set_psp