Ripple tank

Ripple tank preview
remixableManimCEmanim-physics3Dwaves

manim/ripple_tank.py

"""Ripple tank: two sources on a water surface, crossed into interference.

No axes here, unlike the rest of the 3D work. axis_stubs() starts every
stub the same distance out, which cannot serve a surface this wide and this
flat at once: x and y have to clear water reaching to 2.6, while z has to
start near a crest only 0.16 high. One radius cannot do both, and the
asset is about the pattern rather than the coordinates.

Render (the driver does this for every palette; these are for eyeballing):
    P=/opt/homebrew/opt/python@3.11/bin/python3.11
    ASSET_MODE=still  $P -m manim -s -t -r 1600,1600 manim/ripple_tank.py RippleTank
    ASSET_MODE=motion $P -m manim -qh   -r 1080,1080 manim/ripple_tank.py RippleTankLoop
"""

import numpy as np
from manim import DOWN, LEFT, TAU, UP, Dot3D, Text, VGroup, ValueTracker, always_redraw, linear

The full Manim source and the rendered video come with a plan.