/*--------------------------------------------------------------------------*/
/*  author:    Notger Noll                                                  */
/*             Abteilung fuer angewandte Mathematik                         */
/*                                                                          */
/*             Albert Ludwigs Universitaet Freiburg                         */
/*             Herman Herder Str. 10                                        */
/*             D-79106 Freiburg, Germany                                    */
/*                                                                          */
/*  http://www.mathematik.uni-freiburg.de/IAM/ALBERTA                       */
/*                                                                          */
/*  (c) by N. Noll (2008)                                                   */
/*--------------------------------------------------------------------------*/

#ifndef OEM_BLOCK_SOLVE_H_
#define OEM_BLOCK_SOLVE_H_

#include <alberta/alberta.h>

#define N_OEM_BLOCKS_MAX 10

typedef struct block_dof_vec
{
  const char *name;
  int n_components;
  
  DOF_REAL_VEC_D *dof_vec[N_OEM_BLOCKS_MAX];
  
} BLOCK_DOF_VEC;


typedef struct block_dof_schar_vec
{
  const char *name;
  int n_components;
  
  DOF_SCHAR_VEC *schar_vec[N_OEM_BLOCKS_MAX];
  
} BLOCK_DOF_SCHAR_VEC;

typedef enum {
  Full,
  Empty,
  Diag,
  Triag,
  Symm,
  SymmTriag
} MatType;

typedef struct block_dof_matrix 
{
  const char	  *name;
  int		  n_row_components;
  int		  n_col_components;
  
  const FE_SPACE  *row_fe_spaces[N_OEM_BLOCKS_MAX];
  const FE_SPACE  *col_fe_spaces[N_OEM_BLOCKS_MAX];
  
  MatType	  block_type;
  
  DOF_MATRIX      *dof_mat[N_OEM_BLOCKS_MAX][N_OEM_BLOCKS_MAX];
  MatrixTranspose transpose[N_OEM_BLOCKS_MAX][N_OEM_BLOCKS_MAX];
} BLOCK_DOF_MATRIX;

typedef struct block_precon_type
{ 
  /* Block-Precon-Type */
  OEM_PRECON block_type;
  
  REAL block_omega;      /* for BlkSSORPrecon */
  int  block_n_iter;     /* for BlkSSORPrecon */
  
  PRECON_TYPE precon_type[N_OEM_BLOCKS_MAX];
} BLOCK_PRECON_TYPE;

BLOCK_DOF_VEC *get_block_dof_vec(const char *name, int n_components,
				 const FE_SPACE *fe_space, ...);
BLOCK_DOF_SCHAR_VEC *get_block_dof_schar_vec(const char *name, int n_components,
					     const FE_SPACE *fe_space, ...);
void free_block_dof_vec(BLOCK_DOF_VEC *bvec);
void free_block_dof_schar_vec(BLOCK_DOF_SCHAR_VEC *bvec);

BLOCK_DOF_MATRIX *get_block_dof_matrix(const char *name,
				       int n_row_components,
				       int n_col_components,
				       MatType block_type,
				       const FE_SPACE *fe_space, ...);
void free_block_dof_matrix(BLOCK_DOF_MATRIX *bmat);
void clear_block_dof_matrix(BLOCK_DOF_MATRIX *bmat);

const PRECON *init_oem_block_precon(const BLOCK_DOF_MATRIX *block_mat,
				    const BLOCK_DOF_SCHAR_VEC *block_mask,
				    int info,
				    const BLOCK_PRECON_TYPE *prec_type);
int oem_block_solve(const BLOCK_DOF_MATRIX *A, const BLOCK_DOF_SCHAR_VEC *bound,
		    const BLOCK_DOF_VEC *f, BLOCK_DOF_VEC *u,
		    OEM_SOLVER solver,
		    REAL tol,
		    const PRECON *precon, int restart, int max_iter, int info);

void block_dof_copy(const BLOCK_DOF_VEC *x, BLOCK_DOF_VEC *y);
void block_dof_set(REAL stotz, BLOCK_DOF_VEC *bvec);

int copy_from_block_dof_vec(REAL *x, BLOCK_DOF_VEC *bdof);
int copy_to_block_dof_vec(BLOCK_DOF_VEC *bdof, REAL *x);
int block_dof_vec_length(BLOCK_DOF_VEC *bdof);


void get_size_of_dof_matrix(const BLOCK_DOF_MATRIX *block_mat,
					int r, int c, int *n_rows, int *n_cols);
void print_block_dof_vec(BLOCK_DOF_VEC *block_vec);
void print_block_dof_matrix(BLOCK_DOF_MATRIX *block_mat);
void print_block_dof_vec_maple(BLOCK_DOF_VEC *block_vec,
			       const char *block_name);
void print_block_dof_matrix_maple(BLOCK_DOF_MATRIX *block_mat,
				  const char *block_name);
void fprint_block_dof_vec_maple(FILE *fp, BLOCK_DOF_VEC *block_vec,
				const char *block_name);
void fprint_block_dof_matrix_maple(FILE *fp, BLOCK_DOF_MATRIX *block_mat,
				   const char *block_name);
void file_print_block_dof_vec_maple(const char *file_name,
				    const char fopen_options[],
				    BLOCK_DOF_VEC *block_vec,
				    const char *block_name);
void file_print_block_dof_matrix_maple(const char *file_name,
				       const char fopen_options[],
				       BLOCK_DOF_MATRIX *block_mat,
				       const char *block_name);

#endif /*OEM_SOLVE_BLOCK_D_H_*/


