My Project
programmer's documentation
Definition of the variables to post-process

Additional post-processing variables

For the mesh parts defined using the GUI or in cs_user_postprocess.c, the cs_user_postprocess_values function of the cs_user_postprocess.c file may be used to specify the variables to post-process (called for each postprocess output mesh, at every active time step of an associated writer).

The output of a given variable is generated by means of a call to the cs_post_write_var for cell or face values, cs_post_write_vertex_var for vertex values, \cs_post_write_particle_values for particle or trajectory values, and cs_post_write_probe_values for probe or profile values.

The examples of post-processing given below use meshes defined in the examples for \cs_user_postprocess_meshes above.

Output of the turbulent kinetic energy for the Rij-Epsilon model on the volume mesh

One can define, compute and post-process the turbulent kinetic energy for the Rij-Epsilon as shown in the following example:

if (cat_id == CS_POST_MESH_VOLUME && cs_glob_turb_model->itytur == 3) {
cs_real_t *s_cell;
BFT_MALLOC(s_cell, n_cells, cs_real_t);
const cs_real_6_t *cvar_r = (const cs_real_6_t *)(CS_F_(rij)->val);
for (cs_lnum_t i = 0; i < n_cells; i++) {
cs_lnum_t cell_id = cell_list[i];
s_cell[i] = 0.5* ( cvar_r[cell_id][0]
+ cvar_r[cell_id][1]
+ cvar_r[cell_id][2]);
}
}
else {
const cs_real_t *cvar_r11 = CS_F_(r11)->val;
const cs_real_t *cvar_r22 = CS_F_(r22)->val;
const cs_real_t *cvar_r33 = CS_F_(r33)->val;
for (cs_lnum_t i = 0; i < n_cells; i++) {
cs_lnum_t cell_id = cell_list[i];
s_cell[i] = 0.5* ( cvar_r11[cell_id]
+ cvar_r22[cell_id]
+ cvar_r33[cell_id]);
}
}
CS_POST_WRITER_ALL_ASSOCIATED, /* writer id filter */
"Turb energy", /* var_name */
1, /* var_dim */
true, /* interlace, */
false, /* use_parent */
CS_POST_TYPE_cs_real_t, /* var_type */
s_cell, /* cel_vals */
NULL, /* i_face_vals */
NULL, /* b_face_vals */
ts);
BFT_FREE(s_cell);
}

Output of a variable on a surface mesh

Values can also be output on a surface mesh, possibly containing a mix of boundary and internal faces. In the following example, we simply average or project adjacent cell values on faces, but more precise techniques could be used:

if (strcmp(mesh_name, "pressure_surface") == 0) { /* Restrict to this mesh */
cs_real_t *cvar_p = CS_F_(p)->val; /* pressure */
/* Ensure variable is synchronized in parallel or periodic cases;
should already have been done before, repeated for safety */
const cs_mesh_t *m = cs_glob_mesh;
cs_real_t *s_i_faces = NULL, *s_b_faces = NULL;
/* Interior faces */
if (n_i_faces > 0) {
BFT_MALLOC(s_i_faces, n_i_faces, cs_real_t);
for (cs_lnum_t i = 0; i < n_i_faces; i++) {
cs_lnum_t face_id = i_face_list[i];
/* Use unweighted mean of adjacent cell values here */
cs_lnum_t c1 = m->i_face_cells[face_id][0];
cs_lnum_t c2 = m->i_face_cells[face_id][1];
s_i_faces[i] = 0.5 * (cvar_p[c1] + cvar_p[c2]);
}
}
/* Boundary faces */
if (n_b_faces > 0) {
BFT_MALLOC(s_b_faces, n_b_faces, cs_real_t);
for (cs_lnum_t i = 0; i < n_b_faces; i++) {
cs_lnum_t face_id = b_face_list[i];
/* Use adjacent cell value here */
cs_lnum_t cell_id = m->b_face_cells[face_id];
s_b_faces[i] = cvar_p[cell_id];
}
}
CS_POST_WRITER_ALL_ASSOCIATED, /* writer id filter */
"Pressure", /* var_name */
1, /* var_dim */
true, /* interlace, */
false, /* use_parent */
CS_POST_TYPE_cs_real_t, /* var_type */
NULL, /* cel_vals */
s_i_faces, /* i_face_vals */
s_b_faces, /* b_face_vals */
ts);
BFT_FREE(s_i_faces);
BFT_FREE(s_b_faces);
}

Simple output of an existing field or array

For fields or arrays already defined on the full mesh, the "use_parent" option of cs_post_write_var may be used to simply reference the values on the parent (i.e. full) mesh when requesting an output. Note that the example below can also be used with probes or profiles:

if ( cat_id == CS_POST_MESH_VOLUME
|| cat_id == CS_POST_MESH_PROBES) {
const cs_field_t *f = cs_field_by_name_try("my_field");
if (f != NULL)
CS_POST_WRITER_ALL_ASSOCIATED, /* writer id filter */
f->name, /* var_name */
1, /* var_dim */
true, /* interlace, */
true, /* use_parent */
CS_POST_TYPE_cs_real_t, /* var_type */
f->val, /* cel_vals */
NULL, /* i_face_vals */
NULL, /* b_face_vals */
ts);
}

Single output of time-independent values

Finally, a minor modification f the above example shows how it is possible to output time-independent values to a writer also used for time-dependent fields without requiring multiple outputs of those values:

if (cat_id == CS_POST_MESH_VOLUME) {
const cs_field_t *f = cs_field_by_name_try("my_const_field");
if (f != NULL) {
if (ts->nt_cur == ts->nt_prev + 1) { /* before time loop */
ts0.nt_cur = 1; /* Negative time step value implies time-independent */
CS_POST_WRITER_ALL_ASSOCIATED, /* writer id filter */
f->name, /* var_name */
1, /* var_dim */
true, /* interlace, */
true, /* use_parent */
CS_POST_TYPE_cs_real_t, /* var_type */
f->val, /* cel_vals */
NULL, /* i_face_vals */
NULL, /* b_face_vals */
&ts0);
}
}
}

Additional profile variables

The following examples match the advanced profile definitions given in Advanced profile definitions.

The first section is common to both profile series:

const cs_mesh_t *m = cs_glob_mesh;
const cs_real_3_t *cell_cen = (const cs_real_3_t *)mq->cell_cen;
const cs_real_3_t *vel = (const cs_real_3_t *)CS_F_(vel)->val;
const cs_real_t uref2 = uref*uref;
const char *name = cs_probe_set_get_name(probes);
const cs_time_step_t *ts_post = (ts->nt_cur == ts->nt_max) ? NULL : ts;
/* Common variables */
const cs_real_t href = 1.;

For the profiles along fixed x, the following code is used. Note that this code's complexity is mainly due to extracting Reynolds stresses for different turbulence models and options. Specific values are then computed for each colum, in the switch statement:

if (strncmp(name, "buicesat", strlen("buicesat")) == 0) {
cs_real_t *val;
BFT_MALLOC(val, n_cells, cs_real_t);
char var_name[64];
/* mean x */
cs_real_t x_sum[] = {0, 0};
for (cs_lnum_t i = 0; i < n_cells; i++) {
cs_lnum_t c_id = cell_list[i];
x_sum[0] += cell_cen[c_id][0];
}
x_sum[1] = n_cells;
cs_real_t xpos = x_sum[0]/x_sum[1];
/* Reynolds stresses */
cs_real_6_t *rij = NULL;
if ( turb_mdl->itytur == 2
|| turb_mdl->itytur == 5
|| turb_mdl->itytur == 6) {
cs_post_evm_reynolds_stresses(interpolation_type,
n_cells,
cell_list,
NULL, /* coords */
rij);
} else if (turb_mdl->itytur == 3 && turb_rans_mdl->irijco == 0) {
for (cs_lnum_t i = 0; i < n_cells; i++) {
cs_lnum_t c_id = cell_list[i];
rij[i][0] = CS_F_(r11)->val[c_id];
rij[i][1] = CS_F_(r22)->val[c_id];
rij[i][2] = CS_F_(r33)->val[c_id];
rij[i][3] = CS_F_(r12)->val[c_id];
rij[i][4] = CS_F_(r23)->val[c_id];
rij[i][5] = CS_F_(r13)->val[c_id];
}
} else if (turb_mdl->itytur == 3) {
cs_real_6_t *cvar_rij = (cs_real_6_t *)CS_F_(rij)->val;
for (cs_lnum_t i = 0; i < n_cells; i++) {
cs_lnum_t c_id = cell_list[i];
for (cs_lnum_t j = 0; j < 6; j++)
rij[i][j] = cvar_rij[c_id][j];
}
}
/* Loop on columns */
for (int col = 0; col < 7; col++) {
switch(col) {
case 0:
{
strncpy(var_name, "U*10+x/h", 64);
for (cs_lnum_t i = 0; i < n_cells; i++) {
cs_lnum_t c_id = cell_list[i];
val[i] = vel[c_id][0]*10 + xpos;
}
}
break;
case 1:
{
strncpy(var_name, "Y/H", 64);
for (cs_lnum_t i = 0; i < n_cells; i++) {
cs_lnum_t c_id = cell_list[i];
val[i] = mq->cell_cen[c_id*3 + 1] / href;
}
}
break;
case 2:
{
strncpy(var_name, "U/Uc", 64);
for (cs_lnum_t i = 0; i < n_cells; i++) {
cs_lnum_t c_id = cell_list[i];
val[i] = vel[c_id][0] / uref;
}
}
break;
case 3:
{
strncpy(var_name, "uu/Uc^2", 64);
for (cs_lnum_t i = 0; i < n_cells; i++) {
val[i] = rij[i][0] / uref2;
}
}
break;
case 4:
{
strncpy(var_name, "uv/Uc^2", 64);
for (cs_lnum_t i = 0; i < n_cells; i++) {
val[i] = rij[i][3] / uref2;
}
}
break;
case 5:
{
strncpy(var_name, "vv/Uc^2", 64);
for (cs_lnum_t i = 0; i < n_cells; i++) {
val[i] = rij[i][1] / uref2;
}
}
break;
case 6:
{
strncpy(var_name, "X", 64);
for (cs_lnum_t i = 0; i < n_cells; i++) {
cs_lnum_t c_id = cell_list[i];
val[i] = cell_cen[c_id][0];
}
}
break;
}
(mesh_id,
CS_POST_WRITER_ALL_ASSOCIATED, /* writer id filter */
var_name, /* var_name */
1, /* var_dim */
0, /* parent location id */
NULL, /* default interpolation */
NULL, /* interpolation input */
val,
ts_post);
}
BFT_FREE(val);
}

For the profile defined all around a foil, the following code is used to compute the pressure coefficient and output its values:

const cs_mesh_t *m = cs_glob_mesh;
const cs_real_3_t *b_face_cog = (const cs_real_3_t *)mq->b_face_cog;
cs_real_t *val;
BFT_MALLOC(val, n_b_faces, cs_real_t);
/* x coordinate */
for (cs_lnum_t i = 0; i < n_b_faces; i++) {
cs_lnum_t face_id = b_face_list[i];
val[i] = b_face_cog[face_id][0];
}
/* post-process x coordinate */
(mesh_id,
CS_POST_WRITER_ALL_ASSOCIATED, /* writer id filter */
"X", /* var_name */
1, /* var_dim */
0, /* parent location id */
NULL, /* default interpolation */
NULL, /* interpolation input */
val,
ts);
/* compute pressure on selected boundary faces */
cs_post_b_pressure(n_b_faces, b_face_list, val);
cs_real_t p0 = phys_pro->p0; /* reference pressure */
cs_real_t ro0 = phys_pro->ro0; /* reference density */
const cs_real_t uref = cs_glob_turb_ref_values->uref; /*ref. velocity */
const cs_real_t uref2 = uref*uref;
/* reference values can be set in GUI */
/* 1/(1/2 rho U^2) */
cs_real_t div_half_ro0_uref2 = 1. / (0.5 * ro0 * uref2);
/* compute CP at each selected boundary face */
for (cs_lnum_t i = 0; i < n_b_faces; i++)
val[i] = (val[i] - p0) * div_half_ro0_uref2;
/* post-process CP */
(mesh_id,
CS_POST_WRITER_ALL_ASSOCIATED, /* writer id filter */
"CP", /* var_name */
1, /* var_dim */
0, /* parent location id */
NULL, /* default interpolation */
NULL, /* interpolation input */
val,
ts);
BFT_FREE(val);

For the last profiles series, values for each column are also computed, requiring a reference pressure based on the mesh point closest to a given point, and computation of tangential stresses, so as to determine drag coefficients.

else if ( strcmp(name, "buicstr") == 0
|| strcmp(name, "buicinc") == 0) {
const cs_lnum_t *b_face_cells = m->b_face_cells;
const cs_real_3_t *face_cog = (const cs_real_3_t *)mq->b_face_cog;
const cs_real_t *distb = mq->b_dist;
const cs_real_t *pres = CS_F_(p)->val;
cs_real_t div_half_ro0_uref2 = 1. / (0.5 * phys_pro->ro0 * uref2);
cs_real_t *val;
BFT_MALLOC(val, n_b_faces, cs_real_t);
char var_name[64];
/* Reference pressure */
cs_real_t xyz_ref[3] = {-1.7, -0.5, 0.005};
cs_real_t pref = 0;
cs_lnum_t pref_id;
int pref_rank;
(const cs_real_3_t *)(mq->cell_cen),
xyz_ref,
&pref_id,
&pref_rank);
if (pref_rank == cs_glob_rank_id)
pref = pres[pref_id];
cs_parall_bcast(pref_rank, 1, CS_REAL_TYPE, &pref);
/* Stresses */
cs_real_3_t *stresses;
BFT_MALLOC(stresses, n_b_faces, cs_real_3_t);
cs_post_stress_tangential(n_b_faces, b_face_list, stresses);
/* Loop on columns */
for (int col = 0; col < 5; col++) {
switch(col) {
case 0:
{
strncpy(var_name, "X/H", 64);
for (cs_lnum_t i = 0; i < n_b_faces; i++) {
cs_lnum_t f_id = b_face_list[i];
val[i] = face_cog[f_id][0] / href;
}
}
break;
case 1:
{
strncpy(var_name, "CP", 64);
for (cs_lnum_t i = 0; i < n_b_faces; i++) {
cs_lnum_t f_id = b_face_list[i];
cs_lnum_t c_id = b_face_cells[f_id];
val[i] = (pres[c_id] - pref) * div_half_ro0_uref2;
}
}
break;
case 2:
{
strncpy(var_name, "CF", 64);
for (cs_lnum_t i = 0; i < n_b_faces; i++) {
val[i] = cs_math_3_norm(stresses[i]) * div_half_ro0_uref2;
}
}
break;
case 3:
{
strncpy(var_name, "U/UREF", 64);
for (cs_lnum_t i = 0; i < n_b_faces; i++) {
/* previous value in val[i] from case2:
norm(stresses[i])/(0.5.ro0.uref^2) */
val[i] = copysign(val[i], stresses[i][0]);
}
}
break;
case 4:
{
strncpy(var_name, "YPLUS", 64);
for (cs_lnum_t i = 0; i < n_b_faces; i++) {
cs_lnum_t f_id = b_face_list[i];
cs_lnum_t c_id = b_face_cells[f_id];
val[i] = sqrt(fabs(vel[c_id][0])*distb[f_id]*phys_pro->viscl0);
}
}
break;
}
(mesh_id,
CS_POST_WRITER_ALL_ASSOCIATED, /* writer id filter */
var_name, /* var_name */
1, /* var_dim */
0, /* parent location id */
NULL, /* default interpolation */
NULL, /* interpolation input */
val,
ts_post);
}
BFT_FREE(stresses);
BFT_FREE(val);
}
cs_mesh_t::n_cells
cs_lnum_t n_cells
Definition: cs_mesh.h:73
f_id
void const int * f_id
Definition: cs_gui.h:292
cs_post_b_pressure
void cs_post_b_pressure(cs_lnum_t n_b_faces, const cs_lnum_t b_face_ids[], cs_real_t pres[])
Compute pressure on a specific boundary region.
Definition: cs_post_util.c:633
cpincl::c2
double precision, dimension(ncharm), save c2
Definition: cpincl.f90:233
cs_math_3_norm
static cs_real_t cs_math_3_norm(const cs_real_t v[3])
Compute the euclidean norm of a vector of dimension 3.
Definition: cs_math.h:372
CS_POST_MESH_VOLUME
#define CS_POST_MESH_VOLUME
Definition: cs_post.h:78
cs_get_glob_fluid_properties
cs_fluid_properties_t * cs_get_glob_fluid_properties(void)
Definition: cs_physical_constants.c:524
cs_post_write_probe_values
void cs_post_write_probe_values(int mesh_id, int writer_id, const char *var_name, int var_dim, cs_post_type_t var_type, int parent_location_id, cs_interpolate_from_location_t *interpolate_func, void *interpolate_input, const void *vals, const cs_time_step_t *ts)
Output a variable defined at cells or faces of a post-processing mesh using associated writers.
Definition: cs_post.c:5619
cs_glob_mesh_quantities
cs_mesh_quantities_t * cs_glob_mesh_quantities
cs_real_3_t
cs_real_t cs_real_3_t[3]
vector of 3 floating-point values
Definition: cs_defs.h:315
cstphy::ro0
real(c_double), pointer, save ro0
reference density.
Definition: cstphy.f90:146
cs_glob_turb_model
const cs_turb_model_t * cs_glob_turb_model
cs_post_evm_reynolds_stresses
void cs_post_evm_reynolds_stresses(cs_field_interpolate_t interpolation_type, cs_lnum_t n_cells, const cs_lnum_t cell_ids[], const cs_real_3_t *coords, cs_real_6_t *rst)
Compute Reynolds stresses in case of Eddy Viscosity Models.
Definition: cs_post_util.c:720
mesh::distb
double precision, dimension(:), pointer distb
Definition: mesh.f90:188
cs_mesh_quantities_t::b_face_cog
cs_real_t * b_face_cog
Definition: cs_mesh_quantities.h:105
r22
Definition: cs_field_pointer.h:74
CS_REAL_TYPE
#define CS_REAL_TYPE
Definition: cs_defs.h:407
cs_field_interpolate_t
cs_field_interpolate_t
Field interpolation modes.
Definition: cs_field_operator.h:54
rij
Definition: cs_field_pointer.h:79
cs_turb_model_t::itytur
int itytur
Definition: cs_turbulence_model.h:99
cs_field_t::name
const char * name
Definition: cs_field.h:126
CS_POST_TYPE_cs_real_t
Definition: cs_post.h:97
cs_time_step_t::nt_cur
int nt_cur
Definition: cs_time_step.h:61
cs_real_t
double cs_real_t
Floating-point value.
Definition: cs_defs.h:302
cs_mesh_t::b_face_cells
cs_lnum_t * b_face_cells
Definition: cs_mesh.h:88
cs_mesh_t::i_face_cells
cs_lnum_2_t * i_face_cells
Definition: cs_mesh.h:87
CS_POST_WRITER_ALL_ASSOCIATED
#define CS_POST_WRITER_ALL_ASSOCIATED
Definition: cs_post.h:66
cs_field_by_name_try
cs_field_t * cs_field_by_name_try(const char *name)
Return a pointer to a field based on its name if present.
Definition: cs_field.c:2357
cs_turb_ref_values_t::uref
double uref
Definition: cs_turbulence_model.h:110
cs_glob_turb_ref_values
const cs_turb_ref_values_t * cs_glob_turb_ref_values
cs_mesh_quantities_t
Definition: cs_mesh_quantities.h:90
cs_parall_sum
static void cs_parall_sum(int n, cs_datatype_t datatype, void *val)
Sum values of a given datatype on all default communicator processes.
Definition: cs_parall.h:147
r23
Definition: cs_field_pointer.h:77
CS_POST_MESH_PROBES
#define CS_POST_MESH_PROBES
Definition: cs_post.h:82
cs_geom_closest_point
void cs_geom_closest_point(cs_lnum_t n_points, const cs_real_t point_coords[][3], const cs_real_t query_coords[3], cs_lnum_t *point_id, int *rank_id)
find the closest point of a set to a given point in space.
Definition: cs_geom.c:162
cs_glob_mesh
cs_mesh_t * cs_glob_mesh
cstphy::uref
real(c_double), pointer, save uref
the characteristic flow velocity, used for the initialization of the turbulence. Negative value: not ...
Definition: cstphy.f90:619
cs_parall_bcast
static void cs_parall_bcast(int root_rank, int n, cs_datatype_t datatype, void *val)
Broadcast values of a given datatype to all default communicator processes.
Definition: cs_parall.h:255
cs_glob_turb_rans_model
const cs_turb_rans_model_t * cs_glob_turb_rans_model
cs_field_t::val
cs_real_t * val
Definition: cs_field.h:145
cs_mesh_quantities_t::cell_cen
cs_real_t * cell_cen
Definition: cs_mesh_quantities.h:92
cs_turb_model_t
Turbulence model general options descriptor.
Definition: cs_turbulence_model.h:75
BFT_MALLOC
#define BFT_MALLOC(_ptr, _ni, _type)
Allocate memory for _ni elements of type _type.
Definition: bft_mem.h:62
cs_turb_rans_model_t
RANS turbulence model descriptor.
Definition: cs_turbulence_model.h:117
cs_time_step_t
time step descriptor
Definition: cs_time_step.h:51
BFT_FREE
#define BFT_FREE(_ptr)
Free allocated memory.
Definition: bft_mem.h:101
CS_F_
#define CS_F_(e)
Macro used to return a field pointer by its enumerated value.
Definition: cs_field_pointer.h:51
CS_FIELD_INTERPOLATE_MEAN
Definition: cs_field_operator.h:56
r13
Definition: cs_field_pointer.h:78
cs_real_6_t
cs_real_t cs_real_6_t[6]
vector of 6 floating-point values
Definition: cs_defs.h:317
r33
Definition: cs_field_pointer.h:75
cs_fluid_properties_t::viscl0
double viscl0
Definition: cs_physical_constants.h:73
ts
void cs_int_t cs_int_t cs_int_t cs_real_t * ts
Definition: cs_at_plugin.h:63
cs_lnum_t
int cs_lnum_t
local mesh entity id
Definition: cs_defs.h:298
cs_glob_rank_id
int cs_glob_rank_id
Definition: cs_defs.c:176
r12
Definition: cs_field_pointer.h:76
cs_post_write_var
void cs_post_write_var(int mesh_id, int writer_id, const char *var_name, int var_dim, bool interlace, bool use_parent, cs_post_type_t var_type, const void *cel_vals, const void *i_face_vals, const void *b_face_vals, const cs_time_step_t *ts)
Output a variable defined at cells or faces of a post-processing mesh using associated writers.
Definition: cs_post.c:5080
cs_fluid_properties_t::ro0
double ro0
Definition: cs_physical_constants.h:72
vel
void const cs_int_t *const const cs_int_t *const const cs_int_t *const const cs_int_t *const const cs_int_t *const const cs_int_t *const const cs_int_t *const const cs_int_t *const const cs_real_t *const const cs_real_t *const const cs_real_t const cs_real_t const cs_real_3_t vel[]
Definition: cs_divergence.h:64
cs_post_stress_tangential
void cs_post_stress_tangential(cs_lnum_t n_b_faces, const cs_lnum_t b_face_ids[], cs_real_3_t stress[])
Compute tangential stress on a specific boundary.
Definition: cs_post_util.c:592
cs_mesh_sync_var_scal
void cs_mesh_sync_var_scal(cs_real_t *var)
Definition: cs_mesh.c:3214
r11
Definition: cs_field_pointer.h:73
cs_fluid_properties_t
Fluid properties descriptor.
Definition: cs_physical_constants.h:61
cs_turb_rans_model_t::irijco
int irijco
Definition: cs_turbulence_model.h:155
atimbr::xpos
double precision, dimension(:,:), allocatable xpos
Positions.
Definition: atimbr.f90:103
p0
void const cs_real_t * p0
Definition: cs_ctwr_air_props.h:85
cs_fluid_properties_t::p0
double p0
Definition: cs_physical_constants.h:74
cs_field_t
Field descriptor.
Definition: cs_field.h:124
cs_mesh_t
Definition: cs_mesh.h:63
cs_mesh_quantities_t::b_dist
cs_real_t * b_dist
Definition: cs_mesh_quantities.h:124
cs_probe_set_get_name
const char * cs_probe_set_get_name(cs_probe_set_t *pset)
Retrieve the name related to a cs_probe_set_t structure.
Definition: cs_probe.c:538
p
Definition: cs_field_pointer.h:67
cpincl::c1
double precision, dimension(ncharm), save c1
Definition: cpincl.f90:233