Lab 5-3: Mixing length theory at Kettle Ponds#

Written by Eli Schwat - February 2024.

import xarray as xr
import numpy as np
import os 
import urllib
import pandas as pd
import datetime as dt
import matplotlib.pyplot as plt
import altair as alt

SOS Data#

sos_file = "../data/sos_full_dataset_30min.nc"
sos_dataset = xr.open_dataset(sos_file)

Plotting velocity profiles during different stability conditions#

The dataset already has temperature gradients (that indicate stability) calculated.

sos_dataset['temp_gradient_3m_c'].loc['20221101'].plot()
[<matplotlib.lines.Line2D at 0x7f10dfbb8750>]
../../_images/fce2558da2fb629472b2831cd5ac5c20e3b4d848c0c0a00d1706b03f00034405.png

We can see that the atmosphere was stable except for the middle of the day

Let’s look at velocity profiles at different times of the day. What do we expect them to look like?

wind_df = sos_dataset[[
    'spd_1m_c',
    'spd_2m_c',
    'spd_3m_c',
    'spd_5m_c',
    'spd_10m_c',
    'spd_15m_c',
    'spd_20m_c',  
]].to_dataframe().melt(ignore_index=False)
# Extract the number from the string in the 'column'
wind_df['height'] = wind_df['variable'].str.extract('(\d+)').astype('int')
wind_df
variable value height
time
2022-11-01 00:00:00 spd_1m_c 0.847002 1
2022-11-01 00:30:00 spd_1m_c 1.782696 1
2022-11-01 01:00:00 spd_1m_c 1.118848 1
2022-11-01 01:30:00 spd_1m_c 1.762465 1
2022-11-01 02:00:00 spd_1m_c 1.999188 1
... ... ... ...
2023-06-19 15:30:00 spd_20m_c 3.620165 20
2023-06-19 16:00:00 spd_20m_c 5.240737 20
2023-06-19 16:30:00 spd_20m_c 4.676786 20
2023-06-19 17:00:00 spd_20m_c 4.952941 20
2023-06-19 17:30:00 spd_20m_c 3.563722 20

77518 rows × 3 columns

Let’s look at wind velocity profiles at 12pm (near neutral conditions)

Here, we plot both in linear space (left plot) and log space (right plot)

base = alt.Chart(
    wind_df.loc['20221101 1200']
).mark_circle(size=50).encode(
    alt.X('value:Q')
).properties(width=150, height = 150)

(
    base.encode(alt.Y('height:Q'))
    |
    base.encode(alt.Y('height:Q').scale(type='log'))
)

How about at 5pm during stable conditions?

base = alt.Chart(
    wind_df.loc['20221101 1700']
).mark_circle(size=50).encode(
    alt.X('value:Q')
).properties(width=150, height = 150)

(
    base.encode(alt.Y('height:Q'))
    |
    base.encode(alt.Y('height:Q').scale(type='log'))
)

We see that the wind profile is not quite logarithmic…it seems to depart from a logarithmic curve higher up.

Why would the velocity profile depart from the log curve like it does above, during stable conditions?

Fitting a log profile to the measured velocity profile#

Let’s fit a wind profile to the 1200 data

\[ \overline{u} = \frac{u^*}{k}log(z / z_0)\]

For this exercise, we will assume a z0 value, but we could calculate it if we wanted to.

We will also extract a measured \(u^*\) value.

sos_dataset[[
    'u*_3m_c',
    'u*_5m_c',
    'u*_10m_c',
    'u*_15m_c',
]].to_dataframe().loc['20221101 1200']
u*_3m_c     0.046698
u*_5m_c     0.066276
u*_10m_c    0.101627
u*_15m_c    0.110692
Name: 2022-11-01 12:00:00, dtype: float64
ustar_df = sos_dataset[[
    'u*_3m_c',
]].to_dataframe().melt(ignore_index=False)
z0 = 0.001

ustar = ustar_df.loc['20221101 1200'].value
plt.figure(figsize=(3,3))
plt.scatter(
    wind_df.loc['20221101 1200']['value'],
    wind_df.loc['20221101 1200']['height'],
    label='measured'
)
plt.plot(
    (ustar / 0.4)*np.log(np.arange(1,20,1) / z0),
    np.arange(1,20,1),
    color='orange',
    label='fit'
)
plt.yscale('log')
plt.legend
<function matplotlib.pyplot.legend(*args, **kwargs) -> 'Legend'>
../../_images/f1b4a30bb36806f21ce403d2d401acead3678894a83fd3f10604d04664f33cda.png
plt.figure(figsize=(4,4))
plt.scatter(
    wind_df.loc['20221101 1200']['value'],
    wind_df.loc['20221101 1200']['height'],
    label='measured'
)
plt.plot(
    (ustar / 0.4)*np.log(np.arange(1,20,1) / z0),
    np.arange(1,20,1),
    color='orange',
    label='fit'
)
plt.legend()
<matplotlib.legend.Legend at 0x7f10de945490>
../../_images/84d8d54bbb3bcfcd84f0d5d98a8808b62c7371b984fa7e608bd0a0449c5a4220.png

How could we extract \(z_0\) and \(u^*\) from the data?

\[ \overline{u} = \frac{u^*}{k}log(z / z_0)\]