|
My Project
programmer's documentation
|
Output meshes defined by user-defined functions
More advanced mesh element selection is possible using cs_post_define_volume_mesh_by_func or cs_post_define_surface_mesh_by_func, which allow defining volume or surface meshes using user-defined element lists.
The possibility to modify a mesh over time is limited by the most restrictive writer which is associated with. For instance, if writer 1 allows the modification of the mesh topology (argument time_dep
= FVM_WRITER_TRANSIENT_CONNECT in the call to cs_post_define_writer) and writer 2 allows no modification (time_dep
= FVM_WRITER_FIXED_MESH), a user post-processing mesh associated with writers 1 and 2 will not be modifiable, but a mesh associated with writer 1 only will be modifiable. The modification can be done by using the advanced cs_post_define_volume_mesh_by_func or cs_post_define_surface_mesh_by_func, associated with a user-defined selection function based on time-varying criteria (such as field values being above a given threshold). If the time_dep
argument is set to true
, the mesh will be redefined using the selection function at each output time step for every modifiable mesh.
Example: surface mesh with complex selection criteria
In the following example, we build a surface mesh containing interior faces separating cells of group "2" from those of group "3", (assuming no cell has both colors), as well as boundary faces of group "4".
This is done by first defining 2 selection functions, whose arguments and behavior match the cs_post_elt_select_t type.
The function for selection of interior faces separating cells of two groups also illustrates the usage of the cs_selector_get_family_list function to build a mask allowing direct checking of this criterion when comparing cells adjacent to a given face:
static void
_i_faces_select_example(
void *
input,
{
int *family_mask = NULL;
family_mask[i] = 0;
for (i = 0; i < n_families; i++)
family_mask[family_list[i] - 1] += 1;
for (i = 0; i < n_families; i++)
family_mask[family_list[i] - 1] += 2;
for (face_id = 0; face_id < m->
n_i_faces; face_id++) {
if ((iflag1 == 1 && iflag2 == 2) || (iflag1 == 2 && iflag2 == 1)) {
i_face_ids[n_i_faces] = face_id;
n_i_faces += 1;
}
}
*n_faces = n_i_faces;
*face_ids = i_face_ids;
}
The function for selection of boundary faces is simpler, as it simply needs to apply the selection criterion for boundary faces:
static void
_i_faces_select_example(
void *
input,
{
int *family_mask = NULL;
family_mask[i] = 0;
for (i = 0; i < n_families; i++)
family_mask[family_list[i] - 1] += 1;
for (i = 0; i < n_families; i++)
family_mask[family_list[i] - 1] += 2;
for (face_id = 0; face_id < m->
n_i_faces; face_id++) {
if ((iflag1 == 1 && iflag2 == 2) || (iflag1 == 2 && iflag2 == 1)) {
i_face_ids[n_i_faces] = face_id;
n_i_faces += 1;
}
}
*n_faces = n_i_faces;
*face_ids = i_face_ids;
}
Given these tow functions, the mesh can be defined using the cs_post_define_surface_mesh_by_func function, passing it the user-defined selection functions (actually, function pointers):
{
const int n_writers = 1;
const int writer_ids[] = {1};
"Mixed surface",
_i_faces_select_example,
_b_faces_select_example,
NULL,
NULL,
false,
false,
false,
n_writers,
writer_ids);
}
Example: time-varying mesh
A mesh defined through the advanced cs_post_define_surface_mesh_by_func, cs_post_define_volume_mesh_by_func, or cs_post_define_particles_mesh_by_func may vary in time, as long as the matching time_varying
argument is set to true
, and the mesh (or aliases thereof) id only associated to writers defined with the FVM_WRITER_TRANSIENT_CONNECT option. In the case of particles, which always vary in time, this allows also varying the selection (filter) function with time.
In the following example, we build a volume mesh containing cells with values of field named "He_fraction" greater than 0.05.
First, we define the selection function:
static void
_he_fraction_05_select(
void *
input,
{
if (f == NULL)
"No field with name \"He_fraction\" defined");
_cell_ids[_n_cells] = i;
_n_cells += 1;
}
}
}
*n_cells = _n_cells;
*cell_ids = _cell_ids;
}
Then, we simply define matching volume mesh passing the associated selection function pointer:
{
const int n_writers = 1;
const int writer_ids[] = {2};
"He_fraction_05",
_he_fraction_05_select,
NULL,
true,
false,
false,
n_writers,
writer_ids);
}
The matching function will be called at all time steps requiring output of this mesh.
- Warning
- some mesh formats do not allow changing meshes (or the implemented output functions do not allow them yet) and some may not allow empty meshes, even if this is only transient.
Other advanced mesh types
Example: edges mesh
In cases where a mesh containing polygonal elements is output through a writer configured to divide polygons into triangles (for example when visualization tools do not support polygons, or when highly non convex faces lead to visualization artifacts), it may be useful to extract a mesh containing the edges of the original mesh so as to view the polygon boundaries as an overlay.
In the following example, we build such a mesh (with id 5), based on the faces of a mesh with id 1:
{
const int n_writers = 1;
const int writer_ids[] = {4};
1,
n_writers,
writer_ids);
}
Output of various space-filling curves
In the below example, edge meshes illustrating various space-filling curves possibilities are output.
First the below functions write the various space-filling curves either in serial or parallel.
static void
_cs_post_write_sfc_serial(fvm_writer_t *writer)
{
double *
coords = NULL, *val = NULL;
fvm_nodal_t *nm = NULL;
const double *var_ptr[1] = {NULL};
sfc_id++) {
3,
sfc_id);
j = order[i];
val[i] = i+1;
}
for (i = 0; i < n_edges; i++) {
connect[i*2] = i+1;
connect[i*2+1] = i+2;
}
cell_gnum = NULL;
NULL,
NULL,
NULL,
connect,
NULL);
var_ptr[0] = val;
nm,
1,
0,
0,
-1,
0.0,
(const void * *)var_ptr);
}
}
#if defined(HAVE_MPI)
static void
_cs_post_write_sfc_parall(fvm_writer_t *writer)
{
cs_gnum_t *vtx_gnum = NULL, *edge_gnum = NULL;
double *val = NULL;
fvm_nodal_t *nm = NULL;
const double *var_ptr[1] = {NULL};
sfc_id++) {
3,
sfc_id);
0,
0,
bi,
cell_gnum);
if (block_size > 0) {
}
3,
cell_gnum = NULL;
if (block_size > 0) {
MPI_Status status;
if (prev_rank < 0)
prev_rank = MPI_PROC_NULL;
next_rank = MPI_PROC_NULL;
MPI_Sendrecv(
coords, 3, MPI_DOUBLE, prev_rank, 0,
coords + 3*block_size, 3, MPI_DOUBLE, next_rank, 0,
}
for (i = 0; i < block_size; i++) {
connect[n_edges*2] = i+1;
connect[n_edges*2+1] = i+2;
edge_gnum[n_edges] = vtx_gnum[i];
n_edges++;
}
val[i] = vtx_gnum[i];
}
if (block_size > 0) {
vtx_gnum[block_size] = bi.
gnum_range[0] + block_size;
val[block_size] = vtx_gnum[block_size];
}
n_edges,
NULL,
NULL,
NULL,
connect,
NULL);
connect = NULL;
var_ptr[0] = val;
nm,
1,
0,
0,
-1,
0.0,
(const void * *)var_ptr);
if (block_size > 0) {
}
}
}
#endif
Then a fake cell selection function is used to call the writing of the space-filling curves at the correct step.
static void
_sfc_cell_select(
void *
input,
{
*n_cells = 0;
*cell_ids = NULL;
fvm_writer_t *w = NULL;
"postprocessing",
#if defined(HAVE_MPI)
_cs_post_write_sfc_parall(w);
#endif
_cs_post_write_sfc_serial(w);
}
Finally edge meshes are defined to illustrate the various possibilities.
int * cell_family
Definition: cs_mesh.h:167
cs_lnum_t n_cells
Definition: cs_mesh.h:73
const char * cs_post_get_default_format_options(void)
Return the default writer format options.
Definition: cs_post.c:4686
double precision, dimension(ncharm), save c2
Definition: cpincl.f90:233
void cs_part_to_block_copy_array(cs_part_to_block_t *d, cs_datatype_t datatype, int stride, const void *part_values, void *block_values)
Definition: cs_part_to_block.c:662
int n_families
Definition: cs_mesh.h:164
cs_mesh_quantities_t * cs_glob_mesh_quantities
void fvm_nodal_set_shared_vertices(fvm_nodal_t *this_nodal, const cs_coord_t vertex_coords[])
Definition: fvm_nodal.c:1643
cs_part_to_block_t * cs_part_to_block_create_by_gnum(MPI_Comm comm, cs_block_dist_info_t bi, cs_lnum_t n_ents, const cs_gnum_t global_ent_num[])
Definition: cs_part_to_block.c:551
Definition: fvm_io_num.h:78
fvm_nodal_t * fvm_nodal_create(const char *name, int dim)
Definition: fvm_nodal.c:1132
struct _fvm_io_num_t fvm_io_num_t
Definition: fvm_io_num.h:72
cs_block_dist_info_t cs_block_dist_compute_sizes(int rank_id, int n_ranks, int min_rank_step, cs_lnum_t min_block_size, cs_gnum_t n_g_ents)
Compute block size and rank info for use with a block distribution.
Definition: cs_block_dist.c:91
cs_field_t * cs_field_by_name(const char *name)
Return a pointer to a field based on its name.
Definition: cs_field.c:2331
fvm_writer_t * fvm_writer_init(const char *name, const char *path, const char *format_name, const char *format_options, fvm_writer_time_dep_t time_dependency)
Definition: fvm_writer.c:1084
#define _(String)
Definition: cs_defs.h:52
struct _cs_part_to_block_t cs_part_to_block_t
Definition: cs_part_to_block.h:57
const cs_gnum_t * fvm_io_num_get_global_num(const fvm_io_num_t *const this_io_num)
Definition: fvm_io_num.c:2762
cs_lnum_2_t * i_face_cells
Definition: cs_mesh.h:87
fvm_io_num_t * fvm_io_num_create_from_sfc(const cs_coord_t coords[], int dim, size_t n_entities, fvm_io_num_sfc_t sfc_type)
Definition: fvm_io_num.c:2391
void fvm_writer_export_nodal(fvm_writer_t *this_writer, const fvm_nodal_t *mesh)
Definition: fvm_writer.c:1429
Definition: fvm_defs.h:50
Definition: cs_mesh_quantities.h:90
Definition: cs_defs.h:265
void bft_error(const char *const file_name, const int line_num, const int sys_error_code, const char *const format,...)
Calls the error handler (set by bft_error_handler_set() or default).
Definition: bft_error.c:193
#define BFT_REALLOC(_ptr, _ni, _type)
Reallocate memory for _ni elements of type _type.
Definition: bft_mem.h:78
void cs_post_define_edges_mesh(int mesh_id, int base_mesh_id, int n_writers, const int writer_ids[])
Create a mesh based upon the extraction of edges from an existing mesh.
Definition: cs_post.c:4100
void cs_part_to_block_destroy(cs_part_to_block_t **d)
Definition: cs_part_to_block.c:589
fvm_io_num_t * fvm_io_num_destroy(fvm_io_num_t *this_io_num)
Definition: fvm_io_num.c:2679
int cs_glob_n_ranks
Definition: cs_defs.c:177
cs_real_t * val
Definition: cs_field.h:145
void cs_order_gnum_allocated(const cs_lnum_t list[], const cs_gnum_t number[], cs_lnum_t order[], size_t nb_ent)
Compute an ordering table associated with an array of global numbers.
Definition: cs_order.c:962
Definition: cs_block_dist.h:50
void cs_post_define_volume_mesh_by_func(int mesh_id, const char *mesh_name, cs_post_elt_select_t *cell_select_func, void *cell_select_input, bool time_varying, bool add_groups, bool auto_variables, int n_writers, const int writer_ids[])
Define a volume post-processing mesh using a selection function.
Definition: cs_post.c:3652
MPI_Comm cs_glob_mpi_comm
Definition: cs_defs.c:181
cs_real_t * cell_cen
Definition: cs_mesh_quantities.h:92
void cs_post_define_surface_mesh_by_func(int mesh_id, const char *mesh_name, cs_post_elt_select_t *i_face_select_func, cs_post_elt_select_t *b_face_select_func, void *i_face_select_input, void *b_face_select_input, bool time_varying, bool add_groups, bool auto_variables, int n_writers, const int writer_ids[])
Define a surface post-processing mesh using selection functions.
Definition: cs_post.c:3774
unsigned long cs_gnum_t
global mesh entity number
Definition: cs_defs.h:286
#define BFT_MALLOC(_ptr, _ni, _type)
Allocate memory for _ni elements of type _type.
Definition: bft_mem.h:62
Definition: fvm_writer.h:59
fvm_writer_t * fvm_writer_finalize(fvm_writer_t *this_writer)
Definition: fvm_writer.c:1229
#define BFT_FREE(_ptr)
Free allocated memory.
Definition: bft_mem.h:101
const char * cs_post_get_default_format(void)
Return the default writer format name.
Definition: cs_post.c:4672
Definition: cs_defs.h:441
int cs_lnum_t
local mesh entity id
Definition: cs_defs.h:298
fvm_nodal_t * fvm_nodal_destroy(fvm_nodal_t *this_nodal)
Definition: fvm_nodal.c:1192
int cs_glob_rank_id
Definition: cs_defs.c:176
fvm_io_num_sfc_t
Definition: fvm_io_num.h:76
void fvm_writer_export_field(fvm_writer_t *this_writer, const fvm_nodal_t *mesh, const char *name, fvm_writer_var_loc_t location, int dimension, cs_interlace_t interlace, int n_parent_lists, const cs_lnum_t parent_num_shift[], cs_datatype_t datatype, int time_step, double time_value, const void *const field_values[])
Definition: fvm_writer.c:1482
#define CS_UNUSED(x)
Definition: cs_defs.h:453
void fvm_nodal_append_by_transfer(fvm_nodal_t *this_nodal, cs_lnum_t n_elements, fvm_element_t type, cs_lnum_t face_index[], cs_lnum_t face_num[], cs_lnum_t vertex_index[], cs_lnum_t vertex_num[], cs_lnum_t parent_element_num[])
Definition: fvm_nodal_append.c:260
int cs_int_t
Fortran-compatible integer.
Definition: cs_defs.h:301
Definition: fvm_writer.h:71
Definition: fvm_io_num.h:81
double cs_coord_t
Definition: cs_defs.h:299
cs_gnum_t n_g_cells
Definition: cs_mesh.h:98
int rank_step
Definition: cs_block_dist.h:55
void cs_selector_get_family_list(const char *criteria, cs_lnum_t *n_families, cs_int_t family_list[])
Fill a list of families verifying a given selection criteria.
Definition: cs_selector.c:675
void const cs_int_t const cs_real_t const cs_real_t * coords
Definition: cs_measures_util.h:360
cs_gnum_t gnum_range[2]
Definition: cs_block_dist.h:52
Field descriptor.
Definition: cs_field.h:124
void fvm_nodal_init_io_num(fvm_nodal_t *this_nodal, const cs_gnum_t parent_global_numbers[], int entity_dim)
Definition: fvm_nodal.c:1479
cs_lnum_t n_i_faces
Definition: cs_mesh.h:74
Definition: cs_field_pointer.h:70
const char * fvm_io_num_sfc_type_name[]
double precision, dimension(ncharm), save c1
Definition: cpincl.f90:233