Working with Model Objects
When using the Model Builder in the COMSOL Desktop interface, an embedded model with variable name model is automatically created. The embedded model has a special status. For example, the automatic code generation tools only consider the embedded model. In addition, when you save to or load from an MPH file, only the embedded model is saved or loaded. General tools include the Save Application As command in the Application Builder and File > Save As, from the File menu of the COMSOL Desktop environment.
However, in an application you are allowed to create and edit multiple models. Saving and loading such models is done by using the built-in methods saveModel and loadModel. An MPH file can only contain a single embedded model object.
If you need to create model objects, in addition to the embedded model, use the built-in method createModel.
To create a new model you use:
Model extmodel = createModel();
A unique model tag is created automatically and assigned to the model. If you want to explicitly control the model tag, use a syntax like:
Model extmodel = createModel("My_model_1");
where My_model_1 is a unique tag. It is recommended that you do not use the names Model1, Model2, Model3, and so on, since these names are used by the mechanism that automatically generates model tags for the embedded model when loading and saving MPH files.
The following example retrieves the model tag of the embedded model:
String my_modeltag = model.tag();
however, you rarely need to use the model tag of the embedded model object.
Instead of creating and building up the contents of a model from scratch, you can load an existing model and edit it.
For example in the Windows operating system, load a model my_model.mph from the folder C:\COMSOL_Work, by using the built-in method loadModel:
Model extmodel = loadModel("C:\\COMSOL_Work\\my_model.mph");
A unique model tag is created automatically and is assigned to the model upon load. Note the double-backslash syntax in the filename. Backslash (\) is a special character in Java and the double backslash is needed in this case.
To make your application portable, you can use the file scheme syntax available in the Application Builder. Assuming you stored the MPH file in the common folder, the call to loadModel should be:
Model extmodel = loadModel("My_Model_1", "common:///my_model.mph");
In this example, the tag My_Model_1 is important because it is used to reference the model from other methods. Once loaded, the model object extmodel exists in the workspace of the current COMSOL Multiphysics or COMSOL Server session.
Note that an MPH file can only contain a single embedded model object, so there is no ambiguity about which model is being referenced when loading an MPH file.
Assume that you, in one method, have loaded the model extmodel with the tag My_Model_1, such as in the example above. The model variable extmodel is not available in other methods. In order to retrieve the model from another method use:
Model mymodel = getModel("MyModel_1");
The contents of mymodel and extmodel are the same, but these variables exist in the variable space of two different methods.
The tag My_Model_1 uniquely identified and retrieved the model object from the current COMSOL Multiphysics or COMSOL Server session.
To reset your model before running a model method, call the built-in clearModel method. For example:
clearModel(model);
Placing this at the top of your model method automatically clears the Model Builder tree contents on each run.
For a list of model utility methods, see Model Utility Methods.
A Complete Example in 1D
The following code listing uses all the elements of the previous sections—including material definitions, geometry setup, physics configuration, and boundary conditions— and demonstrates how to set up and run a 1D stationary heat transfer simulation in a 10 cm long steel rod, focusing on its lengthwise thermal behavior. In this model, the left side of the rod is cooled while a random heat source is applied throughout the rod.
To use this code:
1
2
3
Choose the corresponding Run option to start the simulation.
// Set up and run a 1D stationary heat transfer simulation
clearModel(model);
 
model.component().create("comp1", true);
 
model.component("comp1").geom().create("geom1", 1);
model.component("comp1").mesh().create("mesh1");
model.component("comp1").geom("geom1").create("i1", "Interval");
model.component("comp1").geom("geom1").feature("i1").setIndex("coord", 0.1, 1);
model.component("comp1").geom("geom1").run();
 
model.component("comp1").physics().create("ht", "HeatTransfer", "geom1");
 
model.component("comp1").material().create("mat1", "Common");
model.component("comp1").material("mat1").label("Steel AISI 4340");
model.component("comp1").material("mat1").propertyGroup("def").set("density", "7850[kg/m^3]");
model.component("comp1").material("mat1").propertyGroup("def").set("heatcapacity", "475[J/(kg*K)]");
model.component("comp1").material("mat1").propertyGroup("def")
.set("thermalconductivity", new String[]{"44.5[W/(m*K)]", "0", "0", "0", "44.5[W/(m*K)]", "0", "0", "0", "44.5[W/(m*K)]"});
 
model.func().create("rn1", "Random");
model.func("rn1").set("type", "uniform");
model.func("rn1").set("mean", 0.5);
 
model.component("comp1").physics("ht").create("temp1", "TemperatureBoundary", 0);
model.component("comp1").physics("ht").feature("temp1").selection().set(1);
model.component("comp1").physics("ht").create("hs1", "HeatSource", 1);
model.component("comp1").physics("ht").feature("hs1").selection().set(1);
model.component("comp1").physics("ht").feature("hs1").set("Q0", "1e6*(1+rn1(x))");
 
model.study().create("std1");
model.study("std1").create("stat", "Stationary");
model.study("std1").feature("stat").setSolveFor("/physics/ht", true);
model.study("std1").createAutoSequences("all");
model.sol("sol1").runAll();
 
model.result().create("pg1", "PlotGroup1D");
model.result("pg1").label("Temperature (ht)");
model.result("pg1").feature().create("lngr1", "LineGraph");
model.result("pg1").feature("lngr1").set("xdata", "expr");
model.result("pg1").feature("lngr1").set("xdataexpr", "x");
model.result("pg1").feature("lngr1").set("data", "parent");
model.result("pg1").feature("lngr1").selection().geom("geom1", 1);
model.result("pg1").feature("lngr1").selection().set(1);
model.result("pg1").run();
 
model.result("pg1").run();
A Complete Example in 3D
The following code listing is similar to the 1D case, but simulates heat transfer in a 3D cylinder. This example demonstrates how to set up and run a stationary 3D heat transfer simulation in a 10 cm long cylindrical steel rod with a radius of 0.5 cm. One end of the rod is cooled, while a random heat source is applied throughout its volume.
// Set up and run a 3D stationary heat transfer simulation
clearModel(model);
 
model.component().create("comp1", true);
 
model.component("comp1").geom().create("geom1", 3);
model.component("comp1").geom("geom1").geomRep("comsol");
model.component("comp1").mesh().create("mesh1");
 
model.component("comp1").geom("geom1").create("cyl1", "Cylinder");
model.component("comp1").geom("geom1").feature("cyl1").set("h", 0.1);
model.component("comp1").geom("geom1").feature("cyl1").set("r", 0.005);
model.component("comp1").geom("geom1").run();
 
model.component("comp1").physics().create("ht", "HeatTransfer", "geom1");
 
model.component("comp1").material().create("mat1", "Common");
model.component("comp1").material("mat1").label("Steel AISI 4340");
model.component("comp1").material("mat1").propertyGroup("def").set("density", "7850[kg/m^3]");
model.component("comp1").material("mat1").propertyGroup("def").set("heatcapacity", "475[J/(kg*K)]");
model.component("comp1").material("mat1").propertyGroup("def")
.set("thermalconductivity", new String[]{"44.5[W/(m*K)]", "0", "0", "0", "44.5[W/(m*K)]", "0", "0", "0", "44.5[W/(m*K)]"});
 
model.func().create("rn1", "Random");
model.func("rn1").set("type", "uniform");
model.func("rn1").set("nargs", 3);
model.func("rn1").set("mean", 0.5);
 
model.component("comp1").physics("ht").create("temp1", "TemperatureBoundary", 2);
model.component("comp1").physics("ht").feature("temp1").selection().set(3);
model.component("comp1").physics("ht").create("hs1", "HeatSource", 3);
model.component("comp1").physics("ht").feature("hs1").selection().set(1);
model.component("comp1").physics("ht").feature("hs1").set("Q0", "1e6*(1+rn1(x,y,z))");
 
model.study().create("std1");
model.study("std1").create("stat", "Stationary");
model.study("std1").feature("stat").setSolveFor("/physics/ht", true);
model.study("std1").createAutoSequences("all");
model.sol("sol1").runAll();
 
model.result().create("pg1", "PlotGroup3D");
model.result("pg1").label("Temperature (ht)");
model.result("pg1").feature().create("vol1", "Volume");
model.result("pg1").feature("vol1").set("colortable", "HeatCameraLight");
model.result("pg1").run();
 
model.result("pg1").run();
Note: When using the Record Code or Record Method options, additional code may be generated automatically. In the examples above, any unnecessary or extraneous code has been removed for clarity.
This example is part of a collection available for download:
www.comsol.com/model/application-programming-guide-examples-140771
The relevant file for this example is:
heat_transfer_in_cylindrical_rod.mph
Turning Off and Resetting The Model History
When running model method code to automate modeling tasks, the stored model history can grow excessively large. The model history is used, for example, when saving to a Model M-file or Model Java-file. Depending on the repetitive nature of your code, you may want to temporarily disable history logging to keep the model history manageable. This can be done as shown below:
model.hist().disable();
// some code
model.hist().enable();
To reset the model history to an almost minimal sequence of commands that reproduces the current state of the model object, you can use:
model.resetHist();
In the File menu, this action is referred to as Compact History.
Note that model history logging is only used for model methods and is automatically turned off when running an application. Also, when history logging is disabled, certain features are not available, such as saving to a Model M-file or Java-file and using the Copy to Clipboard functionality.
Optimizing Physics Feature Creation Performance
Repeated create operations for features in the Model Builder can become slow when you add many of them. Different feature types vary in complexity—for example, the TemperatureBoundary boundary condition is relatively simple, while, for example, a Thermal Contact boundary condition performs more advanced operations. Although certain optimizations are possible, identifying and resolving bottlenecks can be time-consuming.
A common technique to speed up these processes is to temporarily disable updates, as shown below:
try {
    // Turn off updates
    model.disableUpdates(true);
 
    // Perform the required operations here,
    // typically involving repeated manipulations of physics features
 
} finally {
    // Important: re-enable updates before leaving the method
    // The try–finally block ensures this is done even if errors occur
    model.disableUpdates(false);
}
// Note: Some operations cannot be performed while updates are disabled.
By using this approach, certain methods can show significant reduction in processing time.
Disabling model updates can lead to unexpected side effects. For example, parameters in a physics feature, such as model inputs ending in _src, may remain invalid until the model is updated. Attempting to set any of these parameters while updates are disabled can produce errors. In addition, generated variables may be unavailable to the unit evaluator, and the equation view may show incomplete data. As soon as updates are re-enabled, the program performs a full variable refresh and returns the model to a fully functional state.
The following example uses this technique to test the speed when adding a large number of model parameters. Change the value of the disableFlag variable to toggle between the disabled and enabled states.
// Enable or disable updates
boolean disableFlag = true;
 
// Number of parameter updates to perform
int maxIterations = 2000;
 
// Clear model
clearTheModel(); // This may take several seconds and is not part of the time measured
 
// Record start time
long startTime = timeStamp();
debugLog("Start of test.");
debugLog("Disable is: "+disableFlag);
 
// Disable model updates (returns previous state) to speed up the loop
boolean updatesWereEnabled = model.disableUpdates(disableFlag);
 
try {
// Bulk-set parameters Val1, Val2, …
for (int i = 1; i <= maxIterations; i++) {
model.param("default").set("Val"+i, i);
}
} finally {
// Always restore the original update state, even if an error occurs
model.disableUpdates(updatesWereEnabled);
}
 
// Compute and log elapsed time in h:mm:ss format
long endTime = timeStamp();
debugLog("End of test.");
debugLog("Data reading time: "+formattedTime(endTime-startTime, "h:min:s"));
This example is part of a collection available for download:
www.comsol.com/model/application-programming-guide-examples-140771
The relevant file for this example is:
disable_updates.mph
Limitations with Loading and Saving Models
If you use the loadModel method to load another model into your application, then the usual functionality for displaying the geometry, mesh, and results, for the loaded model, is not directly available in the application since that functionality is reserved for the embedded model. However, you can use the API to call geometry, mesh, study, and results functionality and extract numerical results from the loaded model. For example, you can change the value of parameters or variables of the loaded model, run a study, and extract numerical results.
However, in an application, you can display plots generated from models other than the embedded model by writing specific method code. First, you will need to use the loadModel method to load the desired model. Following this, the useGraphics method can be used to display a particular plot group from the loaded model. Here is a simplified example to illustrate this process:
Model m = loadModel(...);
useGraphics(m.result("pg1"), "/form1/graphics1");
In this example, loadModel is used to load a model, and useGraphics is used to display a plot group "pg1" from the loaded model in the graphics component
"/form1/graphics1"
Note that useGraphics exclusively supports the display of plot groups. This method cannot be used for displaying other graphical elements like geometry or mesh. Note, however, that functionality for plotting the CAD model as well as the mesh is possible also from plot groups. For example, by plotting a constant expression or a fixed color for a surface or volume plot. Or, by using a dedicated mesh plot.
The toolbar accompanying these plots is limited compared to the one available for plots from the embedded model. This limitation exists as certain actions associated with the full toolbar are not supported in this scenario.
Note that the loadModel and saveModel methods are not supported in standalone applications that have been compiled with COMSOL Compiler.