Changeset 378

Show
Ignore:
Timestamp:
06/26/08 10:52:01 (4 months ago)
Author:
powell
Message:

Add pressure to ternary.c; try to use hullRefine (segfaults for now).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/matml/src/ternary/qhull.c

    r376 r378  
    8080  This uses Newton iteration to refine a single  
    8181 
    82   double *point Composition coordinates of the starting point for refining; the 
     82  coordT *point Composition coordinates of the starting point for refining; the 
    8383  result will be returned here. 
    8484 
    85   double *corners Coordinates (including energies) of the corners of this 
     85  coordT *corners Coordinates (including energies) of the corners of this 
    8686  facet, used for the facet normal: C21,C31,G1, C22,C32,G2, C23,C33,G3. 
    8787 
    8888  energy_params *eparams Collection of energy parameter structures. 
    8989 
    90   int nparams Number of energy parameter structures in eparams. 
    91  
    9290  double T Temperature. 
    9391 
     
    9795 
    9896  int localdims Dimensionality over which to do the refinement. 
    99  
    100   int side Side of the phase diagram on which to refine, if 
    101   localdims<globaldims. 
    10297 
    10398  double newton_tolerance Stop Newton iterations when the vertex motion falls 
     
    106101 
    107102static void NewtonRefine 
    108 (coordT *point, coordT *corners, energy_params *eparams, int nparams, 
    109  double T, double P, int globaldims, int localdims, int side, 
    110  double newton_tolerance) 
     103(coordT *point, coordT *corners, energy_params *eparams, double T, double P, 
     104 int globaldims, int localdims, double newton_tolerance) 
    111105{ 
    112   int i, minfunc=0
     106  int i
    113107  double distance = 1., G, slope2, slope3; 
    114108  ternary_point current; 
     
    119113  current.C3 = point[1]; 
    120114 
    121   /*+ Determine which is the lowest energy function at this point +*/ 
    122115  G = free_energy (current.C2, current.C3, T, P, eparams); 
    123   for (i=1; i<nparams; i++) 
    124     if (slope2 = free_energy (current.C2, current.C3, T, P, eparams+i) < G) 
    125       { 
    126         G = slope2; 
    127         minfunc = i; 
    128       } 
    129116 
    130117  /*+ Determine the slope(s) of the facet +*/ 
     
    135122        xG=corners[5]-corners[2], yG=corners[8]-corners[2]; 
    136123      double vG=x2*y3-x3*y2; 
    137       slope2 = (x3*yG-xG*y3)/vG; 
     124      slope2 = (xG*y3-x3*yG)/vG; 
    138125      slope3 = (xG*y2-x2*yG)/vG; 
     126 
     127      printf ("      corners: %g %g %g %g %g %g %g %g %g\n      slopes: %g %g\n", 
     128              corners[0], corners[1], corners[2], 
     129              corners[3], corners[4], corners[5], 
     130              corners[6], corners[7], corners[8], slope2, slope3); 
    139131    } 
    140132  else 
    141133    { 
    142       /* Slope for the binary case */ 
     134      /* 
     135      // Slope for the binary case 
    143136      if (side==0 || side==2) // C3=0 or C2+C3=1 sides: dG/dC2 
    144137        slope2 = (corners[5]-corners[2])/(corners[3]-corners[0]); 
    145138      else if (side==1) // C2=0 side: dG/dC3 
    146139        slope2 = (corners[5]-corners[2])/(corners[4]-corners[1]); 
     140      */ 
    147141    } 
    148142 
    149   while (distance >= newton_tolerance
     143  while (distance >= newton_tolerance * newton_tolerance
    150144    { 
    151145      double dC2, dC3; 
    152146 
    153147      /*+ Calculate the energy derivatives +*/ 
    154       free_energy_derivatives (&current, 1, T, P, eparams+minfunc); 
     148      free_energy_derivatives (&current, 1, T, P, eparams); 
    155149 
    156150      /*+ Subtract the facet slopes from the energy derivatives +*/ 
    157       current.G2 -= slope2; 
    158       current.G3 -= slope3; 
     151      current.G2 += slope2; 
     152      current.G3 += slope3; 
    159153 
    160154      /*+ Solve the linear system to estimate the vector to the minimum +*/ 
     
    167161      current.C3 += dC3; 
    168162      distance = dC2*dC2 + dC3*dC3; 
     163      printf ("        Added %g,%g (dist %g) to go to %g,%g\n", dC2,dC3, 
     164              sqrt(distance), current.C2,current.C3); 
    169165    } 
    170166 
     
    218214  FORALLfacets 
    219215    { 
    220       double corners [6], energies [3], centroid [3], Gcenter; 
     216      double corners [9], centroid [3], Gcenter; 
    221217      vertexT *vertex, **vertexp; 
    222       int j=0
     218      int j=0, eparam [3] = {0,0,0}
    223219 
    224220      /*+ 
    225221        +latex+\item 
    226222        +html+ <li> 
    227         Copy vertex information into local variables. 
     223        Copy vertex information into local variables: composition, energy, 
     224        closest energy function. 
    228225        +html+ </li> 
    229226        +*/ 
     
    234231          if (j<3) 
    235232            { 
    236               corners [2*j]   = vertex->point[0]; 
    237               corners [2*j+1] = vertex->point[1]; 
    238               energies [j]    = vertex->point[2]; 
     233              int i; 
     234              double emin; 
     235 
     236              corners [3*j]   = vertex->point[0]; 
     237              corners [3*j+1] = vertex->point[1]; 
     238              corners [3*j+2] = vertex->point[2]; 
     239 
     240              emin = fabs (corners [3*j+2] - free_energy 
     241                           (corners [3*j], corners [3*j+1], T, P, eparams)); 
     242 
     243              for (i=1; i<nparams; i++) 
     244                if (fabs (corners [3*j+2] - free_energy 
     245                          (corners [3*j], corners [3*j+1], T, P, eparams+i)) 
     246                    < emin) 
     247                  { 
     248                    emin = fabs (corners [3*j+2] - free_energy 
     249                                 (corners [3*j], corners [3*j+1], T, P, eparams+i)); 
     250                    eparam [j] = i; 
     251                  } 
     252              if (emin > 1.e-10) // Sanity check; this should always be zero 
     253                printf ("Vertex at %g,%g: eparam=%d, emin=%g\n", 
     254                        corners [3*j], corners [3*j+1], eparam [j], emin); 
    239255            } 
    240256          j++; 
    241257        } 
    242258 
    243       if (j<3) /* Ignore non-simplical facets */ 
     259      // Ignore non-simplical facets and top facet 
     260      if (fabs((corners[3]-corners[0])*(corners[7]-corners[1]) - 
     261               (corners[6]-corners[0])*(corners[4]-corners[1])) < 0.999999 
     262          && j==3) 
    244263        { 
     264          int eparamc=0; 
     265          realT bestdist; 
     266          boolT isoutside; 
     267 
     268          printf ("Triangle: %g,%g %g,%g %g,%g\n", 
     269                  corners[0], corners[1], corners[3], 
     270                  corners[4], corners[6], corners[7]); 
     271          printf ("  Curves: %d %d %d, Area: %g\n", 
     272                  eparam[0], eparam[1], eparam[2], 
     273                  fabs((corners[3]-corners[0])*(corners[7]-corners[1]) - 
     274                       (corners[6]-corners[0])*(corners[4]-corners[1]))); 
     275 
    245276          /*+ 
    246277            +latex+\item 
    247278            +html+ <li> 
    248279            If the lowest free energy function at the centroid has lower energy 
    249             than the average energy of the vertices, add it as a new vertex. 
     280            than the average energy of the vertices, and the three vertices are 
     281            on the same free energy curve, add it as a new vertex. 
    250282            +html+ </li> 
    251283            +*/ 
    252           centroid[0] = (corners[0] + corners[2] + corners[4]) / 3.; 
    253           centroid[1] = (corners[1] + corners[3] + corners[5]) / 3.; 
    254           centroid[2] = (energies[0] + energies[1] + energies[2]) / 3.; 
    255           /*** CHECK ALL EPARAMS OF CORNERS ***/ 
     284          centroid[0] = (corners[0] + corners[3] + corners[6]) / 3.; 
     285          centroid[1] = (corners[1] + corners[4] + corners[7]) / 3.; 
     286          centroid[2] = (corners[2] + corners[5] + corners[8]) / 3.; 
     287           
    256288          Gcenter = free_energy (centroid[0], centroid[1], T, P, eparams); 
    257  
    258           if (Gcenter < centroid[2] && one_phase_refine) 
    259               ; 
     289          for (j=1; j<nparams; j++) 
     290            if (Gcenter > free_energy (centroid[0],centroid[1], T,P, eparams)) 
     291              { 
     292                Gcenter = free_energy (centroid[0],centroid[1], T,P, eparams); 
     293                eparamc = j; 
     294              } 
     295 
     296          printf ("  Centroid %g, free energy %g (func %d)\n", 
     297                  centroid[2], Gcenter, eparamc); 
     298 
     299          if (Gcenter < centroid[2] && 
     300              eparam[0] == eparam[1] && eparam[1] == eparam[2]) 
     301            { 
     302              if (one_phase_refine || eparam[0] != eparamc) 
     303                { 
     304                  printf ("  Will refine %s-phase triangle\n", 
     305                          (eparam[0]==eparamc) ? "one" : "multi"); 
     306                  // Change that when we add this as a new vertex 
     307                } 
     308 
     309              else 
     310                { 
     311                  printf ("  Not refining one-phase triangle\n"); 
     312                } 
     313            } 
    260314 
    261315          /*+ 
    262316            +latex+\item 
    263317            +html+ <li> 
    264             Otherwise, use Newton-Raphson iteration to refine each vertex. 
     318            Otherwise, use Newton-Raphson iteration to refine each vertex, 
     319            which consists of the remaining steps. 
    265320            +html+ </li> 
    266321            +*/ 
    267322          else 
    268323            { 
     324              coordT newcorners [9] = { corners[0], corners[1], corners[2], 
     325                                        corners[3], corners[4], corners[5], 
     326                                        corners[6], corners[7], corners[8]}; 
     327 
     328              printf ("  Refining multi-phase triangle\n"); 
     329              for (j=0; j<3; j++) 
     330                { 
     331                  /*+ 
     332                    +latex+\item 
     333                    +html+ <li> 
     334                    If the vertex is on a side of the phase diagram (one or 
     335                    more composition variables is zero or they sum to one), 
     336                    refine generally starting a bit closer to the others. 
     337                    +html+ </li> 
     338                    +*/ 
     339                  if (corners[3*j] == 0. || corners[3*j+1] == 0 || 
     340                      corners[3*j] + corners[3*j+1] == 1.) 
     341                    { 
     342                      newcorners[3*j] = centroid[0]; 
     343                      //0.9999999998 * corners[3*j] + 
     344                      //0.0000000001 * corners[3*((j+1)%3)] + 
     345                      //0.0000000001 * corners[3*((j+2)%3)]; 
     346                      newcorners[3*j+1] = centroid[1]; 
     347                      //0.9999999998 * corners[3*j+1] + 
     348                      //0.0000000001 * corners[3*((j+1)%3)+1] + 
     349                      //0.0000000001 * corners[3*((j+2)%3)+1]; 
     350                      newcorners[3*j+2] = centroid[2]; 
     351                      //0.9999999998 * corners[3*j+2] + 
     352                      //0.0000000001 * corners[3*((j+1)%3)+2] + 
     353                      //0.0000000001 * corners[3*((j+2)%3)+2]; 
     354                    } 
     355                  else 
     356                    { 
     357                  printf ("    Refining point at %g, %g function %d\n", 
     358                          newcorners[3*j], newcorners[3*j+1], eparam[j]); 
     359                  NewtonRefine (newcorners+2*j, corners, eparams+eparam[j], 
     360                                T,P, 3,3, newton_tolerance); 
     361                  printf ("    -> %g, %g\n", newcorners[3*j], 
     362                          newcorners[3*j+1]); 
     363 
     364                  newcorners[3*j+2] = free_energy 
     365                    (newcorners[3*j],newcorners[3*j+1], T,P, eparams+eparam[j]); 
     366                    } 
     367                } 
     368 
    269369              /*+ 
    270370                +latex+\item 
    271371                +html+ <li> 
    272                 Find the lowest free energy function at this vertex. 
     372                If any two new candidate vertices are in the same place (closer 
     373                than vertex_tolerance), eliminate one. 
    273374                +html+ </li> 
    274375                +*/ 
    275376 
    276               /*+ 
    277                 +latex+\item 
    278                 +html+ <li> 
    279                 If the vertex is on a side of the phase diagram (one or more 
    280                 composition variables is zero or they sum to one), refine along 
    281                 each side that it's on, to avoid the "infinite slope at the 
    282                 edge" problem.  If it's on more than one side, add a new 
    283                 candidate vertex for each side it's on. 
    284                 +html+ </li> 
    285                 +*/ 
    286  
    287               /*+ 
    288                 +latex+\item 
    289                 +html+ <li> 
    290                 Otherwise refine starting at this vertex. 
    291                 +html+ </li> 
    292                 +*/ 
     377              // Don't add the point, reallocate the points array instead! 
     378              printf ("    Adding new point %g,%g,%g; result %d\n", 
     379                      newcorners[0], newcorners[1], newcorners[2], 
     380                      qh_addpoint ((pointT *) newcorners,  
     381                                   qh_findbestfacet ((pointT *)newcorners, 
     382                                                     True, &bestdist, &isoutside), 
     383                                   True)); 
     384 
     385              /* 
     386              if ((newcorners[3]-newcorners[0])*(newcorners[3]-newcorners[0]) + 
     387                  (newcorners[4]-newcorners[1])*(newcorners[4]-newcorners[1]) + 
     388                  (newcorners[5]-newcorners[2])*(newcorners[5]-newcorners[2]) > 
     389                  vertex_tolerance * vertex_tolerance) 
     390                printf ("    Adding new point %g,%g,%g; result %d\n", 
     391                        newcorners[3], newcorners[4], newcorners[5], 
     392                        qh_addpoint ((pointT *) newcorners+3, facet, True)); 
     393 
     394              if ((newcorners[6]-newcorners[0])*(newcorners[6]-newcorners[0]) + 
     395                  (newcorners[7]-newcorners[1])*(newcorners[7]-newcorners[1]) + 
     396                  (newcorners[8]-newcorners[2])*(newcorners[8]-newcorners[2]) > 
     397                  vertex_tolerance * vertex_tolerance && 
     398                  (newcorners[6]-newcorners[3])*(newcorners[6]-newcorners[3]) + 
     399                  (newcorners[7]-newcorners[4])*(newcorners[7]-newcorners[4]) + 
     400                  (newcorners[8]-newcorners[5])*(newcorners[8]-newcorners[5]) > 
     401                  vertex_tolerance * vertex_tolerance) 
     402                printf ("    Adding new point %g,%g,%g; result %d\n", 
     403                        newcorners[6], newcorners[7], newcorners[8], 
     404                        qh_addpoint ((pointT *) newcorners+6, facet, True)); 
     405              */ 
    293406            } 
    294  
    295           /*+ 
    296             +latex+\item 
    297             +html+ <li> 
    298             If any two new candidate vertices are in the same place (closer than 
    299             vertex_tolerance), eliminate one. 
    300             +html+ </li> 
    301             +*/ 
    302407        } 
    303408    } 
     
    306411    +html+ </ol> 
    307412    +*/ 
     413 
     414  printf ("Done, returning\n"); 
    308415 
    309416  return 0; 
  • trunk/matml/src/ternary/ternary.c

    r366 r378  
    3131  char gv_version[100]; 
    3232  FILE *pfd = NULL; 
    33   double T=0.75
     33  double T=0.75, P=1.
    3434  ternary_point *points; 
    3535  /* eparams: R,T0, G1@T0,G2,G3, C1,C2,C3, M1,M2,M3, O12,O13,O23,O123 */ 
    3636  energy_params /* Solid, liquid */ 
    3737    eparams1 = {1.,1., 0.,-.1,-.2, -1.,-1.1,-1.2, 1.,2.,5., -.5,2.,.2, 0.}, 
    38     eparams2 = {1.,1., .3,.1,-.1, -2.2,-2.,-1.8, 1.,1.,1.5, -.3,-.4,-.1, -.5}; 
     38    eparams2 = {1.,1., .3,.1,-.1, -2.2,-2.,-1.8, 1.,1.,1.5, -.3,-.4,-.1, -.5}, 
     39      allparams[2] = {eparams1, eparams2}; 
    3940 
    4041  if (argc>1) 
     
    6667 
    6768  /* Calculate free energies */ 
    68   if (i=free_energies (points, (loop_max+1)*(loop_max+2)/2, T, 1., &eparams1)) 
     69  if (i=free_energies (points, (loop_max+1)*(loop_max+2)/2, T, P, &eparams1)) 
    6970    { printf ("main: Error %d in free_energies\n", i); exit (i); } 
    7071  if (i=free_energies (points+(loop_max+1)*(loop_max+2)/2, 
    71                        (loop_max+1)*(loop_max+2)/2, T, 1., &eparams2)) 
     72                       (loop_max+1)*(loop_max+2)/2, T, P, &eparams2)) 
    7273    { printf ("main: Error %d in free_energies\n", i); exit (i); } 
    7374 
    7475  /* Scale all free energy values */ 
    7576  if (i=scale_energy_array ((loop_max+1)*(loop_max+2), points, 
    76                               0., -.2, 1., .9, NULL, NULL)) 
     77                            0., -.2, 1., .9, NULL, NULL)) 
    7778    { printf ("main: Error %d in scale_triangle_array\n", i); exit (i); } 
    7879 
     
    8788  if (i=hullCalculate (3, (loop_max+1)*(loop_max+2), points)) 
    8889    { printf ("main: Error %d in hullCalculate\n", i); exit (i); } 
     90  if (i=hullRefine (allparams, 2, T, P, 1e-15, 1e-10, 0)) 
     91    { printf ("main: error %d in hullRefine\n", i); exit (i); } 
    8992  if (i=hullReturnFacets (&hullnumverts, &hullverts)) 
    9093    { printf ("main: Error %d in hullReturnFacets\n", i); exit (i); } 
     
    110113      /* Test whether hull facet is in one-phase region: free energy at 
    111114         centroid is below facet; if so, remove it */ 
    112       if (fmin (free_energy (C2av, C3av, T, 1., &eparams1), 
    113                 free_energy (C2av, C3av, T, 1., &eparams2)) < Gav) 
     115      if (fmin (free_energy (C2av, C3av, T, P, &eparams1), 
     116                free_energy (C2av, C3av, T, P, &eparams2)) < Gav) 
    114117        { 
    115118          for (j=i; j<hullnumverts-1; j++) 
  • trunk/matml/src/ternary/ternary.h

    r373 r378  
    119119/* From qhull.c */ 
    120120int hullCalculate (int dim, int numpoints, ternary_point *points); 
     121int hullRefine (energy_params *eparams, int nparams, double T, double P, 
     122                double newton_tolerance, double vertex_tolerance, 
     123                int one_phase_refine); 
    121124int hullReturnFacets (int *facets, int **verts); 
    122125char *hullQHullVersion (); 




About | Terms of Use | Contact | Privacy Policy