"""Copyright (c) 2024 MPI-M, Clara Bayley----- Microphysics Test Cases -----File: kid_dynamics.pyProject: test_case_1dkidCreated Date: Monday 2nd September 2024Author: Clara Bayley (CB)Additional Contributors:-----Last Modified: Wednesday 4th June 2025Modified By: CB-----License: BSD 3-Clause "New" or "Revised" Licensehttps://opensource.org/licenses/BSD-3-Clause-----File Description:class for driving KiD rainshaft test case"""importnumpyasnpfromPyMPDATAimportOptionsfromPyMPDATA_examples.Shipway_and_Hill_2012importsifromPyMPDATA_examples.Shipway_and_Hill_2012importformulaeasSH2012formulaefrom.mpdataimportMPDATAfrom.settingsimportSettings
[docs]classKiDDynamics:"""A class for driving the KiD rainshaft test case, based on Shipway and Hill 2012. This class is a wrapper around the MPDATA driver of the Shipway and Hill 2012 example in the PyMPDATA-examples library. See https://github.com/open-atmos/PyMPDATA/tree/main/examples/PyMPDATA_examples/Shipway_and_Hill_2012 for the original source code. """def__init__(self,z_delta,z_max,timestep,t_end):"""Initialize the KiDDynamics object. Args: z_delta (float): Vertical grid spacing [m]. z_max (float): Maximum height of the domain (top of half-cell) [m]. timestep (float): Size of time steps of simulation [s]. t_end (float): End time of the simulation [s]. """options=Options(n_iters=3,nonoscillatory=True)RHOD_VERTVELO=3*si.m/si.s*si.kg/si.m**3P0=1007*si.hPaself.settings=Settings(dt=timestep,dz=z_delta,rhod_w_const=RHOD_VERTVELO,t_max=t_end,p0=P0,z_max=z_max,)self.mpdata=MPDATA(nz=self.settings.nz,dt=self.settings.dt,qv_of_zZ_at_t0=lambdazZ:self.settings.qv(zZ*self.settings.dz),g_factor_of_zZ=lambdazZ:self.settings.rhod(zZ*self.settings.dz),options=options,)assertself.settings.nz==int(z_max/z_delta)assertself.settings.dz==z_deltanz=self.settings.nzzfull=np.linspace(z_delta/2,(nz-1/2)*z_delta,nz,endpoint=True)self.zhalf=np.linspace(0,nz*z_delta,nz+1,endpoint=True)self.rhod_prof=self.settings.rhod(zfull)self.temp_prof=SH2012formulae.temperature(self.rhod_prof,self.settings.thd(zfull))qvap0=self.mpdata["qvap"].advectee.get()self.press_prof=SH2012formulae.pressure(self.rhod_prof,self.temp_prof,qvap0)key=f"nr={self.mpdata.nr}, dz={self.settings.dz}, dt={self.settings.dt}, options={options}"print(f"Simulating {self.settings.nt} timesteps using {key}")
[docs]defset_thermo(self,thermo):"""Set thermodynamics from the dynamics solver. Args: thermo (Thermodynamics): Object representing the thermodynamic state. Returns: Thermodynamics: Updated thermodynamic state. """thermo.temp=self.temp_profthermo.rho=self.rhod_profthermo.press=self.press_profthermo.massmix_ratios[0]=self.mpdata["qvap"].advectee.get()# qvapthermo.massmix_ratios[1]=self.mpdata["qcond"].advectee.get()# qcondthermo.massmix_ratios[2]=self.mpdata["qice"].advectee.get()# qcondthermo.massmix_ratios[3]=self.mpdata["qrain"].advectee.get()# qcondthermo.massmix_ratios[4]=self.mpdata["qsnow"].advectee.get()# qcondthermo.massmix_ratios[5]=self.mpdata["qgrau"].advectee.get()# qcondreturnthermo
[docs]defrun(self,time,timestep,thermo):""" Run the 1-D KiD motion computations. This method integrates the equations from time to time+timestep for the dynamics of a 1-D KiD rainshaft. Args: time (float): Current time [s]. timestep (float): Size of timestep for the simulation [s]. thermo (Thermodynamics): Object representing the thermodynamic state. Returns: Thermodynamics: Updated thermodynamic state. """asserttimestep==self.settings.dt,"Timestep must match initialised value."t=int(time/timestep)asserttime%timestep==0,"Time not a multiple of the timestep."GC=(self.settings.rhod_w((t+0.5)*self.settings.dt)*self.settings.dt/self.settings.dz)advector_0=np.ones_like(self.settings.z_vec)*GCforfieldinself.mpdata.fields:self.mpdata[field].advector.get_component(0)[:]=advector_0self.mpdata[field].advance(1)thermo=self.set_thermo(thermo)returnthermo