ElmerSolver GSSF Component

ElmerSolver is the simulation tool within the Elmer suite. This GSSF component prepares configuration for it based on the GSSF-XML input, runs it and monitors it for percentage progress.

Elmer SIF template

The Elmer SIF provides the configuration of the solver. It is generated from a Jinja2 template, which is supplied in the GSSF-XML. Parameter dictionaries provide access to the global GSSF parameter list from the template - see Constants (Parameters) for more detail.

In addition to the global parameter dictionary, p, and the dictionary of needle parameter dictionaries needles, there is a counter dictionary, c. It may used in a similar fashion to the parameter dictionaries, by member syntax. If a member c.BODY, say, has not been used before, its first usage will return 1. The second will return 2 and so forth. Prefixing the member with an underscore, c._BODY will return the current index without incrementing.

Note that, while the GSSA simulation server scrubs SIF files, GSSF itself does not. As such, if running GSSF separately you should only accept SIF templates from trusted sources, Specifically, several MATC functions provide access to the filesystem or printf, so precautions should be taken.

Algorithms in MATC will be written to a file with a unique ID. A line sourcing it will be added at the end of the SIF, and the constant representing the result, will be substituted with a call to it. For instance, Electric conductivity = {{ p.ELECTRIC_CONDUCTIVITY }}, when with an algorithm with result ELECTRIC_CONDUCTIVITY based on Argument Temperature is provided, would become:

Electric conductivity = Variable Temperature
    Real MATC "ELECTRIC_CONDUCTIVITY(tx(0))"

The following filters are available, in addition to basic Jinja2 sandbox filters:

Filter name Apply to Purpose Parameters
typed Parameter render parameter with SIF type prefix -
totyped any Parameter-wrappable value render value with SIF type prefix based on type d d (desired type)
discretize number round to nearest r (returns int if r >= 1) r (granularity)

The following global functions are available, in addition to basic Jinja2 sandbox globals:

Function Arguments Description
zip as usu. Python built-in
list as usu. Python built-in
map as usu. Python built-in
str as usu. Python built-in
needle_distance needle1id,
needle2id,
(opt) d,
(opt) ref
returns the perpendicular distance between needle1 and needle2, optionally starting from d metres (or simulation scale) along shaft from tip of needle ref (needle1id or needle2id)

TIP: Elmer tends to die without reporting an error if there is a problem with a MATC function, sometimes with a segfault or an unpredictable number output. If you notice you are getting simulations failing at the solver step, it is recommended that you run ElmerSolver_mpi manually in the elmer folder to see whether this is the case. If so, removing and progressively adding in MATC functions should clarify which is causing the problem.

Status updates

The solver module starts a socket listening on percentage.sock in the simulation directory. An Elmer solver (NumaProgress) is available to connect to and update this based on the solver Percentage Progress value. By adding this solver into your SIF file and setting Percentage Progress within it, you can receive percentage updates in the main Python process.

TODO: Add in user-configurable status text, after checking for security issues that may rise.

Runtime compilation

Models can be tagged with certain library Fortran modules, which are then used in the SIF file as user-defined functions (UDFs). For security reasons, only predefined modules are available, such as mwa_RelPerm or mwa_ElecCond, which provide temperature-dependent relative permittivity and electric conductivity for microwave ablation. These modules can contain GSSF constants, which are inserted before compilation. They must be cast to numeric types only to prevent injection and it is recommended that any new modules are used only in standalone mode with trusted template input.

In general, it is recommended to avoid this method as it is harder to abstract and errors in adding modules can compromise security, at least until GSSF is reorganised for use inside the Docker workflow and sandboxing allows for user-supplied routines.

Point source location factories

For the point source models, where a series of heating points defines the input power distribution, a factory is used to simplify setting of models. The factory can output locations at various probe extensions without these needing to be pre-calculated on the client-side, or in the CDM. For this to work correctly, at least in the current version, there must only be one needle present in a simulation at a time. If needed, a workaround may be to add additional heating points for a secondary needle to the first, provided all extension lengths and times match.

Several probe location factories are contained in the GSSF codebase. These may be extended by subclassing GoSmartElmerProbeLocationFactory and adding to the dictionary, gssf.elmer_probelocation.probe_location_factories.

A number of thermocouples may be defined, which can be used to label each of the heating points. These are passed to the actual solver and, normally, used to switch points on and off according to some thermocouple-based algorithm. The remaining points are split between ends and middles, which are generally used to distribute power between two different levels by the simulation module.

The default factories are outlined below.

Manual Probe Location Factory

GoSmartElmerProbeLocationFactoryManual is selected by setting the point sources system to manual. This requires all points to be configured for GSSF-XML and assumes a single extension.

The pointsources XML block should be formatted as follows:

<pointsources system="manual">
  [(
    <ends|middles|thermocouples>
      <location x="X1" y="Y1" z="Z1" t="T1" />
      ...
    </ends|middles|thermocouples>
  |
    <ends|middles|thermocouples input="block">
        X1  Y1  Z1  T1 (tabbed)
      ...
    </ends|middles|thermocouples>
  )]*
</pointsources>

where T, an integer, is the index of the controlling thermocouple in the list of point sources.

Straight Tines Location Factory

GoSmartElmerProbeLocationFactoryStraightTines generates all point locations based only on the shaft location and (scalar) extensions. It assumes the locus from shaft tip to the end of each of the tines is linear. Note that this does not, strictly, equate to the tine itself being linear, but states that there should be a middle heating point at the mid-point of a line from the shaft tip to each end point.

The pointsources XML block should be formatted as follows:

<pointsources system="straight tines" [ offset="X Y Z" ]>
  <extensions>
    <extension phase="0" length="L1"/>
    <extension phase="1" length="L2"/>
    ...
  </extensions>
</pointsources>

The offset parameter allows the user to change the point location relative to the needle-shaft tip. The shaft location is taken from the geometry section. Ln lengths should be provided in metres. Note that the change of phase over time is usually controlled via a simulation module.

Umbrella Tines Location Factory

GoSmartElmerProbeLocationFactoryUmbrellaTines provides an arched configuration of heating points, where the end is perpendicular to the tip and the middle is at an angle beyond the tip, such that opposing tines form an M shape.

Configuration is identical to the Straight Tines Location Factory, using system="umbrella tines".

Extrapolated Tine Factory

GoSmartElmerProbeLocationFactoryExtrapolated takes the tip locations for the largest extension and scales accordingly for other extensions. Note that clinicians generally do imaging showing full extension before starting the protocol (at least, in radiofrequency ablation), so this location information is available at the beginning of the procedure.

The pointsources XML block should be formatted as follows:

<pointsources system="extrapolated" [ offset="X Y Z" ]>
  <extensions>
    <extension phase="0" length="L1"/>
    <extension phase="1" length="L2"/>
    ...
  </extensions>
  <points>
    <point i="1" x="X1" y="Y1" z="Z1"/>
    <point i="2" x="X2" y="Y2" z="Z2"/>
    ...
  </points>
</pointsources>

Configuration

The XML format for the <elmer> first-level configuration node is as follows:

<elmer [ skip="SKIP_ELMER:false" ]>
    [ <restart time="RESTART_TIME" position="RESTART_INDEX" old="PREVIOUS_SIF_PREFIX" /> ]
    [ <pointsources system="TINE_FACTORY">
        <!-- AS DEFINED ABOVE -->
      </pointsources> ]
    (
      <variant [ modules="f90module1; f90module2;..." ] name="SIF_TEMPLATE_LIBRARY_NAME" />
    |
      <variant [ modules="f90module1; f90module2;..." ] >
        ! SIF TEMPLATE
        !
        ...
      </variant>
    )
    [ <settings>
        <setting|constant name="non-slug setting name" value="CONSTANT_VALUE" type="CONSTANT_TYPE" />
        ...
      </settings> ]
    [ <algorithms>
        <algorithm>
            <arguments>
              <argument name="ARGUMENT_NAME" />
            </arguments>
            <content>
              <!-- Algorithm content - usu. MATC -->
            </content>
        </algorithm>
        ...
      </algorithms> ]
</elmer>

Note that non-slug setting name will translate to SETTING_NON_SLUG_SETTING_NAME in the SIF parameter dictionary.