Skip to content

Diffusion (polykin.properties.diffusion)¤

This module implements methods to calculate mutual and self-diffusion coefficients in binary liquid and gas mixtures.

DL_Hayduk_Minhas ¤

DL_Hayduk_Minhas(
    T: float,
    method: Literal["paraffin", "aqueous"],
    MA: float,
    rhoA: float,
    viscB: float,
) -> float

Estimate the infinite-dilution coefficient of a solute A in a liquid solvent B, \(D^0_{AB}\), using the Hayduk-Minhas method.

References

  • RC Reid, JM Prausniz, and BE Poling. The properties of gases & liquids 4th edition, 1986, p. 602.
PARAMETER DESCRIPTION
T

Temperature. Unit = K.

TYPE: float

method

Method selection. Chose 'paraffin' for normal paraffin solutions and 'aqueous' for solutes in aqueous solutions.

TYPE: Literal['paraffin', 'aqueous']

MA

Molar mass of solute A. Unit = kg/mol.

TYPE: float

rhoA

Density of solute A at the normal boiling point. Unit = kg/m³.

TYPE: float

viscB

Viscostity of solvent B. Unit = Pa.s.

TYPE: float

RETURNS DESCRIPTION
float

Diffusion coefficient of A in B at infinite dilution. Unit = m²/s.

See also

Examples:

Estimate the diffusion coefficient of vinyl chloride through liquid water.

>>> from polykin.properties.diffusion import DL_Hayduk_Minhas
>>> D = DL_Hayduk_Minhas(
...     T=298.,           # temperature
...     method='aqueous', # equation for aqueous solutions
...     MA=62.5e-3,       # molar mass of vinyl chloride
...     rhoA=910.,        # density of vinyl chloride at the boiling point
...     viscB=0.89e-3     # viscosity of water at solution temperature
...     )
>>> print(f"{D:.2e} m²/s")
1.26e-09 m²/s
Source code in src/polykin/properties/diffusion/liquid.py
 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
def DL_Hayduk_Minhas(T: float,
                     method: Literal['paraffin', 'aqueous'],
                     MA: float,
                     rhoA: float,
                     viscB: float,
                     ) -> float:
    r"""Estimate the infinite-dilution coefficient of a solute A in a liquid
    solvent B, $D^0_{AB}$, using the Hayduk-Minhas method.

    **References**

    *   RC Reid, JM Prausniz, and BE Poling. The properties of gases & liquids
        4th edition, 1986, p. 602.

    Parameters
    ----------
    T : float
        Temperature. Unit = K.
    method : Literal['paraffin', 'aqueous']
        Method selection. Chose `'paraffin'` for normal paraffin solutions and
        `'aqueous'` for solutes in aqueous solutions.
    MA : float
        Molar mass of solute A. Unit = kg/mol.
    rhoA : float
        Density of solute A at the normal boiling point. Unit = kg/m³.
    viscB : float
        Viscostity of solvent B. Unit = Pa.s.

    Returns
    -------
    float
        Diffusion coefficient of A in B at infinite dilution. Unit = m²/s.

    See also
    --------
    * [`DL_Wilke_Chang`](DL_Wilke_Chang.md): alternative method.

    Examples
    --------
    Estimate the diffusion coefficient of vinyl chloride through liquid water.

    >>> from polykin.properties.diffusion import DL_Hayduk_Minhas
    >>> D = DL_Hayduk_Minhas(
    ...     T=298.,           # temperature
    ...     method='aqueous', # equation for aqueous solutions
    ...     MA=62.5e-3,       # molar mass of vinyl chloride
    ...     rhoA=910.,        # density of vinyl chloride at the boiling point
    ...     viscB=0.89e-3     # viscosity of water at solution temperature
    ...     )
    >>> print(f"{D:.2e} m²/s")
    1.26e-09 m²/s
    """
    VA = 1e6*MA/rhoA

    if method == 'paraffin':
        epsilon = 10.2/VA - 0.791
        DAB0 = 13.3e-12*T**1.47*(viscB*1e3)**epsilon/VA**0.71
    elif method == 'aqueous':
        epsilon = 9.58/VA - 1.12
        DAB0 = 1.25e-12*(VA**-0.19 - 0.292)*T**1.52*(viscB*1e3)**epsilon
    else:
        raise ValueError(f"Invalid `method` input: {method}")

    return DAB0

DL_Wilke_Chang ¤

DL_Wilke_Chang(
    T: float,
    MA: float,
    MB: float,
    rhoA: float,
    viscB: float,
    phi: float = 1.0,
) -> float

Estimate the infinite-dilution coefficient of a solute A in a liquid solvent B, \(D^0_{AB}\), using the Wilke-Chang method.

\[ D^0_{AB} = 5.9\times 10^{-17} \frac{(\phi M_B)^{1/2} T}{\eta_B (M_A/\rho_A)^{0.6}} \]

where the meaning of all symbols is as described below in the parameters section. The numerical factor has been adjusted to convert the equation to SI units.

References

  • RC Reid, JM Prausniz, and BE Poling. The properties of gases & liquids 4th edition, 1986, p. 598.
PARAMETER DESCRIPTION
T

Temperature. Unit = K.

TYPE: float

MA

Molar mass of solute A. Unit = kg/mol.

TYPE: float

MB

Molar mass of solvent B. Unit = kg/mol.

TYPE: float

rhoA

Density of solute A at the normal boiling point, \(\rho_A\). Unit = kg/m³.

TYPE: float

viscB

Viscostity of solvent B, \(\eta_B\). Unit = Pa.s.

TYPE: float

phi

Association factor of solvent B, \(\phi\). The following values are recomended: {water: 2.6, methanol: 1.9, ethanol: 1.5, unassociated: 1.0}.

TYPE: float DEFAULT: 1.0

RETURNS DESCRIPTION
float

Diffusion coefficient of A in B at infinite dilution. Unit = m²/s.

See also

Examples:

Estimate the diffusion coefficient of vinyl chloride through liquid water.

>>> from polykin.properties.diffusion import DL_Wilke_Chang
>>> D = DL_Wilke_Chang(
...     T=298.,         # temperature
...     MA=62.5e-3,     # molar mass of vinyl chloride
...     MB=18.0e-3,     # molar mass of water
...     rhoA=910.,      # density of vinyl chloride at the boiling point
...     viscB=0.89e-3,  # viscosity of water at solution temperature
...     phi=2.6         # association factor for water (see docstring)
...     )
>>> print(f"{D:.2e} m²/s")
1.34e-09 m²/s
Source code in src/polykin/properties/diffusion/liquid.py
15
16
17
18
19
20
21
22
23
24
25
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
def DL_Wilke_Chang(T: float,
                   MA: float,
                   MB: float,
                   rhoA: float,
                   viscB: float,
                   phi: float = 1.0
                   ) -> float:
    r"""Estimate the infinite-dilution coefficient of a solute A in a liquid
    solvent B, $D^0_{AB}$, using the Wilke-Chang method.

    $$
    D^0_{AB} = 5.9\times 10^{-17}
        \frac{(\phi M_B)^{1/2} T}{\eta_B (M_A/\rho_A)^{0.6}}
    $$

    where the meaning of all symbols is as described below in the parameters
    section. The numerical factor has been adjusted to convert the equation to
    SI units.

    **References**

    *   RC Reid, JM Prausniz, and BE Poling. The properties of gases & liquids
        4th edition, 1986, p. 598.

    Parameters
    ----------
    T : float
        Temperature. Unit = K.
    MA : float
        Molar mass of solute A. Unit = kg/mol.
    MB : float
        Molar mass of solvent B. Unit = kg/mol.
    rhoA : float
        Density of solute A at the normal boiling point, $\rho_A$.
        Unit = kg/m³.
    viscB : float
        Viscostity of solvent B, $\eta_B$. Unit = Pa.s.
    phi : float
        Association factor of solvent B, $\phi$. The following values are
        recomended: {water: 2.6, methanol: 1.9, ethanol: 1.5,
        unassociated: 1.0}.

    Returns
    -------
    float
        Diffusion coefficient of A in B at infinite dilution. Unit = m²/s.

    See also
    --------
    * [`DL_Hayduk_Minhas`](DL_Hayduk_Minhas.md): alternative method.

    Examples
    --------
    Estimate the diffusion coefficient of vinyl chloride through liquid water.

    >>> from polykin.properties.diffusion import DL_Wilke_Chang
    >>> D = DL_Wilke_Chang(
    ...     T=298.,         # temperature
    ...     MA=62.5e-3,     # molar mass of vinyl chloride
    ...     MB=18.0e-3,     # molar mass of water
    ...     rhoA=910.,      # density of vinyl chloride at the boiling point
    ...     viscB=0.89e-3,  # viscosity of water at solution temperature
    ...     phi=2.6         # association factor for water (see docstring)
    ...     )
    >>> print(f"{D:.2e} m²/s")
    1.34e-09 m²/s
    """
    return 7.4e-12*sqrt(phi*MB*1e3)*T/((viscB*1e3)*(1e6*MA/rhoA)**0.6)

DV_Wilke_Lee ¤

DV_Wilke_Lee(
    T: float,
    P: float,
    MA: float,
    MB: float,
    rhoA: float,
    rhoB: float | None,
    TA: float,
    TB: float | None,
) -> float

Estimate the mutual diffusion coefficient of a binary gas mixture, \(D_{AB}\), using the Wilke-Lee method.

Note

If air is one of the components of the mixture, arguments TB and rhoB should both be set to None.

References

  • RC Reid, JM Prausniz, and BE Poling. The properties of gases & liquids 4th edition, 1986, p. 587.
PARAMETER DESCRIPTION
T

Temperature. Unit = K.

TYPE: float

P

Pressure. Unit = Pa.

TYPE: float

MA

Molar mass of component A. Unit = kg/mol.

TYPE: float

MA

Molar mass of component B. Unit = kg/mol.

TYPE: float

rhoA

Density of component A at the normal boiling point. Unit = kg/m³.

TYPE: float

rhoB

Density of component B at the normal boiling point. If None, air is assumeed to be the component B. Unit = kg/m³.

TYPE: float | None

TA

Normal boiling temperature of component A. Unit = K.

TYPE: float

TB

Normal boiling temperature of component B. If None, air is assumeed to be the component B. Unit = K.

TYPE: float | None

RETURNS DESCRIPTION
float

Binary diffusion coefficient. Unit = m²/s.

Examples:

Estimate the diffusion coefficient of vinyl chloride through water vapor.

>>> from polykin.properties.diffusion import DV_Wilke_Lee
>>> D = DV_Wilke_Lee(
...     T=298.,       # temperature
...     P=1e5,        # pressure
...     MA=62.5e-3,   # molar mass of vinyl chloride
...     MB=18.0e-3,   # molar mass of water
...     rhoA=910.,    # density of vinyl chloride at the normal boiling point
...     rhoB=959.,    # density of water at the normal boiling point
...     TA=260.,      # normal boiling point of vinyl chloride
...     TB=373.,      # normal boiling point of water
...     )
>>> print(f"{D:.2e} m²/s")
1.10e-05 m²/s

Estimate the diffusion coefficient of vinyl chloride through air.

>>> from polykin.properties.diffusion import DV_Wilke_Lee
>>> D = DV_Wilke_Lee(
...     T=298.,       # temperature
...     P=1e5,        # pressure
...     MA=62.5e-3,   # molar mass of vinyl chloride
...     MB=18.0e-3,   # molar mass of water
...     rhoA=910.,    # density of vinyl chloride at the normal boiling point
...     rhoB=None,    # air
...     TA=260.,      # normal boiling point of vinyl chloride
...     TB=None,      # air
...     )
>>> print(f"{D:.2e} m²/s")
1.37e-05 m²/s
Source code in src/polykin/properties/diffusion/vapor.py
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 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
def DV_Wilke_Lee(T: float,
                 P: float,
                 MA: float,
                 MB: float,
                 rhoA: float,
                 rhoB: float | None,
                 TA: float,
                 TB: float | None
                 ) -> float:
    r"""Estimate the mutual diffusion coefficient of a binary gas mixture,
    $D_{AB}$, using the Wilke-Lee method.

    !!! note
        If air is one of the components of the mixture, arguments `TB` and
        `rhoB` should both be set to `None`.

    **References**

    *   RC Reid, JM Prausniz, and BE Poling. The properties of gases & liquids
        4th edition, 1986, p. 587.

    Parameters
    ----------
    T : float
        Temperature. Unit = K.
    P : float
        Pressure. Unit = Pa.
    MA : float
        Molar mass of component A. Unit = kg/mol.
    MA : float
        Molar mass of component B. Unit = kg/mol.
    rhoA : float
        Density of component A at the normal boiling point. Unit = kg/m³.
    rhoB : float | None
        Density of component B at the normal boiling point. If `None`,
        air is assumeed to be the component B. Unit = kg/m³.
    TA : float
        Normal boiling temperature of component A. Unit = K.
    TB : float | None
        Normal boiling temperature of component B. If `None`, air is assumeed
        to be the component B. Unit = K.

    Returns
    -------
    float
        Binary diffusion coefficient. Unit = m²/s.

    Examples
    --------
    Estimate the diffusion coefficient of vinyl chloride through water vapor.

    >>> from polykin.properties.diffusion import DV_Wilke_Lee
    >>> D = DV_Wilke_Lee(
    ...     T=298.,       # temperature
    ...     P=1e5,        # pressure
    ...     MA=62.5e-3,   # molar mass of vinyl chloride
    ...     MB=18.0e-3,   # molar mass of water
    ...     rhoA=910.,    # density of vinyl chloride at the normal boiling point
    ...     rhoB=959.,    # density of water at the normal boiling point
    ...     TA=260.,      # normal boiling point of vinyl chloride
    ...     TB=373.,      # normal boiling point of water
    ...     )
    >>> print(f"{D:.2e} m²/s")
    1.10e-05 m²/s

    Estimate the diffusion coefficient of vinyl chloride through air.

    >>> from polykin.properties.diffusion import DV_Wilke_Lee
    >>> D = DV_Wilke_Lee(
    ...     T=298.,       # temperature
    ...     P=1e5,        # pressure
    ...     MA=62.5e-3,   # molar mass of vinyl chloride
    ...     MB=18.0e-3,   # molar mass of water
    ...     rhoA=910.,    # density of vinyl chloride at the normal boiling point
    ...     rhoB=None,    # air
    ...     TA=260.,      # normal boiling point of vinyl chloride
    ...     TB=None,      # air
    ...     )
    >>> print(f"{D:.2e} m²/s")
    1.37e-05 m²/s
    """

    MAB = 1e3*2/(1/MA + 1/MB)

    # ϵ_AB and σ_AB
    eA = 1.15*TA
    sA = 1.18*(1e6*MA/rhoA)**(1/3)
    if rhoB is None and TB is None:
        # values for air
        sB = 3.62
        eB = 97.
    elif rhoB is not None and TB is not None:
        sB = 1.18*(1e6*MB/rhoB)**(1/3)
        eB = 1.15*TB
    else:
        raise ValueError(
            "Invalid input. `rhoB` and `TB` must both be None or floats.")

    eAB = sqrt(eA*eB)
    sAB = (sA + sB)/2

    # Ω_D
    Ts = T/eAB
    A = 1.06036
    B = 0.15610
    C = 0.19300
    D = 0.47635
    E = 1.03587
    F = 1.52996
    G = 1.76474
    H = 3.89411
    omegaD = A/Ts**B + C/exp(D*Ts) + E/exp(F*Ts) + G/exp(H*Ts)

    return 1e-2*(3.03 - 0.98/sqrt(MAB))*T**1.5 / (P*sqrt(MAB)*sAB**2*omegaD)

VrentasDudaBinary ¤

Vrentas-Duda free volume model for the diffusivity of binary polymer solutions.

The solvent self-diffusion coefficient is given by:

\[ D_1 = D_0 e^{\left(-\frac{E}{RT}\right)} \exp\left[-\frac{\gamma (w_1\hat{V}_1^* + w_2 \xi \hat{V}_2^*)} {w_1 K_{11}(K_{21}-T_{g1}+T) + w_2 K_{12}(K_{22}-T_{g2}+T)}\right] \]

and the mutual diffusion coefficient is given by:

\[ D = D_1 (1 - w_1)^2 (1 - 2\chi w_1) \]

where \(D_0\) is the pre-exponential factor, \(E\) is the activation energy required to overcome the atractive forces between neighboring molecules, \(K_{ij}\) are free-volume parameters, \(T\) is the temperature, \(T_{gi}\) is the glass-transition temperature of component \(i\), \(\hat{V}_i^*\) is the specific volume of component \(i\) at 0 kelvin, \(w_i\) is the mass fraction of compoenent \(i\), \(\gamma\) is the overlap factor, \(\xi\) is the ratio between the critical volume of the polymer and the solvent jumping units, and \(\chi\) is the Flory-Huggins' interaction parameter.

References

  • Vrentas, J.S. and Duda, J.L. (1977), J. Polym. Sci. Polym. Phys. Ed., 15: 403-416.
PARAMETER DESCRIPTION
D0

Pre-exponential factor. Unit = L²/T.

TYPE: float

E

Activation energy required to overcome the atractive forces between neighboring molecules. Units = J/mol/K.

TYPE: float

v1star

Specific volume of solvent at 0 K. Unit = L³/M.

TYPE: float

v2star

Specific volume of polymer at 0 K. Unit = L³/M.

TYPE: float

z

Ratio between the critical volume of the polymer and the solvent jumping units, \(\xi\).

TYPE: float

K11

Free-volume parameter of solvent. Unit = L³/M/K.

TYPE: float

K12

Free-volume parameter of polymer. Unit = L³/M/K.

TYPE: float

K21

Free-volume parameter of solvent. Unit = K.

TYPE: float

K22

Free-volume parameter of polymer. Unit = K.

TYPE: float

Tg1

Glas-transition temperature of solvent. Unit = K.

TYPE: float DEFAULT: 0.0

Tg2

Glas-transition temperature of polymer. Unit = K.

TYPE: float DEFAULT: 0.0

y

Overlap factor, \(\gamma\).

TYPE: float DEFAULT: 1.0

X

Flory-Huggings interaction parameter, \(\chi\).

TYPE: float DEFAULT: 0.5

unit

Unit of diffusivity, by definition equal to L²/T.

TYPE: str DEFAULT: 'm²/s'

name

Name.

TYPE: str DEFAULT: ''

Examples:

Estimate the mutual and self-diffusion coefficient of toluene in polyvinylacetate at 20 wt% toluene and 25°C.

>>> from polykin.properties.diffusion import VrentasDudaBinary
>>> d = VrentasDudaBinary(
...     D0=4.82e-4, E=0., v1star=0.917, v2star=0.728, z=0.82,
...     K11=1.45e-3, K12=4.33e-4, K21=-86.32, K22=-258.2, X=0.5,
...     unit='cm²/s',
...     name='Tol(1)/PVAc(2)')
>>> D = d(0.2, 25., Tunit='C')
>>> print(f"D = {D:.2e} {d.unit}")
D = 3.79e-08 cm²/s
>>> D1 = d(0.2, 25., Tunit='C', selfd=True)
>>> print(f"D1 = {D1:.2e} {d.unit}")
D1 = 7.40e-08 cm²/s
Source code in src/polykin/properties/diffusion/vrentasduda.py
 25
 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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
class VrentasDudaBinary():
    r"""Vrentas-Duda free volume model for the diffusivity of binary polymer
    solutions.

    The solvent self-diffusion coefficient is given by:

    $$ D_1 = D_0 e^{\left(-\frac{E}{RT}\right)}
       \exp\left[-\frac{\gamma (w_1\hat{V}_1^* + w_2 \xi \hat{V}_2^*)}
       {w_1 K_{11}(K_{21}-T_{g1}+T) + w_2 K_{12}(K_{22}-T_{g2}+T)}\right] $$

    and the mutual diffusion coefficient is given by:

    $$ D = D_1 (1 - w_1)^2 (1 - 2\chi w_1) $$

    where $D_0$ is the pre-exponential factor,
    $E$ is the activation energy required to overcome the atractive forces
    between neighboring molecules,
    $K_{ij}$ are free-volume parameters,
    $T$ is the temperature,
    $T_{gi}$ is the glass-transition temperature of component $i$,
    $\hat{V}_i^*$ is the specific volume of component $i$ at 0 kelvin,
    $w_i$ is the mass fraction of compoenent $i$,
    $\gamma$ is the overlap factor,
    $\xi$ is the ratio between the critical volume of the polymer and the
    solvent jumping units,
    and $\chi$ is the Flory-Huggins' interaction parameter.

    **References**

    *   Vrentas, J.S. and Duda, J.L. (1977), J. Polym. Sci. Polym. Phys. Ed.,
        15: 403-416.

    Parameters
    ----------
    D0 : float
        Pre-exponential factor.
        Unit = L²/T.
    E : float
        Activation energy required to overcome the atractive forces
        between neighboring molecules.
        Units = J/mol/K.
    v1star : float
        Specific volume of solvent at 0 K.
        Unit = L³/M.
    v2star : float
        Specific volume of polymer at 0 K.
        Unit = L³/M.
    z : float
        Ratio between the critical volume of the polymer and the
        solvent jumping units, $\xi$.
    K11 : float
        Free-volume parameter of solvent.
        Unit = L³/M/K.
    K12 : float
        Free-volume parameter of polymer.
        Unit = L³/M/K.
    K21 : float
        Free-volume parameter of solvent.
        Unit = K.
    K22 : float
        Free-volume parameter of polymer.
        Unit = K.
    Tg1 : float
        Glas-transition temperature of solvent.
        Unit = K.
    Tg2 : float
        Glas-transition temperature of polymer.
        Unit = K.
    y : float
        Overlap factor, $\gamma$.
    X : float
        Flory-Huggings interaction parameter, $\chi$.
    unit : str
        Unit of diffusivity, by definition equal to L²/T.
    name : str
        Name.

    Examples
    --------
    Estimate the mutual and self-diffusion coefficient of toluene in
    polyvinylacetate at 20 wt% toluene and 25°C.

    >>> from polykin.properties.diffusion import VrentasDudaBinary
    >>> d = VrentasDudaBinary(
    ...     D0=4.82e-4, E=0., v1star=0.917, v2star=0.728, z=0.82,
    ...     K11=1.45e-3, K12=4.33e-4, K21=-86.32, K22=-258.2, X=0.5,
    ...     unit='cm²/s',
    ...     name='Tol(1)/PVAc(2)')

    >>> D = d(0.2, 25., Tunit='C')
    >>> print(f"D = {D:.2e} {d.unit}")
    D = 3.79e-08 cm²/s

    >>> D1 = d(0.2, 25., Tunit='C', selfd=True)
    >>> print(f"D1 = {D1:.2e} {d.unit}")
    D1 = 7.40e-08 cm²/s

    """  # noqa: E501

    D0: float
    E: float
    v1star: float
    v2star: float
    z: float
    K11: float
    K12: float
    K21: float
    K22: float
    Tg1: float
    Tg2: float
    y: float
    X: float
    unit: str

    def __init__(self,
                 D0: float,
                 E: float,
                 v1star: float,
                 v2star: float,
                 z: float,
                 K11: float,
                 K12: float,
                 K21: float,
                 K22: float,
                 Tg1: float = 0.,
                 Tg2: float = 0.,
                 y: float = 1.,
                 X: float = 0.5,
                 unit: str = 'm²/s',
                 name: str = ''
                 ) -> None:

        check_bounds(D0, 0., np.inf, 'D0')
        check_bounds(E, 0., np.inf, 'E')
        check_bounds(v1star, 0., np.inf, 'v1star')
        check_bounds(v2star, 0., np.inf, 'v2star')
        check_bounds(z, 0., np.inf, 'z')
        check_bounds(K11, 0., np.inf, 'K11')
        check_bounds(K12, 0., np.inf, 'K12')
        check_bounds(K21, -np.inf, np.inf, 'K21')
        check_bounds(K22, -np.inf, np.inf, 'K22')
        check_bounds(Tg1, 0., np.inf, 'Tg1')
        check_bounds(Tg2, 0., np.inf, 'Tg2')
        check_bounds(y, 0.5, 1., 'y')
        check_bounds(X, -10, 10, 'X')

        self.D0 = D0
        self.E = E
        self.v1star = v1star
        self.v2star = v2star
        self.z = z
        self.K11 = K11
        self.K12 = K12
        self.K21 = K21
        self.K22 = K22
        self.Tg1 = Tg1
        self.Tg2 = Tg2
        self.y = y
        self.X = X
        self.unit = unit
        self.name = name

    def __repr__(self) -> str:
        return (
            f"name: {self.name}\n"
            f"unit: {self.unit}\n"
            f"D0:   {self.D0}\n"
            f"E:    {self.E}\n"
            f"v1*:  {self.v1star}\n"
            f"v2*:  {self.v2star}\n"
            f"ξ:    {self.z}\n"
            f"K11:  {self.K11}\n"
            f"K12:  {self.K12}\n"
            f"K21:  {self.K21}\n"
            f"K22:  {self.K22}\n"
            f"Tg1:  {self.Tg1}\n"
            f"Tg2:  {self.Tg2}\n"
            f"𝛾:    {self.y}\n"
            f"𝜒:    {self.X}"
        )

    def __call__(self,
                 w1: Union[float, FloatArrayLike],
                 T: Union[float, FloatArrayLike],
                 Tunit: Literal['C', 'K'] = 'K',
                 selfd: bool = False
                 ) -> Union[float, FloatArray]:
        r"""Evaluate solvent self-diffusion, $D_1$, or mutual diffusion
        coefficient, $D$, at given solvent content and temperature, including
        unit conversion and range check.

        Parameters
        ----------
        w1 : float | FloatArrayLike
            Mass fraction of solvent.
            Unit = kg/kg.
        T : float | FloatArrayLike
            Temperature.
            Unit = `Tunit`.
        Tunit : Literal['C', 'K']
            Temperature unit.
        selfd: bool
            Switch result between mutual diffusion coefficient (if `False`) and
            self-diffusion coefficient (if `True`).

        Returns
        -------
        float | FloatArray
            Solvent self-diffusion or mutual diffusion coefficient.
        """
        if isinstance(w1, (list, tuple)):
            w1 = np.array(w1, dtype=np.float64)

        check_bounds(w1, 0., 1., 'w1')

        TK = convert_check_temperature(T, Tunit)
        if selfd:
            return self.selfd(w1, TK)
        else:
            return self.mutual(w1, TK)

    def selfd(self,
              w1: Union[float, FloatArray],
              T: Union[float, FloatArray]
              ) -> Union[float, FloatArray]:
        r"""Evaluate solvent self-diffusion coefficient, $D_1$, at given SI
        conditions, without unit conversions or checks.

        Parameters
        ----------
        w1 : float | FloatArray
            Mass fraction of solvent.
            Unit = kg/kg.
        T : float | FloatArray
            Temperature.
            Unit = K.

        Returns
        -------
        float | FloatArray
            Solvent self-diffusion coefficient, $D_1$.
        """

        D0 = self.D0
        E = self.E
        V1star = self.v1star
        V2star = self.v2star
        z = self.z
        K11 = self.K11
        K12 = self.K12
        K21 = self.K21
        K22 = self.K22
        Tg1 = self.Tg1
        Tg2 = self.Tg2
        y = self.y

        w2 = 1 - w1
        D1 = D0*exp(-E/(Rgas*T)) * \
            exp(-(w1*V1star + w2*z*V2star) /
                (w1*(K11/y)*(K21 - Tg1 + T) + w2*(K12/y)*(K22 - Tg2 + T)))
        return D1

    def mutual(self,
               w1: Union[float, FloatArray],
               T: Union[float, FloatArray]
               ) -> Union[float, FloatArray]:
        r"""Evaluate mutual diffusion coefficient, $D$, at given SI conditions,
        without unit conversions or checks.

        Parameters
        ----------
        w1 : float | FloatArray
            Mass fraction of solvent.
            Unit = kg/kg.
        T : float | FloatArray
            Temperature.
            Unit = K.

        Returns
        -------
        float | FloatArray
            Mutual diffusion coefficient, $D$.
        """
        D1 = self.selfd(w1, T)
        X = self.X
        D = D1 * (1 - w1)**2 * (1 - 2*X*w1)
        return D

    def plot(self,
             T: Union[float, FloatArrayLike],
             w1range: tuple[float, float] = (0., 0.5),
             Tunit: Literal['C', 'K'] = 'K',
             selfd: bool = False,
             title: Optional[str] = None,
             ylim: Optional[tuple[float, float]] = None,
             axes: Optional[Axes] = None,
             return_objects: bool = False
             ) -> Optional[tuple[Optional[Figure], Axes]]:
        """Plot the mutual or self-diffusion coefficient as a function of
        solvent content and temperature.

        Parameters
        ----------
        T : float | FloatArrayLike
            Temperature.
            Unit = `Tunit`.
        w1range : tuple[float, float]
            Range of solvent mass fraction to be ploted.
            Unit = kg/kg.
        Tunit : Literal['C', 'K']
            Temperature unit.
        selfd: bool
            Switch result between mutual diffusion coefficient (if `False`) and
            self-diffusion coefficient (if `True`).
        title : str | None
            Title of plot. If `None`, the object name will be used.
        ylim : tuple[float, float] | None
            User-defined limit of y-axis. If `None`, the default settings of
            matplotlib are used.
        axes : Axes | None
            Matplotlib Axes object.
        return_objects : bool
            If `True`, the Figure and Axes objects are returned (for saving or
            further manipulations).

        Returns
        -------
        tuple[Figure | None, Axes] | None
            Figure and Axes objects if return_objects is `True`.
        """

        # Check inputs
        check_in_set(Tunit, {'K', 'C'}, 'Tunit')
        check_valid_range(w1range, 0., 1., 'w1range')

        # Plot objects
        if axes is None:
            fig, ax = plt.subplots()
            if title is None:
                title = self.name
            if title:
                fig.suptitle(title)
        else:
            fig = None
            ax = axes

        Tsymbol = Tunit
        if Tunit == 'C':
            Tsymbol = '°C'
        if not isinstance(T, Iterable):
            T = [T]

        w1 = np.linspace(*w1range, 100)
        for Ti in T:
            y = self.__call__(w1, Ti, Tunit, selfd)
            ax.semilogy(w1, y, label=f"{Ti}{Tsymbol}")
        if ylim:
            ax.set_ylim(*ylim)
        ax.set_xlabel("$w_1$ [kg/kg]")
        if selfd:
            Dsymbol = "$D_1$"
        else:
            Dsymbol = "$D$"
        ax.set_ylabel(Dsymbol + f" [{self.unit}]")
        ax.grid(True)
        ax.legend(bbox_to_anchor=(1.05, 1.0), loc="upper left")

        if return_objects:
            return (fig, ax)

    def fit(self):
        return NotImplemented

__call__ ¤

__call__(
    w1: Union[float, FloatArrayLike],
    T: Union[float, FloatArrayLike],
    Tunit: Literal["C", "K"] = "K",
    selfd: bool = False,
) -> Union[float, FloatArray]

Evaluate solvent self-diffusion, \(D_1\), or mutual diffusion coefficient, \(D\), at given solvent content and temperature, including unit conversion and range check.

PARAMETER DESCRIPTION
w1

Mass fraction of solvent. Unit = kg/kg.

TYPE: float | FloatArrayLike

T

Temperature. Unit = Tunit.

TYPE: float | FloatArrayLike

Tunit

Temperature unit.

TYPE: Literal['C', 'K'] DEFAULT: 'K'

selfd

Switch result between mutual diffusion coefficient (if False) and self-diffusion coefficient (if True).

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
float | FloatArray

Solvent self-diffusion or mutual diffusion coefficient.

Source code in src/polykin/properties/diffusion/vrentasduda.py
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
def __call__(self,
             w1: Union[float, FloatArrayLike],
             T: Union[float, FloatArrayLike],
             Tunit: Literal['C', 'K'] = 'K',
             selfd: bool = False
             ) -> Union[float, FloatArray]:
    r"""Evaluate solvent self-diffusion, $D_1$, or mutual diffusion
    coefficient, $D$, at given solvent content and temperature, including
    unit conversion and range check.

    Parameters
    ----------
    w1 : float | FloatArrayLike
        Mass fraction of solvent.
        Unit = kg/kg.
    T : float | FloatArrayLike
        Temperature.
        Unit = `Tunit`.
    Tunit : Literal['C', 'K']
        Temperature unit.
    selfd: bool
        Switch result between mutual diffusion coefficient (if `False`) and
        self-diffusion coefficient (if `True`).

    Returns
    -------
    float | FloatArray
        Solvent self-diffusion or mutual diffusion coefficient.
    """
    if isinstance(w1, (list, tuple)):
        w1 = np.array(w1, dtype=np.float64)

    check_bounds(w1, 0., 1., 'w1')

    TK = convert_check_temperature(T, Tunit)
    if selfd:
        return self.selfd(w1, TK)
    else:
        return self.mutual(w1, TK)

mutual ¤

mutual(
    w1: Union[float, FloatArray],
    T: Union[float, FloatArray],
) -> Union[float, FloatArray]

Evaluate mutual diffusion coefficient, \(D\), at given SI conditions, without unit conversions or checks.

PARAMETER DESCRIPTION
w1

Mass fraction of solvent. Unit = kg/kg.

TYPE: float | FloatArray

T

Temperature. Unit = K.

TYPE: float | FloatArray

RETURNS DESCRIPTION
float | FloatArray

Mutual diffusion coefficient, \(D\).

Source code in src/polykin/properties/diffusion/vrentasduda.py
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
def mutual(self,
           w1: Union[float, FloatArray],
           T: Union[float, FloatArray]
           ) -> Union[float, FloatArray]:
    r"""Evaluate mutual diffusion coefficient, $D$, at given SI conditions,
    without unit conversions or checks.

    Parameters
    ----------
    w1 : float | FloatArray
        Mass fraction of solvent.
        Unit = kg/kg.
    T : float | FloatArray
        Temperature.
        Unit = K.

    Returns
    -------
    float | FloatArray
        Mutual diffusion coefficient, $D$.
    """
    D1 = self.selfd(w1, T)
    X = self.X
    D = D1 * (1 - w1)**2 * (1 - 2*X*w1)
    return D

plot ¤

plot(
    T: Union[float, FloatArrayLike],
    w1range: tuple[float, float] = (0.0, 0.5),
    Tunit: Literal["C", "K"] = "K",
    selfd: bool = False,
    title: Optional[str] = None,
    ylim: Optional[tuple[float, float]] = None,
    axes: Optional[Axes] = None,
    return_objects: bool = False,
) -> Optional[tuple[Optional[Figure], Axes]]

Plot the mutual or self-diffusion coefficient as a function of solvent content and temperature.

PARAMETER DESCRIPTION
T

Temperature. Unit = Tunit.

TYPE: float | FloatArrayLike

w1range

Range of solvent mass fraction to be ploted. Unit = kg/kg.

TYPE: tuple[float, float] DEFAULT: (0.0, 0.5)

Tunit

Temperature unit.

TYPE: Literal['C', 'K'] DEFAULT: 'K'

selfd

Switch result between mutual diffusion coefficient (if False) and self-diffusion coefficient (if True).

TYPE: bool DEFAULT: False

title

Title of plot. If None, the object name will be used.

TYPE: str | None DEFAULT: None

ylim

User-defined limit of y-axis. If None, the default settings of matplotlib are used.

TYPE: tuple[float, float] | None DEFAULT: None

axes

Matplotlib Axes object.

TYPE: Axes | None DEFAULT: None

return_objects

If True, the Figure and Axes objects are returned (for saving or further manipulations).

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
tuple[Figure | None, Axes] | None

Figure and Axes objects if return_objects is True.

Source code in src/polykin/properties/diffusion/vrentasduda.py
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
def plot(self,
         T: Union[float, FloatArrayLike],
         w1range: tuple[float, float] = (0., 0.5),
         Tunit: Literal['C', 'K'] = 'K',
         selfd: bool = False,
         title: Optional[str] = None,
         ylim: Optional[tuple[float, float]] = None,
         axes: Optional[Axes] = None,
         return_objects: bool = False
         ) -> Optional[tuple[Optional[Figure], Axes]]:
    """Plot the mutual or self-diffusion coefficient as a function of
    solvent content and temperature.

    Parameters
    ----------
    T : float | FloatArrayLike
        Temperature.
        Unit = `Tunit`.
    w1range : tuple[float, float]
        Range of solvent mass fraction to be ploted.
        Unit = kg/kg.
    Tunit : Literal['C', 'K']
        Temperature unit.
    selfd: bool
        Switch result between mutual diffusion coefficient (if `False`) and
        self-diffusion coefficient (if `True`).
    title : str | None
        Title of plot. If `None`, the object name will be used.
    ylim : tuple[float, float] | None
        User-defined limit of y-axis. If `None`, the default settings of
        matplotlib are used.
    axes : Axes | None
        Matplotlib Axes object.
    return_objects : bool
        If `True`, the Figure and Axes objects are returned (for saving or
        further manipulations).

    Returns
    -------
    tuple[Figure | None, Axes] | None
        Figure and Axes objects if return_objects is `True`.
    """

    # Check inputs
    check_in_set(Tunit, {'K', 'C'}, 'Tunit')
    check_valid_range(w1range, 0., 1., 'w1range')

    # Plot objects
    if axes is None:
        fig, ax = plt.subplots()
        if title is None:
            title = self.name
        if title:
            fig.suptitle(title)
    else:
        fig = None
        ax = axes

    Tsymbol = Tunit
    if Tunit == 'C':
        Tsymbol = '°C'
    if not isinstance(T, Iterable):
        T = [T]

    w1 = np.linspace(*w1range, 100)
    for Ti in T:
        y = self.__call__(w1, Ti, Tunit, selfd)
        ax.semilogy(w1, y, label=f"{Ti}{Tsymbol}")
    if ylim:
        ax.set_ylim(*ylim)
    ax.set_xlabel("$w_1$ [kg/kg]")
    if selfd:
        Dsymbol = "$D_1$"
    else:
        Dsymbol = "$D$"
    ax.set_ylabel(Dsymbol + f" [{self.unit}]")
    ax.grid(True)
    ax.legend(bbox_to_anchor=(1.05, 1.0), loc="upper left")

    if return_objects:
        return (fig, ax)

selfd ¤

selfd(
    w1: Union[float, FloatArray],
    T: Union[float, FloatArray],
) -> Union[float, FloatArray]

Evaluate solvent self-diffusion coefficient, \(D_1\), at given SI conditions, without unit conversions or checks.

PARAMETER DESCRIPTION
w1

Mass fraction of solvent. Unit = kg/kg.

TYPE: float | FloatArray

T

Temperature. Unit = K.

TYPE: float | FloatArray

RETURNS DESCRIPTION
float | FloatArray

Solvent self-diffusion coefficient, \(D_1\).

Source code in src/polykin/properties/diffusion/vrentasduda.py
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
def selfd(self,
          w1: Union[float, FloatArray],
          T: Union[float, FloatArray]
          ) -> Union[float, FloatArray]:
    r"""Evaluate solvent self-diffusion coefficient, $D_1$, at given SI
    conditions, without unit conversions or checks.

    Parameters
    ----------
    w1 : float | FloatArray
        Mass fraction of solvent.
        Unit = kg/kg.
    T : float | FloatArray
        Temperature.
        Unit = K.

    Returns
    -------
    float | FloatArray
        Solvent self-diffusion coefficient, $D_1$.
    """

    D0 = self.D0
    E = self.E
    V1star = self.v1star
    V2star = self.v2star
    z = self.z
    K11 = self.K11
    K12 = self.K12
    K21 = self.K21
    K22 = self.K22
    Tg1 = self.Tg1
    Tg2 = self.Tg2
    y = self.y

    w2 = 1 - w1
    D1 = D0*exp(-E/(Rgas*T)) * \
        exp(-(w1*V1star + w2*z*V2star) /
            (w1*(K11/y)*(K21 - Tg1 + T) + w2*(K12/y)*(K22 - Tg2 + T)))
    return D1

Tutorial