-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerate_technical_note.py
More file actions
409 lines (338 loc) · 18 KB
/
Copy pathgenerate_technical_note.py
File metadata and controls
409 lines (338 loc) · 18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
"""
Generate ASCE Technical Note — 7 double-spaced pages max.
Adaptive Lagrangian Refinement for Observation-Dependent
Hydraulic Simulation Using Vortex Particle Methods
"""
import os
import sys
import numpy as np
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from docx import Document
from docx.shared import Inches, Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
# ── Run experiments ───────────────────────────────────────────────────────
print("Running experiments...")
from quantum_hydraulics.research.alr_experiments import (
run_convergence, run_cost_benefit, run_sigma_field, run_scour,
CHANNEL_LENGTH, CHANNEL_WIDTH, DEPTH, Q, PIER_X, OBS_CENTER,
)
from quantum_hydraulics.research.sediment_scenarios import generate_clearwater_scour_scenario
from quantum_hydraulics.integration.sediment_transport import QuasiUnsteadyEngine
cost = run_cost_benefit()
scour_r = run_scour()
channel, sed_mix, hydrograph, sed_meta = generate_clearwater_scour_scenario()
engine = QuasiUnsteadyEngine(channel=channel, sediment_mix=sed_mix,
upstream_feed_fraction=0.0,
computational_increment_hours=5.0, bed_mixing_steps=3)
engine.set_hydrograph_durations(hydrograph)
sed_sim = engine.run()
# Ensure figures
os.system("python run_benchmark_validation.py --figures 2>nul >nul")
# ── Document setup (ASCE format) ─────────────────────────────────────────
doc = Document()
style = doc.styles["Normal"]
font = style.font
font.name = "Times New Roman"
font.size = Pt(12)
style.paragraph_format.line_spacing = 2.0 # ASCE: double-spaced
style.paragraph_format.space_after = Pt(0)
style.paragraph_format.space_before = Pt(0)
for level in range(1, 4):
hs = doc.styles[f"Heading {level}"]
hs.font.name = "Times New Roman"
hs.font.color.rgb = RGBColor(0, 0, 0)
hs.font.bold = True
hs.font.size = Pt(12)
hs.paragraph_format.line_spacing = 2.0
hs.paragraph_format.space_before = Pt(12)
hs.paragraph_format.space_after = Pt(0)
for section in doc.sections:
section.top_margin = Cm(2.54)
section.bottom_margin = Cm(2.54)
section.left_margin = Cm(2.54)
section.right_margin = Cm(2.54)
def body(text, indent=True):
p = doc.add_paragraph(text)
if indent:
p.paragraph_format.first_line_indent = Cm(1.27)
return p
def heading(text, level=1):
# ASCE: word headings, not numbered
doc.add_heading(text, level=level)
def add_table(headers, rows, caption=None):
t = doc.add_table(rows=1 + len(rows), cols=len(headers))
t.alignment = WD_TABLE_ALIGNMENT.CENTER
for j, h in enumerate(headers):
cell = t.rows[0].cells[j]
cell.text = h
for para in cell.paragraphs:
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
for run in para.runs:
run.bold = True
run.font.size = Pt(10)
run.font.name = "Times New Roman"
for i, row in enumerate(rows):
for j, val in enumerate(row):
cell = t.rows[i + 1].cells[j]
cell.text = str(val)
for para in cell.paragraphs:
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
for run in para.runs:
run.font.size = Pt(10)
run.font.name = "Times New Roman"
# ASCE: horizontal rules only for header and bottom, no vertical rules
from docx.oxml.ns import qn
tbl = t._tbl
tblPr = tbl.tblPr if tbl.tblPr is not None else tbl.makeelement(qn('w:tblPr'), {})
borders = tblPr.makeelement(qn('w:tblBorders'), {})
for border_name in ['top', 'bottom', 'insideH']:
border = borders.makeelement(qn(f'w:{border_name}'), {
qn('w:val'): 'single', qn('w:sz'): '4',
qn('w:space'): '0', qn('w:color'): '000000'
})
borders.append(border)
for border_name in ['left', 'right', 'insideV']:
border = borders.makeelement(qn(f'w:{border_name}'), {
qn('w:val'): 'none', qn('w:sz'): '0',
qn('w:space'): '0', qn('w:color'): '000000'
})
borders.append(border)
tblPr.append(borders)
if caption:
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run(caption)
run.font.size = Pt(10)
run.font.name = "Times New Roman"
def add_figure(path, caption, width=5.0):
if os.path.exists(path):
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run().add_picture(path, width=Inches(width))
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run(caption)
run.font.size = Pt(10)
run.font.name = "Times New Roman"
# ══════════════════════════════════════════════════════════════════════════
# TECHNICAL NOTE CONTENT (~1,500 words + 1 table + 1 figure)
# ══════════════════════════════════════════════════════════════════════════
# ── Title block ───────────────────────────────────────────────────────────
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run(
"Adaptive Lagrangian Refinement for Observation-Dependent "
"Hydraulic Simulation Using Vortex Particle Methods"
)
run.bold = True
run.font.size = Pt(14)
run.font.name = "Times New Roman"
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run("Michael Flynn, PE, M.ASCE")
run.font.size = Pt(12)
run.font.name = "Times New Roman"
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run("McGill Associates, PA, Asheville, North Carolina")
run.font.size = Pt(12)
run.font.name = "Times New Roman"
doc.add_paragraph() # blank line
# ── Abstract ──────────────────────────────────────────────────────────────
heading("Abstract")
body(
"This technical note presents Adaptive Lagrangian Refinement (ALR), a method "
"that enables physics-based turbulence simulation at engineering-relevant "
"locations without the cost of uniform high-resolution computation. ALR employs "
"observation-dependent resolution within a vortex particle framework using a "
"symmetrized variable-core Biot-Savart kernel (Barba et al. 2005) that conserves "
"total vortex strength to within 0.1% over full simulations. Each particle carries an adaptive "
"core size that concentrates computational effort at bridge piers, scour-prone "
"junctions, or other critical locations while maintaining coarse approximation "
"elsewhere. The underlying hydraulics use Colebrook-White friction rather than "
"Manning's equation. Observation-concentrated particle placement reaches a "
"given in-zone induced-velocity accuracy with about 4x fewer particles than "
"uniform placement (measured against a converged reference at fixed core "
"size), at the cost of larger error outside the zone. Cross-validation "
"against six established methods shows "
"correlation coefficients of 0.998 with Laursen contraction scour and 0.605 "
"with the HEC-18 pier scour equation. The method provides a complementary "
"turbulence amplification factor that augments rather than replaces these "
"empirical methods. A quasi-unsteady sediment transport demonstration with "
"fractional bedload transport, Hirano active-layer armoring, and Exner "
"morphodynamic feedback produces physically consistent clear-water degradation "
"behavior. The method integrates with PCSWMM as a post-processor for both "
"1D and 2D models, requiring no additional meshing or CFD software. The "
"complete source code and validation suite are open-source.",
indent=False,
)
# ── Introduction ──────────────────────────────────────────────────────────
heading("Introduction")
body(
"Manning's equation has served hydraulic engineering for over 130 years, but "
"it collapses complex turbulent boundary layer physics into a single empirical "
"roughness coefficient. At bridge piers, channel contractions, and culvert "
"outlets, the local turbulent velocity field determines whether bed material "
"mobilizes and at what rate. Computational fluid dynamics resolves these "
"fields, but uniform high-resolution simulation is prohibitively expensive "
"for routine screening."
)
body(
"This note introduces Adaptive Lagrangian Refinement (ALR), which makes "
"computational resolution observation-dependent. ALR is the primary "
"contribution; supporting modules for scour assessment, pier vortex shedding, "
"free-surface correction, and quasi-unsteady sediment transport are included "
"to demonstrate practical extensibility. The method integrates with PCSWMM as "
"a lightweight post-processor, filling the gap between Manning-based screening "
"and full 3D CFD."
)
# ── Methodology ───────────────────────────────────────────────────────────
heading("Methodology")
heading("Vortex Particle Method", level=2)
body(
"Particles carry 3D vorticity vectors in a Structure-of-Arrays layout. "
"Velocity is computed via the Biot-Savart integral using a symmetrized "
"regularized kernel: the effective core size for the interaction between "
"particles i and j is computed as the root-sum-square of their individual "
"core sizes, ensuring momentum conservation when core sizes vary "
"(Barba et al. 2005). Viscous diffusion uses a relaxation-based approximation "
"(not strict Particle Strength Exchange). The hydraulic engine uses Colebrook-White friction with "
"log-law velocity profiles rather than Manning's equation."
)
heading("Observation-Dependent Resolution", level=2)
body(
"Each particle's core size adapts based on distance from observation zones "
"via a Gaussian enhancement function that produces up to 5-fold resolution "
"concentration at the observation center with smooth decay to base resolution "
"at distance. Multiple observation zones are supported; the maximum "
"enhancement across all zones determines the local core size. "
f"Concentrating particle placement on the observation zone reaches a given "
f"in-zone induced-velocity accuracy with about {cost.reduction_factor:.1f}x "
f"fewer particles than uniform placement (both error curves scale as "
f"1/sqrt(N)), at the cost of {cost.out_of_zone_penalty:.1f}x larger error "
f"outside the zone."
)
# ── Validation ────────────────────────────────────────────────────────────
heading("Validation")
body(
"The method was cross-validated against six independent published methods. "
"Colebrook-White velocity was compared to Manning's equation across five "
"channel types, showing 25.5% average difference consistent with the known "
"Strickler conversion offset. The Shields parameter and Neill's critical "
"velocity trends are reproduced correctly across grain sizes, consistent "
"with established threshold behavior."
)
heading("Contraction and Pier Scour", level=2)
body(
"Contraction shear amplification was compared against Laursen live-bed scour "
"across five width ratios (0.9 to 0.5). The Pearson correlation is r = 0.998. "
"At 50% contraction, ALR predicts 3.3-fold shear amplification, consistent "
"with continuity-based velocity scaling modified by Colebrook-White friction "
"factor variation. HEC-18 pier scour correlation across five configurations "
"yields r = 0.605; all cases with significant scour are detected."
)
heading("Melville Design Curve", level=2)
body(
"The Melville (1997) dimensionless design equation was compared against "
"ALR's turbulence amplification factor across flow intensity ratios from "
"0.3 to 1.5 for a 3-ft circular pier in deep water. ALR provides a "
"consistent constriction-based shear amplification of approximately "
"1.11-fold, independent of flow intensity (Table 1). This captures the "
"geometric blockage effect. The Tier 2 vortex particle analysis yields a "
"higher amplification (1.44-fold) because it additionally captures "
"turbulence-induced Reynolds stresses via Biot-Savart induction. "
"ALR and Melville capture different physics and are complementary."
)
add_table(
["V/Vc", "Melville K_I", "ALR Amplification", "Melville ds (ft)", "Combined ds (ft)"],
[
["0.3", "0.30", "1.11", "2.16", "2.40"],
["0.5", "0.50", "1.11", "3.60", "4.00"],
["0.7", "0.70", "1.11", "5.04", "5.60"],
["0.9", "0.90", "1.11", "6.48", "7.20"],
["1.0", "1.00", "1.11", "7.20", "8.00"],
],
"Table 1. Melville (1997) design curve vs ALR amplification (b = 3 ft, y/b = 3.3).",
)
body(
"This comparison uses the published dimensionless design curve, not "
"individual measured data points from flume experiments. Direct comparison "
"against measured scour profiles requires extracting exact test conditions "
"from the original publications and is identified as future work.",
)
add_figure(
"Benchmark_figures/fig3_melville_design_curve.png",
"Fig. 1. Melville (1997) dimensionless design curve (left) and resulting "
"scour depth with and without ALR turbulence amplification factor (right) "
"for a 3-ft pier.",
width=5.5,
)
# ── Conclusions ───────────────────────────────────────────────────────────
heading("Conclusions")
body(
"Cross-validation against six independent published methods shows ALR "
"produces physically consistent trends (Laursen contraction r = 0.998, "
"HEC-18 pier scour r = 0.605). ALR provides a complementary turbulence "
"amplification factor that augments established empirical methods. "
f"Observation-concentrated placement reaches a given in-zone induced-velocity "
f"accuracy with about {cost.reduction_factor:.1f}x fewer particles than uniform "
f"placement, with total vortex strength conserved to within 0.1% via the "
f"symmetrized Biot-Savart kernel. A quasi-unsteady sediment "
f"transport demonstration produces {abs(sed_sim.total_scour_ft):.1f} ft of "
f"clear-water scour with {sed_sim.final_d50_mm / sed_sim.initial_gradation.d50_mm:.0f}-fold "
f"surface coarsening, consistent with downstream-of-dam behavior "
f"(Williams and Wolman 1984). The method integrates with PCSWMM as a "
f"post-processor requiring no additional meshing or CFD software."
)
# ── Code Availability ─────────────────────────────────────────────────────
heading("Data Availability Statement")
body(
"The complete ALR source code, validation suite, and synthetic test cases "
"are open-source under the MIT license (DOI: 10.5281/zenodo.19462126).",
indent=False,
)
# ── References (ASCE author-date style) ───────────────────────────────────
heading("References")
refs = [
'Barba, L., and Rossi, L. (2010). "Global field interpolation for particle '
'methods." J. Comput. Phys., 229(4), 1292\u20131310.',
'Colebrook, C. F. (1939). "Turbulent flow in pipes, with particular reference '
'to the transition region between smooth and rough pipe laws." J. Inst. Civ. '
'Eng., 11(4), 133\u2013156.',
'Egiazaroff, I. (1965). "Calculation of non-uniform sediment concentrations." '
'J. Hydraul. Div., 91(HY4), 225\u2013248.',
'Hirano, M. (1971). "River bed degradation with armoring." Trans. Jpn. Soc. '
'Civ. Eng., 195, 55\u201365.',
'Melville, B. W. (1997). "Pier and abutment scour: Integrated approach." '
'J. Hydraul. Eng., 123(2), 125\u2013136.',
'Meyer-Peter, E., and M\u00fcller, R. (1948). "Formulas for bed-load transport." '
'Proc., 2nd Meeting, Int. Assoc. Hydraul. Res., Stockholm, 39\u201364.',
'Richardson, E. V., and Davis, S. R. (2001). Evaluating scour at bridges, '
'4th Ed., Hydraulic Engineering Circular No. 18, FHWA-NHI-01-001, Federal '
'Highway Administration, Washington, DC.',
'Williams, G. P., and Wolman, M. G. (1984). "Downstream effects of dams on '
'alluvial rivers." Professional Paper 1286, U.S. Geological Survey, '
'Washington, DC.',
]
for ref in refs:
p = doc.add_paragraph(ref)
p.paragraph_format.first_line_indent = Cm(-1.27)
p.paragraph_format.left_indent = Cm(1.27)
p.paragraph_format.line_spacing = 2.0
for run in p.runs:
run.font.size = Pt(12)
run.font.name = "Times New Roman"
# ── Save ──────────────────────────────────────────────────────────────────
output_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"Flynn_ASCE_JHE_Technical_Note.docx",
)
doc.save(output_path)
# Word count estimate
word_count = 0
for para in doc.paragraphs:
word_count += len(para.text.split())
print(f"\nTechnical Note saved: {output_path}")
print(f"Estimated word count: {word_count}")
print(f"Target: ~1,750 words for 7 double-spaced pages")