Note

In VSim 9, the transition to direct macros has been completed, so the previous macros are being deprecated.

The macros are organized following a well defined-methodology. The philosophical change is that rather than having only macros that write out input file snippets directly, now there are macros that instead write the snippets into “accumulation variables”. Then, at the end of the file, a call is made to finalize(), which writes out the accumulated information with the nesting needed for correct interpretation by Vorpal. A requirement for use of these version 8 macros is that the input (.pre) file must adhere to some structure, but the result is a much less constrained structure compared with the previous macros, which had to be placed in the pre-file in the location where the substitution was desired.

Here we provide an overview of these depcrecated macros. We will define direct macros to be those that directly write snippets. They can be used just as macros were used before. We define accumulation macros to be those that add snippets to accumulation variables. The latter are often effected by the former, as we shall see. The old macros will be removed in a later version.

Direct Macros Overview: Namespacing and input file structure

All global variables, e.g., the accumulation variables (to be discussed later), for the new macros start with VPM_. The standard macros are not namespaced, but may be namespaced in a future release. Also, there are variables that are namespaced starting with TXU_; for instance, variables that describe units.

With the new macros, the input file has to have a particular structure:

  • Preamble: Setting of user-defined variables and variables that determine the type of simulation, e.g., electromagnetic versus electrostatic.
  • Macro file importing.
  • The user-defined regular and space-time functions.
  • The ordered macros, i.e., grid and timing.
  • The unordered macros (for all other dynamics).
  • Finalization.

The Preamble

The preamble consists of the setting of the variables that one might want to use in the input file. For pre files generated from visual setup, the input file preamble begins with

#######################################################
#
# This PRE file,
#   emcartfull.pre,
# was generated from the simulation definition file,
#   emcartfull.sdf,
# by the sdf2vpre translator.
# Any changes to this file will be lost if the
# translator is rerun.
#
#######################################################

#######################################################
#
# Ordered blocks
#
#######################################################

#######################################################
# User defined constants and parameters
#######################################################

$ import mathphys

$ WAVELENGTH = 1.00000000000000e-01
$ WIDTH = 3*WAVELENGTH
$ DX = WAVELENGTH/16
$ QWID = 0.5*HALFWIDTH
$ EXPFAC = 0.5/(QWID^2)
$ XeMass = 131.3*PROTMASS

Of course, the comments (anything after the #) are not processed, nor are the blank lines. The user has freedom to choose the variable names provided they do not clash with the names in mathphys.mac, nor do they begin with VPM_ or TXU_, which are reserved for distinguishing variables that are defined for system use. The macro system defines various boolean variables, so the user should not define variables with names like True or FALSE. Similarly, common math functions and Python system functions are reserved and should not be used as variable names. For this reason, users should not assign variable names like cos, sqrt, open, or float.

Next follows the basic variables that define the simulation:

#######################################################
# Simulation definition from the basic settings
#######################################################

$ VPM_COORDINATE_SYSTEM = "cartesian"
# cylindrical not found.
$ VPM_NDIM = "3"
$ VPM_PRECISION = "double"
$ VPM_USE_GPU = "False"
$ VPM_SIMULATION_TYPE = "electromagnetic"
# electrostatic not found.
$ VPM_GRID_SPACING = "uniform"
$ VPM_INCLUDE_PARTICLES = "False"
# include particles.estimated max electron density not found.
# include particles.estimated min electron temperature (eV) not found.
$ VPM_TOP_LEVEL_VERBOSITY = VPM_INFO
$ VPM_GRID_TYPE = UniformCartesian

and if VPM_INCLUDE_PARTICLES is True, one must also define

$ VPM_MAX_ELECTRON_DENSITY = "1.e18"
$ VPM_MAX_ELECTRON_TEMP_EV = "1.0"

These variables are used later to calculate the time step, if one is not provided, by later macros.

Macro Importing

To obtain that standard macros, the user need import only a single file, VSim,

$ import VSim

This in turn imports all of the standard macro files needed for the simulation of type defined in the preamble. This also initializes all of the accumulation variables, which will be further discussed below. If a user creates custom macro files, they should be imported after the above statement. For example,

$ import mymacrofile

User-defined regular and space-time functions.

The user defines regular and space-time functions in this part of the file in the regular way. Examples are shown below.

#######################################################
# User defined functions
#######################################################

<function SomeFunc(x,y)>
  cos(x)*sin(y)
</function>

#######################################################
# User defined space-time functions
#######################################################

$ Jz = exp(-EXPFAC*(y^2+z^2))*sin(OMEGA*t)

The Ordered Macro Calls

There are only two ordered macro calls. Each must be preceded by the definition of some global variables. The grid macro call comes first and has the form,

#######################################################
# Translation of grid
#######################################################

$ VPM_BGN0 = 0 * TXU_METERS
$ VPM_BGN1 = NEGHW * TXU_METERS
$ VPM_BGN2 = NEGHW * TXU_METERS

$ VPM_L0 = $LENGTH - 0$ * TXU_METERS
$ VPM_L1 = $HALFWIDTH - NEGHW$ * TXU_METERS
$ VPM_L2 = $HALFWIDTH - NEGHW$ * TXU_METERS

$ VPM_N0 = NX
$ VPM_N1 = NPERP
$ VPM_N2 = NPERP

$ VPM_PERIODIC_DIRS = []

setGridData(VPM_NDIM, VPM_GRID_TYPE)

with the following definitions

VPM_BGN0: The start of the grid in the first coordinate.

VPM_BGN1: The start of the grid in the second coordinate.

VPM_BGN2: The start of the grid in the third coordinate.

VPM_L0: The extent of the grid in the first coordinate.

VPM_L1: The extent of the grid in the second coordinate.

VPM_L2: The extent of the grid in the third coordinate.

VPM_N0: The number of cells in the first direction.

VPM_N1: The number of cells in the second direction.

VPM_N2: The number of cells in the third direction.

VPM_PERIODIC_DIRS: An array listing the coordinate directions in
which one has periodic boundary conditions.

Following that is the timing setup, which has the form,

#######################################################
# Translation of the time group
#######################################################

$ VPM_DT = "0.0"
$ VPM_CFL_NUMBER = "0.95"
$ VPM_NSTEPS = 100
$ VPM_DUMP_PERIOD = 20

setTimingData()
VPM_DT: The time step for the simulation. If it is set to zero,
the setTimingData macro will provide a best guess.
VPM_CFL_NUMBER: This is used when VPM_DT is set to zero.
The time step is set to this factor times the maximum known stable time step.

VPM_NSTEPS: The number of time steps for the simulation.

VPM_DUMP_PERIOD: The number of time steps between each data dump.

The Unordered Macro Calls

With the new version-8 macros, one can now call the accumulation macros in any order. For example, one can add boundary conditions via

addBoundaryLauncher(boundaryLauncher0, ElectricField, 0.0, None, 0.0, upperY)
addMalBoundary(mal0, emField, lowerY, MALWID)
addOpenBoundary(open0, emField, upperX)

and one can add particle species, sinks and loaders with

addParticleSpecies(Xenon, 1.602176487e-19, XeMass, relBoris, variableWeights, 1.e18, 5.0, None)

addParticleSpeciesSink(absorbAndSave0, electrons0, absAndSav, lowerX)
addParticleSpeciesLoader(particleLoader0, xvLoaderEmitter, electrons0, 0.00000000000000e+00, 0.00000000000000e+00, relativeDensity, 1.0, grid, beamVelocityGen, [0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00],[5.00000000000000e+06, 5.00000000000000e+06, 5.00000000000000e+06], [-0.5, -0.5, -0.5], [0.5, 0.5, 0.5])
addParticleSpecies(electrons0, ELECCHARGE, ELECMASS, relBoris, variableWeights, 1.e18, 5.0, None)

From the above one can see that the order is independent, as the species, electrons0, is added after its loaders and sinks. However, if a loader or sink is added for a species that ultimately is not added, no such species shows up in the simulation.

Finalization

Finalization consists of a single line,

$ finalize()

This macro takes all of the accumulated descriptions of the simulation, held in the accumulation variables, and writes it into the file with correct ordering and nesting.

Version 8 Macros Methodology

The basic units of the new macro system are the direct macros. An example of one from solvers.mac is

# Add the base solver block to an accumulation variable.
# @param name the accumulation variable
# @param krySize the Krylov subspace size (for gmres)
# @param orthogType the orthogonality type for the Krylov subspace (for gmres
<macro writeBaseSolverBlock(name, krySize, orthogType)>
  <BaseSolver myBS>
    kind = name
    $ if isEqualString(name, generalized minimal residual solver)
      kspace = krySize
      orthog = orthogType
    $ endif
  </BaseSolver>
</macro>

Like all macros, this macro has basic documentation in the macros file, giving the macro name along with any parameters. In this case the macro directly writes an input file fragment, hence its name. Direct macros can be used just like any of the traditional macros, where the user controls the file structure, and the user knows where to place this macro call for the desired effect. Because all direct macros directly write, their names begin with write.

The above is actually an independent direct macro in that it can be used at any place in the file (though it may not make sense in any place). In particular, it need not be preceded with any other macros that set any accumulation variables, which we now turn to.

However, for deferred writing to allow the system to get the order of the macros correct, instead of writing directly, we accumulate these blocks in accumulation variables using accumulation macros, and then we write those out at finalization time. An example of an accumulation macro is

# Add the base solver block to the accumulation variable, VPM_MATRIX_SOLVER.
# Used for iterative solvers, such as gmres.
# @param name the name of the base solver block
# @param krySize the Krylov subspace size (for gmres)
# @param orthog the orthogonality type for the Krylov subspace (for gmres)
<macro addBaseSolver(name, krySize, orthog)>
  $ requires VPM_MATRIX_SOLVER
  $ VPM_MATRIX_SOLVER = appendToBlock(VPM_MATRIX_SOLVER, writeBaseSolverBlock(name, krySize, orthog) )
  $ global VPM_MATRIX_SOLVER
</macro>

This macro counts on there being a global accumulation variable, VPM_MATRIX_SOLVER, which is defined in solvers.mac. It is important to initialize accumulation variables to an empty string prior to accumulating input file lines into them. Thus, the definition of an accumulation variable should be of the form,

$ VPM_MATRIX_SOLVER = ""

Accumulation into a variable appends to that variable the output of the previous macro, e.g. writeBaseSolverBlock(...). With this device, we now have the base solver stored in the variable VPM_MATRIX_SOLVER, and we can write that variable out where it is needed.

For example, to write out a linear solver, one calls the dependent direct macro,

# Write the interative poisson solver block.  When used, it must come
# after addBaseSolver and addPreconditioner, as it writes the accumulation
# variables for the base solver and the preconditioner.
# @param maxIt the maximum number of iterations allowed.
# @param tol the tolerance for the solution
# @param met the metric for convergence, e.g., L1, L2
# Verbosity set to same as top level verbosity
<macro writePoissonSolverIterativeBlock(maxIt, tol, met)>
  $ requires VPM_TOP_LEVEL_VERBOSITY
  <LinearSolver linearSolver>
    kind = iterativeSolver
    verbosity = VPM_TOP_LEVEL_VERBOSITY
    maxIterations = maxIt
    tolerance = tol
    metric = met
    VPM_MATRIX_SOLVER
    VPM_PRE_CONDITIONER
  </LinearSolver>
</macro>

This is called dependent because it relies on previous macro calls to have defined VPM_MATRIX_SOLVER and VPM_PRE_CONDITIONER. This writes (and so is a direct macro) a linear solver block, which can be used inside a multifield block. A user may use this macro just like any of the pre-version-8 macros, provided that the variables, VPM_MATRIX_SOLVER and VPM_PRE_CONDITIONER have been appropriately initialized.

In the application to multifields, one has at least the updaters, the update steps, and the update step order. The above macro would be used to write an update step. It is accumulated in the variable, VPM_ES_SOLVER_UPDATERS, which is finally written into the multifield block during the call to finalize().

Version 8 Macro Files Organization

There are three sections in a macro file for (1) public macros, (2) global (including accumulation) variables, and (3) private macros. When working in the visual setup, the problem description is written out in an xml-like format that the translator translates to macro calls that are then processed to produce input file lines. Because most users only ever see these macro calls, they come first in the macro file. After those macro calls, the file defines the accumulation variables and then the other macros.

Public Macros

These are the macros currently written by the translator plus a few more, so they are sometimes called translator macros. They can be order dependent. For example, the macros calls for defining an iterative solver must occur as

addBaseSolver(bicgstab)
addPreconditioner(multigrid, SA, 30, GaussSeidel, 3, before, Jacobi, 1.33300000000000e+00, 0.00000000000000e+00, increasing)
# This writes preconditioner, so it must be last.
addPoissonSolver(relPerm, 1000, 1.00000000000000e-08, r0)

Global (including accumulation) Variables

These are the variables into which one accumulates blocks for later printing in the correct order. All variables are namespaced with VPMT_, VPM_ or TXU_ so that the user can confidently use names that are not namespaced with VPMT_, VPM_, or TXU_ provided they also avoid the names in mathphys.mac.

There is no guarantee that these variables will not change with future versions.

Private Macros

The translator macros make use of many other macros to accumulate blocks. These other macros take many forms: direct macros, utility macros, string manipulation, and so forth. These macros are not guaranteed to be stable between versions unless they appear in the documentation.

Top Level Macro Files

The top-level macro files are VSim.mac, VSimEm.mac, and VSimEs.mac. These control which other macro files are included, provide some universally used macros, and define the basic accumulation variables. In particular, if VPM_SIMULATION_TYPE equals Electromagnetic, then VSimEm.mac is loaded and it loads the macro files needed for electromagnetic simulations. If VPM_SIMULATION_TYPE equals Electrostatic, then VSimEs.mac is loaded and it loads the macro files needed for electrostatic simulations. Subsequently, VSim.mac loads the macro files for particles, fluids, collisions, etc., depending on what the preamble requested.

Remaining Macro Files

The remaining macro files are organized by functionality. For example, electrostatic boundary condition macros are in esbcs.mac. The particle macros are in particles.mac. When following the standard organization decribed above, the accumulation variables for any macros in a macro file are defined and initialized in either that file or in a previously loaded file.