Droplet Lagrangian Transient One-dimensional Reacting Code Implementation of both liquid and gas phase governing equations.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

residue.cpp 113KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289
  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. }