31 {
32
33 {
34 const double vol = 4.0;
35 const double Rc = 1.0;
36 const double h = 0.2;
40 if (!
near(full, vol) || !
near(mid, 0.5 * vol) || !
near(edge, 0.)) {
41 std::cerr << "correctedContactVolume failed: full=" << full
42 << " mid=" << mid << " edge=" << edge << "\n";
43 return 1;
44 }
45 }
46
48 false, false,
49 100.0);
50
56 0,
57 1,
58 0,
59 1,
60 2.0,
61 3.0,
62 1.0,
63 1.0,
64 1.e-6,
65 false,
66 false};
67
69
70
71 const auto fj = law_j->springForce(p);
72 if (!
near(fj.d_x, -150.)) {
73 std::cerr << "spring should equal Kn*(R-Rc)*Vj: fj.x=" << fj.d_x << "\n";
74 return 1;
75 }
76
77
78 const auto nodal = p.voli * fj;
79 if (!
near(nodal.d_x, -300.)) {
80 std::cerr << "nodal force Vi*fj failed: " << nodal.d_x << "\n";
81 return 1;
82 }
83
84
85 {
87 true, false,
88 100.0);
89 dd.d_K = 1.e6;
90 dd.d_betan = 0.2;
96 0,
97 1,
98 0,
99 1,
100 2.0,
101 3.0,
102 1.0,
103 1.0,
104 1.e-6,
105 false,
106 false};
107 const auto fd = law_j->nodeDampingForce(
pd);
108 if (!(fd.length() > 0.)) {
109 std::cerr << "node damping should be nonzero for approaching pair\n";
110 return 1;
111 }
114 std::cerr << "Damping_Law node flags incorrect\n";
115 return 1;
116 }
117 }
118
119
120 {
122 false, true,
123 100.0, 1., 0.2);
129 0,
130 1,
131 0,
132 1,
133 1.0,
134 1.0,
135 1.0,
136 1.0,
137 1.e-3,
138 false,
139 false};
141 ss->beginStep();
142
144 for (int k = 0; k < 20; ++k)
145 fss = ss->springForce(q);
146 ss->endStep();
147
148 const double fn = 100.0 * (1.0 - 0.5) * 1.0;
149 const double ft_max = 0.2 * fn;
150 const double ft = std::abs(fss.
d_y);
151 if (ft > ft_max + 1.e-9) {
152 std::cerr << "stick-slip exceeded Coulomb cap: ft=" << ft
153 << " ft_max=" << ft_max << "\n";
154 return 1;
155 }
156 if (ft < 0.5 * ft_max) {
157 std::cerr << "stick-slip did not mobilize friction: ft=" << ft << "\n";
158 return 1;
159 }
160 }
161
162 std::cout << "TestContact spring / stick_slip OK\n";
163
164
165 {
168 std::cerr << "off/node should not create COM damping\n";
169 return 1;
170 }
173 std::cerr << "com/com_and_node should create COM damping\n";
174 return 1;
175 }
181 std::cerr << "damping law flags incorrect\n";
182 return 1;
183 }
184 }
185
186 std::cout << "TestContact damping laws OK\n";
187
188
189
190 {
194 const double volj = 1.0;
195 const double Kn = 10.0;
196 const double Rc = 1.0;
197 const double r0 = 0.5;
198 const auto f_bb = bb->force(yji, volj, Kn, Rc, r0);
199 const auto f_rg = rg->force(yji, volj, Kn, Rc, r0);
200 if (!
near(f_bb.d_x, -2.5)) {
201 std::cerr << "broken_bond_kn unexpected: " << f_bb.d_x << "\n";
202 return 1;
203 }
204 if (!
near(f_rg.d_x, -1.0)) {
205 std::cerr << "reference_gap unexpected: " << f_rg.d_x << "\n";
206 return 1;
207 }
208
209 const auto f_rg2 = rg->force(
util::Point(0.8, 0., 0.), volj, Kn, Rc, r0);
210 if (!
near(f_rg2.d_x, 0.) || !
near(f_rg2.length(), 0.)) {
211 std::cerr << "reference_gap should be zero when R > r0\n";
212 return 1;
213 }
214 }
215
216 std::cout << "TestContact self-contact OK\n";
217
218
219 {
222 if (!meshed || meshed->skipsMeshedGrainWall() || !anal ||
223 !anal->skipsMeshedGrainWall()) {
224 std::cerr << "Wall_Contact factory flags incorrect\n";
225 return 1;
226 }
227
230 if (!plane.wallContactQuery(
util::Point(0., 0.3, 0.), hit) ||
232 std::cerr << "Plane wallContactQuery free-space failed\n";
233 return 1;
234 }
235 if (!plane.wallContactQuery(
util::Point(0., -0.2, 0.), hit) ||
237 std::cerr << "Plane wallContactQuery penetration failed\n";
238 return 1;
239 }
240
242 if (!rect.wallContactQuery(
util::Point(0., 0.8, 0.), hit) ||
244 std::cerr <<
"Rectangle wallContactQuery failed: gap=" << hit.
signed_gap
246 return 1;
247 }
248
249
250 const double Kn = 100., Rc = 1., vol = 2.;
251 plane.wallContactQuery(
util::Point(0., 0.3, 0.), hit);
253 auto scalar = Kn * (gap - Rc) * vol;
254 if (scalar > 0.)
255 scalar = 0.;
258 std::cerr <<
"analytical wall force failed: f=(" << f.
d_x <<
","
260 return 1;
261 }
262 }
263
264 std::cout << "TestContact wall contact OK\n";
265
266
267 {
269 false, true,
270 100.0, 1., 0.2);
276 0,
277 1,
278 0,
279 1,
280 1.0,
281 1.0,
282 1.0,
283 1.0,
284 1.e-3,
285 false,
286 false};
289 const auto f_cs = cs->springForce(q);
290 ss->beginStep();
292 for (int k = 0; k < 5; ++k)
293 f_ss = ss->springForce(q);
294 ss->endStep();
295
296 if (
near(f_cs.d_y, f_ss.
d_y, 1.e-6) &&
near(f_cs.d_x, f_ss.
d_x, 1.e-6)) {
297 std::cerr << "coulomb_simple and stick_slip should differ in Ft\n";
298 return 1;
299 }
300 }
301
302 std::cout << "TestContact friction laws differ OK\n";
303 return 0;
304}
Infinite plane: free space is the half-space in the normal direction.
bool near(double a, double b, double tol=1.e-12)
std::unique_ptr< SelfContact > makeSelfContact(const std::string &name)
Build self-contact law named by Model.Self_Contact.
A structure to represent 3d vectors.
double d_y
the y coordinate
double d_x
the x coordinate