Skip to content

Commit ea02d47

Browse files
committed
Add the documentation for FEAScript 0.2.0
Add a 0.2.0 snapshot in versioned_docs/ for the 0.2.0 API, with the version in the dropdown and an "unmaintained" banner. Describe the versioning rule in the README: one docs version per minor release, labeled with its latest patch release.
1 parent d93dded commit ea02d47

20 files changed

Lines changed: 1740 additions & 6 deletions

‎README.md‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,24 @@ The navbar's GitHub pill matches the website and fetches the FEAScript-core star
2929

3030
## Versioning
3131

32-
When a new FEAScript-core version is released, snapshot the current docs:
32+
The docs keep one version per **minor** release of FEAScript-core (`MAJOR.MINOR`), labeled with its latest patch release. Patch releases do not change the API, so they get no docs version of their own.
33+
34+
- `docs/` holds the docs of the latest minor version and is served at the unversioned URLs (`lastVersion: "current"` in `docusaurus.config.js`). Its label in the version dropdown is set in `docusaurus.config.js`.
35+
- Older minor versions are snapshots in `versioned_docs/version-x.y.z/`, served at `docs.feascript.com/x.y.z/...`, with their sidebars in `versioned_sidebars/` and their names in `versions.json`.
36+
37+
**Patch release** (for example 0.3.1 → 0.3.2): update the docs in `docs/` if needed and change the label of `current` in `docusaurus.config.js` to the new version.
38+
39+
**Minor or major release** (for example 0.3.x → 0.4.0): before changing `docs/`, snapshot it under the latest patch release of the previous minor version:
3340

3441
```bash
35-
npm run version -- 0.3.0
42+
npm run version -- 0.3.1
3643
```
3744

38-
This copies `docs/` to `versioned_docs/version-0.3.0/`, the sidebar to `versioned_sidebars/`, and records the version in `versions.json`. Released docs are then available at `docs.feascript.com/0.3.0/...` and appear in the version dropdown.
45+
This copies `docs/` to `versioned_docs/version-0.3.1/`, the sidebar to `versioned_sidebars/`, and records the version in `versions.json`. Then add the snapshot to `versions` in `docusaurus.config.js` (with `banner: "unmaintained"`), change the label of `current` to the new version, and update `docs/` for the new release.
3946

40-
Versions appear inside that dropdown, not as separate links across the navbar. The space between the logo and the right-hand controls is flexible layout spacing.
47+
Versions appear inside the dropdown, not as separate links across the navbar. The space between the logo and the right-hand controls is flexible layout spacing.
4148

42-
After the first release, edit `docusaurus.config.js`: remove `lastVersion: "current"` so the newest released version becomes the default (unversioned URLs). Fixes to an old version are made directly in its `versioned_docs/version-x.y.z/` folder.
49+
Fixes to an old version are made directly in its `versioned_docs/version-x.y.z/` folder. Absolute links in those pages, such as CDN URLs and examples, must point to that version (for example `feascript@0.2.0` and the `0.2.0` tag of FEAScript-core), not to the latest release.
4350

4451
## Deployment
4552

‎docusaurus.config.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ const config = {
4545
editUrl: "https://github.com/FEAScript/FEAScript-documentation/tree/main/",
4646
remarkPlugins: [remarkMath],
4747
rehypePlugins: [rehypeKatex],
48-
// "current" holds the unreleased docs; released versions are snapshots (see README)
48+
// "current" holds the docs of the latest minor version; older minor versions are snapshots (see README)
4949
lastVersion: "current",
5050
versions: {
5151
current: { label: "0.3.1" },
52+
"0.2.0": { label: "0.2.0", banner: "unmaintained" },
5253
},
5354
},
5455
blog: false,
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
sidebar_position: 1
3+
---
4+
5+
# FEAScriptModel
6+
7+
`FEAScriptModel` is the main class of FEAScript. It holds the configuration of a simulation (model, mesh,
8+
boundary conditions and solver) and solves it.
9+
10+
```javascript
11+
import * as math from "mathjs";
12+
global.math = math;
13+
14+
import { FEAScriptModel } from "feascript";
15+
16+
const model = new FEAScriptModel();
17+
model.setModelConfig("heatConductionScript");
18+
model.setMeshConfig({ meshDimension: "1D", elementOrder: "linear", numElementsX: 10, maxX: 0.15 });
19+
model.addBoundaryCondition("0", ["convection", 1, 25]);
20+
model.addBoundaryCondition("1", ["constantTemp", 5]);
21+
model.setSolverMethod("lusolve");
22+
const { solutionVector, nodesCoordinates } = model.solve();
23+
```
24+
25+
## Constructor
26+
27+
### `new FEAScriptModel()`
28+
29+
Creates an empty model. The solver method defaults to `"lusolve"`.
30+
31+
## Methods
32+
33+
### `setModelConfig(modelConfig, options)`
34+
35+
Selects the physical model and sets its options.
36+
37+
| Parameter | Type | Description |
38+
| ------------- | -------- | ---------------------------------- |
39+
| `modelConfig` | `string` | Name of the model (see below) |
40+
| `options` | `object` | Optional model options (see below) |
41+
42+
| `modelConfig` | Model | Dimensions |
43+
| -------------------------- | --------------------------------------------------- | ---------- |
44+
| `"heatConductionScript"` | [Heat conduction](../models/heat-conduction.md) | 1D, 2D |
45+
| `"generalFormPDEScript"` | [General form PDE](../models/general-form-pde.md) | 1D |
46+
| `"frontPropagationScript"` | [Front propagation](../models/front-propagation.md) | 2D |
47+
| `"creepingFlowScript"` | [Creeping flow](../models/creeping-flow.md) | 2D |
48+
49+
| Option | Type | Used by | Description |
50+
| ---------------------- | -------- | ---------------- | ---------------------------------------------------- |
51+
| `coefficientFunctions` | `object` | General form PDE | Coefficients of the equation; see the model page |
52+
| `maxIterations` | `number` | All | Maximum iterations of the iterative method in use |
53+
| `tolerance` | `number` | All | Convergence tolerance of the iterative method in use |
54+
55+
`maxIterations` and `tolerance` apply to the Jacobi solvers in linear models and to the Newton–Raphson method in
56+
the front propagation model; see [Solvers](../fundamentals/solvers.md) for their defaults.
57+
58+
```javascript
59+
model.setModelConfig("generalFormPDEScript", {
60+
coefficientFunctions: {
61+
A: (x) => 1,
62+
B: (x) => -10,
63+
C: (x) => 0,
64+
D: (x) => 10 * Math.exp(-200 * Math.pow(x - 0.5, 2)),
65+
},
66+
});
67+
```
68+
69+
### `setSolverConfig(solverConfig, options)`
70+
71+
Deprecated alias of `setModelConfig`, with the same parameters. It logs a deprecation warning; use
72+
`setModelConfig`. It was removed in version 0.3.0.
73+
74+
### `setMeshConfig(meshConfig)`
75+
76+
Sets the mesh: either the parameters of a structured mesh or a mesh imported from Gmsh.
77+
78+
| Property | Type | Description |
79+
| --------------- | -------- | --------------------------------------------------------------------------------- |
80+
| `meshDimension` | `string` | `"1D"` or `"2D"` (required, also for `parsedMesh`) |
81+
| `elementOrder` | `string` | `"linear"` (default) or `"quadratic"` (must match the elements of a `parsedMesh`) |
82+
| `numElementsX` | `number` | Number of elements along $x$ (structured mesh) |
83+
| `numElementsY` | `number` | Number of elements along $y$ (structured 2D mesh) |
84+
| `maxX` | `number` | Length of the domain along $x$ (structured mesh) |
85+
| `maxY` | `number` | Height of the domain along $y$ (structured 2D mesh) |
86+
| `angleLeft` | `number` | Interior angle of the left side in degrees, default `90` (structured 2D mesh) |
87+
| `angleRight` | `number` | Interior angle of the right side in degrees, default `90` (structured 2D mesh) |
88+
| `parsedMesh` | `object` | Mesh returned by [`importGmshQuadTri`](./gmsh-import.md) |
89+
90+
See [Mesh](../fundamentals/mesh.md) for the geometry, the boundary keys and the node numbering.
91+
92+
### `addBoundaryCondition(boundaryKey, condition)`
93+
94+
Adds a boundary condition, or replaces the condition of a boundary that already has one.
95+
96+
| Parameter | Type | Description |
97+
| ------------- | -------- | ----------------------------------------------------------------------- |
98+
| `boundaryKey` | `string` | Boundary key (`"0"`, `"1"`, ...) |
99+
| `condition` | `array` | Condition type followed by its parameters, e.g. `["convection", 1, 20]` |
100+
101+
See [Boundary conditions](../fundamentals/boundary-conditions.md) for the condition types of each model.
102+
Condition types that the selected model does not recognize are ignored without a message.
103+
104+
### `setSolverMethod(solverMethod)`
105+
106+
Selects the linear system solver: `"lusolve"` (default), `"jacobi"`, `"frontal"` or `"jacobi-gpu"`. See
107+
[Solvers](../fundamentals/solvers.md) for the methods supported by each model.
108+
109+
### `solve(options)`
110+
111+
Prepares the mesh, assembles the system, applies the boundary conditions and solves it. This method is
112+
synchronous.
113+
114+
| Parameter | Type | Description |
115+
| --------- | -------- | ------------------------------------------------------------------------------------------- |
116+
| `options` | `object` | Optional `{ maxIterations, tolerance }`; they take precedence over `setModelConfig` options |
117+
118+
Returns an object with:
119+
120+
| Property | Type | Description |
121+
| ------------------------------------ | ---------- | --------------------------------------------- |
122+
| `solutionVector` | `number[]` | The computed unknowns (see the model pages) |
123+
| `nodesCoordinates.nodesXCoordinates` | `number[]` | $x$ coordinates of the mesh nodes |
124+
| `nodesCoordinates.nodesYCoordinates` | `number[]` | $y$ coordinates of the mesh nodes (2D meshes) |
125+
126+
For the heat conduction, general form PDE and front propagation models, `solutionVector` has one value per node,
127+
in the order of `nodesCoordinates`. For the [creeping flow](../models/creeping-flow.md#results) model, it holds
128+
the velocity components and the pressure in consecutive blocks.
129+
130+
### `solveAsync(computeEngine, options)`
131+
132+
Asynchronous version of `solve`, used with the `"jacobi-gpu"` solver method. It returns a `Promise` that resolves
133+
to the same object as `solve()`.
134+
135+
```javascript
136+
model.setSolverMethod("jacobi-gpu");
137+
const { solutionVector, nodesCoordinates } = await model.solveAsync();
138+
```
139+
140+
| Parameter | Type | Description |
141+
| --------------- | -------- | ------------------------------------------------------------------------------------ |
142+
| `computeEngine` | `object` | Not used in version 0.2.0: FEAScript creates a WebGPU compute engine for every solve |
143+
| `options` | `object` | Optional `{ maxIterations, tolerance }` |
144+
145+
:::caution
146+
`solveAsync` supports only `heatConductionScript` with the `"jacobi-gpu"` solver method, in browsers with WebGPU
147+
support, with FEAScript imported from `src/index.js` (see
148+
[Solvers](../fundamentals/solvers.md#jacobi-method-on-the-gpu-jacobi-gpu)). For other models or solver methods, it
149+
returns an empty solution vector.
150+
:::
151+
152+
## Error handling
153+
154+
FEAScript reports configuration problems (for example a creeping flow model on linear elements, or a solver that
155+
did not converge) as `[ERROR]` messages in the console, and in most cases continues instead of throwing an
156+
exception. Some invalid configurations, such as a missing `meshDimension`, end in a JavaScript error later in the
157+
solution. Check the console output when a result looks wrong.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---
2+
sidebar_position: 2
3+
---
4+
5+
# importGmshQuadTri
6+
7+
```javascript
8+
const parsedMesh = await importGmshQuadTri(file);
9+
```
10+
11+
Reads a 2D quadrilateral mesh generated by [Gmsh](https://gmsh.info/) (`.msh` format version 4.1, ASCII) and
12+
returns it in the form that `setMeshConfig` expects through its `parsedMesh` property. See
13+
[Mesh](../fundamentals/mesh.md#gmsh-meshes) for the supported element types and for how boundaries are defined.
14+
15+
:::note
16+
Despite its name, `importGmshQuadTri` supports quadrilateral elements only in version 0.2.0. Version 0.3.0
17+
replaced it with `importGmshMesh`, which also reads triangles.
18+
:::
19+
20+
| Parameter | Type | Description |
21+
| --------- | -------- | --------------------------------------------------------------------------------------------------------------- |
22+
| `file` | `object` | A `File` object, or any object with an asynchronous `text()` method that returns the content of the `.msh` file |
23+
24+
Returns a `Promise` that resolves to the parsed mesh. Pass it to `setMeshConfig` together with
25+
`meshDimension: "2D"` and the `elementOrder` of the mesh, which are not detected from the file.
26+
27+
## In the browser
28+
29+
From a file input:
30+
31+
```html
32+
<input type="file" id="meshFile" accept=".msh" />
33+
34+
<script type="module">
35+
import {
36+
FEAScriptModel,
37+
importGmshQuadTri,
38+
} from "https://cdn.jsdelivr.net/npm/feascript@0.2.0/dist/feascript.esm.js";
39+
40+
document.getElementById("meshFile").addEventListener("change", async (event) => {
41+
const parsedMesh = await importGmshQuadTri(event.target.files[0]);
42+
43+
const model = new FEAScriptModel();
44+
model.setModelConfig("heatConductionScript");
45+
model.setMeshConfig({ parsedMesh, meshDimension: "2D", elementOrder: "quadratic" });
46+
// ...boundary conditions and solve
47+
});
48+
</script>
49+
```
50+
51+
From a file on the server:
52+
53+
```javascript
54+
const response = await fetch("./rect_quad.msh");
55+
const meshFile = new File([await response.text()], "rect_quad.msh");
56+
const parsedMesh = await importGmshQuadTri(meshFile);
57+
```
58+
59+
## In Node.js
60+
61+
Node.js has no `File` object for files on disk, so pass an object with a `text()` method:
62+
63+
```javascript
64+
import fs from "fs";
65+
import * as math from "mathjs";
66+
global.math = math;
67+
68+
import { FEAScriptModel, importGmshQuadTri } from "feascript";
69+
70+
// 1. Create the model and select the physics
71+
const model = new FEAScriptModel();
72+
model.setModelConfig("heatConductionScript");
73+
74+
// 2. Load the Gmsh mesh
75+
const meshContent = fs.readFileSync("rect_quad.msh", "utf8");
76+
const parsedMesh = await importGmshQuadTri({ text: async () => meshContent });
77+
model.setMeshConfig({ parsedMesh, meshDimension: "2D", elementOrder: "quadratic" });
78+
79+
// 3. Apply the boundary conditions
80+
model.addBoundaryCondition("0", ["constantTemp", 200]); // Physical curve "bottom", tag 1
81+
model.addBoundaryCondition("1", ["constantTemp", 200]); // Physical curve "right", tag 2
82+
model.addBoundaryCondition("2", ["convection", 1, 20]); // Physical curve "top", tag 3
83+
model.addBoundaryCondition("3", ["symmetry"]); // Physical curve "left", tag 4
84+
85+
// 4. Solve
86+
const { solutionVector, nodesCoordinates } = model.solve();
87+
```
88+
89+
The mesh file of this example,
90+
[`rect_quad.msh`](https://github.com/FEAScript/FEAScript-core/blob/0.2.0/examples/heatConductionScript/heatConduction2DFin/rect_quad.msh),
91+
is in the examples of FEAScript-core 0.2.0. Its physical curves are tagged bottom, right, top, left, so the keys
92+
differ from those of a structured mesh.
93+
94+
## Limitations
95+
96+
- Only 2D meshes of quadrilaterals are supported, all of the same order (linear or quadratic).
97+
- The boundaries must be named 1D physical groups (see
98+
[Boundaries of a Gmsh mesh](../fundamentals/mesh.md#boundaries-of-a-gmsh-mesh)).
99+
- Only the ASCII variant of the version 4.1 format is read. Export with
100+
`gmsh model.geo -2 -format msh41 -o model.msh`, or with **File → Export** and the "Version 4 ASCII" format in
101+
the Gmsh interface.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
sidebar_position: 5
3+
---
4+
5+
# Utilities
6+
7+
## `logSystem`
8+
9+
```javascript
10+
import { logSystem } from "feascript";
11+
12+
logSystem("debug");
13+
```
14+
15+
Sets how much FEAScript prints to the console.
16+
17+
| Level | Output |
18+
| --------- | --------------------------------------------------------------------------------------------------------------------- |
19+
| `"basic"` | Default. Progress messages (`[INFO]`), including the error norm of every Newton–Raphson iteration |
20+
| `"debug"` | Adds detailed messages (`[DEBUG]`), such as the nodes of every boundary condition and the number of Jacobi iterations |
21+
22+
Errors (`[ERROR]`) and warnings (`[WARN]`) are always printed. Any other value falls back to `"basic"` with a
23+
warning. The timings of the solution steps (`totalSolvingTime`, `systemSolving`) are printed with `console.time`
24+
at every level.
25+
26+
## `printVersion`
27+
28+
```javascript
29+
import { printVersion } from "feascript";
30+
31+
console.log("FEAScript version:", printVersion); // "0.2.0"
32+
```
33+
34+
A string constant with the version of the library.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
sidebar_position: 3
3+
---
4+
5+
# Visualization
6+
7+
FEAScript 0.2.0 plots results with [Plotly](https://plotly.com/javascript/). Load Plotly with a `<script>` tag
8+
before using these functions; FEAScript uses the global `Plotly` object:
9+
10+
```html
11+
<script src="https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.35.3/plotly.min.js"></script>
12+
<div id="resultsCanvas"></div>
13+
```
14+
15+
Both plotting functions take the same arguments:
16+
17+
| Parameter | Type | Description |
18+
| ----------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
19+
| `model` | `object` | The `FEAScriptModel`, or any object with its `solverConfig` and `meshConfig` (for example the result of `FEAScriptWorker.getModelInfo()`) |
20+
| `result` | `object` | The object returned by `solve()`: `{ solutionVector, nodesCoordinates }` |
21+
| `plotType` | `string` | `"line"` for 1D meshes, `"contour"` for 2D meshes |
22+
| `plotDivId` | `string` | `id` of the HTML element in which the plot is drawn |
23+
24+
The plotting functions draw one value per mesh node. For the creeping flow model, whose `solutionVector` holds
25+
several fields, slice the field to plot and pass it as the `solutionVector` of `result` (see
26+
[Creeping flow](../models/creeping-flow.md#results)).
27+
28+
## `plotSolution(model, result, plotType, plotDivId)`
29+
30+
Plots the nodal values directly:
31+
32+
- `"line"` (1D): a line plot of the solution along $x$.
33+
- `"contour"` (2D): a contour plot built from the nodal values and coordinates.
34+
35+
```javascript
36+
const result = model.solve();
37+
plotSolution(model, result, "contour", "resultsCanvas");
38+
```
39+
40+
## `plotInterpolatedSolution(model, result, plotType, plotDivId)`
41+
42+
Evaluates the finite element solution, with the basis functions of each element, on a regular grid of 50 points
43+
per unit length, and draws a contour plot of it. Grid points outside the mesh are left empty, so non-rectangular
44+
domains (for example Gmsh meshes) are drawn with their true shape. It supports `"contour"` on 2D meshes only.
45+
46+
```javascript
47+
plotInterpolatedSolution(model, result, "contour", "resultsCanvas");
48+
```
49+
50+
:::note
51+
The grid density is fixed at 50 points per unit length of the domain, so the number of grid points depends on the
52+
units of the model: a domain of 0.1 × 0.1 gets a coarse grid, and a very large domain a very dense one. Use
53+
`plotSolution` in these cases.
54+
:::

0 commit comments

Comments
 (0)