PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
testUtilLib.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2026 Prashant K. Jha
4 * -------------------------------------------
5 * PeriDEM https://github.com/prashjha/PeriDEM
6 *
7 * Distributed under the Boost Software License, Version 1.0. (See accompanying
8 * file LICENSE)
9 */
10
11#include "testUtilLib.h"
12#include "geom/geomIncludes.h"
13#include "util/vecMethods.h"
15#include "util/function.h"
16#include <cmath>
17#include <fstream>
18#include <format>
19#include <string>
20
21namespace {
22
23void errExit(std::string msg){
24 std::cerr << msg;
25 exit(EXIT_FAILURE);
26}
27}
28
30
31 const double tol = 1.e-10;
32
33 //
34 {
35 std::pair<util::Point, util::Point> box = {util::Point(),
36 util::Point(1., 1., 1.)};
37 auto corner_pts = geom::getCornerPoints(3, box);
38 auto edges = geom::getEdges(3, box);
39 auto xc = geom::getCenter(3, box);
40
41 for (size_t i=0; i<2; i++)
42 for (size_t j=0; j<2; j++)
43 for (size_t k=0; k<2; k++) {
44
45 auto p = util::Point(double(i), double(j), double(k));
46 bool found_p = false;
47 for (auto q : corner_pts) {
48 if (q.dist(p) < tol)
49 found_p = true;
50 }
51 if (!found_p)
52 errExit(std::format("Error: Can not find corner point {}\n", p.printStr()));
53 }
54
55 if (xc.dist(util::Point(0.5, 0.5, 0.5)) > tol)
56 errExit("Error: getCenter()\n");
57 }
58
59 //
60 {
61 if (std::abs(geom::triangleArea(util::Point(0., 0., 0.), util::Point(2., 0., 0.), util::Point(1., 1., 0.)) - 1.) > tol)
62 errExit("Error: triangleArea()\n");
63 }
64
65 //
66 {
67 std::vector<double> x = {1., 0., 0.};
68 std::vector<double> y_check = {1./std::sqrt(2.), -1./std::sqrt(2.), 0.};
69 auto y = util::rotateCW2D(x, M_PI * 0.25);
70 if (util::methods::l2Dist(y_check, y) > tol)
71 errExit("Error: rotateCW2D()\n");
72
73 if (util::Point(y_check).dist(util::rotateCW2D(util::Point(x), M_PI * 0.25)) > tol)
74 errExit("Error: rotateCW2D()\n");
75
76 y_check = {1./std::sqrt(2.), 1./std::sqrt(2.), 0.};
77 y = util::rotateACW2D(x, M_PI * 0.25);
78 if (util::methods::l2Dist(y_check, y) > tol)
79 errExit("Error: rotateACW2D()\n");
80 }
81
82 //
83 {
84 auto x = util::Point(1., 0., 0.);
85 auto a = util::Point(0., 0., 1.);
86 auto y_check = util::Point(0., 1., 0.);
87 auto y = util::rotate(x, M_PI * 0.5, a);
88 if (y_check.dist(y) > tol)
89 errExit(std::format("Error: rotate(). y_check = {}, y = {}\n", y_check.printStr(), y.printStr()));
90
91 x = util::Point(1., 1., 1.);
92 y_check = util::Point(-1., 1., 1.);
93 y = util::rotate(x, M_PI * 0.5, a);
94 if (y_check.dist(y) > tol)
95 errExit(std::format("Error: rotate(). y_check = {}, y = {}\n", y_check.printStr(), y.printStr()));
96 }
97
98 //
99 {
100 auto x1 = util::Point(1., 1., 0.);
101 auto x2 = util::Point(1., 0., 0.);
102 if (std::abs(M_PI*0.25 - util::angle(x1, x2)) > tol)
103 errExit("Error: angle()\n");
104
105 x2 = util::Point(0., 0., 1.);
106 if (std::abs(M_PI*0.5 - util::angle(x1, x2)) > tol)
107 errExit("Error: angle()\n");
108
109 x2 = util::Point(0., 1., 1.);
110 if (std::abs(M_PI/3. - util::angle(x1, x2)) > tol)
111 errExit("Error: angle()\n");
112 }
113}
114
116
117 // Bulk moduli and horizons that appear in the examples and tests.
118 const std::vector<double> Ks = {2.16e7, 1.0e4, 1.0e5,
119 159.2e9, 216000.0, 2.0e9, 1.23e9};
120 const std::vector<double> hs = {6.0e-4, 2.0e-4, 4.0e-4,
121 3.0e-3, 3.2e-4, 1.25e-3, 3.75e-3};
122
123 size_t n_checked = 0;
124 for (auto K1 : Ks) {
125 for (auto K2 : Ks) {
126 for (auto h : hs) {
127 // The form the example and test drivers used, at both exponents.
128 for (int p : {4, 5}) {
129 const double expected =
130 18.0 * util::harmonicMean(K1, K2) / (M_PI * std::pow(h, p));
131 const double got = util::normalContactStiffness(K1, K2, h, p);
132 if (got != expected)
133 errExit(std::format(
134 "normalContactStiffness({}, {}, {}, {}) = {:.20g}, expected "
135 "{:.20g}: the replaced expression gave a different value\n",
136 K1, K2, h, p, got, expected));
137 ++n_checked;
138 }
139 }
140 }
141 for (auto h : hs) {
142 // The form BaseParticle uses for internal contact. The grouping is
143 // (18 / (pi h^5)) * K and not 18 K / (pi h^5).
144 const double expected = (18. / (M_PI * std::pow(h, 5))) * K1;
145 const double got = util::selfContactStiffness(K1, h);
146 if (got != expected)
147 errExit(std::format(
148 "selfContactStiffness({}, {}) = {:.20g}, expected {:.20g}: the "
149 "order of operations differs from the one in BaseParticle\n",
150 K1, h, got, expected));
151 ++n_checked;
152 }
153 }
154
155 // The two forms are the same quantity because harmonicMean(K, K) == K.
156 for (auto K : Ks)
157 if (util::harmonicMean(K, K) != K)
158 errExit(std::format("harmonicMean({0}, {0}) != {0}\n", K));
159
160 // A horizon of zero divides by zero, so it is rejected instead.
161 bool threw = false;
162 try {
164 } catch (const std::exception &) {
165 threw = true;
166 }
167 if (!threw)
168 errExit("normalContactStiffness accepted a zero horizon\n");
169
170 std::cout << std::format(
171 "testContactStiffness: {} values equal to the replaced expressions\n",
172 n_checked);
173}
util::Point getCenter(size_t dim, const std::pair< util::Point, util::Point > &box)
Returns center point.
std::vector< std::pair< util::Point, util::Point > > getEdges(size_t dim, const std::pair< util::Point, util::Point > &box)
Returns all corner points in the box.
std::vector< util::Point > getCornerPoints(size_t dim, const std::pair< util::Point, util::Point > &box)
Returns all corner points in the box.
double triangleArea(const util::Point &x1, const util::Point &x2, const util::Point &x3)
Compute area of triangle.
void testContactStiffness()
Checks the contact-stiffness helpers are bit-for-bit what the expressions they replaced produced.
void testUtilMethods()
Test methods
T l2Dist(const std::vector< T > &x1, const std::vector< T > &x2)
Computes l2 distance between two vectors.
Definition vecMethods.h:395
double selfContactStiffness(const double &K, const double &horizon, int horizonPower=5)
Contact stiffness for a body against itself.
Definition function.cpp:148
double normalContactStiffness(const double &K1, const double &K2, const double &horizon, int horizonPower=5)
Silling normal contact stiffness from two bulk moduli and the horizon.
Definition function.cpp:139
double angle(util::Point a, util::Point b)
Computes angle between two vectors.
std::vector< double > rotateACW2D(const std::vector< double > &x, const double &theta)
Rotates a vector in xy-plane in anti-clockwise direction.
std::vector< double > rotateCW2D(const std::vector< double > &x, const double &theta)
Rotates a vector in xy-plane in clockwise direction.
double harmonicMean(const double &m1, const double &m2)
Definition function.cpp:135
util::Point rotate(const util::Point &p, const double &theta, const util::Point &axis)
Returns the vector after rotating by desired angle.
A structure to represent 3d vectors.
Definition point.h:30