/*
    Copyright (C) 1998  Dennis Roddeman
    email: dennis.roddeman@uibk.ac.at

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation 
    59 Temple Place, Suite 330, Boston, MA, 02111-1307, USA
*/

#include "tochnog.h"

void split( long int version )

{
  long int swit=0, max_node=0, max_element=0,
    name=0, inod=0, inol=0, nnol=0, length=0, length_element=0, 
    tmp_max_element=0, isplit=0, nsplit=0, element=0, idim=0,
    iwork[1], el[MNOL+1], nodes[MNOL], split_nodes[36];
  double ddum[MUKNWN], tmp_node[MDIM], tmp_node_dof[MUKNWN], 
    tmp_node_start_refined[MDIM], tmp_node_dof_start_refined[MUKNWN],
    *node_dof=NULL, *node=NULL, *node_start_refined=NULL, 
    *node_dof_start_refined=NULL;

  if ( ndim==1 ) return;

  swit = set_swit(-1,-1,"split");
  if ( swit ) pri( "In routine SPLIT" );

  array_set( ddum, 0., MUKNWN );
  db_max_index( NODE, max_node, version, GET );
  db_max_index( ELEMENT, max_element, version, GET );

  for ( element=0; element<=max_element; element++ ) {
    if ( db_active_index( ELEMENT, element, version ) ) {
      db( ELEMENT, element, el, ddum, length, version, GET );
      name = el[0];
      if ( name!=-TRIA3 && name!=-QUAD4 && name!=-TET4 && name!=-HEX8 ) {
        cout << "Error: element " << db_name(name) << " is illegal for CONTROL_MESH_SPLIT.\n";
        exit(TN_EXIT_STATUS);
      }
      else {
        nnol = length - 1; array_move( &el[1], nodes, nnol );
        if ( name==-TRIA3 || name==-TET4 ) {
          for ( inol=0; inol<nnol; inol++ ) {
            inod = nodes[inol];
            node = db_dbl( NODE, inod, version );
            if ( db_active_index( NODE_START_REFINED, inod, version ) )
              node_start_refined = db_dbl( NODE_START_REFINED, inod, version );
            else
              node_start_refined = ddum;
            if ( nuknwn>0 ) {
              if ( db_active_index( NODE_DOF_START_REFINED, inod, version ) )
                node_dof_start_refined = db_dbl( NODE_DOF_START_REFINED, inod, version );
              else
                node_dof_start_refined = ddum;
              node_dof = db_dbl( NODE_DOF, inod, version );
            }
            iwork[0] = inod; create_node( iwork, 1, inod, node, node_dof,
              node_start_refined, node_dof_start_refined,
              version, VERSION_TMP ); 
          }
          create_element( element, tmp_max_element, el, length,
            version, VERSION_TMP );
          tmp_max_element++;
        }
        else {
          if ( name==-QUAD4 ) {
            split_nodes[0] = 0; split_nodes[1] = 1;
            split_nodes[2] = 1; split_nodes[3] = 3;
            split_nodes[4] = 3; split_nodes[5] = 2;
            split_nodes[6] = 2; split_nodes[7] = 0;
            nsplit = 4;
          }
          else if ( name==-HEX8 ) {
            split_nodes[0]  = 0; split_nodes[1]  = 1; split_nodes[2]  = 3;
            split_nodes[3]  = 0; split_nodes[4]  = 3; split_nodes[5]  = 2;
            split_nodes[6]  = 4; split_nodes[7]  = 5; split_nodes[8]  = 7;
            split_nodes[9]  = 4; split_nodes[10] = 7; split_nodes[11] = 6;
            split_nodes[12] = 1; split_nodes[13] = 3; split_nodes[14] = 7;
            split_nodes[15] = 1; split_nodes[16] = 7; split_nodes[17] = 5;
            split_nodes[18] = 0; split_nodes[19] = 2; split_nodes[20] = 6;
            split_nodes[21] = 0; split_nodes[22] = 6; split_nodes[23] = 4;
            split_nodes[24] = 0; split_nodes[25] = 1; split_nodes[26] = 5;
            split_nodes[27] = 0; split_nodes[28] = 5; split_nodes[29] = 4;
            split_nodes[30] = 2; split_nodes[31] = 3; split_nodes[32] = 7;
            split_nodes[33] = 2; split_nodes[34] = 7; split_nodes[35] = 6;
            nsplit = 12;
          }
          array_set( tmp_node, 0., ndim );
          array_set( tmp_node_start_refined, 0., ndim );
          if ( nuknwn>0 ) {
            array_set( tmp_node_dof_start_refined, 0., nuknwn );
            array_set( tmp_node_dof, 0., nuknwn );
          }
          for ( inol=0; inol<nnol; inol++ ) {
            inod = nodes[inol];
            node = db_dbl( NODE, inod, version );
            if ( db_active_index(  NODE_START_REFINED, inod, version ) )
              node_start_refined = db_dbl( NODE_START_REFINED, inod, version );
            else
              node_start_refined = ddum;
            array_add( node, tmp_node, tmp_node, ndim );
            array_add( node_start_refined, tmp_node_start_refined, 
              tmp_node_start_refined, ndim );
            if ( nuknwn>0 ) {
              if ( db_active_index( NODE_DOF_START_REFINED, inod, version ) )
                node_dof_start_refined = db_dbl( NODE_DOF_START_REFINED, inod, version );
              else
                node_dof_start_refined = ddum;
              array_add( node_dof_start_refined, tmp_node_dof_start_refined, 
                tmp_node_dof_start_refined, nuknwn );
              node_dof = db_dbl( NODE_DOF, inod, version );
              array_add( node_dof, tmp_node_dof, tmp_node_dof, nuknwn );
            }
            else {
              node_dof_start_refined = ddum;
              node_dof = ddum;
            }
            iwork[0] = inod; create_node( iwork, 1, inod, node, node_dof,
              node_start_refined, node_dof_start_refined,
              version, VERSION_TMP ); 
          }
          array_multiply( tmp_node, tmp_node, 1./nnol, ndim );
          array_multiply( tmp_node_start_refined, tmp_node_start_refined, 
            1./nnol, ndim );
          if ( nuknwn>0 ) {
            array_multiply( tmp_node_dof_start_refined, tmp_node_dof_start_refined, 
              1./nnol, nuknwn );
            array_multiply( tmp_node_dof, tmp_node_dof, 1./nnol, nuknwn );
          }
          max_node++;
          create_node( nodes, nnol, max_node, tmp_node, tmp_node_dof,
            tmp_node_start_refined, tmp_node_dof_start_refined,
            version, VERSION_TMP );
          if ( name==-QUAD4 ) {
            el[0] = -TRIA3;
            length_element = 4;
          }
          else {
            assert( name==-HEX8 );
            el[0] = -TET4;
            length_element = 5;
          }
          for ( isplit=0; isplit<nsplit; isplit++ ) {
            for ( idim=0; idim<ndim; idim++ )
              el[1+idim] = nodes[split_nodes[isplit*ndim+idim]];
            el[1+ndim] = max_node;
            create_element( element, tmp_max_element, el, length_element,
              version, VERSION_TMP );
            tmp_max_element++;
          }
        }
      }
    }
  }

  db_version_copy( VERSION_TMP, version );
  db_version_delete( VERSION_TMP );

  mesh_has_changed( version );

  if ( swit ) pri( "Out routine SPLIT" );

}
