This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Using multiple scales for node-spacing in mshr.generate_mesh? (EDITED)

0 votes

I'd like to build a mesh of a 2d rectangle that contains a small circle. I'd like the node-spacing along the circle to be fine, where the node-spacing along the boundary of the rectangle to be sparse. Currently, I can only seem to send one spacing parameter to generate_mesh:

from dolfin import *
from mshr import *

cx, cy, radius = 0.5, 0.5, 0.1
lx, ly = 1.0, 1.0
RESOLUTION = 20
class circle(SubDomain):
    def inside(self, x, on_boundary):
        return pow(x[0] - cx, 2) + pow(x[1] - cy, 2) <= pow(radius, 2) + DOLFIN_EPS

# Define 2D geometry
domain1 = Rectangle(Point(0.0, 0.0), Point(lx, ly))
domain2 = Circle(Point(cx,cy),radius)
domain = domain1 - domain2
mesh = generate_mesh(domain, RESOLUTION)

I'd like to be able to pass two (or more) values for the resolution parameter, if possible? One for each domain?

EDIT:

I'm noticing the following quirk:

Let's say I want to compute a path integral about my circle (which, incidentally, why I'd like to increase the resolution). Simply refining the mesh doesn't seem to improve the accuracy.
Example: The circumference of the circle in this example is 2*pi / 10 ~ 0.6283185307179586.

When I compute the following path integration:

markers = FacetFunctionSizet(mesh, 0)
ds = ds[markers]
circle().mark(markers,1)
form = 1*ds(1,domain=mesh)
ans = assemble(form)
print(ans)

Which returns: 0.627309698109

Increasing the RESOLUTION from 20 to 100 does not improve this answer at all. I'm a little vexxed by this, so any guidance would be greatly appreciated.

asked Jul 28, 2016 by qwetico FEniCS Novice (360 points)
edited Jul 28, 2016 by qwetico

1 Answer

+1 vote
 
Best answer

The reason you're experiencing this issue is because Circle does not represent a "perfect" circle. By default, it represents an approximation with 32 segments. Using a finer resolution will only increase the number of points around this approximation, and not increase the resolution of the actual circle, which is why your answer isn't improving.

There is an optional third argument to Circle which you can increase to increase the accuracy of the approximation. Note that regardless of RESOLUTION, mshr will always create a mesh such that the geometry of this circle is maintained (try setting RESOLUTION = 1 to see this).

Thus regarding your initial question, you can do something like this to achieve what you want:

from dolfin import *
from mshr import *

cx, cy, radius = 0.5, 0.5, 0.1
lx, ly = 1.0, 1.0
RESOLUTION = 20
SEGMENTS = 100
domain1 = Rectangle(Point(0.0, 0.0), Point(lx, ly))
domain2 = Circle(Point(cx,cy),radius, SEGMENTS)
domain = domain1 - domain2
mesh = generate_mesh(domain, RESOLUTION)
plot(mesh) 
interactive()

You should see that this mesh results in a better answer.

As a side note, if you ever need to vary mesh resolution in a more complex way (e.g. the top half of the circle better resolved than the bottom half, or something like that), I would recommend gmsh, which seems to have more fine-grained control over mesh resolution compared to mshr.

answered Jul 29, 2016 by FF FEniCS User (4,630 points)
selected Jul 29, 2016 by qwetico

Thank you, this seems to sort the problem out.

...