/*--------------------------------------------------------------------------*/
/* ALBERTA:  an Adaptive multi Level finite element toolbox using           */
/*           Bisectioning refinement and Error control by Residual          */
/*           Techniques for scientific Applications                         */
/*--------------------------------------------------------------------------*/
/*                                                                          */
/* file:     slip_bound.h                                                   */
/*                                                                          */
/*                                                                          */
/* description: header for slip_bound.c                                     */
/*                                                                          */
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*  authors:   Daniel Koester                                               */
/*             Institut fuer Mathematik                                     */
/*             Universitaet Augsburg                                        */
/*             Universitaetsstr. 14                                         */
/*             D-86159 Augsburg, Germany                                    */
/*                                                                          */
/*  http://www.alberta-fem.de                                               */
/*                                                                          */
/*--------------------------------------------------------------------------*/

typedef enum bound_type {FREE=-3, DO_NOTHING=-2, SLIP=-1, NO_SLIP=1} BOUND_TYPE;

/* Slip boundary transformation status                                      */

#define SB_UNDEFINED   0
#define SB_NORMAL      1
#define SB_TRANSFORMED 2
typedef int SB_STATUS;

static inline void MM_DOW(REAL_DD a, REAL_DD b, REAL_DD res)
{
  int i, j, k;

  for (i = 0; i < DIM_OF_WORLD; i++) {
    for (j = 0; j < DIM_OF_WORLD; j++) {
      for (res[i][j] = k = 0; k < DIM_OF_WORLD; k++) {
	res[i][j] += a[i][k] * b[k][j];
      }
    }
  }

  return;
}

SB_STATUS sb_get_status_dof_real_d_vec(const DOF_REAL_D_VEC *drdv);
SB_STATUS sb_get_status_dof_dowb_matrix(const DOF_DOWB_MATRIX *ddm);
void sb_set_status_dof_real_d_vec(DOF_REAL_D_VEC *drdv, SB_STATUS status);
void sb_set_status_dof_dowb_matrix(DOF_DOWB_MATRIX *ddm, SB_STATUS status);
void sb_unset_status_dof_real_d_vec(DOF_REAL_D_VEC *drdv);
void sb_unset_status_dof_dowb_matrix(DOF_DOWB_MATRIX *ddm);
void sb_transform_dof_real_d_vec(DOF_REAL_D_VEC *drdv1, DOF_REAL_D_VEC *drdv2,
				 DOF_REAL_D_VEC *normal, DOF_SCHAR_VEC *bound,
				 SB_STATUS current_status);
void sb_transform_dof_dowb_matrix(DOF_DOWB_MATRIX *ddm,
				  DOF_REAL_D_VEC *normal, DOF_SCHAR_VEC *bound,
				  SB_STATUS current_status);
void sb_slip_bound(DOF_DOWB_MATRIX *ddm, DOF_REAL_D_VEC *drdv1, 
		   DOF_REAL_D_VEC *drdv2, DOF_SCHAR_VEC *bound);
