@theerapat-s28/ts-structural-eng-tools 1.5.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +34 -3
  2. package/dist/core/constants/frame.constant.d.ts +14 -0
  3. package/dist/core/constants/frame.constant.js +18 -0
  4. package/dist/core/constants/frame.constant.js.map +1 -0
  5. package/dist/core/errors/frame-analysis.error.d.ts +33 -0
  6. package/dist/core/errors/frame-analysis.error.js +74 -0
  7. package/dist/core/errors/frame-analysis.error.js.map +1 -0
  8. package/dist/core/index.d.ts +4 -0
  9. package/dist/core/index.js +12 -1
  10. package/dist/core/index.js.map +1 -1
  11. package/dist/core/types/section-properties.type.d.ts +13 -0
  12. package/dist/core/types/section-properties.type.js +3 -0
  13. package/dist/core/types/section-properties.type.js.map +1 -0
  14. package/dist/esm/core/constants/frame.constant.js +15 -0
  15. package/dist/esm/core/constants/frame.constant.js.map +1 -0
  16. package/dist/esm/core/constants/rc.constant.js +63 -0
  17. package/dist/esm/core/constants/rc.constant.js.map +1 -0
  18. package/dist/esm/core/errors/frame-analysis.error.js +70 -0
  19. package/dist/esm/core/errors/frame-analysis.error.js.map +1 -0
  20. package/dist/esm/core/errors/rc-design.error.js +64 -0
  21. package/dist/esm/core/errors/rc-design.error.js.map +1 -0
  22. package/dist/esm/core/index.js +9 -0
  23. package/dist/esm/core/index.js.map +1 -0
  24. package/dist/esm/core/types/output-message.type.js +2 -0
  25. package/dist/esm/core/types/output-message.type.js.map +1 -0
  26. package/dist/esm/core/types/plate-jacketing.type.js +18 -0
  27. package/dist/esm/core/types/plate-jacketing.type.js.map +1 -0
  28. package/dist/esm/core/types/rc-beam.type.js +11 -0
  29. package/dist/esm/core/types/rc-beam.type.js.map +1 -0
  30. package/dist/esm/core/types/section-properties.type.js +2 -0
  31. package/dist/esm/core/types/section-properties.type.js.map +1 -0
  32. package/dist/esm/core/types/unit.type.js +2 -0
  33. package/dist/esm/core/types/unit.type.js.map +1 -0
  34. package/dist/esm/fea/frame/elements/beam-3d-stiffness.js +84 -0
  35. package/dist/esm/fea/frame/elements/beam-3d-stiffness.js.map +1 -0
  36. package/dist/esm/fea/frame/elements/fixed-end-forces.js +75 -0
  37. package/dist/esm/fea/frame/elements/fixed-end-forces.js.map +1 -0
  38. package/dist/esm/fea/frame/elements/static-condensation.js +55 -0
  39. package/dist/esm/fea/frame/elements/static-condensation.js.map +1 -0
  40. package/dist/esm/fea/frame/index.js +6 -0
  41. package/dist/esm/fea/frame/index.js.map +1 -0
  42. package/dist/esm/fea/frame/post/demand-envelope.js +97 -0
  43. package/dist/esm/fea/frame/post/demand-envelope.js.map +1 -0
  44. package/dist/esm/fea/frame/post/envelope.js +59 -0
  45. package/dist/esm/fea/frame/post/envelope.js.map +1 -0
  46. package/dist/esm/fea/frame/post/member-diagram.js +332 -0
  47. package/dist/esm/fea/frame/post/member-diagram.js.map +1 -0
  48. package/dist/esm/fea/frame/post/present-state.js +106 -0
  49. package/dist/esm/fea/frame/post/present-state.js.map +1 -0
  50. package/dist/esm/fea/frame/solver/analyze-frame.js +123 -0
  51. package/dist/esm/fea/frame/solver/analyze-frame.js.map +1 -0
  52. package/dist/esm/fea/frame/solver/boundary-conditions.js +33 -0
  53. package/dist/esm/fea/frame/solver/boundary-conditions.js.map +1 -0
  54. package/dist/esm/fea/frame/solver/combinations.js +69 -0
  55. package/dist/esm/fea/frame/solver/combinations.js.map +1 -0
  56. package/dist/esm/fea/frame/solver/frame-system.js +122 -0
  57. package/dist/esm/fea/frame/solver/frame-system.js.map +1 -0
  58. package/dist/esm/fea/frame/solver/global-assembly.js +27 -0
  59. package/dist/esm/fea/frame/solver/global-assembly.js.map +1 -0
  60. package/dist/esm/fea/frame/solver/load-case-solver.js +119 -0
  61. package/dist/esm/fea/frame/solver/load-case-solver.js.map +1 -0
  62. package/dist/esm/fea/frame/transformation/coordinate-transform.js +71 -0
  63. package/dist/esm/fea/frame/transformation/coordinate-transform.js.map +1 -0
  64. package/dist/esm/fea/frame/types/model.type.js +2 -0
  65. package/dist/esm/fea/frame/types/model.type.js.map +1 -0
  66. package/dist/esm/fea/frame/types/results.type.js +2 -0
  67. package/dist/esm/fea/frame/types/results.type.js.map +1 -0
  68. package/dist/esm/fea/frame/validation/validate-model.js +292 -0
  69. package/dist/esm/fea/frame/validation/validate-model.js.map +1 -0
  70. package/dist/esm/fea/index.js +3 -0
  71. package/dist/esm/fea/index.js.map +1 -0
  72. package/dist/esm/index.js +10 -0
  73. package/dist/esm/index.js.map +1 -0
  74. package/dist/esm/package.json +1 -0
  75. package/dist/esm/rc/general.js +32 -0
  76. package/dist/esm/rc/general.js.map +1 -0
  77. package/dist/esm/rc/index.js +5 -0
  78. package/dist/esm/rc/index.js.map +1 -0
  79. package/dist/esm/rc/rc-bar-layout.js +89 -0
  80. package/dist/esm/rc/rc-bar-layout.js.map +1 -0
  81. package/dist/esm/rc/rc-beam-design.js +320 -0
  82. package/dist/esm/rc/rc-beam-design.js.map +1 -0
  83. package/dist/esm/rc/rc-section-properties.js +55 -0
  84. package/dist/esm/rc/rc-section-properties.js.map +1 -0
  85. package/dist/esm/strengthening/index.js +4 -0
  86. package/dist/esm/strengthening/index.js.map +1 -0
  87. package/dist/esm/strengthening/rc-beam-plate-interface-bolts.js +338 -0
  88. package/dist/esm/strengthening/rc-beam-plate-interface-bolts.js.map +1 -0
  89. package/dist/esm/strengthening/rc-beam-side-plate-shear.js +381 -0
  90. package/dist/esm/strengthening/rc-beam-side-plate-shear.js.map +1 -0
  91. package/dist/esm/strengthening/rc-beam-steel-plate-jacketing.js +90 -0
  92. package/dist/esm/strengthening/rc-beam-steel-plate-jacketing.js.map +1 -0
  93. package/dist/esm/utils/index.js +5 -0
  94. package/dist/esm/utils/index.js.map +1 -0
  95. package/dist/esm/utils/math.js +30 -0
  96. package/dist/esm/utils/math.js.map +1 -0
  97. package/dist/esm/utils/matrix.js +145 -0
  98. package/dist/esm/utils/matrix.js.map +1 -0
  99. package/dist/esm/utils/merge-warning.js +11 -0
  100. package/dist/esm/utils/merge-warning.js.map +1 -0
  101. package/dist/esm/utils/skyline.js +151 -0
  102. package/dist/esm/utils/skyline.js.map +1 -0
  103. package/dist/fea/frame/elements/beam-3d-stiffness.d.ts +29 -0
  104. package/dist/fea/frame/elements/beam-3d-stiffness.js +90 -0
  105. package/dist/fea/frame/elements/beam-3d-stiffness.js.map +1 -0
  106. package/dist/fea/frame/elements/fixed-end-forces.d.ts +22 -0
  107. package/dist/fea/frame/elements/fixed-end-forces.js +79 -0
  108. package/dist/fea/frame/elements/fixed-end-forces.js.map +1 -0
  109. package/dist/fea/frame/elements/static-condensation.d.ts +19 -0
  110. package/dist/fea/frame/elements/static-condensation.js +59 -0
  111. package/dist/fea/frame/elements/static-condensation.js.map +1 -0
  112. package/dist/fea/frame/index.d.ts +9 -0
  113. package/dist/fea/frame/index.js +16 -0
  114. package/dist/fea/frame/index.js.map +1 -0
  115. package/dist/fea/frame/post/demand-envelope.d.ts +36 -0
  116. package/dist/fea/frame/post/demand-envelope.js +101 -0
  117. package/dist/fea/frame/post/demand-envelope.js.map +1 -0
  118. package/dist/fea/frame/post/envelope.d.ts +8 -0
  119. package/dist/fea/frame/post/envelope.js +63 -0
  120. package/dist/fea/frame/post/envelope.js.map +1 -0
  121. package/dist/fea/frame/post/member-diagram.d.ts +26 -0
  122. package/dist/fea/frame/post/member-diagram.js +336 -0
  123. package/dist/fea/frame/post/member-diagram.js.map +1 -0
  124. package/dist/fea/frame/post/present-state.d.ts +19 -0
  125. package/dist/fea/frame/post/present-state.js +111 -0
  126. package/dist/fea/frame/post/present-state.js.map +1 -0
  127. package/dist/fea/frame/solver/analyze-frame.d.ts +67 -0
  128. package/dist/fea/frame/solver/analyze-frame.js +128 -0
  129. package/dist/fea/frame/solver/analyze-frame.js.map +1 -0
  130. package/dist/fea/frame/solver/boundary-conditions.d.ts +14 -0
  131. package/dist/fea/frame/solver/boundary-conditions.js +37 -0
  132. package/dist/fea/frame/solver/boundary-conditions.js.map +1 -0
  133. package/dist/fea/frame/solver/combinations.d.ts +11 -0
  134. package/dist/fea/frame/solver/combinations.js +73 -0
  135. package/dist/fea/frame/solver/combinations.js.map +1 -0
  136. package/dist/fea/frame/solver/frame-system.d.ts +42 -0
  137. package/dist/fea/frame/solver/frame-system.js +126 -0
  138. package/dist/fea/frame/solver/frame-system.js.map +1 -0
  139. package/dist/fea/frame/solver/global-assembly.d.ts +17 -0
  140. package/dist/fea/frame/solver/global-assembly.js +33 -0
  141. package/dist/fea/frame/solver/global-assembly.js.map +1 -0
  142. package/dist/fea/frame/solver/load-case-solver.d.ts +34 -0
  143. package/dist/fea/frame/solver/load-case-solver.js +124 -0
  144. package/dist/fea/frame/solver/load-case-solver.js.map +1 -0
  145. package/dist/fea/frame/transformation/coordinate-transform.d.ts +21 -0
  146. package/dist/fea/frame/transformation/coordinate-transform.js +76 -0
  147. package/dist/fea/frame/transformation/coordinate-transform.js.map +1 -0
  148. package/dist/fea/frame/types/model.type.d.ts +112 -0
  149. package/dist/fea/frame/types/model.type.js +3 -0
  150. package/dist/fea/frame/types/model.type.js.map +1 -0
  151. package/dist/fea/frame/types/results.type.d.ts +134 -0
  152. package/dist/fea/frame/types/results.type.js +3 -0
  153. package/dist/fea/frame/types/results.type.js.map +1 -0
  154. package/dist/fea/frame/validation/validate-model.d.ts +18 -0
  155. package/dist/fea/frame/validation/validate-model.js +298 -0
  156. package/dist/fea/frame/validation/validate-model.js.map +1 -0
  157. package/dist/fea/index.d.ts +1 -0
  158. package/dist/fea/index.js +19 -0
  159. package/dist/fea/index.js.map +1 -0
  160. package/dist/index.d.ts +8 -4
  161. package/dist/index.js +37 -1
  162. package/dist/index.js.map +1 -1
  163. package/dist/rc/index.d.ts +2 -0
  164. package/dist/rc/index.js +3 -1
  165. package/dist/rc/index.js.map +1 -1
  166. package/dist/rc/rc-section-properties.d.ts +35 -0
  167. package/dist/rc/rc-section-properties.js +59 -0
  168. package/dist/rc/rc-section-properties.js.map +1 -0
  169. package/dist/utils/index.d.ts +4 -0
  170. package/dist/utils/index.js +19 -1
  171. package/dist/utils/index.js.map +1 -1
  172. package/dist/utils/matrix.d.ts +45 -0
  173. package/dist/utils/matrix.js +157 -0
  174. package/dist/utils/matrix.js.map +1 -0
  175. package/dist/utils/skyline.d.ts +49 -0
  176. package/dist/utils/skyline.js +161 -0
  177. package/dist/utils/skyline.js.map +1 -0
  178. package/package.json +20 -2
@@ -0,0 +1,381 @@
1
+ import { RCDesignError, Errors } from "../core/errors/rc-design.error.js";
2
+ import * as MyMath from "../utils/math.js";
3
+ import * as RCConstants from "../core/constants/rc.constant.js";
4
+ import { concreteShearCapacity, stirrupShearCapacity } from "../rc/rc-beam-design.js";
5
+ import { boltShearCapacity } from "./rc-beam-plate-interface-bolts.js";
6
+ import { hasSidePlate, } from "../core/types/plate-jacketing.type.js";
7
+ const resolveSidePlateGeometry = (plates) => {
8
+ const sides = plates.sides ?? RCConstants.DEFAULT_SIDE_PLATE_SIDES;
9
+ const Es = plates.Es ?? RCConstants.DEFAULT_PLATE_ELASTIC_MODULUS;
10
+ const strips = plates.configuration === "strips";
11
+ // A continuous plate is the limiting case of strips with wp = s, so it carries
12
+ // a coverage ratio of 1 and the vertical orientation the model assumes.
13
+ const wp = strips ? (plates.width ?? 0) : null;
14
+ const s = strips ? (plates.spacing ?? 0) : null;
15
+ const angle = strips
16
+ ? (plates.angle ?? RCConstants.DEFAULT_SIDE_PLATE_ANGLE)
17
+ : RCConstants.DEFAULT_SIDE_PLATE_ANGLE;
18
+ return {
19
+ sides,
20
+ tp: plates.thickness,
21
+ dp: plates.depth,
22
+ wp,
23
+ s,
24
+ coverageRatio: strips && s !== null && s > 0 ? wp / s : 1,
25
+ angleRad: (angle * Math.PI) / 180,
26
+ Es,
27
+ fy: plates.fy,
28
+ configuration: plates.configuration,
29
+ };
30
+ };
31
+ const validateSidePlateGeometry = (section, plates, geo) => {
32
+ if (!hasSidePlate(plates) ||
33
+ geo.fy <= 0 ||
34
+ geo.Es <= 0 ||
35
+ (geo.sides !== 1 && geo.sides !== 2) ||
36
+ section.bw <= 0 ||
37
+ section.d <= 0 ||
38
+ geo.dp > section.d) {
39
+ throw new RCDesignError(Errors.SIDE_PLATE_GEOMETRY_INVALID);
40
+ }
41
+ if (geo.configuration === "strips") {
42
+ const wp = geo.wp ?? 0;
43
+ const s = geo.s ?? 0;
44
+ // A strip wider than its pitch is a continuous plate described wrongly, and
45
+ // an inclination outside (0, 90] has no meaning in the tie model.
46
+ if (wp <= 0 || s <= 0 || wp > s || geo.angleRad <= 0 || geo.angleRad > Math.PI / 2) {
47
+ throw new RCDesignError(Errors.SIDE_PLATE_GEOMETRY_INVALID);
48
+ }
49
+ }
50
+ if (plates.anchorage !== undefined) {
51
+ const { boltsPerRow, rowSpacing } = plates.anchorage;
52
+ if (boltsPerRow <= 0 || rowSpacing <= 0) {
53
+ throw new RCDesignError(Errors.SIDE_PLATE_GEOMETRY_INVALID);
54
+ }
55
+ }
56
+ };
57
+ /**
58
+ * Shear capacity of the section before strengthening: φVc + φVs.
59
+ *
60
+ * A section with no stirrups (`Av <= 0` or `s <= 0`) contributes φVs = 0 rather
61
+ * than dividing by a zero spacing.
62
+ *
63
+ * An existing Vs beyond the ACI 318-19 22.5.1.2 maximum reaches `stirrupShearCapacity`
64
+ * as error 105 ("section too small for shear"). In the strengthening context the
65
+ * useful diagnosis is the more specific one — the web is already at its ceiling, so
66
+ * no added plate force can be developed — so it is re-thrown as 206.
67
+ */
68
+ const baselineShearCapacity = (section) => {
69
+ const concrete = concreteShearCapacity(section);
70
+ const hasStirrups = section.Av > 0 && section.s > 0;
71
+ let stirrups;
72
+ if (hasStirrups) {
73
+ try {
74
+ stirrups = stirrupShearCapacity(section);
75
+ }
76
+ catch (error) {
77
+ if (error instanceof RCDesignError && error.code === Errors.SHEAR_STRENGTH_EXCEEDS_MAX.code) {
78
+ throw new RCDesignError(Errors.STRENGTHENED_SHEAR_NO_HEADROOM);
79
+ }
80
+ throw error;
81
+ }
82
+ }
83
+ else {
84
+ stirrups = { phiVs: 0, calculationDetails: { Vs: 0 }, warnings: [] };
85
+ }
86
+ return {
87
+ phiVn: MyMath.roundToDecimalPlaces(concrete.phiVc + stirrups.phiVs, 2),
88
+ phiVc: concrete.phiVc,
89
+ phiVs: stirrups.phiVs,
90
+ Vc: concrete.calculationDetails.Vc,
91
+ Vs: stirrups.calculationDetails.Vs,
92
+ warnings: [...concrete.warnings, ...stirrups.warnings],
93
+ };
94
+ };
95
+ /**
96
+ * Design strength the bolt group can drag into the concrete across a 45° crack.
97
+ *
98
+ * The crack's horizontal projection is taken as `dp`, so the rows anchoring the
99
+ * plate beyond it number `floor(dp / rowSpacing)`, at least one — the same
100
+ * `dfv / sf` counting ACI 440.2R uses for bonded shear reinforcement.
101
+ *
102
+ * The returned value already carries the anchor φ of 0.65 from `boltShearCapacity`,
103
+ * so it is compared against the plate's φVp on a design-strength basis.
104
+ */
105
+ const anchorageCapacity = (anchorage, geo, warnings) => {
106
+ const boltResult = boltShearCapacity(anchorage.bolt);
107
+ warnings.push(...boltResult.warnings);
108
+ const exactRows = geo.dp / anchorage.rowSpacing;
109
+ const rows = Math.max(1, Math.floor(exactRows));
110
+ if (exactRows < 1) {
111
+ warnings.push({
112
+ message: `Bolt row spacing (${anchorage.rowSpacing} mm) exceeds the engaged plate depth (${geo.dp} mm); only one row was taken as crossing the assumed 45 degree crack.`,
113
+ });
114
+ }
115
+ // Same minimum anchor spacing `plateInterfaceBoltRequirement` checks, so the two
116
+ // strengthening paths hold bolt layouts to one rule.
117
+ if (anchorage.bolt.diameter !== undefined) {
118
+ const minSpacing = RCConstants.MIN_ANCHOR_SPACING_DIAMETER_FACTOR * anchorage.bolt.diameter;
119
+ if (anchorage.rowSpacing < minSpacing) {
120
+ warnings.push({
121
+ reference: "ACI318-19, 17.9.2",
122
+ message: `Bolt row spacing (${anchorage.rowSpacing} mm) is below the minimum anchor spacing of 4*da (${minSpacing} mm); use a larger pitch, a smaller bolt, or fewer rows.`,
123
+ });
124
+ }
125
+ }
126
+ return {
127
+ phiVanchorage: MyMath.roundToDecimalPlaces(geo.sides * rows * anchorage.boltsPerRow * boltResult.phiVbolt, 2),
128
+ rows,
129
+ phiVbolt: boltResult.phiVbolt,
130
+ boltsPerRow: anchorage.boltsPerRow,
131
+ };
132
+ };
133
+ /** Detailing and modelling warnings shared by both capacity models. */
134
+ const collectCommonWarnings = (section, plates, geo, warnings) => {
135
+ warnings.push({
136
+ message: "ACI 318-19 contains no provisions for steel side plates in shear; this capacity is an engineering model, not a code-sanctioned calculation, and must be confirmed against test data or a specialist review.",
137
+ });
138
+ if (geo.dp < section.d) {
139
+ warnings.push({
140
+ message: `Engaged plate depth dp (${geo.dp} mm) is less than the effective depth d (${section.d} mm); only the plated depth was taken as resisting shear.`,
141
+ });
142
+ }
143
+ // Strip pitch is checked against ACI 318-19 9.7.6.2.2 alone, in `assembleResult`
144
+ // where Vp is known. ACI 440.2R-17 11.4.2 defers to the ACI 318 limits for internal
145
+ // steel shear reinforcement rather than imposing its own, so that one check
146
+ // satisfies both documents. (The `wf + d/4` rule of ACI 440.2R-08 did not survive
147
+ // into the 2017 edition and is deliberately not applied.)
148
+ if (geo.sides === 1) {
149
+ warnings.push({
150
+ message: "A plate on one face only loads the section eccentrically; the resulting torsion and out-of-plane twist are not captured by this in-plane shear model and must be assessed separately.",
151
+ });
152
+ }
153
+ if (plates.anchorage === undefined) {
154
+ warnings.push({
155
+ message: "No anchorage was supplied, so the reported capacity assumes the plate is fully developed; the bolt group or bond must be checked separately.",
156
+ });
157
+ }
158
+ };
159
+ /**
160
+ * Applies the ACI 318-19 22.5.1.2 web crushing cap and the anchorage limit, then
161
+ * assembles the `before`/`after` result both models return.
162
+ *
163
+ * The cap `Vs + Vp <= 0.66 sqrt(fc') bw d` — mirrored for bonded shear
164
+ * strengthening by ACI 440.2R-17 11.4.3, Eq. (11.4.3) — is a property of the concrete web, so
165
+ * it limits the plate force the web can host rather than invalidating the design:
166
+ * the plate contribution is truncated to the remaining headroom and a warning
167
+ * says so. Only a section whose existing Vs already exhausts the cap throws,
168
+ * because there no strengthening at all can be developed.
169
+ *
170
+ * @param VpNominal - Plate nominal shear contribution in N, before φ and before
171
+ * any model-specific reduction factor
172
+ * @param reductionFactor - Model-specific factor applied to the plate term only
173
+ * (1.0 for web yielding, psi_f for the tension tie)
174
+ */
175
+ const assembleResult = (section, plates, geo, VpNominal, reductionFactor, method, modelDetails, warnings) => {
176
+ const before = baselineShearCapacity(section);
177
+ const baseWarnings = [...before.warnings, ...warnings];
178
+ const VpModelKN = VpNominal * reductionFactor * 0.001;
179
+ const maxVsKN = RCConstants.MAX_VS_COEFFICIENT * Math.sqrt(section.fc_) * section.bw * section.d * 0.001;
180
+ const headroomKN = maxVsKN - before.Vs;
181
+ if (headroomKN <= 0) {
182
+ throw new RCDesignError(Errors.STRENGTHENED_SHEAR_NO_HEADROOM);
183
+ }
184
+ const VpEffectiveKN = Math.min(VpModelKN, headroomKN);
185
+ const webCrushingGoverns = VpEffectiveKN < VpModelKN;
186
+ if (webCrushingGoverns) {
187
+ baseWarnings.push({
188
+ reference: "ACI318-19, 22.5.1.2",
189
+ message: `Plate contribution of ${MyMath.roundToDecimalPlaces(VpModelKN, 2)} kN truncated to the remaining web capacity of ${MyMath.roundToDecimalPlaces(headroomKN, 2)} kN, so that Vs + Vp stays within 0.66*sqrt(fc')*bw*d (${MyMath.roundToDecimalPlaces(maxVsKN, 2)} kN); a thinner or shallower plate carries the section just as far.`,
190
+ });
191
+ }
192
+ // ACI 318-19 9.7.6.2.2 halves the permitted spacing once the shear reinforcement
193
+ // carries more than 0.33*sqrt(fc')*bw*d. The plate is what usually pushes a section
194
+ // over that threshold, so the limit is keyed off Vs + Vp rather than Vs alone.
195
+ if (geo.configuration === "strips" && geo.s !== null) {
196
+ const sqrtFc = Math.sqrt(section.fc_);
197
+ const vsThresholdKN = RCConstants.VS_SPACING_THRESHOLD_COEFFICIENT * sqrtFc * section.bw * section.d * 0.001;
198
+ const highShear = before.Vs + VpEffectiveKN > vsThresholdKN;
199
+ const maxSpacing = highShear
200
+ ? Math.min(RCConstants.MAX_STIRRUP_SPACING_HIGH_VS_DEPTH_FACTOR * section.d, RCConstants.MAX_STIRRUP_SPACING_HIGH_VS)
201
+ : Math.min(RCConstants.MAX_STIRRUP_SPACING_LOW_VS_DEPTH_FACTOR * section.d, RCConstants.MAX_STIRRUP_SPACING_LOW_VS);
202
+ if (geo.s > maxSpacing) {
203
+ baseWarnings.push({
204
+ reference: "ACI318-19, 9.7.6.2.2",
205
+ message: `Strip pitch (${geo.s} mm) exceeds the maximum shear reinforcement spacing of ${MyMath.roundToDecimalPlaces(maxSpacing, 2)} mm${highShear ? `, tightened because Vs + Vp (${MyMath.roundToDecimalPlaces(before.Vs + VpEffectiveKN, 2)} kN) exceeds 0.33*sqrt(fc')*bw*d (${MyMath.roundToDecimalPlaces(vsThresholdKN, 2)} kN)` : ""}; a diagonal crack can pass between strips without crossing one.`,
206
+ });
207
+ }
208
+ }
209
+ const phiVpPlate = MyMath.roundToDecimalPlaces(RCConstants.SHEAR_STRENGTH_REDUCTION_FACTOR * VpEffectiveKN, 2);
210
+ const anchorage = plates.anchorage !== undefined ? anchorageCapacity(plates.anchorage, geo, baseWarnings) : null;
211
+ const anchorageGoverns = anchorage !== null && anchorage.phiVanchorage < phiVpPlate;
212
+ const phiVp = anchorageGoverns
213
+ ? anchorage.phiVanchorage
214
+ : phiVpPlate;
215
+ let governedBy = "plateCapacity";
216
+ if (anchorageGoverns) {
217
+ governedBy = "anchorage";
218
+ }
219
+ else if (webCrushingGoverns) {
220
+ governedBy = "webCrushing";
221
+ }
222
+ return {
223
+ method,
224
+ before: {
225
+ phiVn: before.phiVn,
226
+ calculationDetails: {
227
+ phiVc: before.phiVc,
228
+ phiVs: before.phiVs,
229
+ Vc: before.Vc,
230
+ Vs: before.Vs,
231
+ },
232
+ unit: "kN",
233
+ warnings: before.warnings,
234
+ },
235
+ after: {
236
+ phiVn: MyMath.roundToDecimalPlaces(before.phiVn + phiVp, 2),
237
+ phiVp: MyMath.roundToDecimalPlaces(phiVp, 2),
238
+ governedBy,
239
+ calculationDetails: {
240
+ phiVc: before.phiVc,
241
+ phiVs: before.phiVs,
242
+ Vp: MyMath.roundToDecimalPlaces(VpModelKN, 2),
243
+ VpEffective: MyMath.roundToDecimalPlaces(VpEffectiveKN, 2),
244
+ maxVs: MyMath.roundToDecimalPlaces(maxVsKN, 2),
245
+ headroom: MyMath.roundToDecimalPlaces(headroomKN, 2),
246
+ phiVpPlate,
247
+ phiVanchorage: anchorage !== null ? anchorage.phiVanchorage : null,
248
+ anchorageRows: anchorage !== null ? anchorage.rows : null,
249
+ phiVbolt: anchorage !== null ? anchorage.phiVbolt : null,
250
+ sides: geo.sides,
251
+ coverageRatio: MyMath.roundToDecimalPlaces(geo.coverageRatio, 4),
252
+ ...modelDetails,
253
+ },
254
+ unit: "kN",
255
+ warnings: baseWarnings,
256
+ },
257
+ };
258
+ };
259
+ /**
260
+ * Shear capacity of a beam strengthened with bolted steel side plates, treating
261
+ * each plate as a supplementary web that resists in-plane shear.
262
+ *
263
+ * The plate reaches the von Mises shear yield stress of 0.6 fy (AISC 360 G2.1):
264
+ *
265
+ * - continuous: `Vp = nSides · 0.6 fy · tp · dp`
266
+ * - strips: `Vp = nSides · 0.6 fy · tp · dp · wp / s`
267
+ *
268
+ * Strips are handled as the fraction `wp / s` of a continuous web, which is an
269
+ * approximation — a discrete strip works more as a tension tie than as a web
270
+ * panel, which is what `sidePlateShearCapacityByTensionTie` models. Run both and
271
+ * take the lower value, or call `compareSidePlateShearCapacity`.
272
+ *
273
+ * ACI 318-19 has no provisions for steel side plates in shear; a warning always
274
+ * says so.
275
+ *
276
+ * @param section - Original beam shear properties (fc_, bw, d, Av, fyt, s, optional lambda)
277
+ * @param plates - Side plate geometry, strength, layout, and optional anchorage
278
+ * @returns `before` and `after` results, each with `phiVn` (kN), `calculationDetails`,
279
+ * `unit`, and `warnings`; `after` also carries `phiVp` and `governedBy`
280
+ * @throws {RCDesignError} 205 if the plate geometry is inconsistent, 206 if the
281
+ * existing Vs leaves no headroom under the ACI 318-19 22.5.1.2 maximum, 202 if
282
+ * the supplied bolt capacity is invalid
283
+ */
284
+ export const sidePlateShearCapacityByWebYielding = (section, plates) => {
285
+ const warnings = [];
286
+ const geo = resolveSidePlateGeometry(plates);
287
+ validateSidePlateGeometry(section, plates, geo);
288
+ collectCommonWarnings(section, plates, geo, warnings);
289
+ const tauY = RCConstants.PLATE_SHEAR_YIELD_COEFFICIENT * geo.fy; // MPa
290
+ const VpNominal = geo.sides * tauY * geo.tp * geo.dp * geo.coverageRatio; // N
291
+ // AISC 360 G2.1(a): beyond this slenderness the panel buckles in shear before it
292
+ // yields. The concrete restrains the inner face, so this is a warning, not a limit.
293
+ const slenderness = geo.dp / geo.tp;
294
+ const slendernessLimit = RCConstants.PLATE_SHEAR_SLENDERNESS_COEFFICIENT * Math.sqrt(geo.Es / geo.fy);
295
+ if (slenderness > slendernessLimit) {
296
+ warnings.push({
297
+ reference: "AISC360-22, G2.1",
298
+ message: `Plate slenderness dp/tp (${MyMath.roundToDecimalPlaces(slenderness, 1)}) exceeds 2.24*sqrt(Es/fy) (${MyMath.roundToDecimalPlaces(slendernessLimit, 1)}); shear buckling may precede yielding unless the plate is stiffened or continuously restrained by the concrete.`,
299
+ });
300
+ }
301
+ return assembleResult(section, plates, geo, VpNominal, 1.0, "webYielding", {
302
+ tauY: MyMath.roundToDecimalPlaces(tauY, 2),
303
+ slenderness: MyMath.roundToDecimalPlaces(slenderness, 1),
304
+ slendernessLimit: MyMath.roundToDecimalPlaces(slendernessLimit, 1),
305
+ }, warnings);
306
+ };
307
+ /**
308
+ * Shear capacity of a beam strengthened with bolted steel side plates, treating
309
+ * each plate as a tension tie crossing the diagonal crack, following the bonded
310
+ * shear reinforcement model of ACI 440.2R-17 §11.4 with steel in place of FRP:
311
+ *
312
+ * `Vp = nSides · tp · wp · ffe · (sin α + cos α) · dp / s`
313
+ *
314
+ * with `ffe = min(fy, Es · 0.004)` — the 0.004 strain cap of 440.2R §11.4, which
315
+ * keeps the crack tight enough for aggregate interlock — and the additional
316
+ * reduction factor `psi_f = 0.85` for two-sided bonded strengthening. A continuous
317
+ * plate is the case `wp = s`, `α = 90°`.
318
+ *
319
+ * Note that for structural steel `Es · 0.004 = 800 MPa` sits above any normal `fy`,
320
+ * so the strain cap does not bind and the tie reaches yield; this model therefore
321
+ * usually returns a higher capacity than `sidePlateShearCapacityByWebYielding` for
322
+ * a continuous plate. Neither is code-sanctioned for steel side plates — a warning
323
+ * always says so.
324
+ *
325
+ * @param section - Original beam shear properties (fc_, bw, d, Av, fyt, s, optional lambda)
326
+ * @param plates - Side plate geometry, strength, layout, and optional anchorage
327
+ * @returns `before` and `after` results, each with `phiVn` (kN), `calculationDetails`,
328
+ * `unit`, and `warnings`; `after` also carries `phiVp` and `governedBy`
329
+ * @throws {RCDesignError} 205 if the plate geometry is inconsistent, 206 if the
330
+ * existing Vs leaves no headroom under the ACI 318-19 22.5.1.2 maximum, 202 if
331
+ * the supplied bolt capacity is invalid
332
+ */
333
+ export const sidePlateShearCapacityByTensionTie = (section, plates) => {
334
+ const warnings = [];
335
+ const geo = resolveSidePlateGeometry(plates);
336
+ validateSidePlateGeometry(section, plates, geo);
337
+ collectCommonWarnings(section, plates, geo, warnings);
338
+ const strainLimitedStress = geo.Es * RCConstants.SIDE_PLATE_EFFECTIVE_STRAIN_LIMIT; // MPa
339
+ const ffe = Math.min(geo.fy, strainLimitedStress);
340
+ if (ffe < geo.fy) {
341
+ warnings.push({
342
+ reference: "ACI440.2R-17, 11.4",
343
+ message: `Effective plate stress limited to ${MyMath.roundToDecimalPlaces(ffe, 2)} MPa by the 0.004 strain cap, below fy (${geo.fy} MPa); the plate does not reach yield.`,
344
+ });
345
+ }
346
+ const orientation = Math.sin(geo.angleRad) + Math.cos(geo.angleRad);
347
+ const VpNominal = geo.sides * geo.tp * ffe * geo.dp * geo.coverageRatio * orientation; // N
348
+ return assembleResult(section, plates, geo, VpNominal, RCConstants.SIDE_PLATE_REDUCTION_FACTOR_PSI, "tensionTie", {
349
+ ffe: MyMath.roundToDecimalPlaces(ffe, 2),
350
+ strainLimitedStress: MyMath.roundToDecimalPlaces(strainLimitedStress, 2),
351
+ orientation: MyMath.roundToDecimalPlaces(orientation, 4),
352
+ psi: RCConstants.SIDE_PLATE_REDUCTION_FACTOR_PSI,
353
+ }, warnings);
354
+ };
355
+ /**
356
+ * Runs both side plate shear models on the same section and reports the lower
357
+ * result as governing, which is the intended entry point when selecting a
358
+ * conservative design capacity.
359
+ *
360
+ * @param section - Original beam shear properties (fc_, bw, d, Av, fyt, s, optional lambda)
361
+ * @param plates - Side plate geometry, strength, layout, and optional anchorage
362
+ * @returns `webYielding` and `tensionTie` results plus `governing`, holding the
363
+ * lower `phiVn`, its `phiVp`, and the `method` that produced it
364
+ * @throws {RCDesignError} Whatever either model throws — see their documentation
365
+ */
366
+ export const compareSidePlateShearCapacity = (section, plates) => {
367
+ const webYielding = sidePlateShearCapacityByWebYielding(section, plates);
368
+ const tensionTie = sidePlateShearCapacityByTensionTie(section, plates);
369
+ const governing = tensionTie.after.phiVn < webYielding.after.phiVn ? tensionTie : webYielding;
370
+ return {
371
+ webYielding,
372
+ tensionTie,
373
+ governing: {
374
+ method: governing.method,
375
+ phiVn: governing.after.phiVn,
376
+ phiVp: governing.after.phiVp,
377
+ governedBy: governing.after.governedBy,
378
+ },
379
+ };
380
+ };
381
+ //# sourceMappingURL=rc-beam-side-plate-shear.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-beam-side-plate-shear.js","sourceRoot":"","sources":["../../../src/strengthening/rc-beam-side-plate-shear.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import { rectBeamMomentCapacity } from "../rc/rc-beam-design.js";
2
+ import { roundToDecimalPlaces } from "../utils/math.js";
3
+ import { isSinglyReinforced, } from "../core/types/rc-beam.type.js";
4
+ import { hasTopPlate, hasBottomPlate, } from "../core/types/plate-jacketing.type.js";
5
+ import { mergeWarnings } from "../utils/merge-warning.js";
6
+ /**
7
+ * Calculates the moment capacity of an RC beam strengthened with steel plate jacketing.
8
+ *
9
+ * Converts steel plate areas into equivalent rebar areas, adjusts the effective depth,
10
+ * and delegates to `rectBeamMomentCapacity` for the actual capacity calculation.
11
+ *
12
+ * The bottom plate is added to the tension steel and the top plate to the
13
+ * compression steel — including on an originally singly reinforced section,
14
+ * which a top plate turns into a doubly reinforced one.
15
+ *
16
+ * @param section - Original beam cross-section properties
17
+ * @param jacketedProperties - Steel plate dimensions, modulus, and yield strength
18
+ * @returns `before` and `after` results, each with `phiMn` (kN·m), `calculationDetails`,
19
+ * `unit`, and `warnings`
20
+ * @throws {RCDesignError} 102 if either section is not tension controlled — the
21
+ * added plate steel can push a jacketed section out of the tension-controlled region
22
+ */
23
+ export const calculateSteelJacketedBeamMomentCapacity = (section, jacketedProperties) => {
24
+ const warnings = [];
25
+ // Calculate the moment capacity of the original (before strengthening) section
26
+ const originalResult = rectBeamMomentCapacity(section);
27
+ // Convert steel plate strength to the same as rebar strength
28
+ const n = jacketedProperties.fy / section.fy;
29
+ // A plate only counts when both its width and thickness are positive, so a
30
+ // bottom-only jacket may omit the top plate fields entirely.
31
+ const topSteelThickness = hasTopPlate(jacketedProperties)
32
+ ? jacketedProperties.topSteelThickness
33
+ : 0;
34
+ const bottomSteelThickness = hasBottomPlate(jacketedProperties)
35
+ ? jacketedProperties.bottomSteelThickness
36
+ : 0;
37
+ // Calculate the effective area of the steel plates converted to rebar.
38
+ const plateTopSteelArea = hasTopPlate(jacketedProperties)
39
+ ? n * jacketedProperties.topSteelWidth * topSteelThickness
40
+ : 0;
41
+ const plateBottomSteelArea = hasBottomPlate(jacketedProperties)
42
+ ? n * jacketedProperties.bottomSteelWidth * bottomSteelThickness
43
+ : 0;
44
+ // Existing compression steel, if any. A section the type guard reports as
45
+ // singly reinforced contributes nothing here, but a top plate still can.
46
+ const existingAs_ = isSinglyReinforced(section) ? 0 : section.As_;
47
+ const existingD_ = isSinglyReinforced(section) ? 0 : section.d_;
48
+ // Depths stay measured from the extreme concrete compression fibre — the top
49
+ // face of the concrete — so the equivalent rectangular stress block that
50
+ // `rectBeamMomentCapacity` lays down from that datum covers concrete only.
51
+ // Existing depths are therefore unchanged; the bottom plate sits below the
52
+ // soffit and the top plate above the datum, at a negative depth.
53
+ const newD = roundToDecimalPlaces((section.d * section.As + (section.h + bottomSteelThickness / 2) * plateBottomSteelArea) /
54
+ (section.As + plateBottomSteelArea), 3);
55
+ const jacketedAs_ = existingAs_ + plateTopSteelArea;
56
+ let modifiedSection;
57
+ if (jacketedAs_ <= 0) {
58
+ // No compression steel and no top plate — the jacketed section stays singly
59
+ // reinforced.
60
+ modifiedSection = {
61
+ ...section,
62
+ As: section.As + plateBottomSteelArea,
63
+ d: newD,
64
+ };
65
+ }
66
+ else {
67
+ // A top plate acts as compression steel, so a bare singly reinforced
68
+ // section becomes doubly reinforced once one is added. Its centroid is half
69
+ // a plate thickness above the concrete face, hence the negative depth.
70
+ const newD_ = roundToDecimalPlaces((existingD_ * existingAs_ + (-topSteelThickness / 2) * plateTopSteelArea) / jacketedAs_, 3);
71
+ modifiedSection = {
72
+ ...section,
73
+ As: section.As + plateBottomSteelArea,
74
+ As_: jacketedAs_,
75
+ d: newD,
76
+ d_: newD_,
77
+ };
78
+ }
79
+ // Calculate the moment capacity of the modified (after strengthening) section
80
+ let jacketedResult = rectBeamMomentCapacity(modifiedSection);
81
+ jacketedResult = {
82
+ ...jacketedResult,
83
+ warnings: mergeWarnings(jacketedResult.warnings, warnings),
84
+ };
85
+ return {
86
+ before: originalResult,
87
+ after: jacketedResult,
88
+ };
89
+ };
90
+ //# sourceMappingURL=rc-beam-steel-plate-jacketing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-beam-steel-plate-jacketing.js","sourceRoot":"","sources":["../../../src/strengthening/rc-beam-steel-plate-jacketing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { solveQuadratic, roundToDecimalPlaces } from "./math.js";
2
+ export { mergeWarnings } from "./merge-warning.js";
3
+ export { zeros, identity, transpose, matMul, matVec, choleskyFactor, choleskySolveFactored, choleskySolve, solveLinearSystem, } from "./matrix.js";
4
+ export { createSkyline, skylineAdd, skylineGet, skylineSize, skylineFactor, skylineSolve, reverseCuthillMcKee, } from "./skyline.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EACL,KAAK,EACL,QAAQ,EACR,SAAS,EACT,MAAM,EACN,MAAM,EACN,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,aAAa,EACb,UAAU,EACV,UAAU,EACV,WAAW,EACX,aAAa,EACb,YAAY,EACZ,mBAAmB,GACpB,MAAM,WAAW,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Solves the quadratic equation ax² + bx + c = 0.
3
+ *
4
+ * @param a - Coefficient of x²
5
+ * @param b - Coefficient of x
6
+ * @param c - Constant term
7
+ * @returns Array of real roots (empty if discriminant < 0)
8
+ */
9
+ export const solveQuadratic = (a, b, c) => {
10
+ const discriminant = b * b - 4 * a * c;
11
+ if (discriminant < 0) {
12
+ return [];
13
+ }
14
+ const sqrtDiscriminant = Math.sqrt(discriminant);
15
+ const root1 = (-b + sqrtDiscriminant) / (2 * a);
16
+ const root2 = (-b - sqrtDiscriminant) / (2 * a);
17
+ return [root1, root2];
18
+ };
19
+ /**
20
+ * Rounds a number to a specified number of decimal places.
21
+ *
22
+ * @param value - The number to round
23
+ * @param decimalPlaces - Number of decimal places to keep
24
+ * @returns The rounded number
25
+ */
26
+ export const roundToDecimalPlaces = (value, decimalPlaces) => {
27
+ const factor = Math.pow(10, decimalPlaces);
28
+ return Math.round(value * factor) / factor;
29
+ };
30
+ //# sourceMappingURL=math.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.js","sourceRoot":"","sources":["../../../src/utils/math.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS,EAAY,EAAE;IAC1E,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACxB,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAa,EAAE,aAAqB,EAAU,EAAE;IACnF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;IAC3C,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;AAC7C,CAAC,CAAC"}