Do you ever find yourself performing the same modeling operations over and over again in each new model file that you work with? Or do you work with colleagues who send you model files that you have to manually add physics and features to? If so, you can greatly accelerate your workflow by using methods, new as of version 5.3 of the COMSOL Multiphysics® software. Let’s find out how.
Manually Creating a Method in COMSOL Multiphysics®
As we saw in a previous blog post on creating randomized geometries, you can use the Record Method functionality to record a series of operations that you’re performing within the COMSOL Multiphysics graphical user interface (GUI) and then replay that method to reproduce those same steps. Of course, this doesn’t do us any good if we have already created the file — we don’t want to go back and rerecord the entire file. As it turns out, though, COMSOL Multiphysics automatically keeps a history of everything that you’ve done in a model file as Java® code. We can just extract the relevant operations directly from this code and insert them into a new method.
The Compact History option.
To extract all of the history of all operations within a file, there are a few steps you need to take. First, go to the File menu and choose the Compact History option. We do this because COMSOL Multiphysics keeps a history of all commands, but we only want the minimum set of commands that were used to generate the existing model. Next, go to File Menu > Save As and save to a Model File for Java file type. You now have a text file that contains Java® code. Try this out yourself and open the resulting file in a text editor. This file always has lines of code at the beginning and end that are similar to what is shown below:
/*example_model.java */ import com.comsol.model.*; import com.comsol.model.util.*; public class example_model { public static Model run() { Model model = ModelUtil.create("Model"); model.modelPath("C:\\Temp"); model.label("example_model.mph"); model.comments("This is an example model"); ... ... /* Lines of code describing the model contents */ ... return model; } public static void main(String[] args) { run();} }
The above code snippet shows us what we can remove. Only the code between the Model model = ModelUtil.create("Model");
and return model;
is used to define all of the features within the model. In fact, we can also remove the model.modelPath();
, model.label();
, and model.comments();
lines. Go ahead and remove all of these lines of code in your text editor and you are left with just the set of commands needed to reproduce the model in a method.
Next, open a new blank model file, go to the Application Builder, and create a new method. Copy all of the lines from your edited Java® file into this new method. Then, switch back to the Model Builder, go to the Developer tab, and choose Run Model Method to run this code. Running this method reproduces all of the steps from your original file, including solving the model. Solving the model may take a long time, so we often want to trim our method.
A method within the Application Builder.
Trimming the Method
There are two approaches that you can take for trimming down the code. The first is to manually edit the Java® code itself, pruning out any code that you don’t want to rerun. It’s helpful to have the COMSOL Programming Reference Manual handy if you’re going to do this, because you may need to know what every line does before you delete it. The second, simpler approach is to delete the features directly within the COMSOL Multiphysics GUI. Start with a copy of your original model file and delete everything that you don’t want to appear within the method. You can delete the geometry sequence, mesh, study steps, results visualizations, and anything else that you don’t want to reproduce.
Let’s take a look at a quick example of this. Suppose that you’ve built a model that simulates thermal curing and you want to include this thermal curing simulation in other existing models that already have the heat transfer simulations set up.
As we saw in a previous blog post, modeling thermal curing in addition to heat transfer requires three steps:
- Defining a set of material parameters
- Adding a Domain ODE interface to model the evolution of the cure over time
- Coupling the heat of reaction from the curing into the thermal problem
We can build a model in the GUI that contains just these steps and then write out the Java® file. Of course, we still need to do some manual editing, and it’s also helpful to go through the Application Programming Guide to get an introduction to the basics. But once you’re comfortable with all of the syntax, you’ll see that the above three steps within the GUI can be written in the method shown here:
model.param().set("H_r", "500[kJ/kg]", "Total Heat of Reaction"); model.param().set("A", "200e3[1/s]", "Frequency Factor"); model.param().set("E_a", "150[kJ/mol]", "Activation Energy"); model.param().set("n", "1.4", "Order of Reaction"); model.component("comp1").physics("ht").create("hsNEW", "HeatSource"); model.component("comp1").physics("ht").feature("hsNEW").selection().all(); model.component("comp1").physics("ht").feature("hsNEW").set("Q0", "-ht.rho*H_r*d(alpha,t)"); model.component("comp1").physics().create("dode", "DomainODE", "geom1"); model.component("comp1").physics("dode").field("dimensionless").field("alpha"); model.component("comp1").physics("dode").field("dimensionless").component(new String[]{"alpha"}); model.component("comp1").physics("dode").prop("Units").set("SourceTermQuantity", "frequency"); model.component("comp1").physics("dode").feature("dode1").set("f", "A*exp(-E_a/R_const/T)*(1-alpha)^n");
The first four lines of this code snippet define an additional set of global parameters. The next three lines add a Heat Source domain feature to an existing Heat Transfer interface (with the tag ht), define the heat source term, and apply the heat source to all domains. The last five lines set up a Domain ODE interface that is applied by default to all domains in the model and sets the variable name, the units, as well as the equation to solve.
Running the method from the Developer tab.
We can run the above method in a file that already has a heat transfer analysis set up. For example, try adding and running this method in the Axisymmetric Transient Heat Transfer tutorial, available in the Application Library in COMSOL Multiphysics. Then, just re-solve the model to solve for both temperature and degree of cure.
Now, there are a few assumptions in the above code snippet:
- We want to model curing in all of the domains in our model
- There is already a component with the tag comp1 to which we can add physics interfaces
- There is not already a Domain ODE interface with the tag dode in that component
- The temperature variable is defined as T, which we can use in the Domain ODE interface
- A heat transfer physics interface with tag ht already exists and that we can add a feature with tag hsNEW to it
Of course, as you develop your own methods, you need to be able to recognize and address these kinds of general logical issues.
Closing Remarks on Methods
From this simple example, you can also see that you can create a method that acts as a reusable template for any part of the modeling process in COMSOL Multiphysics. You might want to run such a template method in every new file you create, possibly to load in a set of custom material properties, set up a complicated physics interface, or define a complicated set of expressions. You might also want to reuse the same method in an existing file to set up a particular customized study type, modify solver settings, or define a results visualization that you plan to reuse over and over again.
Once you get comfortable with the basics of this workflow, you’ll find yourself saving lots of time, which we hope you’ll appreciate!
Learn About Other Ways to Use Model Methods
- How to Generate Random Surfaces in COMSOL Multiphysics®
- How to Model Gearbox Vibration and Noise in COMSOL Multiphysics®
- How to Create a Randomized Geometry Using Methods
Oracle and Java are registered trademarks of Oracle and/or its affiliates.
Comments (3)
Ivar KJELBERG
July 17, 2017Hello Walter
I was using your procedure described here above to get the series (about 1000 lines!) of plot code to make a method to regenerate the same plots in a 2nd and 3rd run of a large file, having only a few parameter values of differences, i.e. having identical data sets and variable names.
I noticed that even after a “compact history” many “model.results.(…”) java lines appear scattered in my saved .java file.
Is there any specific reason for this, or rather may I regroup them (as long as a “.create” parent appear before its “childs”) ?
Walter Frei
July 17, 2017 COMSOL EmployeeHello Ivar,
It is certainly worth trying this out, yes. You are of course correct that you would need to create an object before modifying it, yes.
Best Regards,
Ke Wang
October 2, 2021Thank you for your share, it’s very useful!