In a first-order (P1) triangle the vector potential is linear, so B — its gradient — is constant over the element. Every quantity an engineer actually cares about in a motor model is computed from B: air-gap flux density, torque, iron loss, back-EMF. A piecewise-constant B across a four-element-thick air gap is the quiet reason a torque number wobbles when you remesh.

The trade, stated honestly

A P2 triangle carries six nodes instead of three — the three corners plus one on the middle of each edge. A is quadratic, B is linear within the element, and the local stiffness block is 6×6 rather than 3×3. You pay roughly four times the unknowns per element and a denser matrix row. The question is whether you get more than four times the accuracy back, because if you do not, you should simply have refined the mesh instead.

The measurement that answers it

A 3-pole-pair, 18-slot PMSM in a nonlinear transient run with an anti-periodic sector, an arc sliding band and three coils. Four runs: coarse P1, coarse P2 (the same 6330-element mesh), and 4×-refined versions of both. Sampled on a 241-point circle in the air gap and in the iron, against the refined P2 reference:

Runrel L2 in Arel L2 in |B|, air gap
coarse P11.4e-3 … 2.6e-35.5e-3
4×-refined P10.9e-3 … 1.5e-35.2e-3
coarse P25e-5 … 2.5e-47e-5 … 6e-4

Coarse P2 is an order of magnitude closer to the converged answer than P1 on a mesh four times finer — and all four runs converged in the same number of Newton iterations. Notice also how little the refined P1 row moved: in the air gap, quadrupling the P1 mesh bought 5 %. That is the signature of an error that is not going to be refined away at any mesh size you would tolerate.

The same shape shows up in a clean analytic case — a round conductor in air with a circular Dirichlet boundary. L2(|B|) under refinement: P1 gives 1.38e-2 → 7.7e-3 → 3.6e-3; P2 gives 1.66e-3 → 6.6e-4 → 4.9e-4. P2 on the coarsest mesh beats P1 on the finest.

And on a quadratic patch test — a rectangle with Dirichlet and Neumann boundaries and a source whose exact solution is A = x² — P2 reproduces the exact answer to 1.9e-14 relative in A and 1.2e-15 in B, on every mesh, while P1 shows the expected O(h²) error. That is not an accuracy result so much as a correctness one: it is the test that catches a wrong shape-function gradient or a mis-numbered midside node.

Three details that decide whether you get the accuracy

Midside numbering, and gradients that are actually gradients

Which edge each midside node belongs to is a convention, and the two plausible conventions differ by a rotation. Get it wrong and the model still solves — it simply solves something else. A related failure mode is worse: an implementation that fakes the quadratic gradients by averaging corner values produces a 6×6 element matrix of rank 3, which is to say a P1 element wearing six nodes. Both are invisible without a patch test, which is why the A = x² case above matters more than it looks.

Material state is per quadrature point, not per element

A P1 element has one B, so it has one permeability. A P2 element has a B that varies across it, so the saturating material model has to be evaluated at each quadrature point. The subtle failure here is in the non-saturating path: if K is assembled once up front, with no Newton loop to trigger a field recovery first, every quadrature point still carries its default μ = 1 — and the stator and rotor cores behave as air. In our own case that collapsed peak |B| in a PMSM from 2.5 T to 0.99 T (the magnets alone). Saturating runs never showed it, because their Newton loop recovers the field before each re-assembly. A bug that only appears when you turn the nonlinearity off is exactly the kind a validation suite has to be built to catch.

Interfaces and post-processing have to be quadratic too

A P2 boundary ring alternates corner and midside nodes. Tying a periodic-boundary slave node linearly between two adjacent ring entries caps an otherwise third-order sector model at second order — all the cost of P2, some of the benefit. The same applies to a sliding band, which ties node values across a rotating interface: the moving ring has to be interpolated against the full quadratic master edge.

Post-processing is the one people forget. Integrating over the three corners only — the natural thing to do, since that is what P1 needs — injects an O(h²·∂²A) quadrature error, the same order as the P1 interpolation error, on top of a field accurate to about 1e-4. The quadrature then becomes the dominant error term and silently erases the accuracy you paid for. For a straight-sided quadratic triangle the corner shape functions integrate to zero and each midside function to S/3, so the correct element mean is (A₃+A₄+A₅)/3 over the midside values — the corners do not appear at all.

What P2 supports in Nabla

Planar and axisymmetric; static, transient and time-harmonic; linear and saturating; with eddy currents, with backward-Euler or Crank–Nicolson time integration, with circuit coupling (staggered and monolithic), with Dirichlet, Neumann and far-field boundaries, with periodic and anti-periodic interfaces, with rotary and linear motion through the averaging sliding band, and through the thermal module.

Two configurations are rejected at P2 rather than quietly degraded: skewed models with more than one slice, and motion without the averaging sliding band. The solver exits non-zero and says what is unsupported and how to get back to a working configuration. Nothing silently falls back to first order — a solver that downgrades the discretisation without telling you is worse than one that refuses.

And P1 results did not move: a nonlinear transient PMSM with motion, sliding band and circuit, and a 252-step induction machine with eddy currents and anti-periodic boundaries, both produce bit-identical solution files before and after the whole P2 feature. That is the regression standard worth holding a solver to.

The cheapest experiment. Take a model you already trust, switch the element order, and compare the torque ripple. If it moves, the P1 answer was telling you about your mesh, not your machine.

Download Nabla Feature matrix

Second-order elements are part of Nabla Core. Related: second-order time integration, far-field boundaries, and the validation dossier.