|
| 1 | +from ds import * |
| 2 | + |
| 3 | +def parse_gmsh_file(file): |
| 4 | + sections=set(['$MeshFormat', '$PhysicalNames', '$Nodes', '$Elements']) |
| 5 | + lineno = 0 |
| 6 | + section_count = 0 |
| 7 | + section_expected = 0 |
| 8 | + dimension = 0 |
| 9 | + with open(file, 'r') as ih: |
| 10 | + state = 'begin' |
| 11 | + for line in ih: |
| 12 | + line = line.rstrip() |
| 13 | + lineno += 1 |
| 14 | + if state == 'begin': |
| 15 | + if line in sections: |
| 16 | + state = line |
| 17 | + else: |
| 18 | + raise RuntimeError("Error Line %d" % lineno) |
| 19 | + elif line.find('$End') == 0: |
| 20 | + state = 'begin' |
| 21 | + section_count = 0 |
| 22 | + section_expected = None |
| 23 | + elif state == '$MeshFormat': |
| 24 | + continue |
| 25 | + elif state == '$PhysicalNames': |
| 26 | + if not section_expected: |
| 27 | + section_expected=int(line) |
| 28 | + physical_names = [] |
| 29 | + else: |
| 30 | + line = line.split() |
| 31 | + name = line[2][1:-1] |
| 32 | + physical_names.append((name, int(line[0]), int(line[1]))) |
| 33 | + section_count += 1 |
| 34 | + elif state == '$Nodes': |
| 35 | + if not section_expected: |
| 36 | + section_expected=int(line) |
| 37 | + nodes = [] |
| 38 | + else: |
| 39 | + line = line.split() |
| 40 | + nodes.append([int(line[0]), float(line[1]), float(line[2]), float(line[3])]) |
| 41 | + section_count += 1 |
| 42 | + elif state == '$Elements': |
| 43 | + if not section_expected: |
| 44 | + section_expected=int(line) |
| 45 | + elements = [None]*section_expected |
| 46 | + else: |
| 47 | + elements[section_count] = [int(x) for x in line.split()] |
| 48 | + section_count += 1 |
| 49 | + else: |
| 50 | + raise RuntimeError("Unknown %s" % line) |
| 51 | + dimension = max([x[1] for x in physical_names]) |
| 52 | + return { |
| 53 | + 'dimension' : dimension, |
| 54 | + 'physical_names' : physical_names, |
| 55 | + 'coordinates' : nodes, |
| 56 | + 'elements' : elements |
| 57 | + } |
| 58 | + |
| 59 | +def read_gmsh_file(filename): |
| 60 | + '''reads gmsh file and converts to python representation''' |
| 61 | + data = parse_gmsh_file(filename) |
| 62 | + #namemap = {} |
| 63 | + print '%d dimension' % data['dimension'] |
| 64 | + print '%d coordinates' % len(data['coordinates']) |
| 65 | + #for i in sorted(data['physical_names'].keys()): |
| 66 | + # print "%s %s %d" % (i, data['physical_names'][i], len(data['elements'][i])) |
| 67 | + # namemap[data['physical_names'][i]] = i |
| 68 | + |
| 69 | + coordinate_indexes = [x[0] for x in data['coordinates']] |
| 70 | + max_coordinate_index = max(coordinate_indexes) |
| 71 | + coordinate_to_index = [-1] * (max_coordinate_index+1) |
| 72 | + for i,j in enumerate(coordinate_indexes): |
| 73 | + coordinate_to_index[j] = i |
| 74 | + |
| 75 | + coordinates=[] |
| 76 | + for i in data['coordinates']: |
| 77 | + coordinates.extend(i[1:]) |
| 78 | + |
| 79 | + all_physical_numbers = sorted(set([x[3] for x in data['elements']])) |
| 80 | + sorted_physical_names = sorted(data['physical_names'],key = lambda x : x[0]) |
| 81 | + physical_number_map = { |
| 82 | + 1 : {}, |
| 83 | + 2 : {}, |
| 84 | + 3 : {}, |
| 85 | + } |
| 86 | + for i, j in enumerate(sorted_physical_names): |
| 87 | + # mapped dimension, physical number, new index |
| 88 | + physical_number_map[j[1]][j[2]] = i |
| 89 | + physical_names = [x[0] for x in sorted_physical_names] |
| 90 | + |
| 91 | + |
| 92 | + #gmsh format |
| 93 | + #elm-number elm-type number-of-tags < tag > ... node-number-list |
| 94 | + #our format |
| 95 | + elements = [] |
| 96 | + for i in data['elements']: |
| 97 | + t = i[1] |
| 98 | + if (t == 4): |
| 99 | + #tetrahedron |
| 100 | + etype = 3 |
| 101 | + dimension = 3 |
| 102 | + elif (t == 2): |
| 103 | + #triangle |
| 104 | + etype = 2 |
| 105 | + dimension = 2 |
| 106 | + elif (t == 1): |
| 107 | + #edge |
| 108 | + etype = 1 |
| 109 | + dimension = 1 |
| 110 | + elif (t == 15): |
| 111 | + #point |
| 112 | + etype = 0 |
| 113 | + else: |
| 114 | + raise RuntimeError("Cannot handle element type " % i) |
| 115 | + |
| 116 | + #physical number |
| 117 | + # will be remapped later |
| 118 | + pnum = physical_number_map[dimension][i[3]] |
| 119 | + |
| 120 | + #nodes |
| 121 | + # position 2 + number of tags |
| 122 | + nodes = i[i[2]+3:] |
| 123 | + nodes = [coordinate_to_index[x] for x in nodes] |
| 124 | + elements.extend([etype, pnum]) |
| 125 | + elements.extend(nodes) |
| 126 | + |
| 127 | + return { |
| 128 | + 'physical_names' : physical_names, |
| 129 | + 'coordinates' : coordinates, |
| 130 | + 'elements' : elements, |
| 131 | + } |
| 132 | + |
0 commit comments