# Smaller free gas bubbles (note, it is not necessary to have more than # one bubble size) mb0 = 2. # total mass flux in kg/s de = 0.0075 # bubble diameter in m lambda_1 = 0.9 disp_phases.append( stratified_plume_model.particle_from_mb0(ctd, z0, gas, yk, mb0, de, lambda_1, T0)) # Liquid hydrocarbon. This could either be a dissolving phase (mixture # of liquid phases) or an inert phase. We demonstrate here the simple # case of an inert oil phase oil = dbm.InsolubleParticle(True, True, rho_p=890., gamma=30., beta=0.0007, co=2.90075e-9) mb0 = 10. # total mass flux in kg/s de = 0.004 # bubble diameter in m lambda_1 = 0.9 disp_phases.append( stratified_plume_model.particle_from_mb0(ctd, z0, oil, np.array([1.]), mb0, de, lambda_1, T0)) # Run the simulation spm.simulate(disp_phases, z0, R, maxit=15, toler=0.2, delta_z=1.) # Save the model results spm.save_sim( '../../test/output/spm_blowout.nc', '../../test/output/test_BM54.nc',
def get_sim_data(): """ Get the input data to the `params.Scales` object Create an `ambient.Profile` object and a list of `stratified_plume_model.Particle` objects as the required input for the `params.Scales` object. Returns ------- profile : `ambient.Profile` object profile object from the BM54 CTD data disp_phases: list list of `stratified_plume_model.Particle` objects describing the blowout dispersed phases. z0 : float depth at the plume model origin (m) """ # Get the netCDF file nc = test_sbm.make_ctd_file() # Create a profile object with all available chemicals in the CTD data profile = ambient.Profile(nc, chem_names='all') # Create the stratified plume model object spm = stratified_plume_model.Model(profile) # Set the release conditions T0 = 273.15 + 35. # Release temperature in K R = 0.15 # Radius of leak source in m # Create the gas phase particles composition = ['methane', 'ethane', 'propane', 'oxygen'] yk = np.array([0.93, 0.05, 0.02, 0.0]) gas = dbm.FluidParticle(composition) z0 = 1000. disp_phases = [] # Larger free gas bubbles mb0 = 8. # total mass flux in kg/s de = 0.025 # bubble diameter in m lambda_1 = 0.85 disp_phases.append( stratified_plume_model.particle_from_mb0(profile, z0, gas, yk, mb0, de, lambda_1, T0)) # Smaller free gas bubbles (note, it is not necessary to have more than # one bubble size) mb0 = 2. # total mass flux in kg/s de = 0.0075 # bubble diameter in m lambda_1 = 0.9 disp_phases.append( stratified_plume_model.particle_from_mb0(profile, z0, gas, yk, mb0, de, lambda_1, T0)) # Liquid hydrocarbon. This could either be a dissolving phase (mixture # of liquid phases) or an inert phase. We demonstrate here the simple # case of an inert oil phase oil = dbm.InsolubleParticle(True, True, rho_p=890., gamma=30., beta=0.0007, co=2.90075e-9) mb0 = 10. # total mass flux in kg/s de = 0.004 # bubble diameter in m lambda_1 = 0.9 disp_phases.append( stratified_plume_model.particle_from_mb0(profile, z0, oil, np.array([1.]), mb0, de, lambda_1, T0)) # Return the simulation data return (profile, disp_phases, z0)
def get_sim_data(): """ Create the data needed to initialize a simulation Performs the steps necessary to set up a stratified plume model simulation and passes the input variables to the `Model` object and `Model.simulate()` method. Returns ------- profile : `ambient.Profile` object Return a profile object from the BM54 CTD data particles : list of `PlumeParticle` objects List of `PlumeParticle` objects containing the dispersed phase initial conditions z : float Depth of the release port (m) R : float Radius of the release port (m) maxit : float Maximum number of iterations to converge between inner and outer plumes toler : float Relative error tolerance to accept for convergence (--) delta_z : float Maximum step size to use in the simulation (m). The ODE solver in `calculate` is set up with adaptive step size integration, so in theory this value determines the largest step size in the output data, but not the numerical stability of the calculation. """ # Get the ambient CTD data profile = get_profile() # Specify the release location and geometry and initialize a particle # list z0 = 300. R = 0.15 particles = [] # Add a dissolving particle to the list composition = ['oxygen', 'nitrogen', 'argon'] yk = np.array([1.0, 0., 0.]) o2 = dbm.FluidParticle(composition) Q_N = 150. / 60. / 60. de = 0.005 lambda_1 = 0.85 particles.append( stratified_plume_model.particle_from_Q(profile, z0, o2, yk, Q_N, de, lambda_1)) # Add an insoluble particle to the list composition = ['inert'] yk = np.array([1.]) oil = dbm.InsolubleParticle(True, True) mb0 = 50. de = 0.01 lambda_1 = 0.8 particles.append( stratified_plume_model.particle_from_mb0(profile, z0, oil, [1.], mb0, de, lambda_1)) # Set the other simulation parameters maxit = 2 toler = 0.2 delta_z = 1.0 # Return the results return (profile, particles, z0, R, maxit, toler, delta_z)
def test_objects(): """ Test the class instantiation functions to ensure proper creations of class instances. """ # Define the properties of a simple fluid mixture comp = ['oxygen', 'nitrogen', 'carbon_dioxide'] delta = np.zeros((3, 3)) M = np.array([0.031998800000000001, 0.028013400000000001, 0.04401]) Pc = np.array([5042827.4639999997, 3399806.1560000004, 7373999.99902408]) Tc = np.array([154.57777777777773, 126.19999999999999, 304.12]) omega = np.array([0.0216, 0.0372, 0.225]) kh_0 = np.array( [4.1054468295090059e-07, 1.7417658031088084e-07, 1.47433500e-05]) neg_dH_solR = np.array([1650.0, 1300.0, 2368.988311]) nu_bar = np.array([3.20000000e-05, 3.3000000000000e-05, 3.20000000e-05]) B = np.array( [4.2000000000000004e-06, 7.9000000000000006e-06, 5.00000000e-06]) dE = np.array([18380.044045116938, 19636.083501503061, 16747.19275181]) K_salt = np.array([0.000169, 0.0001834, 0.0001323]) # Initiate a simple mixture from a composition list air = dbm.FluidMixture(comp) mixture_attributes(air, comp, 3) chem_properties(air, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) bub = dbm.FluidParticle(comp) mixture_attributes(bub, comp, 3) chem_properties(bub, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) # Initiate a simple mixture from a composition list with delta specified air = dbm.FluidMixture(comp, delta=delta) mixture_attributes(air, comp, 3) chem_properties(air, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) bub = dbm.FluidParticle(comp, delta=delta) mixture_attributes(bub, comp, 3) chem_properties(bub, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) # Define the properties of a single-component mixture comp = 'oxygen' delta = np.zeros((1, 1)) M = np.array([0.031998800000000001]) Pc = np.array([5042827.4639999997]) Tc = np.array([154.57777777777773]) omega = np.array([0.021600000000000001]) kh_0 = np.array([4.1054468295090059e-07]) neg_dH_solR = np.array([1650.0]) nu_bar = np.array([3.1999999999999999e-05]) B = np.array([4.2000000000000004e-06]) dE = np.array([18380.044045116938]) K_salt = np.array([0.000169]) # Initiate a single-component mixture from a list o2 = dbm.FluidMixture([comp]) mixture_attributes(o2, [comp], 1) chem_properties(o2, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) bub = dbm.FluidParticle([comp]) mixture_attributes(bub, [comp], 1) chem_properties(bub, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) # Initiate a single-componment mixture from a string with delta specified o2 = dbm.FluidMixture(comp, delta) mixture_attributes(o2, [comp], 1) chem_properties(o2, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) bub = dbm.FluidParticle(comp, delta) mixture_attributes(bub, [comp], 1) chem_properties(bub, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) # Initiate a single-componet mixture from a string with scalar delta o2 = dbm.FluidMixture(comp, 0.) mixture_attributes(o2, [comp], 1) chem_properties(o2, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) bub = dbm.FluidParticle(comp, 0.) mixture_attributes(bub, [comp], 1) chem_properties(bub, delta, M, Pc, Tc, omega, kh_0, neg_dH_solR, nu_bar, B, dE, K_salt) # Define the properties of an inert fluid particle isfluid = True iscompressible = False rho_p = 870. gamma = 29., beta = 0.0001 co = 1.0e-9 # Initiate an inert fluid particle with different combinations of input # variables oil = dbm.InsolubleParticle(isfluid, iscompressible) inert_attributes(oil, isfluid, iscompressible, 930., 30., 0.0007, 2.90075e-9) oil = dbm.InsolubleParticle(isfluid, iscompressible, rho_p=rho_p) inert_attributes(oil, isfluid, iscompressible, rho_p, 30., 0.0007, 2.90075e-9) oil = dbm.InsolubleParticle(isfluid, iscompressible, gamma=gamma) inert_attributes(oil, isfluid, iscompressible, 930., gamma, 0.0007, 2.90075e-9) oil = dbm.InsolubleParticle(isfluid, iscompressible, beta=beta) inert_attributes(oil, isfluid, iscompressible, 930., 30., beta, 2.90075e-9) oil = dbm.InsolubleParticle(isfluid, iscompressible, co=co) inert_attributes(oil, isfluid, iscompressible, 930., 30., 0.0007, co) oil = dbm.InsolubleParticle(isfluid, iscompressible, rho_p, gamma, beta, co) inert_attributes(oil, isfluid, iscompressible, rho_p, gamma, beta, co) oil = dbm.InsolubleParticle(isfluid, iscompressible, beta=beta, rho_p=rho_p, gamma=gamma, co=co) inert_attributes(oil, isfluid, iscompressible, rho_p, gamma, beta, co)
from datetime import datetime from netCDF4 import date2num import numpy as np if __name__ == '__main__': # Create the lake netCDF dataset and get the Profile object lake = lake_bub.get_lake_data() # Create the stratified plume model object spm = stratified_plume_model.Model(lake) # Create the dispersed phase particles sphere = dbm.InsolubleParticle(False, False, rho_p=15.) z0 = 46. particles = [] # Small particle Q_N = 100. / 60. / 60. de = 0.01 lambda_1 = 0.7 particles.append(stratified_plume_model.particle_from_Q(lake, z0, sphere, 1., Q_N, de, lambda_1, 273.15 + 20.)) # Initialize a simulation R = 6.5 / 2. spm.simulate(particles, z0, R, maxit=5, delta_z = 0.2) # Save the model results
def test_particle_obj(): """ Test the object behavior for the `PlumeParticle` object Test the instantiation and attribute data for the `PlumeParticle` object of the `stratified_plume_model` module. """ # Set up the base parameters describing a particle object T = 273.15 + 15. P = 150e5 Sa = 35. Ta = 273.15 + 4. composition = ['methane', 'ethane', 'propane', 'oxygen'] yk = np.array([0.85, 0.07, 0.08, 0.0]) de = 0.005 lambda_1 = 0.85 K = 1. Kt = 1. fdis = 1e-6 # Compute a few derived quantities bub = dbm.FluidParticle(composition) nb0 = 1.e5 m0 = bub.masses_by_diameter(de, T, P, yk) # Create a `PlumeParticle` object bub_obj = dispersed_phases.PlumeParticle(bub, m0, T, nb0, lambda_1, P, Sa, Ta, K, Kt, fdis) # Check if the initialized attributes are correct for i in range(len(composition)): assert bub_obj.composition[i] == composition[i] assert_array_almost_equal(bub_obj.m0, m0, decimal=6) assert bub_obj.T0 == T assert_array_almost_equal(bub_obj.m, m0, decimal=6) assert bub_obj.T == T assert bub_obj.cp == seawater.cp() * 0.5 assert bub_obj.K == K assert bub_obj.K_T == Kt assert bub_obj.fdis == fdis for i in range(len(composition) - 1): assert bub_obj.diss_indices[i] == True assert bub_obj.diss_indices[-1] == False assert bub_obj.nb0 == nb0 assert bub_obj.lambda_1 == lambda_1 # Including the values after the first call to the update method us_ans = bub.slip_velocity(m0, T, P, Sa, Ta) rho_p_ans = bub.density(m0, T, P) A_ans = bub.surface_area(m0, T, P, Sa, Ta) Cs_ans = bub.solubility(m0, T, P, Sa) beta_ans = bub.mass_transfer(m0, T, P, Sa, Ta) beta_T_ans = bub.heat_transfer(m0, T, P, Sa, Ta) assert bub_obj.us == us_ans assert bub_obj.rho_p == rho_p_ans assert bub_obj.A == A_ans assert_array_almost_equal(bub_obj.Cs, Cs_ans, decimal=6) assert_array_almost_equal(bub_obj.beta, beta_ans, decimal=6) assert bub_obj.beta_T == beta_T_ans # No need to test the properties or diameter objects since they are # inherited from the `single_bubble_model` and tested in `test_sbm`. # Check functionality of insoluble particle drop = dbm.InsolubleParticle(isfluid=True, iscompressible=True) m0 = drop.mass_by_diameter(de, T, P, Sa, Ta) drop_obj = dispersed_phases.PlumeParticle(drop, m0, T, nb0, lambda_1, P, Sa, Ta, K, fdis=fdis, K_T=Kt) assert len(drop_obj.composition) == 1 assert drop_obj.composition[0] == 'inert' assert_array_almost_equal(drop_obj.m0, m0, decimal=6) assert drop_obj.T0 == T assert_array_almost_equal(drop_obj.m, m0, decimal=6) assert drop_obj.T == T assert drop_obj.cp == seawater.cp() * 0.5 assert drop_obj.K == K assert drop_obj.K_T == Kt assert drop_obj.fdis == fdis assert drop_obj.diss_indices[0] == True assert drop_obj.nb0 == nb0 assert drop_obj.lambda_1 == lambda_1 # Including the values after the first call to the update method us_ans = drop.slip_velocity(m0, T, P, Sa, Ta) rho_p_ans = drop.density(T, P, Sa, Ta) A_ans = drop.surface_area(m0, T, P, Sa, Ta) beta_T_ans = drop.heat_transfer(m0, T, P, Sa, Ta) assert drop_obj.us == us_ans assert drop_obj.rho_p == rho_p_ans assert drop_obj.A == A_ans assert drop_obj.beta_T == beta_T_ans
def get_particles(self, composition, data, md_gas0, md_oil0, profile, d50_gas, d50_oil, nbins, T0, z0, dispersant, sigma_fac, oil, mass_frac, hydrate, inert_drop): """ docstring for get_particles """ # Reduce surface tension if dispersant is applied if dispersant is True: sigma = np.array([[1.], [1.]]) * sigma_fac else: sigma = np.array([[1.], [1.]]) # Create DBM objects for the bubbles and droplets bubl = dbm.FluidParticle(composition, fp_type=0, sigma_correction=sigma[0], user_data=data) drop = dbm.FluidParticle(composition, fp_type=1, sigma_correction=sigma[1], user_data=data) # Get the local ocean conditions T, S, P = profile.get_values(z0, ['temperature', 'salinity', 'pressure']) rho = seawater.density(T, S, P) # Get the mole fractions of the released fluids molf_gas = bubl.mol_frac(md_gas0) molf_oil = drop.mol_frac(md_oil0) print molf_gas print molf_oil # Use the Rosin-Rammler distribution to get the mass flux in each # size class # de_gas, md_gas = sintef.rosin_rammler(nbins, d50_gas, np.sum(md_gas0), # bubl.interface_tension(md_gas0, T0, S, P), # bubl.density(md_gas0, T0, P), rho) # de_oil, md_oil = sintef.rosin_rammler(nbins, d50_oil, np.sum(md_oil0), # drop.interface_tension(md_oil0, T0, S, P), # drop.density(md_oil0, T0, P), rho) # Get the user defined particle size distibution de_oil, vf_oil, de_gas, vf_gas = self.userdefined_de() md_gas = np.sum(md_gas0) * vf_gas md_oil = np.sum(md_oil0) * vf_oil # Define a inert particle to be used if inert liquid particles are use # in the simulations molf_inert = 1. isfluid = True iscompressible = True rho_o = drop.density(md_oil0, T0, P) inert = dbm.InsolubleParticle(isfluid, iscompressible, rho_p=rho_o, gamma=40., beta=0.0007, co=2.90075e-9) # Create the particle objects particles = [] t_hyd = 0. # Bubbles for i in range(nbins): if md_gas[i] > 0.: (m0, T0, nb0, P, Sa, Ta) = dispersed_phases.initial_conditions( profile, z0, bubl, molf_gas, md_gas[i], 2, de_gas[i], T0) # Get the hydrate formation time for bubbles if hydrate is True and dispersant is False: t_hyd = dispersed_phases.hydrate_formation_time(bubl, z0, m0, T0, profile) if np.isinf(t_hyd): t_hyd = 0. else: t_hyd = 0. particles.append(bpm.Particle(0., 0., z0, bubl, m0, T0, nb0, 1.0, P, Sa, Ta, K=1., K_T=1., fdis=1.e-6, t_hyd=t_hyd)) # Droplets for i in range(len(de_oil)): # Add the live droplets to the particle list if md_oil[i] > 0. and not inert_drop: (m0, T0, nb0, P, Sa, Ta) = dispersed_phases.initial_conditions( profile, z0, drop, molf_oil, md_oil[i], 2, de_oil[i], T0) # Get the hydrate formation time for bubbles if hydrate is True and dispersant is False: t_hyd = dispersed_phases.hydrate_formation_time(drop, z0, m0, T0, profile) if np.isinf(t_hyd): t_hyd = 0. else: t_hyd = 0. particles.append(bpm.Particle(0., 0., z0, drop, m0, T0, nb0, 1.0, P, Sa, Ta, K=1., K_T=1., fdis=1.e-6, t_hyd=t_hyd)) # Add the inert droplets to the particle list if md_oil[i] > 0. and inert_drop is True: (m0, T0, nb0, P, Sa, Ta) = dispersed_phases.initial_conditions( profile, z0, inert, molf_oil, md_oil[i], 2, de_oil[i], T0) particles.append(bpm.Particle(0., 0., z0, inert, m0, T0, nb0, 1.0, P, Sa, Ta, K=1., K_T=1., fdis=1.e-6, t_hyd=0.)) # Define the lambda for particles model = params.Scales(profile, particles) for j in range(len(particles)): particles[j].lambda_1 = model.lambda_1(z0, j) # Return the particle list return particles
import numpy as np import matplotlib.pyplot as plt if __name__ == '__main__': # Define the type of inert fluid particle isfluid = True iscompressible = False gamma = 29. # deg API beta = 0.0007 # Pa^(-1) co = 3.7e-9 # K^(-1) # Create a DBM InsolubleParticle object for this simple oil oil = dbm.InsolubleParticle(isfluid, iscompressible, gamma=gamma, beta=beta, co=co) # Specify some generic deepwater ocean conditions T = 273.15 + 4. P = 150.0 * 1.0e5 Ta = 273.15 + 4.0 Sa = 34.5 L = 1500 # Compute the rise velocity for several droplet sizes de = np.logspace(np.log10(0.00010), np.log10(0.05)) t = np.zeros(len(de)) for i in range(len(t)): m = oil.mass_by_diameter(de[i], T, P, Sa, Ta)
nb0, lambda_1, P, Sa, Ta, K=1., K_T=1., fdis=1.e-6, t_hyd=0., lag_time=False)) # Larger oil droplets oil = dbm.InsolubleParticle(True, True, rho_p=890., gamma=30., beta=0.0007, co=2.90075e-9, k_bio=3.000e-6, t_bio=86400.) mb0 = 10. # total mass flux in kg/s de = 0.005 # bubble diameter in m lambda_1 = 0.9 (m0, T0, nb0, P, Sa, Ta) = dispersed_phases.initial_conditions(ctd, z0, oil, yk, mb0, 2, de, Tj) disp_phases.append( bent_plume_model.Particle(0., 0., z0, oil, m0,
def test_simulation(): """ Test the output from the `Model.simulate` method Test the output of the `Model.simulate` method of the `single_bubble_model` module. These tests include a single component bubble, multi-component bubbles and drops, and multi-component fluid particles with gas stripping from the ambient dissolved chemicals. """ # Get the ambient profile data profile = get_profile() # Initialize a Model object sbm = single_bubble_model.Model(profile) # Set up the initial conditions composition = ['methane', 'ethane', 'propane', 'oxygen'] bub = dbm.FluidParticle(composition) mol_frac = np.array([0.90, 0.07, 0.03, 0.0]) de = 0.005 z0 = 1000. T0 = 273.15 + 30. # Run the simulation sbm.simulate(bub, np.array([0., 0., z0]), de, mol_frac, T0, K_T=1, fdis=1e-8, delta_t=10.) # Check the solution assert sbm.y.shape[0] == 1117 assert sbm.y.shape[1] == 8 assert sbm.t.shape[0] == 1117 assert_approx_equal(sbm.t[-1], 11016.038751523512, significant=6) assert_array_almost_equal(sbm.y[-1, :], np.array([ 0.00000000e+00, 0.00000000e+00, 3.36934635e+02, 4.31711152e-14, 6.66318106e-15, -2.91389824e-13, -1.08618680e-15, -1.37972400e-07 ]), decimal=6) # Write the output files sbm.save_sim('./output/sbm_data.nc', './test_BM54.nc', 'Results of ./test_sbm.py script') sbm.save_txt('./output/sbm_data', './test_BM54.nc', 'Results of ./test_sbm.py script') # Reload the simulation sbm_f = single_bubble_model.Model(simfile='./output/sbm_data.nc') # Check that the attributes are loaded correctly assert sbm_f.y[0, 0] == sbm.y[0, 0] # x0 assert sbm_f.y[0, 1] == sbm.y[0, 1] # y0 assert sbm_f.y[0, 2] == sbm.y[0, 2] # z0 assert_array_almost_equal(sbm_f.particle.m0, sbm.particle.m0, decimal=6) assert sbm_f.particle.T0 == sbm.particle.T0 print sbm_f.particle.K_T, sbm.particle.K_T assert sbm_f.particle.K == sbm.particle.K assert sbm_f.particle.K_T == sbm.particle.K_T assert sbm_f.particle.fdis == sbm.particle.fdis assert sbm_f.K_T0 == sbm.K_T0 assert sbm_f.delta_t == sbm.delta_t (T, S, P) = profile.get_values(1000., ['temperature', 'salinity', 'pressure']) (Tp, Sp, Pp) = sbm_f.profile.get_values(1000., ['temperature', 'salinity', 'pressure']) assert Tp == T assert Sp == S assert Pp == P # Check that the results are still correct assert sbm.y.shape[0] == 1117 assert sbm.y.shape[1] == 8 assert sbm.t.shape[0] == 1117 assert_approx_equal(sbm.t[-1], 11016.038751523512, significant=6) assert_array_almost_equal(sbm.y[-1, :], np.array([ 0.00000000e+00, 0.00000000e+00, 3.36934635e+02, 4.31711152e-14, 6.66318106e-15, -2.91389824e-13, -1.08618680e-15, -1.37972400e-07 ]), decimal=6) # Load the data in the txt file and check the solution data = np.loadtxt('./output/sbm_data.txt') assert sbm.y.shape[0] == 1117 assert sbm.y.shape[1] == 8 assert sbm.t.shape[0] == 1117 assert_approx_equal(sbm.t[-1], 11016.038751523512, significant=6) assert_array_almost_equal(sbm.y[-1, :], np.array([ 0.00000000e+00, 0.00000000e+00, 3.36934635e+02, 4.31711152e-14, 6.66318106e-15, -2.91389824e-13, -1.08618680e-15, -1.37972400e-07 ]), decimal=6) # Create an inert particle that is compressible oil = dbm.InsolubleParticle(True, True, rho_p=840.) mol_frac = np.array([1.]) # Specify the remaining particle initial conditions de = 0.03 z0 = 1000. T0 = 273.15 + 30. # Simulate the trajectory through the water column and plot the results sbm.simulate(oil, np.array([0., 0., z0]), de, mol_frac, T0, K_T=1, delta_t=10.) ans = np.array([ 0.00000000e+00, 0.00000000e+00, 1.16067764e-01, 1.26136097e-02, 7.57374681e+03 ]) for i in range(5): assert_approx_equal(sbm.y[-1, i], ans[i], significant=6)
def test_particle_obj(): """ Test the object behavior for the `Particle` object Test the instantiation and attribute data for the `Particle` object of the `single_bubble_model` module. """ # Set up the base parameters describing a particle object T = 273.15 + 15. P = 150e5 Sa = 35. Ta = 273.15 + 4. composition = ['methane', 'ethane', 'propane', 'oxygen'] yk = np.array([0.85, 0.07, 0.08, 0.0]) de = 0.005 K = 1. Kt = 1. fdis = 1e-6 # Compute a few derived quantities bub = dbm.FluidParticle(composition) m0 = bub.masses_by_diameter(de, T, P, yk) # Create a `SingleParticle` object bub_obj = dispersed_phases.SingleParticle(bub, m0, T, K, fdis=fdis, K_T=Kt) # Check if the initial attributes are correct for i in range(len(composition)): assert bub_obj.composition[i] == composition[i] assert_array_almost_equal(bub_obj.m0, m0, decimal=6) assert bub_obj.T0 == T assert bub_obj.cp == seawater.cp() * 0.5 assert bub_obj.K == K assert bub_obj.K_T == Kt assert bub_obj.fdis == fdis for i in range(len(composition) - 1): assert bub_obj.diss_indices[i] == True assert bub_obj.diss_indices[-1] == False # Check if the values returned by the `properties` method match the input (us, rho_p, A, Cs, beta, beta_T, T_ans) = bub_obj.properties(m0, T, P, Sa, Ta, 0.) us_ans = bub.slip_velocity(m0, T, P, Sa, Ta) rho_p_ans = bub.density(m0, T, P) A_ans = bub.surface_area(m0, T, P, Sa, Ta) Cs_ans = bub.solubility(m0, T, P, Sa) beta_ans = bub.mass_transfer(m0, T, P, Sa, Ta) beta_T_ans = bub.heat_transfer(m0, T, P, Sa, Ta) assert us == us_ans assert rho_p == rho_p_ans assert A == A_ans assert_array_almost_equal(Cs, Cs_ans, decimal=6) assert_array_almost_equal(beta, beta_ans, decimal=6) assert beta_T == beta_T_ans assert T == T_ans # Check that dissolution shuts down correctly m_dis = np.array([m0[0] * 1e-10, m0[1] * 1e-8, m0[2] * 1e-3, 1.5e-5]) (us, rho_p, A, Cs, beta, beta_T, T_ans) = bub_obj.properties(m_dis, T, P, Sa, Ta, 0) assert beta[0] == 0. assert beta[1] == 0. assert beta[2] > 0. assert beta[3] > 0. m_dis = np.array([m0[0] * 1e-10, m0[1] * 1e-8, m0[2] * 1e-7, 1.5e-16]) (us, rho_p, A, Cs, beta, beta_T, T_ans) = bub_obj.properties(m_dis, T, P, Sa, Ta, 0.) assert np.sum(beta[0:-1]) == 0. assert us == 0. assert rho_p == seawater.density(Ta, Sa, P) # Check that heat transfer shuts down correctly (us, rho_p, A, Cs, beta, beta_T, T_ans) = bub_obj.properties(m_dis, Ta, P, Sa, Ta, 0) assert beta_T == 0. (us, rho_p, A, Cs, beta, beta_T, T_ans) = bub_obj.properties(m_dis, T, P, Sa, Ta, 0) assert beta_T == 0. # Check the value returned by the `diameter` method de_p = bub_obj.diameter(m0, T, P, Sa, Ta) assert_approx_equal(de_p, de, significant=6) # Check functionality of insoluble particle drop = dbm.InsolubleParticle(isfluid=True, iscompressible=True) m0 = drop.mass_by_diameter(de, T, P, Sa, Ta) # Create a `Particle` object drop_obj = dispersed_phases.SingleParticle(drop, m0, T, K, fdis=fdis, K_T=Kt) # Check if the values returned by the `properties` method match the input (us, rho_p, A, Cs, beta, beta_T, T_ans) = drop_obj.properties(np.array([m0]), T, P, Sa, Ta, 0) us_ans = drop.slip_velocity(m0, T, P, Sa, Ta) rho_p_ans = drop.density(T, P, Sa, Ta) A_ans = drop.surface_area(m0, T, P, Sa, Ta) beta_T_ans = drop.heat_transfer(m0, T, P, Sa, Ta) assert us == us_ans assert rho_p == rho_p_ans assert A == A_ans assert beta_T == beta_T_ans # Check that heat transfer shuts down correctly (us, rho_p, A, Cs, beta, beta_T, T_ans) = drop_obj.properties(m_dis, Ta, P, Sa, Ta, 0) assert beta_T == 0. (us, rho_p, A, Cs, beta, beta_T, T_ans) = drop_obj.properties(m_dis, T, P, Sa, Ta, 0) assert beta_T == 0. # Check the value returned by the `diameter` method de_p = drop_obj.diameter(m0, T, P, Sa, Ta) assert_approx_equal(de_p, de, significant=6)
from tamoc import single_bubble_model import numpy as np if __name__ == '__main__': # Open an ambient profile object from the netCDF dataset nc = '../../test/output/test_bm54.nc' bm54 = ambient.Profile(nc, chem_names='all') bm54.close_nc() # Initialize a single_bubble_model.Model object with this data sbm = single_bubble_model.Model(bm54) # Create an inert particle that is compressible oil = dbm.InsolubleParticle(True, True, rho_p=840., k_bio=0.001, t_bio = 0.) mol_frac = np.array([1.]) # Specify the remaining particle initial conditions de = 0.03 z0 = 1000. T0 = 273.15 + 30. # Simulate the trajectory through the water column and plot the results sbm.simulate(oil, z0, de, mol_frac, T0, K_T=1, delta_t=10.) sbm.post_process() # Save the simulation to a netCDF file sbm.save_sim('./particle.nc', '../../test/output/test_bm54.nc', 'Results of ./particle.py script')
def get_sim_data(): """ Create the data needed to initialize a simulation Performs the steps necessary to set up a bent plume model simulation and passes the input variables to the `Model` object and `Model.simulate()` method. Returns ------- profile : `ambient.Profile` object Return a profile object from the BM54 CTD data z0 : float Depth of the release port (m) D : float Diameter of the release port (m) Vj : float Initial velocity of the jet (m/s) phi_0 : float Vertical angle from the horizontal for the discharge orientation (rad in range +/- pi/2) theta_0 : float Horizontal angle from the x-axis for the discharge orientation. The x-axis is taken in the direction of the ambient current. (rad in range 0 to 2 pi) Sj : float Salinity of the continuous phase fluid in the discharge (psu) Tj : float Temperature of the continuous phase fluid in the discharge (T) cj : ndarray Concentration of passive tracers in the discharge (user-defined) tracers : string list List of passive tracers in the discharge. These can be chemicals present in the ambient `profile` data, and if so, entrainment of these chemicals will change the concentrations computed for these tracers. However, none of these concentrations are used in the dissolution of the dispersed phase. Hence, `tracers` should not contain any chemicals present in the dispersed phase particles. particles : list of `Particle` objects List of `Particle` objects describing each dispersed phase in the simulation dt_max : float Maximum step size to take in the storage of the simulation solution (s) sd_max : float Maximum number of orifice diameters to compute the solution along the plume centerline (m/m) """ # Get the ambient CTD data profile = get_profile() # Specify the release location and geometry and initialize a particle # list z0 = 300. D = 0.3 particles = [] # Add a dissolving particle to the list composition = ['oxygen', 'nitrogen', 'argon'] yk = np.array([1.0, 0., 0.]) o2 = dbm.FluidParticle(composition) Q_N = 1.5 / 60. / 60. de = 0.009 lambda_1 = 0.85 (m0, T0, nb0, P, Sa, Ta) = dispersed_phases.initial_conditions( profile, z0, o2, yk, Q_N, 1, de) particles.append(bent_plume_model.Particle(0., 0., z0, o2, m0, T0, nb0, lambda_1, P, Sa, Ta, K=1., K_T=1., fdis=1.e-6, t_hyd=0.)) # Add an insoluble particle to the list composition = ['inert'] yk = np.array([1.]) oil = dbm.InsolubleParticle(True, True) mb0 = 1. de = 0.01 lambda_1 = 0.8 (m0, T0, nb0, P, Sa, Ta) = dispersed_phases.initial_conditions( profile, z0, oil, yk, mb0, 1, de) particles.append(bent_plume_model.Particle(0., 0., z0, oil, m0, T0, nb0, lambda_1, P, Sa, Ta, K=1., K_T=1., fdis=1.e-6, t_hyd=0.)) # Set the other simulation parameters Vj = 0. phi_0 = -np.pi/2. theta_0 = 0. Sj = 0. Tj = Ta cj = np.array([1.]) tracers = ['tracer'] dt_max = 60. sd_max = 3000. # Return the results return (profile, np.array([0., 0., z0]), D, Vj, phi_0, theta_0, Sj, Tj, cj, tracers, particles, dt_max, sd_max)