Building a Xylophone, Part 4: Xylo-gorithms
The first step in the process was to create a Finite Element Model. Most of the software structural engineers would use for FEM is either proprietary or expensive, so I shopped around a bit to find a free option. I ended up using MATLAB and its Partial Differential Equation Toolbox, since I already had a student license and knew the language.
With the canvas staring blankly before me, all I had left to do was paint my masterpiece, right?
Actually, I had to give the program a palette of colors and it was going to do the painting for me. Finite Element Analysis needs three colors: the model, the material, and the constraints. The model was the trickiest part, and was redrawn each iteration based on the results of each analysis — we’ll address that later.
The material can be described with a set of properties: the elastic modulus, or how bendy the wood is; the poisson ratio, or how stretchy the wood is; and the density, or how likely it is to hurt if you drop it on your foot. Since wood is anisotropic, or directional, the properties change depending on which direction you measure, but since we only care about the direction aligned with the grain (also called the longitudinal direction), we can use those properties. Luckily, that’s generally the direction people care about for wood, and I found the corresponding elastic modulus and poisson ratio for padauk wood online. I calculated the density of my own block with a tape measure and food scale.
We didn’t have any constraints for our FEA because the bar will be moving as freely as possible — there will be no outside forces or restrictions on its movement. With the properties set, I ran my first FEA on a plain rectangular block.
However, our bars were not going to be boring rectangles, so we had a lot of work ahead. Our bars needed a curve cut out from the underside (an “undercurve”) in order to match the first three desired resonant frequencies. To accomplish this, I tried to emulate Kirkland’s experiment as closely as possible, but I also wanted to simplify since I had a time restraint.
I based the width, thickness, and lengths of my bars on this Yamaha marching xylophone, which had dimensions listed in the specs. I chose this one because it was particularly small, which meant I could cut the maximum number of bars out of my padauk block.
Kirkland’s set up was to keep constant the width, length, and thickness outside the undercurve for each bar, while varying the thickness within the undercurve (matching what xylophones generally do). Specifically, he used eleven equally-spaced points along a spline to model the undercurve, with constraints that the curve be symmetrical and the two end points be at full thickness. This left five variables to optimize: the cut depth of five inner spline points (one point in the center, four pairs of symmetrical points).
I generally stuck to his experiment set up (more details of which are in his paper), except in how I modeled the undercurve. I knew I wanted to decrease the number of variables in order to decrease the time it would take for the optimization to run. In retrospect, I think decreasing the variables did limit the algorithm and increased the overall error of the results, but I knew the errors the program reported were unlikely to be translated to reality anyway, due to the unique swirly nature of the wood.
My first approach to optimizing the curve was based on Bork’s 1995 paper, which found that cutting at the antinodes of a mode had the greatest effect on its frequency. The location of antinodes for a plain rectangular block are known (as a proportion of its length), so I used those to approximate the antinodes of my block. To start, I only bothered with the first two modes, which meant I could model the undercurve with five points: a center point for the first antinode, two inner points for the second antinodes, and two end points. Since the curve had to be symmetrical, this left me two variables: the cut depth at the center and inner antinodes. Since there were five points, the curve could be modeled by a unique quartic polynomial (found by solving a system of linear equations).
I made my own simple optimization algorithm based on Bork’s results: find the frequency most out of tune, cut its antinode more if too sharp, uncut its antinode if too flat, rinse and repeat. Though simple, this strategy sometimes produced impossible geometry.
Since that clearly wasn’t working, I designed a new strategy. I knew that a polynomial curve to describe the undercut had to be at least fourth degree in order to produce the range of shapes typically seen in a xylophone, from round to w-shaped. Generally, a quartic polynomial has the following form, with five coefficients a, b, c, d, and e:
f(x) = ax⁴+bx³+cx²+dx+e
I wanted to find a more specific form for my quartic, given the constraints that the curve be symmetrical and the end points (or roots) be at specific locations along the x-axis. In math-y words, the quartic would be biquadratic (or have odd-degree coefficients of zero), have two real and two imaginary roots, and it would be a frowny face. I derived the new quartic equation and found it could be described with two coefficient variables instead of five:
f(x) = –a(x⁴–(–t²+s²)x²–t²s²)
where s is a constant — the x-coordinate of the real roots, or the start and end points of the undercurve. This gave me two variables to optimize, t and a. t essentially corresponds to the location of the imaginary roots, or the curve’s ‘w’-ness, and a refers to the slope.
With variables in hand, I set up the optimization as closely as possible to Kirkland’s using MATLAB’s Optimization Toolbox. The optimization algorithm tried to minimize an objective function while also satisfying a set of nonlinear constraints. Our objective function found the mass of the bar, which meant the algorithm tried to minimize the bar’s mass. Our constraints limited the algorithm to accept only solutions that satisfied our desired frequencies within a certain error tolerance.
To recap, given the algorithm’s guess of the variables t and a at each iteration, we:
- Created a 3d bar model with an undercurve shaped by t and a
- Ran a Finite Element Analysis on that bar
- Found the frequencies we cared about (the first three transverse modes)
- Set a nonlinear constraint that the error of each of those frequencies was less than 0.25%
- If those constraints could be satisfied, ran the objective function, which found the bar’s mass
Based on the results of each iteration, the algorithm picked new variables t and a. The error tolerance of 0.25% was chosen because humans apparently cannot detect changes in pitch within that range.
How well did it work? Instant gratification.