Peano
Loading...
Searching...
No Matches
CouplingSynchronization.py
Go to the documentation of this file.
2 solverSource,
3 solverDestination,
4 indexArrayDestination,
5 function,
6 numberOfUnknownsToCopy,
7):
8 """!
9 @coupling: This function can be used to copy values and transform them while doing so. Particularly nice for momenta and the like.
10
11 solverSource:
12 The solver to copy values from.
13
14 solverDestination:
15 The solver to copy values to.
16
17 indexArrayDestination:
18 Array of indices of length numberOfUnknownsToCopy providing a local index to copy source to. Source value depends on function.
19
20 function:
21 A function applied to source values before copying. Unknown to copy is given by "unknown" and source cell base index by "sourceIndexLinearised".
22
23 numberOfUnknownsToCopy:
24 Number of unknowns to copy in loop for each cell in patch.
25 """
26 assert solverSource.patch_size == solverDestination.patch_size
27 patch_size = solverSource.patch_size
28 numberOfVariablesSource = solverSource.unknowns + solverSource.auxiliary_variables
29 numberOfVariablesDestination = (
30 solverDestination.unknowns + solverDestination.auxiliary_variables
31 )
32 return f"""
33 // this is copied and adapted from toolbox::blockstructured::copyUnknown()
34 #if DIMENSIONS==2
35 for (int x=0; x<{patch_size}; x++)
36 for (int y=0; y<{patch_size}; y++)
37 for (int unknown = 0; unknown < {numberOfUnknownsToCopy}; ++unknown) {{
38 const int sourceIndexLinearised = (x + y * {patch_size} ) * {numberOfVariablesSource};
39 const int destIndexLinearised = (x + y * {patch_size} ) * {numberOfVariablesDestination} + {indexArrayDestination}[unknown];
40 // apply any function to source value
41 const auto sourceValue = {function};
42 fineGridCell{solverDestination.name}Q.data()[destIndexLinearised] = sourceValue;
43 }}
44 #elif DIMENSIONS==3
45 for (int x=0; x<{solverSource.patch_size}; x++)
46 for (int y=0; y<{solverSource.patch_size}; y++)
47 for (int z=0; z<{solverSource.patch_size}; z++)
48 for (int unknown = 0; unknown < {numberOfUnknownsToCopy}; ++unknown) {{
49 const int sourceIndexLinearised = (x + y * {patch_size} + z * {patch_size} * {patch_size}) * {numberOfVariablesSource};
50 const int destIndexLinearised = (x + y * {patch_size} + z * {patch_size} * {patch_size}) * {numberOfVariablesDestination} + {indexArrayDestination}[unknown];
51 // apply any function to source value
52 const auto sourceValue = {function}
53 fineGridCell{solverDestination.name}Q.data()[destIndexLinearised] = sourceValue;
54 }}
55 #else
56 #error DIMENSIONS not supported
57 #endif
58 """
59
60
61def determineSolverCoupling(atmospheric_solver, diffusion_solver, chemical_solver):
62 couple_chemical_solver = False
63 couple_diffusion_solver = False
64 if atmospheric_solver is not None:
65 # any solver to couple?
66 couple_chemical_solver = chemical_solver is not None
67 couple_diffusion_solver = diffusion_solver is not None
68
69 return couple_diffusion_solver, couple_chemical_solver
70
71
72def setLastSolver(atmospheric_solver, diffusion_solver, chemical_solver):
73 couple_diffusion_solver, couple_chemical_solver = determineSolverCoupling(
74 atmospheric_solver=atmospheric_solver,
75 diffusion_solver=diffusion_solver,
76 chemical_solver=chemical_solver,
77 )
78
79 if couple_chemical_solver:
80 # couple chemical solver
81 atmospheric_solver.last_solver = chemical_solver
82 if couple_diffusion_solver:
83 # if a diffusion solver is to be coupled as well
84 diffusion_solver.last_solver = chemical_solver
85 chemical_solver.last_solver = chemical_solver
86
87 elif couple_diffusion_solver:
88 # no chemical solver, just diffusion
89 atmospheric_solver.last_solver = diffusion_solver
90 diffusion_solver.last_solver = diffusion_solver
91
92
93def synchronizePatchGravityWaves(atmospheric_solver, diffusion_solver, chemical_solver):
94 couple_diffusion_solver, couple_chemical_solver = determineSolverCoupling(
95 atmospheric_solver=atmospheric_solver,
96 diffusion_solver=diffusion_solver,
97 chemical_solver=chemical_solver,
98 )
99 if (
100 atmospheric_solver is not None
101 or couple_chemical_solver
102 or couple_diffusion_solver
103 ):
104 dimensions = atmospheric_solver._dimensions
105 else:
106 dimensions = chemical_solver._dimensions
107
108 if couple_chemical_solver or couple_diffusion_solver:
109 # add toolbox include to solvers for coupling by copying values
110 atmospheric_solver.add_user_action_set_includes(
111 '#include "toolbox/blockstructured/Copy.h"\n'
112 )
113 numberOfVariablesAtmospheric = (
114 atmospheric_solver.auxiliary_variables + atmospheric_solver.unknowns
115 )
116
117 if couple_chemical_solver:
118 chemical_solver.add_user_action_set_includes(
119 '#include "toolbox/blockstructured/Copy.h"\n'
120 )
121 numberOfVariablesChemical = (
122 chemical_solver.auxiliary_variables + chemical_solver.unknowns
123 )
124
125 if not couple_diffusion_solver:
126 # take velocities and temperature from atmosphere
128 atmospheric_solver=atmospheric_solver,
129 chemical_solver=chemical_solver,
130 numberOfVariablesAtmospheric=numberOfVariablesAtmospheric,
131 numberOfVariablesChemical=numberOfVariablesChemical,
132 dimensions=dimensions,
133 )
134
135 # copy chemistry values back to atmosphere
137 atmospheric_solver=atmospheric_solver, chemical_solver=chemical_solver
138 )
139
140 if couple_diffusion_solver:
141 numberOfVariablesDiffusion = (
142 diffusion_solver.auxiliary_variables + diffusion_solver.unknowns
143 )
144
145 diffusion_solver.add_user_action_set_includes(
146 '#include "toolbox/blockstructured/Copy.h"\n'
147 )
148
149 # copy atmospheric values to diffusion solver
151 atmospheric_solver=atmospheric_solver,
152 diffusion_solver=diffusion_solver,
153 dimensions=dimensions,
154 )
155
156 # copy diffusion back to atmosphere
158 atmospheric_solver=atmospheric_solver,
159 diffusion_solver=diffusion_solver,
160 numberOfVariablesAtmospheric=numberOfVariablesAtmospheric,
161 numberOfVariablesDiffusion=numberOfVariablesDiffusion,
162 dimensions=dimensions,
163 )
164
165 if couple_chemical_solver:
166 # copy diffusion to chemistry
168 diffusion_solver=diffusion_solver,
169 chemical_solver=chemical_solver,
170 numberOfVariablesDiffusion=numberOfVariablesDiffusion,
171 numberOfVariablesChemical=numberOfVariablesChemical,
172 dimensions=dimensions,
173 )
174
175
176def coupleTimeStepping(atmospheric_solver, diffusion_solver, chemical_solver):
177 couple_diffusion_solver, couple_chemical_solver = determineSolverCoupling(
178 atmospheric_solver=atmospheric_solver,
179 diffusion_solver=diffusion_solver,
180 chemical_solver=chemical_solver,
181 )
182
183 if couple_diffusion_solver:
184 # diffusion solver accompanies atmospheric solver
185 diffusion_solver._compute_time_step_size = (
186 """
187 const double timeStepSize = repositories::"""
188 + atmospheric_solver.get_name_of_global_instance()
189 + """.getAdmissibleTimeStepSize();
190 """
191 )
192
193 if couple_chemical_solver:
194 # the time step size of the atmospheric solver will always be <= that of the chemical solver
195 # so make synchronization easy and always use the atmospheric dt instead of the chemical one
196 chemical_solver._compute_time_step_size = (
197 """
198 const double timeStepSize = repositories::"""
199 + atmospheric_solver.get_name_of_global_instance()
200 + """.getAdmissibleTimeStepSize();
201 """
202 )
203
204
206 atmospheric_solver,
207 chemical_solver,
208 numberOfVariablesAtmospheric,
209 numberOfVariablesChemical,
210 dimensions,
211):
212 copy_function = copyPatchAndApplyFunction(
213 solverSource=atmospheric_solver,
214 solverDestination=chemical_solver,
215 indexArrayDestination="chemicalIndices",
216 function=f"fineGridCell{atmospheric_solver.name}Q.data()[sourceIndexLinearised + atmosphericIndices[unknown]] / fineGridCell{atmospheric_solver.name}Q.data()[sourceIndexLinearised + densityIndex]",
217 numberOfUnknownsToCopy=dimensions,
218 )
219
220 atmospheric_solver.postprocess_updated_patch += f"""// copy velocities to chemical solver
221 {{
222 const int atmosphericIndices[DIMENSIONS] = {{
223 {atmospheric_solver.variable_names.index("rhou")},
224 {atmospheric_solver.variable_names.index("rhov")}{"," + str(atmospheric_solver.variable_names.index("rhow")) if dimensions == 3 else ""}
225 }};
226
227 const int chemicalIndices[DIMENSIONS] = {{
228 {chemical_solver.variable_names.index("u")},
229 {chemical_solver.variable_names.index("v")}{"," + str(chemical_solver.variable_names.index("w")) if dimensions == 3 else ""}
230 }};
231
232 const int densityIndex = {atmospheric_solver.variable_names.index("rho")};
233
234 {copy_function}
235 }}"""
236
237 atmospheric_solver.postprocess_updated_patch += f"""// copy temperature
238 ::toolbox::blockstructured::copyUnknown(
239 {atmospheric_solver.patch_size}, // no of unknowns per dimension
240 fineGridCell{atmospheric_solver.name}Q.data(), // source
241 {atmospheric_solver.variable_names.index("T")}, // temperature in source
242 {numberOfVariablesAtmospheric}, // unknowns in source (incl material parameters)
243 0, // no overlap/halo here
244 fineGridCell{chemical_solver.name}Q.data(), // dest
245 {chemical_solver.variable_names.index("T")} , // temperature in dest
246 {numberOfVariablesChemical}, // unknowns in dest (incl material parameters)
247 0 // no overlap/halo here
248 );
249 """
250
251
252def atmosphereToDiffusion(atmospheric_solver, diffusion_solver, dimensions):
253 # copy velocities to diffusion solver
254 copy_function = copyPatchAndApplyFunction(
255 solverSource=atmospheric_solver,
256 solverDestination=diffusion_solver,
257 indexArrayDestination="diffusionIndices",
258 function=f"fineGridCell{atmospheric_solver.name}Q.data()[sourceIndexLinearised + atmosphericIndices[unknown]] / fineGridCell{atmospheric_solver.name}Q.data()[sourceIndexLinearised + densityIndex]",
259 numberOfUnknownsToCopy=dimensions,
260 )
261
262 atmospheric_solver.postprocess_updated_patch += f"""// copy velocities to diffusion solver
263 {{
264 const int atmosphericIndices[DIMENSIONS] = {{
265 {atmospheric_solver.variable_names.index("rhou")},
266 {atmospheric_solver.variable_names.index("rhov")}{"," + str(atmospheric_solver.variable_names.index("rhow")) if dimensions == 3 else ""}
267 }};
268
269 const int diffusionIndices[DIMENSIONS] = {{
270 {diffusion_solver.variable_names.index("u")},
271 {diffusion_solver.variable_names.index("v")}{"," + str(diffusion_solver.variable_names.index("w")) if dimensions == 3 else ""}
272 }};
273
274 const int densityIndex = {atmospheric_solver.variable_names.index("rho")};
275
276 {copy_function}
277 }}
278 """
279
280 # copy other unknowns to diffusion solver
281 copy_function = copyPatchAndApplyFunction(
282 solverSource=atmospheric_solver,
283 solverDestination=diffusion_solver,
284 indexArrayDestination="diffusionIndices",
285 function=f"fineGridCell{atmospheric_solver.name}Q.data()[sourceIndexLinearised + atmosphericIndices[unknown]]",
286 numberOfUnknownsToCopy=dimensions,
287 )
288
289 atmospheric_solver.postprocess_updated_patch += f"""// copy other unknowns to diffusion solver
290 {{
291 const int atmosphericIndices[] = {{
292 {atmospheric_solver.variable_names.index("rho")},
293 {atmospheric_solver.variable_names.index("E")},
294 {atmospheric_solver.variable_names.index("O")},
295 {atmospheric_solver.variable_names.index("O2")},
296 {atmospheric_solver.variable_names.index("N2")},
297 {atmospheric_solver.variable_names.index("T")}
298 }};
299
300 const int diffusionIndices[] = {{
301 {diffusion_solver.variable_names.index("rho")},
302 {diffusion_solver.variable_names.index("E")},
303 {diffusion_solver.variable_names.index("O")},
304 {diffusion_solver.variable_names.index("O2")},
305 {diffusion_solver.variable_names.index("N2")},
306 {diffusion_solver.variable_names.index("T")}
307 }};
308
309 {copy_function}
310 }}
311 """
312
313
315 atmospheric_solver,
316 diffusion_solver,
317 numberOfVariablesAtmospheric,
318 numberOfVariablesDiffusion,
319 dimensions,
320):
321 # copy updated velocities to atmospheric solver
322 copy_function = copyPatchAndApplyFunction(
323 solverSource=diffusion_solver,
324 solverDestination=atmospheric_solver,
325 indexArrayDestination="atmosphericIndices",
326 function=f"fineGridCell{diffusion_solver.name}Q.data()[sourceIndexLinearised + diffusionIndices[unknown]] * fineGridCell{atmospheric_solver.name}Q.data()[destIndexLinearised - atmosphericIndices[unknown] + densityIndex]",
327 numberOfUnknownsToCopy=dimensions,
328 )
329
330 diffusion_solver.postprocess_updated_patch += f"""// copy velocities to atmospheric solver
331 {{
332 const int atmosphericIndices[DIMENSIONS] = {{
333 {atmospheric_solver.variable_names.index("rhou")},
334 {atmospheric_solver.variable_names.index("rhov")}{"," + str(atmospheric_solver.variable_names.index("rhow")) if dimensions == 3 else ""}
335 }};
336
337 const int diffusionIndices[DIMENSIONS] = {{
338 {diffusion_solver.variable_names.index("u")},
339 {diffusion_solver.variable_names.index("v")}{"," + str(diffusion_solver.variable_names.index("w")) if dimensions == 3 else ""}
340 }};
341
342 const int densityIndex = {atmospheric_solver.variable_names.index("rho")};
343
344 {copy_function}
345 }}
346 """
347
348 # copy updated temperature to atmospheric solver
349 diffusion_solver.postprocess_updated_patch += f"""// copy temperature
350 ::toolbox::blockstructured::copyUnknown(
351 {atmospheric_solver.patch_size}, // no of unknowns per dimension
352 fineGridCell{diffusion_solver.name}Q.data(), // source
353 {diffusion_solver.variable_names.index("T")}, // temperature in source
354 {numberOfVariablesDiffusion}, // unknowns in source (incl material parameters)
355 0, // no overlap/halo here
356 fineGridCell{atmospheric_solver.name}Q.data(), // dest
357 {atmospheric_solver.variable_names.index("T")} , // temperature in dest
358 {numberOfVariablesAtmospheric}, // unknowns in dest (incl material parameters)
359 0 // no overlap/halo here
360 );
361 """
362
363 # calculate new energy from pressure with new temperature and new velocities
364 diffusion_solver.postprocess_updated_patch += f""" // copy new energy for atmosphere
365 ::toolbox::blockstructured::copyUnknown(
366 {atmospheric_solver.patch_size}, // no of unknowns per dimension
367 fineGridCell{diffusion_solver.name}Q.data(), // source
368 {diffusion_solver.variable_names.index("E")}, // temperature in source
369 {numberOfVariablesDiffusion}, // unknowns in source (incl material parameters)
370 0, // no overlap/halo here
371 fineGridCell{atmospheric_solver.name}Q.data(), // dest
372 {atmospheric_solver.variable_names.index("E")} , // temperature in dest
373 {numberOfVariablesAtmospheric}, // unknowns in dest (incl material parameters)
374 0 // no overlap/halo here
375 );
376 """
377
378
380 diffusion_solver,
381 chemical_solver,
382 numberOfVariablesDiffusion,
383 numberOfVariablesChemical,
384 dimensions,
385):
386 # copy updated velocities to chemical solver
387 copy_function = copyPatchAndApplyFunction(
388 solverSource=diffusion_solver,
389 solverDestination=chemical_solver,
390 indexArrayDestination="chemicalIndicies",
391 function=f"fineGridCell{chemical_solver.name}Q.data()[sourceIndexLinearised + diffusionIndicies[unknown]]",
392 numberOfUnknownsToCopy=dimensions,
393 )
394
395 diffusion_solver.postprocess_updated_patch += f"""// copy velocities to chemical solver
396 {{
397 const int chemicalIndices[DIMENSIONS] = {{
398 {chemical_solver.variable_names.index("u")},
399 {chemical_solver.variable_names.index("v")}{"," + str(chemical_solver.variable_names.index("w")) if dimensions == 3 else ""}
400 }};
401
402 const int diffusionIndices[DIMENSIONS] = {{
403 {diffusion_solver.variable_names.index("u")},
404 {diffusion_solver.variable_names.index("v")}{"," + str(diffusion_solver.variable_names.index("w")) if dimensions == 3 else ""}
405 }};
406
407 {copy_function}
408 }}
409 """
410
411 # copy updated temperature to chemical solver
412 diffusion_solver.postprocess_updated_patch += f"""// copy temperature
413 ::toolbox::blockstructured::copyUnknown(
414 {chemical_solver.patch_size}, // no of unknowns per dimension
415 fineGridCell{diffusion_solver.name}Q.data(), // source
416 {diffusion_solver.variable_names.index("T")}, // temperature in source
417 {numberOfVariablesDiffusion}, // unknowns in source (incl material parameters)
418 0, // no overlap/halo here
419 fineGridCell{chemical_solver.name}Q.data(), // dest
420 {chemical_solver.variable_names.index("T")} , // temperature in dest
421 {numberOfVariablesChemical}, // unknowns in dest (incl material parameters)
422 0 // no overlap/halo here
423 );
424 """
425
426
427def chemistryToAtmosphere(atmospheric_solver, chemical_solver):
428 # copy chemical densities of major species over to atmospheric model
429 copy_function = copyPatchAndApplyFunction(
430 solverSource=chemical_solver,
431 solverDestination=atmospheric_solver,
432 indexArrayDestination="atmosphericIndices",
433 function=f"fineGridCell{chemical_solver.name}Q.data()[sourceIndexLinearised + chemicalIndices[unknown]]",
434 numberOfUnknownsToCopy=3,
435 )
436
437 chemical_solver.postprocess_updated_patch += f"""
438 // copy major species densities
439 {{
440 const int chemicalIndices[3] = {{
441 {chemical_solver.variable_names.index("O")},
442 {chemical_solver.variable_names.index("O2")},
443 {chemical_solver.variable_names.index("N2")}
444 }};
445
446 const int atmosphericIndices[3] = {{
447 {atmospheric_solver.variable_names.index("O")},
448 {atmospheric_solver.variable_names.index("O2")},
449 {atmospheric_solver.variable_names.index("N2")}
450 }};
451
452 {copy_function}
453 }}
454 """
diffusionToAtmosphere(atmospheric_solver, diffusion_solver, numberOfVariablesAtmospheric, numberOfVariablesDiffusion, dimensions)
copyPatchAndApplyFunction(solverSource, solverDestination, indexArrayDestination, function, numberOfUnknownsToCopy)
@coupling: This function can be used to copy values and transform them while doing so.
diffusionToChemistry(diffusion_solver, chemical_solver, numberOfVariablesDiffusion, numberOfVariablesChemical, dimensions)
setLastSolver(atmospheric_solver, diffusion_solver, chemical_solver)
atmosphereToDiffusion(atmospheric_solver, diffusion_solver, dimensions)
synchronizePatchGravityWaves(atmospheric_solver, diffusion_solver, chemical_solver)
atmosphereToChemistry(atmospheric_solver, chemical_solver, numberOfVariablesAtmospheric, numberOfVariablesChemical, dimensions)
determineSolverCoupling(atmospheric_solver, diffusion_solver, chemical_solver)
chemistryToAtmosphere(atmospheric_solver, chemical_solver)
coupleTimeStepping(atmospheric_solver, diffusion_solver, chemical_solver)