5. Writing the results
The results of a solver can be large: solver does not build them in memory, it streams them with an xml_writer, element by element.
f90
program solver
!< Tutorial, chapter 5: writing the results.
use foxy
implicit none
type(xml_writer) :: results
integer(I4P) :: iostat, step, i
character(len=256) :: iomsg
call results%open(filename='results.xml', iostat=iostat, iomsg=iomsg)
call results%declaration(encoding='UTF-8')
call results%start('results')
call results%attribute('case', 'cavity')
call results%attribute('steps', 500_I4P)
do step=100, 500, 200
call results%start('snapshot')
call results%attribute('step', step)
call results%attribute('time', real(step, R8P)*1.0e-3_R8P, fmt='(F5.3)')
call results%start('residual')
call results%text('converged & stable')
call results%end('residual')
call results%start('pressure')
call results%attribute('format', 'ascii')
call results%text([(100.0_R8P/real(i*step, R8P), i=1, 3)], fmt='(F6.3)') ! a list of numbers
call results%end('pressure')
call results%end('snapshot')
enddo
call results%comment(' 3 snapshots ')
call results%close(iostat=iostat, iomsg=iomsg) ! closes the open elements, reports the first error
print '(A,I0)', 'results.xml written, iostat = ', iostat
endprogram solveropen(filename=)creates the file;open(unit=)writes to a unit you opened withaccess='stream', form='unformatted'(closeleaves it open);open()writes to memory, read back withstring().declaration(encoding=)writes<?xml version="1.0" encoding="UTF-8"?>: the writer writes UTF-8, so no other encoding is accepted.start(name)opens an element; its start tag stays open forattributecalls until its first content. Attributes take characters (escaped), integers and reals (both with an optionalfmt), logicals, and lists of numbers.textwrites escaped character data, or a number, a logical or a list of numbers (here withfmt=; without it, reals get the shortest text that reads back exactly);rawwrites characters as they are (base64, pre-formatted data) and can be called many times for one element;comment,cdataandpiwrite the other markup.end(name)closes the innermost element (the name is checked);closecloses all of them and the file (a file it opened itself).- Errors are sticky: the first one is kept, the following calls do nothing,
closereturns it. A misuse (an invalid name, a duplicate attribute,endwith nothing open) isXML_MALFORMED; withoutiostat,closestops the program on it, so no error is lost.
Running it
$ solver
results.xml written, iostat = 0$ cat results.xml
<?xml version="1.0" encoding="UTF-8"?>
<results case="cavity" steps="500">
<snapshot step="100" time="0.100">
<residual>converged & stable</residual>
<pressure format="ascii">1.000 0.500 0.333</pressure>
</snapshot>
<snapshot step="300" time="0.300">
<residual>converged & stable</residual>
<pressure format="ascii">0.333 0.167 0.111</pressure>
</snapshot>
<snapshot step="500" time="0.500">
<residual>converged & stable</residual>
<pressure format="ascii">0.200 0.100 0.067</pressure>
</snapshot>
<!-- 3 snapshots -->
</results>What you learned
xml_writer streams a document of any size, with layout, escaping and well-formedness checks. Reference: Writing.
Next: 6. Large outputs: the index.