    

 ## On this page

  

 

 # DVS Reader

 Last update: 16.07.2025 

DVS Reader API can be used to read data from a cache.

DVS Reader API can be used to read data from a cache.

The DVS Reader API is an external API to allow applications to read data from a DVS Cache

The API is built around using chained queries and filtering (dvs\_filtering\_overview) to select what data you are interested in and then iterate over that data. You start with a high level [DVS::IQuery](class_d_v_s_1_1_i_query.html "The query interface for the DVS Reader API."), add filters based on what you are interesting in looking at and then make calls to iterate over the data. The filtering mechanism is used to let you iterate over the data in different axis. Eg. A single part over all of time or all parts over a specific timestep. The filtering also allows for letting you set your parallelism model. I.E. if the data was written with 3 DVS servers you can easily tell it if you want to process all data at once (eg. 1 postprocessing processes) or possibly round robin them (eg. 2 postprocessing processes). This should be clearer in the examples [DVS Reader Examples](#dvs_reader_examples).

---

### Table of Contents

---

- [DVS Reader Data Model](#dvs_reader_data_model)
- [DVS Reader Examples](#dvs_reader_examples)

---

---

## <a class="anchor" id="dvs_reader_data_model"></a>DVS Reader Data Model

A conceptual view of the DVS Reader data model is below.

![](/sites/default/files/migrate-content/ensight_2025_r2_1/dvs_reader_data_model_concept.png "DVS Reader Data Model")

For a high level view of the overall DVS Data model see dvs\_data\_model. A high level summary is that you start with a [DVS::IQuery](class_d_v_s_1_1_i_query.html "The query interface for the DVS Reader API.") object, point it towards a DVS URI, interrogate the data model, set filters, and then begin iterating over [DVS::IPlotChunk](class_d_v_s_1_1_i_plot_chunk.html "Plot Chunk Interface for DVS Reader API."), [DVS::IMeshChunk](class_d_v_s_1_1_i_mesh_chunk.html "Mesh Chunk Interface for DVS Reader API."), and [DVS::IElementBlock](class_d_v_s_1_1_i_element_block.html "Element Block Interface for DVS Reader API.") objects. The [DVS::IPlotChunk](class_d_v_s_1_1_i_plot_chunk.html "Plot Chunk Interface for DVS Reader API.") and [DVS::IMeshChunk](class_d_v_s_1_1_i_mesh_chunk.html "Mesh Chunk Interface for DVS Reader API.") objects each refer to a unique tuple of {Time,Object,Rank,Chunk} where Object is based on the Part or Plot they refer to.

[DVS::IPlotChunk](class_d_v_s_1_1_i_plot_chunk.html "Plot Chunk Interface for DVS Reader API.") objects shouldn't need to be split into rank/chunks. Currently EnSight expects to only see one [DVS::IPlotChunk](class_d_v_s_1_1_i_plot_chunk.html "Plot Chunk Interface for DVS Reader API.") per time over all ranks/chunks.

[DVS::IMeshChunk](class_d_v_s_1_1_i_mesh_chunk.html "Mesh Chunk Interface for DVS Reader API.") is a subportion of the mesh and contains methods to get coordinates of the mesh for this chunk and nodal variable data. The elemental connectivity data for the current [DVS::IMeshChunk](class_d_v_s_1_1_i_mesh_chunk.html "Mesh Chunk Interface for DVS Reader API.") is stored on an [DVS::IElementBlock](class_d_v_s_1_1_i_element_block.html "Element Block Interface for DVS Reader API.") for each element type.

[DVS::IElementBlock](class_d_v_s_1_1_i_element_block.html "Element Block Interface for DVS Reader API.") contains the connectivity for unstructured meshes (Structured mesh connectivity is implied) and elemental variable data.

All coordinates, connectivity, and variables also contain a hash which can be used for comparison so see if the internal data is different.

---

# <a class="anchor" id="dvs_reader_getting_started"></a>Getting started with the DVS Reader API

The latest stable code and binaries and can be found in [Artifactory](http://canartifactory.ansys.com:8080/artifactory/webapp/#/artifacts/browse/tree/General/CEI_Upload/dvs). They can also be found in the EnSight install under: CEI/ensightXXX/src/readers/dvs if pulling from artifactory make sure to grab the version which matches your EnSight install if using them together.

The binaries to statically link against can be found under either linux\_2.6\_64 for Linux and win64 for Windows. For the DVS Reader API you will need the libdvsreader.lib/dll or libdvsreader.so depending on the platform.

All the headers needed for the DVS Reader API are under the include directory. The top level header being the [dvs\_query\_interface.h](dvs__query__interface_8h.html "DVS Reader API Query Interface.") which includes the [DVS::IQuery](class_d_v_s_1_1_i_query.html "The query interface for the DVS Reader API.") interface.

For examples of using the API refer to [DVS Reader Examples](#dvs_reader_examples).

---

## <a class="anchor" id="dvs_reader_examples"></a>DVS Reader Examples

## <a class="anchor" id="dvs_example_hello_world"></a>Hello World Example

Simple application to open a cache and iterate over all of the high level information it contains (datasets, timesteps, objects etc.)

\#include "[dvs\_query\_interface.h](dvs__query__interface_8h.html)"

\#include "[logger\_verbose.h](logger__verbose_8h.html)"

\#include &lt;functional&gt;

\#include &lt;memory&gt;

 

static void logging_function(void* user_data, const char* message)

{

 fprintf(stdout, message);

}

 

int [main](test__dvs__client_8c.html#a3c04138a5bfe5d72780bb7e82a18e627)(int argc, char** argv)

{

 std::unique_ptr&lt;[DVS::IQuery](class_d_v_s_1_1_i_query.html), std::function&lt;void([DVS::IQuery](class_d_v_s_1_1_i_query.html)*)&gt;&gt; dataset_query(DVS::CREATE_QUERY_INSTANCE(),

 []([DVS::IQuery](class_d_v_s_1_1_i_query.html)* p){p-&gt;[release](class_d_v_s_1_1_i_query.html#a257f79d7de21658c07dc602dfa6bbf34)();});

 dataset_query-&gt;[set\_logger](class_d_v_s_1_1_i_query.html#ab6ce54c68281ea1676af650ebc5716a0)(new [DVS::LoggerVerbose](class_d_v_s_1_1_logger_verbose.html)(nullptr, [dvs\_verbosity::DVS\_VERBOSE](dynamic__visualization__store__enums_8h.html#aafcfd80cd55c92c53106bb56fdaf026da95f57c1525070266247b1a687f565f5b), &amp;logging_function));

 //Add a cache uri to open

 auto err = dataset_query-&gt;add_uri("hdf5://localhost/D:/my/cache");

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 return err;

 }

 

 //Get all of the datasets in the cache

 uint32_t num_datasets = 0;

 err = dataset_query-&gt;get_num_datasets(num_datasets);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 fprintf (stdout, "Error getting number of datasets\\n");

 return err;

 }

 

 for (uint32_t index = 0; index &lt; num_datasets; index++)

 {

 [DVS::IDataset](class_d_v_s_1_1_i_dataset.html)* dataset = dataset_query-&gt;[get\_dataset](class_d_v_s_1_1_i_object.html#aea688a307b1cb02ae53e0e8fd3791e64)(index);

 }

 

 //Get all of the available timesteps

 uint32_t num_timesteps = 0;

 err = dataset_query-&gt;get_num_timesteps(num_timesteps);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 fprintf(stdout, "Error getting number of timesteps\\n");

 return err;

 }

 std::vector&lt;float&gt; timesteps(num_timesteps, 0.f);

 dataset_query-&gt;get_timesteps(timesteps.data());

 

 //Get all of the ranks

 uint32_t num_ranks = 0;

 err = dataset_query-&gt;get_num_ranks(num_ranks);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 fprintf(stdout, "Error getting number of ranks\\n");

 return err;

 }

 std::vector&lt;uint32_t&gt; global_ranks(num_ranks, 0);

 dataset_query-&gt;get_ranks(global_ranks.data());

 

 //Get all of the chunks for every rank

 uint32_t num_chunks_per_rank = 0;

 err = dataset_query-&gt;get_num_chunks_per_rank(num_chunks_per_rank);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 fprintf(stdout, "Error getting number of chunks per rank\\n");

 return err;

 }

 std::vector&lt;uint32_t&gt; global_chunk_max(num_chunks_per_rank, 0);

 dataset_query-&gt;get_chunks_per_rank(global_chunk_max.data());

 

 //Get all of the parts

 uint32_t num_parts = 0;

 err = dataset_query-&gt;get_num_parts(num_parts);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 fprintf(stdout, "Error getting number of parts\\n");

 return err;

 }

 

 for (uint32_t part_index = 0; part_index &lt; num_parts; part_index++) {

 [DVS::IObject](class_d_v_s_1_1_i_object.html)* part = dataset_query-&gt;get_part(part_index);

 }

 

 //Get all the plots

 uint32_t num_plots = 0;

 err = dataset_query-&gt;get_num_plots(num_plots);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 fprintf(stdout, "Error getting number of plots\\n");

 return err;

 }

 

 for (uint32_t plot_index = 0; plot_index &lt; num_plots; plot_index++)

 {

 [DVS::IObject](class_d_v_s_1_1_i_object.html)* plot = dataset_query-&gt;get_plot(plot_index);

 }

 

 //Get all the variables

 uint32_t num_vars = 0;

 err = dataset_query-&gt;get_num_variables(num_vars);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 fprintf(stdout, "Error getting number of vars\\n");

 return err;

 }

 for (uint32_t var_index = 0; var_index &lt; num_vars; var_index++)

 {

 [DVS::IVar](class_d_v_s_1_1_i_var.html)* var = dataset_query-&gt;get_variable(var_index);

 }

 return 0;

}

[DVS::IDataset](class_d_v_s_1_1_i_dataset.html)

Interface for datasets for the DVS Reader API.

**Definition** [dvs\_dataset\_interface.h:44](dvs__dataset__interface_8h_source.html#l00043)



[DVS::IObject](class_d_v_s_1_1_i_object.html)

Interface for part/plot objects for DVS Reader API.

**Definition** [dvs\_object\_interface.h:45](dvs__object__interface_8h_source.html#l00044)



[DVS::IObject::get\_dataset](class_d_v_s_1_1_i_object.html#aea688a307b1cb02ae53e0e8fd3791e64)

virtual const DVS::IDataset * get_dataset() const =0

Get the reference dataset for this object.



[DVS::IQuery](class_d_v_s_1_1_i_query.html)

The query interface for the DVS Reader API.

**Definition** [dvs\_query\_interface.h:79](dvs__query__interface_8h_source.html#l00078)



[DVS::IQuery::release](class_d_v_s_1_1_i_query.html#a257f79d7de21658c07dc602dfa6bbf34)

virtual void release()=0

Release the memory of the query.



[DVS::IQuery::set\_logger](class_d_v_s_1_1_i_query.html#ab6ce54c68281ea1676af650ebc5716a0)

virtual void set_logger(DVS::ILogger *logger)=0

Set the logger object.



[DVS::IVar](class_d_v_s_1_1_i_var.html)

Interface for variables for the DVS Reader API.

**Definition** [dvs\_var\_interface.h:58](dvs__var__interface_8h_source.html#l00057)



[DVS::LoggerVerbose](class_d_v_s_1_1_logger_verbose.html)

Logger class based on verbosity.

**Definition** [logger\_verbose.h:40](logger__verbose_8h_source.html#l00039)



[dvs\_query\_interface.h](dvs__query__interface_8h.html)

DVS Reader API Query Interface.



[DVS\_VERBOSE](dynamic__visualization__store__enums_8h.html#aafcfd80cd55c92c53106bb56fdaf026da95f57c1525070266247b1a687f565f5b)

@ DVS_VERBOSE

Displays informational messages, warnings, errors.

**Definition** [dynamic\_visualization\_store\_enums.h:101](dynamic__visualization__store__enums_8h_source.html#l00101)



[DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7)

\#define DVS_NONE

No detected error has occurred.

**Definition** [dynamic\_visualization\_store\_error\_codes.h:103](dynamic__visualization__store__error__codes_8h_source.html#l00103)



[logger\_verbose.h](logger__verbose_8h.html)

Verbosity based logger for DVS.



[main](test__dvs__client_8c.html#a3c04138a5bfe5d72780bb7e82a18e627)

int main(int argc, char **argv)

Main method of test client application.

**Definition** [test\_dvs\_client.c:57](test__dvs__client_8c_source.html#l00057)





## <a class="anchor" id="dvs_example_using_filters"></a>Using Filters Example

This is a simple example of filtering down to a specific dataset and part and then iterating over the mesh chunks. Note that since we didn't filter based on time we will find mesh chunks across all of time and will want to look at the time of each mesh chunk returned.

int [main](test__dvs__client_8c.html#a3c04138a5bfe5d72780bb7e82a18e627)(int argc, char** argv)

{

 std::unique_ptr&lt;[DVS::IQuery](class_d_v_s_1_1_i_query.html), std::function&lt;void([DVS::IQuery](class_d_v_s_1_1_i_query.html)*)&gt;&gt; dataset_query(DVS::CREATE_QUERY_INSTANCE(),

 []([DVS::IQuery](class_d_v_s_1_1_i_query.html)* p){p-&gt;[release](class_d_v_s_1_1_i_query.html#a257f79d7de21658c07dc602dfa6bbf34)();});

 dataset_query-&gt;[set\_logger](class_d_v_s_1_1_i_query.html#ab6ce54c68281ea1676af650ebc5716a0)(new [DVS::LoggerVerbose](class_d_v_s_1_1_logger_verbose.html)(nullptr, [dvs\_verbosity::DVS\_VERBOSE](dynamic__visualization__store__enums_8h.html#aafcfd80cd55c92c53106bb56fdaf026da95f57c1525070266247b1a687f565f5b), &amp;logging_function));

 //Add a cache uri to open

 auto err = dataset_query-&gt;add_uri("hdf5://localhost/D:/my/cache");

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 return err;

 }

 

 //Down select to only Parts name Part1 in dataset Dataset1

 std::string filter = "/dataset.name/eq/Dataset1//and/part.name/eq/Part1";

 

 //child\_query will be released when the parent query is released. You can release it

 //early however. If a query has a child it can no longer be modified until the children

 //are all released.

 [DVS::IQuery](class_d_v_s_1_1_i_query.html)* child_query = dataset_query-&gt;[filter](class_d_v_s_1_1_i_query.html#a8a810da09342690eb371b324079f206e)(filter);

 if (!child_query) {

 fprintf(stdout, "Error creating child query\\n");

 }

 

 uint32_t num_mesh_chunks = 0;

 err = child_query-&gt;[get\_num\_mesh\_chunks](class_d_v_s_1_1_i_query.html#a0e4ef2e5ffb8a6e3cfe1d1841ef4007b)(num_mesh_chunks);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 return err;

 }

 for (uint32_t index = 0; index &lt; num_mesh_chunks; index++) {

 [DVS::IMeshChunk](class_d_v_s_1_1_i_mesh_chunk.html)* current_chunk = child_query-&gt;[get\_mesh\_chunk](class_d_v_s_1_1_i_query.html#a00a3a6962690c69ea8cef8815a72c011)(index);

 }

 

 return 0;

}

[DVS::IMeshChunk](class_d_v_s_1_1_i_mesh_chunk.html)

Mesh Chunk Interface for DVS Reader API.

**Definition** [dvs\_mesh\_chunk\_interface.h:49](dvs__mesh__chunk__interface_8h_source.html#l00048)



[DVS::IQuery::get\_mesh\_chunk](class_d_v_s_1_1_i_query.html#a00a3a6962690c69ea8cef8815a72c011)

virtual DVS::IMeshChunk * get_mesh_chunk(uint32_t index)=0

Get the mesh chunk based on the index.



[DVS::IQuery::get\_num\_mesh\_chunks](class_d_v_s_1_1_i_query.html#a0e4ef2e5ffb8a6e3cfe1d1841ef4007b)

virtual dvs_ret get_num_mesh_chunks(uint32_t &amp;num_mesh_chunks)=0

Get the number of mesh chunks for this query.



[DVS::IQuery::filter](class_d_v_s_1_1_i_query.html#a8a810da09342690eb371b324079f206e)

virtual DVS::IQuery * filter(const char *filter)=0

The filter method will allocate a new chained query with the passed in filter appended to it.





## <a class="anchor" id="dvs_example_parallelism"></a>Setting up for parallel reads of cache

This is an example of querying a cache for how many servers it was written with and round robining the cache across parallel readers.

**Server 1 of 2**

int [main](test__dvs__client_8c.html#a3c04138a5bfe5d72780bb7e82a18e627)(int argc, char** argv)

{

 std::string cache_uri = hdf5://localhost/D:/my/cache;

 uint32_t num_servers = 0;

 {

 [DVS::IQuery](class_d_v_s_1_1_i_query.html)* server_query = DVS::CREATE_QUERY_INSTANCE();

 auto err = server_query-&gt;[get\_num\_servers](class_d_v_s_1_1_i_query.html#a05dc766c5d6789ca3dcbab72cf4ca4e9)(cache, num_servers);

 if (err != [DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7)) {

 //There might be an error if the cache uri is invalid or

 //if there is a problem with the cache

 fprintf(stdout, "Error getting number of servers\\n");

 return err;

 }

 server_query-&gt;[release](class_d_v_s_1_1_i_query.html#a257f79d7de21658c07dc602dfa6bbf34)();

 }

 

 if (num_servers == 0 ) {

 fprintf(stdout, "Number of servers should be &gt;= 1);

 return -1;

 }

 else if (num\_server == 1) {

 //This isn't a problem except the round robining won't work in this example

 //since the second parallel reader won't get any data.

 fprintf(stdout, "Warning, cache was written with only one server\n");

 }

 

 std::unique\_ptr&lt;DVS::IQuery, std::function&lt;void(DVS::IQuery\*)&gt;&gt; query(DVS::CREATE\_QUERY\_INSTANCE(),

 \[\](DVS::IQuery\* p){p-&gt;release();});

 query-&gt;set\_logger(new DVS::LoggerVerbose(nullptr, dvs\_verbosity::DVS\_VERBOSE, &amp;logging\_function));

 

 //Add a cache uri to open

 auto err = query-&gt;add\_uri("hdf5://localhost/D:/my/cache");

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 return err;

 }

 //reader\_number and num\_readers should be programatically determined, not hardcoded like this

 uint32_t reader_number = 0;

 uint32_t num_readers = 2;

 //This will round robin the cache folders across readers

 //Setting num\_readers = 0 tells the query to read the folder corresponding to reader\_number and

 //no others.

 query-&gt;set_server_mod(reader_number, num_readers);

 

 //Get all of the parts

 uint32_t num_parts = 0;

 err = dataset_query-&gt;get_num_parts(num_parts);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 fprintf(stdout, "Error getting number of parts\\n");

 return err;

 }

 

 for (uint32_t part_index = 0; part_index &lt; num_parts; part_index++) {

 [DVS::IObject](class_d_v_s_1_1_i_object.html)* part = dataset_query-&gt;get_part(part_index);

 }

 

 return 0;

}

[DVS::IQuery::get\_num\_servers](class_d_v_s_1_1_i_query.html#a05dc766c5d6789ca3dcbab72cf4ca4e9)

virtual dvs_ret get_num_servers(const char *uri, uint32_t &amp;num_servers)=0

Get the num servers object.





**Server 2 of 2**

int [main](test__dvs__client_8c.html#a3c04138a5bfe5d72780bb7e82a18e627)(int argc, char** argv)

{

 std::string cache_uri = hdf5://localhost/D:/my/cache;

 uint32_t num_servers = 0;

 {

 [DVS::IQuery](class_d_v_s_1_1_i_query.html)* server_query = DVS::CREATE_QUERY_INSTANCE();

 auto err = server_query-&gt;[get\_num\_servers](class_d_v_s_1_1_i_query.html#a05dc766c5d6789ca3dcbab72cf4ca4e9)(cache, num_servers);

 if (err != [DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7)) {

 //There might be an error if the cache uri is invalid or

 //if there is a problem with the cache

 fprintf(stdout, "Error getting number of servers\\n");

 return err;

 }

 server_query-&gt;[release](class_d_v_s_1_1_i_query.html#a257f79d7de21658c07dc602dfa6bbf34)();

 }

 

 if (num_servers == 0 ) {

 fprintf(stdout, "Number of servers should be &gt;= 1);

 return -1;

 }

 else if (num\_server == 1) {

 //This isn't a problem except the round robining won't work in this example

 //since the second parallel reader won't get any data.

 fprintf(stdout, "Warning, cache was written with only one server\n");

 }

 

 std::unique\_ptr&lt;DVS::IQuery, std::function&lt;void(DVS::IQuery\*)&gt;&gt; query(DVS::CREATE\_QUERY\_INSTANCE(),

 \[\](DVS::IQuery\* p){p-&gt;release();});

 query-&gt;set\_logger(new DVS::LoggerVerbose(nullptr, dvs\_verbosity::DVS\_VERBOSE, &amp;logging\_function));

 

 //Add a cache uri to open

 auto err = query-&gt;add\_uri("hdf5://localhost/D:/my/cache");

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 return err;

 }

 //reader\_number and num\_readers should be programatically determined, not hardcoded like this

 uint32_t reader_number = 1;

 uint32_t num_readers = 2;

 //This will round robin the cache folders across readers

 //Setting num\_readers = 0 tells the query to read the folder corresponding to reader\_number and

 //no others.

 query-&gt;set_server_mod(reader_number, num_readers);

 

 //Get all of the parts

 uint32_t num_parts = 0;

 err = dataset_query-&gt;get_num_parts(num_parts);

 if ([DVS\_NONE](dynamic__visualization__store__error__codes_8h.html#a83b88ce16159d34fe5ce63e7024462a7) != err) {

 fprintf(stdout, "Error getting number of parts\\n");

 return err;

 }

 

 for (uint32_t part_index = 0; part_index &lt; num_parts; part_index++) {

 [DVS::IObject](class_d_v_s_1_1_i_object.html)* part = dataset_query-&gt;get_part(part_index);

 }

 

 return 0;

}