/*!base class for all assembling routines, implementing one-component stationary problem assemblage. Its  data types are suitable for multicomponent systems in preparation
of being inherited, but its methods only work with one component.*/
class build_stat:  public  fem_base , public fem_elfunc
{
private:
     	REAL  **el_mat; 
	int common_construct_func(const char *const name, const int quad_degree);
//  const QUAD     *quad_face;
protected:
  virtual int calc(const EL_INFO * const el_info);
  virtual int set_at_el(const EL_INFO * const el_info, REAL eval_time);
  OPERATOR_INFO   op_info ;
  //immer ein Vektor und ein Zeiger auf das zum aktuellen Block gehoerende Element. So laesst sich der
  //code am Besten recyclen und fuer Blocksysteme einsetzen
  EL_MATRIX_INFO   *const matrix_infos;
  EL_MATRIX_INFO   *matrix_info;
  DOF_MATRIX     *matrix;
  DOF_MATRIX     **matrix_blocks;
  const QUAD_FAST  * *  test_quad_fasts;      /*--  ... element integration  -------------*/
  DOF_REAL_VEC   **f_h;
	REAL *el_f;
  const  REAL     * const *a_mat;
  REAL           *f_vec;
  REAL           *u_vec;
  S_CHAR 		* b_vec;
  const REAL theta;
public:
 
//  virtual void el_fct(const EL_INFO *el_info);
  virtual int assemble();

  DOF_REAL_VEC *const get_rhs(int row) const
  { 
    FUNCNAME("get_rhs");
    TEST_EXIT(row<=ncomps, "%s: comps  %d called, which is bigger than ncomps\n"
    			, f_h[0]->name,row);
    return((DOF_REAL_VEC *const)f_h[row]);
  };
  DOF_REAL_VEC *const get_rhs(void) const
  {
    return((DOF_REAL_VEC *const)f_h[0]);
  };

  DOF_MATRIX *const get_mat(void) const
  {
    return((DOF_MATRIX *const)matrix);
  };
  DOF_MATRIX *const get_mat_block(int i, int j) const
  {
    return((DOF_MATRIX *const)matrix_blocks[i*ncomps + j]);
  };
  REAL   sol_ex(const REAL_D x)
  {
    FUNCNAME("sol_ex");
    TEST(prob_data_ptr->sol_ex,"no exact solution\n");

    if (prob_data_ptr->sol_ex)
      return(prob_data_ptr->sol_ex(x));
    else
      return(0.0); 
  };
  virtual ~build_stat()
	{ 
	delete [] el_f;
	
  	for (int i=0; i<f_h[0]->fe_space->bas_fcts->n_bas_fcts; i++)
  		delete [] el_mat[i];
  	delete []  el_mat;
//noch viel zu tun
	};
//private:wird alles von build_diff gebraucht
protected:
 	int 	robin(const EL_INFO *el_info, const int face , const S_CHAR face_bound,const REAL eval_time
                  			);
private:
	int set_std_op_info(int row, int col); //und viell. noch einen f. spezielle ops
public:
						
  build_stat(const char *const name, 
			 DOF_REAL_VEC **u_h, DOF_REAL_VEC   **u_h_old
			 , DOF_SCHAR_VEC** bound_vec, DOF_REAL_VEC  **f_h
			 , const PROB_DATA_DIFF * const* const prob_data, const int ncomps
			 , int quad_degree,REAL const   * const time
			, REAL const   * const timestep, const REAL theta);

  build_stat(const char *const name,fem_base const * const base, DOF_REAL_VEC   **f_h,  int quad_degree
				,  const  REAL *const timestep, const REAL theta);

  build_stat(const char *const name,  FE_SPACE const *const fe_space,
		       const PROB_DATA_DIFF * const * const prob_data
		       , const int ncomps, int quad_degree,
			REAL const   * const time
			,  const  REAL *const timestep, 
						 const REAL theta);
};

//Matrixaddition B=B+A:
int dof_ApB(const DOF_MATRIX* A, DOF_MATRIX* B,const DOF_SCHAR_VEC   *bound);
