Source code for WaveBlocksND.PerturbedSplittingParameters

"""The WaveBlocks Project

This file contains data to build several closely
related splitting methods for perturbed operators.

@author: V. Gradinaru, R. Bourquin
@copyright: Copyright (C) 2014 R. Bourquin
@license: Modified BSD License
"""

from numpy import zeros, floating

__all__ = ["PerturbedSplittingParameters"]


[docs]class PerturbedSplittingParameters(object):
[docs] def build(self, method): r""" :param method: A string specifying the method for time integration. :return: Two arrays :math:`a` and :math:`b`. ====== ====== ========= ========= Method Order Authors Reference ====== ====== ========= ========= L42 (4,2) McLachlan [1]_ page 6 L62 (6,2) McLachlan [1]_ page 6 L82 (8,2) McLachlan [1]_ page 6 L102 (10,2) McLachlan [1]_ page 6 L84 (8,4) McLachlan [1]_ page 8 ====== ====== ========= ========= .. [1] R.I. McLachlan, "Composition methods in the presence of small parameters", BIT Numerical Mathematics, Volume 35, Issue 2, (1995) 258-268. There is also a 2003 version which was used for the implementation. """ if method == "L42": # Pattern ABA and m = s = 2 m = 2 a = zeros(m + 1) b = zeros(m) # a[0] = 0.21132486540518713 a[1] = 0.57735026918962584 a[2] = 0.21132486540518713 # b[0] = 0.5 b[1] = 0.5 elif method == "L62": # Pattern ABA and m = s = 3 m = 3 a = zeros(m + 1) b = zeros(m) # a[0] = 0.1127016653792583 a[1] = 0.3872983346207417 a[2] = 0.3872983346207417 a[3] = 0.1127016653792583 # b[0] = 0.2777777777777778 b[1] = 0.4444444444444444 b[2] = 0.2777777777777778 elif method == "L82": # Pattern ABA and m = s = 4 m = 4 a = zeros(m + 1) b = zeros(m) # a[0] = 0.069431844202973714 a[1] = 0.26057763400459816 a[2] = 0.33998104358485626 a[3] = 0.26057763400459816 a[4] = 0.069431844202973714 # b[0] = 0.17392742256872692 b[1] = 0.3260725774312731 b[2] = 0.3260725774312731 b[3] = 0.17392742256872692 elif method == "L102": # Pattern ABA and m = s = 5 m = 5 a = zeros(m + 1) b = zeros(m) # a[0] = 0.046910077030668018 a[1] = 0.18385526791649043 a[2] = 0.26923465505284155 a[3] = 0.26923465505284155 a[4] = 0.18385526791649043 a[5] = 0.046910077030668018 # b[0] = 0.11846344252809454 b[1] = 0.23931433524968324 b[2] = 0.28444444444444444 b[3] = 0.23931433524968324 b[4] = 0.11846344252809454 elif method == "L84": # Pattern ABA and m = 5 m = 5 a = zeros(m + 1) b = zeros(m) # a[0] = 0.07534696026989288842 a[1] = 0.51791685468825678230 a[2] = -0.09326381495814967072 a[3] = -0.09326381495814967072 a[4] = 0.51791685468825678230 a[5] = 0.07534696026989288842 # b[0] = 0.19022593937367661925 b[1] = 0.84652407044352625706 b[2] = -1.07350001963440575260 b[3] = 0.84652407044352625706 b[4] = 0.19022593937367661925 else: raise NotImplementedError("Unknown method: " + method) return a, b
[docs] def intsplit(self, psia, psib, a, b, tspan, N, argsa=[], argsb=[]): r""" Compute a single, full propagation step by operator splitting. :param psia: First evolution operator :math:`\Psi_a` :param psib: Second evolution operator :math:`\Psi_b` :param a: Parameters for evolution with :math:`\Psi_a` :param b: Parameters for evolution with :math:`\Psi_b` :param tspan: Timespan :math:`t` of a single, full splitting step :param N: Number of substeps to perform :param argsa: Additional optional arguments of :math:`\Psi_a` :param argsb: Additional optional arguments of :math:`\Psi_b` .. note:: The values for ``argsa`` and ``argsb`` have to be of type ``list`` even in case of single items. """ psi = (psia, psib) args = (argsa, argsb) h = (tspan[1] - tspan[0]) / float(N) sa = a.shape[0] sb = b.shape[0] c = zeros(sa + sb, dtype=floating) c[::2] = a c[1::2] = b for k in range(N): for j in range(sa + sb): psi[j % 2](c[j] * h, *args[j % 2])