import numpy as np import math import xarray as xr import matplotlib.pyplot as plt from scipy.spatial import cKDTree from scipy import interpolate import cartopy.crs as ccrs from datetime import datetime start = datetime.now() print(start) begin_time = datetime.now() from models.sun import sun_angles_analytical from models.sun import sun_angles_astropy from models.drag import drag #, c_d from input.user_input import * from input.natural_constants import * from astropy.time import Time import astropy.units as unit from models.thermal import AirMass from netCDF4 import Dataset import pandas as pd data = pd.read_excel(r'C:\Users\marcel\PycharmProjects\MasterThesis\Mappe1.xls', sheet_name='Tabelle3') comp_time = pd.DataFrame(data, columns= ['Time']) comp_height = pd.DataFrame(data, columns= ['Height']) comp_lat = pd.DataFrame(data, columns= ['Latitude']) comp_lon = pd.DataFrame(data, columns= ['Longitude']) Reynolds = [0.0, 0.002, 0.004, 0.007, 0.01] #, 0.04, 0.07, 0.1, 0.2, 0.3, 0.5, 0.7, 1, 2, 3, 5, 7, 10, 20, 30, 50, 70, 100, 200, # 300, 500, 700, 1000, 2000, 3000, 5000, 7000, 10000, 20000, 30000, 50000] drag_coeff = [20000, 12000, 6000, 3429, 2400] #, 600, 343, 240, 120, 80, 49, 36.5, 26.5, 14.4, 10.4, 6.9, 5.4, 4.1, 2.55, 2, 1.5, # 1.27, 1.07, 0.77, 0.65, 0.55, 0.5, 0.46, 0.42, 0.4, 0.385, 0.39, 0.405, 0.45, 0.47, 0.49] cd_interp1d = interpolate.interp1d(Reynolds, drag_coeff) Re_list = [] def cd_func(Re): w = np.log10(Re) if Re <= 0.01: c_d = 9/2 + 24/Re elif Re <= 20: c_d = 24/Re * (1 + 0.1315 * Re ** (0.82 - 0.05 * w)) elif Re <= 260: c_d = 24/Re * (1 + 0.1935 * Re ** 0.6305) elif Re <= 1.5 * 10e3: c_d = 10 ** (1.6435 - 1.1242 * w + 0.1558 * w ** 2) elif Re <= 1.2 * 10e4: c_d = 10 ** (-2.4571 + 2.5558 * w - 0.9295 * w ** 2 + 0.1049 * w ** 3) elif Re <= 4.4 * 10e4: c_d = 10 ** (-1.9181 + 0.6370 * w - 0.0636 * w ** 3) elif Re <= 3.38 * 10e5: c_d = 10 ** (-4.3390 + 1.5809 * w - 0.1546 * w ** 2) elif Re <= 4 * 10e5: c_d = 29.78 - 5.3 * w elif Re <= 10 ** 6: c_d = 0.1 * w - 0.49 elif Re > 10e6: c_d = 0.19 - 8 * 10e4/Re else: c_d = 0.47 return c_d def cd_func_garg(Re): if Re == 0: c_d = 2.0 elif Re < 2 * 10e5: c_d = 5.4856 * 10e9 * np.tanh(4.3774 * 10e-9 / Re) + 0.0709 * np.tanh(700.6575 / Re) + 0.3894 * np.tanh(74.1539 / Re) - 0.1198 * np.tanh(7429.0843 / Re) + 1.7174 * np.tanh(9.9851 / Re + 2.3384) + 0.4744 elif 2 * 10e5 < Re <= 10e6: c_d = 8 * 10e-6 * ((Re/6530) ** 2 + np.tanh(Re) - 8 * np.log(Re) / np.log(10)) - 0.4119 * np.exp(-2.08 * 10 ** 43 / (Re + Re ** 2) ** 4) - 2.1344 * np.exp(-((np.log(Re ** 2 + 10.7563) / np.log(10)) ** 2 + 9.9867) / Re) + 0.1357 * np.exp(-((Re / 1620) ** 2 + 10370) / Re) - 8.5 * 10e-3 * (2 * np.log(np.tanh(np.tanh(Re))) / np.log(10) - 2825.7162) / Re + 2.4795 elif Re > 10e6: c_d = 0.212546 else: c_d = 2.0 return 0.80 # c_d #cd_interp1d = interpolate.interp1d(Reynolds, drag_coeff) def transform(lon, lat, t): # WGS 84 reference coordinate system parameters A = 6378137.0 # major axis [m] E2 = 6.69437999014e-3 # eccentricity squared t_s = 1000 * t lon_rad = np.radians(lon) lat_rad = np.radians(lat) # convert to cartesian coordinates r_n = A / (np.sqrt(1 - E2 * (np.sin(lat_rad) ** 2))) x = r_n * np.cos(lat_rad) * np.cos(lon_rad) y = r_n * np.cos(lat_rad) * np.sin(lon_rad) z = r_n * (1 - E2) * np.sin(lat_rad) return x, y, z, t_s data = Dataset("test2021.nc", "r", format="NETCDF4") ERAtime = data.variables['time'][:] # time ERAlat = data.variables['latitude'][:] # latitude ERAlon = data.variables['longitude'][:] # longitude ERAz = data.variables['z'][:]/g # geopotential to geopotential height ERApress = data.variables['level'][:] # pressure level ERAtemp = data.variables['t'][:] # temperature in K vw_x = data.variables['u'][:] # v_x vw_y = data.variables['v'][:] # v_y vw_z = data.variables['w'][:] # v_z lon_era2d, lat_era2d, time_era = np.meshgrid(ERAlon, ERAlat, ERAtime) xs, ys, zs, ts = transform(lon_era2d.flatten(), lat_era2d.flatten(), time_era.flatten()) tree = cKDTree(np.column_stack((xs, ys, zs, ts))) # ! lat = start_lat # deg lon = start_lon # deg t = 0 # simulation time in seconds h = start_height utc = Time(start_utc) epoch_diff = (Time(start_utc).jd - Time('1900-01-01 00:00:00.0').jd) * 24.000000 t_epoch = epoch_diff xt, yt, zt, tt = transform(lon, lat, t) # test coordinates d, inds = tree.query(np.column_stack((xt, yt, zt, tt)), k=8) # longitude, latitude, time in h # ! w = 1.0 / d[0] ** 2 lat_sel = np.unravel_index(inds[0], lon_era2d.shape)[0] lon_sel = np.unravel_index(inds[0], lon_era2d.shape)[1] time_sel = np.unravel_index(inds[0], lon_era2d.shape)[2] interp4d_height = np.ma.dot(w, ERAz[time_sel, :, lat_sel, lon_sel]) / np.sum(w) interp4d_temp = np.ma.dot(w, ERAtemp[time_sel, :, lat_sel, lon_sel]) / np.sum(w) interp4d_vw_x = np.ma.dot(w, vw_x[time_sel, :, lat_sel, lon_sel]) / np.sum(w) interp4d_vw_y = np.ma.dot(w, vw_y[time_sel, :, lat_sel, lon_sel]) / np.sum(w) interp4d_vw_z = np.ma.dot(w, vw_z[time_sel, :, lat_sel, lon_sel]) / np.sum(w) pressure_hPa = np.array([1, 2, 3, 5, 7, 10, 20, 30, 50, 70, 100, 125, 150, 175, 200,225, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000]) pressure = 100 * pressure_hPa # print(pressure) # height_interp1d = interpolate.interp1d(interp4d_height, pressure) temp_interp1d = interpolate.interp1d(interp4d_height, interp4d_temp) press_interp1d = interpolate.interp1d(interp4d_height, pressure) vw_x_interp1d = interpolate.interp1d(interp4d_height, interp4d_vw_x) vw_y_interp1d = interpolate.interp1d(interp4d_height, interp4d_vw_y) vw_z_interp1d = interpolate.interp1d(interp4d_height, interp4d_vw_z) #u = 0 #v = 0 #w = 0 T_air = temp_interp1d(h) p_air = press_interp1d(h) rho_air = p_air/(R_air * T_air) u = vw_x_interp1d(h) v = vw_y_interp1d(h) w = -1 / g * vw_z_interp1d(h) * R_air * T_air / p_air v_x = 0 v_y = 0 v_z = 0 v_rel = 0 T_gas = T_air T_film = T_gas t_list = [] h_list = [] v_list = [] lat_list = [] lon_list = [] p_list = [] Temp_list = [] rho_list = [] while t <= t_end and h >= 0: t_list.append(t) h_list.append(h) v_list.append(v_rel) lat_list.append(lat) lon_list.append(lon) p_list.append(p_air) Temp_list.append(T_air) rho_list.append(rho_air) t_epoch = epoch_diff + t/3600 xt, yt, zt, tt = transform(lon, lat, t_epoch) # current balloon coordinates in cartesian coordinates: x [m], y [m], z [m], time [h since 1900-01-01 00:00:00.0] d, inds = tree.query(np.column_stack((xt, yt, zt, tt)), k=8) # longitude, latitude, time in h # ! w = 1.0 / d[0] ** 2 lat_sel = np.unravel_index(inds[0], lon_era2d.shape)[0] lon_sel = np.unravel_index(inds[0], lon_era2d.shape)[1] time_sel = np.unravel_index(inds[0], lon_era2d.shape)[2] interp4d_height = np.ma.dot(w, ERAz[time_sel, :, lat_sel, lon_sel]) / np.sum(w) interp4d_temp = np.ma.dot(w, ERAtemp[time_sel, :, lat_sel, lon_sel]) / np.sum(w) interp4d_vw_x = np.ma.dot(w, vw_x[time_sel, :, lat_sel, lon_sel]) / np.sum(w) interp4d_vw_y = np.ma.dot(w, vw_y[time_sel, :, lat_sel, lon_sel]) / np.sum(w) interp4d_vw_z = np.ma.dot(w, vw_z[time_sel, :, lat_sel, lon_sel]) / np.sum(w) press_interp1d = interpolate.interp1d(interp4d_height, pressure) temp_interp1d = interpolate.interp1d(interp4d_height, interp4d_temp) vw_x_interp1d = interpolate.interp1d(interp4d_height, interp4d_vw_x) vw_y_interp1d = interpolate.interp1d(interp4d_height, interp4d_vw_y) vw_z_interp1d = interpolate.interp1d(interp4d_height, interp4d_vw_z) try: p_air = press_interp1d(h) T_air = temp_interp1d(h) except: if (h > interp4d_height[0]): h = interp4d_height[0] else: h = interp4d_height[-1] p_air = press_interp1d(h) T_air = temp_interp1d(h) #print("height") #print(h) #print("temperature") #print(temp_interp1d(h)) #print("pressure") #print(press_interp1d(h)) #print("vw_x") #print(vw_x_interp1d(h)) p_gas = p_air rho_air = p_air / (R_air * T_air) u = vw_x_interp1d(h) v = vw_y_interp1d(h) w = -1/g * vw_z_interp1d(h) * R_air * T_air / p_air v_relx = u - v_x v_rely = v - v_y v_relz = w - v_z v_rel = (v_relx ** 2 + v_rely ** 2 + v_relz ** 2) ** (1/2) rho_gas = p_gas/(R_gas * T_gas) # calculate gas density through ideal(!) gas equation V_b = m_gas/rho_gas # calculate balloon volume from current gas mass and gas density if V_b > V_design: V_b = V_design m_gas = V_design * rho_gas else: pass m_gross = m_pl + m_film m_tot = m_pl + m_film + m_gas m_virt = m_tot + c_virt * rho_air * V_b d_b = 1.383 * V_b ** (1/3) # calculate diameter of balloon from its volume L_goreB = 1.914 * V_b ** (1/3) h_b = 0.748 * d_b A_surf = 4.94 * V_b ** (2/3) A_surf1 = 4.94 * V_design ** (2/3) * (1 - np.cos(np.pi * L_goreB/L_goreDesign)) A_eff = 0.65 * A_surf + 0.35 * A_surf1 A_top = np.pi/4 * d_b ** 2 AZ, ELV = sun_angles_analytical(lat, lon, utc) A_proj = A_top * (0.9125 + 0.0875 * np.cos(np.pi - 2 * np.deg2rad(ELV))) # CALCULATIONS FOR THERMAL MODEL if ELV >= -(180 / np.pi * np.arccos(R_E / (R_E + h))): tau_atm = 0.5 * (np.exp(-0.65 * AirMass(p_air, p_0, ELV, h)) + np.exp(-0.095 * AirMass(p_air, p_0, ELV, h))) tau_atmIR = 1.716 - 0.5 * (np.exp(-0.65 * p_air / p_0) + np.exp(-0.095 * p_air / p_0)) else: tau_atm = 0 tau_atmIR = 0 doy = int(utc.doy) MA = (357.52911 + 0.98560028 * (utc.jd - 2451545)) % 360 # in degree, reference: see folder "literature" TA = MA + 2 * e * np.sin(np.deg2rad(MA)) + 5 / 4 * e ** 2 * np.sin(np.deg2rad(2 * MA)) I_Sun = 1367.5 * ((1 + e * np.cos(np.deg2rad(TA))) / (1 - e ** 2)) ** 2 I_SunZ = I_Sun * tau_atm q_sun = I_SunZ q_IRground = epsilon_ground * sigma * T_ground ** 4 q_IREarth = q_IRground * tau_atmIR if ELV <= 0: q_Albedo = 0 else: q_Albedo = Albedo * I_Sun * np.sin(np.deg2rad(ELV)) my_air = (1.458 * 10 ** -6 * T_air ** 1.5) / (T_air + 110.4) my_gas = 1.895 * 10 ** -5 * (T_gas / 273.15) ** 0.647 k_air = 0.0241 * (T_air / 273.15) ** 0.9 k_gas = 0.144 * (T_gas / 273.15) ** 0.7 Pr_air = 0.804 - 3.25 * 10 ** (-4) * T_air Pr_gas = 0.729 - 1.6 * 10 ** (-4) * T_gas Gr_air = (rho_air ** 2 * g * np.abs(T_film - T_air) * d_b ** 3) / (T_air * my_air ** 2) Nu_air = 2 + 0.45 * (Gr_air * Pr_air) ** 0.25 HC_free = Nu_air * k_air / d_b Re = np.abs(v_relz) * d_b * rho_air / my_air Re_list.append(Re) HC_forced = k_air / d_b * (2 + 0.41 * Re ** 0.55) HC_internal = 0.13 * k_gas * ((rho_gas ** 2 * g * np.abs(T_film - T_gas) * Pr_gas) / (T_gas * my_air ** 2)) ** ( 1 / 3) HC_external = np.maximum(HC_free, HC_forced) HalfConeAngle = np.arcsin(R_E / (R_E + h)) ViewFactor = (1 - np.cos(HalfConeAngle)) / 2 Q_Sun = alpha_VIS * A_proj * q_sun * (1 + tau_VIS / (1 - r_VIS)) Q_Albedo = alpha_VIS * A_surf * q_Albedo * ViewFactor * (1 + tau_VIS / (1 - r_VIS)) Q_IREarth = alpha_IR * A_surf * q_IREarth * ViewFactor * (1 + tau_IR / (1 - r_IR)) Q_IRfilm = sigma * epsilon * alpha_IR * A_surf * T_film ** 4 * 1 / (1 - r_IR) Q_IRout = sigma * epsilon * A_surf * T_film ** 4 * (1 * tau_IR / (1 - r_IR)) Q_ConvExt = HC_external * A_eff * (T_air - T_film) Q_ConvInt = HC_internal * A_eff * (T_film - T_gas) try: c_d = cd_func(Re) except: print(Re) D = drag(c_d, rho_air, d_b, v_rel) # calculate drag force if v_rel == 0: Drag_x = 0 Drag_y = 0 Drag_z = 0 else: Drag_x = D * v_relx / v_rel Drag_y = D * v_rely / v_rel Drag_z = D * v_relz / v_rel I = g * V_b * (rho_air - rho_gas) # calculate gross inflation W = g * m_gross # calculate weight (force) F = I - W + Drag_z # RoC = -v_z # dT_gas = (Q_ConvInt / (gamma * m_gas * c_v) - (gamma - 1) / gamma * rho_air(h) * g / (rho_gas * R_gas) * RoC) * dt # dT_film = ((Q_Sun + Q_Albedo + Q_IREarth + Q_IRfilm + Q_ConvExt - Q_ConvInt - Q_IRout) / (c_f * m_film)) * dt # v_w = w # v = v_z s = h a_x = Drag_x/m_virt a_y = Drag_y/m_virt a_z = F/m_virt # DIFFERENTIAL EQUATIONS dx = dt * v_x + 0.5 * a_x * dt ** 2 # lon dy = dt * v_y + 0.5 * a_y * dt ** 2 # lat lon = lon + np.rad2deg(np.arctan(dx/((6371229.0 + h) * np.cos(np.deg2rad(lat))))) lat = lat + np.rad2deg(np.arctan(dy/(6371229.0 + h))) v_xn = v_x + dt * a_x v_yn = v_y + dt * a_y s_n = s + dt * v_z + 0.5 * a_z * dt ** 2 dh = s_n - s v_n = v_z + dt * a_z T_gn = T_gas + dt * (Q_ConvInt / (gamma * c_v * m_gas) - g * R_gas * T_gas * dh / (c_v * gamma * T_air * R_air)) T_en = T_film + (Q_Sun + Q_Albedo + Q_IREarth + Q_IRfilm + Q_ConvExt - Q_ConvInt - Q_IRout) / (c_f * m_film) * dt T_g = T_gn T_e = T_en s = s_n v_x = v_xn v_y = v_yn v_z = v_n h = s T_gas = T_g T_film = T_e # v_z = v t += dt # time increment utc = Time(start_utc) + t * unit.second #print(len(lon_list), len(lat_list)) #""" ax = plt.axes(projection=ccrs.Mollweide()) #ax.coastlines() ax.stock_img() plt.plot(start_lon, start_lat, 'rx', transform=ccrs.Geodetic()) plt.plot(lon_list, lat_list, 'k--', transform=ccrs.Geodetic()) plt.plot(comp_lon, comp_lat, 'r-', transform=ccrs.Geodetic()) #plt.xticks() plt.show() #""" ### WORKS! ### ###dset = xr.open_dataset("test2021.nc") ### ###print(dset['t'][1][0]) # [time] [level] ### #fig = plt.figure() #figsize=[120,50]) ### #ax = fig.add_subplot(111, projection=ccrs.PlateCarree()) ### ###dset['t'][1][0].plot(ax=ax, cmap='jet', transform=ccrs.PlateCarree()) ###ax.coastlines() ###plt.show() #print(len(ERAlat)) #print(len(ERAlon)) #print(len(ERAz)) #""" plt.plot(comp_time, comp_height, 'r--', label='PoGo Flight Test') #plt.plot(t_list, Re_list, 'k-', label="Reynolds-Number") #plt.plot(t_list, v_list, 'k--', label='Ballon v_rel') plt.plot(t_list, h_list, 'k-', label='Balloon Altitude') #plt.plot(t_list, p_list, 'r-', label='Air Pressure [Pa]') #plt.plot(t_list, Temp_list, 'b-', label='Air Temperature [K]') #plt.plot(t_list, rho_list, 'g-', label='Air Density in [kg/m$^3$]') plt.xlabel('time in s') plt.ylabel('Balloon Altitude in m') plt.legend() plt.show() #"""