# 1 Optimizing the length of a tuning fork

To illustrate how to use FeenoX in an optimization loop, let us consider the problem of finding the length \ell_1 of a tuning fork (fig. 1) such that the fundamental frequency on a free-free oscillation is equal to the base A frequency at 440 Hz. Figure 1: What length \ell_1 is needed so the fork vibrates at 440 Hz?

The FeenoX input is extremely simple input file, since it has to solve the free-free mechanical modal problem (i.e. without any Dirichlet boundary condition). All it has to do is to print the fundamental frequency.

To find the length \ell_1, FeenoX is sucessively called from a Python driving script called fork.py. This script uses Gmsh’s Python API to create the CAD and the mesh of the tuning fork given the geometrical arguments r, w, \ell_1 and \ell_2. The parameter n controls the number of elements through the fork’s thickness. Here is the driving script without the CAD & mesh details (the full implementation of the function is available in the examples directory of the FeenoX distribution):

import math
import gmsh
import subprocess  # to call FeenoX and read back

def create_mesh(r, w, l1, l2, n):
gmsh.initialize()
...
gmsh.write("fork.msh")
gmsh.finalize()
return len(nodes)

def main():
target = 440    # target frequency
eps = 1e-2      # tolerance
r = 4.2e-3      # geometric parameters
w = 3e-3
l1 = 30e-3
l2 = 60e-3

for n in range(1,7):   # mesh refinement level
l1 = 60e-3              # restart l1 & error
error = 60
while abs(error) > eps:   # loop
l1 = l1 - 1e-4*error
# mesh with Gmsh Python API
nodes = create_mesh(r, w, l1, l2, n)
# call FeenoX and read scalar back
# TODO: FeenoX Python API (like Gmsh)
result = subprocess.run(['feenox', 'fork.fee'], stdout=subprocess.PIPE)
freq = float(result.stdout.decode('utf-8'))
error = target - freq

print(nodes, l1, freq)

Note that in this particular case, the FeenoX input files does not expand any command-line argument. The trick is that the mesh file fork.msh is overwritten in each call of the optimization loop. The detailed steps between gmsh.initialize() and gmsh.finalize() are not shown here,

Since the computed frequency depends both on the length \ell_1 and on the mesh refinement level n, there are actually two nested loops: one parametric over n=1,2\dots,7 and the optimization loop itself that tries to find \ell_1 so as to obtain a frequency equal to 440 Hz within 0.01% of error.

PROBLEM modal 3D MODES 1  # only one mode needed
E = 2.07e11         # in [Pa]
nu = 0.33
rho = 7829          # in [kg/m^2]

# no BCs! It is a free-free vibration problem
SOLVE_PROBLEM

# write back the fundamental frequency to stdout
PRINT f(1)
$python fork.py > fork.dat$ pyxplot fork.ppl
$ Figure 2: Estimated length \ell_1 needed to get 440 Hz for different mesh refinement levels n # 2 Five natural modes of a cantilevered wire Back in College, we had this subject Experimental Physics 101. I had to measure the natural modes of two cantilevered wires and determine the Young modulus of of those measurements. The report is here. Two comments: 1. It is in Spanish 2. There was a systematic error and a factor of two sneaked in into the measured values Here is a finite-element version of the experimental setup with a comparison to then theoretical values written directly as Markdown tables. The material (either aluminum or copper) and the mesh type (either tet or hex) and be chosen at runtime through command line arguments. DEFAULT_ARGUMENT_VALUE 1 hex # mesh, either hex or unstruct DEFAULT_ARGUMENT_VALUE 2 copper # material, either copper or aluminum l = 0.5*303e-3 # cantilever wire length [ m ] d = 1.948e-3 # wire diameter [ m ] # material properties for copper m_copper = 0.5*8.02e-3 # total mass (half the measured because of the experimental disposition) [ kg ] E_copper = 2*66.2e9 # [ Pa ] Young modulus (twice because the factor-two error) # material properties for aluminum m_aluminum = 0.5*2.67e-3 E_aluminum = 2*40.2e9 # problem’s properties E = E_$2                     # [ MPa ]
rho = m_$2/(pi*(0.5*d)^2*l) # [ kg / m^3 ] density = mass (measured) / volume nu = 0 # Poisson’s ratio (does not appear in Euler-Bernoulli) # analytical solution VECTOR kl VECTOR f_euler # first compute the first five roots ok cosh(kl)*cos(kl)+1 kl[i] = root(cosh(t)*cos(t)+1, t, 3*i-2,3*i+1) # then compute the frequencies according to Euler-Bernoulli # note that we need to use SI inside the square root A = pi * (d/2)^2 I = pi/4 * (d/2)^4 f_euler[i] = 1/(2*pi) * kl(i)^2 * sqrt((E * I)/(rho * A * l^4)) # now compute the modes numerically with FEM # note that each mode is duplicated as it is degenerated READ_MESH wire-$1.msh DIMENSIONS 3
PROBLEM modal MODES 10
BC fixed fixed
SOLVE_PROBLEM

# github-formatted markdown table
# compare the frequencies
PRINT "  \$n\$   |    FEM [Hz]   |   Euler [Hz]  |  Relative difference [%]"
PRINT   ":------:|:-------------:|:-------------:|:--------------:"
PRINT_VECTOR SEP "\t|\t" i  %.4g f(2*i-1) f_euler   %.2f 100*(f_euler(i)-f(2*i-1))/f_euler(i)
PRINT
PRINT ": $2 wire over$1 mesh"

# commonmark table
PRINT
PRINT "  \$n\$   |          \$L\$          |       \$\\Gamma\$        |      \$\\mu\$    |       \$M\$"
PRINT   ":------:+:---------------------:+:---------------------:+:-------------:+:--------------:"
PRINT_VECTOR SEP "\t|\t" i "%+.1e" L Gamma "%.4f" mu Mu
PRINT
PRINT ": $2 wire over$1 mesh, participation and excitation factors \$L\$ and \$\\Gamma\$, effective per-mode and cummulative mass fractions \$\\mu\$ and \$M\$"

# write the modes into a vtk file
WRITE_MESH wire-$1-$2.vtk \
VECTOR u1 v1 w1 VECTOR u2 v2 w2 VECTOR u3 v3 w3 \
VECTOR u4 v4 w4 VECTOR u5 v5 w5 VECTOR u6 v6 w6 \
VECTOR u7 v7 w7 VECTOR u8 v8 w8 VECTOR u9 v9 w9 VECTOR u10 v10 w10

# and into a msh file
WRITE_MESH wire-$1-$2.msh {
u1 v1 w1
u2 v2 w2
u3 v3 w3
u4 v4 w4
u5 v5 w5
u6 v6 w6
u7 v7 w7
u8 v8 w8
u9 v9 w9
u10 v10 w10
}
$gmsh -3 wire-hex.geo [...] Info : Done meshing order 2 (Wall 0.0169025s, CPU 0.016804s) Info : 8398 nodes 4676 elements Info : Writing 'wire-hex.msh'... Info : Done writing 'wire-hex.msh' Info : Stopped on Fri Dec 24 17:07:19 2021 (From start: Wall 0.0464517s, CPU 0.133498s)$ gmsh -3 wire-tet.geo
[...]
Info    : Done optimizing mesh (Wall 0.0229018s, CPU 0.022892s)
Info    : 16579 nodes 13610 elements
Info    : Writing 'wire-tet.msh'...
Info    : Done writing 'wire-tet.msh'
Info    : Stopped on Fri Dec 24 17:07:59 2021 (From start: Wall 2.5798s, CPU 2.64745s)
$feenox wire.fee$n$| FEM [Hz] | Euler [Hz] | Relative difference [%] :------:|:-------------:|:-------------:|:--------------: 1 | 45.84 | 45.84 | 0.02 2 | 287.1 | 287.3 | 0.06 3 | 803.4 | 804.5 | 0.13 4 | 1573 | 1576 | 0.24 5 | 2596 | 2606 | 0.38 : copper wire over hex mesh$n$|$L$|$\Gamma$|$\mu$|$M$:------:+:---------------------:+:---------------------:+:-------------:+:--------------: 1 | +1.3e-03 | +4.2e-01 | 0.1371 | 0.1371 2 | -1.8e-03 | -5.9e-01 | 0.2716 | 0.4087 3 | +9.1e-05 | +1.7e-02 | 0.0004 | 0.4091 4 | -1.7e-03 | -3.0e-01 | 0.1252 | 0.5343 5 | -3.3e-05 | -5.9e-03 | 0.0000 | 0.5343 6 | -9.9e-04 | -1.8e-01 | 0.0431 | 0.5775 7 | +7.3e-04 | +1.2e-01 | 0.0221 | 0.5995 8 | +4.5e-06 | +7.5e-04 | 0.0000 | 0.5995 9 | +5.4e-04 | +9.9e-02 | 0.0134 | 0.6129 10 | +2.7e-05 | +4.9e-03 | 0.0000 | 0.6129 : copper wire over hex mesh, participation and excitation factors$L$and$\Gamma$, effective per-mode and cummulative mass fractions$\mu$and$M feenox wire.fee hex copper   | pandoc -o wire-hex-copper.html
$feenox wire.fee tet copper | pandoc -o wire-tet-copper.html$ feenox wire.fee hex aluminum | pandoc -o wire-hex-aluminum.html
\$ feenox wire.fee tet aluminum | pandoc -o wire-tet-aluminum.html

copper wire over hex mesh
n FEM [Hz] Euler [Hz] Relative difference [%]
1 45.84 45.84 0.02
2 287.1 287.3 0.06
3 803.4 804.5 0.13
4 1573 1576 0.24
5 2596 2606 0.38
copper wire over hex mesh, participation and excitation factors L and \Gamma, effective per-mode and cummulative mass fractions \mu and M
n L \Gamma \mu M
1 -1.8e-03 -5.9e-01 0.2713 0.2713
2 +1.3e-03 +4.2e-01 0.1374 0.4087
3 +9.7e-05 +1.8e-02 0.0004 0.4091
4 -1.6e-03 -3.1e-01 0.1251 0.5343
5 -3.5e-05 -6.3e-03 0.0001 0.5343
6 -9.9e-04 -1.8e-01 0.0431 0.5774
7 +7.2e-04 +1.2e-01 0.0221 0.5995
8 -8.6e-06 -1.5e-03 0.0000 0.5995
9 -2.6e-05 -4.7e-03 0.0000 0.5996
10 +5.4e-04 +9.9e-02 0.0134 0.6130
copper wire over tet mesh
n FEM [Hz] Euler [Hz] Relative difference [%]
1 45.84 45.84 0.00
2 287.2 287.3 0.05
3 803.4 804.5 0.13
4 1573 1576 0.24
5 2596 2606 0.38
copper wire over tet mesh, participation and excitation factors L and \Gamma, effective per-mode and cummulative mass fractions \mu and M
n L \Gamma \mu M
1 -1.9e-03 -6.1e-01 0.2925 0.2925
2 +1.2e-03 +3.8e-01 0.1163 0.4087
3 -1.0e-03 -3.3e-01 0.0861 0.4948
4 +7.0e-04 +2.3e-01 0.0395 0.5343
5 -6.0e-04 -1.9e-01 0.0292 0.5634
6 +4.2e-04 +1.3e-01 0.0140 0.5774
7 -4.0e-04 -1.3e-01 0.0133 0.5908
8 +3.3e-04 +1.1e-01 0.0087 0.5995
9 +3.5e-04 +1.1e-01 0.0096 0.6091
10 -2.2e-04 -6.9e-02 0.0038 0.6129
aluminum wire over hex mesh
n FEM [Hz] Euler [Hz] Relative difference [%]
1 61.91 61.92 0.02
2 387.8 388 0.06
3 1085 1086 0.13
4 2124 2129 0.24
5 3506 3519 0.38
aluminum wire over hex mesh, participation and excitation factors L and \Gamma, effective per-mode and cummulative mass fractions \mu and M
n L \Gamma \mu M
1 -6.9e-04 -6.2e-01 0.3211 0.3211
2 +3.6e-04 +3.3e-01 0.0876 0.4087
3 +4.2e-05 +2.4e-02 0.0008 0.4095
4 -5.4e-04 -3.1e-01 0.1248 0.5343
5 +3.7e-05 +2.3e-02 0.0006 0.5349
6 -3.0e-04 -1.9e-01 0.0425 0.5774
7 +2.4e-04 +1.2e-01 0.0221 0.5995
8 -3.2e-06 -1.6e-03 0.0000 0.5995
9 +1.8e-04 +9.8e-02 0.0132 0.6127
10 -9.5e-06 -5.2e-03 0.0000 0.6128
aluminum wire over tet mesh
n FEM [Hz] Euler [Hz] Relative difference [%]
1 61.91 61.92 0.00
2 387.8 388 0.05
3 1085 1086 0.13
4 2124 2129 0.24
5 3506 3519 0.38
aluminum wire over tet mesh, participation and excitation factors L and \Gamma, effective per-mode and cummulative mass fractions \mu and M
n L \Gamma \mu M
1 -6.4e-04 -6.1e-01 0.2923 0.2923
2 +4.0e-04 +3.8e-01 0.1164 0.4087
3 -3.5e-04 -3.3e-01 0.0861 0.4948
4 +2.3e-04 +2.3e-01 0.0395 0.5343
5 -2.0e-04 -1.9e-01 0.0292 0.5634
6 +1.4e-04 +1.3e-01 0.0140 0.5774
7 -1.3e-04 -1.3e-01 0.0133 0.5908
8 +1.1e-04 +1.1e-01 0.0087 0.5995
9 +1.2e-04 +1.1e-01 0.0096 0.6091
10 -7.3e-05 -6.9e-02 0.0038 0.6129