Exemplo n.º 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;
}
Exemplo n.º 2
0
SymmetricContainer<double> FEM::computeLocalRobinMatrix(BoundaryConditions const & BCs,
                                                        array<Node, 2>& nodes,
                                                        double length) {
	SymmetricContainer<double> r(2);
	r(0, 0) = length * ( 3. * BCs.RobinCoefficient(nodes[0]) +      BCs.RobinCoefficient(nodes[1]) ) / 12.;
	r(0, 1) = length * (      BCs.RobinCoefficient(nodes[0]) +      BCs.RobinCoefficient(nodes[1]) ) / 12.;
	r(1, 1) = length * (      BCs.RobinCoefficient(nodes[0]) + 3. * BCs.RobinCoefficient(nodes[1]) ) / 12.;
	return r;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
vector<double> FEM::computeDiscreteSolution(DiffusionReactionEqn const & PDE, 
                                            Triangulation& Omega,
                                            BoundaryConditions& BCs) {
	// data structures for final linear system A.xi = b:
	SymmetricCSlRMatrix A(Omega.generateAdjList()); // build final matrix portrait
	vector<double> b(Omega.numbOfNodes(), 0.), // load vector
	               xi(Omega.numbOfNodes(), 0.); // discrete solution	
	// data structures for assemby of A and b:
	SymmetricContainer<double> localMassMatrix(3), // for hat functions on triangles 
	                           localStiffnessMatrix(3), // we have 3 × 3 element matricies
	                           localRobinMatrix(2); // and 2 × 2 element matricies for Robin BCs (just like element matrix in 1D)
	array<double, 3> localLoadVector; // and their
	array<double, 2> localRobinVector; // friends, element vectors
	array<Node, 3> elementNodes, // nodes of the current triangle
	               elementMiddleNodes; // and nodes on the middle of edges
	array<Node, 2> edgeNodes; // nodes spanning an edge of the current triangle that is part of bndry
	Node midPoint; // middle point of the edge (to define which BCs to apply)
	double measure; // area of ith triangle / length of bndry edge of ith thiangle
	array<size_t, 3> l2g_elem; // local to global mapping of nodes on the element
	array<size_t, 2> l2g_edge; // and on the edge
	LocalIndex j, k, leftNodeIndex, rightNodeIndex; // dummy indicies
	for (size_t i = 0; i < Omega.numbOfTriangles(); ++i) {
		// (1) quadratures over elements
		// in order to assemble stiffness matrix and load vector,
		// it is convenient to iterate over mesh elements (i.e. triangles)
		elementNodes = Omega.getNodes(i); // get nodes of ith triangle
		for (j = 0; j < 3; ++j) // and middle nodes of its edges
			elementMiddleNodes[j] = elementNodes[k = nextIndex(j)].midPoint(elementNodes[nextIndex(k)]);
		measure = Omega.area(i); // compute area of ith triangle
		l2g_elem = Omega.l2g(i); // local to global mapping of nodes of ith element
		// compute
		// (1.1) local mass matrix,
		// (1.2) local stiffness matrix, and
		// (1.3) local load vector
		localStiffnessMatrix = computeLocalStiffnessMatrix(PDE.diffusionTerm(), elementNodes, elementMiddleNodes, measure);
		localMassMatrix      = computeLocalMassMatrix(PDE.reactionTerm(), elementNodes, measure);
		localLoadVector      = computeLocalLoadVector(PDE.forceTerm(), elementNodes, elementMiddleNodes, measure);
		// (1.4) assemble contributions
		for (j = 0; j < 3; ++j) {
			for (k = j; k < 3; ++k)
				A(l2g_elem[j], l2g_elem[k]) += localMassMatrix(j, k) + localStiffnessMatrix(j, k);
			b[l2g_elem[j]] += localLoadVector[j];
		}
		// (2) quadratures over edges
		// iterate over list of local indicies of boundary nodes
		for (LocalIndex edgeIndex : Omega.getBoundaryIndicies(i)) {
			// if edgeIndex = 2, then the edge against second node of ith triangle
			// is part of the boundary
			// so we need to assemble BCs here
			leftNodeIndex = nextIndex(edgeIndex); // local indicies of nodes that
			rightNodeIndex = nextIndex(leftNodeIndex); // define the edge
			edgeNodes = { elementNodes[leftNodeIndex], elementNodes[rightNodeIndex] }; // and the nodes themselves
			l2g_edge[0] = l2g_elem[leftNodeIndex]; // local to global nodes
			l2g_edge[1] = l2g_elem[rightNodeIndex]; // numeration mapping 
			measure = Omega.length(i, edgeIndex);
			// define BCs to apply
			midPoint = edgeNodes[0].midPoint(edgeNodes[1]);
			BCs.defineBCsAt(midPoint);
			// compute
			// (2.1) local Robin matrix
			// (2.2) local Robin vector
			localRobinMatrix = computeLocalRobinMatrix(BCs, edgeNodes, measure);
			localRobinVector = computeLocalRobinVector(BCs, edgeNodes, measure);
			// (2.3) assemble contributions
			for (j = 0; j < 2; ++j) {
				for (k = j; k < 2; ++k)
					A(l2g_edge[j], l2g_edge[k]) += localRobinMatrix(j, k);
				b[l2g_edge[j]] += localRobinVector[j];
			}
		}
	}
	// now we are ready to compute xi, A.xi = b
	xi = CG(A, b, xi, 10e-70);
	return xi;
}
Exemplo n.º 5
0
array<double, 2> FEM::computeLocalRobinVector(BoundaryConditions const & BCs,
                                              array<Node, 2>& nodes,
                                              double length) {
	array<double, 2> r;
	return (r = {
		4. * BCs.NeumannValue(nodes[0]) + 2. * BCs.NeumannValue(nodes[1]) +
		BCs.DirichletCondition(nodes[0]) * ( 3. * BCs.RobinCoefficient(nodes[0]) + BCs.RobinCoefficient(nodes[1]) ) +
		BCs.DirichletCondition(nodes[1]) * ( BCs.RobinCoefficient(nodes[0]) + BCs.RobinCoefficient(nodes[1]) ),
		2. * BCs.NeumannValue(nodes[0]) + 4. * BCs.NeumannValue(nodes[1]) +
		BCs.DirichletCondition(nodes[0]) * ( BCs.RobinCoefficient(nodes[0]) + BCs.RobinCoefficient(nodes[1]) ) +
		BCs.DirichletCondition(nodes[1]) * ( BCs.RobinCoefficient(nodes[0]) + 3. * BCs.RobinCoefficient(nodes[1]) )
	}) *= length / 12.;
}
// Reference another set of BoundaryConditions
void mgrid::BoundaryConditions::reference(const BoundaryConditions& referent) {
    foreach(BoundaryFlag boundaryFlag, allBoundaryFlags)
        boundaries(boundaryFlag).reference(referent.boundaries(boundaryFlag));
}