Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testPlaneSectionMesh.cpp
Go to the documentation of this file.
1#include <PlaneSectionMesh.h>
2#include <MeshPlane.h>
3#include <iostream>
4
5void require(bool value,const char* message)
6{
7 if(!value)
8 {
9 throw std::runtime_error(message);
10 }
11}
12
13// Independent area oracle: intersect every tetrahedron, then sum its convex cut.
15{
16 double area=0.0;
17 for(const auto& entry : mesh.simplices())
18 {
19 const auto vertices=entry.second->vertexPositionMatrix();
20 std::vector<Eigen::Vector2d> points;
21 for(int i=0;i<4;++i)
22 {
23 for(int j=i+1;j<4;++j)
24 {
25 const double a=(vertices.col(i)-plane.P).dot(plane.unitNormal);
26 const double b=(vertices.col(j)-plane.P).dot(plane.unitNormal);
27 if(a*b<0.0)
28 {
29 points.push_back(plane.localPosition(vertices.col(i)+a/(a-b)*(vertices.col(j)-vertices.col(i))));
30 }
31 }
32 }
33 if(points.size()<3)
34 {
35 continue;
36 }
37 Eigen::Vector2d center=Eigen::Vector2d::Zero();
38 for(const auto& point : points)
39 {
40 center+=point/double(points.size());
41 }
42 std::sort(points.begin(),points.end(),[&](const auto& a,const auto& b)
43 {
44 return std::atan2(a.y()-center.y(),a.x()-center.x())<std::atan2(b.y()-center.y(),b.x()-center.x());
45 });
46 for(size_t k=0;k<points.size();++k)
47 {
48 const Eigen::Vector2d a=points[k]-center;
49 const Eigen::Vector2d b=points[(k+1)%points.size()]-center;
50 area+=0.5*(a.x()*b.y()-a.y()*b.x());
51 }
52 }
53 return area;
54}
55
56double check(const model::SimplicialMesh<3>& mesh,const model::Plane<3>& plane,double maxArea)
57{
58 const auto section=model::planeSectionMesh(mesh,plane,maxArea);
59 double area=0.0;
60 for(const auto& triangle : section.triangles())
61 {
62 const Eigen::Vector2d a=section.vertices().at(triangle[0]);
63 const Eigen::Vector2d b=section.vertices().at(triangle[1]);
64 const Eigen::Vector2d c=section.vertices().at(triangle[2]);
65 const double triArea=0.5*((b.x()-a.x())*(c.y()-a.y())-(b.y()-a.y())*(c.x()-a.x()));
66 require(triArea>0.0 && triArea<=maxArea*1.00001,"Invalid triangle or mesh area not respected");
67 area+=triArea;
68 require(mesh.search(plane.globalPosition((a+b+c)/3.0)).first,"Triangle bridges empty space outside mesh");
69 }
70 return area;
71}
72
73int main(int argc,char** argv)
74{
75 try
76 {
77 require(argc==2,"Expected repository path");
78 const double scale=14693.56435087598;
79 model::SimplicialMesh<3> mesh(std::string(argv[1])+"/Library/Meshes/polycrystalCube_10_periodicXY.msh",
80 scale*Eigen::Matrix3d::Identity(),Eigen::Vector3d::Zero(),{});
81 // Reconstruct the reported cut from three of its printed edge endpoints.
82 const Eigen::Vector3d a(-4724.304124390713,15395.35594008324,0);
83 const Eigen::Vector3d b(6756.931196017786,15784.62596385352,0);
84 const Eigen::Vector3d c(-4183.466787360541,11902.59340322532,3411.985017726859);
85 const model::Plane<3> plane(a,(b-a).cross(c-a));
86 const double expected=tetrahedralArea(mesh,plane);
87 for(const double maxArea : {1.e6,2.e5})
88 {
89 require(std::abs(check(mesh,plane,maxArea)-expected)<1.e-8*expected,"Section area differs from tetrahedron cuts");
90 }
91 require(check(mesh,model::Plane<3>(mesh.xMax()+Eigen::Vector3d::Ones()*scale,Eigen::Vector3d::UnitZ()),1.e6)==0.0,
92 "Outside plane should produce an empty section");
93 model::SimplicialMesh<3> cube(std::string(argv[1])+"/Library/Meshes/bicrystal_48.msh",
94 Eigen::Matrix3d::Identity(),Eigen::Vector3d::Zero(),{});
95 const Eigen::Vector3d center=0.5*(cube.xMin()+cube.xMax());
96 // Coincident internal GB must be displayed once, not twice.
97 const double gbArea=check(cube,model::Plane<3>(center,Eigen::Vector3d::UnitX()),0.1);
98 const double boxArea=(cube.xMax().y()-cube.xMin().y())*(cube.xMax().z()-cube.xMin().z());
99 require(std::abs(gbArea-boxArea)<1.e-9,"Coincident internal face duplicated or missing");
100 require(std::abs(check(cube,model::Plane<3>(cube.xMin(),Eigen::Vector3d::UnitZ()),0.1)
101 -(cube.xMax().x()-cube.xMin().x())*(cube.xMax().y()-cube.xMin().y()))<1.e-9,"External coincident face missing");
102 require(check(cube,model::Plane<3>(cube.xMin(),Eigen::Vector3d::Ones()),0.1)==0.0,"Vertex tangent should be empty");
103 bool rejected=false;
104 try
105 {
106 model::planeSectionMesh(cube,plane,0.0);
107 }
108 catch(const std::invalid_argument&)
109 {
110 rejected=true;
111 }
112 require(rejected,"Zero mesh area accepted");
113 std::cout<<"PASS: non-convex field plane, area, refinement, outside and coincident cuts\n";
114 }
115 catch(const std::exception& error)
116 {
117 std::cerr<<error.what()<<'\n';
118 return 1;
119 }
120}
id z()
c
Definition int_R.m:15
a
Definition int_R.m:14
b
Definition int_R.m:16
TriangularMesh planeSectionMesh(const SimplicialMesh< 3 > &mesh, const Plane< 3 > &plane, const double maxArea)
double check(const model::SimplicialMesh< 3 > &mesh, const model::Plane< 3 > &plane, double maxArea)
double tetrahedralArea(const model::SimplicialMesh< 3 > &mesh, const model::Plane< 3 > &plane)
void require(bool value, const char *message)
int j
REAL ** triangle
Definition triangle.cpp:508
void argv
void b int argc
int k
int i
REAL area
void vertices