Marie Rastello
email: marie.rastello@ec-lyon.fr

Jean-Louis Marié
email: jean-louis.marie@ec-lyon.fr

Nathalie Grosjean
email: nathalie.grosjean@ec-lyon.fr

Michel Lance
email: michel.lance@ec-lyon.fr

Study of bubble's equilibrium in rotating flow

Keywords: bubble, lift force, drag force, wake interaction, rotating flow

Introduction

In many industrial processes such as oil industry or chemical engineering for example, it is essential to know, as far as possible, the motion of bubbles relatively to the fluid to be able to predict the dynamic of the whole flow or the efficiency of the chemical reaction. To that purpose, it is necessary to understand the forces acting on each bubble and to have an expression or a value of them in the considered context. Referring to recent simulations, a calculation of the forces becomes now possible (see for example [START_REF] Lu | A DNS study of laminar bubbly flows in a vertical channel[END_REF]). Nevertheless, to increase the number of bubbles that can be simulated, reliable information on theses forces is required. From several aspects such as deformable versus rigid shape or zerostress versus non-zero stress condition at the interface, bubbles differ from particles. The forces cannot then be simply deduced from the one applied on particles. At present even the forces on a single bubble are under discussion and their expression is not unanimously established. When the flow is sheared or the bubble deformed a key problem lies in the lift force [START_REF] Magnaudet | Dynamics of high Re bubbles in inhomogeneous flows[END_REF]. Analytical developments exist in different asymptotic cases. The viscous case has been considered by Saffman (1965) for a small rigid sphere in a linear shear flow with large shear. The analysis was extended by [START_REF] Mclaughlin | Inertial migration of a small sphere in linear shear flows[END_REF] taking into account inertia effects. [START_REF] Legendre | A note on the lift force on a spherical bubble or drop in a low-Reynolds-number shear flow[END_REF] revisited Saffman results and obtained a lift force (2/3) 2 that of a solid sphere. The other limit, that of inviscid fluids, was explored, among others, by [START_REF] Auton | The dynamics of bubbles, drops and particles in motion in liquids[END_REF][START_REF] Auton | The lift force on a spherical body in a rotational flow[END_REF]. In the case of a weak linear shear flow, the lift coefficient value obtained is 0.5. Numerical studies have been performed to determine the forces in generic flow situations such as uniform or linear shear flows [START_REF] Legendre | The lift force on a spherical bubble in a viscous linear shear flow[END_REF]) and predictive laws have been determined for the drag and lift forces depending on the Reynolds number and on the shear rate. Simultaneously, experiments were performed following the same kind of ideas: reference flows were studied such as to have reference values for the forces and especially the lift force. [START_REF] Naciri | Contribution à l'étude des forces exercées par un liquide sur une bulle de gaz: portance, masse ajoutée et interactions hydrodynamiques[END_REF] studied the equilibrium position of a bubble in a solid body rotating flow around an horizontal axis and deduced from it values and some scaling for the lift and drag forces. The fluids were water and glycerin/water mixtures, the bubbles were seemingly of the order of a few millimeters. In parallel to the present study another one still on the same kind of flow has been performed with water and glycerin/water mixtures with millimetric bubbles (Van Nierop 2003;Van Nierop et al. 2007). Results on both drag and lift forces have been obtained, especially a change of sign of the lift force when the Reynolds number becomes low has been observed. The present study S1_Tue_C_22 6 th International Conference on Multiphase Flow, ICMF 2007, Leipzig, Germany, July 9 -13, 2007 also concerns a solid body rotating flow around an horizontal axis. It concentrates on moderate to high Reynolds numbers with low to moderate values of the shear rate. The forces are determined and the effect of Reynolds and shear are studied. Attention is payed to occurring phenomena that can disturb this measurement. In particular, the interaction between the bubble, its wake and the reference flow and on the conditions for which the interaction occurs is studied. A particular feature is that the bubble never stabilizes completely, it is always moving, oscillating around its equilibrium position. The movements are of small amplitude (a few tenths of a millimeter) but with specified frequencies. Some work also concerns this aspect. The outline of the paper is as follows. Section 2 presents the force balance for a bubble, and how in the framework of a horizontal solid body rotation the measurement of the equilibrium position gives access directly to the forces applied to the bubble. The experimental setup, the caracterisation of the reference flow and the measurement process are presented in section 3. The measured drag and lift forces come with section 4. The last part deals with the oscillating motions of the bubble.

2 Force balance on a bubble.

In the present section, the force balance on a bubble is given and then applied for the bubble at its equilibrium position in the solid body rotating flow. Some non-dimensional numbers that can be used to describe the system are then presented. For a clean, uncontaminated, spherical bubble, moving relatively to the fluid at moderate to large Reynolds number, the dynamical equation is [START_REF] Magnaudet | Dynamics of high Re bubbles in inhomogeneous flows[END_REF]:

ρ l V b C A dv dt = -ρ l V b g + ρ l V b (C A + 1) DU Dt (1) +ρ l V b C L (U -v) × (∇ × U) + 1 2 ρ l C D A b |U -v|(U -v)
where ρ l is the liquid density, V b the volume of the bubble, A b its projected area, v the bubble velocity, g the acceleration due to gravity and U the velocity of the undisturbed ambient flow taken at the center of the bubble. The gas density is neglected because ρ g ρ l . C A is the added mass coefficient, its value is 0.5 for spherical bubbles [START_REF] Magnaudet | Dynamics of high Re bubbles in inhomogeneous flows[END_REF] and depends on the ratio between the major and the minor axis for ellipsoidal ones [START_REF] Lamb | Hydrodynamics[END_REF]. C L is the lift coefficient and C D the drag coefficient. Because the bubble is a sphere the lift here is only induced by shear and not by bubble deformation.

The present study deals with a bubble immersed in a fluid in solid-body rotation around an horizontal axis. As mentioned before a first positive point for the present study is that the bubble is immersed in a reference flow. Another major interest of the setup is that the bubble comes roughly to an equilibrium position in the non-transient regime. This gives the opportunity to measure the forces without having to measure an instantaneous velocity or acceleration for the bubble. Mentioned in the order of appearance in equation ( 1), the forces applied on the bubble are F B the buoyancy force, F A which takes into account the added mass force and pressure gradient effects, F L the lift force and F D the drag force (see

x y z ω r e F D F L F B F A θ e Figure 1:
The forces applied on a bubble at equilibrium at moderate to high Reynolds numbers. F B is the buoyancy force, F D , the drag force, F L the lift force. F A takes into account the added mass force and pressure gradient effects. In the present sketch, the angular velocity ω and equilibrium angle θ e are negative. figure 1). Because U = ωre θ , equation (1) at equilibrium can be rewritten in:

C L = 1 2 1 + C A - g sin θ e r e ω 2 (2)
and

C D = - 4 3 gd cos θ e |r e ω|r e ω (3)
with ω the angular velocity of the rotating tank and of the fluid, (r, θ) the polar coordinates whose values at equilibrium are (r e , θ e ) and d the diameter of the bubble. Thus, the measurement of r e and θ e when the bubble is at equilibrium, knowing the other characteristics (d, ω, C A ) provides a value for the lift and drag coefficients in the non-transient regime.

To describe this non-transient state, the only parameters that are needed are, the angular velocity ω, the diameter of the bubble d, the viscosity ν of the fluid, its density ρ l and its surface tension σ , all chosen by the experimenter and r e and θ e measured when the bubble is at equilibrium. These seven parameters need three units. Using the Π-theorem it appears that four non-dimensional parameters are needed to describe the forces applied on the bubble at equilibrium. One possible set is for example the Reynolds number (Re) based on the relative velocity between the bubble (zero) and the fluid (ωr), the Froude number (Fr) which is the ratio between inertia effects and buoyancy, the Strouhal number (Sr) which is a ratio between the difference of velocity seen by both sides of the bubble and the mean velocity of the fluid at the place of the bubble and the Morton number (Mo) which is representative of the characteristics of the fluid:

Re = |v -U|d ν , F r = |v -U| 2 gd , Sr = |∆U| |v -U| , M o = gν 4 ρ 3 σ 3 (4)
Here, the different numbers express as follows: ICMF 2007, Leipzig, Germany, July 9 -13, 2007 3 The experimental and measuring facilities This part deals with the presentation of the experiment. First the experimental setup is described. The caracterisation of the reference flow comes after. The part ends with the description of the measuring protocol.

Re = ωr e d ν , F r = ω 2 r 2 e gd , Sr = d r e , M o = gν 4 ρ 3 σ 3 (5) S1_Tue_C_22 6 th International Conference on Multiphase Flow,

The experimental setup

The device is made of a Plexiglas cylindrical tank (Ø=10 cm, L=10 cm) rotating around its axis (horizontal). The tank is In front of it is the high-speed camera. In the back the toothed belt and the opto-electronic sensor can be seen.

mounted in a cylindrical counterbore and the contact is made using ball bearings (see figure 2). A motor is coupled to the tank, at the back, using a toothed belt. The rotation rates for the tank ranges from 1 rad.s -1 to 100 rad.s -1 . The motor is driven using a Labview program on the computer. The same program is also used to determine an effective rotation rate of the tank. Indeed, a reflecting sticker has been put on the side of the tank. An opto-electronic sensor detects the passages of the sticker in front of him, the electrical signal is transmitted to the computer. A detection of the rising fronts in the signal is then used to obtain the rotation rate of the tank. The front face of the tank is removable for cleaning use and three aligned holes have been done on the side of the cylinder. They are closed with stoppers. They are used to fill in the tank with water and to inject the bubble.

Description of the reference flow

Because the purpose of the work is to determine the forces applied on a bubble in a given flow (the solid-body rotating flow), a first step is to check that the flow is effectively the one waited for. Hence, the present part deals with three different aspects of this verification. First, velocity profiles have been determined on the whole section of the tank to check that the flow is effectively a solid body rotation. The second one deals with the position of the axis of rotation of the flow.

The purpose was there to see if the axis of rotation of the flow is stable or moving. The last one deals with the study of the flow in presence of a bubble to see if a coupling could appear between the flow and the bubble. Such a coupling could modify the behavior of the bubble and thus the force measurements.

PIV measurements were performed to determine the velocity profiles in the reference flow. Experiments were done with the tank full of water, without any bubble. Small hollow glass spheres of 10 µm diameter (Dantec product) were dispersed in the fluid. The laser sheet was generated perpendicularly to the axis of rotation by a dual-cavity pulsed laser Nd-Yag Quantel 120 mJ -8Hz. The images were recorded with a low speed camera Dantec FlowSense working at 15 frames per second, using a field of view covering the whole section of the flow (size of the field: 11 cm 2 ). The measured velocity profiles are all well linear. An example of such a velocity profile is presented on figure To study the possible movements of the axis of rotation of the flow, a second different PIV campaign was done. Indeed, when the experiments are performed with bubbles, bubbles never stabilize completely and always oscillate with one frequency among others that is the rotation frequency of the tank (see section 5). The purpose was then to check if there was or not a precession of the axis of rotation of the fluid, which could make the bubble oscillate. The PIV measurements were done using a reduced field. The field size is 2 mm 2 . The particles were fluorescent polyamide spheres doped in Rhodamin B of size 10 µm (Dantec product). They absorbe in the green light and emit in the orange. The laser sheet was perpendicular to the axis of rotation as before. The laser was a Spectra Physics Millenia IIs continuous diode pumped (2W). The camera was a high-speed video camera (Phantom V4.3 black and white) with an orange filter mounted on it. The frame rate used was 200 frames per second. To reduce the field of view to the expected size an Optem Zoom 125C objective was used. For the PIV correlations to be possible in the 2 mm 2 field, a high concentration of seeding particles was necessary. These particles being expensive, the experiment was repeated only four times. The rotation speed of the tank was the same for the four runs. A small motion of the axis of rotation of the flow with a privileged vertical di-S1_Tue_C_22 ICMF 2007, Leipzig, Germany, July 9 -13, 2007 rection is observed (see figure 4). The order of magnitude of the amplitude of the motion is about ±0.1 mm. This will be taken into account in the calculation of the uncertainties when studying the bubble's behavior. When looking at the fourier transform of the x-position of the axis of rotation, for the four runs, a peak appears in the spectrum at the rotation rate of the tank. This result is interesting to be connected with the oscillations of the bubble presented in section 5.

6 th International Conference on Multiphase Flow,
The third study of flow behavior was performed with one bubble present in the tank. The purpose was there to investigate if sometimes the bubble can perturb the flow so much that it feels back its own perturbation. In that case, this feedback of the perturbation makes the incoming flow on the bubble to be also modified. It is important to be able to discriminate these "perturbed" cases from the "unperturbed" ones while working on the values of the forces (see section 4). The study was done using PIV measurements in the flow surrounding the bubble to see where and when perturbations appear. A global view of the perturbed zone was sought. PIV measurements were here again performed with the fluorescent particles, the continuous laser and the high speed camera with the orange filter but with a standard objective (60 mm) and a frame rate of 900 images per second. The procedure is the following. PIV measurements were successively performed with the bubble stabilized in the laser sheet and without the bubble, keeping the same rotation rate. Then, the velocity field obtained from the run without bubble and averaged on the 2000 fields was substracted to the instantaneous fields with the bubble. This gives access to the way the bubble disturbs the basic solid rotation velocity field. Then, using a sliding averaging operation, the disturbed fields are averaged over 50 instantaneous fields. The obtained disturbed averaged fields are then visualized to see when the wake of the bubble modifies so much the reference flow that it feels it back. Examples are presented on figures (5), ( 6) and (7). Figure ( 5) presents an example of the resulting fields obtained for a small bubble (d ≈ 0.5 mm, Re ≈ 20). For this kind of bubbles, whatever the position of the bubble in the tank and thus whatever the Strouhal number the wake is so small that it does not perturb significantly the flow. Indeed, when looking at the 2000 disturbed averaged fields for such small bubbles, the center of the tank, here around X = 8.5 mm, Y = -0.5 mm, always presents velocity vectors that are practically zero. Figure ( 6) and ( 7)

Figure 5: A small bubble (d ≈ 0.5 mm, Re ≈ 20) and its wake. The center of the tank is around X = 8.5 mm, Y = -0.5 mm. The field is obtained using a sliding average over 50 instantaneous fields to which the basic solid rotation field has been substracted. The bubble is located where the large vectors are. The center of the flow appears as not perturbed by the presence of the bubble. In this case Sr -1 ≈ 6 -7.

deal with middle size bubbles ( d ≈ 0.9 mm, Re ≈ 80 for figure (6) and d ≈ 1 mm, Re ≈ 100 for figure ( 7)). For this kind of bubbles, three behaviors have been pointed out. First for large Strouhal numbers (eg) small distances to the center relatively to the diameter the wake perturbs the center of the reference flow and the bubble feels this perturbation. A coupling between the bubble and the reference flow arises and the system becomes different from the one that should be studied. This concerns Sr -1 6. Figure ( 6) is an illustration of such a behavior. The two images are two disturbed averaged fields for the same bubble during a run. The center of the tank is around X = 13.5 mm, Y = -0.5 mm. The comparison of both images show that when the bubble and its wake oscillate they induce fluid aspirations and forcings back in the zone of the center of the tank; zone that is close to the bubble. For 6

Sr -1 10 and the same kind of bubbles, an example is on figure (7). What can be observed is that even long and oscillating with the bubble, the wake of the bubble only induces very low secondary flows toward the center of the tank (X = 13.5 mm, Y = 1.5 mm) that seem to have a quasi-negligible back influence on the bubble. Thus, in this range the wake perturbs a little bit the center of the flow but it seems that the perturbation is very weak. However, at the present stage it is difficult to tell if such a weak perturbation still has a small influence on the measured forces or not. For this kind of bubbles the case 10 Sr -1 (bubbles far from the center) exhibits no coupling and no perturbation coming back onto the bubble. The incoming flow onto the bubble is a clean flow of solid body rotation. When the size of the bubble increases (Re 100), the three regions for the Strouhal number remain. In that case the perturbation of the center, when present is even stronger and a very large coupling can appear for Sr 6. An example of such a coupling Figure 6: A middle size bubble (d ≈ 0.9 mm, Re ≈ 80) and its wake at two different instants. The center of the tank is around X = 13.5 mm, Y = -0.5 mm. The field is obtained using a sliding average over 50 instantaneous fields to which the basic solid rotation field has been substracted. The bubble is located where the large vectors are. Comparing the two images it can be observed that the bubble's wake perturbs the center of the flow. The bubble feels that perturbation and its motion and behavior are modified. In this case Sr -1 ≈ 5 Figure 7: A middle size bubble (d ≈ 1 mm, Re ≈ 100) and its wake, at two different instants. The center of the tank is around X = 13.5 mm, Y = 1.5 mm. The field is obtained using a sliding average over 50 instantaneous fields to which the basic solid rotation field has been substracted. The bubble is located where the large vectors are. Comparing the two images it can be observed that the wake has only a very small influence on the center of the flow. The bubble in this case seems not to feel that perturbation. Sr -1 ≈ 7 8)). These vortices directly interact with the bubble. Nevertheless, as for smaller bubbles, for larger values of Sr -1 , the bubble here again doesn't feel any feedback of its perturbation. All these behaviors can be classified as follows. For bubbles with Re 60 -70, whatever the position of the bubble in the tank and thus the Strouhal number it does not feel its own perturbation. That is due to the smallness of the wake. For larger Reynolds numbers, when Sr -1 6, there is a clear coupling between the bubble and its own perturbation. The incoming flow on the bubble is no more a pure flow of solid body rotation. For 6

Sr -1 10, a slight influence of the perturbated zone on the bubble may occur and for 10 Sr -1 no perturbation is felt back by the bubble.

Description of the experiment with a bubble

The experiments are performed as follows. The tank is filled with demineralized water. When all the residual bubbles have been removed, a unique bubble is injected. The range of sizes of the bubbles is [0.2 mm; 2 mm]. After the injection has been performed, the tank is set in rotation. It is then necessary to wait for a few minutes for the flow and the bubble to reach their non-transient regime. Non-transient regime means for the fluid to be in solid body rotation. For the bubble it means to have reached its equilibrium position.

In practice the bubble never stabilizes completely. It oscillates around the equilibrium position even after a long time waiting. Nevertheless, the amplitudes are small. The order of magnitude is a few tenths of a millimeter.

When the bubble has reached its non-transient regime and oscillates around its equilibrium position, the measurements begin. The position of the bubble in the direction parallel to the axis of rotation Z is determined, using a laser pointer moving along a rod located above the tank. In practice, the laser beam is changed into a sheet using a small cylindrical lens. The laser sheet is oriented to be parallel to the faces of the cylinder. This sheet is translated manually till it intercepts the bubble. This gives the bubble's position Z. The bubble is filmed using the high-speed video camera aligned with the cylinder. Indeed the camera is mounted on a rail and has been very carefully aligned with the cylinder with micrometer screw translating devices. The rail is bound to the structure of the experiment to remain aligned. It is supported by an iron bar covered with rubber and fixed to the wall of the room to reduce vibrations. The frame rate is 100 frames per seconds and the recording lasts around 20 seconds. After a run, the 2000 images are then transferred on the computer and treated using a Matlab software. On each image the position of the bubble (r, θ), its size, its flatness and its applied forces and non-dimensional numbers are determined.

Characteristics of the measurement

In the present section, the difficulties inherent to the measurement are presented. It is followed by the description of the way the bubble characteristics are determined. The main difficulty with the present experiment is that the stabilization point of the bubbles is very close to the horizontal axis and then sin θ and θ are very small. Indeed, θ is of the order of a few radians. Thus, the measurement of θ requires a lot of precision. The three principal sources of uncertainty in the measurement of the parameters have been inventoried and quantified.

The first difficulty is to convert the pixels of the image into physical length units for the plane at position Z, where the bubble is stabilized. This is achieved as follows. An image of two circular test patterns, temporarily fixed on the front and back faces of the tank, is captured (see for example figure 9). This provides the ratios between pixels and centimeters for the two faces distant of 10 cm. Using the laser pointer sheet the Z position of the bubble has been determined, with a precision of ±1 mm. The ratio between pixels and centimeters at the location of the bubble is then obtained using a linear regression. The typical order of magnitude of the ratio between centimeters and pixels is: 220 pixels/cm for the front face and 130 pixels/cm for the back face.

The second point that needs attention is that despite all the care used to align the camera a small misalignment can Figure 9: Image of the tank with both circular test patterns put on the faces to determine the ratio between pixels and centimeters. The continuous line is on the test pattern of the front face, the dotted one is the one on the rear face. The space between two successive similar lines corresponds to 0.5 mm. remain. Its order of magnitude is a few pixels. So small it is, it must be corrected because for the bubbles that have their equilibrium position close to the horizontal axis, it can be of the same order of magnitude as the ∆y between the bubble and the horizontal axis. Because it was not possible to be more precise in the alignment it was decided to measure the shift between the axis of the tank and of the camera and to apply a correction to the results. The principle is as follows. First a circular sticker with a diameter of the order of 1 cm is put on the front face. Its motion is captured when the tank is rotating. The center of the circle described by the center of the sticker is determined. This gives the measured center of the front face. The same protocol is then performed with the back face. This provides a measurement of the shift between both measured centers and thus of the misalignment. As for the ratio between pixels and centimeters a linear regression is then used to determine the effective position of the center of the tank in the plane in which the bubble is stabilized. In the present measurements the typical shift between both centers is of the order of 3 pixels in x and 3 pixels in y. The precision of the measured shift is ±0.25 pixels.

The third and last aspect that need to be payed attention to are the vibrations of the camera. Indeed, even fixed on a rail itself attached to the experiment which is heavy, the camera is sensitive to vibrations of the working environment, such as ground vibrations. These vibrations can cause small instantaneous misalignments of the camera, which are source of noise on the results. This problem was partly removed by calculating the bubble position on each image relative to the instantaneous center of rotation seen by the camera. This center is given by the trajectory of a small sticker glued on the center of the front face of the tank. As the sticker could not be perfectly centered on the rotation axis, it describes each turn a small circle. The center of the circle accomplished during the N/2 images before and the N/2 images after the bubble image treated, N being the number of images for the tank to do a turn, is considered as the instantaneous center of rotation of the front face and used to calculate, after the Z correction, the bubble position. The precision on the determination of the center is estimated as ±1 pixel. During this procedure a fourier transform of the x-position of the center of the sticker is performed. The resulting peak gives the rotation rate of the tank ω with a precision of ±0.15 rad/s. This measurment is more precise than the one obtained with the opto-electronic sensor.

The treatment of the images with the Matlab software to determine the useful characteristics for the bubble is performed as follows. A first pass on all the 2000 images is done to determine the instantaneous positions of the center of the tank with the sliding technique as described before. Then, using the image with the test patterns the ratio pixel versus centimeters is determined for the front and back face. Knowing the position of the bubble in the tank determined with the laser sheet, the ratio is calculated for the bubble position. All the images are then treated a second time to determine the bubble characteristics. A mask is applied around the bubble, then a threshold is determined automatically and applied to the image to detect the bubble. The image is binarized and the size of the bubble, its position and its flatness are determined in pixels and then converted in real size. For all the studied bubbles the flatness is less than 1.1. Knowing the position of the center of the tank for each image, r and θ can be determined. The forces are then calculated using equations ( 2) and ( 3). During the image treatment, the uncertainties of the different parameters have been evaluated. d has a precision of ±1 pixel. As for the center of the tank, the precision of the bubble position is ±1 pixel. As a first approximation, this gives an uncertainty for C L of the order of 30% to 40% and 15% for C D . Calculating C D and C L can be done using the instantaneous values of the parameters and then averaging the coefficient over the 2000 images. It can also be calculated directly with the mean value of the parameters. It was checked that the values of the coefficient are the same to the order of our precision if calculated using the mean value of the parameters or if averaged afterwards.

Drag and lift forces

In the present section are presented the results for the drag and lift forces and the comparison to existing results.

Drag force

As usual, the drag coefficients are plotted as a function of the Reynolds number (see figure 10). The experimental data have been classified into three categories saying 4 ≤ Sr -1 < 6 (green stars), 6 ≤ Sr -1 < 10 (red x) and 10 ≤ Sr -1 (blue cross). Two curves are also plotted. The upper one is the drag for solid spheres [START_REF] Clift | Bubbles, Drops and Particles[END_REF]:

C D = 24 Re (1 + 0.15Re 0.687 ) (6)
The lower one is the one for clean bubbles [START_REF] Mei | A note on the history force on a spherical bubble at finite Reynolds number[END_REF]:

C D = 16 Re 1 + 8 Re + 1 2 (1 + 3.315Re -1/2 ) -1 (7)
Both curves have been obtained for bubbles in a uniform flow. As discussed in section 3.2 bubbles with 4 ≤ Sr -1 < 6 and Re 60 -70 are so close to the axis of rotation of the flow, that a significant coupling exists between the reference flow, the bubble and its wake. This modifies the incident flow + are bubbles with 10 ≤ Sr -1 , x are bubbles with 6 ≤ Sr -1 < 10, * are bubbles with 4 ≤ Sr -1 < 6, the plain line is the drag curve for solid spheres and the dashed line is that of clean bubbles.

arriving on the bubble and in that case the measurements cannot be considered as representative of the drag in a pure rotating flow. They are therefore disregarded. Nevertheless, it is interesting to note that coupling effects increase the drag coefficient. This is particularly visible for Re > 100 (green stars). In the range 10 ≤ Sr -1 (blue plus) there is no such two-way coupling and the incident solid rotation flow on the bubbles is not affected. The drag coefficient for these bubbles coincides rather well with the curve for solid spheres. Two main reasons can explain this trend. The first one is that the interface of the bubble is entirely contaminated. Such a possibility cannot be excluded, but is surprising given the care we have brought to work with clean water. We would expect that interfaces be weakly contaminated and the data to fall between the curve for solid sphere and clean bubble. The second reason for the data be higher than the curve for clean bubbles in uniform flow can be the effect of the shear. Indeed, [START_REF] Legendre | The lift force on a spherical bubble in a viscous linear shear flow[END_REF] performed numerical simulation in a linear shear flow for moderate to large Reynolds number showing that shear effects increased the drag coefficient, according to a relation in the form

C Dshear (Re, Sr) = C Dunif orm × (1 + 0.55Sr 2 ) (8)
A detailed inspection of our experimental points reveals that drag coefficient increases with the shear rate. This clearly appears for Re ≤ 60 -70 in the range 6 ≤ Sr -1 < 10 (red cross); 4 ≤ Sr -1 < 6 (green stars), where there is no two-way coupling (section 3.2) and the points are systematically above the solid drag curve. Interestingly, this increase with the dimensionless shear number Sr seems more pronounced than the increase predicted for the linear shear flow. We tried to fit our points using a relation similar to equation (8) and found a coefficient of the order of 5 instead of 0.55. If we correct the data to account for shear effects as it was done by Van Nierop et al. (2007) using this value of 5, we obtain drag coefficients which are slightly below the solid drag curve. However it is too early to conclude at this stage of the study and further developments are needed. The increase of drag with the shear is also visible for larger bubbles Re > 100; 6 ≤ Sr -1 < 10, but may also include in that case the effect of a slight coupling.

We have compared the present data to results obtained by other authors. Naciri (1992) (x) have drag coefficients that are slightly lower. It is not evident to understand the origin of these differences. Nevertheless, it can be mentioned at this stage that [START_REF] Naciri | Contribution à l'étude des forces exercées par un liquide sur une bulle de gaz: portance, masse ajoutée et interactions hydrodynamiques[END_REF] worked with larger bubbles than those presented in the other studies. Indeed his bubbles had typical sizes of a few millimeters, which could explain that they are less sensitive to contamination. Van Nierop (2003) have some dispersion in the values of the drag coefficient for bubbles in water. Hence it is difficult to perform a comparison with the present data for example as a function of the Strouhal number because of this dispersion. 4 ≤ Sr -1 < 6 correspond to a situation where the two-way coupling is significant and must not be considered as representative of the lift force in a pure solid body rotation. Here again we note that the coupling between the bubble and the reference flow tends to diminish the lift coefficient, this effect increasing as the bubble gets closer to the axis of rotation of the flow. In the range 10 ≤ Sr -1 no coupling occurs and lift coefficients collapse onto a single curve. This curve increases first rapidly with Re and then seems to reach an asymptotic level for Re > 100. This point still needs to be confirmed by additional measurements in the range 100 < Re < 300. However, the global trend suggests an asymptotic value of the order of unity which is higher than the 0.5 value predicted by [START_REF] Auton | The lift force on a spherical body in a rotational flow[END_REF]'potential theory. The reason for this difference remains unclear, but it must be kept in mind that this theory is valid for linear shear flow. Interestingly, the small bubbles (Re 60) have their lift coefficients on the same curve whatever the value of the dimensionless shear number Sr, thus indicating that the lift essentially depends on the Reynolds number over that range. On the opposite for larger bubbles (Re > 60 -70) in the range (6 ≤ Sr -1 < 10) and where coupling effects remain negligible, we see that an increase of the shear makes the lift coefficient slightly diminish. A more detailed analysis of the data is planned for the future.

Lift force

We have compared our results with the values of the lift coefficients found in the literature for the same range of flow parameters (see figure ( 13)). We have not retained for this comparison the study of [START_REF] Sridhar | Drag and lift forces on microscopic bubbles entrained by a vortex[END_REF] which concerns microscopic bubbles entrained by a vortex. [START_REF] Naciri | Contribution à l'étude des forces exercées par un liquide sur une bulle de gaz: portance, masse ajoutée et interactions hydrodynamiques[END_REF] results obtained with water/glycerin mixtures. The plain line is the curve obtained by [START_REF] Legendre | The lift force on a spherical bubble in a viscous linear shear flow[END_REF].

For Re > 5 and Sr ≤ 0.2, [START_REF] Legendre | The lift force on a spherical bubble in a viscous linear shear flow[END_REF] established numerically the following empirical correlation:

C L (Re) = 0.5 × 1 + 16Re -1 1 + 29Re -1 (9)
The range of applicability of this equation corresponds to the one of the present data. (2007). Although it is difficult to conclude, a possible reason for these could be that Naciri (1992) used larger bubbles (eg) bubbles of a few millimeters and that the behavior of such deforming bubbles is different.

Oscillations of the bubble

As mentioned before, the bubble never stabilizes on its equilibrium position. but it oscillates around it. The amplitude of the movements are of the order of a few tenths of a millimeter. A primary study shows qualitatively that different sources of oscillation are competing. Three kinds of frequencies are generally obtained, one related with the rotation rate of the tank, and sometimes its harmonics, one associated with a three-dimensional motion of the bubble and sometimes one related with an interaction between the vortex shedding and the bubble. An example of the fourier transform of the x position of the bubble is presented on figure (14). Indeed, when ICMF 2007, Leipzig, Germany, July 9 -13, 2007 coming to its equilibrium position. After this first phase, the bubble appears to be moving around its equilibrium position. During a first laps of time it moves with short movements (few tenths of a millimeter) in the plane in which it stabilized. In the spectrum the rotation rate of the tank and its harmonics are very present. When waiting more, the bubble begins to oscillate also in the third direction (parallel to the axis of rotation) and another peak (around a few hertz) appears while the previous ones can sometimes diminish. For certain kind of bubbles (mean-size bubbles far from the axis of rotation) also appears a frequency around 10 Hz. This frequency is of the order of magnitude of the frequency at which vortices are released from the bubble. It seems reasonable to believe that the presence of this frequency in the spectrum could be linked to an interaction between the vortex shedding and the bubble trajectory. In future work, we intend to investigate these phenomena and try to give a full explanation of the sources of excitement of the bubble and how it reacts to them. For what concerns the lift and drag coefficients it should be mentioned that whatever the "regime" of frequency in which the measurement is performed the equilibrium position is the same and so does the value of the forces.

Conclusion

The behavior of a single bubble included in a solid body rotation flow has been studied. The equilibrium position of the bubble has been measured for moderate to high Reynolds number, low to moderate dimensionless shear number Sr, and the drag and lift coefficients calculated from this position. To have reliable results an important effort was done to characterize the reference flow. Using PIV, the flow has been checked to have a linear velocity profile on the whole section of the tank. The small movements of the axis of rotation of the flow have also been studied and quantified. Because they are small, these movements appear as having no influence for the determination of the lift and drag coefficients. On the other hand the rotation rate of the tank appears in the frequencies of these movements and can be a source of excitation for the bubble. The possible coupling of the bubble, its wake and the solid rotating flow have been also investigated in detail with PIV. For Re 60 -70, the flow arriving on the bubble is not modified whatever the position of the bubble close to the axis of rotation and thus the Strouhal number Sr. This seems due to the fact that the wake is very thin in that case. For larger Reynolds numbers (Re 100), a significant coupling occurs when Sr -1 6 and this perturbs the flow arriving on the bubbles. For 6

Sr -1 10, the coupling is weak so that it does not influence significantly the incident flow on the bubbles and for 10 Sr -1 no perturbation is felt back by the bubble. The drag and lift coefficients obtained over the range of parameter where the incident flow on the bubble is not perturbed and can be considered as a pure solid body rotation exhibits interesting trends. Concerning the drag, the coefficients obtained are closed to the ones of solid spheres, probably because of a partial contamination of interfaces and increases significantly with the shear. This agrees with results found by Van Nierop et al. (2007). The lift force coefficients come in continuity with the val-ues obtained in glycerin by Van Nierop et al. (2007) at low Reynolds number and tend asymptotically to a value of order unity which is higher than the 0.5 value of [START_REF] Auton | The lift force on a spherical body in a rotational flow[END_REF]' potential theory for linear shear flow. This qualitatively agree with the measurements in water of Van Nierop et al. (2007) which are also higher than 0.5. Interestingly, the lift coefficient seems to be independent of Sr for Reynolds numbers below 60-70 and to slightly decrease with Sr for large bubbles having Reynolds number above 100. Because the bubble never stabilizes on its equilibrium position, its small movements have been studied showing the presence of different frequencies among which one outstanding an interaction of the bubble with its own wake. Future work will come to give explanations to these different points that remain at the moment effective but with a partial explanation.

Figure 2 :

 2 Figure 2: Photography of the experimental device showing the tank. In front of it is the high-speed camera. In the back the toothed belt and the opto-electronic sensor can be seen.

Figure 3 :

 3 Figure 3: An example of the velocity profiles obtained with the PIV measurements. Here, the velocity of the tank is 1.2 m/s . ment was not able to resolve the flow close to the side of the tank. Hence the values obtained on the sides (see figure (3))are false. To get the true velocity of the fluid near the tank, it is thus necessary to do an extrapolation of the data using a linear regression. As expected, the extrapoled velocity fits well with the velocity of the tank.To study the possible movements of the axis of rotation of the flow, a second different PIV campaign was done. Indeed, when the experiments are performed with bubbles, bubbles never stabilize completely and always oscillate with one frequency among others that is the rotation frequency of the tank (see section 5). The purpose was then to check if there was or not a precession of the axis of rotation of the fluid, which could make the bubble oscillate. The PIV measurements were done using a reduced field. The field size is 2 mm 2 . The particles were fluorescent polyamide spheres doped in Rhodamin B of size 10 µm (Dantec product). They absorbe in the green light and emit in the orange. The laser sheet was perpendicular to the axis of rotation as before. The laser was a Spectra Physics Millenia IIs continuous diode pumped (2W). The camera was a high-speed video camera (Phantom V4.3 black and white) with an orange filter mounted on it. The frame rate used was 200 frames per second. To reduce the field of view to the expected size an Optem Zoom 125C objective was used. For the PIV correlations to be possible in the 2 mm 2 field, a high concentration of seeding particles was necessary. These particles being expensive, the experiment was repeated only four times. The rotation speed of the tank was the same for the four runs. A small motion of the axis of rotation of the flow with a privileged vertical di-

Figure 4 :

 4 Figure 4: Colored 2d histogramm of the position of the axis of rotation of the flow for a run of 2000 images.

S1_Tue_C_226

  th International Conference on Multiphase Flow,ICMF 2007, Leipzig, Germany, July 9 -13, 2007

S1_Tue_C_226Figure 8 :

 8 Figure8: Long time exposure for a "large" bubble. In that case, Re > 100, Sr -1 < 6 and a strong coupling between the bubble and its perturbation occurs. time exposure for the camera. During a run, depending on the moment, one, two or three vortices can appear in the region of the center (see for example right side of figure (8)). These vortices directly interact with the bubble. Nevertheless, as for smaller bubbles, for larger values of Sr -1 , the bubble here again doesn't feel any feedback of its perturbation. All these behaviors can be classified as follows. For bubbles with Re 60 -70, whatever the position of the bubble in the tank and thus the Strouhal number it does not feel its own perturbation. That is due to the smallness of the wake. For larger Reynolds numbers, when Sr -1 6, there is a clear coupling between the bubble and its own perturbation. The incoming flow on the bubble is no more a pure flow of solid body rotation. For 6Sr -1 10, a slight influence of the perturbated zone on the bubble may occur and for 10 Sr -1 no perturbation is felt back by the bubble.

S1_Tue_C_226

  th International Conference on Multiphase Flow,ICMF 2007, Leipzig, Germany, July 9 -13, 2007

Figure 10 :

 10 Figure 10: Drag coefficient C D as a function of Reynolds number Re.+ are bubbles with 10 ≤ Sr -1 , x are bubbles with 6 ≤ Sr -1 < 10, * are bubbles with 4 ≤ Sr -1 < 6, the plain line is the drag curve for solid spheres and the dashed line is that of clean bubbles.

Figure 11 :

 11 Figure 11: Drag coefficient C D as a function of Reynolds number Re. + are data from the present study, + are Van Nierop (2003) results for experiments in water, + are Van Nierop et al. (2007) results for experiments in water/glycerin mixtures, with Re > 5 and x are Naciri (1992) results obtained with water/glycerin mixtures. The plain line is the drag curve for solid spheres and the dashed line is that of clean bubbles the glycerin/water data of Van Nierop et al. (2007) (+) seem to collapse onto a same curve. The data obtained in water by Van Nierop (2003) (+) and the data obtained by Naciri (1992) (x) have drag coefficients that are slightly lower. It is not evident to understand the origin of these differences. Nevertheless, it can be mentioned at this stage that[START_REF] Naciri | Contribution à l'étude des forces exercées par un liquide sur une bulle de gaz: portance, masse ajoutée et interactions hydrodynamiques[END_REF] worked with larger bubbles than those presented in the other studies. Indeed his bubbles had typical sizes of a few millimeters, which could explain that they are less sensitive to contamination.Van Nierop (2003) have some dispersion in the values of the drag coefficient for bubbles in water. Hence it is difficult to perform a comparison with the present data for example as a function of the Strouhal number because of this dispersion.

Figure 12 :

 12 Figure12: Lift coefficient C L as a function of Reynolds number Re. + are bubbles with 10 ≤ Sr -1 , x are bubbles with 6 ≤ Sr -1 < 10, * are bubbles with 4 ≤ Sr -1 < 6.

Figure 13 :

 13 Figure 13: Lift coefficient C L as a function of Reynolds number Re. + are data from the present study, + are Van Nierop et al. (2007) results for experiments in water, + are Van Nierop et al. (2007) results for experiments in water/glycerin mixtures, with Re > 5 and x are[START_REF] Naciri | Contribution à l'étude des forces exercées par un liquide sur une bulle de gaz: portance, masse ajoutée et interactions hydrodynamiques[END_REF] results obtained with water/glycerin mixtures. The plain line is the curve obtained by[START_REF] Legendre | The lift force on a spherical bubble in a viscous linear shear flow[END_REF].

Figure 14 :

 14 Figure14: Spectrum of the x-position of a bubble. The rotation rate of the tank was 2.5 turn per second. The first peak corresponds to the three-dimensional motion, the other one to the rotation rate of the tank. the experiment begins a first phase corresponds to the bubble

  (2007) results gives interesting features. The present "low" Reynolds values of the lift coefficient well coincide with the values obtained by these authors (green plus) and prolong their tendency in the intermediate range of Reynolds number 20 < Re < 70. This is all the most interesting that the fluid is different in the two studies. IndeedVan Nierop et al. (2007) used glycerin for this range of Reynolds number. The comparison with the values at higher Reynolds numbers gives rise to more questions. We see on the figure that there is a discrepancy between the values of the lift coefficient obtained byVan Nierop et al. (2007) in water and the present ones. No definitive explanation for the moment can be given. Referring toVan Nierop (2003) this discrepancy could originate from a problem of alignment mentioned by this author in his experiments with water, which seems plausible given the importance of alignment for the determination of the lift coefficient. Despite their data are subject to more dispersion than ours for this reason, it is worth noting that they globally tend to a value which is also higher than 0.5 at high Reynolds number. The other comparison that can be done is with the results of[START_REF] Naciri | Contribution à l'étude des forces exercées par un liquide sur une bulle de gaz: portance, masse ajoutée et interactions hydrodynamiques[END_REF]. Here again the values does not agree with the present values nor with the ones of Van Nierop et al.

[START_REF] Legendre | The lift force on a spherical bubble in a viscous linear shear flow[END_REF]

's curve also tends toward 0.5 at high Reynolds number. Logically it does not fit our data. The comparison with Van Nierop et al.

th International Conference on Multiphase Flow,ICMF 2007, Leipzig, Germany, July 9 -13, 2007

S1_Tue_C_22

6 th International Conference on Multiphase Flow, ICMF 2007, Leipzig, Germany, July 9 -13, 2007 Saffman, P.G., The lift force on a small sphere in a slow shear flow. Journal of Fluid Mechanics, Volume 22, 385 -400 (1965), Corrigendum: Journal of Fluid Mechanics, Volume 31, 624 (1968) van Nierop, E.A., Towards controlling bubbles -understanding lift, Master's thesis (2003) van Nierop, E.A., Luther, S., Bluemink, J.J., Magnaudet, J., Prosperetti, A.,Lohse D., Drag and lift forces on bubbles in a rotating flow. Journal of Fluid Mechanics, Volume 571, 439 -454 (2007)


Matthew Ralston
email: mralston@ryerson.ca

Dave Mason
email: dmason@ryerson.ca

IWST

Keywords:

Tail call elimination is a common optimization, particularly for functional languages, where it is a semantic requirement. The value is less obvious in an Object-Oriented language such as Smalltalk. In this paper we show that it has a significant execution-time improvement for typical workloads. It also has significant memory savings for certain programs, and enables novel (to Smalltalk) programming styles.

Motivation and State of the Art

The term "tail call" comes originally from the functional programming world. It refers to a function call that is the last thing that another function does before returning the result of that call.

In object-oriented language terms it is a message send where the result of the send is returned as the result of the sending method. This call or send is said to be in "tail position".

In pure functional languages, the recognition of tail calls is critical, since the looping idiom is manifested by tail-recursive calls. If the tail calls were not to be removed, the stack would quickly grow to unacceptable size.

Tail call elimination has not previously been recognized as an important optimization for object-oriented languages, since they invariably have a natural iterative structure available to the programmer. However, space is not the only saving of tail call elimination. If creation of new activation records can be avoided, the instructions required to create them can be avoided, and the [Copyright notice will appear here once 'preprint' option is removed.] stack will become more localized -improving cache performance.

Tail calls are actually quite common in objectoriented programming. They are heavily used in any double-dispatch methods, in particular the visitor pattern. Figure 1 arithmetic operations, is a message send in Smalltalk, tail calls only account for just over 6% of total static message sends. However they are more common in the Squeak compiler, where the visitor pattern is common. 1 While this may not seem particularly hopeful as a source of optimization, those tail-calls are often in high-frequency code. Figure 2 shows that during image startup 2 or recompile-all, the dynamic frequency is in the range of 1/6 to 1/5 of all calls. With these fre- quencies, even a 30% improvement in execution time for tail-calls would produce valuable speed-ups, which we describe in §4.

Contributions and outline

We performed a series of experiments on Squeak 6 which, like Pharo and Cuis, runs on the OpenSmalltalk Virtual Machine -an open source virtual machine for Smalltalk. 3 OpenSmalltalk uses features such as context-to-stack mapping, inline message caching, and JIT compilation for efficient message sending. We implemented tail-call elimination for the Stack Interpreter and Cog Just-In-Time (JIT) native code generator. We observed significant improvement in most of our experiments when we eliminated tail calls.

In the remainder of this paper, we first discuss tail calls in greater depth ( §2). Then we look at our implementations for the stack interpreter and the Cog JIT ( §3). Then we show preliminary results of the optimization ( §4). Then we discuss some of the related work on tail-call elimination ( §5). Lastly we conclude the paper and sketch some future work ( §6).

Tail Calls

For discussion purposes, we will consider the three methods in figure 3.

The first method is methodA:, which simply takes an argument, and sends the message methodB: with that argument to itself. The result is not explicitly returned; in Smalltalk syntax, a reference to self is returned implicity in this case. This means that methodA: does not contain a "tail call'. methodC: also does not contain a "tail call" because there is an assignment between the send and the return. 4 methodB: does contain a "tail call" since the result of the send is immediately returned from the method.

This becomes very clear when looking at the bytecodes produced by the compiler for these methods, in figure 4. Here a tail call is recognizable by a send followed immediately by a returnTop. It is clear that methodA: is not a tail call -this method is just for producing side effects. The return result of the send to methodB: is discarded before returning self.

The next method is methodB:, which takes one argument, and sends a message to methodC: with its own argument, and then returns the result. Looking at the bytecode, it is obvious that methodB: has a 3 tail call, as it performs a send of methodC; and then returns the top of the stack.

Finally, in methodC:, a temporary variable is created and assigned the value of the argument + 1. Then the temporary variable is returned. Looking at the bytecode, it's clear that methodC: does not perform a tail call. The result of the send to + is used after the send for other operations before returning the top of the stack. Clearly the pop followed by the push could be removed, which would make this a tail call (and would be a worthwhile optimization regardless), but as the code is show, this is not a tail call.

Let's now look at the call stack and the execution variables. Since the point of interest here ultimately is the tail call in methodB:, the activation of methodA: will be skipped and the details of methodA:'s frame will be ignored. Figure 5 shows the state of the stack just before the return from methodC: for the normal stack interpreter.

When preforming tail call elimination, the stack frame for methodB: gets reused by the call and execution of methoC:. Figure 6 shows the state of the stack just before the return from methodC: for the stack interpreter with tail call elimination.

Implementations

The essential approach to tail call elimination is that the current context/stack-frame will be re-used by the 1. adjusting the frame to the appropriate size -removing local variables;

2. putting the parameters in the right place -the called method may have more, fewer, or the same number of parameters;

3. jumping to the target method -rather than calling.

The complexity for Smalltalk is in that 3 rd item: finding the right target method. Because of dynamic dispatch, the method needs to be looked up in the methodDictionary of the class of the target object.

A return from a method that was invoked by a tail call is no different from any other. Because of the way the call was set up, the return bypasses the caller and goes directly to its caller.

Stack Interpreter

We explored many clever approaches to recognizing tail calls for the Stack Interpreter, including creating new bytecodes for tail calls. However in the end, nothing worked better than the simplest approach of:

• for each message send type, look at the next instruction;

• if it is a returnTop, jump to the target method

• otherwise, handle the send normally.

Cog JIT

The first time a method send is executed, the target method is cached and the send and target method are interpreted. The second time the send will be turned into machine code. The machine code loads the class of the target option into a register and calls the expected target method. The method checks for a match of the register with the class known to be associated with associated with the method. If they match, this is a monomorphic call, and the method is executed. It they don't then a couple different approaches are used to look up the correct target -either polymorphic (for less than, e.g., 6 possible classes) or megamophic (for an unbounded number of possible classes).

Our current implementation only handles the monomorphic case. If the class doesn't match, we fall back to the non-tail-call code and let it handle the polymophic or megamorphic cases.

Because "tail-call"-ness is a property of the sender of a message, rather than the receiver, when we jump to the target, we use an alternate entry-point of the method, bypassing some of the code.

The pre-existing code to handle the polymorphic and megamorphic dispatch depends on a pointer back to the call site (stored on the stack by the call instruction. There are two ways to do this:

1. We could have either left the call in, but called an alternative entry point for tail calls which would discard the return address if not needed. This could get the space-saving of tail-call, but would have limited speed-up potential.

2. We could put the checking code for the matching class at the call site, and if that fails, fall back to the pre-existing code. We chose this approach.

The JITed code goes into a fixed buffer so that generated code doesn't get moved. Tail-call elimination puts generates longer code, which puts pressure on this buffer. Unfortunately simply enlarging this buffer doesn't completely resolve this pressure.

Debugging

The only possible downside to tail-call elimination is that stack frames may not exist, so that when a debugger window is opened, the complete set of methods that was traversed to get to the execution point may not be available. Once in the debugger, there is no issue, as stepping through the debugger does not recognize tail call elimination. In the other cases, a simple flag could be set that caused the interpreter or JIT to simply bypass checking for tail calls. SInce, excluding infinite or near-infinite loops, the semantics of a program don't change with tail-call elimination, debugging should not be an issue.

Results

We ran a sequence of tail recursive tests (microbenchmarks), and a couple of real world tests. For each we show Stack Interpreter results and Cog JIT results. Each test result section will be broken down into execution time and memory, and will be followed with a discussion of the results. All memory results reflect total image memory -for the micro-benchmarks at the deepest recursive level; for the real world tests periodic samples.

In the descriptions of the tests, iterations refers to the number of times an individual calculation is run before collecting a measurement, and runs refers to the number of times a test is run, with each run corresponding to a measurement. Mean results of the measurements are presented in graphical form. In addition, the mean, standard deviation, and median for each test are presented in a table. Percentage improvement for tail call eliminating implementations is also included, with the column headers %Imp for the mean improvement, and %SD for the percentage of uncertainty in the improvement. The formulas to calculate the percentage improvement and the uncertainty in the improvement are:

imp ab = mean b -mean a mean b * 100 (1)
unc ab = σ 2 a + σ 2 b mean b * 100 (2)
where:

σ a =

Memory Usage

For this test, memory usage was measured in the base case when calculating the Fibonacci sequence for 1000. Measurements were taken for 1000 runs -see figure 8 for the results. Memory usage across all implementations is very similar across the different runs, with a slight increase in usage for the tail call eliminating implementation of the Stack Interpreter.

Fibonacci 10000 Tests

The Fibonacci 10000 tests use the calculation of the Fibonacci sequence for 10000.

Execution Time

For execution time, each test consists of 100 iterations of calculating the Fibonacci sequence for 10000. The milliseconds to run each test was collected for 25 runs. See figure 9 for the results. Execution time shows a significant difference, with large reductions in execution time indicated for both implementations of tail call elimination.

Memory Usage

For this test, memory usage was again measured in the base case when calculating the Fibonacci sequence for 10000. Measurements were taken for 250 runs -see figure 10 for the results. Memory usage also shows a significant difference between implementations with tail call elimination and implementations without tail call elimination. This demonstrates a significant decrease in memory usage for both tail call eliminating implementations.

WhileTrue 10000 Tests

The WhileTrue 10000 test again uses the tail recursive implementation of whileTrue: to repeatedly execute a block 10000 times.

Execution Time

In the final tail recursive test, execution time for this test is measured by running the whiletrue loop with a value of 10000, and measuring execution time for 1000 iterations. This test is repeated for 25 runs and results are presented in figure 11.

The execution results for this test is also interestingboth implementations show a large reduction in execution time when using tail call elimination, particularly for the Cog implementation. They are not as fast as the normal, in-lined, version of whileTrue: because it is still forced to send value to the blocks, however it may be fast enough to encourage developers to create their own looping strutures that provide better semantics for their application.

Memory usage has similar characteristics to that shown for the other recursive examples, so we have omitted the data here.

Compile All Test

The compile all test calls the recompileAll method on the Compiler object and recompiles every method in the Smalltalk image.

Compiler>>recompileAll

Smalltalk allClassesAndTraits do:

[: classOrTrait | classOrTrait compileAll] displayingProgress: [: classOrTrait | 'Recompiling ', classOrTrait]

Execution Time

To determine execution time, the method is run 10 times and the time in milliseconds collected for each run. The results are displayed in figure 12.

Both implementations show an improvement in overall execution time when using tail call elimination. The Stack Interpreter implementation's execution time shows a 5.0±1.7% improvement. The Cog VM implementation shows less of an improvement -a 3.4±0.9% improvement to mean execution time. While this improvement is small, the results are tightly clustered enough that this improvement is still several standard deviations away from the non-tail-call-eliminating version of Cog.

Memory Usage

For the memory usage tests for the Compiler tests, a measurement of memory usage is taken after compiling each class. See figure 13 for the results. In general, the results seen are not particularly different from one another, or even particularly different between the Stack Interpreter and the Cog Interpreter, with minor increases in memory usage being registered that fall well below one standard deviation.

Execution Time

For the execution time for the windows test, the method is run 10 times and the time in milliseconds collected for each run. The results are displayed in figure 14

Memory Usage

The next results to show are the memory usage tests for the Windows tests. A measurement of memory usage is taken after opening all windows, and again after closing all windows. See figure 15 for the results. The results here are not particularly interesting, with tests indicating decreases in memory usage for both tail call eliminating versions.

State of the Art

Tail Call Semantics

Most of the work with tail calls has been to support tail recursion for semantic reasons, without any reference to performance improvement. In pure functional languages like Haskell and Erlang/Elixir looping constructs make little sense -since there is no mutation and limited side effecting code. For these languagues, and other mostly-functional languages like Scheme [START_REF]The Revised6 Report on the Algorithmic Language Scheme[END_REF], tail-call elimination is part of the definition. Without this, idiomatic tail-recursion would consume excessive memory. Where the language system is an interpreter, or compiles to machine code or C-(see below), this is not particularly difficult to achieve -simply rearrange the parameters (whether stack or registers) and jump to the target..

Survey of Tail calls in languages

Scheme, a dialect of Lisp, is particularly noteworthy in tail call elimination research, as general tail call elim-ination was first presented as part of the development of the Scheme language. Scheme requires implementations to be properly tail-recursive as part of its specification [START_REF]The Revised6 Report on the Algorithmic Language Scheme[END_REF]. The definition of properly tail-recursive as presented in the specification encompasses all tail calls as well [START_REF] William | Proper Tail Recursion and Space Efficiency[END_REF].

Javascript is an implementation of the ECMAScript specification. The ECMAScript 6, or 2015, specification introduced proper tail call elimination into the specification when using strict mode [START_REF]ECMAScript 2015 Language Specification[END_REF]. The language definition defines what tail calls are considered and an abstract operation is provided which handles the tail call. However, support at the time of this writing is limited, with Safari/Webkit being the most notable inclusion [START_REF]ECMAScript 6 compatibility table[END_REF].

Python explicitly declines to support any form tail call elimination -this is by design for several reasons discussed in the context of tail recursion elimination [START_REF] Van Rossum | Tail Recursion Elimination[END_REF] even optionally. First, as tail recursion elimination removes stack frames, stack traces will not have the eliminated stack frames. This will make debugging more difficult. Second, if tail recursion elimination is introduced as a choice for implementers, programs may be written that rely on the presence of tail recursion elimination and not run on implementations that choose not to implement it. Third, Python also allows functions to be rebound at runtime, so implementing tail recursion may be difficult to accommodate in all cases.

Compilation targets supporting tail call elimination

Steele presented tail call elimination implemented as a compiler optimization of machine code while discussing the cost of procedure calls compared to goto statements [START_REF] Lewis | Debunking the "Expensive Procedure Call"; Myth or, Procedure Call Implementations Considered Harmful or, LAMBDA: The Ultimate GOTO[END_REF]. Steele was demonstrating several points in comparing procedure calls to goto statements in order to show that procedure calls were not necessarily too expensive and not expressive enough compared to goto statements. When demonstrating cost, a simple Lisp method was shown compiled to a machine language with a small set of instructions: JUMP, PUSHJ, and POPJ. JUMP jumps to an address, PUSHJ pushes a location onto a call stack and then jumps to an address, and POPJ pops a location off of a call stack and jumps to that location. The machine code representation of a procedure call is shown to be a PUSHJ operation in that it pushes the current instruction and then jumps.

The machine code representation of a return at the end of the procedure is shown to be a POPJ operation -it pops the previous address off the call stack and jumps. Steele shows that the final procedure call in the procedure can actually simply be executed as a JUMP without pushing the address (with a PUSHJ) and without needing the POPJ instruction for the return. Procedure calls can be optimized in this way within the branches of conditionals, looping constructs and the last component of a block, amongst others. Steele recognized this as a universal technique for optimizing procedure calls as opposed to tail recursive specific optimization done in earlier work.

Hanson builds on Steele's work presenting a technique for compiling tail-recursive languages using stack allocation [START_REF] Hanson | Efficient Stack Allocation for Tailrecursive Languages[END_REF].

Kelsey presents several methods for implementing proper tail recursion in a stack-based interpreter [START_REF] Kelsey | Tail-Recursive Stack Disciplines for an Interpreter[END_REF]. Kelsey first presents the issue as to why a traditional call stack doesn't provide proper tail recursion. As discussed elsewhere, when a function calls another function in tail position, the environment (variables, access link) for the calling function is left on the stack despite never needing to be referenced again. Kelsey then considers three general approaches to dealing with this issue. The first is to allocate all environments to a heap, and then later garbage collect any unused environments. The second is to overwrite the existing environment with the new environment, replacing existing arguments with new arguments. Third, the stack could be allowed to fill with environments, and then later be garbage collected. Three garbage collection strategies for the stack were looked at as well -compacting the existing stack, copying the stack to a new stack and copying it to a heap. Looking at the three different approaches for im-plementing tail recursion, as well as not using a stack at all, Kelsey looked at the costs of making continuations, making procedure calls and garbage collection. Kelsey found that the second approach worked best in general for languages except Scheme.

Assembler code can, of course, support tail call elimination, but compiler developers usually want a more portable target.

Peyton Jones, Ramsey and Reig designed an intermediate assembly language named C-that provided tail call elimination [START_REF] Simon | C-: A Portable Assembly Language That Supports Garbage Collection[END_REF]. The motivation for writing this language was to produce a portable high quality assembly language that other languages could target. The authors reject C as an intermediate language for various reasons -relevant to here is the lack of easy implementation of tail call elimination. In C-, tail calls are treated as jumps from which control does not return. An implementation is required to reorganize the caller's stack frame before the jump.

The LLVM compiler infrastructure, which has become the portable target of choice for compilers such as the clang C compiler, has optional tail call elimination depending on the calling convention of the caller and the callee (typically preferring calling conventions where arguments are passed in registers). Tail call elimination is implemented by having the callee reuse the stack of the caller for calls in tail position. When the callee has more arguments than the caller, the convention is that the callee pops the arguments [START_REF]LLVM Language Reference Manual[END_REF].

The Common Language Runtime, or CLR, is Microsoft's virtual machine for .NET applications programmed in languages such as C# and F#. The specification for the CLR is laid out in the Common Language Infrastructure (CLI) specification and supports a specific tail prefix to call instructions -this indicates that the stack frame of the current method can be eliminated before the call is executed [START_REF]Standard ECMA-335 Common Language Infrastructure (CLI)[END_REF]. Implementations are only required to honor the tail prefix for call instructions for which the targets are known at compile time. F# uses the tail call capabilities laid out in the CLI for tail-recursive calls, but does not perform general tail call elimination [START_REF]Tail calls in F#[END_REF]. The Roslyn compiler for C#, however, never emits the tail instruction [START_REF]ProposalSupport tail recursion #1235[END_REF]. Regardless of whether the individual languages emit the tail instruction, the JIT compiler for CLR on AMD64 platforms can opportunistically eliminate tail calls [START_REF]JIT Compiler Structure[END_REF].

Other compilation targets

C and the JVM are the two most popular targets for compilers. Unfortunately, neither support tail-call elimination.

The Java Virtual Machine, or JVM, is the specification for virtual machines to run the Java programming language, as well as numerous other languages that target the JVM. Tail call elimination was originally not included as part of the JVM due to security methods that relied on counting stack frames -as tail call elimination may change the number of frames, this security implementation prevented tail call elimination [START_REF] Clojuretv | Stewardship: the Sobering Parts[END_REF]. Clements and Felleisen presented an abstract machine with general tail call elimination that also has security stack inspection, which they claim invalidates the belief that tail call elimination and stack inspection are incompatible [START_REF] Clements | A Tailrecursive Machine with Stack Inspection[END_REF]. Subsequently this security implementation has been replaced with something more robust, tail call elimination has yet to be implemented. This creates a problem for functional languages which rely on tail call elimination for, at the very least, tail recursive calls to implement looping in a functional paradigm. The approach taken by some languages is to add special syntax to indicate tail recursive calls to the compiler. Examples of languages designed for the JVM use this approach include Clojure [START_REF]The Clojure Programming Language[END_REF], Scala [START_REF]The Scala Programming Language[END_REF], and Kotlin [START_REF] Kotlin | [END_REF].

The two basic approaches are:

1. Only support tail calls for directly self-recursive functions (or method). This approach essentially translates the recursion into a loop within the function, with the tail calls becoming jumps. While this sometimes meets the language requirements, it is not a complete solution and misses many optimization opportunities where tail-calls exist in OO code.

Benton, Kennedy, and Russell presented a compiler for Standard ML to Java bytecode which, amongst other things, implemented tail recursion elimination [START_REF] Benton | Compiling Standard ML to Java Bytecodes[END_REF]. The compiler converts tail recursive calls into goto instructions, but does not perform general tail call elimination, as the authors believed that general tail call elimination would be added to JVMs (as mentioned before, this has yet to happen).

Bothner presented a compiler for dynamic languages such as Scheme on the JVM, based on the Kawa Scheme interpreter [START_REF] Bothner | Kawa: Compiling Dynamic Languages to the Java VM[END_REF]. The implementation that the author presented supported almost all features of Scheme at the time, but only handles self-recursive tail calls.

2. Use a trampoline. This approach monitors the depth of the call stack 5 , and when it gets too deep, it throws control back to a loop in the outer function of the program, which then resumes calling at the interrupted point. This preserves semantics, but can have a significant amount of overhead.

Tauber et al. presented FCore, which is a JVM implementation of System F, a typed lambda calculus, that has full tail call elimination [START_REF] Tauber | Memory-Efficient tail calls in the JVM with imperative functional objects[END_REF]. The authors discard two typical approaches on how to represent functions: (a) representing functions as Java methods has limitations as JVM methods don't support currying; (b) representing functions as Java objects, which languages like Scala and Clojure use, allows for more flexibility. Functions as objects (FAO) can be represented as a FAO interface, with an apply method that takes an argument. Neither option provided a good solution to the problem of general tail call elimination. The authors presented a different approach to representing first class functions called imperative function objects (IFO). IFOs are represented as an abstract class with argument and result fields, and an apply function. This is distinct from the previous approach for representing functions as objects in that setting an argument and invoking a function are two different steps. In tail calls, the IFO has its arguments set, but invocation is delayedinstead, an auxillary structure saves the IFO. The saved IFO is executed at the original call site, looping until the auxillary structure is null.

Conclusion and Future Work

We extended the OpenSmalltalk Stack Interpreter and the Cog JIT code generator to recognize monomophic tail-calls and eliminate them. This can produce dramatic space-saving and moderate execution-time improvements for particular applications without negatively affecting other applications. Based on our preliminary research, it appears this would be a worthwhile improvement to the OpenSmalltalk VM.

The next step is to extend the handling of tail calls to include polymorphic sends. Megamophic sends are rare and would probably not benefit significantly from this optimization.

Once the optimization is part of the VM, the compiler should be tweaked to recognize patterns of hidden tail calls, such as returning the result of an ifTrue:ifFalse: message send. 5

Sometimes only to a depth of 1

Tail-call elimination 10 2019/6/25

Figure 2 .

 2 Figure 2. Dynamic Tail Call Counts

Figure 3 .

 3 Figure 3. Three example methods

Figure 4 .

 4 Figure 4. Bytecode for the methods in figure 3

Figure 6 .

 6 Figure 6. Prior to return in methodC: with tail-call elimination

  standard deviation of tail call eliminating version σ b = standard deviation of non tail call eliminating version mean b = mean of non tail call eliminating version mean a = mean of tail call eliminating version imp a b = percentage of difference of a relative to b unc a b = percentage of uncertainty in difference from a relative to b 4.1 Fibonacci 1000 Tests The Fibonacci 1000 tests use the calculation of the Fibonacci sequence for 1000. Here is a tail recursive implementation of the calculation of a Fibonacci sequence number. ExpTestSuite class>>fibonacci: n ↑self fibonacci: n a: 0 b: 1. ExpTestSuite class>>fibonacci: n a: a b: b (n = 0) ifTrue:[↑a]. (n = 1) ifTrue:[↑b]. ↑self fibonacci: n -1 a: b b: a+b

  shows the static frequency of tail calls in a Squeak 6 image. Because every operation, including

	Platform Packages Tail Calls	Total	Percentage
	Squeak -All	25162	407971	6.17
	Squeak -Compiler	863	8747	9.87
	Figure 1. Static Tail Call Counts

Tail-call elimination

2019/6/25


Guillaume Monneret

Morgane Gossez

Fabienne Venet

Sepsis in PD-1 light

Increasing evidence suggests that after the first pro-inflammatory hours, sepsis is characterized by the occurrence of severe immunosuppression. Several mechanisms have been reported to participate in sepsis-induced immune alterations affecting both innate and adaptive immunity. Of these, the concept of 'cell exhaustion' has gained a lot of interest because some parallels can be drawn with the cancer field in which immunostimulation approaches through blocking immune checkpoints currently obtain remarkable success. Herein, perspectives regarding co-inhibitory receptors' contribution to lymphocyte exhaustion in sepsis will be discussed in the context of a recently published study investigating the potential of PD-1 molecule expression (i.e. PD-1 on lymphocytes, PD-L1 on monocytes) to predict mortality in septic shock patients.

The work by Shao et al. [START_REF] Shao | Monocyte programmed death ligand-1 expression after 3-4 days of sepsis is associated with risk stratification and mortality in septic patients: a prospective cohort study[END_REF] provides further insights regarding the potential of Programmed Death-1 (PD-1)-related molecule expression to predict mortality in septic shock patients. These immune checkpoint molecules constitute a system of negative regulators involved in controlling T-cell responses. Co-ligation of TCR with PD-1 molecules induces an inhibitory signal in T cells characterized by cell cycle arrest, inability to proliferate and reduced cytokine synthesis (IFN-γ and/or IL-2). This system is composed of PD-1 (CD279) and its two ligands, PD-L1 (B7-H1, CD274) and PD-L2 (B7-DC, CD273). Viruses and tumour cells take advantage of this pathway to escape the host's immune defences. In sepsis, pioneering work by Pr Ayala's group published in 2009 * Correspondence: guillaume.monneret@chu-lyon.fr reported that PD-1 knockout mice exhibited greater capacity to clear bacteria and lower mortality after experimental sepsis [START_REF] Huang | PD-1 expression by macrophages plays a pathologic role in altering microbial clearance and the innate inflammatory response to sepsis[END_REF]. Since this report, the implication of PD-1 molecules in sepsis-induced immunosuppression has been largely demonstrated both in experimental and clinical studies.

In septic mice, administration of anti-PD1/anti-PD-L1 antibodies enhanced bacterial clearance by preventing lymphocyte depletion and alterations [START_REF] Zhang | PD-L1 blockade improves survival in experimental sepsis by inhibiting lymphocyte apoptosis and reversing monocyte dysfunction[END_REF][START_REF] Chang | Blockade of the negative co-stimulatory molecules PD-1 and CTLA-4 improves survival in primary and secondary fungal sepsis[END_REF]. In a two-hit model nicely mimicking the occurrence of nosocomial infection (sepsis + secondary fungal infection), those antibodies significantly improved survival [START_REF] Chang | Blockade of the negative co-stimulatory molecules PD-1 and CTLA-4 improves survival in primary and secondary fungal sepsis[END_REF]. In septic patients, several groups reported increased PD-1 expression on lymphocytes and monocytes [START_REF] Zhang | Upregulation of programmed death-1 on T cells and programmed death ligand-1 on monocytes in septic shock patients[END_REF][START_REF] Guignant | Programmed death-1 levels correlate with increased mortality, nosocomial infection and immune dysfunctions in septic shock patients[END_REF][START_REF] Boomer | A prospective analysis of lymphocyte phenotype and function over the course of acute sepsis[END_REF][START_REF] Boomer | Immunosuppression in patients who die of sepsis and multiple organ failure[END_REF]. Depending on studies, this overexpression was regularly observed to be associated with increased risk of nosocomial infections and mortality. Of note, other co-inhibitory receptors (BTLA, CTLA-4, TIM-3, LAG-3) are also overexpressed in sepsis. Along with altered functional responses (proliferation/IFN-γ production), this depicts a full picture of sepsis-induced lymphocyte exhaustion. Importantly, those results obtained in circulating blood cells were confirmed locally in organs (lung and spleen), illustrating this overexpression is a severe and profound mechanism [START_REF] Boomer | Immunosuppression in patients who die of sepsis and multiple organ failure[END_REF]. The magnitude of this immunosuppression is also exemplified by patients' difficulty to fight the primary bacterial infection, decreased resistance to secondary nosocomial infections and reactivation of viral infections [START_REF] Hotchkiss | Sepsis-induced immunosuppression: from cellular dysfunctions to immunotherapy[END_REF]. Noteworthy, the implication of PD-1 molecules was recently reported in Ebola disease pathophysiology (which shares many clinical similarities with septic shock). While every Ebola-infected patient showed massive T-cell activation irrespective of outcome, the increased expression of these immune checkpoint molecules marked fatal evolution in some patients and correlated with high viraemia [START_REF] Ruibal | Unique human immune signature of Ebola virus disease in Guinea[END_REF]. The authors hypothesized that these inhibitory molecules inhibit T-cell functions leading to poor viral clearance-a similar consequence to those observed during sepsis-induced immunosuppression.

Shao et al.'s study [START_REF] Shao | Monocyte programmed death ligand-1 expression after 3-4 days of sepsis is associated with risk stratification and mortality in septic patients: a prospective cohort study[END_REF] agrees with this body of literature and provides two important novel aspects. Firstly, to our knowledge, this study represents the first description of a PD1 molecule, namely PD-L1, as an independent predictor of mortality in a multivariate analysis. Indeed, a combined score including the SAPS II score and PD-L1 expression provided good prognostic performances with an area under the curve in ROC analysis of 0.88. This illustrates the weight of initial severity and immunosuppression in sepsis. Secondly, it highlights the importance of monocytes in the PD-1 system and more broadly in sepsis-induced immune alterations. Indeed, the best result for predicting mortality is not obtained with PD-1-related molecule expressions on lymphocytes but rather with PD-L1 expression on monocytes. This again places monocytes at the centre of the pathophysiological game. Correlations between increased monocyte PD-L1 expression and decreased expression of HLA-DR or in-vitro TNF release-both typical markers of monocyte alterations-would thus have been interesting to support this hypothesis. In line with this, Shindo et al. [START_REF] Shindo | Interleukin-7 and anti-programmed cell death 1 antibody have differing effects to reverse sepsis-induced immunosuppression[END_REF] reported that anti-PD-1 antibody treatment had a positive effect on MHC class II molecule expression on macrophages and dendritic cells. Thus, the real importance of the PD-1 system on myeloid cells deserves further investigation.

Importantly, sepsis-induced impaired immune function is reversible and it remains possible to rejuvenate exhausted lymphocytes [START_REF] Venet | IL-7 restores lymphocyte functions in septic patients[END_REF]. Among molecules able to participate in battling sepsis-induced immunosuppression, anti-PD-1/anti-PD-L1 antibodies thus appear as plausible candidates. In septic patients' cells, ex-vivo blockade of the PD-1 system restored immune functions [START_REF] Chang | Targeting the programmed cell death 1: programmed cell death ligand 1 pathway reverses T cell exhaustion in patients with sepsis[END_REF] while these agents currently provide excellent results in cancer therapy, in which they boost immune functions in adjunction to classical therapies. Nevertheless, this approach deserves to be envisaged with caution. Indeed, PD-1-related molecules are also involved in the tolerance phenomenon and belong to the normal process of T-cell differentiation/maturation and activation. In other words, PD-1 expression is not always a sign of T-cell alteration and does not necessarily mark reduced T-cell functions and exhaustion [START_REF] Marraco | Inhibitory receptors beyond T cell exhaustion[END_REF]. By unbalancing the immune system, immune checkpoint blockade thus favours the development of various autoimmune manifestations [START_REF] Michot | Immune-related adverse events with immune checkpoint blockade: a comprehensive review[END_REF]. As a consequence, one important issue if we are to give anti-PD-L1 therapy to septic patients is to identify the right patient that could benefit from such therapy because it is unlikely, due to wellestablished heterogeneity of septic patients, that blocking a given immune checkpoint will be a magic bullet for all. Thus, robust standardized tools for patients' stratification are highly desirable. In that sense, the work of Shao et al. [START_REF] Shao | Monocyte programmed death ligand-1 expression after 3-4 days of sepsis is associated with risk stratification and mortality in septic patients: a prospective cohort study[END_REF] contributes to a better knowledge of PD-L1 expression as a potential biomarker.

1 Hospices

 1 Civils de Lyon, Immunology Laboratory, Hôpital E. Herriot, 5, place d'Arsonval, 69437, Lyon, Cedex 03, France 2 EA 7426 PI3 (Pathophysiology of Injury-induced Immunosuppression), Hospices Civils de Lyon/Université Claude Bernard Lyon 1/bioMérieux, Hôpital E. Herriot, 5, place d'Arsonval, 69437, Lyon, Cedex 03, France See related research by Shao et al., http://ccforum.biomedcentral.com/articles/10.1186/s13054-016-1301-x

Abbreviations PD- 1 ,

 1 AbbreviationsPD-1, Programmed Death-1; PD-L1, Programmed Death-ligand 1

Funding

All authors are supported by Hospices Civils de Lyon and Université Claude Bernard Lyon 1.

Authors' contributions

All authors contributed to the writing of this manuscript. All authors read and approved the final manuscript.

Competing interests

The authors declare that they have no competing interests.

Consent for publication

All authors gave final approval for manuscript publication.