xdfem3d 2026.11.14__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- xdfem3d-2026.11.14/LICENSE.md +58 -0
- xdfem3d-2026.11.14/PKG-INFO +310 -0
- xdfem3d-2026.11.14/README.md +279 -0
- xdfem3d-2026.11.14/pyproject.toml +48 -0
- xdfem3d-2026.11.14/rust/Cargo.lock +269 -0
- xdfem3d-2026.11.14/rust/Cargo.toml +17 -0
- xdfem3d-2026.11.14/rust/src/beam3d.rs +741 -0
- xdfem3d-2026.11.14/rust/src/corot.rs +754 -0
- xdfem3d-2026.11.14/rust/src/fiber.rs +209 -0
- xdfem3d-2026.11.14/rust/src/geomsearch.rs +217 -0
- xdfem3d-2026.11.14/rust/src/lib.rs +1540 -0
- xdfem3d-2026.11.14/rust/src/material.rs +309 -0
- xdfem3d-2026.11.14/rust/src/shell.rs +1856 -0
- xdfem3d-2026.11.14/rust/src/solid.rs +1023 -0
- xdfem3d-2026.11.14/rust/src/spring.rs +72 -0
- xdfem3d-2026.11.14/src/xdfem3d/__init__.py +51 -0
- xdfem3d-2026.11.14/src/xdfem3d/analysis.py +370 -0
- xdfem3d-2026.11.14/src/xdfem3d/buckling.py +111 -0
- xdfem3d-2026.11.14/src/xdfem3d/cases.py +648 -0
- xdfem3d-2026.11.14/src/xdfem3d/commands.py +81 -0
- xdfem3d-2026.11.14/src/xdfem3d/constraints.py +232 -0
- xdfem3d-2026.11.14/src/xdfem3d/discretize.py +255 -0
- xdfem3d-2026.11.14/src/xdfem3d/dxf.py +842 -0
- xdfem3d-2026.11.14/src/xdfem3d/dynamics.py +456 -0
- xdfem3d-2026.11.14/src/xdfem3d/events.py +66 -0
- xdfem3d-2026.11.14/src/xdfem3d/fibers.py +108 -0
- xdfem3d-2026.11.14/src/xdfem3d/fieldloads.py +163 -0
- xdfem3d-2026.11.14/src/xdfem3d/fields.py +122 -0
- xdfem3d-2026.11.14/src/xdfem3d/fileformat.py +374 -0
- xdfem3d-2026.11.14/src/xdfem3d/geometry.py +659 -0
- xdfem3d-2026.11.14/src/xdfem3d/ifc.py +594 -0
- xdfem3d-2026.11.14/src/xdfem3d/library.py +183 -0
- xdfem3d-2026.11.14/src/xdfem3d/mcp/__init__.py +8 -0
- xdfem3d-2026.11.14/src/xdfem3d/mcp/__main__.py +72 -0
- xdfem3d-2026.11.14/src/xdfem3d/mcp/session.py +53 -0
- xdfem3d-2026.11.14/src/xdfem3d/mcp/tools.py +364 -0
- xdfem3d-2026.11.14/src/xdfem3d/members.py +174 -0
- xdfem3d-2026.11.14/src/xdfem3d/merge.py +427 -0
- xdfem3d-2026.11.14/src/xdfem3d/modal.py +194 -0
- xdfem3d-2026.11.14/src/xdfem3d/model.py +3790 -0
- xdfem3d-2026.11.14/src/xdfem3d/modelcheck.py +702 -0
- xdfem3d-2026.11.14/src/xdfem3d/modelinfo.py +149 -0
- xdfem3d-2026.11.14/src/xdfem3d/nonlinear.py +745 -0
- xdfem3d-2026.11.14/src/xdfem3d/panels.py +255 -0
- xdfem3d-2026.11.14/src/xdfem3d/resultsio.py +279 -0
- xdfem3d-2026.11.14/src/xdfem3d/sap2000.py +705 -0
- xdfem3d-2026.11.14/src/xdfem3d/scriptexport.py +160 -0
- xdfem3d-2026.11.14/src/xdfem3d/sections.py +91 -0
- xdfem3d-2026.11.14/src/xdfem3d/solidgeom.py +68 -0
- xdfem3d-2026.11.14/src/xdfem3d/solidnl.py +265 -0
- xdfem3d-2026.11.14/src/xdfem3d/spectra.py +64 -0
- xdfem3d-2026.11.14/src/xdfem3d/spectrum.py +117 -0
- xdfem3d-2026.11.14/src/xdfem3d/springs.py +209 -0
- xdfem3d-2026.11.14/src/xdfem3d/statics.py +522 -0
- xdfem3d-2026.11.14/src/xdfem3d/templates.py +1282 -0
- xdfem3d-2026.11.14/src/xdfem3d/x2d_import.py +721 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
xdfem3d — GNU Lesser General Public License v3
|
|
2
|
+
================================================
|
|
3
|
+
|
|
4
|
+
This licence covers the **calculation engine**: the `xdfem3d` Python package.
|
|
5
|
+
|
|
6
|
+
It does **not** cover the xdfem3D desktop application — the graphical
|
|
7
|
+
interface, which forms a separate package — distributed as freeware in
|
|
8
|
+
compiled form only, under its own terms (the License Agreement that comes
|
|
9
|
+
with the application). Nothing in those terms restricts the rights granted here.
|
|
10
|
+
|
|
11
|
+
(Described by package rather than by directory on purpose: this file travels
|
|
12
|
+
with the engine to a repository where the application's directories do not
|
|
13
|
+
exist, and a licence that points at a path the reader cannot find tells them
|
|
14
|
+
nothing.)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
Copyright (c) 2026 Paulo Cachim
|
|
19
|
+
|
|
20
|
+
The xdfem3d calculation engine is free software: you can redistribute it
|
|
21
|
+
and/or modify it under the terms of the GNU Lesser General Public License
|
|
22
|
+
as published by the Free Software Foundation, either version 3 of the
|
|
23
|
+
License, or (at your option) any later version.
|
|
24
|
+
|
|
25
|
+
The xdfem3d calculation engine is distributed in the hope that it will be
|
|
26
|
+
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
27
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
|
28
|
+
General Public License for more details.
|
|
29
|
+
|
|
30
|
+
You should have received a copy of the GNU Lesser General Public License
|
|
31
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
32
|
+
|
|
33
|
+
Full LGPL v3 text: <https://www.gnu.org/licenses/lgpl-3.0.html>
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
Engineering notice
|
|
38
|
+
------------------
|
|
39
|
+
|
|
40
|
+
The warranty disclaimer above is the operative legal text, and the following
|
|
41
|
+
adds nothing to it — but it is the part that matters in practice, so it is
|
|
42
|
+
stated plainly rather than left to be inferred from capital letters.
|
|
43
|
+
|
|
44
|
+
xdfem3d computes structural analysis results. Those results are not verified,
|
|
45
|
+
certified, or checked against any code of practice by their being produced.
|
|
46
|
+
The software is an aid to calculation and not a substitute for engineering
|
|
47
|
+
judgement. Anyone using its output in the design, verification, or
|
|
48
|
+
construction of a real structure is responsible for independently verifying
|
|
49
|
+
it, and remains the engineer of record.
|
|
50
|
+
|
|
51
|
+
Third-party components
|
|
52
|
+
----------------------
|
|
53
|
+
|
|
54
|
+
The engine depends on other packages, each under its own licence — NumPy,
|
|
55
|
+
SciPy, eurocodepy and others listed in pyproject.toml. They are
|
|
56
|
+
dependencies, not part of this Software, and are not relicensed by this
|
|
57
|
+
file. See NOTICE.md for the components bundled with the compiled
|
|
58
|
+
application, where the distinction matters a great deal more.
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xdfem3d
|
|
3
|
+
Version: 2026.11.14
|
|
4
|
+
Classifier: Development Status :: 4 - Beta
|
|
5
|
+
Classifier: Intended Audience :: Science/Research
|
|
6
|
+
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
|
|
7
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Classifier: Programming Language :: Rust
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering
|
|
11
|
+
Requires-Dist: eurocodepy>=2027.0.12
|
|
12
|
+
Requires-Dist: numpy
|
|
13
|
+
Requires-Dist: scipy
|
|
14
|
+
Requires-Dist: ezdxf ; extra == 'dxf'
|
|
15
|
+
Requires-Dist: ifcopenshell ; extra == 'ifc'
|
|
16
|
+
Requires-Dist: mcp ; extra == 'mcp'
|
|
17
|
+
Provides-Extra: dxf
|
|
18
|
+
Provides-Extra: ifc
|
|
19
|
+
Provides-Extra: mcp
|
|
20
|
+
License-File: LICENSE.md
|
|
21
|
+
Summary: 3D structural FEM engine with a compiled Rust core
|
|
22
|
+
Keywords: finite element,structural analysis,structural engineering,FEM,Eurocode,building frames,shells,solids
|
|
23
|
+
Author: Paulo Cachim
|
|
24
|
+
License: LGPL-3.0-or-later
|
|
25
|
+
Requires-Python: >=3.12
|
|
26
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
27
|
+
Project-URL: Documentation, https://pcachim.github.io/xdfem3d
|
|
28
|
+
Project-URL: Homepage, https://github.com/pcachim/xdfem3d
|
|
29
|
+
Project-URL: Issues, https://github.com/pcachim/xdfem3d/issues
|
|
30
|
+
|
|
31
|
+
# xdfem3D
|
|
32
|
+
|
|
33
|
+
[](https://www.python.org/)
|
|
34
|
+
[](https://www.rust-lang.org/)
|
|
35
|
+
[](https://github.com/pcachim/eurocodepy)
|
|
36
|
+
[](LICENSE.md)
|
|
37
|
+
|
|
38
|
+
This repository holds two things, under two licences.
|
|
39
|
+
|
|
40
|
+
**The calculation engine** — the source in this tree, `xdfem3d`, is a Python
|
|
41
|
+
library with a compiled core (Rust) for three-dimensional finite element
|
|
42
|
+
analysis of building frames, shells, slabs, walls and solids: linear and
|
|
43
|
+
nonlinear, modal and time-history. It is under the GNU Lesser General Public
|
|
44
|
+
License v3 (LGPLv3). It has no interface and no dependency on one: it builds a
|
|
45
|
+
model, solves it, and gives back numbers.
|
|
46
|
+
|
|
47
|
+
**The desktop application** — a graphical interface built on that engine. It is
|
|
48
|
+
free to use, distributed as a compiled application under its own terms, and its
|
|
49
|
+
source is **not** published. It is the way most people will meet the engine:
|
|
50
|
+
you draw and load a model in a window, run it, and look at the results. Download
|
|
51
|
+
it from [Releases](https://github.com/pcachim/xdfem3d/releases).
|
|
52
|
+
|
|
53
|
+
**AI in the engine and in the application** — optional, and off until you use
|
|
54
|
+
it. The engine includes an [MCP](https://modelcontextprotocol.io) server
|
|
55
|
+
(`python -m xdfem3d.mcp`) through which an agent you already use (Claude Code,
|
|
56
|
+
OpenCode, Codex, Visual Studio Code, Claude Desktop) builds, checks and analyses
|
|
57
|
+
a model. The application adds an Agent panel in which an agent works on the model
|
|
58
|
+
you have open, while you watch it change, with a model of your choice (a local
|
|
59
|
+
one through [Ollama](https://ollama.com), or a remote one with your own
|
|
60
|
+
account). Remote models receive what the agent reads of your model.
|
|
61
|
+
|
|
62
|
+
**The documentation** is at
|
|
63
|
+
[pcachim.github.io/xdfem3d](https://pcachim.github.io/xdfem3d). It is the
|
|
64
|
+
manual of the application, and it also describes the engine: the
|
|
65
|
+
[Scripting](https://pcachim.github.io/xdfem3d/scripting.html) section is the
|
|
66
|
+
guide to the Python API, with a reference for every method, and the
|
|
67
|
+
[Command Language](https://pcachim.github.io/xdfem3d/commands.html) lists the
|
|
68
|
+
commands.
|
|
69
|
+
|
|
70
|
+
The rest of this page is about the library.
|
|
71
|
+
|
|
72
|
+
## The engine and the application
|
|
73
|
+
|
|
74
|
+
They are two programs with one boundary, and the boundary is kept on purpose:
|
|
75
|
+
|
|
76
|
+
- **The application uses the engine only through its public API and the
|
|
77
|
+
`.xdfem3d` file.** It reaches nothing else, which is checked by a test on the
|
|
78
|
+
application's side. So everything the application does to a model, a program
|
|
79
|
+
can do: every change is a *command*, a method of `Model3D`.
|
|
80
|
+
- **The `.xdfem3d` file is the meeting point.** A model saved by the
|
|
81
|
+
application opens in a script, and the other way round, with its results if it
|
|
82
|
+
has some. The format is versioned: a file is read by the version that wrote
|
|
83
|
+
it and by every newer one, and a newer file is refused with a message and not
|
|
84
|
+
guessed at.
|
|
85
|
+
- **They are released independently**, on separate cycles. An engine release
|
|
86
|
+
does not imply an application release, and vice versa; the two version numbers
|
|
87
|
+
do not line up. The application's **Help ▸ About** lists both, so a report
|
|
88
|
+
can name the right one.
|
|
89
|
+
- **The licences differ, and neither restricts the other.** The engine is
|
|
90
|
+
LGPLv3: you may use, modify and redistribute it, from here. The application is
|
|
91
|
+
a separate work, freeware in compiled form, under its own terms. Nothing in
|
|
92
|
+
those terms restricts your rights to the engine.
|
|
93
|
+
|
|
94
|
+
What you would use the engine alone for: scripts that build or change many
|
|
95
|
+
models, parametric studies and optimisation, analysis in a service or a
|
|
96
|
+
pipeline, a post-processor, a front end of your own, or an AI agent working on a
|
|
97
|
+
model with no window at all.
|
|
98
|
+
|
|
99
|
+
## Install
|
|
100
|
+
|
|
101
|
+
Python **3.12 or later**. The compiled core is written in Rust and built with
|
|
102
|
+
[maturin](https://www.maturin.rs), so building from source needs a
|
|
103
|
+
[Rust toolchain](https://rustup.rs) and [`uv`](https://docs.astral.sh/uv/).
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
git clone https://github.com/pcachim/xdfem3d.git
|
|
107
|
+
cd xdfem3d
|
|
108
|
+
uv sync
|
|
109
|
+
uv run maturin develop # builds the core and installs the package in the environment
|
|
110
|
+
uv run pytest # the tests, and the validation cases
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The core install is NumPy, SciPy and
|
|
114
|
+
[eurocodepy](https://github.com/pcachim/eurocodepy) (the Eurocode actions and
|
|
115
|
+
combinations, and the catalogues of materials and profiles). The formats that
|
|
116
|
+
need a library of their own are extras, so that a solver in a script or a
|
|
117
|
+
service does not have to install them:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
pip install "xdfem3d[mcp]" # the MCP server: the mcp package
|
|
121
|
+
pip install "xdfem3d[ifc]" # ifcopenshell — IFC (openBIM) import and export
|
|
122
|
+
pip install "xdfem3d[dxf]" # ezdxf — DXF import and export
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Everything they cover is reached when it is used, so the engine imports,
|
|
126
|
+
assembles and solves without them.
|
|
127
|
+
|
|
128
|
+
## A first model
|
|
129
|
+
|
|
130
|
+
Units are metres, kN and kPa (kN/m²), tonne for mass, degrees for angles. A
|
|
131
|
+
model is built from the materials and the sections up to the elements and the
|
|
132
|
+
loads, and an analysis case says what to solve.
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from xdfem3d import Model3D
|
|
136
|
+
|
|
137
|
+
m = Model3D("beam")
|
|
138
|
+
m.add_material("C30", E=3.3e7, nu=0.2, unit_weight=25.0, type="concrete")
|
|
139
|
+
m.add_section_shape("S", "C30", "rectangular", b=0.3, h=0.5)
|
|
140
|
+
|
|
141
|
+
m.add_node("A", 0, 0, 0)
|
|
142
|
+
m.add_node("B", 6, 0, 0)
|
|
143
|
+
m.add_bar("b", "A", "B", "S")
|
|
144
|
+
|
|
145
|
+
m.support("A", "ux", "uy", "uz", "rx") # a pin that also holds the twist
|
|
146
|
+
m.support("B", "uy", "uz") # a roller along x
|
|
147
|
+
|
|
148
|
+
m.add_load_case("Q", action_type="Q")
|
|
149
|
+
m.add_uniform_load("Q", "b", (0, 0, -10)) # 10 kN/m downwards, in global axes
|
|
150
|
+
m.add_analysis_case("ULS", "linear", coefficients={"Q": 1.0})
|
|
151
|
+
|
|
152
|
+
assert m.check() == [] # what would stop the analysis; empty when nothing does
|
|
153
|
+
results = m.solve_pending() # the analysis cases that have no current results
|
|
154
|
+
r = results["ULS"]
|
|
155
|
+
|
|
156
|
+
print(r.reaction("ULS", "A")) # fx, fy, fz, mx, my, mz — here fz = qL/2 = 30 kN
|
|
157
|
+
print(r.displacement("ULS", "B"))
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Every id is a name you choose. A command that gets something that does not
|
|
161
|
+
exist or does not fit raises `ModelError`, says what is wrong, and leaves the
|
|
162
|
+
model as it was. A model with results can be **locked**, so that its input
|
|
163
|
+
cannot change under them.
|
|
164
|
+
|
|
165
|
+
A model is saved with `xdfem3d.save(m, "beam.xdfem3d")` and read with
|
|
166
|
+
`xdfem3d.load(...)`; `export_script(m)` writes the model as a Python script that
|
|
167
|
+
rebuilds it. The [Scripting](https://pcachim.github.io/xdfem3d/scripting.html)
|
|
168
|
+
section goes on from here: combinations, results, files, and recipes that are
|
|
169
|
+
run by the tests of the documentation.
|
|
170
|
+
|
|
171
|
+
## What it does
|
|
172
|
+
|
|
173
|
+
- **Elements** — 3D frame bars with releases, offsets and member loads, in any
|
|
174
|
+
orientation; triangular and quadrilateral **shells** (membrane and bending,
|
|
175
|
+
with layered and reinforced-concrete sections); **solids** (hexahedra,
|
|
176
|
+
prisms, tetrahedra); node, line and surface **springs**; rigid links,
|
|
177
|
+
rigid diaphragms and equal-DOF constraints imposed exactly. **Panels** (slabs
|
|
178
|
+
and walls) are meshed from their outline, with openings, and share nodes with
|
|
179
|
+
their neighbours.
|
|
180
|
+
- **Sections and materials** — rectangular and general shapes, rolled profiles
|
|
181
|
+
and reinforced-concrete sections from the catalogues, fibre sections, and
|
|
182
|
+
shell and solid sections; materials from the catalogue or your own, with
|
|
183
|
+
uniaxial laws for the nonlinear analyses.
|
|
184
|
+
- **Loads** — nodal, point and uniform loads, loads on part of a bar, shell
|
|
185
|
+
pressure, temperature on bars, shells and solids, support settlements, masses,
|
|
186
|
+
and **field loads** given by functions of the coordinates.
|
|
187
|
+
- **Analysis** — linear static, P-Delta (second order), modal, response
|
|
188
|
+
spectrum (EC8 spectra included, CQC and SRSS), buckling, geometric nonlinear
|
|
189
|
+
(large displacements, corotational), material nonlinear (fibre sections,
|
|
190
|
+
plasticity in solids and in layered shells), pushover, and time history.
|
|
191
|
+
- **Combinations** — sums, envelopes, absolute sums and SRSS over the results
|
|
192
|
+
of analysis cases and of other combinations, and the **EN 1990** combinations
|
|
193
|
+
generated for you.
|
|
194
|
+
- **Structures from the library** — 26 **templates** (frames, trusses, slabs,
|
|
195
|
+
walls, a tower, a steel hall, a bridge deck, a block of solids…), and a
|
|
196
|
+
frame grid with stories.
|
|
197
|
+
- **File formats** — its own `.xdfem3d` (a zip of JSON, reproducible
|
|
198
|
+
byte for byte), IFC, DXF, SAP2000 `.s2k`, and an import of xdfem2D models
|
|
199
|
+
(`.x2d`) as a starting point.
|
|
200
|
+
- **Checks and editing** — a model check that says what is wrong or doubtful
|
|
201
|
+
before you run, and about 120 editing commands (add, edit, move, copy, rotate,
|
|
202
|
+
scale, divide, merge, rename, remove…) that are the same commands for a script,
|
|
203
|
+
the application and an agent.
|
|
204
|
+
|
|
205
|
+
Inside, the element kernels (bars, corotational bars, fibres, shells, solids,
|
|
206
|
+
springs and the materials) are written in Rust; assembly and solving use SciPy's
|
|
207
|
+
sparse solvers and ARPACK for the eigenproblems.
|
|
208
|
+
|
|
209
|
+
## Layout
|
|
210
|
+
|
|
211
|
+
- `rust/` — the compiled core (`xdfem3d_core`, exposed to Python with PyO3 as `xdfem3d._core`): the element kernels.
|
|
212
|
+
- `src/xdfem3d/` — the Python package: the model and its commands, the analyses, the file formats, the library and the MCP server.
|
|
213
|
+
- `tests/` — pytest: unit tests and closed-form cases.
|
|
214
|
+
- `validation/` — the cases against xdfem2D and OpenSees (frozen results, so they need neither).
|
|
215
|
+
- `docs/` — design notes of the core ([CORE_DESIGN.md](docs/CORE_DESIGN.md)).
|
|
216
|
+
|
|
217
|
+
## The MCP server
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
python -m xdfem3d.mcp # serves one model over MCP, on standard input and output
|
|
221
|
+
python -m xdfem3d.mcp --root ./work # the agent may read and write files only in that folder
|
|
222
|
+
claude mcp add xdfem3d -- python -m xdfem3d.mcp
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
An agent builds, edits, checks and analyses a model and reads the results through
|
|
226
|
+
fifteen tools; an `edit` is a list of commands applied all together or not at all, and
|
|
227
|
+
undone together. The server works on a model of its own, in memory, and has no window.
|
|
228
|
+
To let an agent work on the model that is open in the application, use the
|
|
229
|
+
application's Agent panel (see [AI Agents](https://pcachim.github.io/xdfem3d/mcp.html)).
|
|
230
|
+
|
|
231
|
+
## Validation and known limits
|
|
232
|
+
|
|
233
|
+
The engine is compared with what is independent of it, and the cases run with
|
|
234
|
+
`uv run pytest` (the validation cases are in `validation/`, next to the unit
|
|
235
|
+
tests in `tests/`):
|
|
236
|
+
|
|
237
|
+
- **Closed forms**: axial, torsion, bending, releases and member loads, diagrams,
|
|
238
|
+
constraints, vibration frequencies, effective masses, a single-degree-of-freedom
|
|
239
|
+
spectrum, Euler loads, beam-columns, the elastica, the Von Mises truss, moment-
|
|
240
|
+
curvature of steel and reinforced-concrete sections, a plastic cantilever, shell
|
|
241
|
+
plates against the Navier–Mindlin series, buckling of a plate, patch tests on
|
|
242
|
+
distorted meshes, among others.
|
|
243
|
+
- **xdfem2D**: plane frames solved by the 3D beam reproduce the 2D engine
|
|
244
|
+
(static, modal, response spectrum with CQC and SRSS, and P-Delta) to 1e-8 and
|
|
245
|
+
better.
|
|
246
|
+
- **OpenSees**: a space frame with torsion and different member axes (static,
|
|
247
|
+
modal and time history), a corotational cantilever in large displacement, fibre
|
|
248
|
+
and reinforced-concrete pushovers, brick and shell plasticity, and MITC4 plates.
|
|
249
|
+
The OpenSees results are frozen in the repository, so the tests need no OpenSees.
|
|
250
|
+
|
|
251
|
+
What that does and does not establish, so the result is not taken for more:
|
|
252
|
+
|
|
253
|
+
- **Validated against a formula** is not **validated for your structure**. A
|
|
254
|
+
case here checks that an element reproduces a textbook solution or another
|
|
255
|
+
program, not that it suits a given geometry, mesh or load path.
|
|
256
|
+
- **There are no design checks in the engine yet**: no verification of
|
|
257
|
+
reinforced concrete, steel or timber members to a code, and no design
|
|
258
|
+
reports. It analyses; it does not dimension. The Eurocode parts it has are the
|
|
259
|
+
actions, the combinations (EN 1990) and the response spectra (EC8).
|
|
260
|
+
- A generated validation report like the one of xdfem2D is **not published
|
|
261
|
+
yet**; what exists is the suite in `validation/` and `tests/`.
|
|
262
|
+
- Where neither a closed form nor a comparison with xdfem2D or OpenSees
|
|
263
|
+
covers a kind of problem, nothing independent does: say so, in a report, when
|
|
264
|
+
your problem is of that kind.
|
|
265
|
+
|
|
266
|
+
## A note on results
|
|
267
|
+
|
|
268
|
+
xdfem3d computes analysis results. It does not verify them, and producing a
|
|
269
|
+
number is not the same as the number being right for your problem. It is an aid
|
|
270
|
+
to calculation, not a substitute for engineering judgement: anyone using its
|
|
271
|
+
output in the design or construction of a real structure is responsible for
|
|
272
|
+
verifying it independently and remains the engineer of record. The same holds
|
|
273
|
+
for anything that an AI agent does with the model or says about it.
|
|
274
|
+
|
|
275
|
+
## Citing
|
|
276
|
+
|
|
277
|
+
If xdfem3d contributes to published work, please cite it:
|
|
278
|
+
|
|
279
|
+
> Cachim, P. (2026). *pcachim/xdfem3d* [Computer software].
|
|
280
|
+
> https://github.com/pcachim/xdfem3d
|
|
281
|
+
|
|
282
|
+
Say the version of the engine you used (`xdfem3d.__version__`, and the
|
|
283
|
+
application's Help ▸ About if you used it).
|
|
284
|
+
|
|
285
|
+
## Support and contributing
|
|
286
|
+
|
|
287
|
+
Bugs and questions, for the library or the application, go to
|
|
288
|
+
[Issues](https://github.com/pcachim/xdfem3d/issues). A report with a model that
|
|
289
|
+
reproduces the problem (the `.xdfem3d` file, or a script) is the most useful
|
|
290
|
+
thing you can send. For anything else, write to
|
|
291
|
+
[eurocodepy@gmail.com](mailto:eurocodepy@gmail.com).
|
|
292
|
+
|
|
293
|
+
Development happens in a private repository, and what is published here is
|
|
294
|
+
that work: open an issue before you spend time on a pull request, because a
|
|
295
|
+
change may not be able to land as it is.
|
|
296
|
+
|
|
297
|
+
## Licence
|
|
298
|
+
|
|
299
|
+
The engine — everything in this tree — is under the **LGPLv3**; see
|
|
300
|
+
[LICENSE.md](LICENSE.md). It depends on
|
|
301
|
+
[eurocodepy](https://github.com/pcachim/eurocodepy), also LGPLv3, for the
|
|
302
|
+
Eurocode actions and combinations and the catalogues of materials and profiles.
|
|
303
|
+
|
|
304
|
+
The desktop application is a separate work, distributed as freeware in compiled
|
|
305
|
+
form under its own terms (see the
|
|
306
|
+
[Licenses page](https://pcachim.github.io/xdfem3d/license.html), and
|
|
307
|
+
`LICENSE.md` shipped with the application). Nothing in those terms restricts
|
|
308
|
+
your rights to the engine: you may use, modify and redistribute it under the
|
|
309
|
+
LGPLv3, from here.
|
|
310
|
+
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# xdfem3D
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/)
|
|
4
|
+
[](https://www.rust-lang.org/)
|
|
5
|
+
[](https://github.com/pcachim/eurocodepy)
|
|
6
|
+
[](LICENSE.md)
|
|
7
|
+
|
|
8
|
+
This repository holds two things, under two licences.
|
|
9
|
+
|
|
10
|
+
**The calculation engine** — the source in this tree, `xdfem3d`, is a Python
|
|
11
|
+
library with a compiled core (Rust) for three-dimensional finite element
|
|
12
|
+
analysis of building frames, shells, slabs, walls and solids: linear and
|
|
13
|
+
nonlinear, modal and time-history. It is under the GNU Lesser General Public
|
|
14
|
+
License v3 (LGPLv3). It has no interface and no dependency on one: it builds a
|
|
15
|
+
model, solves it, and gives back numbers.
|
|
16
|
+
|
|
17
|
+
**The desktop application** — a graphical interface built on that engine. It is
|
|
18
|
+
free to use, distributed as a compiled application under its own terms, and its
|
|
19
|
+
source is **not** published. It is the way most people will meet the engine:
|
|
20
|
+
you draw and load a model in a window, run it, and look at the results. Download
|
|
21
|
+
it from [Releases](https://github.com/pcachim/xdfem3d/releases).
|
|
22
|
+
|
|
23
|
+
**AI in the engine and in the application** — optional, and off until you use
|
|
24
|
+
it. The engine includes an [MCP](https://modelcontextprotocol.io) server
|
|
25
|
+
(`python -m xdfem3d.mcp`) through which an agent you already use (Claude Code,
|
|
26
|
+
OpenCode, Codex, Visual Studio Code, Claude Desktop) builds, checks and analyses
|
|
27
|
+
a model. The application adds an Agent panel in which an agent works on the model
|
|
28
|
+
you have open, while you watch it change, with a model of your choice (a local
|
|
29
|
+
one through [Ollama](https://ollama.com), or a remote one with your own
|
|
30
|
+
account). Remote models receive what the agent reads of your model.
|
|
31
|
+
|
|
32
|
+
**The documentation** is at
|
|
33
|
+
[pcachim.github.io/xdfem3d](https://pcachim.github.io/xdfem3d). It is the
|
|
34
|
+
manual of the application, and it also describes the engine: the
|
|
35
|
+
[Scripting](https://pcachim.github.io/xdfem3d/scripting.html) section is the
|
|
36
|
+
guide to the Python API, with a reference for every method, and the
|
|
37
|
+
[Command Language](https://pcachim.github.io/xdfem3d/commands.html) lists the
|
|
38
|
+
commands.
|
|
39
|
+
|
|
40
|
+
The rest of this page is about the library.
|
|
41
|
+
|
|
42
|
+
## The engine and the application
|
|
43
|
+
|
|
44
|
+
They are two programs with one boundary, and the boundary is kept on purpose:
|
|
45
|
+
|
|
46
|
+
- **The application uses the engine only through its public API and the
|
|
47
|
+
`.xdfem3d` file.** It reaches nothing else, which is checked by a test on the
|
|
48
|
+
application's side. So everything the application does to a model, a program
|
|
49
|
+
can do: every change is a *command*, a method of `Model3D`.
|
|
50
|
+
- **The `.xdfem3d` file is the meeting point.** A model saved by the
|
|
51
|
+
application opens in a script, and the other way round, with its results if it
|
|
52
|
+
has some. The format is versioned: a file is read by the version that wrote
|
|
53
|
+
it and by every newer one, and a newer file is refused with a message and not
|
|
54
|
+
guessed at.
|
|
55
|
+
- **They are released independently**, on separate cycles. An engine release
|
|
56
|
+
does not imply an application release, and vice versa; the two version numbers
|
|
57
|
+
do not line up. The application's **Help ▸ About** lists both, so a report
|
|
58
|
+
can name the right one.
|
|
59
|
+
- **The licences differ, and neither restricts the other.** The engine is
|
|
60
|
+
LGPLv3: you may use, modify and redistribute it, from here. The application is
|
|
61
|
+
a separate work, freeware in compiled form, under its own terms. Nothing in
|
|
62
|
+
those terms restricts your rights to the engine.
|
|
63
|
+
|
|
64
|
+
What you would use the engine alone for: scripts that build or change many
|
|
65
|
+
models, parametric studies and optimisation, analysis in a service or a
|
|
66
|
+
pipeline, a post-processor, a front end of your own, or an AI agent working on a
|
|
67
|
+
model with no window at all.
|
|
68
|
+
|
|
69
|
+
## Install
|
|
70
|
+
|
|
71
|
+
Python **3.12 or later**. The compiled core is written in Rust and built with
|
|
72
|
+
[maturin](https://www.maturin.rs), so building from source needs a
|
|
73
|
+
[Rust toolchain](https://rustup.rs) and [`uv`](https://docs.astral.sh/uv/).
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
git clone https://github.com/pcachim/xdfem3d.git
|
|
77
|
+
cd xdfem3d
|
|
78
|
+
uv sync
|
|
79
|
+
uv run maturin develop # builds the core and installs the package in the environment
|
|
80
|
+
uv run pytest # the tests, and the validation cases
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The core install is NumPy, SciPy and
|
|
84
|
+
[eurocodepy](https://github.com/pcachim/eurocodepy) (the Eurocode actions and
|
|
85
|
+
combinations, and the catalogues of materials and profiles). The formats that
|
|
86
|
+
need a library of their own are extras, so that a solver in a script or a
|
|
87
|
+
service does not have to install them:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
pip install "xdfem3d[mcp]" # the MCP server: the mcp package
|
|
91
|
+
pip install "xdfem3d[ifc]" # ifcopenshell — IFC (openBIM) import and export
|
|
92
|
+
pip install "xdfem3d[dxf]" # ezdxf — DXF import and export
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Everything they cover is reached when it is used, so the engine imports,
|
|
96
|
+
assembles and solves without them.
|
|
97
|
+
|
|
98
|
+
## A first model
|
|
99
|
+
|
|
100
|
+
Units are metres, kN and kPa (kN/m²), tonne for mass, degrees for angles. A
|
|
101
|
+
model is built from the materials and the sections up to the elements and the
|
|
102
|
+
loads, and an analysis case says what to solve.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from xdfem3d import Model3D
|
|
106
|
+
|
|
107
|
+
m = Model3D("beam")
|
|
108
|
+
m.add_material("C30", E=3.3e7, nu=0.2, unit_weight=25.0, type="concrete")
|
|
109
|
+
m.add_section_shape("S", "C30", "rectangular", b=0.3, h=0.5)
|
|
110
|
+
|
|
111
|
+
m.add_node("A", 0, 0, 0)
|
|
112
|
+
m.add_node("B", 6, 0, 0)
|
|
113
|
+
m.add_bar("b", "A", "B", "S")
|
|
114
|
+
|
|
115
|
+
m.support("A", "ux", "uy", "uz", "rx") # a pin that also holds the twist
|
|
116
|
+
m.support("B", "uy", "uz") # a roller along x
|
|
117
|
+
|
|
118
|
+
m.add_load_case("Q", action_type="Q")
|
|
119
|
+
m.add_uniform_load("Q", "b", (0, 0, -10)) # 10 kN/m downwards, in global axes
|
|
120
|
+
m.add_analysis_case("ULS", "linear", coefficients={"Q": 1.0})
|
|
121
|
+
|
|
122
|
+
assert m.check() == [] # what would stop the analysis; empty when nothing does
|
|
123
|
+
results = m.solve_pending() # the analysis cases that have no current results
|
|
124
|
+
r = results["ULS"]
|
|
125
|
+
|
|
126
|
+
print(r.reaction("ULS", "A")) # fx, fy, fz, mx, my, mz — here fz = qL/2 = 30 kN
|
|
127
|
+
print(r.displacement("ULS", "B"))
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Every id is a name you choose. A command that gets something that does not
|
|
131
|
+
exist or does not fit raises `ModelError`, says what is wrong, and leaves the
|
|
132
|
+
model as it was. A model with results can be **locked**, so that its input
|
|
133
|
+
cannot change under them.
|
|
134
|
+
|
|
135
|
+
A model is saved with `xdfem3d.save(m, "beam.xdfem3d")` and read with
|
|
136
|
+
`xdfem3d.load(...)`; `export_script(m)` writes the model as a Python script that
|
|
137
|
+
rebuilds it. The [Scripting](https://pcachim.github.io/xdfem3d/scripting.html)
|
|
138
|
+
section goes on from here: combinations, results, files, and recipes that are
|
|
139
|
+
run by the tests of the documentation.
|
|
140
|
+
|
|
141
|
+
## What it does
|
|
142
|
+
|
|
143
|
+
- **Elements** — 3D frame bars with releases, offsets and member loads, in any
|
|
144
|
+
orientation; triangular and quadrilateral **shells** (membrane and bending,
|
|
145
|
+
with layered and reinforced-concrete sections); **solids** (hexahedra,
|
|
146
|
+
prisms, tetrahedra); node, line and surface **springs**; rigid links,
|
|
147
|
+
rigid diaphragms and equal-DOF constraints imposed exactly. **Panels** (slabs
|
|
148
|
+
and walls) are meshed from their outline, with openings, and share nodes with
|
|
149
|
+
their neighbours.
|
|
150
|
+
- **Sections and materials** — rectangular and general shapes, rolled profiles
|
|
151
|
+
and reinforced-concrete sections from the catalogues, fibre sections, and
|
|
152
|
+
shell and solid sections; materials from the catalogue or your own, with
|
|
153
|
+
uniaxial laws for the nonlinear analyses.
|
|
154
|
+
- **Loads** — nodal, point and uniform loads, loads on part of a bar, shell
|
|
155
|
+
pressure, temperature on bars, shells and solids, support settlements, masses,
|
|
156
|
+
and **field loads** given by functions of the coordinates.
|
|
157
|
+
- **Analysis** — linear static, P-Delta (second order), modal, response
|
|
158
|
+
spectrum (EC8 spectra included, CQC and SRSS), buckling, geometric nonlinear
|
|
159
|
+
(large displacements, corotational), material nonlinear (fibre sections,
|
|
160
|
+
plasticity in solids and in layered shells), pushover, and time history.
|
|
161
|
+
- **Combinations** — sums, envelopes, absolute sums and SRSS over the results
|
|
162
|
+
of analysis cases and of other combinations, and the **EN 1990** combinations
|
|
163
|
+
generated for you.
|
|
164
|
+
- **Structures from the library** — 26 **templates** (frames, trusses, slabs,
|
|
165
|
+
walls, a tower, a steel hall, a bridge deck, a block of solids…), and a
|
|
166
|
+
frame grid with stories.
|
|
167
|
+
- **File formats** — its own `.xdfem3d` (a zip of JSON, reproducible
|
|
168
|
+
byte for byte), IFC, DXF, SAP2000 `.s2k`, and an import of xdfem2D models
|
|
169
|
+
(`.x2d`) as a starting point.
|
|
170
|
+
- **Checks and editing** — a model check that says what is wrong or doubtful
|
|
171
|
+
before you run, and about 120 editing commands (add, edit, move, copy, rotate,
|
|
172
|
+
scale, divide, merge, rename, remove…) that are the same commands for a script,
|
|
173
|
+
the application and an agent.
|
|
174
|
+
|
|
175
|
+
Inside, the element kernels (bars, corotational bars, fibres, shells, solids,
|
|
176
|
+
springs and the materials) are written in Rust; assembly and solving use SciPy's
|
|
177
|
+
sparse solvers and ARPACK for the eigenproblems.
|
|
178
|
+
|
|
179
|
+
## Layout
|
|
180
|
+
|
|
181
|
+
- `rust/` — the compiled core (`xdfem3d_core`, exposed to Python with PyO3 as `xdfem3d._core`): the element kernels.
|
|
182
|
+
- `src/xdfem3d/` — the Python package: the model and its commands, the analyses, the file formats, the library and the MCP server.
|
|
183
|
+
- `tests/` — pytest: unit tests and closed-form cases.
|
|
184
|
+
- `validation/` — the cases against xdfem2D and OpenSees (frozen results, so they need neither).
|
|
185
|
+
- `docs/` — design notes of the core ([CORE_DESIGN.md](docs/CORE_DESIGN.md)).
|
|
186
|
+
|
|
187
|
+
## The MCP server
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
python -m xdfem3d.mcp # serves one model over MCP, on standard input and output
|
|
191
|
+
python -m xdfem3d.mcp --root ./work # the agent may read and write files only in that folder
|
|
192
|
+
claude mcp add xdfem3d -- python -m xdfem3d.mcp
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
An agent builds, edits, checks and analyses a model and reads the results through
|
|
196
|
+
fifteen tools; an `edit` is a list of commands applied all together or not at all, and
|
|
197
|
+
undone together. The server works on a model of its own, in memory, and has no window.
|
|
198
|
+
To let an agent work on the model that is open in the application, use the
|
|
199
|
+
application's Agent panel (see [AI Agents](https://pcachim.github.io/xdfem3d/mcp.html)).
|
|
200
|
+
|
|
201
|
+
## Validation and known limits
|
|
202
|
+
|
|
203
|
+
The engine is compared with what is independent of it, and the cases run with
|
|
204
|
+
`uv run pytest` (the validation cases are in `validation/`, next to the unit
|
|
205
|
+
tests in `tests/`):
|
|
206
|
+
|
|
207
|
+
- **Closed forms**: axial, torsion, bending, releases and member loads, diagrams,
|
|
208
|
+
constraints, vibration frequencies, effective masses, a single-degree-of-freedom
|
|
209
|
+
spectrum, Euler loads, beam-columns, the elastica, the Von Mises truss, moment-
|
|
210
|
+
curvature of steel and reinforced-concrete sections, a plastic cantilever, shell
|
|
211
|
+
plates against the Navier–Mindlin series, buckling of a plate, patch tests on
|
|
212
|
+
distorted meshes, among others.
|
|
213
|
+
- **xdfem2D**: plane frames solved by the 3D beam reproduce the 2D engine
|
|
214
|
+
(static, modal, response spectrum with CQC and SRSS, and P-Delta) to 1e-8 and
|
|
215
|
+
better.
|
|
216
|
+
- **OpenSees**: a space frame with torsion and different member axes (static,
|
|
217
|
+
modal and time history), a corotational cantilever in large displacement, fibre
|
|
218
|
+
and reinforced-concrete pushovers, brick and shell plasticity, and MITC4 plates.
|
|
219
|
+
The OpenSees results are frozen in the repository, so the tests need no OpenSees.
|
|
220
|
+
|
|
221
|
+
What that does and does not establish, so the result is not taken for more:
|
|
222
|
+
|
|
223
|
+
- **Validated against a formula** is not **validated for your structure**. A
|
|
224
|
+
case here checks that an element reproduces a textbook solution or another
|
|
225
|
+
program, not that it suits a given geometry, mesh or load path.
|
|
226
|
+
- **There are no design checks in the engine yet**: no verification of
|
|
227
|
+
reinforced concrete, steel or timber members to a code, and no design
|
|
228
|
+
reports. It analyses; it does not dimension. The Eurocode parts it has are the
|
|
229
|
+
actions, the combinations (EN 1990) and the response spectra (EC8).
|
|
230
|
+
- A generated validation report like the one of xdfem2D is **not published
|
|
231
|
+
yet**; what exists is the suite in `validation/` and `tests/`.
|
|
232
|
+
- Where neither a closed form nor a comparison with xdfem2D or OpenSees
|
|
233
|
+
covers a kind of problem, nothing independent does: say so, in a report, when
|
|
234
|
+
your problem is of that kind.
|
|
235
|
+
|
|
236
|
+
## A note on results
|
|
237
|
+
|
|
238
|
+
xdfem3d computes analysis results. It does not verify them, and producing a
|
|
239
|
+
number is not the same as the number being right for your problem. It is an aid
|
|
240
|
+
to calculation, not a substitute for engineering judgement: anyone using its
|
|
241
|
+
output in the design or construction of a real structure is responsible for
|
|
242
|
+
verifying it independently and remains the engineer of record. The same holds
|
|
243
|
+
for anything that an AI agent does with the model or says about it.
|
|
244
|
+
|
|
245
|
+
## Citing
|
|
246
|
+
|
|
247
|
+
If xdfem3d contributes to published work, please cite it:
|
|
248
|
+
|
|
249
|
+
> Cachim, P. (2026). *pcachim/xdfem3d* [Computer software].
|
|
250
|
+
> https://github.com/pcachim/xdfem3d
|
|
251
|
+
|
|
252
|
+
Say the version of the engine you used (`xdfem3d.__version__`, and the
|
|
253
|
+
application's Help ▸ About if you used it).
|
|
254
|
+
|
|
255
|
+
## Support and contributing
|
|
256
|
+
|
|
257
|
+
Bugs and questions, for the library or the application, go to
|
|
258
|
+
[Issues](https://github.com/pcachim/xdfem3d/issues). A report with a model that
|
|
259
|
+
reproduces the problem (the `.xdfem3d` file, or a script) is the most useful
|
|
260
|
+
thing you can send. For anything else, write to
|
|
261
|
+
[eurocodepy@gmail.com](mailto:eurocodepy@gmail.com).
|
|
262
|
+
|
|
263
|
+
Development happens in a private repository, and what is published here is
|
|
264
|
+
that work: open an issue before you spend time on a pull request, because a
|
|
265
|
+
change may not be able to land as it is.
|
|
266
|
+
|
|
267
|
+
## Licence
|
|
268
|
+
|
|
269
|
+
The engine — everything in this tree — is under the **LGPLv3**; see
|
|
270
|
+
[LICENSE.md](LICENSE.md). It depends on
|
|
271
|
+
[eurocodepy](https://github.com/pcachim/eurocodepy), also LGPLv3, for the
|
|
272
|
+
Eurocode actions and combinations and the catalogues of materials and profiles.
|
|
273
|
+
|
|
274
|
+
The desktop application is a separate work, distributed as freeware in compiled
|
|
275
|
+
form under its own terms (see the
|
|
276
|
+
[Licenses page](https://pcachim.github.io/xdfem3d/license.html), and
|
|
277
|
+
`LICENSE.md` shipped with the application). Nothing in those terms restricts
|
|
278
|
+
your rights to the engine: you may use, modify and redistribute it under the
|
|
279
|
+
LGPLv3, from here.
|