示例#1
0
def SetupUnitMeshHelper(mesh, V=None, Vc=None):

    if V is None:
        V = df.FunctionSpace(mesh, 'CG', 1)
    if Vc is None:
        Vc = df.FunctionSpace(mesh, 'DG', 0)

    boundaries = dict()
    boundaries['left'] = df.CompiledSubDomain("near(x[0], 0.0) && on_boundary")
    boundaries['bottom'] = df.CompiledSubDomain(
        "near(x[1], 0.0) && on_boundary")
    boundaries['top'] = df.CompiledSubDomain("near(x[1], 1.0) && on_boundary")
    boundaries['right'] = df.CompiledSubDomain(
        "near(x[0], 1.0) && on_boundary")

    boundarymarkers = df.MeshFunction('size_t', mesh,
                                      mesh.topology().dim() - 1, 0)
    boundarymarkers.set_all(0)
    domainmarkers = df.MeshFunction('size_t', mesh, mesh.topology().dim(), 0)

    boundaries['left'].mark(boundarymarkers, 1)
    boundaries['bottom'].mark(boundarymarkers, 2)
    boundaries['right'].mark(boundarymarkers, 3)
    boundaries['top'].mark(boundarymarkers, 4)

    ds = df.Measure('ds', domain=mesh, subdomain_data=boundarymarkers)
    dx = df.Measure('dx', domain=mesh, subdomain_data=domainmarkers)

    return boundaries, boundarymarkers, domainmarkers, dx, ds, V, Vc
示例#2
0
def load_2d_muscle_geo(filename='../geo/muscle_2d.xml', L0=1e-2):

    mesh = fe.Mesh(filename)
    coords = mesh.coordinates()
    coords *= L0
    mesh.bounding_box_tree().build(mesh)

    # Define Boundaries
    bottom = fe.CompiledSubDomain("near(x[1], side, 0.01) && on_boundary", side=-20.0 * L0)
    top = fe.CompiledSubDomain("near(x[1], side, 0.01) && on_boundary", side=20.0 * L0)

    # Initialize mesh function for boundary domains
    boundaries = fe.MeshFunction('size_t', mesh, 2)
    boundaries.set_all(0)
    bottom.mark(boundaries, 1)
    top.mark(boundaries, 2)

    # Define new measures associated with the interior domains and
    # exterior boundaries

    dx = fe.Measure('dx', domain=mesh)
    ds = fe.Measure('ds', domain=mesh, subdomain_data=boundaries)

    return mesh, dx, ds, {"top": top, "bottom": bottom}
示例#3
0
#fe.parameters["form_compiler"]["quadrature_degree"] = 5

# Create mesh and define function space
n = 20
mesh = fe.UnitCubeMesh(n, n, n)

# Init function spaces
element_3 = fe.VectorElement("P", mesh.ufl_cell(), 1)
element = fe.FiniteElement("P", mesh.ufl_cell(), 2)

# Mixed function space
TH = element_3 * element
V = fe.FunctionSpace(mesh, TH)

# Define Boundaries
left = fe.CompiledSubDomain("near(x[0], side) && on_boundary", side=0.0)
right = fe.CompiledSubDomain("near(x[0], side) && on_boundary", side=1.0)

# Define Dirichlet boundary (x = 0 or x = 1)
u_left = fe.Expression(("0.0", "0.0", "0.0"), element=element_3)
u_right = fe.Expression(("0.0", "0.0", "0.0"), element=element_3)
p_left = fe.Constant(0.)

# Define acting force
b = fe.Constant((0.0, 0.0, 0.0))  # Body force per unit volume
t_bar = fe.Constant((0.0, 0.0, 0.0))  # Traction force on the boundary

# Define test and trial functions
w = fe.Function(V)  # most recently computed solution
(u, p) = fe.split(w)
(v, q) = fe.TestFunctions(V)
示例#4
0
def regular_box_mesh(n=10,
                     S_x=0.0,
                     S_y=0.0,
                     S_z=None,
                     E_x=1.0,
                     E_y=1.0,
                     E_z=None):
    r"""Creates a mesh corresponding to a rectangle or cube.

	This function creates a uniform mesh of either a rectangle
	or a cube, with specified start (``S_``) and end points (``E_``).
	The resulting mesh uses ``n`` elements along the shortest direction
	and accordingly many along the longer ones. The resulting domain is

	.. math::
		\begin{alignedat}{2}
			&[S_x, E_x] \times [S_y, E_y] \quad &&\text{ in } 2D, \\
			&[S_x, E_x] \times [S_y, E_y] \times [S_z, E_z] \quad &&\text{ in } 3D.
		\end{alignedat}

	The boundary markers are ordered as follows:

	  - 1 corresponds to :math:`x=S_x`.

	  - 2 corresponds to :math:`x=E_x`.

	  - 3 corresponds to :math:`y=S_y`.

	  - 4 corresponds to :math:`y=E_y`.

	  - 5 corresponds to :math:`z=S_z` (only in 3D).

	  - 6 corresponds to :math:`z=E_z` (only in 3D).

	Parameters
	----------
	n : int
		Number of elements in the shortest coordinate direction.
	S_x : float
		Start of the x-interval.
	S_y : float
		Start of the y-interval.
	S_z : float or None, optional
		Start of the z-interval, mesh is 2D if this is ``None``
		(default is ``None``).
	E_x : float
		End of the x-interval.
	E_y : float
		End of the y-interval.
	E_z : float or None, optional
		End of the z-interval, mesh is 2D if this is ``None``
		(default is ``None``).

	Returns
	-------
	mesh : dolfin.cpp.mesh.Mesh
		The computational mesh.
	subdomains : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the subdomains.
	boundaries : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the boundaries.
	dx : ufl.measure.Measure
		The volume measure of the mesh corresponding to subdomains.
	ds : ufl.measure.Measure
		The surface measure of the mesh corresponding to boundaries.
	dS : ufl.measure.Measure
		The interior facet measure of the mesh corresponding to boundaries.
	"""

    n = int(n)

    if not n > 0:
        raise InputError('cashocs.geometry.regular_box_mesh', 'n',
                         'This needs to be positive.')

    if not S_x < E_x:
        raise InputError(
            'cashocs.geometry.regular_box_mesh', 'S_x',
            'Incorrect input for the x-coordinate. S_x has to be smaller than E_x.'
        )
    if not S_y < E_y:
        raise InputError(
            'cashocs.geometry.regular_box_mesh', 'S_y',
            'Incorrect input for the y-coordinate. S_y has to be smaller than E_y.'
        )
    if not ((S_z is None and E_z is None) or (S_z < E_z)):
        raise InputError(
            'cashocs.geometry.regular_box_mesh', 'S_z',
            'Incorrect input for the z-coordinate. S_z has to be smaller than E_z, or only one of them is specified.'
        )

    if S_z is None:
        lx = E_x - S_x
        ly = E_y - S_y
        sizes = [lx, ly]
        dim = 2
    else:
        lx = E_x - S_x
        ly = E_y - S_y
        lz = E_z - S_z
        sizes = [lx, ly, lz]
        dim = 3

    size_min = np.min(sizes)
    num_points = [int(np.round(length / size_min * n)) for length in sizes]

    if S_z is None:
        mesh = fenics.RectangleMesh(fenics.Point(S_x, S_y),
                                    fenics.Point(E_x, E_y), num_points[0],
                                    num_points[1])
    else:
        mesh = fenics.BoxMesh(fenics.Point(S_x, S_y, S_z),
                              fenics.Point(E_x, E_y, E_z), num_points[0],
                              num_points[1], num_points[2])

    subdomains = fenics.MeshFunction('size_t', mesh, dim=dim)
    boundaries = fenics.MeshFunction('size_t', mesh, dim=dim - 1)

    x_min = fenics.CompiledSubDomain('on_boundary && near(x[0], sx, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     sx=S_x)
    x_max = fenics.CompiledSubDomain('on_boundary && near(x[0], ex, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     ex=E_x)
    x_min.mark(boundaries, 1)
    x_max.mark(boundaries, 2)

    y_min = fenics.CompiledSubDomain('on_boundary && near(x[1], sy, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     sy=S_y)
    y_max = fenics.CompiledSubDomain('on_boundary && near(x[1], ey, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     ey=E_y)
    y_min.mark(boundaries, 3)
    y_max.mark(boundaries, 4)

    if S_z is not None:
        z_min = fenics.CompiledSubDomain('on_boundary && near(x[2], sz, tol)',
                                         tol=fenics.DOLFIN_EPS,
                                         sz=S_z)
        z_max = fenics.CompiledSubDomain('on_boundary && near(x[2], ez, tol)',
                                         tol=fenics.DOLFIN_EPS,
                                         ez=E_z)
        z_min.mark(boundaries, 5)
        z_max.mark(boundaries, 6)

    dx = fenics.Measure('dx', mesh, subdomain_data=subdomains)
    ds = fenics.Measure('ds', mesh, subdomain_data=boundaries)
    dS = fenics.Measure('dS', mesh)

    return mesh, subdomains, boundaries, dx, ds, dS
示例#5
0
def regular_mesh(n=10, L_x=1.0, L_y=1.0, L_z=None):
    r"""Creates a mesh corresponding to a rectangle or cube.

	This function creates a uniform mesh of either a rectangle
	or a cube, starting at the origin and having length specified
	in ``L_x``, ``L_y``, and ``L_z``. The resulting mesh uses ``n`` elements along the
	shortest direction and accordingly many along the longer ones.
	The resulting domain is

	.. math::
		\begin{alignedat}{2}
		&[0, L_x] \times [0, L_y] \quad &&\text{ in } 2D, \\
		&[0, L_x] \times [0, L_y] \times [0, L_z] \quad &&\text{ in } 3D.
		\end{alignedat}

	The boundary markers are ordered as follows:

	  - 1 corresponds to :math:`x=0`.

	  - 2 corresponds to :math:`x=L_x`.

	  - 3 corresponds to :math:`y=0`.

	  - 4 corresponds to :math:`y=L_y`.

	  - 5 corresponds to :math:`z=0` (only in 3D).

	  - 6 corresponds to :math:`z=L_z` (only in 3D).

	Parameters
	----------
	n : int
		Number of elements in the shortest coordinate direction.
	L_x : float
		Length in x-direction.
	L_y : float
		Length in y-direction.
	L_z : float or None, optional
		Length in z-direction, if this is ``None``, then the geometry
		will be two-dimensional (default is ``None``).

	Returns
	-------
	mesh : dolfin.cpp.mesh.Mesh
		The computational mesh.
	subdomains : dolfin.cpp.mesh.MeshFunctionSizet
		A :py:class:`fenics.MeshFunction` object containing the subdomains.
	boundaries : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the boundaries.
	dx : ufl.measure.Measure
		The volume measure of the mesh corresponding to subdomains.
	ds : ufl.measure.Measure
		The surface measure of the mesh corresponding to boundaries.
	dS : ufl.measure.Measure
		The interior facet measure of the mesh corresponding to boundaries.
	"""
    if not n > 0:
        raise InputError('cashocs.geometry.regular_mesh', 'n',
                         'This needs to be positive.')
    if not L_x > 0.0:
        raise InputError('cashocs.geometry.regular_mesh', 'L_x',
                         'L_x needs to be positive')
    if not L_y > 0.0:
        raise InputError('cashocs.geometry.regular_mesh', 'L_y',
                         'L_y needs to be positive')
    if not (L_z is None or L_z > 0.0):
        raise InputError('cashocs.geometry.regular_mesh', 'L_z',
                         'L_z needs to be positive or None (for 2D mesh)')

    n = int(n)

    if L_z is None:
        sizes = [L_x, L_y]
        dim = 2
    else:
        sizes = [L_x, L_y, L_z]
        dim = 3

    size_min = np.min(sizes)
    num_points = [int(np.round(length / size_min * n)) for length in sizes]

    if L_z is None:
        mesh = fenics.RectangleMesh(fenics.Point(0, 0), fenics.Point(sizes),
                                    num_points[0], num_points[1])
    else:
        mesh = fenics.BoxMesh(fenics.Point(0, 0, 0), fenics.Point(sizes),
                              num_points[0], num_points[1], num_points[2])

    subdomains = fenics.MeshFunction('size_t', mesh, dim=dim)
    boundaries = fenics.MeshFunction('size_t', mesh, dim=dim - 1)

    x_min = fenics.CompiledSubDomain('on_boundary && near(x[0], 0, tol)',
                                     tol=fenics.DOLFIN_EPS)
    x_max = fenics.CompiledSubDomain('on_boundary && near(x[0], length, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     length=sizes[0])
    x_min.mark(boundaries, 1)
    x_max.mark(boundaries, 2)

    y_min = fenics.CompiledSubDomain('on_boundary && near(x[1], 0, tol)',
                                     tol=fenics.DOLFIN_EPS)
    y_max = fenics.CompiledSubDomain('on_boundary && near(x[1], length, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     length=sizes[1])
    y_min.mark(boundaries, 3)
    y_max.mark(boundaries, 4)

    if L_z is not None:
        z_min = fenics.CompiledSubDomain('on_boundary && near(x[2], 0, tol)',
                                         tol=fenics.DOLFIN_EPS)
        z_max = fenics.CompiledSubDomain(
            'on_boundary && near(x[2], length, tol)',
            tol=fenics.DOLFIN_EPS,
            length=sizes[2])
        z_min.mark(boundaries, 5)
        z_max.mark(boundaries, 6)

    dx = fenics.Measure('dx', mesh, subdomain_data=subdomains)
    ds = fenics.Measure('ds', mesh, subdomain_data=boundaries)
    dS = fenics.Measure('dS', mesh)

    return mesh, subdomains, boundaries, dx, ds, dS
示例#6
0
# Dirichlet data
u_g = fn.Constant((0.0, 0.0))
p_g = fn.Constant(0.0)

h_g = fn.Constant((0.0, -sigma0))


def strain(v):
    return fn.sym(fn.grad(v))


# boundary conditions
bdry = fn.MeshFunction("size_t", mesh, 1)

bdry.set_all(0)
FooT = fn.CompiledSubDomain(
    "(x[0] >= -0.2) && (x[0] <= 0.2) && near(x[1], 0.75) && on_boundary")
GammaU = fn.CompiledSubDomain(
    "( near(x[0], -0.5) || near(x[1], 0.0) ) && on_boundary")
GammaU.mark(bdry, 31)
FooT.mark(bdry, 32)
ds = fn.Measure("ds", subdomain_data=bdry)

bcU = fn.DirichletBC(Hh.sub(0), u_g, bdry, 31)
bcP = fn.DirichletBC(Hh.sub(2), p_g, bdry, 32)
bcs = [bcU, bcP]

# ********  Weak forms ********** #

PLeft =  2*mu*fn.inner(strain(u),strain(v)) * fn.dx \
         - fn.div(v) * phi * fn.dx \
         + (c0/alpha + 1.0/lmbda)* p * q * fn.dx \
示例#7
0
from jaxfenics_adjoint import build_jax_fem_eval
from jaxfenics_adjoint import from_numpy

import matplotlib.pyplot as plt

config.update("jax_enable_x64", True)
fn.set_log_level(fn.LogLevel.ERROR)

# Create mesh, refined in the center
n = 64
mesh = fn.UnitSquareMesh(n, n)

cf = fn.MeshFunction("bool", mesh, mesh.geometry().dim())
subdomain = fn.CompiledSubDomain(
    "std::abs(x[0]-0.5) < 0.25 && std::abs(x[1]-0.5) < 0.25"
)
subdomain.mark(cf, True)
mesh = fa.Mesh(fn.refine(mesh, cf))

# Define discrete function spaces and functions
V = fn.FunctionSpace(mesh, "CG", 1)
W = fn.FunctionSpace(mesh, "DG", 0)

solve_templates = (fa.Function(W),)
assemble_templates = (fa.Function(V), fa.Function(W))

# Define and solve the Poisson equation
@build_jax_fem_eval(solve_templates)
def fenics_solve(f):
    u = fa.Function(V, name="State")
示例#8
0
# dirichlet data
u_g = fn.Constant((0.0, 0.0, 0.0))
p_g = fn.Constant(0.0)

h_g = fn.Constant((0.0, -sigma_0, 0.0))

# symmetric strain tensor
def strain(v):
    return fn.sym(fn.grad(v))

# boundary and boundary conditions
bdry = fn.MeshFunctionSizet(mesh, 2)

bdry.set_all(0)
FooT = fn.CompiledSubDomain(
        "sqrt(x[0]*x[0] + x[2]*x[2]) >= -0.4*L &&" +
        "sqrt(x[0]*x[0] + x[2]*x[2]) <=  0.4*L &&" +
        "near(x[1], 2*L) && on_boundary", L=L)
GammaU = fn.CompiledSubDomain(
        "(near(x[0], -L) || near(x[0], L) ||" +
        " near(x[2], -L) || near(x[2], L) ||" +
        " near(x[1], 0.0)) && on_boundary", L=L)
GammaU.mark(bdry, 31)
FooT.mark(bdry, 32)
fn.ds = fn.Measure("ds", subdomain_data=bdry)

bcU = fn.DirichletBC(Hh.sub(0), u_g, bdry, 31)
bcP = fn.DirichletBC(Hh.sub(2), p_g, bdry, 32)
bcs = [bcU, bcP]

# weak forms
PLeft = 2*mu*fn.inner(strain(u), strain(v)) * fn.dx \
                       - (1.0 - heaviside(E - En)) * n)

def RD_f(E, n):
    return 1.0/tauE * (-E + (Estar - pow(n, M)) \
                       * (1.0 - fn.tanh(E - Eh)) * pow(E, 2) * 0.5)

def D(E, sigma):  # this is important: it's where the coupling occurs
    return fn.Identity(2) * D0 * (1 + D0*E) + pow(D0, 2) * sigma

# boundaries
mesh_boundary = fn.MeshFunctionSizet(mesh, 1)
mesh_boundary.set_all(0)

# section of boundary that is free
free_boundary = fn.CompiledSubDomain(
        "(near(x[1], mesh_height) || near(x[0], mesh_width/2)) && on_boundary",
        mesh_height=mesh_height, mesh_width=mesh_width)

# section of boundary that is a rigid wall
wall_boundary = fn.CompiledSubDomain(
        "(near(x[1], 0.0) || near(x[0], -mesh_width/2)) && on_boundary",
        mesh_width=mesh_width)

# mark boundaries
free_boundary.mark(mesh_boundary, 31)
wall_boundary.mark(mesh_boundary, 32)

# ds, for integrating
ds = fn.Measure("ds", subdomain_data=mesh_boundary)

# boundary conditions
    def compute_static_deformation(self):

        assert self.mesh is not None

        # now we define subdomains on the mesh

        bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary')
        top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary')
        # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7')

        # Initialize mesh function for interior domains
        self.domains = fe.MeshFunction('size_t', self.mesh, 3)
        self.domains.set_all(0)
        # middle.mark(self.domains, 1)

        # Initialize mesh function for boundary domains
        self.boundaries = fe.MeshFunction('size_t', self.mesh, 2)
        self.boundaries.set_all(0)
        bottom.mark(self.boundaries, 1)
        top.mark(self.boundaries, 2)

        # Define new measures associated with the interior domains and
        # exterior boundaries

        self.dx = fe.Measure('dx',
                             domain=self.mesh,
                             subdomain_data=self.domains)
        self.ds = fe.Measure('ds',
                             domain=self.mesh,
                             subdomain_data=self.boundaries)

        # define function spaces
        V = fe.VectorFunctionSpace(self.mesh, "Lagrange", 1)
        # now we define subdomains on the mesh

        bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary')
        top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary')
        # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7')

        d = self.mesh.geometry().dim()

        # Initialize mesh function for interior domains
        self.domains = fe.MeshFunction('size_t', self.mesh, d)
        self.domains.set_all(0)
        # middle.mark(self.domains, 1)

        # Initialize mesh function for boundary domains
        self.boundaries = fe.MeshFunction('size_t', self.mesh, d - 1)
        self.boundaries.set_all(0)
        bottom.mark(self.boundaries, 1)
        top.mark(self.boundaries, 2)

        # Define new measures associated with the interior domains and
        # exterior boundaries

        self.dx = fe.Measure('dx',
                             domain=self.mesh,
                             subdomain_data=self.domains)
        self.ds = fe.Measure('ds',
                             domain=self.mesh,
                             subdomain_data=self.boundaries)

        c_zero = fe.Constant((0, 0, 0))

        # define boundary conditions
        bc_bottom = fe.DirichletBC(V, c_zero, bottom)
        bc_top = fe.DirichletBC(V, c_zero, top)

        bcs = [bc_bottom]  # , bc_top]

        # define functions
        du = TrialFunction(V)
        v = TestFunction(V)
        u = Function(V)
        B = fe.Constant((0., 2.0, 0.))
        T = fe.Constant((0.0, 0.0, 0.0))

        d = u.geometric_dimension()
        I = fe.Identity(d)
        F = I + grad(u)
        C = F.T * F

        I_1 = tr(C)
        J = det(F)

        E, mu = 10., 0.3
        mu, lmbda = fe.Constant(E / (2 * (1 + mu))), fe.Constant(
            E * mu / ((1 + mu) * (1 - 2 * mu)))

        # stored energy (comp. neo-hookean model)
        psi = (mu / 2.) * (I_1 - 3) - mu * fe.ln(J) + (lmbda /
                                                       2.) * (fe.ln(J))**2

        dx = self.dx
        ds = self.ds

        Pi = psi * fe.dx - dot(B, u) * fe.dx - dot(T, u) * fe.ds

        F = fe.derivative(Pi, u, v)
        J = fe.derivative(F, u, du)

        fe.solve(F == 0, u, bcs, J=J)

        # save results
        self.u = u

        # write to disk
        output = fe.File("/tmp/static.pvd")
        output << u
def vocal_tract_solver_backward(f_data, g_data, c_sound, length, Nx,
                                basis_degree, T, num_tsteps, iteration):
    """
    TODO
    """
    # f expression
    f_cppcode = """
    #include <iostream>
    #include <cmath>
    #include <pybind11/pybind11.h>
    #include <pybind11/eigen.h>
    #include <dolfin/function/Expression.h>

    class FExpress: public dolfin::Expression {
      public:
        int t_idx;  // time index
        double DX;  // length of uniformly spaced cell
        Eigen::MatrixXd array;  // external data

        // Constructor
        FExpress() : dolfin::Expression(1), t_idx(0) { }

        // Overload: evaluate at given point in given cell
        void eval(Eigen::Ref<Eigen::VectorXd> values,
                  Eigen::Ref<const Eigen::VectorXd> x) const {
          // values: values at the point
          // x: coordinates of the point
          int x_idx = std::round(x(0) / DX);  // spatial index
          values(0) = array(t_idx, x_idx);
        }
    };

    // Binding FExpress
    PYBIND11_MODULE(SIGNATURE, m) {
      pybind11::class_<FExpress, std::shared_ptr<FExpress>, dolfin::Expression>
      (m, "FExpress")
      .def(pybind11::init<>())
      .def_readwrite("t_idx", &FExpress::t_idx)
      .def_readwrite("DX", &FExpress::DX)
      .def_readwrite("array", &FExpress::array)
      ;
    }
    """
    f_expr = dolfin.compile_cpp_code(f_cppcode).FExpress()
    f = dolfin.CompiledExpression(f_expr, degree=basis_degree + 2)
    f.array = f_data
    f.t_idx = 0
    f.DX = 1.0 / (Nx * basis_degree)

    # Initial expression
    u_I = F.Constant(0.0)

    # Neumann boundary expression
    g_cppcode = """
    #include <pybind11/pybind11.h>
    #include <pybind11/eigen.h>
    #include <dolfin/function/Expression.h>

    class GExpress: public dolfin::Expression {
      public:
        int idx;  // time-dependent index
        Eigen::VectorXd array;  // external data

        // Constructor
        GExpress() : dolfin::Expression(1), idx(0) { }

        // Overload: evaluate at given point in given cell
        void eval(Eigen::Ref<Eigen::VectorXd> values,
                  Eigen::Ref<const Eigen::VectorXd> x) const {
          // values: values at the point
          // x: coordinates of the point
          values(0) = array(idx);
        }
    };

    // Binding GExpress
    PYBIND11_MODULE(SIGNATURE, m) {
      pybind11::class_<GExpress, std::shared_ptr<GExpress>, dolfin::Expression>
      (m, "GExpress")
      .def(pybind11::init<>())
      .def_readwrite("idx", &GExpress::idx)
      .def_readwrite("array", &GExpress::array)
      ;
    }
    """
    g_expr = dolfin.compile_cpp_code(g_cppcode).GExpress()
    g = dolfin.CompiledExpression(g_expr, degree=basis_degree + 2)
    g.array = g_data

    subboundary_L = F.CompiledSubDomain(
        "on_boundary && near(x[0], length, tol)", length=length,
        tol=1e-14)  # boundary @ L

    # Solve
    boundary_conditions = {1: {"Neumann": g}, "subboundary": subboundary_L}
    divisions = (Nx, )
    dt = T / num_tsteps  # time step size
    U_k = pde_solver_backward(
        f,
        boundary_conditions,
        u_I,
        c_sound,
        divisions,
        T,
        dt,
        num_tsteps,
        initial_method="project",
        degree=basis_degree,
        iteration=iteration,
    )
    return U_k
示例#12
0
p_g = fn.Constant(0.0)

h_g = fn.Constant((0.0, -sigma0))


def strain(v):
    return fn.sym(fn.grad(v))


# boundary conditions
bdry = fn.MeshFunction("size_t", mesh, 1)

bdry.set_all(0)

# foot boundary
FooT = fn.CompiledSubDomain(
    "x[0]>= -0.4*L && x[0] <= 0.4*L && near(x[1],75.0) && on_boundary", L=L)
GammaU = fn.CompiledSubDomain(
    "(near(x[0],-50.0) || near(x[1],0.0) || near(x[0],50.0) ) && on_boundary")
GammaU.mark(bdry, 31)
FooT.mark(bdry, 32)
ds = fn.Measure("ds", subdomain_data=bdry)

bcU = fn.DirichletBC(Hh.sub(0), u_g, bdry, 31)
bcP = fn.DirichletBC(Hh.sub(2), p_g, bdry, 32)
bcs = [bcU, bcP]

# weak forms
PLeft =  2*mu*fn.inner(strain(u),strain(v)) * fn.dx \
         - fn.div(v) * phi * fn.dx \
         + (c0/alpha + 1.0/lmbda)* p * q * fn.dx \
         + kappa/(alpha*nu) * fn.dot(fn.grad(p),fn.grad(q)) * fn.dx \
# dirichlet boundary conditions
u_g = fn.Constant((0.0, 0.0))  # 0 displacement on walls
p_g = fn.Constant(0.0)  # 0 pressure on free surface
h_g = fn.Expression(("0","-sigma0*t"), sigma0=sigma0, t=0.0, degree=3)

# symmetric strain tensor
def strain(u):
    return fn.sym(fn.grad(u))

# boundaries
mesh_boundary = fn.MeshFunctionSizet(mesh, 1)
mesh_boundary.set_all(0)

# section of boundary on which foot presses
foot_boundary = fn.CompiledSubDomain(
        "(x[0] >= -foot_width/2) && (x[0] <= foot_width/2)" +
        "&& near(x[1], mesh_height) && on_boundary",
        foot_width=foot_width, mesh_height=mesh_height)

pressure_boundary = fn.CompiledSubDomain(
        "((x[0] < -foot_width/2) || (x[0] > foot_width/2))" +
        "&& near(x[1], mesh_height) && on_boundary",
        foot_width=foot_width, mesh_height=mesh_height)

# section of boundary that is a rigid wall
wall_boundary = fn.CompiledSubDomain(
        "(near(x[0], -mesh_width/2) || near(x[0], mesh_width/2)" +
        "|| near(x[1], 0.0)) && on_boundary",
        mesh_width=mesh_width)

# mark boundaries
foot_boundary.mark(mesh_boundary, 31)