VPTissue Reference Manual
MBMBuilder.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2016 Universiteit Antwerpen
3  *
4  * Licensed under the EUPL, Version 1.1 or as soon they will be approved by
5  * the European Commission - subsequent versions of the EUPL (the "Licence");
6  * You may not use this work except in compliance with the Licence.
7  * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl5
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the Licence is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the Licence for the specific language governing
13  * permissions and limitations under the Licence.
14  */
20 #include "MBMBuilder.h"
21 
22 #include "Cell.h"
23 #include "Mesh.h"
24 #include "MeshState.h"
25 #include "Node.h"
26 
27 #include <boost/algorithm/string/predicate.hpp>
28 #include <boost/lexical_cast.hpp>
29 #include <boost/property_tree/ptree.hpp>
30 #include <boost/property_tree/xml_parser.hpp>
31 #include <iostream>
32 
33 namespace SimPT_Sim {
34 
35 using namespace std;
36 using namespace boost::property_tree;
37 using namespace SimPT_Sim;
38 
39 shared_ptr<Mesh> MBMBuilder::Build(const MeshState& mesh_state)
40 {
41  unsigned int num_chem = CalculateNumChemicals(mesh_state);
42  m_mesh = make_shared<Mesh>(num_chem);
43 
44  BuildNodes(mesh_state);
45  BuildCells(mesh_state);
46  BuildBoundaryPolygon(mesh_state);
47  BuildWalls(mesh_state);
48  ConnectCellsToWalls(mesh_state);
49 
50  m_mesh->ConstructNeighborList(m_mesh->GetBoundaryPolygon());
51  m_mesh->UpdateNodeOwningNeighbors(m_mesh->GetBoundaryPolygon());
52  for (auto const& cell : m_mesh->GetCells()) {
53  m_mesh->ConstructNeighborList(cell);
54  m_mesh->UpdateNodeOwningNeighbors(cell);
55  }
56 
57  // TODO: Nodesets: I don't know what that is or why it would be useful?
58 
59  return m_mesh;
60 }
61 
62 void MBMBuilder::BuildBoundaryPolygon(const MeshState& mesh_state)
63 {
64  vector<int> bpni = mesh_state.GetBoundaryPolygonNodes();
65  vector<unsigned int> bp_nodes_id(bpni.begin(), bpni.end()); // (convert from int IDs to uint IDs)
66  auto new_bp = m_mesh->BuildBoundaryPolygon(bp_nodes_id);
67  const ptree empty_pt;
68  new_bp->Cell::ReadPtree(empty_pt);
69 }
70 
71 void MBMBuilder::BuildCells(const MeshState& mesh_state)
72 {
73  unsigned int num_chem = m_mesh->GetNumChemicals();
74 
75  // Build cells
76  for (size_t cell_idx = 0; cell_idx < mesh_state.GetNumCells(); ++cell_idx) {
77  // Construct an empty cell.
78  const int cell_id = mesh_state.GetCellID(cell_idx);
79  vector<int> cni = mesh_state.GetCellNodes(cell_idx);
80  vector<unsigned int> cell_nodes_id(cni.begin(), cni.end()); // (convert from int IDs to uint IDs)
81  auto new_cell = m_mesh->BuildCell(cell_id, cell_nodes_id);
82 
83  // Cell geometry.
84  new_cell->SetGeoDirty();
85 
86  // Cell attributes.
87  ptree attributes_pt;
88  auto cell_attr = mesh_state.CellAttributeContainer();
89  attributes_pt.put("boundary", cell_attr.Get<string>(cell_idx, "boundary_type"));
90  attributes_pt.put("dead", static_cast<bool>(cell_attr.Get<int>(cell_idx, "dead")));
91  attributes_pt.put("division_count", cell_attr.Get<int>(cell_idx, "div_counter"));
92  attributes_pt.put("fixed", cell_attr.Get<int>(cell_idx, "fixed"));
93  attributes_pt.put("solute", cell_attr.Get<double>(cell_idx, "solute"));
94  attributes_pt.put("stiffness", cell_attr.Get<double>(cell_idx, "stiffness"));
95  attributes_pt.put("target_area", cell_attr.Get<double>(cell_idx, "target_area"));
96  attributes_pt.put("target_length", cell_attr.Get<double>(cell_idx, "target_length"));
97  attributes_pt.put("type", cell_attr.Get<int>(cell_idx, "type"));
98  for (size_t chem_idx = 0; chem_idx < num_chem; ++chem_idx) {
99  const string chem_name = string("chem_") + boost::lexical_cast<string>(chem_idx);
100  new_cell->SetChemical(chem_idx, cell_attr.Get<double>(cell_idx, chem_name));
101  attributes_pt.add("chemical_array.chemical", cell_attr.Get<double>(cell_idx, chem_name));
102  }
103  new_cell->CellAttributes::ReadPtree(attributes_pt);
104  }
105 }
106 
107 void MBMBuilder::BuildNodes(const MeshState& mesh_state)
108 {
109  // Build nodes from nodes contained in mesh_state
110  for (size_t node_idx = 0; node_idx < mesh_state.GetNumNodes(); ++node_idx) {
111  // Required Node properties & attributes
112  const int node_id = mesh_state.GetNodeID(node_idx);
113  array<double,3> node_xyz {{mesh_state.GetNodeX(node_idx), mesh_state.GetNodeY(node_idx), 0.0}};
114  int node_at_boundary = mesh_state.NodeAttributeContainer().Get<int>(node_idx, "boundary");
115 
116  // Basic node building delegated to Mesh::BuildNode
117  auto new_node = m_mesh->BuildNode(node_id, node_xyz, node_at_boundary);
118 
119  // Required node attributes
120  new_node->SetSam(mesh_state.NodeAttributeContainer().Get<int>(node_idx, "sam"));
121  new_node->SetFixed(mesh_state.NodeAttributeContainer().Get<int>(node_idx, "fixed"));
122  }
123 }
124 
125 void MBMBuilder::BuildWalls(const MeshState& mesh_state)
126 {
127  auto& mesh_cells = m_mesh->GetCells();
128  auto& mesh_nodes = m_mesh->GetNodes();
129  for (size_t wall_idx = 0; wall_idx < mesh_state.GetNumWalls(); ++wall_idx) {
130  const int wall_id = mesh_state.GetWallID(wall_idx);
131  const pair<int,int> nid = mesh_state.GetWallNodes(wall_idx);
132  const pair<int,int> cid = mesh_state.GetWallCells(wall_idx);
133  auto n1 = mesh_nodes[nid.first];
134  auto n2 = mesh_nodes[nid.second];
135  auto c1 = (cid.first != -1) ? mesh_cells[cid.first] : m_mesh->GetBoundaryPolygon();
136  auto c2 = (cid.second != -1) ? mesh_cells[cid.second] : m_mesh->GetBoundaryPolygon();
137 
138  auto new_wall = m_mesh->BuildWall(wall_id, n1, n2, c1, c2);
139 
140  // Wall attributes.
141  ptree attributes_pt;
142  auto wall_attr = mesh_state.WallAttributeContainer();
143  attributes_pt.put("rest_length", wall_attr.Get<double>(wall_idx, "rest_length"));
144  attributes_pt.put("rest_length_init", wall_attr.Get<double>(wall_idx, "rest_length_init"));
145  attributes_pt.put("strength", wall_attr.Get<double>(wall_idx, "strength"));
146  attributes_pt.put("type", wall_attr.Get<string>(wall_idx, "type"));
147 
148  // Wall chemicals (transporters)
149  // (It is assumed throughout SimPT that walls and cells share the same number of chemicals.
150  // Since cells are read first, it is reasonable to rely on correct detection of number of
151  // chemicals in ReadCells())
152  size_t num_chem = m_mesh->GetNumChemicals();
153  for (size_t chem_idx = 0; chem_idx < num_chem; ++chem_idx) {
154  const string trans_1_name = string("trans_1_chem_") + boost::lexical_cast<string>(chem_idx);
155  const string trans_2_name = string("trans_2_chem_") + boost::lexical_cast<string>(chem_idx);
156  new_wall->SetTransporters1(chem_idx, wall_attr.Get<double>(wall_idx, trans_1_name));
157  new_wall->SetTransporters2(chem_idx, wall_attr.Get<double>(wall_idx, trans_2_name));
158  attributes_pt.add("transporter1_array.transporter1", wall_attr.Get<double>(wall_idx, trans_1_name));
159  attributes_pt.add("transporter2_array.transporter2", wall_attr.Get<double>(wall_idx, trans_2_name));
160  }
161  new_wall->WallAttributes::ReadPtree(attributes_pt);
162  }
163 }
164 
165 unsigned int MBMBuilder::CalculateNumChemicals(const MeshState& mesh_state)
166 {
167  // Check how many attributes represent chemicals
168  // (i.e.: have the form chem_n, with n = 0 -> num_chem-1)
169  vector<string> cell_attr_d = mesh_state.CellAttributeContainer().GetNames<double>();
170  size_t num_chem = 0;
171  vector<string> cell_chems; // Will contain the names of all attributes that are chemicals
172  for_each(cell_attr_d.begin(), cell_attr_d.end(), [&](string attr_name){
173  // If an attribute name starts with 'chem_' it MUST be a chemical
174  if(boost::starts_with(attr_name, "chem_")) {
175  cell_chems.push_back(attr_name);
176  ++num_chem;
177  }
178  });
179 
180  // Check chem names collected in 'cell_chems' for consistency
181  // (i.e: must be consecutive numbers from 0 to num_chem-1)
182  for (size_t chem_idx = 0; chem_idx < num_chem; ++chem_idx) {
183  const string chem_name = string("chem_") + boost::lexical_cast<string>(chem_idx);
184  if (find(cell_chems.begin(), cell_chems.end(), chem_name) == cell_chems.end())
185  throw runtime_error("Could not find chemical: \'" + chem_name + "\'");
186  }
187 
188  return num_chem;
189 }
190 
191 void MBMBuilder::ConnectCellsToWalls(const MeshState& mesh_state)
192 {
193  // Loop over all cells in the tissue, check which walls they contain and
194  // set the appropriate wall pointers. Both cells and walls need to be constructed
195  // first for this to work since access to pointers of existing walls and cells is necessary.
196  auto& mesh_cells = m_mesh->GetCells();
197  auto& mesh_walls = m_mesh->GetWalls();
198 
199  for (size_t cell_idx = 0; cell_idx < mesh_state.GetNumCells(); ++cell_idx) {
200  const int cell_id = mesh_state.GetCellID(cell_idx);
201  vector<int> cell_walls = mesh_state.GetCellWalls(cell_idx);
202  // Given the wall IDs in cell_walls, find pointers to these walls and assign them to the cell
203  for (const int wall_id : cell_walls) {
204  auto wall_it = find_if(mesh_walls.begin(), mesh_walls.end(), [wall_id](Wall* w) {
205  return static_cast<unsigned int>(wall_id) == w->GetIndex();
206  });
207  assert((wall_it != mesh_walls.end()) && "Cannot find the cell wall!");
208  mesh_cells[cell_id]->GetWalls().push_back(*wall_it);
209  }
210  }
211 
212  // Boundary polygon has walls as well
213  vector<int> bp_walls = mesh_state.GetBoundaryPolygonWalls();
214  // Given the wall IDs in bp_walls, find pointers to these walls and assign them to the bp
215  for (const int wall_id : bp_walls) {
216  auto wall_it = find_if(mesh_walls.begin(), mesh_walls.end(), [wall_id](Wall* w) {
217  return static_cast<unsigned int>(wall_id) == w->GetIndex();
218  });
219  assert((wall_it != mesh_walls.end()) && "Cannot find the boundary wall!");
220  m_mesh->GetBoundaryPolygon()->GetWalls().push_back(*wall_it);
221  }
222 
223  for (auto &wall : m_mesh->GetWalls()) {
224  m_mesh->UpdateNodeOwningWalls(wall);
225  }
226 }
227 
228 }
229 
double GetNodeY(size_t node_idx) const
Returns the y coordinate of a particular node.
Definition: MeshState.cpp:65
int GetWallID(size_t wall_idx) const
Returns the ID of a particular wall.
Definition: MeshState.cpp:259
Interface for MBMBBuilder.
size_t GetNumCells() const
Returns the number of cells in the mesh.
Definition: MeshState.cpp:131
STL namespace.
Interface of MeshState.
double GetNodeX(size_t node_idx) const
Returns the x coordinate of a particular node.
Definition: MeshState.cpp:60
int GetCellID(size_t cell_idx) const
Returns the ID of a particular cell.
Definition: MeshState.cpp:146
T Get(size_t index, const std::string &name) const
Returns the value of a named attribute.
Namespace for the core simulator.
Interface for Cell.
std::vector< int > GetCellNodes(size_t cell_idx) const
Returns the IDs of the nodes that form the polygon of a particular cell.
Definition: MeshState.cpp:156
AttributeContainer & WallAttributeContainer()
Adds a new named attribute of type T for the nodes.
Definition: MeshState.h:279
AttributeContainer & NodeAttributeContainer()
Adds a new named attribute of type T for the nodes.
Definition: MeshState.h:100
int GetNodeID(size_t node_idx) const
Returns the ID of a particular node.
Definition: MeshState.cpp:55
std::vector< std::string > GetNames() const
Returns a vector containing the names of attributes of type T.
Interface for Node.
std::vector< int > GetBoundaryPolygonWalls() const
Returns the IDs of the walls that form the boundary polygon of the tissue.
Definition: MeshState.cpp:225
Contains the state of the whole Mesh at a given simulation step.
Definition: MeshState.h:41
std::vector< int > GetBoundaryPolygonNodes() const
Returns the IDs of the nodes that form the boundary polygon of the tissue.
Definition: MeshState.cpp:220
AttributeContainer & CellAttributeContainer()
Adds a new named attribute of type T for the nodes.
Definition: MeshState.h:166
size_t GetNumNodes() const
Returns the number of nodes in the mesh.
Definition: MeshState.cpp:40
std::vector< int > GetCellWalls(size_t cell_idx) const
Returns the IDs of walls of a particular cell.
Definition: MeshState.cpp:166
size_t GetNumWalls() const
Returns the number of walls in the mesh.
Definition: MeshState.cpp:244
A cell wall, runs between cell corner points and consists of wall elements.
Definition: Wall.h:48
Interface for Mesh.