Comsol Multiphysics Guide


Add to my manuals
246 Pages

advertisement

Comsol Multiphysics Guide | Manualzz
COMSOL Multiphysics
Application Programming Guide
Application Programming Guide
© 1998–2023 COMSOL
Protected by patents listed on www.comsol.com/patents, or see Help>About COMSOL Multiphysics on the File
menu in the COMSOL Desktop for less detailed lists of U.S. Patents that may apply. Patents pending.
This Documentation and the Programs described herein are furnished under the COMSOL Software License
Agreement (www.comsol.com/sla) and may be used or copied only under the terms of the license agreement.
COMSOL, the COMSOL logo, COMSOL Multiphysics, COMSOL Desktop, COMSOL Compiler, COMSOL Server,
and LiveLink are either registered trademarks or trademarks of COMSOL AB. All other trademarks are the property
of their respective owners, and COMSOL AB and its subsidiaries and products are not affiliated with, endorsed by,
sponsored by, or supported by those trademark owners. For a list of such trademark owners, see www.comsol.com/
trademarks.
Version: COMSOL 6.2
Contact Information
Visit the Contact COMSOL page at www.comsol.com/contact to submit general inquiries or
search for an address and phone number. You can also visit the Worldwide Sales Offices page at
www.comsol.com/contact/offices for address and contact information.
If you need to contact Support, an online request form is located on the COMSOL Access page
at www.comsol.com/support/case. Other useful links include:
• Support Center: www.comsol.com/support
• Product Download: www.comsol.com/product-download
• Product Updates: www.comsol.com/product-update
• COMSOL Blog: www.comsol.com/blogs
• Discussion Forum: www.comsol.com/forum
• Events: www.comsol.com/events
• COMSOL Video Gallery: www.comsol.com/videos
• Support Knowledge Base: www.comsol.com/support/knowledgebase
Part number: CM020012
Contents
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Syntax Primer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Data Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Declarations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Built-in Elementary Math Functions. . . . . . . . . . . . . . . . . . . . . 15
Control Flow Statements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Important Programming Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Ctrl+Space for Code Completion . . . . . . . . . . . . . . . . . . . . . 19
Recording Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Methods Called from the Model Builder . . . . . . . . . . . . . . . . 24
Global Methods, Form Methods, and Local Methods . . . . . 25
Method Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Introduction to the Model Object . . . . . . . . . . . . . . . . . . . . . . . . 26
Model Object Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Creating a Model Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Creating Model Components and Model Object Nodes . . 29
Get and Set Methods for Accessing Properties . . . . . . . . . . 29
Parameters and Variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Unary and Binary Operators in the Model Object . . . . . . . . 37
Geometry. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Physics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Material. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Study. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
|3
Multiphysics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Working with Model Objects . . . . . . . . . . . . . . . . . . . . . . . . . 51
The Model Object Class Structure. . . . . . . . . . . . . . . . . . . . . 54
The Application Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Shortcuts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Accessing the Application Object. . . . . . . . . . . . . . . . . . . . . . 58
The Name of User Interface Components . . . . . . . . . . . . . . 58
Important Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Get and Set Methods for the Color of a Form Object . . . . 59
General Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
The Main Application Methods. . . . . . . . . . . . . . . . . . . . . . . . 62
Main Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Form Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Data Source. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
AppEvent Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
AppEventHandler Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Method Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Form, Form Object, and Item List Methods . . . . . . . . . . . . . 96
The Built-in Method Library for the Application Builder. . . . . . 98
Model Utility Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
License Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
File Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Operating System Methods. . . . . . . . . . . . . . . . . . . . . . . . . . 110
Email Methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Email Class Methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
GUI-Related Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
4|
GUI Command Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
Debug Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Methods for External C Libraries . . . . . . . . . . . . . . . . . . . . . 131
Progress Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .133
Date and Time Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . .139
Conversion Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .142
Array Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
String Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
Collection Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Model Builder Methods for Use in Add-Ins. . . . . . . . . . . . . 156
Programming Examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Running the Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Visualization Without Solution Data: Grid Datasets. . . . . . 158
Visualization of Points, Curves, and Surfaces . . . . . . . . . . . .160
Reading and Writing Data to File . . . . . . . . . . . . . . . . . . . . . 170
Converting Interpolation Curve Data. . . . . . . . . . . . . . . . . . 193
Plotting Points on a Parametric Surface . . . . . . . . . . . . . . . . 195
Using Selections for Editing Geometry Objects . . . . . . . . .196
Recursion and Recursively Defined Geometry Objects. . . 201
Mesh Information and Statistics. . . . . . . . . . . . . . . . . . . . . . . 205
Accessing Higher-Order Finite Element Nodes . . . . . . . . .206
Accessing System Matrices and Vectors. . . . . . . . . . . . . . . . 209
Data Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
Using Selections in Add-Ins . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Using Built-In Methods from an External Java Library. . . . . 232
Measuring the Java Heap Space Memory. . . . . . . . . . . . . . .233
Time-Limited and Hardware-Locked Applications . . . . . . . 233
Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
|5
6|
Introduction
This book is a guide to writing code for COMSOL models and applications
using the Method Editor. The Method Editor is an important part of the
Application Builder and is available in the COMSOL Desktop environment in
the Windows version of COMSOL Multiphysics. For an introduction to using
the Application Builder and its Form editor and Method Editor, see the book
Introduction to Application Builder.
Writing a method is needed when an action is not already available in the standard
run commands associated with functionality in the model tree nodes of the Model
Builder. A method may, for example, contain loops, process inputs and outputs,
and send messages and alerts to the user of the application.
In the Model Builder, the model tree is a graphical representation of the data
structure that represents a model. This data structure is called the model object
and stores the state of the underlying COMSOL Multiphysics model that is
embedded in an application.
The contents of the application tree in the Application Builder is accessed through
the application object, which is an important part of the model object. You can
write code using the Method Editor to directly access and change the user
interface of a running application, for example, to update button text, icons,
colors, and fonts.
In the COMSOL Multiphysics environment, you use the Java programming
language to write methods, which means that you can utilize the extensive
collection of Java libraries. In addition to the Java libraries, the Application
Builder includes a built-in library for building applications and modifying the
model object. A number of tools and resources are available to help you
automatically create code for methods. For more information on autogeneration
of code, see the book Introduction to Application Builder.
This book assumes no prior knowledge of the Javaprogramming language.
However, some familiarity with a programming language is helpful.
|7
Syntax Primer
If you are not familiar with the Java programming language, read this section to
quickly get up to speed with its syntax. When creating applications, it is useful to
know the basics of Java such as how to use the if, for, and while control
statements. The more advanced aspects of Java will not be covered in this book.
For more detail, see any dedicated book on Javaprogramming or one of the many
online resources. You can also learn a lot by reviewing the methods in the example
applications available in the Application Libraries. Note that the Method Editor
supports Java SE 6 syntax.
Data Types
P RIMITIVE D ATA T YPES
Java contains eight primitive data types, listed in the table below.
DATA TYPE
DESCRIPTION
NUMBER OF BYTES
EXAMPLE
byte
Integer between -127 and 128
1
byte b=33;
char
Unicode character; integer between
0 and 65535 (0 and 216-1)
2
char c=’a’;
char c=97;
short
Integer between -32768 and 32767
(-215-1 and 215-1)
2
short s=-1025;
int
Integer between -231 and 231-1
4
int i=15;
long
Integer between -263 and 263-1
8
long l=15;
float
32-bit floating point number
4
float f =4.67f;
double
64-bit floating point number
8
double d=4.67;
boolean
Boolean with values false or true
N/A
boolean b=true;
Other data types such as strings are classes, which are also referred to as composite
data types.
In methods, you can use any5 of the primitive or composite data types available in
Java and the Java libraries. Many of the Application Builder built-in methods make
use of primitive or composite data types. For example, the timeStamp() method
provides a long integer as its output.
8|
A SSIGNMENTS AND L ITERALS
A few examples of using literals in assignments are:
int i=5; // initialize i and assign the value 5
double d=5.0; // initialize d and assign the value 5.0
boolean b=true; // initialize b and assign the value true
The constants 5, 5.0, and true are literals. Java distinguishes between the literals
5 and 5.0, where 5 is an integer and 5.0 is a double (or float).
U NARY AND B INARY O PERATORS IN M ETHODS (J AVA S YNTAX )
You can perform calculations and operations using primitive data types just like
with many other programming languages. The table below describes some of the
most common unary and binary operators used in Java code.
PRECEDENCE LEVEL
SYMBOL
DESCRIPTION
1
++ --
unary: postfix addition and subtraction
2
++ -- + - !
unary: addition, subtraction, positive sign,
negative sign, logical not
3
* / %
binary: multiplication, division, modulus
4
+ -
binary: addition, subtraction
5
!
Logical NOT
6
< <= > >=
comparisons: less than, less than or equal,
greater than, greater than or equal
7
== !=
comparisons: equal, not equal
8
&&
binary: logical AND
9
||
binary: logical OR
10
?:
conditional ternary
11
= += -= *= /=
%= >>= <<= &=
^= |=
assignments
12
,
element separator in lists
T YPE C ONVERSIONS AND T YPE C ASTING
When programming in Java, conversion between data types is automatic in many
cases. For example, the following lines convert from an integer to a double:
int i; // initialize i
double d; //initialize d
i=41;
|9
d=i; // the integer i is assigned to the double d and d is 41.0
However, the opposite will not work automatically (you will get a compilation
error). Instead you can use explicit type casting as follows:
int i; // initialize i
double d; //initialize d
d=41.0;
i=(int) d; // the double d is assigned to the integer i and i is 41
You can convert between integers and doubles within arithmetic statements in
various ways, however you will need to keep track of when the automatic type
conversions are made. For example:
int i; // initialize i
double d; //initialize d
i=41;
d=14/i; // d is 0
In the last line, 14 is seen as an integer literal and the automatic conversion to a
double is happening after the integer division 14/41, which results in 0.
Compare with:
int i; // initialize i
double d; //initialize d
i=41;
d=14.0/i; // d is 0.3414...
In the last line, 14.0 is seen as a double literal and the automatic conversion to a
double is happening before the division and is equivalent to 14.0/41.0.
You can take charge over the type conversions with explicit casting by using the
syntax (int) or (double):
int i; // initialize i
double d,e; //initialize d and e
i=41;
d=((int) 14.0)/i; // d is 0
e=14/((double) i); // e is 0.3414...
S TRINGS AND J AVA O BJECTS
The String data type is a Java object. This is an example of how to declare a string
variable:
String a="string A";
When declaring a string variable, the first letter of the data type is capitalized. This
is a convention for composite data types (or object-oriented classes).
After you have declared a string variable, a number of methods are automatically
made available that can operate on the string in various ways. Two such methods
are concat and equals as described below, but there are many more methods
10 |
available in the String class. See the online Java documentation for more
information.
Concatenating Strings
To concatenate strings, you can use the method concat as follows:
String a = "string A";
String b = " and string B";
a.concat(b);
The resulting string a is "string A and string B". From an object-oriented
perspective, the variable a is an instance of an object of the class String. The
method concat is defined in the String class and available using the a.concat()
syntax.
Alternatively, you can use the + operator as follows:
a = a + b;
which is equivalent to:
a = "string A" + " and string B";
and equivalent to:
a = "string A" + " " + "and string B";
where the middle string is a string with a single whitespace character.
Comparing Strings
Comparing string values in Java is done with the equals method and not with the
== operator. This is due to the fact that the == operator compares whether the
strings are the same when viewed as class objects and does not consider their
values. The code below demonstrates string comparisons:
boolean streq = false;
String a = "string A";
String b = "string B";
streq = a.equals(b);
// In this case streq == false
streq = (a == b);
// In this case streq == false
b = "string A";
streq = a.equals(b);
// In this case streq == true
Special Characters
If you would like to store, for example, a double quotation mark or a new line
character in a string you need to use special character syntax preceded by a
| 11
backslash (\). The table below summarizes some of the most important special
characters.
SPECIAL CHARACTER
DESCRIPTION
\'
Single quotation mark
\"
Double quotation mark
\\
Backslash
\t
Tab
\b
Backspace
\r
Carriage return
\f
Form feed
\n
Newline
Note that in Windows the new line character is the composite \r\n whereas in
Linux and macOS \n is used.
The example below shows how to create a string in Windows that you later on
intend to write to file and that consists of several lines.
String contents = "# Created by me\r\n"
+"# Version 1.0 of this file format \r\n"
+"# Body follows\r\n"
+"0 1 \r\n"
+"2 3\r\n"
+"4 5\r\n";
The string is here broken up into several lines in the code for readability. However,
the above is equivalent to the following:
String contents = "# Created by me\r\n# Version 1.0 of this file format \r\n#
Body follows\r\n0 1 \r\n2 3\r\n4 5\r\n";
which is clearly less readable.
A RRAYS
In the application tree, the Declarations node directly supports 1D and 2D arrays
of type string (String), integer (int), Boolean (boolean), or double (double). A
1D array may be referred to as a vector and a 2D array referred to as a matrix,
provided that the array is rectangular. A nonrectangular array is called jagged or
ragged. In methods, you can define higher-dimensional arrays as well as arrays of
data types other than string, integer, Boolean, or double.
1D Arrays
If you choose not to use the Declarations node to declare an array, then you can
use the following syntax in a method:
12 |
double dv[] = new double[12];
This declares a double array of length 12.
The previous line is equivalent to the following two lines:
double dv[];
dv = new double[12];
When a double vector has been declared in this way, the value of each element in
the array will be zero.
To access elements in an array you use the following syntax:
double e;
e = dv[3]; // e is 0.0
Arrays are indexed starting from 0. This means that dv[0] is the first element of
the array in the examples above, and dv[11] is the last element.
You can simultaneously declare and initialize the values of an array by using curly
braces:
double dv[] = {4.1, 3.2, 2.93, 1.3, 1.52};
In a similar way you can create an array of strings as follows:
String sv[] = {"Alice", "Bob", "Charles", "David", "Emma"};
2D Arrays
2D rectangular arrays can be declared as follows:
double dm[][] = new double[2][3];
This corresponds to a matrix of doubles with 2 rows and 3 columns. The row
index comes first.
You can simultaneously declare and initialize a 2D array as follows:
double dm[][] = {{1.32, 2.11, 3.43},{4.14, 5.16, 6.12}};
where the value of, for example, dm[1][0] is 4.14. This array is a matrix since it is
rectangular (it has same number of columns for each row). You can declare a
ragged array as follows:
double dm[][] = {{1.32, 2.11}, {4.14, 5.16, 6.12, 3.43}};
where the value of, for example, dm[1][3] is 3.43.
Copying Arrays
For copying arrays, the following code:
for (int i1 = 0; i1 <= 11; i1++) {
for (int i2 = 0; i2 <= 2; i2++) {
input_array[i1][i2] = init_input_array[i1][i2];
}
}
is not equivalent to the line:
| 13
input_array = init_input_array;
since the last line will only copy by reference.
Instead, you can use the copy method as follows:
input_table = copy(init_input_table);
which allocates a new array and then copies the values.
D e c l a r a ti o n s
Variables defined in the Declarations node in the application tree are directly
available as global variables in a method and need no further declarations.
Variables declared in methods will have local scope unless you specify otherwise.
The Declarations node directly supports integers (int), doubles (double), and
Booleans (boolean). In addition, strings are supported (see “Strings and Java
Objects” on page 10). In the Declarations node, variables can be scalars, 1D arrays,
and 2D arrays.
14 |
To simplify referencing form objects as well as menu, ribbon, and toolbar items by
name, you can create shortcuts with a custom name. These names are available in
the Declarations node under Shortcuts. They are directly available in methods along
with the other global variables defined under Declarations. For more information
on shortcuts, see “Shortcuts” on page 56.
F ORM D ECLARATIONS
Variables can also be defined as Form Declarations under each respective form node
in the application tree.
Form declarations can be of the types Scalar, Array 1D, Array 2D and Choice List.
Global declarations are exposed to all user-interface components of the application
whereas form declarations are only exposed to the form that they are defined in
and the form objects within that form. Form declarations are used to limit the
scope of variables and thereby logically separate the different parts of an
application.
Built-in Elementary Math Functions
Elementary math functions for use in methods are available in the Java math
library. Some examples:
double a = Math.PI;
// the mathematical constant pi
double b = Math.sin(3*a); // trigonometric sine function
double c = Math.cos(4*a); // trigonometric cosine function
double d = Math.random(); // random number uniformly distributed in [0,1)
double e = Math.exp(2*a); // exponential function
double f = Math.log(1+e); // natural base e logarithm
double g = Math.pow(10,3); // power function
double h = Math.log10(2.5); // base 10 logarithm
double k = Math.sqrt(81.0); // square root
There are several more math functions available in the Java math library. For
additional information, see any Java book or online resource.
| 15
Control Flow Statements
Java supports the usual control flow statements if-else, for, and while. You can
use the Language Elements tool to insert template code corresponding to a number
of control flow, of or block, statements.
The following examples illustrate some of the most common uses of control flow
statements.
T HE IF-ELSE S TATEMENT
This is an example of a general if-else statement:
if (a < b) {
alert("Value too small.");
} else {
alert("Value is just right.");
}
Between curly braces {} you can include multiple lines of code, each terminated
with a semicolon. If you only need one line of code, such as in the example above,
this shortened syntax is available:
if (a < b)
alert("Value too small.");
else
alert("Value is just right.");
16 |
T HE F OR S TATEMENT
Java supports several different types of for statements. This example uses the
perhaps most conventional syntax:
// Iterate i from 1 to N:
int N = 10;
for (int i = 1; i <= N; i++) {
// Do something
}
An alternative syntax is shown in the example on page 66 where the loop is over
all form objects in a list of form objects:
for (FormObject formObject : app.form("form1").formObject()) {
if ("Button".equals(formObject.getType())) {
formObject.set("enabled", false);
}
}
where the local iteration variable looped over is formObject of the type, or class,
FormObject. The collection of objects, in this case
app.form("form1").formObject(), can be an array or other types of lists of
objects. Using this syntax, the iteration variable loops over all entries in the
collection, from start to finish. Another example can be found on page 97.
T HE W HILE S TATEMENT
This example shows a while statement.
double t = 0, h = 0.1, tend = 10;
while(t < tend) {
// do something with t
t = t + h;
}
For a more advanced example of a while statement, see “Creating and Removing
Model Tree Nodes” on page 42.
Note that Java also supports do-while statements.
T HE W ITH S TATEMENT
When writing methods in the Method Editor, in addition to the standard Java
control flow statement, there is also an optional with statement that can be used
to make Application Builder code more compact and easier to read (you enable
this in File>Preferences). A simple example is shown below:
// Set the global parameter L to a fixed value
with(model.param());
set("L", "10[cm]");
endwith();
The code above is equivalent to:
| 17
model.param().set("L", "10[cm]");
In this case using the with statement has limited value since just one parameter is
assigned but for multiple assignments readability increases. See “Parameters and
Variables” on page 35 for an example with multiple assignments.
Note that the with statement is only available when writing code in the Method
Editor. It is not available when using the COMSOL API for use with Java. You
can turn off the use of with statements in the section for Methods in Preferences.
The method descr returns the variable description for the last parameter or
variable in a with statement:
with(model.param());
set("L", "10[cm]");
String ds = descr("L");
endwith();
Assuming that the parameter description of the parameter L is Length. The string
ds will have the value Length.
E XCEPTION H ANDLING
An exception is an error that occurs at runtime. The Java programming language
has a sophisticated machinery for handling exceptions and each exception
generates an object of an exception class. The most common way to handle
exceptions is by using try and catch, as in the example below.
double d[][] = new double[2][15];
try {
d = readMatrixFromFile("common:///my_file.txt");
} catch (Exception e) {
error("Cannot find the file my_file.txt.");
}
where an error dialog box is shown in case the file my_file.txt is not found in
the application file folder common. See the Java documentation for more
information about using try and catch.
18 |
Important Programming Tools
The Application Builder includes several tools for automatically generating code
as well as debugging. These tools include code completion, Record Method, Record
Code, Convert to New Method, Editor Tools, Language Elements, Copy as Code to
Clipboard, Call Stack, and Variables, and are described in the book Introduction to
Application Builder. These utilities allow you to quickly get up and running with
programming tasks even if you are not familiar with the syntax.
The following sections describes two of the most important tools: code
completion using Ctrl+Space and Record Code. Using these tools will make you
more productive, for example, by allowing you to copy-paste or autogenerate
blocks of code.
Ctrl+Space for Code Completion
While typing code in the Method Editor, the Application Builder can provide
suggestions for code completions. The list of possible completions are shown in a
separate completion list that opens while typing. In some situations, detailed
information appears in a separate window when an entry is selected in the list.
Code completion can always be requested with the keyboard shortcut Ctrl+Space.
Alternatively Ctrl+/ can be used to request code completion, which is useful if
Ctrl+Space is in use by the Windows operating system such as for certain
languages. When accessing parts of the model object, you will get a list of possible
completions, as shown in the figure below:
Select a completion by using the arrow keys to choose an entry in the list and
double-click, or press the Tab or Enter key, to confirm the selection.
If the list is long, you can filter by typing the first few characters of the completion
you are looking for.
| 19
For example, if you enter the first few characters of a variable or method name,
and press Ctrl+Space, the possible completions are shown:
In the example above, only variables that match the string iv are shown. This
example shows that variables local to the method also appear in the completion
suggestions.
You can also use Ctrl+Space to learn about the syntax for the built-in methods that
are not directly related to the model object. Type the name of the command and
use Ctrl+Space to open a window with information on the various calling
signatures available.
Additional information is also available in the form of tool tips that are displayed
when hovering over the different parts of the code.
The Method Editor also supports code completion for properties, including listing
the properties that are available for a given model object feature node, and
providing a list of allowed values that are available for a given property.
The figure below shows an example of code completion for the mesh element size
property, where a list of the allowed values for the predefined element sizes is
presented.
20 |
COMSOL Multiphysics and its add-on modules contain thousands of physics
features that you can learn about by using, for example, Record Code,
Save as>Model File for Java, and code completion. The figure below shows code
completion for a particular feature in the Electric Currents interface.
Recording Code
Click the Record Code button in the Code section of the Method Editor ribbon to
record a sequence of operations that you perform using the model tree, as shown
in the figure below.
Certain operations in the application tree can also be recorded, for example, code
that changes the color of a text label in a running application may be generated.
To record a new method, click the Record Method button in the Main section of
the Home tab.
| 21
While recording code, the COMSOL Desktop windows are surrounded by a red
frame:
22 |
To stop recording code, click one of the Stop Recording buttons in the ribbon of
either the Model Builder or the Application Builder.
By using Data Access, you can set the values of the Heat transfer coefficient and the
External temperature properties of the busbar tutorial model used in the books
Introduction to COMSOL Multiphysics and Introduction to Application
Builder.
To generate similar code using Record Code (Data Access is not used when
recording code), follow these steps:
• Create a simple application based on the busbar model (MPH file).
• In the Model Builder window, in the Developer tab, click Record Method, or
with the Method Editor open, click Record Code.
• Change the value of the Heat transfer coefficient to 5.
• Change the value of the External temperature to 300[K].
• Click Stop Recording.
• If it is not already open, open the method with the recorded code.
The resulting code is listed below:
model.result("pg2").run();
model.component("comp1").physics("ht").feature("hf1").set("h", 5);
model.component("comp1").physics("ht").feature("hf1").set("Text",
"300[K]");
| 23
To generate code corresponding to changes to the application object, use Record
Code or Record Method, then go to the Form editor, and, for example, change the
appearance of a form object. The following code corresponds to changing the
color of a text label from the default Inherit to Blue:
app.form("form1").formObject("textlabel1").set("foreground", "blue");
Built-in methods that changes the application object are only available when
running applications and not when running methods from the Model Builder.
Use the tools for recording code to quickly learn how to interact with the model
object or the application object. The autogenerated code shows you the names of
properties, parameters, and variables. Use strings and string-number conversions
to assign new parameter values in model properties. By using Data Access while
recording, you can, for example, extract a parameter value using get, process its
value in a method, and save it back into the model object using set. For more
information on Data Access, see the Introduction to Application Builder.
Methods Called from the Model Builder
Methods called from the Model Builder directly modify the model object
represented by the Model Builder in the current session. Using methods in this
way can be used to automate modeling tasks that consist of several manual steps.
For example, in a model with multiple studies, you can record code for the process
of first computing Study 1; then computing Study 2, which may be based on the
solution from Study 1; and so on.
To customize the workflow in the Model Builder you can create an add-in based
on methods by using a Method Call, Settings Form, or a ribbon tab. For an
introductory example of using methods from the Model Builder and for
information on how to create add-ins, see the Introduction to Application
Builder.
You can learn certain how to write methods to manipulate the model object by
reading the method code in the add-ins that are available in the Add-in Libraries.
To load an MPH-files from these libraries, browse to the addins folder in the
installation folder. This is typically located at:
C:\Program Files\COMSOL\COMSOL62\COMSOL_Multiphysics\addins
In these examples you can learn how to identify a model component, how to check
the spatial dimension of a model component, how to work with selections, and
more.
24 |
Global Me tho d s, For m Me thod s, and Local Me tho d s
There are global methods, form methods, and local methods. Global methods are
displayed in the application tree and are accessible from all methods and form
objects. Form methods are displayed in the application tree as child nodes to the
form it belongs to. A local method is associated with a form object or event and
can be opened from the corresponding Settings window.
Global methods are exposed to all components of the application whereas form
methods are only exposed to the form that they are defined in and the form objects
within that form. You can use form methods to provide a logical separation of the
different parts of an application.
Me thod Names
A method name has to be a text string without spaces. The string can contain
letters, numbers, and underscores. Java® programming language keywords
cannot be used. The name must not begin by a number (this is also true for the
name of a form object, variable, and method).
A global method cannot have the same name as a form method and vice versa. In
addition, the following names are reserved:
• onActivate
• onClick
• onClose
• onDataChange
• onEvent
• onFocusGained
• onFocusLost
• onLoad
• onPickingChanged
• onStartup
• onShutdown
| 25
Introduction to the Model Object
The model object is the data structure that stores the state of the COMSOL
Multiphysics model. The model object contents are reflected in the COMSOL
Desktop user interface by the structure of the Model Builder and its model tree.
The model object is associated with a large number of methods for setting up and
running sequences of operations such as geometry sequences, mesh sequences,
and study steps. As an alternative to using the Model Builder, you can write
programs in the Method Editor that directly access and change the contents of the
model object.
The model object methods are structured in a tree-like way, similar to the nodes
in the model tree. The top-level methods just return references that support
further methods. At a certain level the methods perform actions, such as adding
data to the model object, performing computations, or returning data.
For a complete list of methods used to edit the model object, see the
Programming Reference Manual. For an introduction to using the Model
Builder, see the book Introduction to COMSOL Multiphysics.
The contents of the application tree in the Application Builder are accessed
through the application object, which is an important part of the model object.
You can write code using the Method Editor to alter, for example, button text,
icons, colors, and fonts in the user interface of a running application.
This section gives an overview of the model object. The section “The Application
Object” on page 56 gives an overview of the application object.
Model Object Tags
In the model tree and when working with the model object from methods, tags
are used as handles to different parts of the model object. These tags can also be
made visible in the Model Builder by first clicking the Model Builder toolbar
menu Model Tree Node Text and then choosing Tag, as shown in the figure below.
26 |
The figures below show an example of a model tree without tags shown in the left
figure and with tags shown in the right figure.
In code, the tags are referenced using double quotes. For example, in the
following line
model.geom("geom1").create("r1", "Rectangle");
geom1 is a tag for a geometry object and r1 is a tag for a rectangle object. The
following sections contain multiple examples of using tags to create and edit parts
of a model object.
The option Name, available in the Model Tree Node Text menu in the Model Builder
toolbar, represents the name used for scoping. The scope names are used to access
the different parts of the model object. This is important, for example, when
working with global variables for defining the constraints and objective functions
| 27
for an optimization study. In the figure below, the variables mass, freq, and
maxStress are referenced by scope names: comp1.mass, comp1.solid.freq, and
comp1.maxStress.
Using scope names avoids name collisions in cases where there are multiple model
components or multiple physics interfaces with identical variable names.
Creating a Model Object
If you create an application using the Model Builder and the Application Builder,
then a model object model is automatically created the first time you enter the
Model Builder. This is then available as a reserved variable name. When using the
Model Wizard, the creation of the model tag is automatically handled.
You can create additional model objects with calls to the createModel method.
Such additional model objects will not be visible in the Model Builder (only model
is).
For more information on working with several model objects, see the section
“Working with Model Objects” on page 51.
28 |
Creating Model Components and Model Object Nodes
A model contains one or more model components. You create a model
component as follows:
model.modelNode().create("comp1");
The component is given a definite spatial dimension when you create a geometry
node:
model.geom().create("geom1", 2);
where the second argument can be 0, 1, 2, or 3, depending on the spatial
dimension. In the example above, the spatial dimension is 2.
In addition to creating model components and geometry nodes, there are create
methods for many of the nodes in the model tree.
Whether the geometry should be interpreted as being axisymmetric or not is
determined by a Boolean property that you can assign as follows:
boolean makeaxi = true;
model.geom("geom1").axisymmetric(makeaxi);
The axisymmetric property is only applicable to models of spatial dimension 1 or
2.
Using the Model Wizard, if you first create a Blank Model and then add a
component using the Model Builder, you will be prompted to choose the
space dimension of the component. This operation will, in addition to
creating a component, also create a geometry and mesh node. For
example, selecting a 2D component corresponds to the following lines of
code:
model.modelNode().create("comp1");
model.geom().create("geom1", 2);
model.mesh().create("mesh1", "geom1");
G e t a n d S e t M e t h o d s f o r A c c e s s i n g P r o p e r ti e s
The get and set methods are used to access and assign, respectively, property
values in the different parts of the model object. To assign individual elements of
a vector or matrix, the setIndex method is used. The property values can be of
the basic data types: String, int, double, and boolean, as well as vectors or
matrices of these types (1D or 2D arrays).
| 29
The get, set, and create methods (described in the previous section) are also
accessible from the model tree by right-clicking and selecting Copy as Code to
Clipboard.
T HE GET M ETHODS
The family of get methods is used to retrieve the values of properties. For
example, the getDouble method can be used to retrieve the value of the
predefined element size property hauto for a mesh and store it in a variable hv:
double hv = model.mesh("mesh1").feature("size").getDouble("hauto");
See the section “Example Code” on page 33 below for more information on the
property hauto.
The syntax for the family of get methods for the basic data types is summarized in
the following table:
TYPE
SYNTAX
String
getString(String name)
String array
getStringArray(String name)
String matrix
getStringMatrix(String name)
Integer
getInt(String name)
Integer array
getIntArray(String name)
Integer matrix
getIntMatrix(String name)
Double
getDouble(String name)
Double array
getDoubleArray(String name)
Double matrix
getDoubleMatrix(String name)
Boolean
getBoolean(String name)
Boolean array
getBooleanArray(String name)
Boolean matrix
getBooleanMatrix(String name)
30 |
All arrays are returned as copies of the data; writing to a retrieved array does not
change the data in the model object. To change the contents of an array in the
model object, use one of the methods set or setIndex.
Automatic type conversion is attempted from the property type to the requested
return type.
T HE SET M ETHOD
The syntax for assignment using the set method is exemplified by this line of
code, which sets the title of a plot group pg1:
model.result("pg1").set("title", "Temperature T in Kelvin");
The first argument is a string with the name of the property, in the above example
"title". The second argument is the value and can be a basic type as indicated by
the table below.
TYPE
SYNTAX
String
set(String name,String val1)
String array
set(String name,new String[]{"val1","val2"})
String matrix
set(String name,new String[][]{{"1","2"},{"3","4"}})
Integer
set(String name,17)
Integer array
set(String name,new int[]{1,2})
Integer matrix
set(String name,new int[][]{{1,2},{3,4}})
Double
set(String name,1.3)
Double array
set(String name,new double[]{1.3,2.3})
Double matrix
set(String name,new double[][]{{1.3,2.3},{3.3,4.3}})
Boolean
set(String name,true)
Boolean array
set(String name,new boolean[]{true,false})
Boolean matrix
set(String name,new boolean[][]{{true, false},{false, false}})
Using the set method for an object returns the object itself. This allows you to
append multiple calls to set as follows:
model.result("pg1").set("edgecolor", "black").set("edges", "on");
The previous line of code assigns values to both the edgecolor and edges
properties of the plot group pg1 and is equivalent to the two lines:
model.result("pg1").set("edgecolor", "black");
model.result("pg1").set("edges", "on");
In this case, the set method returns a plot group object.
| 31
Automatic type conversion is attempted from the input value type to the property
type. For example, consider a model parameter a that is just a decimal number
with no unit. Its value can be set with the statement:
model.param().set("a", "7.54");
where the value "7" is a string. In this case, the following syntax is also valid:
model.param().set("a",7.54);
T HE SET I NDEX M ETHOD
The setIndex method is used to assign a value to a 1D or 2D array element at a
position given by one or two indices (starting from index 0).
The following line illustrates using setIndex with one index:
model.physics("c").feature("cfeq1").setIndex("f", "2.5", 0);
The following line illustrates using setIndex with two indices:
model.physics("c").feature("cfeq1").setIndex("c", "-0.1", 0, 1);
For the setIndex method in general, use one of these alternatives to set the value
of a single element:
setIndex(String name,String value,int index);
setIndex(String name,String value,int index1,int index2);
The name argument is a string with the name of the property. The value argument
is a string representation of the value. The indices start at 0, for example:
setIndex(name,value,2);
sets the third element of the property name to value.
The setIndex method returns an object of the same type, which means that
setIndex methods can be appended just like the set method.
If the index points beyond the current size of the array, then the array is extended
as needed before the element at index is set. The values of any newly created
intermediate elements are undefined.
The method setIndex and set can both be used to assign values in ragged arrays.
For example, consider a ragged array with 2 rows. The code statements:
setIndex(name,new String[]{"1","2","3"},0);
setIndex(name,new String[]{"4","5"},1);
sets the first and second row of the array and are equivalent to the single statement:
set("name",new String[][]{{"1","2","3"},{"4","5"}});
M ETHODS A SSOCIATED WITH S ET AND G ET M ETHODS
For object types for which the set, setIndex, and get methods can be used, the
following additional methods are available, exemplified by the case of a Heat
Transfer in Solids physics interface:
32 |
// String[] properties();
String[] props =
model.component("comp1").physics("ht").feature("solid1").properties();
returns the names of all available properties,
// boolean hasProperty(String name);
boolean b =
model.component("comp1").physics("ht").feature("solid1").hasProperty("k_mat");
returns true if the feature has the named property,
// String[] getAllowedPropertyValues(String name);
String[] vals =
model.component("comp1").physics("ht").feature("solid1").getAllowedPropertyValu
es("k_mat");
returns the allowed values for named properties, if it is a finite set.
E XAMPLE C ODE
The following code block can be used to warn an application’s user of excessive
simulation times based on the element size:
if (model.mesh("mesh1").feature("size").getDouble("hauto") <= 3) {
exp_time = "Solution times may be more than 10 minutes for finer element
sizes.";
}
In the above example, getDouble is used to retrieve the value of the property
hauto, which corresponds to the Element Size parameter Predefined in the Settings
window of the Size node under the Mesh node. This setting is available when the
Sequence type is set to User-controlled mesh, in the Settings window of the Mesh
node.
The following line of code retrieves an array of strings corresponding to the
legends of a 1D point graph.
String[] legends =
model.results("pg3").feature("ptgr1").getStringArray("legends");
The figure below shows an example of a vector of legends in the Settings window
of the corresponding Point Graph.
| 33
The following line of code sets the Dataset dset1 for the Plot Group pg1:
model.result("pg1").set("data", "dset1");
The following lines of code set the anisotropic diffusion coefficient for a Poisson’s
equation problem on a block geometry.
model.geom("geom1").create("blk1", "Block");
with(model.geom("geom1").feature("blk1"));
set("size", new String[]{"10", "1", "1"});
endwith();
model.geom("geom1").run();
with(model.physics("c").feature("cfeq1"));
setIndex("c", "-0.1", 0, 1);
setIndex("c", "-0.2", 0, 6);
setIndex("f", "2.5", 0);
endwith();
The 3-by-3 diffusion coefficient matrix indices follow column-first ordering.
The code below sets the global parameter L to a fixed value.
model.param().set("L", "10[cm]");
The code below sets the material link index to the string variable alloy, defined
under the Declarations node.
model.material("matlnk1").set("link", alloy);
The code below sets the coordinates of a cut point dataset cpt1 to the values of
the 1D array samplecoords[].
with(model.result().dataset("cpt1"));
set("pointx", samplecoords[0]);
set("pointy", samplecoords[1]);
set("pointz", samplecoords[2]);
endwith();
The code below sets the components of a deformation plot.
with(model.result("pg7").feature("surf1").feature("def"));
setIndex("expr", withstru, 0);
setIndex("expr", withstrv, 1);
setIndex("expr", withstrw, 2);
endwith();
The code below sets the title and color legend of a plot group pg2 and then
regenerates the plot.
with(model.result("pg2"));
set("titletype", "auto");
endwith();
with(model.result("pg2").feature("surf1"));
set("colorlegend", "on");
endwith();
model.result("pg2").run();
34 |
Parameters and Variables
This code defines a global parameter L with Expression 0.5[m] and Description
Length:
model.param().set("L", "0.5[m]");
model.param().descr("L", "Length");
There is an alternative syntax using three input arguments:
model.param().set("L", "0.5[m]", "Length");
You can also use the with syntax to set the Expression and Description for several
parameters, for example:
with(model.param());
set("L", "0.5[m]");
descr("L", "Length");
set("wd", "10[cm]");
descr("wd", "Width");
set("T0", "500[K]");
descr("T0", "Temperature");
endwith();
which corresponds to the following Settings window for Global
Definitions>Parameters:
A CCESSING A G LOBAL P ARAMETER
You would typically use the Editor Tools window for generating code for setting
the value of a global parameter. While in the Method Editor, right-click the
parameter and select Set.
To set the value of the global parameter L to 10 cm:
model.param().set("L", "10[cm]");
To get the global parameter L and store it in a double variable Length:
double Length = model.param().evaluate("L");
The evaluation is in this case with respect to the base Unit System defined in the
model tree root node.
| 35
To return the unit of the parameter L, if any, use:
String Lunit=model.param().evaluateUnit("L");
To write the value of a model expression to a global parameter, you typically need
to convert it to a string. The reason is that model expressions may contain units.
Multiply the value of the variable Length with 2 and write the result to the
parameter L including the unit of cm.
Length = 2*Length;
model.param().set("L", toString(Length) + "[cm]");
To return the value of a parameter in a different unit than the base Unit System,
use:
double Length_real = model.param().evaluate("L","cm");
For the case where the parameter is complex valued, the real and imaginary parts
can be returned as a double vector of length 2:
double[] realImag = model.param().evaluateComplex("Ex", "V/m");
For parameters that are numbers without units, you can use a version of the set
method that accepts a double instead of a string. For example, the lines
double a_double = 7.65;
model.param().set("a_param", a_double);
assigns the value 7.65 to the parameter a_param.
V ARIABLES
The syntax for accessing and assigning variables is similar to that of parameters.
For example, the code:
with(model.variable("var1"));
set("F", "150[N]");
descr("F", "Force");
endwith();
assigns the Expression 150[N] to the variable with Name F.
The following code assigns a model expression to the variable f:
with(model.variable("var1"));
set("f", "(1 - alpha)^2/(alpha^3 + epsilon) + 1");
endwith();
and the following code stores the model expression for the same variable in a string
fs.
String fs = model.variable("var1").get("f");
36 |
Unary and Binary Operators in the Model Object
The table below describes the unary and binary operators that can be used when
accessing a model object, such as the model expressions used when defining
parameters, variables, material properties, and boundary conditions, as well as in
expressions used in results for postprocessing and visualization.
PRECEDENCE LEVEL
SYMBOL
DESCRIPTION
1
() {} .
grouping, lists, scope
2
^
power
3
! - +
unary: logical not, minus, plus
4
[]
unit
5
* /
binary: multiplication, division
6
+ -
binary: addition, subtraction
7
< <= > >=
comparisons: less-than, less-than or equal,
greater-than, greater-than or equal
8
== !=
comparisons: equal, not equal
9
&&
logical and
10
||
logical or
11
,
element separator in lists
The following example code creates a variable to indicate whether the effective von
Mises stress exceeds 200 MPa by using the inequality solid.mises>200[MPa]:
model.variable().create("var1");
model.variable("var1").model("comp1");
model.variable("var1").set("hi_stress", "solid.mises>200[MPa]");
The following code demonstrates using this variable in a surface plot:
model.result().create("pg3", "PlotGroup3D");
model.result("pg3").create("surf1", "Surface");
with(model.result("pg3").feature("surf1"));
set("expr", "hi_stress");
endwith();
model.result("pg3").run();
The same plot can be created by directly using the inequality expression in the
surface plot expression as follows:
with(model.result("pg3").feature("surf1"));
set("expr", "solid.mises > 200[MPa]");
endwith();
model.result("pg3").run();
| 37
Geometry
Once the Geometry node is created (see “Creating Model Components and Model
Object Nodes” on page 29) you can add geometric features to the node. For
example, add a square using default position (0, 0) and default size 1:
model.geom("geom1").create("sq1", "Square");
The first input argument "sq1" to the create method is a tag, a handle, to the
square. The second argument "Square" is the type of geometry object.
Add another square with a different position and size:
model.geom("geom1").create("sq2", "Square");
with(model.geom("geom1").feature("sq2"));
set("pos", new String[]{"0.5", "0.5"});
set("size", "0.9");
endwith();
The with statement in the above example is used to make the code more compact
and, without using with, the code statements above are equivalent to:
model.geom("geom1").feature("sq2").set("pos", new String[]{"0.5", "0.5"});
model.geom("geom1").feature("sq2").set("size", "0.9");
Take the set difference between the first and second square:
model.geom("geom1").create("dif1", "Difference");
with(model.geom("geom1").feature("dif1").selection("input"));
set(new String[]{"sq1"});
endwith();
with(model.geom("geom1").feature("dif1").selection("input2"));
set(new String[]{"sq2"});
endwith();
To build the entire geometry, you call the method run for the Geometry node:
model.geom("geom1").run();
The above example corresponds to the following Geometry node settings:
In this way, you have access to the functionality that is available in the geometry
node of the model tree. Use Record Code or any of the other tools for automatic
generation of code to learn more about the syntax and methods for other
geometry operations.
38 |
R EMOVING M ODEL T REE N ODES
You can remove geometry objects using the remove method:
model.geom("geom1").feature().remove("sq2");
Remove a series of geometry objects (circles) with tags c1, c2, ..., c10:
for (int n = 1; n <= 10; n = n+1) {
model.geom("geom1").feature().remove("c"+n);
}
The syntax "c"+n automatically converts the integer n to a string before
concatenating it to the string "c".
To remove all geometry objects:
for (String tag : model.geom("geom1").feature().tags()) {
model.geom("geom1").feature().remove(tag);
}
However, the same can be achieved with the shorter:
model.geom("geom1").feature().clear();
In a similar way, you can remove other model tree nodes.
Me sh
The following line adds a Mesh node, with tag mesh1, linked to the geometry with
tag geom1:
model.mesh().create("mesh1", "geom1");
You can control the mesh element size either by a preconfigured set of sizes or by
giving low-level input arguments to the meshing algorithm.
The following line:
model.mesh("mesh1").autoMeshSize(6);
corresponds to a mesh with Element size set to Coarse. The argument to the
method autoMeshSize ranges from 1-9, where 1 is Extremely fine and 9 is
Extremely coarse.
To generate the mesh, you call the run method for the mesh node:
model.mesh("mesh1").run();
Use Record Code to generate code for other mesh operations.
The code below shows an example where the global mesh parameters have been
changed.
model.mesh("mesh1").automatic(false); // Turn off Physics-controlled mesh
with(model.mesh("mesh1").feature("size"));
set("custom", "on"); //
Use custom element size
| 39
set("hmax", "0.09"); //
Maximum element size
set("hmin", "3.0E-3"); // Minimum element size
set("hgrad", "1.2"); //
Maximum element growth rate
set("hcurve", "0.35"); // Curvature factor
set("hnarrow", "1.5"); // Resolution of narrow regions
endwith();
model.mesh("mesh1").run();
The above example corresponds to the following Mesh node settings:
Note that you can also set local element size properties for individual points,
edges, faces, and domains. Use Record Code or any of the other tools for automatic
generation of code to learn more about the syntax and methods for other mesh
operations.
Physics
Consider analyzing stationary heat transfer in the solid rectangular geometry
shown earlier. To create a physics interface, for Heat Transfer in Solids, use:
model.physics().create("ht", "HeatTransfer", "geom1");
40 |
The first input argument to the create method is a physics interface tag that is
used as a handle to this physics interface. The second input argument is the type
of physics interface. The third input argument is the tag of the geometry to which
the physics interface is assigned.
To set a fixed temperature boundary condition on a boundary, you first create a
TemperatureBoundary feature using the following syntax:
model.physics("ht").create("temp1", "TemperatureBoundary", 1);
The first input argument to create is a feature tag that is used as a handle to this
boundary condition. The second input argument is the type of boundary
condition. The third input argument is the spatial dimension for the geometric
entity that this boundary condition should be assigned to. Building on the
previous example of creating a 2D rectangle, the input argument being 1 means
that the dimension of this boundary is 1 (that is, an edge boundary in 2D).
The next step is to define which selection of boundaries this boundary condition
should be assigned to. To assign it to boundary 1 use:
model.physics("ht").feature("temp1").selection().set(new int[]{1});
To assign it to multiple boundaries, for example 1 and 3, use:
model.physics("ht").feature("temp1").selection().set(new int[]{1, 3});
To set the temperature on the boundary to a fixed value of 400 K, use:
model.physics("ht").feature("temp1").set("T0", "400[K]");
The following lines of code show how to define a second boundary condition for
a spatially varying temperature, varying linearly with the coordinate y:
model.physics("ht").create("temp2", "TemperatureBoundary", 1);
model.physics("ht").feature("temp2").selection().set(new int[]{4});
model.physics("ht").feature("temp2").set("T0", "(300 + 10[1/m]*y)[K]");
The resulting model tree structure is shown in the figure below.
Use Record Code or any of the other tools for automatic generation of code to learn
more about the syntax and methods for other physics interface features and other
physics interfaces.
| 41
C REATING AND R EMOVING M ODEL T REE N ODES
Below is a larger block of code that removes, creates, and accesses physics interface
feature nodes. It uses the Iterator class and methods available in the java.util
package. For more information, see the Java documentation.
String[] flowrate = column1;
String[] Mw = column2;
java.util.Iterator<PhysicsFeature> iterator =
model.physics("pfl").feature().iterator();
while (iterator.hasNext()) {
if (iterator.next().getType().equals("Inlet"))
iterator.remove();
}
if (flowrate != null) {
for (int i = 0; i < flowrate.length; i++) {
if (flowrate[i].length() > 0) {
if (Mw[i].length() > 0) {
int d = 1 + i;
model.physics("pfl").create("inl" + d, "Inlet");
model.physics("pfl").feature("inl" + d).setIndex("spec", "3", 0);
model.physics("pfl").feature("inl" + d).set("qsccm0", flowrate[i]);
model.physics("pfl").feature("inl" + d).set("Mn", Mw[i]);
model.physics("pfl").feature("inl" + d).selection().set(new int[]{d});
}
}
}
}
The need to remove and create model tree nodes is fundamental when writing
methods because the state of the model object is changing each time a model tree
node is run. In the method above, the number of physics feature nodes are
dynamically changing depending on user inputs. Each time the simulation is run,
old nodes are removed first and then new nodes are added.
M a t e r ia l
A material, represented in the Model Builder by a Materials node, is a collection of
property groups, where each property group defines a set of material properties,
material functions, and model inputs that can be used to define, for example, a
temperature-dependent material property. A property group usually defines
properties used by a particular material model to compute a fundamental quantity.
To create a Materials node:
model.material().create("mat1", "Common", "comp1");
You can give the material a name, for example, Aluminum, as follows:
model.material("mat1").label("Aluminum");
42 |
The following lines of code shows how to create a basic material property group
for heat transfer:
with(model.material("mat1").propertyGroup("def"));
set("thermalconductivity", new String[]{"238[W/(m*K)]"});
set("density", new String[]{"2700[kg/m^3]"});
set("heatcapacity", new String[]{"900[J/(kg*K)]"});
endwith();
The built-in property groups have a read-only tag. In the above example, the tag
def represents the property group Basic in the model tree.
The resulting model tree and Material node settings are shown in the figure below.
Note that some physics interfaces do not require a material to be defined. Instead,
the corresponding properties can be accessed directly in the physics interface. This
is also the case if the physics model settings are changed from From material to User
defined. For example, for the Heat Transfer in Solids interface, this setting can be
| 43
found in the Settings window of the subnode Solid, in the sections Heat Conduction,
Solid and Thermodynamics, Solid, as shown in the figure below.
Use Record Code or any of the other tools for automatic generation of code to learn
more about the syntax and methods for materials.
Study
The Study node in the model tree contains one or more study steps, instructions
that are used to set up solvers and solve for the dependent variables. The settings
for the Study and the Solver Configurations nodes can be quite complicated.
Consider the simplest case for which you just need to create a study, add a study
step, and run it.
Building on the example from the previous sections regarding stationary heat
transfer, let’s add a Stationary study step.
model.study().create("std1"); // Study with tag std1
model.study("std1").create("stat", "Stationary");
model.study("std1").run();
The call to the method run automatically generates a solver sequence in a data
structure model.sol and then runs the corresponding solver. The settings for the
solver are automatically configured by the combination of physics interfaces you
have chosen. You can manually change these settings, as shown later in this
section. The data structure model.sol roughly corresponds to the contents of the
Solver Configurations node under the Study node in the model tree.
All low-level solver settings are available in model.sol. The structure
model.study is used as a high-level instruction indicating which settings should
be created in model.sol when a new solver sequence is created.
44 |
For backward compatibility, some of the low-level settings in model.sol are
automatically generated when using Record Code.
The example below shows a somewhat more elaborate case of programming the
study that would be applicable for the stationary heat transfer example shown
earlier. The instructions below more closely resemble the output autogenerated by
using the Record Code option.
First create instances of the Study node (with tag std1) and a Stationary study step
subnode:
model.study().create("std1");
model.study("std1").create("stat", "Stationary");
The actual settings that determine how the study is run are contained in a
sequence of operations in the Solution data structure, with tag sol1, which is
linked to the study:
model.sol().create("sol1");
model.sol("sol1").study("std1");
The following code defines the sequence of operations contained in sol1.
First, create a Compile Equations node under the Solution node to determine which
study and study step will be used:
model.sol("sol1").create("st1", "StudyStep");
model.sol("sol1").feature("st1").set("study", "std1");
model.sol("sol1").feature("st1").set("studystep", "stat");
Next, create a Dependent Variables node, which controls the scaling and initial
values of the dependent variables and determines how to handle variables that are
not solved for:
model.sol("sol1").create("v1", "Variables");
Now create a Stationary Solver node. The Stationary Solver contains the
instructions that are used to solve the system of equations and compute the values
of the dependent variables.
model.sol("sol1").create("s1", "Stationary");
Add subnodes to the Stationary Solver node to choose specific solver types. In this
example, use an Iterative solver:
model.sol("sol1").feature("s1").create("i1", "Iterative");
Add a Multigrid preconditioner subnode:
model.sol("sol1").feature("s1").feature("i1").create("mg1", "Multigrid");
You can have multiple Solution data structures in a study node (such as sol1, sol2,
and so on) defining different sequences of operations. The process of notifying the
study of which one to use is done by “attaching” the Solution data structure sol1
with study std1:
model.sol("sol1").attach("std1");
| 45
The attachment step determines which Solution data structure sequence of
operations should be run when selecting Compute in the COMSOL Desktop user
interface.
Finally, run the study, which is equivalent to running the Solution data structure
sol1:
model.sol("sol1").runAll();
The resulting Study node structure is shown in the figure below. Note that there
are several additional nodes added automatically. These are default nodes and you
can edit each of these nodes by explicit method calls. You can edit any of the nodes
while using Record Code to see the corresponding methods and syntax used.
Q UICK W AY OF U SING A S TUDY
An alternative for quickly using a study in method code is to use:
model.study(studyTag).createAutoSequences("all");
This will generate the solver sequence automatically.
To run the study, you can use:
46 |
model.study(studyTag).run();
For example, in a model with a study that has the study tag std1, the
corresponding code would be:
model.study("std1").createAutoSequences("all");
model.study("std1").run();
M ODIFYING L OW -L EVEL S OLVER S ETTINGS
To illustrate how some of the low-level solver settings can be modified, consider
a case where the settings for the Fully Coupled node are modified. This subnode
controls the type of nonlinear solver used.
The first line below may not be needed depending on whether the Fully Coupled
subnode has already been generated or not (it could have been automatically
generated by code similar to what was shown above).
model.sol("sol1").feature("s1").create("fc1", "FullyCoupled");
with(model.sol("sol1").feature("s1").feature("fc1"));
set("dtech", "auto"); //
The Nonlinear method (Newton solver)
set("initstep", "0.01"); //
Initial damping factor
set("minstep", "1.0E-6"); // Minimum damping factor
set("rstep", "10"); //
Restriction for step-sized update
set("useminsteprecovery", "auto"); // Use recovery damping factor
set("minsteprecovery", "0.75"); //
Recovery damping factor
set("ntermauto", "tol"); //
Termination technique
set("maxiter", "50"); //
Maximum number of iterations
set("ntolfact", "1"); //
Tolerance factor
set("termonres", "auto"); // Termination criterion
set("reserrfact", "1000"); // Residual factor
endwith();
For more information on the meaning of these and other low-level solver settings,
see the Solver section of the Programming Reference Manual.
Changing the low-level solver settings requires that model.sol has first been
created. It is always created the first time you compute a study, however, you can
trigger the automatic generation of model.sol as follows:
model.study().create("std1");
model.study("std1").create("stat", "Stationary");
model.study("std1").showAutoSequences("sol");
where the call to showAutoSequences corresponds to the option Show Default
Solver, which is available when right-clicking the Study node in the model tree.
This can be used if you do not want to take manual control over the settings in
model.sol (the solver sequence) and are prepared to rely on the physics interfaces
to generate the solver settings. If your application makes use of the automatically
generated solver settings, then updates and improvements to the solvers in future
versions are automatically included. Alternatively, the automatically generated
| 47
model.sol can be useful as a starting point for your own edits to the low-level
solver settings.
C HECKING IF A S OLUTION E XISTS
When creating an application it is often useful to keep track of whether a solution
exists or not. The method model.sol("sol1").isEmpty() returns a boolean and
is true if the solution structure sol1 is empty. Consider an application where the
solution state is stored in a string solutionState. The following code sets the
state depending on the output from the isEmpty method:
if (model.sol("sol1").isEmpty()) {
solutionState = "nosolution";
}
else {
solutionState = "solutionexists";
}
Alternatively, solutionState can be initialized to nosolution and the following
code is used to indicate a state change corresponding to the input values having
changed:
if (solutionState.equals("solutionexists")) {
solutionState = "inputchanged";
}
Almost all of the example applications in the Application Libraries use this
technique.
Results
The Results node contains nodes for Datasets, Derived Values, Tables, Plot Groups,
Export, and Reports. As soon as a solution is obtained, a set of Plot Group nodes
are automatically created. In the example of Heat Transfer in Solids, when setting
up such an analysis in the Model Builder, two Plot Group nodes are added
automatically. The first one is a Surface plot of the Temperature and the second one
is a Contour plot showing the isothermal contours. Below you will see how to set
up the corresponding plots manually.
First create a 2D plot group with tag pg1:
model.result().create("pg1", "PlotGroup2D");
Change the Label of the Plot Group:
model.result("pg1").label("Temperature (ht)");
Use the dataset dset1 for the Plot Group:
model.result("pg1").set("data", "dset1");
48 |
Create a Surface plot for pg1 with settings for the color table used, the
intra-element interpolation scheme, and the dataset referring to the parent of the
Surface plot node, which is the pg1 node:
model.result("pg1").feature().create("surf1", "Surface");
model.result("pg1").feature("surf1").label("Surface");
with(model.result("pg1").feature("surf1"));
set("colortable", "ThermalLight");
set("smooth", "internal");
set("data", "parent");
endwith();
Now create a second 2D plot group with contours for the isotherms:
model.result().create("pg2", "PlotGroup2D");
model.result("pg2").label("Isothermal Contours (ht)");
with(model.result("pg2"));
set("data", "dset1");
endwith();
model.result("pg2").feature().create("con1", "Contour");
model.result("pg2").feature("con1").label("Contour");
with(model.result("pg2").feature("con1"));
set("colortable", "ThermalLight");
set("smooth", "internal");
set("data", "parent");
endwith();
Finally, generate the plot for the Plot Group pg1:
model.result("pg1").run();
To find the maximum temperature, add a Surface Maximum subnode to the Derived
Values node as follows:
First create the Surface Maximum node with tag max1:
model.result().numerical().create("max1", "MaxSurface");
Note that in this context the method corresponding to the Derived Values node is
called numerical.
Next, specify the selection. In this case there is only one domain 1:
model.result().numerical("max1").selection().set(new int[]{1});
Create a Table node to hold the numerical result and write the output from max1
to the Table:
model.result().table().create("tbl1", "Table");
model.result().table("tbl1").comments("Surface Maximum 1 {max1} (T)");
model.result().numerical("max1").set("table", "tbl1");
model.result().numerical("max1").setResult();
Use Record Code or any of the other tools for automatic generation of code to learn
more about the syntax and methods for Results.
| 49
Using Parameterized Solutions in Results
The code below changes the visualization of a plot group pg1 by setting the
property looplevel, which controls the solution parameter, to the string variable
svar.
with(model.result("pg1"));
set("looplevel", new String[]{svar});
endwith();
model.result("pg1").run();
The property looplevel has a central role in accessing parameterized solutions.
Its argument is a 1D string array with one index per "loop level" in a study. The
different loop levels correspond to the different nested parameters in a parametric
sweep with multiple parameters.
Loading Data to Tables
By using the loadFile method you can import data into a table and then display
it using a results table form object or a table surface plot. The following example
demonstrates loading data from an Excel file into a table and visualizing the
contents using a table surface plot. The file in this example is assumed to be
imported, in an application, using a file import form object with a file declaration
file1 as the File Destination.
model.result().table("tbl1").loadFile("upload:///file1", "", cells);
/*
The string variable cells contains the spreadsheet selection to be
imported, for example A1:J7.
The following code creates a plot group pg1 with a table surface plot.
This code is not needed if the embedded model already contains a table
and a table surface plot.
*/
model.result().create("pg1", 2);
model.result("pg1").create("tbls1", "TableSurface");
with(model.result("pg1").feature("tbls1"));
set("table", "tbl1");
endwith();
with(model.result("pg1").feature("tbls1"));
set("dataformat", "cells");
endwith();
model.result("pg1").feature("tbls1").create("hght1", "TableHeight");
with(model.result("pg1").feature("tbls1").feature("hght1"));
set("view", "view3");
endwith();
with(model.view("view3").camera());
set("viewscaletype", "manual");
set("xscale", "1");
set("yscale", "1");
set("zscale", "1");
endwith();
50 |
// The following line is needed to update the plot
model.result("pg1").run();
Multiphysics
Some of the physics interfaces define a multiphysics analysis by themselves without
being coupled to any other interface. This is the case when the physics interface is
used for a coupling that is so strong that it does not easily lend itself to be
separated into several physics interfaces. In other cases, a set of single physics
interfaces, typically two, can be combined by the use of the Multiphysics node. For
example, a Joule Heating analysis is defined as the combination of an Electric
Currents interface and a Heat Transfer in Solids interface with an additional
Electromagnetic Heat Source node under the Multiphysics node. The following lines
of code illustrate the corresponding method calls.
model.physics().create("ec", "ConductiveMedia", "geom1");
model.physics().create("ht", "HeatTransfer", "geom1");
model.multiphysics().create("emh1", "ElectromagneticHeatSource", "geom1",
2);
model.multiphysics("emh1").selection().all();
with(model.multiphysics("emh1"));
set("EMHeat_physics", "ec");
set("Heat_physics", "ht");
endwith();
When using the Model Builder to set up a Joule Heating analysis, nodes in addition
to those shown above will be created corresponding to Joule heating in thin shells,
should they exist in the model, and temperature couplings if there are multiple
field variables for electric potential and temperature.
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 model object.
| 51
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:
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 since it is used to retrieve the
model from other methods. Once loaded, the model extmodel exists in the work
space of the current COMSOL Multiphysics or COMSOL Server session. Note
that an MPH file can only contain one model object, so there is no ambiguity on
which model you refer to 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.
52 |
The tag My_Model_1 uniquely identified and retrieved the model object from the
current COMSOL Multiphysics or COMSOL Server session.
To clear the contents of a model object, use the built-in method clearModel.
For a list of model utility methods, see “Model Utility Methods” on page 98.
T URNING O FF AND R ESETTING T HE M ODEL H ISTORY
When running method code in applications or otherwise in order to automate
modeling tasks, the stored model history may become excessively large. The
model history is used, for example, when saving to a Model M-file or Model
Java-file. Because of this, depending on the repetitive nature of your code, you
may need to temporarily turn off model history recording as illustrated by the
following example:
model.hist().disable();
// some code
model.hist().enable();
If you want to reset the model history to an almost minimal sequence of
commands that creates the current state of the model object you can use:
model.resetHist();
In the File menu, this functionality is referred to as Compact History.
L IMITATIONS WITH L OADING AND S AVING M ODELS
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.
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".
| 53
Note that useGraphics exclusively supports the display of plot groups. This
method cannot be used for displaying other graphical elements like geometry or
mesh. Furthermore, 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.
The Model Object Class Structure
For a full description of the class structure and method signatures, see the HTML
document Java Documentation available in the COMSOL Documentation. You
find the Java documentation under COMSOL API for use with Java at the bottom
of the Documentation window.
The figure below shows the document as displayed in a the COMSOL
documentation viewer.
54 |
If you encounter a class that you are unfamiliar with you will get help by a tooltip
as in the figure below for the output of the getView method.
By using the keyboard shortcut Ctrl+1 the correct type declaration is assigned to
the variable as shown in the figure below.
This way you can avoid having to consult the Java Documentation.
| 55
The Application Object
The application object is a part of the model object and is the data structure that
allows access to the user interface features of an application from within a method.
The state of the application object is reflected in the COMSOL Desktop user
interface by the contents of the Application Builder and its application tree.
You can write code using the Method Editor to directly access and change the
features presented in a running application, including button text, icons, colors,
and fonts.
The application object gives you access to a subset of the features and settings
available in the Application Builder. You can use the application object methods
for runtime modifications to the user interface, but not for building a complete
user interface. For building the user interface of an application, you need to use
the Form editor as described in the book Introduction to Application Builder.
This section gives an overview of the application object.
Shortcuts
Form objects and other user interface components are referenced in methods by
using a certain syntax. For example, using the default naming scheme form3/
button5 refers to a button with name button5 in form3 and form2/graphics3
refers to a graphics object with name graphics3 in form2. You can also change
the default names of forms and form objects. For example, if form1 is your main
form then you can change its name to main.
To simplify referencing form objects as well as menu, ribbon, and toolbar items by
name, you can create shortcuts with a custom name. In the Settings window of an
object or item, click the button to the right of the Name field and type the name
of your choice.
56 |
To create or edit a shortcut, you can also use the keyboard shortcut Ctrl+K.
All shortcuts that you create are made available in a Shortcuts node under
Declarations in the application tree.
In the Settings window for Shortcuts shown below, a number of shortcuts were
created for a various form objects.
The shortcuts can be referenced in other form objects or in code in the Method
Editor. The example below shows a shortcut tempVis used as an input argument
to a temperature plot.
| 57
Shortcuts are automatically updated when objects are renamed, moved, copied,
and duplicated. They are available in application methods as read-only Java
variables, similar to string, integer, double, and Boolean declarations.
Using shortcuts is recommended because it avoids the need to update methods
when the structure of the application user interface changes.
Shortcuts can also be created for most objects in the model builder tree.
E XAMPLE C ODE
If the application contains a button named button1 in a form named form1, and
the button has a shortcut named b1, the following two ways to change the button
text to red are equivalent:
b1.set("foreground", "red");
app.form("form1").formObject("button1").set("foreground", "red");
A cce s s ing t he A pplica t i o n O b j ec t
In the Method Editor you can directly access the application object part of the
model object by using the app variable. This variable is a shorthand for
model.app().
The Name of User Inter face Compone n ts
Access the various parts of the application object by using the name of a form
object, form, item, and so on. A name in the application object has the same
function as the tag in the model object omitting the model.app part.
For example, in the line of code
app.form("form1").formObject("button1").set("enabled", false);
the string form1 is the name of a form and button1 is the name of a button.
I m p o r t a n t C l a ss e s
T HE M AIN A PPLICATION C LASS
When working with an application object, the main application class is AppModel,
which is the type of model.app().
58 |
D ECLARATION C LASSES
In addition to the basic data types and shortcut declarations, the Declaration node
may include Choice List and Unit List declarations. The corresponding classes are
ChoiceList and UnitSet. The parent class to ChoiceList and UnitSet is called
DataSource. In addition, Scalar, Array 1D, and Array 2D data types are handled
by the DataSource class. For more information, see “Data Source” on page 89.
M ETHOD C LASS
The Method class is used to represent methods. For more information, see
“Method Class” on page 96.
M AIN U SER I NTERFACE C OMPONENT C LASSES
In an application object, the main user interface components correspond to the
following classes:
• MainWindow
- The class representing the Main Window node in the application tree.
• Form
- The class representing a form.
• FormObject
- The class representing a form object.
• Item
- The class representing, for example, a menu, toolbar, or ribbon item.
• AppEvent
- The class used for application user-interface events.
Each class has a set of associated methods that are used to edit the corresponding
user interface component at runtime. These are described in the following
sections.
In addition to the main user interface component classes, there are also list
versions of the Form, FormObject, and Item classes. These are: FormList,
FormObjectList, and ItemList.
Get and Set Methods for the Color of a Form Object
The get and set methods described in the section “Get and Set Methods for
Accessing Properties” on page 29 are applicable to the model object as well as the
| 59
model.app part of the model object. In addition, the following methods are
available for changing the color of a form object:
NAME
SYNTAX
DESCRIPTION
getColor
int[] getColor(String prop)
Get the value of a color
property as an array of red,
green, and blue values.
setColor
setColor(String prop, int r, int g, int b)
Set a color property using
red, green, and blue values.
Not all methods are applicable to all properties. Use Ctrl+Space to use code
completion to find out what methods are applicable for a certain object, and what
property names and property values are applicable for a certain method.
General Properties
The following table lists properties that are available for several different user
interface components, including form objects. In the table below, a user interface
component is referred to as an object.
PROPERTY
VALUE
DEFAULT
DESCRIPTION
background
String
default
The background color for the
corresponding user interface element.
enabled
true | false
true
If the value is true, the
corresponding object is enabled in
the user interface, which means that
the user can interact with the object.
font
String
default
The font family name. The special
value default means that the font to
use is determined by the parent
object, which is the corresponding
setting in the Settings window of the
Forms node.
fontbold
true | false
false
If true the font uses boldface style.
fontitalic
true | false
false
If true the font uses italic style.
fontunderline
true | false
false
If true the font uses underline style.
60 |
PROPERTY
VALUE
DEFAULT
DESCRIPTION
fontsize
String
-1
The font size in points. The special
value -1 represents the default size,
which means that the size is taken
from the parent object (the Forms
node) or from the system default size
if no parent object defines the size.
foreground
String
default
The foreground color for the
corresponding user interface element.
visible
true | false
true
If the value is true, the corresponding
object is visible in the user interface.
A foreground or background color property is represented by a string value. The
available colors are: black, blue, cyan, gray, green, magenta, red, white, and
yellow, or a custom color may also be defined. The special value default means
that the color is taken from the parent object. Depending on the parent type, this
could mean that default is Inherit or Transparent, referring to the corresponding
setting in the Settings window in the Form editor. An arbitrary RGB color can be
represented by a string of the form rgb(red,green,blue) where red, green, and
blue are integers between 0 and 255. Color properties can also be manipulated
using the getColor and setColor methods to directly access the red, green, and
blue color components. If a color property has the value default, it does not have
red, green, and blue values. In this case, the getColor method returns the array
[0,0,0].
E XAMPLE C ODE
The following example reads the current background color for a form, makes the
color darker, and applies the modified color to the same form.
int[] rgb = app.form("form1").getColor("background");
for (int i = 0; i < 3; i++)
rgb[i] /= 2;
app.form("form1").setColor("background", rgb[0], rgb[1], rgb[2]);
The following line of code sets the background color to black:
app.form("form1").set("background", "black");
The following line of code sets the background color to default which in the case
of the background color property corresponds to the Form editor setting
Transparent.
app.form("form1").set("background", "default");
The following line of code sets the background color to the RGB values 125, 45,
and 43.
app.form("form1").set("background", "rgb(125,45,43)");
| 61
The M a in A pplica t io n Met h o d s
The main application class AppModel has the following methods:
NAME
SYNTAX
DESCRIPTION
declaration
Declaration declaration()
Returns the list of declarations.
declaration
DataSource
declaration(String name)
Returns the declaration object (Scalar, Array 1D,
Array 2D, ChoiceList, or UnitSet) with the
specified name.
event
AppEventHandlerList event()
Returns the list of event handlers.
event
AppEventHandler event(String
name)
Returns the event handler with the specified
name.
form
FormList form()
Returns the list of forms.
form
Form form(String name)
Returns the form with the specified name.
hasProperty
boolean hasProperty(String
name)
Returns true if there is a modifiable property with
the specified name.
mainWindow
MainWindow mainWindow()
Returns the MainWindow object.
The AppModel class has the following properties:
PROPERTY
VALUE
DEFAULT
DESCRIPTION
asktosave
true | false
false
If true, ask user if changes should be saved before
the application is closed.
startmode
edit | run
edit
Determines whether the application is opened
for editing or running when you double-click the
MPH file, including Windows desktop icons.
E XAMPLE C ODE
app.set("asktosave", true);
The following code appends a text string to the application window title.
String oldTitle = app.mainWindow().getString("title");
app.mainWindow().set("title", oldTitle + " modified");
The following examples show how to query the list of declarations in an
application.
// Get the declaration list
Declaration list = app.declaration();
// Get the names of all DataSource objects in the list.
String[] names = list.names();
62 |
// Get the number of DataSource objects in the list.
int size = list.size();
// Get the DataSource with the name "svar".
DataSource src = list.get("svar");
// Get the index within the list of the DataSource with the name "svar".
int index = list.index("svar");
// Get the DataSource at a certain index within the list.
DataSource src = list.get(index);
// Get the DataSource objects defined in a given form.
Declaration formDeclarations = app.form("form1").declaration();
// Iterate over DataSource objects within the list.
for(DataSource dt : list) {
// Get the type of the DataSource.
String type = dt.getType();
}
Main Window
The MainWindow class has the following methods:
NAME
SYNTAX
DESCRIPTION
fileMenu
ItemList fileMenu()
Returns the list of items in the file menu.
fileMenu
Item fileMenu(String
name)
Returns the file menu item with the specified
name.
hasProperty
boolean
hasProperty(String name)
Returns true if there is a modifiable property with
the specified name.
menuBar
ItemList menuBar()
Returns the list of items in the menu bar.
menuBar
Item menuBar(String
name)
Returns the menu bar item with the specified
name.
ribbon
ItemList ribbon()
Returns the list of items in the ribbon.
ribbon
Item ribbon(String name)
Returns the ribbon item with the specified name.
toolBar
ItemList toolBar()
Returns the list of items in the toolbar.
toolBar
Item toolBar(String
name)
Returns the toolbar item with the specified name.
The menuBar and toolBar items are visible in the application user interface if the
menu type is set to Menu bar in the Settings window of the Main Window. The
ribbon and fileMenu items are visible in the user interface if the menu type is set
to Ribbon. It is possible to access and modify items that are not visible based on
| 63
the menu type setting, but doing so will not have any visible effect in the user
interface.
The MainWindow class has the following properties:
PROPERTY
VALUE
DEFAULT
DESCRIPTION
imagetheme
$default |
$light | $dark
$default
Set the color theme for image
export.
showfilename
true | false
true
If true the filename is included in the
window title bar title.
title
String
My application
The text to display in the window
title bar.
theme
$default |
$light | $dark
$default
Set the color theme for the
application user interface.
E XAMPLE C ODE
// Do not show the filename in the application user interface window bar.
app.mainWindow().set("showfilename", false);
// Set dark application theme.
app.mainWindow().set("theme", "$dark");
// Set light image export theme.
app.mainWindow().set("imagetheme", "$light");
Form
The Form class has the following methods:
NAME
SYNTAX
DESCRIPTION
declaration
DataSource declaration(String name)
Returns a form declaration
object (Scalar, Array 1D,
Array 2D, or ChoiceList) with
the specified name.
formObject
FormObjectList formObject()
Returns the list of form
objects.
formObject
FormObject formObject(String name)
Returns the form object with
the specified name.
getName
String getName()
Returns the name of this
form.
getParentForm
Form getParentForm()
Returns the parent form that
contains this form. Useful for
local cards in a card stack.
64 |
NAME
SYNTAX
DESCRIPTION
hasProperty
boolean hasProperty(String name)
Returns true if there is a
modifiable property with the
specified name.
method
MethodList method()
Returns the list of methods.
method
Method method(String name)
Gets a method with the
specified name.
The Form class has the following properties:
PROPERTY
VALUE
DEFAULT
DESCRIPTION
icon
String
""
The name of the background image.
Valid values are images defined in
Images>Libraries node in the
application tree.
iconhalign
left | center |
right | fill |
repeat
center
Horizontal alignment for the
background image.
iconvalign
top | center |
bottom | fill |
repeat
center
Vertical alignment for the background
image.
title
String
Form N
The form title for an integer N.
E XAMPLE C ODE
app.form("form1").set("icon", "compute.png");
app.form("form1").formObject("button1").set("enabled", false);
DataSource ds = app.form("form1").declaration("var");
For examples of how to use the declaration method, see “The Main Application
Methods” on page 62.
Form Object
The FormObject class has the following methods:
NAME
SYNTAX
DESCRIPTION
declaration
DataSource
declaration(String
name)
Returns a form declaration object (Scalar, Array
1D, Array 2D, or ChoiceList) with the specified
name.
expanded
void expanded(String
form, boolean
expanded)
Sets the expanded state of the form when using
the sections type.
| 65
NAME
SYNTAX
DESCRIPTION
form
FormList form()
For a CardStack form object, returns the list of
local cards.
form
Form form(String name)
For a CardStack form object, returns the local card
with the specified name.
getName
String getName()
Returns the name of this form object.
getParentForm
Form getParentForm()
Returns the parent form that contains this form
object.
getType
String getType()
Returns the form object type name, as defined in
the following sections.
getValue
Value getValue()
Returns the current value of a FormObject when
applicable. The method is supported by the
following types of FormObjects: input field, toggle
button, check box, combo box, file import, array
input, radio button, selection input, text, list box,
table, slider, knob.
hasProperty
boolean
hasProperty(String
name)
Returns true if there is a modifiable property with
the specified name.
item
ItemList item()
For a Toolbar, Graphics, or Table form object,
returns the list of user-defined buttons.
item
Item item(String name)
For a Toolbar, Graphics, or Table form object,
return the user-defined button with the specified
name.
visible
void visible(String
form, boolean visible)
Sets the visible state of the form.
Most form objects have one or more of the properties listed in “General
Properties” on page 60. A form object has a certain property if the corresponding
setting is available in the Form editor. Additional properties are supported for
several types of form objects. The general properties that are supported and any
additional properties for form objects are listed in the following sections.
E XAMPLE C ODE
The following code loops over all buttons and disables them:
for (FormObject formObject : app.form("form1").formObject()) {
if ("Button".equals(formObject.getType())) {
formObject.set("enabled", false);
}
}
The getType method retrieves the type of form object. In the above example the
type of form object is Button and the statement
66 |
"Button".equals(formObject.getType()) represents a string comparison
between the output of the getType method and the string "Button".
For an example of using getValue, see “Data Validation” on page 214.
The following table lists all form object types that can be returned by getType:
FORM OBJECT TYPE
ArrayInput
Hyperlink
SelectionInput
Button
Image
Slider
CardStack
InformationCardStack
Spacer
CheckBox
InputField
Table
ComboBox
Knob
Text
DataDisplay
Line
TextLabel
Equation
ListBox
ToggleButton
FileImport
Log
Toolbar
Form
MessageLog
Unit
FormCollection
ProgressBar
Video
Gauge
RadioButton
WebPage
Graphics
ResultsTable
A RRAY I NPUT
Property
Value
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
Default
Description
See “General Properties” on page 60.
Example Code
app.form("form1").formObject("arrayinput1").set("enabled", false);
| 67
B UTTON
PROPERTY
VALUE
DEFAULT
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
icon
String
""
The button icon. Valid values are
images defined in "Images>Libraries" in
the Application Builder.
text
String
Generated
automatically
The button text. The text must not be
an empty string.
tooltip
String
""
The button tooltip text.
In the Form editor, if a button has its Size setting set to Large, it always displays its
text property. If the button is Small, it either displays the icon or the text
according to the following rule: if the icon property is empty, the text is
displayed, if the icon property is not empty, the icon is displayed.
Example Code
app.form("form1").formObject("button1").set("enabled", false);
C ARD S TACK
PROPERTY
VALUE
enabled
visible
DEFAULT
DESCRIPTION
See “General Properties” on
page 60.
Example Code
app.form("form1").formObject("cardstack1").set("visible", false);
To access objects in a local card, either use shortcuts or use the form method:
app.form("form1").formObject("cardstack1").form("card1")
.formObject("button1").set("enabled", false);
68 |
C HECK B OX
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
fontunderline
foreground
visible
DESCRIPTION
See “General Properties” on
page 60.
text
String
Generated
automatically
The check box label text.
tooltip
String
""
The check box tooltip text.
Example Code
app.form("form1").formObject("checkbox1").set("tooltip", "tooltip text");
C OMBO B OX
PROPERTY
VALUE
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DEFAULT
DESCRIPTION
See “General Properties” on
page 60.
Example Code
app.form("form1").formObject("combobox1").set("foreground", "blue");
| 69
D ATA D ISPLAY
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on
page 60.
exponent
superscript | E
superscript
When set to superscript,
exponents are displayed using
superscript font. When set to E,
exponents are displayed using
the character E followed by the
exponent value.
notation
auto | scientific
| decimal
auto
When the value is scientific,
numbers are always displayed
using scientific notation. When
the value is decimal, numbers
are never displayed using
scientific notation. When the
value is auto, the notation
depends on the size of the
number.
precision
Integer
4
The number of significant digits
that are displayed.
showunit
true | false
true
Controls if the unit is displayed
in addition to numerical values.
tooltip
String
""
The tooltip text.
Example Code
app.form("form1").formObject("datadisplay1")
.setColor("background", 192, 192, 192);
70 |
E QUATION
PROPERTY
VALUE
DEFAULT
enabled
fontsize
foreground
visible
equation
DESCRIPTION
See “General Properties” on
page 60.
String
The string in LaTeX syntax
defining the equation.
Example Code
app.form("form1").formObject("equation1").set("visible", false);
F ILE I MPORT
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
buttontext
String
Browse...
Text to display on the button that opens
the file browser.
dialogtitle
String
File import
Text to display as dialog title for the file
browser dialog. Also displayed as a tooltip
for the FileBrowser form object.
filetypes
String[]
{"ALLFILES"}
Defines the list of file types that can be
selected in the file browser.
Example Code
app.form("form1").formObject("fileimport1")
.set("filetypes", new String[]{"ALL2DCAD"});
F ORM
A form used as a subform does not have any modifiable properties.
| 71
F ORM C OLLECTION
PROPERTY
VALUE
DEFAULT
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
formvisible
boolean[]
Array with each
entry having the
value true
Defines the visible state of forms in a
form collection.
sectionexpanded
boolean[]
Array with each
entry having the
value true
Defines the expanded state of forms in
a form collection when using the
sections type.
To modify the active pane, change the corresponding declaration variable.
Example Code
This line of code changes the font:
app.form("form1").formObject("collection1").set("font", "Arial");
The expanded state of sections in form collections can be controlled by:
app.form("form1").formObject("formcollection1").expanded("form2", false);
The expanded method is only supported by form collections which use sections.
The first argument is the tag of the form which is represented by the section. The
second argument determines if the sections should be expanded or collapsed.
72 |
G RAPHICS
PROPERTY
VALUE
DEFAULT
DESCRIPTION
datapick
true | false
false
If true, data picking is enabled in the
graphics form object.
datapicktarget
ProbeFeature |
GraphicsData
enabled
visible
source
Defines where the picked data is
stored. Valid values are probe features
and GraphicsData declarations.
See “General Properties” on page 60.
ModelEntity
Defines the type of model entity (Plot
Group, Geometry, Mesh, Explicit
Selection or Player Animation) used
to plot in the graphics form object.
Example Code
This line of code displays plot group 5 (pg5) in the graphics object graphics1 in
the form with the name Temperature:
app.form("Temperature").formObject("graphics1")
.set("source", model.result("pg5"));
The following line of code using useGraphics is equivalent to the above example:
useGraphics(model.result("pg5"), "Temperature/graphics1");
Either method changes the source of the graphics form object and then plots the
contents.
To clear the contents of a graphics object, use:
app.form("Temperature").formObject("graphics1")
.set("source", (ModelEntity) null);
or equivalently
useGraphics(null, "Temperature/graphics1");
The code below displays the mesh in the model tree node mesh1 in the graphics
object graphics1 contained in the card of a card stack:
app.form("mesh").formObject("cardstack1").form("card1")
.formObject("graphics1").set("source", model.mesh("mesh1"));
The code below enables data picking for a graphics object and sets the data picking
target to a domain point probe:
app.form("form1").formObject("graphics1").set("datapick", true);
app.form("form1").formObject("graphics1").set("datapicktarget",
model.component("comp1").probe("pdom1"));
If a shortcut graphics1 has been created for the graphics object and a shortcut
pdom1 has been created for the probe object, the above can be shortened to:
| 73
graphics1.set("datapick", true);
graphics1.set("datapicktarget", pdom1);
H YPERLINK
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
visible
DESCRIPTION
See “General Properties” on page 60.
text
String
Generated
automatically
The text to display on the HyperLink
form object.
url
String
""
The URL to open when the HyperLink
is activated.
Example Code
with (app.form("form1").formObject("hyperlink1"));
set("text", "COMSOL");
set("url", "www.comsol.com");
endwith();
I MAGE
PROPERTY
VALUE
DEFAULT
enabled
visible
icon
DESCRIPTION
See “General Properties” on page 60.
String
cube_large.png
Defines the icon name to display in the
Image form object. Valid values are
images defined in the Images>Libraries
node in the application tree.
Example Code
app.form("form1").formObject("image1").set("icon", "compute.png");
74 |
I NFORMATION C ARD S TACK
PROPERTY
background
enabled
font
fontbold
fontitalic
fontsize
fontunderline
visible
VALUE
DEFAULT
DESCRIPTION
See “General Properties” on page
60.
Example Code
app.form("form1").formObject("infocard1").set("fontunderline", true);
| 75
I NPUT F IELD
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on
page 60.
editable
true | false
true
If true then the text in the input
field can be edited by the user.
exponent
superscript | E
superscript
When set to superscript,
exponents are displayed using
superscript font. When set to E,
exponents are displayed using
the character E followed by the
exponent value.
inputformatting
on | off
off
If the value is on, then numerical
values in the input field are
formatted according to the
exponent, notation, and
precision properties. When the
user is editing the text in the
input field, the formatting is
temporarily disabled so that the
original text can be edited.
maxdouble
double
1000
The maximum allowed double
value. This property is only
accessible when the Filter setting
is set to Double and the
corresponding check box is
enabled in the Data Validation
section.
mindouble
double
0
The minimum allowed double
value. This property is only
accessible when the Filter setting
is set to Double and the
corresponding check box is
enabled in the Data Validation
section.
76 |
PROPERTY
VALUE
DEFAULT
DESCRIPTION
maxinteger
Integer
1000
The maximum allowed integer
value. This property is only
accessible when the Filter setting
is set to Integer and the
corresponding check box is
enabled in the Data Validation
section.
mininteger
Integer
0
The minimum allowed integer
value. This property is only
accessible when the Filter setting
is set to Integer and the
corresponding check box is
enabled in the Data Validation
section.
notation
auto | scientific
| decimal
auto
When the value is scientific,
numbers are always displayed
using scientific notation. When
the value is decimal, numbers
are never displayed using
scientific notation. When the
value is auto, the notation
depends on the size of the
number.
precision
Integer
4
The number of significant digits
displayed.
tooltip
String
""
The tooltip displayed when the
mouse pointer is located over
the input field.
Example Code
app.form("form1").formObject("inputfield1").set("precision", 6);
| 77
L INE
PROPERTY
VALUE
DEFAULT
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
text
String
""
Text to display on the line. The text is only
displayed for horizontal lines that have Include
divider text enabled in the Line object Settings
window.
thickness
Integer
1
The line thickness.
linecolor
String
default
The line color.
Example Code
app.form("form1").formObject("line1").set("text", "divider text");
app.form("form1").formObject("line1").set("thickness", 10);
app.form("form1").formObject("line1").set("linecolor", blue);
L IST B OX
PROPERTY
VALUE
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DEFAULT
DESCRIPTION
See “General Properties” on page 60.
Example Code
app.form("form1").formObject("listbox1").set("foreground", "red");
To change the list box contents, modify the corresponding choice list:
app.declaration("choicelist1").appendListRow("new value", "new name");
78 |
L OG
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
Example Code
app.form("form1").formObject("log1").set("fontsize", "20");
M ESSAGE L OG
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
Example Code
app.form("form1").formObject("messages1").set("background", "gray");
P ROGRESS B AR
PROPERTY
VALUE
enabled
visible
DEFAULT
DESCRIPTION
See “General Properties” on page 60.
To create and update progress information see “Progress Methods” on page 133.
Example Code
app.form("form1").formObject("progressbar1").set("visible", false);
| 79
R ADIO B UTTON
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
fontunderline
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
To change the display name for a radio button, modify the value in the
corresponding choice list.
For a choice list that is used by a radio button, it is not possible to change the value
of any row, or to add or remove rows. Only the display name can be changed.
Example Code
app.form("form1").formObject("radiobutton1").set("fontitalic", true);
app.declaration("choicelist1").setDisplayName("new name", 0);
R ESULTS T ABLE
PROPERTY
VALUE
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
source
DEFAULT
DESCRIPTION
See “General Properties” on page 60.
TableFeature
Set the contents of the results table.
To change the contents of the results table use the method useResultsTable or
evaluateToResultsTable. See also “GUI-Related Methods” on page 117.
Example Code
app.form("form1").formObject("resultstable1").set("visible", true);
app.form("form1").formObject("resultstable1").set("source",
model.result().table("tbl2"));
useResultsTable(model.result().table("tbl2"), "/form1/resultstable1");
80 |
S ELECTION I NPUT
PROPERTY
VALUE
DEFAULT
DESCRIPTION
active
true | false
false
The active property controls
whether the Selection Input is active.
Changing the property value selects
or deselects the Activate Selection
button in the Selection Input.
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
See “General Properties” on page 60.
graphics
FormObject
Defines the graphics form object to
use when the selection form object is
active.
source
SelectionFeature
Defines the model selection the
selection form object is connected to.
Example Code
app.form("form1").formObject("selectioninput1").set("graphics",
"graphics1");
Alternatively, if there are shortcuts sel1 and g1 to the selectioninput1 and
graphics1 form objects:
sel1.set("graphics", g1);
To change the model selection, assuming sel1 is a shortcut to the selection input
form object:
sel1.set("source", model.selection("sel2"));
| 81
S LIDER
PROPERTY
VALUE
DEFAULT
enabled
visible
DESCRIPTION
See “General Properties” on page 60.
max
Double
1
The largest possible slider value.
min
Double
0
The smallest possible slider value.
steps
Integer
5
The number of steps between the min and
max values. The number of tick marks is one
more than the number of steps.
tooltip
String
""
The tooltip text.
The min value is allowed to be larger than the max value, in which case the slider
behaves as if the values were swapped. The smallest value always corresponds to
the left side of the slider.
Example Code
app.form("form1").formObject("slider1").set("min", 1);
app.form("form1").formObject("slider1").set("max", 12);
app.form("form1").formObject("slider1").set("steps", 11);
82 |
K NOB
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page
60.
exponent
superscript | E
superscript
When set to superscript,
exponents are displayed using
superscript font. When set to E,
exponents are displayed using the
character E followed by the exponent
value.
knobmaincolor
String
default
The main background color.
knobradius
Integer
knobradiusmanual
on | off
When knobradiusmanual has the
value on, this is the value of the knob.
The tick marks appear outside this
radius.
off
When the value is off the radius is
calculated automatically. When the
value is on, the radius is given by the
knobradius property.
knobsecondarycolor
String
default
The secondary background color.
labelformatting
true | false
false
When true this setting enables
custom label formatting.
max
Double
1
The largest possible knob value.
min
Double
0
The smallest possible knob value.
mouse
distance |
vertical |
circular
distance
The kind of mouse movement to
change the knob value. When set to
distance, the distance the mouse is
moved, either horizontally or
vertically, controls the value. When
set to vertical, only the vertical
distance the mouse is moved controls
the value. When set to circular, the
value is changed using a circular
motion.
needlecolor
String
default
The color of the knob's needle.
| 83
PROPERTY
VALUE
DEFAULT
DESCRIPTION
notation
auto |
scientific |
decimal
auto
When the value is scientific,
numbers are always displayed using
scientific notation. When the value is
decimal, numbers are never
displayed using scientific notation.
When the value is auto, the notation
depends on the size of the number.
precision
Integer
4
The number of significant digits that
are displayed.
scale
none | marks |
markslabels |
marksalllabels
marks
To control whether the scale should
have tick marks or labels. When set
to none, the knob has no tick marks
or labels. When set to marks, the
knob has tick marks but no labels.
When set to markslabels, the knob
has tick marks and labels for the
minimum and maximum values.
When set to marksalllabels, the
knob has ticks marks and all major
ticks has a label.
steps
Integer
5
The number of steps between the
min and max values. The number of
tick marks is one more than the
number of steps.
tooltip
String
""
The tooltip text.
Example Code
app.form("form1").formObject("knob1").set("min", 1);
app.form("form1").formObject("knob1").set("max", 12);
app.form("form1").formObject("knob1").set("steps", 11);
S PACER
A spacer object does not have any modifiable properties.
84 |
T ABLE
PROPERTY
VALUE
DEFAULT
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
headers
String[]
Generated
automatically
Column headers.
showheaders
boolean
Generated
automatically
Show column headers.
To change the contents of the table, change the declaration variables or model
entities the table is displaying.
Example Code
app.form("form1").formObject("table1").set("enabled", false);
T EXT
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
editable
on | off
off
If the value is on, the text can be
edited by the user of the application. If
the value is off, the text can only be
changed programmatically.
textalign
left | center |
right
left
Defines how the text is aligned within
the text area.
wrap
on | off
on
If the value is on, word wrapping is
used to break lines that are too long
to fit within the text area. If the value
is off, long lines may not be
completely visible.
Example Code
app.form("form1").formObject("text1").set("textalign", "center");
| 85
T EXT L ABEL
PROPERTY
VALUE
DEFAULT
DESCRIPTION
background
enabled
font
fontbold
fontitalic
fontsize
fontunderline
foreground
visible
See “General Properties” on
page 60.
text
String
Generated
automatically
The text to display in the
label when the label is not in
multiline mode.
textmulti
String
Generated
automatically
The text to display in the
label when the label is in
multiline mode.
Example Code
app.form("form1").formObject("textlabel1").set("text", "custom text");
T OGGLE B UTTON
PROPERTY
VALUE
DEFAULT
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
icon
String
""
The button icon. Valid values are images
defined in "Images>Libraries" in the
Application Builder.
text
String
Generated
automatically
The button text. The text must not be
an empty string.
tooltip
String
""
The button tooltip text.
A button with size large always displays the text, a button with size small displays
either the icon or the text. If the icon property is empty, the text is displayed. If
the icon property is not empty, the icon is displayed.
Example Code
app.form("form1").formObject("togglebutton1").set("icon",
"about_information.png");
86 |
T OOLBAR
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
Example Code
app.form("form1").formObject("toolbar1").set("background", "gray");
U NIT
PROPERTY
VALUE
DEFAULT
background
enabled
font
fontbold
fontitalic
fontsize
foreground
visible
DESCRIPTION
See “General Properties” on page 60.
Example Code
app.form("form1").formObject("unit1").set("visible", false);
V IDEO
PROPERTY
VALUE
visible
DEFAULT
DESCRIPTION
See “General
Properties” on page 60.
Example Code
app.form("form1").formObject("video1").set("visible", false);
| 87
W EB P AGE
PROPERTY
VALUE
file
String
DEFAULT
DESCRIPTION
html
String
report
ReportFeature
or String
type
page | url |
type | report
page
Determines which property is
used to specify the browser
display contents.
url
String
https://www.comsol.com
The URL to display.
The file to display. File scheme
syntax is supported.
<html></html>
The HTML code to display.
The report feature to display.
visible
See “General Properties” on
page 60.
Example Code
app.form("form1").formObject("webpage1").set("type", "report");
app.form("form1").formObject("webpage1").set("report", "rpt1");
model.result().report("rpt1");
model.result().report("rpt1").run();
Item
Item objects represent items, toggle items, user defined buttons in Toolbar,
Graphics, and Table form objects, and submenus in the menu bar, toolbar, ribbon,
and file menus. The following methods are available:
NAME
SYNTAX
DESCRIPTION
getParentItem
Item getParentItem()
Returns the parent item, or null for a
top-level item.
hasProperty
boolean
hasProperty(String
name)
Returns true if there is a modifiable property
with the specified name.
item
ItemList item()
Returns the list of subitems.
item
Item item(String name)
Returns the subitem with the specified name.
88 |
The Item class contains the following properties:
PROPERTY
VALUE
DEFAULT
DESCRIPTION
enabled
on | off
on
If the value is on, the item can be activated
by the user. If the value is off, the item
cannot be activated.
icon
String
Generated
automatically
The icon name. Valid values are images
defined in Images>Libraries in the
Application Builder.
text
String
Generated
automatically
The text for a menu or ribbon item.
title
String
Generated
automatically
The title text for a menu or submenu.
tooltip
String
""
The tooltip text.
visible
on | off
on
Controls whether the item is visible or not.
In order for an item to be enabled, the enabled property needs to have the value
on for the item itself as well as for all of its parents. In other words, disabling an
item also disables all of its subitems.
Item objects also include separators. However, separators do not have any
accessible properties.
Item objects for user-defined buttons do not have the title and tooltip
properties. For Table form objects, predefined items such as “move up” and
“move down” do not have any modifiable properties.
E XAMPLE C ODE
app.mainWindow().menuBar("menu1").set("title", "new title");
app.mainWindow().menuBar("menu1").item("toggle_item1").set("text",
"test");
Data Source
A DataSource object is either a Scalar, Array 1D, Array 2D, ChoiceList a
UnitSet or a GraphicsData.
| 89
S CALAR , A RRAY 1D, AND A RRAY 2D M ETHODS
The methods described in the following table are applicable for Scalar, Array 1D,
and Array 2D objects (of types String, Boolean, Integer, Double). These
methods are used to manipulate such variable objects during runtime.
NAME
SYNTAX
DESCRIPTION
getBoolean
boolean getBoolean()
Gets the Boolean value stored in
the data source.
getBooleanArray
boolean[] getBooleanArray()
Gets the Boolean array value
stored in the data source.
getBooleanMatrix
boolean[][] getBooleanMatrix()
Gets the Boolean matrix value
stored in the data source.
getDouble
double getDouble()
Gets the double value stored in
the data source.
getDoubleArray
double[] getDoubleArray()
Gets the double array value
stored in the data source.
getDoubleMatrix
double[][] getDoubleMatrix()
Gets the double matrix value
stored in the data source.
getInt
int getInt()
Gets the int value stored in the
data source.
getIntArray
int[] getIntArray()
Gets the int array value stored in
the data source.
getIntMatrix
int[][] getIntMatrix()
Gets the int matrix value stored
in the data source.
getString
String getString()
Gets the String value stored in
the data source.
getStringArray
String[] getStringArray()
Gets the String array value stored
in the data source.
getStringMatrix
String[][] getStringMatrix()
Gets the String matrix value
stored in the data source.
set
set(boolean value)
set(boolean[] value)
set(boolean[][] value)
set(double[] value)
set(double[] value)
set(double[][] value)
set(int value)
set(int[] value)
set(int[][] value)
set(String value)
set(String[] value)
set(String[][] value)
Set the value stored in the data
source. Available methods
depend on the type of the
underlying declaration.
90 |
E XAMPLE C ODE
// Get a scalar double declaration.
DataSource ds = app.declaration("var");
// The 'var' declaration is a scalar double so we use the getDouble method
// to read its value.
double cur = ds.getDouble();
// Modifying the local field 'cur' does not affect the value stored in the
// data source 'ds'.
cur = cur + 1;
// Set the value of the data source.
ds.set(cur);
C HOICE L IST AND U NIT S ET M ETHODS
The methods described in the following table are applicable for both ChoiceList
and UnitSet objects. These methods are used to manipulate choice lists and unit
sets during runtime.
NAME
SYNTAX
DESCRIPTION
addListRow
addListRow(String value, String
displayName, int row)
Inserts a new row with the given
value and display name at the
specified row (0-based).
appendListRow
appendListRow(String value, String
displayName)
Inserts a new row with the given
value and display name at the end
of the list.
getValue
String getValue(int row)
Returns the value for the given
row (0-based).
getDisplayName
String getDisplayName(int row)
Returns the display name for the
given row (0-based).
getDisplayName
String getDisplayName(String value)
Returns the display name for the
row with the given value.
getValues
String[] getValues()
Returns all values as an array.
getDisplayNames
String[] getDisplayNames()
Returns all display names as an
array.
removeListRow
removeListRow(int row)
Removes the given row (0-based)
from the list.
setListRow
setListRow(String value, String
displayName, int row)
Sets the value and display name
for the given row (0-based). If the
row is equal to the length of the
list, a new row is added.
setList
setList(String[] values, String[]
displayNames)
Sets all of the values and display
names, replacing the contents of
the choice list or unit set.
| 91
NAME
SYNTAX
DESCRIPTION
setValue
setValue(String value, int row)
Sets the value for the given row
(0-based). If the row is equal to
the length of the list, a new row is
added with the value and an
empty display name.
setDisplayName
setDisplayName(String displayName, int
row)
Sets the display name for the
given row (0-based). If the row is
equal to the length of the list, a
new row is added with the
display name and an empty value.
Example Code
The code below adds the string Aluminum 3004 to a choice list. Note that the
choice list index starts at 0, whereas the material tags start at 1 (mat1, mat2, mat3,
and mat4).
ChoiceList choiceList = getChoiceList("choicelist1");
choiceList.setListRow("mat4", "Aluminum 3004", 3);
For more information on using choice lists for changing materials, see the book
Introduction to Application Builder.
U NIT S ET M ETHODS
When the object is a UnitSet the following additional methods are also available:
NAME
SYNTAX
DESCRIPTION
getString
String getString()
Returns the currently selected value for the unit
set.
getString
String
getString(String
unitList)
Returns the selected unit for the given unit list.
set
set(String value)
Switch unit for the unit set.
G RAPHICS D ATA M ETHODS
When the object is a GraphicsData the following methods are available:
NAME
SYNTAX
DESCRIPTION
getString
String getString(String name)
Returns the value of the specified
property as a string.
getDouble
double getDouble(String name)
Returns the value of the specified
property as a double value.
92 |
NAME
SYNTAX
DESCRIPTION
getDoubleArray
double[] getDoubleArray(String
name)
Returns the value of the specified
property as a double array value.
set
set(String name, String value)
set(String name, double value)
set(String name, double[] value)
Sets a new value for the property
with the specified name.
The GraphicsData class has the following properties:
PROPERTY
VALUE
DEFAULT
DESCRIPTION
coord
double[]
0, 0, 0
Point location of picked data. Array of
1, 2, 3, or 6 elements, corresponding
to 1D, 2D, 3D, or Smith plot,
respectively.
depth
double
0
Point along a line when data picking in
a domain. Valid values are between 0
and 1, inclusive.
edim
domain |
boundary
domain
Geometric entity level.
eval
double
0
Evaluated value of picked data.
method
pointnormal |
pointdir |
twopoints |
none
pointnormal
Method of selecting a point in a 3D
geometry.
twopoint
first | second
first
Point being picked in the twopoints
line entry method.
Example Code
The following code enables data picking for the graphics1 object, connects it to
the graphicsdata1 object and sets some properties on the graphicsdata1 object:
app.form("form1").formObject("graphics1").set("datapick", true);
app.form("form1").formObject("graphics1").set("datapicktarget",
app.declaration("graphicsdata1"));
app.declaration("graphicsdata1").set("edim", "boundary");
app.declaration("graphicsdata1").set("method", "pointdir");
AppEvent Class
The AppEvent class contains information regarding an application user-interface
events. The event field, accessible in application methods, is initialized with an
| 93
instance of this class when a FormObject event is being triggered. The
getUserControl method retrieves the FormObject where the event originated.
NAME
SYNTAX
DESCRIPTION
getNewValue
Value getNewValue()
New value corresponding to a form object having
an On data change event type.
getOldValue
Value getOldValue()
Old value corresponding to a form object having
an On data change event type.
getUserControl
IPropertyAccess
getUserControl()
To make it convenient to access a user control that
triggered an event the method
event.getUserControl returns the form or form
object that triggered the event. The return type of
the methods is IPropertyAccess and the object
can be cast to an instance of the FormObject or
Form class depending on what type of event is
triggered.
V ALUE C LASS
The methods getNewValue and getOldValue returns an object of type Value
which has methods according to the table below. The Value class represents a
value which can be retrieved in different formats depending on the form object.
For example, an event triggered from an input field is a scalar variable (boolean,
int, double, or String). This means that only a subset of the methods in the table
below is valid for a particular form object event.
NAME
SYNTAX
DESCRIPTION
getBoolean
boolean getBoolean()
Gets the Boolean value.
getBooleanArray
boolean[]
getBooleanArray()
Gets the Boolean array value.
getBooleanMatrix
boolean[][]
getBooleanMatrix()
Gets the Boolean matrix value.
getDouble
double getDouble()
Gets the double value.
getDoubleArray
double[]
getDoubleArray()
Gets the double array value.
getDoubleMatrix
double[][]
getDoubleMatrix()
Gets the double matrix value.
getInt
int getInt()
Gets the int value.
getIntArray
int[] getIntArray()
Gets the int array value.
getIntMatrix
int[][]
getIntMatrix()
Gets the int matrix value.
getString
String getString()
Gets the string value.
94 |
NAME
SYNTAX
DESCRIPTION
getStringArray
String[]
getStringArray()
Gets the string array value.
getStringMatrix
String[][]
getStringMatrix
Gets the string matrix value.
Example Code
The following code exemplifies using the event field, for the class AppEvent, and
the methods getNewValue and getOldValue:
String value = event.getNewValue().getString();
String oldValue = event.getOldValue().getString();
For an example of using the event field and its associated methods, see “Data
Validation” on page 214.
AppEventHandler Class
This class represents the Event and Timer nodes found under Events in the
Application Builder. An AppEventHandler object can be either an Event or a
Timer.
The following methods are available for an AppEventHandler object:
NAME
SYNTAX
DESCRIPTION
getName
String getName()
Returns the name of this event handler.
getType
String getType()
Returns the event handler type name: Event or
Timer.
An AppEventHandler object has the following properties:
PROPERTY
VALUE
DEFAULT
DESCRIPTION
delay
double
1
The interval of a Timer in seconds.
enabled
See “General Properties” on page 60.
Example code
The following code sets the interval of a Timer to 1 hour:
app.event("timer1").set("delay","1[h]");
| 95
Me thod Class
The Method class is used to represent a method. The following method is available
for a Method object:
NAME
SYNTAX
DESCRIPTION
run
Object run(Object... input)
Run the method with the specified
input parameters.
The following code exemplifies using a Method object:
// Get a Method object representing a Form Method.
Method m = app.form("form1").method("method1");
// The method takes a String parameter and returns a double.
double res = (Double) m.run("input");
Form, Form Object, and Item List Methods
The AppEventHandlerList, Declaration, FormList, FormObjectList, and
ItemList classes have the following methods:
NAME
SYNTAX
PURPOSE
get
Form get(int index)
FormObject get(int
index)
Item get(int index)
DataSource get(int
index)
AppEventHandler get(int
index)
Returns the object at a certain index.
get
Form get(String name)
FormObject get(String
name)
Item get(String name)
DataSource get(String
name)
AppEventHandler
get(String name)
Returns the object with a given name.
index
int index(String name)
Returns the 0-based position of the object with a
given name in the list.
names
String[] names()
Returns an array of names for all objects in the
list.
size
int size()
Returns the number of objects in the list.
96 |
Additionally the FormList class has the following methods:
NAME
SYNTAX
PURPOSE
hasProperty
boolean
hasProperty(String name)
Returns true if there is a modifiable property with
the specified name.
It is also possible to use a list in an enhanced for loop to operate on all objects in
the list.
In the following example, the background color is set to red in all forms, by
looping over all forms:
for (Form f : app.form()) { // app.form() is of type FormList
f.set("background", "red");
}
| 97
The Built-in Method Library for the Application Builder
This section lists built-in methods available in the Method Editor in addition to
the methods that operate on the model and application objects. For more
information on the model object and its methods, refer to earlier sections of this
book and the Programming Reference Manual. For more information on the
application object, see “The Application Object” on page 56. Some of the listings
have associated example code but for more extensive programming examples, see
“Programming Examples” on page 158.
The syntax rules are those of the Java® programming language. Note that each line
of code needs to end with a semicolon (;), but the semicolon is omitted in the
listings below.
Model Utility Methods
The following table summarizes the model utility methods for querying, creating,
loading, and saving model objects. The model object is stored on the MPH file
format.
NAME
SYNTAX
DESCRIPTION
clearModel
clearModel(Model model)
clearModel(String tag)
Remove everything from the
model except for the application
part and the things you can
change on the root node in the
Model Builder, such as thumbnail,
comment, and author.
createModel
Model createModel(String tag)
Creates a new model with the
given tag.
createModel
Model createModel()
Create a new model with a
unique tag.
getModel
Model getModel(String tag)
Returns the model with a
specified tag.
loadModel
Model loadModel(String location)
Loads a model with a specified
tag from a file on the file system
or in a database.
loadModel
Model loadModel(String tag, String
location)
Loads a model from a file. The
model is given a unique tag.
98 |
NAME
SYNTAX
DESCRIPTION
loadProtectedModel
Model loadProtectedModel(String tag,
String filename, String password)
Loads a password protected
model with a specified tag from a
file.
loadProtectedModel
Model loadProtectedModel(String
filename, String password)
Loads a password protected
model from a file. The model is
given a unique tag.
loadRecoveryModel
Model loadRecoveryModel(String tag,
String foldername)
Loads a model from a recovery
directory/folder structure.
loadRecoveryModel
Model loadRecoveryModel(String
foldername)
Loads a model from a recovery
directory/folder structure. The
model is given a unique tag.
modelTags
String[] modelTags()
Returns an array of model tags
for all loaded models, including
the embedded model.
removeModel
removeModel(String tag)
removeModel(Model model)
Removes a model. The
embedded model cannot be
removed.
saveModel
saveModel(Model model, String
filename)
Saves a model to a file. The
filename can be a file scheme
path or (if allowed by security
settings) a server file path.
uniqueModeltag
String uniqueModeltag(String prefix)
Returns a model tag that is not in
use.
getComsolVersion
getComsolVersion()
Returns the current software
version as a string.
For the built-in application methods loadModel(<location>) and
loadModel(<tag>, <location>) the <location> argument scan either be the
path to an MPH-file found on the file system or a model location URI referencing
a model version in a Model Manager database.
Example Code
The code below loads a model using loadModel, presented in the table above. It
extracts the x-, y-, and z-coordinates of all mesh nodes and stores them in a 2D
double array coords[3][N], where N is the number of mesh nodes. The individual
x-,y-, and z- coordinates are available as the length-N 1D arrays coords[0],
coords[1], coords[2], respectively. (The node locations can be plotted by using
the Cut Point 3D dataset in combination with a 3D Point Trajectories plot.)
Model extmodel = loadModel("C:\\Paul\\pacemaker_electrode.mph");
SolverFeature step = extmodel.sol("sol1").feature("v1");
XmeshInfo xmi = step.xmeshInfo();
| 99
XmeshInfoNodes nodes = xmi.nodes();
double[][] coords = nodes.coords();
For more information on methods operating on the model object, see the
Programming Reference Manual.
Note that to make the code above platform independent for use in an application
you can instead use the common application file folder:
Model extmodel = loadModel("common:///pacemaker_electrode.mph");
License Methods
The license methods read the license number and check out or test the licenses of
the current session or for an MPH file. This functionality can be used, for example,
to limit the use of an application to one or a few license numbers or to dynamically
adapt functionality of an application depending on which product licenses are
available.
NAME
SYNTAX
DESCRIPTION
checkoutLicense
boolean checkoutLicense(String...
product)
Checks out licenses for all
specified products. If not all
licenses can be checked out, no
licenses are checked out.
checkoutLicenseFor
File
boolean checkoutLicenseForFile(String
file)
Checks out licenses required to
use a given MPH file. If not all
required licenses can be checked
out, no licenses are checked out.
checkoutLicenseFor
FileOnServer
boolean
hasLicenseForFileOnServer(String
file);
Checks out licenses required to
use a given MPH file. If not all
required licenses can be checked
out, no licenses are checked out.
getLicenseNumber
String license = getLicenseNumber()
Returns a string with the license
number for the current session.
hasProduct
boolean hasProduct(String... product)
Returns true if the COMSOL
installation contains the software
components required for running
the specified products. Code
completion can be used to get a
list of valid product names.
100 |
NAME
SYNTAX
DESCRIPTION
hasProductForFile
boolean hasProductForFile(String file)
Returns true if the COMSOL
installation contains the software
components required for running
the products required by a given
MPH file.
hasProductForFileO
nServer
boolean
checkoutLicenseForFileOnServer(String
file);
Returns true if the COMSOL
installation contains the software
components required for running
the products required by a given
MPH file.
E XAMPLE CODE
The following code tries to check out a license for the AC/DC Module, and
displays an error message if it fails:
if (!checkoutLicense("ACDC"))
alert("There seems to be a problem. Please contact Alice and Bob at
123-456-7890.");
You can use this to customize license error messages by calling a method
containing this code before any add-on product specific features are used by the
application.
In the Application Builder root node you can further select the Ignore license errors
during launch check box. This will make it possible for users to start an application
regardless of which licenses are available. However, this will not work if the
application, at startup, uses features required by an add-on product. The
application has to be created in such a way that the add-on product specific
features are not used in the startup phase of the application but instead are
deferred to later in the workflow.
To emulate a scenario where there are not enough available licenses you can, for
example, disable one or more products in the Licensed and Used Products in Session
dialog box, available from the File menu in the COMSOL Desktop environment.
The following code tests if the COMSOL installation has the capability to use an
MPH file:
boolean ok = hasProductForFile(“model_file.mph”);
Note that even if hasProductForFile return true, in a floating network license
situation there may not be any free licenses to check out. If your application is
going to process several MPH files and you want to make sure all licenses are
checked out before the processing starts, instead use the checkoutLicense or
checkoutLicenseForFile methods.
| 101
L ICENSE F EATURE S TRINGS
The following table contains the product strings for all add-on products in the
COMSOL 6.2 product suite that can be used by the method checkoutLicense:
PRODUCT/FEATURE
FEATURE NAME
AC/DC Module
ACDC
Acoustics Module
ACOUSTICS
Battery Design Module
BATTERYDESIGN
CAD Import Module
CADIMPORT
CFD Module
CFD
Chemical Reaction Engineering Module
CHEM
Corrosion Module
CORROSION
Design Module
DESIGN, CADIMPORT
ECAD Import Module
ECADIMPORT
Electrochemistry Module
ELECTROCHEMISTRY
Electrodeposition Module
ELECTRODEPOSITION
Fatigue Module
FATIGUE
File Import for CATIA V5
CATIA5
Fuel Cell & Electrolyzer Module
FUELCELLANDELECTROLYZER
Geomechanics Module
GEOMECHANICS
Heat Transfer Module
HEATTRANSFER
Liquid & Gas Properties Module
LIQUIDANDGASPROPERTIES
LiveLink™ for AutoCAD®
LiveLink™ for PTC® Creo® Parametric™
LLAUTOCAD, CADIMPORT
LiveLink™ for Excel®
LLEXCEL
LiveLink™ for Inventor®
LiveLink™ for MATLAB®
LLINVENTOR, CADIMPORT
LiveLink™ for Revit®
LLREVIT, CADIMPORT
LiveLink™ for Simulink®
LLSIMULINK
LiveLink™ for Solid Edge®
LLSOLIDEDGE, CADIMPORT
LLCREOPARAMETRIC,
CADIMPORT
LLMATLAB
LiveLink™ for SOLIDWORKS®
LLSOLIDWORKS, CADIMPORT
Material Library
MATLIB
MEMS Module
MEMS
Metal Processing Module
METALPROCESSING
102 |
PRODUCT/FEATURE
FEATURE NAME
Microfluidics Module
MICROFLUIDICS
Mixer Module
MIXER
Molecular Flow Module
MOLECULARFLOW
Multibody Dynamics Module
MULTIBODYDYNAMICS
Nonlinear Structural Materials Module
NONLINEARSTRUCTMATERIALS
Optimization Module
OPTIMIZATION
Particle Tracing Module
PARTICLETRACING
Pipe Flow Module
PIPEFLOW
Plasma Module
PLASMA
Polymer Flow Module
POLYMERFLOW
Porous Media Flow Module
POROUSMEDIAFLOW
Ray Optics Module
RAYOPTICS
RF Module
RF
Rotordynamics Module
ROTORDYNAMICS
Semiconductor Module
SEMICONDUCTOR
Structural Mechanics Module
STRUCTURALMECHANICS
Subsurface Flow Module
SUBSURFACEFLOW
Uncertainty Quantification Module
UQ
Wave Optics Module
WAVEOPTICS
File Methods
File methods are used to read and write data to a file or portions of a file. Note
that higher-level techniques for reading and writing to files are available from
within the Application Builder user interface. For more information, see the book
| 103
Introduction to Application Builder and “GUI Command Methods” on page
129.
NAME
SYNTAX
DESCRIPTION
readFile*
String readFile(String name)
Returns the contents in the given
filename as a string. The string
name is the absolute path to a file
or a path given by the file scheme
syntax.
openFileStreamReader*
CsReader
openFileStreamReader(String
name)
Returns a CsReader that can be
used to read line-by-line or
character-by-character from the
given filename.
openBinaryFileStreamReader*
CsBinaryReader
openBinaryFileStreamReader(Stri
ng name)
Returns a CsBinaryReader that
can be used to read from the
given file byte-by-byte.
readMatrixFromFile*
double[][]
readMatrixFromFile(String name)
Reads the contents of the given
file into a double matrix. The file
has the same spreadsheet type
format as available in the model
tree Export node.
readStringMatrixFromFile*
String[][]
readStringMatrixFromFile(String
name)
Reads the contents of the given
file into a string matrix. The file
has the same spreadsheet type
format as available in the model
tree Export node.
readCSVFile*
String[][] readCSVFile(String
name)
Reads a file with
comma-separated values (CSV
file) into a string matrix. Expects
file to use the RFC 4180 format
for CSV.
writeFile*
writeFile(String name, String
contents)
Writes the given string contents
to the given filename.
writeFile*
writeFile(String name, String
contents, boolean append)
Writes the given string contents
to the given filename. If append is
true, then the contents are
appended instead of overwritten.
writeFile*
writeFile(String name,
double[][] data)
Writes the array data to the
given file. The spreadsheet format
is used, which means it can be
read by readMatrixFromFile.
104 |
NAME
SYNTAX
DESCRIPTION
writeFile*
writeFile(String name,
double[][] data, boolean
append)
Writes the array data to the
given file. The spreadsheet format
is used, which means it can be
read by readMatrixFromFile. If
append is true, then the contents
are appended instead of
overwritten.
writeFile*
writeFile(String name,
String[][] data)
Writes the array data to the
given file. The spreadsheet format
is used, which means it can be
read by
readStringMatrixFromFile.
writeFile*
writeFile(String name,
String[][] data, boolean
append)
Writes the array data to the
given file. The spreadsheet format
is used, which means it can be
read by
readStringMatrixFromFile. If
append is true, then the contents
are appended instead of
overwritten.
openFileStreamWriter*
CsWriter
openFileStreamWriter(String
name)
Returns a CsWriter that can
write to the given file.
openFileStreamWriter*
CsWriter
openFileStreamWriter(String
name, boolean append)
Returns a CsWriter that can
write to the given file. If append is
true, then the contents are
appended instead of overwritten.
openBinaryFileStreamWriter*
CsBinaryWriter
openBinaryFileStreamWriter(Stri
ng name)
Returns a CsBinaryWriter that
can be used to write to the given
file byte-by-byte.
openBinaryFileStreamWriter*
CsBinaryWriter
openBinaryFileStreamWriter(Stri
ng name, boolean append)
Returns a CsBinaryWriter that
can be used to write to the given
file byte by byte. If append is true,
then the contents are appended
instead of overwritten.
writeCSVFile*
writeCSVFile(String name,
String[][] data)
Writes the given string array
data to a CSV file. The RFC 4180
format is used for the CSV.
| 105
NAME
SYNTAX
DESCRIPTION
writeCSVFile*
writeCSVFile(String name,
String[][] data, boolean
append)
Writes the given string array
data to a CSV file. The RFC 4180
format is used for the CSV. If
append is true, then the contents
are appended instead of
overwritten.
writeCSVFile*
writeCSVFile(String name,
double[][] data)
Writes the given double array
data to a CSV file. The RFC 4180
format is used for the CSV.
writeCSVFile*
writeCSVFile(String name,
double[][] data, boolean
append)
Writes the given double array
data to a CSV file. The RFC 4180
format is used for the CSV. If
append is true, then the contents
are appended instead of
overwritten.
exists*
boolean exists(String name)
Tests whether a file with the given
name exists.
If the name is not a file scheme
path name or an absolute path,
then the method first finds out
whether a file with file scheme
path embedded:/// + argument
exists. If such a file does not exist,
then it tests whether there is a
file with a matching name in the
current working directory.
deleteFile*
deleteFile(String file)
Delete a file with the given name
if it exists. The file is deleted on
the server,. The name can use a
file scheme path.
copyFile*
copyFile(String sourceFile,
String destFile)
Copies a file on the server. Both
the source and target names can
use file scheme paths.
106 |
NAME
SYNTAX
DESCRIPTION
importFile
importFile(String name)
importFile(String name,
String[] fileTypes)
Displays a file browser dialog box
and uploads the selected file to
the file declaration with the given
name. After this, the uploaded file
can be accessed with upload:///
<name>. The optional fileTypes
argument can be used to filter
which file types are available for
selection in the file browser. The
easiest way to get a list of valid
file types is to use code
completion in the Method Editor.
The file types defined by File Type
declarations can also be used.
importFile
importFile(ModelEntity entity,
String name)
Displays a file browser dialog box
and uploads the selected file to
the Filename text field in the
given model object entity. This
defines an input file that the
application will need at a later
stage. For example, the Filename
of an interpolation function
accessed with
model.func(’<tag>’)). The
uploaded file can be accessed
with upload:///<tag>/
filename.
writeExcelFile*
writeExcelFile(String name,
String[][] data)
Writes the given string array
data starting from the first cell in
the first sheet of an Excel file.
This method requires LiveLink™
®
for Excel .
writeExcelFile*
writeExcelFile(String name,
String sheet, String cell,
String[][] data)
Writes the given string array
data starting from the specified
cell in the specified sheet of an
Excel file. This method requires
LiveLink™ for Excel®.
readExcelFile*
String[][] readExcelFile(String
name)
Reads the first sheet of an Excel
file, starting from the first cell,
into a String[][]. This method
requires LiveLink™ for Excel®.
| 107
NAME
SYNTAX
DESCRIPTION
readExcelFile*
String[][] readExcelFile(String
name, String sheet, String
cell)
Reads the specified sheet of an
Excel file, starting from the
specified cell, into a String[][].
This method requires LiveLink™
®
for Excel .
getFilePath*
String getFilePath(String name)
Returns the absolute server file
path of the server proxy file
corresponding to a certain file
scheme path, or null if the server
proxy file for the given path does
not exist.
This method can be used to pass
the path to, for example, a file
using the temp:/// scheme to
external code or an application.
In addition, this method is used to
retrieve the filename of an
uploaded file when using the file
scheme upload:///inputFile,
for example by using a File
declaration together with a File
Import form object.
getClientFileName
String getClientFileName(String
name)
Returns the original name of an
uploaded file on the client file
system (or null if there is no
uploaded file matching the given
file scheme path).
This method is only useful for
providing user interface feedback.
For example, to get information
on which uploaded file is being
used. There is no guarantee that
the original file would still exist on
the client or even that the
current client would be the same
as the original client.
108 |
NAME
SYNTAX
DESCRIPTION
getClientFilePath
String getClientFilePath(String
name)
Returns the original path of an
uploaded file on the client file
system (or null if there is no
uploaded file matching the given
file scheme path). Returns only
the filename part of the path
when called from an application
running in a web browser.
This method is only useful for
providing user interface feedback.
For example, to get information
on which uploaded file is being
used. There is no guarantee that
the original file would still exist on
the client or even that the
current client would be the same
as the original client.
createDirectory*
createDirectory(String name)
Creates a file directory name, see
examples below in the Example
Code section.
All file methods in the table above that are marked with an asterisk (*) support
working with data files stored in a Model Manager database. Note that all of these
methods automatically load the data file to a working copy directory located on
the same computer that COMSOL Multiphysics runs on. This means that any
updates made to a data file is not persisted to the database unless explicitly saved
as a new file version via the Model Manager database API.
E XAMPLE C ODE
This line of code copies the uploaded file file1 to the temp folder with new
filename file2.mphbin and then prompts the user to save the file to any location.
copyFile("upload:///file1", "temp:///file2.mphbin");
fileSaveAs("temp:///file2.mphbin");
This line of code deletes the file file2.mphbin from the temp folder.
deleteFile("temp:///file2.mphbin");
This line of code creates a directory in the user folder, as specified in Preferences.
createDirectory("user:///a/b");
This line of code creates a directory in the Temp folder under C:.
createDirectory("C:\\Temp\\a\\b");
| 109
Note that the method fileSaveAs returns a boolean that indicates if saving the
file was successful or not. Saving a file will fail if, for example, the user does not
have access to the target folder.
Op e ra ti n g S y st e m Met h o d s
Operating system methods are used for accessing operating system information
and commands from an application.
NAME
SYNTAX
DESCRIPTION
executeOSCommand
String executeOSCommand(String
command, String... params)
Executes the OS command with
the given command (full path)
and parameters. Execution times
out after a default 180 seconds.
Returns everything the process
printed to its out stream as a
string. When applicable, the
command is run server side.
executeOSCommand
String executeOSCommand(String
command, int timeoutSec, String
params...)
Executes the OS command with
the given command (full path)
and parameters. Returns
everything the process printed to
its out stream as a string. The
execution is forcibly stopped after
timeoutSec seconds if the
command has not finished. To
disable the timeout functionality,
timeoutSec value 0 can be used.
When applicable, the command
is run server side.
fileOpen
fileOpen(String name)
Opens the file represented by
name with the associated
program on the client. Also see
the section “Example code”.
getUser
String username = getUser()
Returns the username of the user
that is running the application. If
the application is not run from
COMSOL Server, then the value
of the preference setting
General>Username>Name is
returned.
110 |
NAME
SYNTAX
DESCRIPTION
openURL
openURL(String url)
Opens a URL in the default
browser on the client.
playSound
playSound(String name)
Plays the sounds in the given file
on the client. Only .wav files are
supported; no external libraries
are required.
playSound
playSound(double hz, int millis)
Plays a signal at a given frequency
hz and with given duration
millis in milliseconds on the
client.
E XAMPLE C ODE
The line of code below plays one of the sounds available in the data/sounds folder
of the COMSOL installation and has been embedded in the application and stored
in the Sounds library.
playSound("embedded:///success_1.wav");
In the command sequence of a form object, this is equivalent to selecting a sound
node under Libraries and clicking Run.
The line of code below opens a PDF file embedded in the application and stored
in the File library.
fileOpen("embedded:///li_ion_battery_impedance.pdf");
| 111
In the command sequence of a form object, this is equivalent to selecting an Open
File node under GUI Commands>File Commands and clicking Run, as shown in the
figure below.
This line of code opens the COMSOL home page in the default browser:
openURL("https://www.comsol.com");
This line of code runs an application by means of an OS command:
executeOSCommand("C:\\COMSOL62\\Multiphysics\\bin\\win64\\comsol.exe",
"-run", "C:\\work\\tubular_reactor.mph");
112 |
Email Methods
Email methods are used for sending emails from an application, typically with
attachments containing results from a simulation.
NAME
SYNTAX
DESCRIPTION
emailFromAddress
String emailFromAddress()
Returns the email from address
from the COMSOL Server or
preferences setting.
sendEmail
sendEmail(String subject, String
bodyText)
Sends an email to the default
recipient(s) with the specified
subject and body text.
sendEmail
sendEmail(String subject, String
bodyText, ModelEntity... modelEntity)
Sends an email to the default
recipient(s) with the specified
subject, body text, and zero or
more attachments created from
Report, Export, and Table nodes
in the embedded model.
sendEmail
sendEmail(String toAddress, String
subject, String bodyText,
ModelEntity... modelEntity)
Sends an email to the specified
recipient(s) with the specified
subject, body text, and zero or
more attachments created from
Report, Export, and Table nodes
in the embedded model.
userEmailAddress
String userEmailAddress()
Returns the user email
address(es) corresponding to the
currently logged in user, or an
empty string if the user has not
configured an email address.
Email Class Methods
The class EmailMessage can be used to create custom email messages.
NAME
SYNTAX
DESCRIPTION
EmailMessage
EmailMessage mail = new EmailMessage()
Creates a new EmailMessage
object.
EmailMessage.setSer
ver
mail.setServer(String host, int port)
Sets the email (SMTP) server
host and port to use for this
email message.
| 113
NAME
SYNTAX
DESCRIPTION
EmailMessage.setUse
r
mail.setUser(String name, String
password)
Sets the username and password
to use for email (SMTP) server
authentication. This method must
be called after the setServer
method.
EmailMessage.setSec
urity
mail.setSecurity(String security)
Sets the connection security type
for email (SMTP) server
communication. Valid values are
’none’, ’starttls’ and ’tls’.
This method must be called after
the setServer method.
EmailMessage.setFro
m
mail.setFrom(String fromAddress)
Sets the from address.
EmailMessage.setTo
mail.setTo(String... to)
Sets the to addresses.
EmailMessage.setCc
mail.setCc(String... cc)
Sets the cc addresses.
EmailMessage.setBcc
mail.setBcc(String... bcc)
Sets the bcc addresses.
EmailMessage.setSub
ject
mail.setSubject(String subject)
Sets the email subject line. Note
that newline characters are not
allowed.
EmailMessage.setBod
yText
mail.setBodyText(String body)
Sets the email body as plain text.
An email can contain both a text
and an HTML body.
EmailMessage.setBod
yHtml
mail.setBodyHtml(String body)
Sets the email body as HTML
text. An email can contain both a
text and an HTML body.
EmailMessage.attach
File
mail.attachFile(String filename)
Adds an attachment from a file.
The attachment MIME type is
determined by the filename
extension.
EmailMessage.attach
File
mail.attachFile(String filename,
String mimeType)
Adds an attachment from a file
with the specified MIME type.
EmailMessage.attach
FromModel
mail.attachFromModel(ModelEntity
modelEntity)
Adds an attachment created
from a report, export, or table
feature in the model.
EmailMessage.attach
Text
mail.attachText(String text, String
mimeSubType)
Adds a text attachment with a
specified sub-MIME type, such as
plain or HTML.
114 |
NAME
SYNTAX
DESCRIPTION
EmailMessage.attach
Binary
mail.attachBinary(byte[] binary,
String mimeType)
Adds an attachment from a byte
array with the specified MIME
type.
EmailMessage.send
mail.send()
Sends the email to the email
(SMTP) server. An email object
can only be sent once.
Each to, cc, and bcc address string can contain multiple email addresses separated
by a comma or a semicolon character. Whitespace is allowed before and after the
separator character.
E MAIL P REFERENCES
To set preferences for an outgoing email (SMTP) server, open the Email page of
the Preferences dialog box, as shown in the figure below.
COMSOL Server provides a similar set of email preferences.
E XAMPLE C ODE
The following code sends an email and attaches a report:
EmailMessage mail = new EmailMessage();
mail.setTo(emailTo);
| 115
mail.setSubject("Tubular Reactor Simulation");
mail.setBodyText("The computation has finished. Please find the report
attached.");
mail.attachFromModel(model.result().report("rpt1"));
mail.send();
This code is run in the Tubular Reactor application, which is available as an
application example in the Application Libraries. The figure below shows part of
the user interface with an input field for the email address.
The figure below shows the corresponding form object and Settings window.
The following code is similar but also configures the email server settings.
EmailMessage mail = new EmailMessage();
mail.setServer("smtp.myemail.com", 587);
mail.setUser("[email protected]", "password");
mail.setSecurity("starttls");
mail.setFrom("[email protected]");
mail.setTo("[email protected]");
mail.setSubject("Tubular reaction simulation");
116 |
mail.setBodyText("The computation has finished");
mail.send();
GUI-Related Methods
The graphical user interface (GUI) related methods are used for displaying dialog
boxes with messages, editing form objects and user interface content, getting
run-time properties of the application user interface, and running methods.
NAME
SYNTAX
DESCRIPTION
Call a method directly
<methodName>()
Call a method from the
Methods list by using its
name, for example,
method1(), method2().
callMethod
callMethod(String name)
Alternate way to call a
method from the Methods
list; used internally and in
cases of name collisions.
useGraphics
useGraphics(ModelEntity entity,
String name)
useGraphics(ModelEntity entity,
FormObject graphics)
Plots the given entity (Plot
Group, Geometry, Mesh,
Explicit Selection or Player
Animation) in the graphics
form object given by the
name, name path, or graphics
form object in the second
argument.
openForm
openForm(String name)
Shows the form with the
given name in the current
main window. In a single
window application, the form
replaces the current one. In
an application with
subwindows, the form must
exist in the main window
layout. If not, it will not be
opened. Showing a form that
is already open will only
activate the form.
| 117
NAME
SYNTAX
DESCRIPTION
closeForm
closeForm(String name)
Closes the form with the
given name. Closing forms is
only possible in applications
using subwindows. This
method is not applicable for
single window applications.
closeDialog
closeDialog(String name)
Closes the form, shown as a
dialog box, with the given
name.
dialog
dialog(String name)
Shows the form with the
given name as a dialog box.
Equivalent to the dialog
method of a Form object; see
below.
alert
alert(String text)
Stops execution and displays
an alert message with the
given text.
alert
alert(String text, String title)
Stops execution and displays
an alert message with the
given text and title.
confirm
String confirm(String text)
Stops execution and displays
a confirmation dialog box
with the given text. It also
displays two buttons, "Yes"
and "No". The method
returns "Yes" or "No"
depending on what the user
clicks.
confirm
String confirm(String text, String
title)
Stops execution and displays
a confirmation dialog box
with the given text and title.
It also displays two buttons,
"Yes" and "No". The method
returns "Yes" or "No"
depending on what the user
clicks.
118 |
NAME
SYNTAX
DESCRIPTION
confirm
String confirm(String text, String
title, String yes, String no)
Stops execution and displays
a confirmation dialog box
with the given text and title.
It also displays two buttons
with the given strings as
labels. The method returns
the label of the button that
the user clicks.
confirm
String confirm(String text, String
title, String yes, String no,
String cancel)
Stops execution and displays
a confirmation dialog box
with the given text and title.
It also displays three buttons
with the given strings as
labels. The method returns
the label of the button that
the user clicks.
error
error(String message)
Stops execution and opens
an error dialog box with the
given message.
error
error(String message, Throwable
cause)
Stops execution and opens
an error dialog box with the
given message including the
underlying cause of class
Throwable, the general Java
exception class, or one of its
subclasses, such as
RuntimeException. This can
be used to “wrap” native
COMSOL Multiphysics error
messages with custom error
messages.
request
String request(String text)
Stops execution and displays
a dialog box with a text field,
requesting input from the
user. The given text is the
label of the text field. The
method returns the entered
text or null if the cancel
button is clicked.
| 119
NAME
SYNTAX
DESCRIPTION
request
String request(String text, String
defaultString)
Stops execution and displays
a dialog box with a text field,
requesting input from the
user. The given text is the
label of the text field and the
default string is the text
initially shown in the text
field. The method returns the
entered text or null if the
cancel button is clicked.
request
String request(String text, String
title, String defaultString)
Stops execution and displays
a dialog box with a text field,
requesting input from the
user. The given text is the
label of the text field, the
default string is the text
initially shown in the text
field, and the title is the title
of the dialog box. The
method returns the entered
text or null if the cancel
button is clicked.
message
message(String message)
Sends a message to the
message log if available in the
application.
message
message(arg)
Sends a message arg to the
message log. For an
application this requires that
a message log is added to the
application user interface.
The input argument arg can
be a scalar, 1D array, or 2D
array of the types string,
double, int, or Boolean.
clearLog
clearLog()
Clears the log window.
clearMessageLog
clearMessageLog()
Clears the message log
window.
120 |
NAME
SYNTAX
DESCRIPTION
evaluateToResultsTable
evaluateToResultsTable(NumericalFe
ature entity, String name, boolean
clear)
evaluateToResultsTable(NumericalFe
ature entity, FormObject graphics,
boolean clear)
Evaluates the given entity, a
Derived Value, in the table
object given by the name,
name path, or graphics form
object in the second
argument, which will then be
the default target for the
evaluations of the Derived
Value. If the third argument is
true, the table is cleared
before adding the new data,
otherwise the data is
appended.
evaluateToDoubleArray2D
double[][]
evaluateToDoubleArray2D(NumericalF
eature entity)
Evaluates the given entity, a
Derived Value, and returns
the nonparameter column
part of the real table that is
produced as a double matrix.
All settings in the numerical
feature are respected, but
those in the current table
connected to the numerical
feature are ignored.
evaluateToIntegerArray2D
int[][]
evaluateToIntegerArray2D(Numerical
Feature entity)
Evaluates the given entity, a
Derived Value, and returns
the nonparameter column
part of the real table that is
produced as an integer
matrix. All settings in the
numerical feature are
respected, but those in the
current table connected to
the numerical feature are
ignored.
| 121
NAME
SYNTAX
DESCRIPTION
evaluateToStringArray2D
String[][]
evaluateToStringArray2D(NumericalF
eature entity)
Evaluates the given entity, a
Derived Value, and returns
the nonparameter column
part of the, potentially
complex, table that is
produced as a string matrix.
All settings in the numerical
feature are respected but
those in the current table
connected to the numerical
feature are ignored.
useResultsTable
useResultsTable(TableFeature
tableFeature, String resultsTable)
useResultsTable(TableFeature
tableFeature, FormObject
resultsTable)
Shows the values from the
tableFeature in the
resultsTable form object.
getChoiceList
ChoiceList getChoiceList(String
name)
Returns an object of the type
ChoiceList, representing a
choice list node under the
declarations branch. The type
ChoiceList has methods
that make it easier to change
the matrix value with respect
to changing and accessing
values and display names
individually.
setFormObjectEnabled
setFormObjectEnabled(String name,
boolean enabled)
Sets the enable state for the
form object specified by the
name or name path.
setFormObjectVisible
setFormObjectVisible(String name,
boolean visible)
Sets the visible state for the
form object specified by the
name or name path.
setFormObjectText
setFormObjectText(String name,
String text)
Sets the text for the form
object specified by the name
or name path in the second
argument. This method
throws an error if it is
impossible to set a text for
the specified form object.
122 |
NAME
SYNTAX
DESCRIPTION
setFormObjectEditable
setFormObjectEditable(String name,
boolean editable)
Sets the editable state for the
form object specified by the
name or name path. This
functionality is only available
for text field objects.
setMenuBarItemEnabled
setMenuBarItemEnabled(String name,
boolean enabled)
Sets the enable state for the
menu bar item specified by
the name or name path (from
menu bar) in the first
argument.
setMainToolbarItemEnabled
setMainToolbarItemEnabled(String
name, boolean enabled)
Sets the enable state for the
main toolbar item specified
by the name or name path
(from main toolbar) in the
first argument.
setFileMenuItemEnabled
setFileMenuItemEnabled(String name,
boolean enabled)
Sets the enable state for the
file menu item specified by
the name or name path
(from file menu) in the first
argument.
setRibbonItemEnabled
setRibbonItemEnabled(String name,
boolean enabled)
Sets the enable state for the
ribbon item specified by the
name or name path (from
main window) in the first
argument.
setToolbarItemEnabled
setToolbarItemEnabled(String name,
boolean enabled)
Sets the enable state for the
toolbar form object item
specified by the name or
name path in the first
argument.
useView
useView(View view, String name)
useView(View view, FormObject
graphics)
Applies a view to the
graphics contents given by
the name, name path, or
graphics form object in the
second argument.
resetView
resetView(String name)
resetView(FormObject graphics)
Resets the view to its initial
state in the graphics contents
given by the name, name
path, or graphics form object
in the second argument.
| 123
NAME
SYNTAX
DESCRIPTION
getView
ViewBase getView(String name)
ViewBase getView(FormObject
graphics)
Returns the view currently
used by the graphics contents
given by the name, name
path, or graphics form object
in the second argument.
goToView
goToView(String name);
Goes to a standard view in
main graphics window. The
parameter name is one of the
view orientation strings in the
following list:
"xy","xz","yx","yz","zx"
,"zy".
goToView
goToView(String name, String
graphicsname);
Goes to a standard view in
the given graphics form
object graphicsname.
goToView
goToView(String name, FormObject
graphics);
Goes to standard view in the
given graphics form object
graphics.
setWebPageSource
setWebPageSource(String name,
String source)
Sets the source for the form
object specified by the name
or name path in the first
argument. This method
throws an error if the name
does not refer to a Web Page
form object.
getScreenHeight
int getScreenHeight()
Returns the height in pixels of
the primary screen on client
system, or of the browser
window if Web Client is
used.
getScreenWidth
int getScreenWidth()
Returns the width in pixels of
the primary screen on client
system, or of the browser
window if Web Client is
used.
storeChanges
storeChanges(String form)
Commits the values entered
in a dialog box having On
request enabled. The method
takes the name of the form
as its argument.
124 |
A LERTS AND M ESSAGES
The methods alert, confirm, and request display a dialog box with a text string
and optional user input. The following example uses confirm to ask the user if a
direct or an iterative solver should be used in an application. Based on the answer,
the alert function is then used to show the estimated memory requirement for
the selected solver type in a message dialog box:
String answer = confirm("Which solver do you want to use?",
"Solver Selection","Direct", "Iterative");
if (answer.equals("Direct")) {
alert("Using the direct solver will require about 4GB of memory when solving.");
} else {
alert("Using the iterative solver will require about 2GB of memory when
solving.");
}
E XAMPLE C ODE
The following code changes the camera zoom angle and updates the graphics for
each change.
useView(model.view("view1"), "/form1/graphics1");
for (int i = 0; i < 25; i++) {
sleep(2000);
model.view("view1").camera().set("zoomanglefull", 12-i*5.0/25);
useGraphics(model.geom("geom1"), "/form1/graphics1");
}
This line of code displays plot group 5 (pg5) in the graphics object graphics1 in
the form with the name Temperature:
useGraphics(model.result("pg5"), "/Temperature/graphics1");
The code below displays the mesh in the model tree node mesh1 in the graphics
object graphics1 contained in the card of a card stack. The second line runs a
zoom extents command to ensure proper visualization of the mesh.
useGraphics(model.mesh("mesh1"), "/mesh/cardstack1/card1/graphics1");
zoomExtents("/mesh/cardstack1/card1/graphics1");
To clear the contents of a graphics object use a call such as
useGraphics(null, "/form1/graphics1");
The code below displays a request dialog box that lets the user type in a filename
for an HTML report. If the user has typed a filename, then a report is generated.
String answerh = request("Enter filename","Filename", "Untitled.html");
if (answerh != null) {
model.result().report("rpt1").set("format","html");
model.result().report("rpt1").set("filename","user:///"+answerh);
model.result().report("rpt1").run();
}
| 125
The code below is similar to the code above, but in this case the report is saved in
Microsoft Word format (.docx).
String answerw = request("Enter filename","Filename", "Untitled.docx");
if (answerw != null) {
model.result().report("rpt2").set("format","docx");
model.result().report("rpt2").set("filename","user:///"+answerw);
model.result().report("rpt2").run();
}
This line of code sets the view of the graphics object form1/graphics1 to View 5,
as defined in the model tree:
useView(model.view("view5"), "form1/graphics1");
126 |
You can use Data Access in combination with Editor Tools to create a slider or an
input field that sets the transparency level (alpha) of a plot group. The figure
below shows a Settings window of a slider with the transparency level as Source.
In this case you need to create a method for updating the view that is called to
handle an event from the slider or form object. In the example above, the slider
uses a Local method defined in the Events section. This method contains one line
of code that updates the view:
useView(getView("/form1/graphics1"), "/form1/graphics1");
Note that different transparency levels are not supported when accessing an
application from a browser using COMSOL Server.
| 127
Note that you can also set a view from the command sequence of, for example, a
button: select a view subnode under the Views node in the editor tree and click the
Plot button under the tree.
To go to one of the standard views in the main Graphics window, for example in
an add-in, you can use:
goToView("xy");
In an application you can similarly use one of:
goToView("xz", "form1/graphics1");
goToView("yz", app.form("form1").formObject("graphics1"));
to go to the graphics object graphics1 in the form form1.
This line of code sets the URL source of the form object webpage1 to the
COMSOL web page:
setWebPageSource("/form1/webpage1", "https://www.comsol.com");
This line of code forms a string containing the screen width and height:
screenSize = toString(getScreenWidth()) + "-by-" +
toString(getScreenHeight());
You can present the string with an input field or a data display object using this
string as a source (the string screenSize needs to be declared first).
128 |
GUI Command Methods
The GUI command methods correspond to the GUI Commands node in the editor
tree. The editor tree is displayed in, for example, the Choose Commands to Run
section in the Settings window for a button object in the Application Builder.
NAME
SYNTAX
DESCRIPTION
clearAllMeshes
clearAllMeshes()
Clears all meshes.
clearAllSolutions
clearAllSolutions()
Clears all solutions.
clearSelection
clearSelection(String graphics)
clearSelection(FormObject graphics)
Clears the selection in the given
graphics object.
environmentReflections
environmentReflections(String
graphicsName)
environmentReflections(FormObject
graphics)
Adds environment reflections to
the given graphics object. This
method is run as a toggle action.
exit
exit()
Exits the application.
fileOpen
fileOpen(String name)
Opens a file with the associated
program on the client.
fileSaveAs
boolean fileSaveAs(String file)
Downloads a file to the client.
See also the section “Example
code”. The method returns a
boolean that indicates if the
operation was successful or not.
printGraphics
printGraphics(String graphicsName)
printGraphics(FormObject graphics)
Prints the given graphics object.
rotateEnvironment
rotateEnvironment(String
graphicsName)
rotateEnvironment(FormObject
graphics)
Rotates the environment, that is
used for realistic reflections, to
the given graphics object. This
method is run as a toggle action.
saveApplication
saveApplication(boolean confirm)
Saves the application. The
boolean argument determines if
the user is prompted with a
confirmation dialog before saving.
saveApplicationAs
boolean saveApplication()
Saves the application under a
different name. If the return value
is false then the user canceled the
operation and the application
was not saved.
| 129
NAME
SYNTAX
DESCRIPTION
saveApplicationOnServe
r
saveApplicationOnServer(boolean
confirm)
Saves the application on server.
The boolean argument
determines if the user is
prompted with a confirmation
dialog before saving.
saveApplicationOnServe
rAs
boolean saveApplicationOnServerAs()
Saves the application on server
under a different name. (Or as an
MPH file.) If the return value is
false then the user canceled the
operation and the application
was not saved.
scenelight
sceneLight(String graphicsName)
sceneLight(FormObject graphics)
Toggles scene light in the given
graphics object.
selectAll
selectAll(String graphics)
selectAll(FormObject graphics)
Sets the selection to all entities in
the given graphics object.
skybox
skybox(String graphicsName)
skybox(FormObject graphics)
Adds visualization of the skybox,
used for realistic reflections, to
the given graphics object. This
method is run as a toggle action.
transparency
transparency(String graphicsName)
transparency(FormObject graphics)
Toggles transparency in the given
graphics object.
zoomExtents
zoomExtents(String graphicsName)
zoomExtents(FormObject graphics)
Makes the entire model visible
within the extent of the given
graphics object.
E XAMPLE C ODE
For examples of how to use fileSaveAs, see the Introduction to Application
Builder. This method is frequently needed for saving files in general.
You can create an application that saves and exits automatically by running the
following lines of code, for example, after solving:
saveModel(model,"C:\\COMSOL\\file.mph");
exit();
or
saveModel(model, "common:///file.mph");
exit();
This is useful in a COMSOL Server setting since using exit() in this way will free
up any licenses that are checked out.
130 |
Debu g Methods
The debug method is used to display variable contents in the Debug Log window.
NAME
SYNTAX
DESCRIPTION
clearDebugLog
clearDebugLog()
Clears the Debug Log window.
debugLog
debugLog(arg)
Prints the value of arg to the
Debug Log window. The input
argument arg can be a scalar, 1D
array, or 2D array of the types
string, double, int, or Boolean.
E XAMPLE C ODE
The code below prints strings and doubles to the Debug Log window.
xcoords[i] = Math.cos(2.0*Math.PI*divid);
ycoords[i] = Math.sin(2.0*Math.PI*divid);
debugLog("These are component values for case 1:");
debugLog("x:");
debugLog(xcoords[i]);
debugLog("y:");
debugLog(ycoords[i]);
Me thod s f o r Ex te rna l C Libra ries
The methods for external C libraries are used for linking Application Builder
methods with compiled C-code.
E XTERNAL M ETHOD
NAME
SYNTAX
DESCRIPTION
external
External external(String name)
Returns an interface to an
external C (native) library given
by the name of the library
feature. The External class uses
the Java Native Interface (JNI)
framework.
For more information, see the Application Builder Reference Manual.
| 131
M ETHODS R ETURNED BY THE E XTERNAL M ETHOD
The external method returns an object of type External with the following
methods:
NAME
SYNTAX
DESCRIPTION
invoke
long invoke(String method, Object...
arguments)
Invokes the named native
method in the library with the
supplied arguments. Strings are
converted to char *. Returns the
value returned by the method.
invokeWideString
long invokeWideString(String method,
Object... arguments)
Invokes the named native
method in the library with the
supplied arguments. Strings are
converted to wchar_t *. Returns
the value returned by the
method.
close
void close()
Releases the library and frees
resources. If you do not call this
method, it is automatically
invoked when the external library
is no longer needed.
132 |
Progress Methods
Progress methods are used to create and update progress information in the Status
bar, in a progress form object, and in a dialog box.
NAME
SYNTAX
DESCRIPTION
setProgressInterval
setProgressInterval(String message,
int intervalStart, int intervalEnd)
Sets a progress interval to use
for the top-level progress and
display message at that level.
The top level will go from
intervalStart to
intervalEnd as the second
level goes from 0 to 100. As
the second level increases, the
top level is increased by
(intervalEnd intervalStart) * (second
level progress (0-100) /
100).
The value for intervalStart
must be between 0 and
intervalEnd, and the value for
intervalEnd must be between
intervalStart and 100.
Calling this method implicitly
resets any manual progress
previously set by calls to
setProgress().
setProgress
setProgress(int value, String message)
Sets a value for the
user-controlled progress level.
By default, this is the top level,
but if a progress interval is
active (setProgressInterval
has been called and
resetProgress has not been
called after that), then it is the
second level.
setProgress
setProgress(int value)
Same as
setProgress(message,
value), but uses the latest
message or an empty string (if
no message has been set).
| 133
NAME
SYNTAX
DESCRIPTION
resetProgress
resetProgress()
Removes all progress levels
and resets progress to 0 and
the message to an empty
string.
showIndeterminateProgr
ess
showIndeterminateProgress(String
message)
Shows a progress dialog box
with an indeterminate progress
bar, given message and a cancel
button.
showIndeterminateProgr
ess
showIndeterminateProgress(String
message, boolean cancelButton)
Shows a progress dialog box
with an indeterminate progress
bar, given message and an
optional cancel button.
showProgress
showProgress()
Shows a progress dialog box
with a cancel button. No
model progress is included.
showProgress
showProgress(boolean modelProgress)
Shows a progress dialog box
with a cancel button and an
optional model progress.
showProgress
showProgress(boolean modelProgress,
boolean addSecondLevel)
Shows a progress dialog box
with a cancel button, optional
model progress, and one or
two levels of progress
information. Two levels can
only be used if modelProgress
is true.
showProgress
showProgress(boolean modelProgress,
boolean addSecondLevel, boolean
cancelButton)
Shows a progress dialog box
with optional model progress,
one or two levels, and possibly
a cancel button. Two levels can
only be used if modelProgress
is true.
closeProgress
closeProgress()
Closes the currently shown
progress dialog box.
134 |
NAME
SYNTAX
DESCRIPTION
startProgress
startProgress(String name)
startProgress(FormObject progressBar)
Resets the value of the given
progress bar form object name
to 0. The progress bar to
control can be specified with
an absolute path, such as
form1/progressbar1, or a
name relative to the context
from which the method was
called.
Nothing is done if no progress
bar corresponding to the given
name is found.
setProgressBar
setProgressBar(String name, int
workDone, String message)
setProgressBar(FormObject progressBar,
int workDone, String message)
Sets the value of the given
progress bar form object name
in the range 0-100 and the
associated progress message.
Values out of range are
converted to 0 or 100. The
progress bar to control can be
specified with an absolute path,
such as form1/progressbar1,
or a name relative to the
context from which the
method was called.
Nothing is done if no progress
bar corresponding to the given
name is found, or if the
progress bar is used for
showing model progress.
setProgressBar
setProgressBar(String name, int
workDone)
setProgressBar(FormObject progressBar,
int workDone)
Same as above, but does not
update the progress message.
E XAMPLE C ODE
showProgress(true, true, true);
/* Opens a progress dialog box with cancel button showing two levels of
progress. The values shown in progress dialog box will be updated to match
the two levels of progress. */
setProgressInterval("Preparing application", 0, 20);
/* Sets the current progress scale to go from 0 to 20. This means that the
top-level progress will go from 0 to 20 when second-level progress goes from
0 to 100. */
| 135
setProgress(0, "Init step 1");
/* Sets the second-level progress to 0 and the second-level progress message
to "Init step 1". */
// do some work
setProgress(40);
/* Sets the second-level progress to 40, this causes the top-level progress
to be updated to 8 (40 % of 0-20). */
// do some work
setProgress(80, "Init step 2");
/* Sets the second-level progress to 80 and the progress message to "Init
step 2". The top-level message is still "Preparing application" and
top-level progress is now 16. */
// do some work
setProgressInterval("Meshing", 20, 40);
/* Sets the top-level interval to 20 - 40 and the progress message to
"Meshing" at this point the value shown at the top-level will be 20. The
second-level progress is cleared when the top-level interval is changed. */
<call-meshing algorithm here>
/* The progress messages and values from the meshing algorithm are shown at
the second-level progress. The top-level progress message will be "Meshing",
but the top-level progress advances from 20 to 40 while second-level
progress advances from 0 to 100. */
setProgressInterval("Solving", 40, 100);
/* The top-level progress message is changed to "Solving" and its value to
40.
<call-solver>
/* Similar to meshing, the progress messages and values from the solver are
shown in the second-level progress bar and the top-level progress value goes
from 40 to 100 while the solver progress goes from 0 to 100. */
closeProgress();
Application Progress Information
Progress information can be displayed in three different ways: in the Status bar, in
a progress form object, and in a dialog box. Application progress information is
controlled by the setProgress methods, which take as their input an integer
between 0 and 100 and an optional message. The integer represents how far the
displayed progress bar has progressed. If no message is supplied, the last message
provided is used. For example:
setProgress(10, "Computing data");
setProgress(25);
136 |
This will keep Computing data as the progress message.
Use the setProgress method by itself if you want to display custom progress in
the task and status bar. Once you have done this, that progress bar will no longer
be updated by progress information from the COMSOL model, but will be
completely dependent on further calls to setProgress for changes in its value.
Precede it with a call to showProgress to also display the built-in progress dialog
box, see below.
Note that progress information from the COMSOL model will not be shown in
between calls to setProgress. Progress is reset between method calls. If you want
to combine custom steps of progress in methods with built-in model progress,
then use setProgressInterval instead.
With setProgressInterval, you can control the top two levels of progress
information. The second level can be displayed in a progress dialog box and a
progress bar form object, see the code segment below. The second progress level,
controlled by your own custom progress calculation, is connected to the first level
such that one interval at the top level corresponds to the entire second level. Thus
if the interval is 0–50, when the second level progress reaches 40, for example, the
first level will be set to 20 (=(40/100)*50).
Important uses of the method setProgressInterval are listed below:
• Combining calls to the COMSOL model so that you get continuous
progress going from 0–100.
• Computing several studies as well as evaluating several plots. Call
setProgressInterval before each call to the built-in methods with an
interval that approximates how much time each model computation takes.
For example:
setProgressInterval("Computing solution", 0, 80);
model.study("std1").run();
setProgressInterval("Plotting", 80, 100);
useGraphics(model.result("pg3"), "energy_response_plot/graphics1");
• Combining one or more calls to built-in COMSOL methods with custom
methods that in themselves take significant time. In this case, use
setProgressInterval as in the previous example, followed by your own
custom code with appropriate calls to setProgress. These calls should run
from 0 to 100 as they are controlling the second progress level. For example:
setProgressInterval("Computing solution", 0, 60);
model.study("std1").run();
setProgressInterval("Working", 60, 80);
setProgress(0, "Specific message about what I'm doing");
// ...
// Code that does something
// ...
setProgress(60);
| 137
If you, in a running application, wish to no longer use progress intervals, call
resetProgress to return to the original state. This will also reset progress to 0.
The Progress Dialog Box
A progress dialog box can be used to display application progress as described in
the previous section. The progress dialog has the following options:
• Whether to show model progress or not. When off, no progress from the
model part of the application is forwarded to the progress dialog.
• Whether to show one or two progress levels in the progress dialog.
• Whether to include a cancel button. Cancel also works for user-defined
methods, as it halts execution when the next line in the method is reached.
Use the showProgress methods to enable or disable these options. To close the
progress dialog, use the closeProgress method.
You can show a progress dialog with an indeterminate progress bar that keeps
spinning until you close the progress dialog. Only one progress dialog can be
shown at a time. Use the showIndeterminateProgress methods to display this
progress dialog.
The Progress Bar Form Object
The Progress Bar form object can either show overall application progress
information or customized partial progress information. If you have selected the
Include model progress check box in the Settings window of the Main Window node,
then the overall application progress information becomes available.
When Include model progress is selected, the progress bar will show the same
information as the progress dialog box. That is, one or two levels of progress
information and a cancel button, depending on the settings in the form object.
When Include model progress is cleared, you control the progress bar through the
setProgressBar methods. These take the path name of the progress bar form
object, for example, main/progressbar1.
138 |
Date and Time Methods
The date and time methods are used to retrieve the current date and time as well
as information on computation times.
NAME
SYNTAX
DESCRIPTION
currentDate
String currentDate()
Returns the current date as a
string (formatted according
to the server's defaults) for
the current date.
currentTime
String currentTime()
Returns the current time as a
string (not including date, and
formatted according to the
server defaults).
formattedDateTime
String dateString =
formattedDateTime(long epochInMs)
Returns a formatted and
readable date and time from
an input given as milliseconds
since the epoch.
formattedTime
String formattedTime(long timeInMs,
String format)
Returns a formatted time
using the given format. The
format can either be a time
unit or a text describing a
longer format. Supported
formats are:
’hr:min:sec’ which returns
the time in hours, minutes,
and seconds in the form X hr
Y min Z sec.
’h:min:s’ which returns the
time in hours, minutes, and
seconds in the form X h Y
min Z s.
’detailed’ which returns
the time in seconds and also
includes more readable units
for longer times.
sleep
sleep(long timeInMs)
Sleep for the specified
number of milliseconds.
timeStamp
long timeStamp()
Current time in milliseconds
since midnight, January 1,
1970 UTC.
| 139
NAME
SYNTAX
DESCRIPTION
getExpectedComputa
tionTime
model.setExpectedComputationTime(String
format)
Returns a string describing
the approximate
computation time of the
application. The string can be
altered by the method
setExpectedComputationTi
me.
setLastComputation
Time
model.setLastComputationTime(long time)
Set the last computation
time, overwriting the
automatically generated time.
You can use the timeStamp
method to record time
differences and set the
measured time in ms (a long
integer).
getLastComputation
Time
String model.getLastComputationTime
(String format)
Returns the last computation
time in the given format. The
format can either be a time
unit or text describing a
longer format. Currently
supported formats are:
hr:min:sec Returns the time
in hours, minutes, and
seconds in the format X h Y
min Z sec.
h:min:s Returns the time in
hours, minutes, and seconds
in the format X h Y min Z s.
detailed Returns the time in
seconds and also includes
more readable units for
longer times. This format is
localized and the output is
translated to the current
language setting.
For example, you can
retrieve the time in ms by
using
getLastComputationTime("m
s").
140 |
E XAMPLE C ODE
The following code overrides the built-in computation time that is available in the
information nodes in the model tree.
long t0 = timeStamp(); // initialize record of computation time
// code and computations
model.setLastComputationTime(timeStamp()-t0); // record computation time
If it is possible to give a rough estimate of the computation time based on the
given inputs of an application, you can update the expected computation time and
display it in an information card stack or a text object. Assume that there is an
integer input called objects that controls the number of objects in a geometry
array and that the computation roughly increases linearly with this number. The
following code adjusts the expected computation time accordingly.
// Number of minutes of computation time per object
int minutes = objects*2.1;
model.setExpectedComputationTime("About " + minutes + " minutes" );
Sleep
The code below makes the application idle for 1000 ms.
long delay = 1000;
sleep(delay);
This technique can be used to display graphics in a sequence.
For more information on information nodes and information cards, as well as the
sleep method, see the book Introduction to Application Builder.
| 141
Co n v e rs io n Me th o d s
Conversion methods are used to convert between the different data types
Booleans, integers, doubles, strings, and arrays. These methods are shorthand
versions of conversion methods in the standard Java libraries.
NAME
SYNTAX
DESCRIPTION
toBoolean
boolean toBoolean(String str)
Converts the given string to a
Boolean. (’true’ returns true, all
other strings return false).
toBoolean
boolean [] toBoolean(String[]... strs)
Converts all the strings in the
given array to Booleans (’true’
returns true, all other strings
return false) and returns a
Boolean array.
toBoolean
boolean [][] toBoolean(String[][]... strs)
Converts all the strings in the
given matrix to Booleans (’true’
returns true, all other strings
return false) and returns a
Boolean matrix.
toDouble
double toDouble(String str)
Converts the given string to a
double.
toDouble
double[] toDouble(String... strs)
Converts all the strings in the
given array to doubles and
returns a double array.
toDouble
double[][] toDouble(String[]... strs)
Converts all the strings in the
given matrix to doubles and
returns a double matrix.
toDouble
double toDouble(float flt)
Converts the given float to a
double.
toDouble
double[] toDouble(float... flt)
Converts all the floats in the
given array to doubles and
returns a double array.
toDouble
double[][] toDouble(float[]... flt)
Converts all the floats in the
given matrix to doubles and
returns a double matrix.
toInt
int toInt(String str)
Converts the given string to an
integer.
toInt
int[] toInt(String... strs)
Converts all the strings in the
given array to integers and
returns an integer array.
142 |
NAME
SYNTAX
DESCRIPTION
toInt
int[][] toInt(String[]... strs)
Converts all the strings in the
given matrix to integers and
returns an integer matrix.
toString
String toString(int value)
Converts the given integer to a
string.
toString
String toString(double value)
Converts the given double to a
string.
toString
String toString(boolean value)
Converts the given Boolean to a
string.
toString
String toString(double value, int digits)
Converts the given double to a
string with the given number of
significant digits.
toString
String toString(double value, int
digits,boolean remove)
Converts the given double to a
string with the given number of
significant digits with trailing zeros
removed if the Boolean remove is
true. For example, 10.0000001
with number of digits set to 3 will
return 10 rather than 10.000.
toString
String toString(double value, String format)
Converts the given double to a
string using the given format
specifier, which is the same as
java.util.Formatter. See the
corresponding Java format string
documentation for more
information.
toString
String[] toString(double[] darray)
Converts all the doubles in the
given array to strings and returns
a string array.
toString
String[][] toString(double[][] dmatrix)
Converts all the doubles in the
given matrix to strings and
returns a string matrix.
toString
String[] toString(int[] iarray)
Converts all the integers in the
given array to strings and returns
a string array.
toString
String[][] toString(int[][] imatrix)
Converts all the integers in the
given matrix to strings and
returns a string matrix.
| 143
NAME
SYNTAX
DESCRIPTION
toString
String[] toString(boolean[] barray)
Converts all the Booleans in the
given array to strings and returns
a string array.
toString
String[][] toString(boolean[][] bmatrix)
Converts all the Booleans in the
given matrix to strings and
returns a string matrix.
A r r ay M et h o d s
Array methods are used to add, remove, insert, and extract subsets of 1D and 2D
arrays.
NAME
SYNTAX
DESCRIPTION
getColumn
String[] getColumn(String[][] matrix, int
column)
Returns a String[] for a
specified column in the matrix.
Useful when values have been
read from a file and only certain
columns should be shown in a
table.
getColumn
double[] getColumn(double[][] matrix, int
column)
Returns a double[] for a
specified column in the matrix.
getColumn
int[] getColumn(int[][] matrix, int column)
Returns an int[] for a specified
column in the matrix.
getColumn
boolean[] getColumn(boolean[][] matrix, int
column)
Returns a boolean[] for a
specified column in the matrix.
getSubMatrix
String[][] getSubMatrix(String[][] matrix,
int startCol, int endCol, int startRow, int
endRow)
Returns a rectangular submatrix
of the input matrix spanning
columns from startCol to
endCol, and rows from startRow
to endRow.
getSubMatrix
double[][] getSubMatrix(double[][] matrix,
int startCol,int endCol, int startRow, int
endRow)
Returns a rectangular submatrix
of the input matrix spanning
columns from startCol to
endCol, and rows from startRow
to endRow.
144 |
NAME
SYNTAX
DESCRIPTION
getSubMatrix
int[][] getSubMatrix(int[][] matrix, int
startCol, int endCol, int startRow, int
endRow)
Returns a rectangular submatrix
of the input matrix spanning
columns from startCol to
endCol, and rows from startRow
to endRow.
getSubMatrix
boolean[][] getSubMatrix(boolean[][] matrix,
int startCol, int endCol, int startRow, int
endRow)
Returns a rectangular submatrix
of the input matrix spanning
columns from startCol to
endCol, and rows from startRow
to endRow.
insert
String[] insert(String[] array, String value,
int index)
Inserts an element at position
index in an array and returns the
expanded array.
insert
double[] insert(double[] array, double value,
int index)
Inserts an element at position
index in an array and returns the
expanded array.
insert
int[] insert(int[] array, int value, int
index)
Inserts an element at position
index in an array and returns the
expanded array.
insert
boolean[] insert(boolean[] array, boolean
value, int index)
Inserts an element at position
index in an array and returns the
expanded array.
insert
String[] insert(String[] array, String[]
value, int[] index)
Inserts elements in an array at
positions given by the index array
and returns the expanded array.
insert
double[] insert(double[] array, double[]
value, int[] index)
Inserts elements in an array at
positions given by the index array
and returns the expanded array.
insert
int[] insert(int[] array, int[] value, int[]
index)
Inserts elements in an array at
positions given by the index array
and returns the expanded array.
insert
boolean[] insert(boolean[] array, boolean[]
value, int[] index)
Inserts elements in an array at
positions given by the index array
and returns the expanded array.
append
String[] append(String[] array, String value)
Adds an element to the end of an
array and returns the expanded
array.
append
double[] append(double[] array, double value)
Adds an element to the end of an
array and returns the expanded
array.
| 145
NAME
SYNTAX
DESCRIPTION
append
int[] append(int[] array, int value)
Adds an element to the end of an
array and returns the expanded
array.
append
boolean[] append(boolean[] array, boolean
value)
Adds an element to the end of an
array and returns the expanded
array.
append
String[] append(String[] array, String[]
value)
Adds elements to the end of an
array and returns the expanded
array.
append
double[] append(double[] array, double[]
value)
Adds elements to the end of an
array and returns the expanded
array.
append
int[] append(int[] array, int[] value)
Adds elements to the end of an
array and returns the expanded
array.
append
boolean[] append(boolean[] array, boolean[]
value)
Adds elements to the end of an
array and returns the expanded
array.
remove
String[] remove(String[] array, int index)
Removes an element from an
array and returns the shortened
array.
remove
double[] remove(double[] array, int index)
Removes an element from an
array and returns the shortened
array.
remove
int[] remove(int[] array, int index)
Removes an element from an
array and returns the shortened
array.
remove
boolean[] remove(boolean[] array, int index)
Removes an element from an
array and returns the shortened
array.
remove
String[] remove(String[] array, int[] index)
Removes elements from an array
and returns the shortened array.
remove
double[] remove(double[] array, int[] index)
Removes elements from an array
and returns the shortened array.
remove
int[] remove(int[] array, int[] index)
Removes elements from an array
and returns the shortened array.
remove
boolean[] remove(boolean[] array, int[]
index)
Removes elements from an array
and returns the shortened array.
146 |
NAME
SYNTAX
DESCRIPTION
insertRow
String[][] insertRow(String[][] matrix,
String[] value, int rowIndex)
Inserts a row into a rectangular
2D array and returns the
expanded array.
insertRow
double[][] insertRow(double[][] matrix,
double[] value, int rowIndex)
Inserts a row into a rectangular
2D array and returns the
expanded array.
insertRow
int[][] insertRow(int[][] matrix, int[]
value, int rowIndex)
Inserts a row into a rectangular
2D array and returns the
expanded array.
insertRow
boolean[][] insertRow(boolean[][] matrix,
boolean[] value, int rowIndex)
Inserts a row into a rectangular
2D array and returns the
expanded array.
insertRow
String[][] insertRow(String[][] matrix,
String[][] value, int[] rowIndex)
Adds rows to a rectangular 2D
array and returns the expanded
array.
insertRow
double[][] insertRow(double[][] matrix,
double[][] value, int[] rowIndex)
Adds rows to a rectangular 2D
array and returns the expanded
array.
insertRow
int[][] insertRow(int[][] matrix, int[][]
value, int[] rowIndex)
Adds rows to a rectangular 2D
array and returns the expanded
array.
insertRow
boolean[][] insertRow(boolean[][] matrix,
boolean[][] value, int[] rowIndex)
Adds rows to a rectangular 2D
array and returns the expanded
array.
replaceRow
String[][] replaceRow(String[][] matrix,
String[] value, int rowIndex)
Replaces a row in a rectangular
2D array and returns the array.
replaceRow
double[][] replaceRow(double[][] matrix,
double[] value, int rowIndex)
Replaces a row in a rectangular
2D array and returns the array.
replaceRow
int[][] replaceRow(int[][] matrix, int[]
value, int rowIndex)
Replaces a row in a rectangular
2D array and returns the array.
replaceRow
boolean[][] replaceRow(boolean[][] matrix,
boolean[] value, int rowIndex)
Replaces a row in a rectangular
2D array and returns the array.
replaceRow
String[][] replaceRow(String[][] matrix,
String[][] value, int[] rowIndex)
Replaces rows in a rectangular
2D array and returns the array.
replaceRow
double[][] replaceRow(double[][] matrix,
double[][] value, int[] rowIndex)
Replaces rows in a rectangular
2D array and returns the array.
replaceRow
int[][] replaceRow(int[][] matrix, int[][]
value, int[] rowIndex)
Replaces rows in a rectangular
2D array and returns the array.
| 147
NAME
SYNTAX
DESCRIPTION
replaceRow
boolean[][] replaceRow(boolean[][] matrix,
boolean[][] value, int[] rowIndex)
Replaces rows in a rectangular
2D array and returns the array.
appendRow
String[][] appendRow(String[][] matrix,
String[] value)
Adds a row to the end of a
rectangular 2D array and returns
the expanded array.
appendRow
double[][] appendRow(double[][] matrix,
double[] value)
Adds a row to the end of a
rectangular 2D array and returns
the expanded array.
appendRow
int[][] appendRow(int[][] matrix, int[]
value)
Adds a row to the end of a
rectangular 2D array and returns
the expanded array.
appendRow
boolean[][] appendRow(boolean[][] matrix,
boolean[] value)
Adds a row to the end of a
rectangular 2D array and returns
the expanded array.
appendRow
String[][] appendRow(String[][] matrix,
String[][] value)
Adds rows to the end of a
rectangular 2D array and returns
the expanded array.
appendRow
double[][] appendRow(double[][] matrix,
double[][] value)
Adds rows to the end of a
rectangular 2D array and returns
the expanded array.
appendRow
int[][] appendRow(int[][] matrix, int[][]
value)
Adds rows to the end of a
rectangular 2D array and returns
the expanded array.
appendRow
boolean[][] appendRow(boolean[][] matrix,
boolean[][] value)
Adds rows to the end of a
rectangular 2D array and returns
the expanded array.
removeRow
String[][] removeRow(String[][] matrix, int
rowIndex)
Removes a row from a 2D array
and returns the smaller array.
removeRow
double[][] removeRow(double[][] matrix, int
rowIndex)
Removes a row from a 2D array
and returns the smaller array.
removeRow
int[][] removeRow(int[][] matrix, int
rowIndex)
Removes a row from a 2D array
and returns the smaller array.
removeRow
boolean[][] removeRow(boolean[][] matrix, int
rowIndex)
Removes a row from a 2D array
and returns the smaller array.
removeRow
String[][] removeRow(String[][] matrix, int[]
rowIndex)
Removes rows from a 2D array
and returns the reduced array.
removeRow
double[][] removeRow(double[][] matrix, int[]
rowIndex)
Removes rows from a 2D array
and returns the reduced array.
148 |
NAME
SYNTAX
DESCRIPTION
removeRow
int[][] removeRow(int[][] matrix, int[]
rowIndex)
Removes rows from a 2D array
and returns the reduced array.
removeRow
boolean[][] removeRow(boolean[][] matrix,
int[] rowIndex)
Removes rows from a 2D array
and returns the reduced array.
insertColumn
String[][] insertColumn(String[][] matrix,
String[] value, int columnIndex)
Adds a column into a rectangular
2D array and returns the
expanded array.
insertColumn
double[][] insertColumn(double[][] matrix,
double[] value, int columnIndex)
Adds a column into a rectangular
2D array and returns the
expanded array.
insertColumn
int[][] insertColumn(int[][] matrix, int[]
value, int columnIndex)
Adds a column into a rectangular
2D array and returns the
expanded array.
insertColumn
boolean[][] insertColumn(boolean[][] matrix,
boolean[] value, int columnIndex)
Adds a column into a rectangular
2D array and returns the
expanded array.
insertColumn
String[][] insertColumn(String[][] matrix,
String[][] value, int[] columnIndex)
Adds columns to a rectangular
2D array and returns the
expanded array.
insertColumn
double[][] insertColumn(double[][] matrix,
double[][] value, int[] columnIndex)
Adds columns to a rectangular
2D array and returns the
expanded array.
insertColumn
int[][] insertColumn(int[][] matrix, int[][]
value, int[] columnIndex)
Adds columns to a rectangular
2D array and returns the
expanded array.
insertColumn
boolean[][] insertColumn(boolean[][] matrix,
boolean[][] value, int[] columnIndex)
Adds columns to a rectangular
2D array and returns the
expanded array.
replaceColumn
String[][] replaceColumn(String[][] matrix,
String[] value, int columnIndex)
Replaces a column in a
rectangular 2D array and returns
the array.
replaceColumn
double[][] replaceColumn(double[][] matrix,
double[] value, int columnIndex)
Replaces a column in a
rectangular 2D array and returns
the array.
replaceColumn
int[][] replaceColumn(int[][] matrix, int[]
value, int columnIndex)
Replaces a column in a
rectangular 2D array and returns
the array.
| 149
NAME
SYNTAX
DESCRIPTION
replaceColumn
boolean[][] replaceColumn(boolean[][] matrix,
boolean[] value, int columnIndex)
Replaces a column in a
rectangular 2D array and returns
the array.
replaceColumn
String[][] replaceColumn(String[][] matrix,
String[][] value, int[] columnIndex)
Replaces columns in a rectangular
2D array and returns the array.
replaceColumn
double[][] replaceColumn(double[][] matrix,
double[][] value, int[] columnIndex)
Replaces columns in a rectangular
2D array and returns the array.
replaceColumn
int[][] replaceColumn(int[][] matrix, int[][]
value, int[] columnIndex)
Replaces columns in a rectangular
2D array and returns the array.
replaceColumn
boolean[][] replaceColumn(boolean[][] matrix,
boolean[][] value, int[] columnIndex)
Replaces columns in a rectangular
2D array and returns the array.
appendColumn
String[][] appendColumn(String[][] matrix,
String[] value)
Adds a column at the end of a
rectangular 2D array and returns
the expanded array.
appendColumn
double[][] appendColumn(double[][] matrix,
double[] value)
Adds a column at the end of a
rectangular 2D array and returns
the expanded array.
appendColumn
int[][] appendColumn(int[][] matrix, int[]
value)
Adds a column at the end of a
rectangular 2D array and returns
the expanded array.
appendColumn
boolean[][] appendColumn(boolean[][] matrix,
boolean[] value)
Adds a column at the end of a
rectangular 2D array and returns
the expanded array.
appendColumn
String[][] appendColumn(String[][] matrix,
String[][] value)
Adds columns to the end of a
rectangular 2D array and returns
the expanded array.
appendColumn
double[][] appendColumn(double[][] matrix,
double[][] value)
Adds columns to the end of a
rectangular 2D array and returns
the expanded array.
appendColumn
int[][] appendColumn(int[][] matrix, int[][]
value)
Adds columns to the end of a
rectangular 2D array and returns
the expanded array.
appendColumn
boolean[][] appendColumn(boolean[][] matrix,
boolean[][] value)
Adds columns to the end of a
rectangular 2D array and returns
the expanded array.
removeColumn
String[][] removeColumn(String[][] matrix,
int columnIndex)
Removes a column from a
rectangular 2D array and returns
the smaller array.
150 |
NAME
SYNTAX
DESCRIPTION
removeColumn
double[][] removeColumn(double[][] matrix,
int columnIndex)
Removes a column from a
rectangular 2D array and returns
the smaller array.
removeColumn
int[][] removeColumn(int[][] matrix, int
columnIndex)
Removes a column from a
rectangular 2D array and returns
the smaller array.
removeColumn
boolean[][] removeColumn(boolean[][] matrix,
int columnIndex)
Removes a column from a
rectangular 2D array and returns
the smaller array.
removeColumn
String[][] removeColumn(String[][] matrix,
int[] columnIndex)
Removes columns from a
rectangular 2D array and returns
the reduced array.
removeColumn
double[][] removeColumn(double[][] matrix,
int[] columnIndex)
Removes columns from a
rectangular 2D array and returns
the reduced array.
removeColumn
int[][] removeColumn(int[][] matrix, int[]
columnIndex)
Removes columns from a
rectangular 2D array and returns
the reduced array.
removeColumn
boolean[][] removeColumn(boolean[][] matrix,
int[] columnIndex)
Removes columns from a
rectangular 2D array and returns
the reduced array.
matrixSize
int[] matrixSize(String[][] matrix)
Returns the number of rows and
columns of a matrix as an integer
array of length 2.
matrixSize
int[] matrixSize(double[][] matrix)
Returns the number of rows and
columns of a matrix as an integer
array of length 2.
matrixSize
int[] matrixSize(int[][] matrix)
Returns the number of rows and
columns of a matrix as an integer
array of length 2.
matrixSize
int[] matrixSize(boolean[][] matrix)
Returns the number of rows and
columns of a matrix as an integer
array of length 2.
transpose
String[][] transpose(String[][] matrix)
Returns the transpose of a
matrix.
transpose
double[][] transpose(double[][] matrix)
Returns the transpose of a
matrix.
| 151
NAME
SYNTAX
DESCRIPTION
transpose
int[][] transpose(int[][] matrix)
Returns the transpose of a
matrix.
transpose
boolean[][] transpose(boolean[][] matrix)
Returns the transpose of a
matrix.
String Methods
String methods are used to process string variables and string arrays.
NAME
SYNTAX
DESCRIPTION
concat
String concat(String separator, String ...
strs)
Concatenates the given
varargs-array of strings into a
single string using the given
separator.
concat
String[] concat(String colSepar, String
rowSepar, String[]... matr)
Concatenates the given string
matrix (which can be given as a
varargs of rows) into a single
string. Puts colSepar between
values of columns of a row, and
rowSepar between rows.
contains
boolean contains(String[] strs, String str)
Returns true if the given string
array strs contains the given
string str.
find
int[] find(String[] strs, String str)
Returns an array with the indices
to all occurrences of str in strs.
findIn
int findIn(String[] strs, String str)
Returns the index to the first
occurrence of str in strs or -1 if
no match.
findIn
int findIn(String str, String toFind)
Returns the first index of str that
is the start of the substring
toFind. If there is no substring
matching toFind in str, -1 is
returned.
length
int length(String str)
Returns the length of the string
str.
replace
String replace(String str, String orig,
String replacement)
Returns a string where orig has
been replaced by replacement.
152 |
NAME
SYNTAX
DESCRIPTION
split
String[] split(String str)
Returns an array of strings by
splitting the given string at spaces.
split
String[] split(String str, String separator)
Returns an array of strings by
splitting the given string at the
given separator.
substring
String substring(String str, int start, int
length)
Returns a substring with the given
length starting at the given
position.
unique
String[] unique(String[] strs)
Returns an array of strings with
the unique values in the given
array of strings.
C olle ct ion M e t ho ds
Collection methods are used to copy, compare, sort, and merge variables and
arrays.
NAME
SYNTAX
DESCRIPTION
copy
String[] copy(String... toCopy)
Returns a copy of the given array
of strings, which can also be
specified as a varargs of strings.
copy
String[][] copy(String[]... toCopy)
Returns a copy of the given string
matrix, which can also be
specified as a varargs of rows
(string arrays).
copy
double[] copy(double... toCopy)
Returns a copy of the given array
of doubles, which can also be
specified as a varargs of doubles.
copy
double[][] copy(double[]... toCopy)
Returns a copy of the given
double matrix, which can also be
specified as a varargs of rows
(double arrays).
copy
int[] copy(int... toCopy)
Returns a copy of the given array
of integers, which can also be
specified as a varargs of integers.
copy
int[][] copy(int[]... toCopy)
Returns a copy of the given
integer matrix, which can also be
specified as a varargs of rows
(integer arrays).
| 153
NAME
SYNTAX
DESCRIPTION
copy
boolean[] copy(boolean... toCopy)
Returns a copy of the given array
of booleans, which can also be
specified as a varargs of booleans.
copy
boolean[][] copy(boolean[]... toCopy)
Returns a copy of the given
boolean matrix, which can also
be specified as a varargs of rows
(boolean arrays).
equals
boolean equals(String[] str1, String[] str2)
Returns true if all strings in the
given array are equal and they
have the same number of
elements.
equals
boolean equals(String[][] matr1, String[][]
matr2)
Returns true if all strings in the
given matrix are equal and they
have the same number of
elements.
equals
boolean equals(int[] ints1, int[] ints2)
Returns true if all integers in the
given array are equal and they
have the same number of
elements.
equals
boolean equals(int[][] ints1, int[][] ints2)
Returns true if all integers in the
given matrix are equal and they
have the same number of
elements.
equals
boolean equals(double dl1, double dl2, double
relErrorTolerance)
Compares whether the relative
error of two doubles is within
allowed tolerance using abs(( a b ) / b ), where b is the larger of
the doubles (by absolute value).
equals
boolean equals(double dl1, double dl2)
Same as above, but uses a default
relErrorTolerance of 0.0001.
equals
boolean equals(double[] dbls1, double[]
dbls2, double relErrorTolerance)
Compares the relative errors ( ~
abs(( a - b) / b ) of elements in
the arrays pairwise and returns
true if all relative errors are
below relErrorTolerance and
the arrays have the same number
of elements.
equals
boolean equals(double[] dbls1, double[]
dbls2)
Same as above, but uses a default
relErrorTolerance of 0.0001.
154 |
NAME
SYNTAX
DESCRIPTION
equals
boolean equals(double[][] dbls1, double[][]
dbls2, double relErrorTolerance)
Compares the relative errors ( ~
abs(( a - b ) / b ) of elements in
the matrices pairwise and returns
true if all relative errors are
below relErrorTolerance and
the matrices have the same
number of elements.
equals
boolean equals(double[][] dbls1, double[][]
dbls2)
Same as above, but uses a default
relErrorTolerance of 0.0001.
sort
sort(String[] strs)
Sorts the given array of strings.
NOTE: The array is sorted in
place.
sort
sort(int[] ints)
Sorts the given array of integers.
NOTE: The array is sorted in
place.
sort
sort(double[] doubles)
Sorts the given array of doubles.
NOTE: The array is sorted in
place.
sort
sort(String[][] strs)
Sorts the given 2D array of
strings. The columns are sorted
by their row values from top to
bottom. NOTE: The array is
sorted in place.
sort
sort(int[][] ints)
Sorts the given 2D array of
integers. The columns are sorted
by their row values from top to
bottom. NOTE: The array is
sorted in place.
sort
sort(double[][] doubles)
Sorts the given 2D array of
doubles. The columns are sorted
by their row values from top to
bottom. NOTE: The array is
sorted in place.
merge
merge(String[]... toMerge)
Returns an array of strings with all
strings merged from the given
arrays.
| 155
NAME
SYNTAX
DESCRIPTION
merge
merge(int[]... toMerge)
Returns an array of integers with
all integers merged from the two
given arrays.
merge
merge(double[]... toMerge)
Returns an array of doubles with
all doubles merged from the two
given arrays.
Model Builder Methods for Use in Add-Ins
For writing add-in method code that operates on the current component, current
mesh, current physics, and so on, use the methods in the table below.
NAME
SYNTAX
DESCRIPTION
getCurrentComponent
getCurrentComponent()
Returns an object of the type
ModelNode for the current
component.
getCurrentMesh
getCurrentMesh()
Returns an object of the type
MeshSequence for the current
mesh.
getCurrentNode
getCurrentNode()
Returns an object of the type
ModelEntity for the current
component.
getCurrentPhysics
getCurrentPhysics()
Returns an object of the type
Physics for the current physics
interface.
getCurrentPlotGroup
getCurrentPlotGroup()
Returns an object of the type
ResultFeature for the current
component.
getCurrentStudy
getCurrentStudy()
Returns an object of the type
Study for the current
component.
selectNode
selectNode(ModelEntity entity)
Selects a model tree node and
displays its Settings window after
the execution of a method from
the Model Builder.
These methods return the corresponding entity such that the method code in an
add-in can operate on it. When called from an application a method in this
156 |
category returns null. Also, null is returned if no entity of the corresponding
type exists such that nothing is current.
General utility methods for writing methods for add-ins are listed in the table
below.
NAME
SYNTAX
DESCRIPTION
createAddinForm
FormFeature
createAddinForm(String tag,
String definition)
Creates a Settings Form node
with the given tag based on the
Form Definition node with the
given name definition. The
Form Definition must be
configured to show as Settings
form.
createAddinMethodCall
MethodCallFeature
createAddinMethodCall(String
tag, String definition)
Creates a Method Call node with
the given tag based on the
Method Definition node with the
given name definition. The
Method Definition must be
configured to use as Method call.
To learn more about using these methods you can review the Application Builder
settings for one of the built-in add-ins by opening the corresponding MPH file.
In a typical Windows installation the built-in add-in library is located at
C:\Program Files\COMSOL\COMSOL62\COMSOL_Multiphysics\addins
| 157
Programming Examples
This section contains examples that illustrate solving practical tasks by accessing
and manipulating the model object and using the built-in methods. Note that
additional examples of user-defined methods are provided in the example
applications of the Application Libraries accessible from the File menu.
Running the Examples
To run the code in the examples below, you can create a method for use in a model
or application. You can, for example, choose the option Blank Model in the Model
Wizard. To create a new method, go to the Developer tab in the Model Builder
and click the New Method button in the ribbon. In the Application Builder, paste
the code into the new method. Finally, you can run the code from the Developer
tab in the Model Builder by choosing the method you just created from the Run
Method toolbar menu.
Visualization Without Solution Data: Grid Datasets
The section “Results” on page 48 shows how to write code for various parts of the
Results node in the model tree, including Datasets, Tables, and Plot Groups. These
examples assume that you have solution data available from solving, for example,
a heat transfer, CFD, or structural mechanics problem.
You can also create visualizations without having associated solution data by either
using grid datasets or using low-level functionality only available through
methods. You can, for example, write code for plotting points and triangles
without any associated solution data. These techniques are useful when creating
applications where customized plot functionality is needed. This section shows
how to use grid datasets, and the next section shows how to use low-level
functionality.
P LOTTING A U NIT S PHERE USING A G RID D ATASET
Grid datasets are available in the Model Builder and can be used in applications for
the sole purpose of visualization without any associated solution data. The code
below creates a visualization of a unit sphere as an isosurface with the z-coordinate
as color data.
158 |
model.func().create("an1", "Analytic");
model.result().dataset().create("grid1", "Grid3D");
with(model.result().dataset("grid1"));
set("source", "data");
set("parmin1", -1);
set("parmax1", +1);
set("parmin2", -1);
set("parmax2", +1);
set("parmin3", -1);
set("parmax3", +1);
set("source", "function");
set("function", "an1");
endwith();
model.result().create("pg1", "PlotGroup3D");
model.result("pg1").create("iso1", "Isosurface");
with(model.result("pg1").feature("iso1"));
set("expr", "x^2+y^2+z^2-1");
set("levelmethod", "levels");
set("levels", 0.0);
endwith();
model.result("pg1").feature("iso1").create("col1", "Color");
with(model.result("pg1").feature("iso1").feature("col1"));
set("expr", "z");
endwith();
model.result("pg1").run();
Comments
If there is no solution-based Dataset available, then the Grid3D dataset needs to
have a Function as its Source. In the example above, a default Analytic function is
created with tag an1. A default Analytic function corresponds to f(x) = x, and its
only purpose is to give the grid dataset an evaluation context.
Note: The alternative is to solve a physics problem on a mesh and reference the
corresponding solution dataset. The method of referencing a Function makes it
possible to create visualizations without solution data.
The source for the Grid3D dataset with tag grid1 is set to function, and finally,
the function property of grid1 is set to an1.
The Grid3D dataset has options for max and min parameter bounds, shown in the
example code above. An additional grid resolution option is not shown in this
example. However, you can learn about its syntax by using Record Code from the
Model Builder.
| 159
Visualization of Points, Curves, and Surfaces
The following examples describe low-level functionality for visualization that is
only available from methods and is not associated with any solution data. For
visualization based on solution data, see the section “Results” on page 48.
The examples below illustrate using the following plot types:
• Point Data
• Line Data
• Surface Data
• Tube Data
• Arrow Data
• Annotation Data
Once created, the plot type names are visible in the Settings window of each plot.
In addition to the properties modified by the examples below, in the Settings
window of these plot types, you can see the number of geometric entities created,
such as number of points, line segments, and triangles. Just as for other types of
plots, you can also change the Range of color and data, as well as Coloring and Style.
P OINTS IN 2D
The following code plots a circle of points using the Point Data plot type.
// A circle of points
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 2);
ResultFeature plot = pg.create("pt1", "PointData");
int N = 17;
double[][] p = new double[2][N];
double[] color = new double[N];
double R = 1000;
for (int i = 0; i < N; i++) {
double angle = i*2*Math.PI/N;
p[0][i] = R*Math.cos(angle);
p[1][i] = R*Math.sin(angle);
color[i] = p[1][i];
}
plot.set("pointdata", p)
.set("colordata", color)
.set("coloring", "colortable");
plot.run();
Comments
The first line
String pgTag = model.result().uniquetag("pg");
160 |
creates a unique tag for the plot group to be created. This is useful if you intend
to add a varying number of plot groups in your model or application.
The line
ResultFeature pg = model.result().create(pgTag, 2);
creates a 2D Plot Group using the newly created unique tag. The second argument
to create defines the dimension of the plot group (2 for 2D, 3 for 3D, and so on).
The line
ResultFeature plot = pg.create("pt1", "PointData");
creates a plot of the type PointData. This plot type is only available through
methods.
The middle part of the example code generates the points making up the circle.
The point coordinates are stored in the 2-by-N array p, along with color data in the
array color of length N. The color data is, in this example, simply based on the
index of the points and is used to control the coloring of each point based on a
color table.
The last few lines populate the fields of the Point Data plot.
plot.set("pointdata", p)
.set("colordata", color)
.set("coloring", "colortable");
The property pointdata takes the 2-by-N array p as its input. The options for the
coloring property are colortable or uniform.
To learn about the syntax for the additional properties available for a Point Data
plot, you can run the above code in a blank model, browse to the Settings window
for the Point Data plot, click Record Code, and change the corresponding plot
properties. Note that the name of the plot type in the Settings window of the plot
in the model tree is Point Data.
T URNING O FF M ODEL H ISTORY
When using this type of low-level functionality for larger sets of data, such as a
large number of points, the stored model history may become excessively large.
Because of this, it is recommended to temporarily turn off model history recording
when using this type of functionality; see “Turning Off and Resetting The Model
History” on page 53.
P OINTS IN 3D
The following code plots points in an undulating pattern in 3D using the Point
Data plot type.
// Undulating points in 3D
| 161
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 3);
ResultFeature plot = pg.create("pt1", "PointData");
int N = 37;
double[][] p = new double[3][N];
double[] color = new double[N];
double R = 1000;
for (int i = 0; i < N; i++) {
double angle = i*2*Math.PI/N;
p[0][i] = R*Math.cos(angle);
p[1][i] = R*Math.sin(angle);
p[2][i] = R*Math.cos(3*angle);
color[i] = p[1][i];
}
plot.set("pointdata", p)
.set("colordata", color)
.set("coloring", "colortable")
.set("sphereradiusscale", 1);
plot.run();
selectNode(pg);
Comments
When plotting 3D points the line
model.result().create(pgTag, 3);
has the second argument set to 3 in order to create a 3D Plot Group. In 3D, the
point coordinates, p is a 3-by-N array.
The line
.set("sphereradiusscale", 1);
controls the radius of the sphere used to render each point.
To automatically display the newly created plot, the line
selectNode(pg);
is added last in the code segment.
To get a denser set of points, you can increase the integer N to, say, 370.
C URVE IN 3D
The following code plots line segments in the shape of a 3D helix using the Line
Data plot type.
// A 3D helix from line segments
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 3);
ResultFeature plot = pg.create("line1", "LineData");
int N = 100;
double[][] p = new double[3][N];
int[][] t = new int[2][N-1];
for (int i = 0; i < N; i++) {
double s = 4*Math.PI*i/N;
162 |
p[0][i] = s/5;
p[1][i] = Math.sin(s);
p[2][i] = Math.cos(s);
if (i > 0) {
t[0][i-1] = i-1;
t[1][i-1] = i;
}
}
plot.set("pointdata", p)
.set("elementdata", t);
plot.run();
selectNode(pg);
Comments
The line
ResultFeature plot = pg.create("line1", "LineData");
creates a plot of the type LineData. This plot type is only available through
methods. Just as for Point Data plots, the point coordinates p is a 3-by-N array. In
addition to pointdata, the LineData plot type takes elementdata as its input. In
the example, this is represented by the 2-by-N array t and contains indexes to the
columns of p, corresponding to the start and end points of the lines.
In a similar way, line segments can be plotted in 2D by creating a 2D plot group
and by letting the point coordinates be a 2-by-N array. See also “Points in 2D” on
page 160.
T RIANGULATED S HAPE IN 2D
The following code plots triangles in the shape of a 2D pentagon by using the
Surface Data plot type.
// A 2D pentagon from triangles
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 2);
ResultFeature plot = pg.create("surf1", "SurfaceData");
int N = 5;
double[][] p = new double[2][N+1];
int[][] t = new int[3][N];
p[0][0] = 0;
p[1][0] = 0;
for (int i = 0; i < N; i++) {
double angle = i*2*Math.PI/N;
p[0][i+1] = Math.cos(angle);
p[1][i+1] = Math.sin(angle);
t[0][i] = 0;
t[1][i] = i+1;
t[2][i] = 1+(i+1)%N;
}
plot.set("pointdata", p)
.set("elementdata", t);
plot.run();
| 163
selectNode(pg);
Comments
The line
ResultFeature plot = pg.create("surf1", "SurfaceData");
creates a plot of the type SurfaceData. This plot type is only available through
methods. Just as for 2D Point Data plots, the point coordinates p is a 2-by-N array.
In addition to pointdata, and similar to the LineData plot type, the SurfData
plot type takes elementdata as its input. In the example, this is represented by the
3-by-N array t and contains indexes to the columns of p, corresponding to the
vertexes of the triangles. The ordering of the point indexes in the array t is not
important for 2D Surface Data plots.
F UNCTION S URFACE IN 3D
The following code plots triangles in the shape of a 3D rotationally symmetric
sinc-function surface by using the Surface Data plot type.
// A 3D sinc(r) function surface
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 3);
ResultFeature plot = pg.create("surf1", "SurfaceData");
int Nx = 51;
int Ny = 51;
double[][] p = new double[3][Nx*Ny];
int[][] t = new int[3][2*(Nx-1)*(Ny-1)];
double[] color = new double[Nx*Ny];
int pos = 0;
for (int i = 0; i < Ny; i++) {
for (int j = 0; j < Nx; j++) {
double x = 20*(j-Nx/2)/Nx;
double y = 20*(i-Ny/2)/Ny;
double r = Math.sqrt(x*x+y*y);
double z = 4*((r == 0) ? 1 : (Math.sin(r)/r));
p[0][pos] = x;
p[1][pos] = y;
p[2][pos] = z;
color[pos] = z;
pos++;
}
}
pos = 0;
for (int i = 0; i < Ny-1; i++) {
for (int j = 0; j < Nx-1; j++) {
int p00 = Nx*i+j;
int p01 = Nx*i+j+1;
int p10 = Nx*(i+1)+j;
int p11 = Nx*(i+1)+j+1;
t[0][pos] = p00;
t[1][pos] = p01;
t[2][pos] = p11;
164 |
pos++;
t[0][pos] = p00;
t[1][pos] = p11;
t[2][pos] = p10;
pos++;
}
}
plot.set("pointdata", p)
.set("elementdata", t)
.set("colordata", color)
.set("coloring", "colortable");
plot.run();
selectNode(pg);
Comments
This example is similar to “Triangulated Shape in 2D” on page 163, but with the
point array being a 3-by-N array for 3D surfaces. For Surface Data plots in 3D, the
ordering of the indexes in the elementdata array t matters. It determines the
direction of the surface normal, which is used for the lighting effect when using
Scene Light in the Graphics window. The surface normal of a triangle is determined
according to the “right-hand rule”. In mathematical terms, the surface normal is
defined as the vector product:
n= p t 1 – p t 0   p t 2 – pt0 
where the indexes into t represent the rows in one of the columns of t and p
represents a column in the array of points p.
To ensure that the lighting effect produces expected results, the triangle surface
normal directions need to consistently point in the same direction as the intended
overall surface normal direction. As an alternative to making sure that the indexes
come in the correct order, the normal direction may be given as an additional
input to a Surface Data plot. This is shown in the next example section, Sphere in
3D.
S PHERE IN 3D
The following code plots triangles in the shape of a 3D sphere by using the Surface
Data plot type.
// A coarse sphere with user-supplied normals
int Nx = 20;
int Ny = 10;
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 3);
ResultFeature plot = pg.create("surf1", "SurfaceData");
double[][] p = new double[3][Nx*Ny];
double[][] normals = new double[3][Nx*Ny];
int[][] t = new int[3][2*(Nx-1)*(Ny-1)];
double[] color = new double[Nx*Ny];
| 165
int pos = 0;
double R = 10;
for (int i = 0; i < Ny; i++) {
for (int j = 0; j < Nx; j++) {
double theta = Math.PI*i/(Ny-1);
double phi = 2*Math.PI*j/(Nx-1);
double x = R*Math.sin(theta)*Math.cos(phi);
double y = R*Math.sin(theta)*Math.sin(phi);
double z = R*Math.cos(theta);
p[0][pos] = x;
p[1][pos] = y;
p[2][pos] = z;
normals[0][pos] = x;
normals[1][pos] = y;
normals[2][pos] = z;
color[pos] = z;
pos++;
}
}
pos = 0;
for (int i = 0; i < Ny-1; i++) {
for (int j = 0; j < Nx-1; j++) {
int p00 = Nx*i+j;
int p01 = Nx*i+j+1;
int p10 = Nx*(i+1)+j;
int p11 = Nx*(i+1)+j+1;
t[0][pos] = p00;
t[1][pos] = p01;
t[2][pos] = p11;
pos++;
t[0][pos] = p00;
t[1][pos] = p11;
t[2][pos] = p10;
pos++;
}
}
plot.set("pointdata", p)
.set("elementdata", t)
.set("colordata", color)
.set("normaldata", normals)
.set("coloring", "colortable");
plot.run();
selectNode(pg);
Comments
In this example, information about the surface normal direction is not given
implicitly by the triangle orientation, but instead explicitly by the parameter
normaldata by means of the 3-by-Nx*Ny array normals containing surface normal
vectors at each point. The normal vectors do not need to be normalized; only the
direction is used. The coloring of the sphere is based on the z-coordinate of each
triangle point and is stored for each point in the 3-by-Nx*Ny array color.
166 |
The sphere is constructed from a discrete grid defined in terms of spherical
coordinate angles, where each grid cell is divided into two triangles. The number
of triangles t is then given by 2*(Nx-1)*(Ny-1).
T UBE P LOT IN 3D, L OGARITHMIC S PIRAL
The following code plots a tube in 3D in the shape of a logarithmic spiral by using
the Tube Data plot type.
// A logarithmic tube spiral in 3D
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 3);
ResultFeature plot = pg.create("tube1", "TubeData");
int N = 1000;
double[][] p = new double[3][N];
double[] radius = new double[N];
double[] color = new double[N];
for (int i = 0; i < N; i++) {
double par = 0.005*i;
p[0][i] = Math.exp(par)*Math.cos(10*par);
p[1][i] = Math.exp(par)*Math.sin(10*par);
p[2][i] = 0.1*i;
radius[i] = 0.2*Math.sqrt(i+1);
color[i] = i;
}
plot.set("pointdata", p)
.set("radiusdata", radius)
.set("colordata", color)
.set("coloring", "colortable");
plot.run();
selectNode(pg);
Comments
A Tube Data plot is similar to a Point Data, plot but with an absolute radius array
given as an argument to radiusdata. For the Point Data plot type, there is a similar
sphereradiusscale.
A RROWS IN 2D
The following code plots arrows in a circular pattern by using the Arrow Data plot
type.
// Arrows in a circular pattern in 2D
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 2);
ResultFeature plot = pg.create("arrow1", "ArrowData");
int N = 17;
double[][] p = new double[2][N];
double[][] vec = new double[2][N];
double len = 0.2;
for (int i = 0; i < N; i++) {
| 167
double angle = 2*Math.PI*i/N;
p[0][i] = Math.cos(angle);
p[1][i] = Math.sin(angle);
vec[0][i] = -len*p[0][i];
vec[1][i] = -len*p[1][i];
}
plot.set("pointdata", p)
.set("vectordata", vec);
plot.run();
selectNode(pg);
Comments
An Arrow Data plot associates an array of vectors, in the example vec, to each point
p.
A RROWS IN 3D
The following code plots arrows in a logarithmic spiral pattern by using the Arrow
Data plot type.
// Arrows in a logarithmic spiral pattern in 3D
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 3);
ResultFeature plot = pg.create("arrow1", "ArrowData");
int N = 1000;
double[][] p = new double[3][N];
double[][] vec = new double[3][N];
double[] color = new double[N];
for (int i = 0; i < N; i++) {
double par = 0.005*i;
p[0][i] = Math.exp(par)*Math.cos(10*par);
p[1][i] = Math.exp(par)*Math.sin(10*par);
p[2][i] = 0.1*i;
double len = Math.sqrt(p[0][i]*p[0][i]+p[1][i]*p[1][i]+p[2][i]*p[2][i]);
for (int j = 0; j < 3; j++) {
vec[j][i] = 4*p[j][i]/len;
}
color[i] = i;
}
plot.set("pointdata", p)
.set("vectordata", vec)
.set("colordata", color)
.set("coloring", "colortable");
plot.run();
selectNode(pg);
Comments
In this example, in addition to the example in the section “Arrows in 2D”, color
data is used based on the point index.
168 |
A NNOTATIONS IN 2D
The following code renders text strings in a circular pattern by using the
Annotation Data plot type.
// Letters in a circular pattern in 2D
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 2);
for (int i = 0; i < 26; i++) {
double angle = 2*Math.PI*i/26;
ResultFeature plot = pg.create("ann"+i, "AnnotationData");
plot.set("pos", new double[]{Math.cos(angle), Math.sin(angle)})
.set("text", "ABCDEFGHIJKLMNOPQRSTUVWXYZ".substring(i, i+1))
.set("showpoint", false);
}
pg.run();
selectNode(pg);
Comments
The property pos takes as its input an array of length 2 representing 2D
coordinates for the position of the string to be rendered. The property text takes
as its input the string to be rendered. The Boolean property showpoint determines
if a point, at the 2D coordinate position, should be rendered or not.
A NNOTATIONS IN 3D WITH L A T E X S YNTAX
The following code renders text strings with Greek letters of different colors at the
corners of a cube by using the Annotation Data plot type.
// Greek letters at the corners of a cube
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 3);
String[] texts = {"\\alpha", "\\beta", "\\gamma", "\\delta", "\\epsilon",
"\\zeta", "\\eta", "\\theta"};
String[] colors = {"black", "blue", "cyan", "gray", "green", "magenta", "red",
"yellow"};
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 2; y++) {
for (int z = 0; z < 2; z++) {
int index = x+2*y+4*z;
ResultFeature plot = pg.create("ann"+index, "AnnotationData");
plot.set("pos", new double[]{x, y, z})
.set("text", "$"+texts[index]+"$")
.set("latexmarkup", true)
.set("color", colors[index]);
}
}
}
pg.run();
selectNode(pg);
| 169
Comments
The Boolean property latexmarkup determines if the text should be interpreted
using LaTeX syntax or not.
Reading and Writing Data to File
The Application Builder provides several built-in methods for reading and writing
different types of files: text files, CSV-files, Excel® files (requires LiveLink™ for
Excel®), and binary files. These file methods are listed in the table “File Methods”
on page 103.
Note that easy-to-use user-interface-based techniques for reading and writing to
file are available in the Form editor of the Application Builder. It is recommended
that you consider those techniques first before using the programming-based ways
described in this section. For more information, see the book Introduction to
Application Builder and “GUI Command Methods” on page 129. There, you
can also find information on the various file schemes used in the Application
Builder for reading and writing files when running applications in a web browser.
R EADING AND W RITING T EXT AND S PREADSHEET F ILES O VERVIEW
The following built-in methods are available for reading and writing text files:
• readFile
• readMatrixFromFile
• readStringMatrixFromFile
• readCSVFile
• writeFile
• writeCSVFile
In addition, you can use the low-level methods available in the class CsReader to
read text files line by line or character by character. See the next section,
“Processing Text Files using the CsReader and CsWriter Classes” on page 184, for
more information.
If you have a LiveLink™ for Excel® license, then the following methods are
available for reading and writing Microsoft Excel Workbook files:
• readExcelFile
• writeExcelFile
170 |
I NTRODUCTION TO R EADING F ILES WITH A CSV-F ILE E XAMPLE
Assume that you want to automate a certain thermal analysis of a circuit board by
creating an application that reads in data from a spreadsheet. Further assume that
information about the circuit board components is given by a proprietary format
in a spreadsheet with columns for component type, heat dissipation, locations, and
sizes. Assume that such a file looks like:
B,0,0,0,-1.57,350,200,1.57
B,3,30,10,0,40,10,2
C,1,100,30,0,3,10,
C,1,110,30,0,3,10,
B,4,30,30,0,40,10,2
...
C,1,200,30,0,3,10,
B,10,100,150,0,10,20,30
B,10,130,150,0,10,20,30
B,10,160,150,0,10,20,30
Each row of the spreadsheet represents a different component. The first column
can contain a letter, either B or C, denoting that the component can be modeled
as either a Block or a Cylinder primitive. The next column is the total heat
dissipation within the component (measured in watts). The next three columns
represent the location of the component in the global Cartesian coordinate system
(measured in millimeters). Lastly, if the row contains a block component, there are
three more columns that denote the width, depth, and height of the block. If the
row contains a cylinder component, then there are two more columns that contain
the radius and height information, respectively.
For the example shown above, the first row of the spreadsheet represents the
circuit board itself, which is 1.57 mm thick and 350 mm-by-200 mm. It is offset
from the origin by 1.57 mm in the z direction and does not dissipate any heat.
| 171
You can write the data in the spreadsheet out to a comma-delimited text file, also
known as a CSV-file. The user interface of the application used to read the data is
shown in the figure below.
172 |
The Settings window for the File Import form object is shown in the figure below.
In the Settings window, CSV File (*.csv) is added to the File types list. When
browsing for the file, this setting will filter out any file that is not a CSV-file.
There is also a File Declaration called File 1, which is referenced by the file scheme
syntax upload:///inputFile in the method populateBoard, which is used to
read and process the data. The method is called as an event shown at the bottom
of the Settings window of the File Import form object in the Events section.
Note that if you would like to open a file browser from a button or a menu item,
instead of using a File Import object, you can create a method that calls the built-in
method importFile; for example
importFile("file1");
assuming there is a file declaration file1.
The method populateBoard is listed below.
String[][] D = readCSVFile("upload:///inputFile");
model.geom("geom1").feature().clear();
for (int k = 0; k < D.length; k++) {
if (D[k][0].equals("B")) { // Read in a block
model.geom("geom1").create("P"+k, "Block").set("pos", new
String[]{D[k][2], D[k][3], D[k][4]});
| 173
model.geom("geom1").feature("P"+k).set("size", new String[]{D[k][5],
D[k][6], D[k][7]});
}
else if (D[k][0].equals("C")) { // Read in a cylinder
model.geom("geom1").create("P"+k, "Cylinder").set("pos", new
String[]{D[k][2], D[k][3], D[k][4]});
model.geom("geom1").feature("P"+k).set("r", D[k][5]);
model.geom("geom1").feature("P"+k).set("h", D[k][6]);
}
model.geom("geom1").feature("P"+k).set("selresult", "on");
model.variable().remove("var"+k);
model.variable().create("var"+k).model("comp1");
model.variable("var"+k).selection().named("geom1_P"+k+"_dom");
model.variable("var"+k).set("Q", D[k][1]);
}
model.geom("geom1").run();
zoomExtents("/form1/graphics1");
Comments
In the first line, the data read from the CSV-file is stored in the 2D array D. The
rest of the code parses this array and populates the various parts of a model object.
The application allows you to save the result as an MPH-file with variables defined
for the heat sources and geometry objects defined for the components, as shown
in the figures below.
174 |
You can download the MPH-file for this app from:
https://www.comsol.com/model/using-text-files-to-automate-model-preprocessing-46721
R EADING E XCEL F ILES
The application described above can easily be extended to also read Microsoft
Excel® Workbook files. Note that this requires LiveLink™ for Excel®. In the
Settings window for the File Import form object, you can add Microsoft Excel
| 175
Workbook (*.xlsx) and Microsoft Excel Workbook (*.xls) to the File types section, as
shown in the figure below.
The next step is to add a few lines of code in the beginning of the method
populateBoard, as shown below.
String file_name = getFilePath("upload:///inputFile");
if (file_name.endsWith(".xls") || file_name.endsWith(".xlsx"))
D = readExcelFile("upload:///inputFile");
else if (file_name.endsWith(".csv"))
D = readCSVFile("upload:///inputFile");
else
error("Unknown file type.");
Comments
The 2D array D can be defined as a global array in the Declarations node in the
application tree. Alternatively, it can be declared as an array that is local to the
method by adding the line
String[][] D = null;
before the if statement. Which option to choose depends on how you would like
to use the 2D array data after having read the file.
The method getFilePath returns the full path and name of the uploaded file. The
if statements control which method is used to read the file based on its file
176 |
extension. The file extension is retrieved with the Java® method endsWith(),
which belongs to the String class. Note that you can see which methods are
available for a string by typing the name of the string followed by a period and
Ctrl+Space, as shown in the figure below.
W RITING CSV-F ILES
You can write to a CSV-file using four different call syntaxes for the method
writeCSVFile, depending on if the contents are strings or doubles and whether
you would like to overwrite an already existing file or appending to its contents.
In the case above, the contents are a mix of numbers and characters, so the 2D
array storing the information needs to be a string array.
Assume that we would like to move one of the components, say, the second to last
one, in the file listed above. We would like to change the corresponding line in the
file from
B,10,130,150,0,10,20,30
to
B,10,130,140,0,10,20,30
This corresponds to a change in the y-coordinate of one of the blocks from 150 to
140.
The following code shows how to make this change and then write data on this
format, assuming that the array D has been declared as a global variable in the
Declarations node, as described above.
int[] sz = matrixSize(D);
D[sz[0]-2][3] = "140.0";
writeCSVFile("temp:///my_layout.csv", D);
fileSaveAs("temp:///my_layout.csv");
| 177
Comments
The first line stores the size of the 2D array (or matrix) D in a 1-by-2 array (or
vector) sz. The second line sets the string value of the y-coordinate of the block
of the second-to-last row in D.
The line
writeCSVFile("temp:///my_layout.csv", D);
writes the data to a file my_layout.csv in a temporary folder whose location is
determined by the Preferences of either COMSOL Multiphysics or COMSOL
Server, depending on which software is used to run the application. For example,
in a typical Windows® installation of COMSOL Multiphysics, the location will be
similar to
C:\Users\paul\AppData\Local\Temp\
where the username is paul.
W RITING F ILES IN G ENERAL
Note that as a first step in the example above, the file is written to a temporary file
using the writeCSVFile method. This step is done automatically by the
application. In the second step, the method fileSaveAs opens a file browser and
lets the user of the application choose the file location; for example, a folder on
the computer’s local file system or to a network folder. This extra step is needed
in order for the application to function in a web browser. Due to the security
settings of a typical web browser, the application is not permitted to automatically
save a file to an arbitrary location. Instead, the application is allowed to save to a
few specific locations, including the temp folder, whose location is specified in the
Preferences dialog box. The other locations are the user and common folders, also
specified in the Preferences dialog box. For more information, see the
Introduction to Application Builder.
W RITING E XCEL F ILES
If you have licensed LiveLink™ for Excel®, then you can write to a Microsoft Excel
Workbook file in a way that is similar to that of a CSV-file, with the exception that
the append option is not available. The following code, corresponding to the
previous CSV-file example, shows how to write to an Excel file.
int[] sz = matrixSize(D);
D[sz[0]-2][3] = "140.0";
writeExcelFile("temp:///my_layout.xlsx", D);
fileSaveAs("temp:///my_layout.xlsx");
178 |
R EADING M ATRIX F ILES
Reading files with numerical data in matrix format is easiest when using the
readMatrixFromFile method. This method assumes that the file has the
spreadsheet format, as available in the model tree Export node. The example below
shows a file on the spreadsheet format.
% Model:
my_model.mph
% Version:
COMSOL 6.0.0.278
% Date:
Nov 1 2020, 8:00
% Dimension:
1
% Nodes:
5
% Expressions:
1
% Description:
Line graph
% x
y
1.2 -0.45
1.11 -0.3
1.0440468877558806 -0.38655264416650392
1.041666666666667 -0.49166666666666667
1.02 -0.15
The first few lines with comments start with the character % and are ignored by the
readMatrixFromFile method. You can optionally omit such lines and just have
the numerical part of a file read by readMatrixFromFile. Assume that this file is
uploaded to an application using a File Import form object and a File declaration
file1. The following code can then be used to read the data into a double array p.
double p[][] = readMatrixFromFile("upload:///file1”);
The code below shows how to both import and visualize these points in an
application that, in addition to a File Import form object and a File declaration
file, has a form form1 and a graphics object graphics1.
double p[][] = readMatrixFromFile("upload:///file1");
double pt[][] = transpose(p);
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 2);
ResultFeature plot = pg.create("pt1", "PointData");
plot.set("pointdata", pt);
plot.run();
useGraphics(model.result(pgTag), "form1/graphics1");
Reading files on the spreadsheet format as a string array can be done with the
method readStringMatrixFromFile. Also, in this case, the comment lines will be
ignored. The code below shows how you can replace the first few lines in the
above example using readStringMatrixFromFile instead of
readMatrixFromFile.
| 179
String p[][] = readStringMatrixFromFile("upload:///file1");
double pt[][] = transpose(toDouble(p));
The method readStringMatrixFromFile is most useful when parts of the read
file contains text.
W RITING M ATRIX F ILES
To write numerical matrix data to file, you can use the method writeFile.
Assume that you want to write a matrix of random 2D coordinate values to a file
on the spreadsheet format; for example:
-0.3604014719437022
0.06964952539192892
-0.043869911848460674 -0.14152948348300798
0.08279441507358754
0.3101282179426158
...
0.4419748551931647
0.4139106589169702
0.15830016844077643
-0.08445989494858042
0.38236182707603905
0.4837445802317204
The code below shows how to do this.
int N = 100;
double[][] p = new double[N][2];
for (int k = 0; k < N; k++) {
p[k][0] = Math.random()-0.5;
p[k][1] = Math.random()-0.5;
}
writeFile("temp:///my_data.txt", p);
fileSaveAs("temp:///my_data.txt");
The resulting file can now be read back in and plotted by using the code of the
previous example. The result, in an application, may look like the figure below.
180 |
Note that you can append data to an already existing file by providing an
additional Boolean input argument; for example:
writeFile("temp:///my_data.txt", p,true);
fileSaveAs("temp:///my_data.txt");
If you would like to export a matrix with a mix of numeric and text data, you can
use the writeFile method with a string array instead of a double array. The syntax
for this case is otherwise identical to that of the double array shown in the example
above.
R EADING A T EXT F ILE TO A S TRING
For reading text files into a string, you can use the method readFile. A
straightforward use of readFile is for previewing a text file; for example, before
importing and parsing it, as illustrated by the example application in the figure
below.
| 181
This application has two form objects: a File Import form object referencing a File
declaration file1 and a Text form object referencing a string str declared in the
Declarations node as a global variable.
The File Import form object has an Event that calls the method read_string upon
data change.
This method has one line of code, as shown below.
str = readFile("upload:///file1");
Since the Text object is referencing the global string str, the contents of the file
are displayed in the Text object immediately after import.
Parsing of smaller text files can be done with readFile in combination with the
many text processing methods available in the String class. However, it is often
more efficient to use methods in the CsReader class, as described in the section
“Processing Text Files using the CsReader and CsWriter Classes” on page 184,
especially for larger text files. The reason is that when using the readFile method,
the entire file is read into a string with all its contents kept in memory; whereas
when using the CsReader class methods, only small portions of the file are kept in
memory at any given time.
If you would like to parse smaller text files using readFile, then the built-in
“String Methods” on page 152 are useful. The example code below illustrates
using the built-in methods findIn, substring, split, as well as the regular Java®
methods System.getProperty and String.startsWith. The example parses the
header of a text file containing polygon information to retrieve information about
the number of points of each polygon in the main body of the file (not shown) as
182 |
well as the number of properties (for example, color or material property). The
header portion of the file may look like the example below.
Demo file for string parsing
Created on May 1st 2018
begin_header
number_of_points 4
number_of_properties 4
end_header
The code for parsing the header is listed below. It stores the number of points and
properties in the variables n_of_points and n_of_properties, respectively. To
keep things simple, no error handling is done. For example, the code assumes that
there is exactly one instance of begin_header and end_header.
int n_of_points = 0;
int n_of_properties = 0;
String fileContents = readFile("upload:///file1");
String eol = System.getProperty("line.separator"); // find the system end of line
int headerBeginIndex = findIn(fileContents, "begin_header");
int headerEndIndex = findIn(fileContents, "end_header");
String headerContents = substring(fileContents, headerBeginIndex,
headerEndIndex-headerBeginIndex); // Convert to string array by splitting at
each line.
String[] headerContentsArr = split(headerContents, eol);
int ix = 1;
String[] headerRowArr = new String[2];
do {
// Split each line at space.
headerRowArr = split(headerContentsArr[ix], " ");
if (headerRowArr.length == 2) {
if (headerRowArr[0].trim().equalsIgnoreCase("number_of_points"))
n_of_points = toInt(headerRowArr[1]);
if (headerRowArr[0].trim().equalsIgnoreCase("number_of_properties"))
n_of_properties = toInt(headerRowArr[1]);
}
ix++;
} while (ix < headerContentsArr.length);
The Java® String class has many methods for text processing. See the online
Java® documentation for more information.
W RITING A S TRING TO A T EXT F ILE
The following example shows how to use the method writeFile to write a string
to file.
String contents = "# Created by me\r\n"
+"# Version 1.0 of this file format \r\n"
+"# Body follows\r\n"
+"0 1 \r\n"
| 183
+"2 3\r\n"
+"4 5\r\n";
writeFile("temp:///my_data.txt", contents);
fileSaveAs("temp:///my_data.txt");
The use of the file scheme syntax temp:/// is described above in the earlier
examples of this section. The end-of-line characters of this example are for
Windows®; see also “Special Characters” on page 11.
To append additional data to the same file, for example:
String contents_2 = "6 7\r\n"
+"8 9\r\n"
+"10 11\r\n";
use an additional Boolean input argument, which appends data when set to true:
writeFile("temp:///my_data.txt", contents_2, true);
fileSaveAs("temp:///my_data.txt");
P ROCESSING T EXT F ILES USING THE C S R EADER AND C S W RITER C LASSES
The most efficient and flexible way to read and write to a text file is to use the
methods in the CsReader and CsWriter classes, respectively. However, using the
methods of these classes is more complicated than using any of the built-in
methods described above.
The CsReader class inherits all public methods of the abstract Java® class Reader.
In a similar way, the CsWriter class inherits all public methods of the abstract
Java® class Writer. This means that when using these classes, you get access to a
large number of methods for processing text files. These methods are not
documented here, but you can find a lot of information with regards to using these
methods online as well as in books on Java® programming. In addition, you can
see which methods are available by using code-completion Ctrl+Space.
R EADING T EXT F ILES USING THE C S R EADER C LASS
The example code below shows how to parse the text file header of the earlier
example for reading strings using the built-in method readFile. The header may
look like:
Demo file for string parsing
Created on May 1st 2018
begin_header
number_of_points 4
number_of_properties 4
end_header
and the corresponding code is listed below (compare with the example “Reading
a Text File to a String” on page 181).
int n_of_points = 0;
int n_of_properties = 0;
184 |
int max_header_length = 100;
CsReader reader = openFileStreamReader("upload:///file1");
String line; // Each line in the file
String[] lineArr; // The contents of each line in an array
int li = 0; // Line counter
boolean begin_header_found = false;
boolean end_header_found = false;
while (!begin_header_found && li < max_header_length && ((line =
reader.readLine()) != null)) {
if (line.trim().startsWith("begin_header"))
begin_header_found = true;
li++;
}
while (begin_header_found && !end_header_found && li < max_header_length &&
((line = reader.readLine()) != null)) {
lineArr = split(line, " ");
if (lineArr[0].trim().equalsIgnoreCase("number_of_points"))
n_of_points = toInt(lineArr[1]);
if (lineArr[0].trim().equalsIgnoreCase("number_of_properties"))
n_of_properties = toInt(lineArr[1]);
if (line.trim().startsWith("end_header"))
end_header_found = true;
li++;
}
reader.close();
if (!begin_header_found || !end_header_found)
error("File does not have the right format.");
Comments
The line
CsReader reader = openFileStreamReader("upload:///file1");
opens a Java® character stream and assigns it to the object reader belonging to
the class CsReader.
The while loop condition contains the statement
(line = reader.readLine()) != null)
which is reading a line from the character stream and storing the result in the string
line. A line is considered to be terminated by one of the characters carriage return
\r, line feed \n, or the composite \r\n. If there are no more lines to read, then
null is returned.
For more information on the string methods used in this and earlier examples,
including findIn, substring, and split, see the section “Writing a String to a
Text File” on page 183.
| 185
The line
reader.close();
closes the stream permanently.
Note that you can see which additional methods are available for the reader
object by using Ctrl+Space, as shown in the figure below.
By using Ctrl+Space following a string, you can see the many additional methods
available for strings, including the trim method used in the example above:
W RITING T EXT F ILES USING THE C S W RITER C LASS
The example of the section “Reading Matrix Files” on page 179 uses an example
on the spreadsheet data format. This section contains an example that writes a file
on the sectionwise format, the other primary format in COMSOL Multiphysics for
saving postprocessing data. Data on the sectionwise format can, for example, be
read into an Interpolation Curve geometry primitive. A file on the sectionwise
format may look like this:
186 |
% Version:
COMSOL 6.0.0.278
% Date:
Nov 1 2020, 8:00
% Description:
Interpolation curve
% Coordinates
-1.1
-0.8
1.2
-0.9
0.9
1.3
-0.8
1.05
% Elements (segments)
1
2
2
3
3
4
The first few lines with comments start with the character % and are ignored when
imported as an Interpolation Curve. The first section containing data starts on the
line after % Coordinates. The second section containing data starts on the line
after % Elements (segments). Note that the strings Coordinates and Elements
(segments) are not necessary but each section containing data will be assumed to
start after each block of comments, regardless of what comes after the character %.
There may be additional blocks of data when, for example, exporting Contour plot
data.
The following example code uses a CsWriter stream to write interpolation curve
data to a text file. A template point set p is copied in a circular pattern for a given
radius R and number of copies n_of_copies.
CsWriter writer = openFileStreamWriter("temp:///my_curve.txt");
int n_of_copies = 10;
double[][] p = {{-1.2, -0.9}, {0.9, -1.1}, {1.3, 0.8}, {-0.9, 1.0}}; // template
int template_length = p.length;
double R = 10;
double px, py;
double pi = Math.PI;
String line;
int i1, i2;
String header = "% Version:\tCOMSOL 6.0.0.278\r\n"
+"% Date:\tMay 5 2018, 8 : 00\r\n"
+"% Description:\tInterpolation curve\r\n"
+"% Coordinates:\r\n";
writer.append(header);
for (int j = 0; j < n_of_copies; j++) {
for (int i = 0; i < template_length; i++) {
px = p[i][0];
py = p[i][1];
px = px+R*Math.cos(2*pi*j/n_of_copies);
py = py+R*Math.sin(2*pi*j/n_of_copies);
line = toString(px)+"\t"+toString(py)+"\r\n";
writer.append(line);
}
}
| 187
writer.append("% Elements (segments):\r\n");
for (int j = 0; j < n_of_copies; j++) {
for (int i = 0; i < template_length; i++) {
i1 = i+1;
i2 = (i+1)%template_length+1;
i1 = i1+j*template_length;
i2 = i2+j*template_length;
line = toString(i1)+"\t"+toString(i2)+"\r\n";
writer.append(line);
}
}
writer.flush();
writer.close();
fileSaveAs("temp:///my_curve.txt");
Comments
The line
CsWriter writer = openFileStreamWriter("temp:///my_curve.txt");
opens a Java® character stream and assigns it to the object writer belonging to
the class CsWriter.
The line
writer.append(header);
appends the contents of the string header to the (empty) file my_curve.txt.
The line
writer.flush();
writes the contents of the character stream buffer to file and empties the buffer but
does not close the stream permanently. At this point, you can still write more data
to the stream.
The line
writer.close();
closes the stream permanently. If you wish to write additional data to the file, you
have to open the stream again and append additional data.
188 |
Just as described above for the reader object, you can see which additional
methods are available for the writer object by using Ctrl+Space, as shown in the
figure below.
You can import the resulting interpolation data as an Interpolation Curve by
selecting the Sectionwise option for Data format. This can be done for a 2D
geometry object or for a Work Plane in 3D. The figure below shows the data
imported to a 2D model.
| 189
W RITING B INARY F ILES
You write data to a binary file by using the methods of the class CsBinaryWriter
in a way that is somewhat similar to that of writing text using CsWriter. However,
instead of writing strings and characters, you are writing bytes. To see how many
bytes each data type requires, see the table in the section “Primitive Data Types”
on page 8.
The example code below writes random 3D point data to a binary file. Each point
coordinate is stored as a double and takes 8 bytes to store. The first 4 bytes of the
file stores the number of points in the file as an int.
To conveniently convert between the regular data types, such as double, int, and
byte arrays, the Java® library method java.nio.ByteBuffer is needed. This
method is not part of the standard methods available in the Method Editor and
you need to use the fully qualified Java® class name java.nio.ByteBuffer, as
shown in the example code below.
byte[] bytes8 = new byte[8];
byte[] bytes4 = new byte[4];
CsBinaryWriter bwriter = openBinaryFileStreamWriter("temp:///
my_binary_file.dat");
int N = 1000;
java.nio.ByteBuffer.wrap(bytes4).putInt(N);
bwriter.write(bytes4);
double p[][] = new double[N][3];
for (int k = 0; k < N; k++) {
p[k][0] = Math.random();
java.nio.ByteBuffer.wrap(bytes8).putDouble(p[k][0]);
bwriter.write(bytes8);
p[k][1] = Math.random();
java.nio.ByteBuffer.wrap(bytes8).putDouble(p[k][1]);
bwriter.write(bytes8);
p[k][2] = Math.random();
java.nio.ByteBuffer.wrap(bytes8).putDouble(p[k][2]);
bwriter.write(bytes8);
bwriter.flush();
}
bwriter.close();
fileSaveAs("temp:///my_binary_file.dat");
Comments
The first two lines declare byte arrays of size 8 and 4, respectively
The line
CsBinaryWriter bwriter = openBinaryFileStreamWriter("temp:///
my_binary_file.dat");
opens a Java® byte stream.
The line
190 |
int N = 1000; // The number of points
denotes the number of points written to file.
The line
ByteBuffer.wrap(bytes4).putInt(N);
uses the imported ByteBuffer method to convert the integer N to a byte array
bytes4 of length 4.
The line
bwriter.write(bytes4);
writes the value of N to file.
The for-loop creates N points and writes each x-, y-, and z-coordinate as doubles
using a byte array bytes8 of length 8.
The line
bwriter.flush();
empties the byte buffer and the last two lines
bwriter.close();
fileSaveAs("temp:///my_binary_file.dat");
close the byte stream and display a file browser to the user to select a location to
save the binary file.
R EADING B INARY F ILES
Based on the data format of the previous example, the code below reads a
corresponding binary file and plots the points as 3D point data.
byte[] bytes8 = new byte[8];
byte[] bytes4 = new byte[4];
CsBinaryReader breader = openBinaryFileStreamReader("upload:///file1");
breader.read(bytes4);
int N = java.nio.ByteBuffer.wrap(bytes4).getInt();
double p[][] = new double[N][3];
for (int k = 0; k < N; k++) {
breader.read(bytes8);
p[k][0] = java.nio.ByteBuffer.wrap(bytes8).getDouble();
breader.read(bytes8);
p[k][1] = java.nio.ByteBuffer.wrap(bytes8).getDouble();
breader.read(bytes8);
p[k][2] = java.nio.ByteBuffer.wrap(bytes8).getDouble();
}
breader.close();
| 191
double pt[][] = transpose(p);
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 3);
ResultFeature plot = pg.create("pt1", "PointData");
plot.set("pointdata", pt);
plot.run();
useGraphics(model.result(pgTag), "form1/graphics1");
Comments
The line
CsBinaryReader breader = openBinaryFileStreamReader("upload:///file1");
opens a Java® byte stream based on a File declaration file1, typically referenced
in a File Browser form object, as in the earlier examples on reading text files.
The two lines
breader.read(bytes4);
int N = ByteBuffer.wrap(bytes4).getInt();
read the first 4 bytes and convert them to an int N.
The following for-loop reads chunks of 8 bytes into the byte array bytes8,
converts them and stores the results in a 2D double array p.
The line
breader.close();
closes the byte stream.
The last section of the example code plots the data and is similar to the example
in “Reading Matrix Files” on page 179.
A DDITIONAL C OMMENTS ON R EADING AND W RITING B INARY F ORMATS
When processing binary files, there are two formats in which bytes can be stored:
little endian and big endian, respectively. By default, Java® uses the big endian
format. For example, the line
p[k][2] = ByteBuffer.wrap(bytes8).getDouble();
is the same as
p[k][2] = ByteBuffer.wrap(bytes8).order(ByteOrder.BIG_ENDIAN).getDouble();
In case the format you are reading is on the little endian format, the corresponding
line should be
p[k][2] = ByteBuffer.wrap(bytes8).order(ByteOrder.LITTLE_ENDIAN).getDouble();
192 |
Converting Interpolation Curve Data
The following method converts a geometry Interpolation Curve to an Interpolation
function (by creating an interpolation table). The method demonstrates extracting
geometry information from the underlying parameterization of an edge. The edge
does not have to be an Interpolation Curve but can be any single edge.
The curve is checked for being monotonous, which is required in order to be able
to convert to an interpolation function. Note that since an interpolation curve is
represented using splines, even though the interpolation points form a
monotonous sequence, the resulting curve may not; hence, the second consistency
check (the first check can potentially be skipped).
// Convert using N points
int N = 100;
double monoTol = 1e-6;
int edgeNum=1;
// Update and get geometry information
model.component("comp1").geom("geom1").run("fin");
GeomSequence geom1 = model.component("comp1").geom("geom1");
GeomFeature ic1 = geom1.feature("ic1");
double[][] curvePoints = ic1.getDoubleMatrix("table");
int len = curvePoints.length;
double minX = curvePoints[0][0];
double maxX = curvePoints[len-1][0];
double scale = maxX-minX;
double scaledTol = monoTol*scale;
| 193
for (int i = 1; i < len; i++) {
if ((curvePoints[i][0]-curvePoints[i-1][0]) < scaledTol) {
error("Curve needs to be a function curve with monotonously growing x
coordinates.");
}
}
double minMaxS[] = geom1.edgeParamRange(edgeNum);
double minS = minMaxS[0];
double maxS = minMaxS[1];
double sList[] = new double[N];
for (int k = 0; k < N; k++) {
sList[k] = (double) (N-1-k)/(double) (N-1)*minS+k/(double) (N-1)*maxS;
}
double[][] XY = geom1.edgeX(1, sList);
for (int j = 1; j < N; j++) {
if ((XY[j][0]-XY[j-1][0]) < scaledTol) {
error("Curve needs to be a function curve with monotonously growing x
coordinates.");
}
}
// Create interpolation table
model.func().create("int1", "Interpolation");
with(model.func("int1"));
set("funcname", "int1");
set("interp", "cubicspline");
set("extrap", "linear");
endwith();
model.func("int1").set("table", toString(XY));
Comments
The method assumes that there is a geometry sequence geom1 with an
interpolation curve ic1. It further assumes that there are no other geometry
features and that the geometry object has a single edge. The integer N determines
how granular the interpolation table should be. It is assumed that there is only one
edge in the geometry sequence (edgeNum). Note that the curve parameter range
may not be the unit interval (minS does not have to be 0.0 and maxS does not have
to be 1.0). To run the method more than once, you can create a cleanup method
that contains the lines:
model.func().remove("int1");
model.result().remove("pg1");
for removing previously created model tree nodes.
194 |
P l o t t i n g P o i n t s o n a P a r a me t r i c S u r f a c e
The following method retrieves coordinate values for a regularly sampled
parametric surface and plots the corresponding points using a Point Data plot. The
method demonstrates extracting geometry information from the underlying
parameterization of a surface. The example assumes that a parametric surface
geometry object has already been created.
// Sample and plot N-by-N points on a parametric surface
int N = 20;
int faceNum = 1;
// Update and get geometry information
model.component("comp1").geom("geom1").run("fin");
GeomSequence geom1 = model.component("comp1").geom("geom1");
GeomFeature ps1 = geom1.feature("ps1");
double minMaxS[] = geom1.faceParamRange(faceNum);
double minS1 = minMaxS[0];
double maxS1 = minMaxS[1];
double minS2 = minMaxS[2];
double maxS2 = minMaxS[3];
double s1List[] = new double[N];
double s2List[] = new double[N];
for (int k = 0; k < N; k++) {
s1List[k] = (double) (N-1-k)/(double) (N-1)*minS1+k/(double) (N-1)*maxS1;
s2List[k] = (double) (N-1-k)/(double) (N-1)*minS2+k/(double) (N-1)*maxS2;
}
| 195
double s12List[][] = new double[N*N][2];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
s12List[i+N*j][0] = s1List[i];
s12List[i+N*j][1] = s2List[j];
}
}
double[][] XY = geom1.faceX(faceNum, s12List);
// Plot points
String pgTag = model.result().uniquetag("pg");
ResultFeature pg = model.result().create(pgTag, 3);
ResultFeature plot = pg.create("pt1", "PointData");
double[][] p = new double[3][N*N];
double[] color = new double[N*N];
for (int i = 0; i < N*N; i++) {
p[0][i] = XY[i][0];
p[1][i] = XY[i][1];
p[2][i] = XY[i][2];
color[i] = p[1][i];
}
plot.set("pointdata", p)
.set("colordata", color)
.set("coloring", "colortable")
.set("sphereradiusscale", 1);
plot.run();
selectNode(pg);
U s i n g S e le c t i o n s f o r E d i t i n g G e o m e t r y O b j e c t s
The following method generates a plate with an array of cylinders. The cylinders
may be used, for example, in a difference operation to create an array of holes in
the plate.
GeomSequence geom = model.component("comp1").geom("geom1");
geom.create("blk1", "Block");
geom.feature("blk1").set("size", new int[]{10, 10, 1});
geom.create("start_cyl1", "Cylinder");
geom.feature("start_cyl1").set("pos", new double[]{2.5, 2.5, 0});
geom.create("arr1", "Array");
geom.feature("arr1").selection("input").set("start_cyl1");
geom.feature("arr1").set("fullsize", new int[]{2, 2, 1});
geom.feature("arr1").set("displ", new int[]{5, 5, 0});
geom.run("arr1");
196 |
The resulting geometry is shown in the figure below.
Assume now that the resulting geometry, from the previous step, corresponds to
an imported geometry object and that you would like to replace the cylinders with
larger cylinders before subtracting and generating the holes. Furthermore, assume
that the cylinder objects are generated by an external software in such a way that,
although you know these objects are cylinders, they are represented as generic
geometry objects with no information on radius, height, or position. The
following method finds the array of cylinders, extracts coordinate information for
each cylinder, deletes the cylinders, creates a new array of wider cylinders, and
| 197
finally subtracts the cylinders from the plate. The resulting geometry is shown in
the figure below.
The method exemplifies retrieval of geometry object names, coordinate
information, and the use of selections. To start from another geometry object
(which is also necessarily a plate with cylinders), you can replace the string tag in
the variable plateAndCylinders accordingly.
double selTol = 1e-2; // Selection tolerance
double newR = 1.25; // New cylinder radius
double newH = 1; // New cylinder height
double plateThickness = 1; // Plate thickness
String plateAndCylinders = "arr1";
// Update and split geometry
model.component("comp1").geom("geom1").run("fin");
GeomSequence geom = model.component("comp1").geom("geom1");
geom.run(plateAndCylinders);
geom.create("spl1", "Split");
geom.feature("spl1").selection("input").set(plateAndCylinders);
geom.run("spl1");
// Find extents of geometry in x,y,z directions
double[] bBox = geom.getBoundingBox();
double MinX = bBox[0];
double MaxX = bBox[1];
double MinY = bBox[2];
double MaxY = bBox[3];
double MinZ = bBox[4];
double MaxZ = bBox[5];
// Define scaled coordinate tolerance
198 |
double scale = Math.max(Math.max(MaxX-MinX, MaxY-MinY), MaxZ-MinZ);
double scaleSelTol = scale*selTol;
// Create box selection based on geometry extents
geom.create("boxsel1", "BoxSelection");
with(geom.feature("boxsel1"));
// Select boundaries inside box in X-Y direction using tolerance
set("xmin", MinX+scaleSelTol);
set("xmax", MaxX-scaleSelTol);
set("ymin", MinY+scaleSelTol);
set("ymax", MaxY-scaleSelTol);
set("zmin", MinZ-scaleSelTol);
set("zmax", MaxZ+scaleSelTol);
set("condition", "inside");
set("entitydim", -1); // Select objects
endwith();
geom.run("boxsel1");
// Get object names
String[] so = geom.selection("boxsel1").objects();
int nso = so.length;
// Extract cylinder parameters
double[] MinXC = new double[nso];
double[] MaxXC = new double[nso];
double[] MinYC = new double[nso];
double[] MaxYC = new double[nso];
double[] MinZC = new double[nso];
double[] MaxZC = new double[nso];
double[] bBoxC = new double[6];
for (int i = 0; i < nso; i++) {
bBoxC = geom.obj(so[i]).getBoundingBox();
MinXC[i] = bBoxC[0];
MaxXC[i] = bBoxC[1];
MinYC[i] = bBoxC[2];
MaxYC[i] = bBoxC[3];
MinZC[i] = bBoxC[4];
MaxZC[i] = bBoxC[5];
}
double[] radius = new double[nso];
double[] xc = new double[nso];
double[] yc = new double[nso];
double[] zc = new double[nso];
double[] hc = new double[nso];
double ry;
double tol = scale*1e-6; // Tolerance check for skew cylinders, optional
consistency check
for (int i = 0; i < nso; i++) {
xc[i] = (MaxXC[i]+MinXC[i])/2;
yc[i] = (MaxYC[i]+MinYC[i])/2;
zc[i] = (MaxZC[i]+MinZC[i])/2;
hc[i] = MaxZC[i]-MinZC[i];
radius[i] = (MaxXC[i]-MinXC[i])/2;
ry = (MaxYC[i]-MinYC[i])/2;
| 199
if (Math.abs(radius[i]-ry) > tol)
error("Object is not a circular cylinder.");
}
// Delete all cylinder objects
geom.create("del1", "Delete");
geom.feature("del1").selection("input").init();
geom.feature("del1").selection("input").set(so);
geom.run("del1");
// Add new cylinders
String[] cylname = new String[nso];
for (int i = 0; i < nso; i++) {
cylname[i] = "cyl"+toString(i+1);
geom.create(cylname[i], "Cylinder");
with(geom.feature(cylname[i]));
set("r", newR);
set("h", newH+2*scaleSelTol);
set("pos", new double[]{xc[i], yc[i], plateThickness-2*zc[i]-scaleSelTol});
endwith();
}
// Combine all cylinders into one object
geom.create("uni1", "Union");
geom.feature("uni1").selection("input").set(cylname);
geom.run("uni1");
// Difference between all objects and cylinders
geom.create("dif1", "Difference");
String[] objs = geom.objectNames();
geom.feature("dif1").selection("input").set(objs);
geom.feature("dif1").selection("input2").set("uni1");
geom.run("dif1");
Comments
The method assumes that the input geometry objects have the same structure as
the plate with cylinders example above. Note that to clear the geometry sequence,
you can create a method with the line
model.component("comp1").geom("geom1").feature().clear();
This can be useful if you are running the main method from above repeatedly,
since you need to clear the geometry sequence before each run.
The first of the lines
geom.feature("del1").selection("input").init();
geom.feature("del1").selection("input").set(so);
initializes the selection to be empty of type object. The second line then selects all
objects with names in the array so. In general, a call to init() without input
argument means that the selection is for objects and init(n), where n=0,1,2, or
3, means that the selection is for points, edges, faces, and domains, respectively.
200 |
Note that in some cases n=-1 is used to denote the object level (instead of an
empty input argument); see the Programming Reference Manual.
The figure below shows an example based on a larger array of cylinders.
R e c u r s i o n a n d R e c u r s i v e l y D e f i n ed G eo m e t r y O b j e c t s
Methods can support recursion by having a function calling itself in a recursive
loop. The following examples create recursive CAD geometry models of a
Sierpinski carpet in 2D and a Menger sponge in 3D.
Sierpinski Carpet
The following method, create_carpet, initiates the recursion to a certain
recursive level according to a user-defined Parameter mslevel, defined under
Global Definitions in the Model Builder. It sets a limit at 5 levels in order to avoid
creating an exceedingly large geometry. The method assumes that you have
created a 2D Component and that you have declared an integer scalar variable
counter.
int level = (int) model.param().evaluate("mslevel");
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");
| 201
double cx0 = 0, cy0 = 0;
double si0 = 1;
carpet(level, cx0, cy0, si0);
model.component("comp1").geom("geom1").runPre("fin");
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.
The code for the method carpet is shown below.
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();
202 |
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);
}
}
}
}
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 8N. This means that
for the maximum level 5 set by the method create_carpet, the resulting
geometry has 32,768 geometry objects.
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 method assumes that you have created a 3D Component and that you
have declared an integer scalar variable counter.
The following method, create_sponge, initiates the recursion.
int level = (int) model.param().evaluate("mslevel");
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;
| 203
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 above method 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);
}
}
}
}
}
204 |
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 20N and
the level-2 sponge shown above has 400 block geometry objects.
Note that if you have any of the add-on products for additional CAD
functionality, you can export these geometry objects on standard CAD formats.
Without add-on products, you can export the meshed geometry to any of the
supported mesh formats.
Mesh Information and Statistics
You can retrieve a variety of mesh information and statistical quantities, such as
element quality, the total number of elements, the total mesh volume, and so on.
The figure below shows part of an application displaying such information.
Assuming that you would like to link the various mesh quantities to variables
declared under the Declarations node, the corresponding method code would
include the following lines of code:
| 205
a = model.component("comp1").mesh("mesh1").getNumElem();
b = model.component("comp1").mesh("mesh1").getMinQuality("tet");
c = model.component("comp1").mesh("mesh1").getMeanQuality("tet");
d = model.component("comp1").mesh("mesh1").getMinVolume("tet");
e = model.component("comp1").mesh("mesh1").getVolume("tet");
For more information on available mesh quantities, see the COMSOL
Multiphysics Programming Reference Manual.
A c c e s s i n g H i g h e r - Or d e r F i n i t e E l e m e n t N o d e s
The extended mesh data structure contains information related to the finite
element method including, for example, the placement of higher-order element
nodes. The extended mesh information is contained in the class XmeshInfo and
provides information about the numbering of elements, nodes, and degrees of
freedom (DOFs) in the extended mesh and in the matrices returned by the
Assemble feature and the solvers. For detailed information on XmeshInfo, see the
Programming Reference Manual.
The following example method illustrates how to use the extended mesh
information to plot higher-order nodes in a few important special cases. Note that
general functionality for this is built-in when creating a Mesh Plot under Results
while also using a Study as the referenced Dataset.
206 |
The example below covers cases with one model component, one geometry, and
a subset of physics combinations. If you apply it to other cases, you will get an
error message.
// Note that this method is only implemented for one component and one geometry
and does not work for all physics combinations.
String stdTag = model.study().uniquetag("stdfe");
model.study().create(stdTag);
model.study(stdTag).label("FE Nodes Study "+stdTag.substring(5));
model.study(stdTag).showAutoSequences("sol");
String solTag = model.sol().uniquetag("sol");
model.sol().create(solTag);
model.sol(solTag).create("st1", "StudyStep");
model.sol(solTag).create("v1", "Variables");
SolverFeature step = model.sol(solTag).feature("v1");
XmeshInfo xmi = step.xmeshInfo();
try {
XmeshInfoNodes testnodes = xmi.nodes();
} catch (Exception e) {
error("Cannot access finite element data. Only implemented for one geometry and
stationary studies.");
}
XmeshInfoNodes mynodes = xmi.nodes();
double[][] coords = mynodes.gCoords();
int[] coordsize = matrixSize(coords);
int sdim = 0;
if (coordsize[0] == 3) {
| 207
sdim = 3;
} else if (coordsize[0] == 2) {
sdim = 2;
} else
error("The geometry of the first component is not 2D or 3D.");
String mesh = "mesh"+stdTag;
model.result().dataset().create(mesh, "Mesh");
String pgTag = model.result().uniquetag("pgfe");
ResultFeature pg = model.result().create(pgTag, sdim);
model.result(pgTag).label("FE Nodes Plot "+pgTag.substring(4));
String nodes = pgTag;
model.result(nodes).create("mesh", "Mesh");
if (sdim == 3) {
with(model.result(nodes).feature("mesh"));
set("data", mesh);
set("meshdomain", "volume");
endwith();
} else {
with(model.result(nodes).feature("mesh"));
set("data", mesh);
set("meshdomain", "surface");
endwith();
}
with(model.result(nodes).feature("mesh"));
set("elemcolor", "none");
set("wireframecolor", "gray");
set("elemscale", 0.999);
endwith();
with(model.result(nodes));
set("edges", true);
set("data", mesh);
endwith();
ResultFeature plot = pg.create("pt1", "PointData");
plot.set("pointdata", coords)
.set("coloring", "uniform")
.set("color", "red");
plot.run();
selectNode(pg);
Comments
The first few lines of the method set up a solver step object step, which is used to
extract the extended mesh information. The extended mesh information, which
contains information on the higher-order nodes, is extracted in the line
XmeshInfo xmi = step.xmeshInfo();
The lines
XmeshInfoNodes mynodes = xmi.nodes();
double[][] coords = mynodes.gCoords();
208 |
int[] coordsize = matrixSize(coords);
access and store the finite element node coordinates in a 2-by-coordsize (2D) or
3-by-coordsize (3D) array.
The following code segments set up a mesh dataset and an associated mesh plot.
The last section uses the low-level PointData plot type to visualize the finite
element nodes. For more information on this plot type, see “Points in 3D” on
page 161.
A c c e s s i n g S y s t e m M at r i c e s a n d V e c t o rs
You can gain low-level access to the finite element system matrices and vectors by
adding nodes of the types Assemble and Input Matrix under a Study node.
The example below shows how to set up and solve a 2D electrostatics problem on
the unit square [0,1]-by-[0,1]. After the original problem is solved, the load
vector is modified at a user-defined coordinate. The code searches for the degree
of freedom closest to the target user-defined coordinate and modifies the load
vector to a user-defined value. The physical interpretation of the modified load is
that of an added volume charge.
To run the example code below, first use the Model Wizard to create a blank
model. Then, add a new method and paste the example code below. Finally, run
| 209
the method. You can try changing the variable values in the Initializations section
at the beginning of the code and run again.
// Initializations
double x_load = 0.2; // Target x-coordinate for load
double y_load = 0.2; // Target y-coordinate for load
double load = 1e-9; // Load, volume charge
double dist = 10.0; // Distance to (x_load,y_load) from degree of freedom
int index = 0; // Index of the degree of freedom closest to (x_load,y_load)
// Clear any previous model.
clearModel(model);
// Create a new model component.
model.modelNode().create("comp1");
// Create the 2D geometry.
model.geom().create("geom1", 2);
model.geom("geom1").feature().create("sq1", "Square");
model.geom("geom1").run();
// Create the mesh.
model.mesh().create("mesh1", "geom1");
model.mesh("mesh1").feature().create("fre1", "FreeTri");
model.mesh("mesh1").run();
// Setup the electrostatics physics problem.
model.physics().create("es", "Electrostatics", "geom1");
model.physics("es").feature().create("gnd1", "Ground", 1);
model.physics("es").feature("gnd1").selection().set(new int[]{1});
model.physics("es").feature().create("sfcd1", "SurfaceChargeDensity", 1);
model.physics("es").feature("sfcd1").selection().set(new int[]{4});
// Add a varying distributed charge density along the rightmost boundary.
210 |
model.physics("es").feature("sfcd1").set("rhoqs", "1e-9*y");
model.component("comp1").physics("es").feature("ccn1").set("epsilonr_mat",
"userdef");
model.component("comp1").physics("es").feature("ccn1").set("epsilonr", "1");
// Change to 1st order shape functions, to keep things simple.
model.component("comp1").physics("es").prop("ShapeProperty").
set("order_electricpotential", 1);
// Create and run the study.
model.study().create("std1");
model.study("std1").feature().create("stat1", "Stationary");
model.study("std1").run();
// Create a 2D plot group with a surface plot for the original problem.
model.result().create("pg1", 2);
model.result("pg1").set("data", "dset1");
model.result("pg1").feature().create("surf1", "Surface");
selectNode(model.result("pg1")); // Set focus on the plot node.
// Create a reusable solver feature variable.
SolverFeature solft;
model.study().create("std2"); // Create a Study 2 node.
model.sol().create("sol2"); // Create a dataset Solution 2.
// Create a Solver configurations node under Study 2
model.sol("sol2").study("std2");
model.sol("sol2").create("st1", "StudyStep"); // Create a Compile Equations node.
solft = model.sol("sol2").feature("st1"); // Assign solver step to variable
solver.
solft.set("study", "std2");
model.sol("sol2").create("v1", "Variables"); // Create a Dependent Variables
node.
solft = model.sol("sol2").feature("v1");
model.sol("sol2").attach("std2");
model.sol("sol2").create("a1", "Assemble"); // Add an Assemble node.
solft = model.sol("sol2").feature("a1");
// Now define which system matrices should be output (Noneliminated Output).
// L=Load vector, K=Stiffness matrix, M=Constraint vector, N=Constraint Jacobian
// For more information see the Programming Reference Manual.
solft.set("L", "on");
solft.set("K", "on");
solft.set("M", "on");
solft.set("N", "on");
//Create a Stationary Solver 2 node: Study 2>Solver Configurations>Solution 2.
model.sol("sol2").create("s2", "Stationary");
// Create an Input Matrix node under Stationary Solver 2.
solft = model.sol("sol2").feature("s2").create("im1", "InputMatrix");
// Define which system matrices should be input.
solft.set("L", "on");
solft.set("K", "on");
| 211
solft.set("M", "on");
solft.set("N", "on");
// Find the degree of freedom coordinate closest to the target coordinate.
solft = model.sol("sol2").feature("v1");
XmeshInfo xmi = solft.xmeshInfo();
XmeshInfoDofs mydofs = xmi.dofs();
double[][] coords = mydofs.gCoords();
int[] coordsize = matrixSize(coords);
double new_dist = dist;
for (int k = 0; k < coordsize[1]; k++) {
new_dist = Math.sqrt((coords[0][k]-x_load)*(coords[0][k]-x_load)+
(coords[1][k]-y_load)*(coords[1][k]-y_load));
if (new_dist < dist) {
index = k;
dist = new_dist;
}
}
// Run the solver sequence up to and including the Assemble node.
model.sol("sol2").runFromTo("st1", "a1");
// Extract system matrices and vectors.
solft = model.sol("sol2").feature("a1");
// K
int KM = solft.getM("K");
int KN = solft.getN("K");
int KNnz = solft.getNnz("K");
int[] Ki = solft.getSparseMatrixRow("K");
int[] Kj = solft.getSparseMatrixCol("K");
double[] Kv = solft.getSparseMatrixVal("K");
// For more information, see the Programming Reference Manual.
// L
double[] Lv = solft.getVector("L");
// N
int NM = solft.getM("N");
int NN = solft.getN("N");
int NNnz = solft.getNnz("N");
int[] Ni = solft.getSparseMatrixRow("N");
int[] Nj = solft.getSparseMatrixCol("N");
double[] Nv = solft.getSparseMatrixVal("N");
// M
double[] Mv = solft.getVector("M");
// Modify the load
Lv[index] = load;
// Put the system matrices and vectors back in again.
solft = model.sol("sol2").feature("s2").feature("im1");
// K
solft.createSparseMatrix("K", KM, KN, KNnz, true);
212 |
solft.addSparseMatrixVal("K", Ki, Kj, Kv);
// L
solft.createVector("L", Lv.length, true);
solft.setVector("L", Lv);
// N
solft.createSparseMatrix("N", NM, NN, NNnz, true);
solft.addSparseMatrixVal("N", Ni, Nj, Nv);
// M
solft.createVector("M", Mv.length, true);
solft.setVector("M", Mv);
// Solve Stationary Solver 2 with the modified system.
model.sol("sol2").runFromTo("s2", "s2");
// Plot the results.
model.result().create("pg2", "PlotGroup2D");
with(model.result("pg2"));
set("data", "dset2");
endwith();
model.result("pg2").create("surf1", "Surface");
// Plot electric potential and original mesh overlayed with no smoothing.
with(model.result("pg2").feature("surf1"));
set("resolution", "norefine");
set("smooth", "none");
endwith();
model.result("pg2").create("surf2", "Surface");
with(model.result("pg2").feature("surf2"));
set("resolution", "norefine");
set("coloring", "uniform");
set("color", "gray");
set("wireframe", true);
endwith();
model.result("pg2").run();
selectNode(model.result("pg2")); // Set focus on the plot node.
Comments
In the previous example, “Accessing Higher-Order Finite Element Nodes” on
page 206, the XmeshInfoNodes methods are used to access finite element nodes
that have the same length as the number of finite element nodes. In this example,
the XmeshInfoDofs methods are used to access the degrees of freedom vector,
which has the same length as the load vector.
Note that only the load vector is modified. The other matrices and vectors are
merely extracted and then put back into the system again.
| 213
D a t a V a l i d at i o n
In the Settings window for input fields, the section for Data Validation has a
subsection Numerical validation with settings that allow you to validate user inputs
with respect to values. The figure below shows an example of settings for entering
a radius.
The Filter options, the Lower bound and Upper bound settings are only visible if the
selection in the Unit dimension check combo box is set to one of None, Append unit
to number or Append unit from unit set.
The Value input fields for Lower bound and Upper bound allow you to use global
parameters or scalar declaration variables. Using scalar declaration variables in this
field supports the same type of data conversions as when using declaration names
as a method input argument in a command sequence. This means that scalar
Integer and Double declaration variable will always work and scalar String
declarations will work if they can be converted to a Double.
Using declaration variable names or global parameters in the Value input fields can
only be used when Unit dimension check is set to Append unit to number or Append
unit from unit set. In that case, the bounds are checked based on the numerical
value entered by the user in the input field. In a Value input field, you cannot use
expressions in terms of declared variables but only a single declaration name. If a
parameter exists with the same name as a declaration variable, then the value of the
global parameter will be used.
214 |
The scope of declaration names used in a Value field is limited to the parent form
of the input field.
Note that the bounds are updated dynamically as the value of the parameters or
declaration variable is changed. This means that several input fields, not actively
changed by the user, can fail numerical validation at once caused by a change in
another input field, which causes the value of a parameter used in a validation
bound to change.
The Error message text field allows you to write a customized error message to be
shown when the input values are out of bounds. The error message text can
contain eval(variable), which is also allowed in the title for plot groups in the
Model Builder. In addition, the Tooltip of the input field allows use of
eval(variable). The variable can be the name of any global parameter or scalar
declaration. If a parameter and a declaration with the same name exists, then the
parameter is used. In addition to parameter and declaration names the special
strings MINVALUE and MAXVALUE can be passed to eval and will return the value
entered as lower bound or upper bound.
When using eval for a parameter, it will return the evaluated value of the
parameter using the same unit that is used to enter the bounds in the Value input
field. For a scalar declaration the string value of the declaration is returned which
will be true or false for a boolean declaration.
A CCESS TO O LD V ALUE AND N EW V ALUE IN E VENT M ETHODS
You can create a method for an On data change event directly from the Events
section of an input field, as shown in the figure below.
| 215
In such a case, the method will automatically get a scalar String input argument
with the name newValue, as shown in the figure below.
The variable newValue will get the new value entered in the input field by the user
of the app.
In addition to the new value, you may need to access to the old value entered in
the input field, for example, to be able to restore it if your custom data validation
fails. For this purpose, you can use the event object and its associated methods
which are accessible from methods that are called from events. The event object
has the following methods:
event.getOldValue()
event.getNewValue()
which return the old and new value, respectively, of the source associated with the
form object. The methods return an object called Value which is similar to the
DataSource object returned when you call:
app.declaration(<declarationName>)
A DataSource object has the methods getBoolean, getBooleanArray,
getBooleanMatrix, getDouble, and so on to allow accessing the value stored in
the DataSource object no matter what type it has. It also has the corresponding
set methods to allow setting a value. For more information, see .
The Value object is a read-only version of the DataSource object with only the
get methods.
216 |
A CCESS TO F ORMS AND F ORM O BJECTS IN E VENT M ETHODS
For methods that are called from events, you can access the properties formTag
and formObjectTag for the form object that triggered the event. This way, you
can access the form object from the event method using the syntax:
app.form(<formTag>).formObject(<formObjectTag>)
To make it more convenient to access the user control that triggered the event
there is also a method
event.getUserControl()
that returns the form object, menu item, or ribbon item that triggered the event.
The event object is additionally available for methods called from command
sequences in, for example, menu items and ribbon items. The interface
IPropertyAccess which has methods for getting and setting values on all user
interface controls such as form objects, menu items and so on can then be returned
by the getUserControl method.
D ATA V ALIDATION FROM D IALOG B OXES
A form that is shown as a dialog box can function in two different ways. The first
way, which is the default option, works on a copy of the data and stores changes
when the user clicks OK in the dialog box. The second way is enabled by changing
the Store changes value of the form, used as a dialog box, from On request to
Immediately, as shown in the figure below.
Changes performed in the dialog box will then be stored to the associated source
variable or parameter immediately and it will work like a regular form in the main
application window.
| 217
To accomplish storing of the values when the dialog box is set to work on a copy,
corresponding to the first option above, and store the values on request, the
Settings window for a button object has a check box Store changes in the section
Dialog Actions, as shown in the figure below. When this check box is selected, the
values in the dialog box are stored from the copy used by the dialog box to the
actual values after the command sequence specified for the button has been run.
Part of this command sequence can include a method that performs validation of
the data that the user has entered in the dialog box. The figure below shows an
example of this scenario, with a method validation, for an OK button used in a
dialog box.
However, this validation approach will not work. This is due to the fact that when
the dialog box is set to Store changes on request, the values have not yet been
stored when the validation method runs since dialog actions such as Store
changes are performed after the command sequence for the button has been run.
This means that the validation code cannot access the new values to perform a
validation on them.
To remedy this, there is an access method that can be used together with form
objects such that the value currently entered in them can be used for data
218 |
validation before they have been stored in their associated source. The syntax for
calling this access method is:
app.form(<formTag>).formObject(<formObjectTag>).getValue();
This call will return a Value object, the same type of object described earlier and
used for calls to event.getOldValue() and event.getNewValue(). With this
type of access to the current value in the form object, a data validation can be
performed. The following form object types support the getValue method.
• Input field
• Toggle Button
• Check box
• Combo box
• File import
• Array input
• Radio button
• Selection input
• Text
• List box
• Table
• Slider
• Knob
• Gauge
If the user has clicked OK in a dialog box and the data validation fails, you typically
want to show an error dialog box and then leave the dialog box open to allow the
user to correct the input fields that failed validation. This not possible to achieve
using a direct approach since if the OK button is set to have Store changes as a Dialog
Action the storing of the data will always be performed after the command
sequence, defined in the Settings window of the OK button, has been run.
To remedy this, there is a method for programmatically store changes:
storeChanges(String name)
which will store the changes for a given form, used as a dialog box.
Note that you can call:
closeDialog(<dialogTag>)
to close a specific dialog box.
When using the technique described above, you can clear the Store changes and
Close dialog check boxes, in the Dialog Actions section for the OK button and instead
| 219
call storeChanges and closeDialog as part of the flow in the validation method
if the validation passes.
Having a way to programmatically store changes also helps with the case where
the dialog box contains a button that also performs something when closing the
dialog box, for example, a Compute button. A validation may then be followed by,
for example, a compute method. In order to get this compute method to work on
the new values entered in the dialog box, storeChanges can be called after the
data validation has been performed but before the compute method is called.
E XAMPLE OF D ATA V ALIDATION IN F ORMS AND D IALOG B OXES
This example illustrates the use of data validation in a form and a dialog box. This
app is very simple and does not fulfill any other function than to demonstrate
important aspects of data validation. The app consists of a form with one input
field that expects the user to type the string open dialog, as shown in the figure
below
If the user types a different string, then an alert window with a message Unknown
command is shown:
and the string value for the Command is reset to the default Type open dialog.
220 |
If the correct string open dialog is entered, then a dialog box opens, as shown in
the figures below.
The dialog box expects an integer between 1 and 10, in the first input field. In
addition, it expects the value in the second input field to be identical to the value
in first input field. If all these criteria is fulfilled, no error message is shown and the
app starts from the beginning showing the string Type open dialog in the main
form.
If the user enters different values, as shown in the figure below:
| 221
then an error message is shown with the message The value of y must be equal
to x.
When the user now closes the Error message dialog box, the user gets a new
opportunity to enter matching values in the dialog box.
The data validation functionality in this demonstration app is implemented using
an On data change event for the Command input field in the main form form1, as
shown in the figure below.
222 |
The code in method3 shows the user of event.getNewValue and
event.getOldValue, as shown below:
String value = event.getNewValue().getString();
String oldValue = event.getOldValue().getString();
if (value.toLowerCase().equals("open dialog")) {
dialog("/form2");
} else {
alert("Unknown command.");
command = oldValue;
}
The dialog box form2 has Store changes set to On request, as shown in the figure
below.
In the dialog box, the value of the variable x is validated in the On data Change
event of the input field with label Number x (1-10) and also when clicking the OK
button. The y value is only validated when clicking the OK button. The data
validations are implemented using the form object access method getValue. The
OK button makes use of the storeChanges method. The figure below shows the
| 223
method run for the On data change event for the input field with label Number x
(1-10).
The corresponding code in method2 is as follows:
int valueX =
app.form("form2").formObject("inputfield1").getValue().getInt();
if (valueX < 1 || valueX > 10) {
error("The value of x must be greater than or equal to 1 and less than or
equal to 10.");
}
224 |
The OK button calls method1 for the On data Change event, as shown in the figures
below.
The corresponding code in method1 is as follows:
int valueX =
app.form("form2").formObject("inputfield1").getValue().getInt();
| 225
int valueY =
app.form("form2").formObject("inputfield2").getValue().getInt();
method2();
if (valueX != valueY) {
error("The value of y must be equal to x.");
} else {
storeChanges("/form2");
closeDialog("/form2");
command = "Type open dialog";
}
U s i n g S e le c t i o n s i n A d d - I n s
In order to use selections in the Model Builder from an add-in, you leave the
source settings empty when using a selection input form object at the time the
add-in is created. Then you use a method to create an explicit selection in the
current model and link it to the selection input object of the add-in.
The figure below shows a simple add-in Boundary Selections used to demonstrate
this functionality. It contains a form with a selection input object and a button.
When the add-in is in focus, the user can click on one or more boundaries in the
226 |
graphics window to create the selection. Clicking the button triggers an Alert
with a dialog box where the selected boundaries are listed.
The figure below shows the form of the add-in as it appears when in use in a
model:
| 227
When the add-in Settings form is added to a model, an On load event is triggered
that runs a method createSelection. The Settings form is shown in the figure
below:
The code for the method createSelection is listed below:
// Create explicit selection in the model.
if (model.selection().index(selectionTag) < 0) {
SelectionFeature selection = model.selection().create(selectionTag,
"Explicit");
selection.geom(2);
selectioninput1.set("source", selection);
}
// Activate the selection whenever the settings form is selected
selectioninput1.set("active", true);
The variable selectionTag stores a unique identifier for the Model Builder
Explicit selection feature. This string needs to be different enough not to
228 |
accidentally collide with the user’s selection features, used for other purposes, in
the Model Builder. The figure below shows the declaration of this String variable.
In addition, a shortcut selectioninput1 is used for the selection input object, as
shown in the figure below.
| 229
The figure below shows the Settings window for the Selection Input form object
selectioninput1. Note the empty selection of the Source and Graphics to Use
When Active. These settings are set by the method createSelection.
230 |
The figure below shows the Settings window for the Button form object button1.
When this button is clicked, a method displaySelection is run. The code for this
method is shown below.
SelectionFeature selection = model.selection(selectionTag);
alert("Selection boundaries are: "+concat(", ",
toString(selection.entities())));
For your own add-in, you can replace this code with any number of actions that
accepts an explicit selection as an input. For example, you can add the following
lines of code to the end of the method displaySelection in order to add a
variable a, local to this explicit selection, having the value 5.
model.component("comp1").variable().create("var1");
model.component("comp1").variable("var1").selection().geom("geom1", 2);
model.component("comp1").variable("var1").set("a", "5");
model.component("comp1").variable("var1").selection().named(selectionTag);
| 231
U s i n g B u i l t - I n M e t h o d s f r o m an E xte rna l Ja va Libr ary
When developing an external Java® library to be used in the Application Builder,
it is possible to call the built-in methods from the external library. In order to do
so, the com.comsol.api JAR-file needs to be added to the project build path, and
the classes that call the methods need to extend the ApplicationLanguageBase
class. The following steps explain how to create a simple example JAR library when
using the Eclipse® integrated development environment:
1 Start Eclipse®.
2 Create a new Java® project. Enter JavaLibDemo as the project name and click
Next.
3 Go to the Libraries tab and click Add External JARs. Add the JAR-file
com.comsol.api_1.0.0.jar from the plugins directory under the COMSOL
Multiphysics installation directory; for example
C:\Program Files\COMSOL\COMSOL62\Multiphysics\plugins
4 Click Finish.
5 Right-click the src folder in your Eclipse project and select New... Package. Enter
demo as the package name and click Finish.
6 Right-click the demo package in your Eclipse project and select New... Class. Enter
Hello as the class name.
7 Click on Superclass>Browse and select ApplicationLanguageBase. Click OK
and Finish.
8 In the editor window for the Hello class, add the following method and save
the file:
public static void hello() {
alert("Hello!");
}
9 Right-click the JavaLibDemo project and select Export>Java>JAR file. Select the
export destination JAR-file and click Finish.
10Start COMSOL Multiphysics and create a Blank Model.
11In the Application Builder, under the application tree, right-click Libraries and
select External Java Library. In the Settings window, click Browse and select the
JAR-file previously exported from Eclipse®.
12In the Application Builder, add a form, button, and method for the button.
13In the Method Editor for the method, add the following code:
Hello.hello();
14Click Test Application and click the button in the application to verify that the
alert method is invoked.
232 |
M e as u r i n g t h e J av a H e a p S p a ce M e m o r y
Software components that are based on Java®, such as certain parts of COMSOL
Multiphysics, are predefined to use only a limited amount of memory. This limit,
the Java® heap space, is specified during startup. Note that the Java® heap space
only affects certain parts of the software and not, for example, meshing or solvers.
By default, COMSOL Multiphysics allocates 2 GB of Java® heap space memory.
See the Reference Manual for information about increasing the available heap
space memory.
In a method, you can measure the amount of heap space memory currently in use.
For example, while debugging, you can add the following code:
Runtime runtime = java.lang.Runtime.getRuntime();
runtime.gc();
debugLog("Used memory (MB): "+(runtime.totalMemory()-runtime.freeMemory())/
(1024*1024));
The first line adds a request to run the Java® garbage collector.
In order to monitor the memory usage in an application, you can replace
debugLog with message.
Time-Limited and Hardware-Locked Applications
By writing a few lines of code, you can make your application expire after a set date
and lock the application to specific hardware.
The example MPH-file used in this section is available in the Application
Gallery at https://www.comsol.com/model/
time-limited-and-hardware-locked-application-70151
P ASSWORD P ROTECTION
The settings of an application can in principle be read from the file system by a
user, including method code. By making your application password protected for
editing, the method code will no longer be readable. This setting is available from
the root node in either the model tree or the application tree, as shown in the
| 233
figure below.
Before implementing a time limit or hardware lock, as described below, make sure
your application is password protected. Password protection for running the
application is not required for this purpose.
T IME -L IMITED A PPLICATION
To have an application expire after a specific date, create a method as follows:
java.text.SimpleDateFormat f = new java.text.SimpleDateFormat("yyyy-MM-dd");
//java.text.SimpleDateFormat f = new java.text.SimpleDateFormat("MM/dd/yyyy");
ok = false;
try {
java.util.Date d = f.parse(timeoutDate);
long currentTime = timeStamp();
long timeoutTime = d.getTime()+24*60*60*1000; // To allow running until the end
of the day
if (currentTime < timeoutTime) {
ok = true;
}
}
catch (java.text.ParseException e) {
debugLog("Failed to parse timeout date "+timeoutDate);
debugLog(e.getMessage());
}
In this method, you need to decide on a date format. Two format examples are
shown and you can uncomment the line corresponding to the format you would
like to use. For more details on available formats, see the Java® documentation for
234 |
SimpleDateFormat. This method has one string input argument, timoutDate,
and one Boolean output argument, ok, as shown below.
The expiration date is defined as a string variable, trial_date, in
Declarations>String, as shown below.
H ARDWARE -L OCKED A PPLICATION
To lock an application to the MAC address of a specific network card on a
computer, create a method as follows:
ok = false;
try {
java.util.List < java.net.NetworkInterface > nis =
java.util.Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
for (java.net.NetworkInterface ni : nis) {
StringBuilder macString = new StringBuilder();
byte[] macBytes = ni.getHardwareAddress();
if (macBytes != null && macBytes.length > 0) {
for (byte b : macBytes) {
if (macString.length() > 0) {
macString.append(":");
}
macString.append(String.format("%02x", b));
}
| 235
if (contains(allowedAddresses, macString.toString())) {
ok = true;
break;
}
}
}
}
catch (java.net.SocketException e) {}
In order to check the MAC address when running an application, you need to
enable Allow access to network sockets under Security in Preferences. However, for
a compiled application, no security changes are needed.
This method has one array 1D string input argument, allowedAddresses, and
one Boolean output argument, ok, as shown below.
The MAC address is defined as a string array mac_addresses in Declarations>Array
1D String, as shown below.
Note that you can provide a list of MAC addresses to allow use on a computer with
multiple network cards or multiple computers.
C HECKING F OR A LLOWED D ATE AND H ARDWARE
To check for both the MAC address and the date, create a method
check_allowed_to_run as follows:
if (!check_mac_address(mac_addresses)) {
alert("You are not allowed to run this application on this computer.",
"COMSOL");
236 |
exit();
}
if (!check_date(trial_date)) {
alert("The trial for this application has expired "+trial_date, "COMSOL");
exit();
}
The figure below shows this method in the Method Editor.
You can call this type of method at startup of the application, for example, as an
On load event for the main form of the application. In the Tuning Fork example
application, available in the Application Library of COMSOL Multiphysics, there
is a method p_init_application that is run as an On load event for the main
form. In this case, the method p_init_application can be edited as follows:
check_allowed_to_run();
if (model.sol("sol1").isEmpty()) {
solution_state = "nosolution";
}
else {
solution_state = "solutionexists";
}
zoomExtents("graphics1");
Notice the call to the method check_allowed_to_run in the first line. The figure
below shows this method in the Method Editor.
| 237
The method p_init_application is then called as an On load event. This is
specified in the Settings window of the main form, as shown in the figure below.
238 |
Index
1D array 12, 32, 144
A
binary file
2D array 13, 32, 144
processing 192
accessing 210
reading 191
add-in 24, 156, 226
writing 190
selections 226
Blank Model 29
boolean
Add-in Libraries 24
data type 8, 29
alert 118, 125
anisotropic diffusion coefficient 34
Boolean variable 8
Annotation Data plot type 169
conversion 142
AppEventHandlerList methods 96
bound 214
Application Builder 56
boundary condition 41
Application Builder Reference Manual
built-in method library 98
button
131
object 68
application example
tubular reactor 116
application object 7, 26, 56, 98
C libraries
external 131
app variable 58
card stack object 68
classes 58
carriage return 12
application tree 56
catch 18
array 12
C-code
methods 144
array 1D
object 89
array 2D
object 89
linking 131
char
data type 8
character
data type 8
array input object 67
character stream 185
Arrow Data plot type 167, 168
characters
assignments 9
B
C
special 184
auto complete 19
check box object 69
automatic solver sequence 47
choice list 59, 91, 122
axisymmetric property 29
methods 91
backslash 12
object 89
backspace 12
basic data type 29
big endian 192
classes
application object 58
code completion 19
| 239
code generation 19
dialog box 217, 220
collection methods 153
new value 216
color 61
old value 216
of user interface component 60
dataset 49, 159
combo box object 69
DataSource object 216
Compact History 53
date and time methods 139
Compile Equations node 45
debug
computation time 141
methods 131
last 140
Debug Log window 131
Compute 46
declaration 214
COMSOL Desktop 51
type 55
COMSOL Help Desk 54
Declaration methods 96
COMSOL Multiphysics 7, 26
Declarations 12, 14, 57
COMSOL Multiphysics Programming
deformation plot 34
degrees of freedom 206
Reference Manual 206
confirm 11, 118, 125
Dependent Variables node 45
contour plot 48
description 18
contour plot data 187
parameter 18, 35
control flow statements 16
variable 18
conversion
Developer tab 158
between data types 9
Dialog Actions 218
methods 142
dialog box 117, 118
coordinate information 197, 198
data validation 217, 220
Copy as Code to Clipboard 30
diffusion coefficient
creating
anisotropic 34
dimension
feature node 38, 42
model object 28, 52
spatial 29
CSV-file 170, 177
disable form object 60, 65, 66, 122
curve
Display Name
interpolation 186
for choice list 122
parameterization 193
double 9
cut point
data type 8, 29
variable conversion 142
dataset 34, 99
D
Data Source
class 59, 89
data types
primitive 8
data validation 214
240 |
double quotation mark 11
data display object 70
E
edge
parameterization 193
Editor Tools window 35
Electric Currents 51
element
order 206
name 107
size 33, 39
open 110
elementary math functions 15
reading 170
email
writing to 170
class 113
File Declaration 173
methods 113
file import 173
preferences 115
file import object 71
email attachment
file open
export 113
system method 110
report 113
file scheme
table 113
syntax 104, 173
embedded model 51
Filter 214
enable form object 58, 60, 65, 66, 122
finite element
endian 192
accessing 206
equation
system matrix 209
vector 209
object 71
error dialog box 18
floating point number 8
Error message 215
for loop 17, 66, 97
eval 215
form
events 93, 217
class 59, 64
example code 98, 158
declarations 15
Excel® file 50, 107, 170, 175, 178
list methods 96
exception
form collection 72
form feed 12
handling 18
exit 129
form method 25
application 130
form object 71
expiration date for application 233
class 59, 65
explicit selection 226
list methods 96
export
types 67
FormList methods 96
email attachment 113
F
external C libraries 131
FormObjectList methods 96
external Java® library 232
Fully Coupled node 47
face
parameterization 195
feature node
creating 38, 42
removing 39, 42
file
methods 103, 104
G
general properties 60
generating code 19
Geometry node 38
geometry object 38, 39
names 198
get 29, 30
global method 25
| 241
global parameter 35
class 59
graphics
list methods 96
object 73, 117
menu 88
view 123, 126
object 88
grid dataset 158
toolbar 88
GUI command
ItemList methods 96
methods 129
iterative solver 45
GUI related methods 117
H
hardware lock 233
Iterator class and method 42
J
heap space 233
jagged arrays 12
Java
Heat Transfer in Solids 40, 51
Documentation, model object class
higher-order element nodes 206
structure 54
history
math library 15
programming language 7, 8, 98
model 53
HTML
syntax 9
unary and binary operators 9
report 125
hyperlink object 74
I
Java®
character stream 185
if-else statement 16
classes for read/write 184
image object 74
external library 232
import
heap space 233
file 173
information card stack object 75
K
information node 141
Ctrl+Space 19
inherit
color 61
input field 214
input field object 76
integer
data type 8, 29
variable conversion 142
interpolation curve 186, 193
interpolation function 193
Introduction to Application Builder 7,
19, 23, 24, 56, 92, 104, 141, 170
Introduction to COMSOL Multiphysics
23, 26
isosurface 158
item
242 |
keyboard shortcut
knob object 83
L
legend 33, 34
license
check out 130
method 100
lighting 165
Line Data plot type 162
line object 78
list box object 78
literals 9
little endian 192
load vector 213
loading
model 51, 99
local method 25
M
locking application to hardware 233
Model Builder 26
log object 79
model component 29
looplevel property 50
model data access 23
Lower bound 214
model history 53, 161
recording 53
MAC address 233
turning off 161
main application class 58, 62
Model Java-file 53
main user interface component classes
Model M-file 53
59
model object 7, 26, 42, 56, 98
Main Window
class structure 54
class 59, 63
tag 26
node 59
model tree 26
material
node 41, 42
link 34
model utility methods 53, 98
tag 92
Model Wizard 29, 51
Materials node 42
models, working with multiple 51
math functions 15
MPH file 51, 98, 130
maximum value 49
multiphysics 51
menu
Multiphysics node 51
item 88
multiple models 51
mesh
information and statistics 205
N
name
mesh element size 33, 39
form 56, 58
Mesh node 39
form object 56, 58
message log object 79, 120
in application object 58
message method 125
method 25
method 7, 98
scoping 27
form 25
get 30
shortcut 15, 56
user interface component 56, 58
global 25
network card 233
local 25
new value
name 25
data validation 94, 216
Method class 96
newline 11, 12
Method Editor 98
node
using 7, 19
finite element 206
method name 25
nonlinear solver 47
Microsoft® Word® format 126
normal
model 51
loading 51, 99
saving 51, 99
surface 165, 166
numerical
Derived Values 49
| 243
Numerical validation 214
O
precedence, of operators 9, 37
primitive data types 8
old value
printing
data validation 94, 216
graphics 129
On data change event 94, 215
programming examples 98, 158
operating system
Programming Reference Manual 26, 47,
methods 110
98, 100, 201, 206
operators 37
progress 133
Java 9
dialog box 134, 138
model object 37
methods 133
OS commands 110
progress bar object 79, 135, 137, 138
P
parameter 18, 34, 35, 50
properties
method 17, 24
general 60
real and imaginary part 36
property and property values 29
parameterization
edge 193
face 195
parameterized solution 50
parsing
text file 184
physics interface 41, 44
play sound 111
plot
group 34, 125
mesh element nodes 99
point trajectories 99
surface 37, 48
table surface 50
useGraphics 117
Plot Group node 48
plot type
Annotation Data 169
Arrow Data 167, 168
Line Data 162
Point Data 160, 161, 209
Surface Data 163, 164, 165
Tube Data 167
Point Data plot type 160, 161, 209
point trajectories plot 99
R
radio button object 80
ragged arrays 12, 32
reading
binary file 191
CSV-file 171
Excel® file 175
file 170
matrix file 179
Microsoft Excel® Workbook file 175
spreadsheet 171
text file 184
text file to string 181
real and imaginary part
of parameter 36
Record Code 21, 46
recursion 201
recursive loop 201
removing
feature node 39, 42
report 115
email attachment 113
HTML 125
Microsoft® Word® format 126
request 119, 125
reset
244 |
model history 53
special characters 184
Results node 48
sphere 158
results table object 80, 122
spreadsheet 171
RGB color 61
S
format 104, 179, 180, 186
Stationary Solver node 45
save application 130
Stationary study step 44
save as 129, 130
status bar 133
saving
Store changes, in dialog box 217
model 51, 99
stream
scalar
character 185
object 89
String
scene light 130
data type 10, 29
sectionwise
methods 152
format 186, 189
string variable 50
sectionwise format 186
conversion 143
selection
methods 152
explicit 226
strings
selection input
comparing 11
object 81, 226
concatenating 11
selections 198
Study node 44
add-in 226
subform object 71
set 29
surface
setIndex 29
parameterization 195
shortcuts 15, 56
Surface Data plot type 163, 164, 165
Shortcuts node 15
surface normal 165, 166
single quotation mark 12
surface plot 37, 48
sleep 141
system matrix
slider object 82
accessing 210
SMTP 115
system methods 110
solution
OS commands 110
data 158
system vector 210
data structure 45
parameterized 50
Solution node 45
Solver Configurations node 44
solver sequence 44
T
tab 12
table 50
email attachment 113
object 85, 121
spacer object 84
Table node 49
spatial dimension 29
table surface plot 50
special character 12
tag 58
Java 52
model object 26
| 245
physics interface 41
view
temporary folder
graphics 123, 126
visualization 158
location 178
text file 170
W web page object 88
reading 184
while loop 17
writing 184
with statement 17
text label object 86
writing
text object 85
CSV-file 177
time 139
Excel file 178
time-limited application 233
matrix file 180
title 118
string to text file 183
toggle button object 86
text file 184
toolbar
to binary file 190
item 88
to file 170, 178
object 87
Tooltip 215
transparency 127, 130
transparent
color 61
try and catch 18
Tube Data plot type 167
type declaration 55
U
unit 36
object 87
Unit List 59
unit set
methods 91
object 89
unit sphere 158
Unit System 35
Upper bound 214
username 110
V
Value input field 214
Value object 216
variable 24
description 18
name completion 20
video object 87
246 |
Z
zoom extents 125, 130

advertisement

Was this manual useful for you? Yes No
Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Related manuals

advertisement