diff --git a/pyuff/datasets/dataset_2412.py b/pyuff/datasets/dataset_2412.py index ea46379..adedc1c 100644 --- a/pyuff/datasets/dataset_2412.py +++ b/pyuff/datasets/dataset_2412.py @@ -1,29 +1,35 @@ import numpy as np +import itertools from ..tools import _opt_fields, _parse_header_line, check_dict_for_none def _write2412(fh, dset): try: - elt_type_dict = {'triangle': 3, 'quad': 4} fh.write('%6i\n%6i%74s\n' % (-1, 2412, ' ')) - for elt_type in dset: - if elt_type == "type": - pass - else: - for i in range(len(dset[elt_type]['element_nums'])): - fh.write('%10i%10i%10i%10i%10i%10i\n' % ( - dset[elt_type]['element_nums'][i], - dset[elt_type]['fe_descriptor'][i], - dset[elt_type]['phys_table'][i], - dset[elt_type]['mat_table'][i], - dset[elt_type]['color'][i], - elt_type_dict[elt_type], + for el_type in dset: + if type(el_type) is not int: + # Skip 'type', 'triangle' and 'quad' indices + continue + for elem in dset[el_type]: + fh.write('%10i%10i%10i%10i%10i%10i\n' % ( + elem['element_nums'], + elem['fe_descriptor'], + elem['phys_table'], + elem['mat_table'], + elem['color'], + elem['num_nodes'], + )) + if elem['fe_descriptor'] == 11: + # Rods have to be written in 3 lines - ad additional line here + fh.write('%10i%10i%10i\n' % ( + elem['beam_orientation'], + elem['beam_foreend_cross'], + elem['beam_aftend_cross'] )) - for ii in range(elt_type_dict[elt_type]): - fh.write('%10i' % dset[elt_type]['nodes_nums'][i][ii]) - fh.write('\n') + for ii in elem['nodes_nums']: + fh.write('%10i' % ii) + fh.write('\n') fh.write('%6i\n' % -1) - except: raise Exception('Error writing data-set #2412') @@ -31,32 +37,59 @@ def _write2412(fh, dset): def _extract2412(block_data): """Extract element data - data-set 2412.""" dset = {'type': 2412} - # Define dictionary of possible elements types - # Only 2D non-quadratic elements are supported - elt_type_dict = {'3': 'triangle', '4': 'quad'} + # Define dictionary of possible elements types for legacy interface + elt_type_dict = {41: 'triangle', 44: 'quad'} + # Elements that are seen as rods and read as 3 lines + rods_dict = {11, 21, 22, 23, 24} + # Read data try: split_data = block_data.splitlines() split_data = [a.split() for a in split_data][2:] - # Extract Record 1 - rec1 = np.array(split_data[::2], dtype=int) - # Extract Record 2 - rec2 = split_data[1::2] - # Look for the different types of elements stored in the dataset - elts_types = list(set(rec1[:,5])) - for elt_type in elts_types: - ind = np.where(np.array(rec1[:,5]) == elt_type)[0] + + # Extract Records + i = 0 + while i < len(split_data): dict_tmp = dict() - dict_tmp['element_nums'] = rec1[ind,0].copy() - dict_tmp['fe_descriptor'] = rec1[ind,1].copy() - dict_tmp['phys_table'] = rec1[ind,2].copy() - dict_tmp['mat_table'] = rec1[ind,3].copy() - dict_tmp['color'] = rec1[ind,4].copy() - dict_tmp['nodes_nums'] = np.array([rec2[i] for i in ind], dtype=int).copy().reshape((-1,elt_type)) - dset[elt_type_dict[str(elt_type)]] = dict_tmp + line = split_data[i] + dict_tmp['element_nums'] = int(line[0]) + dict_tmp['fe_descriptor'] = int(line[1]) + dict_tmp['phys_table'] = int(line[2]) + dict_tmp['mat_table'] = int(line[3]) + dict_tmp['color'] = int(line[4]) + dict_tmp['num_nodes'] = int(line[5]) + if dict_tmp['fe_descriptor'] in rods_dict: + # element is a rod and covers 3 lines + dict_tmp['beam_orientation'] = int(split_data[i+1][0]) + dict_tmp['beam_foreend_cross'] = int(split_data[i + 1][1]) + dict_tmp['beam_aftend_cross'] = int(split_data[i + 1][2]) + dict_tmp['nodes_nums'] = [int(e) for e in split_data[i+2]] + i += 3 + else: + # element is no rod and covers 2 lines + dict_tmp['nodes_nums'] = [int(e) for e in split_data[i+1]] + i += 2 + desc = dict_tmp['fe_descriptor'] + if not desc in dset: + dset[desc] = [] + dset[desc].append(dict_tmp) + for num, name in elt_type_dict.items(): + # if we have one of the keys that are enabled for the legacy interface, add everything for that here + if num in dset.keys(): + dset[name] = { + 'element_nums': [e['element_nums'] for e in dset[num]], + 'fe_descriptor': [e['fe_descriptor'] for e in dset[num]], + 'phys_table': [e['phys_table'] for e in dset[num]], + 'mat_table': [e['mat_table'] for e in dset[num]], + 'color': [e['color'] for e in dset[num]], + 'num_nodes': [e['num_nodes'] for e in dset[num]], + 'nodes_nums': [e['nodes_nums'] for e in dset[num]], + } + + return dset + except: raise Exception('Error reading data-set #2412') - return dset def prepare_2412( @@ -67,6 +100,9 @@ def prepare_2412( color=None, num_nodes=None, nodes_nums=None, + beam_orientation=None, + beam_foreend_cross=None, + beam_aftend_cross=None, return_full_dict=False): """Name: Elements @@ -78,7 +114,10 @@ def prepare_2412( :param mat_table: R1 F4, Material property table number :param color: R1 F5, Color, optional :param num_nodes: R1 F6, Number of nodes on element - :param nodes_nums: R2 F1, Node labels defining element + :param nodes_nums: R2 F1 (R3 FOR RODS), Node labels defining element + :param beam_orientation: R2 F1 FOR RODS ONLY, beam orientation node number + :param beam_foreend_cross: R2 F2 FOR RODS ONLY, beam fore-end cross section number + :param beam_aftend_cross: R2 F3 FOR RODS ONLY, beam aft-end cross section number :param return_full_dict: If True full dict with all keys is returned, else only specified arguments are included **Test prepare_2412** @@ -113,6 +152,13 @@ def prepare_2412( raise TypeError('num_nodes must be integer') if np.array(nodes_nums).dtype != int and nodes_nums != None: raise TypeError('nodes_nums must be integer') + if np.array(beam_orientation).dtype != int and beam_orientation != None: + raise TypeError('beam_orientation must be integer') + if np.array(beam_foreend_cross).dtype != int and beam_foreend_cross != None: + raise TypeError('beam_foreend_cross must be integer') + if np.array(beam_aftend_cross).dtype != int and beam_aftend_cross != None: + raise TypeError('beam_aftend_cross must be integer') + dataset={ 'type': 2412, @@ -122,6 +168,9 @@ def prepare_2412( 'mat_table': mat_table, 'color': color, 'num_nodes': num_nodes, + 'beam_orientation': beam_orientation, + 'beam_foreend_cross': beam_foreend_cross, + 'beam_aftend_cross': beam_aftend_cross, 'nodes_nums': nodes_nums } diff --git a/tests/test_2412.py b/tests/test_2412.py index 2cf9cc4..2a32794 100644 --- a/tests/test_2412.py +++ b/tests/test_2412.py @@ -6,15 +6,34 @@ import pyuff def test_read_2412(): + # -- Load small test file uff_ascii = pyuff.UFF('./data/mesh_Oros-modal_uff15_uff2412.uff') a = uff_ascii.read_sets(2) + + # -- Test legacy interface np.testing.assert_array_equal(a['quad']['nodes_nums'][0], np.array([1, 25, 48, 24])) np.testing.assert_array_equal(a['quad']['nodes_nums'][-1], np.array([50, 74, 73, 49])) + # -- Test new interface + np.testing.assert_array_equal(a[44][0]['nodes_nums'], np.array([1, 25, 48, 24])) + np.testing.assert_array_equal(a[44][-1]['nodes_nums'], np.array([50, 74, 73, 49])) + + # -- Load bigger test file with rods + uff_ascii = pyuff.UFF('./data/simcenter_exported_result.uff') + a = uff_ascii.read_sets(2) + + # -- Test new interface + assert all(['type' in a, 21 in a, 91 in a, 94 in a, len(a) == 4]) + np.testing.assert_array_equal(a[21][0]['nodes_nums'], np.array([1894, 1443])) + np.testing.assert_array_equal(a[94][0]['nodes_nums'], np.array([1870, 1046, 1, 946])) + assert sorted(list(a[21][0].keys())) == ['beam_aftend_cross', 'beam_foreend_cross', 'beam_orientation', 'color', 'element_nums', 'fe_descriptor', 'mat_table', 'nodes_nums', 'num_nodes', 'phys_table'] + + def test_read_write_2412_mixed(): # Read dataset 2412 in test file uff_ascii = pyuff.UFF('./data/mesh_test_uff2412_mixed.uff') a = uff_ascii.read_sets(2) + # Test np.testing.assert_array_equal(a['triangle']['nodes_nums'][-1], np.array([3, 6, 11])) np.testing.assert_array_equal(a['quad']['nodes_nums'][-1], np.array([3, 4, 5, 6])) @@ -26,22 +45,26 @@ def test_read_write_2412_mixed(): # Read dataset 2412 in written file uff_ascii = pyuff.UFF('./data/tmp.uff') b = uff_ascii.read_sets(0) + # Test - np.testing.assert_array_equal(a['triangle']['nodes_nums'], b['triangle']['nodes_nums']) - np.testing.assert_array_equal(a['quad']['nodes_nums'], b['quad']['nodes_nums']) + np.testing.assert_array_equal(a[41], b[41]) + np.testing.assert_array_equal(a[44], b[44]) def test_prepare_2412(): dict_2412 = pyuff.prepare_2412(return_full_dict=True) x = sorted(list(dict_2412.keys())) - y = sorted(['type', + y = sorted(['beam_aftend_cross', + 'beam_foreend_cross', + 'beam_orientation', + 'color', 'element_nums', 'fe_descriptor', - 'phys_table', 'mat_table', - 'color', + 'nodes_nums', 'num_nodes', - 'nodes_nums']) + 'phys_table', + 'type']) np.testing.assert_array_equal(x,y) #empty dictionary test @@ -51,6 +74,7 @@ def test_prepare_2412(): if x2['type'] != 2412: raise Exception('Not correct type') + if __name__ == '__main__': # test_read_2412() test_read_write_2412_mixed() \ No newline at end of file