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, for particle or trjectory 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 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);
}

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_(u)->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;
BFT_MALLOC(rij, n_cells, cs_real_6_t);
if ( turb_mdl->itytur == 2
|| turb_mdl->itytur == 5
|| turb_mdl->itytur == 6) {
cs_post_evm_reynolds_stresses(n_cells, cell_list, 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; i < 6; i++)
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(rij);
BFT_FREE(val);
}

For the second 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);
}