def circle_rand():
     tmp_me = newDistArray(self.fft, self.params.spectral)
     ndim = len(tmp_me.shape)
     L = int(self.params.L)
     # get random radii for circles/spheres
     np.random.seed(1)
     lbound = 3.0 * self.params.eps
     ubound = 0.5 - self.params.eps
     rand_radii = (ubound - lbound) * np.random.random_sample(
         size=tuple([L] * ndim)) + lbound
     # distribute circles/spheres
     tmp = newDistArray(self.fft, False)
     if ndim == 2:
         for i in range(0, L):
             for j in range(0, L):
                 # build radius
                 r2 = (self.X[0] + i - L + 0.5)**2 + (self.X[1] + j -
                                                      L + 0.5)**2
                 # add this blob, shifted by 1 to avoid issues with adding up negative contributions
                 tmp += np.tanh((rand_radii[i, j] - np.sqrt(r2)) /
                                (np.sqrt(2) * self.params.eps)) + 1
     # normalize to [0,1]
     tmp *= 0.5
     assert np.all(tmp <= 1.0)
     if self.params.spectral:
         tmp_me[:] = self.fft.forward(tmp)
     else:
         tmp_me[:] = tmp[:]
     return tmp_me
    def eval_f(self, u, t):
        """
        Routine to evaluate the RHS

        Args:
            u (dtype_u): current values
            t (float): current time

        Returns:
            dtype_f: the RHS
        """

        f = self.dtype_f(self.init)

        if self.params.spectral:

            f.impl[..., 0] = -self.K2 * u[..., 0]

            if self.params.eps > 0:
                tmp_u = newDistArray(self.fft, False)
                tmp_T = newDistArray(self.fft, False)
                tmp_u = self.fft.backward(u[..., 0], tmp_u)
                tmp_T = self.fft.backward(u[..., 1], tmp_T)
                tmpf = - 2.0 / self.params.eps ** 2 * tmp_u * (1.0 - tmp_u) * (1.0 - 2.0 * tmp_u) - \
                    6.0 * self.params.dw * (tmp_T - self.params.TM) / self.params.TM * tmp_u * (1.0 - tmp_u)
                f.expl[..., 0] = self.fft.forward(tmpf)

            f.impl[..., 1] = -self.params.D * self.K2 * u[..., 1]
            f.expl[..., 1] = -f.impl[..., 0] - f.expl[..., 0]

        else:

            u_hat = self.fft.forward(u[..., 0])
            lap_u_hat = -self.K2 * u_hat
            f.impl[..., 0] = self.fft.backward(lap_u_hat, f.impl[..., 0])

            if self.params.eps > 0:
                f.expl[..., 0] = -2.0 / self.params.eps**2 * u[..., 0] * (
                    1.0 - u[..., 0]) * (1.0 - 2.0 * u[..., 0])
                f.expl[..., 0] -= 6.0 * self.params.dw * (u[..., 1] - self.params.TM) / self.params.TM * u[..., 0] * \
                    (1.0 - u[..., 0])

            u_hat = self.fft.forward(u[..., 1])
            lap_u_hat = -self.params.D * self.K2 * u_hat
            f.impl[..., 1] = self.fft.backward(lap_u_hat, f.impl[..., 1])
            f.expl[..., 1] = -f.impl[..., 0] - f.expl[..., 0]

        return f
示例#3
0
    def post_step(self, step, level_number):
        """
        Overwrite standard post step hook

        Args:
            step (pySDC.Step.step): the current step
            level_number (int): the current level number
        """
        super(dump, self).post_step(step, level_number)

        # some abbreviations
        L = step.levels[0]

        # get real space values
        if L.prob.params.spectral:
            if hasattr(L.prob, 'ncomp'):
                tmp1 = newDistArray(L.prob.fft, False)
                tmp = np.zeros(tmp1.shape + (L.prob.ncomp,))
                for i in range(L.prob.ncomp):
                    tmp[..., i] = L.prob.fft.backward(L.uend[..., i])
            else:
                tmp = L.prob.fft.backward(L.uend)
        else:
            tmp = L.uend[:]

        # compute local offset for I/O
        nbytes_local = tmp.nbytes
        if self.comm is not None:
            nbytes_global = self.comm.allgather(nbytes_local)
        else:
            nbytes_global = [nbytes_local]
        local_offset = sum(nbytes_global[:self.rank])

        #  dump initial data
        fname = f"./data/{L.prob.params.name}_{self.time_step + step.status.slot:08d}"
        fh = MPI.File.Open(self.comm, fname + ".dat", self.amode)
        fh.Write_at_all(local_offset, tmp)
        fh.Close()

        sizes = list(L.prob.params.nvars)
        if hasattr(L.prob, 'ncomp'):
            sizes.append(L.prob.ncomp)

        # write json description
        if self.rank == 0:
            json_obj = dict()
            json_obj['type'] = 'dataset'
            json_obj['datatype'] = str(tmp.dtype)
            json_obj['endian'] = str(tmp.dtype.byteorder)
            json_obj['time'] = L.time + L.dt
            json_obj['space_comm_size'] = self.size
            json_obj['time_comm_size'] = step.status.time_size
            json_obj['shape'] = sizes
            json_obj['elementsize'] = tmp.dtype.itemsize

            with open(fname + '.json', 'w') as fp:
                json.dump(json_obj, fp)

        # update step count
        self.time_step += step.status.time_size
示例#4
0
def test_newDistArray():
    N = (8, 8, 8)
    pfft = PFFT(MPI.COMM_WORLD, N)
    for forward_output in (True, False):
        for view in (True, False):
            for rank in (0, 1, 2):
                a = newDistArray(pfft,
                                 forward_output=forward_output,
                                 rank=rank,
                                 view=view)
                if view is False:
                    assert isinstance(a, DistArray)
                    assert a.rank == rank
                    if rank == 0:
                        qfft = PFFT(MPI.COMM_WORLD, darray=a)
                    elif rank == 1:
                        qfft = PFFT(MPI.COMM_WORLD, darray=a[0])
                    else:
                        qfft = PFFT(MPI.COMM_WORLD, darray=a[0, 0])
                    qfft.destroy()

                else:
                    assert isinstance(a, np.ndarray)
                    assert a.base.rank == rank
    pfft.destroy()
示例#5
0
    def restrict(self, F):
        """
        Restriction implementation

        Args:
            F: the fine level data (easier to access than via the fine attribute)
        """
        if isinstance(F, parallel_mesh):
            if self.spectral:
                G = self.coarse_prob.dtype_u(self.coarse_prob.init)
                if hasattr(self.fine_prob, 'ncomp'):
                    for i in range(self.fine_prob.ncomp):
                        tmpF = newDistArray(self.fine_prob.fft, False)
                        tmpF = self.fine_prob.fft.backward(F[..., i], tmpF)
                        tmpG = tmpF[::int(self.ratio[0]), ::int(self.ratio[1])]
                        G[..., i] = self.coarse_prob.fft.forward(tmpG, G[..., i])
                else:
                    tmpF = self.fine_prob.fft.backward(F)
                    tmpG = tmpF[::int(self.ratio[0]), ::int(self.ratio[1])]
                    G[:] = self.coarse_prob.fft.forward(tmpG, G)
            else:
                G = self.coarse_prob.dtype_u(self.coarse_prob.init)
                G[:] = F[::int(self.ratio[0]), ::int(self.ratio[1])]
        else:
            raise TransferError('Unknown data type, got %s' % type(F))

        return G
示例#6
0
def test_2D(backend, forward_output):
    if backend == 'netcdf4':
        assert forward_output is False
    T = PFFT(comm, (N[0], N[1]))
    for i, domain in enumerate([
            None, ((0, np.pi), (0, 2 * np.pi)),
        (np.arange(N[0], dtype=float) * 1 * np.pi / N[0],
         np.arange(N[1], dtype=float) * 2 * np.pi / N[1])
    ]):
        for rank in range(3):
            filename = "".join(
                ('test2D_{}{}{}'.format(ex[i == 0], ex[forward_output],
                                        rank), ending[backend]))
            if backend == 'netcdf4':
                remove_if_exists(filename)
            u = newDistArray(T,
                             forward_output=forward_output,
                             val=1,
                             rank=rank)
            hfile = writer[backend](filename, domain=domain)
            assert hfile.backend() == backend
            hfile.write(0, {'u': [u]})
            hfile.write(1, {'u': [u]})
            u.write(hfile, 'u', 2)
            if rank > 0:
                hfile.write(0, {'u': [u]}, as_scalar=True)
                hfile.write(1, {'u': [u]}, as_scalar=True)
                u.write(hfile, 'u', 2, as_scalar=True)
            u.write('t' + filename, 'u', 0)
            u.write('t' + filename, 'u', 0, [slice(None), 3])

            if not forward_output and backend == 'hdf5' and comm.Get_rank(
            ) == 0:
                generate_xdmf(filename)
                generate_xdmf(filename, order='visit')

            u0 = newDistArray(T, forward_output=forward_output, rank=rank)
            read = reader[backend](filename)
            read.read(u0, 'u', step=0)
            u0.read(filename, 'u', 2)
            u0.read(read, 'u', 2)
            assert np.allclose(u0, u)
            if backend == 'netcdf4':  # Test opening file in mode 'a' when not existing
                remove_if_exists('nctesta.nc')
                _ = NCFile('nctesta.nc', domain=domain, mode='a')
    T.destroy()
示例#7
0
 def __init__(self,
              Nx,
              Ny,
              padx=1.5,
              pady=1.5,
              num_in=6,
              num_out=2,
              fmultin=mult_in,
              fmultout=mult_out62,
              comm=MPI.COMM_WORLD):
     self.comm = comm
     self.num_in = num_in
     self.num_out = num_out
     self.nar = max(num_in, num_out)
     self.ffti = PFFT(comm,
                      shape=(self.num_in, Nx, Ny),
                      axes=(1, 2),
                      grid=[1, -1, 1],
                      padding=[1, 1.5, 1.5],
                      collapse=False)
     self.ffto = PFFT(comm,
                      shape=(self.num_out, Nx, Ny),
                      axes=(1, 2),
                      grid=[1, -1, 1],
                      padding=[1, 1.5, 1.5],
                      collapse=False)
     self.datk = newDistArray(self.ffti, forward_output=True)
     self.dat = newDistArray(self.ffti, forward_output=False)
     lkx = np.r_[0:int(Nx / 2), -int(Nx / 2):0]
     lky = np.r_[0:int(Ny / 2 + 1)]
     self.kx = DistArray((Nx, int(Ny / 2 + 1)),
                         subcomm=(1, 0),
                         dtype=float,
                         alignment=0)
     self.ky = DistArray((Nx, int(Ny / 2 + 1)),
                         subcomm=(1, 0),
                         dtype=float,
                         alignment=0)
     self.kx[:], self.ky[:] = np.meshgrid(lkx[self.kx.local_slice()[0]],
                                          lky[self.ky.local_slice()[1]],
                                          indexing='ij')
     self.ksqr = self.kx**2 + self.ky**2
     self.fmultin = fmultin
     self.fmultout = fmultout
示例#8
0
    def u_exact(self, t):
        """
        Routine to compute the exact solution at time t

        Args:
            t (float): current time

        Returns:
            dtype_u: exact solution
        """

        assert t == 0, 'ERROR: u_exact only valid for t=0'
        me = self.dtype_u(self.init, val=0.0)
        if self.params.init_type == 'circle':
            r2 = (self.X[0] - 0.5)**2 + (self.X[1] - 0.5)**2
            if self.params.spectral:
                tmp = 0.5 * (1.0 + np.tanh((self.params.radius - np.sqrt(r2)) /
                                           (np.sqrt(2) * self.params.eps)))
                me[:] = self.fft.forward(tmp)
            else:
                me[:] = 0.5 * (1.0 + np.tanh(
                    (self.params.radius - np.sqrt(r2)) /
                    (np.sqrt(2) * self.params.eps)))
        elif self.params.init_type == 'circle_rand':
            ndim = len(me.shape)
            L = int(self.params.L)
            # get random radii for circles/spheres
            np.random.seed(1)
            lbound = 3.0 * self.params.eps
            ubound = 0.5 - self.params.eps
            rand_radii = (ubound - lbound) * np.random.random_sample(
                size=tuple([L] * ndim)) + lbound
            # distribute circles/spheres
            tmp = newDistArray(self.fft, False)
            if ndim == 2:
                for i in range(0, L):
                    for j in range(0, L):
                        # build radius
                        r2 = (self.X[0] + i - L + 0.5)**2 + (self.X[1] + j -
                                                             L + 0.5)**2
                        # add this blob, shifted by 1 to avoid issues with adding up negative contributions
                        tmp += np.tanh((rand_radii[i, j] - np.sqrt(r2)) /
                                       (np.sqrt(2) * self.params.eps)) + 1
            # normalize to [0,1]
            tmp *= 0.5
            assert np.all(tmp <= 1.0)
            if self.params.spectral:
                me[:] = self.fft.forward(tmp)
            else:
                me[:] = tmp[:]
        else:
            raise NotImplementedError(
                'type of initial value not implemented, got %s' %
                self.params.init_type)

        return me
示例#9
0
def test_4D(backend, forward_output):
    if backend == 'netcdf4':
        assert forward_output is False
    T = PFFT(comm, (N[0], N[1], N[2], N[3]))
    d0 = ((0, np.pi), (0, 2 * np.pi), (0, 3 * np.pi), (0, 4 * np.pi))
    d1 = (np.arange(N[0], dtype=float) * 1 * np.pi / N[0],
          np.arange(N[1], dtype=float) * 2 * np.pi / N[1],
          np.arange(N[2], dtype=float) * 3 * np.pi / N[2],
          np.arange(N[3], dtype=float) * 4 * np.pi / N[3])
    for i, domain in enumerate([None, d0, d1]):
        for rank in range(3):
            filename = "".join(
                ('h5test4_{}{}{}'.format(ex[i == 0], ex[forward_output],
                                         rank), ending[backend]))
            if backend == 'netcdf4':
                remove_if_exists('uv' + filename)
            u = newDistArray(T, forward_output=forward_output, rank=rank)
            v = newDistArray(T, forward_output=forward_output, rank=rank)
            h0file = writer[backend]('uv' + filename, domain=domain)
            u[:] = np.random.random(u.shape)
            v[:] = 2
            for k in range(3):
                h0file.write(
                    k, {
                        'u':
                        [u, (u, [slice(None), 4,
                                 slice(None),
                                 slice(None)])],
                        'v': [v,
                              (v, [slice(None), slice(None), 5, 6])]
                    })

            if not forward_output and backend == 'hdf5' and comm.Get_rank(
            ) == 0:
                generate_xdmf('uv' + filename)

            u0 = newDistArray(T, forward_output=forward_output, rank=rank)
            read = reader[backend]('uv' + filename)
            read.read(u0, 'u', step=0)
            assert np.allclose(u0, u)
            read.read(u0, 'v', step=0)
            assert np.allclose(u0, v)
    T.destroy()
 def sine():
     tmp_me = newDistArray(self.fft, self.params.spectral)
     if self.params.spectral:
         tmp = np.sin(2 * np.pi * self.X[0]) * np.sin(
             2 * np.pi * self.X[1])
         tmp_me[:] = self.fft.forward(tmp)
     else:
         tmp_me[:] = np.sin(2 * np.pi * self.X[0]) * np.sin(
             2 * np.pi * self.X[1])
     return tmp_me
示例#11
0
    def eval_f(self, u, t):
        """
        Routine to evaluate the RHS

        Args:
            u (dtype_u): current values
            t (float): current time

        Returns:
            dtype_f: the RHS
        """

        f = self.dtype_f(self.init)

        if self.params.spectral:

            f.comp1[..., 0] = self.Ku * u[..., 0]
            f.comp1[..., 1] = self.Kv * u[..., 1]
            tmpu = newDistArray(self.fft, False)
            tmpv = newDistArray(self.fft, False)
            tmpu[:] = self.fft.backward(u[..., 0], tmpu)
            tmpv[:] = self.fft.backward(u[..., 1], tmpv)
            tmpfu = -tmpu * tmpv**2 + self.params.A * (1 - tmpu)
            tmpfv = tmpu * tmpv**2 - self.params.B * tmpv
            f.comp2[..., 0] = self.fft.forward(tmpfu)
            f.comp2[..., 1] = self.fft.forward(tmpfv)

        else:

            u_hat = self.fft.forward(u[..., 0])
            lap_u_hat = self.Ku * u_hat
            f.comp1[..., 0] = self.fft.backward(lap_u_hat, f.comp1[..., 0])
            u_hat = self.fft.forward(u[..., 1])
            lap_u_hat = self.Kv * u_hat
            f.comp1[..., 1] = self.fft.backward(lap_u_hat, f.comp1[..., 1])
            f.comp2[...,
                    0] = -u[..., 0] * u[...,
                                        1]**2 + self.params.A * (1 - u[..., 0])
            f.comp2[...,
                    1] = u[..., 0] * u[..., 1]**2 - self.params.B * u[..., 1]

        return f
 def circle():
     tmp_me = newDistArray(self.fft, self.params.spectral)
     r2 = (self.X[0] - 0.5)**2 + (self.X[1] - 0.5)**2
     if self.params.spectral:
         tmp = 0.5 * (1.0 + np.tanh((self.params.radius - np.sqrt(r2)) /
                                    (np.sqrt(2) * self.params.eps)))
         tmp_me[:] = self.fft.forward(tmp)
     else:
         tmp_me[:] = 0.5 * (1.0 + np.tanh(
             (self.params.radius - np.sqrt(r2)) /
             (np.sqrt(2) * self.params.eps)))
     return tmp_me
示例#13
0
dt = 0.01

# Set global size of the computational box
M = 6
N = [2**M, 2**M, 2**M]
L = np.array(
    [2 * np.pi, 4 * np.pi, 4 * np.pi], dtype=float
)  # Needs to be (2*int)*pi in all directions (periodic) because of initialization

# Create instance of PFFT to perform parallel FFT + an instance to do FFT with padding (3/2-rule)
FFT = PFFT(MPI.COMM_WORLD, N, collapse=False)
#FFT_pad = PFFT(MPI.COMM_WORLD, N, padding=[1.5, 1.5, 1.5])
FFT_pad = FFT

# Declare variables needed to solve Navier-Stokes
U = newDistArray(FFT, False, rank=1, view=True)  # Velocity
U_hat = newDistArray(FFT, rank=1, view=True)  # Velocity transformed
P = newDistArray(FFT, False, view=True)  # Pressure (scalar)
P_hat = newDistArray(FFT, view=True)  # Pressure transformed
U_hat0 = newDistArray(FFT, rank=1, view=True)  # Runge-Kutta work array
U_hat1 = newDistArray(FFT, rank=1, view=True)  # Runge-Kutta work array
a = [1. / 6., 1. / 3., 1. / 3., 1. / 6.]  # Runge-Kutta parameter
b = [0.5, 0.5, 1.]  # Runge-Kutta parameter
dU = newDistArray(FFT, rank=1, view=True)  # Right hand side of ODEs
curl = newDistArray(FFT, False, rank=1, view=True)
U_pad = newDistArray(FFT_pad, False, rank=1, view=True)
curl_pad = newDistArray(FFT_pad, False, rank=1, view=True)


def get_local_mesh(FFT, L):
    """Returns local mesh."""
示例#14
0
fft = PFFT(MPI.COMM_WORLD,
           N,
           axes=None,
           collapse=True,
           grid=(-1, ),
           transforms=transforms)
pfft = PFFT(MPI.COMM_WORLD,
            N,
            axes=((0, ), (1, 2)),
            grid=(-1, ),
            padding=[1.5, 1.0, 1.0],
            transforms=transforms)

assert fft.axes == pfft.axes

u = newDistArray(fft, forward_output=False)
u[:] = np.random.random(u.shape).astype(u.dtype)

u_hat = newDistArray(fft, forward_output=True)
u_hat = fft.forward(u, u_hat)
uj = np.zeros_like(u)
uj = fft.backward(u_hat, uj)
assert np.allclose(uj, u)

u_padded = newDistArray(pfft, forward_output=False)
uc = u_hat.copy()
u_padded = pfft.backward(u_hat, u_padded)
u_hat = pfft.forward(u_padded, u_hat)
assert np.allclose(u_hat, uc)

#cfft = PFFT(MPI.COMM_WORLD, N, dtype=complex, padding=[1.5, 1.5, 1.5])
示例#15
0
import numpy as np
import matplotlib.pylab as plt

howmany = 6
Nx, Ny = 128, 128
padx, pady = 3 / 2, 3 / 2
Npx, Npy = int(128 * padx), int(128 * pady)
comm = MPI.COMM_WORLD

pf = PFFT(comm,
          shape=(howmany, Nx, Ny),
          axes=(1, 2),
          grid=[1, -1, 1],
          padding=[1, 1.5, 1.5],
          collapse=False)
u = newDistArray(pf, forward_output=False)
uk = newDistArray(pf, forward_output=True)

n, x, y = np.meshgrid(np.arange(0, howmany),
                      np.linspace(-1, 1, Npx),
                      np.linspace(-1, 1, Npy),
                      indexing='ij')
nl, xl, yl = n[u.local_slice()], x[u.local_slice()], y[u.local_slice()]
u[:] = np.sin(4 * np.pi * (xl + 2 * yl)) * np.exp(-xl**2 / 2 / 0.04 -
                                                  yl**2 / 2 / 0.08) * (nl - 3)
u0 = u.copy()

pf.forward(u, uk)
pf.backward(uk, u)

plt.figure()
示例#16
0
    def __init__(self,
                 problem_params,
                 dtype_u=parallel_mesh,
                 dtype_f=parallel_imex_mesh):
        """
        Initialization routine

        Args:
            problem_params (dict): custom parameters for the example
            dtype_u: fft data type (will be passed to parent class)
            dtype_f: fft data type wuth implicit and explicit parts (will be passed to parent class)
        """

        if 'L' not in problem_params:
            problem_params['L'] = 1.0
        if 'init_type' not in problem_params:
            problem_params['init_type'] = 'circle'
        if 'comm' not in problem_params:
            problem_params['comm'] = None
        if 'dw' not in problem_params:
            problem_params['dw'] = 0.0

        # these parameters will be used later, so assert their existence
        essential_keys = ['nvars', 'eps', 'L', 'radius', 'dw', 'spectral']
        for key in essential_keys:
            if key not in problem_params:
                msg = 'need %s to instantiate problem, only got %s' % (
                    key, str(problem_params.keys()))
                raise ParameterError(msg)

        if not (isinstance(problem_params['nvars'], tuple)
                and len(problem_params['nvars']) > 1):
            raise ProblemError('Need at least two dimensions')

        # Creating FFT structure
        ndim = len(problem_params['nvars'])
        axes = tuple(range(ndim))
        self.fft = PFFT(problem_params['comm'],
                        list(problem_params['nvars']),
                        axes=axes,
                        dtype=np.float,
                        collapse=True)

        # get test data to figure out type and dimensions
        tmp_u = newDistArray(self.fft, problem_params['spectral'])

        # invoke super init, passing the communicator and the local dimensions as init
        super(allencahn_imex,
              self).__init__(init=(tmp_u.shape, problem_params['comm'],
                                   tmp_u.dtype),
                             dtype_u=dtype_u,
                             dtype_f=dtype_f,
                             params=problem_params)

        L = np.array([self.params.L] * ndim, dtype=float)

        # get local mesh
        X = np.ogrid[self.fft.local_slice(False)]
        N = self.fft.global_shape()
        for i in range(len(N)):
            X[i] = (X[i] * L[i] / N[i])
        self.X = [np.broadcast_to(x, self.fft.shape(False)) for x in X]

        # get local wavenumbers and Laplace operator
        s = self.fft.local_slice()
        N = self.fft.global_shape()
        k = [np.fft.fftfreq(n, 1. / n).astype(int) for n in N[:-1]]
        k.append(np.fft.rfftfreq(N[-1], 1. / N[-1]).astype(int))
        K = [ki[si] for ki, si in zip(k, s)]
        Ks = np.meshgrid(*K, indexing='ij', sparse=True)
        Lp = 2 * np.pi / L
        for i in range(ndim):
            Ks[i] = (Ks[i] * Lp[i]).astype(float)
        K = [np.broadcast_to(k, self.fft.shape(True)) for k in Ks]
        K = np.array(K).astype(float)
        self.K2 = np.sum(K * K, 0, dtype=float)

        # Need this for diagnostics
        self.dx = self.params.L / problem_params['nvars'][0]
        self.dy = self.params.L / problem_params['nvars'][1]
示例#17
0
    def eval_f(self, u, t):
        """
        Routine to evaluate the RHS

        Args:
            u (dtype_u): current values
            t (float): current time

        Returns:
            dtype_f: the RHS
        """

        f = self.dtype_f(self.init)

        if self.params.spectral:

            f.impl = -self.K2 * u

            tmp = newDistArray(self.fft, False)
            tmp[:] = self.fft.backward(u, tmp)

            if self.params.eps > 0:
                tmpf = -2.0 / self.params.eps**2 * tmp * (1.0 - tmp) * (
                    1.0 - 2.0 * tmp)
            else:
                tmpf = self.dtype_f(self.init, val=0.0)

            # build sum over RHS without driving force
            Rt_local = float(np.sum(self.fft.backward(f.impl) + tmpf))
            if self.params.comm is not None:
                Rt_global = self.params.comm.allreduce(sendobj=Rt_local,
                                                       op=MPI.SUM)
            else:
                Rt_global = Rt_local

            # build sum over driving force term
            Ht_local = float(np.sum(6.0 * tmp * (1.0 - tmp)))
            if self.params.comm is not None:
                Ht_global = self.params.comm.allreduce(sendobj=Ht_local,
                                                       op=MPI.SUM)
            else:
                Ht_global = Rt_local

            # add/substract time-dependent driving force
            if Ht_global != 0.0:
                dw = Rt_global / Ht_global
            else:
                dw = 0.0

            tmpf -= 6.0 * dw * tmp * (1.0 - tmp)
            f.expl[:] = self.fft.forward(tmpf)

        else:

            u_hat = self.fft.forward(u)
            lap_u_hat = -self.K2 * u_hat
            f.impl[:] = self.fft.backward(lap_u_hat, f.impl)

            if self.params.eps > 0:
                f.expl = -2.0 / self.params.eps**2 * u * (1.0 - u) * (1.0 -
                                                                      2.0 * u)

            # build sum over RHS without driving force
            Rt_local = float(np.sum(f.impl + f.expl))
            if self.params.comm is not None:
                Rt_global = self.params.comm.allreduce(sendobj=Rt_local,
                                                       op=MPI.SUM)
            else:
                Rt_global = Rt_local

            # build sum over driving force term
            Ht_local = float(np.sum(6.0 * u * (1.0 - u)))
            if self.params.comm is not None:
                Ht_global = self.params.comm.allreduce(sendobj=Ht_local,
                                                       op=MPI.SUM)
            else:
                Ht_global = Rt_local

            # add/substract time-dependent driving force
            if Ht_global != 0.0:
                dw = Rt_global / Ht_global
            else:
                dw = 0.0

            f.expl -= 6.0 * dw * u * (1.0 - u)

        return f
示例#18
0
ndim = 2
axes = tuple(range(ndim))
N = np.array([nvars] * ndim, dtype=int)
print(N, axes)
fft = PFFT(subcomm, N, axes=axes, dtype=np.float, slab=True)
# L = np.array([2*np.pi] * ndim, dtype=float)
L = np.array([1] * ndim, dtype=float)

print(fft.subcomm)

X = get_local_mesh(fft, L)
K = get_local_wavenumbermesh(fft, L)
K = np.array(K).astype(float)
K2 = np.sum(K * K, 0, dtype=float)

u = newDistArray(fft, False)
print(type(u))
print(u.subcomm)
uex = newDistArray(fft, False)

u[:] = np.sin(2 * np.pi * X[0]) * np.sin(2 * np.pi * X[1])
print(u.shape, X[0].shape)
# exit()
uex[:] = -2.0 * (2.0 * np.pi)**2 * np.sin(2 * np.pi * X[0]) * np.sin(
    2 * np.pi * X[1])
u_hat = fft.forward(u)

lap_u_hat = -K2 * u_hat

lap_u = np.zeros_like(u)
lap_u = fft.backward(lap_u_hat, lap_u)
示例#19
0
    def solve_system_2(self, rhs, factor, u0, t):
        """
        Newton-Solver for the second component

        Args:
            rhs (dtype_f): right-hand side for the linear system
            factor (float) : abbrev. for the node-to-node stepsize (or any other factor required)
            u0 (dtype_u): initial guess for the iterative solver (not used here so far)
            t (float): current time (e.g. for time-dependent BCs)

        Returns:
            dtype_u: solution as mesh
        """
        u = self.dtype_u(u0)

        if self.params.spectral:
            tmpu = newDistArray(self.fft, False)
            tmpv = newDistArray(self.fft, False)
            tmpu[:] = self.fft.backward(u[..., 0], tmpu)
            tmpv[:] = self.fft.backward(u[..., 1], tmpv)
            tmprhsu = newDistArray(self.fft, False)
            tmprhsv = newDistArray(self.fft, False)
            tmprhsu[:] = self.fft.backward(rhs[..., 0], tmprhsu)
            tmprhsv[:] = self.fft.backward(rhs[..., 1], tmprhsv)

        else:
            tmpu = u[..., 0]
            tmpv = u[..., 1]
            tmprhsu = rhs[..., 0]
            tmprhsv = rhs[..., 1]

        # start newton iteration
        n = 0
        res = 99
        while n < self.params.newton_maxiter:
            # print(n, res)
            # form the function g with g(u) = 0
            tmpgu = tmpu - tmprhsu - factor * (-tmpu * tmpv**2 + self.params.A)
            tmpgv = tmpv - tmprhsv - factor * (tmpu * tmpv**2)

            # if g is close to 0, then we are done
            res = max(np.linalg.norm(tmpgu, np.inf),
                      np.linalg.norm(tmpgv, np.inf))
            if res < self.params.newton_tol:
                break

            # assemble dg
            dg00 = 1 - factor * (-tmpv**2)
            dg01 = -factor * (-2 * tmpu * tmpv)
            dg10 = -factor * (tmpv**2)
            dg11 = 1 - factor * (2 * tmpu * tmpv)

            # interleave and unravel to put into sparse matrix
            dg00I = np.ravel(np.kron(dg00, np.array([1, 0])))
            dg01I = np.ravel(np.kron(dg01, np.array([1, 0])))
            dg10I = np.ravel(np.kron(dg10, np.array([1, 0])))
            dg11I = np.ravel(np.kron(dg11, np.array([0, 1])))

            # put into sparse matrix
            dg = sp.diags(dg00I, offsets=0) + sp.diags(dg11I, offsets=0)
            dg += sp.diags(dg01I, offsets=1, shape=dg.shape) + sp.diags(
                dg10I, offsets=-1, shape=dg.shape)

            # interleave g terms to apply inverse to it
            g = np.kron(tmpgu.flatten(), np.array([1, 0])) + np.kron(
                tmpgv.flatten(), np.array([0, 1]))
            # invert dg matrix
            b = sp.linalg.spsolve(dg, g)
            # update real-space vectors
            tmpu[:] -= b[::2].reshape(self.params.nvars)
            tmpv[:] -= b[1::2].reshape(self.params.nvars)

            # increase iteration count
            n += 1

        if np.isnan(res) and self.params.stop_at_nan:
            raise ProblemError(
                'Newton got nan after %i iterations, aborting...' % n)
        elif np.isnan(res):
            self.logger.warning('Newton got nan after %i iterations...' % n)

        if n == self.params.newton_maxiter:
            self.logger.warning(
                'Newton did not converge after %i iterations, error is %s' %
                (n, res))

        # self.newton_ncalls += 1
        # self.newton_itercount += n
        me = self.dtype_u(self.init)
        if self.params.spectral:
            me[..., 0] = self.fft.forward(tmpu)
            me[..., 1] = self.fft.forward(tmpv)
        else:
            me[..., 0] = tmpu
            me[..., 1] = tmpv
        return me
def run_simulation(name='',
                   spectral=None,
                   nprocs_time=None,
                   nprocs_space=None,
                   dt=None,
                   cwd='.'):
    """
    A test program to do PFASST runs for the AC equation with temperature-based forcing

    (slightly inefficient, but will run for a few seconds only)

    Args:
        name (str): name of the run, will be used to distinguish different setups
        spectral (bool): run in real or spectral space
        nprocs_time (int): number of processors in time
        nprocs_space (int): number of processors in space (None if serial)
        dt (float): time-step size
        cwd (str): current working directory
    """

    # set MPI communicator
    comm = MPI.COMM_WORLD

    world_rank = comm.Get_rank()
    world_size = comm.Get_size()

    # split world communicator to create space-communicators
    if nprocs_space is not None:
        color = int(world_rank / nprocs_space)
    else:
        color = int(world_rank / 1)
    space_comm = comm.Split(color=color)
    space_rank = space_comm.Get_rank()
    space_size = space_comm.Get_size()

    assert world_size == space_size, 'This script cannot run parallel-in-time with MPI, only spatial parallelism'

    # initialize level parameters
    level_params = dict()
    level_params['restol'] = 1E-12
    level_params['dt'] = dt
    level_params['nsweeps'] = [1]

    # initialize sweeper parameters
    sweeper_params = dict()
    sweeper_params['collocation_class'] = CollGaussRadau_Right
    sweeper_params['num_nodes'] = [3]
    sweeper_params['QI'] = [
        'LU'
    ]  # For the IMEX sweeper, the LU-trick can be activated for the implicit part
    sweeper_params['initial_guess'] = 'spread'

    # initialize problem parameters
    problem_params = dict()
    problem_params['L'] = 1.0
    problem_params['nvars'] = [(128, 128), (32, 32)]
    problem_params['eps'] = [0.04]
    problem_params['radius'] = 0.25
    problem_params['TM'] = 1.0
    problem_params['D'] = 0.1
    problem_params['dw'] = [21.0]
    problem_params['comm'] = space_comm
    problem_params['name'] = name
    problem_params['init_type'] = 'circle'
    problem_params['spectral'] = spectral

    # initialize step parameters
    step_params = dict()
    step_params['maxiter'] = 50

    # initialize controller parameters
    controller_params = dict()
    controller_params[
        'logger_level'] = 30 if space_rank == 0 else 99  # set level depending on rank
    controller_params['predict_type'] = 'pfasst_burnin'

    # fill description dictionary for easy step instantiation
    description = dict()
    description['problem_params'] = problem_params  # pass problem parameters
    description['sweeper_class'] = imex_1st_order
    description['sweeper_params'] = sweeper_params  # pass sweeper parameters
    description['level_params'] = level_params  # pass level parameters
    description['step_params'] = step_params  # pass step parameters
    description['space_transfer_class'] = fft_to_fft
    description['problem_class'] = allencahn_temp_imex

    # set time parameters
    t0 = 0.0
    Tend = 1 * 0.001

    if space_rank == 0:
        out = f'---------> Running {name} with spectral={spectral} and {space_size} process(es) in space...'
        print(out)

    # instantiate controller
    controller = controller_nonMPI(num_procs=nprocs_time,
                                   controller_params=controller_params,
                                   description=description)

    # get initial values on finest level
    P = controller.MS[0].levels[0].prob
    uinit = P.u_exact(t0)

    # call main function to get things done...
    uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend)

    if space_rank == 0:

        # convert filtered statistics of iterations count, sorted by time
        iter_counts = sort_stats(filter_stats(stats, type='niter'),
                                 sortby='time')
        niters = np.mean(np.array([item[1] for item in iter_counts]))
        out = f'Mean number of iterations: {niters:.4f}'
        print(out)

        # get setup time
        timing = sort_stats(filter_stats(stats, type='timing_setup'),
                            sortby='time')
        out = f'Setup time: {timing[0][1]:.4f} sec.'
        print(out)

        # get running time
        timing = sort_stats(filter_stats(stats, type='timing_run'),
                            sortby='time')
        out = f'Time to solution: {timing[0][1]:.4f} sec.'
        print(out)

        refname = f'{cwd}/data/AC-reference-tempforce_00001000'
        with open(f'{refname}.json', 'r') as fp:
            obj = json.load(fp)

        array = np.fromfile(f'{refname}.dat', dtype=obj['datatype'])
        array = array.reshape(obj['shape'], order='C')

        if spectral:
            ureal = newDistArray(P.fft, False)
            ureal = P.fft.backward(uend[..., 0], ureal)
            Treal = newDistArray(P.fft, False)
            Treal = P.fft.backward(uend[..., 1], Treal)
            err = max(np.amax(abs(ureal - array[..., 0])),
                      np.amax(abs(Treal - array[..., 1])))
        else:
            err = abs(array - uend)

        out = f'...Done <---------\n'
        print(out)

        return err
示例#21
0
def test_3D(backend, forward_output):
    if backend == 'netcdf4':
        assert forward_output is False
    T = PFFT(comm, (N[0], N[1], N[2]))
    d0 = ((0, np.pi), (0, 2 * np.pi), (0, 3 * np.pi))
    d1 = (np.arange(N[0], dtype=float) * 1 * np.pi / N[0],
          np.arange(N[1], dtype=float) * 2 * np.pi / N[1],
          np.arange(N[2], dtype=float) * 3 * np.pi / N[2])
    for i, domain in enumerate([None, d0, d1]):
        for rank in range(3):
            filename = ''.join(
                ('test_{}{}{}'.format(ex[i == 0], ex[forward_output],
                                      rank), ending[backend]))
            if backend == 'netcdf4':
                remove_if_exists('uv' + filename)
                remove_if_exists('v' + filename)

            u = newDistArray(T, forward_output=forward_output, rank=rank)
            v = newDistArray(T, forward_output=forward_output, rank=rank)
            h0file = writer[backend]('uv' + filename, domain=domain)
            h1file = writer[backend]('v' + filename, domain=domain)
            u[:] = np.random.random(u.shape)
            v[:] = 2
            for k in range(3):
                h0file.write(
                    k, {
                        'u': [
                            u, (u, [slice(None), slice(None), 4]),
                            (u, [5, 5, slice(None)])
                        ],
                        'v': [v,
                              (v, [slice(None), 6, slice(None)])]
                    })
                h1file.write(
                    k, {
                        'v': [
                            v,
                            (v, [slice(None), 6, slice(None)]),
                            (v, [6, 6, slice(None)])
                        ]
                    })
            # One more time with same k
            h0file.write(
                k, {
                    'u': [
                        u, (u, [slice(None), slice(None), 4]),
                        (u, [5, 5, slice(None)])
                    ],
                    'v': [v, (v, [slice(None), 6, slice(None)])]
                })
            h1file.write(
                k, {
                    'v': [
                        v, (v, [slice(None), 6, slice(None)]),
                        (v, [6, 6, slice(None)])
                    ]
                })

            if rank > 0:
                for k in range(3):
                    u.write('uv' + filename, 'u', k, as_scalar=True)
                    u.write('uv' + filename,
                            'u',
                            k, [slice(None), slice(None), 4],
                            as_scalar=True)
                    u.write('uv' + filename,
                            'u',
                            k, [5, 5, slice(None)],
                            as_scalar=True)
                    v.write('uv' + filename, 'v', k, as_scalar=True)
                    v.write('uv' + filename,
                            'v',
                            k, [slice(None), 6, slice(None)],
                            as_scalar=True)

            if not forward_output and backend == 'hdf5' and comm.Get_rank(
            ) == 0:
                generate_xdmf('uv' + filename)
                generate_xdmf('v' + filename, periodic=False)
                generate_xdmf('v' + filename, periodic=(True, True, True))
                generate_xdmf('v' + filename, order='visit')

            u0 = newDistArray(T, forward_output=forward_output, rank=rank)
            read = reader[backend]('uv' + filename)
            read.read(u0, 'u', step=0)
            assert np.allclose(u0, u)
            read.read(u0, 'v', step=0)
            assert np.allclose(u0, v)
    T.destroy()