/** @file
 *
 *
 *      authors: Claus-Justus Heine
 *               Abteilung fuer Angewandte Mathematik                     
 *               Albert-Ludwigs-Universitaet Freiburg
 *               Hermann-Herder-Str. 10
 *               79104 Freiburg
 *               Germany
 *               claus@mathematik.uni-freiburg.de
 *
 *      Copyright (c) by C.-J. Heine (2003-2006)
 *
 *
 * Header file for ILU(k) implementation.
 */
#ifndef _ALBERTA_ILU_K_H_
#define _ALBERTA_ILU_K_H_

#include <crs_matrix.h>

/**@addtogroup CRS_MATRIX 
 * @{
 */
/**@addtogroup CRS_PRECON
 * @{
 */

/**@name Access macros
 * @internal
 * @brief Some macros to access the entries of an CRS matrix
 */
#define CRS_COL(M, r, index) ((M)->info->col[(M)->info->row[r] + (index)])
#define CRS_VAL_REL(M, r, index, type) ((type *)((M)->entries))[(M)->info->row[r] + (index)]
#define CRS_BEG(M, r)        ((M)->info->row[r])
#define CRS_END(M, r)        ((M)->info->row[r+1])
#define CRS_DIAG(M, r, type) CRS_VAL_REL(M, r, 0, type) /* diagonal entry */

/* BIG FAT NOTE: the matrix columns are sorted, we store the first
 * upper diagonal index in col[row[i]] (we know that entries[row[i]]
 * is the diagonal entry
 */
#define CRS_U(M, r)          CRS_COL(M, r, 0) /**< first index > r */
/**@} */

/* Constructors for ILU(k) from CRS_MATRIXes */
extern CRS_MATRIX *ilu_k_create_profile(const CRS_MATRIX *A,
					int level, int info_level);
extern int ilu_k_create(const CRS_MATRIX *A, CRS_MATRIX *ilu,
			REAL alpha, REAL beta, int info);
extern int ilu_k_create_adaptive(const CRS_MATRIX *A,
				 CRS_MATRIX *ilu, int info);
extern int ilu_k_create_dd(const CRS_MATRIX *A, CRS_MATRIX *ilu,
			   REAL alpha, REAL beta, int info);
extern int ilu_k_create_dd_adaptive(const CRS_MATRIX *A,
				    CRS_MATRIX *ilu, int info);

/* Constructors for ILU(k) from DOF_MATRIXes */
extern CRS_MATRIX *ilu_k_dm_create_profile(const DOF_MATRIX *A,
					   const DOF_SCHAR_VEC *mask,
					   int level, int info_level);
extern int ilu_k_dm_create(const DOF_MATRIX *A, CRS_MATRIX *ilu,
			   REAL alpha, REAL beta, int info);
extern int ilu_k_dm_create_adaptive(const DOF_MATRIX *A,
				    CRS_MATRIX *ilu, int info);
extern int ilu_k_dm_create_dd(const DOF_MATRIX *A, CRS_MATRIX *ilu,
			      REAL alpha, REAL beta, int info);
extern int ilu_k_dm_create_dd_adaptive(const DOF_MATRIX *A,
				       CRS_MATRIX *ilu, int info);

/* The preconditioner itself, i.e. LU solve. */
extern void ilu_k_solve(const CRS_MATRIX *ilu, REAL *x);
extern void ilu_k_solve_d(const CRS_MATRIX *ilu, REAL_D *x);
extern void ilu_k_solve_b(const CRS_MATRIX *ilu, REAL_D *x);

/* ALBERTA precon interface */
extern const PRECON *get_ILUk_precon(const DOF_MATRIX *A,
				     const DOF_SCHAR_VEC *mask,
				     int ilu_level, int info);

/**@} CRS_PRECON */
/**@} CRS_MATRIX */

#endif /* _ILU_K_H_ */
