Syntax definition

Documentation of input file syntax, use of variables and parser validation syntax.

Use of variables, IF statements and tags

# This is a comment line.
 x = 3.0   # This is comment, too.
           # Note that a comment runs until the end of the line.

The input file is almost white space independent. For example,

x=5 y=6 z=[1,2]

and

x = 5
y = 6
z = [1,
     2]

have the same effect. Similarly,

band{

and

band {

do the same. However, adding a line break as

band
{

is not allowed here due to parser limitations.

Next, we define variables. Variables are defined as

$x = 123
$y = 123.3
$zzz_ks = [12.3, 4]

Thus a variable name always starts with a dollar sign $ and is followed by a character, and then by an arbitrary number of characters, numbers, or underscores. Variables always have global scope and can be used for math as:

$y = sqrt($y)*$x
a = $zzz_ks

Note that mathematical variables are either doubles or double arrays, but get converted to integers if needed (only if no rounding is needed!). But elementwise mathematical operations between vectors or between scalars and vectors are not supported.

In addition, it is also possible to define string variables as:

$name = "some text"    #   quoted string constant
$id = hello            # unquoted string constant (must not start with a number)

Similar to variable names, also unquoted string constants must start with a letter (or underscore) in order to avoid conflicts with e.g. numbers in scientific notation. Please use quoted string constants instead if e.g. names starting with a number are needed.

Leading and trailing blanks are trimmed, and multiple string constants as

"aa b" "c"

or

aa b c

are automatically concatenated as

"aa b c"

with blanks inserted in between. Using the + operator, string variables can be concatenated (without inserted blanks) with each other or with double constants, double variables, or quoted (!) string constants as:

$id = hello
$id2 = "world"
$num = 3
$concat = $id + "_" + $id2 + $num + 5    # result: "hello_world35"

Double values are rounded into an integer first, before being concatenated to a string variable. Note that quoted string constants can only be added from the right.

Finally, variables can also be used to define conditional comments and conditional blocks.

#IF
#if    # deprecated
  • #IF (new)

    Conditional comments must be written in upper case (since 2020-12).

  • #if (deprecated)

    Conditional comments written in lower case are deprecated since 2020-12.

Conditional comments have the form

#IF $x schottky{
#IF $x    name = air
#IF $x }

and allow enabling/disabling of individual lines. Note that $x must be either undefined or a number, otherwise an error message will occur. In this example, the text is always commented out, unless $x is defined with value $x != 0 (actually 0.0, no rounding or truncation is being performed here!).

Similarly, conditional blocks have the form

schottky{
  !IF($x)
     name = air
     note = "Some text"
    #IF $y note2 = "This is a nested conditional line."
  !ELIF($test)   # (optional)
     ...
  !ELSE
     name = GaAs
  !ENDIF
}

and allow enabling/disabling of whole blocks. Note that the use of

!ELSE

is optional and that nesting conditional blocks is not allowed. Also here, $x needs to defined with value $x != 0 to be considered TRUE. And the debug statements

!VARS
!TABLE
!STOP

(see below) are also executed in the conditional block regions which are false.

Also note that all variables are removed from the final symbol table. Finally, remember that the parser is case sensitive.

Next, we define groups and attributes. Their name follows (except for the leading dollar symbol $) the same convention as variable names. Validation files may also contain groupnames starting with a question mark ?. We have here the following syntax:

groupname{
   attribute1 = value1
   group2{
      attribute1 = value2  # Each group has its own scope !!
      ....
   }
   group2{                 # groups with the same name and content may repeat
      ....
   }
   attribute2 = value2     # but attributes are unique.
}                          # the group groupname ends here

Note that the order of groups is relevant, but the order of the attributes in a group is ignored. Also note that groups may be empty as:

emptygroup{}

The curly brackets {} belonging to each group are checked for correctness.

Tags

In addition, it is possible to add tags to explicitely check the current scope. For example,

groupname{
   ...
   <groupname>
   ...
}

or

groupname{
   ...
<groupname>}

will have no effect, while

groupname{
   ...
<differentgroupname> }

will cause an error message, since the assumed scope and the actual scope do not match.

Input files may also be decorated at the root level (i.e. outside of any group) with XML tags such as

<id>
</id>

or also:

<id/>

Here, id follows (except for the leading dollar symbol) the same convention as variable names. For backwards compatibility, in addition, also the empty (non-XML) tag <> is still available to e.g. check root level group closure. Please note that, whereas the simulator completely ignores the content of XML tags, they may have special meaning for calling programs such as nextnanomat and thus should not be altered without understanding their use. Practically, this means that, outside of groups, you may decorate input files/templates or also databases with XML tags in any way you wish. Just make sure to comment out stuff to be ignored by nextnano++ with double comments ## (to avoid possible collisions with conditional ifs) in order to add things such as:

<description>
##
## any stuff you want, e.g. rich text, nextnano++ will happily ignore it
##
</description>
<variables> $mass = 0.067 <unit># m_0</unit> </variables>

At the root level, one can use the empty tag

<>

to check for the root scope. This is optional and not required. Tags with these brackets <...> are ignored by the parser and can be used to provide additional meta data. That is, everything right (or left) of such symbols is executed normally, as if there was just a ; (optional separator) instead of each tag.

Example:

<tag/>

It might look like an XML tag but it is much simpler. Nesting and matching tags are not checked. No blanks or special characters except underscores _ may be used within tags <...>.

There exist different types of attributes. Allowed are

  • real numbers

    x = 12.121
    
  • integers

    i = 12
    
  • vectors of real numbers

    xV = [12.3e-4, 2, 3, sqrt(54.12)+2.1]
    
  • vectors of integers

    iV = [1, 2]
    
  • strings

    c="ohohi-oh ./opij "  # But many exotic characters are not allowed!
    
  • choices and

    color = red           # Pick one from a set of tokens
    
  • enumerations

    food = "juice bread dessert"  # Pick subset from a set of tokens
    

Attributes may also (like variables) be initialized with values of variables or the results of computations. But note that unlike variables, attributes may neither be redefined nor be used in mathematical expressions.

Next, there are also a couple of debug statements available, that can be used at any (reasonable) point inside of an input file or validation file:

!VARS    # prints all variables with their values into the standard output
!TABLE   # prints the entire symbol table into the standard output

Example:

--- Variables at line 14 -------------
$QW_WIDTH = 6
$QW_SEPERATION = 4
$QW_min = 20
$QW_max = 26
--------------------------------------

But note that result of these debug statements obviously depends on their location in the file. Additionally, all variables and their values that are used in a simulation are written to the output folder into a file called

  • variables_input.txt (for variables used in the input file)

  • variables_database.txt (for variables used in the database file)

Syntax validation

How to use validation and validation files

The syntax is listed in the files input.val and database.val that are located in the Syntax/ folder. In fact, this is obsolete. These files are no longer distributed to the customer. The contents of these files are now contained inside the source code. If one starts nextnano++ with the argument -p, i.e. nextnano++.exe -p, then the syntax definition files input_syntax.txt and database_syntax.txt are written out. They are not needed. They have just informative character to display available input file syntax to the user.

As we have seen, the syntax of input files and validation files is except for some details mostly identical. As in content format languages such as XML or HTML, an almost unlimited hierarchy of objects is possible, as long as the resulting file is wellformed (means conforms with the syntax). But of course we would like now to impose constraints on what can be in an input file. This is easily done with a validation file. If desired, every input file can validated with respect to the constraints of any validation file. In this section, we describe the format used to define such constraints.

We start out with the definition of attributes. Here are some examples:

x1{ TYPE=real }
x2{ TYPE=real MIN=0 }
x3{ TYPE=real MIN=0 MAX=1.2 OPT="" }

Thus, x1, x2, and x3 are attributes of the type real number. x2 has also a mandatory minimum value defined, x3 has also a mandatory minimum value. Furthermore, x3 is an optional attribute that may be omitted, while x1 and x2 are mandatory. Also note that as usual the order of the modifiers in the curly brackets {} is ignored.

Similary, we have for integers:

i1{ TYPE=int }
i2{ TYPE=int MIN=0 }
i3{ TYPE=int MIN=0 MAX=2 OPT="" }

Vectors of real numbers can be defined as:

v1{ TYPE=vector }
v2{ TYPE=vector DIM=3 }
v3{ TYPE=vector MINDIM=2 MAXDIM=3 }
v4{ TYPE=vector MINDIM=2 MODDIM=3 OPT="" }

Here, the modifier DIM states an explicit dimensionality of the vector, MINDIM and MAXDIM an explicit minimum and maximum dimensionality, and MODDIM=3 requires that the dimension of the vector can be divided by 3.

Similarly, the correponding definition for integer vectors are:

iv1{ TYPE=intvector }
iv2{ TYPE=intvector DIM=3 }
iv3{ TYPE=intvector MINDIM=2 MAXDIM=3 }
iv4{ TYPE=intvector MINDIM=2 MODDIM=3 OPT="" }

Note that MIN and MAX can also applied to check the elements of vectors. In this case, the same bounds apply to all elements of a vector.

When validating vectors or intvectors, numerical variable values are automatically converted, therefore no extra brackets as [123] are needed for one-dimensional objects.

Next, strings are defined as

name{ TYPE=string }

and choices as

enable{ TYPE=choice  VAL="yes no"}
boundary{ TYPE=choice  VAL="dirichlet neumann periodic"  OPT=""}

Finally, enumerations are defined as

color{ TYPE=enum  VAL="white black red green blue"}

When validating strings, choices, or enums, numerical variable values are automatically converted into strings, therefore no extra quotes as "123" are needed.

Each attribute definition must be defined inside of a group definition as

shape_cuboid{ TYPE=group OPT=""
   x{ TYPE=vector DIM=2}
   y{ TYPE=vector DIM=2}
   z{ TYPE=vector DIM=2}
}

An empty group is defined using a group definition that does not contain any attribute definitions, while a group definition inside another group definition indicates that the one group is supposed to contain the other group.

Of course, there are special modifiers for group definitions as well. Here we have available

groupname1{ TYPE=group ITEMS=3
   ...
}
groupname1{ TYPE=group MINITEMS=5 MODITEMS=4
   ...
}
groupname{ TYPE=group MAXITEMS=3 OPT=""
...
}

Here, ITEMS=3 means that the group needs to be defined 3 times in the current scope, while MINITEMS=5, MODITEMS=4, and MAXITEMS=3 have the expected meanings. Note that the use of MINITEMS or ITEMS together with OPT may lead to constraints that cannot be fullfilled.

In addition, it also possible to specify dependencies between groups. Here is an example:

groupname{ TYPE=group
   ?ONE{ TARGETS="x1 x2 x3" }
   ...
      x1{TYPE=group OPT="" MAXITEMS=3 }
      x2{TYPE=group OPT="" MAXITEMS=3 }
      x3{TYPE=group OPT="" MAXITEMS=5 }
      ...
}

This means, that in the group groupname exactly one of the three children groups x1, x2, and x3 must be present. At the same time, if x3 is present, it may occur up to 5 times.

Similary,

groupname{ TYPE=group
   ?SOME{ TARGETS="x1 x2 x3" }
   ...
      x1{TYPE=group OPT="" MAXITEMS=3 }
      x2{TYPE=group OPT="" MAXITEMS=3 }
      x3{TYPE=group OPT="" MAXITEMS=5 }
      ...
}

means, that at least some (even all but not none) of the children groups x1, x2, x3 must be present in the current scope.

Finally, by writing

groupname{ TYPE=group
   ?MAXONE{ TARGETS="x1 x2 x3" }
   ...
      x1{TYPE=group OPT="" MAXITEMS=3 }
      x2{TYPE=group OPT="" MAXITEMS=3 }
      x3{TYPE=group OPT="" MAXITEMS=5 }
      ...
}

we can guarantee that atmost one of the children groups x1, x2, x3 is present in the current scope.

Finally, using

groupname{ TYPE=group
   ?NONE{ TARGETS="x1 x2 x3" }
   ...
      x1{TYPE=group OPT="" MAXITEMS=3 }
      x2{TYPE=group OPT="" MAXITEMS=3 }
      x3{TYPE=group OPT="" MAXITEMS=5 }
      ...
}

we can enforce that none of the children groups x1, x2, x3 are present. This feature is only useful for inherited groups.

Similarly, the conditions ?TWO, ?THREE, ?MAXTWO, ?MAXTHREE, ?COND_TWO, ?COND_THREE, ?COND_MAXTWO, ?COND_MAXTHREE can be used to check for 2 or 3 occurences.

In addition, it is also possible to define conditional dependencies as

groupname{ TYPE=group
   ?COND_SOME{ COND="n" TARGETS="x1 x2 x3" }
   ...
      n{TYPE=group OPT="" MAXITEMS=5 }
      ...
      x1{TYPE=group OPT="" MAXITEMS=3 }
      x2{TYPE=group OPT="" MAXITEMS=3 }
      x3{TYPE=group OPT="" MAXITEMS=5 }
      ...
}

which that if group n is present in the current scope, then at least some of the children groups x1, x2, x3 must also be present in the current scope.

Similarly,

?COND_NONE{   COND="n" TARGETS="x1 x2 x3" }
?COND_ONE{    COND="n" TARGETS="x1 x2 x3" }
?COND_MAXONE{ COND="n" TARGETS="x1 x2 x3" }
?COND_SOME{   COND="n" TARGETS="x1 x2 x3" }
?COND_ALL{    COND="n" TARGETS="x1 x2 x3" }

have the expected meaning as well.

Finally we also have the following tests

?EXISTS{     TARGET="global/parameters/simulate3D" }
?EXISTS_NOT{ TARGET="global/parameters/simulate3D" }

for the presence or absence of an object.

As the last examples show, both the TARGET attribute as well as the COND attribute may also contain a path to the element in question, as for example:

?COND_ALL{ COND="/global/parameters/simulate3D" TARGETS="x1 x2 x3" }

Here, a path beginning with a slash / is an absolute path that is searched from the root level.

Warning

Paths in COND and TARGET do not result into an exhaustive search of the symbol table yet!

Variables: Operators and functions

For the use with number variables, the following operators (sorted with decreasing precedence) and functions are available in the parser:

Operators

The following operators are supported.

round arithmetic brackets

( )

power (exponentiation)

^

right associative

unary minus and unary plus

- +

right associative

arithmetic multiplication, division, remainder

* / %

remainder = modulo

arithmetic plus and minus

+ -

arithmetic comparisons

< <= >= >

less than, less than or equal, …

arithmetic comparisons

== !=

equal, not equal

Functions

The following mathematical functions are supported.

sqrt()

square root \(\sqrt{\text{ }}\)

cbrt()

cubic root \(\sqrt[3]{\text{ }}\)

exp()

exponential function \(\exp({\text{ }})\)

log()

natural logarithm \(\log\)

ln()

natural logarithm \(\ln\)

log2()

decadic logarithm (base 2) \(\log_{2}\)

log10()

decadic logarithm (base 10) \(\log_{10}\)

sin()

sine \(\sin({\text{ }})\)

cos()

cosine \(\cos({\text{ }})\)

tan()

tangent \(\tan({\text{ }})\)

asin()

acrsine \(\sin^{-1}({\text{ }})\)

acos()

arccosine \(\cos^{-1}({\text{ }})\)

atan()

arctangent \(\tan^{-1}({\text{ }})\)

sinh()

hyperbolic sine \(\sinh({\text{ }})\)

cosh()

hyperbolic cosine \(\cosh({\text{ }})\)

tanh()

hyperbolic tangent \(\tanh({\text{ }})\)

asinh()

inverse hyperbolic sine \(\sinh^{-1}({\text{ }})\)

acosh()

inverse hyperbolic cosine \(\cosh^{-1}({\text{ }})\)

atanh()

inverse hyperbolic tangent \(\tanh^{-1}({\text{ }})\)

erf()

error function \(\text{erf}({\text{ }})\)

erfc()

complementary error function \(\text{erfc}({\text{ }})\)

gamma()

Gamma function \(\Gamma({\text{ }})\)

fdm3half()

complete Fermi–Dirac integral \(F_{-3/2}({ })\) of order -3/2 (includes the \(1/\Gamma(-1/2)\) prefactor)

fdmhalf()

complete Fermi–Dirac integral \(F_{-1/2}({ })\) of order -1/2 (includes the \(1/\Gamma(1/2)\) prefactor)

fdzero()

complete Fermi–Dirac integral \(F_{0}({ })\) of order 0 (includes the \(1/\Gamma(1)=1\) prefactor)

fdphalf()

complete Fermi–Dirac integral \(F_{1/2}({ })\) of order 1/2 (includes the \(1/\Gamma(3/2)\) prefactor)

fdp3half()

complete Fermi–Dirac integral \(F_{3/2}({ })\) of order 3/2 (includes the \(1/\Gamma(5/2)\) prefactor)

abs()

absolute value \(|{\text{ }}|\)

floor()

floor function floor(x): largest integer \(\le x\)

ceil()

ceiling function ceil(x): smallest integer \(\ge x\)

round()

rounds the number to the nearest integer

sign()

sign function

iszero()

check if value is zero

isnotzero()

check if value is not zero

ispositive()

check if value is positive

isnotpositive()

check if value is not positive

isnegative()

check if value is negative

isnotnegative()

check if value is not negative (corresponds to heaviside())

heaviside()

Heaviside step function (corresponds to isnotnegative())

Here, the results of the comparison operators and of the comparison functions ispositive(), …, isnotzero() are either 1 for TRUE or 0 for FALSE. Please be careful when comparing the results of floating point computations und use round() if necessary, since e.g. (1/3)*3 has the value 0.99999999... and not 1.0.

Also please note that while conditional comments and conditional blocks consider any nonzero number as true, the use of positive numbers for TRUE is preferred, since then the arithmetic operators + and * can be used in conjunction with the comparison functions to implement logical expressions. E.g. you can define:

$pi = 4 * atan(1)

This will give 3.1415926535897932384626433832795029. You can also specify:

$pi = 3.1415926535897932384626433832795029

Variable evaluation occurs already during parsing of the input/database file and thus before the beginning of the actual simulation. The input file after variable evaluation and the database file after the variable evaluation and possible modification by database{} in the input file (which are the real inputs of the simulation) are written into files

  • simulation_input.txt and

  • simulation_database.txt.

In case of problems, or when many variables are used, it is highly recommended to review the file simulation_input.txt for possible mistakes. Similarly, simulation_database.txt will tell you (and our customer support) which values of material parameters were actually used for the simulation.

Further remarks

Except within comments, input files are strictly 7-bit ASCII. That is, no umlauts, diacritics, etc. in strings, names, etc. This is an inherent limitation of the parser. Command line parameters, file paths, and file names may contain all characters except \ / ? * ^ & ' ` < > : " and control characters (e.g. newlines). Unfortunately, e.g. on (US localized) windows, file names or file paths containing characters outside of code page 1252 (https://en.wikipedia.org/wiki/Windows-1252) may not be found or properly processed. Similar issues also may arise for other Windows localizations or for other operating systems. In order to avoid such problems, please make to sure to avoid characters outside of code page 1252 for all file names and file paths.

Advanced syntax documentation for validation files

only for developers

Validation files also offer the feature of parser-level group inheritance. Suppose, we have defined a group structure:

something{ TYPE=group
   section_base{ TYPE=group ITEMS=0 OPT=1
      x{ TYPE=real OPT=1 }
      y{ TYPE=real OPT=1 }
      z{ TYPE=real OPT=1 }
      another_group{ TYPE=group
         # more stuff in here
      }

   section : section_base{ TYPE=group OPT=1
      w{ TYPE=real OPT=1}
   }
}

In this case, the group section is inherited from the group section_base.

Inheritance means here the following procedure:

  • Since the file is parsed once from the top to the bottom, first the group section_base is generated in the symboltable of the validation file. Note that while section_base is abstract here (it may not occur), there is no need for a base group to abstract.

  • Once the group section is encountered, it is constructed by deep copying all (parser-level) subgroups of section_base (thus x, y, z, another_group with all their content) and calling it section.

  • Only afterwards the content of section itself (in this case is w) will be added.

Obviously, the following rules and restrictions to inheritence then apply:

  • Base group and derived group must both reside in the same group or both at root level.

  • Inheritance occurs in the parser, not in the validator. Thus, from a purely technical point it is also possible to inherit off group x{} in the example above, with the derived group having a different TYPE (even TYPE=GROUP). But since all parser-items of the base group like TYPE or ITEMS are not copied, any such operation is useless for constructing a validation file and not recommended.

  • For the same reason, deriving from a TYPE=GROUP into a different TYPE is not useful either.

  • Next, since derivation does not copy ITEMS, OPT, MINVAL,… definitions of the base group, they must be defined in all derived groups as well.

  • Finally, any derived group may as well be base group for other inherited groups. However, self-inheritance or inheritance from a group not encountered yet during parsing is not possible.