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).data() + BasisElementsPerFace2,
68 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d).data() + BasisElementsPerFace,
69 proj, toPoints, fromPoints, ({{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}}));
70 dg2dgFace(
71 fineGridFaces""" + solver_name + """Estimates(d+DIMENSIONS).data(),
72 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d + DIMENSIONS).data(),
73 proj, toPoints, fromPoints, ({{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}}));
74
75 // Projected flux estimations
76 dg2dgFace(
77 fineGridFaces""" + solver_name + """FluxEstimates(d).data() + FluxElementsPerFace2,
78 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d).data() + FluxElementsPerFace,
79 proj, toPoints, fromPoints, {{NUMBER_OF_UNKNOWNS}});
80 dg2dgFace(
81 fineGridFaces""" + solver_name + """FluxEstimates(d+DIMENSIONS).data(),
82 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d + DIMENSIONS).data(),
83 proj, toPoints, fromPoints, {{NUMBER_OF_UNKNOWNS}});
84 }
85
86 }
87""")
88
89def same_basis_postprocessing_kernel(condition, 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 // 1 if right side, 0 if left
109 //const int ownFaceSide = marker.getSelectedFaceNumber() > DIMENSIONS;
110 const int ownFaceSide = fineGridFace{{SOLVER_NAME}}FaceLabel.getUpdated(0) ? 0 : 1;
111
112 // Make sure that I have indeed been updated, as if the split is between spacetrees it is possible
113 // neither side has been updated
114 if( fineGridFace{{SOLVER_NAME}}FaceLabel.getUpdated(ownFaceSide) ){
115 // Projected solution estimations
116 std::copy_n(
117 fineGridFace{{UNKNOWN_IDENTIFIER}}Estimates.data() + ownFaceSide * BasisElementsPerFace,
118 BasisElementsPerFace,
119 fineGridFace""" + solver_name + """QEstimates.data() + ownFaceSide * BasisElementsPerFace
120 );
121 // Projected flux estimations
122 std::copy_n(
123 fineGridFace{{UNKNOWN_IDENTIFIER}}FluxEstimates.data() + ownFaceSide * FluxElementsPerFace,
124 FluxElementsPerFace,
125 fineGridFace""" + solver_name + """QFluxEstimates.data() + ownFaceSide * FluxElementsPerFace
126 );
127 }
128 }
129""")
130
131
133 return """
134#pragma once
135#include "peano4/utils/Loop.h"
136
137template<typename pTo, typename pFrom>
138inline void dg2dgFace(pTo* Qto, const pFrom* Qfrom, const double* proj, int toPoints, int fromPoints, int numVars){
139
140#if DIMENSIONS==3
141 const int toSize = toPoints*toPoints*numVars;
142#else
143 const int toSize = toPoints*numVars;
144#endif
145
146 std::fill_n(Qto, toSize, 0.0);
147
148 //For each point we project to
149 dfore(dofTo, toPoints, DIMENSIONS-1, 0) {
150 const int dofToSerialised = dofTo[0]
151 #if DIMENSIONS==3
152 + dofTo[1] * toPoints
153 #endif
154 ;
155
156 //Compute the contribution from each contributing point
157 dfore(dofFrom, fromPoints, DIMENSIONS-1, 0) {
158 const int dofFromSerialised = dofFrom[0]
159 #if DIMENSIONS==3
160 + dofFrom[1] * fromPoints
161 #endif
162 ;
163
164 for(int var=0; var<numVars; var++){
165 Qto[dofToSerialised*numVars+var] += Qfrom[dofFromSerialised*numVars+var] * proj[dofTo[0]*fromPoints+dofFrom[0]]
166 #if DIMENSIONS==3
167 * proj[dofTo[1]*fromPoints+dofFrom[1]]
168 #endif
169 ;
170 }
171 }
172
173 }
174}
175"""
176
177def updateSolverStorage(solver, cond):
178 s1_load_cell = solver._load_cell_data_default_guard() + cond
179 s1_store_cell = solver._store_cell_data_default_guard() + cond
180 s1_provide_cell = solver._provide_cell_data_to_compute_kernels_default_guard() + cond
181
182 solver._load_cell_data_default_guard = lambda : s1_load_cell
183 solver._store_cell_data_default_guard = lambda : s1_store_cell
184 solver._provide_cell_data_to_compute_kernels_default_guard = lambda : s1_provide_cell
185
186 # Remove faces load
187 s1_load_face = solver._load_face_data_default_guard() + cond
188 s1_store_face = solver._store_face_data_default_guard() + cond
189 s1_provide_face = solver._provide_face_data_to_compute_kernels_default_guard() + cond
190
191 solver._load_face_data_default_guard = lambda : s1_load_face
192 solver._store_face_data_default_guard = lambda : s1_store_face
193 solver._provide_face_data_to_compute_kernels_default_guard = lambda : s1_provide_face
194
195 solver.set_implementation()
196
197 solver._rhs_estimates_projection.generator.send_condition += cond
198 solver._rhs_estimates_projection.generator.receive_and_merge_condition += cond
199 solver._flux_estimates_projection.generator.send_condition += cond
200 solver._flux_estimates_projection.generator.receive_and_merge_condition += cond
201
202
209
210def fuseADERSolvers(solver1, solver2, cond_1, cond_2):
211
212 solver_1_cond = " and " + cond_1
213 solver_2_cond = " and " + cond_2
214
215 updateSolverStorage(solver1, solver_1_cond)
216 updateSolverStorage(solver2, solver_2_cond)
217
218# # Checks for periodic bc, in which case the boundaries should still be covered in case
219# # the neigbour on the other side exists
220# s1_face_cond = (" and (" + cond_1 + """
221# or (PeriodicBC.test(0) and (marker.x()[0]==DomainOffset[0] or (marker.x()[0]==DomainOffset[0]+DomainSize[0]) ) )
222# or (PeriodicBC.test(1) and (marker.x()[1]==DomainOffset[1] or (marker.x()[1]==DomainOffset[1]+DomainSize[1]) ) )
223# #if DIMENSIONS==3
224# or (PeriodicBC.test(2) and (marker.x()[2]==DomainOffset[2] or (marker.x()[2]==DomainOffset[2]+DomainSize[2]) ) )
225# #endif
226# )
227# """)
228# solver1._rhs_estimates_projection.generator.send_condition += s1_face_cond
229# solver1._rhs_estimates_projection.generator.receive_and_merge_condition += s1_face_cond
230
231 # s2_load_cell = solver2._load_cell_data_default_guard() + solver_2_cond
232 # s2_store_cell = solver2._store_cell_data_default_guard() + solver_2_cond
233 # s2_provide_cell = solver2._provide_cell_data_to_compute_kernels_default_guard() + solver_2_cond
234
235 # solver2._load_cell_data_default_guard = lambda : s2_load_cell
236 # solver2._store_cell_data_default_guard = lambda : s2_store_cell
237 # solver2._provide_cell_data_to_compute_kernels_default_guard = lambda : s2_provide_cell
238
239 # solver1.set_implementation()
240 # solver2.set_implementation()
241
242
247
248 # # #Add solver guards
249 # solver1._action_set_prediction.guard += solver_1_cond
250 # # solver1._action_set_prediction_on_hanging_cells.guard += solver_1_cond
251 # solver1._action_set_correction.guard += solver_1_cond
252 # solver1._action_set_correction._riemann_guard += solver_1_cond #doesn't do anything at the moment, this variable isn't connected to anything
253
254 # solver2._action_set_prediction.guard += solver_2_cond
255 # # solver2._action_set_prediction_on_hanging_cells.guard += solver_2_cond
256 # solver2._action_set_correction.guard += solver_2_cond
257 # # solver2._action_set_correction._riemann_guard += solver_2_cond #doesn't do anything at the moment, this variable isn't connected to anything
258
259
260
261 # fit timestep sizes to one another
262 compute_time_step_size = """
263 double timeStepSize = std::min( repositories::""" + solver1.get_name_of_global_instance() + """.getAdmissibleTimeStepSize(),
264 repositories::""" + solver2.get_name_of_global_instance() + """.getAdmissibleTimeStepSize());
265 """
266
267 solver1._compute_time_step_size = compute_time_step_size
268 solver2._compute_time_step_size = compute_time_step_size
269
270 aderSolver1QuadPoints = solver1._basis.quadrature_points(render=False)
271 aderSolver2QuadPoints = solver2._basis.quadrature_points(render=False)
272
273 if(aderSolver1QuadPoints!=aderSolver2QuadPoints):
274 proj1 = flatten(compute_projector_to_point_set(aderSolver1QuadPoints, aderSolver2QuadPoints))
275 proj2 = flatten(compute_projector_to_point_set(aderSolver2QuadPoints, aderSolver1QuadPoints))
276 # add postprocessing action set to interpolate and copy data from one face to the other
277 solver1._action_set_postprocess_solution._compute_cell_kernel += different_basis_postprocessing_kernel(solver_1_cond, str(solver2._order), proj1, solver2._unknown_identifier())
278 solver2._action_set_postprocess_solution._compute_cell_kernel += different_basis_postprocessing_kernel(solver_2_cond, str(solver1._order), proj2, solver1._unknown_identifier())
279
280 # provide helper function to both solvers:
281 if not os.path.exists("observers"):
282 try:
283 os.makedirs("observers")
284 except:
285 raise Exception("Path /observers could not be created")
286 f = open("observers/dg2dgface.h", "w")
287 f.write(dg2dgFace())
288 f.close()
289
290 solver1.add_user_solver_includes("""\n#include "observers/dg2dgface.h"\n""")
291 solver2.add_user_solver_includes("""\n#include "observers/dg2dgface.h"\n""")
292 else:
293 # add postprocessing action set to copy data from one face to the other
294 solver1._action_set_postprocess_solution._face_compute_kernel += same_basis_postprocessing_kernel(solver_1_cond + solver_2_cond, solver2.name)
295 solver2._action_set_postprocess_solution._face_compute_kernel += same_basis_postprocessing_kernel(solver_1_cond + solver_2_cond, solver1.name)
same_basis_postprocessing_kernel(condition, solver_name)
different_basis_postprocessing_kernel(condition, order, proj, solver_name)
updateSolverStorage(solver, cond)
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...