76#ifndef HYDRODYNAMICS_RPYBLOCKS_HPP
77#define HYDRODYNAMICS_RPYBLOCKS_HPP
83#include "utils/Constants.hpp"
85namespace OpenMD::RPY {
87 enum Regime { FarField, PartialOverlap, FullImmersion };
90 inline Regime
classify(RealType R, RealType ai, RealType aj) {
91 if (R > ai + aj)
return FarField;
92 if (R > std::fabs(ai - aj))
return PartialOverlap;
97 inline Mat3x3d
skew(
const Vector3d& v) {
109 inline RealType
heavi(RealType x) {
return (x > 0.0) ? 1.0 : 0.0; }
113 inline Mat3x3d muTT_self(RealType a, RealType eta) {
114 return (1.0 / (6.0 * Constants::PI * eta * a)) *
117 inline Mat3x3d muRR_self(RealType a, RealType eta) {
118 return (1.0 / (8.0 * Constants::PI * eta * a * a * a)) *
126 inline Mat3x3d
muTT(
const Vector3d& rij, RealType ai, RealType aj,
128 RealType R = rij.
length();
129 Vector3d rh = rij / R;
130 RealType R2 = R * R, R3 = R2 * R;
132 Mat3x3d op = outProduct(rh, rh);
133 RealType eye = 0.0, hat = 0.0;
137 RealType c = 1.0 / (8.0 * Constants::PI * eta * R);
138 RealType asum = (ai * ai + aj * aj) / R2;
139 eye = c * (1.0 + asum / 3.0);
140 hat = c * (1.0 - asum);
143 case PartialOverlap: {
144 RealType d2 = (ai - aj) * (ai - aj);
145 RealType invc = 1.0 / (6.0 * Constants::PI * eta * ai * aj);
146 eye = ((16.0 * R3 * (ai + aj) - (d2 + 3.0 * R2) * (d2 + 3.0 * R2)) /
149 hat = (3.0 * (d2 - R2) * (d2 - R2) / (32.0 * R3)) * invc;
152 case FullImmersion: {
153 RealType asup = std::max(ai, aj);
154 eye = 1.0 / (6.0 * Constants::PI * eta * asup);
159 return eye * I + hat * op;
163 inline Mat3x3d
muRR(
const Vector3d& rij, RealType ai, RealType aj,
165 RealType R = rij.
length();
166 Vector3d rh = rij / R;
167 RealType R2 = R * R, R3 = R2 * R, R4 = R2 * R2, R6 = R3 * R3;
169 Mat3x3d op = outProduct(rh, rh);
170 RealType eye = 0.0, hat = 0.0;
174 RealType c = 1.0 / (16.0 * Constants::PI * eta * R3);
179 case PartialOverlap: {
180 RealType d2 = (ai - aj) * (ai - aj);
181 RealType d4 = d2 * d2;
182 RealType calA = (5.0 * R6 - 27.0 * R4 * (ai * ai + aj * aj) +
183 32.0 * R3 * (ai * ai * ai + aj * aj * aj) -
184 9.0 * R2 * (ai * ai - aj * aj) * (ai * ai - aj * aj) -
185 d4 * (ai * ai + 4.0 * ai * aj + aj * aj)) /
187 RealType calB = (3.0 * (d2 - R2) * (d2 - R2) *
188 (ai * ai + 4.0 * ai * aj + aj * aj - R2)) /
191 1.0 / (8.0 * Constants::PI * eta * ai * ai * ai * aj * aj * aj);
196 case FullImmersion: {
197 RealType asup = std::max(ai, aj);
198 eye = 1.0 / (8.0 * Constants::PI * eta * asup * asup * asup);
203 return eye * I + hat * op;
212 return 1.0 / (8.0 * Constants::PI * eta * R2);
213 case PartialOverlap: {
214 RealType num = (ai - aj + R) * (ai - aj + R) *
215 (aj * aj + 2.0 * aj * (ai + R) - 3.0 * (ai - R) * (ai - R));
216 return (num / (8.0 * R2)) /
217 (16.0 * Constants::PI * eta * ai * ai * ai * aj);
221 return heavi(ai - aj) * R / (8.0 * Constants::PI * eta * ai * ai * ai);
227 inline Mat3x3d
muRT(
const Vector3d& rij, RealType ai, RealType aj,
229 RealType R = rij.
length();
230 Vector3d rh = rij / R;
236 inline Mat3x3d
muTR(
const Vector3d& rij, RealType ai, RealType aj,
238 RealType R = rij.
length();
239 Vector3d rh = rij / R;
248 inline Vector3d
muTD_dot_E(
const Vector3d& rij, RealType ai, RealType aj,
250 RealType R = rij.
length();
251 Vector3d rh = rij / R;
252 RealType R2 = R * R, R4 = R2 * R2, R5 = R4 * R, R6 = R4 * R2;
253 RealType ai2 = ai * ai, aj2 = aj * aj;
254 RealType hat1 = 0.0, hat3 = 0.0;
258 hat1 = (5.0 * aj / 6.0) * (-2.0 * (5.0 * ai2 * aj2 + 3.0 * aj2 * aj2)) /
260 hat3 = (5.0 * aj / 6.0) * aj2 * (5.0 * ai2 + 3.0 * aj2 - 3.0 * R2) / R4;
262 case PartialOverlap: {
263 RealType d = ai - aj;
264 RealType dm = aj - ai;
266 dm * dm * dm * dm * dm;
267 RealType calC = (10.0 * R6 - 24.0 * R5 * ai - 15.0 * R4 * (aj2 - ai2) +
268 dm5 * (ai + 5.0 * aj)) /
269 (40.0 * ai * aj * R4);
270 RealType calD = ((d * d - R2) * (d * d - R2) *
271 (d * (ai + 5.0 * aj) - R2)) /
272 (16.0 * ai * aj * R4);
273 hat1 = (5.0 * aj / 6.0) * calC;
274 hat3 = (5.0 * aj / 6.0) * calD;
278 hat1 = -
heavi(aj - ai) * R;
283 Vector3d Erh = E * rh;
284 RealType rEr =
dot(rh, Erh);
285 return hat1 * Erh + (hat3 * rEr) * rh;
290 inline Vector3d
muRD_dot_E(
const Vector3d& rij, RealType ai, RealType aj,
292 RealType R = rij.
length();
293 Vector3d rh = rij / R;
294 RealType R2 = R * R, R3 = R2 * R;
299 p = -2.5 * (aj / R) * (aj / R) * (aj / R);
301 case PartialOverlap: {
302 RealType d2 = (ai - aj) * (ai - aj);
303 RealType calB = (3.0 * (d2 - R2) * (d2 - R2) *
304 (ai * ai + 4.0 * ai * aj + aj * aj - R2)) /
306 p = -5.0 * calB / (3.0 * ai * ai * ai);
314 Vector3d Erh = E * rh;
315 return p *
cross(Erh, rh);
Mat3x3d muRT(const Vector3d &rij, RealType ai, RealType aj, RealType eta)
rotation-translation: Omega_i from F_j. carries 1/eta.
Vector3d muRD_dot_E(const Vector3d &rij, RealType ai, RealType aj, const Mat3x3d &E)
mu_rd_ij : E -> angular-velocity disturbance at bead i = p [ (E rhat) x rhat ]
Mat3x3d muRR(const Vector3d &rij, RealType ai, RealType aj, RealType eta)
rotation-rotation, carries 1/eta
RealType heavi(RealType x)
Heaviside step used by the full-immersion rt/td branches: 1 if x>0 else 0.
Mat3x3d muTT(const Vector3d &rij, RealType ai, RealType aj, RealType eta)
translation-translation, carries 1/eta
Regime classify(RealType R, RealType ai, RealType aj)
Classify a pair by centre-to-centre distance R and radii a_i, a_j.
RealType rtPrefactor(RealType R, RealType ai, RealType aj, RealType eta)
rt prefactor pf such that mu_rt = -pf * skew(rhat) (Omega_i from F_j).
Vector3d muTD_dot_E(const Vector3d &rij, RealType ai, RealType aj, const Mat3x3d &E)
mu_td_ij : E -> translational disturbance velocity at bead i = hat1 (E rhat) + hat3 (rhat ....
Mat3x3d muTR(const Vector3d &rij, RealType ai, RealType aj, RealType eta)
translation-rotation: U_i from T_j. Uses the i<->j swapped prefactor (equal to muRT only in the far f...
Mat3x3d skew(const Vector3d &v)
cross-product (skew) matrix S(v) such that S(v) * w = v x w
static SquareMatrix< Real, Dim > identity()
Real & z()
Returns reference of the third element of Vector3.
Real & x()
Returns reference of the first element of Vector3.
Real & y()
Returns reference of the second element of Vector3.
Real length() const
Returns the length of this vector.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.