Beispiel #1
0
def rhs_to_scipy_ode(rhs, t, x_vect, u_vect, constants, *args,
                     **lambdify_kwargs):
    """Convert rhs to lambda function and jacobian comaptible with scipy.

    Given a state space description of a dynamic system, create
    a lambda function with a signature compatible with
    scipy.ode.integrate: f(t, x, u, *args).

    Parameters
    ----------
    rhs : sympy.Matrix
        Column vector of expressions for
        the derivative of x (continuous),
        or for the change in x (discrete).
    t : sympy.Symbol
        The independent time-like variable.
    x_vect : sympy.Matrix
        Column vector of symbols in the x (state) vector.
    u_vect : sympy.Matrix
        Column vector of symbols in the u (input) vector.
        Most controllers pass a vector of inputs and this
        supports this structure.
    constants: dict
        Dictionary of constants to substitute into rhs.
    *args: dict
        Additioinal symbols in f_vect that are not states, inputs
        or constants.
    **lambdify_kwargs:
        Additional arugments to pass to lambdify.
        @see sympy.utilities.lambdify.lambdify

    Returns
    -------
    f : function
        A lambda function that compute the right hand side
        of the ode: f(t, x, u, *f_args).
    jac : function
        A lambda function that computes the jacobian
        of the right hand side with respect to the state x:
        jac(t, x, u, *jac_args).
    """
    if constants is not None:
        rhs = rhs.subs(constants)
    x = sympy.DeferredVector('x')
    u = sympy.DeferredVector('u')
    ss_subs = {x_vect[i]: x[i] for i in range(len(x_vect))}
    ss_subs.update({u_vect[i]: u[i] for i in range(len(u_vect))})
    if 'default_array' not in lambdify_kwargs.keys():
        lambdify_kwargs['default_array'] = True
    f = sympy.lambdify((t, x, u) + args, rhs.subs(ss_subs), **lambdify_kwargs)
    jac_vect = rhs.jacobian(x_vect)
    jac = sympy.lambdify((t, x, u) + args, jac_vect.subs(ss_subs),
                         **lambdify_kwargs)
    return (f, jac)
Beispiel #2
0
def _integrate_exact(f, tetrahedron):
    #
    # Note that
    #
    #     \int_T f(x) dx = \int_T0 |J(xi)| f(P(xi)) dxi
    #
    # with
    #
    #     P(xi) = x0 * (1-xi[0]-xi[1]) + x1 * xi[0] + x2 * xi[1].
    #
    # and T0 being the reference tetrahedron [(0.0, 0.0), (1.0, 0.0), (0.0,
    # 1.0)].
    # The determinant of the transformation matrix J equals twice the volume of
    # the tetrahedron. (See, e.g.,
    # <http://math2.uncc.edu/~shaodeng/TEACHING/math5172/Lectures/Lect_15.PDF>).
    #
    xi = sympy.DeferredVector('xi')
    x_xi = \
        + tetrahedron[0] * (1 - xi[0] - xi[1] - xi[2]) \
        + tetrahedron[1] * xi[0] \
        + tetrahedron[2] * xi[1] \
        + tetrahedron[3] * xi[2]
    abs_det_J = 6 * quadpy.tetrahedron.volume(tetrahedron)
    exact = sympy.integrate(
        sympy.integrate(
            sympy.integrate(abs_det_J * f(x_xi),
                            (xi[2], 0, 1 - xi[0] - xi[1])),
            (xi[1], 0, 1 - xi[0])), (xi[0], 0, 1))
    return float(exact)
Beispiel #3
0
def test_serendipity_derivatives():
    cell = UFCQuadrilateral()
    S = Serendipity(cell, 2)

    x = sympy.DeferredVector("X")
    X, Y = x[0], x[1]
    basis_functions = [
        (1 - X) * (1 - Y),
        Y * (1 - X),
        X * (1 - Y),
        X * Y,
        Y * (1 - X) * (Y - 1),
        X * Y * (Y - 1),
        X * (1 - Y) * (X - 1),
        X * Y * (X - 1),
    ]
    points = [[0.5, 0.5], [0.25, 0.75]]
    for alpha, actual in S.tabulate(2, points).items():
        expect = list(
            sympy.diff(basis, *zip([X, Y], alpha))
            for basis in basis_functions)
        expect = list(
            [basis.subs(dict(zip([X, Y], point))) for point in points]
            for basis in expect)
        assert actual.shape == (8, 2)
        assert np.allclose(np.asarray(expect, dtype=float),
                           actual.reshape(8, 2))
Beispiel #4
0
    def __init__(self):
        from sympy import pi, sin, cos
        x = sympy.DeferredVector('x')

        u = (
            +pi * 2 * sin(pi * x[1]) * cos(pi * x[1]) * sin(pi * x[0])**2,
            -pi * 2 * sin(pi * x[0]) * cos(pi * x[0]) * sin(pi * x[1])**2,
        )
        p = cos(pi * x[0]) * sin(pi * x[1])

        self.solution = {
            'u': {
                'value': u,
                'degree': MAX_DEGREE
            },
            'p': {
                'value': p,
                'degree': MAX_DEGREE
            },
        }
        self.mu = 1.0
        self.f = {
            'value': _get_stokes_rhs(u, p, self.mu),
            'degree': MAX_DEGREE,
        }
        return
Beispiel #5
0
    def to_riesz(self, poly_set):
        es = poly_set.get_expansion_set()
        ed = poly_set.get_embedded_degree()

        result = numpy.zeros(es.get_num_members(ed))
        sd = self.ref_el.get_spatial_dimension()

        X = sympy.DeferredVector('x')
        dX = numpy.asarray([X[i] for i in range(sd)])

        # evaluate bfs symbolically
        bfs = es.tabulate(ed, [dX])[:, 0]

        n = self.n
        qwts = self.Q.get_weights()

        for i in range(len(result)):
            thing = sympy.lambdify(
                X,
                sum([sympy.diff(bfs[i], dxi) * ni for dxi, ni in zip(dX, n)]))

            for j, pt in enumerate(self.deriv_dict.keys()):
                result[i] += qwts[j] * self.f_at_qpts[j] * thing(pt)

        return result
    def _setup(self):
        self._F0_N_ssro, self._F1_N_ssro, self._F0_e_ssro, self._F1_e_ssro, self._F0_RO_pulse, self._F1_RO_pulse, self._P_min1, self._P_0 = \
            sympy.symbols('F0_N_ssro F1_N_ssro F0_e_ssro F1_e_ssro F0_RO_pulse F1_RO_pulse P_min1 P_0')
        self._p_correlations = sympy.DeferredVector('p_correlations')

        # The total error matrix is the tensor product of the nitrogen and electron error matrices.
        # The nitrogen error matrix is built up of three matrices RO_err, CNOT_err and Init_err.
        # RO_err reflects fidelities of the electron RO,
        # CNOT_err reflects the fidelities in the pi (F0) and 2pi (F1) parts of the pi-2pi pulse (as CNOT gate).
        # Init_err includes populations in the three nitrogen lines after initialization in -1.
        #The inverse matrices are calculated before the tensorproduct, since this is much faster.

        self.error_matrix_N = (sympy.Matrix([[self._F0_N_ssro, 1.-self._F1_N_ssro],[1.-self._F0_N_ssro, self._F1_N_ssro]]) * \
            sympy.Matrix([[self._F0_RO_pulse, 1.-self._F1_RO_pulse, 0.],[1.-self._F0_RO_pulse, self._F1_RO_pulse, 1.]]) * \
                sympy.Matrix([[self._P_min1,self._P_0],[self._P_0,self._P_min1],[1.-self._P_0-self._P_min1,1.-self._P_0-self._P_min1]]))

        self.error_matrix_e = (sympy.Matrix(
            [[self._F0_e_ssro, 1. - self._F1_e_ssro],
             [1. - self._F0_e_ssro, self._F1_e_ssro]]))

        self.correction_matrix_N = self.error_matrix_N.inv()
        self.correction_matrix_e = self.error_matrix_e.inv()
        self.correction_matrix = TensorProduct(self.correction_matrix_N,
                                               self.correction_matrix_e)

        corr_vec =  self.correction_matrix * \
            sympy.Matrix([self._p_correlations[0], self._p_correlations[1], self._p_correlations[2], self._p_correlations[3]])
        corr_p_correlations = corr_vec

        self.p0_formula = error.Formula()
        self.p0_formula.formula = corr_p_correlations
Beispiel #7
0
def problem_taylor():
    '''Taylor--Green vortex, cf.
    <http://en.wikipedia.org/wiki/Taylor%E2%80%93Green_vortex>.
    '''
    def mesh_generator(n):
        return RectangleMesh(Point(0.0, 0.0), Point(2 * pi, 2 * pi), n, n,
                             'crossed')

    mu = 1.0
    rho = 1.0
    cell_type = triangle
    x = sympy.DeferredVector('x')
    t = sympy.symbols('t')
    x0 = x[0]
    x1 = x[1]
    # F = sympy.exp(-2*mu*t)
    F = 1 - 2 * mu * t
    u = (sympy.sin(x0) * sympy.cos(x1) * F, -sympy.cos(x0) * sympy.sin(x1) * F,
         0)
    p = rho / 4 * (sympy.cos(2 * x0) + sympy.cos(2 * x1)) * F**2
    solution = {
        'u': {
            'value': u,
            'degree': MAX_DEGREE
        },
        'p': {
            'value': p,
            'degree': MAX_DEGREE
        },
    }
    f = {
        'value': _get_navier_stokes_rhs(u, p),
        'degree': MAX_DEGREE,
    }
    return mesh_generator, solution, f, mu, rho, cell_type
Beispiel #8
0
def problem_guermond2():
    '''Problem 2 from section 3.7.2 in
        An overview of projection methods for incompressible flows;
        Guermond, Minev, Shen;
        Comp. Meth. in Appl. Mech. and Eng., vol. 195, 44-47, pp. 6011-6045;
        <http://www.sciencedirect.com/science/article/pii/S0045782505004640>.
    '''
    def mesh_generator(n):
        return UnitSquareMesh(n, n, 'crossed')

    cell_type = triangle
    x = sympy.DeferredVector('x')
    t = sympy.symbols('t')
    u = (sympy.sin(x[0] + t) * sympy.sin(x[1] + t),
         sympy.cos(x[0] + t) * sympy.cos(x[1] + t))
    p = sympy.sin(x[0] - x[1] + t)
    solution = {
        'u': {
            'value': u,
            'degree': MAX_DEGREE
        },
        'p': {
            'value': p,
            'degree': MAX_DEGREE
        },
    }
    f = {
        'value': _get_navier_stokes_rhs(u, p),
        'degree': MAX_DEGREE,
    }
    mu = 1.0
    rho = 1.0
    return mesh_generator, solution, f, mu, rho, cell_type
Beispiel #9
0
def problem_guermond1():
    '''Problem 1 from section 3.7.1 in
        An overview of projection methods for incompressible flows;
        Guermond, Minev, Shen;
        Comp. Meth. in Appl. Mech. and Eng., vol. 195, 44-47, pp. 6011-6045;
        <http://www.sciencedirect.com/science/article/pii/S0045782505004640>.
    '''
    def mesh_generator(n):
        return RectangleMesh(Point(-1, -1), Point(1, 1), n, n, 'crossed')

    cell_type = triangle
    x = sympy.DeferredVector('x')
    t = sympy.symbols('t')
    # m = sympy.exp(t) - 0.0
    m = sympy.sin(t)
    u = (+pi * m * 2 * sympy.sin(pi * x[1]) * sympy.cos(pi * x[1]) *
         sympy.sin(pi * x[0])**2, -pi * m * 2 * sympy.sin(pi * x[0]) *
         sympy.cos(pi * x[0]) * sympy.sin(pi * x[1])**2)
    p = m * sympy.cos(pi * x[0]) * sympy.sin(pi * x[1])
    solution = {
        'u': {
            'value': u,
            'degree': MAX_DEGREE
        },
        'p': {
            'value': p,
            'degree': MAX_DEGREE
        }
    }
    f = {'value': _get_navier_stokes_rhs(u, p), 'degree': MAX_DEGREE}
    mu = 1.0
    rho = 1.0
    return mesh_generator, solution, f, mu, rho, cell_type
Beispiel #10
0
    def __init__(self, f, past, helpers=(), control_pars=(), n_basic=None):
        self.past = past
        self.t, self.y, self.diff = self.past[-1]
        self.n = len(self.y)
        self.n_basic = n_basic or self.n
        self.last_garbage = -1
        self.old_new_y = None

        self.parameters = []

        from jitcdde._jitcdde import t, y, current_y, past_y, anchors
        Y = sympy.DeferredVector("Y")
        substitutions = list(helpers[::-1]) + [(y(i), Y[i])
                                               for i in range(self.n)]

        past_calls = 0
        f_wc = []
        for entry in f():
            new_entry = entry.subs(substitutions).simplify(ratio=1.0)
            past_calls += new_entry.count(anchors)
            f_wc.append(new_entry)

        F = sympy.lambdify([t, Y] + list(control_pars), f_wc,
                           [{
                               anchors.__name__: self.get_past_anchors,
                               past_y.__name__: self.get_past_value
                           }, "math"])

        self.f = lambda *args: np.array(F(*args)).flatten()

        self.anchor_mem = (len(past) - 1) * np.ones(past_calls, dtype=int)
Beispiel #11
0
def problem_whirl():
    '''Example from Teodora I. Mitkova's text
    "Finite-Elemente-Methoden fur die Stokes-Gleichungen".
    '''
    def mesh_generator(n):
        return UnitSquareMesh(n, n, 'left/right')

    cell_type = triangle
    x = sympy.DeferredVector('x')
    # t = sympy.symbols('t')

    # Note that the exact solution is indeed div-free.
    u = (x[0]**2 * (1 - x[0])**2 * 2 * x[1] * (1 - x[1]) * (2 * x[1] - 1),
         x[1]**2 * (1 - x[1])**2 * 2 * x[0] * (1 - x[0]) * (1 - 2 * x[0]))
    p = x[0] * (1 - x[0]) * x[1] * (1 - x[1])
    solution = {
        'u': {
            'value': u,
            'degree': 7
        },
        'p': {
            'value': p,
            'degree': 4
        },
    }
    f = {
        'value': _get_navier_stokes_rhs(u, p),
        'degree': MAX_DEGREE,
    }
    mu = 1.0
    rho = 1.0
    return mesh_generator, solution, f, mu, rho, cell_type
Beispiel #12
0
    def _lambdify(self, outputs):
        # TODO : We could forgo this substitution for generation speed
        # purposes and have lots of args for lambdify (like it used to be
        # done) but there may be some limitations on number of args.
        subs = {}
        vec_inputs = []
        if self.specifieds is None:
            def_vecs = ['q', 'u', 'p']
        else:
            def_vecs = ['q', 'u', 'r', 'p']

        for syms, vec_name in zip(self.inputs, def_vecs):
            v = sm.DeferredVector(vec_name)
            for i, sym in enumerate(syms):
                subs[sym] = v[i]
            vec_inputs.append(v)

        try:
            outputs = [me.msubs(output, subs) for output in outputs]
        except AttributeError:
            # msubs doesn't exist in SymPy < 0.7.6.
            outputs = [output.subs(subs) for output in outputs]

        modules = [{'ImmutableMatrix': np.array}, 'numpy']

        return sm.lambdify(vec_inputs, outputs, modules=modules)
Beispiel #13
0
def _get_data(dim, n, point_fun, symbolic):
    # points
    idxs = numpy.array(get_all_exponents(dim + 1, n)[-1])
    points = point_fun(idxs)

    # weights
    weights = numpy.empty(len(points))
    kk = 0
    for idx in idxs:
        # Define the polynomial which to integrate over the simplex.
        t = sympy.DeferredVector("t")
        g = prod(
            sympy.poly((t[i] - point_fun(k)) / (point_fun(m) - point_fun(k)))
            for i, m in enumerate(idx) for k in range(m))
        if isinstance(g, int):
            exp = [0] * (dim + 1)
            coeffs = g
        else:
            # make sure the exponents are all of the correct length
            exp = [list(m) + [0] * (dim - len(m) + 1) for m in g.monoms()]
            coeffs = g.coeffs()
        weights[kk] = sum(c * integrate_bary(m, symbolic)
                          for c, m in zip(coeffs, exp))
        kk += 1

    return weights, points
Beispiel #14
0
def problem_taylor_cylindrical():
    """Taylor--Green vortex, cf.
    <http://en.wikipedia.org/wiki/Taylor%E2%80%93Green_vortex>.
    """
    alpha = 1.0

    def mesh_generator(n):
        return RectangleMesh(
            Point(0.0 + alpha, 0.0), Point(2 * pi + alpha, 2 * pi), n, n, "crossed"
        )

    mu = 1.0
    rho = 1.0
    cell_type = triangle
    x = sympy.DeferredVector("x")
    t = sympy.symbols("t")
    x0 = x[0] - alpha
    x1 = x[1]
    F = 1 - 2 * mu * t
    u = (
        +sympy.sin(x0) * sympy.cos(x1) * F / x[0],
        -sympy.cos(x0) * sympy.sin(x1) * F / x[0],
        0,
    )
    p = rho / 4 * (sympy.cos(2 * x0) + sympy.cos(2 * x1)) * F ** 2
    solution = {
        "u": {"value": u, "degree": numpy.infty},
        "p": {"value": p, "degree": numpy.infty},
    }
    f = {"value": _get_navier_stokes_rhs_cylindrical(u, p), "degree": numpy.infty}
    return mesh_generator, solution, f, mu, rho, cell_type
Beispiel #15
0
def problem_flat():
    '''Nothing interesting happening in the domain.
    '''
    def mesh_generator(n):
        return UnitSquareMesh(n, n, 'left/right')

    cell_type = triangle
    x = sympy.DeferredVector('x')
    u = (0.0 * x[0], 0.0 * x[1])

    # Only grad(p) is of physical significance, and the numerical procedure
    # chooses p such that int(p) = 0. Also, numerical solutions have n.grad(p)
    # = 0 for non-penetration boundaries.  Make sure that the exact solution
    # respects those things to make error analysis easier.
    # p = sympy.cos(pi * x[1])
    p = -x[1]

    solution = {
        'u': {
            'value': u,
            'degree': 1
        },
        'p': {
            'value': p,
            'degree': 1
        },
    }
    f = {
        'value': _get_navier_stokes_rhs(u, p),
        'degree': MAX_DEGREE,
    }
    mu = 1.0
    rho = 1.0
    return mesh_generator, solution, f, mu, rho, cell_type
Beispiel #16
0
    def __call__(self, fn):
        """Evaluate the functional on the function fn. Note that this depends
        on sympy being able to differentiate fn."""
        x = list(self.deriv_dict.keys())[0]

        X = sympy.DeferredVector('x')
        dX = numpy.asarray([X[i] for i in range(len(x))])

        dvars = tuple(d for d, a in zip(dX, self.alpha) for count in range(a))

        return sympy.diff(fn(X), *dvars).evalf(subs=dict(zip(dX, x)))
Beispiel #17
0
def _newton_cotes(n, point_fun):
    '''
    Construction after

    P. Silvester,
    Symmetric quadrature formulae for simplexes
    Math. Comp., 24, 95-100 (1970),
    <https://doi.org/10.1090/S0025-5718-1970-0258283-6>.
    '''
    degree = n

    # points
    idx = numpy.array([[i, j, k, n - i - j - k] for i in range(n + 1)
                       for j in range(n + 1 - i)
                       for k in range(n + 1 - i - j)])
    bary = point_fun(idx, n)
    points = bary[:, [1, 2, 3]]

    # weights
    if n == 0:
        weights = numpy.ones(1)
        return points, weights, degree

    def get_poly(t, m, n):
        return sympy.prod([
            sympy.poly(
                (t - point_fun(k, n)) / (point_fun(m, n) - point_fun(k, n)))
            for k in range(m)
        ])

    weights = numpy.empty(len(points))
    idx = 0
    for i in range(n + 1):
        for j in range(n + 1 - i):
            for k in range(n + 1 - i - j):
                L = n - i - j - k
                # Compute weight.
                # Define the polynomial which to integrate over the
                # tetrahedron.
                t = sympy.DeferredVector('t')
                g = get_poly(t[0], i, n) \
                    * get_poly(t[1], j, n) \
                    * get_poly(t[2], k, n) \
                    * get_poly(t[3], L, n)
                # The integral of monomials over a tetrahedron are well-known,
                # see Silvester.
                weights[idx] = numpy.sum([
                    c * numpy.prod([math.factorial(k) for k in m]) * 6.0 /
                    math.factorial(numpy.sum(m) + 3)
                    for m, c in zip(g.monoms(), g.coeffs())
                ])
                idx += 1
    return points, weights, degree
Beispiel #18
0
def test_lambdify_matrix_vec_input():
    X = sympy.DeferredVector('X')
    M = Matrix([[X[0]**2, X[0] * X[1], X[0] * X[2]],
                [X[1] * X[0], X[1]**2, X[1] * X[2]],
                [X[2] * X[0], X[2] * X[1], X[2]**2]])
    f = lambdify(X, M, [{'ImmutableMatrix': numpy.array}, "numpy"])

    Xh = array([1.0, 2.0, 3.0])
    expected = array([[Xh[0]**2, Xh[0] * Xh[1], Xh[0] * Xh[2]],
                      [Xh[1] * Xh[0], Xh[1]**2, Xh[1] * Xh[2]],
                      [Xh[2] * Xh[0], Xh[2] * Xh[1], Xh[2]**2]])
    actual = f(Xh)
    assert numpy.allclose(actual, expected)
Beispiel #19
0
def _integrate_exact(k, pyra):
    def f(x):
        return x[0] ** int(k[0]) * x[1] ** int(k[1]) * x[2] ** int(k[2])

    # map the reference hexahedron [-1,1]^3 to the pyramid
    xi = sympy.DeferredVector("xi")
    pxi = (
        +pyra[0] * (1 - xi[0]) * (1 - xi[1]) * (1 - xi[2]) / 8
        + pyra[1] * (1 + xi[0]) * (1 - xi[1]) * (1 - xi[2]) / 8
        + pyra[2] * (1 + xi[0]) * (1 + xi[1]) * (1 - xi[2]) / 8
        + pyra[3] * (1 - xi[0]) * (1 + xi[1]) * (1 - xi[2]) / 8
        + pyra[4] * (1 + xi[2]) / 2
    )

    pxi = [sympy.expand(pxi[0]), sympy.expand(pxi[1]), sympy.expand(pxi[2])]
    # determinant of the transformation matrix
    J = sympy.Matrix(
        [
            [
                sympy.diff(pxi[0], xi[0]),
                sympy.diff(pxi[0], xi[1]),
                sympy.diff(pxi[0], xi[2]),
            ],
            [
                sympy.diff(pxi[1], xi[0]),
                sympy.diff(pxi[1], xi[1]),
                sympy.diff(pxi[1], xi[2]),
            ],
            [
                sympy.diff(pxi[2], xi[0]),
                sympy.diff(pxi[2], xi[1]),
                sympy.diff(pxi[2], xi[2]),
            ],
        ]
    )
    det_J = sympy.det(J)
    # we cannot use abs(), see <https://github.com/sympy/sympy/issues/4212>.
    # abs_det_J = sympy.Piecewise((det_J, det_J >= 0), (-det_J, det_J < 0))
    # This is quite the leap of faith, but sympy will cowardly bail out
    # otherwise.
    abs_det_J = det_J

    exact = sympy.integrate(
        sympy.integrate(
            sympy.integrate(abs_det_J * f(pxi), (xi[2], -1, 1)), (xi[1], -1, +1)
        ),
        (xi[0], -1, +1),
    )

    return float(exact)
Beispiel #20
0
def _integrate_exact(f, hexa):
    xi = sympy.DeferredVector('xi')
    pxi = \
        + hexa[0] * 0.125*(1.0 - xi[0])*(1.0 - xi[1])*(1.0 - xi[2]) \
        + hexa[1] * 0.125*(1.0 + xi[0])*(1.0 - xi[1])*(1.0 - xi[2]) \
        + hexa[2] * 0.125*(1.0 + xi[0])*(1.0 + xi[1])*(1.0 - xi[2]) \
        + hexa[3] * 0.125*(1.0 - xi[0])*(1.0 + xi[1])*(1.0 - xi[2]) \
        + hexa[4] * 0.125*(1.0 - xi[0])*(1.0 - xi[1])*(1.0 + xi[2]) \
        + hexa[5] * 0.125*(1.0 + xi[0])*(1.0 - xi[1])*(1.0 + xi[2]) \
        + hexa[6] * 0.125*(1.0 + xi[0])*(1.0 + xi[1])*(1.0 + xi[2]) \
        + hexa[7] * 0.125*(1.0 - xi[0])*(1.0 + xi[1])*(1.0 + xi[2])
    pxi = [
        sympy.expand(pxi[0]),
        sympy.expand(pxi[1]),
        sympy.expand(pxi[2]),
    ]
    # determinant of the transformation matrix
    J = sympy.Matrix([
        [
            sympy.diff(pxi[0], xi[0]),
            sympy.diff(pxi[0], xi[1]),
            sympy.diff(pxi[0], xi[2])
        ],
        [
            sympy.diff(pxi[1], xi[0]),
            sympy.diff(pxi[1], xi[1]),
            sympy.diff(pxi[1], xi[2])
        ],
        [
            sympy.diff(pxi[2], xi[0]),
            sympy.diff(pxi[2], xi[1]),
            sympy.diff(pxi[2], xi[2])
        ],
    ])
    det_J = sympy.det(J)
    # we cannot use abs(), see <https://github.com/sympy/sympy/issues/4212>.
    # pylint: disable=invalid-unary-operand-type
    abs_det_J = sympy.Piecewise((det_J, det_J >= 0), (-det_J, det_J < 0))
    g_xi = f(pxi)
    exact = \
        sympy.integrate(
            sympy.integrate(
                sympy.integrate(abs_det_J * g_xi, (xi[2], -1, 1)),
                (xi[1], -1, 1)
            ),
            (xi[0], -1, 1)
        )
    return float(exact)
Beispiel #21
0
    def to_riesz(self, poly_set):
        x = list(self.deriv_dict.keys())[0]

        X = sympy.DeferredVector('x')
        dx = numpy.asarray([X[i] for i in range(len(x))])

        es = poly_set.get_expansion_set()
        ed = poly_set.get_embedded_degree()

        bfs = es.tabulate(ed, [dx])[:, 0]

        # Expand the multi-index as a series of variables to
        # differentiate with respect to.
        dvars = tuple(d for d, a in zip(dx, self.alpha) for count in range(a))

        return numpy.asarray(
            [sympy.lambdify(X, sympy.diff(b, *dvars))(x) for b in bfs])
Beispiel #22
0
def problem_flat_cylindrical():
    """Nothing interesting happening in the domain.
    """

    def mesh_generator(n):
        return UnitSquareMesh(n, n, "left/right")

    cell_type = triangle
    # Coordinates ordered as (r, z, phi).
    x = sympy.DeferredVector("x")
    u = (0.0 * x[0], 0.0 * x[1], 0.0 * x[2])
    p = -9.81 * x[1]
    solution = {"u": {"value": u, "degree": 1}, "p": {"value": p, "degree": 1}}
    f = {"value": _get_navier_stokes_rhs_cylindrical(u, p), "degree": numpy.infty}
    mu = 1.0
    rho = 1.0
    return mesh_generator, solution, f, mu, rho, cell_type
Beispiel #23
0
def _get_stokes_rhs(u, p, mu):
    '''Given a solution u of the Cartesian Navier-Stokes equations, return
    a matching right-hand side f.
    '''
    x = sympy.DeferredVector('x')

    # Make sure that the exact solution is indeed analytically div-free.
    d = sympy.diff(u[0], x[0]) + sympy.diff(u[1], x[1])
    d = sympy.simplify(d)
    assert d == 0

    f0 = (-mu * (sympy.diff(u[0], x[0], 2) + sympy.diff(u[0], x[1], 2)) +
          sympy.diff(p, x[0]))
    f1 = (-mu * (sympy.diff(u[1], x[0], 2) + sympy.diff(u[1], x[1], 2)) +
          sympy.diff(p, x[1]))
    f = (sympy.simplify(f0), sympy.simplify(f1))

    return f
Beispiel #24
0
    def to_riesz(self, poly_set):
        x = list(self.deriv_dict.keys())[0]

        X = sympy.DeferredVector('x')
        dx = numpy.asarray([X[i] for i in range(len(x))])

        es = poly_set.get_expansion_set()
        ed = poly_set.get_embedded_degree()

        bfs = es.tabulate(ed, [dx])[:, 0]

        # We need the gradient dotted with the normal.
        return numpy.asarray([
            sympy.lambdify(
                X,
                sum([sympy.diff(b, dxi) * ni
                     for dxi, ni in zip(dx, self.n)]))(x) for b in bfs
        ])
Beispiel #25
0
def _integrate_exact(f, quadrilateral):
    xi = sympy.DeferredVector("xi")
    pxi = (quadrilateral[0] * 0.25 * (1.0 + xi[0]) * (1.0 + xi[1]) +
           quadrilateral[1] * 0.25 * (1.0 - xi[0]) * (1.0 + xi[1]) +
           quadrilateral[2] * 0.25 * (1.0 - xi[0]) * (1.0 - xi[1]) +
           quadrilateral[3] * 0.25 * (1.0 + xi[0]) * (1.0 - xi[1]))
    pxi = [sympy.expand(pxi[0]), sympy.expand(pxi[1])]
    # determinant of the transformation matrix
    det_J = +sympy.diff(pxi[0], xi[0]) * sympy.diff(
        pxi[1], xi[1]) - sympy.diff(pxi[1], xi[0]) * sympy.diff(pxi[0], xi[1])
    # we cannot use abs(), see <https://github.com/sympy/sympy/issues/4212>.
    abs_det_J = sympy.Piecewise((det_J, det_J >= 0), (-det_J, det_J < 0))

    g_xi = f(pxi)

    exact = sympy.integrate(sympy.integrate(abs_det_J * g_xi, (xi[1], -1, 1)),
                            (xi[0], -1, 1))
    return float(exact)
Beispiel #26
0
def problem_guermond1_cylindrical():
    """Cylindrical variation of Guermond's test problem.
    """
    alpha = 1.5

    def mesh_generator(n):
        return RectangleMesh(
            Point(-1 + alpha, -1), Point(1 + alpha, 1), n, n, "crossed"
        )

    cell_type = triangle
    x = sympy.DeferredVector("x")
    t = sympy.symbols("t")
    x0 = x[0] - alpha
    x1 = x[1]
    # m = sympy.exp(t) - 0.0
    m = sympy.sin(t) + 1.0
    u = (
        +pi
        * m
        * 2
        * sympy.sin(pi * x1)
        * sympy.cos(pi * x1)
        * sympy.sin(pi * x0) ** 2
        / x[0],
        -pi
        * m
        * 2
        * sympy.sin(pi * x0)
        * sympy.cos(pi * x0)
        * sympy.sin(pi * x1) ** 2
        / x[0],
        0,
    )
    p = m * sympy.cos(pi * x0) * sympy.sin(pi * x1)
    solution = {
        "u": {"value": u, "degree": numpy.infty},
        "p": {"value": p, "degree": numpy.infty},
    }
    f = {"value": _get_navier_stokes_rhs_cylindrical(u, p), "degree": numpy.infty}
    mu = 1.0
    rho = 1.0
    return mesh_generator, solution, f, mu, rho, cell_type
Beispiel #27
0
def _newton_cotes(n, point_fun):
    degree = n

    # points
    idx = numpy.array([[i, j, k, n - i - j - k] for i in range(n + 1)
                       for j in range(n + 1 - i)
                       for k in range(n + 1 - i - j)])
    points = point_fun(idx, n)

    # weights
    if n == 0:
        weights = numpy.ones(1)
        return weights, points, weights, degree

    def get_poly(t, m, n):
        return sympy.prod([
            sympy.poly(
                (t - point_fun(k, n)) / (point_fun(m, n) - point_fun(k, n)))
            for k in range(m)
        ])

    weights = numpy.empty(len(points))
    idx = 0
    for i in range(n + 1):
        for j in range(n + 1 - i):
            for k in range(n + 1 - i - j):
                L = n - i - j - k
                # Compute weight.
                # Define the polynomial which to integrate over the
                # tetrahedron.
                t = sympy.DeferredVector("t")
                g = (get_poly(t[0], i, n) * get_poly(t[1], j, n) *
                     get_poly(t[2], k, n) * get_poly(t[3], L, n))
                # The integral of monomials over a tetrahedron are well-known,
                # see Silvester.
                weights[idx] = numpy.sum([
                    c * numpy.prod([math.factorial(k) for k in m]) * 6.0 /
                    math.factorial(numpy.sum(m) + 3)
                    for m, c in zip(g.monoms(), g.coeffs())
                ])
                idx += 1
    return weights, points, degree, citation
Beispiel #28
0
 def __init__(self):
     x = sympy.DeferredVector('x')
     u = (0 * x[0], 0 * x[1])
     p = -9.81 * x[1]
     self.solution = {
         'u': {
             'value': u,
             'degree': 1
         },
         'p': {
             'value': p,
             'degree': 1
         },
     }
     self.mu = 1.0
     self.f = {
         'value': _get_stokes_rhs(u, p, self.mu),
         'degree': MAX_DEGREE,
     }
     return
Beispiel #29
0
def problem_whirl_cylindrical():
    """Example from Teodora I. Mitkova's text
    "Finite-Elemente-Methoden fur die Stokes-Gleichungen", adapted for
    cylindrical Navier-Stokes.
    """
    alpha = 1.0

    def mesh_generator(n):
        # return UnitSquareMesh(n, n, 'left/right')
        return RectangleMesh(
            Point(alpha, 0.0), Point(1.0 + alpha, 1.0), n, n, "left/right"
        )

    cell_type = triangle
    x = sympy.DeferredVector("x")
    # Note that the exact solution is indeed div-free.
    x0 = x[0] - alpha
    x1 = x[1]
    u = (
        x0 ** 2 * (1 - x0) ** 2 * 2 * x1 * (1 - x1) * (2 * x1 - 1) / x[0],
        x1 ** 2 * (1 - x1) ** 2 * 2 * x0 * (1 - x0) * (1 - 2 * x0) / x[0],
        0,
    )
    p = x0 * (1 - x0) * x1 * (1 - x1)
    solution = {
        "u": {"value": u, "degree": numpy.infty},
        "p": {"value": p, "degree": 4},
    }
    plot_solution = False
    if plot_solution:
        sol_u = Expression(
            (helpers.ccode(u[0]), helpers.ccode(u[1])),
            degree=numpy.infty,
            t=0.0,
            cell=cell_type,
        )
        plot(sol_u, mesh=mesh_generator(20))
    f = {"value": _get_navier_stokes_rhs_cylindrical(u, p), "degree": numpy.infty}
    mu = 1.0
    rho = 1.0
    return mesh_generator, solution, f, mu, rho, cell_type
Beispiel #30
0
def _get_navier_stokes_rhs(u, p):
    '''Given a solution u of the Cartesian Navier-Stokes equations, return
    a matching right-hand side f.
    '''
    x = sympy.DeferredVector('x')
    t, mu, rho = sympy.symbols('t, mu, rho')

    # Make sure that the exact solution is indeed analytically div-free.
    d = sympy.diff(u[0], x[0]) + sympy.diff(u[1], x[1])
    d = sympy.simplify(d)
    assert d == 0

    # Get right-hand side associated with this solution, i.e., according
    # the Navier-Stokes
    #
    #     rho (du_x/dt + u_x du_x/dx + u_y du_x/dy)
    #         = - dp/dx + mu [d^2u_x/dx^2 + d^2u_x/dy^2] + f_x,
    #     rho (du_y/dt + u_x du_y/dx + u_y du_y/dy)
    #         = - dp/dx + mu [d^2u_y/dx^2 + d^2u_y/dy^2] + f_y,
    #     du_x/dx + du_y/dy = 0.
    #
    #     rho (du/dt + (u.\nabla)u) = -\nabla p + mu [\div(\nabla u)] + f,
    #     div(u) = 0.
    #
    f0 = rho * (sympy.diff(u[0], t)
                + u[0] * sympy.diff(u[0], x[0])
                + u[1] * sympy.diff(u[0], x[1])
                ) \
        + sympy.diff(p, x[0]) \
        - mu * (sympy.diff(u[0], x[0], 2) + sympy.diff(u[0], x[1], 2))
    f1 = rho * (sympy.diff(u[1], t)
                + u[0] * sympy.diff(u[1], x[0])
                + u[1] * sympy.diff(u[1], x[1])
                ) \
        + sympy.diff(p, x[1]) \
        - mu * (sympy.diff(u[1], x[0], 2) + sympy.diff(u[1], x[1], 2))

    f = (sympy.simplify(f0), sympy.simplify(f1))
    return f