Robert Elder commited on
Commit
ddaa121
·
1 Parent(s): f17905e

syncing 50% EtOH changes from master branch

Browse files
quantity_module/data/solvent-viscosity.xlsx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:967a90804b91a62ab8220affebd22eabdd459803340211ec3548618f5a0aba72
3
- size 18595
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:54dcc8e1abe242707b2039ff8735a7a986b28023cc23ef9a9e96f3aa5223b451
3
+ size 13816
quantity_module/functions.py CHANGED
@@ -21,6 +21,7 @@ N_sample = int(1e6)
21
 
22
  ## list of solvents to include, all semi-polar and non-polar solvents in ISO 10993-18:2020 Table D.1 (except DMSO, which is not used in practice)
23
  solvents = ['acetonitrile','methanol','acetone','ethanol','tetrahydrofuran','propanol','isopropanol','dichloromethane','toluene','cyclohexane','heptane','hexane']
 
24
 
25
  ## c distribution parameters
26
  T_cut = 20
@@ -68,23 +69,42 @@ else:
68
  df_final = pd.merge(df_final, df_desc[['Solute_InChIKey', 'Vabc', 'VMcGowan']], how='left', on='Solute_InChIKey', suffixes=('', '_dupe'))
69
 
70
  #### solvent-specific viscosity
71
- # add MW
72
- mws = []
73
- for solv in df_visc['Solvent_Name']:
74
- mw = chemicals.search_chemical(solv).MW
75
- mws.append(mw)
76
- df_visc['MW'] = mws
77
  ## selected solvent MWs
78
- Solvent_MWs = {solv:df_visc.loc[df_visc['Solvent_Name']==solv,'MW'].iloc[0] for solv in solvents}
 
79
  #Solvent_Densities = {solv:string2density(solv)[0] for solv in solvents} # can fail sometimes, so these are hardcoded for now
80
  #Solvent_Densities = {'ethanol': 0.79, 'isopropanol': 0.787515, 'acetonitrile': 0.78467, 'toluene': 0.86925, 'dichloromethane': 1.326875, 'hexane': 0.6602}
81
- Solvent_Densities = {'acetonitrile': 0.7847, 'methanol': 0.7955, 'acetone': 0.7893, 'ethanol': 0.7898, 'tetrahydrofuran': 0.8878, 'propanol': 0.8057, 'isopropanol': 0.787, 'dichloromethane': 1.3269, 'toluene': 0.8673, 'cyclohexane': 0.7793, 'heptane': 0.6808, 'hexane': 0.6599}
82
  # linear relation to estimate Vabc when it fails for a molecule
83
  Vabc = df_desc['Vabc']
84
  Vmcg = df_desc['VMcGowan']
85
  m = ~pd.isna(Vabc)
86
  popt_V = np.polyfit(Vmcg[m], Vabc[m], 1)
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  def get_WC(T,solv,V):
89
  params = df_visc[df_visc['Solvent_Name']==solv].iloc[0]
90
  if params['Equation'] == '10^A(1/T-1/B)':
@@ -103,9 +123,12 @@ def get_WC(T,solv,V):
103
  eta = params['A'] * 298.15/T
104
  elif params['Equation'] == 'A*T+B':
105
  eta = params['A'] * T + params['A']
 
 
 
106
  else:
107
  eta = np.nan
108
- D_WC = 7.4e-8*(params['MW']*params['WC_assoc_param'])**0.5*(T)/eta/V**0.6
109
  return D_WC, eta, params['MW']
110
 
111
  #### add Wilke-Chang
 
21
 
22
  ## list of solvents to include, all semi-polar and non-polar solvents in ISO 10993-18:2020 Table D.1 (except DMSO, which is not used in practice)
23
  solvents = ['acetonitrile','methanol','acetone','ethanol','tetrahydrofuran','propanol','isopropanol','dichloromethane','toluene','cyclohexane','heptane','hexane']
24
+ #solvents = ['acetonitrile','methanol','acetone','ethanol','50% ethanol','tetrahydrofuran','propanol','isopropanol','dichloromethane','toluene','cyclohexane','heptane','hexane']
25
 
26
  ## c distribution parameters
27
  T_cut = 20
 
69
  df_final = pd.merge(df_final, df_desc[['Solute_InChIKey', 'Vabc', 'VMcGowan']], how='left', on='Solute_InChIKey', suffixes=('', '_dupe'))
70
 
71
  #### solvent-specific viscosity
72
+ # add MW -- already in the spreadsheet
73
+ #mws = []
74
+ #for solv in df_visc['Solvent_Name']:
75
+ # mw = chemicals.search_chemical(solv).MW
76
+ # mws.append(mw)
77
+ #df_visc['MW'] = mws
78
  ## selected solvent MWs
79
+ #Solvent_MWs = {solv:df_visc.loc[df_visc['Solvent_Name']==solv,'MW'].iloc[0] for solv in solvents}
80
+ Solvent_MWs = dict(df_visc[['Solvent_Name','MW']].itertuples(index=False))
81
  #Solvent_Densities = {solv:string2density(solv)[0] for solv in solvents} # can fail sometimes, so these are hardcoded for now
82
  #Solvent_Densities = {'ethanol': 0.79, 'isopropanol': 0.787515, 'acetonitrile': 0.78467, 'toluene': 0.86925, 'dichloromethane': 1.326875, 'hexane': 0.6602}
83
+ Solvent_Densities = {'acetonitrile': 0.7847, 'methanol': 0.7955, 'acetone': 0.7893, 'ethanol': 0.7898, '50% ethanol': (0.7898+1)/2, 'tetrahydrofuran': 0.8878, 'propanol': 0.8057, 'isopropanol': 0.787, 'dichloromethane': 1.3269, 'toluene': 0.8673, 'cyclohexane': 0.7793, 'heptane': 0.6808, 'hexane': 0.6599}
84
  # linear relation to estimate Vabc when it fails for a molecule
85
  Vabc = df_desc['Vabc']
86
  Vmcg = df_desc['VMcGowan']
87
  m = ~pd.isna(Vabc)
88
  popt_V = np.polyfit(Vmcg[m], Vabc[m], 1)
89
 
90
+ # ---- model: Grunberg–Nissan style with polynomial interaction that vanishes at x=0,1 ----
91
+ # fitted to data from R. Belda, J. V. Herráez, O. Diez, Rheological study and thermodynamic analysis of the binary system (water/ethanol): Influence of concentration. Physics and Chemistry of Liquids 42, 467-479 (2004).
92
+ popt_etoh = np.array([-6.35036532e+00, 1.86507282e+03, -5.30902320e+00, 1.60463200e+03, -1.03040657e+01, 3.05646061e+00, -4.93824317e+00, 4.16274239e+03, -1.18411097e+03, 1.69557649e+03])
93
+ def predict_lneta(p, T, x, n_poly=3, interaction_has_T=True):
94
+ Aw, Bw, Ae, Be = p[:4] # ln(eta_w)=Aw+Bw/T, ln(eta_e)=Ae+Be/T
95
+ ln_eta_w = Aw + Bw / T
96
+ ln_eta_e = Ae + Be / T
97
+ xc = 2.0*x - 1.0 # map wt frac [0,1] -> [-1,1]
98
+ Phi = np.vstack([xc**k for k in range(n_poly)]) # (n_poly, N)
99
+ if interaction_has_T:
100
+ a = p[4:4+n_poly]
101
+ b = p[4+n_poly:4+2*n_poly]
102
+ G = (a @ Phi) + (b @ Phi) / T
103
+ else:
104
+ a = p[4:4+n_poly]
105
+ G = (a @ Phi)
106
+ return x*ln_eta_e + (1-x)*ln_eta_w + x*(1-x)*G
107
+
108
  def get_WC(T,solv,V):
109
  params = df_visc[df_visc['Solvent_Name']==solv].iloc[0]
110
  if params['Equation'] == '10^A(1/T-1/B)':
 
123
  eta = params['A'] * 298.15/T
124
  elif params['Equation'] == 'A*T+B':
125
  eta = params['A'] * T + params['A']
126
+ elif params['Equation'] == 'fitted_EtOH':
127
+ # assuming 50% is by volume --> by mass for consistency with fitted model
128
+ eta = np.exp(predict_lneta(popt_etoh, T, 0.5*0.7898/(0.5*0.7898+0.5*1.000), n_poly=3, interaction_has_T=True))
129
  else:
130
  eta = np.nan
131
+ D_WC = 7.4e-8*(params['MW']*params['WC_assoc_param'])**0.5*T/eta/V**0.6
132
  return D_WC, eta, params['MW']
133
 
134
  #### add Wilke-Chang