CellModules
contactsurfacebody.hpp
Go to the documentation of this file.
1#ifndef CONTACTSURFACEBODY_HPP
2#define CONTACTSURFACEBODY_HPP
3#include <future>
4#include <memory>
5#include "contactsurface.hpp"
8#include "integrators.hpp"
9#include "orientable.h"
13
14namespace MecaCell {
15
16template <typename Cell> class ContactSurfaceBody : public OrientedParticle {
18
19 Cell *cell = nullptr;
21
22 // params
23 double incompressibility = 0.01;
24 double membraneStiffness = 0.5;
25
26 double restRadius = 40;
27 // dynamic target radius:
30 static constexpr double MAX_DYN_RADIUS_RATIO = 2.0;
31 double currentArea = 4.0 * M_PI * restRadius * restRadius;
32 double restVolume = (4.0 * M_PI / 3.0) * restRadius * restRadius;
34 double pressure = 0;
36
37 public:
39
41 : OrientedParticle(pos), cell(c){};
42
43 void updateInternals(double dt) {
46 }
48 void setRestVolume(double v) { restVolume = v; }
49 void setRadius(double r) { restRadius = r; }
50 double getDynamicRadius() const { return dynamicRadius; }
51 double getBoundingBoxRadius() const { return dynamicRadius; };
52 std::tuple<Cell *, double> getConnectedCellAndMembraneDistance(const Vec &d) const {
53 // /!\ assumes that d is normalized
54 Cell *closestCell = nullptr;
55 double closestDist = dynamicRadius;
56 for (auto &con : cellConnections) {
57 auto direction = cell == con->cells.first ? -con->direction : con->direction;
58 double dot = direction.dot(d);
59 if (dot < 0) {
60 const auto &midpoint =
61 cell == con->cells.first ? con->midpoint.first : con->midpoint.second;
62 double l = -midpoint / dot;
63 if (l < closestDist) {
64 closestDist = l;
65 closestCell = con->cells.first == cell ? con->cells.second : con->cells.first;
66 }
67 }
68 }
69 return std::make_tuple(closestCell, closestDist);
70 }
71
73 restVolume = (4.0 * M_PI / 3.0) * restRadius * restRadius * restRadius;
74 double volumeLoss = 0;
75 // double surfaceLoss = 0;
76 // cell connections
77 for (auto &con : cellConnections) {
78 auto &midpoint =
79 cell == con->cells.first ? con->midpoint.first : con->midpoint.second;
80 auto h = dynamicRadius - midpoint;
81 volumeLoss += (M_PI * h / 6.0) * (3.0 * con->sqradius + h * h);
82 // surfaceLoss += 2.0 * M_PI * dynamicRadius * h - con->area;
83 }
84 // TODO : soustraire les overlapps
85 double baseVol = (4.0 * M_PI / 3.0) * dynamicRadius * dynamicRadius * dynamicRadius;
86 // double baseArea = (4.0 * M_PI) * dynamicRadius * dynamicRadius;
87 currentVolume = baseVol - volumeLoss;
88 // currentArea = baseArea - surfaceLoss;
89 const double minVol = 0.1 * restVolume;
90 // const double minArea =
91 // 0.1 * getRestArea(); // garde fou en attendant de soustraire les overlaps
92 if (currentVolume < minVol) currentVolume = minVol;
93 // if (currentArea < minArea) currentArea = minArea;
94 }
95
96 void updateDynamicRadius(double dt) {
98 double dA = max(0.0, currentArea - getRestArea());
99 double dV = restVolume - currentVolume;
100 auto Fv = incompressibility * dV;
101 auto Fa = membraneStiffness * dA;
102 pressure = Fv / currentArea;
103 double dynSpeed = (dynamicRadius - prevDynamicRadius) / dt;
104 double c = .1;
105 dynamicRadius += dt * dt * (Fv - Fa - dynSpeed * c);
108 else if (dynamicRadius < restRadius)
110 } else
112 }
113
120 template <typename Integrator = Euler> void updatePositionsAndOrientations(double dt) {
121 Integrator::updatePosition(*this, dt);
122 Integrator::updateOrientation(*this, getMomentOfInertia(), dt);
123 }
124
126 for (auto &c : cellConnections) c->fixedAdhesion = true;
127 }
129 for (auto &c : cellConnections) c->fixedAdhesion = false;
130 }
131
132 inline Cell *getConnectedCell(const Vec &d) const {
133 return get<0>(getConnectedCellAndMembraneDistance(d));
134 }
135 inline double getPreciseMembraneDistance(const Vec &d) const {
136 return get<1>(getConnectedCellAndMembraneDistance(d));
137 }
138 inline double getRestArea() const { return 4.0 * M_PI * restRadius * restRadius; }
139 inline void computeRestVolume() {
140 restVolume = (4.0 * M_PI / 3.0) * restRadius * restRadius * restRadius;
141 }
142 inline double getRestMomentOfInertia() const {
143 return 0.4 * this->getMass() * restRadius * restRadius;
144 }
145
146 inline double getMomentOfInertia() const { return getRestMomentOfInertia(); }
147 inline double getVolumeVariation() const { return restVolume - currentVolume; }
148
149 double getVolume() const { return restVolume; }
150 // SET
152 void setStiffness(double k) { membraneStiffness = k; }
153 void setDynamicRadius(double r) { dynamicRadius = r; }
154 double getPressure() const { return pressure; }
155 double getRadius(void) const { return restRadius; }
156 void moveTo(Vector3D newpos) { this->setPosition(newpos); }
157};
158} // namespace MecaCell
159#endif
MecaCell::Vec pos
Definition: CellBody.hpp:34
std::vector< ContactSurface< Cell > * > cellConnections
double dynamicRadius
radiius of the cell when at rest
double getPreciseMembraneDistance(const Vec &d) const
ContactSurfaceBody(Cell *c, Vector3D pos=Vector3D::zero())
static constexpr double MAX_DYN_RADIUS_RATIO
void updatePositionsAndOrientations(double dt)
uses
std::tuple< Cell *, double > getConnectedCellAndMembraneDistance(const Vec &d) const
Cell * getConnectedCell(const Vec &d) const
double getMass() const
Definition: movable.h:30
void setPosition(const Vec &p)
Definition: movable.h:31
general purpose 3D vector/point class.
Definition: vector3D.h:20
static Vector3D zero()
constructs a zero vector
Definition: vector3D.h:170
Represents a cell in the simulation.
Definition: PrimoCell.hpp:53
A simple vector class template.
Definition: std.hpp:290
this file contains various miscellanious utility functions & helpers *