def test_actual_to_renate_idl(self): for test_case in self.test_cases: path = os.path.join('test_dataset', 'crm_systemtests', 'archive', 'renate_idl', test_case + '.xml') reference = Beamlet(data_path=path, solver='disregard') actual_source = reference.copy(object_copy='without-results') actual = Beamlet(param=actual_source.param, profiles=actual_source.profiles, components=actual_source.components, atomic_db=actual_source.atomic_db, solver='numerical') msg = 'Failure for following test case: ' + test_case + '\n' self.assertAlmostEqualRateEvolution( actual, reference, precision=self.EXPECTED_PRECISION, msg=msg)
def test_profiles(self): actual = Beamlet(solver='disregard') self.assertIsInstance( actual.profiles, pandas.core.frame.DataFrame, msg='Expected data type of profiles is: pandas DataFrame.') self.assertEqual( len(actual.profiles), self.EXPECTED_PROFILES_LENGTH, msg='Expected profile length for test case does not match.') self.assertTupleEqual( actual.profiles.shape, (self.EXPECTED_PROFILES_LENGTH, 2 * len(self.EXPECTED_COMPONENTS_KEYS) + 1), msg='Plasma description lacks necessary' ' density and/or temperature profiles for all components.') self.assertIsInstance( actual.profiles.axes[0], pandas.Int64Index, msg='Expected data type of X - axis for profiles is Int64Index.') self.assertIsInstance( actual.profiles.axes[1], pandas.MultiIndex, msg='Expected data type of Y - axis for profiles is MultiIndex.') for key in range(len(actual.profiles.keys())): self.assertTupleEqual( actual.profiles.keys()[key], self.EXPECTED_PROFILES_KEYS[key], msg='Profiles key description fails for test case.')
def _compute_all_benchmarks(self): for test_case in self.test_cases: test_path = self.test_path + '/' + self.actual_folder + '/' + test_case + '.xml' reference = Beamlet(data_path=test_path, solver='disregard') actual_source = reference.copy(object_copy='without-results') actual = Beamlet(param=actual_source.param, profiles=actual_source.profiles, components=actual_source.components, atomic_db=actual_source.atomic_db, solver='numerical') actual.compute_linear_density_attenuation() actual.compute_linear_emission_density() actual.compute_relative_populations() self.write.write_beamlet_profiles(actual, subdir=self.release_folder + '/')
def test_actual_to_previous_release(self): for test_case in self.test_cases: path = os.path.join('test_dataset', 'crm_systemtests', 'actual', test_case + '.xml') reference = Beamlet(data_path=path, solver='disregard') actual_source = reference.copy(object_copy='without-results') actual = Beamlet(param=actual_source.param, profiles=actual_source.profiles, components=actual_source.components, atomic_db=actual_source.atomic_db, solver='numerical') msg = 'Failure for following test case: ' + test_case + '\n' self.assertAlmostEqualRateEvolution( actual, reference, precision=self.EXPECTED_PRECISION, msg=msg) actual.compute_linear_density_attenuation() self.assertAlmostEqualBeamAttenuation( actual, reference, precision=self.EXPECTED_PRECISION, msg=msg) actual.compute_linear_emission_density() self.assertAlmostEqualEmissionDensity( actual, reference, precision=self.EXPECTED_PRECISION, msg=msg) actual.compute_relative_populations() self.assertAlmostEqualRelativePopulation( actual, reference, precision=self.EXPECTED_PRECISION, msg=msg)
def __init__(self, plasma, beam): # TODO - input variable validation # build species specifications, starting with electrons charges = [-1] charges.extend( [s.charge for s in plasma.composition if not s.charge == 0]) nuclear_charges = [0] nuclear_charges.extend([ s.element.atomic_number for s in plasma.composition if not s.charge == 0 ]) atomic_weights = [0] atomic_weights.extend([ int(s.element.atomic_weight) for s in plasma.composition if not s.charge == 0 ]) index = ['electron'] index.extend( ['ion{}'.format(i + 1) for i in range(len(atomic_weights) - 1)]) components = pd.DataFrame(data={ 'q': charges, 'Z': nuclear_charges, 'A': atomic_weights }, index=index) # sample plasma parameters along the beam axis beam_axis = np.linspace(0, beam.length, num=500) beam_to_world = beam.to_root() num_params = 1 + 2 + len( plasma.composition ) * 2 # *2 since every species has density and temperature profiles = np.zeros((num_params, 500)) type_labels = [] property_labels = [] unit_labels = [] profiles[0, :] = beam_axis type_labels.append('beamlet grid') property_labels.append('distance') unit_labels.append('m') profiles[1, :] = _sample_along_beam_axis( plasma.electron_distribution.density, beam_axis, beam_to_world, debug=True) type_labels.append('electron') property_labels.append('density') unit_labels.append('m-3') profiles[2, :] = _sample_along_beam_axis( plasma.electron_distribution.effective_temperature, beam_axis, beam_to_world) type_labels.append('electron') property_labels.append('temperature') unit_labels.append('eV') for i, species in enumerate(plasma.composition): profiles[i * 2 + 3, :] = _sample_along_beam_axis( species.distribution.density, beam_axis, beam_to_world) type_labels.append('ion{}'.format(i)) property_labels.append('density') unit_labels.append('m-3') profiles[i * 2 + 4, :] = _sample_along_beam_axis( species.distribution.effective_temperature, beam_axis, beam_to_world) type_labels.append('ion{}'.format(i)) property_labels.append('temperature') unit_labels.append('eV') profiles = np.swapaxes(profiles, 0, 1) row_index = [i for i in range(500)] column_index = pd.MultiIndex.from_arrays( [type_labels, property_labels, unit_labels], names=['type', 'property', 'unit']) profiles = pd.DataFrame(data=profiles, columns=column_index, index=row_index) # construct beam param specification xml = etree.Element('xml') head = etree.SubElement(xml, 'head') id_tag = etree.SubElement(head, 'id') id_tag.text = 'beamlet_test' body_tag = etree.SubElement(xml, 'body') beamlet_energy = etree.SubElement(body_tag, 'beamlet_energy', {'unit': 'keV'}) beamlet_energy.text = str(int(beam.energy / 1000)) beamlet_species = etree.SubElement(body_tag, 'beamlet_species') beamlet_species.text = beam.element.symbol beamlet_source = etree.SubElement(body_tag, 'beamlet_source') beamlet_source.text = 'beamlet/test_impurity.h5' beamlet_current = etree.SubElement(body_tag, 'beamlet_current', {'unit': 'A'}) beamlet_current.text = '0.001' beamlet_mass = etree.SubElement(body_tag, 'beamlet_mass', {'unit': 'kg'}) beamlet_mass.text = '1.15258e-026' beamlet_velocity = etree.SubElement(body_tag, 'beamlet_velocity', {'unit': 'm/s'}) beamlet_velocity.text = '1291547.1348855693' beamlet_profiles = etree.SubElement(body_tag, 'beamlet_profiles', {}) beamlet_profiles.text = './beamlet_test.h5' param = etree.ElementTree(element=xml) # move this outside # from crm_solver.atomic_db import AtomicDB # renata_ad = AtomicDB(param=param) b = Beamlet(param=param, profiles=profiles, components=components) b.compute_linear_density_attenuation() b.compute_relative_populations() self.renate_beamlet = b
xml = etree.Element('xml') head = etree.SubElement(xml, 'head') id_tag = etree.SubElement(head, 'id') id_tag.text = 'beamlet_test' body_tag = etree.SubElement(xml, 'body') beamlet_energy = etree.SubElement(body_tag, 'beamlet_energy', {'unit': 'keV'}) beamlet_energy.text = '100' beamlet_species = etree.SubElement(body_tag, 'beamlet_species') beamlet_species.text = 'H' # Li beamlet_source = etree.SubElement(body_tag, 'beamlet_source') beamlet_source.text = 'beamlet/test_impurity.h5' beamlet_current = etree.SubElement(body_tag, 'beamlet_current', {'unit': 'A'}) beamlet_current.text = '0.001' beamlet_mass = etree.SubElement(body_tag, 'beamlet_mass', {'unit': 'kg'}) beamlet_mass.text = '1.15258e-026' beamlet_velocity = etree.SubElement(body_tag, 'beamlet_velocity', {'unit': 'm/s'}) beamlet_velocity.text = '1291547.1348855693' beamlet_profiles = etree.SubElement(body_tag, 'beamlet_profiles', {}) beamlet_profiles.text = './beamlet_test.h5' param = etree.ElementTree(element=xml) b = Beamlet(param=param, profiles=profiles, components=components) b.compute_linear_emission_density() b.compute_linear_density_attenuation() b.compute_relative_populations() plt.plot(b.profiles['beamlet grid'], b.profiles['linear_emission_density'])
class BeamletTest(unittest.TestCase): EXPECTED_ATTR = [ 'param', 'components', 'profiles', 'coefficient_matrix', 'atomic_db', 'initial_condition' ] EXPECTED_INITIAL_CONDITION = [ 4832583106.4753895, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] EXPECTED_PARAM_ATTR = [ 'beamlet_source', 'beamlet_energy', 'beamlet_species', 'beamlet_current' ] EXPECTED_COMPONENTS_KEYS = ['q', 'Z', 'A'] EXPECTED_COMPONENTS_SPECIES = ['electron', 'ion1', 'ion2'] EXPECTED_PROFILES_LENGTH = 101 EXPECTED_PROFILES_KEYS = [('beamlet grid', 'distance', 'm'), ('electron', 'density', 'm-3'), ('electron', 'temperature', 'eV'), ('ion1', 'density', 'm-3'), ('ion1', 'temperature', 'eV'), ('ion2', 'density', 'm-3'), ('ion2', 'temperature', 'eV')] EXPECTED_ATTENUATION_KEY = 'linear_density_attenuation' INPUT_TRANSITION = ['2s', '2p', '5s', '5p'] EXPECTED_ELEMENTS_3 = 3 def setUp(self): self.beamlet = Beamlet() def tearDown(self): del self.beamlet def test_attributes(self): for attr in self.EXPECTED_ATTR: assert hasattr(self.beamlet, attr) def test_initial_conditions(self): self.assertIsInstance(self.beamlet.initial_condition, list, msg='Initial condition is of wrong type. ' 'Expected type: list') self.assertEqual( len(self.beamlet.initial_condition), self.beamlet.atomic_db.atomic_ceiling, msg='Initial conditions must match number of atomic levels.') for element in range(len(self.beamlet.initial_condition)): self.assertIsInstance(self.beamlet.initial_condition[element], float, msg='Expected type for initial' ' conditions is float.') self.assertEqual( self.beamlet.initial_condition[element], self.EXPECTED_INITIAL_CONDITION[element], msg= 'Computed Init conditions do not match expected init conditions.' ) def test_param_xml(self): self.assertIsInstance( self.beamlet.param, etree._ElementTree, msg='Expected type for param input is xml elementtree.') for param_attribute in self.EXPECTED_PARAM_ATTR: self.assertIsInstance(self.beamlet.param.getroot().find( 'body').find(param_attribute).text, str, msg='Failed to load or find attribute ' + param_attribute + ' in xml file.') def test_atomic_db(self): self.assertIsInstance( self.beamlet.atomic_db, AtomicDB, msg='Expected data type for the Atomic database is AtomicDB.') def test_components(self): self.assertIsInstance( self.beamlet.components, pandas.core.frame.DataFrame, msg='Expected data type of components is: pandas DataFrame.') description = self.beamlet.components.keys() species = self.beamlet.components.T.keys() self.assertEqual( len(description), self.EXPECTED_ELEMENTS_3, msg='Three keys are expected for species description: q,Z,A.') for key in range(len(description)): self.assertEqual(description[key], self.EXPECTED_COMPONENTS_KEYS[key], msg='The index: ' + description[key] + ' is a mismatch for ' + self.EXPECTED_COMPONENTS_KEYS[key]) self.assertEqual( len(species), len(self.beamlet.atomic_db.ion_impact_loss[0]) + 1, msg= 'The same amount of species description have to be present in components as in profiles.' ) for key in range(len(species)): self.assertEqual(species[key], self.EXPECTED_COMPONENTS_SPECIES[key], msg='Mismatch of expected plasma species.') for component in species: for coordinate in description: self.assertIsInstance( self.beamlet.components[coordinate][component], numpy.int64, msg='Type mismatch of pandas components content.') def test_profiles(self): actual = Beamlet(solver='disregard') self.assertIsInstance( actual.profiles, pandas.core.frame.DataFrame, msg='Expected data type of profiles is: pandas DataFrame.') self.assertEqual( len(actual.profiles), self.EXPECTED_PROFILES_LENGTH, msg='Expected profile length for test case does not match.') self.assertTupleEqual( actual.profiles.shape, (self.EXPECTED_PROFILES_LENGTH, 2 * len(self.EXPECTED_COMPONENTS_KEYS) + 1), msg='Plasma description lacks necessary' ' density and/or temperature profiles for all components.') self.assertIsInstance( actual.profiles.axes[0], pandas.Int64Index, msg='Expected data type of X - axis for profiles is Int64Index.') self.assertIsInstance( actual.profiles.axes[1], pandas.MultiIndex, msg='Expected data type of Y - axis for profiles is MultiIndex.') for key in range(len(actual.profiles.keys())): self.assertTupleEqual( actual.profiles.keys()[key], self.EXPECTED_PROFILES_KEYS[key], msg='Profiles key description fails for test case.') def test_analytical_solver(self): with self.assertRaises(NotImplementedError): actual = Beamlet(solver='analytical') def test_numerical_solver(self): self.assertTupleEqual( self.beamlet.profiles.shape, (self.EXPECTED_PROFILES_LENGTH, 2 * len(self.EXPECTED_COMPONENTS_KEYS) + 1 + self.beamlet.atomic_db.atomic_ceiling), msg= 'Numerical solver failed to provide expected output into plasma profiles.' ) for key_index in range(2 * len(self.EXPECTED_COMPONENTS_KEYS) + 1, len(self.beamlet.profiles.keys())): self.assertEqual( self.beamlet.profiles.keys()[key_index][0], 'level ' + self.beamlet.atomic_db.inv_atomic_dict[ key_index - 2 * len(self.EXPECTED_COMPONENTS_KEYS) - 1], msg= 'Pandas keys for labeling electron population evolution on atomic levels fails.' ) for level in range(self.beamlet.atomic_db.atomic_ceiling): self.assertIsInstance(self.beamlet.profiles[ 'level ' + self.beamlet.atomic_db.inv_atomic_dict[level]], pandas.core.series.Series, msg='Expected data type of beam evolution ' 'process are pandas series.') self.assertEqual( len(self.beamlet.profiles[ 'level ' + self.beamlet.atomic_db.inv_atomic_dict[level]]), self.EXPECTED_PROFILES_LENGTH, msg='Beam evolution calculation are expected to return ' 'atomic state evolution on the input grid.') def test_not_supported_solver(self): with self.assertRaises(Exception): actual = Beamlet(solver='not-supported') def test_attenuation_calculator(self): self.beamlet.compute_linear_density_attenuation() self.assertEqual( self.beamlet.profiles.keys()[-1][0], self.EXPECTED_ATTENUATION_KEY, msg='Beam attenuation key mismatch within pandas data frame.') self.assertIsInstance( self.beamlet.profiles[self.EXPECTED_ATTENUATION_KEY], pandas.core.series.Series, msg= 'Beam attenuation output expected to be stored in pandas series.') self.assertEqual( len(self.beamlet.profiles[self.EXPECTED_ATTENUATION_KEY]), self.EXPECTED_PROFILES_LENGTH, msg= 'Beam attenuation calculation is expected to be returned on the input grid.' ) test = self.beamlet.profiles['level 2s'] for level in range(1, self.beamlet.atomic_db.atomic_ceiling): test += self.beamlet.profiles[ 'level ' + self.beamlet.atomic_db.inv_atomic_dict[level]] for index in range(self.EXPECTED_PROFILES_LENGTH): self.assertEqual( test[index], self.beamlet.profiles[self.EXPECTED_ATTENUATION_KEY][index], msg='Beam attenuation calculation fails for test case.') def test_spontaneous_emission_fail(self): with self.assertRaises(Exception): self.beamlet.profiles[self.EXPECTED_ATTENUATION_KEY].\ compute_linear_emission_density(to_level=self.INPUT_TRANSITION[1], from_level=self.INPUT_TRANSITION[0]) def test_not_supported_atomic_level_fail(self): with self.assertRaises(Exception): self.beamlet.profiles[self.EXPECTED_ATTENUATION_KEY].\ compute_linear_emission_density(to_level=self.INPUT_TRANSITION[2], from_level=self.INPUT_TRANSITION[3]) def test_emission_calculator(self): self.beamlet.compute_linear_emission_density( to_level=self.INPUT_TRANSITION[0], from_level=self.INPUT_TRANSITION[1]) self.assertEqual( self.beamlet.profiles.keys()[-1][0], self.INPUT_TRANSITION[1] + '-->' + self.INPUT_TRANSITION[0], msg= 'Beam emission calculation key mismatch within pandas data frame.') self.assertIsInstance( self.beamlet.profiles[self.INPUT_TRANSITION[1] + '-->' + self.INPUT_TRANSITION[0]], pandas.core.series.Series, msg='Beam emission output expected to ' 'be stored in pandas series.') self.assertEqual( len(self.beamlet.profiles[self.INPUT_TRANSITION[1] + '-->' + self.INPUT_TRANSITION[0]]), self.EXPECTED_PROFILES_LENGTH, msg='Beam emission calculation is expected to be returned ' 'on the input grid.') test = self.beamlet.profiles[ 'level ' + self. INPUT_TRANSITION[1]] * self.beamlet.atomic_db.spontaneous_trans[ self.beamlet.atomic_db.atomic_dict[self.INPUT_TRANSITION[0]], self.beamlet.atomic_db.atomic_dict[self.INPUT_TRANSITION[1]]] for index in range(len(test)): self.assertEqual( test[index], self.beamlet.profiles[self.INPUT_TRANSITION[1] + '-->' + self.INPUT_TRANSITION[0]][index], msg='Beam emission calculation fails for test case.') def test_relative_population_calculator(self): self.beamlet.compute_relative_populations( reference_level=self.INPUT_TRANSITION[0]) self.assertTupleEqual( self.beamlet.profiles.filter(like='rel.pop').shape, (self.EXPECTED_PROFILES_LENGTH, self.beamlet.atomic_db.atomic_ceiling), msg= 'Relative populations calculated do not match input level number.') for level in range(self.beamlet.atomic_db.atomic_ceiling): for index in range(len(self.beamlet.profiles)): if self.beamlet.atomic_db.inv_atomic_dict[ level] == self.INPUT_TRANSITION[0]: self.assertEqual( self.beamlet.profiles['rel.pop ' + self.beamlet.atomic_db. inv_atomic_dict[level]][index], 1.0, msg='Values on reference level are expected to be 1.') else: self.assertLess( self.beamlet.profiles['rel.pop ' + self.beamlet.atomic_db. inv_atomic_dict[level]][index], 1.0, msg= 'Values on comparative levels are expected to be less than 1.' ) def test_beamlet_pandas_copy(self): actual = self.beamlet.copy(object_copy='full') self.assertTupleEqual( actual.components.shape, self.beamlet.components.shape, msg= 'Actual and copy Beamlet object components are expected to have same shape.' ) logic_components = actual.components == self.beamlet.components self.assertTrue( logic_components.values.all(), msg='Content of actual and reference Beamlet components ' 'objects is required to be equal.') self.assertTupleEqual( actual.profiles.shape, self.beamlet.profiles.shape, msg= 'Actual and copy Beamlet object profiles are expected to have the same shape.' ) logic_profiles = actual.profiles == self.beamlet.profiles self.assertTrue(logic_profiles.values.all(), msg='Content of actual and reference Beamlet profiles ' 'objects is required to be equal.') def test_beamlet_pandas_copy_without_results(self): actual = self.beamlet.copy(object_copy='without-results') self.assertTupleEqual( actual.components.shape, self.beamlet.components.shape, msg= 'Copy and Actual Beamlet object components are expected to have same shape.' ) logic_components = actual.components == self.beamlet.components self.assertTrue(logic_components.values.all(), msg='Content of Copy and Actual Beamlet components ' 'objects is required to be equal.') self.assertEqual( actual.profiles.shape[0], self.beamlet.profiles.shape[0], msg= 'Copy and Actual of Beamlet profiles are expected to have the same number of elements.' ) self.assertEqual( actual.profiles.shape[1], self.beamlet.profiles.shape[1] - self.beamlet.atomic_db.atomic_ceiling, msg= 'Copy of Actual Beamlet object profiles is expected to have nr of atomic levels: ' + str(self.beamlet.atomic_db.atomic_ceiling) + ' less columns.') self.assertEqual( actual.profiles.filter(like='level').shape[1], 0, msg= 'The copy without results is expected NOT to contain any columns labeled <level>.' )
def setUp(self): self.beamlet = Beamlet()
def test_not_supported_solver(self): with self.assertRaises(Exception): actual = Beamlet(solver='not-supported')
def test_analytical_solver(self): with self.assertRaises(NotImplementedError): actual = Beamlet(solver='analytical')