Beispiel #1
0
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
Beispiel #2
0
    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