diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle index 2a9d1db74..73ead4b9e 100644 Binary files a/.doctrees/environment.pickle and b/.doctrees/environment.pickle differ diff --git a/.doctrees/projects/Hamiltonian.doctree b/.doctrees/projects/Hamiltonian.doctree index 98402b0d7..0aca573a0 100644 Binary files a/.doctrees/projects/Hamiltonian.doctree and b/.doctrees/projects/Hamiltonian.doctree differ diff --git a/.doctrees/projects/doc_fput.doctree b/.doctrees/projects/doc_fput.doctree index 082ace82e..0e0345fb4 100644 Binary files a/.doctrees/projects/doc_fput.doctree and b/.doctrees/projects/doc_fput.doctree differ diff --git a/.doctrees/pySDC/implementations.sweeper_classes.Runge_Kutta.doctree b/.doctrees/pySDC/implementations.sweeper_classes.Runge_Kutta.doctree index 3c9af42fe..88f219c61 100644 Binary files a/.doctrees/pySDC/implementations.sweeper_classes.Runge_Kutta.doctree and b/.doctrees/pySDC/implementations.sweeper_classes.Runge_Kutta.doctree differ diff --git a/.doctrees/pySDC/implementations.sweeper_classes.Runge_Kutta_Nystrom.doctree b/.doctrees/pySDC/implementations.sweeper_classes.Runge_Kutta_Nystrom.doctree index c8f9ab83f..3736b943e 100644 Binary files a/.doctrees/pySDC/implementations.sweeper_classes.Runge_Kutta_Nystrom.doctree and b/.doctrees/pySDC/implementations.sweeper_classes.Runge_Kutta_Nystrom.doctree differ diff --git a/.doctrees/tutorial/doc_step_2_C.doctree b/.doctrees/tutorial/doc_step_2_C.doctree index 0cda15cbd..396f3b379 100644 Binary files a/.doctrees/tutorial/doc_step_2_C.doctree and b/.doctrees/tutorial/doc_step_2_C.doctree differ diff --git a/.doctrees/tutorial/doc_step_3_B.doctree b/.doctrees/tutorial/doc_step_3_B.doctree index 72c7e5b18..f5032bfae 100644 Binary files a/.doctrees/tutorial/doc_step_3_B.doctree and b/.doctrees/tutorial/doc_step_3_B.doctree differ diff --git a/.doctrees/tutorial/doc_step_4_D.doctree b/.doctrees/tutorial/doc_step_4_D.doctree index b0ee89ba7..f1956b814 100644 Binary files a/.doctrees/tutorial/doc_step_4_D.doctree and b/.doctrees/tutorial/doc_step_4_D.doctree differ diff --git a/.doctrees/tutorial/doc_step_7_A.doctree b/.doctrees/tutorial/doc_step_7_A.doctree index 58e78f457..e0a146c8f 100644 Binary files a/.doctrees/tutorial/doc_step_7_A.doctree and b/.doctrees/tutorial/doc_step_7_A.doctree differ diff --git a/.doctrees/tutorial/doc_step_7_B.doctree b/.doctrees/tutorial/doc_step_7_B.doctree index 3ea39a5d5..a47c65916 100644 Binary files a/.doctrees/tutorial/doc_step_7_B.doctree and b/.doctrees/tutorial/doc_step_7_B.doctree differ diff --git a/.doctrees/tutorial/doc_step_7_C.doctree b/.doctrees/tutorial/doc_step_7_C.doctree index 396f4fa5d..158b42ffa 100644 Binary files a/.doctrees/tutorial/doc_step_7_C.doctree and b/.doctrees/tutorial/doc_step_7_C.doctree differ diff --git a/.doctrees/tutorial/doc_step_7_D.doctree b/.doctrees/tutorial/doc_step_7_D.doctree index 25071f92e..4dd5fac11 100644 Binary files a/.doctrees/tutorial/doc_step_7_D.doctree and b/.doctrees/tutorial/doc_step_7_D.doctree differ diff --git a/.doctrees/tutorial/doc_step_8_C.doctree b/.doctrees/tutorial/doc_step_8_C.doctree index ec3eb3506..e14193109 100644 Binary files a/.doctrees/tutorial/doc_step_8_C.doctree and b/.doctrees/tutorial/doc_step_8_C.doctree differ diff --git a/.doctrees/tutorial/step_2.doctree b/.doctrees/tutorial/step_2.doctree index afdd2c3cb..60daa451a 100644 Binary files a/.doctrees/tutorial/step_2.doctree and b/.doctrees/tutorial/step_2.doctree differ diff --git a/.doctrees/tutorial/step_3.doctree b/.doctrees/tutorial/step_3.doctree index c65c74b24..b3e78abda 100644 Binary files a/.doctrees/tutorial/step_3.doctree and b/.doctrees/tutorial/step_3.doctree differ diff --git a/.doctrees/tutorial/step_4.doctree b/.doctrees/tutorial/step_4.doctree index 069edf45e..7aa4c9df9 100644 Binary files a/.doctrees/tutorial/step_4.doctree and b/.doctrees/tutorial/step_4.doctree differ diff --git a/.doctrees/tutorial/step_7.doctree b/.doctrees/tutorial/step_7.doctree index 19136608f..04241dd94 100644 Binary files a/.doctrees/tutorial/step_7.doctree and b/.doctrees/tutorial/step_7.doctree differ diff --git a/.doctrees/tutorial/step_8.doctree b/.doctrees/tutorial/step_8.doctree index 728844011..0f79c53ab 100644 Binary files a/.doctrees/tutorial/step_8.doctree and b/.doctrees/tutorial/step_8.doctree differ diff --git a/_images/coverage-badge.svg b/_images/coverage-badge.svg index 44d9fa3b1..0a658e60c 100644 --- a/_images/coverage-badge.svg +++ b/_images/coverage-badge.svg @@ -1 +1 @@ -coverage: 77.80%coverage77.80% \ No newline at end of file +coverage: 77.81%coverage77.81% \ No newline at end of file diff --git a/_images/timings_SDC_variants_Fisher.png b/_images/timings_SDC_variants_Fisher.png index d0333966d..20d527382 100644 Binary files a/_images/timings_SDC_variants_Fisher.png and b/_images/timings_SDC_variants_Fisher.png differ diff --git a/_images/timings_SDC_variants_GrayScott.png b/_images/timings_SDC_variants_GrayScott.png index 5baadbf95..c48701692 100644 Binary files a/_images/timings_SDC_variants_GrayScott.png and b/_images/timings_SDC_variants_GrayScott.png differ diff --git a/_modules/implementations/convergence_controller_classes/estimate_embedded_error.html b/_modules/implementations/convergence_controller_classes/estimate_embedded_error.html index 1af82992b..c66cf049f 100644 --- a/_modules/implementations/convergence_controller_classes/estimate_embedded_error.html +++ b/_modules/implementations/convergence_controller_classes/estimate_embedded_error.html @@ -145,10 +145,10 @@

Source code for implementations.convergence_controller_classes.estimate_embe dtype_u: The embedded error estimate """ if self.params.sweeper_type == "RK": - # lower order solution is stored in the second to last entry of L.u - return abs(L.u[-2] - L.u[-1]) + L.sweep.compute_end_point() + return abs(L.uend - L.sweep.u_secondary) elif self.params.sweeper_type == "SDC": - # order rises by one between sweeps, making this so ridiculously easy + # order rises by one between sweeps return abs(L.uold[-1] - L.u[-1]) elif self.params.sweeper_type == 'MPI': comm = L.sweep.comm diff --git a/_modules/implementations/sweeper_classes/Runge_Kutta.html b/_modules/implementations/sweeper_classes/Runge_Kutta.html index a61a94004..5ce5056e5 100644 --- a/_modules/implementations/sweeper_classes/Runge_Kutta.html +++ b/_modules/implementations/sweeper_classes/Runge_Kutta.html @@ -58,44 +58,16 @@

Source code for implementations.sweeper_classes.Runge_Kutta

nodes (numpy.ndarray): Butcher tableau nodes matrix (numpy.ndarray): Butcher tableau entries """ - # check if the arguments have the correct form - if type(matrix) != np.ndarray: - raise ParameterError('Runge-Kutta matrix needs to be supplied as a numpy array!') - elif len(np.unique(matrix.shape)) != 1 or len(matrix.shape) != 2: - raise ParameterError('Runge-Kutta matrix needs to be a square 2D numpy array!') - - if type(weights) != np.ndarray: - raise ParameterError('Weights need to be supplied as a numpy array!') - elif len(weights.shape) != 1: - raise ParameterError(f'Incompatible dimension of weights! Need 1, got {len(weights.shape)}') - elif len(weights) != matrix.shape[0]: - raise ParameterError(f'Incompatible number of weights! Need {matrix.shape[0]}, got {len(weights)}') - - if type(nodes) != np.ndarray: - raise ParameterError('Nodes need to be supplied as a numpy array!') - elif len(nodes.shape) != 1: - raise ParameterError(f'Incompatible dimension of nodes! Need 1, got {len(nodes.shape)}') - elif len(nodes) != matrix.shape[0]: - raise ParameterError(f'Incompatible number of nodes! Need {matrix.shape[0]}, got {len(nodes)}') - - self.globally_stiffly_accurate = np.allclose(matrix[-1], weights) + self.check_method(weights, nodes, matrix) self.tleft = 0.0 self.tright = 1.0 - self.num_solution_stages = 0 if self.globally_stiffly_accurate else 1 - self.num_nodes = matrix.shape[0] + self.num_solution_stages + self.num_nodes = matrix.shape[0] self.weights = weights - if self.globally_stiffly_accurate: - # For globally stiffly accurate methods, the last row of the Butcher tableau is the same as the weights. - self.nodes = np.append([0], nodes) - self.Qmat = np.zeros([self.num_nodes + 1, self.num_nodes + 1]) - self.Qmat[1:, 1:] = matrix - else: - self.nodes = np.append(np.append([0], nodes), [1]) - self.Qmat = np.zeros([self.num_nodes + 1, self.num_nodes + 1]) - self.Qmat[1:-1, 1:-1] = matrix - self.Qmat[-1, 1:-1] = weights # this is for computing the solution to the step from the previous stages + self.nodes = np.append([0], nodes) + self.Qmat = np.zeros([self.num_nodes + 1, self.num_nodes + 1]) + self.Qmat[1:, 1:] = matrix self.left_is_node = True self.right_is_node = self.nodes[-1] == self.tright @@ -108,37 +80,19 @@

Source code for implementations.sweeper_classes.Runge_Kutta

self.delta_m[0] = self.nodes[0] - self.tleft # check if the RK scheme is implicit - self.implicit = any(matrix[i, i] != 0 for i in range(self.num_nodes - self.num_solution_stages))
- + self.implicit = any(matrix[i, i] != 0 for i in range(self.num_nodes)) - -
-[docs] -class ButcherTableauEmbedded(object): - def __init__(self, weights, nodes, matrix): +
+[docs] + def check_method(self, weights, nodes, matrix): """ - Initialization routine to get a quadrature matrix out of a Butcher tableau for embedded RK methods. - - Be aware that the method that generates the final solution should be in the first row of the weights matrix. - - Args: - weights (numpy.ndarray): Butcher tableau weights - nodes (numpy.ndarray): Butcher tableau nodes - matrix (numpy.ndarray): Butcher tableau entries + Check that the method is entered in the correct format """ - # check if the arguments have the correct form if type(matrix) != np.ndarray: raise ParameterError('Runge-Kutta matrix needs to be supplied as a numpy array!') elif len(np.unique(matrix.shape)) != 1 or len(matrix.shape) != 2: raise ParameterError('Runge-Kutta matrix needs to be a square 2D numpy array!') - if type(weights) != np.ndarray: - raise ParameterError('Weights need to be supplied as a numpy array!') - elif len(weights.shape) != 2: - raise ParameterError(f'Incompatible dimension of weights! Need 2, got {len(weights.shape)}') - elif len(weights[0]) != matrix.shape[0]: - raise ParameterError(f'Incompatible number of weights! Need {matrix.shape[0]}, got {len(weights[0])}') - if type(nodes) != np.ndarray: raise ParameterError('Nodes need to be supplied as a numpy array!') elif len(nodes.shape) != 1: @@ -146,31 +100,50 @@

Source code for implementations.sweeper_classes.Runge_Kutta

elif len(nodes) != matrix.shape[0]: raise ParameterError(f'Incompatible number of nodes! Need {matrix.shape[0]}, got {len(nodes)}') - # Set number of nodes, left and right interval boundaries - self.num_solution_stages = 2 - self.num_nodes = matrix.shape[0] + self.num_solution_stages - self.tleft = 0.0 - self.tright = 1.0 + self.check_weights(weights, nodes, matrix)
- self.nodes = np.append(np.append([0], nodes), [1, 1]) - self.weights = weights - self.Qmat = np.zeros([self.num_nodes + 1, self.num_nodes + 1]) - self.Qmat[1:-2, 1:-2] = matrix - self.Qmat[-1, 1:-2] = weights[0] # this is for computing the higher order solution - self.Qmat[-2, 1:-2] = weights[1] # this is for computing the lower order solution - self.left_is_node = True - self.right_is_node = self.nodes[-1] == self.tright +
+[docs] + def check_weights(self, weights, nodes, matrix): + """ + Check that the weights of the method are entered in the correct format + """ + if type(weights) != np.ndarray: + raise ParameterError('Weights need to be supplied as a numpy array!') + elif len(weights.shape) != 1: + raise ParameterError(f'Incompatible dimension of weights! Need 1, got {len(weights.shape)}') + elif len(weights) != matrix.shape[0]: + raise ParameterError(f'Incompatible number of weights! Need {matrix.shape[0]}, got {len(weights)}')
+ + + @property + def globally_stiffly_accurate(self): + return np.allclose(self.Qmat[-1, 1:], self.weights)
- # compute distances between the nodes - if self.num_nodes > 1: - self.delta_m = self.nodes[1:] - self.nodes[:-1] - else: - self.delta_m = np.zeros(1) - self.delta_m[0] = self.nodes[0] - self.tleft - # check if the RK scheme is implicit - self.implicit = any(matrix[i, i] != 0 for i in range(self.num_nodes - self.num_solution_stages))
+ +
+[docs] +class ButcherTableauEmbedded(ButcherTableau): + +
+[docs] + def check_weights(self, weights, nodes, matrix): + """ + Check that the weights of the method are entered in the correct format + """ + if type(weights) != np.ndarray: + raise ParameterError('Weights need to be supplied as a numpy array!') + elif len(weights.shape) != 2: + raise ParameterError(f'Incompatible dimension of weights! Need 2, got {len(weights.shape)}') + elif len(weights[0]) != matrix.shape[0]: + raise ParameterError(f'Incompatible number of weights! Need {matrix.shape[0]}, got {len(weights[0])}')
+ + + @property + def globally_stiffly_accurate(self): + return np.allclose(self.Qmat[-1, 1:], self.weights[0])
@@ -356,8 +329,7 @@

Source code for implementations.sweeper_classes.Runge_Kutta

lvl.u[m + 1][:] = rhs[:] # update function values (we don't usually need to evaluate the RHS at the solution of the step) - if m < M - self.coll.num_solution_stages or self.params.eval_rhs_at_right_boundary: - lvl.f[m + 1] = prob.eval_f(lvl.u[m + 1], lvl.time + lvl.dt * self.coll.nodes[m + 1]) + lvl.f[m + 1] = prob.eval_f(lvl.u[m + 1], lvl.time + lvl.dt * self.coll.nodes[m + 1]) # indicate presence of new values at this level lvl.status.updated = True @@ -371,7 +343,28 @@

Source code for implementations.sweeper_classes.Runge_Kutta

""" In this Runge-Kutta implementation, the solution to the step is always stored in the last node """ - self.level.uend = self.level.u[-1]
+ lvl = self.level + + if lvl.f[1] is None: + lvl.uend = lvl.prob.dtype_u(lvl.u[0]) + if type(self.coll) == ButcherTableauEmbedded: + self.u_secondary = lvl.prob.dtype_u(lvl.u[0]) + elif self.coll.globally_stiffly_accurate: + lvl.uend = lvl.prob.dtype_u(lvl.u[-1]) + if type(self.coll) == ButcherTableauEmbedded: + self.u_secondary = lvl.prob.dtype_u(lvl.u[0]) + for w2, k in zip(self.coll.weights[1], lvl.f[1:]): + self.u_secondary += lvl.dt * w2 * k + else: + lvl.uend = lvl.prob.dtype_u(lvl.u[0]) + if type(self.coll) == ButcherTableau: + for w, k in zip(self.coll.weights, lvl.f[1:]): + lvl.uend += lvl.dt * w * k + elif type(self.coll) == ButcherTableauEmbedded: + self.u_secondary = lvl.prob.dtype_u(lvl.u[0]) + for w1, w2, k in zip(self.coll.weights[0], self.coll.weights[1], lvl.f[1:]): + lvl.uend += lvl.dt * w1 * k + self.u_secondary += lvl.dt * w2 * k
@property @@ -430,6 +423,7 @@

Source code for implementations.sweeper_classes.Runge_Kutta

""" matrix_explicit = None + weights_explicit = None ButcherTableauClass_explicit = ButcherTableau def __init__(self, params): @@ -440,6 +434,7 @@

Source code for implementations.sweeper_classes.Runge_Kutta

params: parameters for the sweeper """ super().__init__(params) + type(self).weights_explicit = self.weights if self.weights_explicit is None else self.weights_explicit self.coll_explicit = self.get_Butcher_tableau_explicit() self.QE = self.coll_explicit.Qmat @@ -467,7 +462,7 @@

Source code for implementations.sweeper_classes.Runge_Kutta

[docs] @classmethod def get_Butcher_tableau_explicit(cls): - return cls.ButcherTableauClass_explicit(cls.weights, cls.nodes, cls.matrix_explicit)
+ return cls.ButcherTableauClass_explicit(cls.weights_explicit, cls.nodes, cls.matrix_explicit)
@@ -533,14 +528,49 @@

Source code for implementations.sweeper_classes.Runge_Kutta

else: lvl.u[m + 1][:] = rhs[:] - # update function values (we don't usually need to evaluate the RHS at the solution of the step) - if m < M - self.coll.num_solution_stages or self.params.eval_rhs_at_right_boundary: - lvl.f[m + 1] = prob.eval_f(lvl.u[m + 1], lvl.time + lvl.dt * self.coll.nodes[m + 1]) + # update function values + lvl.f[m + 1] = prob.eval_f(lvl.u[m + 1], lvl.time + lvl.dt * self.coll.nodes[m + 1]) # indicate presence of new values at this level lvl.status.updated = True return None
+ + +
+[docs] + def compute_end_point(self): + """ + In this Runge-Kutta implementation, the solution to the step is always stored in the last node + """ + lvl = self.level + + if lvl.f[1] is None: + lvl.uend = lvl.prob.dtype_u(lvl.u[0]) + if type(self.coll) == ButcherTableauEmbedded: + self.u_secondary = lvl.prob.dtype_u(lvl.u[0]) + elif self.coll.globally_stiffly_accurate and self.coll_explicit.globally_stiffly_accurate: + lvl.uend = lvl.u[-1] + if type(self.coll) == ButcherTableauEmbedded: + self.u_secondary = lvl.prob.dtype_u(lvl.u[0]) + for w2, w2E, k in zip(self.coll.weights[1], self.coll_explicit.weights[1], lvl.f[1:]): + self.u_secondary += lvl.dt * (w2 * k.impl + w2E * k.expl) + else: + lvl.uend = lvl.prob.dtype_u(lvl.u[0]) + if type(self.coll) == ButcherTableau: + for w, wE, k in zip(self.coll.weights, self.coll_explicit.weights, lvl.f[1:]): + lvl.uend += lvl.dt * (w * k.impl + wE * k.expl) + elif type(self.coll) == ButcherTableauEmbedded: + self.u_secondary = lvl.u[0].copy() + for w1, w2, w1E, w2E, k in zip( + self.coll.weights[0], + self.coll.weights[1], + self.coll_explicit.weights[0], + self.coll_explicit.weights[1], + lvl.f[1:], + ): + lvl.uend += lvl.dt * (w1 * k.impl + w1E * k.expl) + self.u_secondary += lvl.dt * (w2 * k.impl + w2E * k.expl)
@@ -573,6 +603,17 @@

Source code for implementations.sweeper_classes.Runge_Kutta

+[docs] +class IMEXEuler(RungeKuttaIMEX): + nodes = BackwardEuler.nodes + weights = BackwardEuler.weights + + matrix = BackwardEuler.matrix + matrix_explicit = ForwardEuler.matrix
+ + +
[docs] class CrankNicolson(RungeKutta): @@ -628,8 +669,13 @@

Source code for implementations.sweeper_classes.Runge_Kutta

Second order explicit embedded Runge-Kutta method. """ + ButcherTableauClass = ButcherTableauEmbedded + generator = RK_SCHEMES["HEUN"]() - nodes, weights, matrix = generator.genCoeffs() + nodes, _weights, matrix = generator.genCoeffs() + weights = np.zeros((2, len(_weights))) + weights[0] = _weights + weights[1] = matrix[-1]
[docs] @@ -868,6 +914,62 @@

Source code for implementations.sweeper_classes.Runge_Kutta

return 5
+ + +
+[docs] +class ARK324L2SAERK(RungeKutta): + generator = RK_SCHEMES["ARK324L2SAERK"]() + nodes, weights, matrix = generator.genCoeffs(embedded=True) + ButcherTableauClass = ButcherTableauEmbedded + +
+[docs] + @classmethod + def get_update_order(cls): + return 3
+
+ + + +
+[docs] +class ARK324L2SAESDIRK(ARK324L2SAERK): + generator = RK_SCHEMES["ARK324L2SAESDIRK"]() + matrix = generator.Q
+ + + +
+[docs] +class ARK32(RungeKuttaIMEX): + ButcherTableauClass = ButcherTableauEmbedded + ButcherTableauClass_explicit = ButcherTableauEmbedded + + nodes = ARK324L2SAESDIRK.nodes + weights = ARK324L2SAESDIRK.weights + + matrix = ARK324L2SAESDIRK.matrix + matrix_explicit = ARK324L2SAERK.matrix + +
+[docs] + @classmethod + def get_update_order(cls): + return 3
+
+ + + +
+[docs] +class ARK2(RungeKuttaIMEX): + generator_IMP = RK_SCHEMES["ARK222EDIRK"]() + generator_EXP = RK_SCHEMES["ARK222ERK"]() + + nodes, weights, matrix = generator_IMP.genCoeffs() + _, weights_explicit, matrix_explicit = generator_EXP.genCoeffs()
+
diff --git a/_modules/implementations/sweeper_classes/Runge_Kutta_Nystrom.html b/_modules/implementations/sweeper_classes/Runge_Kutta_Nystrom.html index e5929d0cc..e85f44470 100644 --- a/_modules/implementations/sweeper_classes/Runge_Kutta_Nystrom.html +++ b/_modules/implementations/sweeper_classes/Runge_Kutta_Nystrom.html @@ -43,11 +43,77 @@

Source code for implementations.sweeper_classes.Runge_Kutta_Nystrom

from pySDC.core.sweeper import Sweeper, _Pars from pySDC.core.errors import ParameterError from pySDC.implementations.datatype_classes.particles import particles, fields, acceleration -from pySDC.implementations.sweeper_classes.Runge_Kutta import ButcherTableau -from copy import deepcopy from pySDC.implementations.sweeper_classes.Runge_Kutta import RungeKutta +
+[docs] +class ButcherTableauNoCollUpdate(object): + """Version of Butcher Tableau that does not need a collocation update because the weights are put in the last line of Q""" + + def __init__(self, weights, nodes, matrix): + """ + Initialization routine to get a quadrature matrix out of a Butcher tableau + + Args: + weights (numpy.ndarray): Butcher tableau weights + nodes (numpy.ndarray): Butcher tableau nodes + matrix (numpy.ndarray): Butcher tableau entries + """ + # check if the arguments have the correct form + if type(matrix) != np.ndarray: + raise ParameterError('Runge-Kutta matrix needs to be supplied as a numpy array!') + elif len(np.unique(matrix.shape)) != 1 or len(matrix.shape) != 2: + raise ParameterError('Runge-Kutta matrix needs to be a square 2D numpy array!') + + if type(weights) != np.ndarray: + raise ParameterError('Weights need to be supplied as a numpy array!') + elif len(weights.shape) != 1: + raise ParameterError(f'Incompatible dimension of weights! Need 1, got {len(weights.shape)}') + elif len(weights) != matrix.shape[0]: + raise ParameterError(f'Incompatible number of weights! Need {matrix.shape[0]}, got {len(weights)}') + + if type(nodes) != np.ndarray: + raise ParameterError('Nodes need to be supplied as a numpy array!') + elif len(nodes.shape) != 1: + raise ParameterError(f'Incompatible dimension of nodes! Need 1, got {len(nodes.shape)}') + elif len(nodes) != matrix.shape[0]: + raise ParameterError(f'Incompatible number of nodes! Need {matrix.shape[0]}, got {len(nodes)}') + + self.globally_stiffly_accurate = np.allclose(matrix[-1], weights) + + self.tleft = 0.0 + self.tright = 1.0 + self.num_solution_stages = 0 if self.globally_stiffly_accurate else 1 + self.num_nodes = matrix.shape[0] + self.num_solution_stages + self.weights = weights + + if self.globally_stiffly_accurate: + # For globally stiffly accurate methods, the last row of the Butcher tableau is the same as the weights. + self.nodes = np.append([0], nodes) + self.Qmat = np.zeros([self.num_nodes + 1, self.num_nodes + 1]) + self.Qmat[1:, 1:] = matrix + else: + self.nodes = np.append(np.append([0], nodes), [1]) + self.Qmat = np.zeros([self.num_nodes + 1, self.num_nodes + 1]) + self.Qmat[1:-1, 1:-1] = matrix + self.Qmat[-1, 1:-1] = weights # this is for computing the solution to the step from the previous stages + + self.left_is_node = True + self.right_is_node = self.nodes[-1] == self.tright + + # compute distances between the nodes + if self.num_nodes > 1: + self.delta_m = self.nodes[1:] - self.nodes[:-1] + else: + self.delta_m = np.zeros(1) + self.delta_m[0] = self.nodes[0] - self.tleft + + # check if the RK scheme is implicit + self.implicit = any(matrix[i, i] != 0 for i in range(self.num_nodes - self.num_solution_stages))
+ + +
[docs] class RungeKuttaNystrom(RungeKutta): @@ -75,9 +141,13 @@

Source code for implementations.sweeper_classes.Runge_Kutta_Nystrom

All of these variables are either determined by the RK rule, or are not part of an RK scheme. Attribues: - butcher_tableau (ButcherTableau): Butcher tableau for the Runge-Kutta scheme that you want + butcher_tableau (ButcherTableauNoCollUpdate): Butcher tableau for the Runge-Kutta scheme that you want """ + ButcherTableauClass = ButcherTableauNoCollUpdate + weights_bar = None + matrix_bar = None + def __init__(self, params): """ Initialization routine for the custom sweeper @@ -85,48 +155,22 @@

Source code for implementations.sweeper_classes.Runge_Kutta_Nystrom

Args: params: parameters for the sweeper """ - # set up logger - self.logger = logging.getLogger('sweeper') - - essential_keys = ['butcher_tableau'] - for key in essential_keys: - if key not in params: - msg = 'need %s to instantiate step, only got %s' % (key, str(params.keys())) - self.logger.error(msg) - raise ParameterError(msg) - - # check if some parameters are set which only apply to actual sweepers - for key in ['initial_guess', 'collocation_class', 'num_nodes']: - if key in params: - self.logger.warning(f'"{key}" will be ignored by Runge-Kutta sweeper') - - # set parameters to their actual values - params['initial_guess'] = 'zero' - params['collocation_class'] = type(params['butcher_tableau']) - params['num_nodes'] = params['butcher_tableau'].num_nodes - - # disable residual computation by default - params['skip_residual_computation'] = params.get( - 'skip_residual_computation', ('IT_CHECK', 'IT_FINE', 'IT_COARSE', 'IT_UP', 'IT_DOWN') - ) - - self.params = _Pars(params) - - self.coll = params['butcher_tableau'] - self.coll_bar = params['butcher_tableau_bar'] + super().__init__(params) + self.coll_bar = self.get_Butcher_tableau_bar() + self.Qx = self.coll_bar.Qmat - # This will be set as soon as the sweeper is instantiated at the level - self.__level = None +
+[docs] + @classmethod + def get_Butcher_tableau_bar(cls): + return cls.ButcherTableauClass(cls.weights_bar, cls.nodes, cls.matrix_bar)
- self.parallelizable = False - self.QI = self.coll.Qmat - self.Qx = self.coll_bar.Qmat
[docs] def get_full_f(self, f): """ - Test the right hand side funtion is the correct type + Test the right hand side function is the correct type Args: f (dtype_f): Right hand side at a single node @@ -164,7 +208,7 @@

Source code for implementations.sweeper_classes.Runge_Kutta_Nystrom

for m in range(0, M): # build rhs, consisting of the known values from above and new values from previous nodes (at k+1) - rhs = deepcopy(L.u[0]) + rhs = P.dtype_u(L.u[0]) rhs.pos += L.dt * self.coll.nodes[m + 1] * L.u[0].vel for j in range(1, m + 1): @@ -193,7 +237,7 @@

Source code for implementations.sweeper_classes.Runge_Kutta_Nystrom

if self.coll.implicit: # That is why it only works for the Velocity-Verlet scheme L.f[0] = P.eval_f(L.u[0], L.time) - L.f[m + 1] = deepcopy(L.f[0]) + L.f[m + 1] = P.dtype_f(L.f[0]) else: if m != self.coll.num_nodes - 1: L.f[m + 1] = P.eval_f(L.u[m + 1], L.time + L.dt * self.coll.nodes[m]) @@ -226,23 +270,18 @@

Source code for implementations.sweeper_classes.Runge_Kutta_Nystrom

Chapter: II.14 Numerical methods for Second order differential equations """ - def __init__(self, params): - nodes = np.array([0.0, 0.5, 0.5, 1]) - weights = np.array([1.0, 2.0, 2.0, 1.0]) / 6.0 - matrix = np.zeros([4, 4]) - matrix[1, 0] = 0.5 - matrix[2, 1] = 0.5 - matrix[3, 2] = 1.0 - - weights_bar = np.array([1.0, 1.0, 1.0, 0]) / 6.0 - matrix_bar = np.zeros([4, 4]) - matrix_bar[1, 0] = 1 / 8 - matrix_bar[2, 0] = 1 / 8 - matrix_bar[3, 2] = 1 / 2 - params['butcher_tableau'] = ButcherTableau(weights, nodes, matrix) - params['butcher_tableau_bar'] = ButcherTableau(weights_bar, nodes, matrix_bar) + nodes = np.array([0.0, 0.5, 0.5, 1]) + weights = np.array([1.0, 2.0, 2.0, 1.0]) / 6.0 + matrix = np.zeros([4, 4]) + matrix[1, 0] = 0.5 + matrix[2, 1] = 0.5 + matrix[3, 2] = 1.0 - super(RKN, self).__init__(params)
+ weights_bar = np.array([1.0, 1.0, 1.0, 0]) / 6.0 + matrix_bar = np.zeros([4, 4]) + matrix_bar[1, 0] = 1 / 8 + matrix_bar[2, 0] = 1 / 8 + matrix_bar[3, 2] = 1 / 2
@@ -254,18 +293,12 @@

Source code for implementations.sweeper_classes.Runge_Kutta_Nystrom

https://de.wikipedia.org/wiki/Verlet-Algorithmus """ - def __init__(self, params): - nodes = np.array([1.0, 1.0]) - weights = np.array([1 / 2, 0]) - matrix = np.zeros([2, 2]) - matrix[1, 1] = 1 - weights_bar = np.array([1 / 2, 0]) - matrix_bar = np.zeros([2, 2]) - params['butcher_tableau'] = ButcherTableau(weights, nodes, matrix) - params['butcher_tableau_bar'] = ButcherTableau(weights_bar, nodes, matrix_bar) - params['Velocity_verlet'] = True - - super(Velocity_Verlet, self).__init__(params)
+ nodes = np.array([1.0, 1.0]) + weights = np.array([1 / 2, 0]) + matrix = np.zeros([2, 2]) + matrix[1, 1] = 1 + weights_bar = np.array([1 / 2, 0]) + matrix_bar = np.zeros([2, 2])
diff --git a/coverage/class_index.html b/coverage/class_index.html index 94a4a9809..2ce51d0de 100644 --- a/coverage/class_index.html +++ b/coverage/class_index.html @@ -55,7 +55,7 @@

coverage.py v7.6.4, - created at 2024-10-25 11:27 +0000 + created at 2024-11-06 12:12 +0000

@@ -731,10 +731,10 @@

pySDC/implementations/convergence_controller_classes/estimate_embedded_error.py EstimateEmbeddedError - 32 + 33 7 2 - 78% + 79% pySDC/implementations/convergence_controller_classes/estimate_embedded_error.py @@ -2659,146 +2659,154 @@

pySDC/implementations/sweeper_classes/Runge_Kutta.py ButcherTableau - 29 + 25 0 8 - 100% + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ButcherTableauEmbedded - 25 - 1 - 8 - 96% + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ButcherTableauEmbedded + 4 + 0 + 3 + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta - 60 - 9 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta + 78 + 13 2 - 85% + 83% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKuttaIMEX - 35 - 8 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKuttaIMEX + 55 + 14 0 - 77% + 75% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - Heun_Euler + pySDC/implementations/sweeper_classes/Runge_Kutta.py + Heun_Euler 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - Cash_Karp + pySDC/implementations/sweeper_classes/Runge_Kutta.py + Cash_Karp 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - DIRK43 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + DIRK43 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ESDIRK53 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ESDIRK53 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ESDIRK43 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ESDIRK43 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ARK548L2SAERK + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK548L2SAERK 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ARK54 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK54 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ARK548L2SAESDIRK2 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK548L2SAESDIRK2 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ARK548L2SA + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK548L2SA 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - (no class) - 130 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK324L2SAERK + 1 0 0 - 100% + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - RungeKuttaNystrom - 48 - 2 - 2 - 96% + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK32 + 1 + 0 + 0 + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - RKN - 14 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + (no class) + 170 0 0 - 100% + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - Velocity_Verlet - 10 - 0 + pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py + ButcherTableauNoCollUpdate + 29 + 4 + 8 + 86% + + + pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py + RungeKuttaNystrom + 32 0 - 100% + 1 + 100% pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py (no class) - 17 + 37 0 0 - 100% + 100% pySDC/implementations/sweeper_classes/boris_2nd_order.py @@ -5589,23 +5597,23 @@

Total   - 27921 - 6199 - 5474 - 78% + 27986 + 6210 + 5476 + 78%

No items found using the specified filter.

-

51 empty classes skipped.

+

56 empty classes skipped.

coverage.py v7.6.4, - created at 2024-10-25 11:27 +0000 + created at 2024-11-06 12:12 +0000

@@ -3075,10 +3075,10 @@

pySDC/implementations/convergence_controller_classes/estimate_embedded_error.py EstimateEmbeddedError.estimate_embedded_error_serial - 7 + 8 3 1 - 57% + 62% pySDC/implementations/convergence_controller_classes/estimate_embedded_error.py @@ -8915,274 +8915,330 @@

pySDC/implementations/sweeper_classes/Runge_Kutta.py ButcherTableau.__init__ - 29 + 15 0 - 8 - 100% + 0 + 100% + + + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ButcherTableau.check_method + 6 + 0 + 5 + 100% + + + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ButcherTableau.check_weights + 3 + 0 + 3 + 100% pySDC/implementations/sweeper_classes/Runge_Kutta.py - ButcherTableauEmbedded.__init__ - 25 + ButcherTableau.globally_stiffly_accurate 1 - 8 - 96% + 0 + 0 + 100% + + + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ButcherTableauEmbedded.check_weights + 3 + 0 + 3 + 100% + + + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ButcherTableauEmbedded.globally_stiffly_accurate + 1 + 0 + 0 + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.__init__ + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.__init__ 14 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.get_Q_matrix + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.get_Q_matrix 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.get_Butcher_tableau + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.get_Butcher_tableau 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.get_full_f + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.get_full_f 7 + 5 1 - 1 - 86% + 29% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.integrate + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.integrate 8 8 0 0% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.update_nodes - 16 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.update_nodes + 15 0 0 - 100% + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.compute_end_point - 1 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.compute_end_point + 20 0 0 - 100% + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.level + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.level 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.level + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.level 5 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKutta.predict + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKutta.predict 6 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKuttaIMEX.__init__ - 3 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKuttaIMEX.__init__ + 4 0 0 - 100% + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKuttaIMEX.predict + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKuttaIMEX.predict 7 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKuttaIMEX.get_Butcher_tableau_explicit + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKuttaIMEX.get_Butcher_tableau_explicit 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKuttaIMEX.integrate + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKuttaIMEX.integrate 8 8 0 0% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - RungeKuttaIMEX.update_nodes - 16 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKuttaIMEX.update_nodes + 15 0 0 - 100% + 100% + + + pySDC/implementations/sweeper_classes/Runge_Kutta.py + RungeKuttaIMEX.compute_end_point + 20 + 6 + 0 + 70% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - Heun_Euler.get_update_order + pySDC/implementations/sweeper_classes/Runge_Kutta.py + Heun_Euler.get_update_order 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - Cash_Karp.get_update_order + pySDC/implementations/sweeper_classes/Runge_Kutta.py + Cash_Karp.get_update_order 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - DIRK43.get_update_order + pySDC/implementations/sweeper_classes/Runge_Kutta.py + DIRK43.get_update_order 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ESDIRK53.get_update_order + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ESDIRK53.get_update_order 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ESDIRK43.get_update_order + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ESDIRK43.get_update_order 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ARK548L2SAERK.get_update_order + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK548L2SAERK.get_update_order 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ARK54.get_update_order + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK54.get_update_order 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ARK548L2SAESDIRK2.get_update_order + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK548L2SAESDIRK2.get_update_order 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - ARK548L2SA.get_update_order + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK548L2SA.get_update_order 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta.py - (no function) - 130 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK324L2SAERK.get_update_order + 1 0 0 - 100% + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - RungeKuttaNystrom.__init__ - 20 - 2 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + ARK32.get_update_order 1 - 90% + 0 + 0 + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - RungeKuttaNystrom.get_full_f - 2 + pySDC/implementations/sweeper_classes/Runge_Kutta.py + (no function) + 170 0 - 1 - 100% + 0 + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - RungeKuttaNystrom.update_nodes - 25 + pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py + ButcherTableauNoCollUpdate.__init__ + 29 + 4 + 8 + 86% + + + pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py + RungeKuttaNystrom.__init__ + 3 0 0 - 100% + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - RungeKuttaNystrom.compute_end_point + pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py + RungeKuttaNystrom.get_Butcher_tableau_bar 1 0 0 100% - pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - RKN.__init__ - 14 + pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py + RungeKuttaNystrom.get_full_f + 2 0 + 1 + 100% + + + pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py + RungeKuttaNystrom.update_nodes + 25 0 - 100% + 0 + 100% - pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - Velocity_Verlet.__init__ - 10 + pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py + RungeKuttaNystrom.compute_end_point + 1 0 0 - 100% + 100% pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py (no function) - 17 + 37 0 0 - 100% + 100% pySDC/implementations/sweeper_classes/boris_2nd_order.py @@ -17853,10 +17909,10 @@

Total   - 27921 - 6199 - 5474 - 78% + 27986 + 6210 + 5476 + 78% @@ -17869,7 +17925,7 @@

coverage.py v7.6.4, - created at 2024-10-25 11:27 +0000 + created at 2024-11-06 12:12 +0000

@@ -289,10 +289,10 @@

pySDC/implementations/convergence_controller_classes/estimate_embedded_error.py - 104 + 105 22 4 - 79% + 79% pySDC/implementations/convergence_controller_classes/estimate_extrapolation_error.py @@ -863,17 +863,17 @@

pySDC/implementations/sweeper_classes/Runge_Kutta.py - 288 - 18 - 18 - 94% + 343 + 27 + 13 + 92% pySDC/implementations/sweeper_classes/Runge_Kutta_Nystrom.py - 89 - 2 - 2 - 98% + 98 + 4 + 9 + 96% pySDC/implementations/sweeper_classes/boris_2nd_order.py @@ -2461,10 +2461,10 @@

Total - 27921 - 6199 - 5477 - 78% + 27986 + 6210 + 5479 + 78% @@ -2477,7 +2477,7 @@

coverage.py v7.6.4, - created at 2024-10-25 11:27 +0000 + created at 2024-11-06 12:12 +0000

diff --git a/coverage/z_020efe120a771d8a_hamiltonian_and_energy_output_py.html b/coverage/z_020efe120a771d8a_hamiltonian_and_energy_output_py.html index 5475c5c58..d0ed57110 100644 --- a/coverage/z_020efe120a771d8a_hamiltonian_and_energy_output_py.html +++ b/coverage/z_020efe120a771d8a_hamiltonian_and_energy_output_py.html @@ -65,7 +65,7 @@

» next       coverage.py v7.6.4, - created at 2024-10-25 11:27 +0000 + created at 2024-11-06 12:12 +0000

diff --git a/coverage/z_020efe120a771d8a_hamiltonian_output_py.html b/coverage/z_020efe120a771d8a_hamiltonian_output_py.html index da87b6e4c..48a77a08a 100644 --- a/coverage/z_020efe120a771d8a_hamiltonian_output_py.html +++ b/coverage/z_020efe120a771d8a_hamiltonian_output_py.html @@ -65,7 +65,7 @@

» next       coverage.py v7.6.4, - created at 2024-10-25 11:27 +0000 + created at 2024-11-06 12:12 +0000

diff --git a/coverage/z_020efe120a771d8a_harmonic_oscillator_py.html b/coverage/z_020efe120a771d8a_harmonic_oscillator_py.html index 001e07a5b..1c5820257 100644 --- a/coverage/z_020efe120a771d8a_harmonic_oscillator_py.html +++ b/coverage/z_020efe120a771d8a_harmonic_oscillator_py.html @@ -65,7 +65,7 @@

» next       coverage.py v7.6.4, - created at 2024-10-25 11:27 +0000 + created at 2024-11-06 12:12 +0000

diff --git a/coverage/z_020efe120a771d8a_simple_problems_py.html b/coverage/z_020efe120a771d8a_simple_problems_py.html index 531e39ec1..c9d749a90 100644 --- a/coverage/z_020efe120a771d8a_simple_problems_py.html +++ b/coverage/z_020efe120a771d8a_simple_problems_py.html @@ -65,7 +65,7 @@

» next       coverage.py v7.6.4, - created at 2024-10-25 11:27 +0000 + created at 2024-11-06 12:12 +0000