WPBDC 2013.1.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.
- data/ext/WPBDC/WPBDC.c +237 -0
- data/ext/WPBDC/analysis.c +672 -0
- data/ext/WPBDC/bridge.c +288 -0
- data/ext/WPBDC/bridge_cost.c +60 -0
- data/ext/WPBDC/bridge_hash.c +126 -0
- data/ext/WPBDC/bridge_parser.c +1119 -0
- data/ext/WPBDC/bridge_random.c +292 -0
- data/ext/WPBDC/bridge_sketch.c +125 -0
- data/ext/WPBDC/extconf.rb +5 -0
- data/ext/WPBDC/geometry.c +46 -0
- data/ext/WPBDC/internal.h +518 -0
- data/ext/WPBDC/judge.c +563 -0
- data/ext/WPBDC/judge.h +142 -0
- data/ext/WPBDC/loading.c +128 -0
- data/ext/WPBDC/params.c +166 -0
- data/ext/WPBDC/proto.h +98 -0
- data/ext/WPBDC/rc4.c +62 -0
- data/ext/WPBDC/rc4.h +19 -0
- data/ext/WPBDC/rc4_key.c +2 -0
- data/ext/WPBDC/rubydefs.h +75 -0
- data/ext/WPBDC/scenario.c +671 -0
- data/ext/WPBDC/sketch.c +496 -0
- data/ext/WPBDC/sketch.h +51 -0
- data/ext/WPBDC/stdafx.h +11 -0
- data/lib/WPBDC.rb +9 -0
- metadata +71 -0
@@ -0,0 +1,672 @@
|
|
1
|
+
#include "stdafx.h"
|
2
|
+
#include "internal.h"
|
3
|
+
|
4
|
+
// Analysis --------------------------------------------------------------------
|
5
|
+
|
6
|
+
// Initialize an analysis.
|
7
|
+
void init_analysis(TAnalysis *anal)
|
8
|
+
{
|
9
|
+
memset(anal, 0, sizeof(*anal));
|
10
|
+
}
|
11
|
+
|
12
|
+
// Free storage for an analysis and re-initialize it.
|
13
|
+
void clear_analysis(TAnalysis *anal)
|
14
|
+
{
|
15
|
+
Safefree(anal->x_restraint);
|
16
|
+
Safefree(anal->y_restraint);
|
17
|
+
Safefree(anal->stiffness);
|
18
|
+
Safefree(anal->displacement);
|
19
|
+
Safefree(anal->member_force);
|
20
|
+
Safefree(anal->member_strength);
|
21
|
+
Safefree(anal->max_forces);
|
22
|
+
init_analysis(anal);
|
23
|
+
}
|
24
|
+
|
25
|
+
// Max of two floats.
|
26
|
+
static __inline void fold_max(TFloat *max, TFloat x)
|
27
|
+
{
|
28
|
+
if (x > *max) *max = x;
|
29
|
+
}
|
30
|
+
|
31
|
+
// Square a float.
|
32
|
+
static __inline TFloat sqr(TFloat x)
|
33
|
+
{
|
34
|
+
return x * x;
|
35
|
+
}
|
36
|
+
|
37
|
+
// Do the analysis, filling it in along the way.
|
38
|
+
void setup_analysis(TAnalysis *anal,
|
39
|
+
TBridge *bridge,
|
40
|
+
TGeometry *geometry,
|
41
|
+
TLoading *loading,
|
42
|
+
TParams *params)
|
43
|
+
{
|
44
|
+
unsigned member_index, joint_index, load_instance_index, equation_index;
|
45
|
+
TGeometry local_geometry[1];
|
46
|
+
TParams local_params[1];
|
47
|
+
TLoading local_loading[1];
|
48
|
+
|
49
|
+
unsigned n_equations = bridge->n_joints * 2;
|
50
|
+
|
51
|
+
clear_analysis(anal);
|
52
|
+
|
53
|
+
// Punt if bridge is in error.
|
54
|
+
if (bridge->error != BridgeNoError) {
|
55
|
+
anal->error = AnalBadBridge;
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
|
59
|
+
// If caller didn't provide these things, we'll do it ourselves.
|
60
|
+
if (!geometry) {
|
61
|
+
geometry = local_geometry;
|
62
|
+
init_geometry(geometry);
|
63
|
+
setup_geometry(geometry, bridge);
|
64
|
+
}
|
65
|
+
|
66
|
+
if (!params) {
|
67
|
+
params = local_params;
|
68
|
+
init_params(params);
|
69
|
+
setup_params(params);
|
70
|
+
}
|
71
|
+
|
72
|
+
if (!loading) {
|
73
|
+
loading = local_loading;
|
74
|
+
init_loading(loading);
|
75
|
+
setup_loading(loading, bridge, geometry, params);
|
76
|
+
}
|
77
|
+
|
78
|
+
// Since calloc returns zero'ed memory, these are automagically false.
|
79
|
+
Newz(260, anal->x_restraint, bridge->n_joints + 1, TBool);
|
80
|
+
Newz(270, anal->y_restraint, bridge->n_joints + 1, TBool);
|
81
|
+
|
82
|
+
// Apply restraints.
|
83
|
+
|
84
|
+
// Assume simple support. Left side...
|
85
|
+
anal->x_restraint[1] = anal->y_restraint[1] = True;
|
86
|
+
// Right side...
|
87
|
+
anal->y_restraint[bridge->load_scenario.n_loaded_joints] = True;
|
88
|
+
|
89
|
+
// Set up index to point to joint after last loaded joint.
|
90
|
+
joint_index = bridge->load_scenario.n_loaded_joints + 1;
|
91
|
+
|
92
|
+
// Adjust for intermediate support.
|
93
|
+
if (bridge->load_scenario.support_type & INTERMEDIATE_SUPPORT) {
|
94
|
+
if (bridge->load_scenario.support_type & HI_NOT_LO) {
|
95
|
+
anal->x_restraint[bridge->load_scenario.intermediate_support_joint_no] =
|
96
|
+
anal->y_restraint[bridge->load_scenario.intermediate_support_joint_no] = True;
|
97
|
+
anal->x_restraint[1] = False;
|
98
|
+
}
|
99
|
+
else {
|
100
|
+
anal->x_restraint[joint_index] = anal->y_restraint[joint_index] = True;
|
101
|
+
joint_index++;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
// And arches
|
106
|
+
if (bridge->load_scenario.support_type & ARCH_SUPPORT) {
|
107
|
+
|
108
|
+
// Set x and y restraints for both arch supports.
|
109
|
+
anal->x_restraint[joint_index] = anal->y_restraint[joint_index] = True;
|
110
|
+
joint_index++;
|
111
|
+
anal->x_restraint[joint_index] = anal->y_restraint[joint_index] = True;
|
112
|
+
joint_index++;
|
113
|
+
|
114
|
+
// Undo simple support. Left side...
|
115
|
+
anal->x_restraint[1] = anal->y_restraint[1] = False;
|
116
|
+
// Right side...
|
117
|
+
anal->y_restraint[bridge->load_scenario.n_loaded_joints] = False;
|
118
|
+
}
|
119
|
+
|
120
|
+
// And cable supports
|
121
|
+
if (bridge->load_scenario.support_type & CABLE_SUPPORT_LEFT) {
|
122
|
+
anal->x_restraint[joint_index] = anal->y_restraint[joint_index] = True;
|
123
|
+
joint_index++;
|
124
|
+
}
|
125
|
+
if (bridge->load_scenario.support_type & CABLE_SUPPORT_RIGHT) {
|
126
|
+
anal->x_restraint[joint_index] = anal->y_restraint[joint_index] = True;
|
127
|
+
joint_index++;
|
128
|
+
}
|
129
|
+
|
130
|
+
Newz(280, anal->stiffness, n_equations * n_equations, TFloat);
|
131
|
+
|
132
|
+
// Go through this hassle to save some memory for cache coherency.
|
133
|
+
#define Stiffness(I, J) (anal->stiffness[((I)-1) * n_equations + ((J)-1)])
|
134
|
+
|
135
|
+
// Initialize stiffness matrix.
|
136
|
+
|
137
|
+
for (member_index = 1; member_index <= bridge->n_members; member_index++) {
|
138
|
+
unsigned j1 = bridge->members[member_index].start_joint;
|
139
|
+
unsigned j2 = bridge->members[member_index].end_joint;
|
140
|
+
TXSection *xs = &bridge->members[member_index].x_section;
|
141
|
+
TFloat aeoverl = params->shapes[xs->section][xs->size].area * params->materials[xs->material].E / geometry->length[member_index];
|
142
|
+
TFloat xx = aeoverl * sqr(geometry->cos_x[member_index]);
|
143
|
+
TFloat yy = aeoverl * sqr(geometry->cos_y[member_index]);
|
144
|
+
TFloat xy = aeoverl * geometry->cos_x[member_index] * geometry->cos_y[member_index];
|
145
|
+
unsigned j12m1 = 2 * j1 - 1;
|
146
|
+
unsigned j12 = 2 * j1;
|
147
|
+
unsigned j22m1 = 2 * j2 - 1;
|
148
|
+
unsigned j22 = 2 * j2;
|
149
|
+
Stiffness(j12m1, j12m1) += xx;
|
150
|
+
Stiffness(j12m1, j12) += xy;
|
151
|
+
Stiffness(j12m1, j22m1) -= xx;
|
152
|
+
Stiffness(j12m1, j22) -= xy;
|
153
|
+
Stiffness(j12, j12m1) += xy;
|
154
|
+
Stiffness(j12, j12) += yy;
|
155
|
+
Stiffness(j12, j22m1) -= xy;
|
156
|
+
Stiffness(j12, j22) -= yy;
|
157
|
+
Stiffness(j22m1, j12m1) -= xx;
|
158
|
+
Stiffness(j22m1, j12) -= xy;
|
159
|
+
Stiffness(j22m1, j22m1) += xx;
|
160
|
+
Stiffness(j22m1, j22) += xy;
|
161
|
+
Stiffness(j22, j12m1) -= xy;
|
162
|
+
Stiffness(j22, j12) -= yy;
|
163
|
+
Stiffness(j22, j22m1) += xy;
|
164
|
+
Stiffness(j22, j22) += yy;
|
165
|
+
}
|
166
|
+
|
167
|
+
// Apply support restraints.
|
168
|
+
|
169
|
+
for (load_instance_index = 1; load_instance_index <= loading->n_load_instances; load_instance_index++) {
|
170
|
+
TLoadInstance *load_instance = &loading->load_instances[load_instance_index];
|
171
|
+
for (joint_index = 1; joint_index <= bridge->n_joints; joint_index++) {
|
172
|
+
if (anal->x_restraint[joint_index]) {
|
173
|
+
unsigned i2m1 = 2 * joint_index - 1;
|
174
|
+
unsigned j;
|
175
|
+
for (j = 1; j <= n_equations; j++)
|
176
|
+
Stiffness(i2m1, j) = Stiffness(j, i2m1) = 0;
|
177
|
+
Stiffness(i2m1, i2m1) = 1;
|
178
|
+
load_instance->point_load[i2m1] = 0;
|
179
|
+
}
|
180
|
+
if (anal->y_restraint[joint_index]) {
|
181
|
+
unsigned i2 = 2 * joint_index;
|
182
|
+
unsigned j;
|
183
|
+
for (j = 1; j <= n_equations; j++)
|
184
|
+
Stiffness(i2, j) = Stiffness(j, i2) = 0;
|
185
|
+
Stiffness(i2, i2) = 1;
|
186
|
+
load_instance->point_load[i2] = 0;
|
187
|
+
}
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
191
|
+
// Invert.
|
192
|
+
|
193
|
+
for (equation_index = 1; equation_index <= n_equations; equation_index++) {
|
194
|
+
|
195
|
+
unsigned j, k;
|
196
|
+
TFloat pivr;
|
197
|
+
|
198
|
+
TFloat pivot = Stiffness(equation_index, equation_index);
|
199
|
+
if (fabs(pivot) < 0.99) {
|
200
|
+
anal->error = AnalBadPivot;
|
201
|
+
return;
|
202
|
+
}
|
203
|
+
|
204
|
+
pivr = 1.0 / pivot;
|
205
|
+
for (k = 1; k <= n_equations; k++)
|
206
|
+
Stiffness(equation_index, k) /= pivot;
|
207
|
+
|
208
|
+
for (k = 1; k <= n_equations; k++) {
|
209
|
+
if (k != equation_index) {
|
210
|
+
pivot = Stiffness(k, equation_index);
|
211
|
+
for (j = 1; j <= n_equations; j++)
|
212
|
+
Stiffness(k, j) -= Stiffness(equation_index, j) * pivot;
|
213
|
+
Stiffness(k, equation_index) = -pivot * pivr;
|
214
|
+
}
|
215
|
+
}
|
216
|
+
Stiffness(equation_index, equation_index) = pivr;
|
217
|
+
}
|
218
|
+
|
219
|
+
Newz(290, anal->displacement, n_equations * loading->n_load_instances, TFloat);
|
220
|
+
Newz(300, anal->member_force, bridge->n_members * loading->n_load_instances, TFloat);
|
221
|
+
|
222
|
+
#define Displacement(I, J) (anal->displacement[((I)-1) * loading->n_load_instances + ((J)-1)])
|
223
|
+
#define MemberForce(I, J) (anal->member_force[((I)-1) * loading->n_load_instances + ((J)-1)])
|
224
|
+
|
225
|
+
// Compute joint displacements.
|
226
|
+
|
227
|
+
for (load_instance_index = 1; load_instance_index <= loading->n_load_instances; load_instance_index++) {
|
228
|
+
unsigned i, j;
|
229
|
+
for (i = 1; i <= n_equations; i++) {
|
230
|
+
TFloat tmp = 0;
|
231
|
+
for (j = 1; j <= n_equations; j++)
|
232
|
+
tmp += Stiffness(i, j) * loading->load_instances[load_instance_index].point_load[j];
|
233
|
+
Displacement(i, load_instance_index) = tmp;
|
234
|
+
}
|
235
|
+
|
236
|
+
#ifdef TEST_PRINT
|
237
|
+
printf("\nJoint displacements for Load Case %d\n", load_instance_index);
|
238
|
+
printf("Jnt # /\\X /\\Y\n");
|
239
|
+
printf("----- ----------- -----------\n");
|
240
|
+
for (i = 1; i <= bridge->n_joints; i++) {
|
241
|
+
TFloat d1 = Displacement(2 * i - 1, load_instance_index);
|
242
|
+
TFloat d2 = Displacement(2 * i, load_instance_index);
|
243
|
+
printf("%5d %11.5lf %11.5lf\n", i, d1, d2);
|
244
|
+
}
|
245
|
+
#endif
|
246
|
+
|
247
|
+
// Compute end forces.
|
248
|
+
|
249
|
+
for (member_index = 1; member_index <= bridge->n_members; member_index++) {
|
250
|
+
TXSection *xs = &bridge->members[member_index].x_section;
|
251
|
+
TFloat ae_over_l = params->shapes[xs->section][xs->size].area *
|
252
|
+
params->materials[xs->material].E /
|
253
|
+
geometry->length[member_index];
|
254
|
+
unsigned j1 = bridge->members[member_index].start_joint;
|
255
|
+
unsigned j2 = bridge->members[member_index].end_joint;
|
256
|
+
MemberForce(member_index, load_instance_index) =
|
257
|
+
ae_over_l *
|
258
|
+
((geometry->cos_x[member_index] *
|
259
|
+
(Displacement((2 * j2 - 1), load_instance_index) -
|
260
|
+
Displacement((2 * j1 - 1), load_instance_index))) +
|
261
|
+
(geometry->cos_y[member_index] *
|
262
|
+
(Displacement((2 * j2), load_instance_index) -
|
263
|
+
Displacement((2 * j1), load_instance_index))));
|
264
|
+
}
|
265
|
+
}
|
266
|
+
|
267
|
+
// Compute member strengths.
|
268
|
+
|
269
|
+
Newz(310, anal->member_strength, bridge->n_members + 1, TMemberStrength);
|
270
|
+
|
271
|
+
for (member_index = 1; member_index <= bridge->n_members; member_index++) {
|
272
|
+
TXSection *xs = &bridge->members[member_index].x_section;
|
273
|
+
TMemberStrength *s = &anal->member_strength[member_index];
|
274
|
+
TFloat Fy = params->materials[xs->material].Fy;
|
275
|
+
TFloat area = params->shapes[xs->section][xs->size].area;
|
276
|
+
TFloat moment = params->shapes[xs->section][xs->size].moment;
|
277
|
+
TFloat radius_of_gyration = (area > 0) ? sqrt(moment / area) : 0;
|
278
|
+
TFloat slenderness = (radius_of_gyration > 0) ? geometry->length[member_index] / radius_of_gyration : 0;
|
279
|
+
|
280
|
+
// if the bridge has cable support joints or else slenderness is not excessive
|
281
|
+
if ((bridge->load_scenario.support_type & (CABLE_SUPPORT_LEFT | CABLE_SUPPORT_RIGHT)) != 0 ||
|
282
|
+
slenderness < params->slenderness_limit) {
|
283
|
+
|
284
|
+
// New lambda point method.
|
285
|
+
TFloat lambda =
|
286
|
+
sqr(geometry->length[member_index]) * Fy * area /
|
287
|
+
(9.8696044 * params->materials[xs->material].E * moment);
|
288
|
+
if (lambda <= 2.25) {
|
289
|
+
s->compressive_fail_mode = FailModeYields; // now a misnomer, but usable for debugging
|
290
|
+
s->compressive =
|
291
|
+
params->compression_resistance_factor * pow(0.66, lambda) * Fy * area;
|
292
|
+
}
|
293
|
+
else {
|
294
|
+
s->compressive_fail_mode = FailModeBuckles; // now a misnomer, but usable for debugging
|
295
|
+
s->compressive =
|
296
|
+
params->compression_resistance_factor * 0.88 * Fy * area / lambda;
|
297
|
+
}
|
298
|
+
|
299
|
+
s->tensile_fail_mode = FailModeYields;
|
300
|
+
s->tensile = params->tension_resistance_factor * Fy * area;
|
301
|
+
}
|
302
|
+
else {
|
303
|
+
s->compressive_fail_mode = s->tensile_fail_mode = FailModeSlenderness;
|
304
|
+
s->compressive = s->tensile = 0;
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
308
|
+
// Summarize results.
|
309
|
+
|
310
|
+
Newz(320, anal->max_forces, bridge->n_members + 1, TMaxForces);
|
311
|
+
|
312
|
+
anal->n_compressive_failures = 0;
|
313
|
+
anal->n_tensile_failures = 0;
|
314
|
+
for (member_index = 1; member_index <= bridge->n_members; member_index++) {
|
315
|
+
TFloat max_compression = 0;
|
316
|
+
TFloat max_tension = 0;
|
317
|
+
for (load_instance_index = 1; load_instance_index <= loading->n_load_instances; load_instance_index++) {
|
318
|
+
if (MemberForce(member_index, load_instance_index) < 0)
|
319
|
+
fold_max(&max_compression, -MemberForce(member_index, load_instance_index));
|
320
|
+
else
|
321
|
+
fold_max(&max_tension, MemberForce(member_index, load_instance_index));
|
322
|
+
}
|
323
|
+
anal->max_forces[member_index].compression = max_compression;
|
324
|
+
anal->max_forces[member_index].tension = max_tension;
|
325
|
+
|
326
|
+
if (anal->member_strength[member_index].compressive_fail_mode != FailModeSlenderness &&
|
327
|
+
max_compression < anal->member_strength[member_index].compressive)
|
328
|
+
anal->member_strength[member_index].compressive_fail_mode = FailModeNone;
|
329
|
+
else
|
330
|
+
anal->n_compressive_failures++;
|
331
|
+
|
332
|
+
if (anal->member_strength[member_index].tensile_fail_mode != FailModeSlenderness &&
|
333
|
+
max_tension < anal->member_strength[member_index].tensile)
|
334
|
+
anal->member_strength[member_index].tensile_fail_mode = FailModeNone;
|
335
|
+
else
|
336
|
+
anal->n_tensile_failures++;
|
337
|
+
}
|
338
|
+
|
339
|
+
if (geometry == local_geometry)
|
340
|
+
clear_geometry(geometry);
|
341
|
+
if (params == local_params)
|
342
|
+
clear_params(params);
|
343
|
+
if (loading == local_loading)
|
344
|
+
clear_loading(loading);
|
345
|
+
}
|
346
|
+
|
347
|
+
// Struct that describes what happened in analysis.
|
348
|
+
/*
|
349
|
+
struct analysis_result_t {
|
350
|
+
TVersion version; // WPBDC version of parsed bridge.
|
351
|
+
TScenarioIndex scenario; // WPBDC scenario number.
|
352
|
+
TTestStatus test_status; // Load test flag from uploaded file.
|
353
|
+
int status; // Summary status
|
354
|
+
TBridgeError error; // Bridge error condition.
|
355
|
+
double cost; // Cost in dollars.
|
356
|
+
char hash[HASH_SIZE]; // Bridge hash value.
|
357
|
+
};
|
358
|
+
*/
|
359
|
+
|
360
|
+
// Do an analysis. Intermediate buffers may be passed in.
|
361
|
+
// If they are, the caller is responsible for clearing them.
|
362
|
+
void do_analyze(STRING *bridge_as_string,
|
363
|
+
TAnalysis *analysis,
|
364
|
+
TBridge *bridge,
|
365
|
+
TGeometry *geometry,
|
366
|
+
TLoading *loading,
|
367
|
+
TParams *params,
|
368
|
+
struct analysis_result_t *result)
|
369
|
+
{
|
370
|
+
TAnalysis local_analysis[1];
|
371
|
+
TBridge local_bridge[1];
|
372
|
+
TGeometry local_geometry[1];
|
373
|
+
TLoading local_loading[1];
|
374
|
+
TParams local_params[1];
|
375
|
+
struct analysis_result_t local_result[1];
|
376
|
+
|
377
|
+
// User our own memory if caller didn't provide any.
|
378
|
+
// Make sure to clear at end.
|
379
|
+
if (!analysis)
|
380
|
+
analysis = local_analysis;
|
381
|
+
if (!bridge)
|
382
|
+
bridge = local_bridge;
|
383
|
+
if (!geometry)
|
384
|
+
geometry = local_geometry;
|
385
|
+
if (!loading)
|
386
|
+
loading = local_loading;
|
387
|
+
if (!params)
|
388
|
+
params = local_params;
|
389
|
+
|
390
|
+
init_analysis(analysis);
|
391
|
+
init_bridge(bridge);
|
392
|
+
init_geometry(geometry);
|
393
|
+
init_loading(loading);
|
394
|
+
init_params(params);
|
395
|
+
|
396
|
+
// Does not have to be cleared at end.
|
397
|
+
if (!result)
|
398
|
+
result = local_result;
|
399
|
+
|
400
|
+
// Fill result with zeros for cases where we find an error.
|
401
|
+
memset(result, 0, sizeof(struct analysis_result_t));
|
402
|
+
|
403
|
+
// Convert string to a bridge data structure.
|
404
|
+
parse_bridge(bridge, bridge_as_string);
|
405
|
+
|
406
|
+
// Fill in result data structure.
|
407
|
+
result->version = bridge->version;
|
408
|
+
strncpy(result->scenario_id, bridge->scenario_descriptor.id, SCENARIO_ID_SIZE);
|
409
|
+
strncpy(result->scenario_number, bridge->scenario_descriptor.number, SCENARIO_NUMBER_SIZE);
|
410
|
+
result->test_status = bridge->test_status;
|
411
|
+
result->error = bridge->error;
|
412
|
+
|
413
|
+
// Handle parse errors.
|
414
|
+
result->status = BRIDGE_OK;
|
415
|
+
if (bridge->error == BridgeBadHeader) {
|
416
|
+
result->status = BRIDGE_WRONGVERSION;
|
417
|
+
goto err_rtn;
|
418
|
+
}
|
419
|
+
if (bridge->error != BridgeNoError) {
|
420
|
+
result->status = BRIDGE_MALFORMED;
|
421
|
+
goto err_rtn;
|
422
|
+
}
|
423
|
+
if (hash_bridge(bridge, result->hash) != 0) {
|
424
|
+
result->status = BRIDGE_MALFORMED;
|
425
|
+
goto err_rtn;
|
426
|
+
}
|
427
|
+
|
428
|
+
// Run the load test.
|
429
|
+
setup_params(params);
|
430
|
+
setup_geometry(geometry, bridge);
|
431
|
+
setup_loading(loading, bridge, geometry, params);
|
432
|
+
setup_analysis(analysis, bridge, geometry, loading, params);
|
433
|
+
if (analysis->error != NoAnalError ||
|
434
|
+
analysis->n_compressive_failures > 0 ||
|
435
|
+
analysis->n_tensile_failures > 0) {
|
436
|
+
result->status = BRIDGE_FAILEDTEST;
|
437
|
+
goto err_rtn;
|
438
|
+
}
|
439
|
+
|
440
|
+
// Compute cost.
|
441
|
+
result->cost = floor(100 * bridge_cost(bridge, geometry, params) + 0.5);
|
442
|
+
|
443
|
+
// Clear any storage not tied to bufferprovided by user.
|
444
|
+
err_rtn:
|
445
|
+
if (analysis == local_analysis)
|
446
|
+
clear_analysis(analysis);
|
447
|
+
if (bridge == local_bridge)
|
448
|
+
clear_bridge(bridge);
|
449
|
+
if (geometry == local_geometry)
|
450
|
+
clear_geometry(geometry);
|
451
|
+
if (loading == local_loading)
|
452
|
+
clear_loading(loading);
|
453
|
+
if (params == local_params)
|
454
|
+
clear_params(params);
|
455
|
+
}
|
456
|
+
|
457
|
+
char *analysis_to_html(TAnalysis *analysis,
|
458
|
+
TBridge *bridge,
|
459
|
+
TGeometry *geometry,
|
460
|
+
TLoading *loading,
|
461
|
+
TParams *params,
|
462
|
+
struct analysis_result_t *result)
|
463
|
+
{
|
464
|
+
size_t rtn_size = 1024 * 8;
|
465
|
+
char *rtn, *p;
|
466
|
+
char buf[1024];
|
467
|
+
unsigned member_index;
|
468
|
+
TLoadScenario *ls;
|
469
|
+
|
470
|
+
#define Append(S) do { \
|
471
|
+
char *q = (S); \
|
472
|
+
while ((*p = *q++) != 0) \
|
473
|
+
if (++p >= rtn + rtn_size) { \
|
474
|
+
unsigned p_ofs = p - rtn; \
|
475
|
+
rtn_size *= 2; \
|
476
|
+
Renew(rtn, rtn_size, char); \
|
477
|
+
p = rtn + p_ofs; \
|
478
|
+
} \
|
479
|
+
} while (0)
|
480
|
+
|
481
|
+
#define AppendInt(X) do { \
|
482
|
+
sprintf(buf, "%d", (X)); \
|
483
|
+
Append(buf); \
|
484
|
+
} while (0)
|
485
|
+
|
486
|
+
#define AppendFloat(X,N) do { \
|
487
|
+
sprintf(buf, "%." #N "lf", (double)(X)); \
|
488
|
+
Append(buf); \
|
489
|
+
} while (0)
|
490
|
+
|
491
|
+
assert(analysis);
|
492
|
+
assert(bridge);
|
493
|
+
assert(geometry);
|
494
|
+
assert(loading);
|
495
|
+
assert(params);
|
496
|
+
// result is optional
|
497
|
+
|
498
|
+
ls = &bridge->load_scenario;
|
499
|
+
|
500
|
+
// Allocate an initial return buffer.
|
501
|
+
New(140, rtn, rtn_size, char);
|
502
|
+
p = rtn;
|
503
|
+
|
504
|
+
if (analysis->error) {
|
505
|
+
sprintf(buf, "Analysis error: %d\n", analysis->error);
|
506
|
+
Append(buf);
|
507
|
+
return rtn;
|
508
|
+
}
|
509
|
+
|
510
|
+
// Header
|
511
|
+
Append(
|
512
|
+
"<table border=1 cellspacing=0 cellpadding=2>\n"
|
513
|
+
"<tr><th colspan=15>"
|
514
|
+
);
|
515
|
+
Append("Load Test Results Report (Design Iteration #");
|
516
|
+
AppendInt(bridge->n_design_iterations);
|
517
|
+
Append(", Scenario id ");
|
518
|
+
Append(bridge->scenario_descriptor.id);
|
519
|
+
Append(", number ");
|
520
|
+
Append(bridge->scenario_descriptor.number);
|
521
|
+
Append(", Cost $");
|
522
|
+
if (result)
|
523
|
+
AppendFloat(result->cost/100, 2);
|
524
|
+
else
|
525
|
+
AppendFloat(bridge_cost(bridge, geometry, params), 2);
|
526
|
+
Append(
|
527
|
+
")</th></tr>\n"
|
528
|
+
"<tr>\n"
|
529
|
+
" <th colspan=5>Member</th><th> </th><th colspan=4>Compression</th><th> </th><th colspan=4>Tension</th>"
|
530
|
+
"</tr>\n"
|
531
|
+
"<tr>\n"
|
532
|
+
" <th>#</th><th>Size</th><th>Section</th><th>Matl.</th><th>Length<br>(m)</th>\n"
|
533
|
+
" <th> </th>\n"
|
534
|
+
" <th>Force<br>(kN)</th><th>Strength<br>(kN)</th><th>Force/<br>Strength</th><th>Status</th>\n"
|
535
|
+
" <th> </th>\n"
|
536
|
+
" <th>Force<br>(kN)</th><th>Strength<br>(kN)</th><th>Force/<br>Strength</th><th>Status</th>\n"
|
537
|
+
"</tr>\n"
|
538
|
+
);
|
539
|
+
|
540
|
+
for (member_index = 1; member_index <= bridge->n_members; member_index++) {
|
541
|
+
TXSection *xs = &bridge->members[member_index].x_section;
|
542
|
+
TFloat compressive = analysis->member_strength[member_index].compressive;
|
543
|
+
TFloat tensile = analysis->member_strength[member_index].tensile;
|
544
|
+
Append("<tr>\n"
|
545
|
+
" <td align=\"right\">");
|
546
|
+
AppendInt(member_index);
|
547
|
+
Append("</td>\n"
|
548
|
+
" <td align=\"right\">");
|
549
|
+
Append(params->shapes[xs->section][xs->size].name);
|
550
|
+
Append("</td>\n"
|
551
|
+
" <td align=\"center\">");
|
552
|
+
Append(section_str(xs->section));
|
553
|
+
Append("</td>\n"
|
554
|
+
" <td align=\"center\">");
|
555
|
+
Append(params->materials[xs->material].short_name);
|
556
|
+
Append("</td>\n"
|
557
|
+
" <td align=\"right\">");
|
558
|
+
AppendFloat(geometry->length[member_index], 2);
|
559
|
+
Append("</td>\n"
|
560
|
+
" <td> </td>\n"
|
561
|
+
" <td align=\"right\">");
|
562
|
+
AppendFloat(analysis->max_forces[member_index].compression, 1);
|
563
|
+
Append("</td>\n"
|
564
|
+
" <td align=\"right\">");
|
565
|
+
AppendFloat(compressive, 1);
|
566
|
+
Append("</td>\n"
|
567
|
+
" <td align=\"right\">");
|
568
|
+
if (compressive > 0)
|
569
|
+
AppendFloat(analysis->max_forces[member_index].compression/compressive, 4);
|
570
|
+
else
|
571
|
+
Append(" oo");
|
572
|
+
Append("</td>\n");
|
573
|
+
switch (analysis->member_strength[member_index].compressive_fail_mode) {
|
574
|
+
case FailModeNone:
|
575
|
+
Append(" <td bgcolor=\"#C0FFC0\" align=\"center\">OK");
|
576
|
+
break;
|
577
|
+
case FailModeSlenderness:
|
578
|
+
Append(" <td bgcolor=\"#FF60FF\" align=\"center\">Fail");
|
579
|
+
break;
|
580
|
+
default:
|
581
|
+
Append(" <td bgcolor=\"#FFC0C0\" align=\"center\">Fail");
|
582
|
+
break;
|
583
|
+
}
|
584
|
+
Append("</td>\n"
|
585
|
+
" <td> </td>\n"
|
586
|
+
" <td align=\"right\">");
|
587
|
+
AppendFloat(analysis->max_forces[member_index].tension, 1);
|
588
|
+
Append("</td>\n"
|
589
|
+
" <td align=\"right\">");
|
590
|
+
AppendFloat(tensile, 1);
|
591
|
+
Append("</td>\n"
|
592
|
+
" <td align=\"right\">");
|
593
|
+
if (tensile > 0)
|
594
|
+
AppendFloat(analysis->max_forces[member_index].tension/tensile, 4);
|
595
|
+
else
|
596
|
+
Append(" oo");
|
597
|
+
Append("</td>\n");
|
598
|
+
switch (analysis->member_strength[member_index].tensile_fail_mode) {
|
599
|
+
case FailModeNone:
|
600
|
+
Append(" <td bgcolor=\"#C0FFC0\" align=\"center\">OK");
|
601
|
+
break;
|
602
|
+
case FailModeSlenderness:
|
603
|
+
Append(" <td bgcolor=\"#FF60FF\" align=\"center\">Fail");
|
604
|
+
break;
|
605
|
+
default:
|
606
|
+
Append(" <td bgcolor=\"#FFC0C0\" align=\"center\">Fail");
|
607
|
+
break;
|
608
|
+
}
|
609
|
+
Append("</td>\n"
|
610
|
+
"</tr>\n");
|
611
|
+
}
|
612
|
+
Append("</table>\n");
|
613
|
+
|
614
|
+
return rtn;
|
615
|
+
}
|
616
|
+
|
617
|
+
static char *test_status_str[] = {
|
618
|
+
"Unrecorded",
|
619
|
+
"Untested",
|
620
|
+
"Failed",
|
621
|
+
"Passed",
|
622
|
+
};
|
623
|
+
|
624
|
+
void print_analysis(FILE *f,
|
625
|
+
TAnalysis *anal,
|
626
|
+
TBridge *bridge,
|
627
|
+
TGeometry *geometry,
|
628
|
+
TLoading *loading,
|
629
|
+
TParams *params)
|
630
|
+
{
|
631
|
+
unsigned member_index;
|
632
|
+
|
633
|
+
print_params(f, params);
|
634
|
+
|
635
|
+
if (anal->error) {
|
636
|
+
fprintf(f, "Analysis error: %d\n", anal->error);
|
637
|
+
return;
|
638
|
+
}
|
639
|
+
|
640
|
+
fprintf(f, "\n\nV%x bridge '%s' by '%s' scenario id=%s #=%s, status=%s, iter=%d:\n",
|
641
|
+
bridge->version,
|
642
|
+
bridge->project_id,
|
643
|
+
bridge->designer,
|
644
|
+
bridge->scenario_descriptor.id,
|
645
|
+
bridge->scenario_descriptor.number,
|
646
|
+
bridge->test_status >= 0 ? test_status_str[bridge->test_status] : "Null",
|
647
|
+
bridge->n_design_iterations);
|
648
|
+
|
649
|
+
fprintf(f,
|
650
|
+
" Mem Member Member Compression Compression Compression ? Tension Tension Tension ?\n"
|
651
|
+
" # Size Length Force Strength Ratio ? Force Strength Ratio ?\n"
|
652
|
+
"----- -------------- ---------- ----------- ----------- ----------- - ----------- ----------- ----------- -\n");
|
653
|
+
|
654
|
+
for (member_index = 1; member_index <= bridge->n_members; member_index++) {
|
655
|
+
TXSection *xs = &bridge->members[member_index].x_section;
|
656
|
+
TFloat compressive = anal->member_strength[member_index].compressive;
|
657
|
+
TFloat tensile = anal->member_strength[member_index].tensile;
|
658
|
+
fprintf(f, "%5d %14s %10.1lf %11.5lf %11.5lf %11.6lf %c %11.5lf %11.5lf %11.6lf %c\n",
|
659
|
+
member_index,
|
660
|
+
params->shapes[xs->section][xs->size].name,
|
661
|
+
geometry->length[member_index],
|
662
|
+
(double)anal->max_forces[member_index].compression,
|
663
|
+
(double)compressive,
|
664
|
+
compressive > 0 ? (double)anal->max_forces[member_index].compression/compressive : 0.0,
|
665
|
+
anal->member_strength[member_index].compressive_fail_mode == FailModeNone ? ' ' : '*',
|
666
|
+
(double)anal->max_forces[member_index].tension,
|
667
|
+
(double)tensile,
|
668
|
+
tensile > 0 ? (double)anal->max_forces[member_index].tension/tensile : 0.0,
|
669
|
+
anal->member_strength[member_index].tensile_fail_mode == FailModeNone ? ' ' : '*');
|
670
|
+
}
|
671
|
+
}
|
672
|
+
|