Java utility classes
IdentifierManager
In working with highly customized COMSOL FEMs, we found it convenient to
abstract away from the underlying COMSOL indexing to improve code
readability and enable scalability as models increase in geometric
complexity. We developed a class named IdentifierManager
that allows the
user to assign their own String to identify a COMSOL geometry feature
tag (e.g., wp<#>
, cyl<#>
, rev<#>
, dif<#>
) or selection
(i.e., csel<#>
).
We use IdentifierManagers
to name and keep track of identifier labels
within a PartPrimitive
. IdentifierManagers
assigning tags for products
of individual operations to a unique “pseudonym” in
HashMaps
as
a key-value pair. Additionally, we assign resulting selections
(“csel<#>”
) to meaningful unique pseudonyms to later assign to
meshes, materials, or boundary conditions.
We keep a running total for tags of IdentifierStates
(i.e., the total
number of uses of an individual COMSOL tag) and HashMap
of
IdentifierPseudonyms
(i.e., a HashMap
containing key (pseudonym) and
value (COMSOL tag, e.g., “wp1”)).
IdentifierManager
has a method next()
which takes inputs of a COMSOL tag
(e.g., wp
, cyl
, rev
, dif
) or selection (i.e., csel
) without its index
and a user’s unique pseudonym String. The method appends the next index
(starting at 1) to the COMSOL tag or selection and puts the COMSOL tag
or selection and associated pseudonym in the IdentifierPseudonyms
HashMap
. The method also updates the IdentifierStates
HashMap
total for
the additional instance of a COMSOL tag or selection.
To later reference a COMSOL tag or selection, IdentifierManager
has a
get()
method which takes the input of the previously assigned pseudonym
key and returns the COMSOL tag or selection value from the
IdentifierPseudonyms
HashMap
.
To accommodate mesh recycling (see ModelSearcher
below), we save a
COMSOL model’s IdentifierManagers
to later access selections for
updating model materials and physics. Therefore, we developed
IdentifierManager
methods toJSONObject()
and fromJSONObject()
which
saves an IdentifierManager
to a JSON file and loads an IdentifierManager
into Java from a JSON Object, respectively.
JSONio
JSONio
is a convenient Java class used for reading and writing JSON
Objects to file. The read()
method takes an input String containing the
file path to read and returns a JSON Object to memory. The write()
method takes an input String containing the file path for the saving
destination and a JSON Object containing the data to write to file.
ModelSearcher
The ModelSearcher
class in Java is used to look for previously created
FEM meshed geometries that can be repurposed. For example, if
Model configurations differ only in their material properties or
boundary conditions and the previous Model’s *.mph file with the
mesh (i.e., mesh.mph
) was saved, then it is redundant to build and mesh
the same model geometry for a new Model configuration. The methods
of the ModelSearcher
class can save enormous amounts of computation time
in parameter sweeps of Model if the mesh can be recycled. The user
is unlikely to interface directly with this method as it operates behind
the scenes, but if the user adds new parameter values to Model,
then the user must also add those values to
config/templates/mesh_dependent_model.json
to indicate whether the
added parameter value needs to match between FEMs to recycle the mesh
(explained further below). Generally, changes in geometry or meshing
parameters need to match, but changes in material properties or boundary
conditions do not, since they do not change the FEM geometry.
Specifically, this class compares Model configurations to
determine if their parameters are compatible to repurpose the geometry
and mesh from a previously generated COMSOL model using the meshMatch()
method. The meshMatch()
method takes the inputs of a reference JSON
(i.e., config/templates/mesh_dependent_model.json
, see S7 and S8 Text) containing
conditions for compatibility and a JSON Object for each of two
Model configurations to compare. The parameter keys correspond
one-to-one in Model and mesh_dependent_model.json
. However, in
mesh_dependent_model.json
, rather than numerical or categorical values
for each parameter key, the keys’ values are a Boolean indicating if the
values between two Model configurations must be identical to
define a “mesh match”. For two Model configurations to be a match,
all parameters assigned with the Boolean true in
mesh_dependent_model.json
must be identical. Model
configurations that differ only in values for parameters that are
assigned the Boolean false are considered a mesh match and do not
require that the geometry be re-meshed.
In the class’s searchMeshMatch()
method, the program looks through all
Model configurations under a given Sample and applies the
meshMatch()
method. If a Model match is found, searchMeshMatch
returns a Match class, which is analogous to the ModelWrapper
class,
using the path of the matching Model with the fromMeshPath()
method.