Changeset 421

Show
Ignore:
Timestamp:
02/23/2009 06:38:33 PM (3 years ago)
Author:
powell
Message:

Refactored hullCalculate interface, adding facet type, breaking refine.

Location:
trunk/matml/src/ternary
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • trunk/matml/src/ternary/ChangeLog

    r413 r421  
    44    implementations. 
    55  * Added phase_boundary typedef struct. 
    6   * Changed hull calculation interface to permit (multiple) refinement between 
    7     original calculation and return. 
     6  * Changed hull calculation interface to only hold the qhull variables during 
     7    hull calculation, and permit (multiple) phase boundary refinement. 
    88  * Added WITH_DERIVATIVES and NO_INFINITY options to free energies(). 
    99  * Added spinodal.c with calc_spinodal function. 
  • trunk/matml/src/ternary/qhull.c

    r415 r421  
    1212#include <stdlib.h> 
    1313#include <math.h> 
    14  
    15  
    16 static coordT *qpoints; /*+ Point coordinate storage for qhull +*/ 
    17  
    18  
    19 /*++++++++++++++++++++++++++++++++++++++ 
    20   This initializes qhull and uses it to calculate the convex hull of a set of 
    21   ternary compositions, clipping everything above the energy defined by the 
    22   three corners.  It does not return anything, but leaves all of the facets in 
    23   the qhull structures. 
    24  
    25   int hullCalculate It returns zero or an error code. 
    26  
    27   int dim Number of dimensions (should always be 3 for ternary). 
    28  
    29   ternary_point *points Point information. 
    30  
    31   int numpoints Number of points of which to calculate the convex hull. 
    32   ++++++++++++++++++++++++++++++++++++++*/ 
    33  
    34 int hullCalculate (int dim, ternary_point *points, int numpoints) 
    35 { 
    36   int i, corner1, corner2, corner3; 
    37  
    38   if (dim != 3) 
    39     { printf ("qhullCalcHull: Non-3-D spaces not yet supported\n"); return -1; } 
    40  
    41   /*+ This first copies the points array for qhull, and clips the array at the 
    42     plane defined by the corners. +*/ 
    43   if (!(qpoints = malloc (dim*numpoints*sizeof(coordT)))) 
    44     { printf ("qhullCalcHull: could not allocate memory for points\n"); 
    45       return -1; } 
    46   for (i=0; i<numpoints; i++) 
    47     { 
    48       // Copy compositions into the new array 
    49       qpoints[3*i]   = (coordT) points[i].C2; 
    50       qpoints[3*i+1] = (coordT) points[i].C3; 
    51  
    52       // Find the corners 
    53       if (points[i].C2 == 0. && points[i].C3 == 0.) 
    54         corner1 = i; 
    55       if (points[i].C2 == 0. && points[i].C3 == 1.) 
    56         corner2 = i; 
    57       if (points[i].C2 == 1. && points[i].C3 == 0.) 
    58         corner3 = i; 
    59     } 
    60  
    61   // Copy free energy into the new array, clipping it at the plane given by the 
    62   // corners 
    63   for (i=0; i<numpoints; i++) 
    64     qpoints[3*i+2] = (coordT) 
    65       fmin (points[i].G, points[corner1].G + 
    66             (points[corner2].G-points[corner1].G) * points[i].C3 + 
    67             (points[corner3].G-points[corner1].G) * points[i].C2); 
    68  
    69   // Initialize qhull and calculate the hull 
    70   qh_init_A (stdin, stdout, stderr, 0, NULL); 
    71   qh_init_B (qpoints, numpoints, dim, False); 
    72   qh_qhull (); 
    73 #ifdef DEBUG 
    74   qh_printsummary (stdout); 
    75 #endif 
    76  
    77   return 0; 
    78 } 
    7914 
    8015 
     
    14580 
    14681/*++++++++++++++++++++++++++++++++++++++ 
     82  This initializes qhull and uses it to calculate the convex hull of a set of 
     83  ternary compositions, clipping everything above the energy defined by the 
     84  three corners.  It then builds a set of hull_facet structures, and returns 
     85  those, along with the number of calculated facets.  It frees the qhull 
     86  structures before returning. 
     87 
     88  int hullCalculate It returns zero or an error code. 
     89 
     90  int dim Number of dimensions (should always be 3 for ternary). 
     91 
     92  ternary_point *points Point information. 
     93 
     94  int numpoints Number of points of which to calculate the convex hull. 
     95 
     96  energy_params *eparams Collection of energy parameter structures. 
     97 
     98  int nparams Number of energy parameter structures in eparams. 
     99 
     100  double T Temperature. 
     101 
     102  double P Pressure. 
     103 
     104  hull_facet **tfacets Array of returned facets.  This is changed by realloc() 
     105  each time the function is called, so it should be NULL or a valid array. 
     106 
     107  int *numfacets Number of facets returned. 
     108++++++++++++++++++++++++++++++++++++++*/ 
     109 
     110int hullCalculate 
     111(int dim, ternary_point *points, int numpoints, energy_params *eparams, 
     112 int nparams, double T, double P, hull_facet **facets, int *numfacets) 
     113{ 
     114  int i, corner1=-1, corner2=-1, corner3=-1; 
     115  double G1, G2, G3; 
     116  coordT *qpoints; /*+ Point coordinate storage for qhull +*/ 
     117  facetT *facet; /*+ For the FORALLfacets loop +*/ 
     118 
     119  if (dim != 3) 
     120    { printf ("qhullCalcHull: Non-3-D spaces not yet supported\n"); return -1; } 
     121 
     122  /*+ This first copies the points array for qhull, and clips the array at the 
     123    plane defined by the corners. +*/ 
     124  if (!(qpoints = malloc (dim*numpoints*sizeof(coordT)))) 
     125    { printf ("qhullCalcHull: could not allocate memory for points\n"); 
     126      return -1; } 
     127  for (i=0; i<numpoints; i++) 
     128    { 
     129      // Copy compositions into the new array 
     130      qpoints[3*i]   = (coordT) points[i].C2; 
     131      qpoints[3*i+1] = (coordT) points[i].C3; 
     132 
     133      // Find the top corners 
     134      if ((points[i].C2 == 0. && points[i].C3 == 0.) && 
     135          (corner1 == -1 || points[i].G > G1)) 
     136        { 
     137          corner1 = i; 
     138          G1 = points [corner1].G; 
     139        } 
     140      if ((points[i].C2 == 0. && points[i].C3 == 1.) && 
     141          (corner2 == -1 || points[i].G > G2)) 
     142        { 
     143          corner2 = i; 
     144          G2 = points [corner2].G; 
     145        } 
     146      if ((points[i].C2 == 1. && points[i].C3 == 0.) && 
     147          (corner2 == -1 || points[i].G > G2)) 
     148        { 
     149          corner3 = i; 
     150          G2 = points [corner3].G; 
     151        } 
     152    } 
     153#ifdef DEBUG 
     154  printf ("Corners: %d, %d, %d\n", corner1, corner2, corner3); 
     155#endif 
     156 
     157  // Copy free energy into the new array, clipping it at the plane given by the 
     158  // corners 
     159  for (i=0; i<numpoints; i++) 
     160    qpoints[3*i+2] = (coordT) 
     161      fmin (points[i].G, points[corner1].G + 
     162            (points[corner2].G-points[corner1].G) * points[i].C3 + 
     163            (points[corner3].G-points[corner1].G) * points[i].C2); 
     164 
     165  // Initialize qhull and calculate the hull 
     166  qh_init_A (stdin, stdout, stderr, 0, NULL); 
     167  qh_init_B (qpoints, numpoints, dim, False); 
     168  qh_qhull (); 
     169#ifdef DEBUG 
     170  qh_printsummary (stdout); 
     171#endif 
     172 
     173  /*+ After qhull runs, this reallocates the array pointed to by facets, 
     174    then fills it, eliminating non-simplical facets along the way (which seem 
     175    to typically be the binaries). +*/ 
     176  *numfacets = qh num_facets; 
     177#ifdef DEBUG 
     178  printf ("%d total facets\n", *numfacets); 
     179  printf ("facets: pre-realloc 0x%lx, ", *facets); 
     180#endif 
     181  if (!(*facets = realloc (*facets, *numfacets * sizeof (hull_facet)))) 
     182    { printf ("hullReturnFacets: could not reallocate memory for vertices\n"); 
     183      return -1; } 
     184#ifdef DEBUG 
     185  printf ("  post-realloc 0x%lx\n", *facets); 
     186#endif 
     187 
     188  i=0; 
     189  FORALLfacets 
     190    { 
     191      int j=0; 
     192      coordT corners [9], projarea; 
     193      vertexT *vertex, **vertexp; 
     194 
     195#ifdef DEBUG 
     196      printf ("facet %d:\n", i); 
     197#endif 
     198 
     199      FOREACHvertex_(facet->vertices) 
     200        { 
     201          int thepoint = (vertex->point-qh first_point)/3; 
     202 
     203          if (j<3) 
     204            { 
     205              (*facets) [i].vertex[j] = thepoint; 
     206              corners [3*j]   = vertex->point[0]; 
     207              corners [3*j+1] = vertex->point[1]; 
     208              corners [3*j+2] = vertex->point[2]; 
     209#ifdef DEBUG 
     210              printf ("  vertex %d, coords %g %g %g\n", thepoint, 
     211                      vertex->point[0], vertex->point[1], vertex->point[2]); 
     212#endif 
     213              j++; 
     214            } 
     215        } 
     216           
     217      /*+ This calculates the area of the projection of each facet. 
     218        That area is given by the determinant of the matrix formed by the 
     219        vectors making up the edges of the facet divided by 
     220        (dimensionality-1)!. 
     221        +latex+For a ternary system, that's 
     222        +latex+$\frac12[(x_1-x_0)(y_2-y_0) - (x_2-x_0)(y_1-y_0)]$. 
     223        +*/ 
     224      projarea = 
     225        (corners[3]-corners[0]) * (corners[7]-corners[1]) - 
     226        (corners[6]-corners[0]) * (corners[4]-corners[1]); 
     227#ifdef DEBUG 
     228      printf ("  xyarea %g\n", projarea); 
     229#endif 
     230 
     231      // Remove side facets (zero area) and facet with the three corners 
     232      if (projarea == 0. || fabs (projarea) == 1.) 
     233        (*numfacets)--; 
     234      else 
     235        { 
     236          (*facets) [i].type = facettype (corners, eparams, nparams, T, P); 
     237#ifdef DEBUG 
     238          printf ("  Type %d\n", (*facets) [i].type); 
     239#endif 
     240          i++; 
     241        } 
     242    } 
     243 
     244#ifdef DEBUG 
     245  printf ("After trimming loop: %d total facets, i=%d\n", *numfacets, i); 
     246  printf ("facets: pre-realloc 0x%lx, ", *facets); 
     247#endif 
     248  if (!(*facets = realloc (*facets, *numfacets * sizeof (hull_facet)))) 
     249    { printf ("hullReturnFacets: could not reallocate memory for vertices\n"); 
     250      return -1; } 
     251#ifdef DEBUG 
     252  printf ("  post-realloc 0x%lx\n", *facets); 
     253#endif 
     254 
     255  free (qpoints); 
     256  qh_freeqhull (True); 
     257 
     258  return 0; 
     259} 
     260 
     261 
     262/*++++++++++++++++++++++++++++++++++++++ 
    147263  This uses Newton iteration to refine a single point within a triangle. 
    148264 
     
    534650    return 1; 
    535651           
    536   qh_freeqhull (True); 
    537   free (qpoints); 
     652  //qh_freeqhull (True); 
     653  //free (qpoints); 
    538654 
    539655  for (i=0; i<numnewpoints; i++) 
     
    565681  free(newpoints); 
    566682 
    567   return hullCalculate (3, *points, *numpoints); 
    568 } 
    569  
    570  
    571 /*++++++++++++++++++++++++++++++++++++++ 
    572   This returns the facets of the convex hull comprising the minimum energy 
    573   surface.  It removes the sides and top, currently by getting rid of 
    574   non-simplical facets (sides) and a facet whose projection area is the entire 
    575   triangle (top). 
    576  
    577   int hullReturnFacets It returns zero or an error code. 
    578  
    579   energy_params *eparams Collection of energy parameter structures. 
    580  
    581   int nparams Number of energy parameter structures in eparams. 
    582  
    583   double T Temperature. 
    584  
    585   double P Pressure. 
    586  
    587   int *numfacets Pointer to an integer which will contain the number of facets 
    588   in the convex hull on return. 
    589  
    590   int **facetverts Pointer which contains the array of facet vertices on 
    591   return.  This is changed by realloc() each time the function is called, so it 
    592   should be NULL or a valid array. 
    593  
    594   facet_type **facettypes Pointer which contains the array of facet types on 
    595   return.  This is changed by realloc() each time the function is called, so it 
    596   should be NULL or a valid array. 
    597   ++++++++++++++++++++++++++++++++++++++*/ 
    598  
    599 int hullReturnFacets 
    600 (energy_params *eparams, int nparams, double T,double P, 
    601  int *numfacets, int **facetverts, facet_type **facettypes) 
    602 { 
    603   int i=0; 
    604   facetT *facet; 
    605  
    606   /*+ After qhull runs, this reallocates the array pointed to by facetverts, 
    607     then fills it, eliminating non-simplical facets along the way (which seem 
    608     to typically be the binaries). +*/ 
    609   *numfacets = qh num_facets; 
    610 #ifdef DEBUG 
    611   printf ("%d total facets\n", *numfacets); 
    612   printf ("facetverts: pre-realloc 0x%lx, ", *facetverts); 
    613 #endif 
    614   if (!(*facetverts = realloc (*facetverts, *numfacets * 3 * sizeof (int)))) 
    615     { printf ("hullReturnFacets: could not reallocate memory for vertices\n"); 
    616       return -1; } 
    617 #ifdef DEBUG 
    618   printf ("  post-realloc 0x%lx\n", *facetverts); 
    619   printf ("facettypes: pre-realloc 0x%lx, ", *facettypes); 
    620 #endif 
    621   if (!(*facettypes = realloc (*facettypes, *numfacets * sizeof (facet_type)))) 
    622     { printf ("hullReturnFacets: could not reallocate memory for facet types\n"); 
    623       return -1; } 
    624 #ifdef DEBUG 
    625   printf ("  post-realloc 0x%lx\n", *facettypes); 
    626 #endif 
    627  
    628   FORALLfacets 
    629     { 
    630       int j=0; 
    631       coordT corners [9], projarea; 
    632       vertexT *vertex, **vertexp; 
    633  
    634 #ifdef DEBUG 
    635       printf ("facet %d:\n", i); 
    636 #endif 
    637  
    638       FOREACHvertex_(facet->vertices) 
    639         { 
    640           int thepoint = (vertex->point-qh first_point)/3; 
    641  
    642           if (j<3) 
    643             { 
    644               (*facetverts) [3*i+j] = thepoint; 
    645               corners [3*j]   = vertex->point[0]; 
    646               corners [3*j+1] = vertex->point[1]; 
    647               corners [3*j+2] = vertex->point[2]; 
    648 #ifdef DEBUG 
    649               printf ("  vertex %d, coords %g %g %g\n", thepoint, 
    650                       vertex->point[0], vertex->point[1], vertex->point[2]); 
    651 #endif 
    652               j++; 
    653             } 
    654         } 
    655            
    656       /*+ This calculates the area of the projection of each facet. 
    657         That area is given by the determinant of the matrix formed by the 
    658         vectors making up the edges of the facet divided by 
    659         (dimensionality-1)!. 
    660         +latex+For a ternary system, that's 
    661         +latex+$\frac12[(x_1-x_0)(y_2-y_0) - (x_2-x_0)(y_1-y_0)]$. 
    662         +*/ 
    663       projarea = 
    664         (corners[3]-corners[0]) * (corners[7]-corners[1]) - 
    665         (corners[6]-corners[0]) * (corners[4]-corners[1]); 
    666 #ifdef DEBUG 
    667       printf ("  xyarea %g\n", projarea); 
    668 #endif 
    669  
    670       // Remove side facets (zero area) and facet with the three corners 
    671       if (projarea == 0. || fabs (projarea) == 1.) 
    672         (*numfacets)--; 
    673       else 
    674         { 
    675           (*facettypes) [i] = facettype (corners, eparams, nparams, T, P); 
    676           printf ("  Type %d\n", (*facettypes) [i]); 
    677           i++; 
    678         } 
    679     } 
    680  
    681 #ifdef DEBUG 
    682   printf ("After loop: numfacets=%d, i=%d\n", *numfacets, i); 
    683 #endif 
    684  
    685   /* free (qpoints); 
    686      qh_freeqhull (True); */ 
    687  
    688   return 0; 
     683  //return hullCalculate (3, *points, *numpoints); 
    689684} 
    690685 
  • trunk/matml/src/ternary/ternary.c

    r418 r421  
    2828int main (int argc, char *argv[]) 
    2929{ 
    30   int i,j, index, loop_max=20, numpoints, *verts, 
    31     hullnumverts,*hullverts=NULL; 
    32   facet_type *hulltypes=NULL; 
     30  int i,j, index, loop_max=20, numpoints, *verts, hullnumfacets; 
     31  hull_facet *hullfacets = NULL; 
    3332  char gv_version[100]; 
    3433  FILE *pfd = NULL; 
     
    8281    { printf ("main: error %d in spinodal calculation\n", i); exit (i); } 
    8382 
    84   printf ("First edge: %d %d\n", solid_spinodal.edges [0], solid_spinodal.edges [1]); 
    85  
    8683  /* Scale all free energy values */ 
    8784  if (i=scale_energy_array (numpoints, points, 0., -.2, 1., .9, NULL, NULL)) 
     
    10198  /* Calculate and refine the lower convex hull */ 
    10299  printf ("qhull version: %s\n", hullQHullVersion()); 
    103   if (i=hullCalculate (3, points, numpoints)) 
     100  if (i=hullCalculate (3, points, numpoints, allparams, 2, T, P, 
     101                       &hullfacets, &hullnumfacets)) 
    104102    { printf ("main: Error %d in hullCalculate\n", i); exit (i); } 
    105   if (i=hullRefine (&points, &numpoints, allparams, 2, T, P, 
     103  /*if (i=hullRefine (&points, &numpoints, allparams, 2, T, P, 
    106104                    1e-10, 1e-7, 0)) 
    107105    { printf ("main: error %d in hullRefine\n", i); exit (i); } 
     
    111109  if (i=hullRefine (&points, &numpoints, allparams, 2, T, P, 
    112110                    1e-10, 1e-7, 0)) 
    113     { printf ("main: error %d in hullRefine\n", i); exit (i); } 
    114   if (i=hullReturnFacets (allparams, 2, T, P, &hullnumverts, &hullverts, 
    115                           &hulltypes)) 
    116     { printf ("main: Error %d in hullReturnFacets\n", i); exit (i); } 
     111    { printf ("main: error %d in hullRefine\n", i); exit (i); }*/ 
    117112 
    118113  /* Take out hull triangles which are on the main function (in one phase) */ 
    119   for (i=0; i<hullnumverts; i++) 
     114  /*for (i=0; i<hullnumfacets; i++) 
    120115    { 
    121       /* double Gav = (points [hullverts [3*i]].G + 
    122                     points [hullverts [3*i+1]].G + 
    123                     points [hullverts [3*i+2]].G)/3., 
    124         C2av = (points [hullverts [3*i]].C2 + 
    125                 points [hullverts [3*i+1]].C2 + 
    126                 points [hullverts [3*i+2]].C2)/3., 
    127         C3av = (points [hullverts [3*i]].C3 + 
    128                 points [hullverts [3*i+1]].C3 + 
    129                 points [hullverts [3*i+2]].C3)/3.; 
    130116 
    131 #ifdef DEBUG 
    132       printf ("Facet %d vertices: %d %d %d\n", i, hullverts[3*i], 
    133               hullverts[3*i+1], hullverts[3*i+2]); 
    134               #endif */ 
    135  
    136       /* Test whether hull facet is in one-phase region: free energy at 
    137          centroid is below facet; if so, remove it */ 
    138       /*if (fmin (free_energy (C2av, C3av, T, P, allparams), 
    139         free_energy (C2av, C3av, T, P, allparams+1)) < Gav)*/ 
    140       if (hulltypes [i] == ONE_PHASE) 
     117      // Remove one-phase facets to display just binodal and ternary 
     118      if (hullfacets [i].type == ONE_PHASE) 
    141119        { 
    142           for (j=i; j<hullnumverts-1; j++) 
    143             { 
    144               hullverts [3*j]   = hullverts [3*j+3]; 
    145               hullverts [3*j+1] = hullverts [3*j+4]; 
    146               hullverts [3*j+2] = hullverts [3*j+5]; 
    147               hulltypes [j] = hulltypes [j+1]; 
    148             } 
    149           hullnumverts--; 
     120          for (j=i; j<hullnumfacets-1; j++) 
     121            hullfacets [j] = hullfacets [j+1]; 
     122          hullnumfacets--; 
    150123          i--; 
    151124        } 
    152     } 
     125    } */ 
    153126 
    154   printf ("Binodal region has %d facets\n", hullnumverts); 
     127  printf ("Binodal region has %d facets\n", hullnumfacets); 
    155128 
    156129  if (i=scale_energy_array (numpoints, points, 0., -.2, 1., .9, NULL, NULL)) 
    157130    { printf ("main: Error %d in scale_triangle_array\n", i); exit (i); } 
    158131 
    159   if (i=GeomviewDisplayTriangleCOFF 
    160       (pfd, "Binodal and Tie Lines", "ech", "-face +edge", 
    161        numpoints, points, hullnumverts, hullverts)) 
    162     { printf ("main: Error %d in Geomview Display\n", i); exit (i); } 
    163  
    164132  printf ("Press <return> to close up... "); 
     133  fflush (stdout); 
    165134  fgets (gv_version, 99, stdin); 
    166135 
     
    168137  free (points); 
    169138  free (verts); 
    170   free (hullverts); 
     139  free (hullfacets); 
    171140 
    172141  return 0; 
  • trunk/matml/src/ternary/ternary.h

    r417 r421  
    130130  CRITICAL_POINT, 
    131131  TWO_PHASE, 
    132   THREE_PHASE 
     132  THREE_PHASE, 
     133  ALL_TYPES=127 
    133134} facet_type; 
     135 
     136typedef struct { 
     137  int vertex [3]; 
     138  facet_type type; 
     139} hull_facet; 
    134140 
    135141/* From freenergy.c */ 
     
    157163 
    158164/* From qhull.c */ 
    159 int hullCalculate (int dim, ternary_point *points, int numpoints); 
     165int hullCalculate 
     166(int dim, ternary_point *points, int numpoints, energy_params *eparams, 
     167 int nparams, double T, double P, hull_facet **facets, int *numfacets); 
    160168int hullRefine 
    161169(ternary_point **points, int *numpoints, energy_params *eparams, int nparams, 
    162170 double T,double P, double newton_tolerance, double vertex_tolerance, 
    163171 int one_phase_refine); 
    164 int hullReturnFacets 
    165 (energy_params *eparams, int nparams, double T,double P, 
    166  int *numfacets, int **facetverts, facet_type **facettypes); 
    167172char *hullQHullVersion (); 
    168173 
  • trunk/matml/src/ternary/ternary.tex.in

    r419 r421  
    4141{\tt Ternary} is nearly complete, with the one un-implemented feature being to 
    4242build and neatly visualize how free energy functions create a ternary phase 
    43 diagram.  Also, {\tt qhull.c} needs re-architecting with its own ``facet'' 
    44 structure, such that we can do the hull analysis, store what we need, and free 
    45 {\tt qhull}'s structure arrays and not need to rely on its loops beyond that. 
    46 (This will also make {\tt qhull.c} functions thread-safe.) 
     43diagram. 
    4744 
    4845\section{How it works}