2. Reading the case file
The case lives in a file, case.xml:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- the case of a (pretend) flow solver: the input of the FoXy tutorial -->
<case name="cavity" version="2">
<mesh>
<grid ni="64" nj="32" nk="1"/>
<domain>0.0 1.0 0.0 0.5 0.0 0.0</domain>
</mesh>
<time>
<dt unit="s">1.0e-3</dt>
<steps>500</steps>
<adaptive>true</adaptive>
</time>
<fluid name="air">
<density unit="kg/m3">1.225</density>
<viscosity unit="Pa s">1.8e-5</viscosity>
</fluid>
<boundary side="west" type="inflow">
<velocity>1.0 0.0 0.0</velocity>
</boundary>
<boundary side="east" type="outflow"/>
<boundary side="north" type="wall"/>
<boundary side="south" type="wall"/>
<output every="100">results.xml</output>
<notes>Lid-driven cavity & inflow, after <![CDATA[<paper ref="1">]]>.</notes>
</case>solver parses it and reads its settings as numbers, not as text.
f90
program solver
!< Tutorial, chapter 2: reading the case file.
use foxy
implicit none
type(xml_file) :: case_file
integer(I4P) :: iostat
character(len=256) :: iomsg
real(R8P) :: dt, density
integer(I4P) :: steps, ni, nj
logical :: adaptive
real(R8P), allocatable :: domain(:)
call case_file%parse(filename='case.xml', iostat=iostat, iomsg=iomsg)
if (iostat/=0) then
print '(A)', 'cannot read case.xml: '//trim(iomsg)
stop 1
endif
call case_file%get_content(id=case_file%find(path='case/time/dt'), value=dt)
call case_file%get_content(id=case_file%find(path='case/time/steps'), value=steps)
call case_file%get_content(id=case_file%find(path='case/time/adaptive'), value=adaptive)
call case_file%get_content(id=case_file%find(path='case/mesh/domain'), values=domain)
call case_file%get_attribute(id=case_file%find(name='grid'), name='ni', value=ni)
call case_file%get_attribute(id=case_file%find(name='grid'), name='nj', value=nj)
print '(A,ES10.3,A,I0,A,L1)', 'dt = ', dt, ', steps = ', steps, ', adaptive = ', adaptive
print '(A,I0,A,I0,A,6F5.1)', 'grid ', ni, ' x ', nj, ', domain', domain
density = 1.0_R8P ! a default, kept on error
call case_file%get_content(id=case_file%find(path='case/fluid/densty'), value=density, iostat=iostat, iomsg=iomsg)
if (iostat==XML_NOT_FOUND) print '(A,F6.3)', 'not found, density kept: ', density
call case_file%get_attribute(id=case_file%find(name='density'), name='unit', value=steps, iostat=iostat, iomsg=iomsg)
if (iostat==XML_BAD_VALUE) print '(A)', trim(iomsg)
endprogram solverparse(filename=)reads the file in chunks (1 MiB by default), so it is never read into one big string; the DOM still holds every tag and its text. For a file larger than your memory, use the index (chapter 6) or a handler (chapter 7).iostatis0, the runtime I/O error (the file cannot be read), orXML_MALFORMED(see chapter 9). A UTF-16, UTF-32 or Latin-1 file is converted to UTF-8 as it is read.get_content(id, value)converts the text of a tag intovalue: any integer kind,real(R4P),real(R8P)orlogical(true,false,1,0). Withvalues=, an allocatable array, it reads a blank-separated list.get_attribute(id, name, value)does the same for an attribute.- On error the value is left unchanged, so a default set before the call survives:
iostatisXML_NOT_FOUNDfor a missing tag or attribute (ID0included),XML_BAD_VALUEfor a text that is not a value of that type;iomsgsays which one and where. Withoutiostat, errors are silent.
Running it
$ solver
dt = 1.000E-03, steps = 500, adaptive = T
grid 64 x 32, domain 0.0 1.0 0.0 0.5 0.0 0.0
not found, density kept: 1.000
invalid character "k" in "kg/m3" in attribute "unit" of tag "density"What you learned
Read files with parse(filename=), numbers and lists with get_content/get_attribute; a default plus iostat makes a setting optional. Reference: Typed values.
Next: 3. Walking the tree.