squid_n_core/
rc_rebar_geom.rs1use crate::section_shape::{BarSet, RcRebar, ShearBar};
12
13pub fn rebar_layer_clear(main: &BarSet) -> f64 {
15 25.0_f64.max(1.5 * main.dia)
16}
17
18pub fn rebar_layer_spacing(main: &BarSet) -> f64 {
20 main.dia + rebar_layer_clear(main)
21}
22
23pub fn rebar_layer_depth_from_edge(cover: f64, shear_dia: f64, main: &BarSet, layer: u32) -> f64 {
29 let k1 = cover + shear_dia + main.dia / 2.0;
30 if layer == 0 {
31 return k1;
32 }
33 k1 + layer as f64 * rebar_layer_spacing(main)
34}
35
36pub fn tension_dt(cover: f64, shear_dia: f64, main: &BarSet) -> f64 {
42 let layers = main.layers.max(1);
43 if layers == 1 {
44 return rebar_layer_depth_from_edge(cover, shear_dia, main, 0);
45 }
46 let d0 = rebar_layer_depth_from_edge(cover, shear_dia, main, 0);
47 let d_last = rebar_layer_depth_from_edge(cover, shear_dia, main, layers - 1);
48 0.5 * (d0 + d_last)
49}
50
51pub fn rebar_tension_dt(rebar: &RcRebar) -> f64 {
53 tension_dt(rebar.cover, rebar.shear.dia, &rebar.main_x)
54}
55
56pub fn tension_effective_depth(d: f64, cover: f64, shear_dia: f64, main: &BarSet) -> f64 {
58 (d - tension_dt(cover, shear_dia, main)).max(0.0)
59}
60
61pub fn rebar_effective_depth(d: f64, rebar: &RcRebar) -> f64 {
63 (d - rebar_tension_dt(rebar)).max(0.0)
64}
65
66pub fn pw_ratio(shear: &ShearBar, b: f64) -> f64 {
68 if shear.pitch <= 0.0 || b <= 0.0 {
69 return 0.0;
70 }
71 crate::section_shape::shear_legs_area(shear) / (b * shear.pitch)
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use crate::section_shape::ShearBar;
78
79 fn rebar(layers: u32) -> RcRebar {
80 let main = BarSet {
81 count: 6,
82 dia: 25.0,
83 layers,
84 };
85 RcRebar {
86 main_x: main.clone(),
87 main_y: main,
88 shear: ShearBar {
89 dia: 10.0,
90 pitch: 100.0,
91 legs: 2,
92 },
93 cover: 40.0,
94 }
95 }
96
97 #[test]
98 fn test_tension_dt_single_layer() {
99 let bar = BarSet {
100 count: 4,
101 dia: 22.0,
102 layers: 1,
103 };
104 let dt = tension_dt(40.0, 10.0, &bar);
105 assert!((dt - (40.0 + 10.0 + 11.0)).abs() < 1e-9);
106 }
107
108 #[test]
109 fn test_tension_dt_two_layers() {
110 let bar = BarSet {
111 count: 8,
112 dia: 22.0,
113 layers: 2,
114 };
115 let cover = 40.0;
116 let shear_dia = 10.0;
117 let k1 = cover + shear_dia + bar.dia / 2.0;
118 let k_prime = 25.0_f64.max(1.5 * bar.dia);
119 let k2 = k1 + bar.dia / 2.0 + k_prime + bar.dia / 2.0;
120 let expected = (k1 + k2) / 2.0;
121 let dt = tension_dt(cover, shear_dia, &bar);
122 assert!((dt - expected).abs() < 1e-6);
123 }
124
125 #[test]
126 fn test_rebar_tension_dt_considers_layers() {
127 let k1 = 40.0 + 10.0 + 25.0 / 2.0;
128 assert!((rebar_tension_dt(&rebar(1)) - k1).abs() < 1e-9);
129
130 let two = rebar_tension_dt(&rebar(2));
131 assert!((two - (k1 + 62.5 / 2.0)).abs() < 1e-9, "dt(2段)={two}");
132 assert!(two > k1);
133
134 let r = rebar(2);
135 assert!((two - tension_dt(r.cover, r.shear.dia, &r.main_x)).abs() < 1e-12);
136 }
137
138 #[test]
139 fn test_layer_depth_matches_tension_dt_average() {
140 let bar = BarSet {
141 count: 4,
142 dia: 13.0, layers: 2,
144 };
145 let cover = 40.0;
146 let shear = 10.0;
147 let d0 = rebar_layer_depth_from_edge(cover, shear, &bar, 0);
148 let d1 = rebar_layer_depth_from_edge(cover, shear, &bar, 1);
149 let s = rebar_layer_spacing(&bar);
150 assert!((s - (13.0 + 25.0)).abs() < 1e-12);
151 assert!((d1 - d0 - s).abs() < 1e-12);
152 assert!((tension_dt(cover, shear, &bar) - 0.5 * (d0 + d1)).abs() < 1e-12);
153 }
154
155 #[test]
156 fn test_pw_ratio_zero_pitch() {
157 let shear = ShearBar {
158 dia: 10.0,
159 pitch: 0.0,
160 legs: 2,
161 };
162 assert_eq!(pw_ratio(&shear, 400.0), 0.0);
163 }
164}