Have you ever wanted to include a randomly created geometry in your model? Perhaps you want to simulate a natural material or an arrangement of parts that has some known statistical distribution of dimensional variations. In such cases, we may want to create a random geometry in the COMSOL Multiphysics® software. With the release of version 5.3, we can now create random geometries using a method. Let’s take a look at how to do so with a tasty example.

### Building a Model of Swiss Cheese

Determining the best cheese in the world is a hotly contested task, but I’ll go ahead and add my opinion: a good Emmentaler cheese is hard to beat. A master cheesemaker might joke that it’s really the holes that add the flavor, so if we’re going to build a good COMSOL Multiphysics model of a wheel of cheese, we need to include the holes.

*A model of Emmentaler cheese, with randomly positioned and sized holes.*

It turns out that the reasons for the holes in Swiss cheese are quite complicated, so we aren’t going to try to model the hole formation itself. Instead, we will simply set up a model of the cheese, as shown in the image above. We want to include a randomly distributed set of holes within the cheese, with a random hole radius between some upper and lower limit on the radius. We can build this randomized geometry in COMSOL Multiphysics version 5.3 using the new *method* functionality. Let’s find out how…

### Introducing Methods in COMSOL Multiphysics®

When you’re running COMSOL Multiphysics® version 5.3 on the Windows® platform and working with the Model Builder, you will now see a *Developer* tab in the ribbon, as shown in the screenshot below. One of the options is *Record Method*. When clicked, this option prompts you to enter a new method *Name* and *Method type*. You can enter any string for the method name, while the method type can either be *application method* or *model method*.

An *application method* can be used within a COMSOL app — a process introduced in this tutorial video. A *model method* can be used within the underlying COMSOL Multiphysics model and can operate on (and add information to) the existing model data.

*The* Developer *tab, showing the* Record Method *and* Run Model Method *buttons.*

After you click the *OK* button in the *Record Method* dialog box, you can see a red highlight around the entire graphical user interface. All operations performed are recorded in this method until you click the *Stop Recording* button. You can then switch to the Application Builder and view your recorded method. The screenshot below shows the Application Builder and the method after we record the creation of a single geometry object. The object is a cylinder with the tag `cyl1`

, a radius of 40 cm, and a height of 20 cm — a good starting approximation for a wheel of cheese.

*The Application Builder showing code for a method used to create a geometry.*

When we’re working with the Model Builder, we can call this method within any other model file (as long as it doesn’t already have an existing object with tag `cyl1`

within the geometry sequence) via the *Run Model Method* button in the *Developer* tab. Of course, this simple method just creates a cylinder. If we want to model the holes, we need to introduce a bit of randomness into our method. Let’s look at that next.

### Creating a Random Set of Geometry Features

Within a method, you can call standard Java® classes, such as the Math.random class, which returns a double-precision number greater than or equal to 0.0 and less than 1.0. We want to use this class, along with a little bit of extra code, to set up a specified number of randomly positioned and sized holes within the model of the wheel of cheese.

Let’s say that we want 1000 holes randomly distributed throughout the cheese that each have a random radius between 0.1 cm and 1 cm. We also need to keep in mind that Emmentaler cheese has a natural rind within which no holes form. So, we need to add a bit of logic to make sure that our 1000 holes are actually inside the cheese. The complete method below (with line numbers added and text strings in red) shows how to do this.

1 int NUMBER_OF_HOLES = 1000; 2 int ind = 0; 3 double hx, hy, hz, hr = 0.0; 4 double CHEESE_HEIGHT = 20.0; 5 double CHEESE_RADIUS = 40.0; 6 double RIND_THICKNESS = 0.2; 7 double HOLE_MIN_RADIUS = 0.1; 8 double HOLE_MAX_RADIUS = 1.0; 9 model.component("comp1").geom("geom1").lengthUnit("cm"); 10 model.component("comp1").geom("geom1").selection().create("csel1", "CumulativeSelection"); 11 while (ind < NUMBER_OF_HOLES) { 12 hx = (2.0*Math.random()-1.0)*CHEESE_RADIUS; 13 hy = (2.0*Math.random()-1.0)*CHEESE_RADIUS; 14 hz = Math.random()*CHEESE_HEIGHT; 15 hr = Math.random()*(HOLE_MAX_RADIUS-HOLE_MIN_RADIUS)+HOLE_MIN_RADIUS; 16 if ((Math.sqrt(hx*hx+hy*hy)+hr) > CHEESE_RADIUS-RIND_THICKNESS) {continue; } 17 if (((hz-hr) < RIND_THICKNESS) || ((hz+hr) > CHEESE_HEIGHT-RIND_THICKNESS)) {continue; } 18 model.component("comp1").geom("geom1").create("sph"+ind, "Sphere"); 19 model.component("comp1").geom("geom1").feature("sph"+ind).set("r", hr); 20 model.component("comp1").geom("geom1").feature("sph"+ind).set("pos", new double[]{hx, hy, hz}); 21 model.component("comp1").geom("geom1").feature("sph"+ind).set("contributeto", "csel1"); 22 ind++; 23 } 24 model.component("comp1").geom("geom1").create("cyl1", "Cylinder"); 25 model.component("comp1").geom("geom1").feature("cyl1").set("r", CHEESE_RADIUS); 26 model.component("comp1").geom("geom1").feature("cyl1").set("h", CHEESE_HEIGHT); 27 model.component("comp1").geom("geom1").create("dif1", "Difference"); 28 model.component("comp1").geom("geom1").feature("dif1").selection("input").set("cyl1"); 29 model.component("comp1").geom("geom1").feature("dif1").selection("input2").named("csel1"); 30 model.component("comp1").geom("geom1").run();

Let’s go through this method line by line:

1. Initialize and define the total number of holes that we want to put in the cheese.

2. Initialize and define an index counter to use later.

3. Initialize a set of double-precision numbers that holds the *xyz*-position and radius of each hole.

4–8. Initialize and define a set of numbers that defines the cheese height, radius, ring thickness, and maximum and minimum possible hole radius in centimeters.

9. Set the length unit of the geometry to centimeters.

10. Create a new selection set, with tag `csel`

and name ` CumulativeSelection`

. Note that if such a selection set already exists, the method fails at this point. You could also modify the method to account for this, if you want to run the method repeatedly in the same file.

11. Initialize a while loop to create the specified number of holes.

12–14. Define the *xyz*-position of the holes by calling the random method and scaling the output such that the *xyz*-position of the holes lies within the outer Cartesian bounds of the cheese.

15. Define the hole radius to lie between the specified limits.

16–17. Check if the hole position and size are such that the hole is actually outside of the cheese. If so, continue to the next iteration of the while loop without executing any of the remaining code in the loop. This check can be done in a single line or split into three lines, depending on your preference of programming style.

18. Create a sphere with a name based on the current index value.

19–20. Set the radius and position of the newly created sphere. Although the radius can be passed in directly as a double, the position must be specified as an array of doubles.

21. Specify that this sphere feature is part of (contributes to) the selection set named `csel1`

.

22–23. Iterate the index, indicating that a sphere has been created, and close the while loop.

24–26. Create a cylinder primitive that represents the wheel of cheese.

27–29. Set up a Boolean difference operation. The object to add is the cylinder primitive, while the object to subtract is the selection of all of the spheres.

30. Run the entire geometry sequence, which cuts all of the spheres out of the cylinder, forming the wheel of cheese.

We can run this method in a new (and empty) model file to create a model of a wheel of cheese. Each time we rerun the method, we will get a different model. The geometry sequence in the model file contains all of the spheres and the cylinder primitives as well as the Boolean operation.

If we want to, we could also add some additional code to our method to write out a geometry file of just the final geometry: the cheese. This geometry file can be written in the COMSOL Multiphysics native or STL file format. We could also write out to Parasolid® software or ACIS® software file formats with any of the optional modules that include the Parasolid® software kernel. Working with just the final geometry after it has been exported and reimported is faster than working with the complete geometry sequence.

We can see the final results of our efforts below. Delicious!

*A model of a wheel of Emmentaler cheese, ready to be eaten.*

### Closing Remarks on Creating a Randomized Geometry via Methods

We’ve looked at a simple example of how to use methods to create a geometry with randomly placed and sized features. There are some questions that we haven’t addressed here, such as how to ensure that the holes are not overlapping and how to come up with a close-packed arrangement, but these turn out to be difficult mathematical questions that are fields in their own right.

Of course, there is a lot more that you can do with methods, which we will save for another day. There are also other ways to create a random geometry, such as by parametrically defining a surface.

### Related Resources

- Read about another use of methods: generating simulation results that you can see and hear
- Check out the new features in COMSOL Multiphysics® version 5.3 on the Release Highlights page

*ACIS is a registered trademark of Spatial Corporation. Oracle and Java are registered trademarks of Oracle and/or its affiliates. Parasolid is a trademark or registered trademark of Siemens Product Lifecycle Management Software Inc. or its subsidiaries in the United States and in other countries. Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.*

## Comments (29)

## Thales Fernandes

June 6, 2017With Model Methods is it possible to modify the solution itself? Even defining new variables?

For example, renormalizing the solution (instead of creating new variables) or changing eigenvalue positions?

In EM simulations Comsol sort solutions by neff (and sometimes not even that!). I find it better to sort by TE/TM fraction since this preserves modes orthogonality in a sweep.

Lumerical offers this possibility with “overlap” function but Comsol just sorts the modes in whatever random order that makes sweep discontinuous.

BTW, thanks for the post, post like these really teach us some tricks.

## Tommaso Santagata

June 6, 2017Very nice post, thank you!

Is it possible to use two shapes for the holes and give specific boundary conditions for each shape? e.g. for a fluid dynamics model, cylinders with no slip condition and spheres with a surface reaction term. What do you think about it?

Thank you for this very interesting post!

## Walter Frei

June 8, 2017Hello Thales,

For the types of solution manipulation that you’re asking about, we would recommend that you look to the LiveLink for MATLAB product (https://www.comsol.com/livelink-for-matlab) which lets you evaluate and manipulate your solutions.

Best Regards,

## Walter Frei

June 8, 2017Hello Tommaso,

What you’re asking about could be achieved with the Selections capability. Not only can you use Geometry selections to perform further geometry operations (As we do in this example) but you can also use the Selections in your physics assignments. An example of the usage of these is in the 5.3 version of the heat sink example:

https://www.comsol.com/model/heat-sink-8574

Best Regards,

## thouaiba htira

November 23, 2017Hello,

thank you for this helpfull example. i have some questions :

is it possible to do this with comsol 5.2a?

the code is similar ?

after created the geometry how we can go back to the model builder and plot the geometry to continue adding physics etc… ?

Thank you for help!

Best regards,

## Walter Frei

December 1, 2017Hello Thouaiba,

This functionality described here is new in 5.3.

## H. Richter

December 8, 2017Very informative post, thank you!

Regarding the generation of non-overlapping, random sphere packings, there exist several software tools that address this issue (an open-source one is available at https://github.com/Mote3D/Mote3D_toolbox). Such tools could be easily used in conjunction with java scripting to create advanced microstructure models.

## Walter Frei

December 8, 2017Thank you for the comment, I was not aware of this tool!

## Mojtaba Dargahi

February 20, 2018Hello Walter,

thank you for this helpful example. Just some questions :

How can we call it in my model? I mean, after writing down the sequences and creating the geometry in the way you explained how we can go back to the model builder and plot the geometry to continue adding physics etc… ?

Thank you for help!

Best regards,

Mojtaba

## Caty Fairclough

March 1, 2018Hi Mojtaba,

Thanks for your comment!

For your question, please contact our Support team.

Online Support Center: https://www.comsol.com/support

Email: support@comsol.com

## Sarra Zid

October 23, 2018Hello, thank you for this helpful example,

I would like to ask how to generate a Gaussian distribution of numbers, I know that we must use nextGaussian() but i have some errors in my application builder interface.

Thanks

## QILONG CHENG

July 28, 2022model.func().create(“rn1”, “Random”); // create random function

model.func(“rn1”).set(“type”, “normal”); // set as normal distribution

model.func(“rn1”).set(“mean”, “0.45/2”); // set mean

model.func(“rn1”).set(“normalsigma”, “0.025/2”); // set standard deviation

For example, set the random value for a radius in a while loop:

model.component(“comp1”).geom(“geom1”).feature(“circ”+ind).set(“r”, “rn1(“+ind+”)”);

## Viki Temesvary

January 8, 2019Looks like lines 12-16 in the code snippet magically disappeared?!

## Viki Temesvary

January 11, 2019it’s there in the model file of course!

while (ind CHEESE_RADIUS-RIND_THICKNESS) {continue; }

## Said Bouta

December 25, 2019How to add this line in the script?

## Jeff Hiller

April 25, 2019Thank you, Viki, for reporting the missing lines of code. This has now be corrected.

## Flavio Moraes

June 25, 2020Is it possible to use Nd4j library in my methods? How do I do that?

## Mikhail Kukharevich

September 12, 2020Hello friend) Can I use this example in the optimization process ?) I want to investigate how a certain pore distribution will affect the strength of the cheese) I also have a problem with the fact that with a certain distribution, some of the pores go beyond the cheese) Can I update the form with the removal of pores that go beyond the cheese boundaries during the optimization process ?)

## Sumit Choudhary

December 20, 2020Dear Walter,

Thank you for nice blog.

Math.random() generates the random number between zero to one. I want to generate the random numbers whose elements are normally distributed with mean zero and standard deviation one. Can I generate using Model method in application programming interface of comsol?

## Shuveksha sapkota

June 11, 2021i need the same answer.

## Shuveksha sapkota

June 11, 2021Hey there. I am using Comsol to study about the effects on roughness on heat transfer chractersistics of a circular microchannel. These are the details.

Standard deviation = 1.00 micrometers

Surface roughness mean= 1.40 micrometers

Inner diameter= 123 micrometres

Outer diameter= 282 micrometers

Please provide me a suitable way on how this geomtry can be created and analysis be done.

You have similar file as i ned. Please provide details on how you created this.

random_tube_geometry_4_patches_hollowed_with_cylinder.mph – 6.42MB

## Bojan Jokanovic

July 1, 2021Thanks. It is a very useful method for creating a geometry.

## Kausik Bal

August 4, 2021Thanks for the blog. While trying to replicate this, an error message may come as you have mentioned here:

“10. Create a new selection set, with tag csel and name CumulativeSelection. Note that if such a selection set already exists, the method fails at this point. You could also modify the method to account for this, if you want to run the method repeatedly in the same file.” I do not think the solution to this scenario was clear to me from reading your blog. Can you be a little more explicit and explain exactly what to do if such situation appears (i.e., the method fails to run due to the already existing selection set)? Thanks in advance.

## Tanzila Nurjahan

March 23, 2022Hello Mr. Walter Frei,

I am a new COMSOL user and currently using COMSOL 6.0.

I would like to extract the model of this (Swiss) cheese structure from the .mph file, however, it did not work. Could you please assist in extracting the mph file into modeling the structure? Thanks in advance.

## Walter Frei

March 23, 2022 COMSOL EmployeeHello Tanzila,

If you download the model file and run the method you will then have a sample geometry in the Geometry branch. If you want, toy can then export (right-click Geometry > Export… ) to the file type of your choice.

## Tanzila Nurjahan

March 23, 2022Dear Mr. Walter Frei,

I tried, however, it is not working. Is it possible to arrange an online discussion session, would be really helpful, thanks in advance.

## Uthpala Ekanayake

December 19, 2022Hello

I am trying to place random cubes, How do you set properties of the block.

e.g : model.componnet(“comp1”).geom(“”geom1).features(“blk”).set(“??”,hr)

What should come at “??” In the above code, for a sphere this is given as “r”

## Pablo Ramos

May 9, 2023It is possible to avoid the overlapping of the spheres. And how is it done?

## Walter Frei

May 9, 2023 COMSOL EmployeeHello Pablo,

There is an interesting earlier comment, from H. Richter, that addresses this.

Happy Modeling!