This repository contains MATLAB prototypes of several domain decomposition methods (DDM) for the 2D Poisson equation on triangular meshes produced with Gmsh. Each solver assembles local stiffness matrices for every partition, eliminates interior degrees of freedom to form Schur complements on the interface, and either solves the resulting system directly or with preconditioned conjugate gradients (PCGM). The code is organised by algorithm (direct Schur complement, Neumann preconditioned PCGM, lumped preconditioning, two-level additive Schwarz, and FETI-DP) and shares a common set of mesh-parsing and algebra utilities. Reference solutions are compared with the manufactured solution
u(x,y) = sin(pi*x) * sin(2*pi*y) so that every script reports the maximum-norm error and plots the solution, reference solution, and error surface.
- MATLAB R2018a or newer. The scripts rely only on base MATLAB functions plus
pdesurffor plotting (from PDE Toolbox). - Gmsh 3.x/4.x for generating
.geoand.mshfiles. The sample geometry is insquare.geo. - A mesh partitioner that can inject partition tags into the
.mshfile. The repository ships the GPL-licensedpuffin-0.1.6source, which can partition a Gmsh mesh into equal-sized subdomains and emit the extended.mshfiles that theExtractGmshPart_puffparser expects. - (Optional) A PDF viewer if you want to build the Puffin manual in
puffin-0.1.6/doc/manual.
After cloning the repository, add it to your MATLAB path once per session:
addpath(genpath('/path/to/ddm-matlab'));DirectDDM/- One-level Schur complement solver that eliminates interior unknowns and solves the reduced interface system directly.Neumann/- PCGM solver with a Neumann-Neumann preconditioner assembled from subdomain solves.LumpedPreconditoner/- PCGM solver that uses a lumped interface preconditioner (diagonal of the Schur complement scaled by the partition-of-unity).DDM-TwoLevel/- Two-level additive Schwarz method that augments the lumped preconditioner with a coarse problem built from corner and remaining interface nodes.FETI-DP/- Dual-primal FETI formulation that enforces continuity with Lagrange multipliers and coarse primal variables at corners and edges.ExtractGmsh/- Standalone scripts to parse standard and partitioned.mshfiles, dump intermediate point/edge/triangle tables, and debug interface detection.sparsity/- Copy of the two-level solver withAssembleForSparse.mfor inspecting the sparsity of the assembled global matrix.puffin-0.1.6/andpuffin-0.1.6.zip- Third-party partitioner from Johan Hoffman and Anders Logg (GPLv2). Build it if you need to generate new partitioned Gmsh files.ExtractGmshPart_puff.m,GetInterfaceNodes*.m,GetRestrictionMatrix.m,GetScalingMatrix*.m,AssembleMatrix.m,AssembleVector.m, andPoisson.mare replicated inside each solver directory so that the scripts are self-contained when launched from MATLAB.
Most solver folders also include pre-generated meshes such as squarepart4.msh, square2_part4.msh, or mymeshpart10.msh, and the local stiffness/load files A_i.mat / b_i.mat that are regenerated every time you run a script.
- Generate or edit a geometry. Use the provided
square.geoas a starting point or author a new.geofile in Gmsh. Export a.mshfile with first-order triangles. - Partition the mesh. Run Puffin (or another tool) to split the mesh into the desired number of subdomains and write a
.mshfile that contains, for every triangle, the number of adjacent parts and their IDs. The examplessquarepart{4,10,20,...}.mshandsquare2_part4.mshillustrate the expected format. - Place the mesh where the solver expects it. Copy the partitioned
.mshfile into the solver directory you plan to run and update the filename passed toExtractGmshPart_puff. Each solver currently references eithersquarepart4.msh,square2_part4.msh, ormymeshpart4.msh. - Launch MATLAB and run the solver script. For example:
Every script starts with
cd('DDM-TwoLevel'); PoissonSolver_DDM_TwoLevel;
delete *.matto remove staleA_i.mat/b_i.matfiles, extracts the mesh, assembles local matrices, and executes the solver. Progress is echoed in the Command Window (number of PCGM iterations, residual norms, and the maximum error). - Inspect the results. The scripts call
pdesurfthree times (solution, exact solution, error) and, for iterative solvers, plot residual vs iteration (e.g.,Lump.mat,NN_m.mat,2Level.matstore residual histories).
- Main entry point:
PoissonSolver_Direct.m. - What it does: Forms the Schur complement of each subdomain, assembles the global interface system with
GetRestrictionMatrix, and solves it directly. It then reconstructs interior unknowns by back substitution and compares the field to the manufactured solution. - Key helpers:
ExtractGmshPart_puff.m,AssembleMatrix.m,AssembleVector.m,GetInterfaceNodes*.m. - Sample meshes:
source/square2_part4.msh,source/square_part8_remote.msh,mac/square2_part8.msh.
- Main entry point:
PoissonSolver_PCGM_NN.m. - Algorithm: Preconditioned conjugate gradients on the interface unknowns using a Neumann-Neumann preconditioner assembled in
GetPreconditionedNeumann.m. Interface operators are applied through repeated local solves inGetMatrixVectorProduct.m. Scaling matricesDenforce a partition-of-unity on shared nodes. - Outputs: Stores residual histories in
NN_m.mat.
- Main entry point:
PoissonSolver_PCGM_Lumped.m. - Algorithm: Identical PCGM loop but the preconditioner uses the diagonal (lumped) interface stiffness scaled by
DthroughGetPreconditionedZLumped.m. - Outputs: Residual curves saved in
Lump.mat.
- Main entry point:
PoissonSolver_DDM_TwoLevel.m. - Algorithm: Builds a coarse problem on interface corner nodes (
node_corner) and remaining interface nodes (node_remaining).GetCoarseGrid.m,GetRestrictionMatrix.m, andGetMatrixVectorProductTwoLevel.massemble the coarse operators, whileGetPreconditionedTwolevelNeumann.madds the coarse-space correction. The inner coarse solves reuseDoPCGMLumpedTwoLevel.m. - Meshes: Includes
square.msh,squarepart{2,4,...,80}.msh,mymesh.msh, andmymeshpart*.mshtest cases. - Outputs: Residual curves saved in
2Level.matand intermediate data for sparsity studies inIterVsNS/.
- Main entry point:
PoissonSolver_FETI_DP.m. - Algorithm: Implements a dual-primal FETI method. Coarse primal unknowns live on corner/edge nodes via
Bc, while continuity on the remaining interface is enforced by the jump operatorBrand scalingDr. Lagrange multipliers (lambda) are iteratively updated with PCGM, usingGetMatrixVectorProductFETIDP.mfor the action of the dual Schur complement andGetPreconditioner_FETIDP.mfor diagonal scaling.GetResidue_FETIDP.m,GetGlobalCornerNode.m, andGetGlobalRemainingNode.mreconstruct primal solutions once the dual problem converges. - Outputs: Saves residual curves in
2Level.mat(shared naming) and prints the maximum error.
All solvers invoke ExtractGmshPart_puff.m, which parses a partitioned .msh file and returns:
p_f,e_f,t_f: point, edge, and triangle tables per partition ready forAssembleMatrixandAssembleVector.GLnode: mapping from renamed local node indices back to the global numbering.npart: number of partitions in the mesh.point_exact,triangle_exact: domain-wide coordinates for plotting withpdesurf.node_gamma,node_interior: renamed interface and interior nodes per partition.node_interfacewhole,node_remainingwhole: full lists (with original numbering) used to scatter interface solutions back toU.R: restriction matrices that inject interface unknowns into the subdomain order.D: partition-of-unity scaling derived byGetScalingMatrix.m.node_corner,node_remaining,node_c,node_r: coarse-grid nodes (original and renamed).Rc,Rr,Bc: restriction operators for corner-only, remaining-interface-only, and global corner nodes respectively.node_*_OG: convenience copies that retain original Gmsh numbering for debugging and plotting.
FETI-DP additionally needs Br (jump operator built by GetJumpOperator.m or GetInterfaceNodes_puff.m), Rrr (restriction from global interface to remaining nodes), and Dr (interface scaling for the dual problem). These are exposed by the extended signature of ExtractGmshPart_puff.m inside FETI-DP/.
The ExtractGmsh folder contains alternative parsers (ExtractGmsh.m, ExtractGmsh_part.m, ExtractGmsh_PartInterface.m) that dump mesh subsets to text files (points.txt, edges.txt, etc.) to help debug new meshes or partition assignments.
AssembleMatrix.mandAssembleVector.massemble the finite-element stiffness matrix and load vector for Poisson's equation by quadrature over each triangle and boundary edge (sourced from Hoffman & Logg, GPLv2).Poisson.mspecifies the bilinear and linear forms, boundary conditions, and the manufactured forcingf(x,y) = 5*pi^2*sin(pi*x)*sin(2*pi*y). Modifyf,gd, orgnto solve a different problem.GetMatrixVectorProduct*.mfiles evaluate Schur complement actions by solving interior blocks and combining with interface data.GetPreconditioned*.mfiles assemble Neumann, lumped, two-level, and FETI-DP preconditioners by inverting (or partially inverting) local Schur complements.DoPCGMLumped*.mimplement the PCGM loop used both as an outer solver (Neumann/Lumped) and as an inner coarse-grid solver (TwoLevel/FETI).AssembleForSparse.m(inDDM-TwoLevel/andsparsity/) is a diagnostic utility that reconstructs the global stiffness pattern for plotting sparsity.
Understanding these helpers is useful when adapting the code to a different PDE or when adding diagnostics such as energy norms, iteration logs, or stopping criteria.
The puffin-0.1.6 directory contains the source, scripts, and documentation for Puffin (a light-weight partitioner originally bundled with the FEniCS project). Typical usage:
- Build Puffin following the instructions in
puffin-0.1.6/README. - Run Puffin on a
.mshfile to producesquarepart4.msh,squarepart10.msh, etc. The resulting mesh has extended tags describing how many partitions share each element and lists the adjacent part IDs. Those tags are whatExtractGmshPart_puff.mconsumes. - Copy the new
.mshfile into the solver directory and pointExtractGmshPart_puffto it.
You can keep the zipped archive (puffin-0.1.6.zip) for reproducibility.
A_i.mat/b_i.mat- Local stiffness and load matrices per subdomain written during every solver run. They are re-used insideGetMatrixVectorProduct*and the PCGM loops. The scripts delete them on startup to avoid mixing meshes.Lump.mat,NN_m.mat,2Level.mat- Residual histories (iter,nres) saved by the respective solvers. These files drive the "residual vs iteration" plots.IterVsNS/- Placeholder directories used to store parametric studies (iterations vs number of subdomains). Drop your experiment logs here to keep the solver folders tidy.
- Change the PDE or forcing term: edit
Poisson.m(inside the solver you are running) and updatef,gd,gn, or the penaltyg. Keep the function signature unchanged because it is called byAssembleMatrix/AssembleVector. - Use a different mesh: point
ExtractGmshPart_puffto your.mshfile. The parser assumes linear triangles and that Gmsh stores elements in the standard order (edges before triangles). Verify that the partition tags are present; otherwisenode_gammawill be empty. - Vary tolerances: the Neumann and Lumped solvers stop when
norm(r_new)/norm(r_0)drops below1e-5. The two-level and FETI solvers accept atolcor use1e-6by default - modify the value defined near the top of those scripts. - Reuse assemblies: comment out
delete *.matif you want to inspectA_i.mat/b_i.matacross runs, but be mindful that changing the mesh without deleting the files will corrupt subsequent runs. - Plot sparsity: run
AssembleForSparse.m(fromsparsity/) after buildingA_i.matto capture the global stiffness pattern for debugging or publications. - Batch execution: launch MATLAB with
-nodesktop/-nodisplayand runPoissonSolver_*; exitto execute solvers from a shell script. This is how parameter sweeps inIterVsNSwere produced.
manpathwarnings on macOS are benign and originate from the shell environment when running MATLAB from the terminal.- If
ExtractGmshPart_puffreports missing interface nodes, double-check that the mesh contains partition IDs for every element and that interior nodes were not duplicated when editing the.msh. - Singular local Schur complements typically indicate a disconnected partition or a mesh with hanging nodes. Regenerate the partition or slightly perturb the geometry.
- The plots require MATLAB's PDE Toolbox. If
pdesurfis unavailable, replace the plotting section withtrisurforpatch.
- The finite element assembly routines (
AssembleMatrix.m,AssembleVector.m,Poisson.m) and the Puffin partitioner are copyrighted by Johan Hoffman and Anders Logg and distributed under the GNU GPL v2. This repository preserves that license. - The domain decomposition scripts, mesh utilities, and experiments were authored by Sudhi Sharma P V for research and teaching purposes. Cite accordingly if you use the code in publications.
Please reach out via the repository issue tracker with questions or improvements.