def _read(self, tar, reads, ws): BaseInducedField._read(self, tar, reads, ws) # Test time time = tar['time'] if abs(time - self.time) >= 1e-9: raise IOError('Timestamp is incompatible with calculator.') # Allocate self.allocate() # Read arrays if 'n0' in reads: big_g = tar.get('n0_G') self.gd.distribute(big_g, self.n0_G) if 'Fn' in reads: for w, wread in enumerate(ws): big_g = tar.get('Fn_wsG', wread) self.gd.distribute(big_g, self.Fn_wsG[w]) if 'eps0' in reads: self.eps0_G = self.gd.empty(dtype=float) big_g = tar.get('eps0_G') self.gd.distribute(big_g, self.eps0_G) else: self.eps0_G = None
def __init__(self, filename=None, paw=None, lr=None, ws='all', frequencies=None, folding='Gauss', width=0.08, kickdir=0 ): """ Parameters (see also ``BaseInducedField``): ------------------------------------------- paw: GPAW object GPAW object for ground state lr: LrTDDFT object LrTDDFT object kickdir: int Kick direction: 0, 1, 2 for x, y, z """ # TODO: change kickdir to general kick = [1e-3, 1-e3, 0] etc. if type(lr) is not LrTDDFT: raise RuntimeError('Provide LrTDDFT object.') # Check that lr is diagonalized if len(lr) == 0: raise RuntimeError('Diagonalize LrTDDFT first.') self.lr = lr # "Kick" direction self.kickdir = kickdir self.readwritemode_str_to_list = \ {'': ['Frho', 'atoms'], 'all': ['Frho', 'Fphi', 'Fef', 'Ffe', 'atoms'], 'field': ['Frho', 'Fphi', 'Fef', 'Ffe', 'atoms']} BaseInducedField.__init__(self, filename, paw, ws, frequencies, folding, width)
def _write(self, writer, writes): # Swap classical and quantum cells, and shift atom positions for # the time of writing qmcell = self.atoms.get_cell() self.atoms.set_cell(self.fdtd.cl.cell * Bohr) # Set classical cell self.atoms.positions = (self.atoms.get_positions() + self.fdtd.qm.corner1 * Bohr) BaseInducedField._write(self, writer, writes) self.atoms.set_cell(qmcell) # Restore quantum cell to the atoms object self.atoms.positions = (self.atoms.get_positions() - self.fdtd.qm.corner1 * Bohr) # Write time propagation status writer.write(time=self.time) # Mask, interpolation approach: # self.eps0_G = self.fdtd.classical_material.permittivityValue( # omega=0.0) - self.fdtd.classical_material.epsInfty # self.eps0_G= -interpolator.apply(self.eps0_G) # Mask, direct approach: self.eps0_G = self.fdtd.cl.gd.zeros() for component in self.fdtd.classical_material.components: self.eps0_G += 1.0 * component.get_mask(gd=self.fdtd.cl.gd) # def writearray(name, shape, dtype): # if name.split('_')[0] in writes: # writer.add_array(name, shape, dtype) # a_wxg = getattr(self, name) # for w in range(self.nw): # if self.fdtd.cl.gd == self.gd: # writer.fill(self.gd.collect(a_wxg[w])) # else: # writer.fill(self.gd.collect(Transformer(self.fdtd.cl.gd, # self.gd, self.stencil, self.dtype).apply(a_wxg[w]))) def writearray(name): if name.split('_')[0] in writes: a_xg = getattr(self, name) if self.fdtd.cl.gd != self.gd: a_xg = Transformer(self.fdtd.cl.gd, self.gd, self.stencil, a_xg.dtype).apply(a_xg) writer.write(**{name: self.gd.collect(a_xg)}) # Write time propagation arrays writearray('n0_G') writearray('Fn_wG') writearray('eps0_G') if hasattr(self.fdtd, 'qm') and hasattr(self.fdtd.qm, 'corner1'): writer.write(corner1_v=self.fdtd.qm.corner1) writer.write(corner2_v=self.fdtd.qm.corner2) self.fdtd.cl.gd.comm.barrier()
def initialize(self, paw, allocate=True): BaseInducedField.initialize(self, paw, allocate) # Artificial background electric field (linear response) # TODO: change kickdir to general kick = [1e-3, 1-e3, 0] etc. Fbgef_v = np.zeros((self.nv, ), dtype=float) Fbgef_v[self.kickdir] = 1.0 self.Fbgef_v = Fbgef_v # Initialize PAW object paw.initialize_positions()
def set_folding(self, folding, width): BaseInducedField.set_folding(self, folding, width) if self.folding is None: self.envelope = lambda t: 1.0 else: if self.folding == 'Gauss': self.envelope = lambda t: np.exp(-0.5 * self.width**2 * t**2) elif self.folding == 'Lorentz': self.envelope = lambda t: np.exp(-self.width * t) else: raise RuntimeError('unknown folding "' + self.folding + '"')
def initialize(self, paw, allocate=True): BaseInducedField.initialize(self, paw, allocate) # Artificial background electric field (linear response) # TODO: change kickdir to general kick = [1e-3, 1-e3, 0] etc. Fbgef_v = np.zeros((self.nv,), dtype=float) Fbgef_v[self.kickdir] = 1.0 self.Fbgef_v = Fbgef_v # Initialize PAW object self.density.ghat.set_positions(self.atoms.get_scaled_positions()) paw.converge_wave_functions()
def set_folding(self, folding, width): BaseInducedField.set_folding(self, folding, width) if self.folding is None: self.folder = Folder(None, None) else: if self.folding == 'Gauss': self.folder = Folder(self.width, 'ComplexGauss') elif self.folding == 'Lorentz': self.folder = Folder(self.width, 'ComplexLorentz') else: raise RuntimeError('unknown folding "' + self.folding + '"')
def set_folding(self, folding, width): BaseInducedField.set_folding(self, folding, width) if self.folding is None: self.envelope = lambda t: 1.0 else: if self.folding == 'Gauss': self.envelope = lambda t: np.exp(- 0.5 * self.width**2 * t**2) elif self.folding == 'Lorentz': self.envelope = lambda t: np.exp(- self.width * t) else: raise RuntimeError('unknown folding "' + self.folding + '"')
def __init__(self, filename=None, paw=None, ws='all', frequencies=None, folding='Gauss', width=0.08, interval=1, restart_file=None): """ Parameters (see also ``BaseInducedField``): ------------------------------------------- paw: TDDFT object TDDFT object for time propagation width: float Width in eV for the Gaussian (sigma) or Lorentzian (eta) folding Gaussian = exp(- (1/2) * sigma^2 * t^2) Lorentzian = exp(- eta * t) interval: int Number of timesteps between calls (used when attaching) restart_file: string Name of the restart file """ Observer.__init__(self, interval) # From observer: # self.niter # self.interval # Restart file self.restart_file = restart_file # These are allocated in allocate() self.Fnt_wsG = None self.n0t_sG = None self.FD_awsp = None self.D0_asp = None self.readwritemode_str_to_list = \ {'': ['Fnt', 'n0t', 'FD', 'D0', 'atoms'], 'all': ['Fnt', 'n0t', 'FD', 'D0', 'Frho', 'Fphi', 'Fef', 'Ffe', 'atoms'], 'field': ['Frho', 'Fphi', 'Fef', 'Ffe', 'atoms']} BaseInducedField.__init__(self, filename, paw, ws, frequencies, folding, width)
def initialize(self, paw, allocate=True): BaseInducedField.initialize(self, paw, allocate) assert hasattr(paw, 'time') and hasattr(paw, 'niter'), 'Use TDDFT!' self.time = paw.time self.niter = paw.niter # TODO: remove this requirement assert np.count_nonzero(paw.kick_strength) > 0, \ 'Apply absorption kick before %s' % self.__class__.__name__ # Background electric field self.Fbgef_v = paw.kick_strength # Attach to PAW-type object paw.attach(self, self.interval) # TODO: write more details (folding, freqs, etc) parprint('%s: Attached ' % self.__class__.__name__)
def __init__(self, filename=None, paw=None, ws='all', frequencies=None, folding='Gauss', width=0.08, interval=1, restart_file=None ): """ Parameters (see also ``BaseInducedField``): ------------------------------------------- paw: TDDFT object TDDFT object for time propagation width: float Width in eV for the Gaussian (sigma) or Lorentzian (eta) folding Gaussian = exp(- (1/2) * sigma^2 * t^2) Lorentzian = exp(- eta * t) interval: int Number of timesteps between calls (used when attaching) restart_file: string Name of the restart file """ Observer.__init__(self, interval) # From observer: # self.niter # self.interval # Restart file self.restart_file = restart_file # These are allocated in allocate() self.Fnt_wsG = None self.n0t_sG = None self.FD_awsp = None self.D0_asp = None self.readwritemode_str_to_list = \ {'': ['Fnt', 'n0t', 'FD', 'D0', 'atoms'], 'all': ['Fnt', 'n0t', 'FD', 'D0', 'Frho', 'Fphi', 'Fef', 'Ffe', 'atoms'], 'field': ['Frho', 'Fphi', 'Fef', 'Ffe', 'atoms']} BaseInducedField.__init__(self, filename, paw, ws, frequencies, folding, width)
def _read(self, tar, reads, ws): BaseInducedField._read(self, tar, reads, ws) # Test time time = tar['time'] if abs(time - self.time) >= 1e-9: raise IOError('Timestamp is incompatible with calculator.') # Allocate self.allocate() # Dimensions for D_p for all atoms self.np_a = {} for a in range(self.na): if self.domain_comm.rank == self.rank_a[a]: self.np_a[a] = np.array(tar.dimension('np_%d' % a)) # Read arrays if 'n0t' in reads: for s in range(self.nspins): big_g = tar.get('n0t_sG', s) self.gd.distribute(big_g, self.n0t_sG[s]) if 'Fnt' in reads: for w, wread in enumerate(ws): for s in range(self.nspins): big_g = tar.get('Fnt_wsG', wread, s) self.gd.distribute(big_g, self.Fnt_wsG[w][s]) if 'D0' in reads: self.D0_asp = {} for a in range(self.na): if self.domain_comm.rank == self.rank_a[a]: self.D0_asp[a] = tar.get('D0_%dsp' % a) if 'FD' in reads: self.FD_awsp = {} for a in range(self.na): if self.domain_comm.rank == self.rank_a[a]: self.FD_awsp[a] = tar.get('FD_%dwsp' % a)[ws]
def _read(self, reader, reads): BaseInducedField._read(self, reader, reads) r = reader time = r.time if self.has_paw: # Test time if abs(time - self.time) >= 1e-9: raise IOError('Timestamp is incompatible with calculator.') else: self.time = time # Allocate self.allocate() # Dimensions for D_p for all atoms self.np_a = r.np_a def readarray(name): if name.split('_')[0] in reads: self.gd.distribute(r.get(name), getattr(self, name)) # Read arrays readarray('n0t_sG') readarray('Fnt_wsG') if 'D0' in reads: D0_asp = r.D0_asp self.D0_asp = {} for a in range(self.na): if self.domain_comm.rank == self.rank_a[a]: self.D0_asp[a] = D0_asp[a] if 'FD' in reads: FD_awsp = r.FD_awsp self.FD_awsp = {} for a in range(self.na): if self.domain_comm.rank == self.rank_a[a]: self.FD_awsp[a] = FD_awsp[a]
def _read(self, reader, reads): BaseInducedField._read(self, reader, reads) # Test time r = reader time = r.time if self.has_paw: # Test time if abs(time - self.time) >= 1e-9: raise IOError('Timestamp is incompatible with calculator.') else: self.time = time # Allocate self.allocate() def readarray(name): if name.split('_')[0] in reads: self.gd.distribute(r.get(name), getattr(self, name)) # Read arrays readarray('n0_G') readarray('Fn_wG') readarray('eps0_G')
def _write(self, writer, writes): BaseInducedField._write(self, writer, writes) # Collect np_a to master if self.kpt_comm.rank == 0 and self.band_comm.rank == 0: # Create empty dict on domain master if self.domain_comm.rank == 0: np_a = {} for a in range(self.na): np_a[a] = np.empty(1, dtype=int) else: np_a = {} # Collect dict to master sendreceive_dict(self.domain_comm, np_a, 0, self.np_a, self.rank_a, range(self.na)) # Write time propagation status writer.write(time=self.time, np_a=np_a) def writearray(name, shape, dtype): if name.split('_')[0] in writes: writer.add_array(name, shape, dtype) a_wxg = getattr(self, name) for w in range(self.nw): writer.fill(self.gd.collect(a_wxg[w])) ng = tuple(self.gd.get_size_of_global_array()) # Write time propagation arrays if 'n0t' in writes: writer.write(n0t_sG=self.gd.collect(self.n0t_sG)) writearray('Fnt_wsG', (self.nw, self.nspins) + ng, self.dtype) if 'D0' in writes: # Collect D0_asp to world master if self.kpt_comm.rank == 0 and self.band_comm.rank == 0: # Create empty dict on domain master if self.domain_comm.rank == 0: D0_asp = {} for a in range(self.na): npa = np_a[a] D0_asp[a] = np.empty((self.nspins, npa[0]), dtype=float) else: D0_asp = {} # Collect dict to master sendreceive_dict(self.domain_comm, D0_asp, 0, self.D0_asp, self.rank_a, range(self.na)) # Write writer.write(D0_asp=D0_asp) if 'FD' in writes: # Collect FD_awsp to world master if self.kpt_comm.rank == 0 and self.band_comm.rank == 0: # Create empty dict on domain master if self.domain_comm.rank == 0: FD_awsp = {} for a in range(self.na): npa = np_a[a] FD_awsp[a] = np.empty((self.nw, self.nspins, npa[0]), dtype=complex) else: FD_awsp = {} # Collect dict to master sendreceive_dict(self.domain_comm, FD_awsp, 0, self.FD_awsp, self.rank_a, range(self.na)) # Write writer.write(FD_awsp=FD_awsp)
def deallocate(self): BaseInducedField.deallocate(self) self.n0t_sG = None self.Fnt_wsG = None self.D0_asp = None self.FD_awsp = None
def equal(x, y, tol): new_ref_values.append(x) ref_values = [ 72404.467117024149, 0.520770766296, 0.520770766299, 0.830247064075, 72416.234345610734, 0.517294132489, 0.517294132492, 0.824704513888, 2451.767847927681, 0.088037476748, 0.088037476316, 0.123334033914, 2454.462292798476, 0.087537484422, 0.087537483971, 0.122592730690, 76582.089818637178, 0.589941751987, 0.589941751804, 0.869526245360, 76592.175846021099, 0.586223386358, 0.586223386102, 0.864478308364 ] for fname in ['cl_field.ind', 'qm_field.ind', 'tot_field.ind']: ind = BaseInducedField(filename=fname, readmode='field') # Estimate tolerance (worst case error accumulation) tol = (iterations * ind.fieldgd.integrate(ind.fieldgd.zeros() + 1.0) * max(density_eps, np.sqrt(poisson_eps))) if do_print_values: print('tol = %.12f' % tol) for w in range(len(frequencies)): val = ind.fieldgd.integrate(ind.Ffe_wg[w]) equal(val, ref_values.pop(0), tol) for v in range(3): val = ind.fieldgd.integrate(np.abs(ind.Fef_wvg[w][v])) equal(val, ref_values.pop(0), tol) if do_print_values: print('ref_values = [') for val in new_ref_values:
ax = plt.subplot(1, 1, 1) X, Y = np.meshgrid(x, y) plt.contourf(X, Y, d_yx, 40) plt.colorbar() for atom in atoms: pos = atom.position plt.scatter(pos[2], pos[0], s=50, c='k', marker='o') plt.xlabel(xlabel) plt.ylabel(ylabel) plt.xlim([x[0], x[-1]]) plt.ylim([y[0], y[-1]]) ax.set_aspect('equal') # Read InducedField object ind = BaseInducedField('na2_casida_field.ind', readmode='all') # Choose array w = 1 # Frequency index freq = ind.omega_w[w] * aufrequency_to_eV # Frequency box = np.diag(ind.atoms.get_cell()) # Calculation box d_g = ind.Ffe_wg[w] # Data array ng = d_g.shape # Size of grid atoms = ind.atoms # Atoms do_plot(d_g, ng, box, atoms) plt.title('Field enhancement @ %.2f eV' % freq) plt.savefig('na2_casida_Ffe.png', bbox_inches='tight') # Imaginary part of density d_g = ind.Frho_wg[w].imag * 1e-3 # Multiply by kick strength
def _write(self, tar, writes, ws, masters): # Swap classical and quantum cells, and shift atom positions for the time of writing qmcell = self.atoms.get_cell() self.atoms.set_cell(self.fdtd.cl.cell*Bohr) # Set classical cell self.atoms.positions = self.atoms.get_positions() + self.fdtd.qm.corner1*Bohr BaseInducedField._write(self, tar, writes, ws, masters) self.atoms.set_cell(qmcell) # Restore quantum cell to the atoms object self.atoms.positions = self.atoms.get_positions() - self.fdtd.qm.corner1*Bohr master, domainmaster, bandmaster, kptmaster = masters # Write time propagation status if master: tar['time'] = self.time # Mask, interpolation approach: #self.eps0_G = self.fdtd.classical_material.permittivityValue(omega=0.0) - self.fdtd.classical_material.epsInfty #self.eps0_G= -interpolator.apply(self.eps0_G) # Mask, direct approach: self.eps0_G = self.fdtd.cl.gd.zeros() for component in self.fdtd.classical_material.components: self.eps0_G += 1.0 * component.get_mask(gd = self.fdtd.cl.gd, verbose = False) # Write time propagation arrays if 'n0' in writes: if master: tar.add('n0_G', ('ng0', 'ng1', 'ng2'), dtype=float) if self.fdtd.cl.gd == self.gd: big_g = self.gd.collect(self.n0_G) else: big_g = self.gd.collect(Transformer(self.fdtd.cl.gd, self.gd, self.stencil, float).apply(self.n0_G)) if master: tar.fill(big_g) if 'Fn' in writes: if master: tar.add('Fn_wsG', ('nw', 'nspins', 'ng0', 'ng1', 'ng2'), dtype=self.dtype) for w in ws: #big_g = self.gd.collect(self.Fn_wG[w]) if self.fdtd.cl.gd == self.gd: big_g = self.gd.collect(self.Fn_wsG[w]) else: big_g = self.gd.collect(Transformer(self.fdtd.cl.gd, self.gd, self.stencil, self.dtype).apply(self.Fn_wsG[w])) #big_g = self.gd.collect(interpolator_float.apply(self.n0_G.copy())) if master: tar.fill(big_g) if 'eps0' in writes: if master: tar.add('eps0_G', ('ng0', 'ng1', 'ng2'), dtype=float) #big_g = self.fieldgd.collect(self.eps0_G) if self.fdtd.cl.gd == self.gd: big_g = self.gd.collect(self.eps0_G) else: big_g = self.gd.collect(Transformer(self.fdtd.cl.gd, self.gd, self.stencil, float).apply(self.eps0_G)) if master: tar.fill(big_g) if master and hasattr(self.fdtd, 'qm') and hasattr(self.fdtd.qm, 'corner1'): tar.add('corner1_v', ('nv',), self.fdtd.qm.corner1, dtype=float) tar.add('corner2_v', ('nv',), self.fdtd.qm.corner2, dtype=float) self.fdtd.cl.gd.comm.barrier()
def _write(self, tar, writes, ws, masters): BaseInducedField._write(self, tar, writes, ws, masters) master, domainmaster, bandmaster, kptmaster = masters # Collect np_a to master if self.kpt_comm.rank == 0 and self.band_comm.rank == 0: # Create empty dict on domain master if self.domain_comm.rank == 0: np_a = {} for a in range(self.na): np_a[a] = np.empty((1), dtype=int) else: np_a = {} # Collect dict to master sendreceive_dict(self.domain_comm, np_a, 0, self.np_a, self.rank_a, range(self.na)) # Write time propagation status if master: tar['time'] = self.time for a in range(self.na): tar.dimension('np_%d' % a, int(np_a[a])) # Write time propagation arrays if 'n0t' in writes: if master: tar.add('n0t_sG', ('nspins', 'ng0', 'ng1', 'ng2'), dtype=float) for s in range(self.nspins): big_g = self.gd.collect(self.n0t_sG[s]) if master: tar.fill(big_g) if 'Fnt' in writes: if master: tar.add('Fnt_wsG', ('nw', 'nspins', 'ng0', 'ng1', 'ng2'), dtype=self.dtype) for w in ws: for s in range(self.nspins): big_g = self.gd.collect(self.Fnt_wsG[w][s]) if master: tar.fill(big_g) if 'D0' in writes: # Collect D0_asp to world master if self.kpt_comm.rank == 0 and self.band_comm.rank == 0: # Create empty dict on domain master if self.domain_comm.rank == 0: D0_asp = {} for a in range(self.na): D0_asp[a] = np.empty((self.nspins, np_a[a]), dtype=float) else: D0_asp = {} # Collect dict to master sendreceive_dict(self.domain_comm, D0_asp, 0, self.D0_asp, self.rank_a, range(self.na)) # Write if master: for a in range(self.na): tar.add('D0_%dsp' % a, ('nspins', 'np_%d' % a), dtype=float) tar.fill(D0_asp[a]) if 'FD' in writes: # Collect FD_awsp to world master if self.kpt_comm.rank == 0 and self.band_comm.rank == 0: # Create empty dict on domain master if self.domain_comm.rank == 0: FD_awsp = {} for a in range(self.na): FD_awsp[a] = np.empty((self.nw, self.nspins, np_a[a]), dtype=complex) else: FD_awsp = {} # Collect dict to master sendreceive_dict(self.domain_comm, FD_awsp, 0, self.FD_awsp, self.rank_a, range(self.na)) # Write if master: for a in range(self.na): tar.add('FD_%dwsp' % a, ('nw', 'nspins', 'np_%d' % a), dtype=self.dtype) tar.fill(FD_awsp[a][ws])
def deallocate(self): BaseInducedField.deallocate(self) self.n0t_G = None self.Fnt_wG = None
def deallocate(self): BaseInducedField.deallocate(self) self.n0_G = None self.Fn_wG = None
ax = plt.subplot(1, 1, 1) X, Y = np.meshgrid(x, y) plt.contourf(X, Y, d_yx, 40) plt.colorbar() for atom in atoms: pos = atom.position plt.scatter(pos[2], pos[0], s=50, c='k', marker='o') plt.xlabel(xlabel) plt.ylabel(ylabel) plt.xlim([x[0], x[-1]]) plt.ylim([y[0], y[-1]]) ax.set_aspect('equal') # Read InducedField object ind = BaseInducedField('na2_td_field.ind', readmode='all') # Choose array w = 1 # Frequency index freq = ind.omega_w[w] * aufrequency_to_eV # Frequency box = np.diag(ind.atoms.get_cell()) # Calculation box d_g = ind.Ffe_wg[w] # Data array ng = d_g.shape # Size of grid atoms = ind.atoms # Atoms do_plot(d_g, ng, box, atoms) plt.title('Field enhancement @ %.2f eV' % freq) plt.savefig('na2_td_Ffe.png', bbox_inches='tight') # Imaginary part of density d_g = ind.Frho_wg[w].imag
# Calculate induced electric field ind.calculate_induced_field(gridrefinement=2, from_density='comp', poissonsolver=poissonsolver, extend_N_cd=3 * np.ones((3, 2), int), deextend=True) # Save ind.write('na2_td_field.ind', 'all') ind.paw = None td_calc = None ind = None # Read data (test also field data I/O) ind = BaseInducedField(filename='na2_td_field.ind', readmode='field') # Estimate tolerance (worst case error accumulation) tol = (iterations * ind.fieldgd.integrate(ind.fieldgd.zeros() + 1.0) * max(density_eps, np.sqrt(poisson_eps))) # tol = 0.038905993684 if do_print_values: print('tol = %.12f' % tol) # Test val1 = ind.fieldgd.integrate(ind.Ffe_wg[0]) val2 = ind.fieldgd.integrate(np.abs(ind.Fef_wvg[0][0])) val3 = ind.fieldgd.integrate(np.abs(ind.Fef_wvg[0][1])) val4 = ind.fieldgd.integrate(np.abs(ind.Fef_wvg[0][2])) val5 = ind.fieldgd.integrate(ind.Ffe_wg[1]) val6 = ind.fieldgd.integrate(np.abs(ind.Fef_wvg[1][0]))
plt.colorbar() for atom in atoms: pos = atom.position plt.scatter(pos[1], pos[0], s=50, c='k', marker='o') plt.xlabel(xlabel) plt.ylabel(ylabel) plt.xlim([x[0], x[-1]]) plt.ylim([y[0], y[-1]]) ax.set_aspect('equal') for fname, name in zip( ['cl_field.ind', 'qm_field.ind', 'tot_field.ind'], ['Classical subsystem', 'Quantum subsystem', 'Total hybrid system']): # Read InducedField object ind = BaseInducedField(fname, readmode='all') # Choose array w = 0 # Frequency index freq = ind.omega_w[w] * aufrequency_to_eV # Frequency box = np.diag(ind.atoms.get_cell()) # Calculation box d_g = ind.Ffe_wg[w] # Data array ng = d_g.shape # Size of grid atoms = ind.atoms # Atoms do_plot(d_g, ng, box, atoms) plt.title('%s\nField enhancement @ %.2f eV' % (name, freq)) plt.savefig(fname + '_Ffe.png', bbox_inches='tight') # Imaginary part of density d_g = ind.Frho_wg[w].imag