Case Study - KEPCO engineer assesses scour at a new site
This chapter walks through a complete Op^3 session from the perspective of a third-party engineer – not the framework author – who has a concrete problem to solve. The walk-through is written as a narrative so a reader can follow the same steps end-to-end without prior Op^3 experience.
The scenario
Ji-Hoon is a geotechnical engineer at KEPCO Research Institute (KEPRI). A 4 MW-class offshore wind turbine on a tripod suction bucket foundation at a demonstration site has reported a 0.5 % drop in its first-bending natural frequency over the last six months. The operations team want to know:
Is this scour? If so, how deep?
What is the remaining lateral capacity?
Should we inspect, mitigate, or continue monitoring?
What sensor would give a tighter estimate next?
Ji-Hoon has never used Op^3 before.
Step 1 - Launch the application
pip install op3[viz]
python -m op3_viz.dash_app.app
Opens http://127.0.0.1:8050/ in Chrome. Six tabs visible.
Step 2 - Create a project
from op3_viz.project import Project, save
p = Project.new(name="Demo Site A - scour check")
p.turbine.reference = "ref_4mw_owt"
p.foundation.mode = "distributed_bnwf"
p.soil.su0_kPa = 18.0
p.soil.k_su_kPa_per_m = 1.9
save(p, "demo_site_a.op3proj")
Step 3 - Baseline eigenvalue analysis
from op3 import build_foundation, compose_tower_model
f = build_foundation(mode="distributed_bnwf", scour_depth=0.0)
model = compose_tower_model(
rotor="ref_4mw_owt",
tower="gunsan_u136_tower",
foundation=f,
damping_ratio=0.01,
)
f0 = model.eigen(n_modes=6)
The first frequency is 0.245 Hz. Site measurement is 0.243 Hz – a 0.8 % drop. Consistent with shallow scour.
Step 4 - Bayesian scour inference
Ji-Hoon clicks the Bayesian Scour tab. Posterior:
Mean scour depth: 1.2 m
90 % credible interval: [0.5, 2.1] m
Effective sample size: 145
Step 5 - Remaining capacity check
f_scoured = build_foundation(mode="distributed_bnwf", scour_depth=1.2)
model_scoured = compose_tower_model(
rotor="ref_4mw_owt",
tower="gunsan_u136_tower",
foundation=f_scoured,
damping_ratio=0.01,
)
curve = model_scoured.pushover(target_disp_m=1.0, n_steps=50)
peak_kN = max(curve["reaction_kN"])
Peak lateral capacity ~23,000 kN. 50-year storm demand 14,500 kN. Safety factor 1.59, above the design requirement of 1.30.
Preliminary conclusion: scour is real but manageable; foundation still meets the design SF.
Step 6 - VoI check
From the preposterior tree (Ch 7 Section 7.5.3):
Channel A (frequency): VoI ~ 0.22 C_ref
Channel B (strain): VoI ~ 0.48 C_ref
Channel C (statistics): VoI ~ 0.29 C_ref
Recommendation: add a strain gauge, not another accelerometer.
Step 7 - Generate report
from op3_viz.project import load
from op3_viz.report import build_report
proj = load("demo_site_a.op3proj")
produced = build_report(proj, output_dir="reports/")
Report contains project state, eigenvalue result, scour posterior, pushover curve, and a provenance footer with the Op^3 version and commit hash.
Step 8 - Compliance audit
In the Compliance and Actions tab, click Run DNV-ST-0126 audit. JSON panel fills with clause-by-clause PASS / FAIL / WAIVER.
Total time from install to signed-off report: approximately 45 minutes.
What this demonstrates
Zero prior Op^3 experience is required
Site-specific data drives every step
The decision layer turns an ambiguous signal into a concrete prescription
Reports are self-provenanced via Op^3 version + Zenodo DOI + commit hash