/*============================================================================
 * Define postprocessing output.
 *============================================================================*/

/* Code_Saturne version 6.1-alpha */

/*
  This file is part of Code_Saturne, a general-purpose CFD tool.

  Copyright (C) 1998-2019 EDF S.A.

  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
  Foundation; either version 2 of the License, or (at your option) any later
  version.

  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  details.

  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
  Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

/*----------------------------------------------------------------------------*/

#include "cs_defs.h"

/*----------------------------------------------------------------------------
 * Standard C library headers
 *----------------------------------------------------------------------------*/

#include "stdlib.h"
#include "string.h"

/*----------------------------------------------------------------------------
 *  Local headers
 *----------------------------------------------------------------------------*/

#include "bft_mem.h"
#include "bft_error.h"

#include "cs_base.h"
#include "cs_field.h"
#include "cs_geom.h"
#include "cs_interpolate.h"
#include "cs_mesh.h"
#include "cs_selector.h"
#include "cs_parall.h"
#include "cs_post.h"
#include "cs_post_util.h"
#include "cs_probe.h"
#include "cs_time_plot.h"

#include "cs_field_pointer.h"
#include "cs_parameters.h"
#include "cs_physical_constants.h"
#include "cs_turbulence_model.h"

/*----------------------------------------------------------------------------
 *  Header for the current file
 *----------------------------------------------------------------------------*/

#include "cs_prototypes.h"

/*----------------------------------------------------------------------------*/

BEGIN_C_DECLS

/*============================================================================
 * Local (user defined) function definitions
 *============================================================================*/

/*----------------------------------------------------------------------------
 * Example function for selection of cells with scalar field values above
 * a certain threshold.
 *
 * In this example, the selection is base on the value of a scalar field
 * named "he_fraction" being above above 0.05.
 *
 * parameters:
 *   input    <-> pointer to input (unused here)
 *   n_cells  --> number of selected cells
 *   cell_ids --> array of selected cell ids (0 to n-1 numbering)
 *----------------------------------------------------------------------------*/



/*! [post_select_func_3] */
static void
_xyz_fraction_select(void       *input,
                     cs_lnum_t  *_n_cells,
                     cs_lnum_t  **_cell_idsf
                     )

{
  CS_UNUSED(input);
  cs_lnum_t **cell_ids = NULL;
  cs_lnum_t *n_cells = NULL;
  cs_real_t seg[6] = {55., 0., 1., 55., 240., 1.};
  /* define which cells are within the segmen */
  cs_cell_segment_intersect_select(seg,n_cells,cell_ids);
  printf("Selecting cells\n");
  printf("%d", n_cells[1]);    
/*   char myfields[][9] = { "epsilon", "k", "Pressure", "Velocity", "Velocity[X]", "Velocity[Y]" , "Velocity[Z]", "scalar1","TurbVisc"};
  
  size_t ifields = 0;
  for ( ifields = 0; ifields < sizeof(myfields) / sizeof(myfields[0]); ifields++)
  { */
  cs_lnum_t c_cells = 0;
  cs_lnum_t *_cell_ids = NULL;

  const cs_mesh_t *m = cs_glob_mesh;
  cs_field_t *f = cs_field_by_name("epsilon"); /* Get access to field */
	
  if (f == NULL)
	bft_error(__FILE__, __LINE__, 0,
			  "No field with name \"epsilon\" defined");

  /* Before time loop, field is defined, but has no values yet,
	 so ignore that case (postprocessing mesh will be initially empty) */

  if (f->val != NULL) {
	BFT_MALLOC(cell_ids, m->n_cells, cs_lnum_t); /* Allocate selection list */

	for (cs_lnum_t i = 0; i < m->n_cells; i++) {
	  if (f->val[i] > 5.e-2) {
		cell_ids[c_cells] = i;
		c_cells += 1;
	  }
	}

	BFT_REALLOC(cell_ids, c_cells, cs_lnum_t); /* Adjust size (good practice,
													but not required) */

  }

  /* Set return values */

  *_n_cells = c_cells;
  *_cell_idsf = cell_ids;
}
/*! [post_select_func_3] */

/*============================================================================
 * User function definitions
 *============================================================================*/

/*----------------------------------------------------------------------------*/
/*!
 * \brief Define post-processing writers.
 *
 * The default output format and frequency may be configured, and additional
 * post-processing writers allowing outputs in different formats or with
 * different format options and output frequency than the main writer may
 * be defined.
 */
/*----------------------------------------------------------------------------*/

void
cs_user_postprocess_writers(void)
{

  /* Define additional writers */
  /* ------------------------- */

  /* Common parameters for all writers */

  /*! [post_define_writer_freq] */
      double frequency_n = 1.0;
      double frequency_t = 0.2; 
  /*! [post_define_writer_freq] */

  /*! [post_define_writer_2] */
  cs_post_define_writer(2,                            /* writer_id */
                        "modif",                      /* writer name */
                        "postprocessingmo",             /* directory name */
                        "ensight",                    /* format name */
                        "separate_meshes",
                        FVM_WRITER_TRANSIENT_CONNECT,
                        false,                        /* output_at_start */
                        false,                        /* output_at_end */
                        1,
                        frequency_t);
  /*! [post_define_writer_2] */

}

/*----------------------------------------------------------------------------*/
/*!
 * \brief Define post-processing meshes.
 *
 * The main post-processing meshes may be configured, and additional
 * post-processing meshes may be defined as a subset of the main mesh's
 * cells or faces (both interior and boundary).
 */
/*----------------------------------------------------------------------------*/

void
cs_user_postprocess_meshes(void)
{
  /* Reconfigure predefined meshes (mesh_id -1 for volume, -2 for boundary */

  /* De-activate boundary mesh output by redefining it with no writer
     association (default is:
     int n_writers = 1;
     const int writer_ids[] = {CS_POST_WRITER_DEFAULT});
  */

  /*! [post_define_mesh_m2] */
  /*! [post_define_mesh_m2] */

  /*--------------------------------------------------------------------------*/

  /* Example: select interior faces with y = 0.5 */

  /*! [post_define_mesh_1] */
  /*! [post_define_mesh_1] */

  /*--------------------------------------------------------------------------*/

  /* Advanced example:
     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". */

  /*! [post_define_mesh_3] */
  /*! [post_define_mesh_3] */

  /* Advanced example:
     Build a (time varying) volume mesh containing cells
     with values of field named "He_fraction" > 0.05 */

  /*! [post_define_mesh_4] */
  {
    const int n_writers = 1;
    const int writer_ids[] = {2};  /* Associate to writer 2 */

    /* Define postprocessing mesh */

    cs_post_define_volume_mesh_by_func(4,               /* mesh id */
                                       "Mesh_1_rans.unv",
                                       _xyz_fraction_select,
                                       NULL,            /* _c_05_select_input */
                                       true,            /* time varying */
                                       false,           /* add_groups */
                                       true,           /* auto_variables */
                                       n_writers,
                                       writer_ids);
  }
  /*! [post_define_mesh_4] */


/*----------------------------------------------------------------------------*/
/*!
 * \brief Define monitoring probes and profiles.
 *
 * Profiles are defined as sets of probes.
 */
/*----------------------------------------------------------------------------*/
}

/*----------------------------------------------------------------------------*/
/*!
 * \brief User function for output of values on a post-processing mesh.
 *
 * \param[in]       mesh_name    name of the output mesh for the current call
 * \param[in]       mesh_id      id of the output mesh for the current call
 * \param[in]       cat_id       category id of the output mesh for the
 *                               current call
 * \param[in]       probes       pointer to associated probe set structure if
 *                               the mesh is a probe set, NULL otherwise
 * \param[in]       n_cells      local number of cells of post_mesh
 * \param[in]       n_i_faces    local number of interior faces of post_mesh
 * \param[in]       n_b_faces    local number of boundary faces of post_mesh
 * \param[in]       n_vertices   local number of vertices faces of post_mesh
 * \param[in]       cell_list    list of cells (0 to n-1) of post-processing
 *                               mesh
 * \param[in]       i_face_list  list of interior faces (0 to n-1) of
 *                               post-processing mesh
 * \param[in]       b_face_list  list of boundary faces (0 to n-1) of
 *                               post-processing mesh
 * \param[in]       vertex_list  list of vertices (0 to n-1) of
 *                               post-processing mesh
 * \param[in]       ts           time step status structure, or NULL
 */
/*----------------------------------------------------------------------------*/

void
cs_user_postprocess_values(const char            *mesh_name,
                           int                    mesh_id,
                           int                    cat_id,
                           cs_probe_set_t        *probes,
                           cs_lnum_t              n_cells,
                           cs_lnum_t              n_i_faces,
                           cs_lnum_t              n_b_faces,
                           cs_lnum_t              n_vertices,
                           const cs_lnum_t        cell_list[],
                           const cs_lnum_t        i_face_list[],
                           const cs_lnum_t        b_face_list[],
                           const cs_lnum_t        vertex_list[],
                           const cs_time_step_t  *ts)
{
  /* Output of k=1/2(R11+R22+R33) for the Rij-epsilon model
     ------------------------------------------------------ */

  /*< [postprocess_values_ex_1] */
  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);

    if (cs_glob_turb_rans_model->irijco) {
      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_write_var(mesh_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);
  }
  /*< [postprocess_values_ex_1] */



  /* Output cell-based scalar user field values on volume and meshes
     ---------------------------------------------------------------- */

  /*< [postprocess_values_ex_3] */
  if (   cat_id == CS_POST_MESH_VOLUME
      || cat_id == CS_POST_MESH_PROBES) {

    const cs_field_t *f = cs_field_by_name_try("epsilon");

    if (f != NULL)
      cs_post_write_var(mesh_id,
                        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);
  }
  /*< [postprocess_values_ex_3] */

  /* Output constant cell-based scalar user field values on volume mesh
     ------------------------------------------------------------------ */

  /*< [postprocess_values_ex_4] */
  if (cat_id == CS_POST_MESH_VOLUME) {

    const cs_field_t *f = cs_field_by_name_try("epsilon");

    if (f != NULL) {
      if (ts->nt_cur == ts->nt_prev + 1) { /* before time loop */

        cs_time_step_t ts0 = *ts;
        ts0.nt_cur = 1; /* Negative time step value implies time-independent */

        cs_post_write_var(mesh_id,
                          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);

      }
    }

  }
  /*< [postprocess_values_ex_4] */
}

/*----------------------------------------------------------------------------*/
/*!
 * Override default frequency or calculation end based output.
 *
 * This allows fine-grained control of activation or deactivation,
 *
 * \param  nt_max_abs  maximum time step number
 * \param  nt_cur_abs  current time step number
 * \param  t_cur_abs   absolute time at the current time step
 */
/*----------------------------------------------------------------------------*/

void
cs_user_postprocess_activate(int     nt_max_abs,
                             int     nt_cur_abs,
                             double  t_cur_abs)
{
  /* Use the cs_post_activate_writer() function to force the
   * "active" or "inactive" flag for a specific writer or for all
   * writers for the current time step.

   * the parameters for cs_post_activate_writer() are:
   *   writer_id <-- writer id, or 0 for all writers
   *   activate  <-- false to deactivate, true to activate */

  /* Example: deactivate all output before time step 1000 */

  /*! [post_activate] */
  if (nt_max_abs < 2) {
    int writer_id = 0; /* 0: all writers */
    cs_post_activate_writer(writer_id, false);
  }
  /*! [post_activate] */
}

/*----------------------------------------------------------------------------*/

