void CryptProjectionForce::UpdateNode3dLocationMap(AbstractCellPopulation<2>& rCellPopulation) { mNode3dLocationMap.clear(); c_vector<double, 2> node_location_2d; c_vector<double, 3> node_location_3d; // Only consider nodes corresponding to real cells for (AbstractCellPopulation<2>::Iterator cell_iter = rCellPopulation.Begin(); cell_iter != rCellPopulation.End(); ++cell_iter) { // Get node index unsigned node_index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter); // Get 3D location node_location_2d = rCellPopulation.GetLocationOfCellCentre(*cell_iter); node_location_3d[0] = node_location_2d[0]; node_location_3d[1] = node_location_2d[1]; node_location_3d[2] = CalculateCryptSurfaceHeightAtPoint(node_location_2d); // Add to map mNode3dLocationMap[node_index] = node_location_3d; } }
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); } } }
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); } }