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 a given field or component with a given mesh
To output specific field values on a given postprocessing mesh, that field may be attached (associated) to that mesh.
In the following example, the pressure is output on mesh 4, for all associated writers:
In this second example, the velocity's z component is ouput on mesh 4, only for writer 1:
If the mesh has the auto_variables
option enabled, and a field is already selected for "standard" postprocessing (i.e. selected for output in the GUI, or post_vis
key value includes the CS_POST_ON_LOCATION
bit), it will not be output an additional time, so this option should be safely usable even with limited precautions.
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:
s_cell[i] = 0.5* ( cvar_r[cell_id][0]
+ cvar_r[cell_id][1]
+ cvar_r[cell_id][2]);
}
"Turb energy",
1,
true,
false,
s_cell,
NULL,
NULL,
ts);
}
}
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) {
cs_real_t *s_i_faces = NULL, *s_b_faces = NULL;
if (n_i_faces > 0) {
s_i_faces[i] = 0.5 * (cvar_p[
c1] + cvar_p[
c2]);
}
}
if (n_b_faces > 0) {
s_b_faces[i] = cvar_p[cell_id];
}
}
"Pressure",
1,
true,
false,
NULL,
s_i_faces,
s_b_faces,
ts);
}
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 (f != NULL)
1,
true,
true,
NULL,
NULL,
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 (f != NULL) {
1,
true,
true,
NULL,
NULL,
&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:
bool is_profile = false;
NULL,
NULL,
&is_profile,
NULL,
NULL,
NULL,
NULL,
NULL);
ts = NULL;
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) {
char var_name[64];
x_sum[0] += cell_cen[c_id][0];
}
x_sum[1] = n_cells;
n_cells,
cell_list,
NULL,
rij);
}
else if (turb_mdl->
itytur == 3) {
rij[i][j] = cvar_rij[c_id][j];
}
}
cell_list,
NULL,
inv);
for (int col = 0; col < 9; col++) {
switch(col) {
case 0:
{
strncpy(var_name, "U*10+x/h", 64);
val[i] = vel[c_id][0]*10 +
xpos;
}
}
break;
case 1:
{
strncpy(var_name, "Y/H", 64);
val[i] = mq->
cell_cen[c_id*3 + 1] / href;
}
}
break;
case 2:
{
strncpy(var_name, "U/Uc", 64);
val[i] = vel[c_id][0] /
uref;
}
}
break;
case 3:
{
strncpy(var_name, "uu/Uc^2", 64);
val[i] = rij[i][0] / uref2;
}
}
break;
case 4:
{
strncpy(var_name, "uv/Uc^2", 64);
val[i] = rij[i][3] / uref2;
}
}
break;
case 5:
{
strncpy(var_name, "vv/Uc^2", 64);
val[i] = rij[i][1] / uref2;
}
}
break;
case 6:
{
strncpy(var_name, "X", 64);
val[i] = cell_cen[c_id][0];
}
}
break;
case 7:
{
strncpy(var_name, "eta", 64);
val[i] = inv[c_id][0];
}
}
break;
case 8:
{
strncpy(var_name, "xsi", 64);
val[i] = inv[c_id][1];
}
}
break;
}
(mesh_id,
var_name,
1,
0,
NULL,
NULL,
val,
ts_post);
}
}
For the profile defined all around a foil, the following code is used to compute the pressure coefficient and output its values:
val[i] = b_face_cog[face_id][0];
}
(mesh_id,
"X",
1,
0,
NULL,
NULL,
val,
ts);
cs_real_t div_half_ro0_uref2 = 1. / (0.5 * ro0 * uref2);
val[i] = (val[i] - p0) * div_half_ro0_uref2;
(mesh_id,
"CP",
1,
0,
NULL,
NULL,
val,
ts);
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) {
cs_real_t div_half_ro0_uref2 = 1. / (0.5 * phys_pro->
ro0 * uref2);
char var_name[64];
int pref_rank;
xyz_ref,
&pref_id,
&pref_rank);
pref = pres[pref_id];
for (int col = 0; col < 5; col++) {
switch(col) {
case 0:
{
strncpy(var_name, "X/H", 64);
val[i] = face_cog[f_id][0] / href;
}
}
break;
case 1:
{
strncpy(var_name, "CP", 64);
val[i] = (pres[c_id] - pref) * div_half_ro0_uref2;
}
}
break;
case 2:
{
strncpy(var_name, "CF", 64);
}
}
break;
case 3:
{
strncpy(var_name, "U/UREF", 64);
val[i] = copysign(val[i], stresses[i][0]);
}
}
break;
case 4:
{
strncpy(var_name, "YPLUS", 64);
val[i] = sqrt(fabs(vel[c_id][0])*
distb[f_id]*phys_pro->
viscl0);
}
}
break;
}
(mesh_id,
var_name,
1,
0,
NULL,
NULL,
val,
ts_post);
}
}