/ challenges-old / cymbal2-solutions
Sign in
challenges-old / cymbal2-solutions
cymbal2-solutions
Go to fileHistoryFork
.mochicymbal2-solutions: Hermite finite element solver (direct and modal) for the cymbal2 challenges, site builder, workflow
solutionsLaplacian loss term, rigid constraint by default, geometry-keyed mode cache, README on both solvers
solversLaplacian loss term, rigid constraint by default, geometry-keyed mode cache, README on both solvers
webSite builder tolerates a repository without solutions yet
.gitattributescymbal2-solutions: Hermite finite element solver (direct and modal) for the cymbal2 challenges, site builder, workflow
.gitignoreLaplacian loss term, rigid constraint by default, geometry-keyed mode cache, README on both solvers
README.mdLaplacian loss term, rigid constraint by default, geometry-keyed mode cache, README on both solvers

Solutions to the cymbal2 challenges#

This repository holds solutions to the challenges defined in challenges/cymbal2. It is one of possibly several solution repositories registered with that challenge repository, which clones each of them, compares every solution against a common reference, and publishes the comparison at challenges/cymbal2/site. This repository's own site, at challenges/cymbal2-solutions/site, lists its submissions with audio players and animates the exported displacement fields as a 3D surface.

Layout#

solutions/<challenge-id>/<submission-id>.json    one submission: metadata and one or more solutions
solutions/<challenge-id>/<submission-id>/*.wav   the scored output files, referenced from the JSON
solutions/<challenge-id>/<submission-id>/*.h5    optional displacement fields for visualization (git LFS)
solvers/                                         source code of the submissions
web/                                             this repository's site (built by web/build.py)

The submissions hermite-fem and hermite-modal#

solvers/hermite-fem/fem_shell.py solves the shallow-shell model of MODEL.md directly in the displacements, with no modal reduction. The annulus is approximated by the square cells of a uniform Cartesian grid whose centers lie inside it (a staircase rim and hole). The three fields u, v, w are expanded in bicubic Hermite (Bogner-Fox-Schmit) elements, C1 across cells, four unknowns per node and field. The weak form is integrated with 3 x 3 Gauss points per cell exactly as written: Marguerre membrane strains, bending strains, stress resultants with the Kelvin-Voigt rates, and the assembled virtual work as the internal force, which a test confirms to be the exact gradient of the discrete strain energy; free edges are the natural boundary conditions and need no treatment. The mass is lumped by diagonal scaling of the consistent element mass. The equations are stepped with the explicit leapfrog scheme at 85 percent of the stability limit, which the in-plane block sets through the tiny lumped masses of its derivative unknowns (33 substeps per output sample at 8 mm on the flat annulus, 40 on the crash cymbal, about twice that at 5 mm). Scaling those masses up would halve the step count, and an option does it, but it pulls the spurious derivative-dominated in-plane modes from 40 to 60 kHz down into the audible band, where the cascade pumps them into steady ringing lines; it is off by default. The rigid constraint of MODEL.md is enforced by applying each stick's reaction as the rigid inertial load that cancels its net force and moments, and by projecting the six mass-orthonormal rigid fields out of the state at every chunk of steps. The three loss terms of MODEL.md are all evaluated at the Gauss points: the Kelvin-Voigt rates inside the stress resultants and the Laplacian term as the virtual work of 2 sigma1 rho h grad(w_t). The sticks are point masses stepped with the same scheme through the Hertz law, each started at the current surface height under it with relative speed v_0. The Rayleigh integral is accumulated at every step from the transverse acceleration at the Gauss points, spread onto the output samples at the retarded times with cubic Lagrange interpolation, so no acceleration history is stored. The step runs on a GPU through PyTorch, the constitutive and output blocks fused by torch.compile and the whole step captured as a CUDA graph: about 5100 steps per second at 8 mm (25488 unknowns, a quarter of an hour for the seven seconds).

Checks: the linearized assembly reproduces the free annulus's lowest frequencies to within 1 percent at 8 mm (21.7, 37.6, 50.6, 85.5 Hz against 21.9, 38.0, 50.9, 85.9), the lumped mass shifts them by under 0.3 percent relative to the consistent mass, the internal force matches the energy gradient to 1e-9, and the retarded accumulation matches a direct integral to 4e-5. On the crash geometry the two tilt modes, exact zero modes of the continuum, come out at 2.95 Hz at 8 mm because the bicubic space cannot represent the in-plane displacement that accompanies a rigid tilt of the cosine bell; the constraint removes them anyway. A run of the flat challenge with the shell left free confirmed what MODEL.md says about the constraint: the shell tilted by about a radian in half a second, the partials glided down, the treble drained away, and the explicit run diverged at 0.66 s.

solvers/hermite-fem/modal_shell.py solves the same discrete system in its eigenmodes below a cutoff (20 kHz by default): the linear part is propagated exactly by the two-step scheme of the v1 modal solver at a few substeps per sample, the nonlinear force and the Laplacian loss are evaluated at the Gauss points by the same routine as the finite element solver and projected on the modes, and the six rigid fields are excluded from the eigenproblem by a penalty (Woodbury-corrected shift-invert slices). The modes are cached under solvers/hermite-fem/cache/, keyed by geometry. The two solvers therefore differ only in the modal truncation and the time integration, and their difference measures the effect of the modes above the cutoff, which the finite element solver keeps and the modal one drops.

bash solvers/hermite-fem/run_chain.sh <cymbal2-repo>        # on a CUDA GPU: 8 mm then 4 mm for both challenges, hours
python solvers/hermite-fem/check_modes.py <cymbal2-repo>/challenges/cymbal2-flat-v1/challenge.json 0.008   # linear check, CPU

While a run is going, <tag>.progress.json and <tag>.partial.wav beside the outputs are rewritten every minute with the state of the sticks and the samples computed so far.

Validating locally#

pip install git+https://vault1.magland.org/challenges/challenge-tools
challenge-tools validate --challenges <path-to-cymbal2-repo>/challenges --solutions solutions
python web/build.py --out site
↑↓ move↵openescclose