Skip to content

Commit e435832

Browse files
committed
Remove duplicated line and arc curves used in tests
1 parent 0a60247 commit e435832

9 files changed

Lines changed: 96 additions & 195 deletions
Lines changed: 1 addition & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use nalgebra::{SMatrix, SVector, matrix, vector};
1+
use nalgebra::{SMatrix, SVector};
22

33
// This module contains common traits for describing a beam's geometry
44

@@ -57,124 +57,4 @@ pub trait CrossSection {
5757
// Returns the stress recovery matrices for the cross-section at relative position n and for implementation-specific points of interest.
5858
// When multiplied with the strain vector [epsilon, gamma, kappa], each matrix produces the normal stress at that point.
5959
fn stress_recovery(&self, n: f64) -> Vec<SVector<f64, 3>>;
60-
}
61-
62-
// TODO: Duplicate with testutils/curves.rs?
63-
// Implementation of a linearly varying rectangular cross-section for use in tests
64-
pub struct RectangularSection {
65-
pub w0: f64,
66-
pub h0: f64,
67-
pub w1: f64,
68-
pub h1: f64,
69-
pub ρ: f64,
70-
pub E: f64,
71-
pub G: f64,
72-
}
73-
74-
impl CrossSection for RectangularSection {
75-
fn stiffness(&self, n: f64) -> SMatrix<f64, 3, 3> {
76-
let w = self.width(n);
77-
let h = self.height(n);
78-
79-
let EA = self.E*w*h;
80-
let GA = self.G*w*h;
81-
let EI = self.E*w*h.powi(3)/12.0;
82-
83-
matrix![
84-
EA, 0.0, 0.0;
85-
0.0, GA, 0.0;
86-
0.0, 0.0, EI;
87-
]
88-
}
89-
90-
fn mass(&self, n: f64) -> SMatrix<f64, 3, 3> {
91-
let w = self.width(n);
92-
let h = self.height(n);
93-
94-
let ρA = self.ρ*w*h;
95-
let ρI = self.ρ*w*h.powi(3)/12.0;
96-
97-
matrix![
98-
ρA, 0.0, 0.0;
99-
0.0, ρA, 0.0;
100-
0.0, 0.0, ρI;
101-
]
102-
}
103-
104-
fn width(&self, p: f64) -> f64 {
105-
self.w0 + p*(self.w1 - self.w0)
106-
}
107-
108-
fn height(&self, p: f64) -> f64 {
109-
self.h0 + p*(self.h1 - self.h0)
110-
}
111-
112-
fn strain_recovery(&self, _p: f64) -> Vec<SVector<f64, 3>> {
113-
todo!();
114-
}
115-
116-
fn stress_recovery(&self, _p: f64) -> Vec<SVector<f64, 3>> {
117-
todo!();
118-
}
119-
}
120-
121-
// TODO: Duplicate with testutils/curves.rs?
122-
// Implementation of a straight line curve for use in tests
123-
pub struct LineCurve {
124-
pub x: f64,
125-
pub y: f64,
126-
pub φ: f64,
127-
pub l: f64,
128-
}
129-
130-
impl PlanarCurve for LineCurve {
131-
fn length(&self) -> f64 {
132-
self.l
133-
}
134-
135-
fn position(&self, s: f64) -> SVector<f64, 2> {
136-
vector![
137-
self.x + s*f64::cos(self.φ),
138-
self.y + s*f64::sin(self.φ),
139-
]
140-
}
141-
142-
fn angle(&self, _s: f64) -> f64 {
143-
self.φ
144-
}
145-
146-
fn curvature(&self, _s: f64) -> f64 {
147-
0.0
148-
}
149-
}
150-
151-
// TODO: Duplicate with testutils/curves.rs?
152-
// Implementation of a circular arc curve for use in tests
153-
pub struct ArcCurve {
154-
pub x: f64,
155-
pub y: f64,
156-
pub φ: f64,
157-
pub l: f64,
158-
pub r: f64,
159-
}
160-
161-
impl PlanarCurve for ArcCurve {
162-
fn length(&self) -> f64 {
163-
self.l
164-
}
165-
166-
fn position(&self, s: f64) -> SVector<f64, 2> {
167-
vector![
168-
self.x + self.r*(f64::sin(s/self.r + self.φ) - f64::sin(self.φ)),
169-
self.y + self.r*(f64::cos(self.φ) - f64::cos(s/self.r + self.φ))
170-
]
171-
}
172-
173-
fn angle(&self, s: f64) -> f64 {
174-
self.φ + s/self.r
175-
}
176-
177-
fn curvature(&self, _s: f64) -> f64 {
178-
1.0/self.r
179-
}
18060
}

solver/virtualbow_fem/src/elements/beam/linear.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -196,26 +196,28 @@ mod tests {
196196
use approx::{assert_abs_diff_eq, assert_relative_eq};
197197
use iter_num_tools::lin_space;
198198
use nalgebra::{DMatrix, matrix, SMatrix, stack};
199-
use crate::elements::beam::geometry::{ArcCurve, CrossSection, LineCurve, PlanarCurve, RectangularSection};
199+
use crate::elements::beam::geometry::{CrossSection, PlanarCurve};
200200
use crate::elements::beam::linear::LinearBeamSegment;
201+
use crate::testutils::curves::{ArcCurve, LineCurve};
202+
use crate::testutils::sections::RectangularSection;
201203

202204
#[test]
203205
fn test_linear_stiffness_matrix_straight() {
204206
// Computes the stiffness matrix of a straight beam segment with constant cross-section
205207
// and an arbitrary starting point and -angle and compares it to the exact solution
206208
// as well as the fem approximation.
207209

208-
let angle = 0.1;
209210
let length = 0.8;
210-
let curve = LineCurve { x: 1.5, y: 2.0, φ: angle, l: length };
211-
let section = RectangularSection { w0: 0.01, h0: 0.01, w1: 0.01, h1: 0.01, ρ: 7850.0, E: 210e9, G: 80e9 };
211+
let angle = 0.1;
212+
let curve = LineCurve::new([1.5, 2.0, angle], length);
213+
let section = RectangularSection::new(7850.0, 210e9, 80e9, &[0.01], &[0.01], &[0.0]);
212214

213215
let n_elements = 100;
214216
let segment_fem = LinearBeamSegmentFEM::new(&curve, &section, 0.0, curve.length(), n_elements);
215217
let segment_num = LinearBeamSegment::new(&curve, &section, 0.0, curve.length(), &segment_fem.s_eval);
216218

217219
let C_sec = section.stiffness(0.0);
218-
let K_ref = LinearBeamSegmentFEM::element_stiffness_matrix(C_sec[(0, 0)], C_sec[(1, 1)], C_sec[(2, 2)], curve.length(), angle);
220+
let K_ref = LinearBeamSegmentFEM::element_stiffness_matrix(C_sec[(0, 0)], C_sec[(1, 1)], C_sec[(2, 2)], length, angle);
219221

220222
// Check stiffness matrices
221223
assert_relative_eq!(segment_num.K, K_ref, max_relative=1e-9);
@@ -227,7 +229,7 @@ mod tests {
227229
}
228230

229231
// Check total segment mass
230-
assert_abs_diff_eq!(segment_num.m, section.ρ*section.w0*section.h0*length, epsilon=1e-12);
232+
assert_abs_diff_eq!(segment_num.m, section.ρ*section.w[0]*section.h[0]*length, epsilon=1e-12);
231233
}
232234

233235
#[test]
@@ -236,8 +238,8 @@ mod tests {
236238
// and an arbitrary starting point and -angle and compares it to the fem approximation.
237239

238240
let length = 0.8;
239-
let curve = ArcCurve { x: 1.5, y: 2.0, φ: 0.1, l: length, r: 0.4 };
240-
let section = RectangularSection { w0: 0.01, h0: 0.01, w1: 0.01, h1: 0.01, ρ: 7850.0, E: 210e9, G: 80e9 };
241+
let curve = ArcCurve::new([1.5, 2.0, 0.1], length, 0.4);
242+
let section = RectangularSection::new(7850.0, 210e9, 80e9, &[0.01], &[0.01], &[0.0]);
241243

242244
let n_elements = 100;
243245
let segment_fem = LinearBeamSegmentFEM::new(&curve, &section, 0.0, curve.length(), n_elements);
@@ -252,7 +254,7 @@ mod tests {
252254
}
253255

254256
// Check total segment mass
255-
assert_abs_diff_eq!(segment_num.m, section.ρ*section.w0*section.h0*length, epsilon=1e-12);
257+
assert_abs_diff_eq!(segment_num.m, section.ρ*section.w[0]*section.h[0]*length, epsilon=1e-12);
256258
}
257259

258260
#[test]
@@ -261,8 +263,8 @@ mod tests {
261263
// and an arbitrary starting point and -angle and compares it to the fem approximation.
262264

263265
let length = 0.8;
264-
let curve = ArcCurve { x: 1.5, y: 2.0, φ: 0.1, l: length, r: 0.4 };
265-
let section = RectangularSection { w0: 0.01, h0: 0.01, w1: 0.005, h1: 0.005, ρ: 7850.0, E: 210e9, G: 80e9 };
266+
let curve = ArcCurve::new([1.5, 2.0, 0.1], length, 0.4);
267+
let section = RectangularSection::new(7850.0, 210e9, 80e9, &[0.01, 0.005], &[0.01, 0.005], &[0.0, 0.0]);
266268

267269
let n_elements = 100;
268270
let segment_fem = LinearBeamSegmentFEM::new(&curve, &section, 0.0, curve.length(), n_elements);
@@ -278,8 +280,8 @@ mod tests {
278280

279281
// Check total segment mass
280282
// Analytical volume from truncated pyramid: https://de.wikipedia.org/wiki/Pyramidenstumpf
281-
let A0 = section.w0*section.h0;
282-
let A1 = section.w1*section.h1;
283+
let A0 = section.w[0]*section.h[0];
284+
let A1 = section.w[1]*section.h[1];
283285
assert_abs_diff_eq!(segment_num.m, section.ρ*length/3.0*(A0 + f64::sqrt(A0*A1) + A1), epsilon=1e-12);
284286
}
285287

solver/virtualbow_fem/src/testutils/curves.rs

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,66 +3,81 @@ use std::{f64::consts::FRAC_PI_2, f64::consts::PI};
33
use nalgebra::{vector, SVector};
44
use crate::elements::beam::geometry::PlanarCurve;
55

6-
// Simple straight line of given length for use in tests
7-
pub struct Line {
8-
l: f64
6+
// Implementation of a straight line curve for use in tests
7+
pub struct LineCurve {
8+
x: f64,
9+
y: f64,
10+
φ: f64,
11+
l: f64,
912
}
1013

11-
impl Line {
12-
pub fn new(l: f64) -> Self {
14+
impl LineCurve {
15+
pub fn new(start: [f64; 3], l: f64) -> Self {
1316
Self {
14-
l
17+
x: start[0],
18+
y: start[1],
19+
φ: start[2],
20+
l,
1521
}
1622
}
1723
}
1824

19-
impl PlanarCurve for Line {
25+
impl PlanarCurve for LineCurve {
2026
fn length(&self) -> f64 {
2127
self.l
2228
}
2329

2430
fn position(&self, s: f64) -> SVector<f64, 2> {
25-
vector![s, 0.0]
31+
vector![
32+
self.x + s*f64::cos(self.φ),
33+
self.y + s*f64::sin(self.φ),
34+
]
2635
}
2736

2837
fn angle(&self, _s: f64) -> f64 {
29-
0.0
38+
self.φ
3039
}
3140

3241
fn curvature(&self, _s: f64) -> f64 {
3342
0.0
3443
}
3544
}
3645

37-
pub struct Arc {
46+
// Implementation of a circular arc curve for use in tests
47+
pub struct ArcCurve {
48+
x: f64,
49+
y: f64,
50+
φ: f64,
3851
l: f64,
39-
r: f64
52+
r: f64,
4053
}
4154

42-
impl Arc {
43-
pub fn new(l: f64, r: f64) -> Self {
55+
impl ArcCurve {
56+
pub fn new(start: [f64; 3], l: f64, r: f64) -> Self {
4457
Self {
58+
x: start[0],
59+
y: start[1],
60+
φ: start[2],
4561
l,
4662
r
4763
}
4864
}
4965
}
5066

51-
impl PlanarCurve for Arc {
67+
impl PlanarCurve for ArcCurve {
5268
fn length(&self) -> f64 {
5369
self.l
5470
}
5571

5672
fn position(&self, s: f64) -> SVector<f64, 2> {
57-
let φ = self.angle(s);
5873
vector![
59-
self.r*f64::sin(φ),
60-
self.r*(1.0 - f64::cos(φ))
74+
self.x + self.r*(f64::sin(s/self.r + self.φ) - f64::sin(self.φ)),
75+
self.y + self.r*(f64::cos(self.φ) - f64::cos(s/self.r + self.φ))
6176
]
6277
}
6378

6479
fn angle(&self, s: f64) -> f64 {
65-
s/self.r
80+
self.φ + s/self.r
6681
}
6782

6883
fn curvature(&self, _s: f64) -> f64 {
@@ -89,8 +104,8 @@ impl Wave {
89104
fn center(&self, s: f64) -> (f64, f64, f64) {
90105
let n = s/self.l;
91106

92-
let i = f64::floor(n*(self.k as f64)); // Index of the current arc
93-
let c = self.r*(1.0 + 2.0*i); // Center of the current arc
107+
let i = f64::floor(n*(self.k as f64)); // Index of the current arc
108+
let c = self.r*(1.0 + 2.0*i); // Center of the current arc
94109
let α = (s/self.l*(self.k as f64) - i)*PI; // Angle from arc center
95110

96111
(i, c, α)

solver/virtualbow_fem/src/testutils/sections.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@ use crate::elements::beam::geometry::CrossSection;
33

44
// Simple rectangular cross-section for use in tests
55

6-
pub struct Section {
7-
ρ: f64,
8-
E: f64,
9-
G: f64,
10-
w: Vec<f64>,
11-
h: Vec<f64>,
12-
y: Vec<f64>
6+
pub struct RectangularSection {
7+
pub ρ: f64,
8+
pub E: f64,
9+
pub G: f64,
10+
pub w: Vec<f64>,
11+
pub h: Vec<f64>,
12+
pub y: Vec<f64>
1313
}
1414

15-
impl Section {
15+
impl RectangularSection {
16+
// TODO: &[(width, height, offset)]?
17+
// TODO: More constructors (constant, linear, cubic)
1618
pub fn new(ρ: f64, E: f64, G: f64, w: &[f64], h: &[f64], y: &[f64]) -> Self {
1719
Self {
1820
ρ,
@@ -51,7 +53,7 @@ impl Section {
5153
}
5254
}
5355

54-
impl CrossSection for Section {
56+
impl CrossSection for RectangularSection {
5557
fn stiffness(&self, n: f64) -> SMatrix<f64, 3, 3> {
5658
let w = self.width(n);
5759
let h = self.height(n);

solver/virtualbow_fem/tests/test_01_element_properties.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use virtualbow_fem::elements::beam::beam::BeamElement;
55
use virtualbow_fem::elements::beam::linear::LinearBeamSegment;
66
use virtualbow_fem::elements::string::StringElement;
77
use virtualbow_fem::testutils::syschecks::assert_system_invariants;
8-
use virtualbow_fem::elements::beam::geometry::{ArcCurve, RectangularSection};
98
use virtualbow_fem::system::dof::DofType;
9+
use virtualbow_fem::testutils::curves::ArcCurve;
10+
use virtualbow_fem::testutils::sections::RectangularSection;
1011

1112
// These tests perform basic consistency checks on the various elements
1213
// See the utils::checks::check_system_invariants function for the details
@@ -88,8 +89,9 @@ fn beam_element() {
8889
let l = 0.6;
8990
let r = 0.4;
9091

91-
let curve = ArcCurve { x: 0.0, y: 0.0, φ: 0.0, l, r, };
92-
let section = RectangularSection { w0: 0.01, h0: 0.01, w1: 0.005, h1: 0.005, ρ: 740.0, E: 11670e6, G: 8000e6 };
92+
let curve = ArcCurve::new([0.0; 3], l, r);
93+
let section = RectangularSection::new(740.0, 11670e6, 8000e6, &[0.01, 0.005], &[0.01, 0.005], &[0.0, 0.0]);
94+
9395
let segment = LinearBeamSegment::new(&curve, &section, 0.0, l, &[]);
9496

9597
let mut element = BeamElement::new(&segment);

0 commit comments

Comments
 (0)