Superposition of two fields

A more advanced usage, designed to create a field with a levitation trap and a haptics focus point.

[1]:
import numpy as np
import levitate
[2]:
array = levitate.arrays.RectangularArray((21, 12))
trap_pos = np.array([-20e-3, 0, 60e-3])
haptics_pos = np.array([40e-3, 0, 90e-3])
phases = array.focus_phases(trap_pos) + array.signature(trap_pos, stype='twin') + 0.2 * np.random.uniform(-np.pi, np.pi, array.num_transducers)
start = levitate.complex(phases)

The fields are superposed using mutual quiet zones, created by minimizing the pressure and velocity at the secondary point in each field. We will need three fields, calculating the pressure magnitude, the velocity magnitude, and the stiffenss of the trap.

[3]:
p = abs(levitate.fields.Pressure(array))**2
v = (abs(levitate.fields.Velocity(array))**2).sum()
s = levitate.fields.RadiationForceStiffness(array).sum()

The levitation trap is found using a minimization sequence. First the phases are optimized for just a trap, then the phases and amplitudes are optimized to include the quiet zone.

[4]:
trap_result = levitate.optimization.minimize(
    [
        (s + p * 1)@trap_pos,
        (s + p)@trap_pos + (v * 1e3 + p)@haptics_pos
    ],
    array, start_values=start, variable_amplitudes=[False, True]
)[-1]

The haptics point can be created using a simple focusing algorithm, so we can optimize for the inclusion of the quiet zone straight away. To retain the focus point we set a negative weight for the pressure, i.e. maximizing the pressure.

[5]:
start = levitate.complex(array.focus_phases(haptics_pos))
haptics_result = levitate.optimization.minimize(
    p * (-1)@haptics_pos + (p + v * 1e3)@trap_pos,
    array, start_values=start, variable_amplitudes=True
)
/home/docs/checkouts/readthedocs.org/user_builds/levitate/envs/stable/lib/python3.7/site-packages/levitate/fields/_transformers.py:268: RuntimeWarning: invalid value encountered in true_divide
  jacobians = jacobians * (np.conjugate(values) / abs_values)[self._val_reshape]

Finally, we visualize the individual fields, as well as the superposed field.

[6]:
array.visualize.append('pressure')
array.visualize(
    trap_result, haptics_result, haptics_result * 0.3 + trap_result * 0.7,
    labels=['Trap', 'Haptics', 'Combined']
).show()