Exemplo n.º 1
0
  def sweep(self, b, t0, dt, qSDC, fSDC, feval, **kwargs):
    r"""Perform one SDC sweep with new initial conditions and add FAS
    corrections.

    :param b:    right hand side (numpy array of size ``(nnodes,nqvar)``)
    :param t0:   initial time
    :param dt:   time step
    :param qSDC: solution (numpy array of size ``(nnodes,nqvar)``)
    :param fSDC: function (numpy array of size ``(nnodes,nfvar)``)
    :param feval: implicit/explicit function evaluator (instance
            of :py:class:`pfasst.feval.FEval`)

    Note that *qSDC* and *fSDC* are over-written.

    The sweep performed uses forward/fackward Euler time-stepping:

    XXX

    .. math::

      \begin{multline}
        U^{k+1}_{m+1} = U^k_m + \Delta t_m
            \bigl[ f_I(t_{m+1}, U^{k+1}_{m+1}) +
                 f_E(t_{m}, U^{k+1}_{m}) \bigr] \\
        + \vec{S}^{m,m+1}_E \, f_E(\vec{t}, \vec{U}^{k})
        + \vec{S}^{m,m+1}_I \, f_I(\vec{t}, \vec{U}^{k}).
      \end{multline}

    """

    exp = self.smat_exp
    imp = self.smat_imp

    pieces = fSDC.shape[0]
    nnodes = fSDC.shape[1]
    shape  = fSDC.shape[2:]
    size   = feval.size

    fSDCf = fSDC.reshape((pieces, nnodes, size)) # flatten so we can use np.dot
    rhs   = dt * (np.dot(exp, fSDCf[0]) + np.dot(imp, fSDCf[1]))
    rhs   = rhs.reshape((nnodes-1,)+shape)       # unflatten

    # add b
    if b is not None:
      rhs += b[1:]

    # set initial condition and eval
    qSDC[0] = b[0]

    feval.f1_evaluate(qSDC[0], t0, fSDC[0,0], **kwargs)
    feval.f2_evaluate(qSDC[0], t0, fSDC[1,0], **kwargs)

    # sub time-stepping
    t = t0
    dtsdc = dt * self.dsdc

    for m in range(self.nnodes-1):
      t += dtsdc[m]

      y = qSDC[m] + dtsdc[m]*fSDC[0,m] + rhs[m]

      feval.f2_solve(y, qSDC[m+1], t, dtsdc[m], fSDC[1,m+1], **kwargs)
      feval.f1_evaluate(qSDC[m+1], t, fSDC[0,m+1], **kwargs)
Exemplo n.º 2
0
  def sweep(self, t0, dt, F, **kwargs):
    r"""Perform one SDC sweep.

    Note that *qSDC* and *fSDC* are over-written.

    The sweep performed uses forward/backward Euler time-stepping.
    """

    exp = self.smat_exp
    imp = self.smat_imp

    qSDC = F.qSDC
    fSDC = F.fSDC
    feval = F.feval
    
    pieces = fSDC.shape[0]
    nnodes = fSDC.shape[1]
    shape  = fSDC.shape[2:]
    size   = feval.size

    f1eval = hasattr(feval, 'f1_evaluate')
    f2eval = hasattr(feval, 'f2_evaluate')

    F.call_hooks('pre-sweep', **kwargs)

    # flatten so we can use np.dot
    fSDCf = fSDC.reshape((pieces, nnodes, size))

    # integrate f
    if f1eval and f2eval:
      rhs = dt * (np.dot(exp, fSDCf[0]) + np.dot(imp, fSDCf[1]))
    elif f1eval:
      rhs = dt * np.dot(exp, fSDCf[0])
    else:
      rhs = dt * np.dot(imp, fSDCf[0])

    rhs = rhs.reshape((nnodes-1,)+shape)

    # add tau
    if F.tau is not None:
      rhs += F.tau

    # set initial condition and eval
    qSDC[0] = F.q0
    self.evaluate(t0, qSDC, fSDC, 0, feval, **kwargs)

    if F.gSDC is not None:
      fSDC[0,0] += F.gSDC[0]

    # sub time-stepping
    t = t0
    dtsdc = dt * self.dsdc

    for m in range(self.nnodes-1):
      t += dtsdc[m]

      self.pf.state.node = m + 1
      self.level.call_hooks('pre-feval', **kwargs)

      if f1eval and f2eval:
        # imex

        q1 = qSDC[m] + dtsdc[m]*fSDC[0,m] + rhs[m]
        feval.f2_solve(q1, qSDC[m+1], t, dtsdc[m], fSDC[1,m+1], **kwargs)
        feval.f1_evaluate(qSDC[m+1], t, fSDC[0,m+1], **kwargs)

      elif f1eval:
        # explicit

        qSDC[m+1] = qSDC[m] + dtsdc[m]*fSDC[0,m] + rhs[m]
        feval.f1_evaluate(qSDC[m+1], t, fSDC[0,m+1], **kwargs)

      else:
        # implicit

        q1 = qSDC[m] + dtsdc[m]*fSDC[0,m] + rhs[m]
        feval.f2_solve(q1, qSDC[m+1], t, dtsdc[m], fSDC[0,m+1], **kwargs)

      self.level.call_hooks('post-feval', **kwargs)

      if F.gSDC is not None:
        fSDC[0,m+1] += F.gSDC[m+1]

    F.qend[...] = F.qSDC[-1]

    self.pf.state.node = -1

    F.call_hooks('post-sweep', **kwargs)