Application Programming Guide
Application Programming Guide
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:
   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 . . . . . 24
       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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
        Working with Model Objects . . . . . . . . . . . . . . . . . . . . . . . . . 51
        The Model Object Class Structure. . . . . . . . . . . . . . . . . . . . . 53
     The Application Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
        Shortcuts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
        Accessing the Application Object. . . . . . . . . . . . . . . . . . . . . . 57
        The Name of User Interface Components . . . . . . . . . . . . . . 57
        Important Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
        Get and Set Methods for the Color of a Form Object . . . . 58
        General Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
        The Main Application Methods. . . . . . . . . . . . . . . . . . . . . . . . 61
        Main Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
        Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
        Form Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
        Item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
        Data Source. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
        AppEvent Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
        Method Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
        Form, Form Object, and Item List Methods . . . . . . . . . . . . . 94
     The Built-in Method Library for the Application Builder. . . . . . 96
        Model Utility Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
        License Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
        File Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
        Operating System Methods. . . . . . . . . . . . . . . . . . . . . . . . . . 108
        Email Methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
        Email Class Methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
        GUI-Related Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
        GUI Command Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
4|
   Debug Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
   Methods for External C Libraries . . . . . . . . . . . . . . . . . . . . . 129
   Progress Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .131
   Date and Time Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . .137
   Conversion Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .140
   Array Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
   String Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
   Collection Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
   Model Builder Methods for Use in Add-Ins. . . . . . . . . . . . . 154
Programming Examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
   Running the Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
   Visualization Without Solution Data: Grid Datasets. . . . . . 156
   Visualization of Points, Curves, and Surfaces . . . . . . . . . . . .158
   Reading and Writing Data to File . . . . . . . . . . . . . . . . . . . . . 168
   Converting Interpolation Curve Data. . . . . . . . . . . . . . . . . . 191
   Plotting Points on a Parametric Surface . . . . . . . . . . . . . . . . 193
   Using Selections for Editing Geometry Objects . . . . . . . . .194
   Recursion and Recursively Defined Geometry Objects. . . 199
   Mesh Information and Statistics. . . . . . . . . . . . . . . . . . . . . . . 203
   Accessing Higher-Order Finite Element Nodes . . . . . . . . .204
   Accessing System Matrices and Vectors. . . . . . . . . . . . . . . . 206
   Data Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
   Using Selections in Add-Ins . . . . . . . . . . . . . . . . . . . . . . . . . . 223
   Using Built-In Methods from an External Java Library. . . . . 229
   Measuring the Java Heap Space Memory. . . . . . . . . . . . . . .230
   Time-Limited and Hardware-Locked Applications . . . . . . . 230
                                                                                                 |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.
Data Types
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|
  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).
However, the opposite will not work automatically (you will get a compilation
error). Instead you can use explicit type casting as follows:
                                                                                            |9
  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...
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
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:
10 |
  String a = "string A";
  String b = " and string B";
  a.concat(b);
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
backslash (\). The table below summarizes some of the most important special
characters.
                                                                           | 11
             SPECIAL CHARACTER    DESCRIPTION
             \\                   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";
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:
  double dv[] = new double[12];
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};
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}};
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];
    }
  }
                                                                                | 13
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.
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 55.
14 |
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.
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 65 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 95.
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();
                                                                              | 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.
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.
                                                                                | 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 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 or a Settings Form. 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.
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
24 |
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 55 gives an overview of the application object.
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.
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
The component is given a definite spatial dimension when you create a geometry
node:
  model.geom().create("geom1", 2);
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
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
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");
                                                                               | 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);
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 first and second row of the array and are equivalent to the single statement:
  set("name",new String[][]{{"1","2","3"},{"4","5"}});
32 |
  // String[] properties();
  String[] props =
  model.component("comp1").physics("ht").feature("solid1").properties();
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 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 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");
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();
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);
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();
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.
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 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();
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);
  }
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();
                                                                             | 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();
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
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});
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]");
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
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");
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");
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.
46 |
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");
                                                                              | 47
  else {
    solutionState = "solutionexists";
  }
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");
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"));
48 |
    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();
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
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();
  // The following line is needed to update the plot
  model.result("pg1").run();
Multiphysics
50 |
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.
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.
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.
                                                                              | 51
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 file name. 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.
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 96.
52 |
may need to temporarily turn off model history recording as illustrated by the
following example:
  model.hist().disable();
  // some code
  model.hist().enable();
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.
                                                                                 | 53
The figure below shows the document as displayed in a the COMSOL
documentation viewer.
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.
54 |
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.
                                                                               | 55
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.
56 |
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");
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().
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
                                                                            | 57
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 88.
M ETHOD C LASS
The Method class is used to represent methods. For more information, see
“Method Class” on page 94.
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.
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
58 |
 model.app part of the model object. In addition, the following methods are
 available for changing the color of a form object:
 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.
                                                                                          | 59
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 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)");
 60 |
   The M a in A pplica t i o n Met h o d s
   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");
                                                                                         | 61
       // Get the index within the list of the DataSource with the name "svar".
       int index = list.index("svar");
Main Window
  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
  the menu type setting, but doing so will not have any visible effect in the user
  interface.
  62 |
The MainWindow class has the following properties:
E XAMPLE C ODE
  // Don’t 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
                                                                                     | 63
 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:
 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 61.
Form Object
 64 |
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                  Returns true if there is a modifiable property with
                hasProperty(String
                name)
                                         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      Sets the visible state of the form.
                form, boolean visible)
 Most form objects have one or more of the properties listed in “General
 Properties” on page 59. 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
                                                                                        | 65
"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 211.
The following table lists all form object types that can be returned by getType:
A RRAY I NPUT
Example Code
  app.form("form1").formObject("arrayinput1").set("enabled", false);
66 |
B UTTON
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
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);
                                                                                       | 67
C HECK B OX
Example Code
 app.form("form1").formObject("checkbox1").set("tooltip", "tooltip text");
C OMBO B OX
Example Code
 app.form("form1").formObject("combobox1").set("foreground", "blue");
68 |
D ATA D ISPLAY
Example Code
  app.form("form1").formObject("datadisplay1")
     .setColor("background", 192, 192, 192);
                                                                                     | 69
E QUATION
Example Code
  app.form("form1").formObject("equation1").set("visible", false);
F ILE I MPORT
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.
70 |
F ORM C OLLECTION
Example Code
This line of code changes the font:
  app.form("form1").formObject("collection1").set("font", "Arial");
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.
                                                                                     | 71
G RAPHICS
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:
72 |
  graphics1.set("datapick", true);
  graphics1.set("datapicktarget", pdom1);
H YPERLINK
Example Code
  with (app.form("form1").formObject("hyperlink1"));
    set("text", "COMSOL");
    set("url", "www.comsol.com");
  endwith();
I MAGE
Example Code
  app.form("form1").formObject("image1").set("icon", "compute.png");
                                                                                   | 73
I NFORMATION C ARD S TACK
Example Code
 app.form("form1").formObject("infocard1").set("fontunderline", true);
74 |
I NPUT F IELD
                                                                                   | 75
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   auto        When the value is scientific,
                | decimal                       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);
76 |
L INE
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
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");
                                                                                       | 77
L OG
Example Code
  app.form("form1").formObject("log1").set("fontsize", "20");
M ESSAGE L OG
Example Code
  app.form("form1").formObject("messages1").set("background", "gray");
P ROGRESS B AR
To create and update progress information see “Progress Methods” on page 131.
Example Code
  app.form("form1").formObject("progressbar1").set("visible", false);
78 |
R ADIO B UTTON
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
To change the contents of the results table use the method useResultsTable or
evaluateToResultsTable. See also “GUI-Related Methods” on page 115.
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");
                                                                                       | 79
S ELECTION I NPUT
Example Code
  app.form("form1").formObject("selectioninput1").set("graphics",
      "graphics1");
To change the model selection, assuming sel1 is a shortcut to the selection input
form object:
  sel1.set("source", model.selection("sel2"));
80 |
S LIDER
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);
                                                                                  | 81
K NOB
82 |
PROPERTY            VALUE            DEFAULT     DESCRIPTION
notation            auto |           auto        When the value is scientific,
                    scientific   |               numbers are always displayed using
                    decimal
                                                 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 |   marks       To control whether the scale should
                    markslabels |
                    marksalllabels
                                                 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.
                                                                                 | 83
T ABLE
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
Example Code
  app.form("form1").formObject("text1").set("textalign", "center");
84 |
T EXT L ABEL
Example Code
  app.form("form1").formObject("textlabel1").set("text", "custom text");
T OGGLE B UTTON
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");
                                                                                          | 85
T OOLBAR
Example Code
  app.form("form1").formObject("toolbar1").set("background", "gray");
U NIT
Example Code
  app.form("form1").formObject("unit1").set("visible", false);
V IDEO
Example Code
  app.form("form1").formObject("video1").set("visible", false);
86 |
W EB P AGE
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 menu. The following methods are available:
                                                                                           | 87
The Item class contains the following properties:
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
88 |
      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.
                                                                                      | 89
    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);
    90 |
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        Sets the display name for the
                     row)
                                                                   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:
                                                                                               | 91
NAME             SYNTAX                                  DESCRIPTION
getDoubleArray   double[] getDoubleArray(String          Returns the value of the specified
                 name)
                                                         property as a double array value.
set              set(String name, String value)          Sets a new value for the property
                 set(String name, double value)
                 set(String name, double[] value)
                                                         with the specified name.
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
92 |
instance of this class when a FormObject event is being triggered. The
getUserControl method retrieves the FormObject where the event originated.
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.
                                                                                        | 93
NAME                 SYNTAX                   DESCRIPTION
getStringArray       String[]                 Gets the string array value.
                     getStringArray()
getStringMatrix      String[][]               Gets the string matrix value.
                     getStringMatrix
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 211.
Me thod Class
The Method class is used to represent a method. The following method is available
for a Method object:
94 |
NAME       SYNTAX                       PURPOSE
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.
Additionally the FormList class has the following methods:
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");
  }
                                                                                       | 95
    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 55. Some of the listings
    have associated example code but for more extensive programming examples, see
    “Programming Examples” on page 156.
    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.
    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.
    96 |
NAME                 SYNTAX                                 DESCRIPTION
loadProtectedModel   Model loadProtectedModel(String        Loads a password protected
                     filename, String password)
                                                            model from a file. The model is
                                                            given a unique tag.
loadRecoveryModel    Model loadRecoveryModel(String tag,    Loads a model from a recovery
                     String foldername)
                                                            directory/folder structure.
loadRecoveryModel    Model loadRecoveryModel(String         Loads a model from a recovery
                     foldername)
                                                            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)                Removes a model. The
                     removeModel(Model model)
                                                            embedded model cannot be
                                                            removed.
saveModel            saveModel(Model model, String          Saves a model to a file. The
                     filename)
                                                            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.
    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();
       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");
                                                                                    | 97
    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.
    98 |
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”);
                                                                                | 99
 PRODUCT/FEATURE                         FEATURE NAME
100 |
           PRODUCT/FEATURE                              FEATURE NAME
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
       Introduction to Application Builder and “GUI Command Methods” on page
       127.
                                                                                            | 101
NAME                       SYNTAX                            DESCRIPTION
readMatrixFromFile         double[][]                        Reads the contents of the given
                           readMatrixFromFile(String name)
                                                             file into a double matrix. The file
                                                             has the same spreadsheet type
                                                             format as available in the model
                                                             tree Export node.
readStringMatrixFromFile   String[][]                        Reads the contents of the given
                           readStringMatrixFromFile(String
                           name)
                                                             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     Reads a file with
                           name)
                                                             comma-separated values (CSV
                                                             file) into a string matrix. Expects
                                                             file to use the RFC 4180 format
                                                             for CSV.
writeFile                  writeFile(String name, String     Writes the given string contents
                           contents)
                                                             to the given file name.
writeFile                  writeFile(String name, String     Writes the given string contents
                           contents, boolean append)
                                                             to the given file name. If append is
                                                             true, then the contents are
                                                             appended instead of overwritten.
writeFile                  writeFile(String name,            Writes the array data to the
                           double[][] data)
                                                             given file. The spreadsheet format
                                                             is used, which means it can be
                                                             read by readMatrixFromFile.
writeFile                  writeFile(String name,            Writes the array data to the
                           double[][] data, boolean
                           append)
                                                             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,            Writes the array data to the
                           String[][] data)
                                                             given file. The spreadsheet format
                                                             is used, which means it can be
                                                             read by
                                                             readStringMatrixFromFile.
       102 |
NAME                         SYNTAX                            DESCRIPTION
writeFile                    writeFile(String name,            Writes the array data to the
                             String[][] data, boolean
                             append)
                                                               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                          Returns a CsWriter that can
                             openFileStreamWriter(String
                             name)
                                                               write to the given file.
openFileStreamWriter         CsWriter                          Returns a CsWriter that can
                             openFileStreamWriter(String
                             name, boolean append)
                                                               write to the given file. If append is
                                                               true, then the contents are
                                                               appended instead of overwritten.
openBinaryFileStreamWriter   CsBinaryWriter                    Returns a CsBinaryWriter that
                             openBinaryFileStreamWriter(Stri
                             ng name)
                                                               can be used to write to the given
                                                               file byte-by-byte.
openBinaryFileStreamWriter   CsBinaryWriter                    Returns a CsBinaryWriter that
                             openBinaryFileStreamWriter(Stri
                             ng name, boolean append)
                                                               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,         Writes the given string array
                             String[][] data)
                                                               data to a CSV file. The RFC 4180
                                                               format is used for the CSV.
writeCSVFile                 writeCSVFile(String name,         Writes the given string array
                             String[][] data, boolean
                                                               data to a CSV file. The RFC 4180
                             append)
                                                               format is used for the CSV. If
                                                               append is true, then the contents
                                                               are appended instead of
                                                               overwritten.
writeCSVFile                 writeCSVFile(String name,         Writes the given double array
                             double[][] data)
                                                               data to a CSV file. The RFC 4180
                                                               format is used for the CSV.
writeCSVFile                 writeCSVFile(String name,         Writes the given double array
                             double[][] data, boolean
                                                               data to a CSV file. The RFC 4180
                             append)
                                                               format is used for the CSV. If
                                                               append is true, then the contents
                                                               are appended instead of
                                                               overwritten.
                                                                                     | 103
NAME           SYNTAX                        DESCRIPTION
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,   Copies a file on the server. Both
               String destFile)
                                             the source and target names can
                                             use file scheme paths.
importFile     importFile(String name)       Displays a file browser dialog box
               importFile(String name,
               String[] fileTypes)
                                             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.
       104 |
NAME             SYNTAX                            DESCRIPTION
importFile       importFile(ModelEntity entity,    Displays a file browser dialog box
                 String name)
                                                   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,       Writes the given string array
                 String[][] data)
                                                   data starting from the first cell in
                                                   the first sheet of an Excel file.
                                                   This method requires LiveLink™
                                                            ®
                                                   for Excel .
writeExcelFile   writeExcelFile(String name,       Writes the given string array
                 String sheet, String cell,
                                                   data starting from the specified
                 String[][] data)
                                                   cell in the specified sheet of an
                                                   Excel file. This method requires
                                                   LiveLink™ for Excel®.
readExcelFile    String[][] readExcelFile(String   Reads the first sheet of an Excel
                 name)
                                                   file, starting from the first cell,
                                                   into a String[][]. This method
                                                   requires LiveLink™ for Excel®.
readExcelFile    String[][] readExcelFile(String   Reads the specified sheet of an
                 name, String sheet, String
                 cell)
                                                   Excel file, starting from the
                                                   specified cell, into a String[][].
                                                   This method requires LiveLink™
                                                            ®
                                                   for Excel .
                                                                        | 105
NAME                SYNTAX                            DESCRIPTION
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 file name 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   Returns the original name of an
                    name)
                                                      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.
       106 |
NAME                             SYNTAX                              DESCRIPTION
getClientFilePath                String getClientFilePath(String     Returns the original path of an
                                 name)
                                                                     uploaded file on the client file
                                                                     system (or null if there is no
                                                                     uploaded file matching the given
                                                                     file scheme path). Returns only
                                                                     the file name 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.
       E XAMPLE C ODE
       This line of code copies the uploaded file file1 to the temp folder with new file
       name 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");
       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.
                                                                                           | 107
    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.
    108 |
NAME                SYNTAX                                   DESCRIPTION
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");
                                                                                    | 109
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");
110 |
       Email Methods
       Email methods are used for sending emails from an application, typically with
       attachments containing results from a simulation.
                                                                                       | 111
NAME                  SYNTAX                                DESCRIPTION
EmailMessage.setUse   mail.setUser(String name, String      Sets the username and password
r                     password)
                                                            to use for email (SMTP) server
                                                            authentication. This method must
                                                            be called after the setServer
                                                            method.
EmailMessage.setSec   mail.setSecurity(String security)     Sets the connection security type
urity
                                                            for email (SMTP) server
                                                            communication. Valid values are
                                                            ’none’, ’starttls’ and ’tls’.
                                                            This method must be called after
                                                            the setServer method.
EmailMessage.setFro   mail.setFrom(String fromAddress)      Sets the from address.
m
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   mail.setSubject(String subject)       Sets the email subject line. Note
ject
                                                            that newline characters are not
                                                            allowed.
EmailMessage.setBod   mail.setBodyText(String body)         Sets the email body as plain text.
yText
                                                            An email can contain both a text
                                                            and an HTML body.
EmailMessage.setBod   mail.setBodyHtml(String body)         Sets the email body as HTML
yHtml
                                                            text. An email can contain both a
                                                            text and an HTML body.
EmailMessage.attach   mail.attachFile(String filename)      Adds an attachment from a file.
File
                                                            The attachment MIME type is
                                                            determined by the file name
                                                            extension.
EmailMessage.attach   mail.attachFile(String filename,      Adds an attachment from a file
File                  String mimeType)
                                                            with the specified MIME type.
EmailMessage.attach   mail.attachFromModel(ModelEntity      Adds an attachment created
FromModel             modelEntity)
                                                            from a report, export, or table
                                                            feature in the model.
EmailMessage.attach   mail.attachText(String text, String   Adds a text attachment with a
Text                  mimeSubType)
                                                            specified sub-MIME type, such as
                                                            plain or HTML.
       112 |
NAME                   SYNTAX                                   DESCRIPTION
EmailMessage.attach    mail.attachBinary(byte[] binary,         Adds an attachment from a byte
Binary                 String mimeType)
                                                                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.
       E XAMPLE C ODE
       The following code sends an email and attaches a report:
         EmailMessage mail = new EmailMessage();
         mail.setTo(emailTo);
                                                                                    | 113
  mail.setSubject("Tubular Reactor Simulation");
  mail.setBodyText("The computation has finished. Please find the report
  attached.");
  mail.attachFromModel(model.result().report("rpt1"));
  mail.send();
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("user@myemail.com", "password");
  mail.setSecurity("starttls");
  mail.setFrom("user@myemail.com");
  mail.setTo("otheruser@somedomain.com");
  mail.setSubject("Tubular reaction simulation");
114 |
         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.
                                                                                    | 115
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   Stops execution and displays
                title)
                                                     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.
        116 |
NAME      SYNTAX                               DESCRIPTION
confirm   String confirm(String text, String   Stops execution and displays
          title, String yes, String no)
                                               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   Stops execution and displays
          title, String yes, String no,
          String cancel)
                                               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      Stops execution and opens
          cause)
                                               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.
                                                                 | 117
NAME              SYNTAX                               DESCRIPTION
request           String request(String text, String   Stops execution and displays
                  defaultString)
                                                       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   Stops execution and displays
                  title, String defaultString)
                                                       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.
       118 |
NAME                       SYNTAX                               DESCRIPTION
evaluateToResultsTable     evaluateToResultsTable(NumericalFe   Evaluates the given entity, a
                           ature entity, String name, boolean
                           clear)
                                                                Derived Value, in the table
                           evaluateToResultsTable(NumericalFe   object given by the name,
                           ature entity, FormObject graphics,   name path, or graphics form
                           boolean clear)
                                                                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[][]                           Evaluates the given entity, a
                           evaluateToDoubleArray2D(NumericalF
                           eature entity)
                                                                Derived Value, and returns
                                                                the non-parameter 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[][]                              Evaluates the given entity, a
                           evaluateToIntegerArray2D(Numerical
                           Feature entity)
                                                                Derived Value, and returns
                                                                the non-parameter 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.
                                                                                  | 119
NAME                      SYNTAX                               DESCRIPTION
evaluateToStringArray2D   String[][]                           Evaluates the given entity, a
                          evaluateToStringArray2D(NumericalF
                          eature entity)
                                                               Derived Value, and returns
                                                               the non-parameter 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         Shows the values from the
                          tableFeature, String resultsTable)
                                                               tableFeature in the
                          useResultsTable(TableFeature
                          tableFeature, FormObject             resultsTable form object.
                          resultsTable)
getChoiceList             ChoiceList getChoiceList(String      Returns an object of the type
                          name)
                                                               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,    Sets the enable state for the
                          boolean enabled)
                                                               form object specified by the
                                                               name or name path.
setFormObjectVisible      setFormObjectVisible(String name,    Sets the visible state for the
                          boolean visible)
                                                               form object specified by the
                                                               name or name path.
setFormObjectText         setFormObjectText(String name,       Sets the text for the form
                          String text)
                                                               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.
       120 |
NAME                        SYNTAX                                DESCRIPTION
setFormObjectEditable       setFormObjectEditable(String name,    Sets the editable state for the
                            boolean editable)
                                                                  form object specified by the
                                                                  name or name path. This
                                                                  functionality is only available
                                                                  for text field objects.
setMenuBarItemEnabled       setMenuBarItemEnabled(String name,    Sets the enable state for the
                            boolean enabled)
                                                                  menu bar item specified by
                                                                  the name or name path (from
                                                                  menu bar) in the first
                                                                  argument.
setMainToolbarItemEnabled   setMainToolbarItemEnabled(String      Sets the enable state for the
                            name, boolean enabled)
                                                                  main toolbar item specified
                                                                  by the name or name path
                                                                  (from main toolbar) in the
                                                                  first argument.
setFileMenuItemEnabled      setFileMenuItemEnabled(String name,   Sets the enable state for the
                            boolean enabled)
                                                                  file menu item specified by
                                                                  the name or name path
                                                                  (from file menu) in the first
                                                                  argument.
setRibbonItemEnabled        setRibbonItemEnabled(String name,     Sets the enable state for the
                            boolean enabled)
                                                                  ribbon item specified by the
                                                                  name or name path (from
                                                                  main window) in the first
                                                                  argument.
setToolbarItemEnabled       setToolbarItemEnabled(String name,    Sets the enable state for the
                            boolean enabled)
                                                                  toolbar form object item
                                                                  specified by the name or
                                                                  name path in the first
                                                                  argument.
useView                     useView(View view, String name)       Applies a view to the
                            useView(View view, FormObject
                            graphics)
                                                                  graphics contents given by
                                                                  the name, name path, or
                                                                  graphics form object in the
                                                                  second argument.
resetView                   resetView(String name)                Resets the view to its initial
                            resetView(FormObject graphics)
                                                                  state in the graphics contents
                                                                  given by the name, name
                                                                  path, or graphics form object
                                                                  in the second argument.
                                                                                   | 121
NAME               SYNTAX                             DESCRIPTION
getView            ViewBase getView(String name)      Returns the view currently
                   ViewBase getView(FormObject
                   graphics)
                                                      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       Goes to a standard view in
                   graphicsname);
                                                      the given graphics form
                                                      object graphicsname.
goToView           goToView(String name, FormObject   Goes to standard view in the
                   graphics);
                                                      given graphics form object
                                                      graphics.
setWebPageSource   setWebPageSource(String name,      Sets the source for the form
                   String source)
                                                      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.
       122 |
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");
The code below displays a request dialog box that lets the user type in a file name
for an HTML report. If the user has typed a file name, then a report is generated.
  String answerh = request("Enter file name","File Name", "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();
  }
                                                                             | 123
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 file name","File Name", "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");
124 |
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.
                                                                           | 125
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");
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).
126 |
  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.
                                                                                    | 127
NAME                  SYNTAX                               DESCRIPTION
scenelight            sceneLight(String graphicsName)      Toggles scene light in the given
                      sceneLight(FormObject graphics)
                                                           graphics object.
selectAll             selectAll(String graphics)           Sets the selection to all entities in
                      selectAll(FormObject graphics)
                                                           the given graphics object.
transparency          transparency(String graphicsName)    Toggles transparency in the given
                      transparency(FormObject graphics)
                                                           graphics object.
zoomExtents           zoomExtents(String graphicsName)     Makes the entire model visible
                      zoomExtents(FormObject graphics)
                                                           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.
Debu g Methods
The debug method is used to display variable contents in the Debug Log window.
  E XAMPLE C ODE
  The code below prints strings and doubles to the Debug Log window.
  128 |
         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]);
    The methods for external C libraries are used for linking Application Builder
    methods with compiled C-code.
E XTERNAL M ETHOD
                                                                                       | 129
NAME               SYNTAX                                 DESCRIPTION
invokeWideString   long invokeWideString(String method,   Invokes the named native
                   Object... arguments)
                                                          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.
    130 |
       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.
                                                                                       | 131
NAME                     SYNTAX                                DESCRIPTION
resetProgress            resetProgress()                       Removes all progress levels
                                                               and resets progress to 0 and
                                                               the message to an empty
                                                               string.
showIndeterminateProgr   showIndeterminateProgress(String      Shows a progress dialog box
ess                      message)
                                                               with an indeterminate progress
                                                               bar, given message and a cancel
                                                               button.
showIndeterminateProgr   showIndeterminateProgress(String      Shows a progress dialog box
ess                      message, boolean cancelButton)
                                                               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,   Shows a progress dialog box
                         boolean addSecondLevel)
                                                               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,   Shows a progress dialog box
                         boolean addSecondLevel, boolean
                         cancelButton)
                                                               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.
       132 |
NAME                    SYNTAX                                   DESCRIPTION
startProgress           startProgress(String name)               Resets the value of the given
                        startProgress(FormObject progressBar)
                                                                 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          Sets the value of the given
                        workDone, String message)
                        setProgressBar(FormObject progressBar,
                                                                 progress bar form object name
                        int workDone, String message)            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          Same as above, but does not
                        workDone)
                        setProgressBar(FormObject progressBar,
                                                                 update the progress message.
                        int workDone)
       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. */
                                                                                   | 133
  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
// do some work
  <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();
134 |
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");
                                                                             | 135
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.
136 |
    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.
                                                                                  | 137
NAME                 SYNTAX                                    DESCRIPTION
getExpectedComputa   model.setExpectedComputationTime(String   Returns a string describing
tionTime             format)
                                                               the approximate
                                                               computation time of the
                                                               application. The string can be
                                                               altered by the method
                                                               setExpectedComputationTi
                                                               me.
setLastComputation   model.setLastComputationTime(long time)   Set the last computation
Time
                                                               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   String model.getLastComputationTime       Returns the last computation
Time                 (String format)
                                                               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").
    138 |
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
Sleep
The code below makes the application idle for 1000 ms.
  long delay = 1000;
  sleep(delay);
                                                                            | 139
    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.
    140 |
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              Converts the given double to a
           digits,boolean remove)
                                                          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.
                                                                                   | 141
 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.
       142 |
NAME           SYNTAX                                          DESCRIPTION
getSubMatrix   int[][] getSubMatrix(int[][] matrix, int        Returns a rectangular submatrix
               startCol, int endCol, int startRow, int
               endRow)
                                                               of the input matrix spanning
                                                               columns from startCol to
                                                               endCol, and rows from startRow
                                                               to endRow.
getSubMatrix   boolean[][] getSubMatrix(boolean[][] matrix,    Returns a rectangular submatrix
               int startCol, int endCol, int startRow, int
               endRow)
                                                               of the input matrix spanning
                                                               columns from startCol to
                                                               endCol, and rows from startRow
                                                               to endRow.
insert         String[] insert(String[] array, String value,   Inserts an element at position
               int index)
                                                               index in an array and returns the
                                                               expanded array.
insert         double[] insert(double[] array, double value,   Inserts an element at position
               int index)
                                                               index in an array and returns the
                                                               expanded array.
insert         int[] insert(int[] array, int value, int        Inserts an element at position
               index)
                                                               index in an array and returns the
                                                               expanded array.
insert         boolean[] insert(boolean[] array, boolean       Inserts an element at position
               value, int index)
                                                               index in an array and returns the
                                                               expanded array.
insert         String[] insert(String[] array, String[]        Inserts elements in an array at
               value, int[] index)
                                                               positions given by the index array
                                                               and returns the expanded array.
insert         double[] insert(double[] array, double[]        Inserts elements in an array at
               value, int[] index)
                                                               positions given by the index array
                                                               and returns the expanded array.
insert         int[] insert(int[] array, int[] value, int[]    Inserts elements in an array at
               index)
                                                               positions given by the index array
                                                               and returns the expanded array.
insert         boolean[] insert(boolean[] array, boolean[]     Inserts elements in an array at
               value, int[] index)
                                                               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.
                                                                                   | 143
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      Adds an element to the end of an
               value)
                                                              array and returns the expanded
                                                              array.
append         String[] append(String[] array, String[]       Adds elements to the end of an
               value)
                                                              array and returns the expanded
                                                              array.
append         double[] append(double[] array, double[]       Adds elements to the end of an
               value)
                                                              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[]    Adds elements to the end of an
               value)
                                                              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[]        Removes elements from an array
               index)
                                                              and returns the shortened array.
       144 |
NAME         SYNTAX                                       DESCRIPTION
insertRow    String[][] insertRow(String[][] matrix,      Inserts a row into a rectangular
             String[] value, int rowIndex)
                                                          2D array and returns the
                                                          expanded array.
insertRow    double[][] insertRow(double[][] matrix,      Inserts a row into a rectangular
             double[] value, int rowIndex)
                                                          2D array and returns the
                                                          expanded array.
insertRow    int[][] insertRow(int[][] matrix, int[]      Inserts a row into a rectangular
             value, int rowIndex)
                                                          2D array and returns the
                                                          expanded array.
insertRow    boolean[][] insertRow(boolean[][] matrix,    Inserts a row into a rectangular
             boolean[] value, int rowIndex)
                                                          2D array and returns the
                                                          expanded array.
insertRow    String[][] insertRow(String[][] matrix,      Adds rows to a rectangular 2D
             String[][] value, int[] rowIndex)
                                                          array and returns the expanded
                                                          array.
insertRow    double[][] insertRow(double[][] matrix,      Adds rows to a rectangular 2D
             double[][] value, int[] rowIndex)
                                                          array and returns the expanded
                                                          array.
insertRow    int[][] insertRow(int[][] matrix, int[][]    Adds rows to a rectangular 2D
             value, int[] rowIndex)
                                                          array and returns the expanded
                                                          array.
insertRow    boolean[][] insertRow(boolean[][] matrix,    Adds rows to a rectangular 2D
             boolean[][] value, int[] rowIndex)
                                                          array and returns the expanded
                                                          array.
replaceRow   String[][] replaceRow(String[][] matrix,     Replaces a row in a rectangular
             String[] value, int rowIndex)
                                                          2D array and returns the array.
replaceRow   double[][] replaceRow(double[][] matrix,     Replaces a row in a rectangular
             double[] value, int rowIndex)
                                                          2D array and returns the array.
replaceRow   int[][] replaceRow(int[][] matrix, int[]     Replaces a row in a rectangular
             value, int rowIndex)
                                                          2D array and returns the array.
replaceRow   boolean[][] replaceRow(boolean[][] matrix,   Replaces a row in a rectangular
             boolean[] value, int rowIndex)
                                                          2D array and returns the array.
replaceRow   String[][] replaceRow(String[][] matrix,     Replaces rows in a rectangular
             String[][] value, int[] rowIndex)
                                                          2D array and returns the array.
replaceRow   double[][] replaceRow(double[][] matrix,     Replaces rows in a rectangular
             double[][] value, int[] rowIndex)
                                                          2D array and returns the array.
replaceRow   int[][] replaceRow(int[][] matrix, int[][]   Replaces rows in a rectangular
             value, int[] rowIndex)
                                                          2D array and returns the array.
                                                                              | 145
NAME           SYNTAX                                          DESCRIPTION
replaceRow     boolean[][] replaceRow(boolean[][] matrix,      Replaces rows in a rectangular
               boolean[][] value, int[] rowIndex)
                                                               2D array and returns the array.
appendRow      String[][] appendRow(String[][] matrix,         Adds a row to the end of a
               String[] value)
                                                               rectangular 2D array and returns
                                                               the expanded array.
appendRow      double[][] appendRow(double[][] matrix,         Adds a row to the end of a
               double[] value)
                                                               rectangular 2D array and returns
                                                               the expanded array.
appendRow      int[][] appendRow(int[][] matrix, int[]         Adds a row to the end of a
               value)
                                                               rectangular 2D array and returns
                                                               the expanded array.
appendRow      boolean[][] appendRow(boolean[][] matrix,       Adds a row to the end of a
               boolean[] value)
                                                               rectangular 2D array and returns
                                                               the expanded array.
appendRow      String[][] appendRow(String[][] matrix,         Adds rows to the end of a
               String[][] value)
                                                               rectangular 2D array and returns
                                                               the expanded array.
appendRow      double[][] appendRow(double[][] matrix,         Adds rows to the end of a
               double[][] value)
                                                               rectangular 2D array and returns
                                                               the expanded array.
appendRow      int[][] appendRow(int[][] matrix, int[][]       Adds rows to the end of a
               value)
                                                               rectangular 2D array and returns
                                                               the expanded array.
appendRow      boolean[][] appendRow(boolean[][] matrix,       Adds rows to the end of a
               boolean[][] value)
                                                               rectangular 2D array and returns
                                                               the expanded array.
removeRow      String[][] removeRow(String[][] matrix, int     Removes a row from a 2D array
               rowIndex)
                                                               and returns the smaller array.
removeRow      double[][] removeRow(double[][] matrix, int     Removes a row from a 2D array
               rowIndex)
                                                               and returns the smaller array.
removeRow      int[][] removeRow(int[][] matrix, int           Removes a row from a 2D array
               rowIndex)
                                                               and returns the smaller array.
removeRow      boolean[][] removeRow(boolean[][] matrix, int   Removes a row from a 2D array
               rowIndex)
                                                               and returns the smaller array.
removeRow      String[][] removeRow(String[][] matrix, int[]   Removes rows from a 2D array
               rowIndex)
                                                               and returns the reduced array.
removeRow      double[][] removeRow(double[][] matrix, int[]   Removes rows from a 2D array
               rowIndex)
                                                               and returns the reduced array.
       146 |
NAME            SYNTAX                                         DESCRIPTION
removeRow       int[][] removeRow(int[][] matrix, int[]        Removes rows from a 2D array
                rowIndex)
                                                               and returns the reduced array.
removeRow       boolean[][] removeRow(boolean[][] matrix,      Removes rows from a 2D array
                int[] rowIndex)
                                                               and returns the reduced array.
insertColumn    String[][] insertColumn(String[][] matrix,     Adds a column into a rectangular
                String[] value, int columnIndex)
                                                               2D array and returns the
                                                               expanded array.
insertColumn    double[][] insertColumn(double[][] matrix,     Adds a column into a rectangular
                double[] value, int columnIndex)
                                                               2D array and returns the
                                                               expanded array.
insertColumn    int[][] insertColumn(int[][] matrix, int[]     Adds a column into a rectangular
                value, int columnIndex)
                                                               2D array and returns the
                                                               expanded array.
insertColumn    boolean[][] insertColumn(boolean[][] matrix,   Adds a column into a rectangular
                boolean[] value, int columnIndex)
                                                               2D array and returns the
                                                               expanded array.
insertColumn    String[][] insertColumn(String[][] matrix,     Adds columns to a rectangular
                String[][] value, int[] columnIndex)
                                                               2D array and returns the
                                                               expanded array.
insertColumn    double[][] insertColumn(double[][] matrix,     Adds columns to a rectangular
                double[][] value, int[] columnIndex)
                                                               2D array and returns the
                                                               expanded array.
insertColumn    int[][] insertColumn(int[][] matrix, int[][]   Adds columns to a rectangular
                value, int[] columnIndex)
                                                               2D array and returns the
                                                               expanded array.
insertColumn    boolean[][] insertColumn(boolean[][] matrix,   Adds columns to a rectangular
                boolean[][] value, int[] columnIndex)
                                                               2D array and returns the
                                                               expanded array.
replaceColumn   String[][] replaceColumn(String[][] matrix,    Replaces a column in a
                String[] value, int columnIndex)
                                                               rectangular 2D array and returns
                                                               the array.
replaceColumn   double[][] replaceColumn(double[][] matrix,    Replaces a column in a
                double[] value, int columnIndex)
                                                               rectangular 2D array and returns
                                                               the array.
replaceColumn   int[][] replaceColumn(int[][] matrix, int[]    Replaces a column in a
                value, int columnIndex)
                                                               rectangular 2D array and returns
                                                               the array.
                                                                                  | 147
NAME            SYNTAX                                          DESCRIPTION
replaceColumn   boolean[][] replaceColumn(boolean[][] matrix,   Replaces a column in a
                boolean[] value, int columnIndex)
                                                                rectangular 2D array and returns
                                                                the array.
replaceColumn   String[][] replaceColumn(String[][] matrix,     Replaces columns in a rectangular
                String[][] value, int[] columnIndex)
                                                                2D array and returns the array.
replaceColumn   double[][] replaceColumn(double[][] matrix,     Replaces columns in a rectangular
                double[][] value, int[] columnIndex)
                                                                2D array and returns the array.
replaceColumn   int[][] replaceColumn(int[][] matrix, int[][]   Replaces columns in a rectangular
                value, int[] columnIndex)
                                                                2D array and returns the array.
replaceColumn   boolean[][] replaceColumn(boolean[][] matrix,   Replaces columns in a rectangular
                boolean[][] value, int[] columnIndex)
                                                                2D array and returns the array.
appendColumn    String[][] appendColumn(String[][] matrix,      Adds a column at the end of a
                String[] value)
                                                                rectangular 2D array and returns
                                                                the expanded array.
appendColumn    double[][] appendColumn(double[][] matrix,      Adds a column at the end of a
                double[] value)
                                                                rectangular 2D array and returns
                                                                the expanded array.
appendColumn    int[][] appendColumn(int[][] matrix, int[]      Adds a column at the end of a
                value)
                                                                rectangular 2D array and returns
                                                                the expanded array.
appendColumn    boolean[][] appendColumn(boolean[][] matrix,    Adds a column at the end of a
                boolean[] value)
                                                                rectangular 2D array and returns
                                                                the expanded array.
appendColumn    String[][] appendColumn(String[][] matrix,      Adds columns to the end of a
                String[][] value)
                                                                rectangular 2D array and returns
                                                                the expanded array.
appendColumn    double[][] appendColumn(double[][] matrix,      Adds columns to the end of a
                double[][] value)
                                                                rectangular 2D array and returns
                                                                the expanded array.
appendColumn    int[][] appendColumn(int[][] matrix, int[][]    Adds columns to the end of a
                value)
                                                                rectangular 2D array and returns
                                                                the expanded array.
appendColumn    boolean[][] appendColumn(boolean[][] matrix,    Adds columns to the end of a
                boolean[][] value)
                                                                rectangular 2D array and returns
                                                                the expanded array.
removeColumn    String[][] removeColumn(String[][] matrix,      Removes a column from a
                int columnIndex)
                                                                rectangular 2D array and returns
                                                                the smaller array.
       148 |
NAME           SYNTAX                                         DESCRIPTION
removeColumn   double[][] removeColumn(double[][] matrix,     Removes a column from a
               int columnIndex)
                                                              rectangular 2D array and returns
                                                              the smaller array.
removeColumn   int[][] removeColumn(int[][] matrix, int       Removes a column from a
               columnIndex)
                                                              rectangular 2D array and returns
                                                              the smaller array.
removeColumn   boolean[][] removeColumn(boolean[][] matrix,   Removes a column from a
               int columnIndex)
                                                              rectangular 2D array and returns
                                                              the smaller array.
removeColumn   String[][] removeColumn(String[][] matrix,     Removes columns from a
               int[] columnIndex)
                                                              rectangular 2D array and returns
                                                              the reduced array.
removeColumn   double[][] removeColumn(double[][] matrix,     Removes columns from a
               int[] columnIndex)
                                                              rectangular 2D array and returns
                                                              the reduced array.
removeColumn   int[][] removeColumn(int[][] matrix, int[]     Removes columns from a
               columnIndex)
                                                              rectangular 2D array and returns
                                                              the reduced array.
removeColumn   boolean[][] removeColumn(boolean[][] matrix,   Removes columns from a
               int[] columnIndex)
                                                              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.
                                                                                  | 149
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.
        150 |
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    Returns a substring with the given
               length)
                                                              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.
                                                                                      | 151
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[][]     Returns true if all strings in the
               matr2)
                                                               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   Compares whether the relative
               relErrorTolerance)
                                                               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[]         Compares the relative errors ( ~
               dbls2, double relErrorTolerance)
                                                               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[]         Same as above, but uses a default
               dbls2)
                                                               relErrorTolerance of 0.0001.
       152 |
NAME     SYNTAX                                        DESCRIPTION
equals   boolean equals(double[][] dbls1, double[][]   Compares the relative errors ( ~
         dbls2, double relErrorTolerance)
                                                       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[][]   Same as above, but uses a default
         dbls2)
                                                       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.
                                                                              | 153
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.
    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.
    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
    154 |
category returns null. Also, null is returned if no entity of the corresponding
type exists such that nothing is current.
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\COMSOL60\Multiphysics\addins
                                                                          | 155
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.
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.
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.
156 |
  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.
                                                                            | 157
Visualization of Points, Curves, and Surfaces
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
Comments
The first line
  String pgTag = model.result().uniquetag("pg");
158 |
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.
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
                                                                             | 159
  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);
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
160 |
    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 158.
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
                                                                             | 161
  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
162 |
      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 161, 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];
                                                                            | 163
  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.
164 |
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).
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
                                                                             | 165
    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
Comments
In this example, in addition to the example in the section “Arrows in 2D”, color
data is used based on the point index.
166 |
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
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.
  pg.run();
  selectNode(pg);
                                                                              | 167
Comments
The Boolean property latexmarkup determines if the text should be interpreted
using LaTeX syntax or not.
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 101.
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 127. 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.
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 182, 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
168 |
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.
                                                                            | 169
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.
170 |
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");
                                                                                 | 171
       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.
172 |
You can download the MPH-file for this app from:
https://www.comsol.com/model/using-text-files-to-automate-model-preprocessing-46721
                                                                                  | 173
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
extension. The file extension is retrieved with the Java® method endsWith(),
174 |
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.
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");
                                                                             | 175
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);
176 |
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);
  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.
                                                                             | 177
  String p[][] = readStringMatrixFromFile("upload:///file1");
  double pt[][] = transpose(toDouble(p));
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.
178 |
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.
                                                                              | 179
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 182,
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 150 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
180 |
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;
    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.
                                                                             | 181
    +"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");
and the corresponding code is listed below (compare with the example “Reading
a Text File to a String” on page 179).
  int n_of_points = 0;
  int n_of_properties = 0;
182 |
  int max_header_length = 100;
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 181.
                                                                               | 183
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:
184 |
  -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");
writer.append(header);
                                                                                | 185
    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.
186 |
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.
                                                                         | 187
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);
    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");
188 |
  int N = 1000; // The number of points
uses the imported ByteBuffer method to convert the integer N to a byte array
bytes4 of length 4.
The line
  bwriter.write(bytes4);
close the byte stream and display a file browser to the user to select a location to
save the binary file.
  breader.read(bytes4);
  int N = java.nio.ByteBuffer.wrap(bytes4).getInt();
    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();
                                                                             | 189
  double pt[][] = transpose(p);
  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();
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();
190 |
Converting Interpolation Curve Data
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;
                                                                           | 191
  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.");
    }
  }
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");
192 |
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
                                                                           | 193
  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");
194 |
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
                                                                            | 195
finally subtracts the cylinders from the plate. The resulting geometry is shown in
the figure below.
196 |
double scale = Math.max(Math.max(MaxX-MinX, MaxY-MinY), MaxZ-MinZ);
double scaleSelTol = scale*selTol;
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;
                                                                           | 197
      if (Math.abs(radius[i]-ry) > tol)
        error("Object is not a circular cylinder.");
  }
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.
198 |
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
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");
                                                                                   | 199
  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.
200 |
                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;
                                                                                | 201
  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);
          }
        }
      }
    }
  }
202 |
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.
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:
                                                                           | 203
  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");
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.
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.
204 |
// Note that this method is only implemented for one component and one geometry
and does not work for all physics combinations.
int sdim = 0;
if (coordsize[0] == 3) {
  sdim = 3;
} else if (coordsize[0] == 2) {
  sdim = 2;
} else
  error("The geometry of the first component is not 2D or 3D.");
with(model.result(nodes).feature("mesh"));
  set("elemcolor", "none");
                                                                          | 205
    set("wireframecolor", "gray");
    set("elemscale", 0.999);
  endwith();
  with(model.result(nodes));
    set("edges", true);
    set("data", mesh);
  endwith();
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();
  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 159.
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.
206 |
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
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)
                                                                            | 207
 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.
 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 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");
model.sol("sol2").attach("std2");
208 |
// Define which system matrices should be input.
solft.set("L", "on");
solft.set("K", "on");
solft.set("M", "on");
solft.set("N", "on");
// 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");
                                                                        | 209
  // K
  solft.createSparseMatrix("K", KM, KN, KNnz, true);
  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);
Comments
In the previous example, “Accessing Higher-Order Finite Element Nodes” on
page 204, 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.
210 |
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 can not 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.
                                                                               | 211
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.
212 |
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>)
                                                                              | 213
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.
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.
214 |
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
                                                                           | 215
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>)
216 |
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.
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.
                                                                             | 217
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:
218 |
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.
                                                                         | 219
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
220 |
method run for the On data change event for the input field with label Number x
(1-10).
                                                                         | 221
The OK button calls method1 for the On data Change event, as shown in the figures
below.
222 |
  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";
  }
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
                                                                           | 223
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:
224 |
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:
                                                                          | 225
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.
226 |
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.
                                                                         | 227
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);
228 |
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
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.
                                                                              | 229
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.
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/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
230 |
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.
  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
                                                                            | 231
SimpleDateFormat. This method has one string input argument, timoutDate,
and one Boolean output argument, ok, as shown below.
232 |
            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.
Note that you can provide a list of MAC addresses to allow use on a computer with
multiple network cards or multiple computers.
                                                                             | 233
      exit();
  }
  if (!check_date(trial_date)) {
    alert("The trial for this application has expired "+trial_date, "COMSOL");
    exit();
  }
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.
234 |
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.
                                                                          | 235
236 |
Index
129 button
B backslash 12 object 88
backspace 12 classes
                                                                                | 237
        color 60                                 old value 213
          of user interface component 59       dataset 48, 157
        combo box object 68                    DataSource object 213
        Compact History 53                     date and time methods 137
        Compile Equations node 45              debug
        computation time 139                     methods 128
          last 138                             Debug Log window 128
        Compute 46                             declaration 211
        COMSOL Desktop 51                        type 54
        COMSOL Help Desk 53                    Declarations 12, 14, 56
        COMSOL Multiphysics 7, 26              deformation plot 34
        COMSOL Multiphysics Programming        degrees of freedom 204
            Reference Manual 204               Dependent Variables node 45
        confirm 11, 116, 123                   description 18
        contour plot 48                          parameter 18, 35
        contour plot data 185                    variable 18
        control flow statements 16             Developer tab 156
        conversion                             Dialog Actions 215
          between data types 9                 dialog box 115, 116
          methods 140                            data validation 214, 217
        coordinate information 195, 196        diffusion coefficient
        Copy as Code to Clipboard 30             anisotropic 34
        creating                               dimension
          feature node 38, 42                    spatial 29
          model object 28, 51                  disable form object 59, 64, 65, 120
        CSV-file 168, 175                      Display Name
        curve                                    for choice list 120
          interpolation 184                    double 9
          parameterization 191                   data type 8, 29
        cut point                                variable conversion 140
          dataset 34, 97                       double quotation mark 11
238 |
    email                                          writing to 168
       class 111                                 File Declaration 171
       methods 111                               file import 171
       preferences 113                           file import object 70
    email attachment                             file open
       export 111                                  system method 108
       report 111                                file scheme
       table 111                                   syntax 101, 171
    embedded model 51                            Filter 211
    enable form object 57, 59, 64, 65, 120       finite element
    endian 190                                     accessing 204
    equation                                       system matrix 206
       object 70                                   vector 206
    error dialog box 18                          floating point number 8
    Error message 212                            for loop 17, 65, 95
    eval 212                                     form
    events 92, 214                                 class 58, 63
    example code 96, 156                           declarations 15
    Excel® file 50, 105, 168, 173, 176             list methods 94
    exception                                    form collection 71
       handling 18                               form feed 12
    exit 127                                     form method 24
       application 128                           form object 70
    expiration date for application 230            class 58, 64
    explicit selection 223                         list methods 94
    export                                         types 66
       email attachment 111                      Fully Coupled node 46
    external C libraries 129
                                             G   general properties 59
    external Java® library 229
                                                 generating code 19
F   face                                         Geometry node 38
       parameterization 193                      geometry object 38, 39
    feature node                                   names 196
       creating 38, 42                           get 29, 30
       removing 39, 42                           global method 24
    file                                         global parameter 35
       methods 101                               graphics
       name 105                                    object 72, 115
       open 108                                    view 121, 124
       reading 168                               grid dataset 156
                                                                           | 239
        GUI command                                      toolbar 87
          methods 127                                  iterative solver 45
        GUI related methods 115                        Iterator class and method 42
240 |
main application class 57, 61                 turning off 159
main user interface component classes       Model Java-file 52
    58                                      Model M-file 52
Main Window                                 model object 7, 26, 42, 55, 96
  class 58, 62                                class structure 53
  node 58                                     tag 26
material                                    model tree 26
  link 34                                     node 41, 42
  tag 91                                    model utility methods 52, 96
Materials node 42                           Model Wizard 29, 51
math functions 15                           models, working with multiple 51
maximum value 49                            MPH file 51, 96, 127
menu                                        multiphysics 50
  item 87                                   Multiphysics node 50
mesh                                        multiple models 51
  information and statistics 203
                                        N   name
mesh element size 33, 39
                                              form 55, 57
Mesh node 39
                                              form object 55, 57
message log object 78, 118
                                              in application object 57
message method 123
                                              method 25
method 7, 96
                                              scoping 27
  form 24
                                              shortcut 14, 55
  get 30
                                              user interface component 55, 57
  global 24
                                            network card 230
  local 24
                                            new value
  name 25
                                              data validation 93, 213
Method class 94
                                            newline 11, 12
Method Editor 96
                                            node
  using 7, 19
                                              finite element 204
method name 25
                                            nonlinear solver 46
Microsoft® Word® format 124
                                            normal
model 51
                                              surface 163, 164
  loading 51, 97
                                            numerical
  saving 51, 97
                                              Derived Values 49
Model Builder 26
                                            Numerical validation 211
model component 29
                                        O   old value
model data access 23
                                              data validation 93, 213
model history 52, 159
                                            On data change event 93, 212
  recording 53
                                                                             | 241
        operating system                         Programming Reference Manual 26, 47,
          methods 108                                96, 97, 199, 204
        operators 37                             progress 131
          Java 9                                   dialog box 132, 136
          model object 37                          methods 131
        OS commands 108                          progress bar object 78, 133, 135, 136
                                                 properties
    P   parameter 18, 34, 35, 49
                                                   general 59
          method 17, 24
                                                 property and property values 29
          real and imaginary part 36
        parameterization                     R   radio button object 79
          edge 191                               ragged arrays 12, 32
          face 193                               reading
        parameterized solution 49                  binary file 189
        parsing                                    CSV-file 169
          text file 182                            Excel® file 173
        physics interface 41, 44                   file 168
        play sound 109                             matrix file 177
        plot                                       Microsoft Excel® Workbook file 173
          group 34, 123                            spreadsheet 169
          mesh element nodes 97                    text file 182
          point trajectories 97                    text file to string 179
          surface 37, 48                         real and imaginary part
          table surface 50                         of parameter 36
          useGraphics 115                        Record Code 21, 46
        Plot Group node 48                       recursion 199
        plot type                                recursive loop 199
          Annotation Data 167                    removing
          Arrow Data 165, 166                      feature node 39, 42
          Line Data 160                          report 113
          Point Data 158, 159, 206                 email attachment 111
          Surface Data 161, 162, 163               HTML 123
          Tube Data 165                            Microsoft® Word® format 124
        Point Data plot type 158, 159, 206       request 117, 123
        point trajectories plot 97               reset
        precedence, of operators 9, 37             model history 52
        primitive data types 8                   Results node 48
        printing                                 results table object 79, 120
          graphics 127                           RGB color 60
        programming examples 96, 156             ribbon item 87
242 |
S   save application 128                Stationary Solver node 45
    save as 127                         Stationary study step 44
    saving                              status bar 131
      model 51, 97                      Store changes, in dialog box 214
    scalar                              stream
      object 88                           character 183
    scene light 128                     String
    sectionwise                           data type 10, 29
      format 184, 187                     methods 150
    sectionwise format 184              string variable 49
    selection                             conversion 141
      explicit 223                        methods 150
    selection input                     strings
      object 80, 223                      comparing 11
    selections 196                        concatenating 10
      add-in 223                        Study node 44
    set 29                              subform object 70
    setIndex 29                         surface
    shortcuts 14, 55                      parameterization 193
    Shortcuts node 14                   Surface Data plot type 161, 162, 163
    single quotation mark 11            surface normal 163, 164
    sleep 139                           surface plot 37, 48
    slider object 81                    system matrix
    SMTP 113                              accessing 207
    solution                            system methods 108
      data 156                            OS commands 108
      data structure 45                 system vector 207
      parameterized 49
                                    T   tab 12
    Solution node 45
                                        table 50
    Solver Configurations node 44
                                          email attachment 111
    solver sequence 44
                                          object 84, 119
    spacer object 83
                                        Table node 49
    spatial dimension 29
                                        table surface plot 50
    special character 11
                                        tag 57
      Java 52
                                          model object 26
    special characters 182
                                          physics interface 41
    sphere 156
                                        temporary folder
    spreadsheet 169
                                          location 176
      format 102, 177, 178, 184
                                        text file 168
                                                                     | 243
          reading 182                      while loop 17
          writing 182                      with statement 17
        text label object 85               writing
        text object 84                       CSV-file 175
        time 137                             Excel file 176
        time-limited application 230         matrix file 178
        title 116                            string to text file 181
        toggle button object 85              text file 182
        toolbar                              to binary file 188
          item 87                            to file 168, 176
          object 86
                                       Z   zoom extents 123, 128
        Tooltip 212
        transparency 125, 128
        transparent
          color 60
        try and catch 18
        Tube Data plot type 165
        type declaration 54
    U   unit 36
          object 86
        Unit List 58
        unit set
          methods 90
          object 88
        unit sphere 156
        Unit System 35
        Upper bound 211
        username 108
244 |