#ifndef _new_alberta_hh_
#define _new_alberta_hh_
#ifdef DMALLOC
#include <dmalloc.h>
#endif

#if DIM == 1
#define h2_from_det(det) ((det)*(det))
#endif
#if DIM == 2
#define h2_from_det(det) (det)
#endif
#if DIM == 3
#define h2_from_det(det)  pow((det), 2.0/3.0)
#endif

/*!This variable is counted upward and downward by time stepping algorithms and messages are
indented by it, thus structuring output. Implemented in local msg.c.*/
extern int print_depth;

/*forerunner of EL_GEOM_CACHE, now only evaluation time. Unsure what to do with it.*/
//now is the time to kick it:
//struct lambda_det
//{
//  REAL  Lambda[DIM+1][DIM_OF_WORLD];    /* the gradient of the barycentric coordinates gibts*/
//  REAL    det;              /*  |det D F_S| */
// EL_GEOM_CACHE const *  geom_cache;
		/*an sich per el_info in allen fraglichen
 					Funktionen verfuegbar.
 					Damit ist diese Konstruktion auch eine Altlast. Time
					reicht.  Muessen bloss umstellen*/
// REAL eval_time;	//neu 13.4. scheint mir das beste zu sein, besser als Argumentlisten aendern
//};

//typedef  struct lambda_det LAMBDA_DET;
//EL_GEOM_CACHE beraubt lambda_det seiner Berechtigung. 
//entscheidung treffen: Member eval_time in op_arg_info u. dieses auch als Argument in elfunc verwenden?
// oder Argumente (const EL_INFO * const el_info,	const REAL* const) verwenden?

/*!abstract base class of functions for elementwise calculation of a real nr. It is useful to
calculate expressions that can be calculated for each element (e.g. DOF_REAL_VEC entries for that
element) once for each element and then use them for evaluation at points.*/
class elfunc
{public:
 	virtual int set_at_el(const EL_INFO * const el_info,   REAL eval_time/*LAMBDA_DET* const assem_el_info*/) = 0;
				
 	virtual REAL calc(const REAL* const lambda)=0;
	virtual ~elfunc(){};

protected:
REAL fac;
};


/*!abstract base class of functions that return components of a DIM_OF_WORLD * DIM_OF_WORLD
Real matrix, e.g. the diffusion matrix. Elementwise Initialization is supported.*/
class matfunc
{public:
	virtual int set_at_el(const EL_INFO * const el_info,
					REAL eval_time/*LAMBDA_DET* const assem_el_info*/)=0;
	virtual int set_at_bary(const REAL* const lambda
					)=0; 
					/*5.10.06, initialize at barycentric coordinates*/ 
	REAL getcomp(int i, int j) 
	const{
		return mat[i][j];
		}
		/*get component i,j*/
	virtual ~matfunc(){};
protected:
REAL_DD mat;
};

/****************************************************************************/
//Flags for filling the operator_info flags in set_std_op_info via prob_data_diff->flag
//#define DIFFMAT_SYMMETRIC    (1 << 0)
#define DIFFMAT_PW_CONST (1 << 1)
#define LB0_SYMMETRIC    (1 << 2)
#define LB_PW_CONST (1 << 3)
#define ORDER0_PW_CONST (1 << 4)
#define MASS_CONST (1 << 5)
#define DIFFMAT_FULL    (1 << 6)
#define DIFFMAT_DIAG    (1 << 7)
#define DIFFMAT_ISOTROP    (1 << 8)
/*
Haben jetzt Klassen-Funktionen, die REAL zurueckgeben. */
/*!Structure that bears pointers to coefficient functions for an one-component block of a (possibly
bigger) linear problem. Those functions of type elfunc are  evaluated by LALt and c  of the
OPERATOR_INFO  corresponding to that block. 
The prototypes for g_Dirich and g_Neumann are chosen according to the prototypes needed by functions like
 dirichlet_bound, they are still the first shot and have proven inappropriate in many ways, e.g the
 global variable argument which complicates evaluation of expressions depending on DOF_*_VECS.
 They should be changed to some boundary operators prototype. Unfortunately, neither is there time to find
 out about them, nor to change the Neumann function which implements Robin boundary at the moment (see
 build_stat.cc).*/
struct prob_data_diff
        { // Koeff-functions neu!!!
		 matfunc* diffmat;
/*!read by stiffness matrix OPERATOR_INFO LALt*/
		elfunc* order0func;
/*!read by stiffness matrix OPERATOR_INFO c*/
		elfunc* massfunc;		//neu, ggf. nil
/*!read by mass matrix OPERATOR_INFO c*/
		FLAGS /*const*/flags;		//doch lieberso, nehm ich dann fuer alle - Elmar! Baustelle;
		REAL physconstants[10]; 
		elfunc*   f_sources;
/*Bei all diesen Funktionen ist zu ueberlegen, ob man nicht Klassen macht aehnlich elfunc.*/ 
		REAL (*sol_0)(const REAL_D x);            
/* initial data    */
  		REAL (*g_Dirich)(const REAL_D x, REAL t);  	
/*!See Comment below!!	 Dirichlet bdry values on Dirichlet,
				exterior value on Robin Bound. Warum kein  s_char?  Scheiss Prototyp*/
  		REAL (*g_Neumann)(const REAL_D x, REAL t, S_CHAR);
/*! Neumann (Robin) bdry coeff */
 		 REAL (*sol_ex)(const REAL_D x);   			
/*! known  soln      */
  		REAL *(*grd_sol_ex)(const REAL_D x, REAL t);	
 /*! known  gradient   */
        };
typedef       struct prob_data_diff PROB_DATA_DIFF ;
#if 0
so sehn flags aus:
#define FILL_NOTHING            0x00L
#define FILL_COORDS             0x01L
#define FILL_BOUND              0x02L
#define FILL_NEIGH              0x04L
#define FILL_OPP_COORDS         0x08L
#define FILL_ORIENTATION        0x10L
#endif

/*!structure passed through the OPERATOR_INFO methods like LALt and c via the void*user_data pointer
e.g. to pass a matfunc diffmat to LALt. This allows us to regard LALt as a function instead of an
instance of a diffusion matrix*/
struct op_arg_info
{
	PROB_DATA_DIFF const * const prob_data_ptr;
//	LAMBDA_DET lambda_det; //dann bald mal eval_time??
	REAL eval_time;
	op_arg_info(PROB_DATA_DIFF const * const prob_data_diff)
		:prob_data_ptr(prob_data_diff)
		{};
};


typedef struct op_arg_info OP_ARG_INFO ;
//hamse vergessen
void dof_set(int alpha, DOF_INT_VEC *x);
#endif
