示例#1
0
def test_lhs_rhs_simple():
    """Test taking lhs/rhs of DOLFINX specific forms (constants
    without cell). """

    mesh = RectangleMesh(
        MPI.COMM_WORLD,
        [numpy.array([0.0, 0.0, 0.0]),
         numpy.array([2.0, 1.0, 0.0])], [3, 5], CellType.triangle)
    V = FunctionSpace(mesh, "CG", 1)
    f = 2.0
    g = 3.0
    v = TestFunction(V)
    u = TrialFunction(V)

    F = inner(g * grad(f * v), grad(u)) * dx + f * v * dx
    a, L = system(F)

    Fl = lhs(F)
    Fr = rhs(F)
    assert (Fr)

    a0 = inner(grad(v), grad(u)) * dx

    n = assemble(a).norm("frobenius")  # noqa
    nl = assemble(Fl).norm("frobenius")  # noqa
    n0 = 6.0 * assemble(a0).norm("frobenius")  # noqa

    assert round(n - n0, 7) == 0
    assert round(n - nl, 7) == 0
示例#2
0
def mesh2d():
    """Create 2D mesh with one equilateral triangle"""
    mesh2d = RectangleMesh(
        MPI.comm_world, [np.array([0.0, 0.0, 0.0]),
                         np.array([1., 1., 0.0])], [1, 1], CellType.triangle,
        cpp.mesh.GhostMode.none, 'left')
    mesh2d.geometry.points[3, :2] += 0.5 * (math.sqrt(3.0) - 1.0)
    return mesh2d
示例#3
0
def mesh2d():
    """Create 2D mesh with one equilateral triangle"""
    mesh2d = RectangleMesh(
        MPI.COMM_WORLD, [np.array([0.0, 0.0, 0.0]),
                         np.array([1., 1., 0.0])], [1, 1], CellType.triangle,
        cpp.mesh.GhostMode.none, 'left')
    i1 = np.where((mesh2d.geometry.x == (1, 1, 0)).all(axis=1))[0][0]
    mesh2d.geometry.x[i1, :2] += 0.5 * (math.sqrt(3.0) - 1.0)
    return mesh2d
示例#4
0
def index():
    r"""Use simple flas application to serve dolfinX."""
    RectangleMesh(
        MPI.COMM_WORLD,
        [np.array([0, 0, 0]), np.array([1, 1, 0])], [32, 32],
        CellType.triangle, dolfinx.cpp.mesh.GhostMode.none)
    d = {"numbers": list(range(10)), 'method': request.method}
    if request.method == 'POST':
        data = request.form
        name = data['name']
        d = None
        if name == "numbers":
            d = {"numbers": list(range(10)), 'method': request.method}
    return jsonify(d)
示例#5
0
def rectangle():
    return RectangleMesh(
        MPI.COMM_WORLD, [np.array([0.0, 0.0, 0.0]),
                         np.array([2.0, 2.0, 0.0])], [5, 5], CellType.triangle,
        cpp.mesh.GhostMode.none)
示例#6
0
T = wx / c0 + 2.0 / f0
omega = 2 * np.pi * f0

degree = 2   # discretisation degree
nPerLam = 4  # no. elements per wavelength
CFL = 0.9    # CFL constant

lam = 2 * np.pi * c0 / omega  # wavelength
h = lam / nPerLam             # element dimension
period = 1.0 / f0             # temporal period
nx = np.int(np.round(wx / h))
ny = np.int(np.round(wy / h))

# Build mesh
mesh = RectangleMesh(MPI.COMM_WORLD,
                     [np.array([0, -wy/2, 0]), np.array([wx, wy/2, 0])],
                     [nx, ny],
                     CellType.quadrilateral, dolfinx.cpp.mesh.GhostMode.none)


# Determine timestep for Runge-Kutta via CFL
hmin = min(MPI.COMM_WORLD.allgather(mesh.hmin()))
dt = CFL * hmin / (c0 * (2 * degree + 1))  # CFL condition
# Adjust dt so that it exactly divides one period
n_period = np.int(np.ceil(period / dt))
dt = period / n_period
num_steps = np.int(np.ceil(T / dt))

if (MPI.COMM_WORLD.rank == 0):
    print("#time steps = ", num_steps)

# Create model
import ufl
from dolfinx import DirichletBC, Function, FunctionSpace, RectangleMesh
from dolfinx.cpp.mesh import CellType
from dolfinx.fem import locate_dofs_geometrical, locate_dofs_topological
from dolfinx.io import XDMFFile
from dolfinx.mesh import locate_entities_boundary
from mpi4py import MPI
from petsc4py import PETSc
from ufl import div, dx, grad, inner


# We create a Mesh and attach a coordinate map to the mesh::

# Create mesh
mesh = RectangleMesh(MPI.COMM_WORLD,
                     [np.array([0, 0, 0]), np.array([1, 1, 0])],
                     [32, 32],
                     CellType.triangle, dolfinx.cpp.mesh.GhostMode.none)


# Function to mark x = 0, x = 1 and y = 0
def noslip_boundary(x):
    return np.logical_or(np.logical_or(np.isclose(x[0], 0.0),
                                       np.isclose(x[0], 1.0)),
                         np.isclose(x[1], 0.0))


# Function to mark the lid (y = 1)
def lid(x):
    return np.isclose(x[1], 1.0)

示例#8
0
from dolfinx.cpp.mesh import CellType
from dolfinx.fem import locate_dofs_topological
from dolfinx.io import XDMFFile
from dolfinx.mesh import locate_entities_boundary
from ufl import ds, dx, grad, inner

# We begin by defining a mesh of the domain and a finite element
# function space :math:`V` relative to this mesh. As the unit square is
# a very standard domain, we can use a built-in mesh provided by the
# class :py:class:`UnitSquareMesh <dolfinx.cpp.UnitSquareMesh>`. In order
# to create a mesh consisting of 32 x 32 squares with each square
# divided into two triangles, we do as follows ::

# Create mesh and define function space
mesh = RectangleMesh(
    MPI.COMM_WORLD,
    [np.array([0, 0, 0]), np.array([1, 1, 0])], [32, 32], CellType.triangle,
    dolfinx.cpp.mesh.GhostMode.none)

V = FunctionSpace(mesh, ("Lagrange", 1))

# The second argument to :py:class:`FunctionSpace
# <dolfinx.function.FunctionSpace>` is the finite element
# family, while the third argument specifies the polynomial
# degree. Thus, in this case, our space ``V`` consists of first-order,
# continuous Lagrange finite element functions (or in order words,
# continuous piecewise linear polynomials).
#
# Next, we want to consider the Dirichlet boundary condition. A simple
# Python function, returning a boolean, can be used to define the
# boundary for the Dirichlet boundary condition (:math:`\Gamma_D`). The
# function should return ``True`` for those points inside the boundary
def test_div_grad_then_integrate_over_cells_and_boundary():

    # Define 2D geometry
    n = 10
    mesh = RectangleMesh(
        [numpy.array([0.0, 0.0, 0.0]),
         numpy.array([2.0, 3.0, 0.0])], 2 * n, 3 * n)

    x, y = SpatialCoordinate(mesh)
    xs = 0.1 + 0.8 * x / 2  # scaled to be within [0.1,0.9]
    #    ys = 0.1 + 0.8 * y / 3  # scaled to be within [0.1,0.9]
    n = FacetNormal(mesh)

    # Define list of expressions to test, and configure accuracies
    # these expressions are known to pass with.  The reason some
    # functions are less accurately integrated is likely that the
    # default choice of quadrature rule is not perfect
    F_list = []

    def reg(exprs, acc=10):
        for expr in exprs:
            F_list.append((expr, acc))

    # FIXME: 0*dx and 1*dx fails in the ufl-ffcx-jit framework somewhere
    # reg([Constant(0.0, cell=cell)])
    # reg([Constant(1.0, cell=cell)])
    monomial_list = [x**q for q in range(2, 6)]
    reg(monomial_list)
    reg([2.3 * p + 4.5 * q for p in monomial_list for q in monomial_list])
    reg([xs**xs])
    reg(
        [xs**(xs**2)], 8
    )  # Note: Accuracies here are from 1D case, not checked against 2D results.
    reg([xs**(xs**3)], 6)
    reg([xs**(xs**4)], 2)
    # Special functions:
    reg([atan(xs)], 8)
    reg([sin(x), cos(x), exp(x)], 5)
    reg([ln(xs), pow(x, 2.7), pow(2.7, x)], 3)
    reg([asin(xs), acos(xs)], 1)
    reg([tan(xs)], 7)

    # To handle tensor algebra, make an x dependent input tensor
    # xx and square all expressions
    def reg2(exprs, acc=10):
        for expr in exprs:
            F_list.append((inner(expr, expr), acc))

    xx = as_matrix([[2 * x**2, 3 * x**3], [11 * x**5, 7 * x**4]])
    xxs = as_matrix([[2 * xs**2, 3 * xs**3], [11 * xs**5, 7 * xs**4]])
    x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4])
    cc = as_matrix([[2, 3], [4, 5]])
    reg2(
        [xx]
    )  # TODO: Make unit test for UFL from this, results in listtensor with free indices
    reg2([x3v])
    reg2([cross(3 * x3v, as_vector([-x3v[1], x3v[0], x3v[2]]))])
    reg2([xx.T])
    reg2([tr(xx)])
    reg2([det(xx)])
    reg2([dot(xx, 0.1 * xx)])
    reg2([outer(xx, xx.T)])
    reg2([dev(xx)])
    reg2([sym(xx)])
    reg2([skew(xx)])
    reg2([elem_mult(7 * xx, cc)])
    reg2([elem_div(7 * xx, xx + cc)])
    reg2([elem_pow(1e-3 * xxs, 1e-3 * cc)])
    reg2([elem_pow(1e-3 * cc, 1e-3 * xx)])
    reg2([elem_op(lambda z: sin(z) + 2, 0.03 * xx)], 2)  # pretty inaccurate...

    # FIXME: Add tests for all UFL operators:
    # These cause discontinuities and may be harder to test in the
    # above fashion:
    # 'inv', 'cofac',
    # 'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not',
    # 'conditional', 'sign',
    # 'jump', 'avg',
    # 'LiftingFunction', 'LiftingOperator',

    # FIXME: Test other derivatives: (but algorithms for operator
    # derivatives are the same!):
    # 'variable', 'diff',
    # 'Dx', 'grad', 'div', 'curl', 'rot', 'Dn', 'exterior_derivative',

    # Run through all operators defined above and compare integrals
    debug = 0
    if debug:
        F_list = F_list[1:]

    for F, acc in F_list:
        if debug:
            print('\n', "F:", str(F))

        # Integrate over domain and its boundary
        int_dx = assemble(div(grad(F)) * dx(mesh))  # noqa
        int_ds = assemble(dot(grad(F), n) * ds(mesh))  # noqa

        if debug:
            print(int_dx, int_ds)

        # Compare results. Using custom relative delta instead of
        # decimal digits here because some numbers are >> 1.
        delta = min(abs(int_dx), abs(int_ds)) * 10**-acc
        assert int_dx - int_ds <= delta
示例#10
0
import matplotlib.pyplot as plt
import numpy as np
from mpi4py import MPI
from petsc4py import PETSc

import dolfinx
import dolfinx.plotting
import ufl
from dolfinx import DirichletBC, Function, FunctionSpace, RectangleMesh, solve
from dolfinx.cpp.mesh import CellType
from dolfinx.fem import locate_dofs_topological
from dolfinx.mesh import locate_entities_boundary
from ufl import ds, dx, grad, inner

mesh = RectangleMesh(
        MPI.COMM_WORLD,
        [np.array([0., 0., 0.]), np.array([1., 1., 0.])], [128, 128],
        CellType.triangle, dolfinx.cpp.mesh.GhostMode.none)

V = FunctionSpace(mesh, ("Lagrange", 1))
u0 = Function(V)
u0.vector.set(0.)
facets = locate_entities_boundary(mesh, 1,
        lambda x: np.logical_or(x[0] < np.finfo(float).eps,
                                x[0] > 1.-np.finfo(float).eps)
        )
bc = DirichletBC(u0, local_dofs_topological(V, 1, facets))
u = ufl.TrialFunction(V)
v = ufl.TrialFunction(V)
x = ufl.SpatialCoordinate(mesh)
f = ufl.mathfunctions.ConstantValue(20.)
# The constant sigma_0 is chosen to achieve a specified "round-trip" reflection
# of a wave that through the layer, reflects and returns back into the domain.
# See Oskooi et al. (2008) for more details.
RT = 1.0e-6  # round-trip reflection
sigma0 = -(deg_absorb + 1) * np.log(RT) / (2.0 * d_absorb)
'''                             Meshing                                     '''
# For this problem we use a square mesh with triangular elements.
# The mesh element size is h_elem, and the #elements in one dimension is n_elem
h_elem = wave_len / n_wave
n_elem_x = int(np.round(dim_x / h_elem))
n_elem_y = int(np.round(dim_y / h_elem))

# Create mesh
mesh = RectangleMesh(MPI.COMM_WORLD, [
    np.array([-dim_x / 2, -dim_y / 2, 0]),
    np.array([dim_x / 2, dim_y / 2, 0])
], [n_elem_x, n_elem_y], CellType.triangle, dolfinx.cpp.mesh.GhostMode.none)
'''        Incident field, wavenumber and adiabatic absorber functions      '''


def incident(x):
    # Plane wave travelling in positive x-direction
    return np.exp(1.0j * k0 * x[0])


def wavenumber(x):
    # Create sonic crystal structure
    x_start = -0.5 * (nx - 1) * (2 * rad_crys + gap)
    y_start = -0.5 * (ny - 1) * (2 * rad_crys + gap)
    for i in range(nx):
        for j in range(ny):
示例#12
0
def test_biharmonic():
    """Manufactured biharmonic problem.

    Solved using rotated Regge mixed finite element method. This is equivalent
    to the Hellan-Herrmann-Johnson (HHJ) finite element method in
    two-dimensions."""
    mesh = RectangleMesh(MPI.COMM_WORLD, [np.array([0.0, 0.0, 0.0]),
                                          np.array([1.0, 1.0, 0.0])], [32, 32], CellType.triangle)

    element = ufl.MixedElement([ufl.FiniteElement("Regge", ufl.triangle, 1),
                                ufl.FiniteElement("Lagrange", ufl.triangle, 2)])

    V = FunctionSpace(mesh, element)
    sigma, u = ufl.TrialFunctions(V)
    tau, v = ufl.TestFunctions(V)

    x = ufl.SpatialCoordinate(mesh)
    u_exact = ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1]) * ufl.sin(ufl.pi * x[1])
    f_exact = div(grad(div(grad(u_exact))))
    sigma_exact = grad(grad(u_exact))

    # sigma and tau are tangential-tangential continuous according to the
    # H(curl curl) continuity of the Regge space. However, for the biharmonic
    # problem we require normal-normal continuity H (div div). Theorem 4.2 of
    # Lizao Li's PhD thesis shows that the latter space can be constructed by
    # the former through the action of the operator S:
    def S(tau):
        return tau - ufl.Identity(2) * ufl.tr(tau)

    sigma_S = S(sigma)
    tau_S = S(tau)

    # Discrete duality inner product eq. 4.5 Lizao Li's PhD thesis
    def b(tau_S, v):
        n = FacetNormal(mesh)
        return inner(tau_S, grad(grad(v))) * dx \
            - ufl.dot(ufl.dot(tau_S('+'), n('+')), n('+')) * jump(grad(v), n) * dS \
            - ufl.dot(ufl.dot(tau_S, n), n) * ufl.dot(grad(v), n) * ds

    # Non-symmetric formulation
    a = inner(sigma_S, tau_S) * dx - b(tau_S, u) + b(sigma_S, v)
    L = inner(f_exact, v) * dx

    V_1 = V.sub(1).collapse()
    zero_u = Function(V_1)
    with zero_u.vector.localForm() as zero_u_local:
        zero_u_local.set(0.0)

    # Strong (Dirichlet) boundary condition
    boundary_facets = locate_entities_boundary(
        mesh, mesh.topology.dim - 1, lambda x: np.full(x.shape[1], True, dtype=bool))
    boundary_dofs = locate_dofs_topological((V.sub(1), V_1), mesh.topology.dim - 1, boundary_facets)

    bcs = [DirichletBC(zero_u, boundary_dofs, V.sub(1))]

    A = assemble_matrix(a, bcs=bcs)
    A.assemble()
    b = assemble_vector(L)
    apply_lifting(b, [a], [bcs])
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)

    # Solve
    solver = PETSc.KSP().create(MPI.COMM_WORLD)
    PETSc.Options()["ksp_type"] = "preonly"
    PETSc.Options()["pc_type"] = "lu"
    # PETSc.Options()["pc_factor_mat_solver_type"] = "mumps"
    solver.setFromOptions()
    solver.setOperators(A)

    x_h = Function(V)
    solver.solve(b, x_h.vector)
    x_h.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                           mode=PETSc.ScatterMode.FORWARD)

    # Recall that x_h has flattened indices.
    u_error_numerator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar(
        inner(u_exact - x_h[4], u_exact - x_h[4]) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM))
    u_error_denominator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar(
        inner(u_exact, u_exact) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM))

    assert(np.absolute(u_error_numerator / u_error_denominator) < 0.05)

    # Reconstruct tensor from flattened indices.
    # Apply inverse transform. In 2D we have S^{-1} = S.
    sigma_h = S(ufl.as_tensor([[x_h[0], x_h[1]], [x_h[2], x_h[3]]]))
    sigma_error_numerator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar(
        inner(sigma_exact - sigma_h, sigma_exact - sigma_h) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM))
    sigma_error_denominator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar(
        inner(sigma_exact, sigma_exact) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM))

    assert(np.absolute(sigma_error_numerator / sigma_error_denominator) < 0.005)
示例#13
0
from dolfinx.io import XDMFFile
from dolfinx.mesh import compute_marked_boundary_entities
from dolfinx.fem import locate_dofs_topological
from dolfinx.specialfunctions import SpatialCoordinate
from ufl import ds, dx, grad, inner

# We begin by defining a mesh of the domain and a finite element
# function space :math:`V` relative to this mesh. As the unit square is
# a very standard domain, we can use a built-in mesh provided by the
# class :py:class:`UnitSquareMesh <dolfinx.cpp.UnitSquareMesh>`. In order
# to create a mesh consisting of 32 x 32 squares with each square
# divided into two triangles, we do as follows ::

# Create mesh and define function space
mesh = RectangleMesh(
    MPI.comm_world,
    [np.array([0, 0, 0]), np.array([1, 1, 0])], [32, 32], CellType.triangle,
    dolfinx.cpp.mesh.GhostMode.none)
V = FunctionSpace(mesh, ("Lagrange", 1))

cmap = dolfinx.fem.create_coordinate_map(mesh.ufl_domain())
mesh.geometry.coord_mapping = cmap

# The second argument to :py:class:`FunctionSpace
# <dolfinx.function.FunctionSpace>` is the finite element
# family, while the third argument specifies the polynomial
# degree. Thus, in this case, our space ``V`` consists of first-order,
# continuous Lagrange finite element functions (or in order words,
# continuous piecewise linear polynomials).
#
# Next, we want to consider the Dirichlet boundary condition. A simple
# Python function, returning a boolean, can be used to define the