

{"id":229,"date":"2017-10-24T10:50:27","date_gmt":"2017-10-24T08:50:27","guid":{"rendered":"https:\/\/project.inria.fr\/damaris\/?page_id=229"},"modified":"2023-08-29T10:31:11","modified_gmt":"2023-08-29T08:31:11","slug":"data-description","status":"publish","type":"page","link":"https:\/\/project.inria.fr\/damaris\/data-description\/","title":{"rendered":"Data Description"},"content":{"rendered":"\n<p>In previous pages, you learnt how to instrument a simulation to benefit from Damaris. Now, it is time to describe and then write simulation data to Damaris. This page&nbsp;explains how to describe data in the Damaris XML file and how to access the values at run time. All the data&nbsp;items must be described in the XML configuration within the &lt;data&gt; section.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Parameters<\/h4>\n\n\n\n<p>Parameters are simple values associated with a name and a type. They allow us to easily change some&nbsp;important values of the simulation automatically at runtime and Damaris updates all variables and objects that depend on&nbsp;them. In the following, you can see how to define&nbsp;a parameter with a default value. Parameters must be defined at the root of the &lt;data&gt; section, not&nbsp;within nested groups (explained later).<\/p>\n\n\n\n<pre lang=\"xml\" line=\"1\">\n <data>\n    <parameter name=\"w\" type=\"int\" value=\"2\" \/>\n<\/data>\n<\/pre>\n\n\n\n<p>Parameters must have a valid name, i.e., they should not contain any space or special symbols, and&nbsp;should not start with a digit. Basically any name that is valid as a variable name in C or Fortran is a valid&nbsp;parameter name in Damaris. The type attribute must be one of the types listed in <a href=\"https:\/\/project.inria.fr\/damaris\/damaris-types\/\">Damaris data types<\/a>.&nbsp;The provided value must be acceptable for the specified type. For instance value=&#8221;xyz&#8221; is not valid&nbsp;for an integer parameter.<\/p>\n\n\n\n<p>The below listings show how to get and set parameters at run time from the simulation. Please note that when a process modifies a parameter, this modification is local and not visible to other processes or&nbsp;to dedicated cores\/nodes. The user is responsible for synchronizing all processes when a parameter&nbsp;has to be changed globally.<\/p>\n\n\n\n<pre lang=\"c\" line=\"1\">\n int w_in ;\n int err = damaris_parameter_get (\"w\", &w_in , sizeof (int)) ;\n\n int w_out = 4 ;\n int err = damaris_parameter_set(\"w\", &w_out , sizeof (int)) ;\n<\/pre>\n\n\n\n<p>And for Fortran:<\/p>\n\n\n\n<pre lang=\"fortran\" line=\"1\"> integer: : w_in , w_out\n integer&nbsp;:: ierr\n ...\n\n call damaris_parameter_get_f (\"w\" , w_in , SIZEOF(w_in) , ierr )\n\n w_out = 4\n call damaris_parameter_set_f (\"w\" , w_out , SIZEOF(w_out) , ierr )\n<\/pre>\n\n\n\n<p>Parameters are especially useful in the definition of layouts, which are described in the following part of this document.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Layouts<\/h4>\n\n\n\n<p>Layouts describe the shape of the data. <em>Damaris<\/em> separates the description from the description of&nbsp;the variables themselves since several variables can have the same layout. A layout is characterized&nbsp;by a name, a base type and a list of dimensions. The description allows Damaris to allocate the correct amount of shared memory needed for a variable. Two examples are given in the following listing.<\/p>\n\n\n\n<pre lang=\"xml\" line=\"1\"> <data>\n    <layout name=\"a 3D layout\" type=\"int\" dimensions=\"1,4,32\" \/>\n    <layout name=\"a parameterized layout\" type=\"float\" dimensions=\"w4 ,h\/2\", global=\"100*w, 8*h\" \/>\n<\/data> <\/pre>\n\n\n\n<p>The name of a layout can be any string not including the &#8220;\/&#8221; character (it can include special&nbsp;characters, white spaces, numbers, etc. even though we advise to keep it simple and use classic C&nbsp;identifiers). The name cannot be the name of a basic type (such as int). The type should be one&nbsp;of the basic types listed in <a href=\"https:\/\/project.inria.fr\/damaris\/damaris-types\/\">Damaris data types<\/a>. The list of dimensions is a comma-separated list of&nbsp;arithmetical expression featuring +, -, *, \/, %, parenthesis, numbers and any defined int parameters&nbsp;(as of today, only int and integer parameters are allowed, short and long will produce an error). The global attribute is specified so that output functionality that needs a global size for the data can efficiently allocated it (such as HDF5 Collective output) In&nbsp;the example above, the first layout has three dimensions and the second one has two dimensions.<br>When a layout depends on parameters, any modification of the parameters will automatically&nbsp;modify the layout. Like parameters, the layout is only locally affected and the modification is not&nbsp;propagated to other processes. Making a layout depend on a parameter and changing the parameter at&nbsp;run time can be very useful for particle-based simulations, where the number of particles is different at&nbsp;each process, or simply to make the XML file independent of the simulation size and avoid changing&nbsp;the parameters every time the size changes.<br>The description of a layout will be used when writing a variable. Note that a modification in a&nbsp;layout at run time (through a modification of a parameter) will not affect previously-written iterations&nbsp;of a variable. It only affects the upcoming ones.<\/p>\n\n\n\n<p><strong>Note:<\/strong> string and label data types are variable-length types, thus the dimension of the layout corresponds to the number of characters that the variable can store.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Variables and groups<\/h4>\n\n\n\n<h5 class=\"wp-block-heading\">XML description<\/h5>\n\n\n\n<p>Actual data is described through the &lt;variable&gt; and &lt;group&gt; nodes, which allow to build a hierarchy&nbsp;of variables. An example is given as depicted below. Each variable must be given a name, and be associated&nbsp;with a defined layout. These are the two mandatory attributes. The time-varying attribute indicates&nbsp;whether a variable is expected to be written at every iteration, or just once at the beginning of&nbsp;the simulation (i.e., before the first call to damaris_end_iteration). The visualizable attribute&nbsp;indicates that a variable is visualizable by visualization backends (for instance, coordinate arrays<br>are not visualizable). In the following example, we expect the x coordinates variable to be the&nbsp;coordinate of points in a rectilinear grid. This data is not itself visualizable, however a rectilinear grid&nbsp;(later described) will be a visualizable object. Note that one can use a basic type instead&nbsp;of a layout, as for the simple var variable: basic types are already interpreted as layouts.<\/p>\n\n\n\n<pre lang=\"xml\" line=\"1\">  <data>\n    <variable name=\"x_coordinates\" layout=\"a layout\" visualizable=\"false\" \n              time-varying=\"false\" \/>\n    <group name=\"my group\">;\n        <variable name=\"temperature\" layout=\"some other layout\" \/>\n    <\/group>\n    <variable name=\"simple var\" layout=\"int\" \/>\n<\/data>\n<\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Relative and absolute names<\/h5>\n\n\n\n<p>Variables and layouts can be defined within groups. In Listing 6, the relative name of the temperature&nbsp;variable is &#8220;<em>temperature<\/em>&#8220;, while its absolute name is &#8220;<em>my group\/temperature<\/em>&#8220;. The same goes for the<br>name of layouts.<br>When <em>Damaris<\/em> searches for a layout associated with a variable, it first looks inside the group&nbsp;where the variable is defined, then in the parent group, and so on. It is thus possible to refer to a&nbsp;layout either with its absolute name (if the layout is located in a different group) or with a relative&nbsp;name if the layout can be found in the same group hierarchy.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Writing full variables<\/h5>\n\n\n\n<p>Now that the data is described, we can write it from the simulation. The two samples codes that are shown below present&nbsp;how to write a variable. The full name of the variable should be provided.<\/p>\n\n\n\n<pre lang=\"c\" line=\"1\"> \nfloat data ;\n ...\n int err = damaris_write(\"my group\/temperature\" , data) ;\n<\/pre>\n\n\n\n<p>And for Fortran:<\/p>\n\n\n\n<pre lang=\"fortran\" line=\"1\"> \n real , dimension ( : ) :: mydata\n integer :: ierr\n ...\n call damaris_write_f (\"my group\/temperature\" , mydata , ierr )\n<\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Writing multiple domains<\/h5>\n\n\n\n<p>By default, Damaris expects one block of data per client and per variable. It may be necessary for&nbsp;a client to write multiple blocks of a single variable. To do so, the number of domains have to be&nbsp;specified in the domains section of the XML file, as shown here.<\/p>\n\n\n\n<pre lang=\"xml\" line=\"1\">\n<domains count=\"4\"\/>\n<\/pre>\n\n\n\n<p>This number is a maximum, a client may write less domains, but not more. Besides, if a client writes N domains, it must identify them from 0 to N-1. The below sample code shows how to write&nbsp;multiple blocks. Each block is expected to have the size and shape defined in the layout associated with the variable.<\/p>\n\n\n\n<pre lang=\"c\" line=\"1\">float data[4];\n ...\n for (i=0; i < 4; i++)\n int err = damaris_write_block(\"my group\/temperature\" , i , data);\n<\/pre>\n\n\n\n<p>And for Fortran:<\/p>\n\n\n\n<pre lang=\"fortran\" line=\"1\"> real , dimension(0:3,:) :: mydata\n integer :: i , ierr\n ...\n call damaris_write_block_f(\"my group\/temperature\" , i , mydata (i) , ierr )\n<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">A Visual Example<\/h4>\n\n\n\n<p>A more complete example of a simple decomposition of a 2D matrix into a distributed variable is as follows and is similar to what is present in the Damaris examples directory (providing Damaris was installed with HDF5 support)<\/p>\n\n\n\n<pre lang=\"bash\" line=\"1\">\ncd <damaris install path>\/examples\/damaris\/storage \n\n# 4 Damaris clients and 1 Damaris server\nmpirun -np 5 .\/2dmesh 2dmesh.xml\n<\/pre>\n\n\n\n<p>An excerpt of the 2dmesh.xml file is as follows:<\/p>\n\n\n\n<pre lang=\"xml\" line=\"1\"> \n<data>\n<paramater name=\"HEIGHT\" type=\"int\" value=\"8\" \/>\n<paramater name=\"WIDTH\" type=\"int\" value=\"4\" \/> \n<parameter name=\"size\" type=\"int\" value=\"2\"\/> \n<layout name=\"var_layout\" type=\"float\"\n            dimensions=\"HEIGHT\/size, WIDTH\/size\"\n            global=\"HEIGHT, WIDTH\" \/>\n<variable name=\"var_array\" layout=\"var_layout\"\n           time-varying=\"true\" \/>   \n<\/data> <\/pre>\n\n\n\n<p>The full dataset can be visualised like this:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/project.inria.fr\/damaris\/files\/2023\/03\/Damaris_full_domain.drawio.png\" alt=\"\" class=\"wp-image-1041\"\/><\/figure><\/div>\n\n\n\n<p>Next we show the decomposition into MPI ranks and the use of damaris_set_position() to specify the offsets of the global decomposition: <\/p>\n\n\n\n<pre lang=\"c\" line=\"1\"> \n\/\/ 2D domain\nint dims = 2 ;   \n\/\/ array for offset values    \nint64_t pos[dims]; \n\/\/ values dependent on MPI process \n\/\/ This is for Damaris client process 0\npos[0] = 0 ;         \npos[1] = 0 ;\ndamaris_set_position(\"var_array\", pos)\n<\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/project.inria.fr\/damaris\/files\/2023\/03\/Damaris_distributed_domain.drawio-1.png\" alt=\"\" class=\"wp-image-1041\"\/><\/figure><\/div>\n\n\n\n<p>In the following we see the final result after the damaris_write() call that places a copy of the data into shared memory and is now available for the Damaris server rank to process<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/project.inria.fr\/damaris\/files\/2023\/03\/Damaris_server_process_shmem.drawio.png\" alt=\"\" class=\"wp-image-1041\"\/><\/figure><\/div>\n\n\n\n<p>Layouts may also specify a <code>ghosts<\/code>&nbsp; attribute that describes a constant padding on the boundary edges of a data array. Ghost attributes may also use parameters to allow for a changing amount of padding. Each dimension of an array specifies 2 ghost values, one for each edge of the data along a particular axis.<\/p>\n\n\n\n<p>An example of the layout XML with the ghosts attribute added and a diagram that visualizes the layout for gc0 and gc1 = 2 and gr0 and gr1 = 1 is presented below:<\/p>\n\n\n\n<pre lang=\"xml\" line=\"1\"> \n<paramater name=\"gc0\" type=\"int\" value=\"2\" \/>\n<paramater name=\"gc1\" type=\"int\" value=\"2\" \/>\n<paramater name=\"gr0\" type=\"int\" value=\"1\" \/>\n<paramater name=\"gr1\" type=\"int\" value=\"1\" \/>\n...\n<layout name=\"var_layout_with_ghosts\" type=\"float\" dimensions=\"HEIGHT\/size+gc0+gc1 ,WIDTH\/size+gr0+gr1\" \n             global=\"HEIGHT, WIDTH\"  ghosts=\"gc0:gc1, gr0:gr1\" \/> \n<\/pre>\n\n\n\n<p>The variable that supports the var_layout_with_ghosts above includes the extra padding of the ghost zones, however HDF5 and Visit plugins will automatically remove these extra areas to save the unique data only (ghost zones are usually shared data across ranks who share boundaries. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/project.inria.fr\/damaris\/files\/2023\/03\/Damaris_ghost_zone_diagram.drawio.png\" alt=\"\" class=\"wp-image-1041\"\/><\/figure><\/div>\n\n\n\n<h5 class=\"wp-block-heading\">Meshes<\/h5>\n\n\n\n<p>Please see the documentation on in-situ vizulisation for descriptions and examples of the mesh xml<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/project.inria.fr\/damaris\/visit-connector\/\">VisIt<\/a><\/li><li><a href=\"https:\/\/project.inria.fr\/damaris\/paraview-connector\/\">ParaView <\/a><\/li><\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Direct access to the shared memory<\/h5>\n\n\n\n<p>The API presented above has the disadvantage of copying local data into the shared memory. A&nbsp;more efficient way of proceeding consists of getting direct access to the shared memory. The two below sample codes present this capability available through the use of <em>damaris_alloc()<\/em>.&nbsp; If <em>damaris_alloc<\/em> fails, it will produce a NULL pointer. Otherwise, a valid pointer to an allocated region of shared memory is produced. After writing the data to the returned buffer, a call to&nbsp;<em>damaris_commit<\/em> will notify the server of the presence of new data. After this call, the user is not&nbsp;expected to write the data anymore. Finally <em>damaris_clear<\/em> indicates that the client delegates full&nbsp;responsibility to the servers for the data. It is not supposed to be read nor written anymore. Equivalent functions (<em>damaris_alloc_block<\/em> and <em>damaris_alloc_block_f<\/em>) exist to allocate blocks when each&nbsp;client handles multiple domains.\n<p>Please note, the Damaris variable must be have a valid size <em>before<\/em> the call to <em>damaris_alloc<\/em>, so that the pointer requested has the required space in the allocated shared memory region. This size is specified by the variables XML Layout element and this can require setting Damaris parameter value(s) (using <em>damaris_parameter_set()<\/em>) to allow for dynamic sizing of the memory area being requested.<\/p><\/p>\n\n\n\n<pre lang=\"c\" line=\"1\"> float data;\n int err;\n err = damaris_alloc(\"my group\/temperature\" , &data);\n ...\n \/\/ done writing data for this iteration\n err = damaris_commit (\"my group\/temperature\") ;\n ...\n \/\/ done accessing data for this iteration\n err = damaris_clear(\"my group\/temperature\") ;\n<\/pre>\n\n\n\n<p>And for Fortran:<\/p>\n\n\n\n<pre lang=\"fortran\" line=\"1\"> use Damaris\n type (c_ptr) :: cptr\n integer :: ierr\n real , pointer :: mydata (:,:,:)\n ...\n cptr = damaris_alloc_f (\"my group\/temperature\" , ierr)\n call c_f_pointer(cptr ,mydata , [ 64 , 16 , 4 ] )\n ...\n call damaris_commit_f(\"my group\/temperature\" , ierr)\n ...\n call damaris_clear_f(\"my group\/temperature\" , ierr)\n<\/pre>\n\n\n\n<p>Due to the C\/Fortran interface, the use of <em>damaris_alloc_f<\/em> is more complex in Fortran than in C.&nbsp;The <em>Damaris<\/em> module should be used (this module is located where <em>Damaris<\/em> is installed).&nbsp;An additional call to <a href=\"https:\/\/gcc.gnu.org\/onlinedocs\/gfortran\/C_005fF_005fPOINTER.html\"><em>c_f_pointer<\/em><\/a> is mandatory to convert the returned C pointer into a valid Fortran&nbsp;array. This function takes a shape array to provide the extents along each dimension.<br>Note that it can be desirable, in order to implement efficient double-buffering, that a client waits&nbsp;some iterations before actually committing a variable. Different versions of the function are available:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><em> damaris_commit(const char* var) :<\/em><br>commits all the blocks of the current iteration;<\/li><li>&nbsp;<em>damaris_commit_block(const char* var, int32 t block) :<\/em><br>commits one specific block of the current iteration;<\/li><li><em>damaris_commit_iteration(const char* var, int32 t iteration) :<\/em><br>commits all the blocks of a specific iteration;<\/li><li><em>damaris_commit_block_iteration(const char* var, int32 t block, int32 t iteration)<\/em><br>commits one specific block of a specific iteration.<\/li><li>Equivalent functions are available in Fortran: <em>damaris_commit_f<\/em>, <em>damaris_commit_block_f<\/em>,<br><em>damaris_commit_iteration_f<\/em> and <em>damaris_commit_block_iteration_f<\/em>. All take an ierr integer in<br>addition to the same parameters as the C functions.<\/li><\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Error handling<\/h5>\n\n\n\n<p>Since damaris_write and damaris_alloc (and corresponding functions for writing or allocating&nbsp;blocks) both require to allocate a portion of shared memory, a call may fail if the shared memory&nbsp;is full. When this happens all subsequent calls to damaris_write or damaris_alloc up to the next&nbsp;call to damaris_end_iteration will return with an error without attempting to allocate memory. A&nbsp;special signal will be sent to all the servers when calling damaris_end_iteration, which informs the&nbsp;servers that some data are missing for this iteration. By default, the dedicated cores will not update&nbsp;potentially connected visualization backends, and will delete from memory the data that has been written successfully for this iteration. Over-riding this default behavior will be covered in the documentations of <a href=\"https:\/\/project.inria.fr\/damaris\/damaris-plug-ins\/\">Damaris plug-ins<\/a>.<\/p>\n\n\n\n<p>Next: <a href=\"https:\/\/project.inria.fr\/damaris\/damaris-configuration\/\">Damaris Configuration<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In previous pages, you learnt how to instrument a simulation to benefit from Damaris. Now, it is time to describe and then write simulation data to Damaris. This page&nbsp;explains how to describe data in the Damaris XML file and how to access the values at run time. All the data&nbsp;items&#8230;<\/p>\n<p> <a class=\"continue-reading-link\" href=\"https:\/\/project.inria.fr\/damaris\/data-description\/\"><span>Continue reading<\/span><i class=\"crycon-right-dir\"><\/i><\/a> <\/p>\n","protected":false},"author":1249,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-229","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/project.inria.fr\/damaris\/wp-json\/wp\/v2\/pages\/229","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/project.inria.fr\/damaris\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/project.inria.fr\/damaris\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/project.inria.fr\/damaris\/wp-json\/wp\/v2\/users\/1249"}],"replies":[{"embeddable":true,"href":"https:\/\/project.inria.fr\/damaris\/wp-json\/wp\/v2\/comments?post=229"}],"version-history":[{"count":95,"href":"https:\/\/project.inria.fr\/damaris\/wp-json\/wp\/v2\/pages\/229\/revisions"}],"predecessor-version":[{"id":1195,"href":"https:\/\/project.inria.fr\/damaris\/wp-json\/wp\/v2\/pages\/229\/revisions\/1195"}],"wp:attachment":[{"href":"https:\/\/project.inria.fr\/damaris\/wp-json\/wp\/v2\/media?parent=229"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}