Skip to content

polykin.thermo.acm¤

FloryHuggins ¤

Flory-Huggings multicomponent activity coefficient model.

This model is based on the following Gibbs energy of mixing per mole of sites:

\[ \frac{\Delta g_{mix}}{R T}= \sum_i \frac{\phi_i}{m_i}\ln{\phi_i} + \sum_i \sum_{j>i} \phi_i \phi_j \chi_{ij} \]

where \(\phi_i\) are the volume, mass or segment fractions of the components, \(\chi_{ij}\) are the interaction parameters, and \(m_i\) is the characteristic size of the components.

In this particular implementation, the interaction parameters are allowed to depend on temperature according to the following empirical relationship (as used in Aspen Plus):

\[ \chi_{ij} = a_{ij} + b_{ij}/T + c_{ij} \ln{T} + d_{ij} T + e_{ij} T^2 \]

Moreover, \(\chi_{ij}=\chi_{ji}\) and \(\chi_{ii}=0\).

References

  • P.J. Flory, Principles of polymer chemistry, 1953.
PARAMETER DESCRIPTION
N

Number of components.

TYPE: int

a

Matrix (N,N) of parameters, by default 0. Only the upper triangle must be supplied.

TYPE: FloatSquareMatrix | None DEFAULT: None

b

Matrix (N,N) of parameters, by default 0. Only the upper triangle must be supplied.

TYPE: FloatSquareMatrix | None DEFAULT: None

c

Matrix (N,N) of parameters, by default 0. Only the upper triangle must be supplied.

TYPE: FloatSquareMatrix | None DEFAULT: None

d

Matrix (N,N) of parameters, by default 0. Only the upper triangle must be supplied.

TYPE: FloatSquareMatrix | None DEFAULT: None

e

Matrix (N,N) of parameters, by default 0. Only the upper triangle must be supplied.

TYPE: FloatSquareMatrix | None DEFAULT: None

Source code in src/polykin/thermo/acm/floryhuggins.py
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
class FloryHuggins():
    r"""[Flory-Huggings](https://en.wikipedia.org/wiki/Flory–Huggins_solution_theory)
    multicomponent activity coefficient model.

    This model is based on the following Gibbs energy of mixing per mole of
    sites:

    $$ \frac{\Delta g_{mix}}{R T}= \sum_i \frac{\phi_i}{m_i}\ln{\phi_i}
    + \sum_i \sum_{j>i} \phi_i \phi_j \chi_{ij} $$

    where $\phi_i$ are the volume, mass or segment fractions of the
    components, $\chi_{ij}$ are the interaction parameters, and $m_i$ is the
    characteristic size of the components. 

    In this particular implementation, the interaction parameters are allowed
    to depend on temperature according to the following empirical relationship
    (as used in Aspen Plus):

    $$ \chi_{ij} = a_{ij} + b_{ij}/T + c_{ij} \ln{T} + d_{ij} T + e_{ij} T^2 $$

    Moreover, $\chi_{ij}=\chi_{ji}$ and $\chi_{ii}=0$.

    **References**

    *   P.J. Flory, Principles of polymer chemistry, 1953.

    Parameters
    ----------
    N : int
        Number of components.
    a : FloatSquareMatrix | None
        Matrix (N,N) of parameters, by default 0. Only the upper triangle must
        be supplied.
    b : FloatSquareMatrix | None
        Matrix (N,N) of parameters, by default 0. Only the upper triangle must
        be supplied.
    c : FloatSquareMatrix | None
        Matrix (N,N) of parameters, by default 0. Only the upper triangle must
        be supplied.
    d : FloatSquareMatrix | None
        Matrix (N,N) of parameters, by default 0. Only the upper triangle must
        be supplied.
    e : FloatSquareMatrix | None
        Matrix (N,N) of parameters, by default 0. Only the upper triangle must
        be supplied.

    """

    _N: int
    _a: FloatSquareMatrix
    _b: FloatSquareMatrix
    _c: FloatSquareMatrix
    _d: FloatSquareMatrix
    _e: FloatSquareMatrix

    def __init__(self,
                 N: int,
                 a: Optional[FloatSquareMatrix] = None,
                 b: Optional[FloatSquareMatrix] = None,
                 c: Optional[FloatSquareMatrix] = None,
                 d: Optional[FloatSquareMatrix] = None,
                 e: Optional[FloatSquareMatrix] = None
                 ) -> None:
        """Construct `FloryHuggins` with the given parameters."""

        # Set default values
        if a is None:
            a = np.zeros((N, N))
        if b is None:
            b = np.zeros((N, N))
        if c is None:
            c = np.zeros((N, N))
        if d is None:
            d = np.zeros((N, N))
        if e is None:
            e = np.zeros((N, N))

        # Check shapes
        for array in [a, b, c, d, e]:
            if array.shape != (N, N):
                raise ShapeError(
                    f"The shape of matrix {array} is invalid: {array.shape}.")

        # Check bounds (same as Aspen Plus)
        check_bounds(a, -1e2, 1e2, 'a')
        check_bounds(b, -1e6, 1e6, 'b')
        check_bounds(c, -1e6, 1e6, 'c')
        check_bounds(d, -1e6, 1e6, 'd')
        check_bounds(e, -1e6, 1e6, 'e')

        # Ensure chi_ii=0 and chi_ij=chi_ji
        for array in [a, b, c, d, e]:
            np.fill_diagonal(array, 0.)
            enforce_symmetry(array)

        self._N = N
        self._a = a
        self._b = b
        self._c = c
        self._d = d
        self._e = e

    @functools.cache
    def chi(self, T: float) -> FloatSquareMatrix:
        r"""Compute the matrix of interaction parameters.

        $$
        \chi_{ij} = a_{ij} + b_{ij}/T + c_{ij} \ln{T} + d_{ij} T + e_{ij} T^2
        $$

        Parameters
        ----------
        T : float
            Temperature. Unit = K.

        Returns
        -------
        FloatSquareMatrix
            Matrix of interaction parameters.
        """
        return self._a + self._b/T + self._c*log(T) + self._d*T + self._e*T**2

    def Dgmix(self,
              T: Number,
              phi: FloatVector,
              m: FloatVector) -> Number:
        r"""Gibbs energy of mixing per mole of sites, $\Delta g_{mix}$.

        Parameters
        ----------
        T : float
            Temperature. Unit = K.
        phi : FloatVector
            Volume, mass or segment fractions of all components.
        m : FloatVector
            Characteristic size of all components, typically equal to 1 for
            small molecules and equal to the average degree of polymerization
            for polymers.

        Returns
        -------
        float
            Gibbs energy of mixing per mole of sites. Unit = J/mol.
        """
        p = phi > 0.
        gC = dot(phi[p]/m[p], log(phi[p]))
        gR = 0.5*dot(phi, dot(phi, self.chi(T)))
        return R*T*(gC + gR)

    def Dhmix(self,
              T: float,
              phi: FloatVector,
              m: FloatVector) -> float:
        r"""Enthalpy of mixing per mole of sites, $\Delta h_{mix}$.

        $$ \Delta h_{mix} = \Delta g_{mix} + T \Delta s_{mix} $$

        Parameters
        ----------
        T : float
            Temperature. Unit = K.
        phi : FloatVector
            Volume, mass or segment fractions of all components.
        m : FloatVector
            Characteristic size of all components, typically equal to 1 for
            small molecules and equal to the average degree of polymerization
            for polymers.

        Returns
        -------
        float
            Enthalpy of mixing per mole of sites. Unit = J/mol.
        """
        return self.Dgmix(T, phi, m) + T*self.Dsmix(T, phi, m)

    def Dsmix(self,
              T: float,
              phi: FloatVector,
              m: FloatVector) -> float:
        r"""Entropy of mixing per mole of sites, $\Delta s_{mix}$.

        $$ \Delta s_{mix} = -\left(\frac{\partial \Delta g_{mix}}
           {\partial T}\right)_{P,\phi_i,m_i} $$

        Parameters
        ----------
        T : float
            Temperature. Unit = K.
        phi : FloatVector
            Volume, mass or segment fractions of all components.
        m : FloatVector
            Characteristic size of all components, typically equal to 1 for
            small molecules and equal to the average degree of polymerization
            for polymers.

        Returns
        -------
        float
            Entropy of mixing per mole of sites. Unit = J/(mol·K).
        """
        return -derivative_complex(lambda t: self.Dgmix(t, phi, m), T)[0]

    def a(self,
          T: float,
          phi: FloatVector,
          m: FloatVector
          ) -> FloatVector:
        r"""Activities, $a_i$.

        Parameters
        ----------
        T : float
            Temperature. Unit = K.
        phi : FloatVector
            Volume, mass or segment fractions of all components.
        m : FloatVector
            Characteristic size of all components, typically equal to 1 for
            small molecules and equal to the average degree of polymerization
            for polymers.

        Returns
        -------
        FloatVector
            Activities of all components.
        """
        return FloryHuggins_activity(phi, m, self.chi(T))

Dgmix ¤

Dgmix(
    T: Number, phi: FloatVector, m: FloatVector
) -> Number

Gibbs energy of mixing per mole of sites, \(\Delta g_{mix}\).

PARAMETER DESCRIPTION
T

Temperature. Unit = K.

TYPE: float

phi

Volume, mass or segment fractions of all components.

TYPE: FloatVector

m

Characteristic size of all components, typically equal to 1 for small molecules and equal to the average degree of polymerization for polymers.

TYPE: FloatVector

RETURNS DESCRIPTION
float

Gibbs energy of mixing per mole of sites. Unit = J/mol.

Source code in src/polykin/thermo/acm/floryhuggins.py
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
def Dgmix(self,
          T: Number,
          phi: FloatVector,
          m: FloatVector) -> Number:
    r"""Gibbs energy of mixing per mole of sites, $\Delta g_{mix}$.

    Parameters
    ----------
    T : float
        Temperature. Unit = K.
    phi : FloatVector
        Volume, mass or segment fractions of all components.
    m : FloatVector
        Characteristic size of all components, typically equal to 1 for
        small molecules and equal to the average degree of polymerization
        for polymers.

    Returns
    -------
    float
        Gibbs energy of mixing per mole of sites. Unit = J/mol.
    """
    p = phi > 0.
    gC = dot(phi[p]/m[p], log(phi[p]))
    gR = 0.5*dot(phi, dot(phi, self.chi(T)))
    return R*T*(gC + gR)

Dhmix ¤

Dhmix(T: float, phi: FloatVector, m: FloatVector) -> float

Enthalpy of mixing per mole of sites, \(\Delta h_{mix}\).

\[ \Delta h_{mix} = \Delta g_{mix} + T \Delta s_{mix} \]
PARAMETER DESCRIPTION
T

Temperature. Unit = K.

TYPE: float

phi

Volume, mass or segment fractions of all components.

TYPE: FloatVector

m

Characteristic size of all components, typically equal to 1 for small molecules and equal to the average degree of polymerization for polymers.

TYPE: FloatVector

RETURNS DESCRIPTION
float

Enthalpy of mixing per mole of sites. Unit = J/mol.

Source code in src/polykin/thermo/acm/floryhuggins.py
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
def Dhmix(self,
          T: float,
          phi: FloatVector,
          m: FloatVector) -> float:
    r"""Enthalpy of mixing per mole of sites, $\Delta h_{mix}$.

    $$ \Delta h_{mix} = \Delta g_{mix} + T \Delta s_{mix} $$

    Parameters
    ----------
    T : float
        Temperature. Unit = K.
    phi : FloatVector
        Volume, mass or segment fractions of all components.
    m : FloatVector
        Characteristic size of all components, typically equal to 1 for
        small molecules and equal to the average degree of polymerization
        for polymers.

    Returns
    -------
    float
        Enthalpy of mixing per mole of sites. Unit = J/mol.
    """
    return self.Dgmix(T, phi, m) + T*self.Dsmix(T, phi, m)

Dsmix ¤

Dsmix(T: float, phi: FloatVector, m: FloatVector) -> float

Entropy of mixing per mole of sites, \(\Delta s_{mix}\).

\[ \Delta s_{mix} = -\left(\frac{\partial \Delta g_{mix}} {\partial T}\right)_{P,\phi_i,m_i} \]
PARAMETER DESCRIPTION
T

Temperature. Unit = K.

TYPE: float

phi

Volume, mass or segment fractions of all components.

TYPE: FloatVector

m

Characteristic size of all components, typically equal to 1 for small molecules and equal to the average degree of polymerization for polymers.

TYPE: FloatVector

RETURNS DESCRIPTION
float

Entropy of mixing per mole of sites. Unit = J/(mol·K).

Source code in src/polykin/thermo/acm/floryhuggins.py
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
def Dsmix(self,
          T: float,
          phi: FloatVector,
          m: FloatVector) -> float:
    r"""Entropy of mixing per mole of sites, $\Delta s_{mix}$.

    $$ \Delta s_{mix} = -\left(\frac{\partial \Delta g_{mix}}
       {\partial T}\right)_{P,\phi_i,m_i} $$

    Parameters
    ----------
    T : float
        Temperature. Unit = K.
    phi : FloatVector
        Volume, mass or segment fractions of all components.
    m : FloatVector
        Characteristic size of all components, typically equal to 1 for
        small molecules and equal to the average degree of polymerization
        for polymers.

    Returns
    -------
    float
        Entropy of mixing per mole of sites. Unit = J/(mol·K).
    """
    return -derivative_complex(lambda t: self.Dgmix(t, phi, m), T)[0]

__init__ ¤

__init__(
    N: int,
    a: Optional[FloatSquareMatrix] = None,
    b: Optional[FloatSquareMatrix] = None,
    c: Optional[FloatSquareMatrix] = None,
    d: Optional[FloatSquareMatrix] = None,
    e: Optional[FloatSquareMatrix] = None,
) -> None

Construct FloryHuggins with the given parameters.

Source code in src/polykin/thermo/acm/floryhuggins.py
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
def __init__(self,
             N: int,
             a: Optional[FloatSquareMatrix] = None,
             b: Optional[FloatSquareMatrix] = None,
             c: Optional[FloatSquareMatrix] = None,
             d: Optional[FloatSquareMatrix] = None,
             e: Optional[FloatSquareMatrix] = None
             ) -> None:
    """Construct `FloryHuggins` with the given parameters."""

    # Set default values
    if a is None:
        a = np.zeros((N, N))
    if b is None:
        b = np.zeros((N, N))
    if c is None:
        c = np.zeros((N, N))
    if d is None:
        d = np.zeros((N, N))
    if e is None:
        e = np.zeros((N, N))

    # Check shapes
    for array in [a, b, c, d, e]:
        if array.shape != (N, N):
            raise ShapeError(
                f"The shape of matrix {array} is invalid: {array.shape}.")

    # Check bounds (same as Aspen Plus)
    check_bounds(a, -1e2, 1e2, 'a')
    check_bounds(b, -1e6, 1e6, 'b')
    check_bounds(c, -1e6, 1e6, 'c')
    check_bounds(d, -1e6, 1e6, 'd')
    check_bounds(e, -1e6, 1e6, 'e')

    # Ensure chi_ii=0 and chi_ij=chi_ji
    for array in [a, b, c, d, e]:
        np.fill_diagonal(array, 0.)
        enforce_symmetry(array)

    self._N = N
    self._a = a
    self._b = b
    self._c = c
    self._d = d
    self._e = e

a ¤

a(
    T: float, phi: FloatVector, m: FloatVector
) -> FloatVector

Activities, \(a_i\).

PARAMETER DESCRIPTION
T

Temperature. Unit = K.

TYPE: float

phi

Volume, mass or segment fractions of all components.

TYPE: FloatVector

m

Characteristic size of all components, typically equal to 1 for small molecules and equal to the average degree of polymerization for polymers.

TYPE: FloatVector

RETURNS DESCRIPTION
FloatVector

Activities of all components.

Source code in src/polykin/thermo/acm/floryhuggins.py
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
def a(self,
      T: float,
      phi: FloatVector,
      m: FloatVector
      ) -> FloatVector:
    r"""Activities, $a_i$.

    Parameters
    ----------
    T : float
        Temperature. Unit = K.
    phi : FloatVector
        Volume, mass or segment fractions of all components.
    m : FloatVector
        Characteristic size of all components, typically equal to 1 for
        small molecules and equal to the average degree of polymerization
        for polymers.

    Returns
    -------
    FloatVector
        Activities of all components.
    """
    return FloryHuggins_activity(phi, m, self.chi(T))

chi cached ¤

chi(T: float) -> FloatSquareMatrix

Compute the matrix of interaction parameters.

\[ \chi_{ij} = a_{ij} + b_{ij}/T + c_{ij} \ln{T} + d_{ij} T + e_{ij} T^2 \]
PARAMETER DESCRIPTION
T

Temperature. Unit = K.

TYPE: float

RETURNS DESCRIPTION
FloatSquareMatrix

Matrix of interaction parameters.

Source code in src/polykin/thermo/acm/floryhuggins.py
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
@functools.cache
def chi(self, T: float) -> FloatSquareMatrix:
    r"""Compute the matrix of interaction parameters.

    $$
    \chi_{ij} = a_{ij} + b_{ij}/T + c_{ij} \ln{T} + d_{ij} T + e_{ij} T^2
    $$

    Parameters
    ----------
    T : float
        Temperature. Unit = K.

    Returns
    -------
    FloatSquareMatrix
        Matrix of interaction parameters.
    """
    return self._a + self._b/T + self._c*log(T) + self._d*T + self._e*T**2