Module diskchef.physics.physmodels
Classes
class ReadAndesPhysData (star_mass: Unit("solMass") = <Quantity 1. solMass>, xray_plasma_temperature: Unit("K") = <Quantity 10000000. K>, xray_luminosity: Unit("erg / s") = <Quantity 1.e+31 erg / s>, cr_padovani_use_l: bool = False, folder: Union[str, os.PathLike] = None, index: int = 0, time_mark: Unit("s") = <Quantity 0. s>, age: Unit("Myr") = <Quantity 1. Myr>, read_envelope: bool = False, dim: Literal['2d', '3d'] = '2d', coord_type: Literal['z', 'zr'] = 'zr')-
Class to read a version of ANDES (accounting for jets + no chemistry) output for following usage in
diskchef.mapsIn testingExpand source code
class ReadAndesPhysData(PhysicsBase): """ Class to read a version of ANDES (accounting for jets + no chemistry) output for following usage in `diskchef.maps` In testing """ folder: PathLike = None index: int = 0 time_mark: u.s = 0 * u.s age: u.Myr = 1 * u.Myr read_envelope: bool = False dim: Literal["2d", "3d"] = '2d' coord_type: Literal["z", "zr"] = 'zr' @property def table(self) -> CTable: return self._table def read(self, index: int = None) -> CTable: """Return the associated diskchef.CTable with r, z, and dust and gas properties""" if index is None: index = self.index reader = astropy.io.ascii.get_reader(Reader=astropy.io.ascii.CommentedHeader) reader.header.splitter.delimiter = '|' # if physics[["ir", "iz"]] != chemistry[["ir", "iz"]]: # raise diskchef.engine.exceptions.CHEFRuntimeError("Physics and chemistry tables do not match!") try: self._config = self._config_read(os.path.join(self.folder, "../config.ini")) except FileNotFoundError: self._config = self._config_read(os.path.join(self.folder, "../config_sep.ini")) self.age = float(self._config['last_time_mark [Myr]']) * u.Myr if self.dim == '2d': try: if index == 0: physics = reader.read(os.path.join(self.folder, f"physical_structure_{index:05d}")) else: physics = reader.read(os.path.join(self.folder, f"physical_structure_{index - 1:05d}")) except FileNotFoundError: physics = reader.read(os.path.join(self.folder, f"physical_structure")) table = CTable( [ physics["Radius"] << u.au, physics["Height"] << u.au, ], names=["Radius", "Height"] ) table["Gas temperature"] = physics["Gas temperature"] << (u.K) table["Dust temperature"] = physics["Dust temperature"] << (u.K) if self.dim == '3d': physics = reader.read(os.path.join(self.folder, f"all_data_{index:05d}")) table = CTable( [ physics["Radius"] << u.au, physics["Height"] << u.au, physics["Angle"] << u.rad, ], names=["Radius", "Height", "Phi"], dims='3d' ) table["Gas temperature"] = physics["Temperature"] << (u.K) table["Dust temperature"] = physics["Temperature"] << (u.K) if self.coord_type == 'zr': table["Height to radius"] = np.nan * u.dimensionless_unscaled for izr in physics["iz"]: indices = physics["iz"] == izr table["Height to radius"][indices] = np.nanmedian( physics["Height"][indices] / physics["Radius"][indices]) table["Height"] = table.zr * table.r if self.coord_type == 'z': table["Height to radius"] = table["Height"]/table.r table["Distance to star"] = np.sqrt(table.r ** 2 + table.z ** 2) table["Gas density"] = physics["Gas density"] << (u.g / u.cm ** 3) table["Dust density"] = physics["Dust density"] << (u.g / u.cm ** 3) if self.read_envelope: try: if self.dim == '2d': envelope_mask_table = astropy.io.ascii.read(os.path.join(self.folder, f"Envelope_test1.dat")) if np.any(envelope_mask_table[["ir", "iz"]] != physics[["ir", "iz"]]): raise diskchef.engine.exceptions.CHEFRuntimeError("Physics and envelope tables do not match!") table["Envelope mask"] = envelope_mask_table['is_envelope'] elif self.dim == '3d': table["Envelope mask"] = physics["env"] except FileNotFoundError: self.logger.info("Envelope mask file not found. Assuming no envelope") table["Envelope mask"] = np.zeros(len(table['Gas density'])) dust_types = np.sort(np.unique(table["Envelope mask"])) if len(dust_types) > 1: for dt in dust_types: dtmask = table["Envelope mask"] == dt table[f"Dust density {dt}"] = table[f"Dust density"] table[f"Dust temperature {dt}"] = table[f"Dust temperature"] table[f"Dust density {dt}"][~dtmask] = 0 table[f"Dust temperature {dt}"][~dtmask] = 0 else: table["Envelope mask"] = np.zeros(len(table['Gas density'])) dust_types = np.sort(np.unique(table["Envelope mask"])) if len(dust_types) > 1: for dt in dust_types: dtmask = table["Envelope mask"] == dt table[f"Dust density {dt}"] = table[f"Dust density"] table[f"Dust temperature {dt}"] = table[f"Dust temperature"] table[f"Dust density {dt}"][~dtmask] = 0 table[f"Dust temperature {dt}"][~dtmask] = 0 if self.dim == '2d': if self.coord_type == 'zr': table.sort(['Height to radius', 'Radius']) elif self.coord_type == 'z': table.sort(['Height', 'Radius']) elif self.dim == '3d': if self.coord_type == 'zr': table.sort(['Phi', 'Height to radius', 'Radius']) elif self.coord_type == 'z': table.sort(['Phi', 'Height', 'Radius']) try: self.physics = diskchef.physics.base.PhysicsBase( star_mass=float(self._config['stellar mass [MSun]']) * u.solMass, ) except KeyError: self.physics = diskchef.physics.base.PhysicsBase( star_mass=(float(self._config['stellar mass 1 [MSun]'])+float(self._config['stellar mass 2 [MSun]'])) * u.solMass, ) self.physics.table = table return table def __post_init__(self): super().__post_init__() self._table = self.read() def _config_read(self, path: PathLike) -> dict: out = {} with open(path, 'r') as configfile: for line in configfile.readlines(): if len(line.split('::')) == 1: continue value, key = [entry.strip() for entry in line.split('::')] out[key] = value return out def recalc_dust_dens(self): dust_types = np.sort(np.unique(self.table["Envelope mask"])) if len(dust_types) > 1: for dt in dust_types: dtmask = self.table["Envelope mask"] == dt self.table[f"Dust density {dt}"] = self.table[f"Dust density"] self.table[f"Dust temperature {dt}"] = self.table[f"Dust temperature"] self.table[f"Dust density {dt}"][~dtmask] = 0 self.table[f"Dust temperature {dt}"][~dtmask] = 0Ancestors
Class variables
var age : Unit("Myr")var coord_type : Literal['z', 'zr']var dim : Literal['2d', '3d']var folder : Union[str, os.PathLike]var index : intvar read_envelope : boolvar time_mark : Unit("s")
Methods
def read(self, index: int = None) ‑> CTable-
Return the associated diskchef.CTable with r, z, and dust and gas properties
def recalc_dust_dens(self)
Inherited members
class ReadGFARGO2Data (star_mass: Unit("solMass") = <Quantity 1. solMass>, xray_plasma_temperature: Unit("K") = <Quantity 10000000. K>, xray_luminosity: Unit("erg / s") = <Quantity 1.e+31 erg / s>, cr_padovani_use_l: bool = False, folder: Union[str, os.PathLike] = None, index: int = 0, zr_max: float = 1, nzr: int = 10, rho_grain: Unit("g / cm3") = <Quantity 3. g / cm3>)-
Class to read Hurakan output for following usage in
diskchef.mapsUnfinishedExpand source code
class ReadGFARGO2Data(PhysicsBase): """ Class to read Hurakan output for following usage in `diskchef.maps` Unfinished """ folder: PathLike = None index: int = 0 zr_max: float = 1 nzr: int = 10 rho_grain: u.g/u.cm**3 = 3 * u.g/u.cm**3 @property def table(self) -> CTable: return self._table def read(self, index: int = None) -> CTable: """Return the associated diskchef.CTable with r, z, and dust and gas properties""" if index is None: index = self.index self.config = self._config_read() radii_edges = np.array( [self.config['Rmin'] * np.exp(i / self.config['Nrad'] * np.log(self.config['Rmax'] / self.config['Rmin'])) for i in range(self.config['Nrad'] + 1)]) radii_points = np.sqrt(radii_edges[1:]*radii_edges[:-1]) phi_edges = np.array([2 * np.pi * i / self.config['Nsec'] for i in range(self.config['Nsec'] + 1)]) phi_points = 0.5*(phi_edges[1:] + phi_edges[:-1]) zr_edges = np.linspace(0, self.zr_max, self.nzr+1) zr_points = 0.5*(zr_edges[1:]+zr_edges[:-1]) ZR, R, PHI = np.meshgrid(zr_points, radii_points, phi_points, indexing='ij') R = R * u.au Z = ZR * R PHI = PHI * u.rad R_2D, PHI_2D = np.meshgrid(radii_points, phi_points, indexing='ij') gas_surf_dens = np.fromfile(os.path.join(self.folder, f'gas_dens_{index:06d}.dat')) gas_surf_dens_2D = np.reshape(gas_surf_dens, (self.config['Nrad'], self.config['Nsec'])) self.gas_surf_dens = gas_surf_dens_2D gas_surf_dens = np.repeat(gas_surf_dens_2D[np.newaxis, :, :], self.nzr, axis=0) * u.Msun / u.au**2 ndust = len(self.config['DustSizeBin']) dust_surf_dens = [] nstokes = [] self.dust_sizes = [] self.dust_surf_dens = [] for i in range(ndust): temp_data = np.fromfile(os.path.join(self.folder, f'dust_dens_s{i}_{index:06d}.dat')) temp_data = np.reshape(temp_data, (self.config['Nrad'], self.config['Nsec'])) self.dust_surf_dens.append(temp_data) temp_data = np.repeat(temp_data[np.newaxis, :, :], self.nzr, axis=0) * u.Msun / u.au**2 dust_surf_dens.append(temp_data) if self.config['DustConstStokes'] == 'YES': nstokes.append(np.zeros((self.nzr, self.config['Nrad'], self.config['Nsec'])) + self.config['DustSizeBin'][i]) dsz_distro = (2/np.pi * self.config['DustSizeBin'][i] * gas_surf_dens / self.rho_grain[i]).to(u.cm) self.dust_sizes.append(np.max(dsz_distro)) else: self.dust_sizes.append(self.config['DustSizeBin'][i] * u.cm) nst = (np.pi/2 * self.rho_grain[i] * self.config['DustSizeBin'][i] * u.cm / gas_surf_dens).to(u.dimensionless_unscaled).value nstokes.append(nst) if self.config['Adiabatic'] == 'YES': gas_energy = np.fromfile(os.path.join(self.folder, f'gas_energy_{index:06d}.dat')) gas_energy_2D = np.reshape(gas_energy, (self.config['Nrad'], self.config['Nsec'])) gas_energy = np.repeat(gas_energy_2D[np.newaxis, :, :], self.nzr, axis=0) * u.Msun / u.au**3 # check the real units !! cs_sq = (self.config['AdiabaticIndex']-1)*gas_energy/gas_surf_dens cs_sq_dust = [] for i in range(ndust): cs_sq_dust.append(cs_sq * (self.config['AlphaViscosity']/(self.config['AlphaViscosity']+nstokes[i]))) if self.config['Adiabatic'] == 'NO': raise CHEFNotImplementedError("Not written for now") # gas_temperature = 2.35 * c.m_p / c.k_B * cs_sq self.gas_aspect_ratio = np.sqrt(cs_sq*R).to(u.dimensionless_unscaled).value self.dust_aspect_ratio = [np.sqrt(cs_sq_dust[i]*R).to(u.dimensionless_unscaled).value for i in range(ndust)] f_gas = np.exp(-1/cs_sq*(1/R - 1/np.sqrt(R**2 + Z**2))) f_int = 2*np.trapz(f_gas, x=Z, axis=0) f_int = np.repeat(f_int[np.newaxis, :, :], self.nzr, axis=0) gas_dens = gas_surf_dens * f_gas / f_int dust_dens = [] for i in range(ndust): f = np.exp(-1 / cs_sq_dust[i] * (1 / R - 1 / np.sqrt(R ** 2 + Z ** 2))) f_int = 2*np.trapz(f, x=Z, axis=0) f_int = np.repeat(f_int[np.newaxis, :, :], self.nzr, axis=0) dust_dens.append(dust_surf_dens[i]*f/f_int) table = CTable( [ R.flatten(), Z.flatten(), PHI.flatten(), ], names=["Radius", "Height", 'Phi'], coord_base='cylinder', dims='3d', edges=[radii_edges*u.au, zr_edges, phi_edges*u.rad] ) table['Height to radius'] = ZR.flatten() table['Distance to star'] = np.sqrt(table['Radius']**2 + table['Height']**2) table['Gas density'] = gas_dens.flatten() table.dust_list = [ DustPopulationOptool(opacity_file=f'{self.folder}/dustkappa_{self.dust_sizes[i].value:.2f}.inp', table=table, name=f'{self.dust_sizes[i].value:.2f}', size=self.dust_sizes[i]) for i in range(len(self.dust_sizes))] for i in range(ndust): table[f'{table.dust_list[i].name} density'] = dust_dens[i].flatten() # if not self.isotherm: # table['Gas temperature'] = gas_temperature.flatten() # for i in range(ndust): # table[f'Dust temperature {i}'] = gas_temperature.flatten() table.sort(['Phi', 'Height to radius', 'Radius']) return table def _config_read(self): cfg = np.loadtxt(os.path.join(self.folder, 'disk.cfg'), dtype='str', usecols=(0, 1)) cfg = {key: value for key, value in cfg} for key in cfg: try: if ',' in cfg[key]: cfg[key] = cfg[key].split(',') if 'N' in key: cfg[key] = int(cfg[key]) else: cfg[key] = np.float64(cfg[key]) except ValueError: continue if type(cfg['DustSizeBin']) == np.float64: cfg['DustSizeBin'] = [cfg['DustSizeBin']] if type(cfg['DustMassBin']) == np.float64: cfg['DustMassBin'] = [cfg['DustMassBin']] return cfg def __post_init__(self): super().__post_init__() self._table = self.read()Ancestors
Class variables
var folder : Union[str, os.PathLike]var index : intvar nzr : intvar rho_grain : Unit("g / cm3")var zr_max : float
Methods
def read(self, index: int = None) ‑> CTable-
Return the associated diskchef.CTable with r, z, and dust and gas properties
Inherited members
class ReadHurakanData (star_mass: Unit("solMass") = <Quantity 1. solMass>, xray_plasma_temperature: Unit("K") = <Quantity 10000000. K>, xray_luminosity: Unit("erg / s") = <Quantity 1.e+31 erg / s>, cr_padovani_use_l: bool = False, folder: Union[str, os.PathLike] = None, index: int = 0, time_mark: Unit("s") = <Quantity 0. s>, age: Unit("Myr") = <Quantity 1. Myr>, read_envelope: bool = False)-
Class to read Hurakan output for following usage in
diskchef.mapsUnfinishedExpand source code
class ReadHurakanData(PhysicsBase): """ Class to read Hurakan output for following usage in `diskchef.maps` Unfinished """ folder: PathLike = None index: int = 0 time_mark: u.s = 0 * u.s age: u.Myr = 1 * u.Myr read_envelope: bool = False @property def table(self) -> CTable: return self._table def read(self, index: int = None) -> CTable: """Return the associated diskchef.CTable with r, z, and dust and gas properties""" if index is None: index = self.index physics = astropy.io.ascii.read(os.path.join(self.folder, f"result-{index:04d}.dat"), header_start=3, data_start=4)#, data_end=-101) theta_zeros = physics["Theta"] == 0 physics["Theta"][theta_zeros] = np.abs(np.pi - physics["Theta"][-1]) # physics = physics[~theta_zeros] # Will need fixing !!! table = CTable( [ physics["R"] << u.cm, physics["Theta"] << u.rad, ], names=["Distance to star", "Theta"], coord_base='sphere', coord_style='edge' ) self._config = astropy.io.ascii.read(os.path.join(self.folder, f"result-{index:04d}.dat"), data_end=3) self.time_mark = self._config['col2'][1] * u.s table["Height"] = table.d * np.cos(table.theta) table["Radius"] = table.d * np.sin(table.theta) table["Height to radius"] = np.tan(np.pi/2*u.rad - table.theta) table["Gas density"] = physics["Rho"] << (u.g / u.cm ** 3) table["Dust density"] = table["Gas density"]/100 table["Gas temperature"] = physics["T"] << (u.K) table["Dust temperature"] = table["Gas temperature"] if self.read_envelope: #to be done try: envelope_mask_table = astropy.io.ascii.read(os.path.join(self.folder, f"envelope_{0:05d}")) if np.any(envelope_mask_table[["ir", "iz"]] != physics[["ir", "iz"]]): raise diskchef.engine.exceptions.CHEFRuntimeError("Physics and envelope tables do not match!") table["Envelope mask"] = envelope_mask_table['is_envelope'] except FileNotFoundError: self.logger.info("Envelope mask file not found. Assuming no envelope") table["Envelope mask"] = np.zeros(len(table['Gas density'])) else: table["Envelope mask"] = np.zeros(len(table['Gas density'])) table.sort(['Height to radius', 'Radius']) self.physics = diskchef.physics.base.PhysicsBase( star_mass=float(self._config['col2'][2]) * u.g, ) self.physics.table = table return table def __post_init__(self): super().__post_init__() self._table = self.read()Ancestors
Class variables
var age : Unit("Myr")var folder : Union[str, os.PathLike]var index : intvar read_envelope : boolvar time_mark : Unit("s")
Methods
def read(self, index: int = None) ‑> CTable-
Return the associated diskchef.CTable with r, z, and dust and gas properties
Inherited members