3.029 Spring 2022
Lecture 16 - 03/30/2022

Phase Diagram Explorer

Last lecture, we constructed a binary phase diagram for dummy molar Gibbs free energy functions

In this lecture, we will explore one more “realistic” example of the Ag-Cu binary phase diagram

As well as introduce ternary phase diagrams

Ag-Cu Phase Diagram

The first step is to obtain molar Gibbs free energies for the pure phases

For Silver and Copper, in the range 300K to 1300K, we will consider the following phases

a liquid phase

an FCC solid phase

a BBC solid phase, and

an HCP solid phase

molarGibbsEnergy["Ag-L"][T_]=3815.564+109.310993*T-23.8463314*T*Log[T]-1.790585*10^(-3)*T^2-0.398587*10^(-6)*T^3-12011/T-1.034*10^(-20)*T^7;
molarGibbsEnergy["Ag-FCC"][T_]=-7209.512+118.202013*T-23.8463314*T*Log[T]-1.790585*10^(-3)*T^2-0.398587*10^(-6)*T^3-12011/T;
molarGibbsEnergy["Ag-BCC"][T_]=-3809.512+117.152013*T-23.8463314*T*Log[T]-1.790585*10^(-3)*T^2-0.398587*10^(-6)*T^3-12011/T;
molarGibbsEnergy["Ag-HCP"][T_]=-6909.512+118.502013*T-23.8463314*T*Log[T]-1.790585*10^(-3)*T^2-0.398587*10^(-6)*T^3-12011/T;

molarGibbsEnergy["Cu-L"][T_]=5194.277+120.973331*T-24.112392*T*Log[T]-2.65684*10^(-3)*T^2+0.129223*10^(-6)*T^3+52478/T-5.849*10^(-21)*T^7;
molarGibbsEnergy["Cu-FCC"][T_]=-7770.458+130.485235*T-24.112392*T*Log[T]-2.65684*10^(-3)*T^2+0.129223*10^(-6)*T^3+52478/T;
molarGibbsEnergy["Cu-BCC"][T_]=-3753.458+129.230235*T-24.112392*T*Log[T]-2.65684*10^(-3)*T^2+0.129223*10^(-6)*T^3+52478/T;
molarGibbsEnergy["Cu-HCP"][T_]=-7170.458+130.685235*T-24.112392*T*Log[T]-2.65684*10^(-3)*T^2+0.129223*10^(-6)*T^3+52478/T;

Note: These forms can be obtained from integrating heat capacities, and data for the enthalpies and entropies of the liquid and crystalline phases of Ag and Cu

See e.g. Tables A-2, A-3, and A-5 in Gaskell's Introduction to the Thermodynamics of Materials

With[{phases={"Ag-L","Ag-FCC","Ag-BCC","Ag-HCP","Cu-L","Cu-FCC","Cu-BCC","Cu-HCP"},cols=Join@@((Partition[ResourceFunction["ColorBrewerData"]["Paired",8],2])^\[Transpose])},
Plot[Evaluate[Fold[Construct,molarGibbsEnergy,{#,T}]&/@phases],{T,300,1300},PlotLegends->phases, Frame->True,ImageSize->650, BaseStyle->18,PlotStyle->Thread[{cols,Thick}],FrameLabel-> {"Temperature (K)", "Molar Gibbs Free Energy (J/mol)"}]
]

We will then model the excess free energy using a regular solution model

We will assume different interaction parameters for the liquid and solid phases

xlogx[x_]=x Log[x];
xlogx[0]=xlogx[0.0]=xlogx[1]=xlogx[1.0]=0.0;

excessGibbsMixing["Solid"][T_,ωS_:30000][xCu_]=ωS xCu (1-xCu)+8.31T(xlogx[xCu]+xlogx[1-xCu]);
excessGibbsMixing["Liquid"][T_,ωL_:14000][xCu_]=ωL xCu (1-xCu)+8.31T(xlogx[xCu]+xlogx[1-xCu]);

And linearly interpolate between the various phases to define the molar Gibbs free energies of the solutions

molarGibbsEnergyMixing[name_][T_,___][xs_List]:=molarGibbsEnergyMixing[name][T]/@xs

molarGibbsEnergyMixing["Liquid"][T_,ωL_:14000][xCu_]=molarGibbsEnergy["Ag-L"][T]+(molarGibbsEnergy["Cu-L"][T]-molarGibbsEnergy["Ag-L"][T])xCu + excessGibbsMixing["Liquid"][T,ωL][xCu];
molarGibbsEnergyMixing["Liquid"][T_][0]=molarGibbsEnergyMixing["Liquid"][T_][0.0]=Limit[molarGibbsEnergyMixing["Liquid"][T][x],x->0];
molarGibbsEnergyMixing["Liquid"][T_][1]=molarGibbsEnergyMixing["Liquid"][T_][1.0]=Limit[molarGibbsEnergyMixing["Liquid"][T][x],x->1];

molarGibbsEnergyMixing["FCC"][T_,ωS_:30000][xCu_]=molarGibbsEnergy["Ag-FCC"][T]+(molarGibbsEnergy["Cu-FCC"][T]-molarGibbsEnergy["Ag-FCC"][T])xCu + excessGibbsMixing["Solid"][T,ωS][xCu];
molarGibbsEnergyMixing["FCC"][T_][0]=molarGibbsEnergyMixing["FCC"][T_][0.0]=Limit[molarGibbsEnergyMixing["FCC"][T][x],x->0];
molarGibbsEnergyMixing["FCC"][T_][1]=molarGibbsEnergyMixing["FCC"][T_][1.0]=Limit[molarGibbsEnergyMixing["FCC"][T][x],x->1];

molarGibbsEnergyMixing["BCC"][T_,ωS_:30000][xCu_]=molarGibbsEnergy["Ag-BCC"][T]+(molarGibbsEnergy["Cu-BCC"][T]-molarGibbsEnergy["Ag-BCC"][T])xCu + excessGibbsMixing["Solid"][T,ωS][xCu];
molarGibbsEnergyMixing["BCC"][T_][0]=molarGibbsEnergyMixing["BCC"][T_][0.0]=Limit[molarGibbsEnergyMixing["BCC"][T][x],x->0];
molarGibbsEnergyMixing["BCC"][T_][1]=molarGibbsEnergyMixing["BCC"][T_][1.0]=Limit[molarGibbsEnergyMixing["BCC"][T][x],x->1];

molarGibbsEnergyMixing["HCP"][T_,ωS_:30000][xCu_]=molarGibbsEnergy["Ag-HCP"][T]+(molarGibbsEnergy["Cu-HCP"][T]-molarGibbsEnergy["Ag-HCP"][T])xCu + excessGibbsMixing["Solid"][T,ωS][xCu];
molarGibbsEnergyMixing["HCP"][T_][0]=molarGibbsEnergyMixing["HCP"][T_][0.0]=Limit[molarGibbsEnergyMixing["HCP"][T][x],x->0];
molarGibbsEnergyMixing["HCP"][T_][1]=molarGibbsEnergyMixing["HCP"][T_][1.0]=Limit[molarGibbsEnergyMixing["HCP"][T][x],x->1];

With[{phases={"Liquid","FCC","BCC","HCP"},cols=ResourceFunction["ColorBrewerData"]["Paired",8][[1;;8;;2]]},
Manipulate[
Plot[Evaluate[Fold[Construct,molarGibbsEnergyMixing,{#,T,xCu}]&/@phases],{xCu,0,1},PlotLegends->phases,PlotStyle->Thread[{cols,Thick}],Frame->True,ImageSize->650, BaseStyle->18,FrameLabel-> {"Mole Fraction Cu, (Subscript[X, Cu])", "Molar Gibbs Free Energy (J/mol)"}],{{T,300,"Temperature"},300,1400,5},Paneled->False,SaveDefinitions->True]
]

phaseDiagram["Cu-Ag"]=binaryPhaseDiagram[molarGibbsEnergyMixing/@{"Liquid","FCC","BCC","HCP"},{673.15,1373.15,5},1/1000]

Let’s compare this with a phase-diagram from literature

ImageResize[img=Import[],650]
overlay=ColorNegate[Dilation[RemoveBackground[ImageCrop[img Image[ComponentMeasurements[RemoveBackground[img],"Mask",#Count>(500^2)&][[1,2]]]],{"Background",White}],2]];

As we can see the x-axis is given in weight-percent copper, so we need to to convert our mole-fractions to weight-percent using the formula

weightPercent[xb_]=FullSimplify[(xb ElementData["Copper","AtomicMass"])/(xb ElementData["Copper","AtomicMass"]+(1-xb)ElementData["Silver","AtomicMass"])];

Graphics[{phaseDiagram["Cu-Ag"][[1]]/.Line[{{xbA_,T_},{xbB_,T_}}]:>Line[{{weightPercent[xbA],T},{weightPercent[xbB],T}}],Inset[overlay,Scaled[{0,0}],Scaled[{0,0}],Scaled[1]]},phaseDiagram["Cu-Ag"][[2]],AspectRatio->(#2/#1&@@ImageDimensions[overlay]),Sequence@@phaseDiagram["Cu-Ag"][[4;;]],FrameLabel->{"Weight Percent Copper","Temperature °C"},FrameTicks->{{Thread[{QuantityMagnitude[Quantity[Range[400,1100,100],"DegreesCelsius"],"Kelvins"],Range[400,1100,100]}],Automatic},{Thread[{Subdivide[5],Subdivide[5]100}],Automatic}}]

As we can see, our mixing model captures the copper-rich side quite well

But struggles a little bit at smaller Cu compositions

Gibbs Triangle

The idea of a Convex Hull construction generalizes nicely to ternary phase diagrams

First, let’s generalize our plotting functions

We now have 3 mole fraction compositions, (Subscript[x, A]), (Subscript[x, B]), (Subscript[x, C]) subject to the constraint (Subscript[x, A])+(Subscript[x, B])+(Subscript[x, C])=1

And consider a simple regular solution generalization

molarGibbsEnergy["Regular-Ternary"][xa_,xb_]:=With[{xc=1-xa-xb},100((xa^2) (xb^2) (xc^2) +(xlogx[xa] + xlogx[xb] + xlogx[xc])/1000)]

We can plot this on the (Subscript[x, A])+(Subscript[x, B])+(Subscript[x, C])=1 plane in 3D

First, let’s find the minimum and maximum values

freeEnergyMinimum=NMinValue[{molarGibbsEnergy["Regular-Ternary"][xA,xB],0≤xA≤ 1&&0≤xB≤ 1-xA},{xA,xB}];
freeEnergyMaximum=NMaxValue[{molarGibbsEnergy["Regular-Ternary"][xA,xB],0≤xA≤ 1&&0≤xB≤ 1-xA},{xA,xB}];

With[{cf=MPLColorMap["Magma"]},ContourPlot3D[xA+xB+xC==1,{xA,0,1},{xB,0,1},{xC,0,1},PlotRange->All,PlotPoints->50,Mesh->10,ColorFunctionScaling->False,MeshFunctions->Function[{xA,xB,xC,g},molarGibbsEnergy["Regular-Ternary"][xA,xB]],ColorFunction->Function[{xA,xB,xC,g},cf[Clip[Abs[Rescale[molarGibbsEnergy["Regular-Ternary"][xA,xB],{freeEnergyMinimum,freeEnergyMaximum}]]]]],ViewPoint->{1.3,2.4,2.},AxesLabel->{"(Subscript[x, A])","(Subscript[x, B])","(Subscript[x, C])"},BaseStyle->18,ImageSize->500]]

It follows that due to the concentration constraints we can plot this in 2D over the range 0≤(Subscript[x, A])<= 1 & 0<= (Subscript[x, B])<= 1-(Subscript[x, A])

ContourPlot[molarGibbsEnergy["Regular-Ternary"][xG,yG],{xG,yG}∈Triangle[],PlotPoints->50,Contours->10,ColorFunction->MPLColorMap["Magma"],BaseStyle->18,ImageSize->500,FrameLabel->{"Mole Fraction, (Subscript[x, A])","Mole Fraction, (Subscript[x, B])"}]

It is convenient to convert to plot these into the equilateral Gibbs Triangle

Given by the coordinate transformation

transformationFunction={{1,(1/2)},{0,((Sqrt[3])/2)}};
inverseTransformationFunction=Inverse[transformationFunction];

ContourPlot[molarGibbsEnergy["Regular-Ternary"]@@({xG,yG}.(inverseTransformationFunction^\[Transpose])),{xG,yG}∈SSSTriangle[1,1,1],PlotPoints->50,Contours->10,ColorFunction->MPLColorMap["Magma"],Frame->False]

This form is convenient since it allows us to read off compositions using the following geometric properties:

SeedRandom[10];
randomComposition=RandomPoint[Triangle[CirclePoints[3]]]

intersectionConstruction=RandomInstance[GeometricScene[Join[Thread[{a,b,c,p}->Append[CirclePoints[3],randomComposition]],{pa,pb,pc}],
{Triangle[{a,b,c}],pb∈InfiniteLine[{p,b}]&&pb∈InfiniteLine[{a,c}],
pa∈InfiniteLine[{p,a}]&&pa∈InfiniteLine[{b,c}],pc∈InfiniteLine[{p,c}]&&pc∈InfiniteLine[{a,b}]}]]

{((EuclideanDistance[p,pa])/(EuclideanDistance[pa,a])),((EuclideanDistance[p,pb])/(EuclideanDistance[pb,b])),((EuclideanDistance[p,pc])/(EuclideanDistance[pc,c]))}/.intersectionConstruction["Points"]
Total[%]

altitudeConstruction=RandomInstance[GeometricScene[Join[Thread[{a,b,c,p}->Append[CirclePoints[3],randomComposition]],{pm,pn,pl}],
{Triangle[{a,b,c}],
pn∈InfiniteLine[{a,c}],
pm∈InfiniteLine[{b,c}],
pl∈InfiniteLine[{a,b}],
PlanarAngle[{c,pm,p}]==π/2,
PlanarAngle[{b,pl,p}]==π/2,
PlanarAngle[{a,pn,p}]==π/2}]]

(({EuclideanDistance[p,pm],EuclideanDistance[p,pn],EuclideanDistance[p,pl]})/(Indexed[b,2]-Indexed[a,2]))/.altitudeConstruction["Points"]
Total[%]

Ternary Phase Diagram

We can compute isothermal ternary phase diagrams using a generalization of the convex hull technique

This is sometimes referred to as the “rolling-plane” construction and is analogous to the common-tangent construction

First, let’s plot the regular solution model as a surface

Plot3D[molarGibbsEnergy["Regular-Ternary"]@@({xG,yG}.(inverseTransformationFunction^\[Transpose])),{xG,yG}∈SSSTriangle[1,1,1],PlotPoints->50,BaseStyle->18,ImageSize->650,ColorFunction->Function[{xA,xB,g},MPLColorMap["Magma"][g]],Mesh->10,MeshFunctions->(#3&),AxesLabel->{"Mole Fraction, (Subscript[x, A])","Mole Fraction, (Subscript[x, B])",""}]

And then use a similar function to the one we coded up last lecture to see the ternary phase diagram

ternaryPhaseDiagram[{molarGibbsEnergy["Regular-Ternary"]}]

Note that there’s:

a single one-phase region around the edges (continuous color)

three two phase regions  (black dots)

one three phase region (light gray diamond plate)

As we saw last lecture, the two phase regions hold valuable information regarding the composition of the two phases

We can in-fact use tie-lines to connect these (we’ll also use a finer sampling resolution)

ternaryPhaseDiagram[{molarGibbsEnergy["Regular-Ternary"]},True,150]

We can get multiple single-phase regions by adding a second “inverted” molar free energy curve

molarGibbsEnergy["Inverted-Ternary"][xa_,xb_]:=With[{xc=1-xa-xb},.01-.125Exp[-25((xa-((1/2)-(1/(2 (Sqrt[3])))))^2 + (xb-(1/(Sqrt[3])))^2 +(xc-((1/2)-(1/(2 (Sqrt[3])))))^2)]]

Plot3D[{molarGibbsEnergy["Regular-Ternary"]@@({xG,yG}.(inverseTransformationFunction^\[Transpose])),molarGibbsEnergy["Inverted-Ternary"]@@({xG,yG}.(inverseTransformationFunction^\[Transpose]))},{xG,yG}∈SSSTriangle[1,1,1],PlotPoints->50,BaseStyle->18,ImageSize->650,Mesh->10,MeshFunctions->(#3&),AxesLabel->{"Mole Fraction, (Subscript[x, A])","Mole Fraction, (Subscript[x, B])",""}]

ternaryPhaseDiagram[{molarGibbsEnergy["Regular-Ternary"],molarGibbsEnergy["Inverted-Ternary"]}]

ternaryPhaseDiagram[{molarGibbsEnergy["Regular-Ternary"],molarGibbsEnergy["Inverted-Ternary"]},True,150]

Phase Diagram Constructors

Molar Free Energies

xlogx[x_]=x Log[x];
xlogx[0]=xlogx[0.0]=xlogx[1]=xlogx[1.0]=0.0;

molarGibbsEnergy["Regular-Ternary"][xa_,xb_]:=With[{xc=1-xa-xb},100((xa^2) (xb^2) (xc^2) +(xlogx[xa] + xlogx[xb] + xlogx[xc])/1000)]
molarGibbsEnergy["Inverted-Ternary"][xa_,xb_]:=With[{xc=1-xa-xb},.01-.125Exp[-25((xa-((1/2)-(1/(2 (Sqrt[3])))))^2 + (xb-(1/(Sqrt[3])))^2 +(xc-((1/2)-(1/(2 (Sqrt[3])))))^2)]]

Binary

minimumPoints[functionList_, numPts_] :=Thread[{Subdivide[numPts],Min/@Thread[Through[functionList[Subdivide[numPts]]]]}]

getConvexHullVertices[candidatePoints_] := Module[{
maxY = Max[Last /@ candidatePoints],
amendedPoints
}, 
amendedPoints = Join[{{0., 1 + maxY}}, candidatePoints, {{1., 1 + maxY}}]; 
MeshCoordinates[ConvexHullMesh[amendedPoints]][[2;;-2]]
]

ClearAll[MPLColorMap]
<<"http://pastebin.com/raw/pFsb4ZBS";

backgroundGraphic[Tmin_,Tmax_]:=backgroundGraphic[Tmin,Tmax]=DensityPlot[x,{x,0,1},{y,Tmin,Tmax},ColorFunction->MPLColorMap["Magma"]][[1]]

miscibilityGaps[functionList_,temperature_,numPts_] :=miscibilityGaps[functionList,temperature,numPts]=
Module[{convexHullPoints = getConvexHullVertices[minimumPoints[Through[functionList[temperature]], numPts]],singlePhasePoints,miscibilityGaps,cf=MPLColorMap["Magma"],cols},
singlePhasePoints=Split[convexHullPoints,First[#2]-First[#1]<1.001/numPts&];
miscibilityGaps={Last[#1],First[#2]}&@@@Partition[singlePhasePoints,2,1];
Line/@Map[Thread[{#,temperature}]&,miscibilityGaps[[All,All,1]],{2}]
]

binaryPhaseDiagram[functionList_,{Tmin_,Tmax_,ΔT_},Δx_:1/1000]:=
Block[{numPts=Round[1/Δx],bckg=backgroundGraphic[Tmin,Tmax],Ts=Range[Tmin,Tmax,ΔT],tieLines},

tieLines=Monitor[Table[miscibilityGaps[functionList,Ts[[T]],numPts],{T,Length[Ts]}],ProgressIndicator[T,{1,Length[Ts]}]];

Graphics[{bckg,White,tieLines},PlotRange->{{0,1},{Tmin,Tmax}},FrameLabel->{"Composition","Temperature, T (K)"},Frame->True,PlotRangeClipping->True,ImageSize->650,BaseStyle->18]
]

Ternary

transformationFunction={{1,(1/2)},{0,((Sqrt[3])/2)}};

minimumPoints3D[functionList_, numPts_] :=With[{
pts=Select[Join@@Table[{xA,xB},{xA,Subdivide[numPts]},{xB,Subdivide[numPts]}],Total[#]<= 1&]},
N[Append[#,Min[Through[functionList@@#]]]&/@pts]
]

triangleArea[pts:{{p1x_,p1y_},{p2x_,p2y_},{p3x_,p3y_}}]=Area[Triangle[{{p1x,p1y},{p2x,p2y},{p3x,p3y}}]];

splitSinglePhaseRegions[singlePhaseRegion_MeshRegion]:=Block[{rms,coords,polys,polysSplit},
coords=MeshCoordinates[singlePhaseRegion];
polys=MeshCells[singlePhaseRegion,2];

If[First[Nearest[coords[[All,;;2]]->"Distance",{0.,0.}]]>(10^(-6)),Return[{Extract[coords,List@*First/@polys]}]];

rms=RegionMember@*Polygon/@Rest[Subsets[Append[First[TransformedRegion[Triangle[],ScalingTransform[{4/3,4/3},{1/3,1/3}]]],{1/3,1/3}],{3}]];
polysSplit=GatherBy[polys,Last[Ordering[Boole[Through[rms[coords[[First[#],;;2]]]]],-1,Total[#1]<Total[#2]&]]&];
Extract[coords,List@*First/@#]&/@polysSplit
]

splitTwoPhaseRegions[twoPhaseRegions_]:=Block[{groupByLength,triangles,quads,triangleLines,quadLines},

groupByLength=GroupBy[twoPhaseRegions,Length];

triangles=groupByLength[3];
triangleLines=If[MissingQ[triangles],{},
First[MaximalBy[TriangleConstruct[#[[All,;;2]],{"AngleBisectingCevian",All}],RegionMeasure]]&/@triangles];

quads=groupByLength[4];
quadLines=If[MissingQ[quads],{},
Line/@Partition[#[[All,;;2]],2,1]&/@quads];

Join[triangleLines,quadLines]
]

getConvexHullPolygons3D[candidatePoints_,numPts_] := Module[{
maxZ = Max[Last/@candidatePoints],area=((((1/numPts)))^2),
amendedPoints,ch,pts,polygonIndices,groupedLength,singlePhaseRegionPositions,singlePhaseRegion,singlePhaseRegions,twoPlusPhaseRegions,clusteredRegions,rms,groupByCoexistence
}, 

amendedPoints = Join[{{0., 0.,1 + maxZ}}, candidatePoints, {{1.,0., 1 + maxZ},{0.,1., 1 + maxZ}}]; 
ch=ConvexHullMesh[amendedPoints];
pts=MeshCoordinates[ch];
polygonIndices=MeshCells[ch,2];
polygonIndices=Select[polygonIndices,And@@Thread[pts[[First[#],3]]<=maxZ]&];
groupedLength=GroupBy[polygonIndices,Length@*First];
singlePhaseRegionPositions=Position[groupedLength[3],Polygon[{a_,b_,c_}]/;triangleArea[pts[[{a,b,c},;;2]]]<area];
singlePhaseRegion=Extract[groupedLength[3],singlePhaseRegionPositions];

twoPlusPhaseRegions=Flatten[{Values[KeyDrop[groupedLength,3]],Delete[groupedLength[3],singlePhaseRegionPositions]}];
twoPlusPhaseRegions=Extract[pts,List@*First/@twoPlusPhaseRegions];

singlePhaseRegions=ConnectedMeshComponents[MeshRegion[pts,singlePhaseRegion]];
clusteredRegions=Join@@(splitSinglePhaseRegions/@singlePhaseRegions);

rms=RegionMember@*Polygon/@clusteredRegions;
groupByCoexistence=GroupBy[twoPlusPhaseRegions,Length[Position[Unitize[Total/@Boole[Through[rms[#]]]],1]]&];

{Join@@clusteredRegions,groupByCoexistence[2],groupByCoexistence[3]}

]

concToColor[{xA_,xB_,g_}]:=RGBColor[xA,xB,1-xA-xB]

colorTernaryPhaseDiagram[{singlePhaseRegions_,twoPhaseRegions_,threePhaseRegions_},showTieLines_:False,labels_:{"A","B","C"}]:=
Block[{singlePhaseCols=Map[concToColor,singlePhaseRegions,{2}],graphicsObject,labelCoords},
labelCoords=First[TransformedRegion[SSSTriangle[1,1,1],ScalingTransform[{19/18,19/18},{(1/2),(1/(2 (Sqrt[3])))}]]];
graphicsObject=MapThread[Polygon[#1[[All,;;2]],VertexColors->#2]&,{singlePhaseRegions,singlePhaseCols}];

graphicsObject=Join[graphicsObject,{PatternFilling[{"DiamondPlate",LightGray},ImageScaled[0.025]],Polygon/@threePhaseRegions[[All,All,;;2]]}];

graphicsObject=If[showTieLines,
Join[graphicsObject,{Black,Thin,splitTwoPhaseRegions[twoPhaseRegions]}],
Join[graphicsObject,{PatternFilling[{"Halftone",Black},ImageScaled[0.025]],Polygon/@twoPhaseRegions[[All,All,;;2]]}]];

Graphics[{EdgeForm[None],GeometricTransformation[graphicsObject,transformationFunction],MapThread[Text[#1,#2,BaseStyle->24]&,{labels,labelCoords}]},ImageSize->500]
]

ternaryPhaseDiagram[functionList_,showTieLines_:False,numPts_:100,labels_:{"A","B","C"}]:=Rasterize[colorTernaryPhaseDiagram[getConvexHullPolygons3D[minimumPoints3D[functionList,numPts],numPts],showTieLines,labels],RasterSize->1000,ImageSize->500]