| 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 | | } |
| | 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 | |
| | 110 | int 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 | /*++++++++++++++++++++++++++++++++++++++ |
| 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); |