Section 9.3 of Chapter 9: 2D Stress Analysis: Finite Element Types, Linear Case

CST: Fast MATLAB Solver — Alternative Version

An alternative high-speed CST solver that uses block-diagonal sparse matrices and standard MATLAB sparse multiplication, without the external multiprod function.

CST elementBlock-diagonal matricesSparse assemblyMATLAB R2026a

01

Purpose and strategy

triang2d_fast2 is an alternative high-speed implementation of the CST solver presented in Section 9.1. It is intended for users who wish to avoid the external multiprod function employed by Section 9.2.

Section 9.2 stores the element matrices in three-dimensional arrays and performs the batched products with multiprod. The present routine instead places every element matrix in a large two-dimensional block-diagonal sparse matrix. Standard sparse matrix multiplication then evaluates the products corresponding to BTDB\boldsymbol{B}^{T}\boldsymbol{D}\boldsymbol{B} for all elements.

02

Block-diagonal sparse matrices

For a mesh containing neln_{el} constant-strain triangles, the matrices have dimensions

B:(3nel)×(6nel)D:(3nel)×(3nel) \boldsymbol{B}:\quad(3n_{el})\times(6n_{el}) \qquad \boldsymbol{D}:\quad(3n_{el})\times(3n_{el})

Each element strain-displacement matrix Bel\boldsymbol{B}_{el} has dimensions 3×63\times6, while each plane-stress constitutive block Del\boldsymbol{D}_{el} has dimensions 3×33\times3. These blocks are placed on the diagonals of the large sparse matrices:

B=diag ⁣(B1,B2,,Bnel)D=diag ⁣(D1,D2,,Dnel) \boldsymbol{B}=\operatorname{diag}\!\left(\boldsymbol{B}_1,\boldsymbol{B}_2,\ldots,\boldsymbol{B}_{n_{el}}\right) \qquad \boldsymbol{D}=\operatorname{diag}\!\left(\boldsymbol{D}_1,\boldsymbol{D}_2,\ldots,\boldsymbol{D}_{n_{el}}\right)
Author-supplied sparsity patterns of the block-diagonal D and B matrices
Figure 1. Block-diagonal sparse structure of the constitutive matrix D\boldsymbol{D} and strain-displacement matrix B\boldsymbol{B}.

03

Sparse multiplication and assembly

The matrices B\boldsymbol{B} and D\boldsymbol{D} are assembled as large sparse block-diagonal matrices. Their standard matrix product provides the element stiffness contributions, while MATLAB sparse is then used for the global assembly.

triang2d_fast2.mBlock products
DB=DHooke*B;
kelt=B'*DB;

DB contains the products DelBel\boldsymbol{D}_{el}\boldsymbol{B}_{el} in block-diagonal form, and kelt contains the corresponding 6×66\times6 element stiffness matrices. The index vector ij extracts their 36 entries per element, while ipos1 and ipos2 identify the associated global equation positions:

triang2d_fast2.mGlobal sparse assembly
ij=(ip1(:)-1)*ngel*nel+ip2(:);
K=sparse(ipos1(:),ipos2(:),kelt(ij),neq,neq);

neq is the number of global equations. After the loads and constraints are imposed, K is the global stiffness matrix, F is the global load vector, and the MATLAB displacement variable S is obtained from

triang2d_fast2.mLinear system
S=K\F;

After the solution, the block-sparse product is converted to the element-wise array DBtR3×6×nel\boldsymbol{DBt}\in\mathbb{R}^{3\times6\times n_{el}} required by the standard stress-postprocessing routine:

triang2d_fast2.mStress-postprocessing compatibility
% Convert DB for use with standard plot_stress postprocessing
ii=reshape(1:3*nel,3,1,nel)+(reshape(1:6*nel,1,6,nel)-1)*3*nel;
DBt=reshape(full(DB(ii(:))),3,6,nel);
DBt = DBt./reshape(Ath,1,1,[]);

04

Use with Section 9.1

Start from the MATLAB programs provided in Section 9.1, add triang2d_fast2.m, and replace the call triang2d in main.m with triang2d_fast2. The alternative package therefore contains only the new routine and its README.

For compatibility with the standard stress-postprocessing routine, the vectorized solver also provides DBt in element-wise form. Thus, the same plot_stress routine can be used independently of the internal assembly strategy.

05

MATLAB R2026a benchmark

Benchmark computer

Intel Core i7-14700 @ 2.10 GHz, 32 GB RAM, Windows 11, MATLAB R2026a.

The two representative meshes are identical to those used in the current Section 9.2 benchmark. The Section 9.3 values are arithmetic means of three measured runs after one unrecorded warm-up run. Total time includes matrix construction, loads, constraints, and the solution K\F\boldsymbol{K}\backslash\boldsymbol{F}; assembly and linear-solve intervals were also measured directly.

Rectangular cantilever benchmark mesh with nH subdivisions through the height and nL along the length
Figure 2. Cantilever geometry and mesh notation used for the benchmark.
nH×nLn_H\times n_LCST elementsEquations9.2total (s)9.3total (s)9.2assembly (s)9.3assembly (s)9.3 K\F(s)
80 × 20032,00032,5620.2200.1600.0830.0930.061
100 × 25050,00050,7020.2920.3050.1000.1690.093

The block-sparse alternative remains extremely fast, but its element-generation and assembly stage is slower than the multiprod implementation: approximately 1.13 times for the 80×20080\times200 mesh and 1.69 times for the 100×250100\times250 mesh. Total times are also influenced by run-to-run variation in the common sparse linear-system solution, so the directly measured assembly interval gives the clearest comparison of the two strategies.

For the larger mesh with nH=500n_H=500 and nL=1250n_L=1250, corresponding to 1,253,502 global equations, the supplied triang2d_fast2 result is 4.924 s for element-matrix generation and assembly. The corresponding Section 9.2 value is 2.553 s. The alternative solver therefore remains very fast, while the multiprod formulation is faster at this stage.

06

Numerical equivalence

The global displacement vector and element stress field from triang2d_fast2 were compared with the Section 9.2 solver for both measured meshes.

nH×nLn_H\times n_LMaximum displacement
difference
Relative displacement
difference
Maximum stress
difference
Relative stress
difference
80 × 2000000
100 × 2500000

No numerical difference was recorded in the double-precision comparisons of nodal displacements, displacement extrema, or CST stress components.

07

Program download

Verification status

triang2d_fast2 was executed in MATLAB R2026a on both published benchmark meshes. The routine requires the complete Section 9.1 package but has no external multiprod dependency.