input.xml
The exciting code uses one input file which is written in XML. To access the data in the input file exciting uses the FoX library. The Fox library can parse the contents of the xml into a Document object model (DOM) which is a representation of the XML-structure in memory.
Then the getstructinput(inputnp) function walks througth that tree and converts the data into fortran data types. This code is generated from the XML Schema that describes the detailed grammar and datatypes in the code. Meaning that when something in the schema is added or changed the the fortran code necessary to read it, is automatically adapted. Also, if it comes across an unknown entry the user gets an error message.
This code snippet reads the input file and returns the fortran data structure:
program main
use inputdom ! module that cares about the FoX Calls
use modinput ! module that contains the derived type definitions and parser functions
call loadinputDOM() ! load xml to DOM
input=getstructinput(inputnp) ! builds the tree structure populated with
!default values and configured values
end program
From now on all the data from the input file is available as native fortran datatype in the "input" structure. The values can be used in expressions directly without any further call to a function.
Example
array(1:3)=input%groundstate%ngridk
The expression input%groundstate%ngridk gives the integer array of the number of kmesh points in each direction. All the other attributes are accessed in the same way.
In case of multiple occurrences of an element the syntax to access one of the items in the list is the following as in the example of addressing the coordinates of an atom.
coords(:)=input%structure%speciesarray(is)%species%atomarray(ia)%atom%coord(:)
Remark: The peculiar notation atomarray(index)%atom .. stems from the fact that fortran does not allow the construction of an array of pointers. Rather one can only define an array of derived types that contains a pointer.
<input> <title>LiF</title> <structure speciespath="../../species/"> <crystal> <basevect>3.80402 3.80402 0.00000</basevect> <basevect>3.80402 0.00000 3.80402</basevect> <basevect>0.00000 3.80402 3.80402</basevect> </crystal> <species speciesfile="Li.xml"> <atom coord="0.0000 0.0000 0.0000" /> </species> <species speciesfile="F.xml"> <atom coord="0.5000 0.5000 0.5000" /> </species> </structure> <input>
The default values, data types, and variable names are all defined in the schema. The input reference generated from this schema constitutes the reference documentation for the input file format.
Implied Concepts
The elements and attributes allow for a hierarchical structure of the input file. But also, the syntax of XML implies a meaning of what elements and attributes represent.
Attributes are key value pairs accociated with an element. One attribute name can occur only once within one element. They can be required. Then the attribute must be given. This is enforced if there is no meaningfull default value possible such as in the coord attribute. If an element occurs in the input file it is initialized with all its available attributes. If a required attribute in missing it constitutes an error. Optional attributes are initialized with their default values.
Elements are used for grouping independent submodules. Some elements can be repeated inside the parent element. So repeated data such as the list of atoms are atom elements inside the species element. Elements can be required such that it is an error if it is missing. Like the structure and groundstate element. Optional elements act as a switch that activates the associated feature. Independent parts of the code must not rely on parameters defined in the other element. This is enforced by the fact that optional elements that are not present in the input file are not initialized and will cause an segmentation fault when referenced in the code. It is possible to test for the presence with the associated() inquiry function.
species files
The same as for the input file can be done for the species file too. There is a XML Schema for the species definition and the parser code is generated from this definition. IN order to populate a the species data structure one needs to call this code:
Subroutine readspeciesxml
Use modmain
Use modinput, Only: input
Use modsp
Use FoX_dom
Use modspdb
Implicit None
! local variables
Integer :: is, ist, iostat
Integer :: io, nlx, ilx, lx, ilo
Type (Node), Pointer :: speciesnp, speciesdbnp
!
Allocate (speziesdeflist(nspecies))
config => newDOMConfig ()
parseerror = .False.
! parse xml and create derived type for species definitions speziesdeflist
Do is = 1, nspecies
If (trim(input%structure%speciesarray(is)%species%speciesfile) &
& .Eq. "") Then
input%structure%speciesarray(is)%species%speciesfile = trim &
& (input%structure%speciesarray(is)%species%chemicalSymbol) &
& // ".xml"
End If
Write (*,*) "open ", trim (input%structure%speciespath) // "/" &
& // trim &
& (input%structure%speciesarray(is)%species%speciesfile)
doc => parseFile (trim(input%structure%speciespath)//"/"//&
& trim(input%structure%speciesarray(is)%species%speciesfile), &
& config)
speciesdbnp => getDocumentElement (doc)
speciesnp => item (getElementsByTagname(speciesdbnp, "sp"), 0)
parseerror = .False.
speziesdeflist(is)%sp => getstructsp (speciesnp)
Call destroy (doc)
End Do
!
the type speziesdeflist is of type Type (sp_type_array) which is defined in modsp and declared in modspdb.