Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
EllipsoidalInclusionPlacement.h
Go to the documentation of this file.
1/* This file is part of MoDELib, distributed under GNU GPL v2. */
2#ifndef model_EllipsoidalInclusionPlacement_H_
3#define model_EllipsoidalInclusionPlacement_H_
4#include <Eigen/Dense>
5#include <algorithm>
6#include <cmath>
7#include <stdexcept>
8
10{
11 // Positive shape tensors A*A^T; touching counts as overlap.
12 inline bool overlap(const Eigen::Vector3d &displacement, const Eigen::Matrix3d &first,
13 const Eigen::Matrix3d &second)
14 {
15 if(!displacement.allFinite() || !first.allFinite() || !second.allFinite() ||
16 first.llt().info() != Eigen::Success || second.llt().info() != Eigen::Success)
17 {
18 throw std::invalid_argument("Ellipsoid overlap requires finite positive shape tensors");
19 }
20 // The ellipsoid contact function is concave on [0,1]. Its maximum
21 // exceeds one exactly when the two closed ellipsoids are separated.
22 const double scale = std::max(first.norm(), second.norm());
23 const Eigen::Matrix3d a = first / scale, b = second / scale;
24 const Eigen::Vector3d d = displacement / std::sqrt(scale);
25 const auto contact = [&](double t)
26 {
27 const Eigen::Matrix3d shape = (1 - t) * a + t * b;
28 return t * (1 - t) * d.dot(shape.ldlt().solve(d));
29 };
30 double lo = 0, hi = 1;
31 constexpr double ratio = 0.6180339887498948482;
32 double left = hi - ratio * (hi - lo), right = lo + ratio * (hi - lo);
33 double fl = contact(left), fr = contact(right);
34 for(int k = 0; k < 100; ++k)
35 {
36 if(std::max(fl, fr) > 1.0 + 1.e-12)
37 {
38 return false;
39 }
40 if(fl < fr)
41 {
42 lo = left;
43 left = right;
44 fl = fr;
45 right = lo + ratio * (hi - lo);
46 fr = contact(right);
47 }
48 else
49 {
50 hi = right;
51 right = left;
52 fr = fl;
53 left = hi - ratio * (hi - lo);
54 fl = contact(left);
55 }
56 }
57 return std::max(fl, fr) <= 1.0 + 1.e-12;
58 }
59
60 // Squared distance from the origin to a triangle in unit-ellipsoid coordinates.
61 inline double triangleDistanceSquared(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c)
62 {
63 const auto edgeDistance = [](const Eigen::Vector3d &p, const Eigen::Vector3d &q)
64 {
65 const Eigen::Vector3d edge = q - p;
66 const double t = edge.squaredNorm() > 0 ? std::clamp(-p.dot(edge) / edge.squaredNorm(), 0.0, 1.0) : 0.0;
67 return (p + t * edge).squaredNorm();
68 };
69 double distance = std::min({edgeDistance(a, b), edgeDistance(b, c), edgeDistance(c, a)});
70 const Eigen::Vector3d u = b - a, v = c - a, n = u.cross(v);
71 if(n.squaredNorm() > 0)
72 {
73 const double s = (-a).cross(v).dot(n) / n.squaredNorm();
74 const double t = u.cross(-a).dot(n) / n.squaredNorm();
75 if(s >= 0 && t >= 0 && s + t <= 1)
76 {
77 distance = std::min(distance, (a + s * u + t * v).squaredNorm());
78 }
79 }
80 return distance;
81 }
82} // namespace model::ellipsoidalPlacement
83#endif
the magnitude of the R vector q
final point of the source segment t
c
Definition int_R.m:15
a
Definition int_R.m:14
b
Definition int_R.m:16
double triangleDistanceSquared(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c)
bool overlap(const Eigen::Vector3d &displacement, const Eigen::Matrix3d &first, const Eigen::Matrix3d &second)
right
REAL u[4]
left
vertex p[3]
int k
vertex first
REAL v[4]