MRF vs sliding mesh for a marine propeller in OpenFOAM: NCC and AMI against the PPTC towing-tank data

Published by Ruggero Poletto on

PPTC VP1304 open-water diagram: MRF, NCC and AMI against the SVA Potsdam experiment

TL;DR

  • We ran the Potsdam Propeller Test Case (PPTC, VP1304) in open water with three ways of handling rotation: MRF (steady, OpenFOAM-14), NCC non-conformal sliding mesh (OpenFOAM-14) and AMI sliding mesh (OpenFOAM v2606), all on the same 4.41 M-cell mesh, k-ฯ‰ SST, 48 cores.
  • At the design-like point J = 1.0 the thrust error versus the SVA experiment is โˆ’9.0 % (MRF), โˆ’6.9 % (NCC), โˆ’7.2 % (AMI); torque โˆ’4.5 %, โˆ’1.9 %, โˆ’2.2 %.
  • NCC and AMI agree within 0.5 % on both thrust and torque at every advance ratio: two codes, two interface algorithms, one answer.
  • All three methods drift together at high J (thrust โ‰ˆ โˆ’24 % at J = 1.4): the gap is in the mesh/turbulence modelling, not in how the rotation is handled.
  • One operating point costs โ‚ฌ0.91 with MRF and โ‚ฌ8.4โ€“10.6 with a 4-revolution sliding-mesh run on a 48-vCPU spot instance. Overset was tried and dropped; the reasons are below.
Animation of the PPTC propeller open-water results with MRF, NCC and AMI in OpenFOAM

Why this comparison

Every rotating-machinery CFD job starts with the same choice: freeze the rotor in a multiple reference frame (MRF) and run steady, or actually move the mesh and pay for a transient run. OpenFOAM now offers two mature sliding-mesh interfaces that live in the two OpenFOAM distributions:

  • Non-conformal coupling (NCC) in openfoam.org (released in 2022 with OpenFOAM-10 as the replacement for AMI, which was removed from that line afterwards; here OpenFOAM-14);
  • Arbitrary Mesh Interface (AMI) in openfoam.com (here OpenFOAM v2606, June 2026).

We wanted three answers for cloudHPC users: how far MRF is from a sliding mesh on a real propeller, whether NCC and AMI give the same answer when fed the same mesh, and what each costs per operating point. A propeller in open water is the cleanest test bed: one rotor, axisymmetric inflow, and a public experimental data set.

Results at a glance

JQuantityExperimentMRF (of14)NCC (of14)AMI (v2606)
0.6KT0.62880.6060 (โˆ’3.6 %)0.6218 (โˆ’1.1 %)0.6209 (โˆ’1.3 %)
10KQ1.39641.3804 (โˆ’1.1 %)1.4304 (+2.4 %)1.4279 (+2.3 %)
ฮท00.4300.419 (โˆ’2.5 %)0.415 (โˆ’3.5 %)0.415 (โˆ’3.4 %)
1.0KT0.39940.3635 (โˆ’9.0 %)0.3719 (โˆ’6.9 %)0.3706 (โˆ’7.2 %)
10KQ0.97490.9313 (โˆ’4.5 %)0.9568 (โˆ’1.9 %)0.9530 (โˆ’2.2 %)
ฮท00.6520.621 (โˆ’4.7 %)0.619 (โˆ’5.1 %)0.619 (โˆ’5.1 %)
1.4KT0.18780.1433 (โˆ’23.7 %)0.1415 (โˆ’24.7 %)0.1409 (โˆ’25.0 %)
10KQ0.55880.4958 (โˆ’11.3 %)0.4937 (โˆ’11.7 %)0.4916 (โˆ’12.0 %)
ฮท00.7490.644 (โˆ’14.0 %)0.639 (โˆ’14.7 %)0.639 (โˆ’14.7 %)

Blades-only forces, n = 15 1/s. MRF: mean of the last 100 of 500 iterations per J. NCC and AMI: mean over the 4th revolution (360 time steps). MRF was also run at J = 0.8 and 1.2 (KT 0.4846 / 0.2510, โˆ’5.0 % / โˆ’14.9 %).

PPTC VP1304 open-water diagram: MRF, NCC and AMI against the SVA Potsdam experiment

The test case: PPTC VP1304

Side-view sketch of the PPTC VP1304 open-water set-up: domain, rotating zone, shaft, hub cap and inflow direction
Case set-up (half section). Inflow from the hub-cap side towards the dynamometer shaft (pull configuration).

The Potsdam Propeller Test Case is the controllable-pitch propeller VP1304 of SVA Potsdam, released with geometry and towing-tank data for the smp’11 Propeller Workshop (Second International Symposium on Marine Propulsors, Hamburg, 2011).

ItemValue
PropellerVP1304, D = 0.25 m, Z = 5 blades, P0.7/D = 1.635, right-handed
Rotationn = 15 1/s (ฯ‰ = 94.25 rad/s about +x)
Fluid (smp’11 prescription)ฯ = 998.67 kg/mยณ, ฮฝ = 1.070 ร— 10โปโถ mยฒ/s
Advance ratiosJ = VA/(nD) = 0.6, 1.0, 1.4 (MRF also 0.8 and 1.2)
ReferenceSVA open-water test, n = 15 1/s, blades only (corrected for hub resistance and idle torque); smp’11 Case 2.1 polynomials
GeometrySVA STEP file with closed hub fillets, tessellated with OpenCASCADE into blades / hub / cap / shaft regions; shaft extended to the outlet
Domainbox 9D long (3D upstream, 6D downstream) ร— 6D ร— 6D, slip side walls, fixed velocity inlet, fixed pressure outlet
Rotating zonecylinder r = 0.15 m (0.6D), x = โˆ’0.0265โ€ฆ0.15 m, interface inside the 3 mm gap between hub and shaft fairing

Forces are integrated on the blades only, as in the reference data: KT = T/(ฯnยฒDโด), KQ = Q/(ฯnยฒDโต), ฮท0 = J KT/(2ฯ€ KQ).

How the runs were set up

MRFNCCAMI
Distribution / versionOpenFOAM-14 (openfoam.org)OpenFOAM-14 (openfoam.org)OpenFOAM v2606 (openfoam.com)
SolverfoamRun, incompressibleFluid, steady SIMPLE, MRFPropertiesfoamRun, incompressibleFluid, PIMPLE, solidBody rotationpimpleFoam, dynamicMotionSolverFvMesh, solidBody rotation
Interfacenone (rotor cellZone)createBaffles โ†’ splitBaffles โ†’ createNonConformalCouples (89,666 couplings over 43,961 + 43,961 faces)createBaffles โ†’ cyclicAMI pair, 43,961 + 43,961 faces, lowWeightCorrection 0.2
Meshthe same snappyHexMesh (OpenFOAM-14) grid: 4,408,036 cells, base cell 0.06 m, blades level 7 (โ‰ˆ0.47 mm), 4 prism layers on blades/hub/cap, rotor zone level 4
Time / iterations500 iterations per J (one job: inlet velocity stepped every 500 iterations; inlet k and ฯ‰ kept at the J = 1.0 values)ฮ”t = 1ยฐ of rotation (1.852 ร— 10โปโด s), 4 revolutions = 1,440 steps, 2 outer ร— 2 pressure correctors
Startuniform flowimpulsive startrotation speed ramped 0 โ†’ 15 1/s over 0.25 rev; correctPhi on
Common: k-ฯ‰ SST, Spalding wall function (blade y+ โ‰ˆ 27 on average), inlet turbulence 1 %, ฮฝt/ฮฝ = 1, linearUpwind for U, upwind for k and ฯ‰, GAMG for pressure.
InstancecloudHPC hypercore, 48 vCPU = 48 physical cores (AMD EPYC 9B45), spot pricing, one MPI rank per core

Using one mesh for all three methods was deliberate (and, as told below, also the fix for the AMI runs): the differences in the table above come from the rotation model and the code, not from meshing.

Case 1 โ€” MRF: cheap, and 9 % short on thrust at J = 1.0

A full MRF open-water curve (five advance ratios, 2,500 iterations in one job) took 41 minutes of solver time at 0.99 s per iteration and cost โ‚ฌ4.56 including meshing, boot and upload. Each window had settled: KT changed by at most 0.0005 (0.1 %) between the last two blocks of 100 iterations.

The accuracy is good at high load (J = 0.6: thrust โˆ’3.6 %, torque โˆ’1.1 %) and degrades as the load drops (J = 1.4: โˆ’23.7 % / โˆ’11.3 %). Before blaming MRF we tried to close the gap at J = 1.0:

Variant (J = 1.0, MRF unless noted)CellsKTerr KT10KQerr 10KQblade y+ (avg)
Medium grid, 1,500 iterations4,408,0360.3635โˆ’9.0 %0.9313โˆ’4.5 %27
Fine grid (base 0.048 m), 800 iterations7,143,7960.3630โˆ’9.1 %0.9290โˆ’4.7 %22
Medium + distance refinement around the blades6,242,1850.3640โˆ’8.9 %0.9327โˆ’4.3 %27
12 prism layers, first cell 5 ยตm, k-ฯ‰ SST4,591,3360.3661โˆ’8.3 %0.9289โˆ’4.7 %14
12 prism layers, k-ฯ‰ SST-LM (transition)4,591,3360.3745โˆ’6.2 %0.9313โˆ’4.5 %13
NCC sliding mesh, medium grid, 4 rev4,408,0360.3719โˆ’6.9 %0.9568โˆ’1.9 %โ€”
AMI sliding mesh, medium grid, 4 rev4,408,0360.3706โˆ’7.2 %0.9530โˆ’2.2 %โ€”
Thrust error at J = 1.0 for each MRF variant, NCC and AMI

What we learned. Iterating longer, a finer grid and refinement around the blades move MRF thrust by 0.13 points at most: the result is grid-independent for this wall-function set-up. A 12-layer near-wall grid moves it 0.7 points. Two things move it more: a transition model (SST-LM on the 12-layer grid, a further +2.1 points, โˆ’6.2 % in total) and moving the mesh (+2.1 points with NCC, +1.8 with AMI on the original grid), and at J = 1.0 the sliding mesh also halves the torque error. Note that the 12-layer grid aimed at y+ โ‰ˆ 1 reached an average of only 13โ€“14 because snappyHexMesh did not grow all the layers: a proper low-Re grid remains an open item.

Case 2 โ€” NCC sliding mesh (OpenFOAM-14)

The openfoam.org route is: snappyHexMesh with the rotor cylinder as an internal faceZone, createBaffles and splitBaffles to open it, renumberMesh, then createNonConformalCouples nonCouple1 nonCouple2, which built 89,666 couplings between the two 43,961-face sides in about a second. The rotor moves with a solidBody / rotatingMotion mover.

JKT10KQฮท0err KT / 10KQ / ฮทSolver time (1,440 steps)s per stepBilled cost
0.60.62181.43040.4151โˆ’1.1 / +2.4 / โˆ’3.5 %5,970 s4.15โ‚ฌ9.73
1.00.37190.95680.6186โˆ’6.9 / โˆ’1.9 / โˆ’5.1 %6,211 s4.31โ‚ฌ10.09
1.40.14150.49370.6386โˆ’24.7 / โˆ’11.7 / โˆ’14.7 %6,386 s4.43โ‚ฌ10.59

With an impulsive start the thrust overshoots and settles within one to two revolutions; the mean KT of the last two half-revolutions differs by less than 0.0003 at every J. In the 2-revolution sizing run (โ‚ฌ5.52) the last two half-revolutions still differed by 0.0009, which is why the production runs used four (the 2nd-revolution mean was in the end only 0.15 % above the 4th-revolution value).

Thrust history over four revolutions for NCC and AMI at J = 0.6, 1.0 and 1.4

Case 3 โ€” AMI sliding mesh (OpenFOAM v2606): the same answer, after three false starts

The final AMI runs used the OpenFOAM-14 mesh read into v2606, createBaffles to make a matching cyclicAMI pair (weights 0.99โ€“1.11 at start; as the rotor turns, faces next to the shaftโ€“fairing gap become partly uncovered, weights range 0โ€“1.93, and lowWeightCorrection 0.2 handles them), correctPhi yes, and a 0.25-revolution ramp of the rotation speed.

JKT10KQฮท0err KT / 10KQ / ฮทSolver time (1,440 steps)s per stepBilled cost
0.60.62091.42790.4152โˆ’1.3 / +2.3 / โˆ’3.4 %5,235 s3.64โ‚ฌ8.38
1.00.37060.95300.6189โˆ’7.2 / โˆ’2.2 / โˆ’5.1 %5,590 s3.88โ‚ฌ8.91
1.40.14090.49160.6385โˆ’25.0 / โˆ’12.0 / โˆ’14.7 %5,590 s3.88โ‚ฌ8.87

AMI and NCC differ by at most 0.45 % in KT and 10KQ (0.4 points or less on the error versus experiment). AMI was 10โ€“13 % faster per time step here, with the caveat that the two runs use different solver applications and builds.

Getting there took four mesh/numerics set-ups, all visible in the cloudHPC logs:

  1. snappyHexMesh faceType boundary + createPatch (the shortcut): the two sides of the interface came out different (38,470 vs 36,199 faces) because snappy merges refined boundary faces on one side only. AMI weights ranged from 0 to 2.7 and the run blew up (max Courant 35 โ†’ 4,445 โ†’ 10ยนโฐโต, floating-point exception in GAMG after 74โ€“78 time steps). Cost โ‚ฌ3.51 and โ‚ฌ4.34; the J = 0.6 run did not diverge but was discarded (โ‚ฌ8.07).
  2. Internal faceZone + createBaffles (as in the ESI propeller tutorial): matching sides (44,159 faces each, weights 1.0โ€“1.1), but with correctPhi no and an impulsive start it diverged at step 3.
  3. correctPhi yes + 0.25-revolution ramp on the v2606 snappyHexMesh grid: diverged at step 19 with the rotor still almost at rest. The Courant number jumped to 154 at step 2, which points at a few poor cells in that grid (31 faces above 70ยฐ non-orthogonality, 6 highly skewed faces), not at AMI.
  4. The OpenFOAM-14 grid in v2606: stable from the first step (J = 1.0: max Courant 28 at start, 71 after the first step, 23โ€“59 during the ramp and 43โ€“50 at full speed; up to 98 after the first step at J = 1.4). Two practical notes: rotatingMotion integrates ฯ‰(t), and v2606 refuses to integrate a table beyond its last point, so the ramp table needs a final point far in the future; and cloudHPC unpacks any archive in an uploaded case, so a mesh shipped as .tar.gz inside the case must be renamed (we used .bin) and unpacked by the Allrun.

What didn’t work: overset (OpenFOAM v2606)

The plan included overset (overPimpleDyMFoam) as a third moving-mesh option. We dropped it, and the reasons are worth sharing.

#Configuration (coarse grid, ~1 M cells, one to five steps)Background cells outside the componentOutcome
3Overset interface at x = โˆ’0.0265 m (same as MRF/NCC), inverseDistance, search box around the rotor~145 k of 162 k flagged as holeruns, but the outer flow is not computed
4as 3, search box = whole domain142 k holesearch box not the cause
5as 4, component walls made watertight143.8 k hole, FPE at step 4closed walls not the cause
6โ€“7interface moved to x = โˆ’0.20 m, fairing front inside the component (static, U = 0)0 calculated, 0.4 k interpolated, 121.3 k holehole filling inverted
8bas 7, trackingInverseDistance0 calculated, 121.1 k holesame inversion
8cas 7, inverseDistance + holeLayers 4; useLayer 20 calculated, 121.2 k holesame inversion
8aas 7, cellVolumeWeight121,459 calculated, 0 holecorrect cell types
Background cell types with inverseDistance: the whole outer field is flagged as hole
inverseDistance: the background is solved only where the component overlaps it (orange = hole).
Background cell types with cellVolumeWeight: correct hole map, holes only inside the propeller body
cellVolumeWeight: correct hole map.

On this geometry, where the shaft and fairing walls cross the overset boundary, the three voxel-based hole-cutting methods invert the fill. The geometric-overlap method cellVolumeWeight gets it right, but on the medium grid (4.97 M cells, 48 cores) it cost 155 s per time step, about โ‚ฌ80 per revolution at 1ยฐ per step, and the run was unstable from the first step (max Courant 61 โ†’ 6.5 ร— 10ยนโท, floating-point exception at step 9). Total spent on the overset trials: โ‰ˆ โ‚ฌ4.8. An overset propeller remains possible with the shaft entirely in the background mesh and a larger time step; that is a separate study.

Run times and costs

BlockWhatBilled cost
MRFopen-water curve, 5 J, one jobโ‚ฌ4.56
MRFsizing + 5 diagnostic variants at J = 1.0โ‚ฌ20.92
NCC3 production runs (4 rev) + 2-rev sizingโ‚ฌ35.93
AMI3 production runs (4 rev)โ‚ฌ26.16
AMIfailed attempts, of14 mesh export, testโ‚ฌ22.35
Oversettutorial copy, 10 smoke tests, medium runโ‚ฌ4.76
Othergeometry download jobโ‚ฌ0.05
Whole campaignโ‚ฌ114.72
Billed cost per operating point and wall time per time step

Per operating point the picture is simple: MRF โ‰ˆ โ‚ฌ0.91 (one-fifth of the polar job), NCC โ‰ˆ โ‚ฌ10.1, AMI โ‰ˆ โ‚ฌ8.7 on a 48-vCPU hypercore spot instance (about โ‚ฌ5.3 per hour for the whole machine). Billed cost includes boot, meshing (3โ€“4 min), end-of-run detection and result upload.

Right tool for the job: use MRF to sweep an open-water curve or to screen designs: it is ten times cheaper, and at heavy load (J = 0.6) it is within 3.6 % on thrust and 1.1 % on torque. Use a sliding mesh (NCC or AMI, whichever distribution you already use) near the design point, where it cut the J = 1.0 errors from 9.0 % to 6.9 % on thrust and from 4.5 % to 1.9 % on torque, and whenever you need unsteady blade loads or rotorโ€“stator interaction. Neither fixes the high-J thrust deficit on this grid: that needs a finer near-wall resolution or a transition model.

How to run this on cloudHPC

  • Solver entries: openFoam-of14 (MRF, NCC) and openFoam-v2606 (AMI). With an Allrun script in the case root cloudHPC runs it instead of the standard sequence; numberOfSubdomains is set to the physical cores.
  • Instances: OpenFOAM needs hypercore or highcore (one MPI rank per physical core). Spot instances are fine: with startFrom latestTime a preempted run restarts from the last write.
  • OpenFOAM-14 specifics: controlDict needs application foamRun; solver incompressibleFluid;; mesh utilities overwrite by default; after a parallel snappyHexMesh decompose fields with decomposePar -fields -copyZero.
  • NCC sequence: createBaffles, splitBaffles, renumberMesh, createNonConformalCouples nonCouple1 nonCouple2, in parallel.
  • AMI: keep the rotor faceZone internal in snappyHexMesh and split it with createBaffles into a cyclicAMI pair; check that both sides have the same face count in checkMesh before running.
  • Mesh reuse across distributions: an openfoam.org polyMesh can be read by v2606 after editing the zone headers (cellZoneList/faceZoneList โ†’ regIOobject) and adding type cellZone; / type faceZone; to each zone entry.
  • Archives: do not ship a .tar.gz inside the case folder unless you want cloudHPC to unpack it at upload.
  • The full inputs and the Python scripts that generate every case are in the download package of this post.

FAQ

Is MRF accurate enough for a marine propeller in OpenFOAM? For open-water curves at medium-to-high load, yes: on PPTC it was within 3.6 % on thrust and 1.1 % on torque at J = 0.6, and within 9 % / 4.5 % at J = 1.0. Its error grows at light load, but so did the sliding-mesh error on the same grid.

What is the difference between NCC and AMI in OpenFOAM? Both couple two non-matching mesh regions that slide past each other. NCC (non-conformal coupling) is the openfoam.org implementation, introduced in 2022 as the replacement for AMI, and builds explicit couplings between the two sides; AMI (arbitrary mesh interface) is the openfoam.com implementation based on interpolation weights. On the same mesh they gave the same propeller thrust and torque within 0.5 %.

How many revolutions does a sliding-mesh propeller run need? Here, with 1ยฐ per time step, thrust settled within one to two revolutions and the 4th revolution was used for averaging. After two revolutions the mean thrust was already within 0.2 % of the final value, but still drifting slightly.

Why does my AMI propeller case diverge in the first time steps? Check that both AMI patches have the same number of faces and that the weights are close to 1 (they are printed at start-up). We saw divergence with non-matching sides from snappyHexMesh faceType boundary, without correctPhi, and with a few poor cells near the interface. A short ramp of the rotation speed helps.

Can I use overset for a propeller with a shaft? In our tests with OpenFOAM v2606, when the shaft and fairing crossed the overset boundary the voxel-based hole-cutting methods inverted the hole map; cellVolumeWeight worked but was about 40 times slower per step than the sliding mesh and unstable. Check the cellTypes field after one step before committing to a long run.

References

  1. SVA Potsdam, PPTC smp’11 Workshop: geometry, test reports and evaluation โ€” https://www.sva-potsdam.de/en/pptc-smp11-workshop/
  2. SVA Potsdam, Report on Open Water Tests, SVA Report 3752 (propeller VP1304) โ€” https://www.sva-potsdam.de/wp-content/uploads/2016/04/SVA_report_3752.pdf
  3. smp’11 Propeller Workshop, Case 2.1: Open Water Tests (evaluation of the submitted results) โ€” https://www.sva-potsdam.de/wp-content/uploads/2016/03/smp11_case21_eval_OWT.pdf
  4. CFD Direct, Using non-conformal coupling (OpenFOAM) โ€” https://cfd.direct/openfoam/free-software/using-non-conformal-coupling/
  5. OpenFOAM Foundation, OpenFOAM 14 released โ€” https://openfoam.org/release/14/
  6. OpenCFD, OpenFOAM v2606 release โ€” https://www.openfoam.com/news/main-news/openfoam-v2606
  7. Turunen, T., Siikonen, T., Lundberg, J. and Bensow, R. (2014), Open-water computations of a marine propeller using OpenFOAM, ECFD VI, Barcelona, pp. 1123โ€“1134 โ€” https://research.chalmers.se/en/publication/201623
  8. Mรผhlhรถlzer, R. (2012), Feasibility Study on the Use of Multiple-Reference Frames for Computations of Propeller-Hull Interaction in OpenFOAM, MSc thesis, Chalmers โ€” https://odr.chalmers.se/items/fa3fbb37-77d9-4407-be9e-8fdb7f9edcb2

CloudHPC is a HPC provider to run engineering simulations on the cloud. CloudHPC provides from 1 to 224 vCPUs for each process in several configuration of HPC infrastructure - both multi-thread and multi-core. Current software ranges includes several CAE, CFD, FEA, FEM software among which OpenFOAM, FDS, Blender and several others.

New users benefit of a FREE trial of 300 vCPU/Hours to be used on the platform in order to test the platform, all each features and verify if it is suitable for their needs