1function [uh, wh, thk, drds, dzds, cs, ct] = cymbal_at(basis, sfrac)
2% CYMBAL_AT Mode shapes and local geometry at an arclength fraction.
3%
4% sfrac addresses the meridian from the hole (0) to the rim (1); it is the
5% coordinate the strike positions are expressed in. The meridional shape U is
6% linear within an element, so it is interpolated linearly; the normal shape W
7% is cubic Hermite, and is interpolated with its own shape functions from the
8% nodal (W, dW/ds) pair, which matters because at the top of the retained band
9% there are only about four nodes per flexural wavelength.
10%
11% Returns row vectors uh, wh (1 x n modes) and the local thickness, meridian
12% direction cosines and principal curvatures at that point.
14nn = length(basis.snode);
15S = basis.S;
16s = min(0.999999, max(0, sfrac)) * S;
17idx = sum(basis.snode <= s);
18idx = min(max(idx, 1), nn - 1);
19L = basis.snode(idx + 1) - basis.snode(idx);
20xi = (s - basis.snode(idx)) / L;
22uh = basis.NU(idx, :) + xi * (basis.NU(idx + 1, :) - basis.NU(idx, :));
23h1 = 1 - 3 * xi^2 + 2 * xi^3;
24h2 = L * (xi - 2 * xi^2 + xi^3);
25h3 = 3 * xi^2 - 2 * xi^3;
26h4 = L * (-xi^2 + xi^3);
27wh = h1 * basis.NW(idx, :) + h2 * basis.NT(idx, :) ...
28 + h3 * basis.NW(idx + 1, :) + h4 * basis.NT(idx + 1, :);
30thk = basis.thknode(idx) + xi * (basis.thknode(idx + 1) - basis.thknode(idx));
31drds = basis.drdsnode(idx) + xi * (basis.drdsnode(idx + 1) - basis.drdsnode(idx));
32dzds = basis.dzdsnode(idx) + xi * (basis.dzdsnode(idx + 1) - basis.dzdsnode(idx));
33cs = basis.csnode(idx) + xi * (basis.csnode(idx + 1) - basis.csnode(idx));
34ct = basis.ctnode(idx) + xi * (basis.ctnode(idx + 1) - basis.ctnode(idx));
35end