PageRenderTime 53ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/enzo/oxygen_solver.C

https://bitbucket.org/devinsilvia/enzo-dengo-devin
C | 2123 lines | 1231 code | 563 blank | 329 comment | 149 complexity | b918f9adf7d459fef04598a0d7a5b104 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0
  1. /* THIS FILE HAS BEEN AUTO-GENERATED. DO NOT EDIT. */
  2. /* This is C++ code to read HDF5 files for
  3. reaction rates, cooling rates, and initial
  4. conditions for the chemical network defined
  5. by the user. In addition, this contains
  6. code for calculating temperature from the
  7. gas energy and computing the RHS and the
  8. Jacobian of the system of equations which
  9. will be fed into the solver.
  10. */
  11. #include <alloca.h>
  12. #include "oxygen_solver.h"
  13. oxygen_data *oxygen_setup_data(void) {
  14. oxygen_data *data = (oxygen_data *) malloc(sizeof(oxygen_data));
  15. data->bounds[0] = 1.0;
  16. data->bounds[1] = 1000000000000.0;
  17. data->nbins = 1024;
  18. data->dbin = (log(data->bounds[1]) - log(data->bounds[0])) / data->nbins;
  19. data->idbin = 1.0L / data->dbin;
  20. oxygen_read_rate_tables(data);
  21. fprintf(stderr, "Successfully read in rate tables.\n");
  22. oxygen_read_cooling_tables(data);
  23. fprintf(stderr, "Successfully read in cooling rate tables.\n");
  24. return data;
  25. }
  26. int oxygen_main(int argc, char** argv)
  27. {
  28. oxygen_data *data = oxygen_setup_data();
  29. /* Initial conditions */
  30. hid_t file_id = H5Fopen("oxygen_initial_conditions.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
  31. if (file_id < 0) {fprintf(stderr, "Failed to open "
  32. "oxygen_initial_conditions.h5 so dying.\n");
  33. return(1);}
  34. /* Allocate the correct number of cells */
  35. hsize_t dims; /* We have flat versus number of species */
  36. /* Check gas energy to get the number of cells */
  37. fprintf(stderr, "Getting dimensionality from ge:\n");
  38. herr_t status = H5LTget_dataset_info(file_id, "/ge", &dims, NULL, NULL);
  39. if(status == -1) {
  40. fprintf(stderr, "Error opening initial conditions file.\n");
  41. return 1;
  42. }
  43. fprintf(stderr, " ncells = % 3i\n", (int) dims);
  44. data->ncells = dims;
  45. int N = 11;
  46. double *atol, *rtol;
  47. atol = (double *) alloca(N * dims * sizeof(double));
  48. rtol = (double *) alloca(N * dims * sizeof(double));
  49. double *tics = (double *) alloca(dims * sizeof(double));
  50. double *ics = (double *) alloca(dims * N * sizeof(double));
  51. double *input = (double *) alloca(dims * N * sizeof(double));
  52. unsigned int i = 0, j;
  53. fprintf(stderr, "Reading I.C. for /ge\n");
  54. H5LTread_dataset_double(file_id, "/ge", tics);
  55. for (j = 0; j < dims; j++) {
  56. ics[j * N + i] = tics[j] / 1.0; /* Convert to number density */
  57. atol[j * N + i] = tics[j] * 1e-06;
  58. rtol[j * N + i] = 1e-06;
  59. if(j==0) {
  60. fprintf(stderr, "ge[0] = %0.3g, atol => % 0.16g\n",
  61. tics[j], atol[j]);
  62. }
  63. }
  64. i++;
  65. fprintf(stderr, "Reading I.C. for /de\n");
  66. H5LTread_dataset_double(file_id, "/de", tics);
  67. for (j = 0; j < dims; j++) {
  68. ics[j * N + i] = tics[j] / 1.0; /* Convert to number density */
  69. atol[j * N + i] = tics[j] * 1e-06;
  70. rtol[j * N + i] = 1e-06;
  71. if(j==0) {
  72. fprintf(stderr, "de[0] = %0.3g, atol => % 0.16g\n",
  73. tics[j], atol[j]);
  74. }
  75. }
  76. i++;
  77. fprintf(stderr, "Reading I.C. for /OI\n");
  78. H5LTread_dataset_double(file_id, "/OI", tics);
  79. for (j = 0; j < dims; j++) {
  80. ics[j * N + i] = tics[j] / 16; /* Convert to number density */
  81. atol[j * N + i] = tics[j] * 1e-06;
  82. rtol[j * N + i] = 1e-06;
  83. if(j==0) {
  84. fprintf(stderr, "OI[0] = %0.3g, atol => % 0.16g\n",
  85. tics[j], atol[j]);
  86. }
  87. }
  88. i++;
  89. fprintf(stderr, "Reading I.C. for /OVII\n");
  90. H5LTread_dataset_double(file_id, "/OVII", tics);
  91. for (j = 0; j < dims; j++) {
  92. ics[j * N + i] = tics[j] / 16; /* Convert to number density */
  93. atol[j * N + i] = tics[j] * 1e-06;
  94. rtol[j * N + i] = 1e-06;
  95. if(j==0) {
  96. fprintf(stderr, "OVII[0] = %0.3g, atol => % 0.16g\n",
  97. tics[j], atol[j]);
  98. }
  99. }
  100. i++;
  101. fprintf(stderr, "Reading I.C. for /OII\n");
  102. H5LTread_dataset_double(file_id, "/OII", tics);
  103. for (j = 0; j < dims; j++) {
  104. ics[j * N + i] = tics[j] / 16; /* Convert to number density */
  105. atol[j * N + i] = tics[j] * 1e-06;
  106. rtol[j * N + i] = 1e-06;
  107. if(j==0) {
  108. fprintf(stderr, "OII[0] = %0.3g, atol => % 0.16g\n",
  109. tics[j], atol[j]);
  110. }
  111. }
  112. i++;
  113. fprintf(stderr, "Reading I.C. for /OVI\n");
  114. H5LTread_dataset_double(file_id, "/OVI", tics);
  115. for (j = 0; j < dims; j++) {
  116. ics[j * N + i] = tics[j] / 16; /* Convert to number density */
  117. atol[j * N + i] = tics[j] * 1e-06;
  118. rtol[j * N + i] = 1e-06;
  119. if(j==0) {
  120. fprintf(stderr, "OVI[0] = %0.3g, atol => % 0.16g\n",
  121. tics[j], atol[j]);
  122. }
  123. }
  124. i++;
  125. fprintf(stderr, "Reading I.C. for /OIII\n");
  126. H5LTread_dataset_double(file_id, "/OIII", tics);
  127. for (j = 0; j < dims; j++) {
  128. ics[j * N + i] = tics[j] / 16; /* Convert to number density */
  129. atol[j * N + i] = tics[j] * 1e-06;
  130. rtol[j * N + i] = 1e-06;
  131. if(j==0) {
  132. fprintf(stderr, "OIII[0] = %0.3g, atol => % 0.16g\n",
  133. tics[j], atol[j]);
  134. }
  135. }
  136. i++;
  137. fprintf(stderr, "Reading I.C. for /OIV\n");
  138. H5LTread_dataset_double(file_id, "/OIV", tics);
  139. for (j = 0; j < dims; j++) {
  140. ics[j * N + i] = tics[j] / 16; /* Convert to number density */
  141. atol[j * N + i] = tics[j] * 1e-06;
  142. rtol[j * N + i] = 1e-06;
  143. if(j==0) {
  144. fprintf(stderr, "OIV[0] = %0.3g, atol => % 0.16g\n",
  145. tics[j], atol[j]);
  146. }
  147. }
  148. i++;
  149. fprintf(stderr, "Reading I.C. for /OV\n");
  150. H5LTread_dataset_double(file_id, "/OV", tics);
  151. for (j = 0; j < dims; j++) {
  152. ics[j * N + i] = tics[j] / 16; /* Convert to number density */
  153. atol[j * N + i] = tics[j] * 1e-06;
  154. rtol[j * N + i] = 1e-06;
  155. if(j==0) {
  156. fprintf(stderr, "OV[0] = %0.3g, atol => % 0.16g\n",
  157. tics[j], atol[j]);
  158. }
  159. }
  160. i++;
  161. fprintf(stderr, "Reading I.C. for /OVIII\n");
  162. H5LTread_dataset_double(file_id, "/OVIII", tics);
  163. for (j = 0; j < dims; j++) {
  164. ics[j * N + i] = tics[j] / 16; /* Convert to number density */
  165. atol[j * N + i] = tics[j] * 1e-06;
  166. rtol[j * N + i] = 1e-06;
  167. if(j==0) {
  168. fprintf(stderr, "OVIII[0] = %0.3g, atol => % 0.16g\n",
  169. tics[j], atol[j]);
  170. }
  171. }
  172. i++;
  173. fprintf(stderr, "Reading I.C. for /OIX\n");
  174. H5LTread_dataset_double(file_id, "/OIX", tics);
  175. for (j = 0; j < dims; j++) {
  176. ics[j * N + i] = tics[j] / 16; /* Convert to number density */
  177. atol[j * N + i] = tics[j] * 1e-06;
  178. rtol[j * N + i] = 1e-06;
  179. if(j==0) {
  180. fprintf(stderr, "OIX[0] = %0.3g, atol => % 0.16g\n",
  181. tics[j], atol[j]);
  182. }
  183. }
  184. i++;
  185. H5Fclose(file_id);
  186. double dtf = 2e17;
  187. double dt = -1.0;
  188. for (i = 0; i < dims * N; i++) input[i] = ics[i];
  189. double ttot;
  190. ttot = dengo_evolve_oxygen(dtf, dt, input, rtol, atol, dims, data);
  191. /* Write results to HDF5 file */
  192. file_id = H5Fcreate("oxygen_solution.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
  193. hsize_t dimsarr[1];
  194. dimsarr[0] = dims;
  195. i = 0;
  196. double ge[dims];
  197. for (j = 0; j < dims; j++) {
  198. ge[j] = input[j * N + i] * 1.0;
  199. }
  200. fprintf(stderr, "Writing solution for /ge\n");
  201. H5LTmake_dataset_double(file_id, "/ge", 1, dimsarr, ge);
  202. i++;
  203. double de[dims];
  204. for (j = 0; j < dims; j++) {
  205. de[j] = input[j * N + i] * 1.0;
  206. }
  207. fprintf(stderr, "Writing solution for /de\n");
  208. H5LTmake_dataset_double(file_id, "/de", 1, dimsarr, de);
  209. i++;
  210. double OI[dims];
  211. for (j = 0; j < dims; j++) {
  212. OI[j] = input[j * N + i] * 16;
  213. }
  214. fprintf(stderr, "Writing solution for /OI\n");
  215. H5LTmake_dataset_double(file_id, "/OI", 1, dimsarr, OI);
  216. i++;
  217. double OVII[dims];
  218. for (j = 0; j < dims; j++) {
  219. OVII[j] = input[j * N + i] * 16;
  220. }
  221. fprintf(stderr, "Writing solution for /OVII\n");
  222. H5LTmake_dataset_double(file_id, "/OVII", 1, dimsarr, OVII);
  223. i++;
  224. double OII[dims];
  225. for (j = 0; j < dims; j++) {
  226. OII[j] = input[j * N + i] * 16;
  227. }
  228. fprintf(stderr, "Writing solution for /OII\n");
  229. H5LTmake_dataset_double(file_id, "/OII", 1, dimsarr, OII);
  230. i++;
  231. double OVI[dims];
  232. for (j = 0; j < dims; j++) {
  233. OVI[j] = input[j * N + i] * 16;
  234. }
  235. fprintf(stderr, "Writing solution for /OVI\n");
  236. H5LTmake_dataset_double(file_id, "/OVI", 1, dimsarr, OVI);
  237. i++;
  238. double OIII[dims];
  239. for (j = 0; j < dims; j++) {
  240. OIII[j] = input[j * N + i] * 16;
  241. }
  242. fprintf(stderr, "Writing solution for /OIII\n");
  243. H5LTmake_dataset_double(file_id, "/OIII", 1, dimsarr, OIII);
  244. i++;
  245. double OIV[dims];
  246. for (j = 0; j < dims; j++) {
  247. OIV[j] = input[j * N + i] * 16;
  248. }
  249. fprintf(stderr, "Writing solution for /OIV\n");
  250. H5LTmake_dataset_double(file_id, "/OIV", 1, dimsarr, OIV);
  251. i++;
  252. double OV[dims];
  253. for (j = 0; j < dims; j++) {
  254. OV[j] = input[j * N + i] * 16;
  255. }
  256. fprintf(stderr, "Writing solution for /OV\n");
  257. H5LTmake_dataset_double(file_id, "/OV", 1, dimsarr, OV);
  258. i++;
  259. double OVIII[dims];
  260. for (j = 0; j < dims; j++) {
  261. OVIII[j] = input[j * N + i] * 16;
  262. }
  263. fprintf(stderr, "Writing solution for /OVIII\n");
  264. H5LTmake_dataset_double(file_id, "/OVIII", 1, dimsarr, OVIII);
  265. i++;
  266. double OIX[dims];
  267. for (j = 0; j < dims; j++) {
  268. OIX[j] = input[j * N + i] * 16;
  269. }
  270. fprintf(stderr, "Writing solution for /OIX\n");
  271. H5LTmake_dataset_double(file_id, "/OIX", 1, dimsarr, OIX);
  272. i++;
  273. double temperature[dims];
  274. for (j = 0; j < dims; j++) {
  275. temperature[j] = data->Ts[j];
  276. }
  277. H5LTmake_dataset_double(file_id, "/T", 1, dimsarr, temperature);
  278. double time[1];
  279. time[0] = ttot;
  280. double timestep[1];
  281. timestep[0] = dt;
  282. H5LTset_attribute_double(file_id, "/", "time", time, 1);
  283. H5LTset_attribute_double(file_id, "/", "timestep", timestep, 1);
  284. H5Fclose(file_id);
  285. return 0;
  286. }
  287. double dengo_evolve_oxygen (double dtf, double &dt, double *input,
  288. double *rtol, double *atol, long long dims, oxygen_data *data) {
  289. int i, j;
  290. hid_t file_id;
  291. /*fprintf(stderr, " ncells = % 3i\n", (int) dims);*/
  292. int N = 11;
  293. rhs_f f = calculate_rhs_oxygen;
  294. jac_f jf = calculate_jacobian_oxygen;
  295. if (dt < 0) dt = dtf / 1000.0;
  296. int niter = 0;
  297. int siter = 0;
  298. double ttot = 0;
  299. double *scale = (double *) alloca(dims * N * sizeof(double));
  300. double *prev = (double *) alloca(dims * N * sizeof(double));
  301. for (i = 0; i < dims * N; i++) scale[i] = 1.0;
  302. for (i = 0; i < dims * N; i++) prev[i] = input[i];
  303. double *u0 = (double *) alloca(N*dims*sizeof(double));
  304. double *s = (double *) alloca(N*sizeof(double));
  305. double *gu = (double *) alloca(N*dims*sizeof(double));
  306. double *Ju = (double *) alloca(N*N*dims*sizeof(double));
  307. double floor_value = 1e-25;
  308. double pssum, issum, sumdiff;
  309. int snum;
  310. int relaxed0 = 0;
  311. int relaxed1 = 0;
  312. int relaxed2 = 0;
  313. int maxspeciesi;
  314. double maxspeciesval;
  315. /*
  316. for (i = 0; i < dims * N; i++) {
  317. fprintf(stderr, "rtol[%d] = %0.5g \n", i, rtol[i]);
  318. }
  319. */
  320. while (ttot < dtf) {
  321. int rv = BE_chem_solve(f, jf, input, dt, rtol, atol, dims, N,
  322. scale, (void *) data, u0, s, gu, Ju);
  323. /*
  324. fprintf(stderr, "Return value [%d]: %i. %0.5g / %0.5g = %0.5g (%0.5g)\n",
  325. niter, rv, ttot, dtf, ttot/dtf, dt);
  326. fprintf(stderr, "Value[80] = %0.5g %0.5g %0.5g\n",
  327. input[80], prev[80]);//, ics[80]);
  328. */
  329. for (i = 0; i < dims * N; i++) {
  330. if (input[i] < 0) {
  331. rv = 1;
  332. //fprintf(stderr, "rv = 1, input[%d] = %0.5g\n", i, input[i]);
  333. break;
  334. }
  335. }
  336. if (rv == 0) {
  337. if (siter == 99999999) {
  338. fprintf(stderr, "Hit maximum number of successful iterations allowed.\n");
  339. break;
  340. }
  341. siter++;
  342. if (siter % 100000 == 0) {
  343. fprintf(stderr, "Successful Iteration[%d]: (%0.4g) %0.6g / %0.6g = %0.6g \n",
  344. siter, dt, ttot, dtf, ttot/dtf);
  345. }
  346. ttot += dt;
  347. dt = DMIN(dt * 1.1, dtf - ttot);
  348. if (dt/dtf > 1e-9 && relaxed2 == 1) {
  349. relaxed2 = 0;
  350. for (i = 0; i < dims * N; i++) rtol[i] *= 0.2;
  351. }
  352. if (dt/dtf > 1e-6 && relaxed1 == 1) {
  353. relaxed1 = 0;
  354. for (i = 0; i < dims * N; i++) rtol[i] *= 0.1;
  355. }
  356. if (dt/dtf > 1e-3 && relaxed0 == 1) {
  357. relaxed0 = 0;
  358. for (i = 0; i < dims * N; i++) rtol[i] *= 0.1;
  359. }
  360. for (i = 0; i < dims * N; i++) prev[i] = input[i];
  361. for (i = 0; i < dims * N; i++) {
  362. if (input[i] < floor_value)
  363. input[i] = floor_value; //Do I need to worry about conservation of species
  364. //here? dealt with below (maybe)
  365. }
  366. pssum = 0.0;
  367. issum = 0.0;
  368. maxspeciesval = 0.0;
  369. maxspeciesi = -1;
  370. for (i = 0; i < dims * N; i++) { //this conservation check method only works
  371. //if solving one cell at a time
  372. snum = i % N;
  373. if (snum == 0) continue;
  374. if (snum == 1) {
  375. input[i] = prev[i]; //we need to make sure electrons aren't floored
  376. //or everything gets weird (I think)
  377. continue;
  378. }
  379. if (prev[i] > maxspeciesval) { //which species is largest?
  380. maxspeciesval = prev[i];
  381. maxspeciesi = i;
  382. }
  383. pssum += prev[i];
  384. issum += input[i];
  385. if (snum == (N - 1)) {
  386. sumdiff = issum - pssum; //how much extra species density did we
  387. //generate by flooring?
  388. if (sumdiff > 0.0) {
  389. //fprintf(stderr, "The amount of extra species generated by flooring values was: %0.5g, max species = %d\n", sumdiff, maxspeciesi);
  390. input[maxspeciesi] -= sumdiff; // to maintain conservation, take it out of
  391. //the most abundant ion (ONLY WORKS IF THERE IS A
  392. //SINGLE ELEMENT)
  393. }
  394. pssum = 0.0; // at end, reset
  395. issum = 0.0; // at end, reset
  396. }
  397. }
  398. } else {
  399. dt /= 2.0;
  400. if (dt/dtf < 1e-6 && relaxed0 == 0) {
  401. relaxed0 = 1;
  402. for (i = 0; i < dims * N; i++) rtol[i] *= 10.0;
  403. }
  404. if (dt/dtf < 1e-9 && relaxed1 == 0) {
  405. relaxed1 = 1;
  406. for (i = 0; i < dims * N; i++) rtol[i] *= 10.0;
  407. }
  408. if (dt/dtf < 1e-12 && relaxed2 == 0) {
  409. relaxed2 = 1;
  410. for (i = 0; i < dims * N; i++) rtol[i] *= 5.0;
  411. }
  412. for (i = 0; i < dims * N; i++) input[i] = prev[i];
  413. if (dt/dtf < 1e-15) {
  414. fprintf(stderr, "Dying! dt/dtf = %0.5g\n", dt/dtf);
  415. break;
  416. }
  417. }
  418. niter++;
  419. }
  420. /*fprintf(stderr, "End: %0.5g / %0.5g (%0.5g)\n",
  421. ttot, dtf, dtf-ttot);*/
  422. return ttot;
  423. }
  424. void oxygen_read_rate_tables(oxygen_data *data)
  425. {
  426. hid_t file_id = H5Fopen("oxygen_tables.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
  427. /* Allocate the correct number of rate tables */
  428. H5LTread_dataset_double(file_id, "/OI_i", data->r_OI_i);
  429. H5LTread_dataset_double(file_id, "/OII_i", data->r_OII_i);
  430. H5LTread_dataset_double(file_id, "/OII_r", data->r_OII_r);
  431. H5LTread_dataset_double(file_id, "/OIII_i", data->r_OIII_i);
  432. H5LTread_dataset_double(file_id, "/OIII_r", data->r_OIII_r);
  433. H5LTread_dataset_double(file_id, "/OIV_i", data->r_OIV_i);
  434. H5LTread_dataset_double(file_id, "/OIV_r", data->r_OIV_r);
  435. H5LTread_dataset_double(file_id, "/OIX_r", data->r_OIX_r);
  436. H5LTread_dataset_double(file_id, "/OV_i", data->r_OV_i);
  437. H5LTread_dataset_double(file_id, "/OV_r", data->r_OV_r);
  438. H5LTread_dataset_double(file_id, "/OVI_i", data->r_OVI_i);
  439. H5LTread_dataset_double(file_id, "/OVI_r", data->r_OVI_r);
  440. H5LTread_dataset_double(file_id, "/OVII_i", data->r_OVII_i);
  441. H5LTread_dataset_double(file_id, "/OVII_r", data->r_OVII_r);
  442. H5LTread_dataset_double(file_id, "/OVIII_i", data->r_OVIII_i);
  443. H5LTread_dataset_double(file_id, "/OVIII_r", data->r_OVIII_r);
  444. H5Fclose(file_id);
  445. }
  446. void oxygen_read_cooling_tables(oxygen_data *data)
  447. {
  448. hid_t file_id = H5Fopen("oxygen_tables.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
  449. /* Allocate the correct number of rate tables */
  450. H5Fclose(file_id);
  451. }
  452. void oxygen_calculate_temperature(oxygen_data *data,
  453. double *input, int nstrip, int nchem)
  454. {
  455. int i, j;
  456. double density;
  457. double kb = 1.3806504e-16; // Boltzmann constant [erg/K]
  458. double mh = 1.67e-24;
  459. double gamma = 5.e0/3.e0;
  460. /* Calculate total density */
  461. double ge;
  462. double de;
  463. double OI;
  464. double OVII;
  465. double OII;
  466. double OVI;
  467. double OIII;
  468. double OIV;
  469. double OV;
  470. double OVIII;
  471. double OIX;
  472. for (i = 0; i<nstrip; i++) {
  473. j = i * nchem;
  474. ge = input[j];
  475. /*fprintf(stderr, "ge[%d] = % 0.16g\n",
  476. i, ge);*/
  477. j++;
  478. de = input[j];
  479. /*fprintf(stderr, "de[%d] = % 0.16g\n",
  480. i, de);*/
  481. j++;
  482. OI = input[j];
  483. /*fprintf(stderr, "OI[%d] = % 0.16g\n",
  484. i, OI);*/
  485. j++;
  486. OVII = input[j];
  487. /*fprintf(stderr, "OVII[%d] = % 0.16g\n",
  488. i, OVII);*/
  489. j++;
  490. OII = input[j];
  491. /*fprintf(stderr, "OII[%d] = % 0.16g\n",
  492. i, OII);*/
  493. j++;
  494. OVI = input[j];
  495. /*fprintf(stderr, "OVI[%d] = % 0.16g\n",
  496. i, OVI);*/
  497. j++;
  498. OIII = input[j];
  499. /*fprintf(stderr, "OIII[%d] = % 0.16g\n",
  500. i, OIII);*/
  501. j++;
  502. OIV = input[j];
  503. /*fprintf(stderr, "OIV[%d] = % 0.16g\n",
  504. i, OIV);*/
  505. j++;
  506. OV = input[j];
  507. /*fprintf(stderr, "OV[%d] = % 0.16g\n",
  508. i, OV);*/
  509. j++;
  510. OVIII = input[j];
  511. /*fprintf(stderr, "OVIII[%d] = % 0.16g\n",
  512. i, OVIII);*/
  513. j++;
  514. OIX = input[j];
  515. /*fprintf(stderr, "OIX[%d] = % 0.16g\n",
  516. i, OIX);*/
  517. j++;
  518. // density = 16*OI + 16*OII + 16*OIII + 16*OIV + 16*OIX + 16*OV + 16*OVI + 16*OVII + 16*OVIII;
  519. /*density = (OI + OII + OIII + OIV + OIX + OV + OVI + OVII + OVIII) * 1e5;
  520. data->Ts[i] = density*ge*mh/(kb*((OI/(gamma - 1.0) + OII/(gamma - 1.0) + OIII/(gamma - 1.0) + OIV/(gamma - 1.0) + OIX/(gamma - 1.0) + OV/(gamma - 1.0) + OVI/(gamma - 1.0) + OVII/(gamma - 1.0) + OVIII/(gamma - 1.0))*1e5));// + de/(gamma - 1.0)))*1e5);
  521. data->Ts[i] *= 0.6;*/
  522. data->Ts[i] = ((gamma - 1.0) * 0.6 * mh * ge) / kb; // THIS IS A HACK, BUT IT WILL WORK FOR NOW
  523. if (data->Ts[i] < data->bounds[0]) {
  524. data->Ts[i] = data->bounds[0];
  525. } else if (data->Ts[i] > data->bounds[1]) {
  526. data->Ts[i] = data->bounds[1];
  527. }
  528. data->logTs[i] = log(data->Ts[i]);
  529. /* data->dTs_ge[i] = density*mh/(kb*((OI/(gamma - 1.0) + OII/(gamma - 1.0) + OIII/(gamma - 1.0) + OIV/(gamma - 1.0) + OIX/(gamma - 1.0) + OV/(gamma - 1.0) + OVI/(gamma - 1.0) + OVII/(gamma - 1.0) + OVIII/(gamma - 1.0))*1e5));// + de/(gamma - 1.0)))*1e5);
  530. data->dTs_ge[i] *= 0.6;*/
  531. data->dTs_ge[i] = ((gamma - 1.0) * 0.6 * mh) / kb; // THIS IS A HACK, BUT IT WILL WORK FOR NOW
  532. /*fprintf(stderr, "T[%d] = % 0.16g, density = % 0.16g, ge = % 0.16g \n",
  533. i, data->Ts[i], density, ge);*/
  534. }
  535. }
  536. /*
  537. This setup may be different than the user may anticipate, as a result
  538. of the lockstep timestep we use for a pencil beam through the grid.
  539. As such, it accepts the number of things to interpolate and makes
  540. assumptions about the sizes of the rates.
  541. */
  542. /* This also requires no templating other than for the solver name...*/
  543. void oxygen_interpolate_rates(oxygen_data *data,
  544. int nstrip)
  545. {
  546. int i, bin_id;
  547. double lb, t1, t2;
  548. lb = log(data->bounds[0]);
  549. /*fprintf(stderr, "lb = % 0.16g, ub = % 0.16g\n", lb, ub);*/
  550. for (i = 0; i < nstrip; i++) {
  551. data->bin_id[i] = bin_id = (int) (data->idbin * (data->logTs[i] - lb));
  552. if (data->bin_id[i] <= 0) {
  553. data->bin_id[i] = 1;
  554. } else if (data->bin_id[i] >= data->nbins) {
  555. data->bin_id[i] = data->nbins - 1;
  556. }
  557. t1 = (lb + (bin_id - 1) * data->dbin);
  558. t2 = (lb + (bin_id ) * data->dbin);
  559. data->Tdef[i] = (data->logTs[i] - t1)/(t2 - t1);
  560. data->dT[i] = (t2 - t1);
  561. /*fprintf(stderr, "INTERP: %d, bin_id = %d, dT = % 0.16g, T = % 0.16g, logT = % 0.16g\n",
  562. i, data->bin_id[i], data->dT[i], data->Ts[i],
  563. data->logTs[i]);*/
  564. }
  565. for (i = 0; i < nstrip; i++) {
  566. bin_id = data->bin_id[i];
  567. data->rs_OI_i[i] = data->r_OI_i[bin_id] +
  568. data->Tdef[i] * (data->r_OI_i[bin_id+1] - data->r_OI_i[bin_id]);
  569. data->drs_OI_i[i] = (data->r_OI_i[bin_id+1] - data->r_OI_i[bin_id]);
  570. data->drs_OI_i[i] /= data->dT[i];
  571. data->drs_OI_i[i] /= data->Ts[i];
  572. }
  573. for (i = 0; i < nstrip; i++) {
  574. bin_id = data->bin_id[i];
  575. data->rs_OII_i[i] = data->r_OII_i[bin_id] +
  576. data->Tdef[i] * (data->r_OII_i[bin_id+1] - data->r_OII_i[bin_id]);
  577. data->drs_OII_i[i] = (data->r_OII_i[bin_id+1] - data->r_OII_i[bin_id]);
  578. data->drs_OII_i[i] /= data->dT[i];
  579. data->drs_OII_i[i] /= data->Ts[i];
  580. }
  581. for (i = 0; i < nstrip; i++) {
  582. bin_id = data->bin_id[i];
  583. data->rs_OII_r[i] = data->r_OII_r[bin_id] +
  584. data->Tdef[i] * (data->r_OII_r[bin_id+1] - data->r_OII_r[bin_id]);
  585. data->drs_OII_r[i] = (data->r_OII_r[bin_id+1] - data->r_OII_r[bin_id]);
  586. data->drs_OII_r[i] /= data->dT[i];
  587. data->drs_OII_r[i] /= data->Ts[i];
  588. }
  589. for (i = 0; i < nstrip; i++) {
  590. bin_id = data->bin_id[i];
  591. data->rs_OIII_i[i] = data->r_OIII_i[bin_id] +
  592. data->Tdef[i] * (data->r_OIII_i[bin_id+1] - data->r_OIII_i[bin_id]);
  593. data->drs_OIII_i[i] = (data->r_OIII_i[bin_id+1] - data->r_OIII_i[bin_id]);
  594. data->drs_OIII_i[i] /= data->dT[i];
  595. data->drs_OIII_i[i] /= data->Ts[i];
  596. }
  597. for (i = 0; i < nstrip; i++) {
  598. bin_id = data->bin_id[i];
  599. data->rs_OIII_r[i] = data->r_OIII_r[bin_id] +
  600. data->Tdef[i] * (data->r_OIII_r[bin_id+1] - data->r_OIII_r[bin_id]);
  601. data->drs_OIII_r[i] = (data->r_OIII_r[bin_id+1] - data->r_OIII_r[bin_id]);
  602. data->drs_OIII_r[i] /= data->dT[i];
  603. data->drs_OIII_r[i] /= data->Ts[i];
  604. }
  605. for (i = 0; i < nstrip; i++) {
  606. bin_id = data->bin_id[i];
  607. data->rs_OIV_i[i] = data->r_OIV_i[bin_id] +
  608. data->Tdef[i] * (data->r_OIV_i[bin_id+1] - data->r_OIV_i[bin_id]);
  609. data->drs_OIV_i[i] = (data->r_OIV_i[bin_id+1] - data->r_OIV_i[bin_id]);
  610. data->drs_OIV_i[i] /= data->dT[i];
  611. data->drs_OIV_i[i] /= data->Ts[i];
  612. }
  613. for (i = 0; i < nstrip; i++) {
  614. bin_id = data->bin_id[i];
  615. data->rs_OIV_r[i] = data->r_OIV_r[bin_id] +
  616. data->Tdef[i] * (data->r_OIV_r[bin_id+1] - data->r_OIV_r[bin_id]);
  617. data->drs_OIV_r[i] = (data->r_OIV_r[bin_id+1] - data->r_OIV_r[bin_id]);
  618. data->drs_OIV_r[i] /= data->dT[i];
  619. data->drs_OIV_r[i] /= data->Ts[i];
  620. }
  621. for (i = 0; i < nstrip; i++) {
  622. bin_id = data->bin_id[i];
  623. data->rs_OIX_r[i] = data->r_OIX_r[bin_id] +
  624. data->Tdef[i] * (data->r_OIX_r[bin_id+1] - data->r_OIX_r[bin_id]);
  625. data->drs_OIX_r[i] = (data->r_OIX_r[bin_id+1] - data->r_OIX_r[bin_id]);
  626. data->drs_OIX_r[i] /= data->dT[i];
  627. data->drs_OIX_r[i] /= data->Ts[i];
  628. }
  629. for (i = 0; i < nstrip; i++) {
  630. bin_id = data->bin_id[i];
  631. data->rs_OV_i[i] = data->r_OV_i[bin_id] +
  632. data->Tdef[i] * (data->r_OV_i[bin_id+1] - data->r_OV_i[bin_id]);
  633. data->drs_OV_i[i] = (data->r_OV_i[bin_id+1] - data->r_OV_i[bin_id]);
  634. data->drs_OV_i[i] /= data->dT[i];
  635. data->drs_OV_i[i] /= data->Ts[i];
  636. }
  637. for (i = 0; i < nstrip; i++) {
  638. bin_id = data->bin_id[i];
  639. data->rs_OV_r[i] = data->r_OV_r[bin_id] +
  640. data->Tdef[i] * (data->r_OV_r[bin_id+1] - data->r_OV_r[bin_id]);
  641. data->drs_OV_r[i] = (data->r_OV_r[bin_id+1] - data->r_OV_r[bin_id]);
  642. data->drs_OV_r[i] /= data->dT[i];
  643. data->drs_OV_r[i] /= data->Ts[i];
  644. }
  645. for (i = 0; i < nstrip; i++) {
  646. bin_id = data->bin_id[i];
  647. data->rs_OVI_i[i] = data->r_OVI_i[bin_id] +
  648. data->Tdef[i] * (data->r_OVI_i[bin_id+1] - data->r_OVI_i[bin_id]);
  649. data->drs_OVI_i[i] = (data->r_OVI_i[bin_id+1] - data->r_OVI_i[bin_id]);
  650. data->drs_OVI_i[i] /= data->dT[i];
  651. data->drs_OVI_i[i] /= data->Ts[i];
  652. }
  653. for (i = 0; i < nstrip; i++) {
  654. bin_id = data->bin_id[i];
  655. data->rs_OVI_r[i] = data->r_OVI_r[bin_id] +
  656. data->Tdef[i] * (data->r_OVI_r[bin_id+1] - data->r_OVI_r[bin_id]);
  657. data->drs_OVI_r[i] = (data->r_OVI_r[bin_id+1] - data->r_OVI_r[bin_id]);
  658. data->drs_OVI_r[i] /= data->dT[i];
  659. data->drs_OVI_r[i] /= data->Ts[i];
  660. }
  661. for (i = 0; i < nstrip; i++) {
  662. bin_id = data->bin_id[i];
  663. data->rs_OVII_i[i] = data->r_OVII_i[bin_id] +
  664. data->Tdef[i] * (data->r_OVII_i[bin_id+1] - data->r_OVII_i[bin_id]);
  665. data->drs_OVII_i[i] = (data->r_OVII_i[bin_id+1] - data->r_OVII_i[bin_id]);
  666. data->drs_OVII_i[i] /= data->dT[i];
  667. data->drs_OVII_i[i] /= data->Ts[i];
  668. }
  669. for (i = 0; i < nstrip; i++) {
  670. bin_id = data->bin_id[i];
  671. data->rs_OVII_r[i] = data->r_OVII_r[bin_id] +
  672. data->Tdef[i] * (data->r_OVII_r[bin_id+1] - data->r_OVII_r[bin_id]);
  673. data->drs_OVII_r[i] = (data->r_OVII_r[bin_id+1] - data->r_OVII_r[bin_id]);
  674. data->drs_OVII_r[i] /= data->dT[i];
  675. data->drs_OVII_r[i] /= data->Ts[i];
  676. }
  677. for (i = 0; i < nstrip; i++) {
  678. bin_id = data->bin_id[i];
  679. data->rs_OVIII_i[i] = data->r_OVIII_i[bin_id] +
  680. data->Tdef[i] * (data->r_OVIII_i[bin_id+1] - data->r_OVIII_i[bin_id]);
  681. data->drs_OVIII_i[i] = (data->r_OVIII_i[bin_id+1] - data->r_OVIII_i[bin_id]);
  682. data->drs_OVIII_i[i] /= data->dT[i];
  683. data->drs_OVIII_i[i] /= data->Ts[i];
  684. }
  685. for (i = 0; i < nstrip; i++) {
  686. bin_id = data->bin_id[i];
  687. data->rs_OVIII_r[i] = data->r_OVIII_r[bin_id] +
  688. data->Tdef[i] * (data->r_OVIII_r[bin_id+1] - data->r_OVIII_r[bin_id]);
  689. data->drs_OVIII_r[i] = (data->r_OVIII_r[bin_id+1] - data->r_OVIII_r[bin_id]);
  690. data->drs_OVIII_r[i] /= data->dT[i];
  691. data->drs_OVIII_r[i] /= data->Ts[i];
  692. }
  693. }
  694. int calculate_rhs_oxygen(double *input, double *rhs, int nstrip,
  695. int nchem, void *sdata)
  696. {
  697. /* We iterate over all of the rates */
  698. /* Calculate temperature first */
  699. oxygen_data *data = (oxygen_data*)sdata;
  700. int i, j;
  701. oxygen_calculate_temperature(data, input, nstrip, nchem);
  702. oxygen_interpolate_rates(data, nstrip);
  703. /* Now we set up some temporaries */
  704. //double *T = data->Ts;
  705. double *OI_i = data->rs_OI_i;
  706. double *OII_i = data->rs_OII_i;
  707. double *OII_r = data->rs_OII_r;
  708. double *OIII_i = data->rs_OIII_i;
  709. double *OIII_r = data->rs_OIII_r;
  710. double *OIV_i = data->rs_OIV_i;
  711. double *OIV_r = data->rs_OIV_r;
  712. double *OIX_r = data->rs_OIX_r;
  713. double *OV_i = data->rs_OV_i;
  714. double *OV_r = data->rs_OV_r;
  715. double *OVI_i = data->rs_OVI_i;
  716. double *OVI_r = data->rs_OVI_r;
  717. double *OVII_i = data->rs_OVII_i;
  718. double *OVII_r = data->rs_OVII_r;
  719. double *OVIII_i = data->rs_OVIII_i;
  720. double *OVIII_r = data->rs_OVIII_r;
  721. double ge;
  722. double de;
  723. double OI;
  724. double OVII;
  725. double OII;
  726. double OVI;
  727. double OIII;
  728. double OIV;
  729. double OV;
  730. double OVIII;
  731. double OIX;
  732. double mh = 1.67e-24;
  733. double total, total_e, total_de, mdensity;
  734. double floor_value = 1e-25; //this should probably be globally stored
  735. int is_floored[nchem];
  736. for (i = 0; i<nstrip; i++) {
  737. //fprintf(stderr, "T = %0.5g\n", T[i]);
  738. for (int s = 0; s < nchem; s++)
  739. is_floored[s] = 0;
  740. j = i * nchem;
  741. total = total_e = total_de = mdensity = 0.0;
  742. ge = input[j];
  743. if (ge < 0.0) {
  744. //fprintf(stderr, "RNegative[%d][ge] = % 0.16g [%d]\n",
  745. // i, ge, j);
  746. return 1;
  747. ge = 1e-20;
  748. }
  749. if (ge <= floor_value) {
  750. is_floored[j % nchem] = 1;
  751. }
  752. j++;
  753. de = input[j];
  754. if (de < 0.0) {
  755. //fprintf(stderr, "RNegative[%d][de] = % 0.16g [%d]\n",
  756. // i, de, j);
  757. return 1;
  758. de = 1e-20;
  759. }
  760. if (de <= floor_value) {
  761. is_floored[j % nchem] = 1;
  762. }
  763. j++;
  764. OI = input[j];
  765. if (OI < 0.0) {
  766. //fprintf(stderr, "RNegative[%d][OI] = % 0.16g [%d]\n",
  767. // i, OI, j);
  768. return 1;
  769. OI = 1e-20;
  770. }
  771. if (OI <= floor_value) {
  772. is_floored[j % nchem] = 1;
  773. }
  774. total+=OI * 16;
  775. j++;
  776. OVII = input[j];
  777. if (OVII < 0.0) {
  778. //fprintf(stderr, "RNegative[%d][OVII] = % 0.16g [%d]\n",
  779. // i, OVII, j);
  780. return 1;
  781. OVII = 1e-20;
  782. }
  783. if (OVII <= floor_value) {
  784. is_floored[j % nchem] = 1;
  785. }
  786. total+=OVII * 16;
  787. j++;
  788. OII = input[j];
  789. if (OII < 0.0) {
  790. //fprintf(stderr, "RNegative[%d][OII] = % 0.16g [%d]\n",
  791. // i, OII, j);
  792. return 1;
  793. OII = 1e-20;
  794. }
  795. if (OII <= floor_value) {
  796. is_floored[j % nchem] = 1;
  797. }
  798. total+=OII * 16;
  799. j++;
  800. OVI = input[j];
  801. if (OVI < 0.0) {
  802. //fprintf(stderr, "RNegative[%d][OVI] = % 0.16g [%d]\n",
  803. // i, OVI, j);
  804. return 1;
  805. OVI = 1e-20;
  806. }
  807. if (OVI <= floor_value) {
  808. is_floored[j % nchem] = 1;
  809. }
  810. total+=OVI * 16;
  811. j++;
  812. OIII = input[j];
  813. if (OIII < 0.0) {
  814. //fprintf(stderr, "RNegative[%d][OIII] = % 0.16g [%d]\n",
  815. // i, OIII, j);
  816. return 1;
  817. OIII = 1e-20;
  818. }
  819. if (OIII <= floor_value) {
  820. is_floored[j % nchem] = 1;
  821. }
  822. total+=OIII * 16;
  823. j++;
  824. OIV = input[j];
  825. if (OIV < 0.0) {
  826. //fprintf(stderr, "RNegative[%d][OIV] = % 0.16g [%d]\n",
  827. // i, OIV, j);
  828. return 1;
  829. OIV = 1e-20;
  830. }
  831. if (OIV <= floor_value) {
  832. is_floored[j % nchem] = 1;
  833. }
  834. total+=OIV * 16;
  835. j++;
  836. OV = input[j];
  837. if (OV < 0.0) {
  838. //fprintf(stderr, "RNegative[%d][OV] = % 0.16g [%d]\n",
  839. // i, OV, j);
  840. return 1;
  841. OV = 1e-20;
  842. }
  843. if (OV <= floor_value) {
  844. is_floored[j % nchem] = 1;
  845. }
  846. total+=OV * 16;
  847. j++;
  848. OVIII = input[j];
  849. if (OVIII < 0.0) {
  850. //fprintf(stderr, "RNegative[%d][OVIII] = % 0.16g [%d]\n",
  851. // i, OVIII, j);
  852. return 1;
  853. OVIII = 1e-20;
  854. }
  855. if (OVIII <= floor_value) {
  856. is_floored[j % nchem] = 1;
  857. }
  858. total+=OVIII * 16;
  859. j++;
  860. OIX = input[j];
  861. if (OIX < 0.0) {
  862. //fprintf(stderr, "RNegative[%d][OIX] = % 0.16g [%d]\n",
  863. // i, OIX, j);
  864. return 1;
  865. OIX = 1e-20;
  866. }
  867. if (OIX <= floor_value) {
  868. is_floored[j % nchem] = 1;
  869. }
  870. total+=OIX * 16;
  871. j++;
  872. mdensity = total * mh;
  873. total = 0.0;
  874. j = i * nchem;
  875. //
  876. // Species: ge
  877. //
  878. rhs[j] = 0.0;
  879. //rhs[j] /= mdensity;
  880. j++;
  881. //
  882. // Species: de
  883. //
  884. rhs[j] = OIII_i[i]*OIII*de - OIII_r[i]*OIII*de + OII_i[i]*OII*de - OII_r[i]*OII*de + OIV_i[i]*OIV*de - OIV_r[i]*OIV*de - OIX_r[i]*OIX*de + OI_i[i]*OI*de + OVIII_i[i]*OVIII*de - OVIII_r[i]*OVIII*de + OVII_i[i]*OVII*de - OVII_r[i]*OVII*de + OVI_i[i]*OVI*de - OVI_r[i]*OVI*de + OV_i[i]*OV*de - OV_r[i]*OV*de;
  885. total_de += -rhs[j];
  886. j++;
  887. //
  888. // Species: OI
  889. //
  890. rhs[j] = OII_r[i]*OII*de - OI_i[i]*OI*de;
  891. /* Already in number density, not mass density */
  892. total += rhs[j] * 16;
  893. total_e += OI * 0;
  894. total_de += rhs[j] * 0;
  895. j++;
  896. //
  897. // Species: OVII
  898. //
  899. rhs[j] = OVIII_r[i]*OVIII*de - OVII_i[i]*OVII*de - OVII_r[i]*OVII*de + OVI_i[i]*OVI*de;
  900. /* Already in number density, not mass density */
  901. total += rhs[j] * 16;
  902. total_e += OVII * 6;
  903. total_de += rhs[j] * 6;
  904. j++;
  905. //
  906. // Species: OII
  907. //
  908. rhs[j] = OIII_r[i]*OIII*de - OII_i[i]*OII*de - OII_r[i]*OII*de + OI_i[i]*OI*de;
  909. /* Already in number density, not mass density */
  910. total += rhs[j] * 16;
  911. total_e += OII * 1;
  912. total_de += rhs[j] * 1;
  913. j++;
  914. //
  915. // Species: OVI
  916. //
  917. rhs[j] = OVII_r[i]*OVII*de - OVI_i[i]*OVI*de - OVI_r[i]*OVI*de + OV_i[i]*OV*de;
  918. /* Already in number density, not mass density */
  919. total += rhs[j] * 16;
  920. total_e += OVI * 5;
  921. total_de += rhs[j] * 5;
  922. j++;
  923. //
  924. // Species: OIII
  925. //
  926. rhs[j] = -OIII_i[i]*OIII*de - OIII_r[i]*OIII*de + OII_i[i]*OII*de + OIV_r[i]*OIV*de;
  927. /* Already in number density, not mass density */
  928. total += rhs[j] * 16;
  929. total_e += OIII * 2;
  930. total_de += rhs[j] * 2;
  931. j++;
  932. //
  933. // Species: OIV
  934. //
  935. rhs[j] = OIII_i[i]*OIII*de - OIV_i[i]*OIV*de - OIV_r[i]*OIV*de + OV_r[i]*OV*de;
  936. /* Already in number density, not mass density */
  937. total += rhs[j] * 16;
  938. total_e += OIV * 3;
  939. total_de += rhs[j] * 3;
  940. j++;
  941. //
  942. // Species: OV
  943. //
  944. rhs[j] = OIV_i[i]*OIV*de + OVI_r[i]*OVI*de - OV_i[i]*OV*de - OV_r[i]*OV*de;
  945. /* Already in number density, not mass density */
  946. total += rhs[j] * 16;
  947. total_e += OV * 4;
  948. total_de += rhs[j] * 4;
  949. j++;
  950. //
  951. // Species: OVIII
  952. //
  953. rhs[j] = OIX_r[i]*OIX*de - OVIII_i[i]*OVIII*de - OVIII_r[i]*OVIII*de + OVII_i[i]*OVII*de;
  954. /* Already in number density, not mass density */
  955. total += rhs[j] * 16;
  956. total_e += OVIII * 7;
  957. total_de += rhs[j] * 7;
  958. j++;
  959. //
  960. // Species: OIX
  961. //
  962. rhs[j] = -OIX_r[i]*OIX*de + OVIII_i[i]*OVIII*de;
  963. /* Already in number density, not mass density */
  964. total += rhs[j] * 16;
  965. total_e += OIX * 8;
  966. total_de += rhs[j] * 8;
  967. j++;
  968. }
  969. return 0;
  970. }
  971. int calculate_jacobian_oxygen(double *input, double *Joutput,
  972. int nstrip, int nchem, void *sdata)
  973. {
  974. /* We iterate over all of the rates */
  975. /* Calculate temperature first */
  976. oxygen_data *data = (oxygen_data*)sdata;
  977. int i, j;
  978. oxygen_calculate_temperature(data, input, nstrip, nchem);
  979. oxygen_interpolate_rates(data, nstrip);
  980. /* Now we set up some temporaries */
  981. double *Tge = data->dTs_ge;
  982. double *OI_i = data->rs_OI_i;
  983. double *rOI_i = data->drs_OI_i;
  984. double *OII_i = data->rs_OII_i;
  985. double *rOII_i = data->drs_OII_i;
  986. double *OII_r = data->rs_OII_r;
  987. double *rOII_r = data->drs_OII_r;
  988. double *OIII_i = data->rs_OIII_i;
  989. double *rOIII_i = data->drs_OIII_i;
  990. double *OIII_r = data->rs_OIII_r;
  991. double *rOIII_r = data->drs_OIII_r;
  992. double *OIV_i = data->rs_OIV_i;
  993. double *rOIV_i = data->drs_OIV_i;
  994. double *OIV_r = data->rs_OIV_r;
  995. double *rOIV_r = data->drs_OIV_r;
  996. double *OIX_r = data->rs_OIX_r;
  997. double *rOIX_r = data->drs_OIX_r;
  998. double *OV_i = data->rs_OV_i;
  999. double *rOV_i = data->drs_OV_i;
  1000. double *OV_r = data->rs_OV_r;
  1001. double *rOV_r = data->drs_OV_r;
  1002. double *OVI_i = data->rs_OVI_i;
  1003. double *rOVI_i = data->drs_OVI_i;
  1004. double *OVI_r = data->rs_OVI_r;
  1005. double *rOVI_r = data->drs_OVI_r;
  1006. double *OVII_i = data->rs_OVII_i;
  1007. double *rOVII_i = data->drs_OVII_i;
  1008. double *OVII_r = data->rs_OVII_r;
  1009. double *rOVII_r = data->drs_OVII_r;
  1010. double *OVIII_i = data->rs_OVIII_i;
  1011. double *rOVIII_i = data->drs_OVIII_i;
  1012. double *OVIII_r = data->rs_OVIII_r;
  1013. double *rOVIII_r = data->drs_OVIII_r;
  1014. double ge;
  1015. double de;
  1016. double OI;
  1017. double OVII;
  1018. double OII;
  1019. double OVI;
  1020. double OIII;
  1021. double OIV;
  1022. double OV;
  1023. double OVIII;
  1024. double OIX;
  1025. double mh = 1.67e-24;
  1026. double total, mdensity;
  1027. for (i = 0; i<nstrip; i++) {
  1028. j = i * nchem;
  1029. total = mdensity = 0.0;
  1030. ge = input[j];
  1031. if (ge < 0.0) {
  1032. fprintf(stderr, "JNegative[%d][ge] = % 0.16g [%d]\n",
  1033. i, ge, j);
  1034. /*ge = 0.0;*/
  1035. ge = 1e-20;
  1036. return 1;
  1037. }
  1038. j++;
  1039. de = input[j];
  1040. if (de < 0.0) {
  1041. fprintf(stderr, "JNegative[%d][de] = % 0.16g [%d]\n",
  1042. i, de, j);
  1043. /*de = 0.0;*/
  1044. de = 1e-20;
  1045. return 1;
  1046. }
  1047. j++;
  1048. OI = input[j];
  1049. if (OI < 0.0) {
  1050. fprintf(stderr, "JNegative[%d][OI] = % 0.16g [%d]\n",
  1051. i, OI, j);
  1052. /*OI = 0.0;*/
  1053. OI = 1e-20;
  1054. return 1;
  1055. }
  1056. total+=OI * 16;
  1057. j++;
  1058. OVII = input[j];
  1059. if (OVII < 0.0) {
  1060. fprintf(stderr, "JNegative[%d][OVII] = % 0.16g [%d]\n",
  1061. i, OVII, j);
  1062. /*OVII = 0.0;*/
  1063. OVII = 1e-20;
  1064. return 1;
  1065. }
  1066. total+=OVII * 16;
  1067. j++;
  1068. OII = input[j];
  1069. if (OII < 0.0) {
  1070. fprintf(stderr, "JNegative[%d][OII] = % 0.16g [%d]\n",
  1071. i, OII, j);
  1072. /*OII = 0.0;*/
  1073. OII = 1e-20;
  1074. return 1;
  1075. }
  1076. total+=OII * 16;
  1077. j++;
  1078. OVI = input[j];
  1079. if (OVI < 0.0) {
  1080. fprintf(stderr, "JNegative[%d][OVI] = % 0.16g [%d]\n",
  1081. i, OVI, j);
  1082. /*OVI = 0.0;*/
  1083. OVI = 1e-20;
  1084. return 1;
  1085. }
  1086. total+=OVI * 16;
  1087. j++;
  1088. OIII = input[j];
  1089. if (OIII < 0.0) {
  1090. fprintf(stderr, "JNegative[%d][OIII] = % 0.16g [%d]\n",
  1091. i, OIII, j);
  1092. /*OIII = 0.0;*/
  1093. OIII = 1e-20;
  1094. return 1;
  1095. }
  1096. total+=OIII * 16;
  1097. j++;
  1098. OIV = input[j];
  1099. if (OIV < 0.0) {
  1100. fprintf(stderr, "JNegative[%d][OIV] = % 0.16g [%d]\n",
  1101. i, OIV, j);
  1102. /*OIV = 0.0;*/
  1103. OIV = 1e-20;
  1104. return 1;
  1105. }
  1106. total+=OIV * 16;
  1107. j++;
  1108. OV = input[j];
  1109. if (OV < 0.0) {
  1110. fprintf(stderr, "JNegative[%d][OV] = % 0.16g [%d]\n",
  1111. i, OV, j);
  1112. /*OV = 0.0;*/
  1113. OV = 1e-20;
  1114. return 1;
  1115. }
  1116. total+=OV * 16;
  1117. j++;
  1118. OVIII = input[j];
  1119. if (OVIII < 0.0) {
  1120. fprintf(stderr, "JNegative[%d][OVIII] = % 0.16g [%d]\n",
  1121. i, OVIII, j);
  1122. /*OVIII = 0.0;*/
  1123. OVIII = 1e-20;
  1124. return 1;
  1125. }
  1126. total+=OVIII * 16;
  1127. j++;
  1128. OIX = input[j];
  1129. if (OIX < 0.0) {
  1130. fprintf(stderr, "JNegative[%d][OIX] = % 0.16g [%d]\n",
  1131. i, OIX, j);
  1132. /*OIX = 0.0;*/
  1133. OIX = 1e-20;
  1134. return 1;
  1135. }
  1136. total+=OIX * 16;
  1137. j++;
  1138. mdensity = total * mh;
  1139. j = i * nchem * nchem;
  1140. //
  1141. // Species: ge
  1142. //
  1143. // ge by ge
  1144. Joutput[j] = 0.0;
  1145. //Joutput[j] /= mdensity;
  1146. Joutput[j] *= Tge[i];
  1147. j++;
  1148. // de by ge
  1149. Joutput[j] = OI*de*rOI_i[i] + OII*de*rOII_i[i] - OII*de*rOII_r[i] + OIII*de*rOIII_i[i] - OIII*de*rOIII_r[i] + OIV*de*rOIV_i[i] - OIV*de*rOIV_r[i] - OIX*de*rOIX_r[i] + OV*de*rOV_i[i] - OV*de*rOV_r[i] + OVI*de*rOVI_i[i] - OVI*de*rOVI_r[i] + OVII*de*rOVII_i[i] - OVII*de*rOVII_r[i] + OVIII*de*rOVIII_i[i] - OVIII*de*rOVIII_r[i];
  1150. Joutput[j] *= Tge[i];
  1151. j++;
  1152. // OI by ge
  1153. Joutput[j] = -OI*de*rOI_i[i] + OII*de*rOII_r[i];
  1154. Joutput[j] *= Tge[i];
  1155. j++;
  1156. // OVII by ge
  1157. Joutput[j] = OVI*de*rOVI_i[i] - OVII*de*rOVII_i[i] - OVII*de*rOVII_r[i] + OVIII*de*rOVIII_r[i];
  1158. Joutput[j] *= Tge[i];
  1159. j++;
  1160. // OII by ge
  1161. Joutput[j] = OI*de*rOI_i[i] - OII*de*rOII_i[i] - OII*de*rOII_r[i] + OIII*de*rOIII_r[i];
  1162. Joutput[j] *= Tge[i];
  1163. j++;
  1164. // OVI by ge
  1165. Joutput[j] = OV*de*rOV_i[i] - OVI*de*rOVI_i[i] - OVI*de*rOVI_r[i] + OVII*de*rOVII_r[i];
  1166. Joutput[j] *= Tge[i];
  1167. j++;
  1168. // OIII by ge
  1169. Joutput[j] = OII*de*rOII_i[i] - OIII*de*rOIII_i[i] - OIII*de*rOIII_r[i] + OIV*de*rOIV_r[i];
  1170. Joutput[j] *= Tge[i];
  1171. j++;
  1172. // OIV by ge
  1173. Joutput[j] = OIII*de*rOIII_i[i] - OIV*de*rOIV_i[i] - OIV*de*rOIV_r[i] + OV*de*rOV_r[i];
  1174. Joutput[j] *= Tge[i];
  1175. j++;
  1176. // OV by ge
  1177. Joutput[j] = OIV*de*rOIV_i[i] - OV*de*rOV_i[i] - OV*de*rOV_r[i] + OVI*de*rOVI_r[i];
  1178. Joutput[j] *= Tge[i];
  1179. j++;
  1180. // OVIII by ge
  1181. Joutput[j] = OIX*de*rOIX_r[i] + OVII*de*rOVII_i[i] - OVIII*de*rOVIII_i[i] - OVIII*de*rOVIII_r[i];
  1182. Joutput[j] *= Tge[i];
  1183. j++;
  1184. // OIX by ge
  1185. Joutput[j] = -OIX*de*rOIX_r[i] + OVIII*de*rOVIII_i[i];
  1186. Joutput[j] *= Tge[i];
  1187. j++;
  1188. //
  1189. // Species: de
  1190. //
  1191. // ge by de
  1192. Joutput[j] = 0.0;
  1193. //Joutput[j] /= mdensity;
  1194. j++;
  1195. // de by de
  1196. Joutput[j] = OIII_i[i]*OIII - OIII_r[i]*OIII + OII_i[i]*OII - OII_r[i]*OII + OIV_i[i]*OIV - OIV_r[i]*OIV - OIX_r[i]*OIX + OI_i[i]*OI + OVIII_i[i]*OVIII - OVIII_r[i]*OVIII + OVII_i[i]*OVII - OVII_r[i]*OVII + OVI_i[i]*OVI - OVI_r[i]*OVI + OV_i[i]*OV - OV_r[i]*OV;
  1197. j++;
  1198. // OI by de
  1199. Joutput[j] = OII_r[i]*OII - OI_i[i]*OI;
  1200. j++;
  1201. // OVII by de
  1202. Joutput[j] = OVIII_r[i]*OVIII - OVII_i[i]*OVII - OVII_r[i]*OVII + OVI_i[i]*OVI;
  1203. j++;
  1204. // OII by de
  1205. Joutput[j] = OIII_r[i]*OIII - OII_i[i]*OII - OII_r[i]*OII + OI_i[i]*OI;
  1206. j++;
  1207. // OVI by de
  1208. Joutput[j] = OVII_r[i]*OVII - OVI_i[i]*OVI - OVI_r[i]*OVI + OV_i[i]*OV;
  1209. j++;
  1210. // OIII by de
  1211. Joutput[j] = -OIII_i[i]*OIII - OIII_r[i]*OIII + OII_i[i]*OII + OIV_r[i]*OIV;
  1212. j++;
  1213. // OIV by de
  1214. Joutput[j] = OIII_i[i]*OIII - OIV_i[i]*OIV - OIV_r[i]*OIV + OV_r[i]*OV;
  1215. j++;
  1216. // OV by de
  1217. Joutput[j] = OIV_i[i]*OIV + OVI_r[i]*OVI - OV_i[i]*OV - OV_r[i]*OV;
  1218. j++;
  1219. // OVIII by de
  1220. Joutput[j] = OIX_r[i]*OIX - OVIII_i[i]*OVIII - OVIII_r[i]*OVIII + OVII_i[i]*OVII;
  1221. j++;
  1222. // OIX by de
  1223. Joutput[j] = -OIX_r[i]*OIX + OVIII_i[i]*OVIII;
  1224. j++;
  1225. //
  1226. // Species: OI
  1227. //
  1228. // ge by OI
  1229. Joutput[j] = 0.0;
  1230. //Joutput[j] /= mdensity;
  1231. j++;
  1232. // de by OI
  1233. Joutput[j] = OI_i[i]*de;
  1234. j++;
  1235. // OI by OI
  1236. Joutput[j] = -OI_i[i]*de;
  1237. j++;
  1238. // OVII by OI
  1239. Joutput[j] = 0.0;
  1240. j++;
  1241. // OII by OI
  1242. Joutput[j] = OI_i[i]*de;
  1243. j++;
  1244. // OVI by OI
  1245. Joutput[j] = 0.0;
  1246. j++;
  1247. // OIII by OI
  1248. Joutput[j] = 0.0;
  1249. j++;
  1250. // OIV by OI
  1251. Joutput[j] = 0.0;
  1252. j++;
  1253. // OV by OI
  1254. Joutput[j] = 0.0;
  1255. j++;
  1256. // OVIII by OI
  1257. Joutput[j] = 0.0;
  1258. j++;
  1259. // OIX by OI
  1260. Joutput[j] = 0.0;
  1261. j++;
  1262. //
  1263. // Species: OVII
  1264. //
  1265. // ge by OVII
  1266. Joutput[j] = 0.0;
  1267. //Joutput[j] /= mdensity;
  1268. j++;
  1269. // de by OVII
  1270. Joutput[j] = OVII_i[i]*de - OVII_r[i]*de;
  1271. j++;
  1272. // OI by OVII
  1273. Joutput[j] = 0.0;
  1274. j++;
  1275. // OVII by OVII
  1276. Joutput[j] = -OVII_i[i]*de - OVII_r[i]*de;
  1277. j++;
  1278. // OII by OVII
  1279. Joutput[j] = 0.0;
  1280. j++;
  1281. // OVI by OVII
  1282. Joutput[j] = OVII_r[i]*de;
  1283. j++;
  1284. // OIII by OVII
  1285. Joutput[j] = 0.0;
  1286. j++;
  1287. // OIV by OVII
  1288. Joutput[j] = 0.0;
  1289. j++;
  1290. // OV by OVII
  1291. Joutput[j] = 0.0;
  1292. j++;
  1293. // OVIII by OVII
  1294. Joutput[j] = OVII_i[i]*de;
  1295. j++;
  1296. // OIX by OVII
  1297. Joutput[j] = 0.0;
  1298. j++;
  1299. //
  1300. // Species: OII
  1301. //
  1302. // ge by OII
  1303. Joutput[j] = 0.0;
  1304. //Joutput[j] /= mdensity;
  1305. j++;
  1306. // de by OII
  1307. Joutput[j] = OII_i[i]*de - OII_r[i]*de;
  1308. j++;
  1309. // OI by OII
  1310. Joutput[j] = OII_r[i]*de;
  1311. j++;
  1312. // OVII by OII
  1313. Joutput[j] = 0.0;
  1314. j++;
  1315. // OII by OII
  1316. Joutput[j] = -OII_i[i]*de - OII_r[i]*de;
  1317. j++;
  1318. // OVI by OII
  1319. Joutput[j] = 0.0;
  1320. j++;
  1321. // OIII by OII
  1322. Joutput[j] = OII_i[i]*de;
  1323. j++;
  1324. // OIV by OII
  1325. Joutput[j] = 0.0;
  1326. j++;
  1327. // OV by OII
  1328. Joutput[j] = 0.0;
  1329. j++;
  1330. // OVIII by OII
  1331. Joutput[j] = 0.0;
  1332. j++;
  1333. // OIX by OII
  1334. Joutput[j] = 0.0;
  1335. j++;
  1336. //
  1337. // Species: OVI
  1338. //
  1339. // ge by OVI
  1340. Joutput[j] = 0.0;
  1341. //Joutput[j] /= mdensity;
  1342. j++;
  1343. // de by OVI
  1344. Joutput[j] = OVI_i[i]*de - OVI_r[i]*de;
  1345. j++;
  1346. // OI by OVI
  1347. Joutput[j] = 0.0;
  1348. j++;
  1349. // OVII by OVI
  1350. Joutput[j] = OVI_i[i]*de;
  1351. j++;
  1352. // OII by OVI
  1353. Joutput[j] = 0.0;
  1354. j++;
  1355. // OVI by OVI
  1356. Joutput[j] = -OVI_i[i]*de - OVI_r[i]*de;
  1357. j++;
  1358. // OIII by OVI
  1359. Joutput[j] = 0.0;
  1360. j++;
  1361. // OIV by OVI
  1362. Joutput[j] = 0.0;
  1363. j++;
  1364. // OV by OVI
  1365. Joutput[j] = OVI_r[i]*de;
  1366. j++;
  1367. // OVIII by OVI
  1368. Joutput[j] = 0.0;
  1369. j++;
  1370. // OIX by OVI
  1371. Joutput[j] = 0.0;
  1372. j++;
  1373. //
  1374. // Species: OIII
  1375. //
  1376. // ge by OIII
  1377. Joutput[j] = 0.0;
  1378. //Joutput[j] /= mdensity;
  1379. j++;
  1380. // de by OIII
  1381. Joutput[j] = OIII_i[i]*de - OIII_r[i]*de;
  1382. j++;
  1383. // OI by OIII
  1384. Joutput[j] = 0.0;
  1385. j++;
  1386. // OVII by OIII
  1387. Joutput[j] = 0.0;
  1388. j++;
  1389. // OII by OIII
  1390. Joutput[j] = OIII_r[i]*de;
  1391. j++;
  1392. // OVI by OIII
  1393. Joutput[j] = 0.0;
  1394. j++;
  1395. // OIII by OIII
  1396. Joutput[j] = -OIII_i[i]*de - OIII_r[i]*de;
  1397. j++;
  1398. // OIV by OIII
  1399. Joutput[j] = OIII_i[i]*de;
  1400. j++;
  1401. // OV by OIII
  1402. Joutput[j] = 0.0;
  1403. j++;
  1404. // OVIII by OIII
  1405. Joutput[j] = 0.0;
  1406. j++;
  1407. // OIX by OIII
  1408. Joutput[j] = 0.0;
  1409. j++;
  1410. //
  1411. // Species: OIV
  1412. //
  1413. // ge by OIV
  1414. Joutput[j] = 0.0;
  1415. //Joutput[j] /= mdensity;
  1416. j++;
  1417. // de by OIV
  1418. Joutput[j] = OIV_i[i]*de - OIV_r[i]*de;
  1419. j++;
  1420. // OI by OIV
  1421. Joutput[j] = 0.0;
  1422. j++;
  1423. // OVII by OIV
  1424. Joutput[j] = 0.0;
  1425. j++;
  1426. // OII by OIV
  1427. Joutput[j] = 0.0;
  1428. j++;
  1429. // OVI by OIV
  1430. Joutput[j] = 0.0;
  1431. j++;
  1432. // OIII by OIV
  1433. Joutput[j] = OIV_r[i]*de;
  1434. j++;
  1435. // OIV by OIV
  1436. Joutput[j] = -OIV_i[i]*de - OIV_r[i]*de;
  1437. j++;
  1438. // OV by OIV
  1439. Joutput[j] = OIV_i[i]*de;
  1440. j++;
  1441. // OVIII by OIV
  1442. Joutput[j] = 0.0;
  1443. j++;
  1444. // OIX by OIV
  1445. Joutput[j] = 0.0;
  1446. j++;
  1447. //
  1448. // Species: OV
  1449. //
  1450. // ge by OV
  1451. Joutput[j] = 0.0;
  1452. //Joutput[j] /= mdensity;
  1453. j++;
  1454. // de by OV
  1455. Joutput[j] = OV_i[i]*de - OV_r[i]*de;
  1456. j++;
  1457. // OI by OV
  1458. Joutput[j] = 0.0;
  1459. j++;
  1460. // OVII by OV
  1461. Joutput[j] = 0.0;
  1462. j++;
  1463. // OII by OV
  1464. Joutput[j] = 0.0;
  1465. j++;
  1466. // OVI by OV
  1467. Joutput[j] = OV_i[i]*de;
  1468. j++;
  1469. // OIII by OV
  1470. Joutput[j] = 0.0;
  1471. j++;
  1472. // OIV by OV
  1473. Joutput[j] = OV_r[i]*de;
  1474. j++;
  1475. // OV by OV
  1476. Joutput[j] = -OV_i[i]*de - OV_r[i]*de;
  1477. j++;
  1478. // OVIII by OV
  1479. Joutput[j] = 0.0;
  1480. j++;
  1481. // OIX by OV
  1482. Joutput[j] = 0.0;
  1483. j++;
  1484. //
  1485. // Species: OVIII
  1486. //
  1487. // ge by OVIII
  1488. Joutput[j] = 0.0;
  1489. //Joutput[j] /= mdensity;
  1490. j++;
  1491. // de by OVIII
  1492. Joutput[j] = OVIII_i[i]*de - OVIII_r[i]*de;
  1493. j++;
  1494. // OI by OVIII
  1495. Joutput[j] = 0.0;
  1496. j++;
  1497. // OVII by OVIII
  1498. Joutput[j] = OVIII_r[i]*de;
  1499. j++;
  1500. // OII by OVIII
  1501. Joutput[j] = 0.0;
  1502. j++;
  1503. // OVI by OVIII
  1504. Joutput[j] = 0.0;
  1505. j++;
  1506. // OIII by OVIII
  1507. Joutput[j] = 0.0;
  1508. j++;
  1509. // OIV by OVIII
  1510. Joutput[j] = 0.0;
  1511. j++;
  1512. // OV by OVIII
  1513. Joutput[j] = 0.0;
  1514. j++;
  1515. // OVIII by OVIII
  1516. Joutput[j] = -OVIII_i[i]*de - OVIII_r[i]*de;
  1517. j++;
  1518. // OIX by OVIII
  1519. Joutput[j] = OVIII_i[i]*de;
  1520. j++;
  1521. //
  1522. // Species: OIX
  1523. //
  1524. // ge by OIX
  1525. Joutput[j] = 0.0;
  1526. //Joutput[j] /= mdensity;
  1527. j++;
  1528. // de by OIX
  1529. Joutput[j] = -OIX_r[i]*de;
  1530. j++;
  1531. // OI by OIX
  1532. Joutput[j] = 0.0;
  1533. j++;
  1534. // OVII by OIX
  1535. Joutput[j] = 0.0;
  1536. j++;
  1537. // OII by OIX
  1538. Joutput[j] = 0.0;
  1539. j++;
  1540. // OVI by OIX
  1541. Joutput[j] = 0.0;
  1542. j++;
  1543. // OIII by OIX
  1544. Joutput[j] = 0.0;
  1545. j++;
  1546. // OIV by OIX
  1547. Joutput[j] = 0.0;
  1548. j++;
  1549. // OV by OIX
  1550. Joutput[j] = 0.0;
  1551. j++;
  1552. // OVIII by OIX
  1553. Joutput[j] = OIX_r[i]*de;
  1554. j++;
  1555. // OIX by OIX
  1556. Joutput[j] = -OIX_r[i]*de;
  1557. j++;
  1558. }
  1559. return 0;
  1560. }