Skip to content

Loading a VTU mesh

Rafael Sachetto edited this page Mar 25, 2021 · 7 revisions

Converting a VTU mesh and creating a custom function to load it.

Step 1 - Downloading and compiling the mesh conversion tool (this tool needs the VTK library and the cmake tool installed)

git clone https://github.com/rsachetto/hexa-mesh-from-VTK.git
cd hexa-mesh-from-VTK/
cmake .
make

Step 2 - Converting a mesh extracting only the geometry:

./bin/HexaMeshFromVTK -i vtu_mesh --dx new_mesh_dx --dy new_mesh_dy --dz new_mesh_dz -r unit_conversion_rate -o output_filename

where dx, dy and dz are the new mesh discretization, using the same spatial unit of the original mesh.

Step 3 - Creating the domain function to load the new converted mesh:

./mono domain new_custom_mesh

Now we can edit the function new_custom_mesh created in src/domains_library/custom_functions.c The function below is used to load the rabbit mesh available in the simulator:

SET_SPATIAL_DOMAIN(new_custom_mesh) {

    real_cpu start_discretization = 250;

    char *mesh_file = NULL;
    GET_PARAMETER_STRING_VALUE_OR_REPORT_ERROR(mesh_file, config, "mesh_file");

    real_cpu maximum_discretization = start_discretization;
    GET_PARAMETER_NUMERIC_VALUE_OR_USE_DEFAULT(real_cpu, maximum_discretization, config, "maximum_discretization");

    log_info("Loading Custom Mesh\n");

    int num_volumes = 470197;

    int num_loaded = set_custom_mesh_from_file(the_grid, mesh_file, num_volumes, start_discretization, 0, NULL);

    log_info("Read %d volumes from file: %s\n", num_loaded, mesh_file);

    free(mesh_file);

    the_grid->start_discretization = SAME_POINT3D(start_discretization);
    the_grid->max_discretization = SAME_POINT3D(maximum_discretization);

    return num_loaded > 0;

}

Converting a VTU mesh with extra information and creating a custom function to load it.

Step 1 - Check your mesh (with Paraview for instance) to see the data types (int, double or float) and where the data that you want to load is located (cell or point)

Step 2 - Create a configuration file for the conversion tool with the information about the data to be extracted (example below):

[scarTissue]
type=int
location=cell
n_components=1

[cardiacRegion]
type=int
location=cell
n_components=1

[FibreOrientation]
type=float
location=cell
n_components=3

The arrays will be saved in order of appearance in the .ini file, after the mesh's geometric information. For instance, a line of the converted mesh using this config file would be like below:

center_x,center_y,center_z,scarTissue_value,cardiacRegion_value,FibreOrientation1,FibreOrientation2,FibreOrientation3

Step 3 - Converting the mesh extracting the configured information:

./bin/HexaMeshFromVTK -i vtu_mesh --dx new_mesh_dx --dy new_mesh_dy --dz new_mesh_dz -r unit_conversion_rate -o output_filename -c config_file

Step 4 - Creating the function to load the mesh and the extra information:

First you will have to create a proper data structure to hold the mesh information. For instance, the struct below could be used to hold the information about the mesh converted with the configuration presented before:

struct custom_mesh_info {
	bool fibrotic;
	bool border_zone;
	int tissue_type;
};

Step 4 - Writing the functions to set the custom data and load the domain:

SET_CUSTOM_DATA_FOR_MESH(set_custom_data_for_custom_mesh) {

	ALLOCATE_MESH_INFO(cell, custom_mesh_info);

	MESH_INFO_DATA(cell, custom_mesh_info, tissue_type) = custom_data[0];
	MESH_INFO_DATA(cell, custom_mesh_info, fibrotic)    = (custom_data[1] == 2);
	MESH_INFO_DATA(cell, custom_mesh_info, border_zone) = (custom_data[1] == 1);

	cell->sigma.fibers.f[0] = custom_data[2];
	cell->sigma.fibers.f[1] = custom_data[3];
	cell->sigma.fibers.f[2] = custom_data[4];
}
SET_SPATIAL_DOMAIN(initialize_grid_with_custom_mesh_with_scar_and_fibers) {

    char *mesh_file = NULL;
    GET_PARAMETER_STRING_VALUE_OR_REPORT_ERROR(mesh_file, config, "mesh_file");

    real_cpu start_h = 500.0;
    GET_PARAMETER_NUMERIC_VALUE_OR_USE_DEFAULT(real_cpu, start_h, config, "original_discretization");

    real_cpu desired_h = 500.0;
    GET_PARAMETER_NUMERIC_VALUE_OR_USE_DEFAULT(real_cpu, desired_h, config, "desired_discretization");

    assert(the_grid);

    log_info("Loading Atrial Heart Mesh with discretization: %lf\n", desired_h);

    uint32_t num_volumes = 514389;
    GET_PARAMETER_NUMERIC_VALUE_OR_USE_DEFAULT(uint32_t, num_volumes, config, "num_volumes");

    uint32_t num_extra_fields = 5;
    GET_PARAMETER_NUMERIC_VALUE_OR_USE_DEFAULT(uint32_t, num_extra_fields, config, "num_extra_fields");

    int num_loaded = set_custom_mesh_from_file(the_grid, mesh_file, num_volumes, start_h, num_extra_fields, set_custom_data_for_scv_mesh);

    log_info("Read %d volumes from file: %s\n", num_loaded, mesh_file);

    int num_refs_remaining = (int)(start_h / desired_h) - 1;

    if(num_refs_remaining > 0)
    refine_grid(the_grid, num_refs_remaining);

    the_grid->start_discretization = SAME_POINT3D(desired_h);

    free(mesh_file);

    return num_loaded;
}