A Docker-based development environment for NeoPZ — a C++ finite element method (FEM) library developed by LabMeC at Unicamp.
This repository provides a fully automated, reproducible setup: a single script builds a Docker image with NeoPZ compiled and installed, ready for you to develop, build, and debug your own FEM projects inside a container — with full VS Code integration.
- Overview
- Prerequisites
- Repository Structure
- Quick Start
- Step 1 — Build the Image (
build.sh) - Step 2 — Run the Container (
run.sh) - Container Layout
- Developing Your Own Project
- VS Code Extensions
- Dockerfile Architecture
NeoPZ is a high-performance C++ library for the development of finite element simulations. Setting up its dependencies (CMake, optional solvers, logging libraries, Intel MKL) manually is tedious and error-prone across different operating systems.
This project solves that by packaging NeoPZ and all its optional dependencies into a Docker image. You write your simulation code on your host machine; the container handles compilation and execution in a clean, controlled environment.
| Tool | Notes |
|---|---|
| Docker | Installed automatically by build.sh on Debian/Ubuntu and macOS (via Homebrew) |
| VS Code (optional) | Required only for the VS Code integration features |
| Dev Containers extension (optional) | VS Code extension ms-vscode-remote.remote-containers |
Apple Silicon (M1/M2/M3): Intel MKL is x86_64-only and will be automatically disabled. All other features work normally.
neopz-docker/
├── Dockerfile # Multi-stage image definition
├── build.sh # Interactive image build script
├── run.sh # Container startup and project scaffold script
└── install_vscode_extensions.sh # Installs recommended host-side VS Code extensions
# 1. Build the Docker image (interactive – you will be asked about optional features)
./build.sh
# 2. Start the container and (optionally) create an example project
./run.shThat is all. run.sh will open VS Code attached to the running container if code is in your PATH.
./build.sh # Build the image only
./build.sh vscode # Build the image and also install the host-side VS Code extensionsThe script guides you through an interactive configuration menu, then calls docker build with the chosen flags. If Docker is not installed, it will install it automatically (Linux via the official Docker APT repository; macOS via Homebrew).
| Option | Default | Description |
|---|---|---|
BUILD_TYPE |
Debug |
Debug: includes debug symbols, no optimization — ideal for development and stepping through code in a debugger. Release: full compiler optimizations, smaller binary — use for production runs. |
BUILD_UNITTESTING |
OFF |
Compiles the NeoPZ unit test suite using the Catch2 framework. Enable this if you want to verify the NeoPZ build itself. |
USING_LOG4CXX |
ON |
Enables the Apache Log4cxx logging library inside NeoPZ. Provides structured, levelled log output for simulation diagnostics. |
USING_MUMPS |
OFF |
Enables the MUMPS multifrontal sparse direct solver. Required for large, ill-conditioned, or saddle-point linear systems that iterative solvers struggle with. |
USING_MKL |
OFF |
Links NeoPZ against Intel oneAPI MKL for optimised BLAS/LAPACK routines. Significant performance gain on Intel CPUs. x86_64 only. |
USING_METIS |
OFF |
Enables the METIS graph partitioner for mesh partitioning and reordering. Works independently of other options. When both METIS and MUMPS are enabled, MUMPS is also compiled with METIS support automatically. |
MUMPS supports four floating-point variants. The double (d) variant is always compiled when MUMPS is enabled. You may additionally select:
| Code | Variant | Use case |
|---|---|---|
s |
smumps — real single precision |
Reduced memory footprint |
c |
cmumps — complex single precision |
Complex-valued PDEs (low precision) |
z |
zmumps — complex double precision |
Complex-valued PDEs (high precision) |
all |
All four variants |
./run.shThis script:
- Checks that Docker is available and running (starts the daemon if needed).
- Builds the image automatically if it does not exist yet.
- Asks for the projects directory on your host (default:
~/programming). - Optionally scaffolds a ready-to-compile example project (see below).
- Starts the container in detached mode with your projects directory mounted as a volume.
- Opens VS Code attached to the running container (if
codeis in your PATH).
| Host path | Container path | Purpose |
|---|---|---|
<projects_dir> (you choose) |
/home/labmec/programming/neopz/neopz_projects |
Your source code, live-synced between host and container |
Everything else inside the container (NeoPZ headers, libraries, source, optional solvers) is baked into the image and is read-only from your perspective.
If you choose to create an example project, run.sh generates a complete, compilable project with:
CMakeLists.txt— finds and links against the installed NeoPZ package.main.cpp— a Darcy flow simulation on a 2D quadrilateral mesh, producing VTK output.<name>.code-workspace— a VS Code multi-root workspace that opens both your project folder and the NeoPZ source tree (for IDE navigation and debugger source stepping).
To compile and run it inside the container:
# Open a shell in the running container
docker exec -it neopz-dev /bin/bash
# Navigate to your project and build it
cd /home/labmec/programming/neopz/neopz_projects/firsttest
cmake -B build -G Ninja -DNeoPZ_DIR=$NeoPZ_DIR
cmake --build build
./build/firsttestWhen run.sh finishes, VS Code opens directly attached to the container via the Dev Containers extension. All editing, building, debugging, and IntelliSense happen inside the container — no local C++ toolchain required.
The generated .code-workspace file adds the NeoPZ source tree as a second root folder, enabling:
- Full symbol navigation across NeoPZ headers and implementation files.
- Source-level stepping into NeoPZ code with GDB.
clangd/IntelliSense powered by thecompile_commands.jsongenerated during the NeoPZ build.
To stop the container:
docker stop neopz-devThe container is started with --rm, so it is removed automatically on stop. Your project files remain safe on the host.
/home/labmec/programming/neopz/
├── neopz/ ← NeoPZ source tree (headers + compile_commands.json, no build artifacts)
├── neopz_install/ ← Installed NeoPZ headers and compiled libraries
├── mumps/ ← MUMPS install (present only when built with USING_MUMPS=1)
└── neopz_projects/ ← Volume mount — your project source code lives here
The environment variable NeoPZ_DIR is pre-set to /home/labmec/programming/neopz/neopz_install inside the container, so CMake's find_package(NeoPZ REQUIRED) works without any extra flags.
Any project inside neopz_projects/ follows this minimal CMake template:
cmake_minimum_required(VERSION 3.14)
project(MySimulation)
find_package(NeoPZ REQUIRED HINTS $ENV{NeoPZ_DIR})
add_executable(MySimulation main.cpp)
target_link_libraries(MySimulation NeoPZ::pz)Build it inside the container:
cmake -B build -G Ninja
cmake --build buildRunning ./build.sh vscode (or calling install_vscode_extensions.sh directly) installs the following extensions on the host:
| Extension | Purpose |
|---|---|
ms-vscode.cpptools |
C/C++ language support, IntelliSense, and debugging |
ms-vscode.cmake-tools |
CMake project integration, configure/build from the VS Code UI |
The Dev Containers extension (ms-vscode-remote.remote-containers) must be installed separately from the VS Code Marketplace to use the container-attach workflow.
The image is built in three stages to keep the final image lean:
| Stage | Base | Purpose |
|---|---|---|
builder-mumps |
debian:trixie-slim |
Clones and compiles MUMPS from source. Produces an empty directory when USING_MUMPS=0, so downstream stages are always valid. |
builder |
debian:trixie-slim |
Installs the build toolchain, optional packages (Log4cxx, METIS, MKL), copies MUMPS artifacts, clones NeoPZ, and runs the CMake configure + build + install cycle. Strips build artifacts from the source tree before export. |
| (final) | debian:trixie-slim |
Copies only the installed NeoPZ files, the stripped source tree, MUMPS libs, and MKL runtime libs from the builder stages. Registers shared libraries with ldconfig. Creates the labmec user and sets the working directory. |
This multi-stage approach ensures that compilers, intermediate object files, and build caches are never present in the shipped image.