Cauchy Desktop
Native FEA Application for 2D Structural Analysis
Mesh. Solve. Visualize. -- A complete finite element analysis workflow in a single application.
Engineering Design Process
Problem Statement
Commercial FEA tools like Abaqus and ANSYS are powerful, but their black-box nature hides implementation details. A native desktop application provides direct access to the solver internals, custom visualization of intermediate results, and a transparent workflow for educational and prototyping use. The goal is not to replace commercial tools, but to build a working application that demonstrates the full FEA pipeline from mesh generation to stress recovery.
Why Qt 6?
The GUI framework choice was driven by three constraints: direct C++ solver linkage (no IPC overhead), native look and feel, and cross-platform packaging. Qt 6 satisfies all three. The comparison below shows why alternatives were rejected.
| Framework | Why Not for Cauchy |
|---|---|
| Dear ImGui | No native file dialogs, no dock widgets, custom-only look, less industry recognition |
| Rust + Tauri | C++/Rust FFI overhead makes no sense for a solver-heavy app; two languages to maintain |
| Flutter | Dart/C++ FFI adds complexity; Material Design looks like a phone app on desktop |
| wxWidgets | Sparse documentation, no built-in plotting, manual packaging on macOS |
| GTK | Poor macOS/Windows support, C API is painful from C++, tiny scientific ecosystem |
Solver Integration
The desktop application links directly to the existing header-only
solver. A SolveConfig struct is populated from the GUI,
passed to run_case(), and the returned
SolveResult struct feeds into visualization models.
No JSON serialization, no process spawning, no IPC -- direct struct
passing at function-call speed.
struct SolveConfig {
CaseType case_type;
ElementType element_type;
PlaneType plane_type;
int nx, ny;
Material material;
std::vector<BoundaryCondition> boundary_conditions;
SolverType solver_type;
double cg_tolerance;
int cg_max_iterations;
bool use_adaptivity;
int adaptive_iterations;
};
struct SolveResult {
bool success;
std::string error_message;
Mesh mesh;
std::vector<NodeDisplacement> displacements;
std::vector<ElementStress> stresses;
double max_displacement;
double strain_energy;
// ... convergence data, timing, etc.
};
Async Execution
Solver runs execute on a dedicated QThread. The main
thread remains responsive -- the progress bar updates, the cancel
button works, and the viewport stays interactive. The thread emits
finished(SolveResult) when complete, and the UI
switches to the results view automatically.
Visualization Strategy
All rendering uses QPainter on CPU. For a 2D FEA tool
with meshes under 100K elements, CPU rendering is more than
sufficient. It avoids GPU driver dependencies, works on headless
systems, and produces deterministic output. The tradeoff is acceptable
for the target use case: engineering analysis, not real-time gaming.
Cross-Platform Packaging
CMake builds a native .app bundle on macOS, a
.desktop entry on Linux, and an NSIS installer on
Windows. The same build system produces all three artifacts from a
single CMakeLists.txt. No separate build scripts per platform.
Application Walkthrough
Cauchy Desktop provides a complete FEA workflow organized into dockable panels. The left dock handles input (mesh, boundary conditions, materials), the center is the 2D viewport, and the right dock controls the solver and displays results. A collapsible bottom dock holds analysis plots.
a. Mesh Editor
Generate structured Q4 or Q8 meshes with configurable element counts (nx, ny). Mesh grading allows biased element sizing toward edges or corners. Real-time quality metrics show aspect ratio, skewness, and Jacobian ratio for each element before solving.
b. Boundary Condition Editor
Point-and-click boundary condition assignment. Select nodes or edges in the viewport, choose Dirichlet (fixed displacement) or Neumann (applied force), pick the active DOFs (ux, uy), and enter the value. Boundary conditions appear as colored symbols on the mesh: yellow triangles for fixed, green arrows for forces.
c. Material Properties
Configure material properties for the analysis: Young's modulus (E), Poisson's ratio (ν), density (ρ), thickness (t), and thermal expansion coefficient (α). Preset materials (steel, aluminum, titanium) fill common values. The plane stress/strain toggle adjusts the constitutive matrix automatically.
d. Solver Panel
Choose between Cholesky (direct, for small meshes) or Conjugate Gradient (iterative, for large meshes). Set the CG tolerance and maximum iterations. The progress bar shows assembly and solve phases in real time. The cancel button interrupts the solver mid-run without crashing the application.
e. 2D Viewport
Pan and zoom the mesh with mouse controls. The viewport renders the wireframe mesh, deformed shape (with adjustable scale factor), and contour coloring for any selected field. Toggle between original and deformed configurations. Coordinate axes and grid snapping provide spatial reference.
f. Stress Analysis
Visualize six stress components: sigma_xx, sigma_yy, sigma_xy, Von Mises, sigma_1 (max principal), and sigma_2 (min principal). Scientific colormaps (turbo, viridis, RdBu_r) ensure perceptual accuracy. The colorbar at the bottom shows the exact min/max range. Nodal stress recovery via superconvergent patch recovery (SPR) provides smooth contours.
g. Principal Stress Arrows
Element-based arrow visualization shows the principal stress directions at each element centroid. Red arrows indicate tension (sigma > 0), blue arrows indicate compression (sigma < 0). Arrow length is proportional to stress magnitude. Toggle on/off via the toolbar to reduce visual clutter.
h. Mesh Quality Overlay
A color-coded overlay shows mesh quality metrics per element: aspect ratio, Jacobian ratio, and skewness. Red elements indicate poor quality that may affect solution accuracy. This overlay helps identify problematic regions before running the solver, saving computation time on meshes that need refinement.
i. Probe Tool
Click any point in the viewport to read the local stress and displacement values. The probe tool performs ray-casting from the mouse position to the mesh, interpolates shape functions at the hit point, and displays a tooltip with all six stress components, both displacement components, and the element ID. Essential for quick spot-checks without exporting data.
j. Analysis Plots (Bottom Dock)
A collapsible bottom dock contains a QTabWidget with six analysis plots. Each tab provides a different perspective on the solution data, all rendered with custom QPainter widgets.
| Tab | Widget | Description |
|---|---|---|
| Stress Distribution | StressHistogram | Histogram of sigma_xx, sigma_yy, von_mises across all elements |
| Energy Balance | EnergyBalanceChart | Bar chart comparing strain energy 0.5*u^T*K*u vs work done 0.5*f^T*u |
| Displacement Profile | DisplacementLineChart | uy along top edge of mesh (FEA data points connected by lines) |
| Load-Displacement | LoadDisplacementChart | Applied force vs max displacement, accumulates across multiple solves |
| Error Map | ErrorHeatmap | Per-element ZZ error indicator rendered as a colored overlay |
| Convergence | ConvergenceChart | Log-log plot of mesh refinement convergence (GCI, observed order) |
k. Project Files
Save and load complete project state as JSON files with the
.cauchy extension. Project files store the mesh,
boundary conditions, material properties, solver settings, and
results. Reopen a project to resume analysis without re-entering
parameters. The JSON format is human-readable and compatible with
the existing CLI pipeline.
l. PNG Export
Export the current viewport state as a high-resolution PNG at 1920x1080. The export includes the mesh contour, colorbar with min/max labels, boundary condition symbols, and title text. Suitable for reports, presentations, and the portfolio website.
Architecture Deep-Dive
System Architecture
+-------------------------------------------------------------+
| Cauchy Desktop |
+-------------------------------------------------------------+
| |
| +------------------+ +------------------+ +----------+ |
| | Mesh Editor | | 2D Viewport | | Solver | |
| | (Left Dock) | | (Center) | | Panel | |
| | | | | | (Right) | |
| | - nx, ny | | - QPainter | | | |
| | - Element type | | - Mesh wire | | - Cholesky| |
| | - Grading | | - Deformed shape| | - CG | |
| | - Quality | | - Contours | | - Progress| |
| +------------------+ | - Arrows | | - Cancel | |
| | - Probes | +----------+ |
| +------------------+ +------------------+ |
| | BC Editor | | +----------+ |
| | Material Props | | | Analysis | |
| | (Left Dock) | | | Plots | |
| +------------------+ | | (Bottom) | |
| | | - 6 tabs | |
| +----------+----------+ +----------+ |
| | Qt Signal/Slot | |
| | Communication | |
| +----------+----------+ |
| | |
| +----------+----------+ |
| | Solver Runner | |
| | (QThread) | |
| | - Assembly | |
| | - Solve | |
| | - Postprocess | |
| +----------+----------+ |
| | |
| +----------+----------+ |
| | Solver Backend | |
| | (Header-only C++) | |
| | - fea.hpp | |
| | - elements.hpp | |
| | - sparse.hpp | |
| | - solver.hpp | |
| | - mesh.hpp | |
| +---------------------+ |
+-------------------------------------------------------------+
Component Breakdown
| Component | File | Responsibility |
|---|---|---|
| Application Entry | main.cpp |
QApplication setup, style, window creation |
| Main Window | main_window.hpp/cpp |
QMainWindow with menu, toolbar, dock layout |
| Mesh Editor | mesh_editor.hpp/cpp |
Mesh generation parameters, quality display |
| BC Editor | bc_editor.hpp/cpp |
Boundary condition assignment and editing |
| Viewport | viewport_widget.hpp/cpp |
2D rendering with QPainter, pan/zoom, overlays |
| Solver Panel | solver_panel.hpp/cpp |
Solver settings, progress, results summary |
| Solver Runner | solver_runner.hpp/cpp |
QThread wrapper for async solver execution |
| Result Model | result_model.hpp/cpp |
QAbstractItemModel for stress/displacement tables |
| Project I/O | project_io.hpp/cpp |
Save/load .cauchy JSON project files |
| Convergence Chart | convergence_chart.hpp/cpp |
Log-log mesh refinement convergence plot |
| Stress Histogram | stress_histogram.hpp/cpp |
Element stress distribution histogram |
| Energy Balance | energy_balance_chart.hpp/cpp |
Strain energy vs work done bar chart |
| Probe Tool | probe_tool.hpp/cpp |
Click-to-probe stress/displacement at any point |
| Mesh Quality Overlay | mesh_quality_overlay.hpp/cpp |
Aspect ratio / Jacobian heatmap overlay |
Data Flow
User Input
|
v
Mesh Editor / BC Editor / Material Props
|
v
SolveConfig (struct)
|
v
SolverRunner (QThread) --> run_case(config)
| |
| v
| Solver Backend (fea.hpp)
| |
| v
| SolveResult (struct)
| |
v v
Result Model <----------- UI Update
|
v
Viewport / Analysis Plots / Probe Tool
Thread Model
| Thread | Responsibility | Communication |
|---|---|---|
| Main Thread (UI) | Event loop, rendering, user input, menu actions | Receives signals from solver thread |
| Solver Thread (QThread) | Assembly, solve, postprocess, convergence | Emits progress(int), finished(SolveResult), error(QString) |
The solver thread is short-lived: created when the user clicks "Solve," destroyed when results are received. No shared state between threads -- the solver reads from a const SolveConfig and returns a new SolveResult. The UI thread never blocks.
Technical Specifications
| Specification | Detail |
|---|---|
| Framework | Qt 6 (QWidgets) |
| Language | C++20 |
| Solver | Header-only, linked directly (no IPC) |
| Rendering | QPainter (CPU), no GPU dependency |
| Async Execution | QThread with progress signals |
| Project Format | JSON (.cauchy), human-readable |
| Packaging | MACOSX_BUNDLE, .desktop, NSIS |
| Build System | CMake with AUTOMOC / AUTORCC / AUTOUIC |
| Export Resolution | 1920x1080 PNG |
| Colormaps | Scientific: turbo, viridis, RdBu_r (never rainbow) |
| License | MIT (consistent with solver backend) |
Build & Install
One command builds, installs, and launches the application:
./build-desktop.sh
Under the hood, this script runs:
# Build
cmake -B build-desktop -S . -DCMAKE_BUILD_TYPE=Release
cmake --build build-desktop -j$(nproc)
# Install (macOS: copies to /Applications)
cmake --install build-desktop
# Launch
open /Applications/Cauchy.app # macOS
# or: ./build-desktop/bin/Cauchy # Linux
Prerequisites: Qt 6 (Homebrew on macOS, apt on Linux), C++20 compiler (Clang 14+ or GCC 12+), CMake 3.20+.
Comparison with Commercial Tools
| Feature | Cauchy Desktop | Abaqus | ANSYS | CalculiX |
|---|---|---|---|---|
| Price | Free (MIT) | $20K+/year | $20K+/year | Free (GPL) |
| Source Code | Open source | Closed | Closed | Open source |
| Element Types | Q4, Q8, Bar, T3 | 200+ elements | 200+ elements | ~30 elements |
| 3D Support | In progress | Full 3D | Full 3D | Full 3D |
| Nonlinear | Planned | Full | Full | Partial |
| GUI | Native Qt 6 | Full GUI | Full GUI | Pre/post only |
| Adaptive Refinement | ZZ estimator | Built-in | Built-in | Manual |
| API / Scripting | JSON + CLI | Python (Abaqus API) | APDL / Python | Keywords |
| Target Audience | Learning / Portfolio | Industry / Research | Industry / Research | Academic |
Cauchy Desktop is not a commercial FEA replacement. It is a portfolio piece that demonstrates understanding of element formulation, sparse assembly, solver implementation, and engineering visualization -- skills directly transferable to commercial tool development at companies like SpaceX, Lockheed Martin, or ANSYS.
Verification Checklist
| Status | Item |
|---|---|
| Done | Solver runs asynchronously without blocking UI |
| Done | Mesh generation produces correct mesh for all 6 cases |
| Done | BC editor assigns and persists boundary conditions correctly |
| In Progress | Results visualization matches web viewer output |
| In Progress | Convergence study produces correct GCI and order of convergence |
| Planned | Project save/load round-trips correctly |
| Planned | Error handling shows user-friendly messages for invalid inputs |
| Planned | Probe tool reads correct stress/displacement values at clicked points |
| Planned | Mesh quality overlay correctly identifies invalid elements |
| Done | Cross-platform build passes on macOS |
| Planned | Installer packages build correctly for all target platforms |
| Done | All existing 22 Google Test cases still pass |
| Done | Stress histogram displays sigma_xx, sigma_yy, von_mises distributions |
| Done | Energy balance chart shows strain energy vs work done |
| Done | Displacement line chart plots uy along top edge |
| Done | Load-displacement chart accumulates across multiple solves |
| Done | Error heatmap renders per-element ZZ error indicators |
| Done | Convergence chart wired into bottom dock |
| Done | macOS .app bundle builds and launches correctly |