{"id": "scale_3d", "title": "Largest 3-D solve on one device", "description": "Inviscid flow (M = 0.3) past a sphere on a cubed-sphere mesh of 7680 curved hexahedra (geometry degree 2, mixed block orientations) at p = 2: 1,036,800 degrees of freedom, solved on the GPU (NVIDIA GeForce RTX 3060 Ti) with the standard pseudo-transient Newton\u2013Krylov solver and p-multigrid [2, 1, 0]: residual, Jacobian products and Krylov vectors in double precision, the blocks of the smoother in single precision (solver.precond_precision). Solved to a residual reduction of 1e-8, followed by one discrete adjoint solve for the drag coefficient (derivatives with respect to angle of attack, sideslip, Mach number and the position of each of the 6,146 surface nodes). Wall-clock times include just-in-time compilation unless stated; they depend on what else the machine was doing, which is recorded below. The configuration depends on level and device: quick/CPU 4x4x4 blocks, quick/GPU and full/GPU 16x16x5 (1,036,800 unknowns, single-precision blocks), full/CPU 8x8x5. On the GPU the same solve is first tried with double-precision blocks in a process of its own; what happened is in the table of sizes and is not checked, because it depends on the memory of the device.", "passed": true, "checks": [{"name": "steady solve converged", "value": true, "expected": "true", "passed": true}, {"name": "residual reduction (orders of magnitude)", "value": 9.375246108155029, "expected": ">= 8", "passed": true}, {"name": "adjoint linear solve converged (residual reduction)", "value": 9.965740147004194e-09, "expected": "< 1e-7", "passed": true}, {"name": "spurious drag of the inviscid sphere", "value": 0.017155253693269274, "expected": "< 0.1", "passed": true}, {"name": "lift and side force vanish", "value": 1.824843248489693e-14, "expected": "< 1e-7", "passed": true}, {"name": "shape derivative of the drag for every surface node: finite, and its net transverse component vanishes by symmetry (largest |sum|, relative to the largest entry)", "value": 1.283612460199744e-10, "expected": "< 1e-6", "passed": true}, {"name": "degrees of freedom", "value": 1036800, "expected": ">= 0", "passed": true}], "charts": [{"id": "history", "type": "line", "title": "Residual history", "xlabel": "Newton step", "ylabel": "|R|", "xscale": "linear", "yscale": "log", "series": [{"name": "residual", "x": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], "y": [0.6571930025965984, 0.5971284502232548, 0.4964392625735829, 0.5217435626517558, 0.5234122008285157, 0.3047562638230701, 0.27465638095979183, 0.2001235811968132, 0.11194007008856421, 0.03700630030744343, 0.00690107687300174, 0.0015027238056379369, 0.00018669384121114925, 3.109838806709949e-06, 3.346069887403365e-08, 2.7697898696227733e-10]}]}], "tables": [{"id": "size", "title": "Problem size and memory", "columns": ["quantity", "value"], "rows": [["elements", 7680], ["polynomial degree", 2], ["degrees of freedom", 1036800], ["block size", 135], ["geometry nodes", 67606], ["surface nodes (shape inputs: three coordinates each)", 6146], ["mesh deformation applied matrix-free", true], ["a stored deformation matrix would take (GB)", 3.324051808], ["precision of the smoother's blocks", "single"], ["element-block inverses, all levels (GB)", 0.609792], ["the same blocks in double precision would take (GB)", 1.219584], ["the same solve with double-precision blocks on this device", "out of device memory"], ["peak device memory after the solve (GB)", 3.599195648], ["peak device memory after the adjoint (GB)", 3.599195648], ["smallest scaled Jacobian", 0.2670332513534013]]}, {"id": "timing", "title": "Wall-clock times (s)", "columns": ["phase", "seconds"], "rows": [["mesh generation, discretization and discipline set-up", 15.239272090984741], ["face connectivity (build_connectivity) alone", 0.1147213299991563], ["steady solve, including compilation", 194.3885235786438], ["adjoint total derivatives of cd, first call (with compilation)", 82.41416719500558], ["adjoint total derivatives of cd, second call", 26.6624321959971], ["VTU output (file size in MB: 30)", 3.7494085959915537], ["surface payload (1536 wall faces)", 16.509807494003326]]}, {"id": "solve", "title": "Solver statistics", "columns": ["quantity", "value"], "rows": [["Newton steps", 15], ["Krylov iterations", 256], ["residual reduction", 4.214576020558971e-10], ["adjoint Krylov iterations", 153], ["adjoint residual reduction", 9.965740147004194e-09], ["cd", 0.017155253693269274], ["entropy error", 8.913347101530304e-06], ["d cd / d alpha", -2.4908709847424093e-10], ["d cd / d mach", 0.011520643450311648], ["largest |d cd / d x_surface| over the surface nodes", 0.0003625099004754205], ["net transverse shape derivative (largest |sum|)", 4.6532222519601874e-14]]}], "provenance": {"version": "0.4.0", "commit": "39979fcf902ad6116eb550b881b4278d4599c8e2", "dirty": false, "describe": "39979fcf90", "device": {"platform": "gpu", "device": "cuda:0", "device_kind": "NVIDIA GeForce RTX 3060 Ti", "jax": "0.11.2", "x64": true}, "timestamp": "2026-11-12T11:22:06-0500"}, "wall_time": 452.04, "notes": "The timings were taken on a busy machine (other processes used 87 % of the capacity of the 8 CPUs while the study ran; the GPU was 15 % utilized when the study started). What limits the size on this device: the element-block inverses of the block-Jacobi smoother are dense (block size squared per element and level, in double precision) and their construction holds several copies at once; the Krylov basis is small in comparison. The mesh-deformation operator behind the shape derivative is a dense (volume nodes x surface nodes) matrix; above 2e7 entries it is applied matrix-free, with its transpose written out chunk by chunk, and is not stored.", "level": "quick"}