| @@ -0,0 +1,27 @@ | |||||
| This is the public repository for the code sensBVP. Its use is in | |||||
| calculating sensitivity coefficients of ignition delay time to rate | |||||
| coefficients. In sensBVP, this is carried out by transforming the | |||||
| initial value problem to a boundary value problem, reducing the time to | |||||
| calculate the sensitivity coefficients by at least an order of | |||||
| magnitude. | |||||
| In order to install sensBVP, modify the various paths in the Makefile. | |||||
| Make sure that SUNDIALS (v3.1.1 or higher), Cantera (2.3 or higher), and | |||||
| GSL are installed. Run make all, followed by make install in the source | |||||
| directory. | |||||
| After installing, the executable sensBVP can be executed as follows: | |||||
| sensBVP -a <absolute tolerance> | |||||
| -r <relative tolerance> | |||||
| -f <BVP residue tolerance> | |||||
| -T <initial temperature in K> | |||||
| -P <initial pressure in atm> | |||||
| -m <mechanism file (cti or xml)> | |||||
| -c <mole fraction composition> | |||||
| -t <integration time> | |||||
| -s <enable sensitivity analysis> | |||||
| Execute sensBVP -h for all available options. | |||||
| Try the cases in the examples directory. | |||||
| @@ -0,0 +1 @@ | |||||
| sensBVP -r 1e-06 -a 1e-12 -f 1e-07 -T 900.0 -P 10.0 -m ./mech-FFCM1.cti -c CH4:0.0499002,O2:0.199601,N2:0.750499 -t 1 -s | |||||
| @@ -0,0 +1 @@ | |||||
| sensBrute -r 1e-06 -a 1e-12 -T 900.0 -P 10.0 -m ./mech-FFCM1.cti -c CH4:0.0499002,O2:0.199601,N2:0.750499 -t 1 -s | |||||
| @@ -0,0 +1,64 @@ | |||||
| """ | |||||
| Constant-pressure, adiabatic kinetics simulation with sensitivity analysis | |||||
| """ | |||||
| import sys | |||||
| import time | |||||
| import numpy as np | |||||
| start = time.time() | |||||
| import cantera as ct | |||||
| gas = ct.Solution('./mech-FFCM1.cti') | |||||
| temp = 900.0 | |||||
| pres = 10.0*ct.one_atm | |||||
| gas.TPX = temp, pres, 'CH4:0.0499002,O2:0.199601,N2:0.750499' | |||||
| r = ct.IdealGasConstPressureReactor(gas, name='R1') | |||||
| sim = ct.ReactorNet([r]) | |||||
| # enable sensitivity with respect to all reactions | |||||
| for i in range(0,gas.n_reactions): | |||||
| r.add_sensitivity_reaction(i) | |||||
| # set the tolerances for the solution and for the sensitivity coefficients | |||||
| sim.rtol = 1.0e-6 | |||||
| sim.atol = 1.0e-12 | |||||
| sim.rtol_sensitivity = 1.0e-6 | |||||
| sim.atol_sensitivity = 1.0e-12 | |||||
| #states = ct.SolutionArray(gas, extra=['t','s2']) | |||||
| ignitionStateFound=False | |||||
| Told=temp | |||||
| TIgn=1.115367e+03 #K | |||||
| tEnd=1.0 #s | |||||
| tauIgn=0.0 | |||||
| nPts=1000 | |||||
| dt=tEnd/(float(nPts)-1.0) | |||||
| sens=np.zeros(gas.n_reactions) | |||||
| out=open("ignitionSensitivities.dat","w") | |||||
| for t in np.arange(0, tEnd, dt): | |||||
| TOld=r.T | |||||
| sim.advance(t) | |||||
| TCurrent=r.T | |||||
| for i in range(0,gas.n_reactions): | |||||
| sens[i] = sim.sensitivity('temperature', i) | |||||
| if(ignitionStateFound==False): | |||||
| if(r.T>=TIgn): | |||||
| print("Ignition state found!\n") | |||||
| print("T=%15.6e K\n"%(TCurrent)) | |||||
| print("tau=%15.6e s\n"%(t)) | |||||
| ignitionStateFound=True | |||||
| tauIgn=t | |||||
| dTdtau=(TCurrent-TOld)/dt | |||||
| for i in range(0,gas.n_reactions): | |||||
| sens[i]=sens[i]*(-1.0e0/dTdtau)*(TCurrent/tauIgn) | |||||
| out.write("%15d\t%15.6e\n"%(i,sens[i])) | |||||
| break | |||||
| out.close() | |||||
| end = time.time() | |||||
| print("Elapsed time: %15.6e s\n"%(end-start)) | |||||
| @@ -0,0 +1,61 @@ | |||||
| compiler =g++ | |||||
| CANTERA_DIR =/opt/scientific/cantera-2.4_gnu_blas | |||||
| CVODE_DIR =/opt/scientific/sundials-3.1.1_gnu_blas | |||||
| KINSOL_DIR =/opt/scientific/sundials-3.1.1_gnu_blas | |||||
| BVPEXE =sensBVP | |||||
| BRUTEEXE =sensBrute | |||||
| DESTDIR =~/bin | |||||
| CANTERA_INCLUDES=-I$(CANTERA_DIR)/include | |||||
| CVODE_INCLUDES =-I$(CVODE_DIR)/include | |||||
| KINSOL_INCLUDES =-I$(KINSOL_DIR)/include | |||||
| CVODE_LIBS =-L$(CVODE_DIR)/lib -lsundials_nvecserial -lsundials_cvode | |||||
| KINSOL_LIBS =-L$(KINSOL_DIR)/lib -lsundials_kinsol | |||||
| CANTERA_LIBS =-L$(CANTERA_DIR)/lib -lcantera_shared | |||||
| GSL_INCLUDES =-I/usr/include/gsl | |||||
| GSL_LIBS =-L/usr/lib -lgsl -lgslcblas | |||||
| RPATH =-Wl,-rpath=$(CVODE_DIR)/lib,-rpath=$(KINSOL_DIR)/lib | |||||
| RM=rm -f | |||||
| compiler?=g++ | |||||
| ifeq ($(compiler),g++) | |||||
| CPPFLAGS= -Wall -O3 | |||||
| CPP=g++ | |||||
| endif | |||||
| ifeq ($(compiler),icpc) | |||||
| export GXX_INCLUDE=/usr/lib/gcc/x86_64-pc-linux-gnu/7.4.1/include/c++ | |||||
| CPPFLAGS= -Wall -O3 -gxx-name=/usr/bin/g++-7 -std=c++11 | |||||
| CPP=icpc | |||||
| endif | |||||
| all: $(BVPEXE) $(BRUTEEXE) | |||||
| sensBVP.o: sensBVP.cpp | |||||
| $(CPP) $(CPPFLAGS) $(CANTERA_INCLUDES) $(CVODE_INCLUDES) \ | |||||
| $(KINSOL_INCLUDES) $(GSL_INCLUDES) \ | |||||
| -c sensBVP.cpp -o sensBVP.o | |||||
| sensBrute.o: sensBrute.cpp | |||||
| $(CPP) $(CPPFLAGS) $(CANTERA_INCLUDES) $(CVODE_INCLUDES) \ | |||||
| $(GSL_INCLUDES) \ | |||||
| -c sensBrute.cpp -o sensBrute.o | |||||
| $(BVPEXE): sensBVP.o | |||||
| $(CPP) $(CPPFLAGS) \ | |||||
| sensBVP.o -o $(BVPEXE) $(RPATH) $(CVODE_LIBS) \ | |||||
| $(KINSOL_LIBS) $(CANTERA_LIBS) $(GSL_LIBS) | |||||
| $(BRUTEEXE): sensBrute.o | |||||
| $(CPP) $(CPPFLAGS) \ | |||||
| sensBrute.o -o $(BRUTEEXE) $(RPATH) $(CVODE_LIBS) \ | |||||
| $(CANTERA_LIBS) $(GSL_LIBS) | |||||
| .PHONY: install | |||||
| install: | |||||
| cp $(BVPEXE) $(BRUTEEXE) $(DESTDIR) | |||||
| clean: | |||||
| rm -f $(BVPEXE) $(BRUTEEXE) *.o *.d | |||||
| @@ -1135,30 +1135,12 @@ static int residueKS(N_Vector yp, N_Vector res, void *user_data) | |||||
| static void lookupDpdt(UserData data, realtype t, realtype *P, realtype *dPdt) | static void lookupDpdt(UserData data, realtype t, realtype *P, realtype *dPdt) | ||||
| { | { | ||||
| realtype *tData, *PData, *dPdtData; | |||||
| tData = N_VGetArrayPointer_Serial(data->tArray); | |||||
| PData = N_VGetArrayPointer_Serial(data->PArray); | |||||
| realtype *dPdtData; | |||||
| dPdtData = N_VGetArrayPointer_Serial(data->dPdtArray); | dPdtData = N_VGetArrayPointer_Serial(data->dPdtArray); | ||||
| int jguess=data->jguess; | |||||
| int k=0; | |||||
| int safel=0; | |||||
| int nOrder=4; | |||||
| realtype dy; | |||||
| int npts=data->tArraySize; | int npts=data->tArraySize; | ||||
| if(t<=data->t1){ | if(t<=data->t1){ | ||||
| //k=hunt(t, tData, npts, jguess); | |||||
| ////printf("Desired value at %d: %15.6e\t%15.6e\t%15.6e\n",k,t,P(k),dPdt(k)); | |||||
| //safel=IMIN(IMAX(k-(nOrder)/2,0),data->tArraySize+1-nOrder-1); | |||||
| //data->jguess=safel; | |||||
| ////printf("safel %d: \n",safel); | |||||
| ////printf("safel val %15.6e: \n",*(tData+safel)); | |||||
| //polint(tData+safel-1, PData+safel-1, nOrder+1, t, P, &dy); | |||||
| ////printf("P error %15.6e: \n",dy); | |||||
| //polint(tData+safel-1, dPdtData+safel-1, nOrder+1, t, dPdt, &dy); | |||||
| ////printf("dPdt error %15.6e: \n",dy); | |||||
| //// | |||||
| *P=gsl_spline_eval(data->spline,t,data->acc); | *P=gsl_spline_eval(data->spline,t,data->acc); | ||||
| *dPdt=gsl_spline_eval(data->splinedot,t,data->accdot); | *dPdt=gsl_spline_eval(data->splinedot,t,data->accdot); | ||||