WPBDC 2013.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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>&nbsp;</th><th colspan=4>Compression</th><th>&nbsp;</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>&nbsp;</th>\n"
534
+ " <th>Force<br>(kN)</th><th>Strength<br>(kN)</th><th>Force/<br>Strength</th><th>Status</th>\n"
535
+ " <th>&nbsp;</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>&nbsp;</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("&nbsp;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>&nbsp;</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("&nbsp;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
+