Changeset 378
- Timestamp:
- 06/26/08 10:52:01 (4 months ago)
- Files:
-
- trunk/matml/src/ternary/qhull.c (modified) (9 diffs)
- trunk/matml/src/ternary/ternary.c (modified) (4 diffs)
- trunk/matml/src/ternary/ternary.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/matml/src/ternary/qhull.c
r376 r378 80 80 This uses Newton iteration to refine a single 81 81 82 double*point Composition coordinates of the starting point for refining; the82 coordT *point Composition coordinates of the starting point for refining; the 83 83 result will be returned here. 84 84 85 double*corners Coordinates (including energies) of the corners of this85 coordT *corners Coordinates (including energies) of the corners of this 86 86 facet, used for the facet normal: C21,C31,G1, C22,C32,G2, C23,C33,G3. 87 87 88 88 energy_params *eparams Collection of energy parameter structures. 89 89 90 int nparams Number of energy parameter structures in eparams.91 92 90 double T Temperature. 93 91 … … 97 95 98 96 int localdims Dimensionality over which to do the refinement. 99 100 int side Side of the phase diagram on which to refine, if101 localdims<globaldims.102 97 103 98 double newton_tolerance Stop Newton iterations when the vertex motion falls … … 106 101 107 102 static 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) 111 105 { 112 int i , minfunc=0;106 int i; 113 107 double distance = 1., G, slope2, slope3; 114 108 ternary_point current; … … 119 113 current.C3 = point[1]; 120 114 121 /*+ Determine which is the lowest energy function at this point +*/122 115 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 }129 116 130 117 /*+ Determine the slope(s) of the facet +*/ … … 135 122 xG=corners[5]-corners[2], yG=corners[8]-corners[2]; 136 123 double vG=x2*y3-x3*y2; 137 slope2 = (x 3*yG-xG*y3)/vG;124 slope2 = (xG*y3-x3*yG)/vG; 138 125 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); 139 131 } 140 132 else 141 133 { 142 /* Slope for the binary case */ 134 /* 135 // Slope for the binary case 143 136 if (side==0 || side==2) // C3=0 or C2+C3=1 sides: dG/dC2 144 137 slope2 = (corners[5]-corners[2])/(corners[3]-corners[0]); 145 138 else if (side==1) // C2=0 side: dG/dC3 146 139 slope2 = (corners[5]-corners[2])/(corners[4]-corners[1]); 140 */ 147 141 } 148 142 149 while (distance >= newton_tolerance )143 while (distance >= newton_tolerance * newton_tolerance) 150 144 { 151 145 double dC2, dC3; 152 146 153 147 /*+ Calculate the energy derivatives +*/ 154 free_energy_derivatives (¤t, 1, T, P, eparams +minfunc);148 free_energy_derivatives (¤t, 1, T, P, eparams); 155 149 156 150 /*+ Subtract the facet slopes from the energy derivatives +*/ 157 current.G2 -= slope2;158 current.G3 -= slope3;151 current.G2 += slope2; 152 current.G3 += slope3; 159 153 160 154 /*+ Solve the linear system to estimate the vector to the minimum +*/ … … 167 161 current.C3 += dC3; 168 162 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); 169 165 } 170 166 … … 218 214 FORALLfacets 219 215 { 220 double corners [ 6], energies [3], centroid [3], Gcenter;216 double corners [9], centroid [3], Gcenter; 221 217 vertexT *vertex, **vertexp; 222 int j=0 ;218 int j=0, eparam [3] = {0,0,0}; 223 219 224 220 /*+ 225 221 +latex+\item 226 222 +html+ <li> 227 Copy vertex information into local variables. 223 Copy vertex information into local variables: composition, energy, 224 closest energy function. 228 225 +html+ </li> 229 226 +*/ … … 234 231 if (j<3) 235 232 { 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); 239 255 } 240 256 j++; 241 257 } 242 258 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) 244 263 { 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 245 276 /*+ 246 277 +latex+\item 247 278 +html+ <li> 248 279 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. 250 282 +html+ </li> 251 283 +*/ 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 256 288 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 } 260 314 261 315 /*+ 262 316 +latex+\item 263 317 +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. 265 320 +html+ </li> 266 321 +*/ 267 322 else 268 323 { 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 269 369 /*+ 270 370 +latex+\item 271 371 +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. 273 374 +html+ </li> 274 375 +*/ 275 376 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 */ 293 406 } 294 295 /*+296 +latex+\item297 +html+ <li>298 If any two new candidate vertices are in the same place (closer than299 vertex_tolerance), eliminate one.300 +html+ </li>301 +*/302 407 } 303 408 } … … 306 411 +html+ </ol> 307 412 +*/ 413 414 printf ("Done, returning\n"); 308 415 309 416 return 0; trunk/matml/src/ternary/ternary.c
r366 r378 31 31 char gv_version[100]; 32 32 FILE *pfd = NULL; 33 double T=0.75 ;33 double T=0.75, P=1.; 34 34 ternary_point *points; 35 35 /* eparams: R,T0, G1@T0,G2,G3, C1,C2,C3, M1,M2,M3, O12,O13,O23,O123 */ 36 36 energy_params /* Solid, liquid */ 37 37 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}; 39 40 40 41 if (argc>1) … … 66 67 67 68 /* 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)) 69 70 { printf ("main: Error %d in free_energies\n", i); exit (i); } 70 71 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)) 72 73 { printf ("main: Error %d in free_energies\n", i); exit (i); } 73 74 74 75 /* Scale all free energy values */ 75 76 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)) 77 78 { printf ("main: Error %d in scale_triangle_array\n", i); exit (i); } 78 79 … … 87 88 if (i=hullCalculate (3, (loop_max+1)*(loop_max+2), points)) 88 89 { 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); } 89 92 if (i=hullReturnFacets (&hullnumverts, &hullverts)) 90 93 { printf ("main: Error %d in hullReturnFacets\n", i); exit (i); } … … 110 113 /* Test whether hull facet is in one-phase region: free energy at 111 114 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) 114 117 { 115 118 for (j=i; j<hullnumverts-1; j++) trunk/matml/src/ternary/ternary.h
r373 r378 119 119 /* From qhull.c */ 120 120 int hullCalculate (int dim, int numpoints, ternary_point *points); 121 int hullRefine (energy_params *eparams, int nparams, double T, double P, 122 double newton_tolerance, double vertex_tolerance, 123 int one_phase_refine); 121 124 int hullReturnFacets (int *facets, int **verts); 122 125 char *hullQHullVersion ();