Problem assigning vertices to sub-domain/boundary

With Dolfin version 2019.1.0 I in the Docker environment, I experience problems with correctly assigning mesh vertices to a sub-domain. It seems the edges get assigned all-right. But whether I use dolfin.RectangleMesh or mshr.Rectangle, a lot of boundary vertices clearly matching my criteria do not get assigned the marked correctly.

The MWEs below should produce a rectangular domain and assign a MeshFunction value of 1 to all elements on the outer boundaries of the domain while the inside should be assigned 0. Both vertices and edges seem to be affected, but vertices show this problem much more often (you’ll barely spot the affected edges at first glance).

Here’s my MWE for dolfin.RectangleMesh:

import mshr
import dolfin as do
import fenics as fe
import numpy as np
import matplotlib.pyplot as plt

print(do.__version__)

X, Y = 7e-3, 3.5e-3
mesh = do.RectangleMesh(do.Point(0,0), do.Point(X,Y), 20, 10)
do.plot(mesh)

FE = do.FiniteElement("P", mesh.ufl_cell(), 1)
FS = do.FunctionSpace(mesh, FE)

sub_domains = do.MeshFunction("size_t", mesh, mesh.topology().dim()-1, 0)
sub_domains.set_all(0)

class thePEC(do.SubDomain):
    def inside(self, x, on_boundary):
        val = do.near(x[0], 0.) | do.near(x[0], X) | do.near(x[1], 0.) | do.near(x[1], Y) # & on_boundary
        return val

outerwall = thePEC()
outerwall.mark(sub_domains, 1)

bcs = [
    do.DirichletBC(FS, do.Constant(0.0), sub_domains, 1),
    ]

do.File("bcs2.pvd") << sub_domains

Here’s my MWE for mshr.Rectangle:

import mshr
import dolfin as do
import fenics as fe
import numpy as np
import matplotlib.pyplot as plt

print(do.__version__)

X, Y = 7e-3, 3.5e-3
dom = mshr.Rectangle(do.Point(0,0), do.Point(X, Y))
mesh = mshr.generate_mesh(dom, 20)
do.plot(mesh)

FE = do.FiniteElement("P", mesh.ufl_cell(), 1)
FS = do.FunctionSpace(mesh, FE)

sub_domains = do.MeshFunction("size_t", mesh, mesh.topology().dim()-1, 0)
sub_domains.set_all(0)

class thePEC(do.SubDomain):
    def inside(self, x, on_boundary):
        val = do.near(x[0], 0.) | do.near(x[0], X) | do.near(x[1], 0.) | do.near(x[1], Y) # & on_boundary
        return val

outerwall = thePEC()
outerwall.mark(sub_domains, 1)

bcs = [
    do.DirichletBC(FS, do.Constant(0.0), sub_domains, 1),
    ]

do.File("bcs1.pvd") << sub_domains

Checking the output files (bcs1.pvd and bcs2.pvd) against each other e.g. using “Representation: Points” in Paraview reveals the problem.

It seems when using a circle things work better…

Any ideas?

I cannot reproduce the behavior with the following image:

docker run -ti -v $(pwd):/home/fenics/shared -w /home/fenics/shared --rm quay.io/fenicsproject/stable:2019.1.0.r3

where I ran:

import mshr
import dolfin as do
import fenics as fe
import numpy as np
import matplotlib.pyplot as plt

print(do.__version__)

X, Y = 7e-3, 3.5e-3
dom = mshr.Rectangle(do.Point(0,0), do.Point(X, Y))
mesh = mshr.generate_mesh(dom, 20)

sub_domains = do.MeshFunction("size_t", mesh, mesh.topology().dim()-1, 0)
sub_domains.set_all(0)

class thePEC(do.SubDomain):
    def inside(self, x, on_boundary):
        val = do.near(x[0], 0.) | do.near(x[0], X) | do.near(x[1], 0.) | do.near(x[1], Y) # & on_boundary
        return val

outerwall = thePEC()
outerwall.mark(sub_domains, 1)

do.File("bcs1.pvd") << sub_domains

which produced:

Ah, that’s an interesting finding. I’m using the latest tag (probably from some example I found). Here’s my Dockerfile, just for info. I’m currently re-building it with stable:2019.1.0.r3.

FROM quay.io/fenicsproject/stable:latest
USER root
RUN apt-get -qq update && \
    apt-get -y upgrade && \
    apt-get -y install python3-pip && \
    apt-get -y install python3-lxml python3-h5py && \
    apt-get -y install libcgal-dev libeigen3-dev && \
    apt-get -y install libglu1-mesa libxinerama1 libxcursor1 && \
    apt autoremove && \
    apt-get clean
RUN pip3 install --upgrade pip && \
    pip3 install -U numpy mpi4py && \
    pip3 install -U scipy lxml pygmsh matplotlib tabulate pandas sympy scikit-rf && \
    pip3 install meshio petsc==3.12 slepc==3.12 && \
    pip3 install petsc4py slepc4py && \
    pip3 install --no-binary=h5py h5py && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp*
COPY gmsh-stable-Linux64-sdk.tgz .
# RUN wget https://gmsh.info/bin/Linux/gmsh-stable-Linux64.tgz && \
RUN tar tfz gmsh-stable-Linux64-sdk.tgz | head
RUN tar xfz gmsh-stable-Linux64-sdk.tgz --directory /opt && \
    mv /opt/gmsh-*-Linux64*/ /opt/gmsh
RUN rm /usr/local/bin/gmsh || true
RUN ln -s /opt/gmsh/bin/gmsh /usr/local/bin/gmsh
RUN pip3 install pygmsh
RUN echo "\n\nimport sys\nsys.path.append('/opt/gmsh/lib/')" >> /etc/python3.6/sitecustomize.py
RUN cat /etc/python3.6/sitecustomize.py
RUN python3 -c "import gmsh; print(gmsh.__version__)"
RUN sed -i "s/ax.set_aspect('equal')/# ax.set_aspect('equal')/g" /usr/local/lib/python3.6/dist-packages/dolfin/common/plotting.py
USER root

Maybe changing this solves it already…

I do not observe the behavior with stable/latest. make sure you do a docker pull quay.io/fenicsproject/stable:latest before rebuilding the docker image, to make sure you have the latest version.

It is also quite dangerous to install petsc on top of the existing image (as dolfin is built with its own petsc version).

Could you first try running the commands I gave you to make sure you can reproduce it?

I had to add import mshr to your script but otherwise all ran without errors (using ipython in docker run -ti -v $(pwd):/home/fenics/shared -w /home/fenics/shared --rm quay.io/fenicsproject/stable:2019.1.0.r3).
Edges look fine, but if I switch to “Representation: Points”, it shows me this…

See the scattered red dots?
Can you check that view in your case?

Why would you try to represent edges/facets as points ? If a vertex is connected to facets of multiple values, it is not clear what color it should have. If you want to store vertex data, create a mesh function of dimension 0 and apply the marker.

I’ve had issues with applying boundary conditions. The initial problem was with a mixed function space like

FE_t = do.FiniteElement("RTE", mesh.ufl_cell(), 1)
FE_z = do.FiniteElement("P", mesh.ufl_cell(), 1)
ME = do.MixedElement(FE_t, FE_z)
FS = do.FunctionSpace(mesh, ME)

where my solution always showed weird behaviour. Upon further investigation I figured that the FE_z might be to blame as (edit: I think) it lives on the vertices and they don’t seem to have the BC values applied.