From 01552030b164f7c344e2bbd2e6ac20e74e583c90 Mon Sep 17 00:00:00 2001 From: Violeta Karyofylli Date: Mon, 21 Mar 2022 16:39:13 -0500 Subject: [PATCH 01/32] Clean implementation of chemistry. --- Liu2014Properties.py | 55 ++++++++++++++++++++++++++++++++++++++------ chebSolver.py | 13 +++++++++-- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/Liu2014Properties.py b/Liu2014Properties.py index 5b30da9b2..ed925ea91 100644 --- a/Liu2014Properties.py +++ b/Liu2014Properties.py @@ -1,5 +1,5 @@ import numpy as np - +from scipy.interpolate import CubicSpline class Reaction(object): def __init__(self, *initial_data, **kwargs): @@ -158,14 +158,55 @@ def setLiu2014Properties(gam, inputV0, inputVDC, params, Nr): reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)"] + reactionExpressionTypelist = [True] + reactionsList = [] for i in range(Nr): - rxn = eval("lambda energy :" + reactionExpressionslist[i]) - rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) - - reaction = Reaction(rxnAlfa = params.alfa, rxnBeta = params.beta, - kf = rxn, kf_T = rxn_T) - reactionsList.append(reaction) + if reactionExpressionTypelist[i]: + Nsample = 72 + N300 = 200 + + rateCoeff = np.fromfile('./BOLSIGChemistry/reaction300K_%s.dat' %str(i)) + rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T + + Te = np.fromfile('./BOLSIGChemistry/reaction300K.Te.dat') + Te = np.reshape(Te,[Nsample, N300]).T + + Te[:,0] *= 1.5 + TeLog = np.log(Te[:, 0]) + + nonZeroIndex = np.nonzero(rateCoeff[:, 0]) + rateCoeffYLog = np.zeros(rateCoeff.shape[0]) + rateCoeffYLog[nonZeroIndex[0][0]:] = np.log(rateCoeff[nonZeroIndex[0][0]:, 0]) + rateCoeffYLog[0:nonZeroIndex[0][0]] = rateCoeffYLog[nonZeroIndex[0][0]] + rateCoeffYLog += - np.log(1.0/tau) + np.log(nAr) + + filtering = np.where(rateCoeffYLog Date: Wed, 23 Mar 2022 14:57:12 -0500 Subject: [PATCH 02/32] A new scenario should be included with only seven reactions. At the moment, scenario 2 is adjusted to incorporate this change. --- chebSolver.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/chebSolver.py b/chebSolver.py index 568596177..0a90085ea 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -294,9 +294,7 @@ def rxnRateCoefficient(self, energy, i): energy[indFix,0] = 1.0 if self.reactionsList[i].rxnBolsig: kf = np.exp(self.reactionsList[i].kf_log(np.log(energy))) - print(kf) else: - print(i) kf = self.reactionsList[i].kf(energy) kf[indFix,0] = 0 @@ -403,7 +401,7 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, elif(scenario==1): Nr = 1 elif(scenario==2): - Nr = 8 + Nr = 7 elif(scenario==3): Nr = 8 elif(scenario==4): @@ -1893,7 +1891,7 @@ def plot(self, col, create=True): # Default IC (overwritten below if we are restarting) #tds.U1[0:tds.Ns*tds.Np] = 1e-4 - tds.U1[0:(tds.Ns-1)*tds.Np] = 1e-4 # 'usual' species + tds.U1[0:(tds.Ns-1)*tds.Np] = 1e-1 # 'usual' species tds.U1[(tds.Ns-1)*tds.Np:tds.Ns*tds.Np] = 1.0 # background specie tds.U1[tds.Ns*tds.Np:] = tds.params.EeBC*tds.U1[0:tds.Np] # electron energy From beec14cbc00e1c91ce2e66f6b1e278a42953d60d Mon Sep 17 00:00:00 2001 From: Violeta Karyofylli Date: Wed, 23 Mar 2022 16:26:14 -0500 Subject: [PATCH 03/32] Scenario 0 and 1 should be checked once more. Scenario 2 seems to work well. --- Liu2014Properties.py | 32 +++++++ psaapProperties.py | 54 +++++++++-- psaapPropertiesTestArm.py | 187 +++++++++++++++++++++++++++++++++----- 3 files changed, 243 insertions(+), 30 deletions(-) diff --git a/Liu2014Properties.py b/Liu2014Properties.py index ed925ea91..93b63e262 100644 --- a/Liu2014Properties.py +++ b/Liu2014Properties.py @@ -1,5 +1,8 @@ import numpy as np from scipy.interpolate import CubicSpline +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors + class Reaction(object): def __init__(self, *initial_data, **kwargs): @@ -199,6 +202,35 @@ def setLiu2014Properties(gam, inputV0, inputVDC, params, Nr): kf_T_log = reactionTExpressionsLogFiltered) reactionsList.append(reaction) + # rxn = eval("lambda energy :" + reactionExpressionslist[i]) + # rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + # # setting the axes at the centre + # fig ,ax = plt.subplots(figsize=(9, 6)) + # ax.spines["top"].set_visible(True) + # ax.spines["right"].set_visible(True) + # # ax.set_yscale('log') + # # ax.set_xscale('log') + + # # plot the function + # # plt.plot(rateCoeffXFiner, np.exp(reactionExpressions_cubicSplineDerivative_log(rateCoeffXFiner)), + # # color='salmon', linestyle='--', label='interBolsig') + # # plt.plot(rateCoeffXFine, np.exp(reactionExpressions_cubicSpline_log(rateCoeffXFine)), + # # color='lightgreen', linestyle='--', label='interBolsig') + # plt.plot(Te, reactionTExpressionsLogFiltered(TeLog) * np.exp(reactionExpressionsLog(TeLog)) / Te, + # color='blue', linestyle='-', label='interBolsig') + # plt.plot(Te, np.exp(reactionExpressionsLog(TeLog)), + # color='green', linestyle='-', label='interBolsig') + # plt.plot(Te, rxn(Te), + # color='salmon', linestyle='--', label='interBolsig') + # plt.plot(Te, rxn_T(Te), + # color='red', linestyle='--', label='interBolsig') + # plt.xlim((0.05,100)) + # plt.ylim((1e-200,300)) + # plt.savefig("./VoltageTimeSeries/VoltageTimeSeries_50mTorr_20W" + ".pdf", dpi=300) + # # plt.xlim((-0.0001,0.0255)) + # plt.show() + else: rxn = eval("lambda energy :" + reactionExpressionslist[i]) rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) diff --git a/psaapProperties.py b/psaapProperties.py index bac59d238..383cf7b56 100644 --- a/psaapProperties.py +++ b/psaapProperties.py @@ -1,4 +1,5 @@ import numpy as np +from scipy.interpolate import CubicSpline class Reaction(object): @@ -158,14 +159,55 @@ def setPsaapProperties(gam, inputV0, inputVDC, params, Nr): reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)"] + reactionExpressionTypelist = [True] + reactionsList = [] for i in range(Nr): - rxn = eval("lambda energy :" + reactionExpressionslist[i]) - rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) - - reaction = Reaction(rxnAlfa = params.alfa, rxnBeta = params.beta, - kf = rxn, kf_T = rxn_T) - reactionsList.append(reaction) + if reactionExpressionTypelist[i]: + Nsample = 72 + N300 = 200 + + rateCoeff = np.fromfile('./BOLSIGChemistry/reaction300K_%s.dat' %str(i)) + rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T + + Te = np.fromfile('./BOLSIGChemistry/reaction300K.Te.dat') + Te = np.reshape(Te,[Nsample, N300]).T + + Te[:,0] *= 1.5 + TeLog = np.log(Te[:, 0]) + + nonZeroIndex = np.nonzero(rateCoeff[:, 0]) + rateCoeffYLog = np.zeros(rateCoeff.shape[0]) + rateCoeffYLog[nonZeroIndex[0][0]:] = np.log(rateCoeff[nonZeroIndex[0][0]:, 0]) + rateCoeffYLog[0:nonZeroIndex[0][0]] = rateCoeffYLog[nonZeroIndex[0][0]] + rateCoeffYLog += - np.log(1.0/tau) + np.log(nAr) + + filtering = np.where(rateCoeffYLog Date: Thu, 24 Mar 2022 14:26:17 -0500 Subject: [PATCH 04/32] Adding the option to select the number of sample. --- Liu2014Properties.py | 66 ++++++++++++++--------- chebSolver.py | 20 +++---- psaapProperties.py | 66 ++++++++++++++--------- psaapPropertiesCurrentTestCase.py | 2 +- psaapPropertiesCurrentTestCase100mTorr.py | 2 +- psaapPropertiesTestArm.py | 32 ++--------- timePeriodicSolver.py | 10 ++-- 7 files changed, 106 insertions(+), 92 deletions(-) diff --git a/Liu2014Properties.py b/Liu2014Properties.py index 93b63e262..a898cd77d 100644 --- a/Liu2014Properties.py +++ b/Liu2014Properties.py @@ -12,7 +12,7 @@ def __init__(self, *initial_data, **kwargs): for key in kwargs: setattr(self, key, kwargs[key]) -def setLiu2014Properties(gam, inputV0, inputVDC, params, Nr): +def setLiu2014Properties(gam, inputV0, inputVDC, params, Nr, iSample): """Sets non-dimensional properties corresponding to Liu 2014 paper. Inputs: @@ -170,36 +170,54 @@ def setLiu2014Properties(gam, inputV0, inputVDC, params, Nr): N300 = 200 rateCoeff = np.fromfile('./BOLSIGChemistry/reaction300K_%s.dat' %str(i)) - rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T + rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] Te = np.fromfile('./BOLSIGChemistry/reaction300K.Te.dat') - Te = np.reshape(Te,[Nsample, N300]).T - - Te[:,0] *= 1.5 - TeLog = np.log(Te[:, 0]) - - nonZeroIndex = np.nonzero(rateCoeff[:, 0]) - rateCoeffYLog = np.zeros(rateCoeff.shape[0]) - rateCoeffYLog[nonZeroIndex[0][0]:] = np.log(rateCoeff[nonZeroIndex[0][0]:, 0]) - rateCoeffYLog[0:nonZeroIndex[0][0]] = rateCoeffYLog[nonZeroIndex[0][0]] - rateCoeffYLog += - np.log(1.0/tau) + np.log(nAr) - - filtering = np.where(rateCoeffYLog Date: Thu, 24 Mar 2022 15:23:39 -0500 Subject: [PATCH 05/32] Adding more filtering options related to the interpolation. --- psaapPropertiesTestArm.py | 50 ++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/psaapPropertiesTestArm.py b/psaapPropertiesTestArm.py index f4a85c156..2084860fa 100644 --- a/psaapPropertiesTestArm.py +++ b/psaapPropertiesTestArm.py @@ -273,32 +273,66 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): Te = np.fromfile('./BOLSIGChemistry/reaction300K.Te.dat') Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy and transformation to log scale. + # Te *= 1.5 + # TeLog = np.log(Te) + + # Find first non-zero value of the coefficient rate. + # I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + lastFalse = np.where(indices==False)[-1][-1] + 2 + # Nondimensionalization of mean energy and transformation to log scale. # Te *= 1.5 TeLog = np.log(Te) # Find first non-zero value of the coefficient rate. - I = np.nonzero(rateCoeff) + # I = np.nonzero(rateCoeff) # Compute the slope of the rate coefficient between its first two non-zero values. # Finite differences are used. - dydx = (rateCoeff[I[0][0] + 1] - rateCoeff[I[0][0]]) \ - / (Te[I[0][0] + 1] - Te[I[0][0]]) + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) # Arrhenius form: kf = A * exp(-C / Te) # C = (dkf/dTe) / kf * Te**2.0 # A = kf / exp(-C / Te) - C = Te[I[0][0]]**2.0*dydx / rateCoeff[I[0][0]] - # A = rateCoeff[I[0][0]] / np.exp(-C/Te[I[0][0]]) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + # A = rateCoeff[lastFalse] / np.exp(-C/Te[lastFalse]) # Compute pre-exponential coefficient, A, in log scale. - ALog = np.log(rateCoeff[I[0][0]]) + C / Te[I[0][0]] + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] # Transform rate coefficient in log scale. rateCoeffLog = np.zeros(rateCoeff.shape) - rateCoeffLog[I[0][0]:] = np.log(rateCoeff[I[0][0]:]) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) # For the troublesome values, we use the Arrhenius form. - rateCoeffLog[0:I[0][0]] = ALog - C / Te[0:I[0][0]] + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] # Nondimensionalization in log scale. if i < 2: rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) From 547bf0241e64c182bc7c2bf760aaaa1bed34740b Mon Sep 17 00:00:00 2001 From: Violeta Karyofylli Date: Tue, 29 Mar 2022 10:20:15 -0500 Subject: [PATCH 06/32] Small changes for the 7200 samples. --- chebSolver.py | 10 +- psaapPropertiesTestArm.py | 31 +-- psaapPropertiesWithSampling.py | 367 +++++++++++++++++++++++++++++++++ timePeriodicSolver.py | 5 +- 4 files changed, 396 insertions(+), 17 deletions(-) create mode 100644 psaapPropertiesWithSampling.py diff --git a/chebSolver.py b/chebSolver.py index 043f96300..f450c85dc 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -9,6 +9,7 @@ from psaapPropertiesTestArmInterpTrans import setPsaapPropertiesTestArmInterpTrans from psaapPropertiesCurrentTestCase import setPsaapPropertiesCurrentTestCase from psaapPropertiesCurrentTestCase100mTorr import setPsaapPropertiesCurrentTestCase100mTorr +from psaapPropertiesWithSampling import setPsaapPropertiesWithSampling class modelClosures: """Class providing model parameters.""" @@ -406,6 +407,8 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, Nr = 8 elif(scenario==4): Nr = 8 + elif(scenario==5): + Nr = 7 elif(scenario==21): Nr = 8 else: @@ -428,6 +431,8 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, setPsaapPropertiesCurrentTestCase(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==4): setPsaapPropertiesCurrentTestCase100mTorr(gam, V0, VDC, self.params, Nr, iSample) + elif(scenario==5): + setPsaapPropertiesWithSampling(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==21): setPsaapPropertiesTestArmInterpTrans(gam, V0, VDC, self.params, Nr, iSample) @@ -1844,11 +1849,14 @@ def plot(self, col, create=True): elif(args.scenario==4): print("# Running scenario = 4 (4 species, 8 rxn, Liu 2017)") Ns = 4 + elif(args.scenario==5): + print("# Running scenario = 5 (4 species, 7 rxn, Bolsing and Lay, Moss et al, 2003)") + Ns = 4 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 else: - print("ERROR: Scenario = {0:d} not recognized. Use --scenario i with i=0, 1, 2, or 3. Exiting.".format(args.scenario)) + print("ERROR: Scenario = {0:d} not recognized. Exiting.".format(args.scenario)) exit(-1) elasticCollisionActivationFactor = 1.0 diff --git a/psaapPropertiesTestArm.py b/psaapPropertiesTestArm.py index 2084860fa..c4120aede 100644 --- a/psaapPropertiesTestArm.py +++ b/psaapPropertiesTestArm.py @@ -3,6 +3,7 @@ import matplotlib.pyplot as plt import matplotlib.colors as mcolors +import logging class Reaction(object): def __init__(self, *initial_data, **kwargs): @@ -71,7 +72,7 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): V0 = inputV0 # amplitude of driving voltage [V] verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) tau = (1./13.6e6) # period of driving voltage [s] - L = 2.54*0.005 # half-gap-width [m] (gap width is 2.54cm) + L = 2.00*0.005 # half-gap-width [m] (gap width is 2.54cm) electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) # transport parameters @@ -172,7 +173,7 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): alpha = qe*np0*L*L/(V0*eps0) ks = ks*tau/L p0 = p/qe/np0 - kappaB = 4.878171165833662 # non-dimensional thermal conductivity of background specie + kappaB = 4.878171165833662*1.6129 # non-dimensional thermal conductivity of background specie # (2/3)*tau/L**2*Kb/np0/kB, # where Kb is the thermal conductivity of background specie @@ -262,6 +263,8 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): reactionExpressionTypelist = np.array([True,True,True,False,False,False,False]) reactionsList = [] + LOGFilename = 'interpolationSample%s.log'%str(iSample) + f = open(LOGFilename, 'w') for i in range(Nr): if reactionExpressionTypelist[i]: Nsample = 72 @@ -281,15 +284,15 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): # Find duplicates TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) rateCoeff = rateCoeff[TeDuplicateinds] Te = Te[TeDuplicateinds] - # Nondimensionalization of mean energy and transformation to log scale. + # Nondimensionalization of mean energy. # Te *= 1.5 - # TeLog = np.log(Te) # Find first non-zero value of the coefficient rate. - # I = np.nonzero(rateCoeff) + I = np.nonzero(rateCoeff) diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] @@ -307,23 +310,16 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): lastFalse = np.where(indices==False)[-1][-1] + 2 - # Nondimensionalization of mean energy and transformation to log scale. - # Te *= 1.5 + # Transformation to log scale. TeLog = np.log(Te) - # Find first non-zero value of the coefficient rate. - # I = np.nonzero(rateCoeff) - # Compute the slope of the rate coefficient between its first two non-zero values. # Finite differences are used. dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ / (Te[lastFalse + 1] - Te[lastFalse]) # Arrhenius form: kf = A * exp(-C / Te) - # C = (dkf/dTe) / kf * Te**2.0 - # A = kf / exp(-C / Te) C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] - # A = rateCoeff[lastFalse] / np.exp(-C/Te[lastFalse]) # Compute pre-exponential coefficient, A, in log scale. ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] @@ -338,8 +334,6 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) else: rateCoeffLog += - np.log(1.0/tau) + np.log(np0) - # Nondimensionalization of the original rate, used for the plot and comparison. - rateCoeff *= tau * nAr # Interpolation in log scale. reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) @@ -352,6 +346,13 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): kf_T_log = reactionTExpressionsLog) reactionsList.append(reaction) + logging.basicConfig(filename=LOGFilename) + logging.warning('Interpolation info (Reaction %s):', i) + logging.warning('First non-zero entry in the rate coefficient: %s', I[0][0]) + logging.warning('Monotonicity of the rate coefficient start from entry: %s', lastFalse) + logging.warning('Position of possible duplicates in mean energy array: %s', + TeDuplicateindsForLog[0]) + # rxn = eval("lambda energy :" + reactionExpressionslist[i]) # rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) # # setting the axes at the centre diff --git a/psaapPropertiesWithSampling.py b/psaapPropertiesWithSampling.py new file mode 100644 index 000000000..72caaf66e --- /dev/null +++ b/psaapPropertiesWithSampling.py @@ -0,0 +1,367 @@ +import numpy as np +from scipy.interpolate import CubicSpline + +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors + +import logging + +class Reaction(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +def setPsaapPropertiesWithSampling(gam, inputV0, inputVDC, params, Nr, iSample): + """Sets non-dimensional properties corresponding to Liu 2014 paper. + + Inputs: + gam : Secondary electron emission coefficient + params : chebSolver.modelParams class + + Outputs: None + params data is overwritten using values from Liu 2014. + """ + ################################################################### + # User specified parameters (you may change these if you wish to + # run a different scenario from Liu 2014) + ################################################################### + + # densities + nAr = 3.22e22 # background number density of Ar [1/m^3] (corresponds to p=100 mTorr) + np0 = 8e16 # "nominal" electron density [1/m^3] + + # masses + # me = 9.10938356e-31 # mass of an electron [kg] + # me = 5.489e-4 # mass of an electron [u] + me = 0.511e6 # mass of an electron [eV/c2] + # mAr = 39.948 # mass of an argon atom [u] + # mAr = 39.948 * 1.66054e-27 # mass of an argon atom [kg] + mAr = 37.2158e9 # mass of an electron [eV/c2] + # u = 931.4941e6 # eV/c2 + c = 299792458 # speed of light [m/s] + se = 40 # momentum cross section [m^2] + + # nominal electron energy + e0 = 1.0 # [eV] + + # pressure + p = 133.3224*1.5 # [J/m^3] *1.5 to convert it to energy (1 Torr) + + # gas energy at the wall + Tg0 = 0.038778 # 3/2*300K*kB ~ (p0 - nT[:,0])/ntot + + # characteristics of driving voltage + V0 = inputV0 # amplitude of driving voltage [V] + verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) + tau = (1./13.6e6) # period of driving voltage [s] + L = 2.00*0.005 # half-gap-width [m] (gap width is 2.54cm) + electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) + + # transport parameters + nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] + nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] + nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] + nDm = 2.42e18 # argon number density times metastable diffusivity [1/(cm*s)] + + # reaction parameters (NB: k_i = Ck*exp(-A/Te)) + #Ck = np.array([1.235e-7,3.712e-8,2.05e-7,1.818e-9,2e-7]) # pre-exponential factors [cm^3/s] + #A = np.array([18.687,15.06,4.95,2.14,0.0]) # activation temperature [eV] + #dH = np.array([15.7,11.56,4.14,-11.56,0.0]) # energy lost per electron due to ionization rxn [eV] + + #Ck = np.array([1.235e-7,3.712e-8,2.05e-7,1.818e-9]) # pre-exponential factors [cm^3/s] + #A = np.array([18.687,15.06,4.95,2.14]) # activation temperature [eV] + #dH = np.array([15.7,11.56,4.14,-11.56]) # energy lost per electron due to ionization rxn [eV] + + #Ck = np.array([1.235e-7,0.0,0.0,0.0,0.0]) # pre-exponential factors [cm^3/s] + #A = np.array([18.687,15.06,4.95,2.14,0.0]) # activation temperature [eV] + #dH = np.array([15.7,0.0,0.0,0.0,0.0]) # energy lost per electron due to ionization rxn [eV] + + # nominal + # Ck = np.array([1.235e-7,3.712e-8,2.05e-7,1.818e-9,2e-7,6.2e-10,3.0e-15,1.1e-31]) # pre-exponential factors [cm^3/s] + Ck = np.array([1.235e-7,3.712e-8,2.05e-7,4.0e-13,2e-7,5.0e-10,2.5e-15]) # pre-exponential factors [cm^3/s] + + # slow excitation rate + #Ck = np.array([1.235e-7,0.5*3.712e-8,2.05e-7,1.818e-9,2e-7,6.2e-10,3.0e-15,1.1e-31]) # pre-exponential factors [cm^3/s] + + ## fast excitation rate + #Ck = np.array([1.235e-7,2.0*3.712e-8,2.05e-7,1.818e-9,2e-7,6.2e-10,3.0e-15,1.1e-31]) # pre-exponential factors [cm^3/s] + + # A = np.array([18.687,15.06,4.95,2.14,0.0,0.0,0.0,0.0]) # activation temperature [eV] + # dH = np.array([15.7,11.56,4.14,-11.56,0.0,0.0,0.0,0.0]) # energy lost per electron due to ionization rxn [eV] + # dEps = np.array([0.0,15.7,11.56,0.0]) + + A = np.array([18.687,15.06,4.95,0.0,0.0,0.0,0.0]) # activation temperature [eV] + dH = np.array([15.76,11.56,4.2,0.0,-11.56,-7.56,-11.56]) # energy lost per electron due to ionization rxn [eV] + dEps = np.array([0.0,15.76,11.56,0.0]) + + # BC parameters + # ks = 1.19e7 # electron recombination rate [cm/s] + ks = 1.366109824889323e7 # electron recombination rate [cm/s/eV] + + ################################################################### + # Constants of nature (probably shouldn't change unless you have + # root privileges on universe) + ################################################################### + qe = 1.6e-19 # unit charge [C] + eps0 = 8.86e-12 # permittivity of free space [F/m] + kB = 1.38e-23 # Boltzmann constant [J/K] + # kB = 8.62e−5 # Boltzmann constant [eV/K] + + + ################################################################### + # Calculate non-dimensional parameters + ################################################################### + + # 1) Convert input units to base SI (except eV) + nDe *= 100. # 1/(m*s) + nDi *= 100. # 1/(m*s) + nDm *= 100. + nmue *= 100. # 1/(V*m*s) + nmui *= 100. # 1/(V*m*s) + Ck *= 1e-6 # m^3/s + # Ck[7] *= 1e-6 # Ck[7] is now in m^6/s + ks *= 0.01 # m/s + se *= 1.0e-20 # m^2 + + # 2) Compute "raw" transport parameters + De = nDe/nAr + Di = nDi/nAr + Dm = nDm/nAr + + mue = nmue/nAr + mui = nmui/nAr + mum = nmum/nAr + + # 3) Compute non-dimensional properties required by solver + De = De*tau/(L*L) + Di = Di*tau/(L*L) + Dm = Dm*tau/(L*L) + + mue = mue*V0*tau/(L*L) + mui = mui*V0*tau/(L*L) + mum = mum*V0*tau/(L*L) + + Ck[0:2] = Ck[0:2]*tau*nAr + #Ck[2:5] = Ck[2:5]*tau*np0 + Ck[2:6] = Ck[2:6]*tau*np0 + Ck[6] *= tau*nAr + # Ck[7] *= tau*nAr*nAr + A = A*1.5/e0 # 1.5 to convert from temperature to energy + dH = dH/e0 + qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V + alpha = qe*np0*L*L/(V0*eps0) + ks = ks*tau/L + p0 = p/qe/np0 + kappaB = 4.878171165833662*1.6129 # non-dimensional thermal conductivity of background specie + # (2/3)*tau/L**2*Kb/np0/kB, + # where Kb is the thermal conductivity of background specie + + #params.beta = np.array([[2,2,2,1,1],[1,0,1,0,0],[0,1,0,0,0],[0,0,0,1,1]]) + #params.alfa = np.array([[1,1,1,1,1],[0,0,0,0,0],[0,0,1,1,1],[1,1,0,0,0]]) + #params.beta = np.array([[2,1,2,1],[1,0,1,0],[0,1,0,0],[0,0,0,1]], dtype=np.int) + #params.alfa = np.array([[1,1,1,1],[0,0,0,0],[0,0,1,1],[1,1,0,0]], dtype=np.int) + # params.beta = np.array([[2,1,2,1,1,1,0,0],[1,0,1,0,0,1,0,0],[0,1,0,0,0,0,0,0],[0,0,0,1,0,1,2,1]], dtype=np.int64) + # params.alfa = np.array([[1,1,1,1,1,0,0,0],[0,0,0,0,0,0,0,0],[0,0,1,1,1,2,1,1],[1,1,0,0,0,0,1,2]], dtype=np.int64) + params.beta = np.array([[2,1,2,0,1,1,0],[1,0,1,0,0,1,0],[0,1,0,1,0,0,0],[0,0,0,0,1,1,2]], dtype=np.int64) + params.alfa = np.array([[1,1,1,1,1,0,0],[0,0,0,1,0,0,0],[0,0,1,0,1,2,1],[1,1,0,0,0,0,1]], dtype=np.int64) + + # 4) Set values in params class + params.D[0] = De + params.D[1] = Di + params.D[2] = Dm + + params.mu[0] = mue + params.mu[1] = mui + params.mu[2] = mum + + params.A[:] = Ck[:] + params.B[:] = 0.0 + params.C[:] = A[:] + + params.dH[:] = dH[:] + params.dEps[:] = dEps[:] + params.qStar = qStar + params.alpha = alpha + params.ks = ks + params.gam = gam + params.kappaB = kappaB + params.nAronp0 = nAr / np0 + params.p0 = p0 + params.Tg0 = Tg0 + params.EC = 2.0 * me / mAr \ + * np.sqrt(16.0 * (me + mAr) * e0 * c**2 + / (3.0 * np.pi * me * mAr)) * se * nAr * tau + # params.EC = 2.0 * me / mAr * 3.8e9 * tau + + params.verticalShift = verticalShift / V0 + + # Parameters needed to compute the current with dimensions + params.V0Ltau = V0 / (L * tau) + params.V0L = V0 / L + params.LLV0tau = (L*L) / (V0*tau) + params.tauL = L / tau + params.np0 = np0 # "nominal" electron density [1/m^3] + params.qe = qe # unit charge [C] + params.eps0 = eps0 # unit charge [C] + params.eArea = electrodeArea # electrode area [m^2] + + reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + f"{params.A[3]} * energy**({params.B[3]}-0.5)", + f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)"] + + reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + f"{params.A[3]} * (energy**({params.B[3]}-0.5-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]}-0.5 + {params.C[3]}/energy)", + f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)"] + + reactionExpressionTypelist = np.array([True,True,True,False,False,False,False]) + + reactionsList = [] + LOGFilename = 'interpolationSample%s.log'%str(iSample) + f = open(LOGFilename, 'w') + for i in range(Nr): + if reactionExpressionTypelist[i]: + Nsample = 7200 + N300 = 200 + + rateCoeff = np.fromfile('./BOLSIGChemistryZeroIonDeg7200Samples/reaction300K_%s.dat' %str(i)) + rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + + Te = np.fromfile('./BOLSIGChemistryZeroIonDeg7200Samples/reaction300K.Te.dat') + Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy. + Te *= 1.5 + + # Find first non-zero value of the coefficient rate. + I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + lastFalse = np.where(indices==False)[-1][-1] + 4 + + # Transformation to log scale. + TeLog = np.log(Te) + + # Find first non-zero value of the coefficient rate. + # I = np.nonzero(rateCoeff) + + # Compute the slope of the rate coefficient between its first two non-zero values. + # Finite differences are used. + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) + + # Arrhenius form: kf = A * exp(-C / Te) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + + # Compute pre-exponential coefficient, A, in log scale. + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] + + # Transform rate coefficient in log scale. + rateCoeffLog = np.zeros(rateCoeff.shape) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) + # For the troublesome values, we use the Arrhenius form. + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] + # Nondimensionalization in log scale. + if i < 2: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + else: + rateCoeffLog += - np.log(1.0/tau) + np.log(np0) + + # Interpolation in log scale. + reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) + # Gradient in log scale + reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf_log = reactionExpressionsLog, + kf_T_log = reactionTExpressionsLog) + reactionsList.append(reaction) + + logging.basicConfig(filename=LOGFilename) + logging.warning('Interpolation info (Reaction %s):', i) + logging.warning('First non-zero entry in the rate coefficient: %s', I[0][0]) + logging.warning('Monotonicity of the rate coefficient start from entry: %s', lastFalse) + logging.warning('Position of possible duplicates in mean energy array: %s', + TeDuplicateindsForLog[0]) + + # rxn = eval("lambda energy :" + reactionExpressionslist[i]) + # rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + # # setting the axes at the centre + # fig ,ax = plt.subplots(figsize=(9, 6)) + # ax.spines["top"].set_visible(True) + # ax.spines["right"].set_visible(True) + # ax.set_yscale('log') + # ax.set_xscale('log') + + # # plot the function + # # plt.plot(rateCoeffXFiner, np.exp(reactionExpressions_cubicSplineDerivative_log(rateCoeffXFiner)), + # # color='salmon', linestyle='--', label='interBolsig') + # # plt.plot(rateCoeffXFine, np.exp(reactionExpressions_cubicSpline_log(rateCoeffXFine)), + # # color='lightgreen', linestyle='--', label='interBolsig') + # # plt.plot(Te[:,0], reactionTExpressionsLogFiltered(TeLog[:]) * np.exp(reactionExpressionsLog(TeLog[:])) / Te[:,0], + # # color='blue', linestyle='-', label='interBolsig') + # plt.plot(Te, np.exp(reactionExpressionsLog(TeLog[:])), + # color='green', linestyle='-', label='Bolsig') + # plt.plot(Te, rxn(Te), + # color='salmon', linestyle='--', label='Liu') + # # plt.plot(Te[:,0], rxn_T(Te[:,0]), + # # color='red', linestyle='--', label='interBolsig') + # plt.xlim((0.05,100)) + # plt.ylim((1e-50,300)) + # plt.legend() + # plt.savefig("./Rates_%s.pdf" %str(i), dpi=300) + # # plt.xlim((-0.0001,0.0255)) + # plt.show() + else: + rxn = eval("lambda energy :" + reactionExpressionslist[i]) + rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf = rxn, kf_T = rxn_T) + reactionsList.append(reaction) + + params.reactionsList = reactionsList + #params.Nr = 1 + + # 5) Dump to screen + params.print() diff --git a/timePeriodicSolver.py b/timePeriodicSolver.py index a154f1be8..b7bce87b0 100644 --- a/timePeriodicSolver.py +++ b/timePeriodicSolver.py @@ -182,11 +182,14 @@ def solveNewtonStep(self, Uic, Nt): elif(args.scenario==4): print("# Running scenario = 4 (4 species, 8 rxn, Liu 2017)") Ns = 4 + elif(args.scenario==5): + print("# Running scenario = 5 (4 species, 7 rxn, Bolsing and Lay, Moss et al, 2003)") + Ns = 4 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 else: - print("ERROR: Scenario = {0:d} not recognized. Use --scenario i with i=0, 1, 2, or 3. Exiting.".format(args.scenario)) + print("ERROR: Scenario = {0:d} not recognized. Exiting.".format(args.scenario)) exit(-1) print("#") From 8aa5a84cdf29667be8ea098f18d92f2254d2feb2 Mon Sep 17 00:00:00 2001 From: Violeta Karyofylli Date: Wed, 30 Mar 2022 17:11:33 -0500 Subject: [PATCH 07/32] Computing the Arrhenius coefficients without using the derivative. --- psaapPropertiesWithSampling.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/psaapPropertiesWithSampling.py b/psaapPropertiesWithSampling.py index 72caaf66e..4381a6570 100644 --- a/psaapPropertiesWithSampling.py +++ b/psaapPropertiesWithSampling.py @@ -275,7 +275,7 @@ def setPsaapPropertiesWithSampling(gam, inputV0, inputVDC, params, Nr, iSample): indices = Nan + Inf + Positive - lastFalse = np.where(indices==False)[-1][-1] + 4 + lastFalse = np.where(indices==False)[-1][-1] + 1 # Transformation to log scale. TeLog = np.log(Te) @@ -289,7 +289,9 @@ def setPsaapPropertiesWithSampling(gam, inputV0, inputVDC, params, Nr, iSample): / (Te[lastFalse + 1] - Te[lastFalse]) # Arrhenius form: kf = A * exp(-C / Te) - C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + # C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + C = (np.log(rateCoeff[lastFalse + 1]) - np.log(rateCoeff[lastFalse])) \ + / (1.0 / Te[lastFalse] - 1.0 / Te[lastFalse + 1]) # Compute pre-exponential coefficient, A, in log scale. ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] @@ -332,11 +334,14 @@ def setPsaapPropertiesWithSampling(gam, inputV0, inputVDC, params, Nr, iSample): # ax.set_yscale('log') # ax.set_xscale('log') + # TeFinerResolution = np.linspace(5.0e-4, 100, 20000) + # TeFinerResolutionLog = np.log(TeFinerResolution) + # # plot the function # # plt.plot(rateCoeffXFiner, np.exp(reactionExpressions_cubicSplineDerivative_log(rateCoeffXFiner)), # # color='salmon', linestyle='--', label='interBolsig') - # # plt.plot(rateCoeffXFine, np.exp(reactionExpressions_cubicSpline_log(rateCoeffXFine)), - # # color='lightgreen', linestyle='--', label='interBolsig') + # plt.plot(TeFinerResolution, np.exp(reactionExpressionsLog(TeFinerResolutionLog)), + # color='lightgreen', linestyle='--', label='interBolsig') # # plt.plot(Te[:,0], reactionTExpressionsLogFiltered(TeLog[:]) * np.exp(reactionExpressionsLog(TeLog[:])) / Te[:,0], # # color='blue', linestyle='-', label='interBolsig') # plt.plot(Te, np.exp(reactionExpressionsLog(TeLog[:])), From b527f761f6f986884ac572365028b9475cccbc6e Mon Sep 17 00:00:00 2001 From: Juan Barberena <77763932+jpb3698@users.noreply.github.com> Date: Mon, 12 Sep 2022 12:49:44 -0500 Subject: [PATCH 08/32] Add files via upload --- psaapPropertiesTestJP.py | 396 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 psaapPropertiesTestJP.py diff --git a/psaapPropertiesTestJP.py b/psaapPropertiesTestJP.py new file mode 100644 index 000000000..2d99e2b03 --- /dev/null +++ b/psaapPropertiesTestJP.py @@ -0,0 +1,396 @@ +import numpy as np +from scipy.interpolate import CubicSpline + +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors + +import logging + +class Reaction(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +def setPsaapPropertiesTestJP(gam, inputV0, inputVDC, params, Nr, iSample): + """Sets non-dimensional properties corresponding to Liu 2014 paper. + + Inputs: + gam : Secondary electron emission coefficient + params : chebSolver.modelParams class + + Outputs: None + params data is overwritten using values from Liu 2014. + """ + ################################################################### + # User specified parameters (you may change these if you wish to + # run a different scenario from Liu 2014) + ################################################################### + + # densities + nAr = 3.22e22 # background number density of Ar [1/m^3] (corresponds to p=100 mTorr) + np0 = 8e16 # "nominal" electron density [1/m^3] + + # masses + # me = 9.10938356e-31 # mass of an electron [kg] + # me = 5.489e-4 # mass of an electron [u] + me = 0.511e6 # mass of an electron [eV/c2] + # mAr = 39.948 # mass of an argon atom [u] + # mAr = 39.948 * 1.66054e-27 # mass of an argon atom [kg] + mAr = 37.2158e9 # mass of an electron [eV/c2] + # u = 931.4941e6 # eV/c2 + c = 299792458 # speed of light [m/s] + se = 40 # momentum cross section [m^2] + + # nominal electron energy + e0 = 1.0 # [eV] + + # pressure + p = 133.3224*1.5 # [J/m^3] *1.5 to convert it to energy (1 Torr) + + # gas energy at the wall + Tg0 = 0.038778 # 3/2*300K*kB ~ (p0 - nT[:,0])/ntot + + # characteristics of driving voltage + V0 = inputV0 # amplitude of driving voltage [V] + verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) + tau = (1./13.6e6) # period of driving voltage [s] + L = 2.00*0.005 # half-gap-width [m] (gap width is 2.54cm) + electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) + + # transport parameters + nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] + nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] + nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] + nDm = 2.42e18 # argon number density times metastable diffusivity [1/(cm*s)] + + # reaction parameters (NB: k_i = Ck*Ee^B*exp(-A/Ee)) + # Ee = 3/2*Te (Te in eV) + # -> k_i = [Ck*(2/3)^B] * Ee^B * exp[-(3/2)*A/Ee] + # nominal + Ck = np.array([1.235e-7,3.712e-8,2.05e-7,4.0e-13,5.0e-10,4.3e-10,2.1e-15,10.0,5.0e-27]) # pre-exponential factors [cm^3/s] + B = np.array([0.0,0.0,0.0,-0.5,0,0.74,0,0,-4.5]) + A = np.array([18.687,15.06,4.95,0.0,0.0,0.0,0.0,0.0,0.0]) # activation temperature [eV] + dH = np.array([15.76,11.56,4.2,0.0,-11.56,-7.56,-11.56,0.0,-4.2]) # energy lost per electron due to ionization rxn [eV] + dEps = np.array([0.0,15.76,11.56,0.0]) + + # BC parameters + # ks = 1.19e7 # electron recombination rate [cm/s] + ks = 1.366109824889323e7 # electron recombination rate [cm/s/eV] + + ################################################################### + # Constants of nature (probably shouldn't change unless you have + # root privileges on universe) + ################################################################### + qe = 1.6e-19 # unit charge [C] + eps0 = 8.86e-12 # permittivity of free space [F/m] + kB = 1.38e-23 # Boltzmann constant [J/K] + # kB = 8.62e−5 # Boltzmann constant [eV/K] + + + ################################################################### + # Calculate non-dimensional parameters + ################################################################### + + # 1) Convert input units to base SI (except eV) + nDe *= 100. # 1/(m*s) + nDi *= 100. # 1/(m*s) + nDm *= 100. + nmue *= 100. # 1/(V*m*s) + nmui *= 100. # 1/(V*m*s) + Ck[0:7] *= 1e-6 # m^3/s + Ck[7] *= 1 # 1/s + Ck[8] *= 1e-12 # m^6/s + # Ck[7] *= 1e-6 # Ck[7] is now in m^6/s + ks *= 0.01 # m/s + se *= 1.0e-20 # m^2 + + # 2) Compute "raw" transport parameters + De = nDe/nAr + Di = nDi/nAr + Dm = nDm/nAr + + mue = nmue/nAr + mui = nmui/nAr + mum = nmum/nAr + + # 3) Compute non-dimensional properties required by solver + De = De*tau/(L*L) + Di = Di*tau/(L*L) + Dm = Dm*tau/(L*L) + + mue = mue*V0*tau/(L*L) + mui = mui*V0*tau/(L*L) + mum = mum*V0*tau/(L*L) + + Ck[0:2] = Ck[0:2]*tau*nAr + #Ck[2:5] = Ck[2:5]*tau*np0 + Ck[2:6] = Ck[2:6]*tau*np0 + Ck[6] *= tau*nAr + Ck[7] *= tau + Ck[8] *= tau*np0*np0 + # Ck[7] *= tau*nAr*nAr + A = A*1.5/e0 # 1.5 to convert from temperature to energy + dH = dH/e0 + qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V + alpha = qe*np0*L*L/(V0*eps0) + ks = ks*tau/L + p0 = p/qe/np0 + kappaB = 4.878171165833662*1.6129 # non-dimensional thermal conductivity of background specie + # (2/3)*tau/L**2*Kb/np0/kB, + # where Kb is the thermal conductivity of background specie + + #params.beta = np.array([[2,2,2,1,1],[1,0,1,0,0],[0,1,0,0,0],[0,0,0,1,1]]) + #params.alfa = np.array([[1,1,1,1,1],[0,0,0,0,0],[0,0,1,1,1],[1,1,0,0,0]]) + #params.beta = np.array([[2,1,2,1],[1,0,1,0],[0,1,0,0],[0,0,0,1]], dtype=np.int) + #params.alfa = np.array([[1,1,1,1],[0,0,0,0],[0,0,1,1],[1,1,0,0]], dtype=np.int) + # params.beta = np.array([[2,1,2,1,1,1,0,0],[1,0,1,0,0,1,0,0],[0,1,0,0,0,0,0,0],[0,0,0,1,0,1,2,1]], dtype=np.int64) + # params.alfa = np.array([[1,1,1,1,1,0,0,0],[0,0,0,0,0,0,0,0],[0,0,1,1,1,2,1,1],[1,1,0,0,0,0,1,2]], dtype=np.int64) + params.beta = np.array([[2,1,2,0,1,1,0,0,1],[1,0,1,0,1,0,0,0,0],[0,1,0,1,0,0,0,0,1],[0,0,0,0,1,1,2,1,0]], dtype=np.int64) + params.alfa = np.array([[1,1,1,1,0,1,0,0,2],[0,0,0,1,0,0,0,0,1],[0,0,1,0,2,1,1,1,0],[1,1,0,0,0,0,1,0,0]], dtype=np.int64) + # Rxn1: E + AR -> 2E + AR+ + # Rxn2: E + AR -> E + AR* + # Rxn3: E + AR* -> 2E + AR+ + # Rxn4: E + AR+ -> AR* + # Rxn5: 2AR* -> E + AR+ + AR + # Rxn6: E + AR* -> E + AR + # Rxn7: AR* + AR -> 2AR + # Rxn8: AR* -> AR + # Rxn9: 2E + AR+ -> E + AR* + + # 4) Set values in params class + params.D[0] = De + params.D[1] = Di + params.D[2] = Dm + + params.mu[0] = mue + params.mu[1] = mui + params.mu[2] = mum + + params.A[:] = Ck[:] + params.B[:] = B[:] + params.C[:] = A[:] + + # Account for the 2/3 term to convert from electron temperature to electron energy + for i in params.A: + params.A[i] *= (2/3)**(params.B[i]) + + params.dH[:] = dH[:] + params.dEps[:] = dEps[:] + params.qStar = qStar + params.alpha = alpha + params.ks = ks + params.gam = gam + params.kappaB = kappaB + params.nAronp0 = nAr / np0 + params.p0 = p0 + params.Tg0 = Tg0 + params.EC = 2.0 * me / mAr \ + * np.sqrt(16.0 * (me + mAr) * e0 * c**2 + / (3.0 * np.pi * me * mAr)) * se * nAr * tau + # params.EC = 2.0 * me / mAr * 3.8e9 * tau + + params.verticalShift = verticalShift / V0 + + # Parameters needed to compute the current with dimensions + params.V0Ltau = V0 / (L * tau) + params.V0L = V0 / L + params.LLV0tau = (L*L) / (V0*tau) + params.tauL = L / tau + params.np0 = np0 # "nominal" electron density [1/m^3] + params.qe = qe # unit charge [C] + params.eps0 = eps0 # unit charge [C] + params.eArea = electrodeArea # electrode area [m^2] + + # reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + # f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + # f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + # f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + # f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + # f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + # f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + # f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)"] + + # reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + # f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + # f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + # f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + # f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + # f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + # f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + # f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)"] + + reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)", + f"{params.A[8]} * energy**{params.B[8]} * np.exp(-{params.C[8]} / energy)"] + + reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)", + f"{params.A[8]} * (energy**({params.B[8]}-1)) * np.exp(-{params.C[8]}/energy) * ({params.B[8]} + {params.C[8]}/energy)"] + + reactionExpressionTypelist = np.array([True,True,True,False,False,False,False,False,False]) + + reactionsList = [] + LOGFilename = 'interpolationSample%s.log'%str(iSample) + f = open(LOGFilename, 'w') + # import h5py as h5 + # rxnName = ["Ionization", ...] <- dictionary containing reaction name root string + # for r in range(Nr): + # if reactionExpressionTypeList[r]: + # fileName = "{0:s}.{1:08d}.h5".format(rxnName[r], iSample) + # f = h5.File(filename, "r") + # D = f["table"] + + for i in range(Nr): + if reactionExpressionTypelist[i]: + Nsample = 72 + N300 = 200 + + root_dir = "/g/g92/jbarbere/glowDischarge/toyProblems/timeDomain" + rate_file = "{0:s}/BOLSIGChemistry/reaction300K_{1:d}.dat".format(root_dir, i) + temp_file = "{0:s}/BOLSIGChemistry/reaction300K.Te.dat".format(root_dir) + + #rateCoeff = np.fromfile('/usr/workspace/violetak/BOLSIGSamples/glowDischarge/toyProblems/timeDomain/BOLSIGChemistry/reaction300K_%s.dat' %str(i)) + rateCoeff = np.fromfile(rate_file) + rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + + #Te = np.fromfile('/usr/workspace/violetak/BOLSIGSamples/glowDischarge/toyProblems/timeDomain/BOLSIGChemistry/reaction300K.Te.dat') + Te = np.fromfile(temp_file) + Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy. + # Te *= 1.5 + + # Find first non-zero value of the coefficient rate. + I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + lastFalse = np.where(indices==False)[-1][-1] + 2 + + # Transformation to log scale. + TeLog = np.log(Te) + + # Compute the slope of the rate coefficient between its first two non-zero values. + # Finite differences are used. + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) + + # Arrhenius form: kf = A * exp(-C / Te) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + + # Compute pre-exponential coefficient, A, in log scale. + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] + + # Transform rate coefficient in log scale. + rateCoeffLog = np.zeros(rateCoeff.shape) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) + # For the troublesome values, we use the Arrhenius form. + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] + # Nondimensionalization in log scale. + if i < 2: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + else: + rateCoeffLog += - np.log(1.0/tau) + np.log(np0) + + # Interpolation in log scale. + reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) + # Gradient in log scale + reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf_log = reactionExpressionsLog, + kf_T_log = reactionTExpressionsLog) + reactionsList.append(reaction) + + logging.basicConfig(filename=LOGFilename) + logging.warning('Interpolation info (Reaction %s):', i) + logging.warning('First non-zero entry in the rate coefficient: %s', I[0][0]) + logging.warning('Monotonicity of the rate coefficient start from entry: %s', lastFalse) + logging.warning('Position of possible duplicates in mean energy array: %s', + TeDuplicateindsForLog[0]) + + # rxn = eval("lambda energy :" + reactionExpressionslist[i]) + # rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + # # setting the axes at the centre + # fig ,ax = plt.subplots(figsize=(9, 6)) + # ax.spines["top"].set_visible(True) + # ax.spines["right"].set_visible(True) + # ax.set_yscale('log') + # ax.set_xscale('log') + + # # plot the function + # # plt.plot(rateCoeffXFiner, np.exp(reactionExpressions_cubicSplineDerivative_log(rateCoeffXFiner)), + # # color='salmon', linestyle='--', label='interBolsig') + # # plt.plot(rateCoeffXFine, np.exp(reactionExpressions_cubicSpline_log(rateCoeffXFine)), + # # color='lightgreen', linestyle='--', label='interBolsig') + # # plt.plot(Te[:,0], reactionTExpressionsLogFiltered(TeLog[:]) * np.exp(reactionExpressionsLog(TeLog[:])) / Te[:,0], + # # color='blue', linestyle='-', label='interBolsig') + # plt.plot(Te, np.exp(reactionExpressionsLog(TeLog[:])), + # color='green', linestyle='-', label='Bolsig') + # plt.plot(Te, rxn(Te), + # color='salmon', linestyle='--', label='Liu') + # # plt.plot(Te[:,0], rxn_T(Te[:,0]), + # # color='red', linestyle='--', label='interBolsig') + # plt.xlim((0.05,100)) + # plt.ylim((1e-50,300)) + # plt.legend() + # plt.savefig("./Rates_%s.pdf" %str(i), dpi=300) + # # plt.xlim((-0.0001,0.0255)) + # plt.show() + else: + rxn = eval("lambda energy :" + reactionExpressionslist[i]) + rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf = rxn, kf_T = rxn_T) + reactionsList.append(reaction) + + params.reactionsList = reactionsList + #params.Nr = 1 + + # 5) Dump to screen + params.print() From 0cbddbdb165eecfe7a1c9908d6ee99d71a26689b Mon Sep 17 00:00:00 2001 From: Juan Barberena <77763932+jpb3698@users.noreply.github.com> Date: Mon, 12 Sep 2022 12:52:29 -0500 Subject: [PATCH 09/32] Added 4Species+9Rxn Mechanism --- chebSolver.py | 9 ++++++++- sampleRun.sh | 9 +++++---- sampleRunCN.sh | 5 +++-- timePeriodicSolver.py | 3 +++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/chebSolver.py b/chebSolver.py index f450c85dc..f453be662 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -1,6 +1,5 @@ import numpy as np import numpy.polynomial.chebyshev as cheb -import matplotlib.pyplot as plt import time from Liu2014Properties import setLiu2014Properties @@ -10,6 +9,7 @@ from psaapPropertiesCurrentTestCase import setPsaapPropertiesCurrentTestCase from psaapPropertiesCurrentTestCase100mTorr import setPsaapPropertiesCurrentTestCase100mTorr from psaapPropertiesWithSampling import setPsaapPropertiesWithSampling +from psaapPropertiesTestJP import setPsaapPropertiesTestJP class modelClosures: """Class providing model parameters.""" @@ -409,6 +409,8 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, Nr = 8 elif(scenario==5): Nr = 7 + elif(scenario==6): + Nr = 9 elif(scenario==21): Nr = 8 else: @@ -433,6 +435,8 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, setPsaapPropertiesCurrentTestCase100mTorr(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==5): setPsaapPropertiesWithSampling(gam, V0, VDC, self.params, Nr, iSample) + elif(scenario==6): + setPsaapPropertiesTestJP(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==21): setPsaapPropertiesTestArmInterpTrans(gam, V0, VDC, self.params, Nr, iSample) @@ -1852,6 +1856,9 @@ def plot(self, col, create=True): elif(args.scenario==5): print("# Running scenario = 5 (4 species, 7 rxn, Bolsing and Lay, Moss et al, 2003)") Ns = 4 + elif(args.scenario==6): + print("# Running scenario = 6 (4 species, 9 rxn, Juan's mechanism)") + Ns = 4 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 diff --git a/sampleRun.sh b/sampleRun.sh index 053ff5dc1..af1297760 100755 --- a/sampleRun.sh +++ b/sampleRun.sh @@ -6,8 +6,9 @@ error_exit() exit 1 } -EXE="python3 ./chebSolver.py" -NEWTEXE="python3 ./timePeriodicSolver.py" +module load python/3.8.2 +EXE="python3 ../chebSolver.py" +NEWTEXE="python3 ../timePeriodicSolver.py" # psaap 2 species case #Np=250 @@ -26,11 +27,11 @@ NEWTEXE="python3 ./timePeriodicSolver.py" #saveFile="newton_3spec_Np${Np}_fullsoln.npy" # Liu 4 species case -Np=250 +Np=150 Nt=25600 Nt1=128 dt=0.0078125 -scenario=2 +scenario=6 baseFile="restart_4spec_Np${Np}_" newtFile="newton_4spec_Np${Np}.npy" saveFile="newton_4spec_Np${Np}_fullsoln.npy" diff --git a/sampleRunCN.sh b/sampleRunCN.sh index 34df8591e..fb6a9f314 100755 --- a/sampleRunCN.sh +++ b/sampleRunCN.sh @@ -6,6 +6,7 @@ error_exit() exit 1 } +module load python/3.8.2 EXE="python3 ./chebSolver.py" NEWTEXE="python3 ./timePeriodicSolver.py" @@ -26,11 +27,11 @@ NEWTEXE="python3 ./timePeriodicSolver.py" #saveFile="newton_3spec_CN_Np${Np}_fullsoln.npy" # Liu 4 species case -Np=300 +Np=150 Nt=25600 Nt1=128 dt=0.0078125 -scenario=2 +scenario=6 baseFile="restart_4spec_CN_Np${Np}_" newtFile="newton_4spec_CN_Np${Np}.npy" saveFile="newton_4spec_CN_Np${Np}_fullsoln.npy" diff --git a/timePeriodicSolver.py b/timePeriodicSolver.py index b7bce87b0..b90b55dc2 100644 --- a/timePeriodicSolver.py +++ b/timePeriodicSolver.py @@ -185,6 +185,9 @@ def solveNewtonStep(self, Uic, Nt): elif(args.scenario==5): print("# Running scenario = 5 (4 species, 7 rxn, Bolsing and Lay, Moss et al, 2003)") Ns = 4 + elif(args.scenario==6): + print("# Running scenario = 6 (4 species, 9 rxn, Juan's Mechanism)") + Ns = 4 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 From d203221d5b4a935bca310f8fc4374b42f3966d2e Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Tue, 13 Sep 2022 14:31:36 -0500 Subject: [PATCH 10/32] Fix loop syntax --- psaapPropertiesTestJP.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/psaapPropertiesTestJP.py b/psaapPropertiesTestJP.py index 2d99e2b03..c9b25d109 100644 --- a/psaapPropertiesTestJP.py +++ b/psaapPropertiesTestJP.py @@ -177,7 +177,7 @@ def setPsaapPropertiesTestJP(gam, inputV0, inputVDC, params, Nr, iSample): params.C[:] = A[:] # Account for the 2/3 term to convert from electron temperature to electron energy - for i in params.A: + for i in range(len(params.A)): params.A[i] *= (2/3)**(params.B[i]) params.dH[:] = dH[:] @@ -263,7 +263,9 @@ def setPsaapPropertiesTestJP(gam, inputV0, inputVDC, params, Nr, iSample): Nsample = 72 N300 = 200 - root_dir = "/g/g92/jbarbere/glowDischarge/toyProblems/timeDomain" + # FIXME: this assumes the rxn rate files live in a sub dir + # of where we are running. It should be generalized. + root_dir = "./" rate_file = "{0:s}/BOLSIGChemistry/reaction300K_{1:d}.dat".format(root_dir, i) temp_file = "{0:s}/BOLSIGChemistry/reaction300K.Te.dat".format(root_dir) From bafe23cec3507cc5ab2e3946ba8be2fa400d5aea Mon Sep 17 00:00:00 2001 From: Juan Pablo Barberena Valencia Date: Wed, 14 Sep 2022 14:25:24 -0700 Subject: [PATCH 11/32] Added sampling data and plotting script --- plot_results.py | 235 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 plot_results.py diff --git a/plot_results.py b/plot_results.py new file mode 100644 index 000000000..fc9ac037a --- /dev/null +++ b/plot_results.py @@ -0,0 +1,235 @@ +import numpy as np +import matplotlib.pyplot as plt +import chebSolver as cs +import numpy.polynomial.chebyshev as cheb +import matplotlib +from matplotlib import rc +rc('font',**{'family':'serif','serif':['Times']}) +rc('text', usetex=True) + +# these values are required to "redimensionalize" the results +# they must be consistent with the scenario input file +ne0 = 8e16 # "nominal" electron density [1/m^3] +L = 2.00*0.005 # half-gap-width [m] (gap width is 1in) +tau = (1./13.56e6) # period of driving voltage [s] +V0 = 100.0 + +# Number of Chebyshev modes +Np=150 + +# load solution file +D = np.load('newton_4spec_Np150_fullsoln_AllSamples.npy') +D = np.transpose(D) + +# T = number of time steps +T=128 + +# indices to plot (0, 0.25, 0.5, 0.75)*period +t0 = 0 +t1 = 32 +t2 = 64 +t3 = 96 + +# time +tp = np.linspace(0,1,T+1) +tr = tp*tau + +# spatial grid +xp = -np.cos(np.pi*np.linspace(0,Np-1,Np)/(Np-1)) +xr = (xp+1)*L + +# pull solution out of D +ne = D[0:Np,:] # electron density +ni = D[Np:2*Np,:] # ion density +nm = D[2*Np:3*Np,:] # metastable density +nb = D[3*Np:4*Np,:] # "background" (argon neutral) density +nee = D[4*Np:,:] # electron energy (ne * ee) + + +# (3/2)*electron temp +Te = D[4*Np:,:]/ne + + +# evaluate electric potential (this requires a poisson solve, which is +# why the timeDomainCollocationSolver is loaded) +phi = np.zeros((Np,T+1)) +tds = cs.timeDomainCollocationSolver(4,1,Np,scenario=2) +print("Solving poisson...") +for i in range(0,T+1): + tds.solve_poisson(ne[:,i],ni[:,i],tp[i]) + phi[:,i] = tds.phi[:] + +# make some plots + +# ne +fig,ax = plt.subplots() +h = ax.contourf(xr, tr, np.transpose(ne)*ne0, levels=np.linspace(0,ne0,129)) +cbar = plt.colorbar(h, ticks=np.linspace(0,ne0,9)) +cbar.ax.set_ylabel(r"$n_e$ [m$^{-3}$]", labelpad=6, fontsize=18) +plt.setp(cbar.ax.get_yticklabels(), rotation='horizontal', fontsize=12) +ax.contour(xr, tr, np.transpose(ne)*ne0, levels=np.linspace(0,ne0,129)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +ax.set_ylabel(r"$t$ [s]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) +plt.savefig('ne_4spec_contour.pdf') + +# ni +fig,ax = plt.subplots() +h = ax.contourf(xr, tr, np.transpose(ni)*ne0, levels=np.linspace(0,ne0,129)) +cbar = plt.colorbar(h, ticks=np.linspace(0,ne0,9)) +cbar.ax.set_ylabel(r"$n_i$ [m$^{-3}$]", labelpad=6, fontsize=18) +plt.setp(cbar.ax.get_yticklabels(), rotation='horizontal', fontsize=12) +ax.contour(xr, tr, np.transpose(ni)*ne0, levels=np.linspace(0,ne0,129)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +ax.set_ylabel(r"$t$ [s]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) +plt.savefig('ni_4spec_contour.pdf') + +# nm +fig,ax = plt.subplots() +h = ax.contourf(xr, tr, np.transpose(nm)*ne0, levels=np.linspace(0,5*ne0,129)) +cbar = plt.colorbar(h, ticks=np.linspace(0,ne0,9)) +cbar.ax.set_ylabel(r"$n^{\ast}$ [m$^{-3}$]", labelpad=6, fontsize=18) +plt.setp(cbar.ax.get_yticklabels(), rotation='horizontal', fontsize=12) +ax.contour(xr, tr, np.transpose(ni)*ne0, levels=np.linspace(0,ne0,129)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +ax.set_ylabel(r"$t$ [s]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) +plt.savefig('nm_4spec_contour.pdf') + +# Te +fig,ax = plt.subplots() +h = ax.contourf(xr, tr, np.transpose(Te)*(2./3.), levels=np.linspace(0,16,129)) +cbar = plt.colorbar(h, ticks=np.linspace(0,16,5)) +cbar.ax.set_ylabel(r"$T_e$ [eV]", labelpad=6, fontsize=18) +plt.setp(cbar.ax.get_yticklabels(), rotation='horizontal', fontsize=12) +ax.contour(xr, tr, np.transpose(Te)*(2./3.), levels=np.linspace(0,16,129)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +ax.set_ylabel(r"$t$ [s]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) +plt.savefig('Te_4spec_contour.pdf') + +# nb +fig,ax = plt.subplots() +h = ax.contourf(xr, tr, np.transpose(nb)*ne0, levels=np.linspace(0,5*ne0,129)) +cbar = plt.colorbar(h, ticks=np.linspace(0,ne0,9)) +cbar.ax.set_ylabel(r"$n_b$ [m$^{-3}$]", labelpad=6,fontsize=18) +plt.setp(cbar.ax.set_yticklabels(), rotation='horizontal', fontsize=12) +ax.contour(xr, tr, np.transpose(nb)*ne0, levels=np.linspace(0,ne0,129)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +ax.set_ylabel(r"$t$ [s]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) +plt.savefig('nb_4spec_contour.pdf') + +# phi +fig,ax = plt.subplots() +h = ax.contourf(xr, tr, np.transpose(phi)*V0, levels=np.linspace(-120,120,129)) +cbar = plt.colorbar(h, ticks=np.linspace(-120,120,13)) +cbar.ax.set_ylabel(r"$\phi$ [V]", labelpad=6, fontsize=18) +plt.setp(cbar.ax.get_yticklabels(), rotation='horizontal', fontsize=12) +ax.contour(xr, tr, np.transpose(phi)*V0, levels=np.linspace(-120,120,129)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +ax.set_ylabel(r"$t$ [s]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) +plt.savefig('phi_4spec_contour.pdf') + +print("Plotting lines...") + +# ne +fig,ax = plt.subplots() +ax.plot(xr, ne0*ne[:,t0], 'b-', lw=2, label=r"t={0:.2f}T".format(tp[t0])) +ax.plot(xr, ne0*ne[:,t1], 'r-', lw=2, label=r"t={0:.2f}T".format(tp[t1])) +ax.plot(xr, ne0*ne[:,t2], 'g-', lw=2, label=r"t={0:.2f}T".format(tp[t2])) +ax.plot(xr, ne0*ne[:,t3], 'c-', lw=2, label=r"t={0:.2f}T".format(tp[t3])) +ax.plot(xr, ne0*ni[:,t0], 'b--', lw=2) +ax.plot(xr, ne0*ni[:,t1], 'r--', lw=2) +ax.plot(xr, ne0*ni[:,t2], 'g--', lw=2) +ax.plot(xr, ne0*ni[:,t3], 'c--', lw=2) +ax.plot(xr, ne0*nm[:,t0], 'b:', lw=2) +ax.plot(xr, ne0*nm[:,t1], 'r:', lw=2) +ax.plot(xr, ne0*nm[:,t2], 'g:', lw=2) +ax.plot(xr, ne0*nm[:,t3], 'c:', lw=2) +ax.legend() +ax.set_xlim((0,0.0254)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +ax.set_ylabel(r"Density [m$^{-3}$]", fontsize=18) +#ax.set_ylim((0,8e16)) +plt.setp(ax.get_yticklabels(), fontsize=12) +plt.savefig('density_4spec_line.pdf') + +# Te/phi +fig,ax = plt.subplots() +ax.plot(xr, (2./3.)*Te[:,t0], 'b-', lw=2, label=r"t={0:.2f}T".format(tp[t0])) +ax.plot(xr, (2./3.)*Te[:,t1], 'r-', lw=2, label=r"t={0:.2f}T".format(tp[t1])) +ax.plot(xr, (2./3.)*Te[:,t2], 'g-', lw=2, label=r"t={0:.2f}T".format(tp[t2])) +ax.plot(xr, (2./3.)*Te[:,t3], 'c-', lw=2, label=r"t={0:.2f}T".format(tp[t3])) +ax.set_xlim((0,0.0254)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +#ax.set_ylim((0,30)) +ax.set_ylabel(r"$T_e$ [eV]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) + +ax2 = ax.twinx() +ax2.plot(xr, V0*phi[:,t0], 'b--', lw=2) +ax2.plot(xr, V0*phi[:,t1], 'r--', lw=2) +ax2.plot(xr, V0*phi[:,t2], 'g--', lw=2) +ax2.plot(xr, V0*phi[:,t3], 'c--', lw=2) +#ax2.set_ylim((-120,120)) +ax2.set_ylabel(r"$\phi$ [V]", labelpad=-5, fontsize=18) +plt.setp(ax2.get_yticklabels(), fontsize=12) +plt.savefig('Te_phi_4spec_line.pdf') + +print("Plotting means...") + +# ne +fig,ax = plt.subplots() +ax.semilogy(xr, ne0*np.mean(ne,axis=1), 'b-', lw=2, label=r"$n_e$") +ax.semilogy(xr, ne0*np.mean(ni,axis=1), 'r--', lw=2, label=r"$n_i$") +#ax.plot(xr, ne0*np.mean(nm,axis=1), 'g:', lw=2, label=r"$n^{\ast}$") +ax.legend(fontsize=12) +#ax.set_xlim((0,0.0254)) +ax.set_xlim((0,0.02)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +#ax.set_ylim((0,8e16)) +ax.set_ylabel(r"Density [m$^{-3}$]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) +plt.savefig('density_4spec_mean.pdf') + +fig,ax = plt.subplots() +ax.plot(xr, ne0*np.mean(nm,axis=1), 'g-', lw=2, label=r"$n^{\ast}$") +ax.legend(fontsize=12) +ax.set_xlim((0,0.0254)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +#ax.set_ylim((0,4*8e16)) +ax.set_ylabel(r"Density [m$^{-3}$]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) +plt.savefig('metastable_4spec_mean.pdf') + +# Te/phi +fig,ax = plt.subplots() +ax.plot(xr, (2./3.)*np.mean(Te,axis=1), 'b-', lw=2, label=r"$T_e$") +ax.legend(fontsize=12,loc=2) +ax.set_xlim((0,0.0254)) +ax.set_xlabel(r"$x$ [m]", fontsize=18) +plt.setp(ax.get_xticklabels(), fontsize=12) +ax.set_ylim((0,5.5)) +ax.set_ylabel(r"$T_e$ [eV]", fontsize=18) +plt.setp(ax.get_yticklabels(), fontsize=12) + +ax2 = ax.twinx() +ax2.plot(xr, V0*np.mean(phi,axis=1), 'r--', lw=2, label=r"$\phi$") +ax2.legend(fontsize=12,loc=1) +#ax2.set_ylim((0,70)) +ax2.set_ylabel(r"$\phi$ [V]", fontsize=18) +plt.setp(ax2.get_yticklabels(), fontsize=12) +plt.savefig('Te_phi_4spec_mean.pdf') From 76255cc376aa5a74a7334db0dd5b77502626231b Mon Sep 17 00:00:00 2001 From: Juan Pablo Barberena Valencia Date: Thu, 15 Sep 2022 11:39:49 -0700 Subject: [PATCH 12/32] Added exporting data to CSV file --- plot_results.py | 105 +++++++++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 36 deletions(-) diff --git a/plot_results.py b/plot_results.py index fc9ac037a..3e6d197b9 100644 --- a/plot_results.py +++ b/plot_results.py @@ -1,12 +1,18 @@ import numpy as np import matplotlib.pyplot as plt -import chebSolver as cs +import csv +import sys +#import chebSolver as cs import numpy.polynomial.chebyshev as cheb import matplotlib +import matplotlib.font_manager from matplotlib import rc rc('font',**{'family':'serif','serif':['Times']}) rc('text', usetex=True) +sys.path.insert(0, '../') +import chebSolver as cs + # these values are required to "redimensionalize" the results # they must be consistent with the scenario input file ne0 = 8e16 # "nominal" electron density [1/m^3] @@ -18,7 +24,7 @@ Np=150 # load solution file -D = np.load('newton_4spec_Np150_fullsoln_AllSamples.npy') +D = np.load('newton_4spec_CN_Np150_fullsoln.npy') D = np.transpose(D) # T = number of time steps @@ -52,12 +58,12 @@ # evaluate electric potential (this requires a poisson solve, which is # why the timeDomainCollocationSolver is loaded) -phi = np.zeros((Np,T+1)) -tds = cs.timeDomainCollocationSolver(4,1,Np,scenario=2) -print("Solving poisson...") -for i in range(0,T+1): - tds.solve_poisson(ne[:,i],ni[:,i],tp[i]) - phi[:,i] = tds.phi[:] +#phi = np.zeros((Np,T+1)) +#tds = cs.timeDomainCollocationSolver(4,1,Np,scenario=6) +#print("Solving poisson...") +#for i in range(0,T+1): +# tds.solve_poisson(ne[:,i],ni[:,i],tp[i]) +# phi[:,i] = tds.phi[:] # make some plots @@ -118,7 +124,7 @@ h = ax.contourf(xr, tr, np.transpose(nb)*ne0, levels=np.linspace(0,5*ne0,129)) cbar = plt.colorbar(h, ticks=np.linspace(0,ne0,9)) cbar.ax.set_ylabel(r"$n_b$ [m$^{-3}$]", labelpad=6,fontsize=18) -plt.setp(cbar.ax.set_yticklabels(), rotation='horizontal', fontsize=12) +plt.setp(cbar.ax.get_yticklabels(), rotation='horizontal', fontsize=12) ax.contour(xr, tr, np.transpose(nb)*ne0, levels=np.linspace(0,ne0,129)) ax.set_xlabel(r"$x$ [m]", fontsize=18) plt.setp(ax.get_xticklabels(), fontsize=12) @@ -127,17 +133,17 @@ plt.savefig('nb_4spec_contour.pdf') # phi -fig,ax = plt.subplots() -h = ax.contourf(xr, tr, np.transpose(phi)*V0, levels=np.linspace(-120,120,129)) -cbar = plt.colorbar(h, ticks=np.linspace(-120,120,13)) -cbar.ax.set_ylabel(r"$\phi$ [V]", labelpad=6, fontsize=18) -plt.setp(cbar.ax.get_yticklabels(), rotation='horizontal', fontsize=12) -ax.contour(xr, tr, np.transpose(phi)*V0, levels=np.linspace(-120,120,129)) -ax.set_xlabel(r"$x$ [m]", fontsize=18) -plt.setp(ax.get_xticklabels(), fontsize=12) -ax.set_ylabel(r"$t$ [s]", fontsize=18) -plt.setp(ax.get_yticklabels(), fontsize=12) -plt.savefig('phi_4spec_contour.pdf') +#fig,ax = plt.subplots() +#h = ax.contourf(xr, tr, np.transpose(phi)*V0, levels=np.linspace(-120,120,129)) +#cbar = plt.colorbar(h, ticks=np.linspace(-120,120,13)) +#cbar.ax.set_ylabel(r"$\phi$ [V]", labelpad=6, fontsize=18) +#plt.setp(cbar.ax.get_yticklabels(), rotation='horizontal', fontsize=12) +#ax.contour(xr, tr, np.transpose(phi)*V0, levels=np.linspace(-120,120,129)) +#ax.set_xlabel(r"$x$ [m]", fontsize=18) +#plt.setp(ax.get_xticklabels(), fontsize=12) +#ax.set_ylabel(r"$t$ [s]", fontsize=18) +#plt.setp(ax.get_yticklabels(), fontsize=12) +#plt.savefig('phi_4spec_contour.pdf') print("Plotting lines...") @@ -173,19 +179,19 @@ ax.set_xlim((0,0.0254)) ax.set_xlabel(r"$x$ [m]", fontsize=18) plt.setp(ax.get_xticklabels(), fontsize=12) -#ax.set_ylim((0,30)) +ax.set_ylim((0,30)) ax.set_ylabel(r"$T_e$ [eV]", fontsize=18) plt.setp(ax.get_yticklabels(), fontsize=12) -ax2 = ax.twinx() -ax2.plot(xr, V0*phi[:,t0], 'b--', lw=2) -ax2.plot(xr, V0*phi[:,t1], 'r--', lw=2) -ax2.plot(xr, V0*phi[:,t2], 'g--', lw=2) -ax2.plot(xr, V0*phi[:,t3], 'c--', lw=2) +#ax2 = ax.twinx() +#ax2.plot(xr, V0*phi[:,t0], 'b--', lw=2) +#ax2.plot(xr, V0*phi[:,t1], 'r--', lw=2) +#ax2.plot(xr, V0*phi[:,t2], 'g--', lw=2) +#ax2.plot(xr, V0*phi[:,t3], 'c--', lw=2) #ax2.set_ylim((-120,120)) -ax2.set_ylabel(r"$\phi$ [V]", labelpad=-5, fontsize=18) -plt.setp(ax2.get_yticklabels(), fontsize=12) -plt.savefig('Te_phi_4spec_line.pdf') +#ax2.set_ylabel(r"$\phi$ [V]", labelpad=-5, fontsize=18) +#plt.setp(ax2.get_yticklabels(), fontsize=12) +plt.savefig('Te_4spec_line.pdf') print("Plotting means...") @@ -204,6 +210,7 @@ plt.setp(ax.get_yticklabels(), fontsize=12) plt.savefig('density_4spec_mean.pdf') +# nm fig,ax = plt.subplots() ax.plot(xr, ne0*np.mean(nm,axis=1), 'g-', lw=2, label=r"$n^{\ast}$") ax.legend(fontsize=12) @@ -225,11 +232,37 @@ ax.set_ylim((0,5.5)) ax.set_ylabel(r"$T_e$ [eV]", fontsize=18) plt.setp(ax.get_yticklabels(), fontsize=12) +# +#ax2 = ax.twinx() +#ax2.plot(xr, V0*np.mean(phi,axis=1), 'r--', lw=2, label=r"$\phi$") +#ax2.legend(fontsize=12,loc=1) +##ax2.set_ylim((0,70)) +#ax2.set_ylabel(r"$\phi$ [V]", fontsize=18) +#plt.setp(ax2.get_yticklabels(), fontsize=12) +plt.savefig('Te_4spec_mean.pdf') + +# Write CSV File +header = ['x', 'ne', 'ni', 'nm', 'nb', 'Te'] +data = [] +row = [] +for i in range(len(xr)): + x_temp = xr[i] + ne_temp = ne0*np.mean(ne,axis=1)[i] + ni_temp = ne0*np.mean(ni,axis=1)[i] + nm_temp = ne0*np.mean(nm,axis=1)[i] + nb_temp = ne0*np.mean(nb,axis=1)[i] + Te_temp = (2./3.)*11604.*np.mean(Te,axis=1)[i] + row.append(x_temp) + row.append(ne_temp) + row.append(ni_temp) + row.append(nm_temp) + row.append(nb_temp) + row.append(Te_temp) + data.append(row) + row = [] -ax2 = ax.twinx() -ax2.plot(xr, V0*np.mean(phi,axis=1), 'r--', lw=2, label=r"$\phi$") -ax2.legend(fontsize=12,loc=1) -#ax2.set_ylim((0,70)) -ax2.set_ylabel(r"$\phi$ [V]", fontsize=18) -plt.setp(ax2.get_yticklabels(), fontsize=12) -plt.savefig('Te_phi_4spec_mean.pdf') +f = open('GD_mean_results.csv', 'w') +writer = csv.writer(f) +writer.writerow(header) +writer.writerows(data) +f.close() From 7703f07c2d20de91431de535eef4765bd3d2d307 Mon Sep 17 00:00:00 2001 From: Juan Pablo Barberena Valencia Date: Fri, 16 Sep 2022 15:46:57 -0700 Subject: [PATCH 13/32] Added scenario with Nominal Rxn Rates and algorithm for plotting rates --- chebSolver.py | 8 + psaapPropertiesTestJP_Nominal.py | 369 +++++++++++++++++++++++++++++++ timePeriodicSolver.py | 3 + 3 files changed, 380 insertions(+) create mode 100755 psaapPropertiesTestJP_Nominal.py diff --git a/chebSolver.py b/chebSolver.py index f453be662..35d1d954a 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -10,6 +10,7 @@ from psaapPropertiesCurrentTestCase100mTorr import setPsaapPropertiesCurrentTestCase100mTorr from psaapPropertiesWithSampling import setPsaapPropertiesWithSampling from psaapPropertiesTestJP import setPsaapPropertiesTestJP +from psaapPropertiesTestJP_Nominal import setPsaapPropertiesTestJP_Nominal class modelClosures: """Class providing model parameters.""" @@ -411,6 +412,8 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, Nr = 7 elif(scenario==6): Nr = 9 + elif(scenario==7): + Nr = 9 elif(scenario==21): Nr = 8 else: @@ -437,6 +440,8 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, setPsaapPropertiesWithSampling(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==6): setPsaapPropertiesTestJP(gam, V0, VDC, self.params, Nr, iSample) + elif(scenario==7): + setPsaapPropertiesTestJP_Nominal(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==21): setPsaapPropertiesTestArmInterpTrans(gam, V0, VDC, self.params, Nr, iSample) @@ -1859,6 +1864,9 @@ def plot(self, col, create=True): elif(args.scenario==6): print("# Running scenario = 6 (4 species, 9 rxn, Juan's mechanism)") Ns = 4 + elif(args.scenario==7): + print("# Running scenario = 7 (4 species, 9 rxn, Nominal reaction rates)") + Ns = 4 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 diff --git a/psaapPropertiesTestJP_Nominal.py b/psaapPropertiesTestJP_Nominal.py new file mode 100755 index 000000000..bb60d2663 --- /dev/null +++ b/psaapPropertiesTestJP_Nominal.py @@ -0,0 +1,369 @@ +import numpy as np +from scipy.interpolate import CubicSpline +import csv +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors + +import logging + +class Reaction(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +def setPsaapPropertiesTestJP_Nominal(gam, inputV0, inputVDC, params, Nr, iSample): + """Sets non-dimensional properties corresponding to Liu 2014 paper. + + Inputs: + gam : Secondary electron emission coefficient + params : chebSolver.modelParams class + + Outputs: None + params data is overwritten using values from Liu 2014. + """ + ################################################################### + # User specified parameters (you may change these if you wish to + # run a different scenario from Liu 2014) + ################################################################### + + # densities + nAr = 3.22e22 # background number density of Ar [1/m^3] (corresponds to p=100 mTorr) + np0 = 8e16 # "nominal" electron density [1/m^3] + + # masses + # me = 9.10938356e-31 # mass of an electron [kg] + # me = 5.489e-4 # mass of an electron [u] + me = 0.511e6 # mass of an electron [eV/c2] + # mAr = 39.948 # mass of an argon atom [u] + # mAr = 39.948 * 1.66054e-27 # mass of an argon atom [kg] + mAr = 37.2158e9 # mass of an electron [eV/c2] + # u = 931.4941e6 # eV/c2 + c = 299792458 # speed of light [m/s] + se = 40 # momentum cross section [m^2] + + # nominal electron energy + e0 = 1.0 # [eV] + + # pressure + p = 133.3224*1.5 # [J/m^3] *1.5 to convert it to energy (1 Torr) + + # gas energy at the wall + Tg0 = 0.038778 # 3/2*300K*kB ~ (p0 - nT[:,0])/ntot + + # characteristics of driving voltage + V0 = inputV0 # amplitude of driving voltage [V] + verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) + tau = (1./13.6e6) # period of driving voltage [s] + L = 2.00*0.005 # half-gap-width [m] (gap width is 2.54cm) + electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) + + # transport parameters + nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] + nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] + nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] + nDm = 2.42e18 # argon number density times metastable diffusivity [1/(cm*s)] + + # reaction parameters (NB: k_i = Ck*Ee^B*exp(-A/Ee)) + # Ee = 3/2*Te (Te in eV) + # -> k_i = [Ck*(2/3)^B] * Ee^B * exp[-(3/2)*A/Ee] + # nominal + Ck = np.array([1.235e-7,3.712e-8,2.05e-7,4.0e-13,5.0e-10,4.3e-10,2.1e-15,10.0,5.0e-27]) # pre-exponential factors [cm^3/s] + B = np.array([0.0,0.0,0.0,-0.5,0,0.74,0,0,-4.5]) + A = np.array([18.687,15.06,4.95,0.0,0.0,0.0,0.0,0.0,0.0]) # activation temperature [eV] + dH = np.array([15.76,11.56,4.2,0.0,-11.56,-7.56,-11.56,0.0,-4.2]) # energy lost per electron due to ionization rxn [eV] + dEps = np.array([0.0,15.76,11.56,0.0]) + + # BC parameters + # ks = 1.19e7 # electron recombination rate [cm/s] + ks = 1.366109824889323e7 # electron recombination rate [cm/s/eV] + + ################################################################### + # Constants of nature (probably shouldn't change unless you have + # root privileges on universe) + ################################################################### + qe = 1.6e-19 # unit charge [C] + eps0 = 8.86e-12 # permittivity of free space [F/m] + kB = 1.38e-23 # Boltzmann constant [J/K] + # kB = 8.62e−5 # Boltzmann constant [eV/K] + + + ################################################################### + # Calculate non-dimensional parameters + ################################################################### + + # 1) Convert input units to base SI (except eV) + nDe *= 100. # 1/(m*s) + nDi *= 100. # 1/(m*s) + nDm *= 100. + nmue *= 100. # 1/(V*m*s) + nmui *= 100. # 1/(V*m*s) + Ck[0:7] *= 1e-6 # m^3/s + Ck[7] *= 1 # 1/s + Ck[8] *= 1e-12 # m^6/s + # Ck[7] *= 1e-6 # Ck[7] is now in m^6/s + ks *= 0.01 # m/s + se *= 1.0e-20 # m^2 + + # 2) Compute "raw" transport parameters + De = nDe/nAr + Di = nDi/nAr + Dm = nDm/nAr + + mue = nmue/nAr + mui = nmui/nAr + mum = nmum/nAr + + # 3) Compute non-dimensional properties required by solver + De = De*tau/(L*L) + Di = Di*tau/(L*L) + Dm = Dm*tau/(L*L) + + mue = mue*V0*tau/(L*L) + mui = mui*V0*tau/(L*L) + mum = mum*V0*tau/(L*L) + + Ck[0:2] = Ck[0:2]*tau*nAr + #Ck[2:5] = Ck[2:5]*tau*np0 + Ck[2:6] = Ck[2:6]*tau*np0 + Ck[6] *= tau*nAr + Ck[7] *= tau + Ck[8] *= tau*np0*np0 + # Ck[7] *= tau*nAr*nAr + A = A*1.5/e0 # 1.5 to convert from temperature to energy + dH = dH/e0 + qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V + alpha = qe*np0*L*L/(V0*eps0) + ks = ks*tau/L + p0 = p/qe/np0 + kappaB = 4.878171165833662*1.6129 # non-dimensional thermal conductivity of background specie + # (2/3)*tau/L**2*Kb/np0/kB, + # where Kb is the thermal conductivity of background specie + + #params.beta = np.array([[2,2,2,1,1],[1,0,1,0,0],[0,1,0,0,0],[0,0,0,1,1]]) + #params.alfa = np.array([[1,1,1,1,1],[0,0,0,0,0],[0,0,1,1,1],[1,1,0,0,0]]) + #params.beta = np.array([[2,1,2,1],[1,0,1,0],[0,1,0,0],[0,0,0,1]], dtype=np.int) + #params.alfa = np.array([[1,1,1,1],[0,0,0,0],[0,0,1,1],[1,1,0,0]], dtype=np.int) + # params.beta = np.array([[2,1,2,1,1,1,0,0],[1,0,1,0,0,1,0,0],[0,1,0,0,0,0,0,0],[0,0,0,1,0,1,2,1]], dtype=np.int64) + # params.alfa = np.array([[1,1,1,1,1,0,0,0],[0,0,0,0,0,0,0,0],[0,0,1,1,1,2,1,1],[1,1,0,0,0,0,1,2]], dtype=np.int64) + params.beta = np.array([[2,1,2,0,1,1,0,0,1],[1,0,1,0,1,0,0,0,0],[0,1,0,1,0,0,0,0,1],[0,0,0,0,1,1,2,1,0]], dtype=np.int64) + params.alfa = np.array([[1,1,1,1,0,1,0,0,2],[0,0,0,1,0,0,0,0,1],[0,0,1,0,2,1,1,1,0],[1,1,0,0,0,0,1,0,0]], dtype=np.int64) + # Rxn1: E + AR -> 2E + AR+ + # Rxn2: E + AR -> E + AR* + # Rxn3: E + AR* -> 2E + AR+ + # Rxn4: E + AR+ -> AR* + # Rxn5: 2AR* -> E + AR+ + AR + # Rxn6: E + AR* -> E + AR + # Rxn7: AR* + AR -> 2AR + # Rxn8: AR* -> AR + # Rxn9: 2E + AR+ -> E + AR* + + # 4) Set values in params class + params.D[0] = De + params.D[1] = Di + params.D[2] = Dm + + params.mu[0] = mue + params.mu[1] = mui + params.mu[2] = mum + + params.A[:] = Ck[:] + params.B[:] = B[:] + params.C[:] = A[:] + + # Account for the 2/3 term to convert from electron temperature to electron energy + for i in range(len(params.A)): + params.A[i] *= (2/3)**(params.B[i]) + + params.dH[:] = dH[:] + params.dEps[:] = dEps[:] + params.qStar = qStar + params.alpha = alpha + params.ks = ks + params.gam = gam + params.kappaB = kappaB + params.nAronp0 = nAr / np0 + params.p0 = p0 + params.Tg0 = Tg0 + params.EC = 2.0 * me / mAr \ + * np.sqrt(16.0 * (me + mAr) * e0 * c**2 + / (3.0 * np.pi * me * mAr)) * se * nAr * tau + # params.EC = 2.0 * me / mAr * 3.8e9 * tau + + params.verticalShift = verticalShift / V0 + + # Parameters needed to compute the current with dimensions + params.V0Ltau = V0 / (L * tau) + params.V0L = V0 / L + params.LLV0tau = (L*L) / (V0*tau) + params.tauL = L / tau + params.np0 = np0 # "nominal" electron density [1/m^3] + params.qe = qe # unit charge [C] + params.eps0 = eps0 # unit charge [C] + params.eArea = electrodeArea # electrode area [m^2] + + # reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + # f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + # f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + # f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + # f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + # f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + # f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + # f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)"] + + # reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + # f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + # f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + # f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + # f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + # f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + # f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + # f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)"] + + reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)", + f"{params.A[8]} * energy**{params.B[8]} * np.exp(-{params.C[8]} / energy)"] + + reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)", + f"{params.A[8]} * (energy**({params.B[8]}-1)) * np.exp(-{params.C[8]}/energy) * ({params.B[8]} + {params.C[8]}/energy)"] + + reactionExpressionTypelist = np.array([True,True,True,False,False,False,False,False,False]) + + reactionsList = [] + LOGFilename = 'interpolationSample%s.log'%str(iSample) + f = open(LOGFilename, 'w') + # import h5py as h5 + # rxnName = ["Ionization", ...] <- dictionary containing reaction name root string + # for r in range(Nr): + # if reactionExpressionTypeList[r]: + # fileName = "{0:s}.{1:08d}.h5".format(rxnName[r], iSample) + # f = h5.File(filename, "r") + # D = f["table"] + + for i in range(Nr): + if reactionExpressionTypelist[i]: + Nsample = 1 + N300 = 200 + + root_dir = ".." + rate_file = open("{0:s}/BOLSIGChemistry_NominalRates/reaction300K_{1:d}.txt".format(root_dir, i), 'r') + temp_file = open("{0:s}/BOLSIGChemistry_NominalRates/reaction300K_Te.txt".format(root_dir), 'r') + + #rateCoeff = np.fromfile(rate_file) + rateCoeff = np.genfromtxt(rate_file) + rate_file.close() + rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + + #Te = np.fromfile(temp_file) + Te = np.genfromtxt(temp_file) + temp_file.close() + Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy. + # Te *= 1.5 + + # Find first non-zero value of the coefficient rate. + I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + lastFalse = np.where(indices==False)[-1][-1] + 2 + + # Transformation to log scale. + TeLog = np.log(Te) + + # Compute the slope of the rate coefficient between its first two non-zero values. + # Finite differences are used. + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) + + # Arrhenius form: kf = A * exp(-C / Te) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + + # Compute pre-exponential coefficient, A, in log scale. + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] + + # Transform rate coefficient in log scale. + rateCoeffLog = np.zeros(rateCoeff.shape) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) + # For the troublesome values, we use the Arrhenius form. + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] + # Nondimensionalization in log scale. + if i < 2: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + else: + rateCoeffLog += - np.log(1.0/tau) + np.log(np0) + + # Interpolation in log scale. + reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) + # Gradient in log scale + reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf_log = reactionExpressionsLog, + kf_T_log = reactionTExpressionsLog) + reactionsList.append(reaction) + + logging.basicConfig(filename=LOGFilename) + logging.warning('Interpolation info (Reaction %s):', i) + logging.warning('First non-zero entry in the rate coefficient: %s', I[0][0]) + logging.warning('Monotonicity of the rate coefficient start from entry: %s', lastFalse) + logging.warning('Position of possible duplicates in mean energy array: %s', + TeDuplicateindsForLog[0]) + + else: + rxn = eval("lambda energy :" + reactionExpressionslist[i]) + rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf = rxn, kf_T = rxn_T) + reactionsList.append(reaction) + + params.reactionsList = reactionsList + + # 5) Dump to screen + params.print() diff --git a/timePeriodicSolver.py b/timePeriodicSolver.py index b90b55dc2..a19172eb3 100644 --- a/timePeriodicSolver.py +++ b/timePeriodicSolver.py @@ -188,6 +188,9 @@ def solveNewtonStep(self, Uic, Nt): elif(args.scenario==6): print("# Running scenario = 6 (4 species, 9 rxn, Juan's Mechanism)") Ns = 4 + elif(args.scenario==7): + print("# Running scenario = 7 (4 species, 9 rxn, Nominal Reaction Rates)") + Ns = 4 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 From cfbea97fcb516f3b7d6a8e139b292741d953263d Mon Sep 17 00:00:00 2001 From: Juan Pablo Barberena Valencia Date: Fri, 30 Sep 2022 14:46:15 -0700 Subject: [PATCH 14/32] Added 6-species mechanism --- chebSolver.py | 72 ++++- psaapProperties.py | 2 +- psaapPropertiesTestArm.py | 10 +- psaapPropertiesTestJP.py | 14 +- psaapPropertiesTestJP_Arrhenius.py | 373 +++++++++++++++++++++++++ psaapPropertiesTestJP_Nominal.py | 24 +- psaapPropertiesWithSampling.py | 18 +- psaapProperties_4plus2Species.py | 374 +++++++++++++++++++++++++ psaapProperties_6Species.py | 430 +++++++++++++++++++++++++++++ timePeriodicSolver.py | 7 + 10 files changed, 1291 insertions(+), 33 deletions(-) create mode 100755 psaapPropertiesTestJP_Arrhenius.py create mode 100755 psaapProperties_4plus2Species.py create mode 100755 psaapProperties_6Species.py diff --git a/chebSolver.py b/chebSolver.py index 35d1d954a..4ac4425f0 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -11,6 +11,9 @@ from psaapPropertiesWithSampling import setPsaapPropertiesWithSampling from psaapPropertiesTestJP import setPsaapPropertiesTestJP from psaapPropertiesTestJP_Nominal import setPsaapPropertiesTestJP_Nominal +from psaapPropertiesTestJP_Arrhenius import setPsaapPropertiesTestJP_Arrhenius +from psaapProperties_6Species import setPsaapProperties_6Species +from psaapProperties_4plus2Species import setPsaapProperties_4plus2Species class modelClosures: """Class providing model parameters.""" @@ -91,13 +94,13 @@ def __init__(self, Ns, Nr): self.alfa = np.zeros((Ns,Nr),dtype=np.int64) # reactants # this represents a single rxn: Ar+e -> Ar+ + e + e - self.beta[0,0] = 2 - self.beta[1,0] = 1 - self.beta[2,0] = 0 + #self.beta[0,0] = 2 + #self.beta[1,0] = 1 + #self.beta[2,0] = 0 - self.alfa[0,0] = 1 - self.alfa[1,0] = 0 - self.alfa[2,0] = 1 + #self.alfa[0,0] = 1 + #self.alfa[1,0] = 0 + #self.alfa[2,0] = 1 # other non-dimensional parameters self.qStar = 100.0 @@ -193,6 +196,16 @@ def diffusivity(self, i, energy, mu, nb, EinsteinForm): V0 = self.qStar * 1.0 # V0 = qStar * 1eV DEf = 2.0 / 3.0 * np.multiply(energy[:,[i]], mu[:,[i]]) / V0 + # Einstein for electrons only (for testing purposes) + # if EinsteinForm: + # #V0 = self.qStar * 1.0 # V0 = qStar * 1eV + # #DEf = 2.0 / 3.0 * np.multiply(energy[:,[i]], mu[:,[i]]) / V0 + # if self.Z[i] == -1: ## Added this to use Einstein Relation only with electrons and constant values for heavies + # V0 = self.qStar * 1.0 + # DEf = 2.0 / 3.0 * np.multiply(energy[:,[i]], mu[:,[i]]) / V0 + # else: + # DEf[:,0] = self.D[i] / nb + else: DEf[:,0] = self.D[i] / nb @@ -221,6 +234,12 @@ def diffusivity_U(self, i, j, energy, energy_U, mu, D, nb, EinsteinForm): if (j == self.Ns - 1): D_U[:,:] -= np.diag(D[:,i] / nb) + # Einstein for electrons only (for testing purposes) + # if EinsteinForm: + # if self.Z[i] == -1: + # V0 = self.qStar * 1.0 # V0 = qStar * 1eV + # D_U = 2.0 / 3.0 * np.multiply(mu[:,[i]], energy_U[i,j,:,:]) / V0 + return D_U @@ -414,6 +433,12 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, Nr = 9 elif(scenario==7): Nr = 9 + elif(scenario==8): + Nr = 9 + elif(scenario==9): + Nr = 23 + elif(scenario==10): + Nr = 9 elif(scenario==21): Nr = 8 else: @@ -442,6 +467,12 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, setPsaapPropertiesTestJP(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==7): setPsaapPropertiesTestJP_Nominal(gam, V0, VDC, self.params, Nr, iSample) + elif(scenario==8): + setPsaapPropertiesTestJP_Arrhenius(gam, V0, VDC, self.params, Nr, iSample) + elif(scenario==9): + setPsaapProperties_6Species(gam, V0, VDC, self.params, Nr, iSample) + elif(scenario==10): + setPsaapProperties_4plus2Species(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==21): setPsaapPropertiesTestArmInterpTrans(gam, V0, VDC, self.params, Nr, iSample) @@ -842,6 +873,15 @@ def residualCN(self, Uin, time, dt, weak_bc=False): res[ self.Ns*self.Np-1 ] = dens[ -1,self.Ns-1] \ - ((self.params.p0 - nT[ -1]) / self.params.Tg0 - ntot[-1]) / self.params.nAronp0 + if (self.Ns == 6): # Dirichlet BCs for AR(m), AR(r) and AR(4p) in the 6-species mechanism + #res[2*self.Np ] = dens[ 0,2] - 0.0 + #res[3*self.Np-1] = dens[-1,2] - 0.0 + res[3*self.Np ] = dens[ 0,3] - 0.0 + res[4*self.Np-1] = dens[-1,3] - 0.0 + res[4*self.Np ] = dens[ 0,4] - 0.0 + res[5*self.Np-1] = dens[-1,4] - 0.0 + + # enforce Dirichlet condition on heavy species temperature ntot = np.zeros(self.Np) @@ -893,6 +933,14 @@ def residualLCN(self, Uin, time, dt, weak_bc=False): res[2*self.Np ] = 0.0 #dens[ 0,2] - 0.0 res[3*self.Np-1] = 0.0 #dens[-1,2] - 0.0 + if (self.Ns == 6): + #res[2*self.Np ] = 0.0 + #res[3*self.Np-1] = 0.0 + res[3*self.Np ] = 0.0 + res[4*self.Np-1] = 0.0 + res[4*self.Np ] = 0.0 + res[5*self.Np-1] = 0.0 + # electron temperature res[self.Ns*self.Np ] = 0.0 #(nT[ 0] - 0.75*dens[0,iele]) res[(self.Ns+1)*self.Np-1] = 0.0 #(nT[-1] - 0.75*dens[-1,iele]) @@ -1290,6 +1338,7 @@ def jacobianBE(self, Uin, time, dt, weak_bc=False, solve_poisson=False): self.jac[(i+1)*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) self.jac[(i+1)*self.Np-1,(i+1)*self.Np-1] = 1.0 + # Dirichlet on heavy species temperature if (self.backgroundSpecieActivationFactor > 0): self.jac[(self.Ns-1)*self.Np,:] = np.zeros((1,self.Nv*self.Np)) @@ -1867,6 +1916,13 @@ def plot(self, col, create=True): elif(args.scenario==7): print("# Running scenario = 7 (4 species, 9 rxn, Nominal reaction rates)") Ns = 4 + elif(args.scenario==8): + Ns = 4 + elif(args.scenario==9): + print("# Running scenario = 9 (6 species, 23 rxn)") + Ns = 6 + elif(args.scenario==10): + Ns = 6 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 @@ -1916,7 +1972,9 @@ def plot(self, col, create=True): # Default IC (overwritten below if we are restarting) #tds.U1[0:tds.Ns*tds.Np] = 1e-4 - tds.U1[0:(tds.Ns-1)*tds.Np] = 1e-1 # 'usual' species + #tds.U1[0:(tds.Ns-1)*tds.Np] = 1e-4 # 'usual' species + tds.U1[0:(tds.Ns-3)*tds.Np] = 1e-4 + tds.U1[(tds.Ns-3)*tds.Np:(tds.Ns-1)*tds.Np] = 0.0 # These two lines added for the 4+2 mechanism... delete otherwise tds.U1[(tds.Ns-1)*tds.Np:tds.Ns*tds.Np] = 1.0 # background specie tds.U1[tds.Ns*tds.Np:] = tds.params.EeBC*tds.U1[0:tds.Np] # electron energy diff --git a/psaapProperties.py b/psaapProperties.py index b8765de31..549ce9335 100644 --- a/psaapProperties.py +++ b/psaapProperties.py @@ -159,7 +159,7 @@ def setPsaapProperties(gam, inputV0, inputVDC, params, Nr, iSample): reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)"] - reactionExpressionTypelist = [True] + reactionExpressionTypelist = [False] reactionsList = [] for i in range(Nr): diff --git a/psaapPropertiesTestArm.py b/psaapPropertiesTestArm.py index c4120aede..9c3d55670 100644 --- a/psaapPropertiesTestArm.py +++ b/psaapPropertiesTestArm.py @@ -270,10 +270,16 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): Nsample = 72 N300 = 200 - rateCoeff = np.fromfile('./BOLSIGChemistry/reaction300K_%s.dat' %str(i)) + root_dir = "/g/g92/jbarbere/glowDischarge/toyProblems/timeDomain" + rate_file = "{0:s}/BOLSIGChemistry/reaction300K_{1:d}.dat".format(root_dir, i) + temp_file = "{0:s}/BOLSIGChemistry/reaction300K.Te.dat".format(root_dir) + + #rateCoeff = np.fromfile('/usr/workspace/violetak/BOLSIGSamples/glowDischarge/toyProblems/timeDomain/BOLSIGChemistry/reaction300K_%s.dat' %str(i)) + rateCoeff = np.fromfile(rate_file) rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] - Te = np.fromfile('./BOLSIGChemistry/reaction300K.Te.dat') + #Te = np.fromfile('/usr/workspace/violetak/BOLSIGSamples/glowDischarge/toyProblems/timeDomain/BOLSIGChemistry/reaction300K.Te.dat') + Te = np.fromfile(temp_file) Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] # Sorting mean energy array and rate coefficient array based on diff --git a/psaapPropertiesTestJP.py b/psaapPropertiesTestJP.py index c9b25d109..c826f9b0d 100644 --- a/psaapPropertiesTestJP.py +++ b/psaapPropertiesTestJP.py @@ -42,7 +42,7 @@ def setPsaapPropertiesTestJP(gam, inputV0, inputVDC, params, Nr, iSample): mAr = 37.2158e9 # mass of an electron [eV/c2] # u = 931.4941e6 # eV/c2 c = 299792458 # speed of light [m/s] - se = 40 # momentum cross section [m^2] + se = 40 # momentum cross section [A^2] # nominal electron energy e0 = 1.0 # [eV] @@ -63,8 +63,9 @@ def setPsaapPropertiesTestJP(gam, inputV0, inputVDC, params, Nr, iSample): # transport parameters nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] - nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 - / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + #nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + # / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nmum = 0.0 nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] nDm = 2.42e18 # argon number density times metastable diffusivity [1/(cm*s)] @@ -76,7 +77,7 @@ def setPsaapPropertiesTestJP(gam, inputV0, inputVDC, params, Nr, iSample): Ck = np.array([1.235e-7,3.712e-8,2.05e-7,4.0e-13,5.0e-10,4.3e-10,2.1e-15,10.0,5.0e-27]) # pre-exponential factors [cm^3/s] B = np.array([0.0,0.0,0.0,-0.5,0,0.74,0,0,-4.5]) A = np.array([18.687,15.06,4.95,0.0,0.0,0.0,0.0,0.0,0.0]) # activation temperature [eV] - dH = np.array([15.76,11.56,4.2,0.0,-11.56,-7.56,-11.56,0.0,-4.2]) # energy lost per electron due to ionization rxn [eV] + dH = np.array([15.76,11.56,4.2,0.0,-7.36,-11.56,-11.56,0.0,-4.2]) # energy lost per electron due to ionization rxn [eV] dEps = np.array([0.0,15.76,11.56,0.0]) # BC parameters @@ -106,7 +107,6 @@ def setPsaapPropertiesTestJP(gam, inputV0, inputVDC, params, Nr, iSample): Ck[0:7] *= 1e-6 # m^3/s Ck[7] *= 1 # 1/s Ck[8] *= 1e-12 # m^6/s - # Ck[7] *= 1e-6 # Ck[7] is now in m^6/s ks *= 0.01 # m/s se *= 1.0e-20 # m^2 @@ -263,9 +263,7 @@ def setPsaapPropertiesTestJP(gam, inputV0, inputVDC, params, Nr, iSample): Nsample = 72 N300 = 200 - # FIXME: this assumes the rxn rate files live in a sub dir - # of where we are running. It should be generalized. - root_dir = "./" + root_dir = "/g/g92/jbarbere/glowDischarge/toyProblems/timeDomain" rate_file = "{0:s}/BOLSIGChemistry/reaction300K_{1:d}.dat".format(root_dir, i) temp_file = "{0:s}/BOLSIGChemistry/reaction300K.Te.dat".format(root_dir) diff --git a/psaapPropertiesTestJP_Arrhenius.py b/psaapPropertiesTestJP_Arrhenius.py new file mode 100755 index 000000000..84b12f6e5 --- /dev/null +++ b/psaapPropertiesTestJP_Arrhenius.py @@ -0,0 +1,373 @@ +import numpy as np +from scipy.interpolate import CubicSpline +import csv +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors + +import logging + +class Reaction(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +def setPsaapPropertiesTestJP_Arrhenius(gam, inputV0, inputVDC, params, Nr, iSample): + """Sets non-dimensional properties corresponding to Liu 2014 paper. + + Inputs: + gam : Secondary electron emission coefficient + params : chebSolver.modelParams class + + Outputs: None + params data is overwritten using values from Liu 2014. + """ + ################################################################### + # User specified parameters (you may change these if you wish to + # run a different scenario from Liu 2014) + ################################################################### + + # densities + nAr = 3.22e22 # background number density of Ar [1/m^3] (corresponds to p=100 mTorr) + np0 = 8e16 # "nominal" electron density [1/m^3] + + # masses + # me = 9.10938356e-31 # mass of an electron [kg] + # me = 5.489e-4 # mass of an electron [u] + me = 0.511e6 # mass of an electron [eV/c2] + # mAr = 39.948 # mass of an argon atom [u] + # mAr = 39.948 * 1.66054e-27 # mass of an argon atom [kg] + mAr = 37.2158e9 # mass of an electron [eV/c2] + # u = 931.4941e6 # eV/c2 + c = 299792458 # speed of light [m/s] + se = 40 # momentum cross section [A^2] + + # nominal electron energy + e0 = 1.0 # [eV] + + # pressure + p = 133.3224*1.5 # [J/m^3] *1.5 to convert it to energy (1 Torr) + + # gas energy at the wall + Tg0 = 0.038778 # 3/2*300K*kB ~ (p0 - nT[:,0])/ntot + + # characteristics of driving voltage + V0 = inputV0 # amplitude of driving voltage [V] + verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) + tau = (1./13.56e6) # period of driving voltage [s] + L = 2.00*0.005 # half-gap-width [m] (gap width is 2 cm) + electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) + + # transport parameters + nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] + #nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + #nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + # / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nmum = 0.0 + nmui = 8.0e19 + #nmum = 9.35e19 + nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] + nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] + nDm = 2.42e18 # argon number density times metastable diffusivity [1/(cm*s)] + #nDm = 3.914e20 + + # reaction parameters (NB: k_i = Ck*Ee^B*exp(-A/Ee)) + # Ee = 3/2*Te (Te in eV) + # -> k_i = [Ck*(2/3)^B] * Ee^B * exp[-(3/2)*A/Ee] + # nominal + Ck = np.array([1.235e-7,3.712e-8,2.05e-7,4.0e-13,5.0e-10,4.3e-10,2.1e-15,10.0,5.0e-27]) # pre-exponential factors [cm^3/s] + B = np.array([0.0,0.0,0.0,-0.5,0.0,0.74,0.0,0.0,-4.5]) + A = np.array([18.687,15.06,4.95,0.0,0.0,0.0,0.0,0.0,0.0]) # activation temperature [eV] + dH = np.array([15.76,11.56,4.2,0.0,-7.56,-11.56,-11.56,0.0,-4.2]) # energy lost per electron due to ionization rxn [eV] + dEps = np.array([0.0,15.76,11.56,0.0]) + + # BC parameters + # ks = 1.19e7 # electron recombination rate [cm/s] + ks = 1.366109824889323e7 # electron recombination rate [cm/s/eV] + + ################################################################### + # Constants of nature (probably shouldn't change unless you have + # root privileges on universe) + ################################################################### + qe = 1.6e-19 # unit charge [C] + eps0 = 8.86e-12 # permittivity of free space [F/m] + kB = 1.38e-23 # Boltzmann constant [J/K] + # kB = 8.62e−5 # Boltzmann constant [eV/K] + + + ################################################################### + # Calculate non-dimensional parameters + ################################################################### + + # 1) Convert input units to base SI (except eV) + nDe *= 100. # 1/(m*s) + nDi *= 100. # 1/(m*s) + nDm *= 100. + nmue *= 100. # 1/(V*m*s) + nmui *= 100. # 1/(V*m*s) + Ck[0:7] *= 1e-6 # m^3/s + Ck[7] *= 1 # 1/s + Ck[8] *= 1e-12 # m^6/s + # Ck[7] *= 1e-6 # Ck[7] is now in m^6/s + ks *= 0.01 # m/s + se *= 1.0e-20 # m^2 + + # 2) Compute "raw" transport parameters + De = nDe/nAr + Di = nDi/nAr + Dm = nDm/nAr + + mue = nmue/nAr + mui = nmui/nAr + mum = nmum/nAr + + # 3) Compute non-dimensional properties required by solver + De = De*tau/(L*L) + Di = Di*tau/(L*L) + Dm = Dm*tau/(L*L) + + mue = mue*V0*tau/(L*L) + mui = mui*V0*tau/(L*L) + mum = mum*V0*tau/(L*L) + + Ck[0:2] = Ck[0:2]*tau*nAr + #Ck[2:5] = Ck[2:5]*tau*np0 + Ck[2:6] = Ck[2:6]*tau*np0 + Ck[6] *= tau*nAr + Ck[7] *= tau + Ck[8] *= tau*np0*np0 + # Ck[7] *= tau*nAr*nAr + A = A*1.5/e0 # 1.5 to convert from temperature to energy + dH = dH/e0 + qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V + alpha = qe*np0*L*L/(V0*eps0) + ks = ks*tau/L + p0 = p/qe/np0 + kappaB = 4.878171165833662*1.6129 # non-dimensional thermal conductivity of background specie + # (2/3)*tau/L**2*Kb/np0/kB, + # where Kb is the thermal conductivity of background specie + + #params.beta = np.array([[2,2,2,1,1],[1,0,1,0,0],[0,1,0,0,0],[0,0,0,1,1]]) + #params.alfa = np.array([[1,1,1,1,1],[0,0,0,0,0],[0,0,1,1,1],[1,1,0,0,0]]) + #params.beta = np.array([[2,1,2,1],[1,0,1,0],[0,1,0,0],[0,0,0,1]], dtype=np.int) + #params.alfa = np.array([[1,1,1,1],[0,0,0,0],[0,0,1,1],[1,1,0,0]], dtype=np.int) + # params.beta = np.array([[2,1,2,1,1,1,0,0],[1,0,1,0,0,1,0,0],[0,1,0,0,0,0,0,0],[0,0,0,1,0,1,2,1]], dtype=np.int64) + # params.alfa = np.array([[1,1,1,1,1,0,0,0],[0,0,0,0,0,0,0,0],[0,0,1,1,1,2,1,1],[1,1,0,0,0,0,1,2]], dtype=np.int64) + params.beta = np.array([[2,1,2,0,1,1,0,0,1],[1,0,1,0,1,0,0,0,0],[0,1,0,1,0,0,0,0,1],[0,0,0,0,1,1,2,1,0]], dtype=np.int64) + params.alfa = np.array([[1,1,1,1,0,1,0,0,2],[0,0,0,1,0,0,0,0,1],[0,0,1,0,2,1,1,1,0],[1,1,0,0,0,0,1,0,0]], dtype=np.int64) + # Rxn1: E + AR -> 2E + AR+ + # Rxn2: E + AR -> E + AR* + # Rxn3: E + AR* -> 2E + AR+ + # Rxn4: E + AR+ -> AR* + # Rxn5: 2AR* -> E + AR+ + AR + # Rxn6: E + AR* -> E + AR + # Rxn7: AR* + AR -> 2AR + # Rxn8: AR* -> AR + # Rxn9: 2E + AR+ -> E + AR* + + # 4) Set values in params class + params.D[0] = De + params.D[1] = Di + params.D[2] = Dm + + params.mu[0] = mue + params.mu[1] = mui + params.mu[2] = mum + + params.A[:] = Ck[:] + params.B[:] = B[:] + params.C[:] = A[:] + + # Account for the 2/3 term to convert from electron temperature to electron energy + for i in range(len(params.A)): + params.A[i] *= (2/3)**(params.B[i]) + + params.dH[:] = dH[:] + params.dEps[:] = dEps[:] + params.qStar = qStar + params.alpha = alpha + params.ks = ks + params.gam = gam + params.kappaB = kappaB + params.nAronp0 = nAr / np0 + params.p0 = p0 + params.Tg0 = Tg0 + params.EC = 2.0 * me / mAr \ + * np.sqrt(16.0 * (me + mAr) * e0 * c**2 + / (3.0 * np.pi * me * mAr)) * se * nAr * tau + # params.EC = 2.0 * me / mAr * 3.8e9 * tau + + params.verticalShift = verticalShift / V0 + + # Parameters needed to compute the current with dimensions + params.V0Ltau = V0 / (L * tau) + params.V0L = V0 / L + params.LLV0tau = (L*L) / (V0*tau) + params.tauL = L / tau + params.np0 = np0 # "nominal" electron density [1/m^3] + params.qe = qe # unit charge [C] + params.eps0 = eps0 # unit charge [C] + params.eArea = electrodeArea # electrode area [m^2] + + # reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + # f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + # f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + # f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + # f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + # f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + # f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + # f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)"] + + # reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + # f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + # f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + # f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + # f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + # f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + # f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + # f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)"] + + reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)", + f"{params.A[8]} * energy**{params.B[8]} * np.exp(-{params.C[8]} / energy)"] + + reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)", + f"{params.A[8]} * (energy**({params.B[8]}-1)) * np.exp(-{params.C[8]}/energy) * ({params.B[8]} + {params.C[8]}/energy)"] + + reactionExpressionTypelist = np.array([False,False,False,False,False,False,False,False,False]) + + reactionsList = [] + LOGFilename = 'interpolationSample%s.log'%str(iSample) + f = open(LOGFilename, 'w') + # import h5py as h5 + # rxnName = ["Ionization", ...] <- dictionary containing reaction name root string + # for r in range(Nr): + # if reactionExpressionTypeList[r]: + # fileName = "{0:s}.{1:08d}.h5".format(rxnName[r], iSample) + # f = h5.File(filename, "r") + # D = f["table"] + + for i in range(Nr): + if reactionExpressionTypelist[i]: + Nsample = 1 + N300 = 200 + + root_dir = ".." + rate_file = open("{0:s}/BOLSIGChemistry_NominalRates/reaction300K_{1:d}.txt".format(root_dir, i), 'r') + temp_file = open("{0:s}/BOLSIGChemistry_NominalRates/reaction300K_Te.txt".format(root_dir), 'r') + + #rateCoeff = np.fromfile(rate_file) + rateCoeff = np.genfromtxt(rate_file) + rate_file.close() + rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + + #Te = np.fromfile(temp_file) + Te = np.genfromtxt(temp_file) + temp_file.close() + Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy. + Te *= 1.5 + + # Find first non-zero value of the coefficient rate. + I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + lastFalse = np.where(indices==False)[-1][-1] + 2 + + # Transformation to log scale. + TeLog = np.log(Te) + + # Compute the slope of the rate coefficient between its first two non-zero values. + # Finite differences are used. + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) + + # Arrhenius form: kf = A * exp(-C / Te) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + + # Compute pre-exponential coefficient, A, in log scale. + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] + + # Transform rate coefficient in log scale. + rateCoeffLog = np.zeros(rateCoeff.shape) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) + # For the troublesome values, we use the Arrhenius form. + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] + # Nondimensionalization in log scale. + if i < 2: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + else: + rateCoeffLog += - np.log(1.0/tau) + np.log(np0) + + # Interpolation in log scale. + reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) + # Gradient in log scale + reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf_log = reactionExpressionsLog, + kf_T_log = reactionTExpressionsLog) + reactionsList.append(reaction) + + logging.basicConfig(filename=LOGFilename) + logging.warning('Interpolation info (Reaction %s):', i) + logging.warning('First non-zero entry in the rate coefficient: %s', I[0][0]) + logging.warning('Monotonicity of the rate coefficient start from entry: %s', lastFalse) + logging.warning('Position of possible duplicates in mean energy array: %s', + TeDuplicateindsForLog[0]) + + else: + rxn = eval("lambda energy :" + reactionExpressionslist[i]) + rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf = rxn, kf_T = rxn_T) + reactionsList.append(reaction) + + params.reactionsList = reactionsList + + # 5) Dump to screen + params.print() diff --git a/psaapPropertiesTestJP_Nominal.py b/psaapPropertiesTestJP_Nominal.py index bb60d2663..8b8ce532b 100755 --- a/psaapPropertiesTestJP_Nominal.py +++ b/psaapPropertiesTestJP_Nominal.py @@ -42,7 +42,7 @@ def setPsaapPropertiesTestJP_Nominal(gam, inputV0, inputVDC, params, Nr, iSample mAr = 37.2158e9 # mass of an electron [eV/c2] # u = 931.4941e6 # eV/c2 c = 299792458 # speed of light [m/s] - se = 40 # momentum cross section [m^2] + se = 40 # momentum cross section [A^2] # nominal electron energy e0 = 1.0 # [eV] @@ -56,27 +56,31 @@ def setPsaapPropertiesTestJP_Nominal(gam, inputV0, inputVDC, params, Nr, iSample # characteristics of driving voltage V0 = inputV0 # amplitude of driving voltage [V] verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) - tau = (1./13.6e6) # period of driving voltage [s] - L = 2.00*0.005 # half-gap-width [m] (gap width is 2.54cm) + tau = (1./13.56e6) # period of driving voltage [s] + L = 2.00*0.005 # half-gap-width [m] (gap width is 2 cm) electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) # transport parameters nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] - nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] - nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 - / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + #nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + #nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + # / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nmum = 0.0 + nmui = 8.0e19 + #nmum = 9.35e19 nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] nDm = 2.42e18 # argon number density times metastable diffusivity [1/(cm*s)] + #nDm = 3.914e20 # reaction parameters (NB: k_i = Ck*Ee^B*exp(-A/Ee)) # Ee = 3/2*Te (Te in eV) # -> k_i = [Ck*(2/3)^B] * Ee^B * exp[-(3/2)*A/Ee] # nominal Ck = np.array([1.235e-7,3.712e-8,2.05e-7,4.0e-13,5.0e-10,4.3e-10,2.1e-15,10.0,5.0e-27]) # pre-exponential factors [cm^3/s] - B = np.array([0.0,0.0,0.0,-0.5,0,0.74,0,0,-4.5]) + B = np.array([0.0,0.0,0.0,-0.5,0.0,0.74,0.0,0.0,-4.5]) A = np.array([18.687,15.06,4.95,0.0,0.0,0.0,0.0,0.0,0.0]) # activation temperature [eV] - dH = np.array([15.76,11.56,4.2,0.0,-11.56,-7.56,-11.56,0.0,-4.2]) # energy lost per electron due to ionization rxn [eV] + dH = np.array([15.76,11.56,4.2,0.0,-7.56,-11.56,-11.56,0.0,-4.2]) # energy lost per electron due to ionization rxn [eV] dEps = np.array([0.0,15.76,11.56,0.0]) # BC parameters @@ -129,12 +133,10 @@ def setPsaapPropertiesTestJP_Nominal(gam, inputV0, inputVDC, params, Nr, iSample mum = mum*V0*tau/(L*L) Ck[0:2] = Ck[0:2]*tau*nAr - #Ck[2:5] = Ck[2:5]*tau*np0 Ck[2:6] = Ck[2:6]*tau*np0 Ck[6] *= tau*nAr Ck[7] *= tau Ck[8] *= tau*np0*np0 - # Ck[7] *= tau*nAr*nAr A = A*1.5/e0 # 1.5 to convert from temperature to energy dH = dH/e0 qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V @@ -290,7 +292,7 @@ def setPsaapPropertiesTestJP_Nominal(gam, inputV0, inputVDC, params, Nr, iSample Te = Te[TeDuplicateinds] # Nondimensionalization of mean energy. - # Te *= 1.5 + #Te *= 1.5 # Find first non-zero value of the coefficient rate. I = np.nonzero(rateCoeff) diff --git a/psaapPropertiesWithSampling.py b/psaapPropertiesWithSampling.py index 4381a6570..ce6a6977f 100644 --- a/psaapPropertiesWithSampling.py +++ b/psaapPropertiesWithSampling.py @@ -1,8 +1,8 @@ import numpy as np from scipy.interpolate import CubicSpline -import matplotlib.pyplot as plt -import matplotlib.colors as mcolors +#import matplotlib.pyplot as plt +#import matplotlib.colors as mcolors import logging @@ -237,10 +237,20 @@ def setPsaapPropertiesWithSampling(gam, inputV0, inputVDC, params, Nr, iSample): Nsample = 7200 N300 = 200 - rateCoeff = np.fromfile('./BOLSIGChemistryZeroIonDeg7200Samples/reaction300K_%s.dat' %str(i)) + #rateCoeff = np.fromfile("/g/g92/jbarbere/glowDischarge/toyProblems/timeDomain/BOLSIGChemistryZeroIonDeg7200Samples/reaction300K_%s.dat" %str(i)) + #rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + + #Te = np.fromfile("/g/92/jbarbere/glowDischarge/toyProblems/timeDomain/BOLSIGChemistryZeroIonDeg7200Samples/reaction300K.Te.dat") + #Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + + root_dir = "/g/g92/jbarbere/glowDischarge/toyProblems/timeDomain" + rate_file = "{0:s}/BOLSIGChemistryZeroIonDeg7200Samples/reaction300K_{1:d}.dat".format(root_dir, i) + temp_file = "{0:s}/BOLSIGChemistryZeroIonDeg7200Samples/reaction300K.Te.dat".format(root_dir) + + rateCoeff = np.fromfile(rate_file) rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] - Te = np.fromfile('./BOLSIGChemistryZeroIonDeg7200Samples/reaction300K.Te.dat') + Te = np.fromfile(temp_file) Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] # Sorting mean energy array and rate coefficient array based on diff --git a/psaapProperties_4plus2Species.py b/psaapProperties_4plus2Species.py new file mode 100755 index 000000000..e9f41a1b5 --- /dev/null +++ b/psaapProperties_4plus2Species.py @@ -0,0 +1,374 @@ +import numpy as np +from scipy.interpolate import CubicSpline +import csv +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors + +import logging + +class Reaction(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +def setPsaapProperties_4plus2Species(gam, inputV0, inputVDC, params, Nr, iSample): + """Sets non-dimensional properties corresponding to Liu 2014 paper. + + Inputs: + gam : Secondary electron emission coefficient + params : chebSolver.modelParams class + + Outputs: None + params data is overwritten using values from Liu 2014. + """ + ################################################################### + # User specified parameters (you may change these if you wish to + # run a different scenario from Liu 2014) + ################################################################### + + # densities + nAr = 3.22e22 # background number density of Ar [1/m^3] (corresponds to p=100 mTorr) + np0 = 8e16 # "nominal" electron density [1/m^3] + + # masses + # me = 9.10938356e-31 # mass of an electron [kg] + # me = 5.489e-4 # mass of an electron [u] + me = 0.511e6 # mass of an electron [eV/c2] + # mAr = 39.948 # mass of an argon atom [u] + # mAr = 39.948 * 1.66054e-27 # mass of an argon atom [kg] + mAr = 37.2158e9 # mass of an electron [eV/c2] + # u = 931.4941e6 # eV/c2 + c = 299792458 # speed of light [m/s] + se = 40 # momentum cross section [A^2] + + # nominal electron energy + e0 = 1.0 # [eV] + + # pressure + p = 133.3224*1.5 # [J/m^3] *1.5 to convert it to energy (1 Torr) + + # gas energy at the wall + Tg0 = 0.038778 # 3/2*300K*kB ~ (p0 - nT[:,0])/ntot + + # characteristics of driving voltage + V0 = inputV0 # amplitude of driving voltage [V] + verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) + tau = (1./13.56e6) # period of driving voltage [s] + L = 2.00*0.005 # half-gap-width [m] (gap width is 2 cm) + electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) + + # transport parameters + nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] + #nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + #nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + # / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nmum = 0.0 + nmur = 0.0 + nmu4p = 0.0 + nmui = 8.0e19 + nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] + nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] + nDm = 2.42e18 # argon number density times metastable diffusivity [1/(cm*s)] + nDr = 2.42e18 + nD4p = 2.42e18 + #nDm = 3.914e20 + + # reaction parameters (NB: k_i = Ck*Ee^B*exp(-A/Ee)) + # Ee = 3/2*Te (Te in eV) + # -> k_i = [Ck*(2/3)^B] * Ee^B * exp[-(3/2)*A/Ee] + # nominal + Ck = np.array([1.235e-7,3.712e-8,2.05e-7,4.0e-13,5.0e-10,4.3e-10,2.1e-15,10.0,5.0e-27]) # pre-exponential factors [cm^3/s] + B = np.array([0.0,0.0,0.0,-0.5,0.0,0.74,0.0,0.0,-4.5]) + A = np.array([18.687,15.06,4.95,0.0,0.0,0.0,0.0,0.0,0.0]) # activation temperature [eV] + dH = np.array([15.76,11.56,4.2,0.0,-7.56,-11.56,-11.56,0.0,-4.2]) # energy lost per electron due to ionization rxn [eV] + dEps = np.array([0.0,15.76,11.56,0.0,0.0,0.0]) + + # BC parameters + # ks = 1.19e7 # electron recombination rate [cm/s] + ks = 1.366109824889323e7 # electron recombination rate [cm/s/eV] + + ################################################################### + # Constants of nature (probably shouldn't change unless you have + # root privileges on universe) + ################################################################### + qe = 1.6e-19 # unit charge [C] + eps0 = 8.86e-12 # permittivity of free space [F/m] + kB = 1.38e-23 # Boltzmann constant [J/K] + # kB = 8.62e-5 # Boltzmann constant [eV/K] + + + ################################################################### + # Calculate non-dimensional parameters + ################################################################### + + # 1) Convert input units to base SI (except eV) + nDe *= 100. # 1/(m*s) + nDi *= 100. # 1/(m*s) + nDm *= 100. + nDr *= 100. + nD4p *= 100. + nmue *= 100. # 1/(V*m*s) + nmui *= 100. # 1/(V*m*s) + Ck[0:7] *= 1e-6 # m^3/s + Ck[7] *= 1 # 1/s + Ck[8] *= 1e-12 # m^6/s + ks *= 0.01 # m/s + se *= 1.0e-20 # m^2 + + # 2) Compute "raw" transport parameters + De = nDe/nAr + Di = nDi/nAr + Dm = nDm/nAr + Dr = nDr/nAr + D4p = nD4p/nAr + + mue = nmue/nAr + mui = nmui/nAr + mum = nmum/nAr + mur = nmur/nAr + mu4p = nmu4p/nAr + + # 3) Compute non-dimensional properties required by solver + De = De*tau/(L*L) + Di = Di*tau/(L*L) + Dm = Dm*tau/(L*L) + Dr = Dr*tau/(L*L) + D4p = D4p*tau/(L*L) + + mue = mue*V0*tau/(L*L) + mui = mui*V0*tau/(L*L) + mum = mum*V0*tau/(L*L) + mur = mur*V0*tau/(L*L) + mu4p = mu4p*V0*tau/(L*L) + + Ck[0:2] = Ck[0:2]*tau*nAr + Ck[2:6] = Ck[2:6]*tau*np0 + Ck[6] *= tau*nAr + Ck[7] *= tau + Ck[8] *= tau*np0*np0 + A = A*1.5/e0 # 1.5 to convert from temperature to energy + dH = dH/e0 + qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V + alpha = qe*np0*L*L/(V0*eps0) + ks = ks*tau/L + p0 = p/qe/np0 + kappaB = 4.878171165833662*1.6129 # non-dimensional thermal conductivity of background specie + # (2/3)*tau/L**2*Kb/np0/kB, + # where Kb is the thermal conductivity of background specie + + params.beta = np.array([[2,1,2,0,1,1,0,0,1], + [1,0,1,0,1,0,0,0,0], + [0,1,0,1,0,0,0,0,1], + [0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0], + [0,0,0,0,1,1,2,1,0]], dtype=np.int64) + params.alfa = np.array([[1,1,1,1,0,1,0,0,2], + [0,0,0,1,0,0,0,0,1], + [0,0,1,0,2,1,1,1,0], + [0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0], + [1,1,0,0,0,0,1,0,0]], dtype=np.int64) + # Rxn1: E + AR -> 2E + AR+ + # Rxn2: E + AR -> E + AR* + # Rxn3: E + AR* -> 2E + AR+ + # Rxn4: E + AR+ -> AR* + # Rxn5: 2AR* -> E + AR+ + AR + # Rxn6: E + AR* -> E + AR + # Rxn7: AR* + AR -> 2AR + # Rxn8: AR* -> AR + # Rxn9: 2E + AR+ -> E + AR* + + # 4) Set values in params class + params.D[0] = De + params.D[1] = Di + params.D[2] = Dm + params.D[3] = Dr + params.D[4] = D4p + + params.mu[0] = mue + params.mu[1] = mui + params.mu[2] = mum + params.mu[3] = mur + params.mu[4] = mu4p + + params.A[:] = Ck[:] + params.B[:] = B[:] + params.C[:] = A[:] + + # Account for the 2/3 term to convert from electron temperature to electron energy + for i in range(len(params.A)): + params.A[i] *= (2/3)**(params.B[i]) + + params.dH[:] = dH[:] + params.dEps[:] = dEps[:] + params.qStar = qStar + params.alpha = alpha + params.ks = ks + params.gam = gam + params.kappaB = kappaB + params.nAronp0 = nAr / np0 + params.p0 = p0 + params.Tg0 = Tg0 + params.EC = 2.0 * me / mAr \ + * np.sqrt(16.0 * (me + mAr) * e0 * c**2 + / (3.0 * np.pi * me * mAr)) * se * nAr * tau + # params.EC = 2.0 * me / mAr * 3.8e9 * tau + + params.verticalShift = verticalShift / V0 + + # Parameters needed to compute the current with dimensions + params.V0Ltau = V0 / (L * tau) + params.V0L = V0 / L + params.LLV0tau = (L*L) / (V0*tau) + params.tauL = L / tau + params.np0 = np0 # "nominal" electron density [1/m^3] + params.qe = qe # unit charge [C] + params.eps0 = eps0 # unit charge [C] + params.eArea = electrodeArea # electrode area [m^2] + + + reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)", + f"{params.A[8]} * energy**{params.B[8]} * np.exp(-{params.C[8]} / energy)"] + + reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)", + f"{params.A[8]} * (energy**({params.B[8]}-1)) * np.exp(-{params.C[8]}/energy) * ({params.B[8]} + {params.C[8]}/energy)"] + + reactionExpressionTypelist = np.array([True,True,True,False,False,False,False,False,False]) + + reactionsList = [] + LOGFilename = 'interpolationSample%s.log'%str(iSample) + f = open(LOGFilename, 'w') + # import h5py as h5 + # rxnName = ["Ionization", ...] <- dictionary containing reaction name root string + # for r in range(Nr): + # if reactionExpressionTypeList[r]: + # fileName = "{0:s}.{1:08d}.h5".format(rxnName[r], iSample) + # f = h5.File(filename, "r") + # D = f["table"] + + for i in range(Nr): + if reactionExpressionTypelist[i]: + Nsample = 1 + N300 = 200 + + root_dir = ".." + rate_file = open("{0:s}/BOLSIGChemistry_NominalRates/reaction300K_{1:d}.txt".format(root_dir, i), 'r') + temp_file = open("{0:s}/BOLSIGChemistry_NominalRates/reaction300K_Te.txt".format(root_dir), 'r') + + #rateCoeff = np.fromfile(rate_file) + rateCoeff = np.genfromtxt(rate_file) + rate_file.close() + rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + + #Te = np.fromfile(temp_file) + Te = np.genfromtxt(temp_file) + temp_file.close() + Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy. + Te *= 1.5 + + # Find first non-zero value of the coefficient rate. + I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + lastFalse = np.where(indices==False)[-1][-1] + 2 + + # Transformation to log scale. + TeLog = np.log(Te) + + # Compute the slope of the rate coefficient between its first two non-zero values. + # Finite differences are used. + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) + + # Arrhenius form: kf = A * exp(-C / Te) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + + # Compute pre-exponential coefficient, A, in log scale. + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] + + # Transform rate coefficient in log scale. + rateCoeffLog = np.zeros(rateCoeff.shape) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) + # For the troublesome values, we use the Arrhenius form. + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] + # Nondimensionalization in log scale. + if i < 2: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + else: + rateCoeffLog += - np.log(1.0/tau) + np.log(np0) + + # Interpolation in log scale. + reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) + # Gradient in log scale + reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf_log = reactionExpressionsLog, + kf_T_log = reactionTExpressionsLog) + reactionsList.append(reaction) + + logging.basicConfig(filename=LOGFilename) + logging.warning('Interpolation info (Reaction %s):', i) + logging.warning('First non-zero entry in the rate coefficient: %s', I[0][0]) + logging.warning('Monotonicity of the rate coefficient start from entry: %s', lastFalse) + logging.warning('Position of possible duplicates in mean energy array: %s', + TeDuplicateindsForLog[0]) + + else: + rxn = eval("lambda energy :" + reactionExpressionslist[i]) + rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf = rxn, kf_T = rxn_T) + reactionsList.append(reaction) + + params.reactionsList = reactionsList + + # 5) Dump to screen + params.print() diff --git a/psaapProperties_6Species.py b/psaapProperties_6Species.py new file mode 100755 index 000000000..1cf39704d --- /dev/null +++ b/psaapProperties_6Species.py @@ -0,0 +1,430 @@ +import numpy as np +from scipy.interpolate import CubicSpline +import csv +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors + +import logging + +class Reaction(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +def setPsaapProperties_6Species(gam, inputV0, inputVDC, params, Nr, iSample): + """Sets non-dimensional properties corresponding to Liu 2014 paper. + + Inputs: + gam : Secondary electron emission coefficient + params : chebSolver.modelParams class + + Outputs: None + params data is overwritten using values from Liu 2014. + """ + ################################################################### + # User specified parameters (you may change these if you wish to + # run a different scenario from Liu 2014) + ################################################################### + + # densities + nAr = 3.22e22 # background number density of Ar [1/m^3] (corresponds to p=100 mTorr) + np0 = 8e16 # "nominal" electron density [1/m^3] + + # masses + # me = 9.10938356e-31 # mass of an electron [kg] + # me = 5.489e-4 # mass of an electron [u] + me = 0.511e6 # mass of an electron [eV/c2] + # mAr = 39.948 # mass of an argon atom [u] + # mAr = 39.948 * 1.66054e-27 # mass of an argon atom [kg] + mAr = 37.2158e9 # mass of an argon atom [eV/c2] + # u = 931.4941e6 # eV/c2 + c = 299792458 # speed of light [m/s] + se = 40 # momentum cross section [A^2] + + # nominal electron energy + e0 = 1.0 # [eV] + + # pressure + p = 133.3224*1.5 # [J/m^3] *1.5 to convert it to energy (1 Torr) + + # gas energy at the wall + Tg0 = 0.038778 # 3/2*300K*kB ~ (p0 - nT[:,0])/ntot + + # characteristics of driving voltage + V0 = inputV0 # amplitude of driving voltage [V] + verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) + tau = (1./13.56e6) # period of driving voltage [s] + L = 2.00*0.005 # half-gap-width [m] (gap width is 2 cm) + electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) + + # transport parameters + nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] + #nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + #nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + # / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nmum = 0.0 + nmur = 0.0 + nmu4p = 0.0 + nmui = 8.0e19 + #nmum = 9.35e19 + nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] + nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] + nDm = 2.42e18 # argon number density times AR(m) diffusivity [1/(cm*s)] + nDr = 2.42e18 + nD4p = 2.42e18 + #nDm = 3.914e20 + + # reaction parameters (NB: k_i = Ck*Ee^B*exp(-A/Ee)) + # Ee = 3/2*Te (Te in eV) + # -> k_i = [Ck*(2/3)^B] * Ee^B * exp[-(3/2)*A/Ee] + # nominal + Ck = np.array([2.0e-7,2.1e-9,5.0e-10,6.4e-10,2.1e-15,1.0e5,3.2e7,3.0e7,3.0e7,0.0,0.0,0.0,0.0,4.3e-10,0.0,3.7e-8,8.9e-7,1.8e-7,3.0e-7,3.0e-7,4.3e-10,9.1e-7,8.9e-7]) # pre-exponential factors [cm^3/s] + B = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0.74,0,0,0.51,0.61,0.51,0.51,0.74,0,0.51]) + A = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.59,2.61,0,0,0,0,1.59]) # activation temperature [eV] + dH = np.array([0.0,-7.412,-10.054,-7.336,0.0,0.0,0.0,0.0,0.0,11.548,11.624,12.907,15.76,-11.548,4.212,0.076,1.359,2.853,-1.283,-1.359,-11.624,-0.076,0.983]) # energy lost per electron due to ionization rxn [eV] + dEps = np.array([0.0,15.76,11.548,11.624,12.907,0.0]) # E, AR+, AR(m), AR(r), AR(4p), AR + + # BC parameters + # ks = 1.19e7 # electron recombination rate [cm/s] + ks = 1.366109824889323e7 # electron recombination rate [cm/s/eV] + + ################################################################### + # Constants of nature (probably shouldn't change unless you have + # root privileges on universe) + ################################################################### + qe = 1.6e-19 # unit charge [C] + eps0 = 8.86e-12 # permittivity of free space [F/m] + kB = 1.38e-23 # Boltzmann constant [J/K] + # kB = 8.62e-5 # Boltzmann constant [eV/K] + + + ################################################################### + # Calculate non-dimensional parameters + ################################################################### + + # 1) Convert input units to base SI (except eV) + nDe *= 100. # 1/(m*s) + nDi *= 100. # 1/(m*s) + nDm *= 100. + nDr *= 100. + nD4p *= 100. + nmue *= 100. # 1/(V*m*s) + nmui *= 100. # 1/(V*m*s) + Ck[0:5] *= 1e-6 # m^3/s + Ck[5:9] *= 1 # 1/s + Ck[9:22] *= 1e-6 # m^3/s + ks *= 0.01 # m/s + se *= 1.0e-20 # m^2 + + # 2) Compute "raw" transport parameters + De = nDe/nAr + Di = nDi/nAr + Dm = nDm/nAr + Dr = nDr/nAr + D4p = nD4p/nAr + + mue = nmue/nAr + mui = nmui/nAr + mum = nmum/nAr + mur = nmur/nAr + mu4p = nmu4p/nAr + + # 3) Compute non-dimensional properties required by solver + De = De*tau/(L*L) + Di = Di*tau/(L*L) + Dm = Dm*tau/(L*L) + Dr = Dr*tau/(L*L) + D4p = D4p*tau/(L*L) + + mue = mue*V0*tau/(L*L) + mui = mui*V0*tau/(L*L) + mum = mum*V0*tau/(L*L) + mur = mur*V0*tau/(L*L) + mu4p = mu4p*V0*tau/(L*L) + + Ck[0:4] = Ck[0:4]*tau*np0 + Ck[4] = Ck[4]*tau*nAr + Ck[5:9] *= tau + Ck[9:13] = Ck[9:13]*tau*nAr + Ck[13:] = Ck[13:]*tau*np0 + A = A*1.5/e0 # 1.5 to convert from temperature to energy + dH = dH/e0 + qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V + alpha = qe*np0*L*L/(V0*eps0) + ks = ks*tau/L + p0 = p/qe/np0 + kappaB = 4.878171165833662*1.6129 # non-dimensional thermal conductivity of background specie + # (2/3)*tau/L**2*Kb/np0/kB, + # where Kb is the thermal conductivity of background specie + + params.beta = np.array([[0,1,1,1,0,0,0,0,0,1,1,1,2,1,2,1,1,2,1,1,1,1,1], # E + [0,1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0], # AR+ + [0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0], # AR(m) + [0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,0,0,0], # AR(r) + [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1], # AR(4p) + [2,1,1,1,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0]], dtype=np.int64) # AR + + params.alfa = np.array([[0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1], # E + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], # AR+ + [2,1,0,2,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0], # AR(m) + [0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1], # AR(r) + [0,0,2,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0], # AR(4p) + [0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0]], dtype=np.int64) # AR + # Rxn1: 2AR(m) -> 2AR + # Rxn2: AR(m) + AR(r) -> E + AR+ + AR + # Rxn3: 2AR(4p) -> E + AR+ + AR + # Rxn4: 2AR(m) -> E + AR+ + AR + # Rxn5: AR(m) + AR -> 2AR + # Rxn6: AR(r) -> AR + # Rxn7: AR(4p) -> AR + # Rxn8: AR(4p) -> AR(m) + # Rxn9: AR(4p) -> AR(r) + # Rxn10: E + AR -> E + AR(m) + # Rxn11: E + AR -> E + AR(r) + # Rxn12: E + AR -> E + AR(4p) + # Rxn13: E + AR -> 2E + AR+ + # Rxn14: E + AR(m) -> E + AR + # Rxn15: E + AR(m) -> 2E + AR+ + # Rxn16: E + AR(m) -> E + AR(r) + # Rxn17: E + AR(m) -> E + AR(4p) + # Rxn18: E + AR(4p) -> 2E + AR+ + # Rxn19: E + AR(4p) -> E + AR(r) + # Rxn20: E + AR(4p) -> E + AR(m) + # Rxn21: E + AR(r) -> E + AR + # Rxn22: E + AR(r) -> E + AR(m) + # Rxn23: E + AR(r) -> E + AR(4p) + + # 4) Set values in params class + params.D[0] = De + params.D[1] = Di + params.D[2] = Dm + params.D[3] = Dr + params.D[4] = D4p + + params.mu[0] = mue + params.mu[1] = mui + params.mu[2] = mum + params.mu[3] = mur + params.mu[4] = mu4p + + params.A[:] = Ck[:] + params.B[:] = B[:] + params.C[:] = A[:] + + # Account for the 2/3 term to convert from electron temperature to electron energy + for i in range(len(params.A)): + params.A[i] *= (2/3)**(params.B[i]) + + params.dH[:] = dH[:] + params.dEps[:] = dEps[:] + params.qStar = qStar + params.alpha = alpha + params.ks = ks + params.gam = gam + params.kappaB = kappaB + params.nAronp0 = nAr / np0 + params.p0 = p0 + params.Tg0 = Tg0 + params.EC = 2.0 * me / mAr \ + * np.sqrt(16.0 * (me + mAr) * e0 * c**2 + / (3.0 * np.pi * me * mAr)) * se * nAr * tau + # params.EC = 2.0 * me / mAr * 3.8e9 * tau + + params.verticalShift = verticalShift / V0 + + # Parameters needed to compute the current with dimensions + params.V0Ltau = V0 / (L * tau) + params.V0L = V0 / L + params.LLV0tau = (L*L) / (V0*tau) + params.tauL = L / tau + params.np0 = np0 # "nominal" electron density [1/m^3] + params.qe = qe # unit charge [C] + params.eps0 = eps0 # unit charge [C] + params.eArea = electrodeArea # electrode area [m^2] + + + reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)", + f"{params.A[8]} * energy**{params.B[8]} * np.exp(-{params.C[8]} / energy)", + f"{params.A[9]} * energy**{params.B[9]} * np.exp(-{params.C[9]} / energy)", + f"{params.A[10]} * energy**{params.B[10]} * np.exp(-{params.C[10]} / energy)", + f"{params.A[11]} * energy**{params.B[11]} * np.exp(-{params.C[11]} / energy)", + f"{params.A[12]} * energy**{params.B[12]} * np.exp(-{params.C[12]} / energy)", + f"{params.A[13]} * energy**{params.B[13]} * np.exp(-{params.C[13]} / energy)", + f"{params.A[14]} * energy**{params.B[14]} * np.exp(-{params.C[14]} / energy)", + f"{params.A[15]} * energy**{params.B[15]} * np.exp(-{params.C[15]} / energy)", + f"{params.A[16]} * energy**{params.B[16]} * np.exp(-{params.C[16]} / energy)", + f"{params.A[17]} * energy**{params.B[17]} * np.exp(-{params.C[17]} / energy)", + f"{params.A[18]} * energy**{params.B[18]} * np.exp(-{params.C[18]} / energy)", + f"{params.A[19]} * energy**{params.B[19]} * np.exp(-{params.C[19]} / energy)", + f"{params.A[20]} * energy**{params.B[20]} * np.exp(-{params.C[20]} / energy)", + f"{params.A[21]} * energy**{params.B[21]} * np.exp(-{params.C[21]} / energy)", + f"{params.A[22]} * energy**{params.B[22]} * np.exp(-{params.C[22]} / energy)"] + + reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)", + f"{params.A[8]} * (energy**({params.B[8]}-1)) * np.exp(-{params.C[8]}/energy) * ({params.B[8]} + {params.C[8]}/energy)", + f"{params.A[9]} * (energy**({params.B[9]}-1)) * np.exp(-{params.C[9]}/energy) * ({params.B[9]} + {params.C[9]}/energy)", + f"{params.A[10]} * (energy**({params.B[10]}-1)) * np.exp(-{params.C[10]}/energy) * ({params.B[10]} + {params.C[10]}/energy)", + f"{params.A[11]} * (energy**({params.B[11]}-1)) * np.exp(-{params.C[11]}/energy) * ({params.B[11]} + {params.C[11]}/energy)", + f"{params.A[12]} * (energy**({params.B[12]}-1)) * np.exp(-{params.C[12]}/energy) * ({params.B[12]} + {params.C[12]}/energy)", + f"{params.A[13]} * (energy**({params.B[13]}-1)) * np.exp(-{params.C[13]}/energy) * ({params.B[13]} + {params.C[13]}/energy)", + f"{params.A[14]} * (energy**({params.B[14]}-1)) * np.exp(-{params.C[14]}/energy) * ({params.B[14]} + {params.C[14]}/energy)", + f"{params.A[15]} * (energy**({params.B[15]}-1)) * np.exp(-{params.C[15]}/energy) * ({params.B[15]} + {params.C[15]}/energy)", + f"{params.A[16]} * (energy**({params.B[16]}-1)) * np.exp(-{params.C[16]}/energy) * ({params.B[16]} + {params.C[16]}/energy)", + f"{params.A[17]} * (energy**({params.B[17]}-1)) * np.exp(-{params.C[17]}/energy) * ({params.B[17]} + {params.C[17]}/energy)", + f"{params.A[18]} * (energy**({params.B[18]}-1)) * np.exp(-{params.C[18]}/energy) * ({params.B[18]} + {params.C[18]}/energy)", + f"{params.A[19]} * (energy**({params.B[19]}-1)) * np.exp(-{params.C[19]}/energy) * ({params.B[19]} + {params.C[19]}/energy)", + f"{params.A[20]} * (energy**({params.B[20]}-1)) * np.exp(-{params.C[20]}/energy) * ({params.B[20]} + {params.C[20]}/energy)", + f"{params.A[21]} * (energy**({params.B[21]}-1)) * np.exp(-{params.C[21]}/energy) * ({params.B[21]} + {params.C[21]}/energy)", + f"{params.A[22]} * (energy**({params.B[22]}-1)) * np.exp(-{params.C[22]}/energy) * ({params.B[22]} + {params.C[22]}/energy)"] + + + reactionExpressionTypelist = np.array([False,False,False,False,False,False,False,False,False, + True,True,True,True,False,True,False,False,False,False,False,False,False,False]) + + reactionsList = [] + LOGFilename = 'interpolationSample%s.log'%str(iSample) + f = open(LOGFilename, 'w') + # import h5py as h5 + # rxnName = ["Ionization", ...] <- dictionary containing reaction name root string + # for r in range(Nr): + # if reactionExpressionTypeList[r]: + # fileName = "{0:s}.{1:08d}.h5".format(rxnName[r], iSample) + # f = h5.File(filename, "r") + # D = f["table"] + + for i in range(Nr): + if reactionExpressionTypelist[i]: + Nsample = 1 + N300 = 200 + + root_dir = ".." + rate_file = open("{0:s}/BOLSIGChemistry_6SpeciesRates/reaction300K_{1:d}.txt".format(root_dir, i), 'r') + temp_file = open("{0:s}/BOLSIGChemistry_6SpeciesRates/reaction300K_Te.txt".format(root_dir), 'r') + + #rateCoeff = np.fromfile(rate_file) + rateCoeff = np.genfromtxt(rate_file) + rate_file.close() + rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + + #Te = np.fromfile(temp_file) + Te = np.genfromtxt(temp_file) + temp_file.close() + Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy. + Te *= 1.5 + + # Find first non-zero value of the coefficient rate. + I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + + #lastFalse = np.where(indices==False)[-1][-1] + 2 + for k in range(len(Te)): + if Te[k] < 4.5 and indices[k] == False: + lastFalse = k + 2 + + # Transformation to log scale. + TeLog = np.log(Te) + + # Compute the slope of the rate coefficient between its first two non-zero values. + # Finite differences are used. + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) + + # Arrhenius form: kf = A * exp(-C / Te) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + + # Compute pre-exponential coefficient, A, in log scale. + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] + + # Transform rate coefficient in log scale. + rateCoeffLog = np.zeros(rateCoeff.shape) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) + # For the troublesome values, we use the Arrhenius form. + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] + # Nondimensionalization in log scale. + if i == 9: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + elif i == 10: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + elif i == 11: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + elif i == 12: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + else: + rateCoeffLog += - np.log(1.0/tau) + np.log(np0) + + # Interpolation in log scale. + reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) + # Gradient in log scale + reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf_log = reactionExpressionsLog, + kf_T_log = reactionTExpressionsLog) + reactionsList.append(reaction) + + logging.basicConfig(filename=LOGFilename) + logging.warning('Interpolation info (Reaction %s):', i + 1) + logging.warning('First non-zero entry in the rate coefficient: %s', I[0][0]) + logging.warning('Monotonicity of the rate coefficient start from entry: %s', lastFalse) + logging.warning('Position of possible duplicates in mean energy array: %s', + TeDuplicateindsForLog[0]) + + else: + rxn = eval("lambda energy :" + reactionExpressionslist[i]) + rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf = rxn, kf_T = rxn_T) + reactionsList.append(reaction) + + params.reactionsList = reactionsList + + # 5) Dump to screen + params.print() diff --git a/timePeriodicSolver.py b/timePeriodicSolver.py index a19172eb3..731017caa 100644 --- a/timePeriodicSolver.py +++ b/timePeriodicSolver.py @@ -191,6 +191,13 @@ def solveNewtonStep(self, Uic, Nt): elif(args.scenario==7): print("# Running scenario = 7 (4 species, 9 rxn, Nominal Reaction Rates)") Ns = 4 + elif(args.scenario==8): + Ns = 4 + elif(args.scenario==9): + print("# Running scenario = 9 (6 species, 23 rxn)") + Ns = 6 + elif(args.scenario==10): + Ns = 6 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 From 6a5ba279a57797ec528a5910336f317547430845 Mon Sep 17 00:00:00 2001 From: Juan Pablo Barberena Valencia Date: Sat, 1 Oct 2022 10:13:20 -0700 Subject: [PATCH 15/32] Fixed Dirichlet BCs on Jacobians and Residuals --- .../slurm-11631700.out | 1 + chebSolver.py | 72 +++++++++---------- 2 files changed, 37 insertions(+), 36 deletions(-) create mode 100644 6Species_Nominal_Collisions/slurm-11631700.out diff --git a/6Species_Nominal_Collisions/slurm-11631700.out b/6Species_Nominal_Collisions/slurm-11631700.out new file mode 100644 index 000000000..29bf14913 --- /dev/null +++ b/6Species_Nominal_Collisions/slurm-11631700.out @@ -0,0 +1 @@ +Run 0 to 200...restart_6spec_CN_Np250_T200.npy diff --git a/chebSolver.py b/chebSolver.py index 4ac4425f0..5893251c6 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -873,22 +873,6 @@ def residualCN(self, Uin, time, dt, weak_bc=False): res[ self.Ns*self.Np-1 ] = dens[ -1,self.Ns-1] \ - ((self.params.p0 - nT[ -1]) / self.params.Tg0 - ntot[-1]) / self.params.nAronp0 - if (self.Ns == 6): # Dirichlet BCs for AR(m), AR(r) and AR(4p) in the 6-species mechanism - #res[2*self.Np ] = dens[ 0,2] - 0.0 - #res[3*self.Np-1] = dens[-1,2] - 0.0 - res[3*self.Np ] = dens[ 0,3] - 0.0 - res[4*self.Np-1] = dens[-1,3] - 0.0 - res[4*self.Np ] = dens[ 0,4] - 0.0 - res[5*self.Np-1] = dens[-1,4] - 0.0 - - - # enforce Dirichlet condition on heavy species temperature - ntot = np.zeros(self.Np) - - # add all heavies but background - for i in range(1, self.Ns-1): - ntot += dens[:,i] - # electron temperature res[self.Ns*self.Np ] = (nT[ 0] - self.params.EeBC*dens[0,iele]) res[(self.Ns+1)*self.Np-1] = (nT[-1] - self.params.EeBC*dens[-1,iele]) @@ -929,17 +913,22 @@ def residualLCN(self, Uin, time, dt, weak_bc=False): # change in the associated variables is zero. However, this # *only* works if the IC satisfies the BC. Any errors # introduced by the IC will never be eliminated. - if (self.Ns>2): - res[2*self.Np ] = 0.0 #dens[ 0,2] - 0.0 - res[3*self.Np-1] = 0.0 #dens[-1,2] - 0.0 + #if (self.Ns>2): + # res[2*self.Np ] = 0.0 #dens[ 0,2] - 0.0 + # res[3*self.Np-1] = 0.0 #dens[-1,2] - 0.0 + + if (self.Ns > 2): + for i in range(2, self.Ns-1): + res[i*self.Np ] = res[ 0,i] - 0.0 + res[(i+1)*self.Np-1] = res[-1,i] - 0.0 - if (self.Ns == 6): + #if (self.Ns == 6): #res[2*self.Np ] = 0.0 #res[3*self.Np-1] = 0.0 - res[3*self.Np ] = 0.0 - res[4*self.Np-1] = 0.0 - res[4*self.Np ] = 0.0 - res[5*self.Np-1] = 0.0 + # res[3*self.Np ] = 0.0 + # res[4*self.Np-1] = 0.0 + # res[4*self.Np ] = 0.0 + # res[5*self.Np-1] = 0.0 # electron temperature res[self.Ns*self.Np ] = 0.0 #(nT[ 0] - 0.75*dens[0,iele]) @@ -1338,7 +1327,6 @@ def jacobianBE(self, Uin, time, dt, weak_bc=False, solve_poisson=False): self.jac[(i+1)*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) self.jac[(i+1)*self.Np-1,(i+1)*self.Np-1] = 1.0 - # Dirichlet on heavy species temperature if (self.backgroundSpecieActivationFactor > 0): self.jac[(self.Ns-1)*self.Np,:] = np.zeros((1,self.Nv*self.Np)) @@ -1433,12 +1421,20 @@ def jacobianLCN(self, Uin, time, dt, weak_bc=False): print("Error: Only weak electron flux BCs supported for linearized CN.") exit(-1) - if (self.Ns>2): - self.jac[2*self.Np,:] = np.zeros((1,self.Nv*self.Np)) - self.jac[2*self.Np,2*self.Np] = 1.0 + #if (self.Ns>2): + # self.jac[2*self.Np,:] = np.zeros((1,self.Nv*self.Np)) + # self.jac[2*self.Np,2*self.Np] = 1.0 + + # self.jac[3*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) + # self.jac[3*self.Np-1,3*self.Np-1] = 1.0 + + if (self.Ns > 2): + for i in range(2,self.Ns-1): + self.jac[i*self.Np,:] = np.zeros((1,self.Nv*self.Np)) + self.jac[i*self.Np,i*self.Np] = 1.0 + self.jac[(i+1)*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) + self.jac[(i+1)*self.Np-1,(i+1)*self.Np-1] = 1.0 - self.jac[3*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) - self.jac[3*self.Np-1,3*self.Np-1] = 1.0 self.jac[self.Ns*self.Np,:] = np.zeros((1,self.Nv*self.Np)) self.jac[self.Ns*self.Np,self.Ns*self.Np] = 1.0 @@ -1481,9 +1477,15 @@ def jacobian0(self, time, dt, weak_bc=False): self.jac0[0 ,:] = np.zeros((1,self.Nv*self.Np)) self.jac0[self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) - if (self.Ns>2): - self.jac0[2*self.Np,:] = np.zeros((1,self.Nv*self.Np)) - self.jac0[3*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) + #if (self.Ns>2): + # self.jac0[2*self.Np,:] = np.zeros((1,self.Nv*self.Np)) + # self.jac0[3*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) + + if (self.Ns > 2): + for i in range(2,self.Ns-1): + self.jac0[i*self.Np,:] = np.zeros((1,self.Nv*self.Np)) + self.jac0[(i+1)*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) + # Dirichlet on heavy species temperature if (self.backgroundSpecieActivationFactor > 0): @@ -1972,9 +1974,7 @@ def plot(self, col, create=True): # Default IC (overwritten below if we are restarting) #tds.U1[0:tds.Ns*tds.Np] = 1e-4 - #tds.U1[0:(tds.Ns-1)*tds.Np] = 1e-4 # 'usual' species - tds.U1[0:(tds.Ns-3)*tds.Np] = 1e-4 - tds.U1[(tds.Ns-3)*tds.Np:(tds.Ns-1)*tds.Np] = 0.0 # These two lines added for the 4+2 mechanism... delete otherwise + tds.U1[0:(tds.Ns-1)*tds.Np] = 1e-4 # 'usual' species tds.U1[(tds.Ns-1)*tds.Np:tds.Ns*tds.Np] = 1.0 # background specie tds.U1[tds.Ns*tds.Np:] = tds.params.EeBC*tds.U1[0:tds.Np] # electron energy From d04e49dddaecbcd69045589f3f8863f984442fe0 Mon Sep 17 00:00:00 2001 From: Juan Pablo Barberena Valencia Date: Fri, 7 Oct 2022 10:03:07 -0700 Subject: [PATCH 16/32] Update all files --- .../slurm-11631700.out | 1 - chebSolver.py | 10 +- generate_sample.py | 57 +++ psaapProperties_6Species.py | 42 +- psaapProperties_6Species_Sampling.py | 411 ++++++++++++++++++ 5 files changed, 494 insertions(+), 27 deletions(-) delete mode 100644 6Species_Nominal_Collisions/slurm-11631700.out create mode 100644 generate_sample.py create mode 100755 psaapProperties_6Species_Sampling.py diff --git a/6Species_Nominal_Collisions/slurm-11631700.out b/6Species_Nominal_Collisions/slurm-11631700.out deleted file mode 100644 index 29bf14913..000000000 --- a/6Species_Nominal_Collisions/slurm-11631700.out +++ /dev/null @@ -1 +0,0 @@ -Run 0 to 200...restart_6spec_CN_Np250_T200.npy diff --git a/chebSolver.py b/chebSolver.py index 5893251c6..726395ecf 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -13,7 +13,7 @@ from psaapPropertiesTestJP_Nominal import setPsaapPropertiesTestJP_Nominal from psaapPropertiesTestJP_Arrhenius import setPsaapPropertiesTestJP_Arrhenius from psaapProperties_6Species import setPsaapProperties_6Species -from psaapProperties_4plus2Species import setPsaapProperties_4plus2Species +from psaapProperties_6Species_Sampling import setPsaapProperties_6Species_Sampling class modelClosures: """Class providing model parameters.""" @@ -438,7 +438,7 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, elif(scenario==9): Nr = 23 elif(scenario==10): - Nr = 9 + Nr = 23 elif(scenario==21): Nr = 8 else: @@ -472,7 +472,7 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, elif(scenario==9): setPsaapProperties_6Species(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==10): - setPsaapProperties_4plus2Species(gam, V0, VDC, self.params, Nr, iSample) + setPsaapProperties_6Species_Sampling(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==21): setPsaapPropertiesTestArmInterpTrans(gam, V0, VDC, self.params, Nr, iSample) @@ -919,8 +919,8 @@ def residualLCN(self, Uin, time, dt, weak_bc=False): if (self.Ns > 2): for i in range(2, self.Ns-1): - res[i*self.Np ] = res[ 0,i] - 0.0 - res[(i+1)*self.Np-1] = res[-1,i] - 0.0 + res[i*self.Np ] = 0.0 + res[(i+1)*self.Np-1] = 0.0 #if (self.Ns == 6): #res[2*self.Np ] = 0.0 diff --git a/generate_sample.py b/generate_sample.py new file mode 100644 index 000000000..4c33dc885 --- /dev/null +++ b/generate_sample.py @@ -0,0 +1,57 @@ +import numpy as np +import h5py +import yaml +import argparse +import re + +# reaction units based on the number of reactants. +unitDict = {1: '1/s', 2: 'm3/mol/s', 3: 'm6/mol2/s'} +parser = argparse.ArgumentParser(description = "", formatter_class = argparse.RawTextHelpFormatter) +parser.add_argument('input_file', metavar = 'string', type = str, help = 'filename for an input file.\n') + + +def getNumberOfReactants(equation): + reactants, direction, products = re.split("( => | <=> )", equation) + reactants = re.split(" \+ ", reactants) + return len(reactants) + + +if __name__ == '__main__': + args = parser.parse_args() + with open(args.input_file) as c: + dict_ = yaml.safe_load(c) + + # parse arrhenius-type reactions from the input file. + rxnList = dict_['reactions'] + for rxn in rxnList: + if (rxn['rate_type'] == 'arrhenius'): + print("Equation: %s" % rxn['equation']) + print("Nominal coefficients: %s" % rxn['arrhenius']['coefficients']) + print("%d-body reaction" % getNumberOfReactants(rxn['equation'])) + + # create the directory for samples. + import os + outputDir = dict_['directory'] + if (outputDir != '.'): + os.makedirs(outputDir, exist_ok = True) + + prefix = dict_['prefix'] + error = 0.01* dict_['relative_error'] + nSample = dict_['number_of_samples'] + for k in range(nSample): + filename = '%s/%s.%08d.h5' % (outputDir, prefix, k) + with h5py.File(filename, 'w') as f: + for rxn in rxnList: + if (rxn['rate_type'] =='arrhenius'): + rateUnit = unitDict[getNumberOfReactants(rxn['equation'])] + # Take the nominal value from the input file + coeffs0 = np.array(rxn['arrhenius']['coefficients'], dtype = np.double) + # Add a relative error + coeffs0[0] *= (1.0 + error) ** np.random.normal() + # Create a dataset for the reaction + dset = f.create_dataset(rxn['equation'], (3,), data = coeffs0) + dset.attrs['rate_unit'] = rateUnit + dset.attrs['temperature_unit'] = 'K' + if (k % 10 == 0): + print("%d-th sample generated." % k) + diff --git a/psaapProperties_6Species.py b/psaapProperties_6Species.py index 1cf39704d..e02c158af 100755 --- a/psaapProperties_6Species.py +++ b/psaapProperties_6Species.py @@ -145,11 +145,11 @@ def setPsaapProperties_6Species(gam, inputV0, inputVDC, params, Nr, iSample): mur = mur*V0*tau/(L*L) mu4p = mu4p*V0*tau/(L*L) - Ck[0:4] = Ck[0:4]*tau*np0 - Ck[4] = Ck[4]*tau*nAr - Ck[5:9] *= tau - Ck[9:13] = Ck[9:13]*tau*nAr - Ck[13:] = Ck[13:]*tau*np0 + Ck[0:4] *= tau*np0 + Ck[4] *= tau*nAr + Ck[5:9] *= tau + Ck[9:13] *= tau*nAr + Ck[13:] *= tau*np0 A = A*1.5/e0 # 1.5 to convert from temperature to energy dH = dH/e0 qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V @@ -182,20 +182,20 @@ def setPsaapProperties_6Species(gam, inputV0, inputVDC, params, Nr, iSample): # Rxn7: AR(4p) -> AR # Rxn8: AR(4p) -> AR(m) # Rxn9: AR(4p) -> AR(r) - # Rxn10: E + AR -> E + AR(m) - # Rxn11: E + AR -> E + AR(r) - # Rxn12: E + AR -> E + AR(4p) - # Rxn13: E + AR -> 2E + AR+ - # Rxn14: E + AR(m) -> E + AR - # Rxn15: E + AR(m) -> 2E + AR+ - # Rxn16: E + AR(m) -> E + AR(r) - # Rxn17: E + AR(m) -> E + AR(4p) - # Rxn18: E + AR(4p) -> 2E + AR+ - # Rxn19: E + AR(4p) -> E + AR(r) - # Rxn20: E + AR(4p) -> E + AR(m) - # Rxn21: E + AR(r) -> E + AR - # Rxn22: E + AR(r) -> E + AR(m) - # Rxn23: E + AR(r) -> E + AR(4p) + # Rxn10: E + AR -> E + AR(m) + # Rxn11: E + AR -> E + AR(r) + # Rxn12: E + AR -> E + AR(4p) + # Rxn13: E + AR -> 2E + AR+ + # Rxn14: E + AR(m) -> E + AR + # Rxn15: E + AR(m) -> 2E + AR+ + # Rxn16: E + AR(m) -> E + AR(r) + # Rxn17: E + AR(m) -> E + AR(4p) + # Rxn18: E + AR(4p) -> 2E + AR+ + # Rxn19: E + AR(4p) -> E + AR(r) + # Rxn20: E + AR(4p) -> E + AR(m) + # Rxn21: E + AR(r) -> E + AR + # Rxn22: E + AR(r) -> E + AR(m) + # Rxn23: E + AR(r) -> E + AR(4p) # 4) Set values in params class params.D[0] = De @@ -277,8 +277,8 @@ def setPsaapProperties_6Species(gam, inputV0, inputVDC, params, Nr, iSample): f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", - f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)", - f"{params.A[8]} * (energy**({params.B[8]}-1)) * np.exp(-{params.C[8]}/energy) * ({params.B[8]} + {params.C[8]}/energy)", + f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)", + f"{params.A[8]} * (energy**({params.B[8]}-1)) * np.exp(-{params.C[8]}/energy) * ({params.B[8]} + {params.C[8]}/energy)", f"{params.A[9]} * (energy**({params.B[9]}-1)) * np.exp(-{params.C[9]}/energy) * ({params.B[9]} + {params.C[9]}/energy)", f"{params.A[10]} * (energy**({params.B[10]}-1)) * np.exp(-{params.C[10]}/energy) * ({params.B[10]} + {params.C[10]}/energy)", f"{params.A[11]} * (energy**({params.B[11]}-1)) * np.exp(-{params.C[11]}/energy) * ({params.B[11]} + {params.C[11]}/energy)", diff --git a/psaapProperties_6Species_Sampling.py b/psaapProperties_6Species_Sampling.py new file mode 100755 index 000000000..9abed73e7 --- /dev/null +++ b/psaapProperties_6Species_Sampling.py @@ -0,0 +1,411 @@ +import numpy as np +from scipy.interpolate import CubicSpline +import csv +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors +import h5py as h5 +import logging + +class Reaction(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +def setPsaapProperties_6Species_Sampling(gam, inputV0, inputVDC, params, Nr, iSample): + """Sets non-dimensional properties corresponding to Liu 2014 paper. + + Inputs: + gam : Secondary electron emission coefficient + params : chebSolver.modelParams class + + Outputs: None + params data is overwritten using values from Liu 2014. + """ + ################################################################### + # User specified parameters (you may change these if you wish to + # run a different scenario from Liu 2014) + ################################################################### + + # densities + nAr = 3.22e22 # background number density of Ar [1/m^3] (corresponds to p=100 mTorr) + np0 = 8e16 # "nominal" electron density [1/m^3] + + # masses + # me = 9.10938356e-31 # mass of an electron [kg] + # me = 5.489e-4 # mass of an electron [u] + me = 0.511e6 # mass of an electron [eV/c2] + # mAr = 39.948 # mass of an argon atom [u] + # mAr = 39.948 * 1.66054e-27 # mass of an argon atom [kg] + mAr = 37.2158e9 # mass of an electron [eV/c2] + # u = 931.4941e6 # eV/c2 + c = 299792458 # speed of light [m/s] + se = 40 # momentum cross section [A^2] + + # nominal electron energy + e0 = 1.0 # [eV] + + # pressure + p = 133.3224*1.5 # [J/m^3] *1.5 to convert it to energy (1 Torr) + + # gas energy at the wall + Tg0 = 0.038778 # 3/2*300K*kB ~ (p0 - nT[:,0])/ntot + + # characteristics of driving voltage + V0 = inputV0 # amplitude of driving voltage [V] + verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) + tau = (1./13.56e6) # period of driving voltage [s] + L = 2.00*0.005 # half-gap-width [m] (gap width is 2 cm) + electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) + + # transport parameters + nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] + #nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + #nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + # / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nmum = 0.0 + nmui = 8.0e19 + #nmum = 9.35e19 + nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] + nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] + nDm = 2.42e18 # argon number density times metastable diffusivity [1/(cm*s)] + #nDm = 3.914e20 + + # reaction parameters (NB: k_i = Ck*Ee^B*exp(-A/Ee)) + # Ee = 3/2*Te (Te in eV) + # -> k_i = [Ck*(2/3)^B] * Ee^B * exp[-(3/2)*A/Ee] + # nominal + Ck = np.array([2.0e-7,2.1e-9,5.0e-10,6.4e-10,2.1e-15,1.0e-5,3.2e7,3.0e7,3.0e7,0.0,0.0,0.0,0.0,4.3e-10,0.0,3.7e-8,8.9e-7,1.8e-7,3.0e-7,3.0e-7,4.3e-10,9.1e-7,8.9e-7]) # pre-exponential factors [cm^3/s] + B = np.array([0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.74,0.0,0.0,0.51,0.61,0.51,0.51,0.74,0.0,0.51]) + A = np.array([0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.59,2.61,0.0,0.0,0.0,0.0,1.59]) # activation temperature [eV] + dH = np.array([0.0,-7.412,-10.054,-7.336,0.0,0.0,0.0,0.0,0.0,11.548,11.624,12.907,15.76,-11.548,4.212,0.076,1.359,2.853,-1.283,-1.359,-11.624,-0.076,0.983]) # energy lost per electron due to ionization rxn [eV] + dEps = np.array([0.0,15.76,11.548,11.624,12.907,0.0]) + + # BC parameters + # ks = 1.19e7 # electron recombination rate [cm/s] + ks = 1.366109824889323e7 # electron recombination rate [cm/s/eV] + + ################################################################### + # Constants of nature (probably shouldn't change unless you have + # root privileges on universe) + ################################################################### + qe = 1.6e-19 # unit charge [C] + eps0 = 8.86e-12 # permittivity of free space [F/m] + kB = 1.38e-23 # Boltzmann constant [J/K] + # kB = 8.62e−5 # Boltzmann constant [eV/K] + + + ################################################################### + # Calculate non-dimensional parameters + ################################################################### + + # 1) Convert input units to base SI (except eV) + nDe *= 100. # 1/(m*s) + nDi *= 100. # 1/(m*s) + nDm *= 100. + nmue *= 100. # 1/(V*m*s) + nmui *= 100. # 1/(V*m*s) + Ck[0:5] *= 1e-6 # m^3/s + Ck[5:9] *= 1 # 1/s + Ck[9:22] *= 1e-6 # m^6/s + ks *= 0.01 # m/s + se *= 1.0e-20 # m^2 + + # 2) Compute "raw" transport parameters + De = nDe/nAr + Di = nDi/nAr + Dm = nDm/nAr + + mue = nmue/nAr + mui = nmui/nAr + mum = nmum/nAr + + # 3) Compute non-dimensional properties required by solver + De = De*tau/(L*L) + Di = Di*tau/(L*L) + Dm = Dm*tau/(L*L) + + mue = mue*V0*tau/(L*L) + mui = mui*V0*tau/(L*L) + mum = mum*V0*tau/(L*L) + + Ck[0:4] *= tau*np0 + Ck[4] *= tau*nAr + Ck[5:9] *= tau + Ck[9:13] *= tau*nAr + Ck[13:] *= tau*np0 + A = A*1.5/e0 # 1.5 to convert from temperature to energy + dH = dH/e0 + qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V + alpha = qe*np0*L*L/(V0*eps0) + ks = ks*tau/L + p0 = p/qe/np0 + kappaB = 4.878171165833662*1.6129 # non-dimensional thermal conductivity of background specie + # (2/3)*tau/L**2*Kb/np0/kB, + # where Kb is the thermal conductivity of background specie + + params.beta = np.array([[0,1,1,1,0,0,0,0,0,1,1,1,2,1,2,1,1,2,1,1,1,1,1], # E + [0,1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0], # AR+ + [0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0], # AR(m) + [0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,0,0,0], # AR(r) + [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1], # AR(4p) + [2,1,1,1,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0]], dtype=np.int64) # AR + + params.alfa = np.array([[0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1], # E + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], # AR+ + [2,1,0,2,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0], # AR(m) + [0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1], # AR(r) + [0,0,2,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0], # AR(4p) + [0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0]], dtype=np.int64) # AR + # Rxn1: 2AR(m) -> 2AR + # Rxn2: AR(m) + AR(r) -> E + AR+ + AR + # Rxn3: 2AR(4p) -> E + AR+ + AR + # Rxn4: 2AR(m) -> E + AR+ + AR + # Rxn5: AR(m) + AR -> 2AR + # Rxn6: AR(r) -> AR + # Rxn7: AR(4p) -> AR + # Rxn8: AR(4p) -> AR(m) + # Rxn9: AR(4p) -> AR(r) + # Rxn10: E + AR -> E + AR(m) + # Rxn11: E + AR -> E + AR(r) + # Rxn12: E + AR -> E + AR(4p) + # Rxn13: E + AR -> 2E + AR+ + # Rxn14: E + AR(m) -> E + AR + # Rxn15: E + AR(m) -> 2E + AR+ + # Rxn16: E + AR(m) -> E + AR(r) + # Rxn17: E + AR(m) -> E + AR(4p) + # Rxn18: E + AR(4p) -> 2E + AR+ + # Rxn19: E + AR(4p) -> E + AR(r) + # Rxn20: E + AR(4p) -> E + AR(m) + # Rxn21: E + AR(r) -> E + AR + # Rxn22: E + AR(r) -> E + AR(m) + # Rxn23: E + AR(r) -> E + AR(4p) + + rxnNameDict = {0: "2AR(m) => 2AR", + 1: "AR(m) + AR(r) => E + AR+ + AR", + 2: "2AR(4p) => E + AR+ + AR", + 3: "2AR(m) => E + AR+ + AR", + 4: "AR(m) + AR => 2AR", + 5: "AR(r) => AR", + 6: "AR(4p) => AR", + 7: "AR(4p) => AR(m)", + 8: "Ar(4p) => AR(r)", + 9: "1s-metastable", + 10: "1s-resonance", + 11: "2p-lumped", + 12: "Ionization", + 13: "E + AR(m) => E + AR", + 14: "StepIonization", + 15: "E + AR(m) => E + AR(r)", + 16: "E + AR(m) => E + AR(4p)", + 17: "E + AR(4p) => 2E + AR+", + 18: "E + AR(4p) => E + AR(r)", + 19: "E + AR(4p) => E + AR(m)", + 20: "E + AR(r) => E + AR", + 21: "E + AR(r) => E + AR(m)", + 22: "E + AR(r) => E + AR(4p)"} + + # 4) Set values in params class + params.D[0] = De + params.D[1] = Di + params.D[2] = Dm + + params.mu[0] = mue + params.mu[1] = mui + params.mu[2] = mum + + params.A[:] = Ck[:] + params.B[:] = B[:] + params.C[:] = A[:] + + # Account for the 2/3 term to convert from electron temperature to electron energy + for i in range(len(params.A)): + params.A[i] *= (2/3)**(params.B[i]) + + params.dH[:] = dH[:] + params.dEps[:] = dEps[:] + params.qStar = qStar + params.alpha = alpha + params.ks = ks + params.gam = gam + params.kappaB = kappaB + params.nAronp0 = nAr / np0 + params.p0 = p0 + params.Tg0 = Tg0 + params.EC = 2.0 * me / mAr \ + * np.sqrt(16.0 * (me + mAr) * e0 * c**2 + / (3.0 * np.pi * me * mAr)) * se * nAr * tau + # params.EC = 2.0 * me / mAr * 3.8e9 * tau + + params.verticalShift = verticalShift / V0 + + # Parameters needed to compute the current with dimensions + params.V0Ltau = V0 / (L * tau) + params.V0L = V0 / L + params.LLV0tau = (L*L) / (V0*tau) + params.tauL = L / tau + params.np0 = np0 # "nominal" electron density [1/m^3] + params.qe = qe # unit charge [C] + params.eps0 = eps0 # unit charge [C] + params.eArea = electrodeArea # electrode area [m^2] + + + reactionExpressionTypelist = np.array([False,False,False,False,False,False,False,False,False, + True,True,True,True,False,True,False,False,False,False,False,False,False,False]) + + reactionsList = [] + LOGFilename = 'interpolationSample%s.log'%str(iSample) + f = open(LOGFilename, 'w') + + for i in range(Nr): + Nsample = 20 + N300 = 200 + sample_root_dir = "../6species_SampleFiles" + if reactionExpressionTypelist[i]: + #Nsample = 1 + #N300 = 200 + fileString = sample_root_dir + "/" + rxnNameDict[i] + fileName = "%s.%08d.h5" % (fileString, iSample) + f = h5.File(fileName, 'r') + dataset = f["table"] + + #rateCoeff = np.fromfile(rate_file) + rateCoeff = dataset[:,1] + rateCoeff /= 6.022e23 + #rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + #rateCoeff = np.reshape(rateCoeff,[1, N300]).T[:,1] + + #Te = np.fromfile(temp_file) + Te = dataset[:,0] + Te /= 11604. + #Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + #Te = np.reshape(Te,[1, N300]).T[:,1] + + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy. + Te *= 1.5 + + # Find first non-zero value of the coefficient rate. + I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + #lastFalse = np.where(indices==False)[-1][-1] + 2 + for k in range(len(Te)): + if (Te[k] < 4.5 and indices[k] == False): + lasFalse = k + 2 + + # Transformation to log scale. + TeLog = np.log(Te) + + # Compute the slope of the rate coefficient between its first two non-zero values. + # Finite differences are used. + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) + + # Arrhenius form: kf = A * exp(-C / Te) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + + # Compute pre-exponential coefficient, A, in log scale. + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] + + # Transform rate coefficient in log scale. + rateCoeffLog = np.zeros(rateCoeff.shape) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) + # For the troublesome values, we use the Arrhenius form. + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] + # Nondimensionalization in log scale. + if i == 9: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + elif i == 10: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + elif i == 11: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + elif i == 12: + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + else: + rateCoeffLog += - np.log(1.0/tau) + np.log(np0) + + # Interpolation in log scale. + reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) + # Gradient in log scale + reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf_log = reactionExpressionsLog, + kf_T_log = reactionTExpressionsLog) + reactionsList.append(reaction) + + logging.basicConfig(filename=LOGFilename) + logging.warning('Interpolation info (Reaction %s):', i) + logging.warning('First non-zero entry in the rate coefficient: %s', I[0][0]) + logging.warning('Monotonicity of the rate coefficient start from entry: %s', lastFalse) + logging.warning('Position of possible duplicates in mean energy array: %s', + TeDuplicateindsForLog[0]) + + else: + fileName = "%s/Arrhenius.%08d.h5" % (sample_root_dir, iSample) + f = h5.File(fileName, 'r') + arrh_Coeffs = f[rxnNameDict[i]][...] + A, B, C = arrh_Coeffs + + # Non-dimensionalize the coefficients + if (i < 4): + A /= 6.022e23 + A *= tau*np0 + elif (i == 4): + A /= 6.022e23 + A *= tau*nAr + elif (i > 4 and i < 9): + A *= tau + elif (i > 8 and i < 13): + A /= 6.022e23 + A *= tau*nAr + else: + A /= 6.022e23 + A *= tau*np0 + + A *= 11604**B + C = C*1.5/e0 + + rxn = eval("lambda energy :" + f"{A} * energy**{B} * np.exp(-{C} / energy)") + rxn_T = eval("lambda energy :" + f"{A} * energy**({B}-1) * np.exp(-{C} / energy) * ({B} + {C} / energy)") + + #rxn = eval("lambda energy :" + reactionExpressionslist[i]) + #rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf = rxn, kf_T = rxn_T) + reactionsList.append(reaction) + + params.reactionsList = reactionsList + + # 5) Dump to screen + params.print() From 95388b87dd5ec628686e7a3c5440797b4cf14347 Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Wed, 19 Oct 2022 11:23:54 -0500 Subject: [PATCH 17/32] rm unnecessary if statement --- chebSolver.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/chebSolver.py b/chebSolver.py index 726395ecf..94e6b8038 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -1477,14 +1477,9 @@ def jacobian0(self, time, dt, weak_bc=False): self.jac0[0 ,:] = np.zeros((1,self.Nv*self.Np)) self.jac0[self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) - #if (self.Ns>2): - # self.jac0[2*self.Np,:] = np.zeros((1,self.Nv*self.Np)) - # self.jac0[3*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) - - if (self.Ns > 2): - for i in range(2,self.Ns-1): - self.jac0[i*self.Np,:] = np.zeros((1,self.Nv*self.Np)) - self.jac0[(i+1)*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) + for i in range(2,self.Ns-1): + self.jac0[i*self.Np,:] = np.zeros((1,self.Nv*self.Np)) + self.jac0[(i+1)*self.Np-1,:] = np.zeros((1,self.Nv*self.Np)) # Dirichlet on heavy species temperature From cf44339a5ed1507c3b20380261f2bf126a97201b Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Wed, 19 Oct 2022 11:30:35 -0500 Subject: [PATCH 18/32] Revert changes to scenario 0 (so that regression test makes sense) --- Liu2014Properties.py | 103 +++---------------------------------------- 1 file changed, 7 insertions(+), 96 deletions(-) diff --git a/Liu2014Properties.py b/Liu2014Properties.py index a898cd77d..3ffdaa39d 100644 --- a/Liu2014Properties.py +++ b/Liu2014Properties.py @@ -1,7 +1,4 @@ import numpy as np -from scipy.interpolate import CubicSpline -import matplotlib.pyplot as plt -import matplotlib.colors as mcolors class Reaction(object): @@ -22,6 +19,8 @@ def setLiu2014Properties(gam, inputV0, inputVDC, params, Nr, iSample): Outputs: None params data is overwritten using values from Liu 2014. """ + assert iSample == 0, "This scenario is not set up for sampling" + ################################################################### # User specified parameters (you may change these if you wish to # run a different scenario from Liu 2014) @@ -161,102 +160,14 @@ def setLiu2014Properties(gam, inputV0, inputVDC, params, Nr, iSample): reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)"] - reactionExpressionTypelist = [True] - reactionsList = [] for i in range(Nr): - if reactionExpressionTypelist[i]: - Nsample = 72 - N300 = 200 - - rateCoeff = np.fromfile('./BOLSIGChemistry/reaction300K_%s.dat' %str(i)) - rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] - - Te = np.fromfile('./BOLSIGChemistry/reaction300K.Te.dat') - Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] - - # Nondimensionalization of mean energy and transformation to log scale. - # Te *= 1.5 - TeLog = np.log(Te) - - # Find first non-zero value of the coefficient rate. - I = np.nonzero(rateCoeff) - - # Compute the slope of the rate coefficient between its first two non-zero values. - # Finite differences are used. - dydx = (rateCoeff[I[0][0] + 1] - rateCoeff[I[0][0]]) \ - / (Te[I[0][0] + 1] - Te[I[0][0]]) - - # Arrhenius form: kf = A * exp(-C / Te) - # C = (dkf/dTe) / kf * Te**2.0 - # A = kf / exp(-C / Te) - C = Te[I[0][0]]**2.0*dydx / rateCoeff[I[0][0]] - # A = rateCoeff[I[0][0]] / np.exp(-C/Te[I[0][0]]) - - # Compute pre-exponential coefficient, A, in log scale. - ALog = np.log(rateCoeff[I[0][0]]) + C / Te[I[0][0]] - - # Transform rate coefficient in log scale. - rateCoeffLog = np.zeros(rateCoeff.shape) - rateCoeffLog[I[0][0]:] = np.log(rateCoeff[I[0][0]:]) - # For the troublesome values, we use the Arrhenius form. - rateCoeffLog[0:I[0][0]] = ALog - C / Te[0:I[0][0]] - # Nondimensionalization in log scale. - if i < 2: - rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) - else: - rateCoeffLog += - np.log(1.0/tau) + np.log(np0) - # Nondimensionalization of the original rate, used for the plot and comparison. - rateCoeff *= tau * nAr - - # Interpolation in log scale. - reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) - # Gradient in log scale - reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) - - reaction = Reaction(rxnAlfa = params.alfa, rxnBeta = params.beta, - rxnBolsig = reactionExpressionTypelist[i], - kf_log = reactionExpressionsLog, - kf_T_log = reactionTExpressionsLog) - reactionsList.append(reaction) - - # rxn = eval("lambda energy :" + reactionExpressionslist[i]) - # rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) - - # # setting the axes at the centre - # fig ,ax = plt.subplots(figsize=(9, 6)) - # ax.spines["top"].set_visible(True) - # ax.spines["right"].set_visible(True) - # # ax.set_yscale('log') - # # ax.set_xscale('log') - - # # plot the function - # # plt.plot(rateCoeffXFiner, np.exp(reactionExpressions_cubicSplineDerivative_log(rateCoeffXFiner)), - # # color='salmon', linestyle='--', label='interBolsig') - # # plt.plot(rateCoeffXFine, np.exp(reactionExpressions_cubicSpline_log(rateCoeffXFine)), - # # color='lightgreen', linestyle='--', label='interBolsig') - # plt.plot(Te, reactionTExpressionsLogFiltered(TeLog) * np.exp(reactionExpressionsLog(TeLog)) / Te, - # color='blue', linestyle='-', label='interBolsig') - # plt.plot(Te, np.exp(reactionExpressionsLog(TeLog)), - # color='green', linestyle='-', label='interBolsig') - # plt.plot(Te, rxn(Te), - # color='salmon', linestyle='--', label='interBolsig') - # plt.plot(Te, rxn_T(Te), - # color='red', linestyle='--', label='interBolsig') - # plt.xlim((0.05,100)) - # plt.ylim((1e-200,300)) - # plt.savefig("./VoltageTimeSeries/VoltageTimeSeries_50mTorr_20W" + ".pdf", dpi=300) - # # plt.xlim((-0.0001,0.0255)) - # plt.show() - - else: - rxn = eval("lambda energy :" + reactionExpressionslist[i]) - rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + rxn = eval("lambda energy :" + reactionExpressionslist[i]) + rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) - reaction = Reaction(rxnAlfa = params.alfa, rxnBeta = params.beta, - rxnBolsig = reactionExpressionTypelist[i], - kf = rxn, kf_T = rxn_T) - reactionsList.append(reaction) + reaction = Reaction(rxnAlfa = params.alfa, rxnBeta = params.beta, + kf = rxn, kf_T = rxn_T, rxnBolsig = False) + reactionsList.append(reaction) params.reactionsList = reactionsList From a500eb0fa9ead4994900a756bc4be383f6a717a6 Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Wed, 19 Oct 2022 11:35:33 -0500 Subject: [PATCH 19/32] mv Violeta's version of psaapPropertiesTestArm --- psaapPropertiesTestArm.py => psaapPropertiesTestArmVioleta.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename psaapPropertiesTestArm.py => psaapPropertiesTestArmVioleta.py (100%) diff --git a/psaapPropertiesTestArm.py b/psaapPropertiesTestArmVioleta.py similarity index 100% rename from psaapPropertiesTestArm.py rename to psaapPropertiesTestArmVioleta.py From a90c0e1528eab2fda22f9ac34541dfa2a3a9190d Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Wed, 19 Oct 2022 11:37:17 -0500 Subject: [PATCH 20/32] replace psaapPropertiesTestArm --- psaapPropertiesTestArm.py | 277 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 psaapPropertiesTestArm.py diff --git a/psaapPropertiesTestArm.py b/psaapPropertiesTestArm.py new file mode 100644 index 000000000..622142867 --- /dev/null +++ b/psaapPropertiesTestArm.py @@ -0,0 +1,277 @@ +import numpy as np +from scipy.interpolate import CubicSpline + +class Reaction(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +class Diffusivity(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +class Mobility(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr): + """Sets non-dimensional properties corresponding to Liu 2014 paper. + + Inputs: + gam : Secondary electron emission coefficient + params : chebSolver.modelParams class + + Outputs: None + params data is overwritten using values from Liu 2014. + """ + ################################################################### + # User specified parameters (you may change these if you wish to + # run a different scenario from Liu 2014) + ################################################################### + + # densities + nAr = 3.22e22 # background number density of Ar [1/m^3] (corresponds to p=100 mTorr) + np0 = 8e16 # "nominal" electron density [1/m^3] + + # masses + # me = 9.10938356e-31 # mass of an electron [kg] + # me = 5.489e-4 # mass of an electron [u] + me = 0.511e6 # mass of an electron [eV/c2] + # mAr = 39.948 # mass of an argon atom [u] + # mAr = 39.948 * 1.66054e-27 # mass of an argon atom [kg] + mAr = 37.2158e9 # mass of an electron [eV/c2] + # u = 931.4941e6 # eV/c2 + c = 299792458 # speed of light [m/s] + se = 40 # momentum cross section [m^2] + + # nominal electron energy + e0 = 1.0 # [eV] + + # pressure + p = 133.3224*1.5 # [J/m^3] *1.5 to convert it to energy (1 Torr) + + # gas energy at the wall + Tg0 = 0.038778 # 3/2*300K*kB ~ (p0 - nT[:,0])/ntot + + # characteristics of driving voltage + V0 = inputV0 # amplitude of driving voltage [V] + verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) + tau = (1./13.6e6) # period of driving voltage [s] + L = 2.54*0.005 # half-gap-width [m] (gap width is 2.54cm) + electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) + + # transport parameters + nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] + nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] + nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] + nDm = 2.42e18 # argon number density times metastable diffusivity [1/(cm*s)] + + # reaction parameters (NB: k_i = Ck*exp(-A/Te)) + #Ck = np.array([1.235e-7,3.712e-8,2.05e-7,1.818e-9,2e-7]) # pre-exponential factors [cm^3/s] + #A = np.array([18.687,15.06,4.95,2.14,0.0]) # activation temperature [eV] + #dH = np.array([15.7,11.56,4.14,-11.56,0.0]) # energy lost per electron due to ionization rxn [eV] + + #Ck = np.array([1.235e-7,3.712e-8,2.05e-7,1.818e-9]) # pre-exponential factors [cm^3/s] + #A = np.array([18.687,15.06,4.95,2.14]) # activation temperature [eV] + #dH = np.array([15.7,11.56,4.14,-11.56]) # energy lost per electron due to ionization rxn [eV] + + #Ck = np.array([1.235e-7,0.0,0.0,0.0,0.0]) # pre-exponential factors [cm^3/s] + #A = np.array([18.687,15.06,4.95,2.14,0.0]) # activation temperature [eV] + #dH = np.array([15.7,0.0,0.0,0.0,0.0]) # energy lost per electron due to ionization rxn [eV] + + # nominal + Ck = np.array([1.235e-7,3.712e-8,2.05e-7,1.818e-9,2e-7,6.2e-10,3.0e-15,1.1e-31]) # pre-exponential factors [cm^3/s] + + # slow excitation rate + #Ck = np.array([1.235e-7,0.5*3.712e-8,2.05e-7,1.818e-9,2e-7,6.2e-10,3.0e-15,1.1e-31]) # pre-exponential factors [cm^3/s] + + ## fast excitation rate + #Ck = np.array([1.235e-7,2.0*3.712e-8,2.05e-7,1.818e-9,2e-7,6.2e-10,3.0e-15,1.1e-31]) # pre-exponential factors [cm^3/s] + + A = np.array([18.687,15.06,4.95,2.14,0.0,0.0,0.0,0.0]) # activation temperature [eV] + dH = np.array([15.7,11.56,4.14,-11.56,0.0,0.0,0.0,0.0]) # energy lost per electron due to ionization rxn [eV] + dEps = np.array([0.0,15.7,11.56,0.0]) + + # BC parameters + # ks = 1.19e7 # electron recombination rate [cm/s] + ks = 1.366109824889323e7 # electron recombination rate [cm/s/eV] + + ################################################################### + # Constants of nature (probably shouldn't change unless you have + # root privileges on universe) + ################################################################### + qe = 1.6e-19 # unit charge [C] + eps0 = 8.86e-12 # permittivity of free space [F/m] + kB = 1.38e-23 # Boltzmann constant [J/K] + # kB = 8.62e−5 # Boltzmann constant [eV/K] + + + ################################################################### + # Calculate non-dimensional parameters + ################################################################### + + # 1) Convert input units to base SI (except eV) + nDe *= 100. # 1/(m*s) + nDi *= 100. # 1/(m*s) + nDm *= 100. + nmue *= 100. # 1/(V*m*s) + nmui *= 100. # 1/(V*m*s) + Ck *= 1e-6 # m^3/s + Ck[7] *= 1e-6 # Ck[7] is now in m^6/s + ks *= 0.01 # m/s + se *= 1.0e-20 # m^2 + + # 2) Compute "raw" transport parameters + De = nDe/nAr + Di = nDi/nAr + Dm = nDm/nAr + + mue = nmue/nAr + mui = nmui/nAr + mum = nmum/nAr + + # 3) Compute non-dimensional properties required by solver + De = De*tau/(L*L) + Di = Di*tau/(L*L) + Dm = Dm*tau/(L*L) + + mue = mue*V0*tau/(L*L) + mui = mui*V0*tau/(L*L) + mum = mum*V0*tau/(L*L) + + Ck[0:2] = Ck[0:2]*tau*nAr + #Ck[2:5] = Ck[2:5]*tau*np0 + Ck[2:6] = Ck[2:6]*tau*np0 + Ck[6] *= tau*nAr + Ck[7] *= tau*nAr*nAr + A = A*1.5/e0 # 1.5 to convert from temperature to energy + dH = dH/e0 + qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V + alpha = qe*np0*L*L/(V0*eps0) + ks = ks*tau/L + p0 = p/qe/np0 + kappaB = 4.878171165833662 # non-dimensional thermal conductivity of background specie + # (2/3)*tau/L**2*Kb/np0/kB, + # where Kb is the thermal conductivity of background specie + + #params.beta = np.array([[2,2,2,1,1],[1,0,1,0,0],[0,1,0,0,0],[0,0,0,1,1]]) + #params.alfa = np.array([[1,1,1,1,1],[0,0,0,0,0],[0,0,1,1,1],[1,1,0,0,0]]) + #params.beta = np.array([[2,1,2,1],[1,0,1,0],[0,1,0,0],[0,0,0,1]], dtype=np.int) + #params.alfa = np.array([[1,1,1,1],[0,0,0,0],[0,0,1,1],[1,1,0,0]], dtype=np.int) + params.beta = np.array([[2,1,2,1,1,1,0,0],[1,0,1,0,0,1,0,0],[0,1,0,0,0,0,0,0],[0,0,0,1,0,1,2,1]], dtype=np.int64) + params.alfa = np.array([[1,1,1,1,1,0,0,0],[0,0,0,0,0,0,0,0],[0,0,1,1,1,2,1,1],[1,1,0,0,0,0,1,2]], dtype=np.int64) + + # 4) Set values in params class + params.D[0] = De + params.D[1] = Di + params.D[2] = Dm + + params.mu[0] = mue + params.mu[1] = mui + params.mu[2] = mum + + params.A[:] = Ck[:] + params.B[:] = 0.0 + params.C[:] = A[:] + + params.dH[:] = dH[:] + params.dEps[:] = dEps[:] + params.qStar = qStar + params.alpha = alpha + params.ks = ks + params.gam = gam + params.kappaB = kappaB + params.nAronp0 = nAr / np0 + params.p0 = p0 + params.Tg0 = Tg0 + params.EC = 2.0 * me / mAr \ + * np.sqrt(16.0 * (me + mAr) * e0 * c**2 + / (3.0 * np.pi * me * mAr)) * se * nAr * tau + # params.EC = 2.0 * me / mAr * 3.8e9 * tau + + params.verticalShift = verticalShift / V0 + + # Parameters needed to compute the current with dimensions + params.V0Ltau = V0 / (L * tau) + params.V0L = V0 / L + params.LLV0tau = (L*L) / (V0*tau) + params.tauL = L / tau + params.np0 = np0 # "nominal" electron density [1/m^3] + params.qe = qe # unit charge [C] + params.eps0 = eps0 # unit charge [C] + params.eArea = electrodeArea # electrode area [m^2] + + reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)"] + + reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)"] + + reactionsList = [] + for i in range(Nr): + rxn = eval("lambda energy :" + reactionExpressionslist[i]) + rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + kf = rxn, kf_T = rxn_T, rxnBolsig = False ) + reactionsList.append(reaction) + + params.reactionsList = reactionsList + #params.Nr = 1 + + diffList = [] + Te = np.linspace(0, 1000, 10) + De_interp = params.D[0]*np.ones(10) + De_spline = CubicSpline(Te, De_interp) + De_Te_spline = CubicSpline.derivative(De_spline) + diffusivity = Diffusivity(interpolate = False, D_expression = De_spline, D_T_expression = De_Te_spline) + diffList.append(diffusivity) + + Ns = 4 + for i in range(1, Ns): + diffList.append(Diffusivity(interpolate = False)) + + params.diffusivityList = diffList + + muList = [] + Te = np.linspace(0, 1000, 10) + mue_interp = params.mu[0]*np.ones(10) + mue_spline = CubicSpline(Te, mue_interp) + mue_Te_spline = CubicSpline.derivative(mue_spline) + mobility = Mobility(interpolate = False, mu_expression = mue_spline, mu_T_expression = mue_Te_spline) + muList.append(mobility) + + Ns = 4 + for i in range(1, Ns): + muList.append(Mobility(interpolate = False)) + + params.mobilityList = muList + + # 5) Dump to screen + params.print() From 84e48906e088ff1e933d97f964329290f1c3c2fd Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Wed, 19 Oct 2022 12:46:01 -0500 Subject: [PATCH 21/32] make scenario 2 consistent with what it was historically --- chebSolver.py | 2 +- psaapPropertiesTestArm.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/chebSolver.py b/chebSolver.py index 94e6b8038..2b2e21c87 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -422,7 +422,7 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, elif(scenario==1): Nr = 1 elif(scenario==2): - Nr = 7 + Nr = 8 elif(scenario==3): Nr = 8 elif(scenario==4): diff --git a/psaapPropertiesTestArm.py b/psaapPropertiesTestArm.py index 622142867..b10553372 100644 --- a/psaapPropertiesTestArm.py +++ b/psaapPropertiesTestArm.py @@ -25,7 +25,7 @@ def __init__(self, *initial_data, **kwargs): for key in kwargs: setattr(self, key, kwargs[key]) -def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr): +def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr, iSample): """Sets non-dimensional properties corresponding to Liu 2014 paper. Inputs: @@ -35,6 +35,8 @@ def setPsaapPropertiesTestArm(gam, inputV0, inputVDC, params, Nr): Outputs: None params data is overwritten using values from Liu 2014. """ + assert iSample == 0, "This scenario is not set up for sampling" + ################################################################### # User specified parameters (you may change these if you wish to # run a different scenario from Liu 2014) From 7f54a4d8a2e5277900841372f87ffceb81e85c12 Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Wed, 19 Oct 2022 14:12:32 -0500 Subject: [PATCH 22/32] update to standarized scenario interface --- psaapPropertiesTestArmInterpTrans.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/psaapPropertiesTestArmInterpTrans.py b/psaapPropertiesTestArmInterpTrans.py index db88f0e2c..c1c6f0626 100644 --- a/psaapPropertiesTestArmInterpTrans.py +++ b/psaapPropertiesTestArmInterpTrans.py @@ -25,7 +25,7 @@ def __init__(self, *initial_data, **kwargs): for key in kwargs: setattr(self, key, kwargs[key]) -def setPsaapPropertiesTestArmInterpTrans(gam, inputV0, inputVDC, params, Nr): +def setPsaapPropertiesTestArmInterpTrans(gam, inputV0, inputVDC, params, Nr, iSample): """Sets non-dimensional properties corresponding to Liu 2014 paper. Inputs: @@ -35,6 +35,7 @@ def setPsaapPropertiesTestArmInterpTrans(gam, inputV0, inputVDC, params, Nr): Outputs: None params data is overwritten using values from Liu 2014. """ + assert iSample == 0, "This scenario is not set up for sampling" ################################################################### # User specified parameters (you may change these if you wish to # run a different scenario from Liu 2014) @@ -241,7 +242,7 @@ def setPsaapPropertiesTestArmInterpTrans(gam, inputV0, inputVDC, params, Nr): rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], - kf = rxn, kf_T = rxn_T) + kf = rxn, kf_T = rxn_T, rxnBolsig = False) reactionsList.append(reaction) params.reactionsList = reactionsList From 275d06b3461b89adc436381c498cf70ac8e39a1e Mon Sep 17 00:00:00 2001 From: Juan Pablo Barberena Valencia Date: Wed, 19 Oct 2022 11:51:05 -0700 Subject: [PATCH 23/32] Added regression test script --- reference_solns/Nominal_Np250_restart.npy | 3 ++ reference_solns/Nominal_Np250_solution.npy | 3 ++ test6Species.sh | 40 ++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 reference_solns/Nominal_Np250_restart.npy create mode 100644 reference_solns/Nominal_Np250_solution.npy create mode 100755 test6Species.sh diff --git a/reference_solns/Nominal_Np250_restart.npy b/reference_solns/Nominal_Np250_restart.npy new file mode 100644 index 000000000..de25b95b8 --- /dev/null +++ b/reference_solns/Nominal_Np250_restart.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80e433281f66962468805f299f8a05078790da53944450dbbdd8bb815196f21b +size 14128 diff --git a/reference_solns/Nominal_Np250_solution.npy b/reference_solns/Nominal_Np250_solution.npy new file mode 100644 index 000000000..1fdc30de6 --- /dev/null +++ b/reference_solns/Nominal_Np250_solution.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7d6ff75350bee21dbb6309fd43f498b066598936100869c26040a7d88cf0160 +size 1806128 diff --git a/test6Species.sh b/test6Species.sh new file mode 100755 index 000000000..c8e61a137 --- /dev/null +++ b/test6Species.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +error_exit() +{ + echo "$1" 1>&2 + exit 1 +} + +#module load python/3.8.2 + +tmp_dir=$(mktemp -d -t tmp-test-XXXXXXXXXX --tmpdir=.) +echo "Running 6 species test in $tmp_dir" +cd $tmp_dir +EXE="python3 ../chebSolver.py" +NEWTEXE="python3 ../timePeriodicSolver.py" + +# 6 species + 23 rxn - Nominal Rates case +Np=250 +Nt=25600 +Nt1=128 +dt=0.0078125 +scenario=12 +baseFile="restart_6spec_CN_Np${Np}_" +newtFile="newton_6spec_CN_Np${Np}.npy" +saveFile="newton_6spec_CN_Np${Np}_fullsoln.npy" + +baseCmd="$EXE --Np $Np --Nt $Nt --dt $dt --scenario $scenario --EinsteinForm --elasticCollisionActivation --backgroundSpecieActivation" +newtCmd="$NEWTEXE --Np $Np --Nt $Nt1 --Nn 20 --scenario $scenario --tscheme CN --alpha0 0.1 --increaseFac 1.5 --EinsteinForm --elasticCollisionActivation --backgroundSpecieActivation" +saveCmd="$EXE --Np $Np --Nt $Nt1 --dt $dt --scenario $scenario --tscheme CN --EinsteinForm --elasticCollisionActivation --backgroundSpecieActivation" + +diffCmd="python3 ../diffSolns.py --reference ../reference_solns/Nominal_Np250_solution.npy --Np $Np --Nv 5" + + +screenOut="run6species.out" +rm -f $screenOut + +$newtCmd --V0 100 --VDC 0.0 --gam 0.01 --rtol 1e-8 --restart "../reference_solns/Nominal_Np250_restart.npy" \ + --outfile $newtFile >> $screenOut || error_exit "Shooting failed" + +$diffCmd --solution $newtFile >> $screenOut || error_exit "Solution differs from reference" From fbc91d95868edded80b7c01eb3f56b5eb398a493 Mon Sep 17 00:00:00 2001 From: Juan Pablo Barberena Valencia Date: Wed, 19 Oct 2022 12:34:31 -0700 Subject: [PATCH 24/32] Fixing scenarios --- chebSolver.py | 7 + psaapProperties_6Species_Nominal.py | 461 ++++++++++++++++++++++++++++ timePeriodicSolver.py | 2 + 3 files changed, 470 insertions(+) create mode 100755 psaapProperties_6Species_Nominal.py diff --git a/chebSolver.py b/chebSolver.py index 2b2e21c87..3328bb157 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -14,6 +14,7 @@ from psaapPropertiesTestJP_Arrhenius import setPsaapPropertiesTestJP_Arrhenius from psaapProperties_6Species import setPsaapProperties_6Species from psaapProperties_6Species_Sampling import setPsaapProperties_6Species_Sampling +from psaapProperties_6Species_Nominal import setPsaapProperties_6Species_Nominal class modelClosures: """Class providing model parameters.""" @@ -439,6 +440,8 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, Nr = 23 elif(scenario==10): Nr = 23 + elif(scenario==12): + Nr = 23 elif(scenario==21): Nr = 8 else: @@ -473,6 +476,8 @@ def __init__(self, Ns, NT, Np, elasticCollisionActivationFactor, setPsaapProperties_6Species(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==10): setPsaapProperties_6Species_Sampling(gam, V0, VDC, self.params, Nr, iSample) + elif(scenario==12): + setPsaapProperties_6Species_Nominal(gam, V0, VDC, self.params, Nr, iSample) elif(scenario==21): setPsaapPropertiesTestArmInterpTrans(gam, V0, VDC, self.params, Nr, iSample) @@ -1920,6 +1925,8 @@ def plot(self, col, create=True): Ns = 6 elif(args.scenario==10): Ns = 6 + elif(args.scenario==12): + Ns = 6 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 diff --git a/psaapProperties_6Species_Nominal.py b/psaapProperties_6Species_Nominal.py new file mode 100755 index 000000000..9c6cc8338 --- /dev/null +++ b/psaapProperties_6Species_Nominal.py @@ -0,0 +1,461 @@ +import numpy as np +from scipy.interpolate import CubicSpline +import csv +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors +import h5py as h5 + +import logging + +class Reaction(object): + def __init__(self, *initial_data, **kwargs): + for dictionary in initial_data: + for key in dictionary: + setattr(self, key, dictionary[key]) + for key in kwargs: + setattr(self, key, kwargs[key]) + +def setPsaapProperties_6Species_Nominal(gam, inputV0, inputVDC, params, Nr, iSample): + """Sets non-dimensional properties corresponding to Liu 2014 paper. + + Inputs: + gam : Secondary electron emission coefficient + params : chebSolver.modelParams class + + Outputs: None + params data is overwritten using values from Liu 2014. + """ + ################################################################### + # User specified parameters (you may change these if you wish to + # run a different scenario from Liu 2014) + ################################################################### + + # densities + nAr = 3.22e22 # background number density of Ar [1/m^3] (corresponds to p=100 mTorr) + np0 = 8e16 # "nominal" electron density [1/m^3] + + # masses + # me = 9.10938356e-31 # mass of an electron [kg] + # me = 5.489e-4 # mass of an electron [u] + me = 0.511e6 # mass of an electron [eV/c2] + # mAr = 39.948 # mass of an argon atom [u] + # mAr = 39.948 * 1.66054e-27 # mass of an argon atom [kg] + mAr = 37.2158e9 # mass of an argon atom [eV/c2] + # u = 931.4941e6 # eV/c2 + c = 299792458 # speed of light [m/s] + se = 40 # momentum cross section [A^2] + + # nominal electron energy + e0 = 1.0 # [eV] + + # pressure + p = 133.3224*1.5 # [J/m^3] *1.5 to convert it to energy (1 Torr) + + # gas energy at the wall + Tg0 = 0.038778 # 3/2*300K*kB ~ (p0 - nT[:,0])/ntot + + # characteristics of driving voltage + V0 = inputV0 # amplitude of driving voltage [V] + verticalShift = inputVDC # DC voltage (vertical shift in driving voltage) + tau = (1./13.56e6) # period of driving voltage [s] + L = 2.00*0.005 # half-gap-width [m] (gap width is 2 cm) + electrodeArea = np.pi*0.05**2 # electrode area [m^2] (electrode diameter = 0.1 m) + + # transport parameters + nmue = 9.66e21 # argon number density times electron mobility [1/(V*cm*s)] + #nmui = 4.65e19 # argon number density times ion mobility [1/(V*cm*s)] + #nmum = 1 / (np.sqrt(16.0 * (mAr + mAr) * 300 * 8.62e-5 * c**2 + # / (3.0 * np.pi * mAr * mAr)) * se * mAr * 1.6e-19 / c**2) + nmum = 0.0 + nmur = 0.0 + nmu4p = 0.0 + nmui = 8.0e19 + #nmum = 9.35e19 + nDe = 3.86e22 # argon number density times electron diffusivity [1/(cm*s)] + nDi = 2.07e18 # argon number density times ion diffusivity [1/(cm*s)] + nDm = 2.42e18 # argon number density times AR(m) diffusivity [1/(cm*s)] + nDr = 2.42e18 + nD4p = 2.42e18 + #nDm = 3.914e20 + + # reaction parameters (NB: k_i = Ck*Ee^B*exp(-A/Ee)) + # Ee = 3/2*Te (Te in eV) + # -> k_i = [Ck*(2/3)^B] * Ee^B * exp[-(3/2)*A/Ee] + # nominal + Ck = np.array([2.0e-7,2.1e-9,5.0e-10,6.4e-10,2.1e-15,1.0e5,3.2e7,3.0e7,3.0e7,0.0,0.0,0.0,0.0,4.3e-10,0.0,3.7e-8,8.9e-7,1.8e-7,3.0e-7,3.0e-7,4.3e-10,9.1e-7,8.9e-7]) # pre-exponential factors [cm^3/s] + B = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0.74,0,0,0.51,0.61,0.51,0.51,0.74,0,0.51]) + A = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.59,2.61,0,0,0,0,1.59]) # activation temperature [eV] + dH = np.array([0.0,-7.412,-10.054,-7.336,0.0,0.0,0.0,0.0,0.0,11.548,11.624,12.907,15.76,-11.548,4.212,0.076,1.359,2.853,-1.283,-1.359,-11.624,-0.076,0.983]) # energy lost per electron due to ionization rxn [eV] + dEps = np.array([0.0,15.76,11.548,11.624,12.907,0.0]) # E, AR+, AR(m), AR(r), AR(4p), AR + + # BC parameters + # ks = 1.19e7 # electron recombination rate [cm/s] + ks = 1.366109824889323e7 # electron recombination rate [cm/s/eV] + + ################################################################### + # Constants of nature (probably shouldn't change unless you have + # root privileges on universe) + ################################################################### + qe = 1.6e-19 # unit charge [C] + eps0 = 8.86e-12 # permittivity of free space [F/m] + kB = 1.38e-23 # Boltzmann constant [J/K] + # kB = 8.62e-5 # Boltzmann constant [eV/K] + + + ################################################################### + # Calculate non-dimensional parameters + ################################################################### + + # 1) Convert input units to base SI (except eV) + nDe *= 100. # 1/(m*s) + nDi *= 100. # 1/(m*s) + nDm *= 100. + nDr *= 100. + nD4p *= 100. + nmue *= 100. # 1/(V*m*s) + nmui *= 100. # 1/(V*m*s) + Ck[0:5] *= 1e-6 # m^3/s + Ck[5:9] *= 1 # 1/s + Ck[9:22] *= 1e-6 # m^3/s + ks *= 0.01 # m/s + se *= 1.0e-20 # m^2 + + # 2) Compute "raw" transport parameters + De = nDe/nAr + Di = nDi/nAr + Dm = nDm/nAr + Dr = nDr/nAr + D4p = nD4p/nAr + + mue = nmue/nAr + mui = nmui/nAr + mum = nmum/nAr + mur = nmur/nAr + mu4p = nmu4p/nAr + + # 3) Compute non-dimensional properties required by solver + De = De*tau/(L*L) + Di = Di*tau/(L*L) + Dm = Dm*tau/(L*L) + Dr = Dr*tau/(L*L) + D4p = D4p*tau/(L*L) + + mue = mue*V0*tau/(L*L) + mui = mui*V0*tau/(L*L) + mum = mum*V0*tau/(L*L) + mur = mur*V0*tau/(L*L) + mu4p = mu4p*V0*tau/(L*L) + + Ck[0:4] *= tau*np0 + Ck[4] *= tau*nAr + Ck[5:9] *= tau + Ck[9:13] *= tau*nAr + Ck[13:] *= tau*np0 + A = A*1.5/e0 # 1.5 to convert from temperature to energy + dH = dH/e0 + qStar = V0/e0 # qe*V0/e0, since e0 in eV, need qe*V0 in eV, which is just V0 in V + alpha = qe*np0*L*L/(V0*eps0) + ks = ks*tau/L + p0 = p/qe/np0 + kappaB = 4.878171165833662*1.6129 # non-dimensional thermal conductivity of background specie + # (2/3)*tau/L**2*Kb/np0/kB, + # where Kb is the thermal conductivity of background specie + + params.beta = np.array([[0,1,1,1,0,0,0,0,0,1,1,1,2,1,2,1,1,2,1,1,1,1,1], # E + [0,1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0], # AR+ + [0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0], # AR(m) + [0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,0,0,0], # AR(r) + [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1], # AR(4p) + [2,1,1,1,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0]], dtype=np.int64) # AR + + params.alfa = np.array([[0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1], # E + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], # AR+ + [2,1,0,2,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0], # AR(m) + [0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1], # AR(r) + [0,0,2,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0], # AR(4p) + [0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0]], dtype=np.int64) # AR + # Rxn1: 2AR(m) -> 2AR + # Rxn2: AR(m) + AR(r) -> E + AR+ + AR + # Rxn3: 2AR(4p) -> E + AR+ + AR + # Rxn4: 2AR(m) -> E + AR+ + AR + # Rxn5: AR(m) + AR -> 2AR + # Rxn6: AR(r) -> AR + # Rxn7: AR(4p) -> AR + # Rxn8: AR(4p) -> AR(m) + # Rxn9: AR(4p) -> AR(r) + # Rxn10: E + AR -> E + AR(m) + # Rxn11: E + AR -> E + AR(r) + # Rxn12: E + AR -> E + AR(4p) + # Rxn13: E + AR -> 2E + AR+ + # Rxn14: E + AR(m) -> E + AR + # Rxn15: E + AR(m) -> 2E + AR+ + # Rxn16: E + AR(m) -> E + AR(r) + # Rxn17: E + AR(m) -> E + AR(4p) + # Rxn18: E + AR(4p) -> 2E + AR+ + # Rxn19: E + AR(4p) -> E + AR(r) + # Rxn20: E + AR(4p) -> E + AR(m) + # Rxn21: E + AR(r) -> E + AR + # Rxn22: E + AR(r) -> E + AR(m) + # Rxn23: E + AR(r) -> E + AR(4p) + + rxnNameDict = { 0: "2Ar(m) => 2Ar", + 1: "Ar(m) + Ar(r) => E + Ar+ + Ar", + 2: "2Ar(4p) => E + Ar+ + Ar", + 3: "2Ar(m) => E + Ar+ + Ar", + 4: "Ar(m) + Ar => 2Ar", + 5: "Ar(r) => Ar", + 6: "Ar(4p) => Ar", + 7: "Ar(4p) => Ar(m)", + 8: "Ar(4p) => Ar(r)", + 9: "lumped.metastable", + 10: "lumped.resonance", + 11: "lumped.2p", + 12: "ionization", + 13: "E + Ar(m) => E + Ar", + 14: "step_ionization", + 15: "E + Ar(m) => E + Ar(r)", + 16: "E + Ar(m) => E + Ar(4p)", + 17: "E + Ar(4p) => 2E + Ar+", + 18: "E + Ar(4p) => E + Ar(r)", + 19: "E + Ar(4p) => E + Ar(m)", + 20: "E + Ar(r) => E + Ar", + 21: "E + Ar(r) => E + Ar(m)", + 22: "E + Ar(r) => E + Ar(4p)"} + + # 4) Set values in params class + params.D[0] = De + params.D[1] = Di + params.D[2] = Dm + params.D[3] = Dr + params.D[4] = D4p + + params.mu[0] = mue + params.mu[1] = mui + params.mu[2] = mum + params.mu[3] = mur + params.mu[4] = mu4p + + params.A[:] = Ck[:] + params.B[:] = B[:] + params.C[:] = A[:] + + # Account for the 2/3 term to convert from electron temperature to electron energy + for i in range(len(params.A)): + params.A[i] *= (2/3)**(params.B[i]) + + params.dH[:] = dH[:] + params.dEps[:] = dEps[:] + params.qStar = qStar + params.alpha = alpha + params.ks = ks + params.gam = gam + params.kappaB = kappaB + params.nAronp0 = nAr / np0 + params.p0 = p0 + params.Tg0 = Tg0 + params.EC = 2.0 * me / mAr \ + * np.sqrt(16.0 * (me + mAr) * e0 * c**2 + / (3.0 * np.pi * me * mAr)) * se * nAr * tau + # params.EC = 2.0 * me / mAr * 3.8e9 * tau + + params.verticalShift = verticalShift / V0 + + # Parameters needed to compute the current with dimensions + params.V0Ltau = V0 / (L * tau) + params.V0L = V0 / L + params.LLV0tau = (L*L) / (V0*tau) + params.tauL = L / tau + params.np0 = np0 # "nominal" electron density [1/m^3] + params.qe = qe # unit charge [C] + params.eps0 = eps0 # unit charge [C] + params.eArea = electrodeArea # electrode area [m^2] + + + reactionExpressionslist = [f"{params.A[0]} * energy**{params.B[0]} * np.exp(-{params.C[0]} / energy)", + f"{params.A[1]} * energy**{params.B[1]} * np.exp(-{params.C[1]} / energy)", + f"{params.A[2]} * energy**{params.B[2]} * np.exp(-{params.C[2]} / energy)", + f"{params.A[3]} * energy**{params.B[3]} * np.exp(-{params.C[3]} / energy)", + f"{params.A[4]} * energy**{params.B[4]} * np.exp(-{params.C[4]} / energy)", + f"{params.A[5]} * energy**{params.B[5]} * np.exp(-{params.C[5]} / energy)", + f"{params.A[6]} * energy**{params.B[6]} * np.exp(-{params.C[6]} / energy)", + f"{params.A[7]} * energy**{params.B[7]} * np.exp(-{params.C[7]} / energy)", + f"{params.A[8]} * energy**{params.B[8]} * np.exp(-{params.C[8]} / energy)", + f"{params.A[9]} * energy**{params.B[9]} * np.exp(-{params.C[9]} / energy)", + f"{params.A[10]} * energy**{params.B[10]} * np.exp(-{params.C[10]} / energy)", + f"{params.A[11]} * energy**{params.B[11]} * np.exp(-{params.C[11]} / energy)", + f"{params.A[12]} * energy**{params.B[12]} * np.exp(-{params.C[12]} / energy)", + f"{params.A[13]} * energy**{params.B[13]} * np.exp(-{params.C[13]} / energy)", + f"{params.A[14]} * energy**{params.B[14]} * np.exp(-{params.C[14]} / energy)", + f"{params.A[15]} * energy**{params.B[15]} * np.exp(-{params.C[15]} / energy)", + f"{params.A[16]} * energy**{params.B[16]} * np.exp(-{params.C[16]} / energy)", + f"{params.A[17]} * energy**{params.B[17]} * np.exp(-{params.C[17]} / energy)", + f"{params.A[18]} * energy**{params.B[18]} * np.exp(-{params.C[18]} / energy)", + f"{params.A[19]} * energy**{params.B[19]} * np.exp(-{params.C[19]} / energy)", + f"{params.A[20]} * energy**{params.B[20]} * np.exp(-{params.C[20]} / energy)", + f"{params.A[21]} * energy**{params.B[21]} * np.exp(-{params.C[21]} / energy)", + f"{params.A[22]} * energy**{params.B[22]} * np.exp(-{params.C[22]} / energy)"] + + reactionTExpressionslist = [f"{params.A[0]} * (energy**({params.B[0]}-1)) * np.exp(-{params.C[0]}/energy) * ({params.B[0]} + {params.C[0]}/energy)", + f"{params.A[1]} * (energy**({params.B[1]}-1)) * np.exp(-{params.C[1]}/energy) * ({params.B[1]} + {params.C[1]}/energy)", + f"{params.A[2]} * (energy**({params.B[2]}-1)) * np.exp(-{params.C[2]}/energy) * ({params.B[2]} + {params.C[2]}/energy)", + f"{params.A[3]} * (energy**({params.B[3]}-1)) * np.exp(-{params.C[3]}/energy) * ({params.B[3]} + {params.C[3]}/energy)", + f"{params.A[4]} * (energy**({params.B[4]}-1)) * np.exp(-{params.C[4]}/energy) * ({params.B[4]} + {params.C[4]}/energy)", + f"{params.A[5]} * (energy**({params.B[5]}-1)) * np.exp(-{params.C[5]}/energy) * ({params.B[5]} + {params.C[5]}/energy)", + f"{params.A[6]} * (energy**({params.B[6]}-1)) * np.exp(-{params.C[6]}/energy) * ({params.B[6]} + {params.C[6]}/energy)", + f"{params.A[7]} * (energy**({params.B[7]}-1)) * np.exp(-{params.C[7]}/energy) * ({params.B[7]} + {params.C[7]}/energy)", + f"{params.A[8]} * (energy**({params.B[8]}-1)) * np.exp(-{params.C[8]}/energy) * ({params.B[8]} + {params.C[8]}/energy)", + f"{params.A[9]} * (energy**({params.B[9]}-1)) * np.exp(-{params.C[9]}/energy) * ({params.B[9]} + {params.C[9]}/energy)", + f"{params.A[10]} * (energy**({params.B[10]}-1)) * np.exp(-{params.C[10]}/energy) * ({params.B[10]} + {params.C[10]}/energy)", + f"{params.A[11]} * (energy**({params.B[11]}-1)) * np.exp(-{params.C[11]}/energy) * ({params.B[11]} + {params.C[11]}/energy)", + f"{params.A[12]} * (energy**({params.B[12]}-1)) * np.exp(-{params.C[12]}/energy) * ({params.B[12]} + {params.C[12]}/energy)", + f"{params.A[13]} * (energy**({params.B[13]}-1)) * np.exp(-{params.C[13]}/energy) * ({params.B[13]} + {params.C[13]}/energy)", + f"{params.A[14]} * (energy**({params.B[14]}-1)) * np.exp(-{params.C[14]}/energy) * ({params.B[14]} + {params.C[14]}/energy)", + f"{params.A[15]} * (energy**({params.B[15]}-1)) * np.exp(-{params.C[15]}/energy) * ({params.B[15]} + {params.C[15]}/energy)", + f"{params.A[16]} * (energy**({params.B[16]}-1)) * np.exp(-{params.C[16]}/energy) * ({params.B[16]} + {params.C[16]}/energy)", + f"{params.A[17]} * (energy**({params.B[17]}-1)) * np.exp(-{params.C[17]}/energy) * ({params.B[17]} + {params.C[17]}/energy)", + f"{params.A[18]} * (energy**({params.B[18]}-1)) * np.exp(-{params.C[18]}/energy) * ({params.B[18]} + {params.C[18]}/energy)", + f"{params.A[19]} * (energy**({params.B[19]}-1)) * np.exp(-{params.C[19]}/energy) * ({params.B[19]} + {params.C[19]}/energy)", + f"{params.A[20]} * (energy**({params.B[20]}-1)) * np.exp(-{params.C[20]}/energy) * ({params.B[20]} + {params.C[20]}/energy)", + f"{params.A[21]} * (energy**({params.B[21]}-1)) * np.exp(-{params.C[21]}/energy) * ({params.B[21]} + {params.C[21]}/energy)", + f"{params.A[22]} * (energy**({params.B[22]}-1)) * np.exp(-{params.C[22]}/energy) * ({params.B[22]} + {params.C[22]}/energy)"] + + + reactionExpressionTypelist = np.array([False,False,False,False,False,False,False,False,False, + True,True,True,True,False,True,True,True,False,True,True,False,True,True]) + + reactionsList = [] + LOGFilename = 'interpolationSample%s.log'%str(iSample) + f = open(LOGFilename, 'w') + # import h5py as h5 + # rxnName = ["Ionization", ...] <- dictionary containing reaction name root string + # for r in range(Nr): + # if reactionExpressionTypeList[r]: + # fileName = "{0:s}.{1:08d}.h5".format(rxnName[r], iSample) + # f = h5.File(filename, "r") + # D = f["table"] + + for i in range(Nr): + if reactionExpressionTypelist[i]: + #Nsample = 1 + #N300 = 200 + + #root_dir = ".." + #rate_file = open("{0:s}/BOLSIGChemistry_6SpeciesRates/reaction300K_{1:d}.txt".format(root_dir, i), 'r') + #temp_file = open("{0:s}/BOLSIGChemistry_6SpeciesRates/reaction300K_Te.txt".format(root_dir), 'r') + + #rateCoeff = np.fromfile(rate_file) + #rateCoeff = np.genfromtxt(rate_file) + #rate_file.close() + #rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + + #Te = np.fromfile(temp_file) + #Te = np.genfromtxt(temp_file) + #temp_file.close() + #Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + + if (i < 15): + f = h5.File("../BOLSIGChemistry_6SpeciesRates/{0:s}.h5".format(rxnNameDict[i]), 'r') + dataset = f["table"] + else: + f = h5.File("../BOLSIGChemistry_6SpeciesRates/StepwiseExcitations.nominal.h5", 'r') + dataset = f[rxnNameDict[i]] + + Te = dataset[:,0] + Te /= 11604 + rateCoeff = dataset[:,1] + rateCoeff /= 6.022e23 + + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy. + Te *= 1.5 + + # Find first non-zero value of the coefficient rate. + I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + + #lastFalse = np.where(indices==False)[-1][-1] + 2 + for k in range(len(Te)): + if Te[k] < 4.5 and indices[k] == False: + lastFalse = k + 2 + + # Transformation to log scale. + TeLog = np.log(Te) + + # Compute the slope of the rate coefficient between its first two non-zero values. + # Finite differences are used. + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) + + # Arrhenius form: kf = A * exp(-C / Te) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + + # Compute pre-exponential coefficient, A, in log scale. + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] + + # Transform rate coefficient in log scale. + rateCoeffLog = np.zeros(rateCoeff.shape) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) + # For the troublesome values, we use the Arrhenius form. + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] + # Nondimensionalization in log scale. + if (i < 13): + rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + else: + rateCoeffLog += - np.log(1.0/tau) + np.log(np0) + + # Interpolation in log scale. + reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) + # Gradient in log scale + reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf_log = reactionExpressionsLog, + kf_T_log = reactionTExpressionsLog) + reactionsList.append(reaction) + + logging.basicConfig(filename=LOGFilename) + logging.warning('Interpolation info (Reaction %s):', i + 1) + logging.warning('First non-zero entry in the rate coefficient: %s', I[0][0]) + logging.warning('Monotonicity of the rate coefficient start from entry: %s', lastFalse) + logging.warning('Position of possible duplicates in mean energy array: %s', + TeDuplicateindsForLog[0]) + + else: + rxn = eval("lambda energy :" + reactionExpressionslist[i]) + rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + + reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + rxnBolsig = reactionExpressionTypelist[i], + kf = rxn, kf_T = rxn_T) + reactionsList.append(reaction) + + params.reactionsList = reactionsList + + # 5) Dump to screen + params.print() diff --git a/timePeriodicSolver.py b/timePeriodicSolver.py index 731017caa..cb239002d 100644 --- a/timePeriodicSolver.py +++ b/timePeriodicSolver.py @@ -198,6 +198,8 @@ def solveNewtonStep(self, Uic, Nt): Ns = 6 elif(args.scenario==10): Ns = 6 + elif(args.scenario==12): + Ns = 6 elif(args.scenario==21): print("# Running scenario = 21 (4 species, 8 rxn, Liu 2017, interpolated transport)") Ns = 4 From cff8e6a248f771061f0f6d0e3c6d34ac744c0f49 Mon Sep 17 00:00:00 2001 From: Juan Pablo Barberena Valencia Date: Wed, 19 Oct 2022 14:00:47 -0700 Subject: [PATCH 25/32] Added 6-Species Nominal Rate Files --- .../StepwiseExcitations.nominal.h5 | Bin 0 -> 14208 bytes BOLSIGChemistry_6SpeciesRates/ionization.h5 | Bin 0 -> 9344 bytes BOLSIGChemistry_6SpeciesRates/lumped.2p.h5 | Bin 0 -> 9344 bytes .../lumped.metastable.h5 | Bin 0 -> 9344 bytes .../lumped.resonance.h5 | Bin 0 -> 9344 bytes .../plot_rates_h5.py | 211 ++++++++++++++++++ .../step_ionization.h5 | Bin 0 -> 9344 bytes 7 files changed, 211 insertions(+) create mode 100644 BOLSIGChemistry_6SpeciesRates/StepwiseExcitations.nominal.h5 create mode 100644 BOLSIGChemistry_6SpeciesRates/ionization.h5 create mode 100644 BOLSIGChemistry_6SpeciesRates/lumped.2p.h5 create mode 100644 BOLSIGChemistry_6SpeciesRates/lumped.metastable.h5 create mode 100644 BOLSIGChemistry_6SpeciesRates/lumped.resonance.h5 create mode 100644 BOLSIGChemistry_6SpeciesRates/plot_rates_h5.py create mode 100644 BOLSIGChemistry_6SpeciesRates/step_ionization.h5 diff --git a/BOLSIGChemistry_6SpeciesRates/StepwiseExcitations.nominal.h5 b/BOLSIGChemistry_6SpeciesRates/StepwiseExcitations.nominal.h5 new file mode 100644 index 0000000000000000000000000000000000000000..c02b8063c250b96a87518697d0008c7e85d5d5bc GIT binary patch literal 14208 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 literal 0 HcmV?d00001 diff --git a/BOLSIGChemistry_6SpeciesRates/ionization.h5 b/BOLSIGChemistry_6SpeciesRates/ionization.h5 new file mode 100644 index 0000000000000000000000000000000000000000..1468ca181ea1453f2c1c703727c65ace0df1dd03 GIT binary patch literal 9344 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 literal 0 HcmV?d00001 diff --git a/BOLSIGChemistry_6SpeciesRates/lumped.2p.h5 b/BOLSIGChemistry_6SpeciesRates/lumped.2p.h5 new file mode 100644 index 0000000000000000000000000000000000000000..b8c33b17837a68b95b5adcb87691f677a8252961 GIT binary patch literal 9344 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 literal 0 HcmV?d00001 diff --git a/BOLSIGChemistry_6SpeciesRates/lumped.metastable.h5 b/BOLSIGChemistry_6SpeciesRates/lumped.metastable.h5 new file mode 100644 index 0000000000000000000000000000000000000000..a2fdd27e48db0e3c46abbc0f33fd9718d0a87cc7 GIT binary patch literal 9344 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 literal 0 HcmV?d00001 diff --git a/BOLSIGChemistry_6SpeciesRates/lumped.resonance.h5 b/BOLSIGChemistry_6SpeciesRates/lumped.resonance.h5 new file mode 100644 index 0000000000000000000000000000000000000000..da36bca5d10367bc48560f34bf92e2e832036a51 GIT binary patch literal 9344 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 Wk_bp5Ac=q^0+I+wBJh7D0{;MJX_mGC literal 0 HcmV?d00001 diff --git a/BOLSIGChemistry_6SpeciesRates/plot_rates_h5.py b/BOLSIGChemistry_6SpeciesRates/plot_rates_h5.py new file mode 100644 index 000000000..d580735ba --- /dev/null +++ b/BOLSIGChemistry_6SpeciesRates/plot_rates_h5.py @@ -0,0 +1,211 @@ +import numpy as np +import csv +from matplotlib import pyplot as plt +from scipy.interpolate import CubicSpline +import matplotlib.colors as mcolors +import h5py as h5 + +tau = (1./13.56e6) +nAr = 3.22e22 +np0 = 8e16 +Nr = 23 +iSample = 0 + +reactionExpressionTypelist = np.array([False, False, False, False, False, False, False, False, False, + True, True, True, True, False, True, True, True, False, True, True, False, True, + True]) + +rxnNameDict = {0: "2AR(m) => 2AR", + 1: "AR(m) + AR(r) => E + AR+ + AR", + 2: "2AR(4p) => E + AR+ + AR", + 3: "2AR(m) => E + AR+ + AR", + 4: "AR(m) + AR => 2AR", + 5: "AR(r) => AR", + 6: "AR(4p) => AR", + 7: "AR(4p) => AR(m)", + 8: "AR(4p) => AR(r)", + 9: "lumped.metastable", + 10: "lumped.resonance", + 11: "lumped.2p", + 12: "ionization", + 13: "E + AR(m) => E + AR", + 14: "step_ionization", + 15: "E + Ar(m) => E + Ar(r)", + 16: "E + Ar(m) => E + Ar(4p)", + 17: "E + Ar(4p) => 2E + Ar+", + 18: "E + Ar(4p) => E + Ar(r)", + 19: "E + Ar(4p) => E + Ar(m)", + 20: "E + Ar(r) => E + Ar", + 21: "E + Ar(r) => E + Ar(m)", + 22: "E + Ar(r) => E + Ar(4p)"} + +reactionsList = [] + # import h5py as h5 + # rxnName = ["Ionization", ...] <- dictionary containing reaction name root string + # for r in range(Nr): + # if reactionExpressionTypeList[r]: + # fileName = "{0:s}.{1:08d}.h5".format(rxnName[r], iSample) + # f = h5.File(filename, "r") + # D = f["table"] + +for i in range(Nr): + if reactionExpressionTypelist[i]: + Nsample = 1 + N300 = 200 + + root_dir = "./" + if (i < 15): + f = h5.File("{0:s}.h5".format(rxnNameDict[i]), 'r') + data = f["table"] + else: + f = h5.File("StepwiseExcitations.nominal.h5", 'r') + data = f[rxnNameDict[i]] + + Te = data[:,0] + rateCoeff = data[:,1] + rateCoeff /= 6.022e23 + + row_temp = [] + data = [] + header = ["Te(K)", "kf(m3/s)"] + for j in range(len(Te)): + row_temp.append(Te[j]) + row_temp.append(rateCoeff[j]) + data.append(row_temp) + row_temp = [] + + g = open("./RateProfile_{0:s}.csv".format(rxnNameDict[i]), 'w') + writer = csv.writer(g) + writer.writerow(header) + writer.writerows(data) + g.close() + + + #rateCoeff = np.reshape(rateCoeff,[Nsample, N300]).T[:,iSample] + #rate_file.close() + + #Te = data[:,0] + + Te /= 11604 + #Te = np.reshape(Te,[Nsample, N300]).T[:,iSample] + #print(Te) + #temp_file.close() + + # Sorting mean energy array and rate coefficient array based on + # the mean energy array. + Teinds = Te.argsort() + rateCoeff = rateCoeff[Teinds] + Te = Te[Teinds] + + # Find duplicates + TeDuplicateinds = np.where(np.abs(np.diff(Te, axis=0)) > 0.0) + TeDuplicateindsForLog = np.where(np.abs(np.diff(Te, axis=0)) == 0.0) + rateCoeff = rateCoeff[TeDuplicateinds] + Te = Te[TeDuplicateinds] + + # Nondimensionalization of mean energy. + Te *= 1.5 + + # Find first non-zero value of the coefficient rate. + I = np.nonzero(rateCoeff) + + diffRateCoeff = [j-i for i, j in zip(rateCoeff[:-1], rateCoeff[1:])] + diffTe = [j-i for i, j in zip(Te[:-1], Te[1:])] + + Monotonicity = np.asarray([j/i for i, j in zip(diffTe, diffRateCoeff)]) + Monotonicity = np.insert(Monotonicity, 0, 0.0, axis=0) + + Nan = np.isnan(Monotonicity) + Inf = np.isinf(Monotonicity) + indexPositive = np.where(Monotonicity>0.0) + Positive = np.full(Monotonicity.shape, False, dtype=bool) + Positive[indexPositive] = True + + indices = Nan + Inf + Positive + + #lastFalse = np.where(indices==False)[-1][-1] + 2 + for k in range(len(Te)): + if (Te[k] < 4.5 and indices[k] == False): + lastFalse = k + 2 + + # Transformation to log scale. + TeLog = np.log(Te) + + # Compute the slope of the rate coefficient between its first two non-zero values. + # Finite differences are used. + dydx = (rateCoeff[lastFalse + 1] - rateCoeff[lastFalse]) \ + / (Te[lastFalse + 1] - Te[lastFalse]) + + # Arrhenius form: kf = A * exp(-C / Te) + C = Te[lastFalse]**2.0*dydx / rateCoeff[lastFalse] + + # Compute pre-exponential coefficient, A, in log scale. + ALog = np.log(rateCoeff[lastFalse]) + C / Te[lastFalse] + + # Transform rate coefficient in log scale. + rateCoeffLog = np.zeros(rateCoeff.shape) + rateCoeffLog[lastFalse:] = np.log(rateCoeff[lastFalse:]) + # For the troublesome values, we use the Arrhenius form. + rateCoeffLog[0:lastFalse] = ALog - C / Te[0:lastFalse] + # Nondimensionalization in log scale. + #if i < 2: + # rateCoeffLog += - np.log(1.0/tau) + np.log(nAr) + #else: + # rateCoeffLog += - np.log(1.0/tau) + np.log(np0) + + # Interpolation in log scale. + reactionExpressionsLog = CubicSpline(TeLog, rateCoeffLog) + # Gradient in log scale + reactionTExpressionsLog = CubicSpline.derivative(reactionExpressionsLog) + + #reaction = Reaction(rxnAlfa = params.alfa[:,[i]], rxnBeta = params.beta[:,[i]], + # rxnBolsig = reactionExpressionTypelist[i], + # kf_log = reactionExpressionsLog, + # kf_T_log = reactionTExpressionsLog) + #reactionsList.append(reaction) + + + # rxn = eval("lambda energy :" + reactionExpressionslist[i]) + # rxn_T = eval("lambda energy :" + reactionTExpressionslist[i]) + # setting the axes at the centre + #fig ,ax = plt.subplots(figsize=(9, 6)) + #ax.spines["top"].set_visible(True) + #ax.spines["right"].set_visible(True) + #ax.set_yscale('log') + #ax.set_xscale('log') + + # plot the function + #plt.plot(rateCoeffXFiner, np.exp(reactionExpressions_cubicSplineDerivative_log(rateCoeffXFiner)), + # color='salmon', linestyle='--', label='interBolsig') + #plt.plot(rateCoeffXFine, np.exp(reactionExpressions_cubicSpline_log(rateCoeffXFine)), + # color='lightgreen', linestyle='--', label='interBolsig') + #plt.plot(Te[:,0], reactionTExpressionsLogFiltered(TeLog[:]) * np.exp(reactionExpressionsLog(TeLog[:])) / Te[:,0], + # color='blue', linestyle='-', label='interBolsig') + #plt.plot(Te, np.exp(reactionExpressionsLog(TeLog[:])), + # color='green', linestyle='-', label='Bolsig') + #plt.plot(Te, rxn(Te), + # color='salmon', linestyle='--', label='Liu') + #plt.plot(Te[:,0], rxn_T(Te[:,0]), + # color='red', linestyle='--', label='interBolsig') + #plt.xlim((0.05,100)) + #plt.ylim((1e-50,300)) + #plt.legend() + #plt.savefig("./PlotRates_%s.pdf" %str(i), dpi=300) + #plt.xlim((-0.0001,0.0255)) + #plt.show() + + # Export rates to CSV Files + #header = ['Te', 'kf'] + #row_temp = [] + #data = [] + #for j in range(len(Te)): + # row_temp.append(Te[j]) + # row_temp.append(np.exp(reactionExpressionsLog(TeLog[j]))) + # data.append(row_temp) + # row_temp = [] + + #f = open("./PlotRates_Rxn%s.csv" %str(i), 'w') + #writer = csv.writer(f) + #writer.writerow(header) + #writer.writerows(data) + # f.close() diff --git a/BOLSIGChemistry_6SpeciesRates/step_ionization.h5 b/BOLSIGChemistry_6SpeciesRates/step_ionization.h5 new file mode 100644 index 0000000000000000000000000000000000000000..beabf8706256f02b129935e5318b6401a4ad972c GIT binary patch literal 9344 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 z Date: Fri, 21 Oct 2022 08:42:59 -0500 Subject: [PATCH 26/32] Replace reference solution for 6 species test This file was generated on the 6Species_23Rxn_Juan branch. Replacing original b/c it had the full period (rather than just the solution from the Newton shooting step), and the solution differ isn't configured to handle that. --- reference_solns/Nominal_Np250_solution.npy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference_solns/Nominal_Np250_solution.npy b/reference_solns/Nominal_Np250_solution.npy index 1fdc30de6..59400c490 100644 --- a/reference_solns/Nominal_Np250_solution.npy +++ b/reference_solns/Nominal_Np250_solution.npy @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c7d6ff75350bee21dbb6309fd43f498b066598936100869c26040a7d88cf0160 -size 1806128 +oid sha256:460eb9c41df691b0ada34efb9146c74403422497f106b85fe008d5c008fbecbe +size 14128 From 6e904b5ec0ad06bad3e5f7d5bc7208002b555a8e Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Fri, 21 Oct 2022 10:58:14 -0500 Subject: [PATCH 27/32] Fix number of variables for diff in 6 species test --- test6Species.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test6Species.sh b/test6Species.sh index c8e61a137..af19e0a6f 100755 --- a/test6Species.sh +++ b/test6Species.sh @@ -28,7 +28,7 @@ baseCmd="$EXE --Np $Np --Nt $Nt --dt $dt --scenario $scenario --EinsteinForm --e newtCmd="$NEWTEXE --Np $Np --Nt $Nt1 --Nn 20 --scenario $scenario --tscheme CN --alpha0 0.1 --increaseFac 1.5 --EinsteinForm --elasticCollisionActivation --backgroundSpecieActivation" saveCmd="$EXE --Np $Np --Nt $Nt1 --dt $dt --scenario $scenario --tscheme CN --EinsteinForm --elasticCollisionActivation --backgroundSpecieActivation" -diffCmd="python3 ../diffSolns.py --reference ../reference_solns/Nominal_Np250_solution.npy --Np $Np --Nv 5" +diffCmd="python3 ../diffSolns.py --reference ../reference_solns/Nominal_Np250_solution.npy --Np $Np --Nv 7" screenOut="run6species.out" From 9c450898cfd7907c6af374bfa5c5c928ea27720d Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Fri, 21 Oct 2022 16:56:23 -0500 Subject: [PATCH 28/32] Einstein only for electrons --- chebSolver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chebSolver.py b/chebSolver.py index 3328bb157..6e654858f 100644 --- a/chebSolver.py +++ b/chebSolver.py @@ -193,7 +193,7 @@ def diffusivity(self, i, energy, mu, nb, EinsteinForm): DEf[:,0] = self.diffusivityList[i].D_expression((2./3)*energy[:,i]) / nb - elif EinsteinForm: + elif EinsteinForm and self.Z[i] == -1: V0 = self.qStar * 1.0 # V0 = qStar * 1eV DEf = 2.0 / 3.0 * np.multiply(energy[:,[i]], mu[:,[i]]) / V0 From f56a50a9659202e00cfbf7f0941925b5a25f7628 Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Fri, 21 Oct 2022 16:56:48 -0500 Subject: [PATCH 29/32] be more agressive with Newton solve on 6 species test --- test6Species.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test6Species.sh b/test6Species.sh index af19e0a6f..767a6b7ec 100755 --- a/test6Species.sh +++ b/test6Species.sh @@ -25,7 +25,7 @@ newtFile="newton_6spec_CN_Np${Np}.npy" saveFile="newton_6spec_CN_Np${Np}_fullsoln.npy" baseCmd="$EXE --Np $Np --Nt $Nt --dt $dt --scenario $scenario --EinsteinForm --elasticCollisionActivation --backgroundSpecieActivation" -newtCmd="$NEWTEXE --Np $Np --Nt $Nt1 --Nn 20 --scenario $scenario --tscheme CN --alpha0 0.1 --increaseFac 1.5 --EinsteinForm --elasticCollisionActivation --backgroundSpecieActivation" +newtCmd="$NEWTEXE --Np $Np --Nt $Nt1 --Nn 20 --scenario $scenario --tscheme CN --alpha0 0.25 --increaseFac 2.0 --EinsteinForm --elasticCollisionActivation --backgroundSpecieActivation" saveCmd="$EXE --Np $Np --Nt $Nt1 --dt $dt --scenario $scenario --tscheme CN --EinsteinForm --elasticCollisionActivation --backgroundSpecieActivation" diffCmd="python3 ../diffSolns.py --reference ../reference_solns/Nominal_Np250_solution.npy --Np $Np --Nv 7" From c198ccb10b327f1a942445ce68b567701008aedf Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Fri, 21 Oct 2022 20:49:32 -0500 Subject: [PATCH 30/32] delete tmp test dir when 6 species test passes --- test6Species.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test6Species.sh b/test6Species.sh index 767a6b7ec..3e5faeef3 100755 --- a/test6Species.sh +++ b/test6Species.sh @@ -38,3 +38,6 @@ $newtCmd --V0 100 --VDC 0.0 --gam 0.01 --rtol 1e-8 --restart "../reference_solns --outfile $newtFile >> $screenOut || error_exit "Shooting failed" $diffCmd --solution $newtFile >> $screenOut || error_exit "Solution differs from reference" + +# if test passed, delete tmp dir +rm -rf $tmp_dir From 09aa0fdc52d2eb2af3fd4d9c5ca8a4e81dd10227 Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Tue, 24 Jun 2025 14:42:28 -0500 Subject: [PATCH 31/32] Add 6 species test to automated regression --- .github/workflows/regression_test.yaml | 2 ++ runAllTests.sh | 7 +++++++ test6Species.sh | 3 +-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100755 runAllTests.sh diff --git a/.github/workflows/regression_test.yaml b/.github/workflows/regression_test.yaml index 71d55abb8..307d8b9e9 100644 --- a/.github/workflows/regression_test.yaml +++ b/.github/workflows/regression_test.yaml @@ -33,3 +33,5 @@ jobs: run: ./testInterpTrans.sh - name: Run variable background CN test run: ./testRunBackground.sh + - name: Run six species test + run: ./test6Species.sh diff --git a/runAllTests.sh b/runAllTests.sh new file mode 100755 index 000000000..33b15fbd2 --- /dev/null +++ b/runAllTests.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +./testRunBase.sh || echo "testRunBase.sh failed" +./testRunCN.sh +./testInterpTrans.sh +./testRunBackground.sh +./test6Species.sh diff --git a/test6Species.sh b/test6Species.sh index 3e5faeef3..2a4e0ca72 100755 --- a/test6Species.sh +++ b/test6Species.sh @@ -6,8 +6,6 @@ error_exit() exit 1 } -#module load python/3.8.2 - tmp_dir=$(mktemp -d -t tmp-test-XXXXXXXXXX --tmpdir=.) echo "Running 6 species test in $tmp_dir" cd $tmp_dir @@ -40,4 +38,5 @@ $newtCmd --V0 100 --VDC 0.0 --gam 0.01 --rtol 1e-8 --restart "../reference_solns $diffCmd --solution $newtFile >> $screenOut || error_exit "Solution differs from reference" # if test passed, delete tmp dir +cd .. rm -rf $tmp_dir From 49251f8eacb26766c38fc14d37e9e922c7a1aa61 Mon Sep 17 00:00:00 2001 From: "Todd A. Oliver" Date: Tue, 24 Jun 2025 15:20:45 -0500 Subject: [PATCH 32/32] Add h5py to test environment --- .github/workflows/regression_test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/regression_test.yaml b/.github/workflows/regression_test.yaml index 307d8b9e9..a21f1d20c 100644 --- a/.github/workflows/regression_test.yaml +++ b/.github/workflows/regression_test.yaml @@ -24,7 +24,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install numpy scipy matplotlib + pip install numpy scipy matplotlib h5py - name: Run Liu case test run: ./testRunBase.sh - name: Run constant background CN test