31 using neuroscience::NeuriteElement;
37 return {result[0], result[1], result[2], 0};
42 return {result[0], result[1], result[2], 0};
55 "InteractionForce only supports sphere or cylinder shapes");
61 const Agent* sphere_rhs,
62 Real3* result)
const {
65 real_t ref_iof_coefficient = 0.15;
68 real_t nb_iof_coefficient = 0.15;
70 auto c1 = ref_mass_location;
71 real_t r1 = 0.5 * ref_diameter;
72 auto c2 = nb_mass_location;
73 real_t r2 = 0.5 * nb_diameter;
77 10.0 * std::min(ref_iof_coefficient, nb_iof_coefficient);
78 r1 += additional_radius;
79 r2 += additional_radius;
81 real_t comp1 = c1[0] - c2[0];
82 real_t comp2 = c1[1] - c2[1];
83 real_t comp3 = c1[2] - c2[2];
85 std::sqrt(comp1 * comp1 + comp2 * comp2 + comp3 * comp3);
87 real_t delta = r1 + r2 - center_distance;
90 *result = {0.0, 0.0, 0.0};
95 if (center_distance < 0.00000001) {
97 auto force2on1 = random->template UniformArray<3>(-3.0, 3.0);
102 real_t r = (r1 * r2) / (r1 + r2);
105 real_t f = k * delta - gamma * std::sqrt(r * delta);
107 real_t force_module = f / center_distance;
109 {force_module * comp1, force_module * comp2, force_module * comp3});
115 Real4* result)
const {
116 auto* ne = bdm_static_cast<const NeuriteElement*>(cylinder);
117 auto proximal_end = ne->ProximalEnd();
118 auto distal_end = ne->DistalEnd();
119 auto axis = ne->GetSpringAxis();
121 real_t actual_length = axis.Norm();
122 real_t d = ne->GetDiameter();
129 if (actual_length < r) {
135 Real3 dvec = (axis / actual_length) * rc;
136 Real3 npd = distal_end - dvec;
154 auto proximal_end_closest = c - proximal_end;
159 real_t proximal_end_closest_axis =
160 proximal_end_closest.EntryWiseProduct(axis).Sum();
161 real_t k = proximal_end_closest_axis / (actual_length * actual_length);
163 Real3 cc = proximal_end + (axis * k);
168 real_t proportion_to_proximal_end;
169 if (k <= 1.0 && k >= 0.0) {
174 proportion_to_proximal_end = 1.0 - k;
179 proportion_to_proximal_end = 1.0;
185 proportion_to_proximal_end = 0.0;
194 if (penetration <= 0) {
195 *result =
Real4{0.0, 0.0, 0.0, 0.0};
199 *result = {force[0], force[1], force[2], proportion_to_proximal_end};
204 const Agent* cylinder,
205 Real3* result)
const {
210 *result = {-temp[0], -temp[1], -temp[2]};
214 const Agent* cylinder2,
215 Real4* result)
const {
216 auto* c1 = bdm_static_cast<const NeuriteElement*>(cylinder1);
217 auto* c2 = bdm_static_cast<const NeuriteElement*>(cylinder2);
218 auto a = c1->ProximalEnd();
219 auto b = c1->GetMassLocation();
220 real_t d1 = c1->GetDiameter();
221 auto c = c2->ProximalEnd();
222 auto d = c2->GetMassLocation();
223 real_t d2 = c2->GetDiameter();
229 real_t p13x = a[0] - c[0];
230 real_t p13y = a[1] - c[1];
231 real_t p13z = a[2] - c[2];
232 real_t p43x = d[0] - c[0];
233 real_t p43y = d[1] - c[1];
234 real_t p43z = d[2] - c[2];
235 real_t p21x = b[0] - a[0];
236 real_t p21y = b[1] - a[1];
237 real_t p21z = b[2] - a[2];
239 real_t d1343 = p13x * p43x + p13y * p43y + p13z * p43z;
240 real_t d4321 = p21x * p43x + p21y * p43y + p21z * p43z;
241 real_t d1321 = p21x * p13x + p21y * p13y + p21z * p13z;
242 real_t d4343 = p43x * p43x + p43y * p43y + p43z * p43z;
243 real_t d2121 = p21x * p21x + p21y * p21y + p21z * p21z;
247 real_t denom = d2121 * d4343 - d4321 * d4321;
250 if (denom > 0.000000000001) {
251 real_t numer = d1343 * d4321 - d1321 * d4343;
253 real_t mua = numer / denom;
254 real_t mub = (d1343 + mua * d4321) / d4343;
259 }
else if (mua > 1) {
263 p1 =
Real3{a[0] + mua * p21x, a[1] + mua * p21y, a[2] + mua * p21z};
269 }
else if (mub > 1) {
272 p2 =
Real3{c[0] + mub * p43x, c[1] + mub * p43y, c[2] + mub * p43z};
276 p1 = a + (b - a) * 0.5;
277 p2 = c + (d - c) * 0.5;
283 *result = {force[0], force[1], force[2], k};
290 real_t comp1 = c1[0] - c2[0];
291 real_t comp2 = c1[1] - c2[1];
292 real_t comp3 = c1[2] - c2[2];
293 real_t distance_between_centers =
294 std::sqrt(comp1 * comp1 + comp2 * comp2 + comp3 * comp3);
296 real_t a = r1 + r2 - distance_between_centers;
299 return Real4{0.0, 0.0, 0.0, 0.0};
302 if (distance_between_centers <
305 auto force2on1 = random->template UniformArray<3>(-3.0, 3.0);
306 return Real4{force2on1[0], force2on1[1], force2on1[2], 0.0};
310 real_t force_module = a / distance_between_centers;
311 Real4 force2on1({force_module * comp1, force_module * comp2,
312 force_module * comp3, 0.0});