34 #include <trng/uniform_dist.hpp>
35 #include <trng/uniform01_dist.hpp>
36 #include <trng/normal_dist.hpp>
40 #include <unordered_set>
49 NodeMover::NodeMover()
50 : m_mesh(nullptr), m_tissue_energy(0.0)
59 void NodeMover::CalculateCellEnergies()
61 m_tissue_energy = 0.0;
63 const double e = m_hamiltonian(c);
64 m_cell_energies[c] = e;
69 m_tissue_energy += e_bp;
72 void NodeMover::CalculateCellEnergiesDelta()
74 m_tissue_energy = 0.0;
76 m_tissue_energy += m_hamiltonian(c);
83 assert((cd.
Check() ==
true) &&
"CoreData not OK." );
86 m_cell_energies.clear();
88 const auto model_group = m_cd.m_parameters->get<
string>(
"model.group",
"Default");
90 const bool allow_use_delta = m_cd.m_parameters->get<
bool>(
"cell_mechanics.mc_allow_use_delta",
true);
92 if (allow_use_delta) {
93 m_delta_hamiltonian = factory->CreateDeltaHamiltonian(m_cd);
94 assert((m_delta_hamiltonian) && (
"DeltaHamiltonian produces nullptr."));
98 m_hamiltonian = factory->CreateHamiltonian(m_cd);
99 assert((m_hamiltonian) && (
"Hamiltonian produces nullptr."));
101 m_mesh = m_cd.m_mesh.get();
102 m_tissue_energy = 0.0;
105 for (
size_t i = 0; i < 1; ++i) {
106 m_mc_move_generator.push_back(factory->CreateMoveGenerator(m_cd));
107 m_normal_generator.push_back(m_cd.m_random_engine->GetGenerator(trng::normal_dist<double>(0.0, 1.0), i));
108 m_uniform_generator.push_back(m_cd.m_random_engine->GetGenerator(trng::uniform01_dist<double>(), i));
112 CalculateCellEnergiesDelta();
114 CalculateCellEnergies();
118 bool NodeMover::IsNonIntersecting(
Node* node,
const std::array<double, 3>& move)
const
121 bool non_intersects =
true;
122 for (
const auto& owner : owners) {
123 if ((*owner.GetCell()).MoveSelfIntersects(node, *(node)+move)) {
124 non_intersects =
false;
129 return non_intersects;
139 double old_energy = 0.0;
141 for (
const auto& owner : owners) {
142 Cell*
const cell = owner.GetCell();
143 old_energy += m_cell_energies[cell];
144 stiff += cell->GetStiffness();
148 const array<double,3> move = m_mc_move_generator[0]() * step_size;
150 for (
const auto& owner : owners) {
151 owner.GetCell()->SetGeoDirty();
153 for (
auto& wall : owningWalls) {
154 wall->SetLengthDirty();
162 double new_energy = 0.0;
163 map<Cell*, double> new_energies_cache;
164 for (
auto& owner : owners) {
165 Cell* cell = owner.GetCell();
166 const double e = m_hamiltonian(cell);
167 new_energies_cache[cell] = e;
170 const double dh = new_energy - old_energy;
174 const bool dh_accept = (dh < -stiff);
175 const bool mc_accept = m_uniform_generator[0]() < exp((-dh - stiff)/temperature);
176 if ((dh_accept || mc_accept) && IsNonIntersecting(n, move)) {
178 for (
auto& owner : owners) {
179 Cell* cell = owner.GetCell();
180 m_cell_energies[cell] = new_energies_cache[cell];
182 m_tissue_energy += dh;
183 info = dh_accept ? MetropolisInfo(1U, 0U, dh, 0.0) : MetropolisInfo(0U, 1U, 0.0, dh);
187 for (
auto& owner : owners) {
188 owner.GetCell()->SetGeoDirty();
190 for (
auto& wall : owningWalls) {
191 wall->SetLengthDirty();
205 const array<double,3> move = m_mc_move_generator[0]() * step_size;
208 for (
const auto& owner : owners) {
209 dh += m_delta_hamiltonian(owner, n, move);
210 stiff += owner.GetCell()->GetStiffness();
214 const bool dh_accept = (dh < -stiff);
215 const bool mc_accept = m_uniform_generator[0]() < exp((-dh - stiff)/temperature);
219 if ((dh_accept || mc_accept) && IsNonIntersecting(n, move)) {
221 for (
auto& owner : owners) {
222 owner.GetCell()->SetGeoDirty();
224 for (
auto& wall : owningWalls) {
225 wall->SetLengthDirty();
227 m_tissue_energy += dh;
228 info = dh_accept ? MetropolisInfo(1U, 0U, dh, 0.0) : MetropolisInfo(0U, 1U, 0.0, dh);
239 const auto move_method =
UsesDeltaHamiltonian() ? &NodeMover::MoveNodeDelta : &NodeMover::MoveNode;
244 const auto& nodes = m_mesh->
GetNodes();
245 vector<unsigned int> shuffled_indices(nodes.size());
246 DurstenfeldShuffle::Fill(shuffled_indices, *m_cd.m_random_engine);
252 for (
const auto& i : shuffled_indices) {
253 const auto node = nodes[i];
254 if (!node->IsFixed()) {
255 sweep_info += (this->*move_method)(node, step_size, temperature);
Core data with mesh, parameters, random engine and time data.
A cell contains walls and nodes.
std::list< Wall * > & GetNodeOwningWalls(Node *n)
The walls that contain the given node somewhere on the wall.
Core data used during model execution.
Namespace for miscellaneous utilities.
Interface for MeshGeometry.
static std::shared_ptr< ComponentFactoryProxy > Create(const string &group_name, bool throw_ok=true)
Create a factory proxy.
Interface of RandomEngine.
MetropolisInfo SweepOverNodes(double step_size, double temperature)
Sweep over all nodes, do metropolis move for each of them.
Interface for DurstenfeldShuffle.
const std::vector< Cell * > & GetCells() const
The cells of this mesh, EXCLUDING the boundary polygon.
Namespace for the core simulator.
Macro defs for debug and logging.
Proxy for dealing with the factories.
Cell * GetBoundaryPolygon() const
Get the boundary polygon of the mesh.
bool UsesDeltaHamiltonian() const
Using the delta-hamiltonian.
NodeMover()
Straight initialization of empty object.
const std::vector< Node * > & GetNodes() const
The nodes of the mesh.
std::list< NeighborNodes > & GetNodeOwningNeighbors(Node *n)
Get the neighbors associated with this node.
void Initialize(const CoreData &cd)
Initializes based on values in property tree.
Interface for CellAttributes.
Header file for Exception class.
Information gathered to evaluat effects of Metropolis Algorithm.
bool Check() const
Verify all pointers non-null.