ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
oif_local_forces.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22/** \file
23 * Routines to calculate the OIF local forces for a particle quadruple
24 * (two neighboring triangles with common edge).
25 * See @cite dupin07a.
26 */
27
28#include "config/config.hpp"
29
30#include "BoxGeometry.hpp"
31#include "Particle.hpp"
32
33#include <utils/Vector.hpp>
35
36#include <cmath>
37#include <tuple>
38
39/** Tiny OIF elasticity cutoff. */
40inline constexpr auto tiny_oif_elasticity_coefficient{1e-10};
41
42/** Parameters for OIF local forces
43 *
44 * Characterize the deformation of two triangles sharing an edge.
45 */
47 /** Equilibrium bond length of triangle edges */
48 double r0;
49 /** Non-linear stretching coefficient of triangle edges */
50 double ks;
51 /** Linear stretching coefficient of triangle edges */
52 double kslin;
53 /** Equilibrium angle between the two triangles */
54 double phi0;
55 /** Bending coefficient for the angle between the two triangles */
56 double kb;
57 /** Equilibrium surface of the first triangle */
58 double A01;
59 /** Equilibrium surface of the second triangle */
60 double A02;
61 /** Stretching coefficient of a triangle surface */
62 double kal;
63 /** Viscous coefficient of the triangle vertices */
64 double kvisc;
65
66 double cutoff() const { return 0.; }
67
68 static constexpr int num = 3;
69
70 OifLocalForcesBond(double r0, double ks, double kslin, double phi0, double kb,
71 double A01, double A02, double kal, double kvisc) {
72 this->phi0 = phi0;
73 this->kb = kb;
74 this->r0 = r0;
75 this->ks = ks;
76 this->kslin = kslin;
77 this->A01 = A01;
78 this->A02 = A02;
79 this->kal = kal;
80 this->kvisc = kvisc;
81 }
82
83 std::tuple<Utils::Vector3d, Utils::Vector3d, Utils::Vector3d, Utils::Vector3d>
84 calc_forces(BoxGeometry const &box_geo, Particle const &p2,
85 Particle const &p1, Particle const &p3, Particle const &p4) const;
86};
87
88/** Compute the OIF local forces.
89 * See @cite dupin07a, @cite jancigova16a.
90 * @param box_geo Box geometry.
91 * @param p2 Particle of triangle 1.
92 * @param p1 , p3 Particles common to triangle 1 and triangle 2.
93 * @param p4 Particle of triangle 2.
94 * @return forces on @p p1, @p p2, @p p3, @p p4
95 */
99 Particle const &p1, Particle const &p3,
100 Particle const &p4) const {
101
102 // first-fold-then-the-same approach
103 auto const fp2 = box_geo.unfolded_position(p2.pos(), p2.image_box());
104 auto const fp1 = fp2 + box_geo.get_mi_vector(p1.pos(), fp2);
105 auto const fp3 = fp2 + box_geo.get_mi_vector(p3.pos(), fp2);
106 auto const fp4 = fp2 + box_geo.get_mi_vector(p4.pos(), fp2);
107
109
110 // surface strain constraint
113 auto const dx = fp2 - fp3;
114 auto const len = dx.norm();
115 auto const dr = len - r0;
116 auto fac = 0.;
117 // linear stretching
119 fac -= kslin * dr; // no normalization
120 }
121 // non-linear stretching
123 /** For non-linear stretching, see eq. (19) in @cite dupin07a */
124 auto const lambda = len / r0;
125 auto const spring = (std::pow(lambda, 0.5) + std::pow(lambda, -2.5)) /
126 (lambda + std::pow(lambda, -3.));
127 fac -= ks * spring * dr; // no normalization
128 }
129 auto const f = (fac / len) * dx;
130 force2 += f;
131 force3 -= f;
132 }
133
134 // viscous force
135 if (kvisc > tiny_oif_elasticity_coefficient) { // to be implemented....
136 auto const dx = fp2 - fp3;
137 auto const len2 = dx.norm2();
138 auto const v_ij = p3.v() - p2.v();
139
140 // Variant A
141 // Here the force is in the direction of relative velocity btw points
142
143 // Code:
144 // force2 += kvisc * v;
145 // force3 -= kvisc * v;
146
147 // Variant B
148 // Here the force is the projection of relative velocity btw points onto
149 // line btw the points
150
151 // denote p vector between p2 and p3
152 // denote v the velocity difference between the points p2 and p3
153 // denote alpha the angle between p and v
154 // denote x the projected v onto p
155 // cos alpha = |x|/|v|
156 // cos alpha = (v,p)/(|v||p|)
157 // together we get |x|=(v,p)/|p|
158 // also, x is along p, so x = |x|.p/|p|
159 // so x = p/|p| . (v,p)/|p|
160 // altogether x = p . (v,p)/(|p|)^2
161 // |p|^2 is stored in len2
162
163 // Code:
164 auto const fac = kvisc * (dx * v_ij) / len2;
165 auto const f = fac * dx;
166 force2 += f;
167 force3 -= f;
168 }
169
170 /* bending
171 forceT1 is restoring force for triangle p1,p2,p3 and forceT2 restoring
172 force for triangle p2,p3,p4 p1 += forceT1; p2 -= 0.5*forceT1+0.5*forceT2;
173 p3 -= 0.5*forceT1+0.5*forceT2; p4 += forceT2; */
175 auto const phi = Utils::angle_btw_triangles(fp1, fp2, fp3, fp4);
176 auto const aa = (phi - phi0); // no renormalization by phi0, to be
177 // consistent with Krueger and Fedosov
178 auto const fac = kb * aa;
179
180 // calculates (fp2 - fp1)x(fp3 - fp1), thus Nc = (A - C)x(B - C)
181 auto const Nc = Utils::get_n_triangle(fp1, fp2, fp3);
182 // calculates (fp3 - fp4)x(fp2 - fp4), thus Nd = (B - D)x(A - D)
183 auto const Nd = Utils::get_n_triangle(fp4, fp3, fp2);
184
185 auto const BminA = fp3 - fp2;
186
187 auto const factorFaNc =
188 (fp2 - fp3) * (fp1 - fp3) / BminA.norm() / Nc.norm2();
189 auto const factorFaNd =
190 (fp2 - fp3) * (fp4 - fp3) / BminA.norm() / Nd.norm2();
191 auto const factorFbNc =
192 (fp2 - fp3) * (fp2 - fp1) / BminA.norm() / Nc.norm2();
193 auto const factorFbNd =
194 (fp2 - fp3) * (fp2 - fp4) / BminA.norm() / Nd.norm2();
195
196 force1 -= fac * BminA.norm() / Nc.norm2() * Nc; // Fc
197 force2 += fac * (factorFaNc * Nc + factorFaNd * Nd); // Fa
198 force3 += fac * (factorFbNc * Nc + factorFbNd * Nd); // Fb
199 force4 -= fac * BminA.norm() / Nd.norm2() * Nd; // Fc
200 }
201
202 /* local area
203 * for both triangles, only 1/3 of calculated forces are added, because each
204 * triangle will enter this calculation 3 times (one time per edge).
205 * Proportional distribution of forces, implemented according to
206 * @cite jancigova16a.
207 */
209 auto handle_triangle =
210 [this](double A0, Utils::Vector3d const &c1, Utils::Vector3d const &c2,
213 // calculate triangle barycenter and surface
214 auto const h = (1. / 3.) * (c1 + c2 + c3);
215 auto const A = Utils::area_triangle(c1, c2, c3);
216 auto const t = sqrt(A / A0) - 1.0;
217
218 auto const m1 = h - c1;
219 auto const m2 = h - c2;
220 auto const m3 = h - c3;
221
222 auto const fac = kal * A0 * (2 * t + t * t) /
223 (m1.norm2() + m2.norm2() + m3.norm2());
224
225 // local area force for triangle
226 f1 += (fac / 3.0) * m1;
227 f2 += (fac / 3.0) * m2;
228 f3 += (fac / 3.0) * m3;
229 };
230
233 }
234 return std::make_tuple(force2, force1, force3, force4);
235}
Vector implementation and trait types for boost qvm interoperability.
auto unfolded_position(Utils::Vector3d const &pos, Utils::Vector3i const &image_box) const
Unfold particle coordinates to image box.
ESPRESSO_ATTR_ALWAYS_INLINE Utils::Vector< T, 3 > get_mi_vector(const Utils::Vector< T, 3 > &a, const Utils::Vector< T, 3 > &b) const
Get the minimum-image vector between two coordinates.
T norm() const
Definition Vector.hpp:160
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
VectorXd< 3 > Vector3d
Definition Vector.hpp:185
double angle_btw_triangles(const Vector3d &P1, const Vector3d &P2, const Vector3d &P3, const Vector3d &P4)
Computes the angle between two triangles in 3D space.
double area_triangle(const Vector3d &P1, const Vector3d &P2, const Vector3d &P3)
Computes the area of triangle between vectors P1,P2,P3, by computing the cross product P1P2 x P1P3 an...
Vector3d get_n_triangle(const Vector3d &P1, const Vector3d &P2, const Vector3d &P3)
Computes the normal vector of a triangle.
constexpr auto tiny_oif_elasticity_coefficient
Tiny OIF elasticity cutoff.
Parameters for OIF local forces.
double A02
Equilibrium surface of the second triangle.
OifLocalForcesBond(double r0, double ks, double kslin, double phi0, double kb, double A01, double A02, double kal, double kvisc)
double phi0
Equilibrium angle between the two triangles.
double r0
Equilibrium bond length of triangle edges.
double kslin
Linear stretching coefficient of triangle edges.
double kb
Bending coefficient for the angle between the two triangles.
static constexpr int num
double A01
Equilibrium surface of the first triangle.
double kvisc
Viscous coefficient of the triangle vertices.
double ks
Non-linear stretching coefficient of triangle edges.
double kal
Stretching coefficient of a triangle surface.
std::tuple< Utils::Vector3d, Utils::Vector3d, Utils::Vector3d, Utils::Vector3d > calc_forces(BoxGeometry const &box_geo, Particle const &p2, Particle const &p1, Particle const &p3, Particle const &p4) const
Compute the OIF local forces.
Struct holding all information for one particle.
Definition Particle.hpp:450