Beispiel #1
0
bool count_subsystem_particle_counts_for_match (const Wavefunction<amplitude_t>::Amplitude &wf1, const Wavefunction<amplitude_t>::Amplitude &wf2,
                                                const Subsystem &subsystem)
{
    assert(subsystem.lattice_makes_sense(wf1.get_lattice()));
    assert(subsystem.lattice_makes_sense(wf2.get_lattice()));
    // (we are also assuming that the lattices are in fact equivalent)

    const PositionArguments &r1 = wf1.get_positions();
    const PositionArguments &r2 = wf2.get_positions();

    assert(r1.get_N_species() == r2.get_N_species());
    assert(r1.get_N_sites() == r2.get_N_sites());

    for (unsigned int species = 0; species < r1.get_N_species(); ++species) {
        assert(r1.get_N_filled(species) == r2.get_N_filled(species));

        unsigned int count1 = 0, count2 = 0;

        for (unsigned int i = 0; i < r1.get_N_filled(species); ++i) {
            const Particle particle(i, species);
            if (subsystem.position_is_within(r1[particle], wf1.get_lattice()))
                ++count1;
            if (subsystem.position_is_within(r2[particle], wf2.get_lattice()))
                ++count2;
        }

        if (count1 != count2)
            return false;
    }

    return true;
}
Beispiel #2
0
void SwappedSystem::verify_phibetas (const Wavefunction<amplitude_t>::Amplitude &phialpha1, const Wavefunction<amplitude_t>::Amplitude &phialpha2) const
{
#ifdef NDEBUG
    (void) phialpha1;
    (void) phialpha2;
#else
    const PositionArguments &r1 = phialpha1.get_positions();
    const PositionArguments &r2 = phialpha2.get_positions();

    assert(r1.get_N_species() == r2.get_N_species());
    assert(r1.get_N_sites() == r2.get_N_sites());

    assert(copy1_subsystem_indices.size() == r1.get_N_species());
    assert(copy2_subsystem_indices.size() == r1.get_N_species());

    const Lattice &lattice = phialpha1.get_lattice();

    for (unsigned int species = 0; species < r1.get_N_species(); ++species) {
        const unsigned int N = r1.get_N_filled(species);
        assert(N == r2.get_N_filled(species));

        // verify that the subsystem index arrays have everything they need (and no duplicates!)
        unsigned int c1 = 0, c2 = 0;
        for (unsigned int i = 0; i < N; ++i) {
            const Particle particle(i, species);
            const bool b1 = vector_find(copy1_subsystem_indices[species], i) != -1;
            const bool b2 = vector_find(copy2_subsystem_indices[species], i) != -1;
            if (b1)
                ++c1;
            if (b2)
                ++c2;
            assert(b1 == subsystem->position_is_within(r1[particle], lattice));
            assert(b2 == subsystem->position_is_within(r2[particle], lattice));
        }
        assert(c1 == c2);
        assert(c1 == copy1_subsystem_indices[species].size());
        assert(c2 == copy2_subsystem_indices[species].size());
    }

    assert(phibeta1 != 0);
    assert(phibeta2 != 0);

    // verify that the positions in the phibeta's are correct
    PositionArguments swapped_r1(phialpha1.get_positions()), swapped_r2(phialpha2.get_positions());
    swap_positions(swapped_r1, swapped_r2);

    for (unsigned int species = 0; species < r1.get_N_species(); ++species) {
        for (unsigned int i = 0; i < r1.get_N_filled(species); ++i) {
            const Particle particle(i, species);
            assert(swapped_r1[particle] == phibeta1->get_positions()[particle]);
            assert(swapped_r2[particle] == phibeta2->get_positions()[particle]);
        }
    }
#endif
}
Beispiel #3
0
void SwappedSystem::initialize (const Wavefunction<amplitude_t>::Amplitude &phialpha1, const Wavefunction<amplitude_t>::Amplitude &phialpha2)
{
    assert(current_state == UNINITIALIZED);

    const PositionArguments &r1 = phialpha1.get_positions();
    const PositionArguments &r2 = phialpha2.get_positions();

    // FIXME: we need a way to assert that phialpha1 and phialpha2 represent
    // the same wave function, just with different amplitudes.  Then again,
    // we're only calling this function from two places in the code where this
    // can be easily verified ...

#ifndef NDEBUG
    assert(r1.get_N_species() == r2.get_N_species());
    for (unsigned int i = 0; i < r1.get_N_species(); ++i)
        assert(r1.get_N_filled(i) == r2.get_N_filled(i));
#endif
    assert(r1.get_N_sites() == r2.get_N_sites());
    assert(subsystem->lattice_makes_sense(phialpha1.get_lattice()));
    assert(subsystem->lattice_makes_sense(phialpha2.get_lattice()));
    assert(&phialpha1.get_lattice() == &phialpha2.get_lattice());

    const unsigned int N_species = r1.get_N_species();
    copy1_subsystem_indices.resize(N_species);
    copy2_subsystem_indices.resize(N_species);
    for (unsigned int species = 0; species < N_species; ++species) {
        const unsigned int N = r1.get_N_filled(species);
        for (unsigned int i = 0; i < N; ++i) {
            const Particle particle(i, species);
            if (subsystem->position_is_within(r1[particle], phialpha1.get_lattice()))
                copy1_subsystem_indices[species].push_back(i);
            if (subsystem->position_is_within(r2[particle], phialpha2.get_lattice()))
                copy2_subsystem_indices[species].push_back(i);
        }
    }

    assert(subsystem_particle_counts_match());
    reinitialize_phibetas(phialpha1, phialpha2);

    current_state = READY;
}
Beispiel #4
0
void SwappedSystem::update (const Particle *particle1, const Particle *particle2, const Wavefunction<amplitude_t>::Amplitude &phialpha1, const Wavefunction<amplitude_t>::Amplitude &phialpha2)
{
    // this function should be called *after* the phialpha's have been updated

    assert(current_state == READY);
    current_state = UPDATE_IN_PROGRESS;

    const PositionArguments &r1 = phialpha1.get_positions();
    const PositionArguments &r2 = phialpha2.get_positions();

#ifndef NDEBUG
    assert(r1.get_N_species() == r2.get_N_species());
    for (unsigned int i = 0; i < r1.get_N_species(); ++i)
        assert(r1.get_N_filled(i) == r2.get_N_filled(i));
#endif

    assert(!particle1 || r1.particle_is_valid(*particle1));
    assert(!particle2 || r2.particle_is_valid(*particle2));

    const Lattice &lattice = phialpha1.get_lattice();

    // these will be will be >= 0 if the particle was in the subsystem before,
    // -1 if the particle was not in the subsystem before, and -2 if the
    // particle isn't even being moved.
    int pairing_index1 = (!particle1) ? -2 : vector_find(copy1_subsystem_indices[particle1->species], particle1->index);
    int pairing_index2 = (!particle2) ? -2 : vector_find(copy2_subsystem_indices[particle2->species], particle2->index);

    const bool particle1_now_in_subsystem = (particle1 && subsystem->position_is_within(r1[*particle1], lattice));
    const bool particle2_now_in_subsystem = (particle2 && subsystem->position_is_within(r2[*particle2], lattice));

    const int delta1 = (particle1_now_in_subsystem ? 1 : 0) + (pairing_index1 >= 0 ? -1 : 0);
#ifndef NDEBUG
    const int delta2 = (particle2_now_in_subsystem ? 1 : 0) + (pairing_index2 >= 0 ? -1 : 0);
#endif

    assert(particle1 || delta1 == 0);
    assert(particle2 || delta2 == 0);

    assert(delta1 == delta2);
    const int delta = delta1;

    assert(delta == 0 || (particle1 && particle2 && particle1->species == particle2->species));

    assert(delta == 0 || particle1_now_in_subsystem == particle2_now_in_subsystem);
    // to ensure only a single update is necessary to the phibeta's, we require
    // that a particle only be moved in one copy if the particle number is not
    // changing
    assert(delta != 0 || !(particle1 && particle2));

    // remember a few things in case we need to cancel
    recent_delta = delta;
    if (particle1)
        recent_particle1 = *particle1;
    if (particle2)
        recent_particle2 = *particle2;

    if (delta == -1) {
        // if a particle of the same type leaves each subsystem simultaneously,
        // we need to use some special logic in case we have to re-pair the
        // remaining particles in the subsystem.  (re-pair in the sense of what
        // gets swapped with what)

        // these repeat some logic in the "if" statement, but are a useful
        // sanity check nonetheless (for now)
        assert(pairing_index1 >= 0 && pairing_index2 >= 0);
        assert(!particle1_now_in_subsystem);
        assert(!particle2_now_in_subsystem);

        const unsigned int species = particle1->species;
        std::vector<unsigned int> &c1_s = copy1_subsystem_indices[species];
        std::vector<unsigned int> &c2_s = copy2_subsystem_indices[species];

        if (pairing_index1 != pairing_index2) {
            // in order to re-pair the particles left behind, we move the pair
            // that is leaving the subsystem to the max_pairing_index, and move
            // the pair that is staying behind to the min_pairing_index.
            phibeta1->swap_particles(c1_s[pairing_index1], c1_s[pairing_index2], species);
            phibeta2->swap_particles(c2_s[pairing_index1], c2_s[pairing_index2], species);
            if (pairing_index1 < pairing_index2)
                std::swap(c1_s[pairing_index1], c1_s[pairing_index2]);
            else
                std::swap(c2_s[pairing_index1], c2_s[pairing_index2]);
        }

        // update the phibeta's
        const unsigned int max_pairing_index = std::max(pairing_index1, pairing_index2);
        assert(!phibeta1_dirty && !phibeta2_dirty);
        {
            Move move;
            move.push_back(SingleParticleMove(Particle(c1_s[max_pairing_index], species), r1[*particle1]));
            phibeta1->perform_move(move);
        }
        {
            Move move;
            move.push_back(SingleParticleMove(Particle(c2_s[max_pairing_index], species), r2[*particle2]));
            phibeta2->perform_move(move);
        }
        phibeta1_dirty = true;
        phibeta2_dirty = true;

        // remove the empty pair in the subsystem indices (yes, these steps
        // make sense whether we had to re-pair or not)
        c1_s[max_pairing_index] = c1_s[c1_s.size() - 1];
        c1_s.pop_back();
        c2_s[max_pairing_index] = c2_s[c2_s.size() - 1];
        c2_s.pop_back();
    } else {
        assert(delta == 0 || delta == 1);

        // either both particles moved within their respective subsystems
        // (if they moved at all), or both entered the subsystem and paired
        // with each other immediately

        // update the subsystem indices if necessary
        if (delta == 1) {
            std::vector<unsigned int> &c1_s = copy1_subsystem_indices[particle1->species];
            std::vector<unsigned int> &c2_s = copy2_subsystem_indices[particle2->species];
            c1_s.push_back(particle1->index);
            pairing_index1 = c1_s.size() - 1;
            c2_s.push_back(particle2->index);
            pairing_index2 = c2_s.size() - 1;
        }

        assert(subsystem_particle_counts_match());

        // update the phibeta's
        if (particle1) {
            std::unique_ptr<Wavefunction<amplitude_t>::Amplitude> &phibeta = particle1_now_in_subsystem ? phibeta2 : phibeta1;
            bool &phibeta_dirty = particle1_now_in_subsystem ? phibeta2_dirty : phibeta1_dirty;
            const Particle phibeta_particle = particle1_now_in_subsystem ? Particle(copy2_subsystem_indices[particle1->species][pairing_index1], particle1->species) : *particle1;
            assert(!phibeta_dirty);
            Move move;
            move.push_back(SingleParticleMove(phibeta_particle, r1[*particle1]));
            phibeta->perform_move(move);
            phibeta_dirty = true;
        }

        if (particle2) {
            std::unique_ptr<Wavefunction<amplitude_t>::Amplitude> &phibeta = particle2_now_in_subsystem ? phibeta1 : phibeta2;
            bool &phibeta_dirty = particle2_now_in_subsystem ? phibeta1_dirty : phibeta2_dirty;
            const Particle phibeta_particle = particle2_now_in_subsystem ? Particle(copy1_subsystem_indices[particle2->species][pairing_index2], particle2->species) : *particle2;
            // the only time both particles will move here is when delta == 1,
            // in which case this phibeta and the phibeta above will be
            // different, so we know that phibeta_dirty will never be true
            // here.
            assert(!phibeta_dirty);
            Move move;
            move.push_back(SingleParticleMove(phibeta_particle, r2[*particle2]));
            phibeta->perform_move(move);
            phibeta_dirty = true;
        }
    }
}