Skip to content

Commit d54ef4d

Browse files
committed
Merge branch 'docs/user-guides' into docs/naca0021
2 parents 3cab1b9 + 555396a commit d54ef4d

6 files changed

Lines changed: 122 additions & 11 deletions

File tree

‎.github/workflows/docs-check.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ jobs:
4040
persist-credentials: false
4141
- name: Get release tags for migration reference
4242
run: git -C su2 fetch --quiet --filter=blob:none https://github.com/su2code/SU2.git 'refs/tags/v7.*:refs/tags/v7.*' 'refs/tags/v8.*:refs/tags/v8.*'
43+
- name: Setup Node for search checks
44+
uses: actions/setup-node@v4
45+
with:
46+
node-version: '22'
47+
- name: Check search behavior
48+
run: node site/tools/test_search.js
4349
- name: Setup Ruby and locked gems
4450
uses: ruby/setup-ruby@v1
4551
with:

‎README.md‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ Developer pages and generated references are overlaid from the SU2 repository. E
1414

1515
Use Ruby **3.3.12** from `.ruby-version` and Bundler **2.4.22** with the tracked `Gemfile.lock`. The combined build entry point is `Docs/website/tools/build_docs.py` in the SU2 checkout. Its README, `Docs/website/README.md`, gives the local commands and output-directory rules. It builds and checks the same staged site locally and in CI, including red preview highlighting when `--mark-changes` is passed.
1616

17-
`.github/workflows/docs-check.yml` checks `docs_site` pushes and pull requests against SU2 `docs_site` and uploads `docs-preview`. A manual run accepts an exact SU2 SHA. It checks internal references, search coverage, documented option names and source descriptions for new options. Historical findings are tracked explicitly in SU2's `check-baseline.json`; new findings fail.
17+
`.github/workflows/docs-check.yml` checks pushes to `docs_site`, `docs/user-guides` and `docs/naca0021`, and pull requests targeting `develop`, `docs_site` or `docs/user-guides`. It uses SU2 branch `docs/developer-guides` by default and uploads `docs-preview`. A manual run accepts an exact SU2 SHA through `su2_ref`. It checks internal references, search coverage, documented option names and source descriptions for new options. Historical findings are tracked explicitly in SU2's `check-baseline.json`; new findings fail.
1818

19-
Website-only changes do not publish directly to SU2's Pages site. After their checks pass, start **Docs Website** in `rois1995/SU2`, with the website commit SHA as `site_ref`. The result records both commit SHAs and tool versions in `build-info.json` and check results in `docs-check.json`. This avoids requiring a token with cross-repository write access for website pull requests.
19+
Search behavior is checked separately with Node.js 22: run `node tools/test_search.js` from this repository. CI runs the same check before building the site. No npm packages are needed.
2020

21-
Push development changes only to `rois1995/su2code.github.io`, branch `docs_site`; official-repository pushes are disabled.
21+
Website-only changes do not publish directly to SU2's Pages site. Publishing is currently restricted to `docs_site` in `rois1995/SU2`. First ensure that branch contains the reviewed SU2 tools, then start **Docs Website** there with the reviewed website commit SHA as `site_ref`. Check both recorded source revisions against the reviewed build before accepting the deployment. The result records both commit SHAs and tool versions in `build-info.json` and check results in `docs-check.json`. This avoids requiring a token with cross-repository write access for website pull requests.
22+
23+
The current preview uses the `rois1995` forks. Website PR branches are `docs/user-guides` and `docs/naca0021`; `docs_site` is the existing published preview branch. Submit upstream changes through pull requests to `develop`. Do not push development branches directly to the official repositories.

‎_config.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ exclude:
3737
- .idea/
3838
- .gitignore
3939
- README.md
40+
- tools/
4041
timezone: Europe/Berlin
4142
defaults:
4243
- scope:

‎_docs_v7/Physical-Definition.md‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ SU2 offers different ways of setting and computing this definition. This documen
2424
- [Thermodynamic and Gauge Pressure](#thermodynamic-and-gauge-pressure)
2525
- [Initial State and Non-Dimensionalization](#initial-state-and-non-dimensionalization)
2626
- [Turbulence Models](#turbulence-models)
27+
- [Spalart-Allmaras (SA)](#spalart-allmaras-sa)
28+
- [Shear Stress Transport (SST)](#shear-stress-transport-sst)
2729
- [Transition Models](#transition-models)
2830

2931
---
@@ -125,7 +127,7 @@ The NEMO solvers require a specification of thermochemical nonequilibrium librar
125127

126128
A chemistry model, consisting of a set of flow species, thermochemical properties, and chemical reactions, is specified using `GAS_MODEL`. The names of these models are specific to the thermochemical library. If using the `SU2_NONEQ` option the choices are `ARGON`, `N2`, `AIR-5`, and `AIR-7`.
127129

128-
Free-stream mass fractions must also be specified in list using the option `GAS_COMPOSITION`. The mass fractions are specified as decimal values in the order of the species in the gas model. For example, an AIR-5 mixture of 77% oxygen and 23% nitrogen would be expressed as (0.77, 0.23, 0.00, 0.00, 0.00).
130+
Free-stream mass fractions must also be specified in list using the option `GAS_COMPOSITION`. The mass fractions are specified as decimal values in the order of the species in the gas model. With `FLUID_MODEL= SU2_NONEQ` and `GAS_MODEL= AIR-5`, the species order is N2, O2, NO, N, O. A mixture of 77% nitrogen and 23% oxygen by mass is therefore `GAS_COMPOSITION= (0.77, 0.23, 0.00, 0.00, 0.00)`.
129131

130132
## Transport Coefficient Model (Thermochemical Nonequilibrium) ##
131133

@@ -163,7 +165,14 @@ The reference values $$\rho_{ref}, T_{ref}, v_{ref}$$ equal the initial state va
163165

164166
Set `SOLVER= RANS` or `SOLVER= INC_RANS`, and choose the model with `KIND_TURB_MODEL= SA` or `KIND_TURB_MODEL= SST`.
165167
Choose the variant with `SA_OPTIONS` or `SST_OPTIONS`. The defaults are SA without the ft2 term and SST-2003m.
166-
[Turbulence Models](../Turbulence-Models/) lists all variants, the free-stream and inlet values, and where SU2 differs from the literature.
168+
169+
### Spalart-Allmaras (SA)
170+
171+
See [SA variants and inlet values](../Turbulence-Models/#spalart-allmaras-sa), including the differences between SU2 and the published models.
172+
173+
### Shear Stress Transport (SST)
174+
175+
See [SST variants and inlet values](../Turbulence-Models/#shear-stress-transport-sst), including the differences between SU2 and the published models.
167176

168177
## Transition Models ##
169178

‎search.html‎

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77

88
<div class="container">
99
<h1>Search</h1>
10-
<p>Search the user guide, the tutorials and the V&amp;V pages. All words must appear on the page.</p>
10+
<p>Search the user guide, the tutorials and the V&amp;V pages. All terms of two or more characters must appear on the page; shorter terms are ignored.</p>
11+
<label for="search-box" class="sr-only">Search documentation</label>
1112
<input id="search-box" type="search" class="form-control" placeholder="For example: CFL_ADAPT, wall function, transition" autofocus>
12-
<p id="search-count"></p>
13+
<p id="search-count" role="status"></p>
1314
<ol id="search-results"></ol>
1415
</div>
1516

@@ -19,6 +20,7 @@ <h1>Search</h1>
1920
var count = document.getElementById("search-count");
2021
var list = document.getElementById("search-results");
2122
var pages = null;
23+
var loadError = false;
2224
var names = { docs_v7: "Docs", tutorials: "Tutorials", vandv: "V&V" };
2325

2426
function escapeHtml(s) {
@@ -35,7 +37,14 @@ <h1>Search</h1>
3537
function run() {
3638
var words = box.value.toLowerCase().split(/\s+/).filter(function (w) { return w.length > 1; });
3739
list.innerHTML = "";
38-
if (!pages || words.length === 0) { count.textContent = ""; return; }
40+
if (!pages) {
41+
count.textContent = loadError ? "Search could not load. Reload this page to try again." : "Loading search...";
42+
return;
43+
}
44+
if (words.length === 0) {
45+
count.textContent = box.value.trim() ? "Enter a search term with at least two characters." : "";
46+
return;
47+
}
3948
var hits = [];
4049
pages.forEach(function (p) {
4150
var title = p.title.toLowerCase(), text = p.text.toLowerCase(), score = 0;
@@ -56,10 +65,19 @@ <h1>Search</h1>
5665
});
5766
}
5867

59-
fetch("{{ '/search.json' | relative_url }}").then(function (r) { return r.json(); }).then(function (data) {
68+
var q = new URLSearchParams(location.search).get("q");
69+
if (q) box.value = q;
70+
run();
71+
fetch("{{ '/search.json' | relative_url }}").then(function (r) {
72+
if (!r.ok) throw new Error("Search index request failed");
73+
return r.json();
74+
}).then(function (data) {
75+
if (!Array.isArray(data)) throw new Error("Invalid search index");
6076
pages = data;
61-
var q = new URLSearchParams(location.search).get("q");
62-
if (q) box.value = q;
77+
run();
78+
}).catch(function () {
79+
pages = null;
80+
loadError = true;
6381
run();
6482
});
6583
box.addEventListener("input", run);

‎tools/test_search.js‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"use strict";
2+
3+
const assert = require("node:assert/strict");
4+
const fs = require("node:fs");
5+
const path = require("node:path");
6+
const vm = require("node:vm");
7+
8+
const html = fs.readFileSync(path.join(__dirname, "../search.html"), "utf8");
9+
const script = html.match(/<script>([\s\S]*?)<\/script>/)[1];
10+
const pages = [
11+
{ title: "Wall treatment", text: "wall function transition", url: "/SU2/docs_v7/Wall-Treatment/", section: "docs_v7" },
12+
{ title: "Omega", text: "omega equation", url: "/SU2/docs_v7/Turbulence-Models/", section: "docs_v7" }
13+
];
14+
15+
function openSearch(fetch, query = "") {
16+
const box = { value: "", addEventListener: (_, callback) => { box.run = callback; } };
17+
const count = { textContent: "" };
18+
const list = { rows: [], appendChild: row => list.rows.push(row.innerHTML) };
19+
Object.defineProperty(list, "innerHTML", { set: () => { list.rows = []; } });
20+
const document = {
21+
getElementById: id => ({ "search-box": box, "search-count": count, "search-results": list })[id],
22+
createElement: () => ({ innerHTML: "" })
23+
};
24+
vm.runInNewContext(script, { document, fetch, URLSearchParams, location: { search: query } });
25+
return { box, count, list, search: query => { box.value = query; box.run(); } };
26+
}
27+
28+
const settled = () => new Promise(resolve => setImmediate(resolve));
29+
30+
(async () => {
31+
let resolve;
32+
const page = openSearch(() => new Promise(done => { resolve = done; }), "?q=wall+function");
33+
assert.match(page.count.textContent, /loading/i);
34+
assert.equal(page.box.value, "wall function");
35+
page.search("omega");
36+
assert.match(page.count.textContent, /loading/i);
37+
resolve({ ok: true, json: () => Promise.resolve(pages) });
38+
await settled();
39+
assert.equal(page.box.value, "omega");
40+
assert.equal(page.count.textContent, "1 page found.");
41+
assert.match(page.list.rows[0], /Turbulence-Models/);
42+
page.search("wall function");
43+
assert.equal(page.count.textContent, "1 page found.");
44+
assert.match(page.list.rows[0], /Wall-Treatment/);
45+
page.search("wall omega");
46+
assert.equal(page.count.textContent, "0 pages found.");
47+
page.search("k omega");
48+
assert.equal(page.count.textContent, "1 page found.");
49+
page.search("k");
50+
assert.match(page.count.textContent, /at least two characters/i);
51+
assert.equal(page.list.rows.length, 0);
52+
page.search("ω");
53+
assert.match(page.count.textContent, /at least two characters/i);
54+
page.search(" ");
55+
assert.equal(page.count.textContent, "");
56+
57+
const failures = [
58+
() => Promise.reject(new Error("Network unavailable")),
59+
() => Promise.resolve({ ok: false, json: () => Promise.resolve([]) }),
60+
() => Promise.resolve({ ok: true, json: () => Promise.reject(new SyntaxError("Invalid JSON")) }),
61+
() => Promise.resolve({ ok: true, json: () => Promise.resolve({ error: "No index" }) })
62+
];
63+
for (const fetch of failures) {
64+
const failed = openSearch(fetch);
65+
await settled();
66+
assert.match(failed.count.textContent, /could not load/i);
67+
failed.search("wall");
68+
assert.match(failed.count.textContent, /could not load/i);
69+
assert.equal(failed.list.rows.length, 0);
70+
}
71+
console.log("Search checks passed: loading, matching, short queries and four index failures.");
72+
})().catch(error => {
73+
console.error(error);
74+
process.exitCode = 1;
75+
});

0 commit comments

Comments
 (0)