/*******************************************************************************
 * ALBERTA:  an Adaptive multi Level finite element toolbox using
 *           Bisectioning refinement and Error control by Residual
 *           Techniques for scientific Applications
 *
 * file:     assemble.h
 *
 * description:  fe-space independent assemblation routines of matrices,
 *		 general header
*
 *******************************************************************************
 *
 *  authors:   Alfred Schmidt
 *             Zentrum fuer Technomathematik
 *             Fachbereich 3 Mathematik/Informatik
 *             Universitaet Bremen
 *             Bibliothekstr. 2
 *             D-28359 Bremen, Germany
 *
 *             Kunibert G. Siebert
 *             Institut fuer Mathematik
 *             Universitaet Augsburg
 *             Universitaetsstr. 14
 *             D-86159 Augsburg, Germany
 *
 *             Claus-Justus Heine
 *             Abteilung fuer Angewandte Mathematik
 *             Albert-Ludwigs-Universitaet Freiburg
 *             Hermann-Herder-Str. 10
 *             D-79104 Freiburg im Breisgau, Germany
 *
 *  http://www.alberta-fem.de
 *
 *  (c) by A. Schmidt and K.G. Siebert (1996-2003),
 *         C.-J. Heine (1998-2009)
 *
 ******************************************************************************/
#ifndef _ALBERTA_ASSEMBLE_H_
#define _ALBERTA_ASSEMBLE_H_

#include "alberta_intern.h"
#include "alberta.h"
#include "assemble_bndry.h"

typedef struct bndry_op {
  BNDRY_FLAGS               bndry_type;
  const AI_BNDRY_EL_MAT_FCT *el_mat_fct;
  BNDRY_FILL_INFO           *fill_info;
} BNDRY_OP;

typedef struct adv_cache
{
  const QUAD             *quad;
  const Q010_ETA_PSI_PHI *q010;
  const Q100_ETA_PSI_PHI *q100;
  const QUAD_FAST        *row_quad_fast;
  const QUAD_FAST        *col_quad_fast;
  const QUAD_FAST        *adv_quad_fast;
  REAL_D                 *adv_field;
  int                    adv_field_size;
  DBL_LIST_NODE          chain;
} ADV_CACHE;

typedef struct fill_info FILL_INFO;
struct fill_info
{
  OPERATOR_INFO op_info;

  /* for DOW block-matrices, the block-matrix type of the integral
   * kernel
   */
  MATENT_TYPE krn_blk_type;

  DBL_LIST_NODE row_chain;
  DBL_LIST_NODE col_chain;

  const Q11_PSI_PHI *q11_cache;
  const Q01_PSI_PHI *q01_cache;
  const Q10_PSI_PHI *q10_cache;
  const Q00_PSI_PHI *q00_cache;

  const QUAD_FAST   *row_quad_fast[3];
  const QUAD_FAST   *col_quad_fast[3];

  ADV_CACHE         adv_cache[1];
  const EL_REAL_VEC_D *adv_coeffs;

  int        max_n_row, max_n_col; /* n_row, n_col stored in el.-mat. */
  EL_MATRIX  *el_mat;
  void       *scl_el_mat; /* Block el-mat for vector valued bas-fcts. */

  PARAMETRIC *parametric;

  EL_MATRIX_FCT el_matrix_fct;
  unsigned int  el_mat_idx;

  void       (*dflt_second_order)(const EL_INFO *, const FILL_INFO *);
  void       (*dflt_first_order)(const EL_INFO *, const FILL_INFO *);
  void       (*dflt_zero_order)(const EL_INFO *, const FILL_INFO *);

  void       (*fast_second_order)(const EL_INFO *, const FILL_INFO *);
  void       (*fast_first_order)(const EL_INFO *, const FILL_INFO *);
  void       (*fast_zero_order)(const EL_INFO *, const FILL_INFO *);

  int        c_symmetric;

  BNDRY_OP   *bndry_op;  /* array of boundary operators */
  int        n_bndry_op; /* how many of them */

  /* An operator to be called on _each_ facet */
  const AI_BNDRY_EL_MAT_FCT *wall_el_mat_fct;
  const BNDRY_FILL_INFO     *wall_fill_info;

  FILL_INFO  *next; /* link into the list of cached FILL_INFO structures */
};

extern void SS_AI_assign_assemble_fcts(FILL_INFO *fill_info,
				       const OPERATOR_INFO *oinfo,
				       U_CHAR pre_fl[3], U_CHAR quad_fl[3]);
extern void SV_AI_assign_assemble_fcts(FILL_INFO *fill_info,
				       const OPERATOR_INFO *oinfo,
				       U_CHAR pre_fl[3], U_CHAR quad_fl[3]);
extern void VS_AI_assign_assemble_fcts(FILL_INFO *fill_info,
				       const OPERATOR_INFO *oinfo,
				       U_CHAR pre_fl[3], U_CHAR quad_fl[3]);
extern void CV_AI_assign_assemble_fcts(FILL_INFO *fill_info,
				       const OPERATOR_INFO *oinfo,
				       U_CHAR pre_fl[3], U_CHAR quad_fl[3]);
extern void VC_AI_assign_assemble_fcts(FILL_INFO *fill_info,
				       const OPERATOR_INFO *oinfo,
				       U_CHAR pre_fl[3], U_CHAR quad_fl[3]);
extern void VV_AI_assign_assemble_fcts(FILL_INFO *fill_info,
				       const OPERATOR_INFO *oinfo,
				       U_CHAR pre_fl[3], U_CHAR quad_fl[3]);

#endif
