Quote of the day
"You’re a man looking at the world through a keyhole,
and you’ve spent your whole life trying to widen that keyhole, to see more, to know more,
and now, on hearing that it can be widened, in ways you can’t imagine you reject the possibility."
The Ancient One - Doctor Strange
code parameters allow to store varaibles and parameters outside of actor code in elegant way.
The IMAS environment has specially dedicated library - xmllib to handle it.
1. Accessing code parameters from pure IMAS code
Prepare your environment:
$ module load imasenv/3.24.0/rc $ mkdir -p $ITMWORK/projects $ cd $ITMWORK/projects $ cp -r $SWIMASDIR/resources/tutorials/2019-10-PSNC/code_parameters .
Before proceeding any further, make sure you have configured your Kepler environment. Take a look here 00. Initial setup or here 05.3. IMAS - basic topics - environment set-up(POZ'19Oct)
The structure of your working directory should look like this:
$ cd code_parameters $ tree . ├── input_test_xmllib_pathquery.xml ├── input_test_xmllib_pathquery.xsd ├── Makefile # instructions on how to compile ├── sample_default.xml ├── sample.f90 # code with accessing code parameters ├── sample.xml # file with parameters └── sample.xsd # defining the structure of an XML document
A sample xml file containing information in the form of parameters for an actor:
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="./ets.xsl" charset="ISO-8859-1"?> <parameters> <input> <shot_in> 4 </shot_in> <!-- shot number --> <run_in> 1 </run_in> <!-- run number --> <interpol> 1 </interpol> <!-- interpolation index --> <time_dep_input> 0 </time_dep_input> <!-- 1 implies time dependence in input data --> </input> <output> <shot_out> 5 </shot_out> <!-- shot number --> <run_out> 2 </run_out> <!-- run number --> <tau_out> 0.0003 </tau_out> <!-- output frequency --> <db_out> mdsplus </db_out> <!-- output database format --> </output> <dims> <nrho> 50 </nrho> <!-- NRHO, number of radial points --> <npsi> 100 </npsi> <!-- NPSI, number of equilibrium points --> <neq_dim1> 100 </neq_dim1> <!-- NDIM1, number of points for 2-D equilibrium signals in R direction --> <neq_dim2> 100 </neq_dim2> <!-- NDIM2, number of points for 2-D equilibrium signals in Z direction --> <neq_max_npoints> 100 </neq_max_npoints> <!-- MAX_NPOINTS, number of equilibrium boundary points --> </dims> ... <experimental> <option> -1 </option> <!-- option #: 0: disabled --> </experimental> </parameters>
The first 35 lines of this code show how you can handle reading of the xml file in which the actor's parameters are saved:
!> Test program Christian Konz version of xmllib. program sample use xml_file_reader, only: fill_param use xml2eg_mdl use xmllib_parser, only: element, tree, xmllib_parse, destroy_xml_tree use string_manipulation_tools implicit none ! Input parameters, read from file character(132), pointer :: param_xml(:) => NULL() character(132), pointer :: param_xsd(:) => NULL() character(132), pointer :: param_default(:) => NULL() ! Input file names: character(132) :: fn_xml = 'sample.xml' character(132) :: fn_xml_default = 'sample.xml' character(132) :: fn_xsd = 'sample.xsd' ! Representation of xml parameters TYPE(tree) :: parameter_list TYPE(element), POINTER :: temp_pointer => null() character(len = 132) :: cname ! Values parser from xml integer :: shot_in, run_in integer(4) :: nparm real(8) :: geo_ax call fill_param(param_xml, param_default, param_xsd, fn_xml, fn_xml_default, fn_xsd) CALL XMLLIB_PARSE(param_xml, param_xsd, param_default, nparm, parameter_list) temp_pointer => parameter_list%first outer: do write(*,*)'Next xml element: ',temp_pointer%cname cname = char2str(temp_pointer%cname) ! necessary for AIX !write(0,*)'RFOF_input::RFOF_parse_xml_input_param, cname=',trim(cname) select case (cname) ... end select do if (associated(temp_pointer%sibling)) then temp_pointer => temp_pointer%sibling exit end if if (associated(temp_pointer%parent, parameter_list%first )) & exit outer if (associated(temp_pointer%parent)) then temp_pointer => temp_pointer%parent else write(0, *) 'ERROR: broken list.' stop end if end do end do outer !-- destroy tree call destroy_xml_tree(parameter_list) end program sample
Run an example:
$ module load imasenv/3.24.0/rc # load environment if not set $ make ifort -fPIC -g -I/gw/swimas/extra/xmllib/3.2.0/intel/17.0/include/xmllib -I/usr/include/libxml2 -c -o sample.o sample.f90 ifort -fPIC -g -o sample.exe sample.o -L/gw/swimas/extra/xmllib/3.2.0/intel/17.0/lib -lxmllib -lxml2 ./sample.exe Next xml element: parameters Next xml element: input Next xml element: shot_in Read shot_in= 4 Next xml element: run_in Read shot_in= 1 Next xml element: interpol Next xml element: time_dep_input Next xml element: output Next xml element: dims Next xml element: compositions Next xml element: startup Next xml element: boundary Next xml element: equilibrium Next xml element: geo_ax Read geo_ax= 2.86000000000000 Next xml element: plasma_ax Next xml element: amin Next xml element: elong Next xml element: tria_up Next xml element: tria_low Next xml element: solver Next xml element: experimental
Compare result with data inside sample.xml file.
2. Accessing code parameters from FC2K actor
Before proceeding any further, make sure you have configured your Kepler environment. Take a look here 00. Initial setup or here 05.3. IMAS - basic topics - environment set-up(POZ'19Oct)
Prepare your environment:
$ module load imasenv/3.24.0/rc $ mkdir -p $ITMWORK/projects $ cd $ITMWORK/projects $ git clone ssh://git@git.iter.org/imex/fc2k-testing-framework.git # OR copy from this location $ cp -r $SWIMASDIR/resources/tutorials/2019-10-PSNC/fc2k-testing-framework .
The structure of your working directory should look like this:
$ cd fc2k-testing-framework/primitives_param/fortran/ $ tree . ├── clean.sh ├── Makefile ├── primitives_param.f90 # FC2K actor with accessing code parameters ├── primitivesparam_fc2k.xml # FC2K configuration file ├── primitivesparam_workflow.xml # example workflow ├── run_test.sh # script for run example ├── sample_default.xml ├── sample.xml # XML file with parameters └── sample.xsd # defining the structure of an XML document
Let's see what the xml file looks like with the parameters.
Suppose we want to download an "i" parameter from this file.
<?xml version="1.0"?> <parameters> <r> 3.141592 </r> <i> 2 </i> <boolean> True False </boolean> <realVec> 2.7e2 4.0 </realVec> <intVec> 13 7 </intVec> <booleanVec> True False </booleanVec> </parameters>
Below is an example of the code that retrieves parameters/i value from an xml file:
subroutine primitivesparam(in_input, out_output, user_in_codeparamstruct) use ids_schemas, only: ids_real, ids_int, ids_equilibrium, ids_core_profiles, ids_parameters_input use xml2eg_mdl, only: xml2eg_parse_memory, xml2eg_get, type_xml2eg_document, xml2eg_free_doc, set_verbose use iso_c_binding, only: c_int implicit none integer, intent(in) :: in_input integer, intent(out) :: out_output integer(ids_int) :: value_int integer(c_int) :: tmp_value_int type(ids_parameters_input) :: user_in_codeparamstruct type(type_xml2eg_document) :: doc ! Parse the "codeparam_string". This means that the data is put into a document "doc" call xml2eg_parse_memory( user_in_codeparamstruct%parameters_value, doc ) call set_verbose(.TRUE.) ! Extract data in "doc" at position "parameters/i" and store it in "int_value" call xml2eg_get( doc , 'i' , tmp_value_int) value_int = int( tmp_value_int, ids_int ) ! Make sure to clean up after you!! ! When calling "xml2eg_parse_memory" memory was allocated in the "doc" object. ! This memory is freed by "xml2eg_free_doc(doc)" call xml2eg_free_doc(doc) out_output = in_input + value_int return end subroutine
Run an example:
$ module load imasenv/3.24.0/rc # load environment if not set $ ./run_test.sh Compilation - OK Skipping log removal FC2K build for primitives with params - OK Skipping log removal Workflow execution: primitives with params - OK Skipping log removal Checking output - should be equal to '3' - OK Skipping log removal
Investigate test.log file to find more detailed information on this example.