
/*
  
  FACILITY:  nmmtl
  
  MODULE DESCRIPTION:
  
  contains the function nmmtl_generate_elements()
  
  AUTHOR(S):
  
  Kevin J. Buchs
  
  CREATION DATE:  Fri Mar 13 09:26:49 1992
  
  COPYRIGHT:   Copyright (C) 1992 by Mayo Foundation. All rights reserved.
  
  */


/*
 *******************************************************************
 **  INCLUDE FILES
 *******************************************************************
 */

#include "nmmtl.h"

/*
 *******************************************************************
 **  STRUCTURE DECLARATIONS AND TYPE DEFINTIONS
 *******************************************************************
 */
/*
 *******************************************************************
 **  MACRO DEFINITIONS
 *******************************************************************
 */
/*
 *******************************************************************
 **  PREPROCESSOR CONSTANTS
 *******************************************************************
 */
/*
 *******************************************************************
 **  GLOBALS
 *******************************************************************
 */
/*
 *******************************************************************
 **  FUNCTION DECLARATIONS
 *******************************************************************
 */
/*
 *******************************************************************
 **  FUNCTION DEFINITIONS
 *******************************************************************
 */


/*
  
  FUNCTION NAME:  nmmtl_generate_elements
  
  
  FUNCTIONAL DESCRIPTION:
  
  Take the list of segments for conductors and dielectric boundaries and
  generate the small elements from that.  Point each element to appropriate
  array indicies for the Main arrays used in calculation.
  
  
  FORMAL PARAMETERS:
  
  int conductor_counter,            a count of the number of conductors
  CONDUCTOR_DATA_P *conductor_data,  to-be-allocated array of pointers to
  conductor elements (output)
  DELEMENTS_P *die_elements,         pointer to start of list of die elements
  generated by this function (output)
  unsigned int *node_point_counter   counter of all node points used.
  unsigned int *highest_conductor_node,  highest node number of conductors
  LINE_SEGMENTS_P conductor_ls,      list of conductor line segments
  CIRCLE_SEGMENTS_P conductor_cs,    list of conductor circle segments
  DIELECTRIC_SEGMENTS_P dielectric_segments list of dielectric line segments
  int gnd_planes,                    number of ground planes
  SORTED_GND_DIE_LIST_P upper_sorted_gdl,  die intersections with upper gnd pln
  int pln_seg,                     number of segments to break planes into
  double bottom_of_top_plane,         ""
  double left_of_gnd_planes,          "" 
  double right_of_gnd_planes          ""
  EXTENT_DATA_P extent_data          information about extents given and desired
  
  RETURN VALUE:
  
  SUCCESS, FAIL
  
  
  CALLING SEQUENCE:
  
  status = nmmtl_generate_elements(conductor_counter,&conductor_data,
                                   &die_elements,
				   &node_point_counter,
				   &highest_conductor_node,
				   conductor_ls,conductor_cs,
				   dielectric_segments,
				   gnd_planes,
				   upper_sorted_gdl,pln_seg,
				   bottom_of_top_plane,
				   left_of_gnd_planes,
				   right_of_gnd_planes,
				   &extent_data);
  
  
  
  */

int nmmtl_generate_elements(int conductor_counter,
			    CONDUCTOR_DATA_P *conductor_data,
			    DELEMENTS_P *die_elements,
			    unsigned int *node_point_counter,
			    unsigned int *highest_conductor_node,
			    LINE_SEGMENTS_P conductor_ls,
			    CIRCLE_SEGMENTS_P conductor_cs,
			    DIELECTRIC_SEGMENTS_P dielectric_segments,
			    int gnd_planes,
			    SORTED_GND_DIE_LIST_P upper_sorted_gdl,
			    int pln_seg,
			    double bottom_of_top_plane,
			    double left_of_gnd_planes,
			    double right_of_gnd_planes,
			    EXTENT_DATA_P extent_data)
{
  
  unsigned int current_conductor;
  CONDUCTOR_DATA_P cd;
  LINE_SEGMENTS_P cls;
  CIRCLE_SEGMENTS_P ccs;
  CELEMENTS_P head,tail,gnd_list,gnd_list_head = NULL;
  CELEMENTS_P gnd_plane_list_head = NULL;  
  register unsigned int node_point_counter_start;
  int number_elements = 0;  
  char infostring[256];
  
  /* allocate the array of conductor data */
  
  *conductor_data = (CONDUCTOR_DATA_P)
    calloc(1,sizeof(CONDUCTOR_DATA) * (conductor_counter + 1));
  cd = *conductor_data;
  
  /* process the conductor line segments */
  
  cls=conductor_ls;
  while(cls != NULL)
  {
    current_conductor = cls->conductor;
    if(current_conductor != 0)
    {
      cd[current_conductor].node_start = *node_point_counter;
      nmmtl_generate_elements_cls(&cls,&head,&tail,node_point_counter);
      if(head == NULL)
      {
	printf ("**** Error in element generation: from conductor line segment\n");
	return(FAIL);
      }
      cd[current_conductor].elements = head;
      cd[current_conductor].node_end = *node_point_counter-1;
      number_elements += 
	(cd[current_conductor].node_end -
	 cd[current_conductor].node_start + 1)/2;
      
    }
    else
    {
      if(gnd_list_head == NULL)
	cd[0].node_start = *node_point_counter;
      
      node_point_counter_start = *node_point_counter;
      
      nmmtl_generate_elements_cls(&cls,&head,&tail,node_point_counter);
      if(gnd_list_head == NULL)
	gnd_list_head = head;
      else
	gnd_list->next = head;
      
      gnd_list = tail;
      cd[0].node_end = *node_point_counter-1;
      
      number_elements += 
	(cd[0].node_end - node_point_counter_start + 1)/2;
    }
    
    /* if(cls != NULL) cls = cls->next; */
    
  }
  
  /* process the conductor circle segments */
  
  ccs=conductor_cs;
  while(ccs != NULL)
  {
    current_conductor = ccs->conductor;
    if(current_conductor != 0)
    {
      cd[current_conductor].node_start = *node_point_counter;
      nmmtl_generate_elements_ccs(&ccs,&head,&tail,node_point_counter);
      if(head == NULL)
      {
	printf ("**** Error in element generation: from conductor circle segment");
	return(FAIL);
      }
      cd[current_conductor].elements = head;
      cd[current_conductor].node_end = *node_point_counter-1;
      number_elements += 
	(cd[current_conductor].node_end -
	 cd[current_conductor].node_start + 1)/2;
    }
    else
    {
      if(gnd_list_head == NULL)
	cd[0].node_start = *node_point_counter;
      
      node_point_counter_start = *node_point_counter;
      
      nmmtl_generate_elements_ccs(&ccs,&head,&tail,node_point_counter);
      if(gnd_list_head == NULL)
	gnd_list_head = head;
      else
	gnd_list->next = head;
      
      gnd_list = tail;
      cd[0].node_end = *node_point_counter-1;
      
      number_elements += 
	(cd[0].node_end - node_point_counter_start + 1)/2;
    }      
    
    /* if(ccs != NULL) ccs = ccs->next; */
    
  }
  
  /* process the ground planes */
  
  if(gnd_list_head == NULL)
  {
    cd[0].node_start = *node_point_counter;
  }
  
  node_point_counter_start = *node_point_counter;
  
  nmmtl_generate_elements_gnd(&gnd_plane_list_head,
			      node_point_counter,
			      gnd_planes,
			      pln_seg,
			      bottom_of_top_plane,
			      left_of_gnd_planes,
			      right_of_gnd_planes,
			      upper_sorted_gdl);
  
  /* attach ground plane elements with other ground wire elements */
  if(gnd_list_head == NULL)
    gnd_list_head = gnd_plane_list_head;
  else
    gnd_list->next = gnd_plane_list_head;
  
  /* were any ground elements actually generated?  See if counter advanced */
  if(*node_point_counter == cd[0].node_start)
  {
    cd[0].node_end = 0;
    cd[0].node_start = 0;
  }
  else cd[0].node_end = *node_point_counter-1;
  
  if(cd[0].node_end != 0)
    number_elements += 
      (cd[0].node_end - node_point_counter_start + 1)/2;
  
  /* put the ground wire and ground plane elements 
     all in the conductor data array */
  cd[0].elements = gnd_list_head;
  
  
  /* record how high the conductor nodes go */
  
  *highest_conductor_node = *node_point_counter - 1;
  
  
  /* process the dielectric boundaries */
  
  *die_elements = nmmtl_generate_elements_die(dielectric_segments,
					      node_point_counter,
					      &number_elements,
					      extent_data);
  
  sprintf(infostring,"%d elements and %d nodes were generated\n  largest matrix to be inverted is %d X %d\n",
	  number_elements,*node_point_counter,*node_point_counter,
	  *node_point_counter);
  
  printf ("%s", infostring);
  
  /* dump the elements generated */
#ifdef NMMTL_DUMP_DIAG
  nmmtl_dump_elements(conductor_counter,cd,*die_elements);
#endif

  return(SUCCESS);
  
}




