Doinikov 2021 Viscous - Convergence Study#

In this example we use the model doinikov2021viscous. For the computation of the ARF the acoustic field is integrated from the surface of the particle to infinity. “Infinity” here means a point far away from the particle where the acoustic field is no longer influenced by its presence. Our quadrature method scipy.integrate.quad offers the option to integrate to infinity for converging functions. However, for the given integral this does not work reliably. We therefore choose the distance far away from the particle ourselves. In this example it is shown how.

In this example we study a glass sphere viscous fluid.

20 import numpy as np
21 from matplotlib import pyplot as plt
22
23 import osaft
24
25 # --------
26 # Geometry
27 # --------
28 # Radius
29 R_0 = 1e-6  # [m]
30
31 # --------------------
32 # Properties of Glass
33 # --------------------
34 # Speed of sound
35 c_1_glass = 4_521  # [m/s]
36 c_2_glass = 2_226  # [m/s]
37 # Density
38 rho_glass = 2_240  # [kg/m^3]
39
40 # -----------------
41 # Properties of Oil
42 # -----------------
43 # Speed of sound
44 c_oil = 1_400  # [m/s]
45 # Density
46 rho_oil = 900  # [kg/m^3]
47 # Viscosity
48 eta_oil = 0.04  # [Pa s]
49 zeta_oil = 0  # [Pa s]
50
51 # --------------------------------
52 # Properties of the Acoustic Field
53 # --------------------------------
54 # Frequency
55 f = 5e5  # [Hz]
56 # Pressure
57 p_0 = 1e5  # [Pa]
58 # Wave type
59 wave_type = osaft.WaveType.STANDING
60 # Position of the particle in the field
61 position = np.pi / 4  # [rad]

Here, we are given the primary and the secondary wave speed of glass only. The model doinikov2021viscous, however, takes the Young’s modulus and the Poisson’s ratio as input parameters. We therefore have to convert the properties. The ElasticSolid class offers such conversion methods.

70 E_s = osaft.ElasticSolid.E_from_wave_speed(c_1_glass, c_2_glass, rho_glass)
71 nu_s = osaft.ElasticSolid.nu_from_wave_speed(c_1_glass, c_2_glass)
72
73 doinikov_viscous = osaft.doinikov2021viscous.ARF(
74     f=f,
75     R_0=R_0,
76     rho_s=rho_glass,
77     E_s=80e9,
78     nu_s=0.20,
79     rho_f=rho_oil,
80     c_f=c_oil,
81     eta_f=eta_oil,
82     zeta_f=zeta_oil,
83     p_0=p_0,
84     wave_type=wave_type,
85     position=position,
86     inf_factor=60,
87     inf_type=None,
88 )

We could now straightaway compute the ARF with the model. And for most cases this will work just fine. However, if you need to be extra sure that the integral has been solved accurately you might want to make a conversion study for the value of “infinity”. By default, this value is set to \(60\max{(R_0,\delta)}\). That is, it is set to 60 times the boundary layer thickness or the radius, whichever is greater.

 98 print(f"{doinikov_viscous.R_0 = }")
 99 print(f"{doinikov_viscous.delta = }")
100 print(f"{doinikov_viscous.inf_factor = }")
101 print(f"{doinikov_viscous.inf = }")
doinikov_viscous.R_0 = 1e-06
doinikov_viscous.delta = 5.319230405352436e-06
doinikov_viscous.inf_factor = 60
doinikov_viscous.inf = 0.00031915382432114614

The value of inf can also be set manually using the two parameters inf_factor and inf_type. inf_factor is the prefactor for inf_type and should be a numerical value. For inf_type there are 4 options:

  • None: \(\text{inf_factor}\cdot\max{(R_0,\delta)}\)

  • 'delta': the boundary layer thickness \(\delta\)

  • 'radius': the radius \(\delta\)

  • 1 or '1': inf is simply the inf_factor

Usually leaving it at None is the best option.

116 doinikov_viscous.inf_type = 1
117 doinikov_viscous.inf_factor = 1e-4
118 print(f"{doinikov_viscous.inf_factor = }")
119 print(f"{doinikov_viscous.inf_type = }")
120 print(f"{doinikov_viscous.inf = }")
121 doinikov_viscous.inf_type = "radius"
122 doinikov_viscous.inf_factor = 60
123 print(f"{doinikov_viscous.inf_factor = }")
124 print(f"{doinikov_viscous.inf_type = }")
125 print(f"{doinikov_viscous.inf = }")
doinikov_viscous.inf_factor = 0.0001
doinikov_viscous.inf_type = 1
doinikov_viscous.inf = 0.0001
doinikov_viscous.inf_factor = 60
doinikov_viscous.inf_type = 'radius'
doinikov_viscous.inf = 5.9999999999999995e-05

Often it is not apriori clear what value should be chosen. Therefore, a convergence study can be performed. The plotting functionality of OSAFT can be very handy for this since we can plot the ARF against the inf_factor.

In order for multiprocessing to work you need to run your code inside the if __name__ == '__main__': clause as shown below. Check the multiprocessing example.

138 if __name__ == "__main__":
139
140     doinikov_viscous.inf_type = None
141     plot = osaft.ARFPlot("inf_factor", np.arange(10, 200, 30))
142     plot.add_solutions(doinikov_viscous, multicore=True)
143     fig, ax = plot.plot_solutions(normalization="max", marker="o")
144
145     ax.set_xlabel("inf_factor")
146     ax.ticklabel_format(useOffset=False)
147     fig.tight_layout()
148     plt.show()
example doinikov 2021 convergence

We see that already for a value of inf_factor of 40 the ARF stops changing significantly. In fact, going from inf_factor = 40 to inf_factor = 200 will change the value of the ARF less than 0.001%. This will be sufficiently accurate for most cases. Note that this also means for the given example the default settings would give a very accurate estimate of the ARF.

Total running time of the script: ( 2 minutes 49.474 seconds)

Estimated memory usage: 9 MB

Gallery generated by Sphinx-Gallery