Droplet Lagrangian Transient One-dimensional Reacting Code Implementation of both liquid and gas phase governing equations.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

3289 satır
113KB

  1. #ifndef GSL_DEF
  2. #define GSL_DEF
  3. #include <gsl/gsl_math.h>
  4. #include <gsl/gsl_spline.h>
  5. #endif
  6. #include "residue.h"
  7. #include "macros.h"
  8. #include <cmath>
  9. #include <stdio.h>
  10. #include "timing.hpp"
  11. void REGRID(double *ydata, double *ydotdata, UserData data) {
  12. size_t nPts = data->npts;
  13. size_t nvar = data->nvar;
  14. double WORK[nPts], XNEW[nPts], XOLD[nPts];
  15. double P, R, R0, R1, R2, TV1, TV2, XLEN, B1, B2;
  16. double DX, DDX;
  17. double DETA, ETAJ, DEL;
  18. size_t ISTART;
  19. P = data->PCAD;
  20. R = data->RGTC;
  21. R0 = 1.0 - P;
  22. R1 = P * R / (R + 1.0);
  23. R2 = P - R1;
  24. TV1 = 0.0;
  25. TV2 = 0.0;
  26. for (size_t i = 2; i <= nPts; i++) {
  27. TV1 = TV1 + fabs(T(i) - T(i - 1));
  28. }
  29. for (size_t i = 2; i <= nPts - 1; i++) {
  30. TV2 = TV2 + fabs((T(i + 1) - T(i)) / (R(i + 1) - R(i)) - (T(i) - T(i - 1)) / (R(i) - R(i - 1)));
  31. }
  32. XLEN = R(nPts) - R(1);
  33. B1 = R1 * XLEN / ((1.0 - P) * TV1);
  34. B2 = R2 * XLEN / ((1.0 - P) * TV2);
  35. //Compute partial sum of weight function
  36. WORK(1) = 0.0;
  37. DX = 0.0;
  38. for (size_t i = 2; i <= nPts - 1; i++) {
  39. DX = R(i) - R(i - 1);
  40. WORK(i) = DX + B1 * fabs(T(i) - T(i - 1)) + WORK(i - 1) +
  41. B2 * fabs((T(i + 1) - T(i)) / (R(i + 1) - R(i)) - (T(i) - T(i - 1)) / (R(i) - R(i - 1)));
  42. }
  43. DDX = R(nPts) - R(nPts - 1);
  44. WORK(nPts) = WORK(nPts - 1) + DDX;
  45. for (size_t i = 2; i <= nPts; i++) {
  46. WORK(i) = WORK(i) / WORK(nPts);
  47. }
  48. XNEW(1) = R(1);
  49. XNEW(nPts) = R(nPts);
  50. ISTART = 2;
  51. //double DETA;
  52. DETA = 1.0 / (nPts - 1);
  53. //Fill new grid XNEW[nPts],duplicate from PREMIX REGRID SUBROUTINE
  54. for (size_t j = 2; j <= nPts - 1; j++) {
  55. ETAJ = (j - 1) * DETA;
  56. for (size_t i = ISTART; i <= nPts; i++) {
  57. if (ETAJ <= WORK(i)) {
  58. DEL = (ETAJ - WORK(i - 1)) / (WORK(i) - WORK(i - 1));
  59. XNEW(j) = R(i - 1) + (R(i) - R(i - 1)) * DEL;
  60. break;
  61. } else {
  62. ISTART = i;
  63. }
  64. }
  65. }
  66. //Interpolate solution based on XNEW[]&XOLD[]
  67. for (size_t i = 1; i <= nPts; i++) {
  68. XOLD[i - 1] = R(i);
  69. }
  70. INTERPO(ydata, ydotdata, nvar, nPts, XNEW, XOLD);
  71. }
  72. void INTERPO(double *y, double *ydot, const size_t nvar, size_t nPts, const double XNEW[], const double XOLD[]) {
  73. double ytemp[nPts], ydottemp[nPts];
  74. gsl_interp_accel *acc;
  75. gsl_spline *spline;
  76. acc = gsl_interp_accel_alloc();
  77. spline = gsl_spline_alloc(gsl_interp_steffen, nPts);
  78. gsl_interp_accel *accdot;
  79. gsl_spline *splinedot;
  80. accdot = gsl_interp_accel_alloc();
  81. splinedot = gsl_spline_alloc(gsl_interp_steffen, nPts);
  82. for (size_t j = 0; j < nvar; j++) {
  83. for (size_t i = 0; i < nPts; i++) {
  84. ytemp[i] = y[j + i * nvar];
  85. ydottemp[i] = y[j + i * nvar];
  86. }
  87. gsl_spline_init(spline, XOLD, ytemp, nPts);
  88. gsl_spline_init(splinedot, XOLD, ydottemp, nPts);
  89. for (size_t i = 0; i < nPts; i++) {
  90. y[j + i * nvar] = gsl_spline_eval(spline, XNEW[i], acc);
  91. ydot[j + i * nvar] = gsl_spline_eval(splinedot, XNEW[i], accdot);
  92. }
  93. }
  94. gsl_interp_accel_free(acc);
  95. gsl_spline_free(spline);
  96. gsl_interp_accel_free(accdot);
  97. gsl_spline_free(splinedot);
  98. }
  99. double maxTemperaturePosition(const double *y, const size_t nt, const size_t nvar, const double *x, size_t nPts) {
  100. double maxT = 0.0e0;
  101. double TempT = 0.0e0;
  102. double pos = 0.0e0;
  103. for (size_t i = 1; i <= nPts; i++) {
  104. TempT = y[(i - 1) * nvar + nt];
  105. if (TempT > maxT) {
  106. maxT = TempT;
  107. pos = x[i - 1];
  108. }
  109. }
  110. return (pos);
  111. }
  112. double maxTemperature(const double *y, const size_t nt, const size_t nvar, size_t nPts) {
  113. double maxT = 0.0e0;
  114. double TempT = 0.0e0;
  115. //int index = 0 ;
  116. for (size_t i = 1; i <= nPts; i++) {
  117. TempT = y[(i - 1) * nvar + nt];
  118. if (TempT > maxT) {
  119. maxT = TempT;
  120. }
  121. }
  122. return (maxT);
  123. }
  124. //Index here is 1-based
  125. int maxTemperatureIndex(const double *y, const size_t nt, const size_t nvar, size_t nPts) {
  126. double maxT = 0.0e0;
  127. double TempT = 0.0e0;
  128. int index = 0;
  129. for (size_t i = 1; i <= nPts; i++) {
  130. TempT = y[(i - 1) * nvar + nt];
  131. if (TempT > maxT) {
  132. maxT = TempT;
  133. index = i;
  134. }
  135. }
  136. return (index);
  137. }
  138. double maxCurvPositionR(const double *y, const size_t nt,
  139. const size_t nvar, const size_t nr, size_t nPts) {
  140. double maxCurvT = 0.0e0;
  141. double gradTp = 0.0e0;
  142. double gradTm = 0.0e0;
  143. double curvT = 0.0e0;
  144. double dx = 0.0e0;
  145. double dr = 0.0e0;
  146. double pos = 0.0e0;
  147. size_t j, jm, jp;
  148. size_t r, rp, rm;
  149. for (size_t i = 1; i < nPts - 1; i++) {
  150. j = i * nvar + nt;
  151. jm = (i - 1) * nvar + nt;
  152. jp = (i + 1) * nvar + nt;
  153. r = i * nvar + nr;
  154. rm = (i - 1) * nvar + nr;
  155. rp = (i + 1) * nvar + nr;
  156. //gradTp=fabs((y[jp]-y[j])/(x[i+1]-x[i]));
  157. //gradTm=fabs((y[j]-y[jm])/(x[i]-x[i-1]));
  158. //dx=0.5e0*((x[i]+x[i+1])-(x[i-1]+x[i]));
  159. //curvT=(gradTp-gradTm)/dx;
  160. gradTp = fabs((y[jp] - y[j]) / (y[rp] - y[r]));
  161. gradTp = fabs((y[j] - y[jm]) / (y[r] - y[rm]));
  162. dr = 0.5e0 * (y[rp] - y[rm]);
  163. curvT = (gradTp - gradTm) / dr;
  164. if (curvT >= maxCurvT) {
  165. maxCurvT = curvT;
  166. pos = y[r];
  167. }
  168. }
  169. return (pos);
  170. }
  171. int maxCurvIndexR(const double *y, const size_t nt,
  172. const size_t nvar, const size_t nr, size_t nPts) {
  173. double maxCurvT = 0.0e0;
  174. double gradTp = 0.0e0;
  175. double gradTm = 0.0e0;
  176. double curvT = 0.0e0;
  177. double dx = 0.0e0;
  178. double dr = 0.0e0;
  179. int pos = 0;
  180. size_t j, jm, jp;
  181. size_t r, rm, rp;
  182. for (size_t i = 1; i < nPts - 1; i++) {
  183. j = i * nvar + nt;
  184. jm = (i - 1) * nvar + nt;
  185. jp = (i + 1) * nvar + nt;
  186. r = i * nvar + nr;
  187. rm = (i - 1) * nvar + nr;
  188. rp = (i + 1) * nvar + nr;
  189. //gradTp=fabs((y[jp]-y[j])/(x[i+1]-x[i]));
  190. //gradTm=fabs((y[j]-y[jm])/(x[i]-x[i-1]));
  191. //dx=0.5e0*((x[i]+x[i+1])-(x[i-1]+x[i]));
  192. //curvT=(gradTp-gradTm)/dx;
  193. gradTp = fabs((y[jp] - y[j]) / (y[rp] - y[r]));
  194. gradTp = fabs((y[j] - y[jm]) / (y[r] - y[rm]));
  195. dr = 0.5e0 * (y[rp] - y[rm]);
  196. curvT = (gradTp - gradTm) / dr;
  197. if (curvT >= maxCurvT) {
  198. maxCurvT = curvT;
  199. pos = i;
  200. }
  201. }
  202. return (pos);
  203. }
  204. double maxGradPosition(const double *y, const size_t nt,
  205. const size_t nvar, const double *x, size_t nPts) {
  206. double maxGradT = 0.0e0;
  207. double gradT = 0.0e0;
  208. double pos = 0.0e0;
  209. size_t j, jm;
  210. for (size_t i = 1; i < nPts; i++) {
  211. j = i * nvar + nt;
  212. jm = (i - 1) * nvar + nt;
  213. gradT = fabs((y[j] - y[jm]) / (x[i] - x[i - 1]));
  214. if (gradT >= maxGradT) {
  215. maxGradT = gradT;
  216. pos = x[i];
  217. }
  218. }
  219. return (pos);
  220. }
  221. int maxGradIndex(const double *y, const size_t nt,
  222. const size_t nvar, const double *x, size_t nPts) {
  223. double maxGradT = 0.0e0;
  224. double gradT = 0.0e0;
  225. int pos = 0;
  226. size_t j, jm;
  227. for (size_t i = 1; i < nPts; i++) {
  228. j = i * nvar + nt;
  229. jm = (i - 1) * nvar + nt;
  230. gradT = fabs((y[j] - y[jm]) / (x[i] - x[i - 1]));
  231. if (gradT >= maxGradT) {
  232. maxGradT = gradT;
  233. pos = i;
  234. }
  235. }
  236. return (pos);
  237. }
  238. double maxCurvPosition(const double *y, const size_t nt,
  239. const size_t nvar, const double *x, size_t nPts) {
  240. double maxCurvT = 0.0e0;
  241. double gradTp = 0.0e0;
  242. double gradTm = 0.0e0;
  243. double curvT = 0.0e0;
  244. double dx = 0.0e0;
  245. double pos = 0.0e0;
  246. size_t j, jm, jp;
  247. for (size_t i = 1; i < nPts - 1; i++) {
  248. j = i * nvar + nt;
  249. jm = (i - 1) * nvar + nt;
  250. jp = (i + 1) * nvar + nt;
  251. gradTp = fabs((y[jp] - y[j]) / (x[i + 1] - x[i]));
  252. gradTm = fabs((y[j] - y[jm]) / (x[i] - x[i - 1]));
  253. dx = 0.5e0 * ((x[i] + x[i + 1]) - (x[i - 1] + x[i]));
  254. curvT = (gradTp - gradTm) / dx;
  255. if (curvT >= maxCurvT) {
  256. maxCurvT = curvT;
  257. pos = x[i];
  258. }
  259. }
  260. return (pos);
  261. }
  262. int maxCurvIndex(const double *y, const size_t nt,
  263. const size_t nvar, const double *x, size_t nPts) {
  264. double maxCurvT = 0.0e0;
  265. double gradTp = 0.0e0;
  266. double gradTm = 0.0e0;
  267. double curvT = 0.0e0;
  268. double dx = 0.0e0;
  269. int pos = 0;
  270. size_t j, jm, jp;
  271. for (size_t i = 1; i < nPts - 1; i++) {
  272. j = i * nvar + nt;
  273. jm = (i - 1) * nvar + nt;
  274. jp = (i + 1) * nvar + nt;
  275. gradTp = fabs((y[jp] - y[j]) / (x[i + 1] - x[i]));
  276. gradTm = fabs((y[j] - y[jm]) / (x[i] - x[i - 1]));
  277. dx = 0.5e0 * ((x[i] + x[i + 1]) - (x[i - 1] + x[i]));
  278. curvT = (gradTp - gradTm) / dx;
  279. if (curvT >= maxCurvT) {
  280. maxCurvT = curvT;
  281. pos = i;
  282. }
  283. }
  284. return (pos);
  285. }
  286. //double isothermPosition(const double* y, const double T, const size_t nt,
  287. // const size_t nvar, const double* x, const size_t nPts){
  288. // double pos=x[nPts-1];
  289. // size_t j;
  290. // for (size_t i = 1; i <nPts; i++) {
  291. // j=i*nvar+nt;
  292. // if (y[j]<=T) {
  293. // pos=x[i];
  294. // break;
  295. // }
  296. // }
  297. // return(pos);
  298. //}
  299. //******************* scan the temperature from left to right ******************//
  300. double isothermPosition(const double *y, const double T, const size_t nt,
  301. const size_t nvar, const double *x, const size_t nPts) {
  302. double pos = x[0];
  303. size_t j;
  304. for (size_t i = 0; i < nPts; i++) {
  305. j = i * nvar + nt;
  306. if (y[j] >= T) {
  307. pos = x[i];
  308. break;
  309. }
  310. }
  311. return (pos);
  312. }
  313. void updateSolution(double *y, double *ydot, const size_t nvar,
  314. const double xOld[], const double xNew[], const size_t nPts) {
  315. double ytemp[nPts], ydottemp[nPts];
  316. gsl_interp_accel *acc;
  317. gsl_spline *spline;
  318. acc = gsl_interp_accel_alloc();
  319. spline = gsl_spline_alloc(gsl_interp_steffen, nPts);
  320. gsl_interp_accel *accdot;
  321. gsl_spline *splinedot;
  322. accdot = gsl_interp_accel_alloc();
  323. splinedot = gsl_spline_alloc(gsl_interp_steffen, nPts);
  324. for (size_t j = 0; j < nvar; j++) {
  325. for (size_t i = 0; i < nPts; i++) {
  326. ytemp[i] = y[j + i * nvar];
  327. ydottemp[i] = ydot[j + i * nvar];
  328. }
  329. gsl_spline_init(spline, xOld, ytemp, nPts);
  330. gsl_spline_init(splinedot, xOld, ydottemp, nPts);
  331. for (size_t i = 0; i < nPts; i++) {
  332. y[j + i * nvar] = gsl_spline_eval(spline, xNew[i], acc);
  333. ydot[j + i * nvar] = gsl_spline_eval(splinedot, xNew[i], accdot);
  334. }
  335. }
  336. //Exploring "fixing" boundary conditions:
  337. //for (size_t j = 1; j < nvar; j++) {
  338. // //printf("%15.6e\t%15.6e\n", y[j],y[j+nvar]);
  339. // y[j]=y[j+nvar];
  340. // //y[j+(nPts-1)*nvar]=y[j+(nPts-2)*nvar];
  341. // //ydot[j+nvar]=ydot[j];
  342. //}
  343. //y[0]=0.0e0;
  344. gsl_interp_accel_free(acc);
  345. gsl_spline_free(spline);
  346. gsl_interp_accel_free(accdot);
  347. gsl_spline_free(splinedot);
  348. }
  349. //Locate bath gas:
  350. size_t BathGasIndex(UserData data) {
  351. size_t index = 0;
  352. double max1;
  353. double max = data->gas->massFraction(0);
  354. for (size_t k = 1; k < data->nsp; k++) {
  355. max1 = data->gas->massFraction(k);
  356. if (max1 >= max) {
  357. max = max1;
  358. index = k;
  359. }
  360. }
  361. return (index + 1);
  362. }
  363. //Locate Oxidizer:
  364. size_t oxidizerIndex(UserData data) {
  365. size_t index = 0;
  366. for (size_t k = 1; k < data->nsp; k++) {
  367. if (data->gas->speciesName(k - 1) == "O2") {
  368. index = k;
  369. }
  370. }
  371. return (index);
  372. }
  373. //Locate OH:
  374. size_t OHIndex(UserData data) {
  375. size_t index = 0;
  376. for (size_t k = 1; k < data->nsp; k++) {
  377. if (data->gas->speciesName(k - 1) == "OH") {
  378. index = k;
  379. }
  380. }
  381. return (index);
  382. }
  383. //Locate HO2:
  384. size_t HO2Index(UserData data) {
  385. size_t index = 0;
  386. for (size_t k = 1; k < data->nsp; k++) {
  387. if (data->gas->speciesName(k - 1) == "HO2") {
  388. index = k;
  389. }
  390. }
  391. return (index);
  392. }
  393. //Locate species index:
  394. /*1-based index*/
  395. size_t specIndex(UserData data, const char *specName) {
  396. size_t index = 0;
  397. for (size_t k = 1; k <= data->nsp; k++) {
  398. if (data->gas->speciesName(k - 1) == specName) {
  399. index = k;
  400. }
  401. }
  402. return (index);
  403. }
  404. /*a similar function will be used*/
  405. /*therefore the original function will be commented out*/
  406. // int setAlgebraicVariables(N_Vector* id, UserData data,const double* ydata){
  407. // double *iddata;
  408. // //char* specPtr[2];
  409. // N_VConst(ONE, *id);
  410. // iddata = N_VGetArrayPointer_OpenMP(*id);
  411. // data->k_bath=BathGasIndex(data);
  412. // data->k_oxidizer=oxidizerIndex(data);
  413. // data->k_OH=OHIndex(data);
  414. // data->k_HO2=HO2Index(data);
  415. // /*use char* pointer to get the address*/
  416. // // for(int i=0;i<2;i++){
  417. // // specPtr[i] = data->dropSpec[i];
  418. // // }
  419. // // data->k_drop[0]=specIndex(data,specPtr[0]);
  420. // // data->k_drop[1]=specIndex(data,specPtr[1]);
  421. // for (size_t i = 0; i < data->dropMole.size(); i++){
  422. // size_t index = specIndex(data,data->dropSpec[i]);
  423. // data->k_drop.push_back(index);
  424. // }
  425. // printf("Oxidizer index: %lu\n",data->k_oxidizer);
  426. // printf("Bath gas index:%lu\n",data->k_bath);
  427. // printf("Droplet species index: ");
  428. // for (size_t i = 0; i < data->dropMole.size(); i++)
  429. // {
  430. // printf("%lu\t",data->k_drop[i]);
  431. // }
  432. // printf("\n");
  433. // /*set governing equations' id*/
  434. // for (size_t i = 1; i <=data->npts; i++) {
  435. // /*Algebraic variables: indicated by ZERO.*/
  436. // Rid(i)=ZERO;
  437. // Pid(i)=ZERO;
  438. // Yid(i,data->k_bath)=ZERO;
  439. // Mdotid(i)=ZERO;
  440. // }
  441. // Mdotid(1)=ZERO;
  442. // Rid(1)=ONE;
  443. // Yid(1,data->k_drop[0])=ZERO;
  444. // Yid(1,data->k_drop[1])=ZERO;
  445. // Tid(data->npts)=ZERO;
  446. // if(data->constantPressure){
  447. // Pid(data->npts)=ONE;
  448. // }else{
  449. // Pid(data->npts)=ZERO;
  450. // Rid(data->npts)=ONE;
  451. // }
  452. // if(data->dirichletInner){
  453. // Tid(1)=ZERO;
  454. // }else{
  455. // //double T_boil = getLiquidMaxT(data->dropMole,P(1));
  456. // //if(T(1) <= T_boil){
  457. // // Tid(1)=ONE;
  458. // //}else{
  459. // // Tid(1)=ZERO;
  460. // //}
  461. // Tid(1)=ONE;
  462. // }
  463. // if(data->dirichletOuter){
  464. // for (size_t k = 1; k <=data->nsp; k++) {
  465. // if(k!=data->k_bath){
  466. // Yid(data->npts,k)=ONE;
  467. // }
  468. // Yid(1,k)=ZERO;
  469. // Tid(data->npts)=ONE;
  470. // }
  471. // }else{
  472. // for (size_t k = 1; k <=data->nsp; k++){
  473. // Yid(1,k)=ZERO;
  474. // Yid(data->npts,k)=ZERO;
  475. // Tid(data->npts)=ZERO;
  476. // }
  477. // }
  478. // return(0);
  479. // }
  480. int setAlgebraicVariables(N_Vector *id, UserData data, const double *ydata) {
  481. double *iddata;
  482. //char* specPtr[2];
  483. N_VConst(ONE, *id);
  484. iddata = N_VGetArrayPointer_OpenMP(*id);
  485. data->k_bath = BathGasIndex(data);
  486. data->k_oxidizer = oxidizerIndex(data);
  487. data->k_OH = OHIndex(data);
  488. data->k_HO2 = HO2Index(data);
  489. /*use char* pointer to get the address*/
  490. // for(int i=0;i<2;i++){
  491. // specPtr[i] = data->dropSpec[i];
  492. // }
  493. // data->k_drop[0]=specIndex(data,specPtr[0]);
  494. // data->k_drop[1]=specIndex(data,specPtr[1]);
  495. for (size_t i = 0; i < data->dropMole.size(); i++) {
  496. size_t index = 0;
  497. for (size_t k = 1; k <= data->nsp; k++) {
  498. if (data->gas->speciesName(k - 1) == data->dropSpec[i]) {
  499. index = k;
  500. }
  501. }
  502. // size_t index = specIndex(data, data->dropSpec[i].c_str());
  503. data->k_drop.push_back(index);
  504. }
  505. printf("Oxidizer index: %lu\n", data->k_oxidizer);
  506. printf("Bath gas index:%lu\n", data->k_bath);
  507. printf("Droplet species index: ");
  508. for(auto & arg : data->k_drop){
  509. printf("%lu,\t",arg) ;
  510. }
  511. printf("\n");
  512. /*set governing equations' id*/
  513. for (size_t i = 1; i <= data->npts; i++) {
  514. /*Algebraic variables: indicated by ZERO.*/
  515. Rid(i) = ZERO;
  516. Pid(i) = ZERO;
  517. Yid(i, data->k_bath) = ZERO;
  518. Mdotid(i) = ZERO;
  519. Tid(i) = ONE;
  520. }
  521. Mdotid(1) = ZERO;
  522. /*set radius ids*/
  523. Rid(1) = ONE;
  524. Rid(data->l_npts) = ONE;
  525. /*set temperature ids*/
  526. Tid(1) = ZERO;
  527. Tid(data->l_npts) = ZERO;
  528. Tid(data->l_npts + 1) = ZERO;
  529. /*set liquid phase mass fraction (y) ids*/
  530. if (data->dropType == 0) {
  531. for (size_t k = 1; k <= data->nsp; k++) {
  532. for (size_t i = 1; i <= data->l_npts; i++) {
  533. if (i == 1) {
  534. Yid(i, k) = ONE;
  535. } else {
  536. Yid(i, k) = ZERO;
  537. }
  538. }
  539. }
  540. } else {
  541. for (size_t i = 1; i <= data->l_npts; i++) {
  542. for (size_t k = 1; k <= data->nsp; k++) {
  543. if (i == 1) {
  544. if (k == data->k_drop[0] || k == data->k_drop[1]) {
  545. Yid(i, k) = ZERO;
  546. } else {
  547. Yid(i, k) = ONE;
  548. }
  549. } else if (i == data->l_npts) {
  550. Yid(i, k) = ZERO;
  551. } else {
  552. if (k == data->k_drop[0]) {
  553. Yid(i, k) = ONE;
  554. } else {
  555. Yid(i, k) = ZERO;
  556. }
  557. }
  558. }
  559. }
  560. }
  561. // for (size_t k = 1; k <= data->nsp; k++) {
  562. // Yid(data->l_npts + 1, k) = ZERO;
  563. // }
  564. /*set gas phase mass fraction (y) ids*/
  565. for (size_t i = (data->l_npts + 1); i <= (data->npts - 1); i++) {
  566. for (size_t k = 1; k <= data->nsp; k++) {
  567. if (i == (data->l_npts + 1)) {
  568. Yid(i, k) = ZERO;
  569. } else {
  570. if (k == data->k_bath) {
  571. Yid(i, k) = ZERO;
  572. } else {
  573. Yid(i, k) = ONE;
  574. }
  575. }
  576. }
  577. }
  578. //Yid(1,data->k_drop[0])=ZERO;
  579. //Yid(1,data->k_drop[1])=ZERO;
  580. //Tid(data->npts)=ZERO;
  581. // if(data->dirichletInner){
  582. // Tid(1)=ZERO;
  583. // }else{
  584. // //double T_boil = getLiquidMaxT(data->dropMole,P(1));
  585. // //if(T(1) <= T_boil){
  586. // // Tid(1)=ONE;
  587. // //}else{
  588. // // Tid(1)=ZERO;
  589. // //}
  590. // Tid(1)=ONE;
  591. // }
  592. if (data->constantPressure) {
  593. Pid(data->npts) = ONE;
  594. } else {
  595. Pid(data->npts) = ZERO;
  596. /*Rres(npts) seems to be algebric all the time?*/
  597. Rid(data->npts) = ONE;
  598. }
  599. if (data->dirichletOuter) {
  600. for (size_t k = 1; k <= data->nsp; k++) {
  601. if (k != data->k_bath) {
  602. Yid(data->npts, k) = ONE;
  603. }
  604. //Yid(1,k)=ZERO;
  605. Tid(data->npts) = ONE;
  606. }
  607. } else {
  608. for (size_t k = 1; k <= data->nsp; k++) {
  609. //Yid(1,k)=ZERO;
  610. Yid(data->npts, k) = ZERO;
  611. Tid(data->npts) = ZERO;
  612. }
  613. }
  614. printIddata(data,iddata);
  615. return (0);
  616. }
  617. inline double calc_area(double x, int *i) {
  618. switch (*i) {
  619. case 0:
  620. return (ONE);
  621. case 1:
  622. return (x);
  623. case 2:
  624. return (x * x);
  625. default:
  626. return (ONE);
  627. }
  628. }
  629. /*Similar to function:"setInitialCondition"*/
  630. /*"readInitialCondition" will also be revised here for two-phase LTORC*/
  631. // void readInitialCondition(FILE* input, double* ydata, const size_t nvar, const size_t nr, const size_t nPts, double Rg){
  632. // FILE* output;output=fopen("test.dat","w");
  633. // size_t bufLen=10000;
  634. // size_t nRows=0;
  635. // size_t nColumns=nvar;
  636. // char buf[bufLen];
  637. // char buf1[bufLen];
  638. // char comment[1];
  639. // char *ret;
  640. // while (fgets(buf,bufLen, input)!=NULL){
  641. // comment[0]=buf[0];
  642. // if(strncmp(comment,"#",1)!=0){
  643. // nRows++;
  644. // }
  645. // }
  646. // rewind(input);
  647. // printf("nRows: %ld\n", nRows);
  648. // double y[nRows*nColumns];
  649. // size_t i=0;
  650. // while (fgets(buf,bufLen, input)!=NULL){
  651. // comment[0]=buf[0];
  652. // if(strncmp(comment,"#",1)==0){
  653. // }
  654. // else{
  655. // ret=strtok(buf,"\t");
  656. // size_t j=0;
  657. // y[i*nColumns+j]=(double)(atof(ret));
  658. // j++;
  659. // while(ret!=NULL){
  660. // ret=strtok(NULL,"\t");
  661. // if(j<nColumns){
  662. // y[i*nColumns+j]=(double)(atof(ret));
  663. // }
  664. // j++;
  665. // }
  666. // i++;
  667. // }
  668. // }
  669. // for (i = 0; i < nRows; i++) {
  670. // for (size_t j = 0; j < nColumns; j++) {
  671. // fprintf(output, "%15.6e\t",y[i*nColumns+j]);
  672. // }
  673. // fprintf(output, "\n");
  674. // }
  675. // fclose(output);
  676. // //double xOld[nRows],xNew[nPts],ytemp[nPts];
  677. // double xOld[nRows],xNew[nPts],ytemp[nRows];
  678. // for (size_t j = 0; j < nRows; j++) {
  679. // xOld[j]=y[j*nColumns+nr];
  680. // }
  681. // //double dx=(xOld[nRows-1] - xOld[0])/((double)(nPts)-1.0e0);
  682. // //for (size_t j = 0; j < nPts-1; j++) {
  683. // // xNew[j]=(double)j*dx + xOld[0];
  684. // //}
  685. // //xNew[nPts-1]=xOld[nRows-1];
  686. // double dX0;
  687. // int NN = nPts-2;
  688. // dX0 = (xOld[nRows-1]-xOld[0])*(pow(Rg,1.0/NN) - 1.0)/(pow(Rg,(NN+1.0)/NN) - 1.0);
  689. // xNew[0] = xOld[0];
  690. // for (size_t i = 1; i < nPts-1; i++) {
  691. // xNew[i]=xNew[i-1]+dX0*pow(Rg,(i-1.0)/NN);
  692. // }
  693. // xNew[nPts-1] = xOld[nRows-1];
  694. // gsl_interp_accel* acc;
  695. // gsl_spline* spline;
  696. // acc = gsl_interp_accel_alloc();
  697. // spline = gsl_spline_alloc(gsl_interp_steffen, nRows);
  698. // for (size_t j = 0; j < nColumns; j++) {
  699. // for (size_t k = 0; k < nRows; k++) {
  700. // ytemp[k]=y[j+k*nColumns];
  701. // }
  702. // gsl_spline_init(spline,xOld,ytemp,nRows);
  703. // for (size_t k = 0; k < nPts; k++) {
  704. // ydata[j+k*nColumns]=gsl_spline_eval(spline,xNew[k],acc);
  705. // }
  706. // }
  707. // gsl_interp_accel_free(acc);
  708. // gsl_spline_free(spline);
  709. // }
  710. void readInitialCondition(FILE *input, double *ydata, const size_t nvar, const size_t nr, const size_t nPts,
  711. const size_t l_nPts, double Rg) {
  712. FILE *output;
  713. output = fopen("test.dat", "w");
  714. size_t bufLen = 10000;
  715. size_t nRows = 0;
  716. size_t nColumns = nvar;
  717. char buf[bufLen];
  718. char buf1[bufLen];
  719. char comment[1];
  720. char *ret;
  721. //get the # of rows in the input file:"initialCondition.dat, which equals to # of grid points"
  722. while (fgets(buf, bufLen, input) != NULL) {
  723. comment[0] = buf[0];
  724. if (strncmp(comment, "#", 1) != 0) {
  725. nRows++;
  726. }
  727. }
  728. rewind(input);
  729. printf("nRows: %ld\n", nRows);
  730. double y[nRows * nColumns];
  731. /*extract the initial data from file to y[] array*/
  732. size_t i = 0;
  733. while (fgets(buf, bufLen, input) != NULL) {
  734. comment[0] = buf[0];
  735. if (strncmp(comment, "#", 1) == 0) {
  736. } else {
  737. ret = strtok(buf, "\t");
  738. size_t j = 0;
  739. y[i * nColumns + j] = (double) (atof(ret));
  740. j++;
  741. while (ret != NULL) {
  742. ret = strtok(NULL, "\t");
  743. if (j < nColumns) {
  744. y[i * nColumns + j] = (double) (atof(ret));
  745. }
  746. j++;
  747. }
  748. i++;
  749. }
  750. }
  751. /*print out y[] array to test file*/
  752. for (i = 0; i < nRows; i++) {
  753. for (size_t j = 0; j < nColumns; j++) {
  754. fprintf(output, "%15.6e\t", y[i * nColumns + j]);
  755. }
  756. fprintf(output, "\n");
  757. }
  758. fclose(output);
  759. //double xOld[nRows],xNew[nPts],ytemp[nPts];
  760. //double xOld[nRows],xNew[nPts],ytemp[nRows];
  761. double xOld[nRows], xNew[nPts];
  762. /*get the x(radial) coordinate from y[] array*/
  763. for (size_t j = 0; j < nRows; j++) {
  764. xOld[j] = y[j * nColumns + nr];
  765. }
  766. /*get the first index of droplet interface:adjacent r equals*/
  767. size_t interII;
  768. for (size_t i = 0; i < nRows; i++) {
  769. interII = i;
  770. if (xOld[i] == xOld[i + 1]) {
  771. break;
  772. }
  773. }
  774. //double dx=(xOld[nRows-1] - xOld[0])/((double)(nPts)-1.0e0);
  775. //for (size_t j = 0; j < nPts-1; j++) {
  776. // xNew[j]=(double)j*dx + xOld[0];
  777. //}
  778. //xNew[nPts-1]=xOld[nRows-1];
  779. double dX0, dXL;
  780. int NN = nPts - l_nPts - 2;
  781. /*re-calculate the spatial coordinate: uniform grid in liquid phase and non-uniform for gas(fixed ratio)*/
  782. dXL = (xOld[interII] - xOld[0]) / (l_nPts - 1);
  783. // dX0 = (xOld[nRows-1]-xOld[0])*(pow(Rg,1.0/NN) - 1.0)/(pow(Rg,(NN+1.0)/NN) - 1.0);
  784. xNew[0] = xOld[0];
  785. for (size_t i = 1; i < l_nPts; i++) {
  786. xNew[i] = xNew[i - 1] + dXL;
  787. }
  788. xNew[l_nPts - 1] = xOld[interII];
  789. xNew[l_nPts] = xNew[l_nPts-1];
  790. dX0 = (xOld[nRows - 1]- xOld[interII] ) * (pow(Rg, 1.0 / NN) - 1.0) / (pow(Rg, (NN + 1.0) / NN) - 1.0);
  791. double ratio = pow(Rg,1.0/NN);
  792. for (size_t ii = (l_nPts + 1); ii <= (nPts - 2); ii++) {
  793. xNew[ii] = xNew[ii - 1] + dX0 * pow(ratio,(ii-l_nPts-1)) ;
  794. }
  795. xNew[nPts - 1] = xOld[nRows - 1];
  796. /*pass variable data from ytemp[] to ydata[] array using spline interpolation*/
  797. /*interpolate the liquid phase state variables with old array of size (interII+1)*/
  798. double ytemp0[interII + 1];
  799. double xOld0[interII + 1];
  800. std::copy(xOld, xOld + interII + 1, xOld0);
  801. gsl_interp_accel *acc;
  802. gsl_spline *spline;
  803. acc = gsl_interp_accel_alloc();
  804. spline = gsl_spline_alloc(gsl_interp_steffen, interII + 1);
  805. for (size_t j = 0; j < nColumns; j++) {
  806. for (size_t k = 0; k < (interII + 1); k++) {
  807. ytemp0[k] = y[j + k * nColumns];
  808. }
  809. gsl_spline_init(spline, xOld0, ytemp0, interII + 1);
  810. for (size_t k = 0; k < l_nPts; k++) {
  811. ydata[j + k * nColumns] = gsl_spline_eval(spline, xNew[k], acc);
  812. }
  813. }
  814. gsl_interp_accel_free(acc);
  815. gsl_spline_free(spline);
  816. /*interpolate the gas phase state variables with old array of size (nRows-interII-1)*/
  817. double ytemp1[nRows - interII - 1];
  818. double xOld1[nRows - interII - 1];
  819. std::copy(xOld + interII + 1, xOld + nRows, xOld1);
  820. gsl_interp_accel *acc1;
  821. gsl_spline *spline1;
  822. acc1 = gsl_interp_accel_alloc();
  823. spline1 = gsl_spline_alloc(gsl_interp_steffen, nRows - interII - 1);
  824. for (size_t j = 0; j < nColumns; j++) {
  825. for (size_t k = (interII + 1); k < nRows; k++) {
  826. // ytemp[k]=y[j+k*nColumns];
  827. ytemp1[k - interII - 1] = y[j + k * nColumns];
  828. }
  829. gsl_spline_init(spline1, xOld1, ytemp1, nRows - interII - 1);
  830. for (size_t k = l_nPts; k < nPts; k++) {
  831. ydata[j + k * nColumns] = gsl_spline_eval(spline1, xNew[k], acc);
  832. }
  833. }
  834. gsl_interp_accel_free(acc1);
  835. gsl_spline_free(spline1);
  836. }
  837. double systemMass(double *ydata, UserData data) {
  838. double mass = 0.0e0;
  839. double rho;
  840. for (size_t i = 2; i <= data->npts; i++) {
  841. data->gas->setState_TPY(T(i), P(i), &Y(i, 1));
  842. rho = data->gas->density();
  843. //psi(i)=psi(i-1)+rho*(R(i)-R(i-1))*calc_area(HALF*(R(i)+R(i-1)),&m);
  844. mass += rho * (R(i) - R(i - 1)) * calc_area(R(i), &data->metric);
  845. }
  846. return (mass);
  847. }
  848. /*a different function:initializePsiEtaGrid is implement*/
  849. /*similar to the following function, it create a psi grid in the gas phase*/
  850. /*and a eta grid in the liquid phase*/
  851. int initializePsiGrid(double *ydata, double *psidata, UserData data) {
  852. double rho, rhom;
  853. /*Create a psi grid that corresponds CONSISTENTLY to the spatial grid
  854. * "R" created above. Note that the Lagrangian variable psi has units
  855. * of kg. */
  856. psi(1) = ZERO;
  857. for (size_t i = 2; i <= data->npts; i++) {
  858. data->gas->setState_TPY(T(i), P(i), &Y(i, 1));
  859. rho = data->gas->density();
  860. data->gas->setState_TPY(T(i - 1), P(i - 1), &Y(i - 1, 1));
  861. rhom = data->gas->density();
  862. //psi(i)=psi(i-1)+rho*(R(i)-R(i-1))*calc_area(HALF*(R(i)+R(i-1)),&data->metric);
  863. //psi(i)=psi(i-1)+rho*(R(i)-R(i-1))*calc_area(R(i),&data->metric);
  864. psi(i) = psi(i - 1) + (R(i) - R(i - 1)) *
  865. (rho * calc_area(R(i), &data->metric) + rhom * calc_area(R(i - 1), &data->metric)) / TWO;
  866. }
  867. /*The mass of the entire system is the value of psi at the last grid
  868. * point. Normalize psi by this mass so that it varies from zero to
  869. * one. This makes psi dimensionless. So the mass needs to be
  870. * multiplied back in the approporiate places in the governing
  871. * equations so that units match.*/
  872. data->mass = psi(data->npts);
  873. for (size_t i = 1; i <= data->npts; i++) {
  874. psi(i) = psi(i) / data->mass;
  875. }
  876. return (0);
  877. }
  878. /*create the psi grid in the gas phase and eta grid in the liquid phase*/
  879. /*note: psi has units of kg. while eta is dimensionless*/
  880. int initializePsiEtaGrid(double *ydata, double *psidata, UserData data) {
  881. double rho, rhom, rhop;
  882. /*Create a psi grid that corresponds CONSISTENTLY to the spatial grid
  883. * "R" created above. Note that the Lagrangian variable psi has units
  884. * of kg. */
  885. /*create the psi grid in gas phase*/
  886. psi(data->l_npts + 1) = ZERO;
  887. for (size_t i = data->l_npts + 2; i <= data->npts; i++) {
  888. data->gas->setState_TPY(T(i), P(i), &Y(i, 1));
  889. rho = data->gas->density();
  890. data->gas->setState_TPY(T(i - 1), P(i - 1), &Y(i - 1, 1));
  891. rhom = data->gas->density();
  892. //psi(i)=psi(i-1)+rho*(R(i)-R(i-1))*calc_area(HALF*(R(i)+R(i-1)),&data->metric);
  893. //psi(i)=psi(i-1)+rho*(R(i)-R(i-1))*calc_area(R(i),&data->metric);
  894. psi(i) = psi(i - 1) + (R(i) - R(i - 1)) *
  895. (rho * calc_area(R(i), &data->metric) + rhom * calc_area(R(i - 1), &data->metric)) / TWO;
  896. }
  897. /*create the \eta grid for liquid phase*/
  898. /*for the time being, liquid phase species are hard coded*/
  899. std::vector<std::string> composition = components(data->dropType);
  900. psi(data->l_npts) = ZERO;
  901. if (data->dropType == 0) {
  902. for (size_t i = data->l_npts - 1; i >= 1; i--) {
  903. rho = getLiquidDensity(T(i), P(i), composition);
  904. rhop = getLiquidDensity(T(i + 1), P(i + 1), composition);
  905. psi(i) = psi(i + 1) + (R(i + 1) - R(i)) *
  906. (rho * calc_area(R(i), &data->metric) + rhop * calc_area(R(i + 1), &data->metric)) /
  907. TWO;
  908. }
  909. } else if (data->dropType == 1) {
  910. for (size_t i = data->l_npts - 1; i >= 1; i--) {
  911. std::vector<double> moleFrac, moleFracp;
  912. moleFrac = getLiquidmolevec(data, ydata, i);
  913. moleFracp = getLiquidmolevec(data, ydata, i + 1);
  914. rho = getLiquidDensity(T(i), P(i), composition, moleFrac);
  915. rhop = getLiquidDensity(T(i + 1), P(i + 1), composition, moleFracp);
  916. psi(i) = psi(i + 1) + (R(i + 1) - R(i)) *
  917. (rho * calc_area(R(i), &data->metric) + rhop * calc_area(R(i + 1), &data->metric)) /
  918. TWO;
  919. }
  920. }
  921. /*according to the mehtod described by Stauch et al.*/
  922. /*eta should be dimensionless, so we normalize the eta with total mass of droplet*/
  923. double dropmass = psi(1);
  924. for (size_t i = data->l_npts; i >= 1; i--) {
  925. psi(i) = psi(i) / dropmass;
  926. }
  927. /*The mass of the entire system is the value of psi at the last grid
  928. * point. Normalize psi by this mass so that it varies from zero to
  929. * one. This makes psi dimensionless. So the mass needs to be
  930. * multiplied back in the approporiate places in the governing
  931. * equations so that units match.*/
  932. // data->mass=psi(data->npts);
  933. // for (size_t i = 1; i <=data->npts; i++) {
  934. // psi(i)=psi(i)/data->mass;
  935. // }
  936. return (0);
  937. }
  938. /*A different setInitialCondition is implemented based on the problemType =2 */
  939. /*As such, the following function is commented*/
  940. // int setInitialCondition(N_Vector* y,
  941. // N_Vector* ydot,
  942. // UserData data){
  943. // double* ydata;
  944. // double* ydotdata;
  945. // double* psidata;
  946. // double* innerMassFractionsData, Rd, massDrop;
  947. // double rhomhalf, lambdamhalf, YVmhalf[data->nsp];
  948. // double f=ZERO;
  949. // double g=ZERO;
  950. // double perturb,rho;
  951. // double epsilon=ZERO;
  952. // int m,ier;
  953. // ydata = N_VGetArrayPointer_OpenMP(*y);
  954. // ydotdata = N_VGetArrayPointer_OpenMP(*ydot);
  955. // innerMassFractionsData = data->innerMassFractions;
  956. // Rd = data->Rd;
  957. // // massDrop = data->massDrop;
  958. // //Mass of droplet
  959. // //massDrop=1.0/3.0*Rd*Rd*Rd*997.0; //TODO: The density of the droplet should be a user input
  960. // // massDrop=1.0/3.0*Rd*Rd*Rd*684.0; //TODO:The density of the droplet(n-heptane) should be a user input
  961. // // massDrop = 1.0/3.0*Rd*Rd*Rd*data->dropRho;
  962. // if(data->adaptiveGrid){
  963. // psidata = data->grid->xOld;
  964. // }
  965. // else{
  966. // psidata = data->uniformGrid;
  967. // }
  968. // m=data->metric;
  969. // data->innerTemperature=data->initialTemperature;
  970. // for (size_t k = 1; k <=data->nsp; k++) {
  971. // innerMassFractionsData[k-1]=data->gas->massFraction(k-1);
  972. // }
  973. // //Define Grid:
  974. // double dR=(data->domainLength)/((double)(data->npts)-1.0e0);
  975. // double dv=(pow(data->domainLength,1+data->metric)-pow(data->firstRadius*data->domainLength,1+data->metric))/((double)(data->npts)-1.0e0);
  976. // //Initialize the R(i),T(i)(data->initialTemperature),Y(i,k),P(i)
  977. // for (size_t i = 1; i <=data->npts; i++) {
  978. // if(data->metric==0){
  979. // R(i)=Rd+(double)((i-1)*dR);
  980. // }else{
  981. // if(i==1){
  982. // R(i)=ZERO;
  983. // }else if(i==2){
  984. // R(i)=data->firstRadius*data->domainLength;
  985. // }else{
  986. // R(i)=pow(pow(R(i-1),1+data->metric)+dv,1.0/((double)(1+data->metric)));
  987. // }
  988. // }
  989. // T(i)=data->initialTemperature;
  990. // for (size_t k = 1; k <=data->nsp; k++) {
  991. // Y(i,k)=data->gas->massFraction(k-1); //Indexing different in Cantera
  992. // }
  993. // P(i)=data->initialPressure*Cantera::OneAtm;
  994. // }
  995. // R(data->npts)=data->domainLength+data->Rd;
  996. // // /********** test R(i) and the volumn between grids *****************/
  997. // // printf("Print the first 4 R(i)s and volumn between them: \n") ;
  998. // // printf("Grids: 1st:%2.6e,2nd:%2.6e,3rd:%2.6e,4th:%2.6e \n",R(1),R(2),R(3),R(4));
  999. // // double v1,v2,v3,v4,v5;
  1000. // // v1 =pow(R(2),1+data->metric) - pow(R(1),1+data->metric);
  1001. // // v2 =pow(R(3),1+data->metric) - pow(R(2),1+data->metric);
  1002. // // v3 =pow(R(4),1+data->metric) - pow(R(3),1+data->metric);
  1003. // // v4 =pow(R(5),1+data->metric) - pow(R(4),1+data->metric);
  1004. // // v5 =pow(R(6),1+data->metric) - pow(R(5),1+data->metric);
  1005. // // printf("Volumn: 1st:%2.6e,2nd:%2.6e,3rd:%2.6e,4th:%2.6e,5th:%2.6e\n",v1,v2,v3,v4,v5) ;
  1006. // double Tmax;
  1007. // double Tmin=data->initialTemperature;
  1008. // double w=data->mixingWidth;
  1009. // double YN2=ZERO;
  1010. // double YO2=ZERO;
  1011. // double YFuel,YOxidizer,sum;
  1012. // //if(data->problemType==0){
  1013. // // data->gas->equilibrate("HP");
  1014. // // data->maxTemperature=data->gas->temperature();
  1015. // //}
  1016. // //else if(data->problemType==1){
  1017. // // /*Premixed Combustion: Equilibrium products comprise ignition
  1018. // // * kernel at t=0. The width of the kernel is "mixingWidth"
  1019. // // * shifted by "shift" from the center.*/
  1020. // // data->gas->equilibrate("HP");
  1021. // // Tmax=data->gas->temperature();
  1022. // // for (size_t i = 1; i <=data->npts; i++) {
  1023. // // g=HALF*(tanh((R(i)-data->shift)/w)+ONE); //increasing function of x
  1024. // // f=ONE-g; //decreasing function of x
  1025. // // T(i)=(Tmax-Tmin)*f+Tmin;
  1026. // // for (size_t k = 1; k <=data->nsp; k++) {
  1027. // // Y(i,k)=(data->gas->massFraction(k-1)-Y(i,k))*f+Y(i,k);
  1028. // // }
  1029. // // }
  1030. // // if(data->dirichletOuter){
  1031. // // T(data->npts)=data->wallTemperature;
  1032. // // }
  1033. // //}
  1034. // //else if(data->problemType==2){
  1035. // // FILE* input;
  1036. // // if(input=fopen("initialCondition.dat","r")){
  1037. // // readInitialCondition(input, ydata, data->nvar, data->nr, data->npts);
  1038. // // fclose(input);
  1039. // // }
  1040. // // else{
  1041. // // printf("file initialCondition.dat not found!\n");
  1042. // // return(-1);
  1043. // // }
  1044. // //}
  1045. // initializePsiGrid(ydata,psidata,data);
  1046. // if(data->adaptiveGrid){
  1047. // // if(data->problemType!=0){
  1048. // // data->grid->position=maxGradPosition(ydata, data->nt, data->nvar,
  1049. // // data->grid->xOld, data->npts);
  1050. // // //data->grid->position=maxCurvPosition(ydata, data->nt, data->nvar,
  1051. // // // data->grid->xOld, data->npts);
  1052. // // }
  1053. // // else{
  1054. // // }
  1055. // if(data->problemType!=3){
  1056. // data->grid->position=0.0e0;
  1057. // double x=data->grid->position+data->gridOffset*data->grid->leastMove;
  1058. // printf("New grid center:%15.6e\n",x);
  1059. // ier=reGrid(data->grid, x);
  1060. // if(ier==-1)return(-1);
  1061. // updateSolution(ydata, ydotdata, data->nvar,
  1062. // data->grid->xOld,data->grid->x,data->npts);
  1063. // storeGrid(data->grid->x,data->grid->xOld,data->npts);
  1064. // }
  1065. // }
  1066. // else{
  1067. // double Rg = data->Rg, dpsi0;
  1068. // int NN = data->npts-2;
  1069. // double psiNew[data->npts];
  1070. // dpsi0 = (pow(Rg,1.0/NN) - 1.0)/(pow(Rg,(NN+1.0)/NN) - 1.0);
  1071. // psiNew[0] = 0;
  1072. // for (size_t i = 1; i < data->npts-1; i++) {
  1073. // psiNew[i]=psiNew[i-1]+dpsi0*pow(Rg,(i-1.0)/NN);
  1074. // }
  1075. // psiNew[data->npts-1] = 1.0;
  1076. // printf("Last point:%15.6e\n",psiNew[data->npts-1]);
  1077. // updateSolution(ydata, ydotdata, data->nvar,
  1078. // data->uniformGrid,psiNew,data->npts);
  1079. // storeGrid(psiNew,data->uniformGrid,data->npts);
  1080. // //double psiNew[data->npts];
  1081. // //double dpsi=1.0e0/((double)(data->npts)-1.0e0);
  1082. // //for (size_t i = 0; i < data->npts; i++) {
  1083. // // psiNew[i]=(double)(i)*dpsi;
  1084. // //}
  1085. // //printf("Last point:%15.6e\n",psiNew[data->npts-1]);
  1086. // //updateSolution(ydata, ydotdata, data->nvar,
  1087. // // data->uniformGrid,psiNew,data->npts);
  1088. // //storeGrid(psiNew,data->uniformGrid,data->npts);
  1089. // }
  1090. // if(data->problemType==0){
  1091. // data->gas->equilibrate("HP");
  1092. // data->maxTemperature=data->gas->temperature();
  1093. // }
  1094. // else if(data->problemType==1){
  1095. // /*Premixed Combustion: Equilibrium products comprise ignition
  1096. // * kernel at t=0. The width of the kernel is "mixingWidth"
  1097. // * shifted by "shift" from the center.*/
  1098. // data->gas->equilibrate("HP");
  1099. // Tmax=data->gas->temperature();
  1100. // for (size_t i = 1; i <=data->npts; i++) {
  1101. // g=HALF*(tanh((R(i)-data->shift)/w)+ONE); //increasing function of x
  1102. // f=ONE-g; //decreasing function of x
  1103. // T(i)=(Tmax-Tmin)*f+Tmin;
  1104. // for (size_t k = 1; k <=data->nsp; k++) {
  1105. // Y(i,k)=(data->gas->massFraction(k-1)-Y(i,k))*f+Y(i,k);
  1106. // }
  1107. // }
  1108. // if(data->dirichletOuter){
  1109. // T(data->npts)=data->wallTemperature;
  1110. // }
  1111. // }
  1112. // else if(data->problemType==2){
  1113. // FILE* input;
  1114. // if(input=fopen("initialCondition.dat","r")){
  1115. // readInitialCondition(input, ydata, data->nvar, data->nr, data->npts, data->Rg);
  1116. // fclose(input);
  1117. // }
  1118. // else{
  1119. // printf("file initialCondition.dat not found!\n");
  1120. // return(-1);
  1121. // }
  1122. // initializePsiGrid(ydata,psidata,data);
  1123. // }
  1124. // else if(data->problemType==3){
  1125. // FILE* input;
  1126. // if(input=fopen("restart.bin","r")){
  1127. // readRestart(y, ydot, input, data);
  1128. // fclose(input);
  1129. // printf("Restart solution loaded!\n");
  1130. // printf("Problem starting at t=%15.6e\n",data->tNow);
  1131. // return(0);
  1132. // }
  1133. // else{
  1134. // printf("file restart.bin not found!\n");
  1135. // return(-1);
  1136. // }
  1137. // }
  1138. // if(data->reflectProblem){
  1139. // double temp;
  1140. // int j=1;
  1141. // while (data->npts+1-2*j>=0) {
  1142. // temp=T(j);
  1143. // T(j)=T(data->npts+1-j);
  1144. // T(data->npts+1-j)=temp;
  1145. // for (size_t k = 1; k <=data->nsp; k++) {
  1146. // temp=Y(j,k);
  1147. // Y(j,k)=Y(data->npts+1-j,k);
  1148. // Y(data->npts+1-j,k)=temp;
  1149. // }
  1150. // j=j+1;
  1151. // }
  1152. // }
  1153. // /*Floor small values to zero*/
  1154. // for (size_t i = 1; i <=data->npts; i++) {
  1155. // for (size_t k = 1; k <=data->nsp; k++) {
  1156. // if(fabs(Y(i,k))<=data->massFractionTolerance){
  1157. // Y(i,k)=0.0e0;
  1158. // }
  1159. // }
  1160. // }
  1161. // //Set grid to location of maximum curvature calculated by r instead of x:
  1162. // if(data->adaptiveGrid){
  1163. // //data->grid->position=maxCurvPosition(ydata, data->nt, data->nvar,
  1164. // // data->grid->x, data->npts);
  1165. // int maxCurvII = 0;
  1166. // maxCurvII = maxCurvIndexR(ydata,data->nt,data->nvar,data->nr,data->npts);
  1167. // data->grid->position = data->grid->x[maxCurvII];
  1168. // ier=reGrid(data->grid, data->grid->position);
  1169. // updateSolution(ydata, ydotdata, data->nvar,
  1170. // data->grid->xOld,data->grid->x,data->npts);
  1171. // storeGrid(data->grid->x,data->grid->xOld,data->npts);
  1172. // /******** Test the maxCurvPosition and related variables *******/
  1173. // printf("The maxCurvPositition(based on r) is : %.6f,Temperature is : %.3f \n",data->grid->position,T(maxCurvII+1));
  1174. // }
  1175. // /*Ensure consistent boundary conditions*/
  1176. // //T(1)=T(2);
  1177. // //for (size_t k = 1; k <=data->nsp; k++) {
  1178. // // Y(1,k)=Y(2,k);
  1179. // // Y(data->npts,k)=Y(data->npts-1,k);
  1180. // //}
  1181. // return(0);
  1182. // }
  1183. /*Revise the setInitialCondition function to be suitable for two-phase TORC*/
  1184. int setInitialCondition(N_Vector *y,
  1185. N_Vector *ydot,
  1186. UserData data) {
  1187. double *ydata;
  1188. double *ydotdata;
  1189. double *psidata;
  1190. double *innerMassFractionsData, Rd, massDrop;
  1191. double rhomhalf, lambdamhalf, YVmhalf[data->nsp];
  1192. double f = ZERO;
  1193. double g = ZERO;
  1194. double perturb, rho;
  1195. double epsilon = ZERO;
  1196. int m, ier;
  1197. ydata = N_VGetArrayPointer_OpenMP(*y);
  1198. ydotdata = N_VGetArrayPointer_OpenMP(*ydot);
  1199. innerMassFractionsData = data->innerMassFractions;
  1200. Rd = data->Rd;
  1201. // massDrop = data->massDrop;
  1202. //Mass of droplet
  1203. // massDrop=1.0/3.0*Rd*Rd*Rd*997.0; //TODO: The density of the droplet should be a user input
  1204. // massDrop=1.0/3.0*Rd*Rd*Rd*684.0; //TODO:The density of the droplet(n-heptane) should be a user input
  1205. // massDrop = 1.0/3.0*Rd*Rd*Rd*data->dropRho;
  1206. if (data->adaptiveGrid) {
  1207. psidata = data->grid->xOld;
  1208. } else {
  1209. psidata = data->uniformGrid;
  1210. }
  1211. m = data->metric;
  1212. data->innerTemperature = data->initialTemperature;
  1213. for (size_t k = 1; k <= data->nsp; k++) {
  1214. innerMassFractionsData[k - 1] = data->gas->massFraction(k - 1);
  1215. }
  1216. //Define Grid:
  1217. double dR = (data->domainLength) / ((double) (data->g_npts) - 1.0e0);
  1218. double dv = (pow(data->domainLength, 1 + data->metric) -
  1219. pow(data->firstRadius * data->domainLength, 1 + data->metric)) / ((double) (data->g_npts) - 1.0e0);
  1220. // //Initialize the R(i),T(i)(data->initialTemperature),Y(i,k),P(i)
  1221. // for (size_t i = 1; i <=data->npts; i++) {
  1222. // if(data->metric==0){
  1223. // R(i)=Rd+(double)((i-1)*dR);
  1224. // }else{
  1225. // if(i==1){
  1226. // R(i)=ZERO;
  1227. // }else if(i==2){
  1228. // R(i)=data->firstRadius*data->domainLength;
  1229. // }else{
  1230. // R(i)=pow(pow(R(i-1),1+data->metric)+dv,1.0/((double)(1+data->metric)));
  1231. // }
  1232. // }
  1233. // T(i)=data->initialTemperature;
  1234. // for (size_t k = 1; k <=data->nsp; k++) {
  1235. // Y(i,k)=data->gas->massFraction(k-1); //Indexing different in Cantera
  1236. // }
  1237. // P(i)=data->initialPressure*Cantera::OneAtm;
  1238. // }
  1239. // R(data->npts)=data->domainLength+data->Rd;
  1240. // /********** test R(i) and the volumn between grids *****************/
  1241. // printf("Print the first 4 R(i)s and volumn between them: \n") ;
  1242. // printf("Grids: 1st:%2.6e,2nd:%2.6e,3rd:%2.6e,4th:%2.6e \n",R(1),R(2),R(3),R(4));
  1243. // double v1,v2,v3,v4,v5;
  1244. // v1 =pow(R(2),1+data->metric) - pow(R(1),1+data->metric);
  1245. // v2 =pow(R(3),1+data->metric) - pow(R(2),1+data->metric);
  1246. // v3 =pow(R(4),1+data->metric) - pow(R(3),1+data->metric);
  1247. // v4 =pow(R(5),1+data->metric) - pow(R(4),1+data->metric);
  1248. // v5 =pow(R(6),1+data->metric) - pow(R(5),1+data->metric);
  1249. // printf("Volumn: 1st:%2.6e,2nd:%2.6e,3rd:%2.6e,4th:%2.6e,5th:%2.6e\n",v1,v2,v3,v4,v5) ;
  1250. double Tmax;
  1251. double Tmin = data->initialTemperature;
  1252. double w = data->mixingWidth;
  1253. double YN2 = ZERO;
  1254. double YO2 = ZERO;
  1255. double YFuel, YOxidizer, sum;
  1256. //if(data->problemType==0){
  1257. // data->gas->equilibrate("HP");
  1258. // data->maxTemperature=data->gas->temperature();
  1259. //}
  1260. //else if(data->problemType==1){
  1261. // /*Premixed Combustion: Equilibrium products comprise ignition
  1262. // * kernel at t=0. The width of the kernel is "mixingWidth"
  1263. // * shifted by "shift" from the center.*/
  1264. // data->gas->equilibrate("HP");
  1265. // Tmax=data->gas->temperature();
  1266. // for (size_t i = 1; i <=data->npts; i++) {
  1267. // g=HALF*(tanh((R(i)-data->shift)/w)+ONE); //increasing function of x
  1268. // f=ONE-g; //decreasing function of x
  1269. // T(i)=(Tmax-Tmin)*f+Tmin;
  1270. // for (size_t k = 1; k <=data->nsp; k++) {
  1271. // Y(i,k)=(data->gas->massFraction(k-1)-Y(i,k))*f+Y(i,k);
  1272. // }
  1273. // }
  1274. // if(data->dirichletOuter){
  1275. // T(data->npts)=data->wallTemperature;
  1276. // }
  1277. //}
  1278. //else if(data->problemType==2){
  1279. // FILE* input;
  1280. // if(input=fopen("initialCondition.dat","r")){
  1281. // readInitialCondition(input, ydata, data->nvar, data->nr, data->npts);
  1282. // fclose(input);
  1283. // }
  1284. // else{
  1285. // printf("file initialCondition.dat not found!\n");
  1286. // return(-1);
  1287. // }
  1288. //}
  1289. // initializePsiGrid(ydata,psidata,data);
  1290. // if(data->adaptiveGrid){
  1291. // // if(data->problemType!=0){
  1292. // // data->grid->position=maxGradPosition(ydata, data->nt, data->nvar,
  1293. // // data->grid->xOld, data->npts);
  1294. // // //data->grid->position=maxCurvPosition(ydata, data->nt, data->nvar,
  1295. // // // data->grid->xOld, data->npts);
  1296. // // }
  1297. // // else{
  1298. // // }
  1299. // if(data->problemType!=3){
  1300. // data->grid->position=0.0e0;
  1301. // double x=data->grid->position+data->gridOffset*data->grid->leastMove;
  1302. // printf("New grid center:%15.6e\n",x);
  1303. // ier=reGrid(data->grid, x);
  1304. // if(ier==-1)return(-1);
  1305. // updateSolution(ydata, ydotdata, data->nvar,
  1306. // data->grid->xOld,data->grid->x,data->npts);
  1307. // storeGrid(data->grid->x,data->grid->xOld,data->npts);
  1308. // }
  1309. // }
  1310. // else{
  1311. // double Rg = data->Rg, dpsi0;
  1312. // int NN = data->npts-2;
  1313. // double psiNew[data->npts];
  1314. // dpsi0 = (pow(Rg,1.0/NN) - 1.0)/(pow(Rg,(NN+1.0)/NN) - 1.0);
  1315. // psiNew[0] = 0;
  1316. // for (size_t i = 1; i < data->npts-1; i++) {
  1317. // psiNew[i]=psiNew[i-1]+dpsi0*pow(Rg,(i-1.0)/NN);
  1318. // }
  1319. // psiNew[data->npts-1] = 1.0;
  1320. // printf("Last point:%15.6e\n",psiNew[data->npts-1]);
  1321. // updateSolution(ydata, ydotdata, data->nvar,
  1322. // data->uniformGrid,psiNew,data->npts);
  1323. // storeGrid(psiNew,data->uniformGrid,data->npts);
  1324. // //double psiNew[data->npts];
  1325. // //double dpsi=1.0e0/((double)(data->npts)-1.0e0);
  1326. // //for (size_t i = 0; i < data->npts; i++) {
  1327. // // psiNew[i]=(double)(i)*dpsi;
  1328. // //}
  1329. // //printf("Last point:%15.6e\n",psiNew[data->npts-1]);
  1330. // //updateSolution(ydata, ydotdata, data->nvar,
  1331. // // data->uniformGrid,psiNew,data->npts);
  1332. // //storeGrid(psiNew,data->uniformGrid,data->npts);
  1333. // }
  1334. if (data->problemType == 0) {
  1335. data->gas->equilibrate("HP");
  1336. data->maxTemperature = data->gas->temperature();
  1337. } else if (data->problemType == 1) {
  1338. /*Premixed Combustion: Equilibrium products comprise ignition
  1339. * kernel at t=0. The width of the kernel is "mixingWidth"
  1340. * shifted by "shift" from the center.*/
  1341. data->gas->equilibrate("HP");
  1342. Tmax = data->gas->temperature();
  1343. for (size_t i = 1; i <= data->npts; i++) {
  1344. g = HALF * (tanh((R(i) - data->shift) / w) + ONE); //increasing function of x
  1345. f = ONE - g; //decreasing function of x
  1346. T(i) = (Tmax - Tmin) * f + Tmin;
  1347. for (size_t k = 1; k <= data->nsp; k++) {
  1348. Y(i, k) = (data->gas->massFraction(k - 1) - Y(i, k)) * f + Y(i, k);
  1349. }
  1350. }
  1351. if (data->dirichletOuter) {
  1352. T(data->npts) = data->wallTemperature;
  1353. }
  1354. } else if (data->problemType == 2) {
  1355. FILE *input;
  1356. if (input = fopen("initialCondition.dat", "r")) {
  1357. readInitialCondition(input, ydata, data->nvar, data->nr, data->npts, data->l_npts, data->Rg);
  1358. fclose(input);
  1359. } else {
  1360. printf("file initialCondition.dat not found!\n");
  1361. return (-1);
  1362. }
  1363. // initializePsiGrid(ydata,psidata,data);
  1364. initializePsiEtaGrid(ydata, psidata, data);
  1365. } else if (data->problemType == 3) {
  1366. FILE *input;
  1367. if (input = fopen("restart.bin", "r")) {
  1368. readRestart(y, ydot, input, data);
  1369. fclose(input);
  1370. printf("Restart solution loaded!\n");
  1371. printf("Problem starting at t=%15.6e\n", data->tNow);
  1372. return (0);
  1373. } else {
  1374. printf("file restart.bin not found!\n");
  1375. return (-1);
  1376. }
  1377. }
  1378. if (data->reflectProblem) {
  1379. double temp;
  1380. int j = 1;
  1381. while (data->npts + 1 - 2 * j >= 0) {
  1382. temp = T(j);
  1383. T(j) = T(data->npts + 1 - j);
  1384. T(data->npts + 1 - j) = temp;
  1385. for (size_t k = 1; k <= data->nsp; k++) {
  1386. temp = Y(j, k);
  1387. Y(j, k) = Y(data->npts + 1 - j, k);
  1388. Y(data->npts + 1 - j, k) = temp;
  1389. }
  1390. j = j + 1;
  1391. }
  1392. }
  1393. /*Floor small values to zero*/
  1394. for (size_t i = 1; i <= data->npts; i++) {
  1395. for (size_t k = 1; k <= data->nsp; k++) {
  1396. if (fabs(Y(i, k)) <= data->massFractionTolerance) {
  1397. Y(i, k) = 0.0e0;
  1398. }
  1399. }
  1400. }
  1401. //Set grid to location of maximum curvature calculated by r instead of x:
  1402. if (data->adaptiveGrid) {
  1403. //data->grid->position=maxCurvPosition(ydata, data->nt, data->nvar,
  1404. // data->grid->x, data->npts);
  1405. int maxCurvII = 0;
  1406. maxCurvII = maxCurvIndexR(ydata, data->nt, data->nvar, data->nr, data->npts);
  1407. data->grid->position = data->grid->x[maxCurvII];
  1408. ier = reGrid(data->grid, data->grid->position);
  1409. updateSolution(ydata, ydotdata, data->nvar,
  1410. data->grid->xOld, data->grid->x, data->npts);
  1411. storeGrid(data->grid->x, data->grid->xOld, data->npts);
  1412. /******** Test the maxCurvPosition and related variables *******/
  1413. printf("The maxCurvPositition(based on r) is : %.6f,Temperature is : %.3f \n", data->grid->position,
  1414. T(maxCurvII + 1));
  1415. }
  1416. /*Ensure consistent boundary conditions*/
  1417. //T(1)=T(2);
  1418. //for (size_t k = 1; k <=data->nsp; k++) {
  1419. // Y(1,k)=Y(2,k);
  1420. // Y(data->npts,k)=Y(data->npts-1,k);
  1421. //}
  1422. printPsidata(data,psidata);
  1423. return (0);
  1424. }
  1425. inline double Qdot(double *t,
  1426. double *x,
  1427. double *ignTime,
  1428. double *kernelSize,
  1429. double *maxQdot) {
  1430. double qdot;
  1431. if (*x <= *kernelSize) {
  1432. if ((*t) <= (*ignTime)) {
  1433. qdot = (*maxQdot);
  1434. } else {
  1435. qdot = 0.0e0;
  1436. }
  1437. } else {
  1438. qdot = 0.0e0;
  1439. }
  1440. return (qdot);
  1441. }
  1442. inline void setGas(UserData data,
  1443. double *ydata,
  1444. size_t gridPoint) {
  1445. data->gas->setTemperature(T(gridPoint));
  1446. data->gas->setMassFractions_NoNorm(&Y(gridPoint, 1));
  1447. data->gas->setPressure(P(gridPoint));
  1448. }
  1449. void getTransport(UserData data,
  1450. double *ydata,
  1451. size_t gridPoint,
  1452. double *rho,
  1453. double *lambda,
  1454. double YV[]) {
  1455. double YAvg[data->nsp],
  1456. XLeft[data->nsp],
  1457. XRight[data->nsp],
  1458. gradX[data->nsp];
  1459. setGas(data, ydata, gridPoint);
  1460. data->gas->getMoleFractions(XLeft);
  1461. setGas(data, ydata, gridPoint + 1);
  1462. data->gas->getMoleFractions(XRight);
  1463. for (size_t k = 1; k <= data->nsp; k++) {
  1464. YAvg(k) = HALF * (Y(gridPoint, k) +
  1465. Y(gridPoint + 1, k));
  1466. gradX(k) = (XRight(k) - XLeft(k)) /
  1467. (R(gridPoint + 1) - R(gridPoint));
  1468. }
  1469. double TAvg = HALF * (T(gridPoint) + T(gridPoint + 1));
  1470. double gradT = (T(gridPoint + 1) - T(gridPoint)) /
  1471. (R(gridPoint + 1) - R(gridPoint));
  1472. data->gas->setTemperature(TAvg);
  1473. data->gas->setMassFractions_NoNorm(YAvg);
  1474. data->gas->setPressure(P(gridPoint));
  1475. *rho = data->gas->density();
  1476. *lambda = data->trmix->thermalConductivity();
  1477. data->trmix->getSpeciesFluxes(1, &gradT, data->nsp,
  1478. gradX, data->nsp, YV);
  1479. //setGas(data,ydata,gridPoint);
  1480. }
  1481. void getGasMassFlux(UserData data,
  1482. double *ydata,
  1483. size_t gridPoint,
  1484. double YV[]) {
  1485. double YAvg[data->nsp],
  1486. XLeft[data->nsp],
  1487. XRight[data->nsp],
  1488. gradX[data->nsp];
  1489. setGas(data, ydata, gridPoint);
  1490. data->gas->getMoleFractions(XLeft);
  1491. setGas(data, ydata, gridPoint + 1);
  1492. data->gas->getMoleFractions(XRight);
  1493. for (size_t k = 1; k <= data->nsp; k++) {
  1494. YAvg(k) = HALF * (Y(gridPoint, k) +
  1495. Y(gridPoint + 1, k));
  1496. gradX(k) = (XRight(k) - XLeft(k)) /
  1497. (R(gridPoint + 1) - R(gridPoint));
  1498. }
  1499. double TAvg = HALF * (T(gridPoint) + T(gridPoint + 1));
  1500. double gradT = (T(gridPoint + 1) - T(gridPoint)) /
  1501. (R(gridPoint + 1) - R(gridPoint));
  1502. data->gas->setTemperature(TAvg);
  1503. data->gas->setMassFractions_NoNorm(YAvg);
  1504. data->gas->setPressure(P(gridPoint));
  1505. data->trmix->getSpeciesFluxes(1, &gradT, data->nsp,
  1506. gradX, data->nsp, YV);
  1507. //setGas(data,ydata,gridPoint);
  1508. }
  1509. int residue(double t, N_Vector y, N_Vector ydot, N_Vector res, void *user_data) {
  1510. /*Declare and fetch nvectors and user data:*/
  1511. double *ydata, *ydotdata, *resdata, *psidata, *innerMassFractionsData;
  1512. UserData data;
  1513. data = (UserData) user_data;
  1514. size_t npts = data->npts;
  1515. size_t nsp = data->nsp;
  1516. size_t k_bath = data->k_bath;
  1517. size_t l_npts = data->l_npts;
  1518. int dropType = data->dropType;
  1519. std::vector<size_t> k_drop = data->k_drop;
  1520. std::vector<std::string> dropSpec = data->dropSpec;
  1521. std::vector<std::string> composition = components(data->dropType);
  1522. std::vector<double> dropMole = data->dropMole;
  1523. ydata = N_VGetArrayPointer_OpenMP(y);
  1524. ydotdata = N_VGetArrayPointer_OpenMP(ydot);
  1525. resdata = N_VGetArrayPointer_OpenMP(res);
  1526. if (data->adaptiveGrid == 1) {
  1527. psidata = data->grid->x;
  1528. } else {
  1529. psidata = data->uniformGrid;
  1530. }
  1531. innerMassFractionsData = data->innerMassFractions;
  1532. /* Grid stencil:*/
  1533. /*-------|---------*---------|---------*---------|-------*/
  1534. /*-------|---------*---------|---------*---------|-------*/
  1535. /*-------|---------*---------|---------*---------|-------*/
  1536. /*-------m-------mhalf-------j-------phalf-------p-------*/
  1537. /*-------|---------*---------|---------*---------|-------*/
  1538. /*-------|---------*---------|---------*---------|-------*/
  1539. /*-------|<=======dxm=======>|<=======dxp=======>|-------*/
  1540. /*-------|---------*<======dxav=======>*---------|-------*/
  1541. /*-------|<================dxpm=================>|-------*/
  1542. /* Various variables defined for book-keeping and storing previously
  1543. * calculated values:
  1544. * rho : densities at points m, mhalf, j, p, and phalf.
  1545. * area : the matric at points m, mhalf, j, p, and phalf.
  1546. * m : exponent that determines geometry;
  1547. * lambda : thermal conductivities at mhalf and phalf.
  1548. * mdot : mass flow rate at m, j, and p.
  1549. * X : mole fractions at j and p.
  1550. * YV : diffusion fluxes at mhalf and phalf.
  1551. * Tgrad : temperature gradient at mhalf and phalf.
  1552. * Tav : average temperature between two points.
  1553. * Pav : average pressure between two points.
  1554. * Yav : average mass fractions between two points.
  1555. * Xgradhalf : mole fraction gradient at j.
  1556. * Cpb : mass based bulk specific heat.
  1557. * tranTerm : transient terms.
  1558. * advTerm : advection terms.
  1559. * diffTerm : diffusion terms.
  1560. * srcTerm : source terms.
  1561. */
  1562. double rhomhalf, rhom, lambdamhalf, YVmhalf[nsp],
  1563. rho, Diffcoeffphalf, Diffcoeffmhalf,propYVmhalf,propYVphalf,
  1564. rhophalf, lambdaphalf, YVphalf[nsp],
  1565. Cpb, Cvb, Cp[nsp], Cpl[2], dHvl[2], rhol, wdot[nsp], enthalpy[nsp], energy[nsp], T_boil,
  1566. tranTerm, diffTerm, srcTerm, advTerm,
  1567. area, areamhalf, areaphalf, aream, areamhalfsq, areaphalfsq;
  1568. /*Aliases for difference coefficients:*/
  1569. double cendfm, cendfc, cendfp;
  1570. /*Aliases for various grid spacings:*/
  1571. double dpsip, dpsiav, dpsipm, dpsim, dpsimm;
  1572. dpsip = dpsiav = dpsipm = dpsim = dpsimm = ONE;
  1573. //double mass, mdotIn;
  1574. double mass, massDrop;
  1575. double sum, sum1, sum2, sum3;
  1576. std::vector<double> vapheat, mole_,liquidCp,vapPres;
  1577. // size_t j, k;
  1578. int m;
  1579. m = data->metric; //Unitless
  1580. mass = data->mass; //Units: kg
  1581. /*evaluate and implement the governing equations in the liquid phase*/
  1582. /*implement res @ left boundary i.e., first grid point*/
  1583. Rres(1) = Rdot(1);
  1584. if (dropType == 0) {
  1585. // Yres(1,data->k_drop[0]) = Ydot(1,data->k_drop[0]);
  1586. for (size_t k = 1; k <= nsp; k++) {
  1587. Yres(1, k) = Ydot(1, k);
  1588. }
  1589. } else {
  1590. for (size_t k = 1; k <= nsp; k++) {
  1591. if (k == k_drop[0]) {
  1592. Yres(1, k) = Y(2, k) - Y(1, k);
  1593. } else if (k == k_drop[1]) {
  1594. Yres(1, k) = ONE - Y(1, k_drop[0]) - Y(1, k);
  1595. } else {
  1596. Yres(1, k) = Ydot(1, k);
  1597. }
  1598. }
  1599. }
  1600. Pres(1) = P(2) - P(1);
  1601. Mdotres(1) = Mdot(2) - Mdot(1);
  1602. Tres(1) = T(2) - T(1);
  1603. /*set governing equations at intermediate grid points */
  1604. massDrop = dropletmass(data, ydata);
  1605. if (dropType == 0) {
  1606. for (size_t j = 2; j <= l_npts - 1; j++) {
  1607. /*Mass:*/
  1608. /* ∂r/∂ψ = 1/ρA */
  1609. dpsim = - (psi(j) - psi(j - 1));
  1610. dpsip = - (psi(j + 1) - psi(j));
  1611. dpsiav = - (HALF * (psi(j + 1) - psi(j - 1)));
  1612. rho = getLiquidDensity(T(j), P(j), composition);
  1613. rhom = getLiquidDensity(T(j - 1), P(j - 1), composition);
  1614. rhophalf = getLiquidDensity(HALF * (T(j) + T(j + 1)), HALF * (P(j) + P(j + 1)), composition);
  1615. rhomhalf = getLiquidDensity(HALF * (T(j) + T(j - 1)), HALF * (P(j) + P(j - 1)), composition);
  1616. Cpb = getLiquidCpb(T(j), P(j), composition);
  1617. lambdaphalf = getLiquidCond(HALF * (T(j) + T(j + 1)), HALF * (P(j) + P(j + 1)), composition);
  1618. lambdamhalf = getLiquidCond(HALF * (T(j) + T(j - 1)), HALF * (P(j) + P(j - 1)), composition);
  1619. aream = calc_area(R(j - 1), &m);
  1620. areamhalf = calc_area(HALF * (R(j) + R(j - 1)), &m);
  1621. areaphalf = calc_area(HALF * (R(j + 1) + R(j)), &m);
  1622. areamhalfsq = areamhalf * areamhalf;
  1623. areaphalfsq = areaphalf * areaphalf;
  1624. area = calc_area(R(j), &m);
  1625. Rres(j) = ((R(j) - R(j - 1)) / dpsim) - massDrop * (TWO / (rhom * aream + rho * area));
  1626. Mdotres(j) = Mdot(j + 1) - Mdot(j);
  1627. Pres(j) = P(j + 1) - P(j);
  1628. for (size_t k = 1; k <= nsp; k++) {
  1629. Yres(j, k) = Y(j, k) - Y(j - 1, k);
  1630. }
  1631. tranTerm = Tdot(j);
  1632. advTerm = psi(j) * (-Mdot(j)) / massDrop * (T(j) - T(j - 1)) / dpsim ;
  1633. diffTerm = 1 / (Cpb * massDrop * massDrop) *
  1634. (rhophalf * areaphalfsq * lambdaphalf * (T(j + 1) - T(j)) / dpsip -
  1635. rhomhalf * areamhalfsq * lambdamhalf * (T(j) - T(j - 1)) / dpsim) / dpsiav;
  1636. Tres(j) = tranTerm - advTerm - diffTerm;
  1637. }
  1638. /*Fill up the res at l_npts*/
  1639. rho = getLiquidDensity(T(l_npts), P(l_npts), composition);
  1640. area = calc_area(R(l_npts), &m);
  1641. lambdamhalf = getLiquidCond(T(l_npts), P(l_npts), composition);
  1642. lambdaphalf = getGasCond(data, ydata, l_npts+1);
  1643. vapheat = getLiquidVH(P(l_npts+1), data->dropType);
  1644. Rres(l_npts) = Mdot(l_npts) + rho * Rdot(l_npts) * area;
  1645. Mdotres(l_npts) = Mdot(l_npts + 1) - Mdot(l_npts);
  1646. Pres(l_npts) = P(l_npts + 1) - P(l_npts);
  1647. for (size_t k = 1; k <= nsp; k++) {
  1648. Yres(l_npts, k) = Y(l_npts, k) - Y(l_npts - 1, k);
  1649. }
  1650. Tres(l_npts) = lambdamhalf * (T(l_npts) - T(l_npts - 1)) / (R(l_npts) - R(l_npts - 1)) * area +
  1651. Mdot(l_npts) * vapheat[0] -
  1652. lambdaphalf * (T(l_npts + 2) - T(l_npts + 1)) / (R(l_npts + 2) - R(l_npts + 1)) * area;
  1653. } else {
  1654. /*binary component case*/
  1655. /*implementation of liquid phase inner grid points*/
  1656. for (size_t j = 2; j <= l_npts - 1; j++) {
  1657. mole_ = getLiquidmolevec(data, ydata, j);
  1658. dpsim = - (psi(j) - psi(j - 1));
  1659. dpsip = - (psi(j + 1) - psi(j));
  1660. dpsiav = - (HALF * (psi(j + 1) - psi(j - 1)));
  1661. /*evaluate various central difference coefficients*/
  1662. cendfm = -dpsip / (dpsim * dpsipm);
  1663. cendfc = (dpsip - dpsim) / (dpsip * dpsim);
  1664. cendfp = dpsim / (dpsip * dpsipm);
  1665. /**************************************************/
  1666. rho = getLiquidDensity(T(j), P(j), composition, mole_);
  1667. rhom = getLiquidDensity(T(j - 1), P(j - 1), composition, mole_);
  1668. rhophalf = getLiquidDensity(HALF * (T(j) + T(j + 1)), HALF * (P(j) + P(j + 1)), composition, mole_);
  1669. rhomhalf = getLiquidDensity(HALF * (T(j) + T(j - 1)), HALF * (P(j) + P(j - 1)), composition, mole_);
  1670. Cpb = getLiquidCpb(T(j), P(j), composition, mole_);
  1671. liquidCp = getLiquidCp(T(j),P(j),composition);
  1672. lambdaphalf = getLiquidCond(HALF * (T(j) + T(j + 1)), HALF * (P(j) + P(j + 1)), composition, mole_);
  1673. lambdamhalf = getLiquidCond(HALF * (T(j) + T(j - 1)), HALF * (P(j) + P(j - 1)), composition, mole_);
  1674. aream = calc_area(R(j - 1), &m);
  1675. areamhalf = calc_area(HALF * (R(j) + R(j - 1)), &m);
  1676. areaphalf = calc_area(HALF * (R(j + 1) + R(j)), &m);
  1677. areamhalfsq = areamhalf * areamhalf;
  1678. areaphalfsq = areaphalf * areaphalf;
  1679. area = calc_area(R(j), &m);
  1680. Diffcoeffphalf = getLiquidmassdiff(data, ydata, j, HALF * (T(j) + T(j + 1)));
  1681. Diffcoeffmhalf = getLiquidmassdiff(data, ydata, j, HALF * (T(j) + T(j - 1)));
  1682. Rres(j) = ((R(j) - R(j - 1)) / dpsim) - massDrop * (TWO / (rhom * aream + rho * area));
  1683. Mdotres(j) = Mdot(j + 1) - Mdot(j);
  1684. Pres(j) = P(j + 1) - P(j);
  1685. propYVphalf = (-Diffcoeffphalf * (Y(j + 1, k_drop[0]) - Y(j, k_drop[0])) / (R(j + 1) - R(j)));
  1686. propYVmhalf = (-Diffcoeffmhalf * (Y(j, k_drop[0]) - Y(j - 1, k_drop[0])) / (R(j) - R(j - 1)));
  1687. liquidCp = getLiquidCp(T(j),P(j),composition);
  1688. /*species equation*/
  1689. for (size_t k = 1; k <= nsp; k++) {
  1690. if (k != k_drop[0] && k != k_drop[1]) {
  1691. Yres(j, k) = Y(j, k) - Y(j - 1, k);
  1692. } else if (k == k_drop[0]) {
  1693. tranTerm = Ydot(j, k);
  1694. advTerm = 1 / massDrop * (psi(j) * (-Mdot(j))) * (Y(j, k) - Y(j - 1, k)) / dpsim;
  1695. diffTerm = 1 / massDrop *
  1696. (areaphalf * rhophalf * propYVphalf
  1697. - areamhalf * rhomhalf * propYVmhalf )
  1698. / dpsiav;
  1699. Yres(j, k) = tranTerm - advTerm + diffTerm;
  1700. } else{
  1701. Yres(j,k) = ONE - Y(j,k_drop[0]);
  1702. }
  1703. }
  1704. /*energy equation*/
  1705. tranTerm = Tdot(j);
  1706. advTerm = 1/massDrop *(psi(j)*(-Mdot(j)))* (T(j)-T(j-1))/(psi(j)-psi(j-1));
  1707. double diffTerm1 = 1/(Cpb*massDrop*massDrop) * ( (rhophalf*areaphalfsq*lambdaphalf*(T(j+1)-T(j))/(psi(j+1)-psi(j)) )
  1708. - (rhomhalf*areamhalfsq*lambdamhalf*(T(j)-T(j-1))/(psi(j)-psi(j-1)) ) ) /dpsiav;
  1709. double diffTerm2 = area/(Cpb*massDrop)*rho*(cendfp*T(j+1)+cendfc*T(j)+cendfm*T(j-1)) *
  1710. (HALF*((propYVphalf+propYVmhalf)*liquidCp[0]+(-propYVphalf-propYVmhalf)*liquidCp[1])) ;
  1711. diffTerm = diffTerm1 - diffTerm2 ;
  1712. Tres(j) = tranTerm - advTerm - diffTerm ;
  1713. }
  1714. /*implementation of right boundary of liquid phase*/
  1715. mole_ = getLiquidmolevec(data,ydata,l_npts);
  1716. rho = getLiquidDensity(T(l_npts), P(l_npts), composition,mole_);
  1717. area = calc_area(R(l_npts), &m);
  1718. lambdamhalf = getLiquidCond(T(l_npts), P(l_npts), composition,mole_);
  1719. lambdaphalf = getGasCond(data, ydata, l_npts+1);
  1720. propYVmhalf = (-Diffcoeffmhalf * (Y(l_npts, k_drop[0]) - Y(l_npts - 1, k_drop[0])) / (R(l_npts) - R(l_npts - 1)));
  1721. getGasMassFlux(data,ydata,l_npts+1,YVphalf);
  1722. Diffcoeffmhalf = getLiquidmassdiff(data, ydata, l_npts, HALF * (T(l_npts) + T(l_npts - 1)));
  1723. vapheat = getLiquidVH(P(l_npts), data->dropType);
  1724. Rres(l_npts) = Mdot(l_npts) + rho * Rdot(l_npts) * area;
  1725. Mdotres(l_npts) = Mdot(l_npts + 1) - Mdot(l_npts);
  1726. Pres(l_npts) = P(l_npts + 1) - P(l_npts);
  1727. /*species formualtion*/
  1728. for (size_t k = 1; k <= nsp; k++) {
  1729. if (k == k_drop[0]) {
  1730. Yres(l_npts, k) = Mdot(l_npts) * Y(l_npts, k) + area * rho *
  1731. (-Diffcoeffmhalf * (Y(l_npts, k) - Y(l_npts - 1, k)) /
  1732. (R(l_npts) - R(l_npts - 1)))
  1733. - Mdot(l_npts) * Y(l_npts + 1, k) - area * YVphalf[k_drop[0] - 1];
  1734. } else if (k == k_drop[1]) {
  1735. Yres(l_npts, k) = ONE - Y(l_npts, k_drop[0]) - Y(l_npts, k);
  1736. } else {
  1737. Yres(l_npts, k) = Y(l_npts, k) - Y(l_npts - 1, k);
  1738. }
  1739. }
  1740. /*temperature formulation*/
  1741. double epsilon = Y(l_npts + 1, k_drop[0]) + YVphalf[k_drop[0] - 1] * area / Mdot(l_npts);
  1742. Tres(l_npts) = lambdamhalf * (T(l_npts) - T(l_npts - 1)) / (R(l_npts) - R(l_npts - 1)) * area
  1743. + Mdot(l_npts) * (epsilon * vapheat[0] + (1 - epsilon) * vapheat[1])
  1744. - lambdaphalf * (T(l_npts + 2) - T(l_npts + 1)) / (R(l_npts + 2) - R(l_npts + 1)) * area;
  1745. }
  1746. //massDrop=data->massDrop; //Units: kg
  1747. //mdotIn=data->mdot*calc_area(R(npts),&m); //Units: kg/s
  1748. // /*evaluate properties at j=l_npts+1 *************************/
  1749. setGas(data, ydata, l_npts+1);
  1750. rhom = data->gas->density();
  1751. Cpb = data->gas->cp_mass(); //J/kg/K
  1752. Cvb = data->gas->cv_mass(); //J/kg/K
  1753. //TODO: Create user input model for these. They should not be constant
  1754. //Cpl=4.182e03; //J/kg/K for liquid water
  1755. //Cpl= 5.67508633e-07*pow(T(1),4) - 7.78060597e-04*pow(T(1),3) + 4.08310544e-01*pow(T(1),2) //J/kg/K for liquid water
  1756. // - 9.62429538e+01*T(1) + 1.27131046e+04;
  1757. /*Update specific heat:Cpl for liquid proprane&n-heptane&dodecane*/
  1758. /*Based on the existiong data,a linear expression is used*/
  1759. // Cpl= 12.10476*T(1) - 746.60143; // Unit:J/(kg*K), Need to be improved later
  1760. //Cpl[0] = 2.423*T(1)+1661.074; //Unit:J/(kg*K),range:1atm,propane
  1761. //Cpl[0] = 3.336*T(1)+1289.5; //Unit:J/(kg*K),range:1atm,n-Heptane
  1762. //Cpl[1] = 3.815*T(1)+1081.8; //Unit:J/(kg*K),range:1atm,n-Dodecane
  1763. // double Cp_l = 0.0;
  1764. // Cp_l = getLiquidCp(data->dropMole,T(1),P(1));
  1765. //for(size_t i=0;i<=1;i++){
  1766. // Cp_l=Cp_l+Cpl[i]*data->dropMassFrac[i];
  1767. //}
  1768. //dHvl=2.260e6; //J/kg heat of vaporization of water
  1769. //double Tr = T(1)/647.1; //Reduced Temperature: Droplet Temperature divided by critical temperature of water
  1770. //dHvl= 5.2053e07*pow(1-Tr,0.3199 - 0.212*Tr + 0.25795*Tr*Tr)/18.01; //J/kg latent heat of vaporization of water
  1771. //double Tr1 = T(1)/369.8; //Reduced Temperature;
  1772. //dHvl[0] = 6.32716e5*exp(-0.0208*Tr1)*pow((1-Tr1),0.3766); //Unit:J/kg,Latent Heat of Vaporizaiton of Liquid n-propane,NIST
  1773. //double Tr2 = T(1)/540.2; //Reduced Temperature:Droplet Temperature divided by critical temperature of liquid n-heptane, Source:NIST
  1774. //dHvl[0] = 5.366e5*exp(-0.2831*Tr2) * pow((1-Tr2),0.2831); //Unit:J/kg, latent heat of vaporization of liquid n-heptane, Source: NIST
  1775. //dHvl[1] = 358.118e3; //Unit:J/kg,latent heat of vaporization of n-dodecane,Source:NIST
  1776. // double dHv_l = 0.0;
  1777. // dHv_l = getLiquidHv(data->dropMole,T(1),P(1));
  1778. //for(size_t i=0;i<=1;i++){
  1779. // dHv_l=dHv_l+dHvl[i]*data->dropMassFrac[i];
  1780. //}
  1781. /*Following section is related to the property of water*/
  1782. //rhol = 997.0;
  1783. //massDrop=1.0/3.0*R(1)*R(1)*R(1)*997.0; //TODO: The density of the droplet should be a user input
  1784. /*Following section is related to the property of liquid n-heptane and n-dodecane (mainly density rho)*/
  1785. /*Density of these two species should be temperature dependent*/
  1786. //data->dropDens[0] = -1.046*T(1)+823.794; //Unit:kg/m^3,density of propane @1atm
  1787. //data->dropDens[0] = -0.858*T(1)+933.854; //Unit:kg/m^3,density of n-Heptane @1atm
  1788. //data->dropDens[1] = -0.782*T(1)+979.643; //Unit:kg/m^3,density of n-Dodecane @1atm
  1789. //rhol = data->dropRho; //Unit:kg/m^3
  1790. // rhol = 0.0;
  1791. // rhol = getLiquidRho(data->dropMole,T(1),P(1));
  1792. //for(size_t i=0;i<=1;i++){
  1793. // rhol = rhol + data->dropMassFrac[i]*data->dropDens[i];
  1794. //}
  1795. // massDrop = 1.0/3.0*R(1)*R(1)*R(1)*rhol; //Unit:kg, this is the mass of liquid droplet
  1796. // aream = calc_area(R(1), &m);
  1797. /*******************************************************************/
  1798. /*Calculate values at j=l_npts+2 's m and mhalf*****************************/
  1799. // getTransport(data, ydata, 1, &rhomhalf, &lambdamhalf, YVmhalf);
  1800. // areamhalf = calc_area(HALF * (R(1) + R(2)), &m);
  1801. // aream = calc_area(R(1), &m);
  1802. // areamhalfsq = areamhalf * areamhalf;
  1803. getTransport(data, ydata, l_npts+1, &rhomhalf, &lambdamhalf, YVmhalf);
  1804. areamhalf = calc_area(HALF * (R(l_npts+1) + R(l_npts+2)), &m);
  1805. aream = calc_area(R(l_npts+1), &m);
  1806. areamhalfsq = areamhalf * areamhalf;
  1807. /*******************************************************************/
  1808. /*Fill up res with left side (center) boundary conditions:**********/
  1809. /*We impose zero fluxes at the center:*/
  1810. /*Mass:*/
  1811. if (data->quasiSteady) {
  1812. // Rres(1) = Rdot(1); // Should remain satisfied for quasi-steady droplet
  1813. Rres(l_npts+1) = Rdot(l_npts) ;
  1814. } else {
  1815. Rres(l_npts+1) = R(l_npts+1) - R(l_npts) ;
  1816. // Rres(1) = Rdot(1) + Mdot(1) / rhol / aream;
  1817. }
  1818. //TODO: Antoine Parameters should be part of user input, not hardcoded
  1819. //Yres(1,k_drop)=Y(1,k_drop) - 1.0e5*pow(10,4.6543-(1435.264/(T(1)-64.848)))*data->gas->molecularWeight(k_drop-1)
  1820. // / P(1) / data->gas->meanMolecularWeight();
  1821. //Yres(1,k_drop)=Y(1,k_drop) - 1.0e3*pow(2.71828,16.7-(4060.0/(T(1)-37.0)))*data->gas->molecularWeight(k_drop-1)
  1822. // / P(1) / data->gas->meanMolecularWeight();
  1823. //Yres(1,k_drop)=Y(1,k_drop)-2.566785e-02;
  1824. /*Following using the Antoine Parameters to calculate the pressure of volatile component(n-heptane)*/
  1825. /*Antoine parameter from NIST website*/
  1826. /*Raoult's Law is applied to calculate the partial vapor pressure*/
  1827. // double p_i[2] = {0.0, 0.0};
  1828. // p_i[0] = 1.0e5 * pow(10, 4.53678 - (1149.36 / (T(1) + 24.906))) * data->dropMole[0] *
  1829. // data->gamma[0]; //unit:Pa,Helgeson and Sage,1967,Propane
  1830. // //p_i[0] = 1.0e5*pow(10,4.02832-(1268.636/(T(1)-56.199)))*data->dropMole[0] ;
  1831. // p_i[1] = 1.0e5 * pow(10, 4.02832 - (1268.636 / (T(1) - 56.199))) * data->dropMole[1] *
  1832. // data->gamma[1]; //unit:Pa,n-Heptane
  1833. //p_i[1] = 1.0e5*pow(10,4.10549-(1625.928/(T(1)-92.839)))*data->dropMole[1] ; //Unit:Pa.Williamham and Taylor,n-dodecane
  1834. /*for both dropletTypes(0,1),implementations of Rres,Tres,Pres are the same
  1835. * only Yres and Mdotres are different */
  1836. /*Species:*/
  1837. sum = ZERO;
  1838. /*single component case*/
  1839. if (dropType == 0) {
  1840. double hepPres = 1.0e5 * pow(10, 4.02832 - (1268.636 / (T(l_npts+1) - 56.199)));
  1841. Yres(l_npts + 1, k_drop[0]) = Y(l_npts + 1, k_drop[0]) - hepPres * data->gas->molecularWeight(k_drop[0] - 1) /
  1842. (P(l_npts + 1) * data->gas->meanMolecularWeight());
  1843. sum = sum + Y(l_npts + 1, k_drop[0]);
  1844. Mdotres(l_npts + 1) = Mdot(l_npts + 1) - (YVmhalf(k_drop[0]) * areamhalf) / (1 - Y(l_npts + 1, k_drop[0]));
  1845. for (size_t k = 1; k <= nsp; k++) {
  1846. if (k != k_bath && k != k_drop[0]) {
  1847. Yres(l_npts + 1, k) = Y(l_npts + 1, k) * Mdot(l_npts + 1) + YVmhalf(k) * areamhalf;
  1848. sum = sum + Y(l_npts + 1, k);
  1849. }
  1850. }
  1851. Yres(l_npts + 1, k_bath) = ONE - sum - Y(l_npts + 1, k_bath);
  1852. }
  1853. /*binary componet case for gas phase LHS boundary*/
  1854. if(dropType == 1){
  1855. mole_ = getLiquidmolevec(data,ydata,l_npts);
  1856. vapPres = getVapPressure(data,ydata,l_npts+1,mole_);
  1857. for (size_t i = 0; i < k_drop.size(); i++) {
  1858. Yres(l_npts+1, k_drop[i]) = Y(l_npts+1, k_drop[i]) - vapPres[i] * data->gas->molecularWeight(k_drop[i] - 1) /
  1859. (P(l_npts+1) * data->gas->meanMolecularWeight());
  1860. sum = sum + Y(l_npts+1, k_drop[i]);
  1861. }
  1862. Mdotres(l_npts+1) = Mdot(l_npts+1) - ((YVmhalf(k_drop[0]) + YVmhalf(k_drop[1])) * areamhalf) /
  1863. (1 - Y(l_npts+1, k_drop[0]) - Y(l_npts+1, k_drop[1]));
  1864. for (size_t k = 1; k <= nsp; k++) {
  1865. if (k != k_bath && k != k_drop[0] && k != k_drop[1]) {
  1866. //TODO: May need to include chemical source term
  1867. Yres(l_npts+1, k) = Y(l_npts+1, k) * Mdot(l_npts+1) + YVmhalf(k) * areamhalf;
  1868. //Yres(1,k)=YVmhalf(k)*areamhalf;
  1869. sum = sum + Y(l_npts+1, k);
  1870. //if(fabs(Mdot(1))>1e-14){
  1871. ///Yres(1,k)=innerMassFractionsData[k-1]-
  1872. /// Y(1,k)-
  1873. /// (YVmhalf(k)*areamhalf)/Mdot(1);
  1874. //}
  1875. //else{
  1876. // //Yres(1,k)=Y(1,k)-innerMassFractionsData[k-1];
  1877. // Yres(1,k)=Y(2,k)-Y(1,k);
  1878. // /*The below flux boundary condition makes the
  1879. // * problem more prone to diverge. How does one
  1880. // * fix this?*/
  1881. // //Yres(1,k)=YVmhalf(k);
  1882. //}
  1883. }
  1884. }
  1885. Yres(l_npts+1, k_bath) = ONE - sum - Y(l_npts+1, k_bath);
  1886. }
  1887. //p_i = 1.0e3*pow(2.71828,16.7-(4060.0/(T(1)-37.0))); //Unit:Pa,FOR WATER
  1888. //Yres(1,k_drop)=Y(1,k_drop) - p_i * data->gas->molecularWeight(k_drop-1)
  1889. // / P(1) / data->gas->meanMolecularWeight();
  1890. //Mdotres(1)=Mdot(1) - (YVmhalf(k_drop)*areamhalf) / (1-Y(1,k_drop)); //Evaporating mass
  1891. /*Energy:*/
  1892. if (data->dirichletInner) {
  1893. //Tres(1)=Tdot(1);
  1894. //Tres(1)=T(1)-data->innerTemperature;
  1895. /*Following code should be revised in the future*/
  1896. //Tres(1)=lambdamhalf*rhomhalf*areamhalfsq*(T(2)-T(1))/((psi(2)-psi(1))*mass)/dHv_l - YVmhalf(k_drop)*areamhalf/(1-Y(1,k_drop));
  1897. } else {
  1898. //Tres(1)=Tdot(1) -
  1899. // (rhomhalf*areamhalfsq*lambdamhalf*(T(2)-T(1))/((psi(2)-psi(1))*mass) - Mdot(1)*dHvl)
  1900. // / (massDrop * Cpl);
  1901. //Tres(1)=Tdot(1) -
  1902. // (areamhalf*lambdamhalf*(T(2)-T(1))/(R(2)-R(1)) - Mdot(1)*dHvl)
  1903. // / (massDrop * Cpl);
  1904. /**** Boundary Condition for Temperature @ 1st grid point,
  1905. *** Temperature should not exceed boiling temperature of each liquid component *****/
  1906. // T_boil = getLiquidMaxT(data->dropMole, P(1));
  1907. // if (T(1) <= T_boil) {
  1908. // Tres(1) = Tdot(1) -
  1909. // (areamhalf * lambdamhalf * (T(2) - T(1)) / (R(2) - R(1)) - Mdot(1) * dHv_l)
  1910. // / (massDrop * Cp_l);
  1911. // } else {
  1912. // //Tres(1)=T(1)-T_boil;
  1913. // Tres(1) = Tdot(1);
  1914. // }
  1915. Tres(l_npts+1) = T(l_npts+1) - T(l_npts) ;
  1916. //Tres(1)=T(2)-T(1);
  1917. //Tres(1)=Tdot(1) - (Pdot(1)/(rhom*Cpb))
  1918. // +(double)(data->metric+1)*(rhomhalf*lambdamhalf*areamhalfsq*(T(2)-T(1))/psi(2)-psi(1));
  1919. }
  1920. /*Pressure:*/
  1921. Pres(l_npts+1) = P(l_npts+2) - P(l_npts+1);
  1922. /*Fill up res with governing equations at inner points:*************/
  1923. for (size_t j = l_npts+2 ; j < npts; j++) {
  1924. /*evaluate various mesh differences*///
  1925. // dpsip = (psi(j + 1) - psi(j)) * mass;
  1926. // dpsim = (psi(j) - psi(j - 1)) * mass;
  1927. // dpsiav = HALF * (psi(j + 1) - psi(j - 1)) * mass;
  1928. // dpsipm = (psi(j + 1) - psi(j - 1)) * mass;
  1929. dpsip = (psi(j + 1) - psi(j)) ;
  1930. dpsim = (psi(j) - psi(j - 1)) ;
  1931. dpsiav = HALF * (psi(j + 1) - psi(j - 1)) ;
  1932. dpsipm = (psi(j + 1) - psi(j - 1)) ;
  1933. /***********************************///
  1934. /*evaluate various central difference coefficients*/
  1935. cendfm = -dpsip / (dpsim * dpsipm);
  1936. cendfc = (dpsip - dpsim) / (dpsip * dpsim);
  1937. cendfp = dpsim / (dpsip * dpsipm);
  1938. /**************************************************/
  1939. /*evaluate properties at j*************************/
  1940. setGas(data, ydata, j);
  1941. rho = data->gas->density(); //kg/m^3
  1942. Cpb = data->gas->cp_mass(); //J/kg/K
  1943. Cvb = data->gas->cv_mass(); //J/kg/K
  1944. data->gas->getNetProductionRates(wdot); //kmol/m^3
  1945. data->gas->getEnthalpy_RT(enthalpy); //unitless
  1946. data->gas->getCp_R(Cp); //unitless
  1947. area = calc_area(R(j), &m); //m^2
  1948. /*evaluate properties at p*************************/
  1949. getTransport(data, ydata, j, &rhophalf, &lambdaphalf, YVphalf);
  1950. areaphalf = calc_area(HALF * (R(j) + R(j + 1)), &m);
  1951. areaphalfsq = areaphalf * areaphalf;
  1952. /**************************************************///
  1953. /*Evaporating Mass*/
  1954. Mdotres(j) = Mdot(j) - Mdot(j - 1);
  1955. /*Mass:*/
  1956. /* ∂r/∂ψ = 1/ρA */
  1957. Rres(j) = ((R(j) - R(j - 1)) / dpsim) - (TWO / (rhom * aream + rho * area));
  1958. /*Energy:*/
  1959. /* ∂T/∂t = - ṁ(∂T/∂ψ)
  1960. * + (∂/∂ψ)(λρA²∂T/∂ψ)
  1961. * - (A/cₚ) ∑ YᵢVᵢcₚᵢ(∂T/∂ψ)
  1962. * - (1/ρcₚ)∑ ώᵢhᵢ
  1963. * + (1/ρcₚ)(∂P/∂t) */
  1964. /*Notes:
  1965. * λ has units J/m/s/K.
  1966. * YᵢVᵢ has units kg/m^2/s.
  1967. * hᵢ has units J/kmol, so we must multiply the enthalpy
  1968. * defined above (getEnthalpy_RT) by T (K) and the gas constant
  1969. * (J/kmol/K) to get the right units.
  1970. * cₚᵢ has units J/kg/K, so we must multiply the specific heat
  1971. * defined above (getCp_R) by the gas constant (J/kmol/K) and
  1972. * divide by the molecular weight (kg/kmol) to get the right
  1973. * units.
  1974. * */
  1975. //enthalpy formulation:
  1976. //tranTerm = Tdot(j) - (Pdot(j)/(rho*Cpb));
  1977. tranTerm = Tdot(j);
  1978. sum = ZERO;
  1979. sum1 = ZERO;
  1980. for (size_t k = 1; k <= nsp; k++) {
  1981. sum = sum + wdot(k) * enthalpy(k);
  1982. sum1 = sum1 + (Cp(k) / data->gas->molecularWeight(k - 1)) * HALF * (YVmhalf(k) + YVphalf(k));
  1983. }
  1984. sum = sum * Cantera::GasConstant * T(j);
  1985. sum1 = sum1 * Cantera::GasConstant;
  1986. diffTerm = (((rhophalf * areaphalfsq * lambdaphalf * (T(j + 1) - T(j)) / dpsip)
  1987. - (rhomhalf * areamhalfsq * lambdamhalf * (T(j) - T(j - 1)) / dpsim))
  1988. / (dpsiav * Cpb))
  1989. - (sum1 * area * (cendfp * T(j + 1)
  1990. + cendfc * T(j)
  1991. + cendfm * T(j - 1)) / Cpb);
  1992. srcTerm = (sum - Qdot(&t, &R(j), &data->ignTime, &data->kernelSize, &data->maxQDot)) / (rho *
  1993. Cpb); // Qdot is forced heating to cause ignition, sum is the conversion of chemical enthalpy to sensible enthalpy
  1994. advTerm = (Mdot(j) * (T(j) - T(j - 1)) / dpsim);
  1995. Tres(j) = tranTerm - (Pdot(j) / (rho * Cpb))
  1996. + advTerm
  1997. - diffTerm
  1998. + srcTerm;
  1999. // //energy formulation:
  2000. // tranTerm = Tdot(j);
  2001. // sum=ZERO;
  2002. // sum1=ZERO;
  2003. // sum2=ZERO;
  2004. // sum3=ZERO;
  2005. // for (k = 1; k <=nsp; k++) {
  2006. // energy(k)=enthalpy(k)-ONE;
  2007. // sum=sum+wdot(k)*energy(k);
  2008. // sum1=sum1+(Cp(k)/data->gas->molecularWeight(k-1))*rho
  2009. // *HALF*(YVmhalf(k)+YVphalf(k));
  2010. // sum2=sum2+(YVmhalf(k)/data->gas->molecularWeight(k-1));
  2011. // sum3=sum3+(YVphalf(k)/data->gas->molecularWeight(k-1));
  2012. // }
  2013. // sum=sum*Cantera::GasConstant*T(j);
  2014. // sum1=sum1*Cantera::GasConstant;
  2015. // diffTerm =(( (rhophalf*areaphalfsq*lambdaphalf*(T(j+1)-T(j))/dpsip)
  2016. // -(rhomhalf*areamhalfsq*lambdamhalf*(T(j)-T(j-1))/dpsim) )
  2017. // /(dpsiav*Cvb) )
  2018. // -(sum1*area*(cendfp*T(j+1)
  2019. // +cendfc*T(j)
  2020. // +cendfm*T(j-1))/Cvb);
  2021. // srcTerm = (sum-Qdot(&t,&R(j),&data->ignTime,&data->kernelSize,&data->maxQDot))/(rho*Cvb);
  2022. // advTerm = (mdotIn*(T(j)-T(j-1))/dpsim);
  2023. // advTerm = advTerm + (Cantera::GasConstant*T(j)*area/Cvb)*((sum3-sum2)/dpsiav);
  2024. // Tres(j)= tranTerm
  2025. // +advTerm
  2026. // -diffTerm
  2027. // +srcTerm;
  2028. /*Species:*/
  2029. /* ∂Yᵢ/∂t = - ṁ(∂Yᵢ/∂ψ)
  2030. * - (∂/∂ψ)(AYᵢVᵢ)
  2031. * + (ώᵢWᵢ/ρ) */
  2032. sum = ZERO;
  2033. for (size_t k = 1; k <= nsp; k++) {
  2034. if (k != k_bath) {
  2035. tranTerm = Ydot(j, k);
  2036. diffTerm = (YVphalf(k) * areaphalf
  2037. - YVmhalf(k) * areamhalf) / dpsiav;
  2038. srcTerm = wdot(k)
  2039. * (data->gas->molecularWeight(k - 1)) / rho;
  2040. advTerm = (Mdot(j) * (Y(j, k) - Y(j - 1, k)) / dpsim);
  2041. Yres(j, k) = tranTerm
  2042. + advTerm
  2043. + diffTerm
  2044. - srcTerm;
  2045. sum = sum + Y(j, k);
  2046. }
  2047. }
  2048. Yres(j, k_bath) = ONE - sum - Y(j, k_bath);
  2049. /*Pressure:*/
  2050. Pres(j) = P(j + 1) - P(j);
  2051. /*Assign values evaluated at p and phalf to m
  2052. * and mhalf to save some cpu cost:****************/
  2053. areamhalf = areaphalf;
  2054. areamhalfsq = areaphalfsq;
  2055. aream = area;
  2056. rhom = rho;
  2057. rhomhalf = rhophalf;
  2058. lambdamhalf = lambdaphalf;
  2059. for (size_t k = 1; k <= nsp; k++) {
  2060. YVmhalf(k) = YVphalf(k);
  2061. }
  2062. /**************************************************/
  2063. }
  2064. /*******************************************************************///
  2065. /*Fill up res with right side (wall) boundary conditions:***********/
  2066. /*We impose zero fluxes at the wall:*/
  2067. setGas(data, ydata, npts);
  2068. rho = data->gas->density();
  2069. area = calc_area(R(npts), &m);
  2070. /*Mass:*/
  2071. // dpsim = (psi(npts) - psi(npts - 1)) * mass;
  2072. dpsim = (psi(npts) - psi(npts - 1)) ;
  2073. Rres(npts) = ((R(npts) - R(npts - 1)) / dpsim) - (TWO / (rhom * aream + rho * area));
  2074. /*Energy:*/
  2075. if (data->dirichletOuter) {
  2076. //Tres(npts)=T(npts)-data->wallTemperature;
  2077. Tres(npts) = Tdot(npts);
  2078. } else {
  2079. Tres(npts) = T(npts) - T(npts - 1);
  2080. }
  2081. /*Species:*/
  2082. sum = ZERO;
  2083. if (data->dirichletOuter) {
  2084. for (size_t k = 1; k <= nsp; k++) {
  2085. if (k != k_bath) {
  2086. Yres(npts, k) = Ydot(npts, k);
  2087. sum = sum + Y(npts, k);
  2088. }
  2089. }
  2090. } else {
  2091. for (size_t k = 1; k <= nsp; k++) {
  2092. if (k != k_bath) {
  2093. Yres(npts, k) = Y(npts, k) - Y(npts - 1, k);
  2094. //Yres(npts,k)=YVmhalf(k);
  2095. sum = sum + Y(npts, k);
  2096. }
  2097. }
  2098. }
  2099. Yres(npts, k_bath) = ONE - sum - Y(npts, k_bath);
  2100. /*Pressure:*/
  2101. if (data->constantPressure) {
  2102. Pres(npts) = Pdot(npts) - data->dPdt;
  2103. } else {
  2104. Pres(npts) = R(npts) - data->domainLength;
  2105. //Pres(npts)=Rdot(npts);
  2106. }
  2107. /*Evaporating Mass*/
  2108. Mdotres(npts) = Mdot(npts) - Mdot(npts - 1);
  2109. //for (j = 1; j <=npts; j++) {
  2110. // //for (k = 1; k <=nsp; k++) {
  2111. // // Yres(j,k)=Ydot(j,k);
  2112. // //}
  2113. // //Tres(j)=Tdot(j);
  2114. //}
  2115. return (0);
  2116. }
  2117. void printSpaceTimeHeader(UserData data) {
  2118. fprintf((data->output), "%15s\t", "#1");
  2119. for (size_t k = 1; k <= data->nvar + 1; k++) {
  2120. fprintf((data->output), "%15lu\t", k + 1);
  2121. }
  2122. fprintf((data->output), "%15lu\n", data->nvar + 3);
  2123. fprintf((data->output), "%15s\t%15s\t%15s\t", "#psi", "time(s)", "dpsi");
  2124. fprintf((data->output), "%15s\t%15s\t", "radius(m)", "Temp(K)");
  2125. for (size_t k = 1; k <= data->nsp; k++) {
  2126. fprintf((data->output), "%15s\t", data->gas->speciesName(k - 1).c_str());
  2127. }
  2128. fprintf((data->output), "%15s\t", "Pressure(Pa)");
  2129. fprintf((data->output), "%15s\n", "Mdot (kg/s)");
  2130. }
  2131. void printSpaceTimeOutput(double t, N_Vector *y, FILE *output, UserData data) {
  2132. double *ydata, *psidata;
  2133. ydata = N_VGetArrayPointer_OpenMP(*y);
  2134. if (data->adaptiveGrid) {
  2135. psidata = data->grid->x;
  2136. } else {
  2137. psidata = data->uniformGrid;
  2138. }
  2139. for (size_t i = 0; i < data->npts; i++) {
  2140. fprintf(output, "%15.9e\t%15.9e\t", psi(i + 1), t);
  2141. if (i == 0) {
  2142. fprintf(output, "%15.9e\t", psi(2) - psi(1));
  2143. } else {
  2144. fprintf(output, "%15.6e\t", psi(i + 1) - psi(i));
  2145. }
  2146. for (size_t j = 0; j < data->nvar; j++) {
  2147. if (j != data->nvar - 1) {
  2148. fprintf(output, "%15.9e\t", ydata[j + i * data->nvar]);
  2149. } else {
  2150. fprintf(output, "%15.9e", ydata[j + i * data->nvar]);
  2151. }
  2152. }
  2153. fprintf(output, "\n");
  2154. }
  2155. fprintf(output, "\n");
  2156. }
  2157. void writeRestart(double t, N_Vector *y, N_Vector *ydot, FILE *output, UserData data) {
  2158. double *ydata, *psidata, *ydotdata;
  2159. ydata = N_VGetArrayPointer_OpenMP(*y);
  2160. ydotdata = N_VGetArrayPointer_OpenMP(*ydot);
  2161. if (data->adaptiveGrid) {
  2162. psidata = data->grid->x;
  2163. } else {
  2164. psidata = data->uniformGrid;
  2165. }
  2166. fwrite(&t, sizeof(t), 1, output); //write time
  2167. fwrite(psidata, data->npts * sizeof(psidata), 1, output); //write grid
  2168. fwrite(ydata, data->neq * sizeof(ydata), 1, output); //write solution
  2169. fwrite(ydotdata, data->neq * sizeof(ydotdata), 1, output); //write solutiondot
  2170. }
  2171. void readRestart(N_Vector *y, N_Vector *ydot, FILE *input, UserData data) {
  2172. double *ydata, *psidata, *ydotdata;
  2173. double t;
  2174. if (data->adaptiveGrid) {
  2175. psidata = data->grid->x;
  2176. } else {
  2177. psidata = data->uniformGrid;
  2178. }
  2179. ydata = N_VGetArrayPointer_OpenMP(*y);
  2180. ydotdata = N_VGetArrayPointer_OpenMP(*ydot);
  2181. fread(&t, sizeof(t), 1, input);
  2182. data->tNow = t;
  2183. fread(psidata, data->npts * sizeof(psidata), 1, input);
  2184. fread(ydata, data->neq * sizeof(ydata), 1, input);
  2185. fread(ydotdata, data->neq * sizeof(ydotdata), 1, input);
  2186. if (data->adaptiveGrid) {
  2187. storeGrid(data->grid->x, data->grid->xOld, data->npts);
  2188. }
  2189. }
  2190. void printGlobalHeader(UserData data) {
  2191. fprintf((data->globalOutput), "%8s\t", "#Time(s)");
  2192. //fprintf((data->globalOutput), "%15s","S_u(exp*)(m/s)");
  2193. fprintf((data->globalOutput), "%15s", "bFlux(kg/m^2/s)");
  2194. fprintf((data->globalOutput), "%16s", " IsothermPos(m)");
  2195. fprintf((data->globalOutput), "%15s\t", "Pressure(Pa)");
  2196. fprintf((data->globalOutput), "%15s\t", "Pdot(Pa/s)");
  2197. fprintf((data->globalOutput), "%15s\t", "gamma");
  2198. fprintf((data->globalOutput), "%15s\t", "S_u(m/s)");
  2199. fprintf((data->globalOutput), "%15s\t", "Tu(K)");
  2200. fprintf((data->globalOutput), "\n");
  2201. }
  2202. //
  2203. //void printSpaceTimeRates(double t, N_Vector ydot, UserData data)
  2204. //{
  2205. // double *ydotdata,*psidata;
  2206. // ydotdata = N_VGetArrayPointer_OpenMP(ydot);
  2207. // psidata = N_VGetArrayPointer_OpenMP(data->grid);
  2208. // for (int i = 0; i < data->npts; i++) {
  2209. // fprintf((data->ratesOutput), "%15.6e\t%15.6e\t",psi(i+1),t);
  2210. // for (int j = 0; j < data->nvar; j++) {
  2211. // fprintf((data->ratesOutput), "%15.6e\t",ydotdata[j+i*data->nvar]);
  2212. // }
  2213. // fprintf((data->ratesOutput), "\n");
  2214. // }
  2215. // fprintf((data->ratesOutput), "\n\n");
  2216. //}
  2217. //
  2218. void printGlobalVariables(double t, N_Vector *y, N_Vector *ydot, UserData data) {
  2219. double *ydata, *ydotdata, *innerMassFractionsData, *psidata;
  2220. innerMassFractionsData = data->innerMassFractions;
  2221. if (data->adaptiveGrid) {
  2222. psidata = data->grid->x;
  2223. } else {
  2224. psidata = data->uniformGrid;
  2225. }
  2226. double TAvg, RAvg, YAvg, psiAvg;
  2227. ydata = N_VGetArrayPointer_OpenMP(*y);
  2228. ydotdata = N_VGetArrayPointer_OpenMP(*ydot);
  2229. TAvg = data->isotherm;
  2230. double sum = ZERO;
  2231. double dpsim, area, aream, drdt;
  2232. double Cpb, Cvb, gamma, rho, flameArea, Tu;
  2233. /*Find the isotherm chosen by the user*/
  2234. size_t j = 1;
  2235. size_t jj = 1;
  2236. size_t jjj = 1;
  2237. double wdot[data->nsp];
  2238. double wdotMax = 0.0e0;
  2239. double advTerm = 0.0e0;
  2240. psiAvg = 0.0e0;
  2241. if (T(data->npts) > T(1)) {
  2242. while (T(j) < TAvg) {
  2243. j = j + 1;
  2244. }
  2245. YAvg = innerMassFractionsData[data->k_oxidizer - 1] - Y(data->npts, data->k_oxidizer);
  2246. while (fabs((T(jj + 1) - T(jj)) / T(jj)) > 1e-08) {
  2247. jj = jj + 1;
  2248. }
  2249. setGas(data, ydata, jj);
  2250. Tu = T(jj);
  2251. rho = data->gas->density();
  2252. Cpb = data->gas->cp_mass(); //J/kg/K
  2253. Cvb = data->gas->cv_mass(); //J/kg/K
  2254. gamma = Cpb / Cvb;
  2255. } else {
  2256. while (T(j) > TAvg) {
  2257. j = j + 1;
  2258. }
  2259. YAvg = innerMassFractionsData[data->k_oxidizer - 1] - Y(1, data->k_oxidizer);
  2260. while (fabs((T(data->npts - jj - 1) - T(data->npts - jj)) / T(data->npts - jj)) > 1e-08) {
  2261. jj = jj + 1;
  2262. }
  2263. setGas(data, ydata, data->npts - jj);
  2264. Tu = T(data->npts - jj);
  2265. rho = data->gas->density();
  2266. Cpb = data->gas->cp_mass(); //J/kg/K
  2267. Cvb = data->gas->cv_mass(); //J/kg/K
  2268. gamma = Cpb / Cvb;
  2269. }
  2270. if (T(j) < TAvg) {
  2271. RAvg = ((R(j + 1) - R(j)) / (T(j + 1) - T(j))) * (TAvg - T(j)) + R(j);
  2272. } else {
  2273. RAvg = ((R(j) - R(j - 1)) / (T(j) - T(j - 1))) * (TAvg - T(j - 1)) + R(j - 1);
  2274. }
  2275. ////Experimental burning speed calculation:
  2276. //int nMax=0;
  2277. ////nMax=maxCurvIndex(ydata, data->nt, data->nvar,
  2278. //// data->grid->x, data->npts);
  2279. //nMax=maxGradIndex(ydata, data->nt, data->nvar,
  2280. // data->grid->x, data->npts);
  2281. //advTerm=(T(nMax)-T(nMax-1))/(data->mass*(psi(nMax)-psi(nMax-1)));
  2282. //aream=calc_area(R(nMax),&data->metric);
  2283. ////setGas(data,ydata,nMax);
  2284. ////rho=data->gas->density();
  2285. //psiAvg=-Tdot(nMax)/(rho*aream*advTerm);
  2286. ////if(t>data->ignTime){
  2287. //// for(size_t n=2;n<data->npts;n++){
  2288. //// setGas(data,ydata,n);
  2289. //// data->gas->getNetProductionRates(wdot); //kmol/m^3
  2290. //// advTerm=(T(n)-T(n-1))/(data->mass*(psi(n)-psi(n-1)));
  2291. //// if(fabs(wdot[data->k_oxidizer-1])>=wdotMax){
  2292. //// aream=calc_area(R(n),&data->metric);
  2293. //// psiAvg=-Tdot(n)/(rho*aream*advTerm);
  2294. //// wdotMax=fabs(wdot[data->k_oxidizer-1]);
  2295. //// }
  2296. //// }
  2297. ////}
  2298. ////else{
  2299. //// psiAvg=0.0e0;
  2300. ////}
  2301. //drdt=(RAvg-data->flamePosition[1])/(t-data->flameTime[1]);
  2302. //data->flamePosition[0]=data->flamePosition[1];
  2303. //data->flamePosition[1]=RAvg;
  2304. //data->flameTime[0]=data->flameTime[1];
  2305. //data->flameTime[1]=t;
  2306. //flameArea=calc_area(RAvg,&data->metric);
  2307. /*Use the Trapezoidal rule to calculate the mass burning rate based on
  2308. * the consumption of O2*/
  2309. aream = calc_area(R(1) + 1e-03 * data->domainLength, &data->metric);
  2310. for (j = 2; j < data->npts; j++) {
  2311. dpsim = (psi(j) - psi(j - 1)) * data->mass;
  2312. area = calc_area(R(j), &data->metric);
  2313. sum = sum + HALF * dpsim * ((Ydot(j - 1, data->k_oxidizer) / aream)
  2314. + (Ydot(j, data->k_oxidizer) / area));
  2315. aream = area;
  2316. }
  2317. //double maxOH,maxHO2;
  2318. //maxOH=0.0e0;
  2319. //maxHO2=0.0e0;
  2320. //for(j=1;j<data->npts;j++){
  2321. // if(Y(j,data->k_OH)>maxOH){
  2322. // maxOH=Y(j,data->k_OH);
  2323. // }
  2324. //}
  2325. //for(j=1;j<data->npts;j++){
  2326. // if(Y(j,data->k_HO2)>maxHO2){
  2327. // maxHO2=Y(j,data->k_HO2);
  2328. // }
  2329. //}
  2330. fprintf((data->globalOutput), "%15.6e\t", t);
  2331. //fprintf((data->globalOutput), "%15.6e\t",psiAvg);
  2332. fprintf((data->globalOutput), "%15.6e\t", fabs(sum) / YAvg);
  2333. fprintf((data->globalOutput), "%15.6e\t", RAvg);
  2334. fprintf((data->globalOutput), "%15.6e\t", P(data->npts));
  2335. fprintf((data->globalOutput), "%15.6e\t", Pdot(data->npts));
  2336. fprintf((data->globalOutput), "%15.6e\t", gamma);
  2337. fprintf((data->globalOutput), "%15.6e\t", fabs(sum) / (YAvg * rho));
  2338. fprintf((data->globalOutput), "%15.6e\t", Tu);
  2339. fprintf((data->globalOutput), "\n");
  2340. }
  2341. //
  2342. //void printSpaceTimeOutputInterpolated(double t, N_Vector y, UserData data)
  2343. //{
  2344. // double *ydata,*psidata;
  2345. // ydata = N_VGetArrayPointer_OpenMP(y);
  2346. // psidata = N_VGetArrayPointer_OpenMP(data->grid);
  2347. // for (int i = 0; i < data->npts; i++) {
  2348. // fprintf((data->gridOutput), "%15.6e\t%15.6e\t",psi(i+1),t);
  2349. // for (int j = 0; j < data->nvar; j++) {
  2350. // fprintf((data->gridOutput), "%15.6e\t",ydata[j+i*data->nvar]);
  2351. // }
  2352. // fprintf((data->gridOutput), "\n");
  2353. // }
  2354. // fprintf((data->gridOutput), "\n\n");
  2355. //}
  2356. //
  2357. //
  2358. ////void repairSolution(N_Vector y, N_Vector ydot, UserData data){
  2359. //// int npts=data->npts;
  2360. //// double *ydata;
  2361. //// double *ydotdata;
  2362. //// ydata = N_VGetArrayPointer_OpenMP(y);
  2363. //// ydotdata = N_VGetArrayPointer_OpenMP(ydot);
  2364. ////
  2365. //// T(2)=T(1);
  2366. //// T(npts-1)=T(npts);
  2367. //// Tdot(2)=Tdot(1);
  2368. //// Tdot(npts-1)=Tdot(npts);
  2369. //// for (int k = 1; k <=data->nsp; k++) {
  2370. //// Y(2,k)=Y(1,k);
  2371. //// Y(npts-1,k)=Y(npts,k);
  2372. ////
  2373. //// Ydot(2,k)=Ydot(1,k);
  2374. //// Ydot(npts-1,k)=Ydot(npts,k);
  2375. //// }
  2376. ////}
  2377. /*Following functions are added to derive the characteristic time scale of species*/
  2378. void getTimescale(UserData data, N_Vector *y) {
  2379. size_t i, k, nsp, npts;
  2380. nsp = data->nsp;
  2381. npts = data->npts;
  2382. double rho, wdot_mole[nsp], wdot_mass[nsp], MW[nsp], concentra[nsp];
  2383. //double time_scale[npts*nsp] ;
  2384. double *ydata;
  2385. ydata = N_VGetArrayPointer_OpenMP(*y); //access the data stored in N_Vector* y
  2386. for (i = 1; i <= npts; i++) {
  2387. setGas(data, ydata, i); //set the gas state at each grid point
  2388. rho = data->gas->density(); //get the averaged density at each grid point, Unit:kg/m^3
  2389. data->gas->getNetProductionRates(wdot_mole); //Unit:kmol/(m^3 * s)
  2390. for (k = 1; k <= nsp; k++) {
  2391. MW(k) = data->gas->molecularWeight(k - 1); //Unit:kg/kmol
  2392. }
  2393. for (k = 1; k <= nsp; k++) {
  2394. wdot_mass(k) = wdot_mole(k) * MW(k); //Unit:kg/(m^3 * s)
  2395. }
  2396. for (k = 1; k <= nsp; k++) {
  2397. concentra(k) = Y(i, k) * rho; //Unit:kg/m^3
  2398. }
  2399. for (k = 1; k <= nsp; k++) {
  2400. data->time_scale(i, k) = concentra(k) / (wdot_mass(k) + 1.00e-16);
  2401. }
  2402. }
  2403. }
  2404. void printTimescaleHeader(UserData data) {
  2405. fprintf((data->timescaleOutput), "%15s\t", "#1");
  2406. for (size_t k = 1; k <= data->nsp + 1; k++) {
  2407. fprintf((data->timescaleOutput), "%15lu\t", k + 1);
  2408. }
  2409. fprintf((data->timescaleOutput), "%15lu\n", data->nsp + 3);
  2410. fprintf((data->timescaleOutput), "%15s\t%15s\t%15s\t", "#time", "radius", "Temp(K)");
  2411. //fprintf((data->output), "%15s\t%15s\t","radius(m)","Temp(K)");
  2412. for (size_t k = 1; k <= (data->nsp); k++) {
  2413. fprintf((data->timescaleOutput), "%15s\t", data->gas->speciesName(k - 1).c_str());
  2414. }
  2415. //fprintf((data->output), "%15s\t","Pressure(Pa)");
  2416. //fprintf((data->timescaleOutput), "%15s\n",data->gas->speciesName(data->nsp-1).c_str());
  2417. //fprintf((data->output), "%15s\n","Mdot (kg/s)");
  2418. fprintf((data->timescaleOutput), "\n");
  2419. }
  2420. void printTimescaleOutput(double t, N_Vector *y, FILE *output, UserData data) {
  2421. double *ydata;
  2422. ydata = N_VGetArrayPointer_OpenMP(*y);
  2423. for (size_t i = 1; i <= data->npts; i++) {
  2424. fprintf(output, "%15.9e\t%15.9e\t", t, R(i));
  2425. fprintf(output, "%15.9e\t", T(i));
  2426. for (size_t k = 1; k <= data->nsp; k++) {
  2427. fprintf(output, "%15.9e\t", data->time_scale(i, k));
  2428. }
  2429. fprintf(output, "\n");
  2430. }
  2431. fprintf(output, "\n");
  2432. }
  2433. void floorSmallValue(UserData data, N_Vector *y) {
  2434. double *ydata;
  2435. ydata = N_VGetArrayPointer_OpenMP(*y);
  2436. //double sum = 0.00;
  2437. size_t k_bath = data->k_bath;
  2438. /*Floor small values to zero*/
  2439. for (size_t i = 1; i <= data->npts; i++) {
  2440. for (size_t k = 1; k <= data->nsp; k++) {
  2441. if (fabs(Y(i, k)) <= data->massFractionTolerance) {
  2442. Y(i, k) = 0.0e0;
  2443. }
  2444. }
  2445. }
  2446. /*Dump the error to the bath gas*/
  2447. for (size_t i = 1; i <= data->npts; i++) {
  2448. double sum = 0.00;
  2449. for (size_t k = 1; k <= data->nsp; k++) {
  2450. if (k != k_bath) {
  2451. sum = sum + Y(i, k);
  2452. }
  2453. }
  2454. Y(i, k_bath) = ONE - sum;
  2455. }
  2456. }
  2457. void resetTolerance(UserData data, N_Vector *y, N_Vector *atolv) {
  2458. double *ydata;
  2459. realtype *atolvdata;
  2460. ydata = N_VGetArrayPointer_OpenMP(*y);
  2461. atolvdata = N_VGetArrayPointer_OpenMP(*atolv);
  2462. double relTol, radTol, tempTol, presTol, massFracTol, bathGasTol, mdotTol;
  2463. double maxT = 0.00, deltaT = 400.0;
  2464. relTol = 1.0e-03;
  2465. radTol = 1.0e-05;
  2466. tempTol = 1.0e-03;
  2467. presTol = 1.0e-3;
  2468. massFracTol = 1.0e-06;
  2469. bathGasTol = 1.0e-05;
  2470. mdotTol = 1.0e-10;
  2471. /*Get the maximum Temperature*/
  2472. for (size_t i = 1; i <= data->npts; i++) {
  2473. if (T(i) > maxT) {
  2474. maxT = T(i);
  2475. }
  2476. }
  2477. /*reset the tolerance when maxT > initialTemperature +deltaT*/
  2478. if (maxT >= (data->initialTemperature + deltaT)) {
  2479. data->relativeTolerance = relTol;
  2480. for (size_t i = 1; i <= data->npts; i++) {
  2481. atolT(i) = tempTol;
  2482. atolR(i) = radTol;
  2483. atolP(i) = presTol;
  2484. atolMdot(i) = mdotTol;
  2485. for (size_t k = 1; k <= data->nsp; k++) {
  2486. if (k != data->k_bath) {
  2487. atolY(i, k) = massFracTol;
  2488. } else {
  2489. atolY(i, k) = bathGasTol;
  2490. }
  2491. }
  2492. }
  2493. }
  2494. }
  2495. void getReactions(UserData data, N_Vector *y, FILE *output) {
  2496. double Tmax;
  2497. double *ydata;
  2498. //double deltaT = 400.0;
  2499. //int i = 0;
  2500. size_t nRxns;
  2501. int index;
  2502. nRxns = data->gas->nReactions();
  2503. //DEBUG
  2504. printf("Total Number of Rxns:%zu \n", nRxns);
  2505. double fwdROP[nRxns], revROP[nRxns], netROP[nRxns];
  2506. std::string *rxnArr = new std::string[nRxns];
  2507. ydata = N_VGetArrayPointer_OpenMP(*y);
  2508. Tmax = maxTemperature(ydata, data->nt, data->nvar, data->npts);
  2509. //get the rxns' equation array
  2510. for (size_t ii = 0; ii < nRxns; ii++) {
  2511. rxnArr[ii] = data->gas->reactionString(ii);
  2512. }
  2513. printf("Printing Rxns Rate Of Progress Data......\n");
  2514. if (Tmax >= (data->initialTemperature + data->deltaT)) {
  2515. index = maxTemperatureIndex(ydata, data->nt, data->nvar, data->npts);
  2516. setGas(data, ydata, index);
  2517. /*Get forward/reverse/net rate of progress of rxns*/
  2518. data->gas->getRevRatesOfProgress(revROP);
  2519. data->gas->getFwdRatesOfProgress(fwdROP);
  2520. data->gas->getNetRatesOfProgress(netROP);
  2521. for (size_t j = 0; j < nRxns; j++) {
  2522. fprintf(output, "%30s\t", rxnArr[j].c_str());
  2523. fprintf(output, "%15.9e\t%15.9e\t%15.9e\t\n", fwdROP[j], revROP[j], netROP[j]);
  2524. }
  2525. fprintf(output, "\n");
  2526. fclose(output);
  2527. }
  2528. delete[] rxnArr;
  2529. }
  2530. void getSpecies(UserData data, N_Vector *y, FILE *output) {
  2531. double Tmax;
  2532. double *ydata;
  2533. int index;
  2534. double fwdROP[data->nsp], revROP[data->nsp], netROP[data->nsp];
  2535. std::string *spArr = new std::string[data->nsp];
  2536. ydata = N_VGetArrayPointer_OpenMP(*y);
  2537. Tmax = maxTemperature(ydata, data->nt, data->nvar, data->npts);
  2538. //get the species name array
  2539. for (size_t ii = 0; ii < data->nsp; ii++) {
  2540. spArr[ii] = data->gas->speciesName(ii);
  2541. }
  2542. printf("Printing Species Rate of Production/Destruction Data......\n");
  2543. if (Tmax >= (data->initialTemperature + data->deltaT)) {
  2544. index = maxTemperatureIndex(ydata, data->nt, data->nvar, data->npts);
  2545. setGas(data, ydata, index);
  2546. /*Get forward/reverse/net rate of progress of rxns*/
  2547. data->gas->getDestructionRates(revROP);
  2548. data->gas->getCreationRates(fwdROP);
  2549. data->gas->getNetProductionRates(netROP);
  2550. /*Print data to the pertinent output file*/
  2551. for (size_t j = 0; j < data->nsp; j++) {
  2552. fprintf(output, "%15s\t", spArr[j].c_str());
  2553. fprintf(output, "%15.9e\t%15.9e\t%15.9e\t\n", fwdROP[j], revROP[j], netROP[j]);
  2554. }
  2555. fprintf(output, "\n");
  2556. fclose(output);
  2557. }
  2558. delete[] spArr;
  2559. }
  2560. //
  2561. ////rho : density of liquid phase
  2562. //double getLiquidRho(double dropMole[],double temp,double pres){
  2563. // std::vector<std::string> fluids;
  2564. // fluids.push_back("Propane");
  2565. // fluids.push_back("n-Heptane");
  2566. //
  2567. // std::vector<double> Temperature(1,temp),Pressure(1,pres);
  2568. // std::vector<std::string> outputs;
  2569. // outputs.push_back("D");
  2570. //
  2571. // std::vector<double> moles;
  2572. // moles.push_back(dropMole[0]);
  2573. // moles.push_back(dropMole[1]);
  2574. // double density = CoolProp::PropsSImulti(outputs,"T",Temperature,"P",Pressure,"",fluids,moles)[0][0]; //Unit:kg/m^3
  2575. //
  2576. // return density;
  2577. //}
  2578. ////Cp,l : specific heat capacity at constant pressure of liquid phase
  2579. //double getLiquidCp(double dropMole[],double temp,double pres){
  2580. // std::vector<std::string> fluids;
  2581. // fluids.push_back("Propane");
  2582. // fluids.push_back("n-Heptane");
  2583. //
  2584. // std::vector<double> Temperature(1,temp),Pressure(1,pres);
  2585. // std::vector<std::string> outputs;
  2586. // outputs.push_back("CPMASS");
  2587. //
  2588. // std::vector<double> moles;
  2589. // moles.push_back(dropMole[0]);
  2590. // moles.push_back(dropMole[1]);
  2591. // double cp = CoolProp::PropsSImulti(outputs,"T",Temperature,"P",Pressure,"",fluids,moles)[0][0]; //Unit:J/(kg*K)
  2592. //
  2593. // return cp;
  2594. //}
  2595. ////Hv : heat of vaporization of liquid phase at constant pressure
  2596. //double getLiquidHv(double dropMole[],double temp,double pres){
  2597. // std::vector<std::string> fluids;
  2598. // fluids.push_back("Propane");
  2599. // fluids.push_back("n-Heptane");
  2600. //
  2601. // std::vector<double> Temperature(1,temp),Pressure(1,pres);
  2602. // std::vector<std::string> outputs;
  2603. // outputs.push_back("H");
  2604. //
  2605. // std::vector<double> moles;
  2606. // moles.push_back(dropMole[0]);
  2607. // moles.push_back(dropMole[1]);
  2608. //
  2609. // std::vector<double> state1(1,1.0);
  2610. // std::vector<double> state2(1,0.0);
  2611. //
  2612. // double H_V = CoolProp::PropsSImulti(outputs,"P",Pressure,"Q",state1,"",fluids,moles)[0][0]; //Unit:J/kg
  2613. // double H_L = CoolProp::PropsSImulti(outputs,"P",Pressure,"Q",state2,"",fluids,moles)[0][0]; //Unit:J/kg
  2614. // double delta_H = H_V - H_L;
  2615. //
  2616. // return delta_H;
  2617. //}
  2618. ////MaxT : maximum allowed tempereture of liquid phase
  2619. ////Also the boiling point of more volitile component
  2620. //double getLiquidMaxT(double dropMole[],double pres){
  2621. // std::vector<std::string> fluids;
  2622. // fluids.push_back("Propane");
  2623. // //fluids.push_back("n-Heptane");
  2624. //
  2625. // std::vector<double> Pressure(1,pres);
  2626. // std::vector<std::string> outputs;
  2627. // outputs.push_back("T");
  2628. //
  2629. // double temperature = CoolProp::PropsSI(outputs[0], "P", Pressure[0],"Q",1.0,fluids[0]);
  2630. //
  2631. // return temperature;
  2632. //}
  2633. /*function overloading for single and bi-component*/
  2634. /*calculate the liquid phase density based on droplet type and T,P,X(Y)*/
  2635. /*single component case*/
  2636. double getLiquidDensity(const double temp, const double pres, const std::vector<std::string> &composition) {
  2637. std::vector<double> Temperature(1, temp), Pressure(1, pres);
  2638. double density = CoolProp::PropsSI("D", "T", Temperature[0], "P", Pressure[0], composition[0]); //Unit:kg/m^3
  2639. return density;
  2640. }
  2641. /*binary component case*/
  2642. double getLiquidDensity(const double temp, const double pres, std::vector<std::string> &composition,
  2643. const std::vector<double> &mole) {
  2644. std::vector<double> Temperature(1, temp), Pressure(1, pres);
  2645. std::vector<std::string> outputs;
  2646. outputs.push_back("D");
  2647. double density = CoolProp::PropsSImulti(outputs, "T", Temperature, "P", Pressure, "", composition,
  2648. mole)[0][0]; //Unit:kg/m^3
  2649. return density;
  2650. }
  2651. double getLiquidCond(const double temp, const double pres, const std::vector<std::string> &composition) {
  2652. std::vector<double> Temperature(1, temp), Pressure(1, pres);
  2653. double k = CoolProp::PropsSI("conductivity", "T", Temperature[0], "P", Pressure[0], composition[0]);
  2654. return k; //Unit:W/m/K (kg*m/s^3/K)
  2655. }
  2656. /*binary component case*/
  2657. double getLiquidCond(const double temp, const double pres, std::vector<std::string> &composition,
  2658. const std::vector<double> &mole) {
  2659. std::vector<double> Temperature(1, temp), Pressure(1, pres);
  2660. std::vector<std::string> outputs;
  2661. outputs.push_back("conductivity");
  2662. double k = CoolProp::PropsSImulti(outputs, "T", Temperature, "P", Pressure, "", composition,
  2663. mole)[0][0];
  2664. return k; //Unit:W/m/K (kg*m/s^3/K)
  2665. }
  2666. /*Cpb:total liquid phase specific heat capacity at constant pressure*/
  2667. double getLiquidCpb(const double temp,const double pres, const std::vector<std::string>& composition){
  2668. std::vector<double> Temperature(1, temp), Pressure(1, pres);
  2669. double k = CoolProp::PropsSI("Cpmass", "T", Temperature[0], "P", Pressure[0], composition[0]); //Unit:kg/m^3
  2670. return k; //unit:J/kg/K
  2671. }
  2672. /*binary component case*/
  2673. double getLiquidCpb(const double temp, const double pres, const std::vector<std::string> &composition,
  2674. const std::vector<double> &mole) {
  2675. std::vector<double> Temperature(1, temp), Pressure(1, pres);
  2676. std::vector<std::string> outputs;
  2677. outputs.push_back("Cpmass");
  2678. double k = CoolProp::PropsSImulti(outputs, "T", Temperature, "P", Pressure, "", composition,
  2679. mole)[0][0]; //Unit:kg/m^3
  2680. return k; //unit:J/kg/K
  2681. }
  2682. /*get Cp vector for binary componet droplet*/
  2683. std::vector<double> getLiquidCp(const double temp, const double pres, const std::vector<std::string> &composition){
  2684. std::vector<double> k ;
  2685. double k_temp;
  2686. std::vector<double> Temperature(1, temp), Pressure(1, pres);
  2687. for(auto & species : composition){
  2688. k_temp = CoolProp::PropsSI("Cpmass", "T", Temperature[0], "P", Pressure[0], species);
  2689. k.push_back(k_temp) ;
  2690. }
  2691. return k;
  2692. }
  2693. /*get gas phase thermal conductivity*/
  2694. double getGasCond(UserData data, double *ydata, size_t gridPoint) {
  2695. double k;
  2696. setGas(data, ydata, gridPoint);
  2697. k = data->trmix->thermalConductivity();
  2698. return k; //unit:W/(m*K)
  2699. }
  2700. /*latent heat of vaporizaiton*/
  2701. /*unit: J/kg*/
  2702. std::vector<double> getLiquidVH(const double pres, const int dropType) {
  2703. double H, H_V, H_L;
  2704. std::vector<double> vapheat;
  2705. std::vector<std::string> fluids;
  2706. std::vector<double> Pressure(1, pres);
  2707. fluids = components(dropType);
  2708. if (dropType == 0) {
  2709. // fluids.push_back("nHeptane");
  2710. H_V = CoolProp::PropsSI("H", "P", Pressure[0], "Q", 1, fluids[0]);
  2711. H_L = CoolProp::PropsSI("H", "P", Pressure[0], "Q", 0, fluids[0]);
  2712. H = H_V - H_L;
  2713. vapheat.push_back(H);
  2714. } else {
  2715. for (size_t i = 0; i < fluids.size(); i++) {
  2716. H_V = CoolProp::PropsSI("H", "P", Pressure[0], "Q", 1, fluids[i]);
  2717. H_L = CoolProp::PropsSI("H", "P", Pressure[0], "Q", 0, fluids[i]);
  2718. H = H_V - H_L;
  2719. vapheat.push_back(H);
  2720. }
  2721. }
  2722. return vapheat; //unit:J/kg
  2723. }
  2724. /*convert mass fraction to mole fraction*/
  2725. /*size of both arrays should be identical*/
  2726. void mass2mole(const std::vector<double> &mass, std::vector<double> &mole, UserData data) {
  2727. mole.reserve(mass.size());
  2728. double sum = 0.0;
  2729. double x_temp;
  2730. for (size_t i = 0; i < data->dropMole.size(); i++) {
  2731. sum = sum + mass[i] / data->MW[i];
  2732. }
  2733. x_temp = mass[0] / (data->MW[0] * sum);
  2734. mole.push_back(x_temp);
  2735. mole.push_back(ONE - x_temp);
  2736. }
  2737. /*liquid mass diffusivity D for binary component case*/
  2738. double getLiquidmassdiff(UserData data, double *ydata, size_t gridPoint, const double temp) {
  2739. std::vector<double> V_ = {75.86, 162.34}; //molar volume at normal boiling point, unit: cm^3/mol
  2740. std::vector<double> visc_, mole_, mass_, D_inf_;
  2741. double visc_temp, D, Dinf_temp;
  2742. std::vector<std::string> composition = components(data->dropType);
  2743. for (size_t i = 0; i < data->dropMole.size(); i++) {
  2744. visc_temp = 1000.0 * CoolProp::PropsSI("V", "T", temp, "Q", 0, composition[i]); //unit: mPa*s
  2745. visc_.push_back(visc_temp);
  2746. }
  2747. mole_ = getLiquidmolevec(data, ydata, gridPoint);
  2748. for (size_t i = 0; i < data->dropMole.size(); i++) {
  2749. if (i == 0) {
  2750. Dinf_temp = 9.89e-8 * temp * pow(visc_[1], -0.907) * pow(V_[0], -0.45) * pow(V_[1], 0.265);
  2751. D_inf_.push_back(Dinf_temp);
  2752. } else {
  2753. Dinf_temp = 9.89e-8 * temp * pow(visc_[0], -0.907) * pow(V_[1], -0.45) * pow(V_[0], 0.265);
  2754. D_inf_.push_back(Dinf_temp);
  2755. }
  2756. }
  2757. D = mole_[1] * D_inf_[0] + mole_[0] * D_inf_[1]; //unit:cm^2/s
  2758. return (D / 10000); //unit:m^2/s
  2759. }
  2760. //double dropletmass(UserData data,double* ydata){
  2761. // double mass = 0.0 ;
  2762. // double rho,rhop;
  2763. // if (data->dropType==0){
  2764. // for (size_t i = data->l_npts-1; i>=1 ; i--) {
  2765. // std::vector<std::string> str;
  2766. // str.push_back("nHeptane");
  2767. // rho = getLiquidDensity(T(i), P(i), str);
  2768. // rhop = getLiquidDensity(T(i + 1), P(i + 1), str);
  2769. // mass = mass + (R(i + 1) - R(i)) * (rho * calc_area(R(i), &data->metric) +
  2770. // rhop * calc_area(R(i + 1), &data->metric)) / TWO;
  2771. // }
  2772. // }else if(data->dropType==1){
  2773. // for (size_t i = data->l_npts-1; i>=1 ; i--){
  2774. // std::vector<std::string> str;
  2775. // std::vector<double> massFrac,massFracp,moleFrac,moleFracp;
  2776. // str.push_back("propane");
  2777. // str.push_back("nHeptane");
  2778. // for (size_t j = 0; j < data->dropMole.size(); j++){
  2779. // massFrac.push_back(Y(i,data->k_drop[j]));
  2780. // massFracp.push_back(Y(i+1,data->k_drop[j]));
  2781. // }
  2782. // /*convert mass fraction to mole fraction*/
  2783. // mass2mole(massFrac,moleFrac,data);
  2784. // mass2mole(massFracp,moleFracp,data);
  2785. // rho = getLiquidDensity(T(i),P(i),str,moleFrac);
  2786. // rhop = getLiquidDensity(T(i+1),P(i+1),str,moleFracp);
  2787. // mass = mass +(R(i+1)-R(i))*(rho*calc_area(R(i),&data->metric)+rhop*calc_area(R(i+1),&data->metric))/TWO;
  2788. // }
  2789. // }
  2790. // return mass ;
  2791. //}
  2792. // List of fluid components per dropType
  2793. std::vector<std::string> components(int dropType) {
  2794. if (dropType == 0) {
  2795. return {"nHeptane"};
  2796. } else if (dropType == 1) {
  2797. return {"propane", "nHeptane"};
  2798. }
  2799. return {};
  2800. }
  2801. /*calculat droplet mass*/
  2802. double dropletmass(UserData data, double *ydata) {
  2803. double mass = 0.0;
  2804. double rho, rhop;
  2805. for (size_t i = data->l_npts - 1; i >= 1; i--) {
  2806. std::vector<std::string> composition = components(data->dropType);
  2807. if (data->dropType == 0) {
  2808. rho = getLiquidDensity(T(i), P(i), composition);
  2809. rhop = getLiquidDensity(T(i + 1), P(i + 1), composition);
  2810. } else if (data->dropType == 1) {
  2811. std::vector<double> moleFrac, moleFracp;
  2812. moleFrac = getLiquidmolevec(data, ydata, i);
  2813. moleFracp = getLiquidmolevec(data, ydata, i);
  2814. rho = getLiquidDensity(T(i), P(i), composition, moleFrac);
  2815. rhop = getLiquidDensity(T(i + 1), P(i + 1), composition, moleFracp);
  2816. }
  2817. double area = calc_area(R(i), &data->metric);
  2818. double areap = calc_area(R(i + 1), &data->metric);
  2819. mass += (R(i + 1) - R(i)) * (rho * area + rhop * areap) / TWO;
  2820. }
  2821. return mass;
  2822. }
  2823. std::vector<double> getLiquidmassvec(UserData data, double *ydata, int gridPoint) {
  2824. std::vector<double> mass_;
  2825. mass_.push_back(Y(gridPoint, data->k_drop[0]));
  2826. mass_.push_back(Y(gridPoint, data->k_drop[1]));
  2827. return mass_;
  2828. }
  2829. std::vector<double> getLiquidmolevec(UserData data, double *ydata, int gridPoint) {
  2830. std::vector<double> mass_, mole_;
  2831. mass_ = getLiquidmassvec(data, ydata, gridPoint);
  2832. mass2mole(mass_, mole_, data);
  2833. return mole_;
  2834. }
  2835. /*return droplet species vapor pressure at interface, unit:Pa*/
  2836. std::vector<double> getVapPressure(UserData data, double* ydata,int gridPoint,const std::vector<double> mole_){
  2837. std::vector<double> vapPres;
  2838. vapPres.reserve(mole_.size()) ;
  2839. std::vector<double> gamma_;
  2840. getGamma(mole_,gamma_) ;
  2841. //propane
  2842. double p1 = 1.0e5 * pow(10, 4.53678 - (1149.36 / (T(gridPoint) + 24.906))) * mole_[0] *
  2843. gamma_[0];
  2844. //heptane
  2845. double p2 = 1.0e5 * pow(10, 4.02832 - (1268.636 / (T(gridPoint) - 56.199))) * mole_[1] *
  2846. gamma_[1];
  2847. vapPres.push_back(p1);
  2848. vapPres.push_back(p2);
  2849. return vapPres;
  2850. }
  2851. void printIddata(UserData data, double *iddata) {
  2852. FILE *file;
  2853. file = fopen("id.dat", "w");
  2854. fprintf(file, "%15s\t%15s\t", "Rid", "Tid");
  2855. for (size_t k = 1; k <= data->nsp; k++) {
  2856. fprintf(file, "%15s\t", data->gas->speciesName(k - 1).c_str());
  2857. }
  2858. fprintf(file, "%15s\t", "Pid");
  2859. fprintf(file, "%15s\n", "Mdotid");
  2860. for (size_t i = 1; i <= data->npts; i++) {
  2861. fprintf(file, "%15lu\t", (size_t) Rid(i));
  2862. fprintf(file, "%15lu\t", (size_t) Tid(i));
  2863. for (size_t k = 1; k <= data->nsp; k++) {
  2864. fprintf(file, "%15lu\t", (size_t) Yid(i, k));
  2865. }
  2866. fprintf(file, "%15lu\t", (size_t) Pid(i));
  2867. fprintf(file, "%15lu\n", (size_t) Mdotid(i));
  2868. }
  2869. fclose(file);
  2870. }
  2871. void printPsidata(UserData data, double* psidata) {
  2872. FILE *file;
  2873. file = fopen("psi.dat", "w");
  2874. // fprintf(file, "%15s\t%15s\t", "Rid", "Tid");
  2875. for (size_t j = 1; j <= data->npts; j++) {
  2876. fprintf(file, "%lu\t", j);
  2877. }
  2878. fprintf(file, "\n");
  2879. for (size_t j = 1; j <= data->npts; j++) {
  2880. // fprintf(file, "%15lu\t", (size_t) Rid(i));
  2881. // fprintf(file, "%15lu\t", (size_t) Tid(i));
  2882. // for (size_t k = 1; k <= data->nsp; k++) {
  2883. // fprintf(file, "%15lu\t", (size_t) Yid(i, k));
  2884. // }
  2885. // fprintf(file, "%15lu\t", (size_t) Pid(i));
  2886. // fprintf(file, "%15lu\n", (size_t) Mdotid(i));
  2887. fprintf(file,"%15.6e\t", psi(j));
  2888. }
  2889. fprintf(file, "\n");
  2890. fclose(file);
  2891. }