nmmtl_genel_die.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*
  2. FACILITY: NMMTL
  3. MODULE DESCRIPTION:
  4. Contains the function nmmtl_generated_elements_die()
  5. AUTHOR(S):
  6. Kevin J. Buchs
  7. CREATION DATE: Fri Mar 20 08:43:53 1992
  8. COPYRIGHT: Copyright (C) 1992 by Mayo Foundation. All rights reserved.
  9. */
  10. /*
  11. *******************************************************************
  12. ** INCLUDE FILES
  13. *******************************************************************
  14. */
  15. #include "nmmtl.h"
  16. /*
  17. *******************************************************************
  18. ** STRUCTURE DECLARATIONS AND TYPE DEFINTIONS
  19. *******************************************************************
  20. */
  21. /* chain together the dielectric segments and node numbers used for the first
  22. and last elements generated from a particular segment */
  23. typedef struct chain
  24. {
  25. int nodestart,nodeend;
  26. double endx[2],endy[2];
  27. struct chain *next;
  28. } CHAIN, *CHAIN_P;
  29. /*
  30. *******************************************************************
  31. ** MACRO DEFINITIONS
  32. *******************************************************************
  33. */
  34. /*
  35. *******************************************************************
  36. ** PREPROCESSOR CONSTANTS
  37. *******************************************************************
  38. */
  39. /*
  40. *******************************************************************
  41. ** GLOBALS
  42. *******************************************************************
  43. */
  44. /*
  45. *******************************************************************
  46. ** FUNCTION DECLARATIONS
  47. *******************************************************************
  48. */
  49. /*
  50. *******************************************************************
  51. ** FUNCTION DEFINITIONS
  52. *******************************************************************
  53. */
  54. /*
  55. FUNCTION NAME: nmmtl_generate_elements
  56. FUNCTIONAL DESCRIPTION:
  57. Generate elements from the segments along dielectric-to-dielectric
  58. boundaries. It includes a couple of tough operations, like finding
  59. intersections among the segments. Basically we check the list of
  60. completed segments when we process a new one.
  61. There is code here to check if the element sizes are within
  62. half_minimum_dimension. This code is now disabled with this preprocessor
  63. constant to be defined to re-enable it:
  64. DIE_MIN_ELEMENT_SIZE
  65. FORMAL PARAMETERS:
  66. DIELECTRIC_SEGMENTS_P *ds, - list of dielectric segments
  67. unsigned int *node_point_counter, - counter of node points
  68. int *number_elements - total number of elements
  69. EXTENT_DATA_P extent_data - given and desired extents
  70. RETURN VALUE:
  71. None
  72. CALLING SEQUENCE:
  73. nmmtl_generate_elements_die(die_elements,&node_point_counter,
  74. &number_elements,extent_data);
  75. */
  76. DELEMENTS_P nmmtl_generate_elements_die(DIELECTRIC_SEGMENTS_P ds,
  77. unsigned int *node_point_counter,
  78. int *number_elements,
  79. EXTENT_DATA_P extent_data)
  80. {
  81. DIELECTRIC_SEGMENTS_P die_seg;
  82. CHAIN_P first_link = NULL,last_link,scan_chain;
  83. unsigned char intersection[2];
  84. unsigned int intersection_node[2];
  85. DELEMENTS_P start = NULL,element;
  86. double endx[2],endy[2];
  87. unsigned int cntr;
  88. unsigned int divisions;
  89. unsigned int npcntr;
  90. double xincr,xhalfincr,x,yincr,yhalfincr,y;
  91. int first_element;
  92. double normalx,normaly;
  93. npcntr = *node_point_counter;
  94. die_seg = ds;
  95. while(die_seg != NULL)
  96. {
  97. /* come up with real x,y pairs for endpoints of segment */
  98. if(die_seg->orientation == VERTICAL_ORIENTATION)
  99. {
  100. endx[0] = endx[1] = die_seg->at;
  101. endy[0] = die_seg->start;
  102. endy[1] = die_seg->end;
  103. if(endy[0] < endy[1])
  104. normalx = -1.0; /* segment points upward - normal to left */
  105. else
  106. normalx = 1.0;
  107. normaly = 0.0;
  108. }
  109. else /* Horizontal orientation */
  110. {
  111. endy[0] = endy[1] = die_seg->at;
  112. endx[0] = die_seg->start;
  113. endx[1] = die_seg->end;
  114. if(endx[0] < endx[1])
  115. normaly = 1.0; /* segment points to right - normal is up */
  116. else
  117. normaly = -1.0;
  118. normalx = 0.0;
  119. }
  120. /* Find any intersections with ends of segments already processed */
  121. intersection[0] = FALSE;
  122. intersection[1] = FALSE;
  123. scan_chain = first_link;
  124. while(scan_chain != NULL && !(intersection[0] && intersection[1]))
  125. {
  126. for(cntr = 0; cntr < 2; cntr++)
  127. {
  128. if(scan_chain->endx[0] == endx[cntr] &&
  129. scan_chain->endy[0] == endy[cntr])
  130. {
  131. intersection[cntr] = TRUE;
  132. intersection_node[cntr] = scan_chain->nodestart;
  133. }
  134. else if(scan_chain->endx[1] == endx[cntr] &&
  135. scan_chain->endy[1] == endy[cntr])
  136. {
  137. intersection[cntr] = TRUE;
  138. intersection_node[cntr] = scan_chain->nodeend;
  139. }
  140. }
  141. scan_chain = scan_chain->next;
  142. }
  143. /* Now create the elements from this segment */
  144. divisions = die_seg->divisions;
  145. /* disable the check for the minimum element size for dielectrics */
  146. #ifdef DIE_MIN_ELEMENT_SIZE
  147. /* will the natural sized elements be small enough ? */
  148. if(die_seg->length/divisions > half_minimum_dimension)
  149. {
  150. /* no, make them smaller */
  151. divisions = die_seg->length/half_minimum_dimension + 0.99;
  152. }
  153. #endif
  154. xincr = (endx[1] - endx[0])/divisions;
  155. xhalfincr = xincr/2;
  156. yincr = (endy[1] - endy[0])/divisions;
  157. yhalfincr = yincr/2;
  158. x = endx[0];
  159. y = endy[0];
  160. /* Set up chain structure to store away data about this element for
  161. intersection detection later */
  162. if(first_link == NULL)
  163. {
  164. first_link = (CHAIN_P)malloc(sizeof(CHAIN));
  165. last_link = first_link;
  166. }
  167. else
  168. {
  169. last_link->next = (CHAIN_P)malloc(sizeof(CHAIN));
  170. last_link = last_link->next;
  171. }
  172. last_link->next = NULL;
  173. last_link->endx[0] = endx[0];
  174. last_link->endy[0] = endy[0];
  175. last_link->endx[1] = endx[1];
  176. last_link->endy[1] = endy[1];
  177. first_element = TRUE;
  178. while(divisions > 0)
  179. {
  180. (*number_elements)++;
  181. if(start == NULL) /* first time through */
  182. {
  183. /* create the head of the list */
  184. element = (DELEMENTS_P)malloc(sizeof(DELEMENTS));
  185. start = element;
  186. }
  187. else /* subsequent times through */
  188. {
  189. /* link up to the last element created */
  190. element->next = (DELEMENTS_P)malloc(sizeof(DELEMENTS));
  191. element = element->next;
  192. }
  193. /* terminate the list for now */
  194. element->next = NULL;
  195. /* the global coordinates at the various nodes */
  196. element->xpts[0] = x;
  197. element->ypts[0] = y;
  198. /* advance to the midpoint */
  199. x += xhalfincr;
  200. y += yhalfincr;
  201. element->xpts[1] = x;
  202. element->ypts[1] = y;
  203. /* advance to the endpoint */
  204. x += xhalfincr;
  205. y += yhalfincr;
  206. element->xpts[2] = x;
  207. element->ypts[2] = y;
  208. /* set epsilon values */
  209. element->epsilonplus = die_seg->epsilonplus;
  210. element->epsilonminus = die_seg->epsilonminus;
  211. /* set normal vectors */
  212. element->normalx = normalx;
  213. element->normaly = normaly;
  214. /* Now set up array indicies into the BIG arrays, this is a bit
  215. complex because of the need to take in to account the intersections
  216. which are tested for above. */
  217. /* first node */
  218. if(first_element) /* is this the first element? */
  219. {
  220. first_element = FALSE;
  221. if(intersection[0])
  222. element->node[0] = last_link->nodestart = intersection_node[0];
  223. else
  224. element->node[0] = last_link->nodestart = npcntr++;
  225. }
  226. else element->node[0] = npcntr++;
  227. /* middle node */
  228. element->node[1] = npcntr++;
  229. /* last node
  230. if this isn't the last element for this segment, set up for
  231. overlap of node points, by not advancing npcntr. Conversely,
  232. if this is the last element, we advance npcntr. If this last
  233. element is an intersection with another segment - set the
  234. node based on the element of the other segment, but npcntr was
  235. already advanced for the middle node and not used for this last
  236. node so the same effect is achieved. */
  237. if(divisions == 1) /* is this the last element ? */
  238. {
  239. if(intersection[1])
  240. element->node[2] = last_link->nodeend = intersection_node[1];
  241. else
  242. element->node[2] = last_link->nodeend = npcntr++;
  243. }
  244. else element->node[2] = npcntr;
  245. /* advance to the next element */
  246. divisions--;
  247. } /* while looping through divisions of this segment */
  248. /* Check to see if there should be expansion of the element generation
  249. from this segment with non-linear nodes to a wider dimension.
  250. First, does segment go left to right? In other words, is the starting
  251. x coordinate less than the ending x coordinate? If the normal points
  252. up ( > 0.0 ) then we know the element goes left to right
  253. */
  254. if(normaly > 0.0)
  255. {
  256. /* Do we need expansion on left end? Check this by seeing if the flag was
  257. set to expand on left side (expand_left) and to see that we have approached
  258. the left edge of the edge of the drawn cross section (left_cs_extent = end
  259. of dielectric segment (end[0]).
  260. */
  261. if(extent_data->expand_left && (extent_data->left_cs_extent == endx[0]))
  262. nmmtl_nl_expand(endx[0],extent_data->desired_left,-1*xincr,die_seg->epsilonplus,
  263. die_seg->epsilonminus,normaly,y,&npcntr,&element,
  264. number_elements,last_link->nodestart);
  265. /* need expansion on right end? */
  266. if(extent_data->expand_right && (extent_data->right_cs_extent == endx[1]))
  267. nmmtl_nl_expand(endx[1],extent_data->desired_right,xincr,die_seg->epsilonplus,
  268. die_seg->epsilonminus,normaly,y,&npcntr,&element,
  269. number_elements,last_link->nodeend);
  270. }
  271. /* Or does this segment goes right to left */
  272. else if(normaly < 0.0)
  273. {
  274. /* need expansion on left end? */
  275. if(extent_data->expand_left && (extent_data->left_cs_extent == endx[1]))
  276. nmmtl_nl_expand(endx[1],extent_data->desired_left,xincr,die_seg->epsilonplus,
  277. die_seg->epsilonminus,normaly,y,&npcntr,&element,
  278. number_elements,last_link->nodeend);
  279. /* need expansion on right end? */
  280. if(extent_data->expand_right && (extent_data->right_cs_extent == endx[0]))
  281. nmmtl_nl_expand(endx[0],extent_data->desired_right,-1*xincr,die_seg->epsilonplus,
  282. die_seg->epsilonminus,normaly,y,&npcntr,&element,
  283. number_elements,last_link->nodestart);
  284. }
  285. die_seg = die_seg->next;
  286. }
  287. *node_point_counter = npcntr;
  288. return(start);
  289. }