def iterate( vec_vhxc, pb, conf, eig_solver, n_eigs, mtx_b, log, n_electron = 5 ): global itercount itercount += 1 from sfepy.physics import dft pb.update_materials( extra_mat_args = {'mat_v' : {'vhxc' : vec_vhxc}} ) dummy = pb.create_state_vector() output( 'assembling lhs...' ) tt = time.clock() mtx_a = eval_term_op( dummy, conf.equations['lhs'], pb, dw_mode = 'matrix', tangent_matrix = pb.mtx_a ) output( '...done in %.2f s' % (time.clock() - tt) ) print 'computing the Ax=Blx Kohn-Sham problem...' eigs, mtx_s_phi = eig_solver( mtx_a, mtx_b, conf.options.n_eigs ) if len(eigs) < n_electron: print len(eigs) print eigs raise Exception("Not enough eigenvalues have converged. Exiting.") print "saving solutions, iter=%d" % itercount out = {} var_name = pb.variables.get_names( kind = 'state' )[0] for ii in xrange( len(eigs) ): vec_phi = pb.variables.make_full_vec( mtx_s_phi[:,ii] ) update_state_to_output( out, pb, vec_phi, var_name+'%03d' % ii ) pb.save_state( "tmp/iter%d.vtk" % itercount, out = out ) print "solutions saved" vec_phi = nm.zeros_like( vec_vhxc ) vec_n = nm.zeros_like( vec_vhxc ) for ii in xrange( n_electron ): vec_phi = pb.variables.make_full_vec( mtx_s_phi[:,ii] ) vec_n += vec_phi ** 2 vec_vxc = nm.zeros_like( vec_vhxc ) for ii, val in enumerate( vec_n ): vec_vxc[ii] = dft.getvxc( val/(4*pi), 0 ) pb.set_equations( conf.equations_vh ) pb.time_update() pb.variables['n'].data_from_data( vec_n ) print "Solving Ax=b Poisson equation" vec_vh = pb.solve() #sphere = eval_term_op( dummy, conf.equations['sphere'], pb) #print sphere norm = nla.norm( vec_vh + vec_vxc ) log( norm, norm ) return eigs, mtx_s_phi, vec_n, vec_vh, vec_vxc
def iterate(self, v_hxc_qp, eig_solver, mtx_a_equations, mtx_a_variables, mtx_b, log, file_output, n_electron=None): from sfepy.physics import dft self.itercount += 1 pb = self.problem opts = self.app_options n_electron = get_default( n_electron, opts.n_electron ) sh = self.qp_shape v_hxc_qp = nm.array(v_hxc_qp, dtype=nm.float64) v_hxc_qp.shape = (sh[0] * sh[1],) + sh[2:] mat_v = Materials(mtx_a_equations.collect_materials())['mat_v'] mat_v.set_extra_args(vhxc=v_hxc_qp) mat_v.time_update(None, pb.domain, mtx_a_equations) v_hxc_qp.shape = sh v_ion_qp = mat_v.get_data(('Omega', 'i1'), 0, 'V_ion') output( 'assembling lhs...' ) tt = time.clock() mtx_a = eval_equations(mtx_a_equations, mtx_a_variables, mode='weak', dw_mode='matrix') output( '...done in %.2f s' % (time.clock() - tt) ) assert_( nm.alltrue( nm.isfinite( mtx_a.data ) ) ) output( 'computing the Ax=Blx Kohn-Sham problem...' ) tt = time.clock() eigs, mtx_s_phi = eig_solver( mtx_a, mtx_b, opts.n_eigs, eigenvectors = True ) output( '...done in %.2f s' % (time.clock() - tt) ) n_eigs_ok = len(eigs) output( 'setting-up smearing...' ) e_f, smear_tuned = setup_smearing( eigs, n_electron ) output( 'Fermi energy:', e_f ) if e_f is None: raise Exception("cannot find Fermi energy - exiting.") weights = smear_tuned(eigs) output( '...done' ) if (weights[-1] > 1e-12): output("last smearing weight is nonzero (%s eigs ok)!" % n_eigs_ok) output( "saving solutions, iter=%d..." % self.itercount ) out = {} var_name = mtx_a_variables.get_names(kind='state')[0] for ii in xrange( n_eigs_ok ): vec_phi = mtx_a_variables.make_full_vec(mtx_s_phi[:,ii]) update_state_to_output( out, pb, vec_phi, var_name+'%03d' % ii ) name = op.join( opts.output_dir, "iter%d" % self.itercount ) pb.save_state('.'.join((name, opts.output_format)), out=out) output( "...solutions saved" ) output('computing total charge...') tt = time.clock() aux = pb.create_evaluable('dq_state_in_volume_qp.i1.Omega(Psi)') psi_equations, psi_variables = aux var = psi_variables['Psi'] n_qp = nm.zeros_like(v_hxc_qp) for ii in xrange( n_eigs_ok ): vec_phi = mtx_a_variables.make_full_vec(mtx_s_phi[:,ii]) var.data_from_any(vec_phi) phi_qp = eval_equations(psi_equations, psi_variables) n_qp += weights[ii] * (phi_qp ** 2) output('...done in %.2f s' % (time.clock() - tt)) ap, vg = var.get_approximation(('i1', 'Omega', 0), 'Volume') det = vg.variable(1) charge = (det * n_qp).sum() ## Same as above. ## out = nm.zeros((n_qp.shape[0], 1, 1, 1), dtype=nm.float64) ## vg.integrate(out, n_qp) ## charge = out.sum() vec_n = self._interp_to_nodes(n_qp) var.data_from_any(vec_n) charge_n = pb.evaluate('di_volume_integrate.i1.Omega(Psi)', Psi=var) ## # V_xc in quadrature points. v_xc_qp = nm.zeros((nm.prod(self.qp_shape),), dtype=nm.float64) for ii, val in enumerate(n_qp.flat): ## print ii, val v_xc_qp[ii] = dft.getvxc(val, 0) assert_(nm.isfinite(v_xc_qp).all()) v_xc_qp.shape = self.qp_shape mat_key = mat_v.datas.keys()[0] pb.set_equations( pb.conf.equations_vh ) pb.select_bcs( ebc_names = ['VHSurface'] ) pb.update_materials() output( "solving Ax=b Poisson equation" ) pb.materials['mat_n'].reset() pb.materials['mat_n'].set_all_data({mat_key : {0: {'N' : n_qp}}}) vec_v_h = pb.solve() var.data_from_any(vec_v_h) v_h_qp = pb.evaluate('dq_state_in_volume_qp.i1.Omega(Psi)', Psi=var) v_hxc_qp = v_h_qp + v_xc_qp norm = nla.norm(v_hxc_qp.ravel()) dnorm = abs(norm - self.norm_v_hxc0) log(norm, max(dnorm,1e-20)) # logplot of pure 0 fails. file_output( '%d: F(x) = |VH + VXC|: %f, abs(F(x) - F(x_prev)): %e'\ % (self.itercount, norm, dnorm) ) file_output("-"*70) file_output('Fermi energy:', e_f) file_output("----------------------------------------") file_output(" # | eigs | smearing") file_output("----|-----------------|-----------------") for ii in xrange( n_eigs_ok ): file_output("% 3d | %-15s | %-15s" % (ii+1, eigs[ii], weights[ii])) file_output("----------------------------------------") file_output("charge_qp: ", charge) file_output("charge_n: ", charge_n) file_output("----------------------------------------") file_output("|N|: ", nla.norm(n_qp.ravel())) file_output("|V_H|: ", nla.norm(v_h_qp.ravel())) file_output("|V_XC|: ", nla.norm(v_xc_qp.ravel())) file_output("|V_HXC|: ", norm) if self.iter_hook is not None: # User postprocessing. pb.select_bcs(ebc_names=['ZeroSurface']) mtx_phi = self.make_full(mtx_s_phi) data = Struct(iteration = self.itercount, eigs = eigs, weights = weights, mtx_s_phi = mtx_s_phi, mtx_phi = mtx_phi, vec_n = vec_n, vec_v_h = vec_v_h, n_qp = n_qp, v_ion_qp = v_ion_qp, v_h_qp = v_h_qp, v_xc_qp = v_xc_qp, file_output = file_output) self.iter_hook(self.problem, data = data) file_output("-"*70) self.norm_v_hxc0 = norm return eigs, mtx_s_phi, vec_n, vec_v_h, v_ion_qp, v_xc_qp, v_hxc_qp