Measuring Model Quantities
For measuring geometric and mass properties of a finalized geometry, use the Measure options under Results > Evaluation Group or Results > Derived Values. Note that, for historical reasons, Derived Values are referred to as Numerical in the COMSOL API. The Evaluation Group option is a more recent addition to COMSOL Multiphysics and is the recommended option. The examples below applies to the Thermal Microactuator Simplified model, which you can find in the Application Libraries at COMSOL Multiphysics > Multiphysics.
The complete example, including the method code, is part of a collection available for download:
www.comsol.com/model/application-programming-guide-examples-140771
The relevant file for this example is:
thermal_actuator_simplified_measure.mph
The two code listings below computes the following quantities, using Evaluation Group and Derived Values, respectively:
The first four quantities use purely geometry measure features: MeasureVolume, MeasureSurface, MeasureLine, MeasureDistance.
The last two use the MassProperties feature, which also recomputes volume, so you see the volume twice (once from MeasureVolume, once from MassProperties).
Unit sources:
Volume and area units come from the model’s Unit System, defined at the root node.
Using Evaluation Group
// Create the Evaluation Group
model.result().evaluationGroup().create("eg1", "EvaluationGroup");
 
// ——— 1) Volume ———
model.result().evaluationGroup("eg1").create("meas1", "MeasureVolume");
model.result().evaluationGroup("eg1").feature("meas1").set("unit", "um^3");
model.result().evaluationGroup("eg1").feature("meas1").selection().set(1);
model.result().evaluationGroup("eg1").run();
 
double[][] volumeResult = model.result().evaluationGroup("eg1").getReal();
double volume = volumeResult[0][0];
String volumeUnit = model.result().evaluationGroup("eg1").feature("meas1").getString("unit");
debugLog("Volume: "+volume+" "+volumeUnit);
 
// ——— 2) Surface area ———
model.result().evaluationGroup("eg1").create("meas2", "MeasureSurface");
model.result().evaluationGroup("eg1").feature("meas2").set("unit", "um^2");
model.result().evaluationGroup("eg1").feature("meas2").selection().set(3);
model.result().evaluationGroup("eg1").run();
 
double[][] areaResult = model.result().evaluationGroup("eg1").getReal();
double area = areaResult[0][1];
String areaUnit = model.result().evaluationGroup("eg1").feature("meas2").getString("unit");
debugLog("Surface area: "+area+" "+areaUnit);
 
// ——— 3) Line length ———
model.result().evaluationGroup("eg1").create("meas3", "MeasureLine");
model.result().evaluationGroup("eg1").feature("meas3").set("unit", "um");
model.result().evaluationGroup("eg1").feature("meas3").selection().set(173);
model.result().evaluationGroup("eg1").run();
 
double[][] lengthResult = model.result().evaluationGroup("eg1").getReal();
double length = lengthResult[0][2];
String lengthUnit = model.result().evaluationGroup("eg1").feature("meas3").getString("unit");
debugLog("Line length: "+length+" "+lengthUnit);
 
// ——— 4) Distance between two points ———
model.result().evaluationGroup("eg1").create("meas4", "MeasureDistance");
model.result().evaluationGroup("eg1").feature("meas4").set("unit", "um");
model.result().evaluationGroup("eg1").feature("meas4").selection().set(155, 167);
// Alternative syntax:
// int[] vertices = new int[]{155, 167};
// model.result().evaluationGroup("eg1").feature("meas4").selection().set(vertices);
model.result().evaluationGroup("eg1").run();
 
double[][] distResult = model.result().evaluationGroup("eg1").getReal();
double distance = distResult[0][3];
String distUnit = model.result().evaluationGroup("eg1").feature("meas4").getString("unit");
debugLog("Distance: "+distance+" "+distUnit);
 
// ——— 5) Mass properties ———
model.result().evaluationGroup("eg1").create("mass1", "MassProperties");
model.result().evaluationGroup("eg1").feature("mass1").selection().set(1);
model.result().evaluationGroup("eg1").feature("mass1").setIndex("unit", "um^3", 0);
model.result().evaluationGroup("eg1").feature("mass1").setIndex("unit", "mg", 1);
model.result().evaluationGroup("eg1").feature("mass1").setIndex("unit", "um", 2);
 
// Enable volume, mass and center-of-mass contributions
model.result().evaluationGroup("eg1").feature("mass1").setIndex("contributionenabled", true, 0);
model.result().evaluationGroup("eg1").feature("mass1").setIndex("contributionenabled", true, 1);
model.result().evaluationGroup("eg1").feature("mass1").setIndex("contributionenabled", true, 2);
model.result().evaluationGroup("eg1").run();
 
double[][] massResult = model.result().evaluationGroup("eg1").getReal();
double massVolume = massResult[0][4];
double massMass = massResult[0][5];
double cmX = massResult[0][6];
double cmY = massResult[0][7];
double cmZ = massResult[0][8];
 
// Retrieve the unit strings
String[] massUnits = model.result().evaluationGroup("eg1").feature("mass1").getStringArray("unit");
 
debugLog("Mass volume: "+massVolume+" "+massUnits[0]);
debugLog("Mass: "+massMass+" "+massUnits[1]);
debugLog("CofM x: "+cmX+" "+massUnits[2]);
debugLog("CofM y: "+cmY+" "+massUnits[2]);
debugLog("CofM z: "+cmZ+" "+massUnits[2]);
selectNode(model.result().evaluationGroup("eg1").feature("meas1"));
Using Derived Values
// ——— 1) Volume ———
model.result().numerical().create("meas1", "MeasureVolume");
model.result().numerical("meas1").set("unit", "um^3");
model.result().numerical("meas1").selection().set(1);
double[][] volumeResult = model.result().numerical("meas1").getReal();
double volume = volumeResult[0][0];
String volumeUnit = model.result().numerical("meas1").getString("unit");
debugLog("Volume: "+volume+" "+volumeUnit);
// ——— 2) Surface area ———
model.result().numerical().create("meas2", "MeasureSurface");
model.result().numerical("meas2").set("unit", "um^2");
model.result().numerical("meas2").selection().set(3);
double[][] surfaceResult = model.result().numerical("meas2").getReal();
double area = surfaceResult[0][0];
String areaUnit = model.result().numerical("meas2").getString("unit");
debugLog("Surface area: "+area+" "+areaUnit);
 
// ——— 3) Line length ———
model.result().numerical().create("meas3", "MeasureLine");
model.result().numerical("meas3").set("unit", "um");
model.result().numerical("meas3").selection().set(173);
double[][] lineResult = model.result().numerical("meas3").getReal();
double length = lineResult[0][0];
String lengthUnit = model.result().numerical("meas3").getString("unit");
debugLog("Line length: "+length+" "+lengthUnit);
 
// ——— 4) Distance between two points ———
model.result().numerical().create("meas4", "MeasureDistance");
model.result().numerical("meas4").set("unit", "um");
model.result().numerical("meas4").selection().set(155, 167);
double[][] distanceResult = model.result().numerical("meas4").getReal();
double distance = distanceResult[0][0];
String distanceUnit = model.result().numerical("meas4").getString("unit");
debugLog("Distance: "+distance+" "+distanceUnit);
 
// ——— 5) Mass properties ———
model.result().numerical().create("mass1", "MassProperties");
model.result().numerical("mass1").selection().set(1);
 
model.result().numerical("mass1").setIndex("unit", "um^3", 0);
model.result().numerical("mass1").setIndex("unit", "mg", 1);
model.result().numerical("mass1").setIndex("unit", "um", 2);
 
// Enable volume, mass and center‐of‐mass contributions
model.result().numerical("mass1").setIndex("contributionenabled", true, 0);
model.result().numerical("mass1").setIndex("contributionenabled", true, 1);
model.result().numerical("mass1").setIndex("contributionenabled", true, 2);
 
double[][] massResult = model.result().numerical("mass1").getReal();
double massVolume = massResult[0][0];
double massMass = massResult[1][0];
double cmX = massResult[2][0];
double cmY = massResult[3][0];
double cmZ = massResult[4][0];
 
// Retrieve the unit strings
String[] massUnits = model.result().numerical("mass1").getStringArray("unit");
 
debugLog("Mass volume: "+massVolume+" "+massUnits[0]);
debugLog("Mass: "+massMass+" "+massUnits[1]);
debugLog("CofM x: "+cmX+" "+massUnits[2]);
debugLog("CofM y: "+cmY+" "+massUnits[2]);
debugLog("CofM z: "+cmZ+" "+massUnits[2]);
 
selectNode(model.result().numerical("meas1"));
Comments
Note that when using Derived Values, the massResult array comes back transposed compared to the array returned by an Evaluation Group.
Instead of using the ASCII letter u for the micro-prefix, you can embed the Unicode micro sign (\u00b5) in your unit strings. For example:
model.result().evaluationGroup("eg1").feature("meas1").set("unit", "\u00b5m^3");
This forces the output to render µm^3 rather than um^3.
Rather than hard-coding geometric entity numbers (for example 155, 167), define a named Explicit selection and reuse it. For example:
// Create the Evaluation Group
model.result().evaluationGroup().create("eg1", "EvaluationGroup");
 
// Create Explicit named selections
model.component("comp1").selection().create("sel4", "Explicit");
model.component("comp1").selection("sel4").geom(0);
model.component("comp1").selection("sel4").label("Short Distance");
int[] vertices = new int[]{155, 167};
model.component("comp1").selection("sel4").set(vertices);
 
// ——— Distance between two points ———
model.result().evaluationGroup("eg1").create("meas4", "MeasureDistance");
model.result().evaluationGroup("eg1").feature("meas4").set("unit", "\u00b5m");
model.result().evaluationGroup("eg1").feature("meas4").selection().named("sel4");
model.result().evaluationGroup("eg1").run();
 
double[][] distResult = model.result().evaluationGroup("eg1").getReal();
double distance = distResult[0][0];
String distUnit = model.result().evaluationGroup("eg1").feature("meas4").getString("unit");
debugLog("Distance: "+distance+" "+distUnit);
Note: If you use the Record Code or Record Method tools, the generated code will match the default user interface behavior, it writes all evaluated results into Evaluation Group tables or Table objects. It will not include direct assignments into double[][] arrays or double variables as shown above. The 2D array format is needed because each evaluation feature can compute multiple expressions or perform parametric sweeps.
To account for the circumferential contribution in revolved geometries, set the intvolume flag on a surface measure (and similar for other measures):
model.result().evaluationGroup("eg1").feature("meas2").set("intvolume", true);
This treats the surface integral as a revolved volume.