|
3 | 3 |
|
4 | 4 | """ |
5 | 5 |
|
6 | | - |
7 | 6 | from pyro import compressible_fv4 |
8 | | -from pyro.mesh import patch |
| 7 | +from pyro.mesh import fv, patch |
9 | 8 | from pyro.util import msg |
10 | 9 |
|
11 | 10 |
|
12 | 11 | class Simulation(compressible_fv4.Simulation): |
13 | 12 | """Drive the 4th-order compressible solver with SDC time integration""" |
14 | 13 |
|
| 14 | + def __init__(self, solver_name, problem_name, problem_func, rp, *, |
| 15 | + problem_finalize_func=None, problem_source_func=None, |
| 16 | + timers=None, data_class=fv.FV2d): |
| 17 | + |
| 18 | + super().__init__(solver_name, problem_name, problem_func, rp, |
| 19 | + problem_finalize_func=problem_finalize_func, |
| 20 | + problem_source_func=problem_source_func, |
| 21 | + timers=timers, data_class=data_class) |
| 22 | + |
| 23 | + self.n_nodes = 3 # Gauss-Lobotto temporal nodes |
| 24 | + self.n_iter = 4 # 4 SDC iterations for 4th order |
| 25 | + |
15 | 26 | def sdc_integral(self, m_start, m_end, As): |
16 | 27 | """Compute the integral over the sources from m to m+1 with a |
17 | 28 | Simpson's rule""" |
@@ -58,38 +69,50 @@ def evolve(self): |
58 | 69 | U_knew.append(patch.cell_center_data_clone(self.cc_data)) |
59 | 70 | U_knew.append(patch.cell_center_data_clone(self.cc_data)) |
60 | 71 |
|
61 | | - # loop over iterations |
62 | | - for _ in range(1, 5): |
| 72 | + # we need the advective term at all time nodes at the old |
| 73 | + # iteration -- we'll compute this for the initial state |
| 74 | + # now |
| 75 | + A_kold = [] |
| 76 | + A_kold.append(self.substep(U_kold[0])) |
| 77 | + A_kold.append(A_kold[-1].copy()) |
| 78 | + A_kold.append(A_kold[-1].copy()) |
| 79 | + |
| 80 | + A_knew = [] |
| 81 | + for adv in A_kold: |
| 82 | + A_knew.append(adv.copy()) |
63 | 83 |
|
64 | | - # we need the advective term at all time nodes at the old |
65 | | - # iteration -- we'll compute this now |
66 | | - A_kold = [] |
67 | | - for m in range(3): |
68 | | - _tmp = self.substep(U_kold[m]) |
69 | | - A_kold.append(_tmp) |
| 84 | + # loop over iterations |
| 85 | + for _ in range(self.n_iter): |
70 | 86 |
|
71 | 87 | # loop over the time nodes and update |
72 | | - for m in range(2): |
| 88 | + for m in range(self.n_nodes): |
73 | 89 |
|
74 | 90 | # update m to m+1 for knew |
75 | 91 |
|
76 | 92 | # compute A(U_m^{k+1}) |
77 | | - A_knew = self.substep(U_knew[m]) |
| 93 | + # note: for m = 0, the advective term doesn't change |
| 94 | + if m > 0: |
| 95 | + A_knew[m] = self.substep(U_knew[m]) |
| 96 | + |
| 97 | + # only do an update if we are not at the last node |
| 98 | + if m < self.n_nodes-1: |
78 | 99 |
|
79 | | - # compute the integral over A at the old iteration |
80 | | - integral = self.sdc_integral(m, m+1, A_kold) |
| 100 | + # compute the integral over A at the old iteration |
| 101 | + integral = self.sdc_integral(m, m+1, A_kold) |
81 | 102 |
|
82 | | - # and the final update |
83 | | - for n in range(self.ivars.nvar): |
84 | | - U_knew[m+1].data.v(n=n)[:, :] = U_knew[m].data.v(n=n) + \ |
85 | | - 0.5*self.dt * (A_knew.v(n=n) - A_kold[m].v(n=n)) + integral.v(n=n) |
| 103 | + # and the final update |
| 104 | + for n in range(self.ivars.nvar): |
| 105 | + U_knew[m+1].data.v(n=n)[:, :] = U_knew[m].data.v(n=n) + \ |
| 106 | + 0.5*self.dt * (A_knew[m].v(n=n) - A_kold[m].v(n=n)) + integral.v(n=n) |
86 | 107 |
|
87 | | - # fill ghost cells |
88 | | - U_knew[m+1].fill_BC_all() |
| 108 | + # fill ghost cells |
| 109 | + U_knew[m+1].fill_BC_all() |
89 | 110 |
|
90 | 111 | # store the current iteration as the old iteration |
91 | | - for m in range(1, 3): |
| 112 | + # node m = 0 data doesn't change |
| 113 | + for m in range(1, self.n_nodes): |
92 | 114 | U_kold[m].data[:, :, :] = U_knew[m].data[:, :, :] |
| 115 | + A_kold[m][:, :, :] = A_knew[m][:, :, :] |
93 | 116 |
|
94 | 117 | # store the new solution |
95 | 118 | self.cc_data.data[:, :, :] = U_knew[-1].data[:, :, :] |
|
0 commit comments