"""Handling of .pickle/.db CIA files."""importpickle# noqa: S403importtypingastfrompathlibimportPathimportnumpyasnpimportnumpy.typingasnptfromtaurex.util.mathimportinterp_lin_onlyfrom.ciaimportCIA
[docs]classPickleCIA(CIA):"""Class for using pickled (``.db``) collisionally induced absorptions. Very simple since the format is simple Parameters ---------- filename : str Path to pickle pair_name : str , optional Whilst the name of the pair is determined by the pickle filename since these can be different you can optionally force the name through this parameter """def__init__(self,filename:str,pair_name:t.Optional[t.Union[str,None]]=None,):"""Initialize PickleCIA. Parameters ---------- filename : str Path to pickle pair_name : str , optional Whilst the name of the pair is determined by the pickle filename since these can be different you can optionally force the name through this parameter """ifpair_nameisNone:pair_name=Path(filename).stemsuper().__init__("PickleCIA",pair_name)self._filename=filenameself._molecule_name=Noneself._spec_dict=Noneself._load_pickle_file(filename)def_load_pickle_file(self,filename:str)->None:"""Loads pickle file. Parameters ---------- filename : str Path to pickle cia file """fromtaurex.cacheimportGlobalCachefromtaurex.mpiimportallocate_as_sharedfromtaurex.mpiimporthas_mpifromtaurex.mpiimportshared_rankuse_shared=bool(GlobalCache()["mpi_use_shared"])sh_root=(nothas_mpi())orshared_rank()==0ifuse_sharedandnotsh_root:xsec_arr=Nonewn_arr=Nonetemp_arr=Noneelse:# Load the pickle fileself.info("Loading cia cross section from %s",filename)withopen(filename,"rb")asf:self._spec_dict=pickle.load(f,encoding="latin1")# noqa: S301# Extract arrays and free the pickle dict immediately.# This avoids holding two copies (pickle dict + extracted# arrays) simultaneously during the shared-memory copy below.xsec_arr=self._spec_dict["xsecarr"]wn_arr=self._spec_dict["wno"]temp_arr=self._spec_dict["t"]self._spec_dict=None# Move CIA cross-section array into MPI shared memory so that# all ranks on the same node share one copy instead of each# loading their own.ifuse_shared:self._xsec_grid=allocate_as_shared(xsec_arr,logger=self)self._wavenumber_grid=allocate_as_shared(wn_arr,logger=self)self._temperature_grid=allocate_as_shared(temp_arr,logger=self)else:self._xsec_grid=xsec_arrself._wavenumber_grid=wn_arrself._temperature_grid=temp_arr@propertydefwavenumberGrid(self)->npt.NDArray[np.float64]:# noqa: N802"""Native wavenumber grid. Returns ------- :obj:`array` Native wavenumber grid """returnself._wavenumber_grid@propertydeftemperatureGrid(self)->npt.NDArray[np.float64]:# noqa: N802"""Native temperature grid in Kelvin. Returns ------- :obj:`array` Native temperature grid in Kelvin """returnself._temperature_grid
[docs]deffind_closest_temperature_index(self,temperature:float)->t.Tuple[int,int]:"""Finds the nearest indices for a particular temperature. Parameters ---------- temperature : float Temeprature in Kelvin Returns ------- t_min : int index on temprature grid to the left of ``temperature`` t_max : int index on temprature grid to the right of ``temperature`` """fromtaurex.utilimportfind_closest_pairt_min,t_max=find_closest_pair(self.temperatureGrid,temperature)returnt_min,t_max
[docs]definterp_linear_grid(self,temperature:float,t_idx_min:int,t_idx_max:int)->float:"""For a given temperature and indicies. Interpolate the cross-sections linearly from temperature grid to temperature ``T`` Parameters ---------- temperature : float Temeprature in Kelvin t_idx_min : int index on temprature grid to the left of ``temperature`` t_idx_max : int index on temprature grid to the right of ``temperature`` Returns ------- out : :obj:`array` Interpolated cross-section """iftemperature>self._temperature_grid.max():returnself._xsec_grid[-1]eliftemperature<self._temperature_grid.min():returnself._xsec_grid[0]temp_max=self._temperature_grid[t_idx_max]temp_min=self._temperature_grid[t_idx_min]fx0=self._xsec_grid[t_idx_min]fx1=self._xsec_grid[t_idx_max]returninterp_lin_only(fx0,fx1,temperature,temp_min,temp_max)
[docs]defcompute_cia(self,temperature:float)->npt.NDArray[np.float64]:"""Computes the collisionally induced absorption cross-section. Uses our native temperature and cross-section grids Parameters ---------- temperature : float Temperature in Kelvin Returns ------- out : :obj:`array` Temperature interpolated cross-section """indicies=self.find_closest_temperature_index(temperature)returnself.interp_linear_grid(temperature,*indicies)