Beispiel #1
0
phase_t Lattice::enforce_boundary (LatticeSite &site, const BoundaryConditions &bcs) const
{
    BOOST_ASSERT(site.n_dimensions() == n_dimensions());
    BOOST_ASSERT(bcs.size() == 0 || bcs.size() == n_dimensions());
    phase_t phase_change = 1;
    for (unsigned int dim = 0; dim < n_dimensions(); ++dim) {
        while (site[dim] >= dimensions[dim]) {
            site[dim] -= dimensions[dim];
            if (bcs.size() != 0)
                phase_change *= bcs[dim].phase();
        }
        while (site[dim] < 0) {
            site[dim] += dimensions[dim];
            if (bcs.size() != 0)
                phase_change *= std::conj(bcs[dim].phase());
        }
    }

    // this is often unnecessary ... should it be in a separate
    // function to be called before this one when needed?
    do_safe_modulus(site.basis_index, basis_indices);

    BOOST_ASSERT(site_is_valid(site));
    return phase_change;
}
AmplitudeType BasicOperatorEvaluator::evaluate (const typename Wavefunction<AmplitudeType>::Amplitude &wfa, const BoundaryConditions<AmplitudeType> &bcs) const
{
    typedef AmplitudeType PhaseType;

    assert(&wfa.get_lattice() == m_operator.lattice.get());
    assert(wfa.get_positions().get_N_species() >= min_required_species);

    const PositionArguments &r = wfa.get_positions();
    const Lattice &lattice = wfa.get_lattice();
    const bool is_sum_over_sites = (bcs.size() != 0);

    AmplitudeType meas = 0;

    const Big<AmplitudeType> old_psi(wfa.psi());

    // we only iterate if doing a sum, and even then we only want to iterate
    // over BraivaisSite's
    const unsigned int n_iterations = is_sum_over_sites ? lattice.total_sites() / lattice.basis_indices : 1;

    // FIXME: need a faster way of iterating the lattice
    for (unsigned int i = 0; i < n_iterations; ++i) {
        const LatticeSite site_offset(lattice[i]);
        // we only want to iterate over BravaisSite's
        assert(site_offset.basis_index == 0);

        PhaseType phase = 1;

        Move move;
        for (unsigned int j = 0; j < m_operator.hopv.size(); ++j) {
            PhaseType srcphase;
            const unsigned int species = m_operator.hopv[j].get_species();
            LatticeSite src(m_operator.hopv[j].get_source());
            lattice.asm_add_site_vector(src, site_offset.bravais_site());
            assert(is_sum_over_sites || lattice.site_is_valid(src));
            srcphase = lattice.enforce_boundary(src, bcs);
            if (srcphase == PhaseType(0))
                goto current_measurement_is_zero;
            const int particle_index = r.particle_index_at_position(lattice.index(src), species);
            if (particle_index < 0)
                goto current_measurement_is_zero;
            if (m_operator.hopv[j].get_source() != m_operator.hopv[j].get_destination()) {
                LatticeSite dest(m_operator.hopv[j].get_destination());
                lattice.asm_add_site_vector(dest, site_offset.bravais_site());
                assert(is_sum_over_sites || lattice.site_is_valid(dest));
                phase *= lattice.enforce_boundary(dest, bcs) / srcphase;
                if (phase == PhaseType(0))
                    goto current_measurement_is_zero;
                const unsigned int dest_index = lattice.index(dest);
                if (r.is_occupied(dest_index, species))
                    goto current_measurement_is_zero;
                move.push_back(SingleParticleMove(Particle(particle_index, species), dest_index));
            }
        }

        // now perform the move (if necessary)
        if (move.size() != 0) {
            BasicOperatorEvaluatorLocal::TemporaryMove<AmplitudeType> temp_move(wfa, move);
            // fixme: check logic of multiplying by phase (c.f. above), as
            // well as logic of source and destination
            meas += vmc_conj(phase * wfa.psi().ratio(old_psi));
        } else {
            meas += 1;
        }

    current_measurement_is_zero: ;
    }

    return meas;
}