def test_ionization_shells(): """Tests that the ionization shells have the correct shape and units.""" settings = read_input('data/materials/pmma.yaml') if not check_settings(settings, cstool_model): raise ValueError("Parsed settings do not conform the model.") shells = ionization_shells(settings) assert len(shells) > 0 for shell in shells: assert shell['B'].dimensionality == units('eV').dimensionality assert shell['K'].dimensionality == units('eV').dimensionality assert shell['cs'].dimensionality == units('m^2').dimensionality
def branch_loss(c_s, alpha, lattice, T): """Compute the net average energy loss of phonons. :param c_s_lo: speed of sound for longitudinal mode (m/s) :param alpha_lo: relates to the bending of the dispersion relation towards the Brillouin zone boundary for longitudinal mode (m²/s) :param lattice: Lattice spacing (A) :param T: Temperature (K) """ # Wave factor at 1st Brillouin Zone Boundary k_BZ = 2 * np.pi / lattice h_bar_m = units('1 hbar').to('J s').magnitude k_BZ_m = k_BZ.to('1/m').magnitude c_s_m = c_s.to('m/s').magnitude alpha_m = alpha.to('m^2/s').magnitude kT_m = (1 * units.k * T).to('J').magnitude # Calculate average net loss per acoustic scattering event # Isotropic Dispersion Relation, Verduin (Eq. 3.112) def h_bar_w_AC(k): return h_bar_m * (c_s_m * k - alpha_m * k**2) # Verduin Eq. 3.114 # Bose-Einstein distribution, Verduin (Eq. 3.117) def N_BE(k): return 1. / np.expm1(h_bar_w_AC(k) / kT_m) # (Verduin Eq. 3.116) def nominator(k): return h_bar_w_AC(k) * k**2 def denominator(k): return (2 * N_BE(k) + 1) * k**2 # TO DO: strip the units https://pint.readthedocs.io/en/0.7.2/wrapping.html y1, err1 = quad(nominator, 0, k_BZ_m) y2, err2 = quad(denominator, 0, k_BZ_m) # TO DO: assign the units back return ((y1 / y2) * units('J')).to('eV')
def test_outer_shell_energies(): """Tests that the outer shell energies have the correct units.""" settings = read_input('data/materials/pmma.yaml') if not check_settings(settings, cstool_model): raise ValueError("Parsed settings do not conform the model.") fn = outer_shell_energies(settings) K = np.logspace(1, 4, 100) * units.eV osi = fn(K) assert osi.shape == (100, ) assert osi.dimensionality == units('eV').dimensionality
def test_phonon_cs_fn_dual(): """Tests that the phonon subroutine returns a function that can handle arrays and returns correct units.""" settings = read_input('data/materials/pmma.yaml') if not check_settings(settings, cstool_model): raise ValueError("Parsed settings do not conform the model.") fn = phonon_cs_fn(settings) W = np.logspace(-2, 3, 100) * units.eV theta = np.linspace(0, np.pi, 100) * units.rad cs = fn(theta, W[:, None]) assert cs.shape == (100, 100) assert cs.dimensionality == units('m²/sr').dimensionality
def test_inelastic_cs_fn(): """Tests that the inelastic subroutine returns a function that can handle arrays and returns correct units.""" settings = read_input('data/materials/pmma.yaml') if not check_settings(settings, cstool_model): raise ValueError("Parsed settings do not conform the model.") fn = inelastic_cs_fn(settings) K = np.logspace(1, 4, 100) * units.eV W = np.logspace(-4, 4, 100) * units.eV cs = fn(K, W[:, None]) print(cs) assert cs.shape == (100, 100) assert cs.dimensionality == units('m²/eV').dimensionality
def elastic_cs_fn(a, E): return log_interpolate( lambda E: phonon_cs_fn(s)(a, E).to('cm^2').magnitude, lambda E: mcs.unsafe(a, E.to('eV').magnitude.flat), lambda x: x, 100 * units.eV, 200 * units.eV)(E) * units('cm^2/rad')
def compute_elastic_tcs_icdf(dcs, P): def integrant(theta): return dcs(theta) * 2 * np.pi * np.sin(theta) return compute_tcs_icdf(integrant, 0 * units('rad'), np.pi * units('rad'), P)
tcs, icdf = compute_inelastic_tcs_icdf( dcs, p_inel, s.elf_file.get_min_energy(), w0_max, s.elf_file.get_min_energy_interval()) inel_tcs[i] = tcs.to('m^2') inel_icdf[i] = icdf.to('eV') print('.', end='', flush=True) print() # ionization e_ion = np.logspace(0, 4, 1024) * units.eV p_ion = np.linspace(0.0, 1.0, 1024) print("# Computing ionization energy probabilities") shells = ionization_shells(s) tcstot_at_K = np.zeros(e_ion.shape) * units('m^2') for shell in shells: shell['cs_at_K'] = np.zeros(e_ion.shape) * units('m^2') margin = 10 * units.eV i_able = ((e_ion + margin) > shell['B']) j_able = (shell['K'] > shell['B']) & (shell['cs'] > 0 * units('m^2')) shell['cs_at_K'][i_able] = ion_loglog_interp( shell['K'][j_able], shell['cs'][j_able])( (e_ion + margin)[i_able]).to('m^2') tcstot_at_K += shell['cs_at_K'] Pcum_at_K = np.zeros(e_ion.shape) for shell in shells: shell['P_at_K'] = np.zeros(e_ion.shape) i_able = (tcstot_at_K > 0 * units('m^2')) shell['P_at_K'][
generator=lambda v: v if v is None else '{:~P}'.format(v), parser=lambda s: s if s is None else units.parse_expression(s)) element_model = Model([ ('count', Type("Integer abundance", default=None, check=is_integer)), ('Z', Type("Atomic number", default=None, check=is_integer)), ('M', quantity("Molar mass", 'g/mol')) ]) phonon_branch_model = Model([ ('alpha', maybe_quantity( "Bending in dispersion relation. (TV Eq. 3.112)", 'm²/s', default=units('0 m²/s'))), ('eps_ac', quantity("Accoustic deformation potential", 'eV')), ('c_s', quantity("Speed of sound", 'km/s'))]) phonon_model = Model([ ('model', Type( "Whether the model is the `single` or `dual` mode.", check=is_('single') | is_('dual'), default="single")), ('m_eff', maybe_quantity( "Effective mass.", 'g', default=units('1 m_e'))), ('m_dos', maybe_quantity( "Density of state mass.", 'g', default=units('1 m_e'))), ('lattice', quantity("Lattice spacing", 'Å')), ('single', ModelType(
def dataset_units(dataset): return np.array(dataset) * units(dataset.attrs['units'])
help="Filename of material in HDF5 format.") parser.add_argument('--elastic', action='store_true') parser.add_argument('--inelastic', action='store_true') parser.add_argument('--ionization', action='store_true') parser.add_argument('--mfp', action='store_true', help='Plot mean-free-path instead of cross-section.') args = parser.parse_args() infile = h5.File(args.material_file, 'r') properties = {} for x in infile['properties']: name = x[0].decode('ASCII') value = float(x[1]) * units(x[2].decode('ASCII')) properties[name] = value print('properties:') for name, value in properties.items(): print('{: <16} {}'.format(name, value)) print() if not (args.elastic or args.inelastic or args.ionization): print('Not plotting anything. Use the -h flag for usage.') if args.mfp: rho = properties['density'] def dataset_units(dataset): return np.array(dataset) * units(dataset.attrs['units'])