Ziegler-Natta stereocontrol: isotactic vs. atactic polypropylene#

Natta’s Ziegler-type catalysts insert each propylene with the same orientation, giving isotactic polypropylene (every methyl on the same side, nearly all meso dyads), whereas free-radical placement is close to random (atactic). With meso-placement probability \(P_m\) (Bernoullian statistics), the NMR-observable triad fractions are \([mm]=P_m^2\), \([mr]=2P_m(1-P_m)\), \([rr]=(1-P_m)^2\) (bernoullian_triad_fractions()), and isotactic runs average \(1/(1-P_m)\) dyads (mean_isotactic_run_length()). Seeded dyad sequences (sample_dyad_sequence()) make the difference visible.

import matplotlib.pyplot as plt
import numpy as np

from chemistrykit.polymer.systems.tacticity import (
    bernoullian_triad_fractions,
    mean_isotactic_run_length,
    sample_dyad_sequence,
)

catalysts = {"free radical (atactic)": 0.5, "Ziegler-Natta (isotactic)": 0.98}
for label, Pm in catalysts.items():
    mm, mr, rr = bernoullian_triad_fractions(Pm)
    s = sample_dyad_sequence(100000, Pm, rng=1)
    mm_sim = np.mean(s[:-1] & s[1:])
    run = mean_isotactic_run_length(Pm)
    print(f"{label:28s} Pm={Pm:.2f}: [mm]={mm:.3f} (sampled {mm_sim:.3f}), [mr]={mr:.3f}, [rr]={rr:.3f}, mean isotactic run = {run:.0f} dyads")
free radical (atactic)       Pm=0.50: [mm]=0.250 (sampled 0.251), [mr]=0.500, [rr]=0.250, mean isotactic run = 2 dyads
Ziegler-Natta (isotactic)    Pm=0.98: [mm]=0.960 (sampled 0.961), [mr]=0.039, [rr]=0.000, mean isotactic run = 50 dyads
fig, axes = plt.subplots(1, 2, figsize=(12, 4.2), gridspec_kw={"width_ratios": [1.3, 1]})
n = 60
for row, (label, Pm) in enumerate(catalysts.items()):
    meso = sample_dyad_sequence(n - 1, Pm, rng=row + 3)
    # side of each methyl: stays the same across a meso dyad, flips across racemo
    side = np.concatenate([[1], np.where(np.cumsum(~meso) % 2 == 0, 1, -1)])
    y0 = -3.0 * row
    axes[0].plot(np.arange(n), np.full(n, y0), "k-", lw=1)
    axes[0].vlines(np.arange(n), y0, y0 + 0.8 * side, color="steelblue" if row else "gray")
    axes[0].text(0, y0 + 1.3, label, fontsize=9)
axes[0].set_yticks([])
axes[0].set_xlabel("backbone position")
axes[0].set_title("Methyl side groups up/down along the chain")

Pm_grid = np.linspace(0, 1, 200)
mm, mr, rr = bernoullian_triad_fractions(Pm_grid)
axes[1].plot(Pm_grid, mm, label="[mm] isotactic")
axes[1].plot(Pm_grid, mr, label="[mr] heterotactic")
axes[1].plot(Pm_grid, rr, label="[rr] syndiotactic")
for Pm in catalysts.values():
    axes[1].axvline(Pm, color="gray", ls=":", lw=0.8)
axes[1].set_xlabel("meso placement probability $P_m$")
axes[1].set_ylabel("triad fraction")
axes[1].set_title("Bernoullian triad statistics")
axes[1].legend()
plt.tight_layout()
plt.show()
Methyl side groups up/down along the chain, Bernoullian triad statistics

Total running time of the script: (0 minutes 0.067 seconds)

Gallery generated by Sphinx-Gallery