Recursively defined geometrical structures may be useful in engineering applications such as broadband antennas and metamaterials, to mention a few. For a brief overview of some applications, check out a previous blog post on fractals. In this blog post, we will take a look at how to quickly generate such geometry objects by algorithmic means.

### Using Methods and the Application Builder for Recursively Defined Geometry Objects

You can use the Method Editor in the Application Builder for creating methods that perform almost any type of modeling task, including geometry modeling. It is easy to miss the fact that methods can support recursion by having a method calling itself in a recursive loop.

Here, we will demonstrate recursion by two famous examples of recursive structures: a Sierpinski carpet in 2D and a Menger sponge in 3D. The code for these examples are short enough so that we can list them in full, and there are links to download these examples at the end of the post.

### Sierpinski Carpet

The following method, *create_carpet*, runs the recursion to a certain recursive level according to an input parameter *level*. It sets a limit at 5 levels in order to avoid creating an exceedingly large geometry. (You can change this if you think your computer can handle it.)

if (level < 1) error("Carpet level needs to be at least 1."); if (level > 5) error("Carpet level needs to be at most 5."); counter = 0; model.component("comp1").geom("geom1").feature().clear(); model.component("comp1").geom("geom1").autoRebuild("off"); double cx0 = 0, cy0 = 0; double si0 = 1; carpet(level, cx0, cy0, si0); model.component("comp1").geom("geom1").runPre("fin");

The input argument *level* is defined in the method’s *Settings* window, as shown below.

The method *create_carpet*, in turn, calls the main recursive function *carpet*, listed below, using four input arguments for the recursion level, the center *x-* and *y*-coordinates, and the current side length.

The input arguments are defined in the method’s *Settings* window, as shown below.

This is the code for the method *carpet*:

int l = level; double posx, posy, si1; String strix; int l1; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { posx = cx+i*si-si; posy = cy+j*si-si; strix = toString(i)+toString(j); if ((Math.abs((i-1))+Math.abs((j-1))) > 0) { if (l == 1) { counter = counter+1; model.component("comp1").geom("geom1").create("sq"+strix+"C"+toString(counter), "Square"); with(model.component("comp1").geom("geom1").feature("sq"+strix+"C"+toString(counter))); set("base", "center"); set("size", new double[]{si}); set("pos", new double[]{posx, posy}); endwith(); model.component("comp1").geom("geom1").feature("sq"+strix+"C"+toString(counter)).label("Square"+strix+"C"+toString(counter)); } else { l1 = l-1; si1 = si/3; carpet(l1, posx, posy, si1); } } } }

Note that in order to get a consecutive numbering of the square objects, an integer variable counter is used (under *Declarations*), as shown below.

The code for the two functions are shown below, side by side, in the Method Editor:

In order to run *create_carpet*, you first add it as a *Method Call*. The corresponding menu button is available in the *Developer* tab.

Once added, you can change the recursion level and click the *Run* button.

The figure below shows the resulting geometry for a level 3 carpet.

Note that the number of square geometry objects defined for the level 3 carpet is 512. The number of geometry objects for a level N carpet is 8^{N}. This means that, for the maximum level 5 set by the method *create_carpet*, the resulting geometry has 32,768 geometry objects! If you try a level 5 carpet, make sure you have a powerful enough computer!

### Menger Sponge

We have gone over a recursively defined geometry object in 2D, but what about 3D objects? The 3D version of a Sierpinski carpet is called a Menger sponge. The methods for the Sierpinski carpet readily generalize to 3D. However, in 3D, you need to be careful not to generate more objects than your computer can handle.

The following method, *create_sponge*, initiates the recursion.

if (level < 1) error("Sponge level needs to be at least 1."); if (level > 3) error("Sponge level needs to be at most 3."); counter = 0; model.component("comp1").geom("geom1").feature().clear(); model.component("comp1").geom("geom1").autoRebuild("off"); double cx0 = 0, cy0 = 0, cz0 = 0; double si0 = 1; sponge(level, cx0, cy0, cz0, si0); model.component("comp1").geom("geom1").runPre("fin");

The method *sponge*, shown below, is called by the method above and recursively creates a Menger sponge.

int l = level; double posx, posy, posz, si1; String strix; int l1; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { posx = cx+i*si-si; posy = cy+j*si-si; posz = cz+k*si-si; strix = toString(i)+toString(j)+toString(k); if ((Math.abs((i-1))+Math.abs((j-1))+Math.abs((k-1))) > 1) { if (l == 1) { counter = counter+1; model.component("comp1").geom("geom1").create("blk"+strix+"C"+toString(counter), "Block"); with(model.component("comp1").geom("geom1").feature("blk"+strix+"C"+toString(counter))); set("base", "center"); set("size", new String[]{toString(si), toString(si), toString(si)}); set("pos", new double[]{posx, posy, posz}); endwith(); model.component("comp1").geom("geom1").feature("blk"+strix+"C"+toString(counter)).label("Block"+strix+"C"+toString(counter)); } else { l1 = l-1; si1 = si/3; sponge(l1, posx, posy, posz, si1); } } } } }

The figure below shows the resulting geometry for a level 2 sponge.

In this case, the number of geometry objects grows with the level N as 20^{N}, and the level 2 sponge shown above has 400 block geometry objects.

You don’t have to use recursion to create this type of structure, as demonstrated in a previous blog post on an iterative approach to creating a Koch snowflake.

If you have any of the add-on products for additional CAD functionality, you can export these geometry objects on standard CAD formats. Without an add-on product, you can still export the meshed geometry to any of the supported mesh formats, such as STL.

### Next Step

Try the models featured in this blog post by clicking the button below, which will take you to the Application Gallery.

## Comments (2)

## Bernhard Valentini

July 18, 2019Please remove the programming errors from your example code.

## Bjorn Sjodin

July 18, 2019 COMSOL EmployeeHi Bernhard,

Thanks for spotting the copy-and-paste errors. It has now been fixed.

Bjorn