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.
Files changed (56) hide show
  1. xdfem3d-2026.11.14/LICENSE.md +58 -0
  2. xdfem3d-2026.11.14/PKG-INFO +310 -0
  3. xdfem3d-2026.11.14/README.md +279 -0
  4. xdfem3d-2026.11.14/pyproject.toml +48 -0
  5. xdfem3d-2026.11.14/rust/Cargo.lock +269 -0
  6. xdfem3d-2026.11.14/rust/Cargo.toml +17 -0
  7. xdfem3d-2026.11.14/rust/src/beam3d.rs +741 -0
  8. xdfem3d-2026.11.14/rust/src/corot.rs +754 -0
  9. xdfem3d-2026.11.14/rust/src/fiber.rs +209 -0
  10. xdfem3d-2026.11.14/rust/src/geomsearch.rs +217 -0
  11. xdfem3d-2026.11.14/rust/src/lib.rs +1540 -0
  12. xdfem3d-2026.11.14/rust/src/material.rs +309 -0
  13. xdfem3d-2026.11.14/rust/src/shell.rs +1856 -0
  14. xdfem3d-2026.11.14/rust/src/solid.rs +1023 -0
  15. xdfem3d-2026.11.14/rust/src/spring.rs +72 -0
  16. xdfem3d-2026.11.14/src/xdfem3d/__init__.py +51 -0
  17. xdfem3d-2026.11.14/src/xdfem3d/analysis.py +370 -0
  18. xdfem3d-2026.11.14/src/xdfem3d/buckling.py +111 -0
  19. xdfem3d-2026.11.14/src/xdfem3d/cases.py +648 -0
  20. xdfem3d-2026.11.14/src/xdfem3d/commands.py +81 -0
  21. xdfem3d-2026.11.14/src/xdfem3d/constraints.py +232 -0
  22. xdfem3d-2026.11.14/src/xdfem3d/discretize.py +255 -0
  23. xdfem3d-2026.11.14/src/xdfem3d/dxf.py +842 -0
  24. xdfem3d-2026.11.14/src/xdfem3d/dynamics.py +456 -0
  25. xdfem3d-2026.11.14/src/xdfem3d/events.py +66 -0
  26. xdfem3d-2026.11.14/src/xdfem3d/fibers.py +108 -0
  27. xdfem3d-2026.11.14/src/xdfem3d/fieldloads.py +163 -0
  28. xdfem3d-2026.11.14/src/xdfem3d/fields.py +122 -0
  29. xdfem3d-2026.11.14/src/xdfem3d/fileformat.py +374 -0
  30. xdfem3d-2026.11.14/src/xdfem3d/geometry.py +659 -0
  31. xdfem3d-2026.11.14/src/xdfem3d/ifc.py +594 -0
  32. xdfem3d-2026.11.14/src/xdfem3d/library.py +183 -0
  33. xdfem3d-2026.11.14/src/xdfem3d/mcp/__init__.py +8 -0
  34. xdfem3d-2026.11.14/src/xdfem3d/mcp/__main__.py +72 -0
  35. xdfem3d-2026.11.14/src/xdfem3d/mcp/session.py +53 -0
  36. xdfem3d-2026.11.14/src/xdfem3d/mcp/tools.py +364 -0
  37. xdfem3d-2026.11.14/src/xdfem3d/members.py +174 -0
  38. xdfem3d-2026.11.14/src/xdfem3d/merge.py +427 -0
  39. xdfem3d-2026.11.14/src/xdfem3d/modal.py +194 -0
  40. xdfem3d-2026.11.14/src/xdfem3d/model.py +3790 -0
  41. xdfem3d-2026.11.14/src/xdfem3d/modelcheck.py +702 -0
  42. xdfem3d-2026.11.14/src/xdfem3d/modelinfo.py +149 -0
  43. xdfem3d-2026.11.14/src/xdfem3d/nonlinear.py +745 -0
  44. xdfem3d-2026.11.14/src/xdfem3d/panels.py +255 -0
  45. xdfem3d-2026.11.14/src/xdfem3d/resultsio.py +279 -0
  46. xdfem3d-2026.11.14/src/xdfem3d/sap2000.py +705 -0
  47. xdfem3d-2026.11.14/src/xdfem3d/scriptexport.py +160 -0
  48. xdfem3d-2026.11.14/src/xdfem3d/sections.py +91 -0
  49. xdfem3d-2026.11.14/src/xdfem3d/solidgeom.py +68 -0
  50. xdfem3d-2026.11.14/src/xdfem3d/solidnl.py +265 -0
  51. xdfem3d-2026.11.14/src/xdfem3d/spectra.py +64 -0
  52. xdfem3d-2026.11.14/src/xdfem3d/spectrum.py +117 -0
  53. xdfem3d-2026.11.14/src/xdfem3d/springs.py +209 -0
  54. xdfem3d-2026.11.14/src/xdfem3d/statics.py +522 -0
  55. xdfem3d-2026.11.14/src/xdfem3d/templates.py +1282 -0
  56. 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
+ [![Python versions](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/)
34
+ [![Core: Rust](https://img.shields.io/badge/core-Rust-orange)](https://www.rust-lang.org/)
35
+ [![eurocodepy](https://img.shields.io/badge/uses-eurocodepy-green)](https://github.com/pcachim/eurocodepy)
36
+ [![Licence: LGPLv3](https://img.shields.io/badge/licence-LGPLv3-blue)](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
+ [![Python versions](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/)
4
+ [![Core: Rust](https://img.shields.io/badge/core-Rust-orange)](https://www.rust-lang.org/)
5
+ [![eurocodepy](https://img.shields.io/badge/uses-eurocodepy-green)](https://github.com/pcachim/eurocodepy)
6
+ [![Licence: LGPLv3](https://img.shields.io/badge/licence-LGPLv3-blue)](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.