Explicitly Defining Regions

question.edp (4.9 KB)

Hello FreeFem++ community,

I’m working on a problem that involves a complex 2D geometry, and I need to define and extract specific regions (subdomains) from the generated mesh for further processing.

I have defined several borders, including an outer circle, two inner circles, two tangent lines connecting the inner circles, and two rectangles inside the inner circles. My current code builds the mesh using these borders.

While the buildmesh command generates a mesh, I’m unsure how to explicitly define and assign unique region numbers to the 2D areas enclosed by these borders, or combinations of them. For example, I would like to define the following distinct regions:

  1. The area outside innerCircle1 and innerCircle2 but inside outerCircle, and potentially bounded by the tangent lines.
  2. The area inside innerCircle1 but outside rect1.
  3. The area inside rect1.
  4. The area inside innerCircle2 but outside rect2.
  5. The area inside rect2.
  6. The area between the two tangent lines, outside both inner circles (if distinct from region 1).

What is the best approach in FreeFem++ to achieve this? Should I modify the buildmesh command, use specific region keywords, or are there other techniques that would be more suitable for defining these complex subdomains?

Any guidance or examples on how to properly define and access these regions would be greatly appreciated!

Thank you in advance for your help.

Hello,
First, your construction does not give a mesh inside your rectangles. This is because the boundaries of these rectangles are oriented clockwise. If you want to have these rectangles meshed you need to put the orientation of these boundaries anticlockwise.
Then in order to have also a mesh within the circles you need also to change the orientation of the two circles.

By default, freefem gives a different region number in each region surrounded by borders. In order to get a region number you can do

real xpos= .5*(rect1X1+rect1X2);
real ypos= .5*(rect1Y2+rect1Y3);
cout << "region rect1 " << Th(xpos, ypos).region << endl;

This gives the region of the point of coordinates (xpos,ypos) (here the center of rectangle 1).
By choosing a point in each of your regions, by the previous method you can get all the region numbers.
Then if you like you can use change to modify these values.
For example
int[int] reglabs=[4,1,0,2];
Th=change(Th,region=reglabs);
changes the region label 4 to 1, and the region label 0 to 2 (see the Freefem documentation).
You can put as many couples of integers that you want in the list reglabs.
If you want to “unify” two regions in a single one, you can give them the same label.

Hello,

Thank you for your detailed explanation.

I’m using the Th(x, y).region command to identify region numbers at specific points, which is helpful. However, my main goal is to define the regions myself explicitly using borders, rather than relying on the default automatic region assignment.

The issue I’m currently facing is that I’m unable to define a specific region—the area between the two tangent lines and outside both inner circles. This area is currently being considered as part of the outer circle’s region, but I would like it to be a distinct region with its own label.

Is there a way to define such a region manually using borders and ensure it gets its own unique region label, even if it’s not fully enclosed by a single closed border?

There is no safe way to define a region which is not enclosed by borders. But it is not necessary that the border of your desired region is defined by a single command border, it can be pieces of several border commands. Thus in you case freefem should normally detect that your region is disconnected from the outside region, and give a different region number to it.

However it does not detect it, this is probably due to the fact that the two “tangent lines” do not connect correctly to the two circles (there is probably a gap).

The problem is that even if your define correctly the intersection point, when the boundaries of the circles are discretized (freefem takes vertices on these borders and joins them to build the discrete boundary) the end of the tangent lines does not coincide with one of the chosen vertices.

A solution is to define each circle by several bordercommands instead of one.

Each piece has to be a part of the circle between points that you want to fix. Then the discretization will be forced to have these points as vertices.

For the circle 1 you have to fix the two lower and uper intersection points, and the intersection with circle 2.

For circle 2 you have to fixe the two lower and upper itersection points, and the left and right intersections with circle 1 and the outer circle.

This gives

// Borders of Circles
border outerCircle(t=0,2*pi){x=cos(t);y=sin(t);label=1;}
//border innerCircle1(t=0,2*pi){x=c1x+r1*cos(t);y=c1y+r1*sin(t);label=2;}
//border innerCircle2(t=0,2*pi){x=c2x+r2*cos(t);y=c2y+r2*sin(t);label=2;}
real t1Up=atan2((p1UpY-c1y)/r1,(p1UpX-c1x)/r1);
real t1Down=atan2((p1DownY-c1y)/r1,(p1DownX-c1x)/r1);
border innerCircle1lup(t=t1Up,pi){x=c1x+r1*cos(t);y=c1y+r1*sin(t);label=2;}
border innerCircle1ldown(t=-pi,t1Down){x=c1x+r1*cos(t);y=c1y+r1*sin(t);label=2;}
border innerCircle1r(t=t1Down,t1Up){x=c1x+r1*cos(t);y=c1y+r1*sin(t);label=2;}
real t2Up=atan2((p2UpY-c2y)/r2,(p2UpX-c2x)/r2);
real t2Down=atan2((p2DownY-c2y)/r2,(p2DownX-c2x)/r2);
border innerCircle2lup(t=t2Up,pi){x=c2x+r2*cos(t);y=c2y+r2*sin(t);label=2;}
border innerCircle2ldown(t=-pi,t2Down){x=c2x+r2*cos(t);y=c2y+r2*sin(t);label=2;}
border innerCircle2rdown(t=t2Down,0.){x=c2x+r2*cos(t);y=c2y+r2*sin(t);label=2;}
border innerCircle2rup(t=0.,t2Up){x=c2x+r2*cos(t);y=c2y+r2*sin(t);label=2;}

Then you use in buildmesh

outerCircle(50)
+ innerCircle1lup(-10) + innerCircle1ldown(-10)
+ innerCircle1r(-20)
+ innerCircle2lup(-8)+ innerCircle2ldown(-8)
+ innerCircle2rup(-8) + innerCircle2rdown(-8)