3def parse_patch_file(file_path, solver_type):
5 Transform data from Peano patch file into numpy array
6 in the format [x_vertex, y_vertex, value]
8 :arg file_path: path to Peano patch file
9 :solver_type: "CG" or "DG"
12 if solver_type
not in [
"CG",
"DG"]:
raise ValueError(
"Invalid solver type. Expected 'CG' or 'DG'.")
14 with open(file_path,
'r')
as file:
15 lines = file.readlines()
17 if solver_type ==
'CG':
22 if lines[i].startswith(
"begin patch"):
24 _, xlb, ylb = lines[i+1].split()
29 _, hx, hy = lines[i+2].split()
34 values = [float(value)
for value
in lines[i+4].split()]
37 data.extend([[xlb, ylb, values[0]],
38 [xlb+hx, ylb, values[1]],
39 [xlb, ylb+hy, values[2]],
40 [xlb+hx, ylb+hy, values[3]]])
54 if not any( np.all(np.isclose(row, unique_row, atol=tolerance))
for unique_row
in data_unique ):
55 data_unique.append(row)
60 assert np.sqrt(np.shape(data)[0]) == (np.sqrt(np.shape(data_unique)[0]) - 1) * 2, f
'{np.shape(data) = }, {np.shape(data_unique) = }'
61 result = np.array(data_unique)
63 elif solver_type ==
'DG':
73 if lines[i].startswith(
"begin patch"):
75 _, xlb, ylb = lines[i+1].split()
77 values = [float(value)
for value
in lines[i+4].split()]
78 result[( float(xlb), float(ylb) )] = values
88def reorder_array(array1, array2):
90 Given array1 and array2 of the same format [x,y,val],
91 rearrange array2 in accordance with the order of coordinates
95 array2_reorder = np.zeros_like(array2)
97 for i
in range(np.shape(array1)[0]):
100 mask = np.isclose(array2[:, 0], x) & np.isclose(array2[:, 1], y)
101 matching_row = array2[mask]
102 array2_reorder[i,:] = matching_row
106 return array2_reorder
110 Visualise the parsed field as an interactive scatter plot.
113 import matplotlib.pyplot
as plt
114 from mpl_toolkits.mplot3d
import Axes3D
122 ax = fig.add_subplot(111, projection=
'3d')
123 sc = ax.scatter(x, y, val, c=val, cmap=
'viridis')
124 fig.colorbar(sc, ax=ax, label=
'Value')
131def plot_field_dg(data, H):
133 Visualise the parsed field as an interactive scatter plot.
135 :arg data: parsed patch data in the form of a dictionary as output of parse_patch_file()
136 :arg H: mesh size as list of cell sizes in each direction: [hx, hy]
138 import matplotlib.pyplot
as plt
139 from mpl_toolkits.mplot3d
import Axes3D
142 assert len(H) == 2,
"Only works for 2D"
146 ax = fig.add_subplot(111, projection=
'3d')
152 poly_degree = int(np.sqrt(len(data[(0.0, 0.0)]))) - 1
154 local_node_coordinates = matrices._Xi_C
155 num_of_nodes = len(local_node_coordinates[0])
158 global_node_coordinates = [[np.zeros_like(arr)
for arr
in local_node_coordinates[0]]]
160 for key
in data.keys():
168 for i
in range(num_of_nodes):
169 global_node_coordinates[0][i][0] = xlb + 0.5 * H[0] * (local_node_coordinates[0][i][0] + 1.0)
170 global_node_coordinates[0][i][1] = ylb + 0.5 * H[1] * (local_node_coordinates[0][i][1] + 1.0)
174 x.extend([ global_node_coordinates[0][i][0]
for i
in range(num_of_nodes) ])
175 y.extend([ global_node_coordinates[0][i][1]
for i
in range(num_of_nodes) ])
176 val.extend(data[key])
179 sc = ax.scatter(x, y, val, c=val, cmap=
'viridis')
180 fig.colorbar(sc, ax=ax, label=
'Value')
187def construct_dg_function(data, H):
189 Construct exact solution with the same structure as data
191 :arg data: parsed patch data in the form of a dictionary as output of parse_patch_file()
192 :arg H: mesh size as list of cell sizes in each direction: [hx, hy]
194 import matplotlib.pyplot
as plt
195 from mpl_toolkits.mplot3d
import Axes3D
198 assert len(H) == 2,
"Only works for 2D"
201 result = {key: [0] * len(value)
for key, value
in data.items()}
204 poly_degree = int(np.sqrt(len(data[(0.0, 0.0)]))) - 1
206 local_node_coordinates = matrices._Xi_C
207 num_of_nodes = len(local_node_coordinates[0])
209 for key
in data.keys():
217 for i
in range(num_of_nodes):
218 x_node = xlb + 0.5 * H[0] * (local_node_coordinates[0][i][0] + 1.0)
219 y_node = ylb + 0.5 * H[1] * (local_node_coordinates[0][i][1] + 1.0)
220 result[key][i] = np.sin(2.0*np.pi*x_node) * np.sin(2.0*np.pi*y_node)