Creating new part primitives
Though we provide a library of part primitives to assemble
representations of many cuff electrodes as shown in
examples/parts/sandbox.mph
, users may find it necessary to add their own
part primitives for representing their custom cuff electrode designs.
Use the following instructions as a guide and link to resources for
creating a new part primitive.
The COMSOL GUI has a “Geometry Parts” node under the “Global Definitions”. The pipeline adds part primitives—i.e., the geometry of different pieces of cuff electrodes (e.g., contacts, insulators, cuff fill (e.g., encapsulation tissue, mineral oil, saline), or medium (e.g., surrounding muscle, fat)—as “parts” under “Geometry Parts”. Their resulting volumes (domains), surfaces, and points (used for point current sources) are added to the list of “cumulative selections” which are later used to assign appropriate mesh settings, material properties, and boundary conditions.
Note
For more information on specific primitives, see ASCENT Part Primitives
1. Create and label your part. Open up examples/parts/sandbox.mph
,
secondary-click on “Geometry Parts”, choose “3D Part”. Give your part an
appropriate label as it will later be used in creating “preset” cuff
JSON files and as a flag for the primitive in our Java Part class
(src/model/Part.java
).
2. Define your part’s geometry. Secondary-click on the new part under
“Geometry Parts” to add the geometry operations required to construct
your cuff (e.g., “Block”, “Cone”, “Cylinder”, “Sphere”, “More
Primitives”, “Work Plane”). See the operations under the other part
primitives in sandbox.mph
as a guide in creating your geometry, as well
as COMSOL’s
documentation
(in particular their “Appendix A – Building a Geometry”) and
“Introductory Video Series on How to Build Geometries in
COMSOL”.
In creating your geometry, carefully label each operation to improve
readability of your geometry operations. Taking care to label the
operations will not only help to communicate to other users and your
future self what operations must occur, but also will help you in
cleaning up your Java code in the Part class (part of step 6). The
dimensions and locations of part geometries should refer to “Input
Parameters” or parameters stored in a parameters group under “Global
Definitions”.
3. Assign each feature of interest (i.e., volumes/domains, surfaces, points) to a “Cumulative selection”. The final form of domains that you will want to assign to a material property need to be assigned to a “Cumulative selection”, which can be found for the final geometry operation under the “Settings” tab. In “Settings”, under the “Contribute to” drop down menu within the “Selections of Resulting Entities” section, the first time you refer to a cumulative selection you will need to click the “New” button and type in the name of the selection. Again, take care to give an informative label. Our convention, though not required, is to make the cumulative selection names in all capitals to improve code readability.
4. Compact sandbox.mph
file history. File -> Compact History removes
any operations you may have tested but did not ultimately use to create
your part.
5. Export Java code. Go to File -> Save As, give a meaningful
path/file name, and change the file type to “Model File for Java
(*.java
)”.
6. Add the operations for your part primitive to the
Part.createCuffPartPrimitive()
method in Java (src/model/Part.java
).
With the text editor of your choice, open the newly created *.java
file. Toward the bottom of the file, the operations you just performed
in COMSOL are contained in a block of code. Performing a "Command+F"
(on
Mac) or "Control+F"
(on Windows) for your new part primitive’s name that
you gave in the GUI (from step 1) should take you to the first line of
the code block of interest, which looks like:
"model.geom("part<#>").label(<your part’s name>);
All subsequent lines starting with "model.geom("part<#>")"
are of
interest. Copy them to your clipboard. With
Part.createEnvironmentPartPrimitive()
as a guide (since it is by far the
simplest and most contained “primitive” – in reality it is just a
cylinder contributed to the “MEDIUM” cumulative selection), add your
lines to Part.createCuffPartPrimitive()
.
Add a “case” in the switch-case (e.g., case
"TubeCuff_Primitive"
). Within this case-block, all operations for the new primitive will be added.For each line in your code (copied from the exported
*.java
file) that begin with"model.geom.("part<#>").inputParam().set("<my_parameter>", "<default_value>")
, at the top of your new case-block, add the following line to set the “Input Parameters” you established in the COMSOL GUI:mp.set("<my_parameter>", "<default_value>")
Still looking at
Part.createEnvironmentPartPrimitive()
as an example, now create your list of “selections” in “im.labels” which are the lines that follow after the “Input Parameters” are defined. Then add the for loop that loops over theim.labels [String, …]
adding them to COMSOL’s selections. These lines will look like:
im.labels = new String[] {
"<MY_CUMULATIVE SELECTION_1>", // note: This is index 0
"<MY_CUMULATIVE SELECTION_2>", // note: This is index 1
…
}
for (String cselLabel : im.labels) {
model.geom(id).selection().create(im.next("csel", cselLabel),
"CumulativeSelection").label(cselLabel)
}
The lines that follow the Cumulative Selection labeling add the geometry features of the COMSOL part which COMSOL has also conveniently exported for you in the
*.java
file. See Java Utility Classes for an explanation of our JavaIdentifierManager
utility class that we created to abstract away from COMSOL’s indexing system to improve code readability. Our"IdentifierManager"
class enables the user to access previously defined selection tags by an informative label programmatically.Part.createEnvironmentPartPrimitive()
andPart.createCuffPartPrimitive()
are also great working examples of how we use the COMSOL plugin in an IDE to clean up the code (e.g., creating a COMSOL “GeomFeature” to shorten the length of each line).End the case for your new part primitive with a
"break;"
(this is very important!)
7. Add the operations for your part primitive to the
Part.createCuffPartInstance()
method (src/model/Part.java
).
Create a
List[String]
containing the “Input Parameters” you established in the COMSOL GUI. These lines will look like:
String[] myPrimitiveParameters = {
"<my_parameter1>",
"<my_parameter2>",
… // for all Input Parameters
}
Add a for loop that adds all the “Input Parameters” to the part instance. These lines will look like:
for (String param : myPrimitiveParameters) {
partInstance.setEntry("inputexpr", param, (String) itemObject.get(param));
}
Our primitives have an additional (optional) section for selection imports. Each defined selection used in your geometry operations will be visible in the “Contribute to” drop-down menu unless you toggle each selection “off”. An example of how to “clean up” your selections imported is shown below:
// imports
// so that the program only imports selections that are used
partInstance.set("selkeepnoncontr", false);
// to selectively import the DOMAIN for whatever selection index 0 is in
myLabels (defined in im.labels
in
// createCuffPartPrimitive()
). To exclude, “off” instead of “on”.
partInstance.setEntry("selkeepdom", instanceID + "_" + myIM.get(myLabels[0] + ".dom", "on"));
// to selectively import the BOUNDARY for whatever selection index 0 is
in myLabels (defined in im.labels
// in createCuffPartPrimitive()
). To exclude, “off” instead of “on”.
partInstance.setEntry("selkeepbnd", instanceID + "_" + myIM.get(myLabels[0] + ".bnd", "on"));
// to selectively import the POINT for whatever selection index 0 is in
myLabels (defined in im.labels
// in createCuffPartPrimitive()
). To exclude, “off” instead of “on”.
partInstance.setEntry("selkeeppnt", instanceID + "_" + myIM.get(myLabels[0] + ".pnt", "on"));
End the case for your new part instance with a “break;” (this is very important!)
8. (Step is optional but recommended). Add your new part to
examples/parts/sandbox.mph
. Simply save your sandbox.mph
file as a
*.mph
, if you have not already, for future ability to assemble cuffs
using your new part in the COMSOL GUI.