squid_n_core/
rc_wall_capacity.rs1#[derive(Clone, Copy, Debug)]
23pub struct RcWallShearInput {
24 pub fc: f64,
26 pub te: f64,
28 pub t: f64,
30 pub d_wall: f64,
32 pub dc_compression: f64,
34 pub tension_column_at: f64,
36 pub sigma_wh: f64,
38 pub pwh_ratio: f64,
40 pub sigma_0: f64,
42 pub shear_span_ratio: f64,
44 pub high_strength_shear_rebar: bool,
46 pub opening: Option<(f64, f64, f64, f64)>,
49}
50
51pub fn wall_opening_reduction_strength(opening: Option<(f64, f64, f64, f64)>) -> f64 {
65 match opening {
66 Some((l0, h0, h, lw)) if h > 0.0 && lw > 0.0 => {
67 let r0 = (h0 * l0 / (h * lw)).max(0.0).sqrt();
68 let reduce = r0.max(l0 / lw).max(h0 / h);
69 (1.0 - reduce).clamp(0.0, 1.0)
70 }
71 _ => 1.0,
72 }
73}
74
75pub fn wall_opening_ratio_r0(h0: f64, l0: f64, h: f64, l: f64) -> f64 {
77 if h <= 0.0 || l <= 0.0 {
78 return 0.0;
79 }
80 ((h0 * l0) / (h * l)).max(0.0).sqrt()
81}
82
83pub fn wall_opening_reduction_stiffness(r0: f64) -> f64 {
89 (1.0 - 1.25 * r0.max(0.0)).max(0.0)
90}
91
92pub fn wall_shear_ultimate(inp: &RcWallShearInput) -> f64 {
106 let d = inp.d_wall - inp.dc_compression / 2.0;
107 if inp.fc <= 0.0
108 || inp.te <= 0.0
109 || inp.d_wall <= 0.0
110 || inp.tension_column_at <= 0.0
111 || d <= 0.0
112 {
113 return 0.0;
114 }
115 let pte = 100.0 * inp.tension_column_at / (inp.te * d);
116 let j = 7.0 / 8.0 * d;
117 let shear_span_ratio = inp.shear_span_ratio.clamp(1.0, 3.0);
118 let k = if inp.high_strength_shear_rebar {
119 0.068
120 } else {
121 0.053
122 };
123 let pwh = if inp.te > 0.0 {
124 (inp.pwh_ratio.max(0.0) * inp.t / inp.te).min(0.012)
125 } else {
126 0.0
127 };
128 let denom = if inp.high_strength_shear_rebar {
129 (shear_span_ratio + 0.12).sqrt()
130 } else {
131 shear_span_ratio + 0.12
132 };
133 let concrete_term = k * pte.powf(0.23) * (inp.fc + 18.0) / denom;
134 let hoop_term = 0.85 * (pwh * inp.sigma_wh).max(0.0).sqrt();
135 let sigma_0 = inp.sigma_0.clamp(0.0, 0.4 * inp.fc);
136 let axial_term = 0.1 * sigma_0;
137 let r = wall_opening_reduction_strength(inp.opening);
138 (concrete_term + hoop_term + axial_term) * inp.te * j * r
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 fn sample() -> RcWallShearInput {
146 RcWallShearInput {
147 fc: 24.0,
148 te: 200.0,
149 t: 200.0,
150 d_wall: 4000.0,
151 dc_compression: 0.0,
152 tension_column_at: 1000.0,
153 sigma_wh: 295.0,
154 pwh_ratio: 0.0025,
155 sigma_0: 0.0,
156 shear_span_ratio: 1.0,
157 high_strength_shear_rebar: false,
158 opening: None,
159 }
160 }
161
162 #[test]
165 fn test_opening_reduction_strength_uses_max_rule() {
166 let r = wall_opening_reduction_strength(Some((1000.0, 1000.0, 3000.0, 4000.0)));
170 assert!((r - (1.0 - 1.0 / 3.0)).abs() < 1e-9, "r={}", r);
171 let r1 = 1.0 - 1.25 * (1.0f64 / 12.0).sqrt();
173 assert!((r - r1).abs() > 1e-3, "耐力用 r2 と剛性用 r1 は別式");
174 }
175
176 #[test]
177 fn test_opening_reduction_none_is_one() {
178 assert!((wall_opening_reduction_strength(None) - 1.0).abs() < 1e-12);
179 }
180
181 #[test]
183 fn test_qu_scales_with_opening_reduction() {
184 let mut inp = sample();
185 let qu0 = wall_shear_ultimate(&inp);
186 inp.opening = Some((1000.0, 1000.0, 3000.0, 4000.0));
187 let r = wall_opening_reduction_strength(inp.opening);
188 let qu1 = wall_shear_ultimate(&inp);
189 assert!(
190 (qu1 - qu0 * r).abs() < 1e-6,
191 "qu1={} qu0*r={}",
192 qu1,
193 qu0 * r
194 );
195 }
196
197 #[test]
199 fn test_qu_axial_term_clamped() {
200 let mut inp = sample();
201 let q0 = wall_shear_ultimate(&inp);
202 inp.sigma_0 = 5.0;
203 let q1 = wall_shear_ultimate(&inp);
204 assert!(q1 > q0);
205 inp.sigma_0 = 100.0; let q2 = wall_shear_ultimate(&inp);
207 let mut inp_c = sample();
208 inp_c.sigma_0 = 0.4 * 24.0;
209 assert!((q2 - wall_shear_ultimate(&inp_c)).abs() < 1e-9);
210 }
211
212 #[test]
213 fn test_qu_invalid_inputs_are_zero() {
214 let mut inp = sample();
215 inp.tension_column_at = 0.0;
216 assert_eq!(wall_shear_ultimate(&inp), 0.0);
217 let mut inp = sample();
218 inp.fc = 0.0;
219 assert_eq!(wall_shear_ultimate(&inp), 0.0);
220 }
221
222 #[test]
224 fn test_qu_matches_handcalc() {
225 let inp = sample();
226 let d: f64 = 4000.0;
227 let pte: f64 = 100.0 * 1000.0 / (200.0 * d);
228 let j = 7.0 / 8.0 * d;
229 let concrete = 0.053 * pte.powf(0.23) * (24.0 + 18.0) / (1.0 + 0.12);
230 let hoop = 0.85 * (0.0025f64 * 295.0).sqrt();
231 let expect = (concrete + hoop) * 200.0 * j;
232 assert!(
233 (wall_shear_ultimate(&inp) - expect).abs() < 1e-6,
234 "{} vs {}",
235 wall_shear_ultimate(&inp),
236 expect
237 );
238 }
239}