void PopulationTestingForce<ELEMENT_DIM, SPACE_DIM>::AddForceContribution(AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation)
{
    for (unsigned i=0; i<rCellPopulation.GetNumNodes(); i++)
    {
        c_vector<double, SPACE_DIM> force;

        for (unsigned j=0; j<SPACE_DIM; j++)
        {
            if (mWithPositionDependence)
            {
              force[j] = (j+1)*i*0.01*rCellPopulation.GetNode(i)->rGetLocation()[j];
            }
            else
            {
                force[j] = (j+1)*i*0.01;
            }
        }
        rCellPopulation.GetNode(i)->ClearAppliedForce();
        rCellPopulation.GetNode(i)->AddAppliedForceContribution(force);
    }
}
c_vector<double, DIM> BuskeAdhesiveForce<DIM>::CalculateForceBetweenNodes(unsigned nodeAGlobalIndex,
                                                                          unsigned nodeBGlobalIndex,
                                                                          AbstractCellPopulation<DIM>& rCellPopulation)
{
    // This force class is defined for NodeBasedCellPopulations only
    assert(dynamic_cast<NodeBasedCellPopulation<DIM>*>(&rCellPopulation) != NULL);

    // We should only ever calculate the force between two distinct nodes
    assert(nodeAGlobalIndex != nodeBGlobalIndex);

    Node<DIM>* p_node_a = rCellPopulation.GetNode(nodeAGlobalIndex);
    Node<DIM>* p_node_b = rCellPopulation.GetNode(nodeBGlobalIndex);

    // Get the node locations
    c_vector<double, DIM> node_a_location = p_node_a->rGetLocation();
    c_vector<double, DIM> node_b_location = p_node_b->rGetLocation();

    // Get the unit vector parallel to the line joining the two nodes (assuming no periodicities etc.)
    c_vector<double, DIM> unit_vector = node_b_location - node_a_location;

    // Calculate the distance between the two nodes
    double distance_between_nodes = norm_2(unit_vector);

    // Account for any cutoff in the force law
    if (this->mUseCutOffLength)
    {
        if (distance_between_nodes >= this->GetCutOffLength())
        {
            return zero_vector<double>(DIM);
        }
    }

    // Assert that the nodes are a finite, non-zero distance apart
    assert(distance_between_nodes > 0);
    assert(!std::isnan(distance_between_nodes));

    // Normalize the unit vector
    unit_vector /= distance_between_nodes;

    double radius_of_cell_one = p_node_a->GetRadius();
    double radius_of_cell_two = p_node_b->GetRadius();

    // Compute the force vector
    c_vector<double, DIM> force_between_nodes = GetMagnitudeOfForce(distance_between_nodes,radius_of_cell_one,radius_of_cell_two) * unit_vector;

    return force_between_nodes;
}
Ejemplo n.º 3
0
void CryptProjectionForce::AddForceContribution(AbstractCellPopulation<2>& rCellPopulation)
{
    // First work out the 3D location of each cell
    UpdateNode3dLocationMap(rCellPopulation);

    // Throw an exception message if not using a MeshBasedCellPopulation
    if (dynamic_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation) == NULL)
    {
        EXCEPTION("CryptProjectionForce is to be used with a subclass of MeshBasedCellPopulation only");
    }

    MeshBasedCellPopulation<2>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation);

    for (MeshBasedCellPopulation<2>::SpringIterator spring_iterator = p_static_cast_cell_population->SpringsBegin();
         spring_iterator != p_static_cast_cell_population->SpringsEnd();
         ++spring_iterator)
    {
        unsigned nodeA_global_index = spring_iterator.GetNodeA()->GetIndex();
        unsigned nodeB_global_index = spring_iterator.GetNodeB()->GetIndex();

        c_vector<double, 2> force = CalculateForceBetweenNodes(nodeA_global_index, nodeB_global_index, rCellPopulation);
        c_vector<double, 2> negative_force = -1.0 * force;
        spring_iterator.GetNodeB()->AddAppliedForceContribution(negative_force);
        spring_iterator.GetNodeA()->AddAppliedForceContribution(force);
    }

    if (mIncludeWntChemotaxis)
    {
        assert(WntConcentration<2>::Instance()->IsWntSetUp());

        for (AbstractCellPopulation<2>::Iterator cell_iter = rCellPopulation.Begin();
             cell_iter != rCellPopulation.End();
             ++cell_iter)
        {
            if (cell_iter->GetCellProliferativeType()->IsType<StemCellProliferativeType>())
            {
                c_vector<double, 2> wnt_chemotactic_force = mWntChemotaxisStrength*WntConcentration<2>::Instance()->GetWntGradient(*cell_iter);
                unsigned index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter);

                rCellPopulation.GetNode(index)->AddAppliedForceContribution(wnt_chemotactic_force);
            }
        }
    }
}
    /* The second public method overrides {{{AddForceContribution()}}}.
     * This method takes in one argument, a reference to the cell population itself.
     */
    void AddForceContribution(AbstractCellPopulation<2>& rCellPopulation)
    {
        /* Inside the method, we loop over cells, and add a vector to
         * each node associated with cells with the {{{MotileCellProperty}}}, which is proportional (with constant {{{mStrength}}}) to the negative of the position. Causing
         * cells to move inwards towards the origin. Note that this will currently only work with subclasses of {{{AbstractCentreBasedCellPopulation}}}s as
         * we associate cells with nodes in the force calculation. However, this could easily be modified to make it work for {{{VertexBasedCellPopulation}}}s.
         */
        for (AbstractCellPopulation<2>::Iterator cell_iter = rCellPopulation.Begin();
             cell_iter != rCellPopulation.End();
             ++cell_iter)
        {
            if (cell_iter->HasCellProperty<MotileCellProperty>())
            {
                unsigned node_index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter);

                c_vector<double, 2> location = rCellPopulation.GetLocationOfCellCentre(*cell_iter);
                c_vector<double, 2> force = -1.0 * mStrength * location;
                rCellPopulation.GetNode(node_index)->AddAppliedForceContribution(force);
            }
        }
    }
Ejemplo n.º 5
0
void BuskeCompressionForce<DIM>::AddForceContribution(AbstractCellPopulation<DIM>& rCellPopulation)
{
    // This force class is defined for NodeBasedCellPopulations only
    assert(dynamic_cast<NodeBasedCellPopulation<DIM>*>(&rCellPopulation) != NULL);

    NodeBasedCellPopulation<DIM>* p_static_cast_cell_population = static_cast<NodeBasedCellPopulation<DIM>*>(&rCellPopulation);

    c_vector<double, DIM> unit_vector;

    // Loop over cells in the population
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = rCellPopulation.Begin();
         cell_iter != rCellPopulation.End();
         ++cell_iter)
    {
        // Get the node index corresponding to this cell
        unsigned node_index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter);

        Node<DIM>* p_node_i = rCellPopulation.GetNode(node_index);

        // Get the location of this node
        c_vector<double, DIM> node_i_location = p_node_i->rGetLocation();

        // Get the radius of this cell
        double radius_of_cell_i = p_node_i->GetRadius();

        double delta_V_c = 0.0;
        c_vector<double, DIM> dVAdd_vector = zero_vector<double>(DIM);

        // Get the set of node indices corresponding to this cell's neighbours
        std::set<unsigned> neighbouring_node_indices = p_static_cast_cell_population->GetNeighbouringNodeIndices(node_index);

        // Loop over this set
        for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
             iter != neighbouring_node_indices.end();
             ++iter)
        {
            Node<DIM>* p_node_j = rCellPopulation.GetNode(*iter);

            // Get the location of this node
            c_vector<double, DIM> node_j_location = p_node_j->rGetLocation();

            // Get the unit vector parallel to the line joining the two nodes (assuming no periodicities etc.)
            unit_vector = node_j_location - node_i_location;

            // Calculate the distance between the two nodes
            double dij = norm_2(unit_vector);

            unit_vector /= dij;

            // Get the radius of the cell corresponding to this node
            double radius_of_cell_j = p_node_j->GetRadius();

            // If the cells are close enough to exert a force on each other...
            if (dij < radius_of_cell_i + radius_of_cell_j)
            {
                // ...then compute the adhesion force and add it to the vector of forces...
                double xij = 0.5*(radius_of_cell_i*radius_of_cell_i - radius_of_cell_j*radius_of_cell_j + dij*dij)/dij;
                double dxijdd = 1.0 - xij/dij;
                double dVAdd = M_PI*dxijdd*(5.0*pow(radius_of_cell_i,2.0) + 3.0*pow(xij,2.0) - 8.0*radius_of_cell_i*xij)/3.0;

                dVAdd_vector += dVAdd*unit_vector;

                // ...and add the contribution to the compression force acting on cell i
                delta_V_c += M_PI*pow(radius_of_cell_i - xij,2.0)*(2*radius_of_cell_i - xij)/3.0;
            }
        }

        double V_A = 4.0/3.0*M_PI*pow(radius_of_cell_i,3.0) - delta_V_c;

        /**
         * Target volume of the cell
         * \todo Doesn't say in the Buske paper how they calculate this, so
         * we need to look at this to be sure it's what we want (#1764)
         */
        double V_T = 5.0;

        // Note: the sign in force_magnitude is different from the one in equation (A3) in the Buske paper
        c_vector<double, DIM> applied_force = -mCompressionEnergyParameter/V_T*(V_T - V_A)*dVAdd_vector;
        p_node_i->AddAppliedForceContribution(applied_force);
    }
}
Ejemplo n.º 6
0
c_vector<double,2> CryptProjectionForce::CalculateForceBetweenNodes(unsigned nodeAGlobalIndex, unsigned nodeBGlobalIndex, AbstractCellPopulation<2>& rCellPopulation)
{
    MeshBasedCellPopulation<2>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation);

    // We should only ever calculate the force between two distinct nodes
    assert(nodeAGlobalIndex != nodeBGlobalIndex);

    // Get the node locations in 2D
    c_vector<double,2> node_a_location_2d = rCellPopulation.GetNode(nodeAGlobalIndex)->rGetLocation();
    c_vector<double,2> node_b_location_2d = rCellPopulation.GetNode(nodeBGlobalIndex)->rGetLocation();

    // "Get the unit vector parallel to the line joining the two nodes" [GeneralisedLinearSpringForce]

    // Create a unit vector in the direction of the 3D spring
    c_vector<double,3> unit_difference = mNode3dLocationMap[nodeBGlobalIndex] - mNode3dLocationMap[nodeAGlobalIndex];

    // Calculate the distance between the two nodes
    double distance_between_nodes = norm_2(unit_difference);
    assert(distance_between_nodes > 0);
    assert(!std::isnan(distance_between_nodes));

    unit_difference /= distance_between_nodes;

    // If mUseCutOffLength has been set, then there is zero force between
    // two nodes located a distance apart greater than mUseCutOffLength
    if (this->mUseCutOffLength)
    {
        if (distance_between_nodes >= mMechanicsCutOffLength)
        {
            // Return zero (2D projected) force
            return zero_vector<double>(2);
        }
    }

    // Calculate the rest length of the spring connecting the two nodes

    double rest_length = 1.0;

    CellPtr p_cell_A = rCellPopulation.GetCellUsingLocationIndex(nodeAGlobalIndex);
    CellPtr p_cell_B = rCellPopulation.GetCellUsingLocationIndex(nodeBGlobalIndex);

    double ageA = p_cell_A->GetAge();
    double ageB = p_cell_B->GetAge();

    assert(!std::isnan(ageA));
    assert(!std::isnan(ageB));

    /*
     * If the cells are both newly divided, then the rest length of the spring
     * connecting them grows linearly with time, until mMeinekeSpringGrowthDuration hour after division.
     */
    if (ageA < mMeinekeSpringGrowthDuration && ageB < mMeinekeSpringGrowthDuration)
    {
        /*
         * The spring rest length increases from a predefined small parameter
         * to a normal rest length of 1.0, over a period of one hour.
         */
        std::pair<CellPtr,CellPtr> cell_pair = p_static_cast_cell_population->CreateCellPair(p_cell_A, p_cell_B);
        if (p_static_cast_cell_population->IsMarkedSpring(cell_pair))
        {
            double lambda = mMeinekeDivisionRestingSpringLength;
            rest_length = lambda + (1.0 - lambda) * ageA/mMeinekeSpringGrowthDuration;
        }
        if (ageA+SimulationTime::Instance()->GetTimeStep() >= mMeinekeSpringGrowthDuration)
        {
            // This spring is about to go out of scope
            p_static_cast_cell_population->UnmarkSpring(cell_pair);
        }
    }

    double a_rest_length = rest_length*0.5;
    double b_rest_length = a_rest_length;

    /*
     * If either of the cells has begun apoptosis, then the length of the spring
     * connecting them decreases linearly with time.
     */
    if (p_cell_A->HasApoptosisBegun())
    {
        double time_until_death_a = p_cell_A->GetTimeUntilDeath();
        a_rest_length = a_rest_length * time_until_death_a / p_cell_A->GetApoptosisTime();
    }
    if (p_cell_B->HasApoptosisBegun())
    {
        double time_until_death_b = p_cell_B->GetTimeUntilDeath();
        b_rest_length = b_rest_length * time_until_death_b / p_cell_B->GetApoptosisTime();
    }

    rest_length = a_rest_length + b_rest_length;

    // Assert that the rest length does not exceed 1
    assert(rest_length <= 1.0+1e-12);

    bool is_closer_than_rest_length = true;

    if (distance_between_nodes - rest_length > 0)
    {
        is_closer_than_rest_length = false;
    }

    /*
     * Although in this class the 'spring constant' is a constant parameter, in
     * subclasses it can depend on properties of each of the cells.
     */
    double multiplication_factor = 1.0;
    multiplication_factor *= VariableSpringConstantMultiplicationFactor(nodeAGlobalIndex, nodeBGlobalIndex, rCellPopulation, is_closer_than_rest_length);

    // Calculate the 3D force between the two points
    c_vector<double,3> force_between_nodes = multiplication_factor * this->GetMeinekeSpringStiffness() * unit_difference * (distance_between_nodes - rest_length);

    // Calculate an outward normal unit vector to the tangent plane of the crypt surface at the 3D point corresponding to node B
    c_vector<double,3> outward_normal_unit_vector;

    double dfdr = CalculateCryptSurfaceDerivativeAtPoint(node_b_location_2d);
    double theta_B = atan2(node_b_location_2d[1], node_b_location_2d[0]); // use atan2 to determine the quadrant
    double normalization_factor = sqrt(1 + dfdr*dfdr);

    outward_normal_unit_vector[0] = dfdr*cos(theta_B)/normalization_factor;
    outward_normal_unit_vector[1] = dfdr*sin(theta_B)/normalization_factor;
    outward_normal_unit_vector[2] = -1.0/normalization_factor;

    // Calculate the projection of the force onto the plane z=0
    c_vector<double,2> projected_force_between_nodes_2d;
    double force_dot_normal = inner_prod(force_between_nodes, outward_normal_unit_vector);

    for (unsigned i=0; i<2; i++)
    {
        projected_force_between_nodes_2d[i] = force_between_nodes[i]
                                              - force_dot_normal*outward_normal_unit_vector[i]
                                              + force_dot_normal*outward_normal_unit_vector[2];
    }

    return projected_force_between_nodes_2d;
}