/ proof-of-concept / cymsim
Sign in
proof-of-concept / cymsim
cymsim
Go to fileHistoryFork
docscymsim: nonlinear FEM cymbal simulation package
examplescymsim: nonlinear FEM cymbal simulation package
srccymsim: nonlinear FEM cymbal simulation package
testscymsim: nonlinear FEM cymbal simulation package
.gitignorecymsim: nonlinear FEM cymbal simulation package
prototype.pycymsim: nonlinear FEM cymbal simulation package
pyproject.tomlcymsim: nonlinear FEM cymbal simulation package
README.mdcymsim: nonlinear FEM cymbal simulation package

cymsim#

Explicit nonlinear finite-element simulation of struck cymbals. The cymbal is a Marguerre-von Karman shallow shell with a bell, a bow, a thickness taper and seeded imperfections, discretized on a triangulated disk with constant-strain membrane triangles and Discrete Kirchhoff bending triangles, integrated in time with an explicit leapfrog scheme, struck by one or more rigid exciters through power-law contact springs, and heard at a listener point through a Rayleigh-integral radiation model. The equations, the discretization and the time-stepping method are written out in docs/model.md.

Installation#

pip install -e ".[dev]"          # numpy, scipy, jax (CPU), pyyaml, pytest, matplotlib
pip install "jax[cuda12]"        # optional: run the time loop on a GPU

Runs at the default resolution (6 mm elements, about 4700 nodes and 40 sub-steps per audio sample) need a GPU to finish in minutes. On a CPU, use a coarser mesh and a shorter duration, as in examples/quick_cpu.yaml.

Usage#

cymsim example-config my_run.yaml --exciter mallet   # write a default config
cymsim check my_run.yaml                             # mesh, time step, element self-tests, no time stepping
cymsim simulate my_run.yaml                          # run; writes <prefix>_rayleigh.wav, _unbaffled.wav, _result.npz, _cascade.png
cymsim simulate my_run.yaml --linear --duration 0.5  # linear reference run

The same from Python:

from cymsim import SimulationConfig, Hit, StickExciter, simulate

cfg = SimulationConfig.from_yaml("examples/crash_mallet.yaml")
cfg.hits.append(Hit(time=0.8, r=0.19, phi=2.0, velocity=7.0, exciter=StickExciter()))
result = simulate(cfg)
result.write_wav("crash")
print(result.hits)          # peak force, contact time and rebound velocity of each hit
print(result.energy_log)    # kinetic / membrane / bending / exciter energy and max|w|/h over time

A run is described by one SimulationConfig made of Material, Profile, Imperfections, MeshConfig, a list of Hits (each with a StickExciter or MalletExciter), Listener, Numerics and Output. The YAML file mirrors the dataclass fields; omitted fields take the defaults, which reproduce an 18 inch medium-thin B20 crash. Units are SI throughout. See examples/ for a mallet stroke, a stick crash, a train of four hits and a quick CPU run.

Layout#

module contents
config.py configuration dataclasses, YAML load/save, validation
geometry.py mid-surface height z0(x, y) and thickness h(x, y), seeded imperfections
mesh.py numpy disk mesher (concentric rings, angular stitching, smoothing), CST operators
elements.py DKT bending stiffness, Marguerre-von Karman membrane strains, element energies
shell.py assembled shell: lumped mass, rigid modes, internal force by autodiff, stability bound
exciter.py contact patches, power-law contact law, schedule of hits
radiation.py Rayleigh integral and the unbaffled (rim-diffraction) approximation
simulate.py leapfrog time loop, block compilation, result container
diagnostics.py band envelopes, onset times, spectral centroid, cascade plot
cli.py cymsim simulate, cymsim check, cymsim example-config

prototype.py is the original single-file prototype that this package reorganizes; it is kept for reference and is not used by the package.

Tests#

pytest

The tests check the mesher (manifold, orientation, quality), the DKT element (rigid modes, constant curvature, twist), the membrane strains, the assembled shell (mass, rigid-mode annihilation, force = minus energy gradient, dissipative damping), the configuration round trip, and short coarse simulations with one and two hits.

↑↓ move↵openescclose