
//
// fem_base enthaelt alle Daten des Problems
// gemeinsamer Nenner aller Methoden, die eine FEM_Loesung einer DGL verarbeiten.
//ist sinngemaess eine abstrakte Klasse, dennoch kann man instanzieren, um build und est von gleicher
//Basis ableiten zu koennen. Diese haben dann natuerlich Kopien der fem_base, von moeglichst geringer
//Tiefe natuerlich.
#include <alberta.h>
#if (defined(ALBERTA_VER) && (ALBERTA_VER==2))
//# include "/opt/alberta-20070522-1869/alberta/src/Common/alberta_intern.h"
//wegen der  AI_add_real_vec_to_admins
//#include <alberta_util_inlines.h>
# include "alberta1_wrapper.h"
#endif

#include "newalberta.hh"
#include "do_on_el.hh"
#include "do_elfunc_on_el.hh"
#include "prototype_fem_elfunc.hh"
#include "fem_elfunc.hh"
#include "fem_base.hh"


void fem_base::init_timestep()
{
  int i;
  for (i=0; i<ncomps; i++)
    {
      dof_copy(u_h[i], u_old[i]);
    }
   return;
}


fem_base::fem_base(const char *const name, 
		   DOF_REAL_VEC **u_h, DOF_REAL_VEC **u_h_old, 
		   DOF_SCHAR_VEC** bound_vec, 
		   const PROB_DATA_DIFF * const* const prob_data, 
		    const int ncomps,  REAL const   * const time)
  : ncomps(ncomps), u_h(u_h), u_old(u_h_old), 
    bound_vec(bound_vec), /*op_arg_info(new OP_ARG_INFO(prob_data)),*/  
    time(time), op_arg_infos(new OP_ARG_INFO* [ncomps*ncomps])
{
 int comp, col_comp;
  FUNCNAME("fem_base constructor");
  TEST_EXIT(prob_data,"no prob_data\n");
  char  key[128];
  sprintf(key, "%s info_level",name);
  if (!(GET_PARAMETER(2, key, "%d", &info_level)))
  {
    info_level=6;
  }
  MSG("%s: %d\n",key,info_level);
 
  for (comp =0; comp<ncomps; comp++)
  {
 
  	dof_set(0.0, u_h[comp]);
 	dof_set(0.0, u_old[comp]);
   	for (col_comp =0; col_comp<ncomps; col_comp++)
 		op_arg_infos[comp*ncomps + col_comp] = new OP_ARG_INFO(prob_data[comp*ncomps + col_comp]);
  }
  op_arg_info = op_arg_infos[0];
  common_source_contrib = nil;
}

//Konstruktor fuer Typumwandlung! 
// fem_base::fem_base(const char *const name, build_diff const *const discrete_prob)
//  : fem_base(name, build_diff->fe_space, 
//		   build_diff->u_h, build_diff->u_h_old, build_diff->bound_vec,
//						build_diff->prob_data) {};

//fuer Systeme
// get_dof_real_vec istt kein vernuenftiger Konstruktor, kann keine Vektoren allokieren
  fem_base::fem_base(const char *const name,  FE_SPACE const *const fe_space,
	   const PROB_DATA_DIFF *const* const prob_data, const int ncomps, REAL  const   * const time)
		: ncomps(ncomps)
		,u_h(new DOF_REAL_VEC* [ncomps])
		,u_old(new DOF_REAL_VEC* [ncomps])
		,bound_vec(new DOF_SCHAR_VEC* [ncomps])
		,time(time)
		,  op_arg_infos(new OP_ARG_INFO* [ncomps*ncomps]) /*Baustelle. dies implizert, dass wir es mit der Basisklasse
  				eines Systems zu tun haben und nicht mit einem mehrkomponentigen Vektor. Dies
				ist spezieller als zuerst gedacht.*/

{ int comp, col_comp;
  FUNCNAME("fem_base constructor");
  char  key[128];
  TEST_EXIT(fe_space,"no fe_space\n");
  TEST_EXIT(prob_data,"no prob_data\n");
  sprintf(key, "%s info_level",name);
  if (!(GET_PARAMETER(2, key, "%d", &info_level))) {info_level=6;}

  for (comp =0; comp<ncomps; comp++)
  {
  	sprintf(key, "%s_h%d",name,comp);
  	u_h[comp]                  = get_dof_real_vec(key, fe_space);
  	u_h[comp]->refine_interpol = fe_space->bas_fcts->real_refine_inter;
  	u_h[comp]->coarse_restrict = fe_space->bas_fcts->real_coarse_inter;
  	sprintf(key, "%s_old%d",name,comp);
  	u_old[comp]                  = get_dof_real_vec(key, fe_space);
  	u_old[comp]->refine_interpol = fe_space->bas_fcts->real_refine_inter;
  	u_old[comp]->coarse_restrict = fe_space->bas_fcts->real_coarse_inter;
  	sprintf(key, "%s_bound%d",name,comp);
  	bound_vec[comp]  = get_dof_schar_vec(key, fe_space);
 
  	dof_set(0.0, u_h[comp]);
 	 dof_set(0.0, u_old[comp]);
   	for (col_comp =0; col_comp<ncomps; col_comp++)
 		op_arg_infos[comp*ncomps + col_comp] = new OP_ARG_INFO(prob_data[comp*ncomps + col_comp]);
  }
  op_arg_info = op_arg_infos[0];
  common_source_contrib = nil;
  }
