Peano
Loading...
Searching...
No Matches
fuseADERSolvers.py
Go to the documentation of this file.
1import mpmath as mp
2import os
3
4def compute_projector_to_point_set(quad_points_from, quad_points_to):
5 """
6 Transforms the degrees of freedom located at Lagrange quadrature_points to degrees of freedom
7 located at a set of points as defined by the parameter points.
8
9 Let us denote by P the projection operator. The DoF are computed according to:
10
11 u@x = sum_{m} P_m u^DG_m
12
13 Returns:
14 Projector:
15 The corresponding degrees of freedom located at the set of points defined by the parameter x.
16 """
17 proj = [[mp.mpf(0) for _ in range(len(quad_points_from))] for _ in range(len(quad_points_to))]
18 for idx, point in enumerate(quad_points_to):
19 # For each point to which we project, calculate lagrange weights for that point
20 n = len(quad_points_from)
21 # weights = []
22 for i in range(n):
23 numerator = 1.0
24 denominator = 1.0
25 result = 1.0
26 for k in range(n):
27 if i != k:
28 numerator *= (point - quad_points_from[k])
29 denominator *= (quad_points_from[i] - quad_points_from[k])
30 result*= numerator / denominator
31 proj[idx][i] = result
32 return proj
33
34def flatten(xss):
35 return ', '.join([mp.nstr(x, n=12) for xs in xss for x in xs])
36
37def different_basis_postprocessing_kernel(condition, order, proj, solver_name):
38 return ("""
39 if (
40 repositories::{{SOLVER_INSTANCE}}.isFirstGridSweepOfTimeStep()
41 and not marker.willBeRefined() and not marker.hasBeenRefined()
42 """ + condition + """
43 ) {
44
45 constexpr int fromPoints = {{ORDER}} + 1;
46 constexpr int toPoints = """ + str(order) + """ + 1;
47
48 #if DIMENSIONS == 2
49 constexpr int SpaceFaceSize = fromPoints;
50 constexpr int SpaceFaceSize2 = toPoints;
51 #else
52 constexpr int SpaceFaceSize = fromPoints*fromPoints;
53 constexpr int SpaceFaceSize2 = toPoints*toPoints;
54 #endif
55
56 constexpr int FluxElementsPerFace = SpaceFaceSize * {{NUMBER_OF_UNKNOWNS}};
57 constexpr int BasisElementsPerFace = SpaceFaceSize * ({{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}});
58
59 constexpr int FluxElementsPerFace2 = SpaceFaceSize2 * {{NUMBER_OF_UNKNOWNS}};
60 constexpr int BasisElementsPerFace2 = SpaceFaceSize2 * ({{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}});
61
62 constexpr double proj[toPoints*fromPoints] = {""" + proj + """};
63
64 for (int d = 0; d < DIMENSIONS; d++) {
65 // Projected solution estimations
66 dg2dgFace(
67 fineGridFaces""" + solver_name + """Estimates(d).value + BasisElementsPerFace2,
68 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d).value + BasisElementsPerFace,
69 proj, toPoints, fromPoints, ({{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}}));
70 dg2dgFace(
71 fineGridFaces""" + solver_name + """Estimates(d+DIMENSIONS).value,
72 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d + DIMENSIONS).value,
73 proj, toPoints, fromPoints, ({{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}}));
74
75 // Projected flux estimations
76 dg2dgFace(
77 fineGridFaces""" + solver_name + """FluxEstimates(d).value + FluxElementsPerFace2,
78 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d).value + FluxElementsPerFace,
79 proj, toPoints, fromPoints, {{NUMBER_OF_UNKNOWNS}});
80 dg2dgFace(
81 fineGridFaces""" + solver_name + """FluxEstimates(d+DIMENSIONS).value,
82 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d + DIMENSIONS).value,
83 proj, toPoints, fromPoints, {{NUMBER_OF_UNKNOWNS}});
84 }
85
86 }
87""")
88
89def same_basis_postprocessing_kernel(condition, order, solver_name):
90 return ("""
91 if (
92 repositories::{{SOLVER_INSTANCE}}.isFirstGridSweepOfTimeStep()
93 and not marker.willBeRefined() and not marker.hasBeenRefined()
94 """ + condition + """
95 ) {
96
97 constexpr int fromPoints = {{ORDER}} + 1;
98
99 #if DIMENSIONS == 2
100 constexpr int SpaceFaceSize = fromPoints;
101 #else
102 constexpr int SpaceFaceSize = fromPoints*fromPoints;
103 #endif
104
105 constexpr int FluxElementsPerFace = SpaceFaceSize * {{NUMBER_OF_UNKNOWNS}};
106 constexpr int BasisElementsPerFace = SpaceFaceSize * ({{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}});
107
108 for (int d = 0; d < DIMENSIONS; d++) {
109 // Projected solution estimations
110 std::copy_n(
111 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d).value + BasisElementsPerFace,
112 BasisElementsPerFace,
113 fineGridFaces""" + solver_name + """Estimates(d).value + BasisElementsPerFace
114 );
115 std::copy_n(
116 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d+DIMENSIONS).value,
117 BasisElementsPerFace,
118 fineGridFaces""" + solver_name + """Estimates(d+DIMENSIONS).value
119 );
120
121 // Projected flux estimations
122 std::copy_n(
123 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d).value + FluxElementsPerFace,
124 FluxElementsPerFace,
125 fineGridFaces""" + solver_name + """FluxEstimates(d).value + FluxElementsPerFace
126 );
127 std::copy_n(
128 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d + DIMENSIONS).value,
129 FluxElementsPerFace,
130 fineGridFaces""" + solver_name + """FluxEstimates(d+DIMENSIONS).value
131 );
132 }
133 }
134""")
135
136
138 return """
139#pragma once
140#include "peano4/utils/Loop.h"
141
142template<typename pTo, typename pFrom>
143inline void dg2dgFace(pTo* Qto, const pFrom* Qfrom, const double* proj, int toPoints, int fromPoints, int numVars){
144
145#if DIMENSIONS==3
146 const int toSize = toPoints*toPoints*numVars;
147#else
148 const int toSize = toPoints*numVars;
149#endif
150
151 std::fill_n(Qto, toSize, 0.0);
152
153 //For each point we project to
154 dfore(dofTo, toPoints, DIMENSIONS-1, 0) {
155 const int dofToSerialised = dofTo[0]
156 #if DIMENSIONS==3
157 + dofTo[1] * toPoints
158 #endif
159 ;
160
161 //Compute the contribution from each contributing point
162 dfore(dofFrom, fromPoints, DIMENSIONS-1, 0) {
163 const int dofFromSerialised = dofFrom[0]
164 #if DIMENSIONS==3
165 + dofFrom[1] * fromPoints
166 #endif
167 ;
168
169 for(int var=0; var<numVars; var++){
170 Qto[dofToSerialised*numVars+var] += Qfrom[dofFromSerialised*numVars+var] * proj[dofTo[0]*fromPoints+dofFrom[0]]
171 #if DIMENSIONS==3
172 * proj[dofTo[1]*fromPoints+dofFrom[1]]
173 #endif
174 ;
175 }
176 }
177
178 }
179}
180"""
181
182
183
190
191def fuseADERSolvers(solver1, solver2, cond_1, cond_2):
192
193 solver_1_cond = " and " + cond_1
194 solver_2_cond = " and " + cond_2
195
196 s1 = solver1._load_cell_data_default_guard() + solver_1_cond
197 s12 = solver1._store_cell_data_default_guard() + solver_1_cond
198 s13 = solver1._provide_cell_data_to_compute_kernels_default_guard() + solver_1_cond
199
200 def s1_guard():
201 return s1
202
203 def s12_guard():
204 return s12
205
206 def s13_guard():
207 return s13
208
209 solver1._load_cell_data_default_guard = s1_guard
210 solver1._store_cell_data_default_guard = s12_guard
211 solver1._provide_cell_data_to_compute_kernels_default_guard = s13_guard
212
213 s2 = solver2._load_cell_data_default_guard() + solver_2_cond
214 s21 = solver2._store_cell_data_default_guard() + solver_2_cond
215 s23 = solver2._provide_cell_data_to_compute_kernels_default_guard() + solver_2_cond
216
217 def s2_guard():
218 return s2
219
220 def s21_guard():
221 return s21
222
223 def s23_guard():
224 return s23
225
226 solver2._load_cell_data_default_guard = s2_guard
227 solver2._store_cell_data_default_guard = s21_guard
228 solver2._provide_cell_data_to_compute_kernels_default_guard = s23_guard
229
230 solver1.set_implementation()
231 solver2.set_implementation()
232
233
238
239 # # #Add solver guards
240 # solver1._action_set_prediction.guard += solver_1_cond
241 # # solver1._action_set_prediction_on_hanging_cells.guard += solver_1_cond
242 # solver1._action_set_correction.guard += solver_1_cond
243 # solver1._action_set_correction._riemann_guard += solver_1_cond #doesn't do anything at the moment, this variable isn't connected to anything
244
245 # solver2._action_set_prediction.guard += solver_2_cond
246 # # solver2._action_set_prediction_on_hanging_cells.guard += solver_2_cond
247 # solver2._action_set_correction.guard += solver_2_cond
248 # # solver2._action_set_correction._riemann_guard += solver_2_cond #doesn't do anything at the moment, this variable isn't connected to anything
249
250
251
252 # fit timestep sizes to one another
253 compute_time_step_size = """
254 double timeStepSize = std::min( repositories::""" + solver1.get_name_of_global_instance() + """.getAdmissibleTimeStepSize(),
255 repositories::""" + solver2.get_name_of_global_instance() + """.getAdmissibleTimeStepSize());
256 """
257
258 solver1._compute_time_step_size = compute_time_step_size
259 solver2._compute_time_step_size = compute_time_step_size
260
261 aderSolver1QuadPoints = solver1._basis.quadrature_points(render=False)
262 aderSolver2QuadPoints = solver2._basis.quadrature_points(render=False)
263
264 if(aderSolver1QuadPoints!=aderSolver2QuadPoints):
265 proj1 = flatten(compute_projector_to_point_set(aderSolver1QuadPoints, aderSolver2QuadPoints))
266 proj2 = flatten(compute_projector_to_point_set(aderSolver2QuadPoints, aderSolver1QuadPoints))
267 # add postprocessing action set to interpolate and copy data from one face to the other
268 solver1._action_set_postprocess_solution._compute_kernel += different_basis_postprocessing_kernel(solver_1_cond, str(solver2._order), proj1, solver2._unknown_identifier())
269 solver2._action_set_postprocess_solution._compute_kernel += different_basis_postprocessing_kernel(solver_2_cond, str(solver1._order), proj2, solver1._unknown_identifier())
270
271 # provide helper function to both solvers:
272 if not os.path.exists("observers"):
273 try:
274 os.makedirs("observers")
275 except:
276 raise Exception("Path /observers could not be created")
277 f = open("observers/dg2dgface.h", "w")
278 f.write(dg2dgFace())
279 f.close()
280
281 solver1.add_user_solver_includes("""\n#include "observers/dg2dgface.h"\n""")
282 solver2.add_user_solver_includes("""\n#include "observers/dg2dgface.h"\n""")
283 else:
284 # add postprocessing action set to copy data from one face to the other
285 solver1._action_set_postprocess_solution._compute_kernel += same_basis_postprocessing_kernel(solver_1_cond, str(solver2._order), solver2._unknown_identifier())
286 solver2._action_set_postprocess_solution._compute_kernel += same_basis_postprocessing_kernel(solver_2_cond, str(solver1._order), solver1._unknown_identifier())
287
different_basis_postprocessing_kernel(condition, order, proj, solver_name)
compute_projector_to_point_set(quad_points_from, quad_points_to)
Transforms the degrees of freedom located at Lagrange quadrature_points to degrees of freedom located...
same_basis_postprocessing_kernel(condition, order, solver_name)