/*--------------------------------------------------------------------------*/
/* ALBERTA:  an Adaptive multi Level finite element toolbox using           */
/*           Bisectioning refinement and Error control by Residual          */
/*           Techniques for scientific Applications                         */
/*--------------------------------------------------------------------------*/
/*                                                                          */
/* file:     memory_0d.c                                                    */
/*                                                                          */
/*                                                                          */
/* description:  special routines for getting new FE_SPACEs, 0D-Version     */
/*                                                                          */
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*  authors:   Daniel Koester                                               */
/*             Institut fuer Mathematik                                     */
/*             Universitaet Augsburg                                        */
/*             Universitaetsstr. 14                                         */
/*             D-86159 Augsburg, Germany                                    */
/*                                                                          */
/*  http://www.alberta-fem.de                                               */
/*                                                                          */
/*  (c) by D. Koester (2005)                                                */
/*--------------------------------------------------------------------------*/


/****************************************************************************/
/* adjust_dofs_and_dof_ptrs_0d(mesh, new_admin, old_n_node_el,              */
/*                             old_n_dof, old_node):                        */
/* 1) If el->dof pointers have changed, adjust these. Keep old information! */
/* 2) Determine what types of new DOF pointers must be allocated.           */
/* 3) Change all DOFs on all elements.                                      */
/****************************************************************************/

static void adjust_dofs_and_dof_ptrs_0d(MESH *mesh, DOF_ADMIN *new_admin,
					int old_n_node_el,
					int *old_n_dof, int *old_node)
{
  /* FUNCNAME("adjust_dofs_and_dof_ptrs_0d"); */
  DOF            **old_dof_ptr;
  int              i, n, n_elements, node;
  int              change_v_d = 0, change_c_d = 0;
  EL              *el;
  TRAVERSE_STACK  *stack = get_traverse_stack();
  const EL_INFO   *el_info = NULL;

  /* Adjust the length of el->dof pointer fields. Allocate new ones if      */
  /* necessary and transfer old information.                                */
  
  if(mesh->n_node_el > old_n_node_el) {
    el_info = traverse_first(stack, mesh, -1, CALL_EVERY_EL_PREORDER);
    while(el_info) {
      el = el_info->el;

      old_dof_ptr = el->dof;
      el->dof = get_dof_ptrs(mesh);

      if(old_n_dof[VERTEX])
	for(i = 0; i < N_VERTICES_1D; i++)
	  el->dof[mesh->node[VERTEX] + i] = old_dof_ptr[old_node[VERTEX] + i];
      if(old_n_dof[CENTER])
	el->dof[mesh->node[CENTER]] = old_dof_ptr[old_node[CENTER]];

      el_info = traverse_next(stack, el_info);
    }
  }

  /* Determine which DOF types have changed on the mesh with the new admin. */

  if(mesh->n_dof[VERTEX] > old_n_dof[VERTEX])
    change_v_d = 1;
  if(mesh->n_dof[CENTER] > old_n_dof[CENTER])
    change_c_d = 1;

  /* Change all DOFs on all elements of the mesh.                           */

  n_elements = mesh->n_elements;

  for(n = 0; n < n_elements; n++) {
    el = mesh->macro_els[n].el;
    
    if(change_v_d) {
      node = mesh->node[VERTEX];
      
      el->dof[node] = 
	transfer_dofs(mesh, new_admin, el->dof[node], VERTEX, false, false);
    }
      
    if(change_c_d) {
      node = mesh->node[CENTER];
      
      el->dof[node] = 
	transfer_dofs(mesh, new_admin, el->dof[node], CENTER, false, false);
    }
  }

/*  Clean up operations.                                                    */

  free_traverse_stack(stack);
  
  return;
}
