mabruzzo

arg-reduced solve_rate_cool_g-cpp.C

Dec 4th, 2024
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 129.66 KB | None | 0 0
  1. #include <cstdio>
  2. #include <vector>
  3.  
  4. #include "grackle.h"
  5. #include "fortran_func_decls.h"
  6. #include "utils-cpp.hpp"
  7. #include "solve_rate_cool_g-cpp.h"
  8.  
  9. //_// TODO: ADD ANY OTHER INCLUDE DIRECTIVES
  10.  
  11. extern "C" {
  12. void solve_rate_cool_g(
  13.   int* imetal, double* dt, double* utem, double* uxyz, double* urho, int* ierr,
  14.   chemistry_data* my_chemistry, chemistry_data_storage* my_rates,
  15.   code_units* my_units, grackle_field_data* my_fields,
  16.   photo_rate_storage* my_uvb_rates
  17. )
  18. {
  19.  
  20.  
  21.   // SOLVE MULTI-SPECIES RATE EQUATIONS AND RADIATIVE COOLING
  22.  
  23.   // written by: Yu Zhang, Peter Anninos and Tom Abel
  24.   // date:
  25.   // modified1:  January, 1996 by Greg Bryan; converted to KRONOS
  26.   // modified2:  October, 1996 by GB; adapted to AMR
  27.   // modified3:  May,     1999 by GB and Tom Abel, 3bodyH2, solver, HD
  28.   // modified4:  June,    2005 by GB to solve rate & cool at same time
  29.   // modified5:  April,   2009 by JHW to include radiative transfer
  30.   // modified6:  September, 2009 by BDS to include cloudy cooling
  31.  
  32.   // PURPOSE:
  33.   //   Solve the multi-species rate and cool equations.
  34.  
  35.   // INPUTS:
  36.   //   icool    - flag to update energy from radiative cooling
  37.   //   in,jn,kn - dimensions of 3D fields
  38.  
  39.   //   d        - total density field
  40.   //   de       - electron density field
  41.   //   HI,HII   - H density fields (neutral & ionized)
  42.   //   HeI/II/III - He density fields
  43.   //   DI/II    - D density fields (neutral & ionized)
  44.   //   HDI      - neutral HD molecule density field
  45.   //   HM       - H- density field
  46.   //   H2I      - H_2 (molecular H) density field
  47.   //   H2II     - H_2+ density field
  48.   //   metal    - metal density field
  49.   //   dust     - dust density field
  50.   //   kph*     - photoionization fields
  51.   //   gamma*   - photoheating fields
  52.   //   f_shield_custom - custom H2 shielding factor
  53.  
  54.   //   is,ie    - start and end indices of active region (zero based)
  55.   //   iexpand  - comoving coordinates flag (0 = off, 1 = on)
  56.   //   idim     - dimensionality (rank) of problem
  57.   //   ispecies - chemistry module (1 - H/He only, 2 - molecular H, 3 - D)
  58.   //   imetal   - flag if metal field is active (0 = no, 1 = yes)
  59.   //   imcool   - flag if there is metal cooling
  60.   //   idust    - flag for H2 formation on dust grains
  61.   //   idustall - flag for dust (0 - none, 1 - heating/cooling + H2 form.)
  62.   //   idustfield - flag if a dust density field is present
  63.   //   iisrffield - flag if a field for the interstellar radiation field is present
  64.   //   ih2co    - flag to include H2 cooling (1 = on, 0 = off)
  65.   //   ipiht    - flag to include photoionization heating (1 = on, 0 = off)
  66.   //   idustrec - flag to include dust recombination cooling (1 = on, -1 = off)
  67.   //   iH2shield - flag for approximate self-shielding of H2 (Wolcott-Green+ 2011)
  68.   //   iradshield - flag for approximate self-shielding of UV background
  69.   //   avgsighi   - spectrum averaged ionization crs for HI for use with shielding
  70.   //   avgsighei  - spectrum averaged ionization crs for HeI for use with shielding
  71.   //   avgsigheii - spectrum averaged ionization crs for HeII for use with shielding
  72.   //   iradtrans - flag to include radiative transfer (1 = on, 0 = off)
  73.   //   iradcoupled - flag to indicate coupled radiative transfer
  74.   //   iradstep  - flag to indicate intermediate coupled radiative transfer timestep
  75.   //   irt_honly - flag to indicate applying RT ionization and heating to HI only
  76.   //   iH2shieldcustom - flag to indicate a custom H2 shielding factor is provided
  77.  
  78.   //     fh       - Hydrogen mass fraction (typically 0.76)
  79.   //     dtoh     - Deuterium to H mass ratio
  80.   //     z_solar  - Solar metal mass fraction
  81.   //     fgr      - the local dust to gas ratio (by mass)
  82.   //     dt       - timestep to integrate over
  83.   //     aye      - expansion factor (in code units)
  84.  
  85.   //     utim     - time units (i.e. code units to CGS conversion factor)
  86.   //     uaye     - expansion factor conversion factor (uaye = 1/(1+zinit))
  87.   //     urho     - density units
  88.   //     uxyz     - length units
  89.   //     utem     - temperature(-like) units
  90.  
  91.   //     temstart, temend - start and end of temperature range for rate table
  92.   //     nratec   - dimensions of chemical rate arrays (functions of temperature)
  93.   //     dtemstart, dtemend - start and end of dust temperature range
  94.   //     ndratec  - extra dimension for H2 formation on dust rate (dust temperature)
  95.  
  96.   //     icmbTfloor - flag to include temperature floor from cmb
  97.   //     iClHeat    - flag to include cloudy heating
  98.   //     priGridRank - rank of cloudy primordial cooling data grid
  99.   //     priGridDim  - array containing dimensions of cloudy primordial data
  100.   //     priPar1, priPar2, priPar3 - arrays containing primordial grid parameter values
  101.   //     priDataSize - total size of flattened 1D primordial cooling data array
  102.   //     priCooling  - primordial cooling data
  103.   //     priHeating  - primordial heating data
  104.   //     priMMW      - primordial mmw data
  105.   //     metGridRank - rank of cloudy metal cooling data grid
  106.   //     metGridDim  - array containing dimensions of cloudy metal data
  107.   //     metPar1, metPar2, metPar3 - arrays containing metal grid parameter values
  108.   //     metDataSize - total size of flattened 1D metal cooling data array
  109.   //     metCooling  - metal cooling data
  110.   //     metHeating  - metal heating data
  111.   //     iVheat      - flag for using volumetric heating rate
  112.   //     iMheat      - flag for using specific heating rate
  113.   //     Vheat       - array of volumetric heating rates
  114.   //     Mheat       - array of specific heating rates
  115.   //     iTfloor     - flag for using temperature floor field
  116.   //     Tfloor_scalar - scalar temperature floor value
  117.   //     Tfloor      - array of temperature floor values
  118.   //     itmax       - maximum allowed sub-cycle iterations
  119.   //     exititmax   - flag to exit if max iterations exceeded
  120.  
  121.   //   OUTPUTS:
  122.   //     update chemical rate densities (HI, HII, etc)
  123.  
  124.   //   PARAMETERS:
  125.   //     mh      - H mass in cgs units
  126.  
  127.   // -----------------------------------------------------------------------
  128.  
  129.  
  130.   // General Arguments
  131.  
  132.   int ierror;
  133.  
  134.   // -- removed line (previously just declared arg types) --
  135.  
  136.   // Density, energy and velocity fields fields
  137.  
  138.   grackle::impl::View<gr_float***> de(my_fields->e_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  139.   grackle::impl::View<gr_float***> HI(my_fields->HI_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  140.   grackle::impl::View<gr_float***> HII(my_fields->HII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  141.   grackle::impl::View<gr_float***> HeI(my_fields->HeI_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  142.   grackle::impl::View<gr_float***> HeII(my_fields->HeII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  143.   grackle::impl::View<gr_float***> HeIII(my_fields->HeIII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  144.   grackle::impl::View<gr_float***> HM(my_fields->HM_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  145.   grackle::impl::View<gr_float***> H2I(my_fields->H2I_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  146.   grackle::impl::View<gr_float***> H2II(my_fields->H2II_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  147.   grackle::impl::View<gr_float***> DI(my_fields->DI_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  148.   grackle::impl::View<gr_float***> DII(my_fields->DII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  149.   grackle::impl::View<gr_float***> HDI(my_fields->HDI_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  150.   grackle::impl::View<gr_float***> d(my_fields->density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  151.   grackle::impl::View<gr_float***> e(my_fields->internal_energy, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  152.   grackle::impl::View<gr_float***> u(my_fields->x_velocity, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  153.   grackle::impl::View<gr_float***> v(my_fields->y_velocity, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  154.   grackle::impl::View<gr_float***> w(my_fields->z_velocity, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  155.   grackle::impl::View<gr_float***> metal(my_fields->metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  156.   grackle::impl::View<gr_float***> dust(my_fields->dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  157.   grackle::impl::View<gr_float***> Vheat(my_fields->volumetric_heating_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  158.   grackle::impl::View<gr_float***> Mheat(my_fields->specific_heating_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  159.   grackle::impl::View<gr_float***> Tfloor(my_fields->temperature_floor, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  160.   grackle::impl::View<gr_float***> DM(my_fields->DM_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  161.   grackle::impl::View<gr_float***> HDII(my_fields->HDII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  162.   grackle::impl::View<gr_float***> HeHII(my_fields->HeHII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  163.   grackle::impl::View<gr_float***> CI(my_fields->CI_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  164.   grackle::impl::View<gr_float***> CII(my_fields->CII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  165.   grackle::impl::View<gr_float***> CO(my_fields->CO_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  166.   grackle::impl::View<gr_float***> CO2(my_fields->CO2_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  167.   grackle::impl::View<gr_float***> OI(my_fields->OI_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  168.   grackle::impl::View<gr_float***> OH(my_fields->OH_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  169.   grackle::impl::View<gr_float***> H2O(my_fields->H2O_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  170.   grackle::impl::View<gr_float***> O2(my_fields->O2_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  171.   grackle::impl::View<gr_float***> SiI(my_fields->SiI_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  172.   grackle::impl::View<gr_float***> SiOI(my_fields->SiOI_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  173.   grackle::impl::View<gr_float***> SiO2I(my_fields->SiO2I_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  174.   grackle::impl::View<gr_float***> CH(my_fields->CH_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  175.   grackle::impl::View<gr_float***> CH2(my_fields->CH2_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  176.   grackle::impl::View<gr_float***> COII(my_fields->COII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  177.   grackle::impl::View<gr_float***> OII(my_fields->OII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  178.   grackle::impl::View<gr_float***> OHII(my_fields->OHII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  179.   grackle::impl::View<gr_float***> H2OII(my_fields->H2OII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  180.   grackle::impl::View<gr_float***> H3OII(my_fields->H3OII_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  181.   grackle::impl::View<gr_float***> O2II(my_fields->O2II_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  182.   grackle::impl::View<gr_float***> Mg(my_fields->Mg_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  183.   grackle::impl::View<gr_float***> Al(my_fields->Al_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  184.   grackle::impl::View<gr_float***> S(my_fields->S_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  185.   grackle::impl::View<gr_float***> Fe(my_fields->Fe_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  186.   grackle::impl::View<gr_float***> SiM(my_fields->SiM_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  187.   grackle::impl::View<gr_float***> FeM(my_fields->FeM_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  188.   grackle::impl::View<gr_float***> Mg2SiO4(my_fields->Mg2SiO4_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  189.   grackle::impl::View<gr_float***> MgSiO3(my_fields->MgSiO3_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  190.   grackle::impl::View<gr_float***> Fe3O4(my_fields->Fe3O4_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  191.   grackle::impl::View<gr_float***> AC(my_fields->AC_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  192.   grackle::impl::View<gr_float***> SiO2D(my_fields->SiO2_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  193.   grackle::impl::View<gr_float***> MgO(my_fields->MgO_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  194.   grackle::impl::View<gr_float***> FeS(my_fields->FeS_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  195.   grackle::impl::View<gr_float***> Al2O3(my_fields->Al2O3_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  196.   grackle::impl::View<gr_float***> reforg(my_fields->ref_org_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  197.   grackle::impl::View<gr_float***> volorg(my_fields->vol_org_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  198.   grackle::impl::View<gr_float***> H2Oice(my_fields->H2O_ice_dust_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  199.   grackle::impl::View<gr_float***> metal_loc(my_fields->local_ISM_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  200.   grackle::impl::View<gr_float***> metal_C13(my_fields->ccsn13_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  201.   grackle::impl::View<gr_float***> metal_C20(my_fields->ccsn20_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  202.   grackle::impl::View<gr_float***> metal_C25(my_fields->ccsn25_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  203.   grackle::impl::View<gr_float***> metal_C30(my_fields->ccsn30_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  204.   grackle::impl::View<gr_float***> metal_F13(my_fields->fsn13_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  205.   grackle::impl::View<gr_float***> metal_F15(my_fields->fsn15_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  206.   grackle::impl::View<gr_float***> metal_F50(my_fields->fsn50_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  207.   grackle::impl::View<gr_float***> metal_F80(my_fields->fsn80_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  208.   grackle::impl::View<gr_float***> metal_P170(my_fields->pisn170_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  209.   grackle::impl::View<gr_float***> metal_P200(my_fields->pisn200_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  210.   grackle::impl::View<gr_float***> metal_Y19(my_fields->y19_metal_density, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  211.  
  212.   // Radiative transfer fields
  213.  
  214.   grackle::impl::View<gr_float***> kphHI(my_fields->RT_HI_ionization_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  215.   grackle::impl::View<gr_float***> kphHeI(my_fields->RT_HeI_ionization_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  216.   grackle::impl::View<gr_float***> kphHeII(my_fields->RT_HeII_ionization_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  217.   grackle::impl::View<gr_float***> kdissH2I(my_fields->RT_H2_dissociation_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  218.   grackle::impl::View<gr_float***> photogamma(my_fields->RT_heating_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  219.  
  220.   // -- removed line (previously just declared arg types) --
  221.   grackle::impl::View<gr_float***> kdissHDI(my_fields->RT_HDI_dissociation_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  222.   grackle::impl::View<gr_float***> kphCI(my_fields->RT_CI_ionization_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  223.   grackle::impl::View<gr_float***> kphOI(my_fields->RT_OI_ionization_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  224.   grackle::impl::View<gr_float***> kdissCO(my_fields->RT_CO_dissociation_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  225.   grackle::impl::View<gr_float***> kdissOH(my_fields->RT_OH_dissociation_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  226.   grackle::impl::View<gr_float***> kdissH2O(my_fields->RT_H2O_dissociation_rate, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  227.   // -- removed line (previously just declared arg types) --
  228.  
  229.   // H2 self-shielding length-scale field
  230.  
  231.   grackle::impl::View<gr_float***> xH2shield(my_fields->H2_self_shielding_length, my_fields->grid_dimension[0], my_fields->grid_dimension[1], my_fields->grid_dimension[2]);
  232.  
  233.   // Interstellar radiation field for dust heating
  234.  
  235.  
  236.   // Custom H2 shielding factor
  237.  
  238.  
  239.   // Cooling tables (coolings rates as a function of temperature)
  240.  
  241.   // -- removed line (previously just declared arg types) --
  242.   // -- removed line (previously just declared arg types) --
  243.   // -- removed line (previously just declared arg types) --
  244.   // -- removed line (previously just declared arg types) --
  245.   // -- removed line (previously just declared arg types) --
  246.   // -- removed line (previously just declared arg types) --
  247.   // -- removed line (previously just declared arg types) --
  248.   // -- removed line (previously just declared arg types) --
  249.   // -- removed line (previously just declared arg types) --
  250.   // -- removed line (previously just declared arg types) --
  251.   // -- removed line (previously just declared arg types) --
  252.   // -- removed line (previously just declared arg types) --
  253.   // -- removed line (previously just declared arg types) --
  254.   // -- removed line (previously just declared arg types) --
  255.   // -- removed line (previously just declared arg types) --
  256.   // -- removed line (previously just declared arg types) --
  257.   // -- removed line (previously just declared arg types) --
  258.   // -- removed line (previously just declared arg types) --
  259.   // -- removed line (previously just declared arg types) --
  260.   // -- removed line (previously just declared arg types) --
  261.   // -- removed line (previously just declared arg types) --
  262.   // -- removed line (previously just declared arg types) --
  263.   // -- removed line (previously just declared arg types) --
  264.   // -- removed line (previously just declared arg types) --
  265.   // -- removed line (previously just declared arg types) --
  266.   // opacity table
  267.   // -- removed line (previously just declared arg types) --
  268.   // -- removed line (previously just declared arg types) --
  269.   // -- removed line (previously just declared arg types) --
  270.  
  271.   // -- removed line (previously just declared arg types) --
  272.  
  273.   // Chemistry tables (rates as a function of temperature)
  274.  
  275.   // -- removed line (previously just declared arg types) --
  276.  
  277.   // Cloudy cooling data
  278.  
  279.   // -- removed line (previously just declared arg types) --
  280.   // -- removed line (previously just declared arg types) --
  281.   // -- removed line (previously just declared arg types) --
  282.  
  283.   // Parameters
  284.  
  285. #ifdef GRACKLE_FLOAT_4
  286.   const gr_float tolerance = (gr_float)(1.0e-05);
  287. #else
  288.   const gr_float tolerance = (gr_float)(1.0e-10);
  289. #endif
  290.  
  291.   const double mh = mass_h;
  292.   const double pi = pi_val;
  293.  
  294.   // Locals
  295.  
  296.   int i, j, k, iter;
  297.   int t, dj, dk;
  298.   double ttmin, dom, energy, comp1, comp2;
  299.   double coolunit, dbase1, tbase1, xbase1, chunit, uvel;
  300.   double heq1, heq2, eqk221, eqk222, eqk131, eqk132, eqt1, eqt2, eqtdef, dheq, heq, dlogtem, dx_cgs, c_ljeans, min_metallicity;
  301.   gr_float factor;
  302.  
  303.   // row temporaries
  304.  
  305.   std::vector<long long> indixe(my_fields->grid_dimension[0]);
  306.   double olddtit;
  307.   std::vector<double> t1(my_fields->grid_dimension[0]);
  308.   std::vector<double> t2(my_fields->grid_dimension[0]);
  309.   std::vector<double> logtem(my_fields->grid_dimension[0]);
  310.   std::vector<double> tdef(my_fields->grid_dimension[0]);
  311.   std::vector<double> dtit(my_fields->grid_dimension[0]);
  312.   std::vector<double> ttot(my_fields->grid_dimension[0]);
  313.   std::vector<double> p2d(my_fields->grid_dimension[0]);
  314.   std::vector<double> tgas(my_fields->grid_dimension[0]);
  315.   std::vector<double> tgasold(my_fields->grid_dimension[0]);
  316.   std::vector<double> tdust(my_fields->grid_dimension[0]);
  317.   std::vector<double> metallicity(my_fields->grid_dimension[0]);
  318.   std::vector<double> dust2gas(my_fields->grid_dimension[0]);
  319.   std::vector<double> rhoH(my_fields->grid_dimension[0]);
  320.   std::vector<double> mmw(my_fields->grid_dimension[0]);
  321.   std::vector<double> mynh(my_fields->grid_dimension[0]);
  322.   std::vector<double> myde(my_fields->grid_dimension[0]);
  323.   std::vector<double> gammaha_eff(my_fields->grid_dimension[0]);
  324.   std::vector<double> gasgr_tdust(my_fields->grid_dimension[0]);
  325.   std::vector<double> regr(my_fields->grid_dimension[0]);
  326.   std::vector<double> ddom(my_fields->grid_dimension[0]);
  327.  
  328.   // Rate equation row temporaries
  329.  
  330.   std::vector<double> HIp(my_fields->grid_dimension[0]);
  331.   std::vector<double> HIIp(my_fields->grid_dimension[0]);
  332.   std::vector<double> HeIp(my_fields->grid_dimension[0]);
  333.   std::vector<double> HeIIp(my_fields->grid_dimension[0]);
  334.   std::vector<double> HeIIIp(my_fields->grid_dimension[0]);
  335.   std::vector<double> HMp(my_fields->grid_dimension[0]);
  336.   std::vector<double> H2Ip(my_fields->grid_dimension[0]);
  337.   std::vector<double> H2IIp(my_fields->grid_dimension[0]);
  338.   std::vector<double> dep(my_fields->grid_dimension[0]);
  339.   std::vector<double> dedot(my_fields->grid_dimension[0]);
  340.   std::vector<double> HIdot(my_fields->grid_dimension[0]);
  341.   std::vector<double> dedot_prev(my_fields->grid_dimension[0]);
  342.   std::vector<double> DIp(my_fields->grid_dimension[0]);
  343.   std::vector<double> DIIp(my_fields->grid_dimension[0]);
  344.   std::vector<double> HDIp(my_fields->grid_dimension[0]);
  345.   std::vector<double> HIdot_prev(my_fields->grid_dimension[0]);
  346.   std::vector<double> k24shield(my_fields->grid_dimension[0]);
  347.   std::vector<double> k25shield(my_fields->grid_dimension[0]);
  348.   std::vector<double> k26shield(my_fields->grid_dimension[0]);
  349.   std::vector<double> k28shield(my_fields->grid_dimension[0]);
  350.   std::vector<double> k29shield(my_fields->grid_dimension[0]);
  351.   std::vector<double> k30shield(my_fields->grid_dimension[0]);
  352.   std::vector<double> k31shield(my_fields->grid_dimension[0]);
  353.   std::vector<double> k1(my_fields->grid_dimension[0]);
  354.   std::vector<double> k2(my_fields->grid_dimension[0]);
  355.   std::vector<double> k3(my_fields->grid_dimension[0]);
  356.   std::vector<double> k4(my_fields->grid_dimension[0]);
  357.   std::vector<double> k5(my_fields->grid_dimension[0]);
  358.   std::vector<double> k6(my_fields->grid_dimension[0]);
  359.   std::vector<double> k7(my_fields->grid_dimension[0]);
  360.   std::vector<double> k8(my_fields->grid_dimension[0]);
  361.   std::vector<double> k9(my_fields->grid_dimension[0]);
  362.   std::vector<double> k10(my_fields->grid_dimension[0]);
  363.   std::vector<double> k11(my_fields->grid_dimension[0]);
  364.   std::vector<double> k12(my_fields->grid_dimension[0]);
  365.   std::vector<double> k13(my_fields->grid_dimension[0]);
  366.   std::vector<double> k14(my_fields->grid_dimension[0]);
  367.   std::vector<double> k15(my_fields->grid_dimension[0]);
  368.   std::vector<double> k16(my_fields->grid_dimension[0]);
  369.   std::vector<double> k17(my_fields->grid_dimension[0]);
  370.   std::vector<double> k18(my_fields->grid_dimension[0]);
  371.   std::vector<double> k19(my_fields->grid_dimension[0]);
  372.   std::vector<double> k22(my_fields->grid_dimension[0]);
  373.   std::vector<double> k50(my_fields->grid_dimension[0]);
  374.   std::vector<double> k51(my_fields->grid_dimension[0]);
  375.   std::vector<double> k52(my_fields->grid_dimension[0]);
  376.   std::vector<double> k53(my_fields->grid_dimension[0]);
  377.   std::vector<double> k54(my_fields->grid_dimension[0]);
  378.   std::vector<double> k55(my_fields->grid_dimension[0]);
  379.   std::vector<double> k56(my_fields->grid_dimension[0]);
  380.   std::vector<double> k57(my_fields->grid_dimension[0]);
  381.   std::vector<double> k58(my_fields->grid_dimension[0]);
  382.   std::vector<double> k13dd(my_fields->grid_dimension[0] * 14);
  383.   std::vector<double> h2dust(my_fields->grid_dimension[0]);
  384.   std::vector<double> ncrn(my_fields->grid_dimension[0]);
  385.   std::vector<double> ncrd1(my_fields->grid_dimension[0]);
  386.   std::vector<double> ncrd2(my_fields->grid_dimension[0]);
  387.   std::vector<double> DMp(my_fields->grid_dimension[0]);
  388.   std::vector<double> HDIIp(my_fields->grid_dimension[0]);
  389.   std::vector<double> HeHIIp(my_fields->grid_dimension[0]);
  390.   std::vector<double> CIp(my_fields->grid_dimension[0]);
  391.   std::vector<double> CIIp(my_fields->grid_dimension[0]);
  392.   std::vector<double> COp(my_fields->grid_dimension[0]);
  393.   std::vector<double> CO2p(my_fields->grid_dimension[0]);
  394.   std::vector<double> OIp(my_fields->grid_dimension[0]);
  395.   std::vector<double> OHp(my_fields->grid_dimension[0]);
  396.   std::vector<double> H2Op(my_fields->grid_dimension[0]);
  397.   std::vector<double> O2p(my_fields->grid_dimension[0]);
  398.   std::vector<double> SiIp(my_fields->grid_dimension[0]);
  399.   std::vector<double> SiOIp(my_fields->grid_dimension[0]);
  400.   std::vector<double> SiO2Ip(my_fields->grid_dimension[0]);
  401.   std::vector<double> CHp(my_fields->grid_dimension[0]);
  402.   std::vector<double> CH2p(my_fields->grid_dimension[0]);
  403.   std::vector<double> COIIp(my_fields->grid_dimension[0]);
  404.   std::vector<double> OIIp(my_fields->grid_dimension[0]);
  405.   std::vector<double> OHIIp(my_fields->grid_dimension[0]);
  406.   std::vector<double> H2OIIp(my_fields->grid_dimension[0]);
  407.   std::vector<double> H3OIIp(my_fields->grid_dimension[0]);
  408.   std::vector<double> O2IIp(my_fields->grid_dimension[0]);
  409.   std::vector<double> Mgp(my_fields->grid_dimension[0]);
  410.   std::vector<double> Alp(my_fields->grid_dimension[0]);
  411.   std::vector<double> Sp(my_fields->grid_dimension[0]);
  412.   std::vector<double> Fep(my_fields->grid_dimension[0]);
  413.   std::vector<gr_float> SiMp(my_fields->grid_dimension[0]);
  414.   std::vector<gr_float> FeMp(my_fields->grid_dimension[0]);
  415.   std::vector<gr_float> Mg2SiO4p(my_fields->grid_dimension[0]);
  416.   std::vector<gr_float> MgSiO3p(my_fields->grid_dimension[0]);
  417.   std::vector<gr_float> Fe3O4p(my_fields->grid_dimension[0]);
  418.   std::vector<gr_float> ACp(my_fields->grid_dimension[0]);
  419.   std::vector<gr_float> SiO2Dp(my_fields->grid_dimension[0]);
  420.   std::vector<gr_float> MgOp(my_fields->grid_dimension[0]);
  421.   std::vector<gr_float> FeSp(my_fields->grid_dimension[0]);
  422.   std::vector<gr_float> Al2O3p(my_fields->grid_dimension[0]);
  423.   std::vector<gr_float> reforgp(my_fields->grid_dimension[0]);
  424.   std::vector<gr_float> volorgp(my_fields->grid_dimension[0]);
  425.   std::vector<gr_float> H2Oicep(my_fields->grid_dimension[0]);
  426.  
  427.   std::vector<double> k125(my_fields->grid_dimension[0]);
  428.   std::vector<double> k129(my_fields->grid_dimension[0]);
  429.   std::vector<double> k130(my_fields->grid_dimension[0]);
  430.   std::vector<double> k131(my_fields->grid_dimension[0]);
  431.   std::vector<double> k132(my_fields->grid_dimension[0]);
  432.   std::vector<double> k133(my_fields->grid_dimension[0]);
  433.   std::vector<double> k134(my_fields->grid_dimension[0]);
  434.   std::vector<double> k135(my_fields->grid_dimension[0]);
  435.   std::vector<double> k136(my_fields->grid_dimension[0]);
  436.   std::vector<double> k137(my_fields->grid_dimension[0]);
  437.   std::vector<double> k148(my_fields->grid_dimension[0]);
  438.   std::vector<double> k149(my_fields->grid_dimension[0]);
  439.   std::vector<double> k150(my_fields->grid_dimension[0]);
  440.   std::vector<double> k151(my_fields->grid_dimension[0]);
  441.   std::vector<double> k152(my_fields->grid_dimension[0]);
  442.   std::vector<double> k153(my_fields->grid_dimension[0]);
  443.   std::vector<double> kz15(my_fields->grid_dimension[0]);
  444.   std::vector<double> kz16(my_fields->grid_dimension[0]);
  445.   std::vector<double> kz17(my_fields->grid_dimension[0]);
  446.   std::vector<double> kz18(my_fields->grid_dimension[0]);
  447.   std::vector<double> kz19(my_fields->grid_dimension[0]);
  448.   std::vector<double> kz20(my_fields->grid_dimension[0]);
  449.   std::vector<double> kz21(my_fields->grid_dimension[0]);
  450.   std::vector<double> kz22(my_fields->grid_dimension[0]);
  451.   std::vector<double> kz23(my_fields->grid_dimension[0]);
  452.   std::vector<double> kz24(my_fields->grid_dimension[0]);
  453.   std::vector<double> kz25(my_fields->grid_dimension[0]);
  454.   std::vector<double> kz26(my_fields->grid_dimension[0]);
  455.   std::vector<double> kz27(my_fields->grid_dimension[0]);
  456.   std::vector<double> kz28(my_fields->grid_dimension[0]);
  457.   std::vector<double> kz29(my_fields->grid_dimension[0]);
  458.   std::vector<double> kz30(my_fields->grid_dimension[0]);
  459.   std::vector<double> kz31(my_fields->grid_dimension[0]);
  460.   std::vector<double> kz32(my_fields->grid_dimension[0]);
  461.   std::vector<double> kz33(my_fields->grid_dimension[0]);
  462.   std::vector<double> kz34(my_fields->grid_dimension[0]);
  463.   std::vector<double> kz35(my_fields->grid_dimension[0]);
  464.   std::vector<double> kz36(my_fields->grid_dimension[0]);
  465.   std::vector<double> kz37(my_fields->grid_dimension[0]);
  466.   std::vector<double> kz38(my_fields->grid_dimension[0]);
  467.   std::vector<double> kz39(my_fields->grid_dimension[0]);
  468.   std::vector<double> kz40(my_fields->grid_dimension[0]);
  469.   std::vector<double> kz41(my_fields->grid_dimension[0]);
  470.   std::vector<double> kz42(my_fields->grid_dimension[0]);
  471.   std::vector<double> kz43(my_fields->grid_dimension[0]);
  472.   std::vector<double> kz44(my_fields->grid_dimension[0]);
  473.   std::vector<double> kz45(my_fields->grid_dimension[0]);
  474.   std::vector<double> kz46(my_fields->grid_dimension[0]);
  475.   std::vector<double> kz47(my_fields->grid_dimension[0]);
  476.   std::vector<double> kz48(my_fields->grid_dimension[0]);
  477.   std::vector<double> kz49(my_fields->grid_dimension[0]);
  478.   std::vector<double> kz50(my_fields->grid_dimension[0]);
  479.   std::vector<double> kz51(my_fields->grid_dimension[0]);
  480.   std::vector<double> kz52(my_fields->grid_dimension[0]);
  481.   std::vector<double> kz53(my_fields->grid_dimension[0]);
  482.   std::vector<double> kz54(my_fields->grid_dimension[0]);
  483.   // -- removed line (previously just declared arg types) --
  484.   std::vector<double> kdSiM(my_fields->grid_dimension[0]);
  485.   std::vector<double> kdFeM(my_fields->grid_dimension[0]);
  486.   std::vector<double> kdMg2SiO4(my_fields->grid_dimension[0]);
  487.   std::vector<double> kdMgSiO3(my_fields->grid_dimension[0]);
  488.   std::vector<double> kdFe3O4(my_fields->grid_dimension[0]);
  489.   std::vector<double> kdAC(my_fields->grid_dimension[0]);
  490.   std::vector<double> kdSiO2D(my_fields->grid_dimension[0]);
  491.   std::vector<double> kdMgO(my_fields->grid_dimension[0]);
  492.   std::vector<double> kdFeS(my_fields->grid_dimension[0]);
  493.   std::vector<double> kdAl2O3(my_fields->grid_dimension[0]);
  494.   std::vector<double> kdreforg(my_fields->grid_dimension[0]);
  495.   std::vector<double> kdvolorg(my_fields->grid_dimension[0]);
  496.   std::vector<double> kdH2Oice(my_fields->grid_dimension[0]);
  497.   // grain temperature
  498.   std::vector<double> tSiM(my_fields->grid_dimension[0]);
  499.   std::vector<double> tFeM(my_fields->grid_dimension[0]);
  500.   std::vector<double> tMg2SiO4(my_fields->grid_dimension[0]);
  501.   std::vector<double> tMgSiO3(my_fields->grid_dimension[0]);
  502.   std::vector<double> tFe3O4(my_fields->grid_dimension[0]);
  503.   std::vector<double> tAC(my_fields->grid_dimension[0]);
  504.   std::vector<double> tSiO2D(my_fields->grid_dimension[0]);
  505.   std::vector<double> tMgO(my_fields->grid_dimension[0]);
  506.   std::vector<double> tFeS(my_fields->grid_dimension[0]);
  507.   std::vector<double> tAl2O3(my_fields->grid_dimension[0]);
  508.   std::vector<double> treforg(my_fields->grid_dimension[0]);
  509.   std::vector<double> tvolorg(my_fields->grid_dimension[0]);
  510.   std::vector<double> tH2Oice(my_fields->grid_dimension[0]);
  511.  
  512.   // Cooling/heating row locals
  513.  
  514.   std::vector<double> ceHI(my_fields->grid_dimension[0]);
  515.   std::vector<double> ceHeI(my_fields->grid_dimension[0]);
  516.   std::vector<double> ceHeII(my_fields->grid_dimension[0]);
  517.   std::vector<double> ciHI(my_fields->grid_dimension[0]);
  518.   std::vector<double> ciHeI(my_fields->grid_dimension[0]);
  519.   std::vector<double> ciHeIS(my_fields->grid_dimension[0]);
  520.   std::vector<double> ciHeII(my_fields->grid_dimension[0]);
  521.   std::vector<double> reHII(my_fields->grid_dimension[0]);
  522.   std::vector<double> reHeII1(my_fields->grid_dimension[0]);
  523.   std::vector<double> reHeII2(my_fields->grid_dimension[0]);
  524.   std::vector<double> reHeIII(my_fields->grid_dimension[0]);
  525.   std::vector<double> brem(my_fields->grid_dimension[0]);
  526.   std::vector<double> edot(my_fields->grid_dimension[0]);
  527.   std::vector<double> hyd01k(my_fields->grid_dimension[0]);
  528.   std::vector<double> h2k01(my_fields->grid_dimension[0]);
  529.   std::vector<double> vibh(my_fields->grid_dimension[0]);
  530.   std::vector<double> roth(my_fields->grid_dimension[0]);
  531.   std::vector<double> rotl(my_fields->grid_dimension[0]);
  532.   std::vector<double> gpldl(my_fields->grid_dimension[0]);
  533.   std::vector<double> gphdl(my_fields->grid_dimension[0]);
  534.   std::vector<double> hdlte(my_fields->grid_dimension[0]);
  535.   std::vector<double> hdlow(my_fields->grid_dimension[0]);
  536.   std::vector<double> cieco(my_fields->grid_dimension[0]);
  537.  
  538.   // Iteration mask
  539.  
  540.   gr_mask_type anydust;
  541.   std::vector<gr_mask_type> itmask(my_fields->grid_dimension[0]);
  542.   std::vector<gr_mask_type> itmask_tmp(my_fields->grid_dimension[0]);
  543.   std::vector<gr_mask_type> itmask_nr(my_fields->grid_dimension[0]);
  544.   std::vector<gr_mask_type> itmask_metal(my_fields->grid_dimension[0]);
  545.   int itr, itr_time;
  546.   std::vector<int> imp_eng(my_fields->grid_dimension[0]);
  547.   int nsp, isp, jsp, id;
  548.   double dspj, err, err_max;
  549.   const int i_eng = 52;
  550.   std::vector<double> dsp(i_eng);
  551.   std::vector<double> dsp0(i_eng);
  552.   std::vector<double> dsp1(i_eng);
  553.   std::vector<double> dspdot(i_eng);
  554.   std::vector<double> dspdot1(i_eng);
  555.   std::vector<double> ddsp(i_eng);
  556.   std::vector<double> der_data_(i_eng * i_eng);
  557.   grackle::impl::View<double**> der(der_data_.data(), i_eng, i_eng);
  558.   std::vector<int> idsp;
  559.   std::vector<double> mtrx_data_;
  560.   grackle::impl::View<double**> mtrx;
  561.   std::vector<double> vec;
  562.   const double eps = 1.e-4;
  563.  
  564.  
  565.   // \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/////////////////////////////////
  566.   // =======================================================================
  567.  
  568.   // Set error indicator
  569.  
  570.   (*ierr) = 1;
  571.  
  572.   // Set flag for dust-related options
  573.  
  574.   if ((my_chemistry->h2_on_dust > 0)  ||  (my_chemistry->dust_chemistry > 0))  {
  575.     anydust = MASK_TRUE;
  576.   } else {
  577.     anydust = MASK_FALSE;
  578.   }
  579.  
  580.   // ignore metal chemistry/cooling below this metallicity
  581.   min_metallicity = 1.e-9 / my_chemistry->SolarMetalFractionByMass;
  582.      
  583.   // Set units
  584.  
  585.   dom      = (*urho)*(std::pow(my_units->a_value,3))/mh;
  586.   tbase1   = my_units->time_units;
  587.   xbase1   = (*uxyz)/(my_units->a_value*my_units->a_units);    // uxyz is [x]*a      = [x]*[a]*a'        '
  588.   dbase1   = (*urho)*std::pow((my_units->a_value*my_units->a_units),3); // urho is [dens]/a^3 = [dens]/([a]*a')^3 '
  589.   coolunit = (std::pow(my_units->a_units,5) * std::pow(xbase1,2) * std::pow(mh,2)) / (std::pow(tbase1,3) * dbase1);
  590.   uvel = ((*uxyz)/my_units->a_value) / my_units->time_units;
  591.   // chunit = (1.60218e-12_DKIND)/(2._DKIND*uvel*uvel*mh)   ! 1 eV per H2 formed
  592.   chunit = (1.60218e-12)/(uvel*uvel*mh);            // 1 eV per REACTION (Feb 2020, Gen Chiaki)
  593.  
  594.   dx_cgs = my_fields->grid_dx * xbase1;
  595.   c_ljeans = std::sqrt((my_chemistry->Gamma * pi * kboltz) /
  596.        (GravConst * mh * dbase1));
  597.  
  598.   dlogtem = (std::log(my_chemistry->TemperatureEnd) - std::log(my_chemistry->TemperatureStart))/(double)(my_chemistry->NumberOfTemperatureBins-1 );
  599.  
  600.   // We better make consistent at first GC202002
  601.  
  602.   if (my_chemistry->primordial_chemistry > 0)  {
  603.  
  604. #define ABUNDANCE_CORRECTION
  605. #ifdef ABUNDANCE_CORRECTION
  606.      FORTRAN_NAME(make_consistent_g)(de.data(), HI.data(), HII.data(), HeI.data(), HeII.data(), HeIII.data(),
  607.                          HM.data(), H2I.data(), H2II.data(), DI.data(), DII.data(), HDI.data(), metal.data(), dust.data(),
  608.                          d.data(), &my_fields->grid_start[0], &my_fields->grid_end[0], &my_fields->grid_start[1], &my_fields->grid_end[1], &my_fields->grid_start[2], &my_fields->grid_end[2],
  609.                          &my_fields->grid_dimension[0], &my_fields->grid_dimension[1], &my_fields->grid_dimension[2], &my_chemistry->primordial_chemistry, imetal, &my_chemistry->HydrogenFractionByMass, &my_chemistry->DeuteriumToHydrogenRatio,
  610.                         &my_chemistry->use_dust_density_field, &my_chemistry->metal_chemistry, &my_chemistry->grain_growth, &dom,
  611.                         DM.data(), HDII.data(), HeHII.data(),
  612.                         CI.data(), CII.data(), CO.data(), CO2.data(),
  613.                         OI.data(), OH.data(), H2O.data(), O2.data(),
  614.                         SiI.data(), SiOI.data(), SiO2I.data(),
  615.                         CH.data(), CH2.data(), COII.data(), OII.data(),
  616.                         OHII.data(), H2OII.data(), H3OII.data(), O2II.data(),
  617.                         Mg.data(), Al.data(), S.data(), Fe.data(),
  618.                         SiM.data(), FeM.data(), Mg2SiO4.data(), MgSiO3.data(), Fe3O4.data(),
  619.                         AC.data(), SiO2D.data(), MgO.data(), FeS.data(), Al2O3.data(),
  620.                         reforg.data(), volorg.data(), H2Oice.data(),
  621.                         &my_chemistry->multi_metals, &my_chemistry->metal_abundances, &my_chemistry->dust_species, &my_chemistry->use_multiple_dust_temperatures, &my_chemistry->dust_sublimation,
  622.                         metal_loc.data(),
  623.                         metal_C13.data(), metal_C20.data(), metal_C25.data(), metal_C30.data(),
  624.                         metal_F13.data(), metal_F15.data(), metal_F50.data(), metal_F80.data(),
  625.                         metal_P170.data(), metal_P200.data(), metal_Y19.data(),
  626.                         &my_rates->SN0_N,
  627.                         my_rates->SN0_XC, my_rates->SN0_XO, my_rates->SN0_XMg, my_rates->SN0_XAl, my_rates->SN0_XSi,
  628.                         my_rates->SN0_XS, my_rates->SN0_XFe,
  629.                         my_rates->SN0_fC, my_rates->SN0_fO, my_rates->SN0_fMg, my_rates->SN0_fAl, my_rates->SN0_fSi,
  630.                         my_rates->SN0_fS, my_rates->SN0_fFe
  631.                           );
  632. #endif
  633.  
  634.   }
  635.  
  636.   // Convert densities from comoving to proper
  637.  
  638.   if (my_units->comoving_coordinates == 1)  {
  639.  
  640.     factor = (gr_float)(std::pow(my_units->a_value,(-3)) );
  641.  
  642.      FORTRAN_NAME(scale_fields_g)(
  643.       &my_chemistry->primordial_chemistry, imetal, &my_chemistry->use_dust_density_field, &my_chemistry->metal_chemistry,
  644.       &my_chemistry->metal_abundances, &my_chemistry->dust_species, &my_chemistry->multi_metals, &my_chemistry->grain_growth, &my_chemistry->dust_sublimation, &factor,
  645.       &my_fields->grid_start[0], &my_fields->grid_end[0], &my_fields->grid_start[1], &my_fields->grid_end[1], &my_fields->grid_start[2], &my_fields->grid_end[2], &my_fields->grid_dimension[0], &my_fields->grid_dimension[1], &my_fields->grid_dimension[2],
  646.       d.data(), de.data(), HI.data(), HII.data(), HeI.data(), HeII.data(), HeIII.data(),
  647.       HM.data(), H2I.data(), H2II.data(), DI.data(), DII.data(), HDI.data(), DM.data(), HDII.data(), HeHII.data(),
  648.       metal.data(), dust.data(),
  649.       CI.data(), CII.data(), CO.data(), CO2.data(),
  650.       OI.data(), OH.data(), H2O.data(), O2.data(),
  651.       SiI.data(), SiOI.data(), SiO2I.data(),
  652.       CH.data(), CH2.data(), COII.data(), OII.data(),
  653.       OHII.data(), H2OII.data(), H3OII.data(), O2II.data(),
  654.       Mg.data(), Al.data(), S.data(), Fe.data(),
  655.       SiM.data(), FeM.data(), Mg2SiO4.data(), MgSiO3.data(), Fe3O4.data(),
  656.       AC.data(), SiO2D.data(), MgO.data(), FeS.data(), Al2O3.data(),
  657.       reforg.data(), volorg.data(), H2Oice.data(),
  658.       metal_loc.data(), metal_C13.data(), metal_C20.data(), metal_C25.data(), metal_C30.data(),
  659.       metal_F13.data(), metal_F15.data(), metal_F50.data(), metal_F80.data(),
  660.       metal_P170.data(), metal_P200.data(), metal_Y19.data());
  661.  
  662.   }
  663.  
  664. #ifdef ABUNDANCE_CORRECTION
  665.    FORTRAN_NAME(ceiling_species_g)(d.data(), de.data(), HI.data(), HII.data(), HeI.data(), HeII.data(), HeIII.data(),
  666.                        HM.data(), H2I.data(), H2II.data(), DI.data(), DII.data(), HDI.data(), metal.data(), dust.data(),
  667.                        &my_fields->grid_start[0], &my_fields->grid_end[0], &my_fields->grid_start[1], &my_fields->grid_end[1], &my_fields->grid_start[2], &my_fields->grid_end[2],
  668.                        &my_fields->grid_dimension[0], &my_fields->grid_dimension[1], &my_fields->grid_dimension[2], &my_chemistry->primordial_chemistry, imetal, &my_chemistry->use_dust_density_field,
  669.                       DM.data(), HDII.data(), HeHII.data(),
  670.                       &my_chemistry->metal_abundances, &my_chemistry->metal_chemistry, &my_chemistry->dust_species, &my_chemistry->multi_metals,
  671.                       &my_chemistry->grain_growth, &my_chemistry->dust_sublimation,
  672.                       CI.data(), CII.data(), CO.data(), CO2.data(),
  673.                       OI.data(), OH.data(), H2O.data(), O2.data(),
  674.                       SiI.data(), SiOI.data(), SiO2I.data(),
  675.                       CH.data(), CH2.data(), COII.data(), OII.data(),
  676.                       OHII.data(), H2OII.data(), H3OII.data(), O2II.data(),
  677.                       Mg.data(), Al.data(), S.data(), Fe.data(),
  678.                       SiM.data(), FeM.data(), Mg2SiO4.data(), MgSiO3.data(), Fe3O4.data(),
  679.                       AC.data(), SiO2D.data(), MgO.data(), FeS.data(), Al2O3.data(),
  680.                       reforg.data(), volorg.data(), H2Oice.data(),
  681.                       metal_loc.data(),
  682.                       metal_C13.data(), metal_C20.data(), metal_C25.data(), metal_C30.data(),
  683.                       metal_F13.data(), metal_F15.data(), metal_F50.data(), metal_F80.data(),
  684.                       metal_P170.data(), metal_P200.data(), metal_Y19.data());
  685. #endif
  686.  
  687.  
  688.   // Loop over zones, and do an entire i-column in one go
  689.   dk = my_fields->grid_end[2] - my_fields->grid_start[2] + 1;
  690.   dj = my_fields->grid_end[1] - my_fields->grid_start[1] + 1;
  691.  
  692.   // parallelize the k and j loops with OpenMP
  693.   // flat j and k loops for better parallelism
  694.   //_// PORT: #ifdef _OPENMP
  695.   //_// PORT: ! ierr is declared as shared and should be modified with atomic operation
  696.   //_// PORT: !$omp parallel do schedule(runtime) private(
  697.   //_// PORT: !$omp&   i, j, k, iter,
  698.   //_// PORT: !$omp&   ttmin, energy, comp1, comp2,
  699.   //_// PORT: !$omp&   heq1, heq2, eqk221, eqk222, eqk131, eqk132,
  700.   //_// PORT: !$omp&   eqt1, eqt2, eqtdef, dheq, heq,
  701.   //_// PORT: !$omp&   indixe,
  702.   //_// PORT: !$omp&   t1, t2, logtem, tdef,
  703.   //_// PORT: !$omp&   dtit, ttot, p2d, tgas, tgasold,
  704.   //_// PORT: !$omp&   tdust, metallicity, dust2gas, rhoH, mmw,
  705.   //_// PORT: !$omp&   mynh, myde, gammaha_eff, gasgr_tdust, regr, ddom,
  706.   //_// PORT: !$omp&   olddtit,
  707.   //_// PORT: !$omp&   HIp, HIIp, HeIp, HeIIp, HeIIIp,
  708.   //_// PORT: !$omp&   HMp, H2Ip, H2IIp,
  709.   //_// PORT: !$omp&   dep, dedot,HIdot, dedot_prev,
  710.   //_// PORT: !$omp&   DIp, DIIp, HDIp, HIdot_prev,
  711.   //_// PORT: !$omp&   k24shield, k25shield, k26shield,
  712.   //_// PORT: !$omp&   k28shield, k29shield, k30shield,
  713.   //_// PORT: !$omp&   k31shield,
  714.   //_// PORT: !$omp&   k1 , k2 , k3 , k4 , k5,
  715.   //_// PORT: !$omp&   k6 , k7 , k8 , k9 , k10,
  716.   //_// PORT: !$omp&   k11, k12, k13, k14, k15,
  717.   //_// PORT: !$omp&   k16, k17, k18, k19, k22,
  718.   //_// PORT: !$omp&   k50, k51, k52, k53, k54,
  719.   //_// PORT: !$omp&   k55, k56, k57, k58, k13dd, h2dust,
  720.   //_// PORT: !$omp&   ncrn, ncrd1, ncrd2,
  721.   //_// PORT: !$omp&   ceHI, ceHeI, ceHeII,
  722.   //_// PORT: !$omp&   ciHI, ciHeI, ciHeIS, ciHeII,
  723.   //_// PORT: !$omp&   reHII, reHeII1, reHeII2, reHeIII,
  724.   //_// PORT: !$omp&   brem, edot,
  725.   //_// PORT: !$omp&   hyd01k, h2k01, vibh, roth, rotl,
  726.   //_// PORT: !$omp&   gpldl, gphdl, hdlte, hdlow, cieco,
  727.   //_// PORT: !$omp&   itmask, itmask_metal )
  728.   //_// PORT: #endif
  729.   for (t = 0; t<=(dk * dj - 1); t++) {
  730.     k = t/dj      + my_fields->grid_start[2]+1;
  731.     j = grackle::impl::mod(t,dj) + my_fields->grid_start[1]+1;
  732.  
  733.     // tolerance = 1.0e-06_DKIND * dt
  734.  
  735.     // Initialize iteration mask to true for all cells.
  736.  
  737.     for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  738.       itmask[i-1] = MASK_TRUE;
  739.     }
  740.  
  741.     // If we are using coupled radiation with intermediate stepping,
  742.     // set iteration mask to include only cells with radiation in the
  743.     // intermediate coupled chemistry / energy step
  744.     if (my_chemistry->use_radiative_transfer == 1)  {
  745.       if (my_chemistry->radiative_transfer_coupled_rate_solver == 1  &&  my_chemistry->radiative_transfer_intermediate_step == 1)  {
  746.         for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  747.           if (kphHI(i-1,j-1,k-1) > 0)  {
  748.             itmask[i-1] = MASK_TRUE;
  749.           } else {
  750.             itmask[i-1] = MASK_FALSE;
  751.           }
  752.         }
  753.       }
  754.  
  755.       // Normal rate solver, but don't double count cells with radiation
  756.       if (my_chemistry->radiative_transfer_coupled_rate_solver == 1  &&  my_chemistry->radiative_transfer_intermediate_step == 0)  {
  757.         for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  758.           if (kphHI(i-1,j-1,k-1) > 0)  {
  759.             itmask[i-1] = MASK_FALSE;
  760.           } else {
  761.             itmask[i-1] = MASK_TRUE;
  762.           }
  763.         }
  764.       }
  765.     }
  766.  
  767.     // Set time elapsed to zero for each cell in 1D section
  768.  
  769.     for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  770.       ttot[i-1] = 0.;
  771.     }
  772.  
  773.     // A useful slice variable since we do this a lot
  774.  
  775.     for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  776.       ddom[i-1] = d(i-1,j-1,k-1) * dom;
  777.     }
  778.  
  779.     // ------------------ Loop over subcycles ----------------
  780.  
  781.     for (iter = 1; iter<=(my_chemistry->max_iterations); iter++) {
  782.  
  783.       for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  784.         if (itmask[i-1] != MASK_FALSE)  {
  785.           dtit[i-1] = huge8;
  786.         }
  787.       }
  788.  
  789.       // Compute the cooling rate, tgas, tdust, and metallicity for this row// Look-up rates as a function of temperature for 1D set of zones
  790.         //  (maybe should add itmask to this call)// Compute dedot and HIdot, the rates of change of de and HI
  791.         //   (should add itmask to this call)
  792.  
  793.          FORTRAN_NAME(rate_timestep_g)(
  794.                        dedot.data(), HIdot.data(), &my_chemistry->primordial_chemistry, &anydust,
  795.                        de.data(), HI.data(), HII.data(), HeI.data(), HeII.data(), HeIII.data(), d.data(),
  796.                        HM.data(), H2I.data(), H2II.data(),
  797.                        &my_fields->grid_dimension[0], &my_fields->grid_dimension[1], &my_fields->grid_dimension[2], &my_fields->grid_start[0], &my_fields->grid_end[0], &j, &k,
  798.                        k1.data(), k2.data(), k3.data(), k4.data(), k5.data(), k6.data(), k7.data(), k8.data(), k9.data(), k10.data(), k11.data(),
  799.                        k12.data(), k13.data(), k14.data(), k15.data(), k16.data(), k17.data(), k18.data(), k19.data(), k22.data(),
  800.                        &my_uvb_rates->k24, &my_uvb_rates->k25, &my_uvb_rates->k26, &my_uvb_rates->k27, &my_uvb_rates->k28, &my_uvb_rates->k29, &my_uvb_rates->k30,
  801.                        k50.data(), k51.data(), k52.data(), k53.data(), k54.data(), k55.data(), k56.data(), k57.data(), k58.data(),
  802.                        h2dust.data(), ncrn.data(), ncrd1.data(), ncrd2.data(), rhoH.data(),
  803.                        k24shield.data(), k25shield.data(), k26shield.data(),
  804.                        k28shield.data(), k29shield.data(), k30shield.data(), k31shield.data(),
  805.                        &my_chemistry->use_radiative_transfer, &my_chemistry->radiative_transfer_hydrogen_only,
  806.                        kphHI.data(), kphHeI.data(), kphHeII.data(),
  807.                        itmask.data(), edot.data(), &chunit, &dom, metal.data(),
  808.                       HDI.data(), &my_chemistry->metal_chemistry, CI.data(), OI.data(), OH.data(), CO.data(), H2O.data(),
  809.                       &my_chemistry->radiative_transfer_HDI_dissociation, kdissHDI.data(), &my_chemistry->radiative_transfer_metal_ionization, kphCI.data(), kphOI.data(),
  810.                       &my_chemistry->radiative_transfer_metal_dissociation, kdissCO.data(), kdissOH.data(), kdissH2O.data()
  811.                             );
  812.  
  813.         // move itmask temporary array
  814.         // then split cells with low densities
  815.         //    => Gauss-Seidel scheme
  816.         //              and with high densities
  817.         //    => Newton-Raphson scheme
  818.  
  819.         std::memcpy(itmask_tmp.data(), itmask.data(), sizeof(gr_mask_type)*my_fields->grid_dimension[0]);
  820.         std::memcpy(itmask_nr.data(), itmask.data(), sizeof(gr_mask_type)*my_fields->grid_dimension[0]);
  821.         for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  822.           if ( itmask_tmp[i-1] != MASK_FALSE )  {
  823.  
  824.             if ( ( ((*imetal) == 0)
  825.               &&  (ddom[i-1] < 1.e8) )
  826.              ||  ( ((*imetal) == 1)
  827.               &&  ( ( (metallicity[i-1] <= min_metallicity)
  828.                   &&  (ddom[i-1] < 1.e8) )
  829.                  ||  ( (metallicity[i-1] > min_metallicity)
  830.                   &&  (ddom[i-1] < 1.e6) ) ) ) )  {
  831.               itmask_nr[i-1] = MASK_FALSE;
  832.             } else {
  833.               itmask[i-1] = MASK_FALSE;
  834.             }
  835.  
  836.           }
  837.         }
  838.  
  839.         for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  840.           if (itmask_nr[i-1] != MASK_FALSE)  {
  841.             if ( (my_chemistry->with_radiative_cooling == 1)  &&  (my_chemistry->primordial_chemistry > 1)  &&
  842.                  ((ddom[i-1] > 1.e7)
  843.              && (tgas[i-1] > 1650.e0)) )  {
  844.               imp_eng[i-1] = 1;
  845.             } else {
  846.               imp_eng[i-1] = 0;
  847.             }
  848.           }
  849.         }
  850.  
  851.         // Find timestep that keeps relative chemical changes below 10%
  852.  
  853.         for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  854.           if (itmask[i-1] != MASK_FALSE)  {
  855.             // Bound from below to prevent numerical errors
  856.                
  857.             if (std::fabs(dedot[i-1]) < tiny8)
  858.                        { dedot[i-1] = std::fmin(tiny,de(i-1,j-1,k-1)); }
  859.             if (std::fabs(HIdot[i-1]) < tiny8)
  860.                        { HIdot[i-1] = std::fmin(tiny,HI(i-1,j-1,k-1)); }
  861.  
  862.             // If the net rate is almost perfectly balanced then set
  863.             //     it to zero (since it is zero to available precision)
  864.  
  865.             if (std::fmin(std::fabs(k1[i-1]* de(i-1,j-1,k-1)*HI(i-1,j-1,k-1)),
  866.                     std::fabs(k2[i-1]*HII(i-1,j-1,k-1)*de(i-1,j-1,k-1)))/
  867.                 std::fmax(std::fabs(dedot[i-1]),std::fabs(HIdot[i-1])) >
  868.                  1.0e6)  {
  869.               dedot[i-1] = tiny8;
  870.               HIdot[i-1] = tiny8;
  871.             }
  872.  
  873.             // If the iteration count is high then take the smaller of
  874.             //   the calculated dedot and last time step's actual dedot.
  875.             //   This is intended to get around the problem of a low
  876.             //   electron or HI fraction which is in equilibrium with high
  877.             //   individual terms (which all nearly cancel).
  878.  
  879.             if (iter > 50)  {
  880.               dedot[i-1] = std::fmin(std::fabs(dedot[i-1]), std::fabs(dedot_prev[i-1]));
  881.               HIdot[i-1] = std::fmin(std::fabs(HIdot[i-1]), std::fabs(HIdot_prev[i-1]));
  882.             }
  883.  
  884.             // compute minimum rate timestep
  885.  
  886.             olddtit = dtit[i-1];
  887.             dtit[i-1] = grackle::impl::fmin(std::fabs(0.1*de(i-1,j-1,k-1)/dedot[i-1]),
  888.                  std::fabs(0.1*HI(i-1,j-1,k-1)/HIdot[i-1]),
  889.                  (*dt)-ttot[i-1], 0.5*(*dt));
  890.  
  891.             if (ddom[i-1] > 1.e8  &&
  892.                  edot[i-1] > 0.       &&
  893.                 my_chemistry->primordial_chemistry > 1)  {
  894.               // Equilibrium value for H is:
  895.               // H = (-1._DKIND / (4*k22)) * (k13 - sqrt(8 k13 k22 rho + k13^2))
  896.               // We now want this to change by 10% or less, but we're only
  897.               // differentiating by dT.  We have de/dt.  We need dT/de.
  898.               // T = (g-1)*p2d*utem/N; tgas == (g-1)(p2d*utem/N)
  899.               // dH_eq / dt = (dH_eq/dT) * (dT/de) * (de/dt)
  900.               // dH_eq / dT (see above; we can calculate the derivative here)
  901.               // dT / de = utem * (gamma - 1._DKIND) / N == tgas / p2d
  902.               // de / dt = edot
  903.               // Now we use our estimate of dT/de to get the estimated
  904.               // difference in the equilibrium
  905.               eqt2 = std::fmin(std::log(tgas[i-1]) + 0.1*dlogtem, t2[i-1]);
  906.               eqtdef = (eqt2 - t1[i-1])/(t2[i-1] - t1[i-1]);
  907.               eqk222 = my_rates->k22[indixe[i-1]-1] +
  908.                 (my_rates->k22[indixe[i-1]+1-1] -my_rates->k22[indixe[i-1]-1])*eqtdef;
  909.               eqk132 = my_rates->k13[indixe[i-1]-1] +
  910.                 (my_rates->k13[indixe[i-1]+1-1] -my_rates->k13[indixe[i-1]-1])*eqtdef;
  911.               heq2 = (-1. / (4.*eqk222)) * (eqk132-
  912.                    std::sqrt(8.*eqk132*eqk222*
  913.                    my_chemistry->HydrogenFractionByMass*d(i-1,j-1,k-1)+std::pow(eqk132,2.)));
  914.  
  915.               eqt1 = std::fmax(std::log(tgas[i-1]) - 0.1*dlogtem, t1[i-1]);
  916.               eqtdef = (eqt1 - t1[i-1])/(t2[i-1] - t1[i-1]);
  917.               eqk221 = my_rates->k22[indixe[i-1]-1] +
  918.                 (my_rates->k22[indixe[i-1]+1-1] -my_rates->k22[indixe[i-1]-1])*eqtdef;
  919.               eqk131 = my_rates->k13[indixe[i-1]-1] +
  920.                 (my_rates->k13[indixe[i-1]+1-1] -my_rates->k13[indixe[i-1]-1])*eqtdef;
  921.               heq1 = (-1. / (4.*eqk221)) * (eqk131-
  922.                    std::sqrt(8.*eqk131*eqk221*
  923.                    my_chemistry->HydrogenFractionByMass*d(i-1,j-1,k-1)+std::pow(eqk131,2.)));
  924.  
  925.               dheq = (std::fabs(heq2-heq1)/(std::exp(eqt2) - std::exp(eqt1)))
  926.                    * (tgas[i-1]/p2d[i-1]) * edot[i-1];
  927.               heq = (-1. / (4.*k22[i-1])) * (k13[i-1]-
  928.                    std::sqrt(8.*k13[i-1]*k22[i-1]*
  929.                    my_chemistry->HydrogenFractionByMass*d(i-1,j-1,k-1)+std::pow(k13[i-1],2.)));
  930.               dtit[i-1] = std::fmin(dtit[i-1], 0.1*heq/dheq);
  931.             }
  932.             if (iter>10LL)  {
  933.               dtit[i-1] = std::fmin(olddtit*1.5, dtit[i-1]);
  934.             }
  935.  
  936.           } else if ((itmask_nr[i-1]!=MASK_FALSE) &&
  937.                    (imp_eng[i-1]==0))  {
  938.             dtit[i-1] = grackle::impl::fmin(std::fabs(0.1*e(i-1,j-1,k-1)/edot[i-1]*d(i-1,j-1,k-1)),
  939.                  (*dt)-ttot[i-1], 0.5*(*dt));
  940.  
  941.           } else if ((itmask_nr[i-1]!=MASK_FALSE) &&
  942.                    (imp_eng[i-1]==1))  {
  943.             dtit[i-1] = (*dt) - ttot[i-1];
  944.  
  945.           } else {
  946.             dtit[i-1] = (*dt);
  947.           }
  948.         }
  949.  
  950.       }
  951.  
  952.       // Compute maximum timestep for cooling/heating
  953.  
  954.       for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  955.         if (itmask[i-1] != MASK_FALSE)  {
  956.           // Set energy per unit volume of this cell based in the pressure
  957.           // (the gamma used here is the right one even for H2 since p2d
  958.           //  is calculated with this gamma).
  959.  
  960.           energy = std::fmax(p2d[i-1]/(my_chemistry->Gamma-1.), tiny8);
  961.  
  962.           // If the temperature is at the bottom of the temperature look-up
  963.           // table and edot < 0, then shut off the cooling.
  964.  
  965.           if (tgas[i-1] <= 1.01*my_chemistry->TemperatureStart  &&
  966.                edot[i-1] < 0.)
  967.                { edot[i-1] = tiny8; }
  968.           if (std::fabs(edot[i-1]) < tiny8) { edot[i-1] = tiny8; }
  969.  
  970.           // Compute timestep for 10% change
  971.  
  972.           dtit[i-1] = grackle::impl::fmin((double)(std::fabs(0.1*
  973.             energy/edot[i-1]) ),
  974.             (*dt)-ttot[i-1], dtit[i-1]);
  975.  
  976.           if (dtit[i-1] != dtit[i-1])  {
  977.             OMP_PRAGMA_CRITICAL
  978.             {
  979.               eprintf("HUGE dtit ::  %g %g %g %g %g %g %g\n",
  980.                       energy,
  981.                       edot [ i-1 ],
  982.                       dtit [ i-1 ],
  983.                       (*dt),
  984.                       ttot [ i-1 ],
  985.                       std::fabs ( 0.1 * energy / edot [ i-1 ] ),
  986.                       (double) ( std::fabs ( 0.1 * energy / edot [ i-1 ] ) ));
  987.             }
  988.           }
  989.  
  990.         }
  991.       }
  992.  
  993.       // Update total and gas energy
  994.  
  995.       if (my_chemistry->with_radiative_cooling == 1)  {
  996.         for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  997.           if (itmask[i-1] != MASK_FALSE)  {
  998.             e(i-1,j-1,k-1)  = e(i-1,j-1,k-1) +
  999.                     (gr_float)(edot[i-1]/d(i-1,j-1,k-1)*dtit[i-1] );
  1000.  
  1001.           }
  1002.         }
  1003.       }
  1004.  
  1005.       if (my_chemistry->primordial_chemistry > 0)  {
  1006.  
  1007.         // Solve rate equations with one linearly implicit Gauss-Seidel
  1008.         // sweep of a backward Euler method ---
  1009.  
  1010.          FORTRAN_NAME(step_rate_g)(de.data(), HI.data(), HII.data(), HeI.data(), HeII.data(), HeIII.data(), d.data(),
  1011.                        HM.data(), H2I.data(), H2II.data(), DI.data(), DII.data(), HDI.data(), dtit.data(),
  1012.                        &my_fields->grid_dimension[0], &my_fields->grid_dimension[1], &my_fields->grid_dimension[2], &my_fields->grid_start[0], &my_fields->grid_end[0], &j, &k,
  1013.                        &my_chemistry->primordial_chemistry, &anydust,
  1014.                        k1.data(), k2.data(), k3.data(), k4.data(), k5.data(), k6.data(), k7.data(), k8.data(), k9.data(), k10.data(), k11.data(),
  1015.                        k12.data(), k13.data(), k14.data(), k15.data(), k16.data(), k17.data(), k18.data(), k19.data(), k22.data(),
  1016.                        &my_uvb_rates->k24, &my_uvb_rates->k25, &my_uvb_rates->k26, &my_uvb_rates->k27, &my_uvb_rates->k28, &my_uvb_rates->k29, &my_uvb_rates->k30,
  1017.                        k50.data(), k51.data(), k52.data(), k53.data(), k54.data(), k55.data(), k56.data(), k57.data(), k58.data(),
  1018.                        h2dust.data(), rhoH.data(),
  1019.                        k24shield.data(), k25shield.data(), k26shield.data(),
  1020.                        k28shield.data(), k29shield.data(), k30shield.data(), k31shield.data(),
  1021.                        HIp.data(), HIIp.data(), HeIp.data(), HeIIp.data(), HeIIIp.data(), dep.data(),
  1022.                        HMp.data(), H2Ip.data(), H2IIp.data(), DIp.data(), DIIp.data(), HDIp.data(),
  1023.                        dedot_prev.data(), HIdot_prev.data(),
  1024.                        &my_chemistry->use_radiative_transfer, &my_chemistry->radiative_transfer_hydrogen_only,
  1025.                        kphHI.data(), kphHeI.data(), kphHeII.data(),
  1026.                        itmask.data(), itmask_metal.data(),
  1027.                       DM.data(), HDII.data(), HeHII.data(), imetal, metal.data(),
  1028.                       &my_chemistry->metal_chemistry, &my_chemistry->dust_species, &my_chemistry->grain_growth, &my_chemistry->dust_sublimation,
  1029.                       CI.data(), CII.data(), CO.data(), CO2.data(),
  1030.                       OI.data(), OH.data(), H2O.data(), O2.data(),
  1031.                       SiI.data(), SiOI.data(), SiO2I.data(),
  1032.                       CH.data(), CH2.data(), COII.data(), OII.data(),
  1033.                       OHII.data(), H2OII.data(), H3OII.data(), O2II.data(),
  1034.                       Mg.data(), Al.data(), S.data(), Fe.data(),
  1035.                       SiM.data(), FeM.data(), Mg2SiO4.data(), MgSiO3.data(), Fe3O4.data(),
  1036.                       AC.data(), SiO2D.data(), MgO.data(), FeS.data(), Al2O3.data(),
  1037.                       reforg.data(), volorg.data(), H2Oice.data(),
  1038.                       k125.data(), k129.data(), k130.data(), k131.data(), k132.data(),
  1039.                       k133.data(), k134.data(), k135.data(), k136.data(), k137.data(),
  1040.                       k148.data(), k149.data(), k150.data(), k151.data(), k152.data(),
  1041.                       k153.data(),
  1042.                       kz15.data(),  kz16.data(),  kz17.data(),  kz18.data(),  kz19.data(),
  1043.                       kz20.data(),  kz21.data(),  kz22.data(),  kz23.data(),  kz24.data(),
  1044.                       kz25.data(),  kz26.data(),  kz27.data(),  kz28.data(),  kz29.data(),
  1045.                       kz30.data(),  kz31.data(),  kz32.data(),  kz33.data(),  kz34.data(),
  1046.                       kz35.data(),  kz36.data(),  kz37.data(),  kz38.data(),  kz39.data(),
  1047.                       kz40.data(),  kz41.data(),  kz42.data(),  kz43.data(),  kz44.data(),
  1048.                       kz45.data(),  kz46.data(),  kz47.data(),  kz48.data(),  kz49.data(),
  1049.                       kz50.data(),  kz51.data(),  kz52.data(),  kz53.data(),  kz54.data(),
  1050.                       DMp.data(), HDIIp.data(), HeHIIp.data(),
  1051.                       CIp.data(), CIIp.data(), COp.data(), CO2p.data(),
  1052.                       OIp.data(), OHp.data(), H2Op.data(), O2p.data(),
  1053.                       SiIp.data(), SiOIp.data(), SiO2Ip.data(),
  1054.                       CHp.data(), CH2p.data(), COIIp.data(), OIIp.data(),
  1055.                       OHIIp.data(), H2OIIp.data(), H3OIIp.data(), O2IIp.data(),
  1056.                       Mgp.data(), Alp.data(), Sp.data(), Fep.data(),
  1057.                       SiMp.data(), FeMp.data(), Mg2SiO4p.data(), MgSiO3p.data(), Fe3O4p.data(),
  1058.                       ACp.data(), SiO2Dp.data(), MgOp.data(), FeSp.data(), Al2O3p.data(),
  1059.                       reforgp.data(), volorgp.data(), H2Oicep.data(),
  1060.                       kdSiM.data(), kdFeM.data(), kdMg2SiO4.data(), kdMgSiO3.data(), kdFe3O4.data(),
  1061.                       kdAC.data(), kdSiO2D.data(), kdMgO.data(), kdFeS.data(), kdAl2O3.data(),
  1062.                       kdreforg.data(), kdvolorg.data(), kdH2Oice.data(),
  1063.                       &my_chemistry->radiative_transfer_HDI_dissociation, kdissHDI.data(), &my_chemistry->radiative_transfer_metal_ionization, kphCI.data(), kphOI.data(),
  1064.                       &my_chemistry->radiative_transfer_metal_dissociation, kdissCO.data(), kdissOH.data(), kdissH2O.data()
  1065.              );
  1066.  
  1067.         // Note 10/18/2024: the code from here to the comment "end Newton-Raphson scheme"
  1068.         // should be put into its own function.
  1069.         //       Start Newton-Raphson scheme
  1070.         for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  1071.           if (itmask_nr[i-1] != MASK_FALSE)  {
  1072.  
  1073.             // If density and temperature are low, update gas energy explicitly
  1074.  
  1075.             if (my_chemistry->with_radiative_cooling == 1)  {
  1076.               if (imp_eng[i-1] == 0)  {
  1077.                 e(i-1,j-1,k-1)  = e(i-1,j-1,k-1) +
  1078.                      (gr_float)(edot[i-1]/d(i-1,j-1,k-1)*dtit[i-1] );
  1079.               }
  1080.             }
  1081.  
  1082.             // initialize arrays
  1083.             if (my_chemistry->primordial_chemistry > 0) { nsp = 6; }
  1084.             if (my_chemistry->primordial_chemistry > 1) { nsp = nsp + 3; }
  1085.             if (my_chemistry->primordial_chemistry > 2) { nsp = nsp + 3; }
  1086.             if (my_chemistry->primordial_chemistry > 3) { nsp = nsp + 3; }
  1087.             if (itmask_metal[i-1] != MASK_FALSE)  {
  1088.               if (my_chemistry->metal_chemistry == 1)  {
  1089.                 nsp = nsp + 19;
  1090.                 if ( ( my_chemistry->grain_growth == 1 )  ||  ( my_chemistry->dust_sublimation == 1) )  {
  1091.                   if (my_chemistry->dust_species > 0) { nsp = nsp + 1; }
  1092.                   if (my_chemistry->dust_species > 1) { nsp = nsp + 3; }
  1093.                 }
  1094.               }
  1095.               if ( ( my_chemistry->grain_growth == 1 )  ||  ( my_chemistry->dust_sublimation == 1) )  {
  1096.                 if (my_chemistry->dust_species > 0) { nsp = nsp + 2; }
  1097.                 if (my_chemistry->dust_species > 1) { nsp = nsp + 8; }
  1098.                 if (my_chemistry->dust_species > 2) { nsp = nsp + 3; }
  1099.               }
  1100.             }
  1101.             nsp = nsp + imp_eng[i-1];
  1102.             idsp.reserve(nsp);
  1103.             mtrx_data_.reserve(nsp * nsp);
  1104.             mtrx = grackle::impl::View<double**>(mtrx_data_.data(), nsp, nsp);
  1105.             vec.reserve(nsp);
  1106.  
  1107.             if ( my_chemistry->primordial_chemistry > 0 )  {
  1108.               dsp[ 1-1] = de(i-1,j-1,k-1);
  1109.               dsp[ 2-1] = HI(i-1,j-1,k-1);
  1110.               dsp[ 3-1] = HII(i-1,j-1,k-1);
  1111.               dsp[ 4-1] = HeI(i-1,j-1,k-1);
  1112.               dsp[ 5-1] = HeII(i-1,j-1,k-1);
  1113.               dsp[ 6-1] = HeIII(i-1,j-1,k-1);
  1114.             }
  1115.             if ( my_chemistry->primordial_chemistry > 1 )  {
  1116.               dsp[ 7-1] = HM(i-1,j-1,k-1);
  1117.               dsp[ 8-1] = H2I(i-1,j-1,k-1);
  1118.               dsp[ 9-1] = H2II(i-1,j-1,k-1);
  1119.             }
  1120.             if ( my_chemistry->primordial_chemistry > 2 )  {
  1121.               dsp[10-1] = DI(i-1,j-1,k-1);
  1122.               dsp[11-1] = DII(i-1,j-1,k-1);
  1123.               dsp[12-1] = HDI(i-1,j-1,k-1);
  1124.             }
  1125.             if ( my_chemistry->primordial_chemistry > 3 )  {
  1126.               dsp[13-1] = DM(i-1,j-1,k-1);
  1127.               dsp[14-1] = HDII(i-1,j-1,k-1);
  1128.               dsp[15-1] = HeHII(i-1,j-1,k-1);
  1129.             }
  1130.             if ( itmask_metal[i-1] != MASK_FALSE )  {
  1131.               if ( my_chemistry->metal_chemistry == 1 )  {
  1132.                 dsp[16-1] = CI(i-1,j-1,k-1);
  1133.                 dsp[17-1] = CII(i-1,j-1,k-1);
  1134.                 dsp[18-1] = CO(i-1,j-1,k-1);
  1135.                 dsp[19-1] = CO2(i-1,j-1,k-1);
  1136.                 dsp[20-1] = OI(i-1,j-1,k-1);
  1137.                 dsp[21-1] = OH(i-1,j-1,k-1);
  1138.                 dsp[22-1] = H2O(i-1,j-1,k-1);
  1139.                 dsp[23-1] = O2(i-1,j-1,k-1);
  1140.                 dsp[24-1] = SiI(i-1,j-1,k-1);
  1141.                 dsp[25-1] = SiOI(i-1,j-1,k-1);
  1142.                 dsp[26-1] = SiO2I(i-1,j-1,k-1);
  1143.                 dsp[27-1] = CH(i-1,j-1,k-1);
  1144.                 dsp[28-1] = CH2(i-1,j-1,k-1);
  1145.                 dsp[29-1] = COII(i-1,j-1,k-1);
  1146.                 dsp[30-1] = OII(i-1,j-1,k-1);
  1147.                 dsp[31-1] = OHII(i-1,j-1,k-1);
  1148.                 dsp[32-1] = H2OII(i-1,j-1,k-1);
  1149.                 dsp[33-1] = H3OII(i-1,j-1,k-1);
  1150.                 dsp[34-1] = O2II(i-1,j-1,k-1);
  1151.                 if ( ( my_chemistry->grain_growth == 1 )  ||  ( my_chemistry->dust_sublimation == 1) )  {
  1152.                   if (my_chemistry->dust_species > 0)  {
  1153.                     dsp[35-1] = Mg(i-1,j-1,k-1);
  1154.                   }
  1155.                   if (my_chemistry->dust_species > 1)  {
  1156.                     dsp[36-1] = Al(i-1,j-1,k-1);
  1157.                     dsp[37-1] = S(i-1,j-1,k-1);
  1158.                     dsp[38-1] = Fe(i-1,j-1,k-1);
  1159.                   }
  1160.                 }
  1161.               }
  1162.               if ( ( my_chemistry->grain_growth == 1 )  ||  ( my_chemistry->dust_sublimation == 1) )  {
  1163.                 if (my_chemistry->dust_species > 0)  {
  1164.                   dsp[39-1] = MgSiO3(i-1,j-1,k-1);
  1165.                   dsp[40-1] = AC(i-1,j-1,k-1);
  1166.                 }
  1167.                 if (my_chemistry->dust_species > 1)  {
  1168.                   dsp[41-1] = SiM(i-1,j-1,k-1);
  1169.                   dsp[42-1] = FeM(i-1,j-1,k-1);
  1170.                   dsp[43-1] = Mg2SiO4(i-1,j-1,k-1);
  1171.                   dsp[44-1] = Fe3O4(i-1,j-1,k-1);
  1172.                   dsp[45-1] = SiO2D(i-1,j-1,k-1);
  1173.                   dsp[46-1] = MgO(i-1,j-1,k-1);
  1174.                   dsp[47-1] = FeS(i-1,j-1,k-1);
  1175.                   dsp[48-1] = Al2O3(i-1,j-1,k-1);
  1176.                 }
  1177.                 if (my_chemistry->dust_species > 2)  {
  1178.                   dsp[49-1] = reforg(i-1,j-1,k-1);
  1179.                   dsp[50-1] = volorg(i-1,j-1,k-1);
  1180.                   dsp[51-1] = H2Oice(i-1,j-1,k-1);
  1181.                 }
  1182.               }
  1183.             }
  1184.             dsp[i_eng-1] = e(i-1,j-1,k-1);
  1185.  
  1186.             id = 0;
  1187.             if (my_chemistry->primordial_chemistry > 0)  {
  1188.               for (isp = 1; isp<=(6); isp++) {
  1189.                 id = id + 1;
  1190.                 idsp[id-1] = isp;
  1191.               }
  1192.             }
  1193.             if (my_chemistry->primordial_chemistry > 1)  {
  1194.               for (isp = 7; isp<=(9); isp++) {
  1195.                 id = id + 1;
  1196.                 idsp[id-1] = isp;
  1197.               }
  1198.             }
  1199.             if (my_chemistry->primordial_chemistry > 2)  {
  1200.               for (isp = 10; isp<=(12); isp++) {
  1201.                 id = id + 1;
  1202.                 idsp[id-1] = isp;
  1203.               }
  1204.             }
  1205.             if (my_chemistry->primordial_chemistry > 3)  {
  1206.               for (isp = 13; isp<=(15); isp++) {
  1207.                 id = id + 1;
  1208.                 idsp[id-1] = isp;
  1209.               }
  1210.             }
  1211.             if (itmask_metal[i-1] != MASK_FALSE)  {
  1212.               if (my_chemistry->metal_chemistry == 1)  {
  1213.                 for (isp = 16; isp<=(34); isp++) {
  1214.                   id = id + 1;
  1215.                   idsp[id-1] = isp;
  1216.                 }
  1217.                 if ( ( my_chemistry->grain_growth == 1 )  ||  ( my_chemistry->dust_sublimation == 1) )  {
  1218.                   if (my_chemistry->dust_species > 0)  {
  1219.                     for (isp = 35; isp<=(35); isp++) {
  1220.                       id = id + 1;
  1221.                       idsp[id-1] = isp;
  1222.                     }
  1223.                   }
  1224.                   if (my_chemistry->dust_species > 1)  {
  1225.                     for (isp = 36; isp<=(38); isp++) {
  1226.                       id = id + 1;
  1227.                       idsp[id-1] = isp;
  1228.                     }
  1229.                   }
  1230.                 }
  1231.               }
  1232.               if ( ( my_chemistry->grain_growth == 1 )  ||  ( my_chemistry->dust_sublimation == 1) )  {
  1233.                 if (my_chemistry->dust_species > 0)  {
  1234.                   for (isp = 39; isp<=(40); isp++) {
  1235.                     id = id + 1;
  1236.                     idsp[id-1] = isp;
  1237.                   }
  1238.                 }
  1239.                 if (my_chemistry->dust_species > 1)  {
  1240.                   for (isp = 41; isp<=(48); isp++) {
  1241.                     id = id + 1;
  1242.                     idsp[id-1] = isp;
  1243.                   }
  1244.                 }
  1245.                 if (my_chemistry->dust_species > 2)  {
  1246.                   for (isp = 49; isp<=(51); isp++) {
  1247.                     id = id + 1;
  1248.                     idsp[id-1] = isp;
  1249.                   }
  1250.                 }
  1251.               }
  1252.             }
  1253.             if ( imp_eng[i-1] ==1 )  {
  1254.               id = id + 1;
  1255.               idsp[id-1] = i_eng;
  1256.             }
  1257.  
  1258.             // Save arrays at ttot(i)
  1259.  
  1260.             std::memcpy(dsp0.data(), dsp.data(), sizeof(double)*i_eng);
  1261.             std::memset(ddsp.data(), 0, sizeof(double)*i_eng);
  1262.  
  1263.             // Search for the timestep for which chemistry converges
  1264.  
  1265.             ierror=1;
  1266.             itr_time=0;
  1267.             while ((ierror==1)) {
  1268.  
  1269.               // If not converge, restore arrays at ttot(i)
  1270.  
  1271.               std::memcpy(dsp.data(), dsp0.data(), sizeof(double)*i_eng);
  1272.               std::memset(ddsp.data(), 0, sizeof(double)*i_eng);
  1273.  
  1274.               // Iteration to solve ODEs// to get more accuracy
  1275.                 for (isp = 1; isp<=(nsp); isp++) {
  1276.                   vec[isp-1] = vec[isp-1]/d(i-1,j-1,k-1);
  1277.                 }
  1278.  
  1279.                  FORTRAN_NAME(gaussj_g)(&nsp, mtrx.data(), vec.data(), &ierror);
  1280.                 if(ierror == 1)  {
  1281.                   goto label_9998;
  1282.                 }
  1283.  
  1284.                 // multiply with density again
  1285.                 for (isp = 1; isp<=(nsp); isp++) {
  1286.                   vec[isp-1] = vec[isp-1]*d(i-1,j-1,k-1);
  1287.                 }
  1288.  
  1289.                 for (isp = 1; isp<=(nsp); isp++) {
  1290.                   ddsp[idsp[isp-1]-1] = ddsp[idsp[isp-1]-1] + vec[isp-1];
  1291.                   dsp[idsp[isp-1]-1]  = dsp[idsp[isp-1]-1]  + vec[isp-1];
  1292.                 }
  1293.  
  1294.                 if (imp_eng[i-1] == 1)  {
  1295.                   if( (my_chemistry->primordial_chemistry > 0)  &&  (my_chemistry->with_radiative_cooling == 1) )  {
  1296.                     for (isp = 1; isp<=(nsp); isp++) {
  1297.                       if ( (dsp[idsp[isp-1]-1] != dsp[idsp[isp-1]-1])
  1298.                        ||  (dsp[idsp[isp-1]-1] <= 0.) )  {
  1299.                         ierror = 1;
  1300.                         goto label_9997;
  1301.                       }
  1302.                     }
  1303.                   }
  1304.                 }
  1305.  
  1306.                 err_max = 0.e0;
  1307.                 for (isp = 1; isp<=(nsp); isp++) {
  1308.                   if(dsp[idsp[isp-1]-1] > tiny8)  {
  1309.                     err = grackle::impl::dabs(vec[isp-1] / dsp[idsp[isp-1]-1]);
  1310.                   } else {
  1311.                     err = 0.e0;
  1312.                   }
  1313.                   if(err > err_max)  {
  1314.                     err_max = err;
  1315.                   }
  1316.                 }
  1317.  
  1318.                 itr=itr+1;
  1319.               }
  1320.  
  1321. label_9998:
  1322. label_9997:
  1323. label_9996:
  1324.  
  1325.  
  1326.               // Check if the fractions are valid after an iteration
  1327.  
  1328.               if( (my_chemistry->primordial_chemistry > 0)  &&  (my_chemistry->with_radiative_cooling == 1) )  {
  1329.                 for (isp = 1; isp<=(nsp); isp++) {
  1330.                   if ( (dsp[idsp[isp-1]-1] != dsp[idsp[isp-1]-1])
  1331.                    ||  (dsp[idsp[isp-1]-1] <= 0.) )  {
  1332.                     ierror = 1;
  1333.                   }
  1334.                 }
  1335.               }
  1336.               if(ierror == 1)  {
  1337.                 dtit[i-1] = 0.5e0*dtit[i-1];
  1338.               }
  1339.  
  1340.               itr_time=itr_time+1;
  1341.             }
  1342.  
  1343.             if ( my_chemistry->primordial_chemistry > 0 )  {
  1344.               de(i-1,j-1,k-1)      = dsp[ 1-1];
  1345.               HI(i-1,j-1,k-1)      = dsp[ 2-1];
  1346.               HII(i-1,j-1,k-1)     = dsp[ 3-1];
  1347.               HeI(i-1,j-1,k-1)     = dsp[ 4-1];
  1348.               HeII(i-1,j-1,k-1)    = dsp[ 5-1];
  1349.               HeIII(i-1,j-1,k-1)   = dsp[ 6-1];
  1350.             }
  1351.             if ( my_chemistry->primordial_chemistry > 1 )  {
  1352.               HM(i-1,j-1,k-1)      = dsp[ 7-1];
  1353.               H2I(i-1,j-1,k-1)     = dsp[ 8-1];
  1354.               H2II(i-1,j-1,k-1)    = dsp[ 9-1];
  1355.             }
  1356.             if ( my_chemistry->primordial_chemistry > 2 )  {
  1357.               DI(i-1,j-1,k-1)      = dsp[10-1];
  1358.               DII(i-1,j-1,k-1)     = dsp[11-1];
  1359.               HDI(i-1,j-1,k-1)     = dsp[12-1];
  1360.             }
  1361.             if ( my_chemistry->primordial_chemistry > 3 )  {
  1362.               DM(i-1,j-1,k-1)      = dsp[13-1];
  1363.               HDII(i-1,j-1,k-1)    = dsp[14-1];
  1364.               HeHII(i-1,j-1,k-1)   = dsp[15-1];
  1365.             }
  1366.             if ( itmask_metal[i-1] != MASK_FALSE )  {
  1367.               if ( my_chemistry->metal_chemistry == 1 )  {
  1368.                 CI(i-1,j-1,k-1)      = dsp[16-1];
  1369.                 CII(i-1,j-1,k-1)     = dsp[17-1];
  1370.                 CO(i-1,j-1,k-1)      = dsp[18-1];
  1371.                 CO2(i-1,j-1,k-1)     = dsp[19-1];
  1372.                 OI(i-1,j-1,k-1)      = dsp[20-1];
  1373.                 OH(i-1,j-1,k-1)      = dsp[21-1];
  1374.                 H2O(i-1,j-1,k-1)     = dsp[22-1];
  1375.                 O2(i-1,j-1,k-1)      = dsp[23-1];
  1376.                 SiI(i-1,j-1,k-1)     = dsp[24-1];
  1377.                 SiOI(i-1,j-1,k-1)    = dsp[25-1];
  1378.                 SiO2I(i-1,j-1,k-1)   = dsp[26-1];
  1379.                 CH(i-1,j-1,k-1)      = dsp[27-1];
  1380.                 CH2(i-1,j-1,k-1)     = dsp[28-1];
  1381.                 COII(i-1,j-1,k-1)    = dsp[29-1];
  1382.                 OII(i-1,j-1,k-1)     = dsp[30-1];
  1383.                 OHII(i-1,j-1,k-1)    = dsp[31-1];
  1384.                 H2OII(i-1,j-1,k-1)   = dsp[32-1];
  1385.                 H3OII(i-1,j-1,k-1)   = dsp[33-1];
  1386.                 O2II(i-1,j-1,k-1)    = dsp[34-1];
  1387.                 if ( ( my_chemistry->grain_growth == 1 )  ||  ( my_chemistry->dust_sublimation == 1 ) )  {
  1388.                   if (my_chemistry->dust_species > 0)  {
  1389.                     Mg(i-1,j-1,k-1)      = dsp[35-1];
  1390.                   }
  1391.                   if (my_chemistry->dust_species > 1)  {
  1392.                     Al(i-1,j-1,k-1)      = dsp[36-1];
  1393.                     S(i-1,j-1,k-1)       = dsp[37-1];
  1394.                     Fe(i-1,j-1,k-1)      = dsp[38-1];
  1395.                   }
  1396.                 }
  1397.               }
  1398.               if ( ( my_chemistry->grain_growth == 1 )  ||  ( my_chemistry->dust_sublimation == 1 ) )  {
  1399.                 if (my_chemistry->dust_species > 0)  {
  1400.                   MgSiO3(i-1,j-1,k-1)  = dsp[39-1];
  1401.                   AC(i-1,j-1,k-1)      = dsp[40-1];
  1402.                 }
  1403.                 if (my_chemistry->dust_species > 1)  {
  1404.                   SiM(i-1,j-1,k-1)     = dsp[41-1];
  1405.                   FeM(i-1,j-1,k-1)     = dsp[42-1];
  1406.                   Mg2SiO4(i-1,j-1,k-1) = dsp[43-1];
  1407.                   Fe3O4(i-1,j-1,k-1)   = dsp[44-1];
  1408.                   SiO2D(i-1,j-1,k-1)   = dsp[45-1];
  1409.                   MgO(i-1,j-1,k-1)     = dsp[46-1];
  1410.                   FeS(i-1,j-1,k-1)     = dsp[47-1];
  1411.                   Al2O3(i-1,j-1,k-1)   = dsp[48-1];
  1412.                 }
  1413.                 if (my_chemistry->dust_species > 2)  {
  1414.                   reforg(i-1,j-1,k-1)  = dsp[49-1];
  1415.                   volorg(i-1,j-1,k-1)  = dsp[50-1];
  1416.                   H2Oice(i-1,j-1,k-1)  = dsp[51-1];
  1417.                 }
  1418.               }
  1419.             }
  1420.  
  1421.             e(i-1,j-1,k-1)     = dsp[i_eng-1];
  1422.  
  1423.             idsp.clear();
  1424.             vec.clear();
  1425.             mtrx = grackle::impl::View<double**>();
  1426.             mtrx_data_.clear();
  1427.  
  1428.           }
  1429.         }
  1430.  
  1431.       }
  1432.  
  1433.       // return itmask
  1434.       for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  1435.         itmask[i-1] = itmask_tmp[i-1];
  1436.       }
  1437.  
  1438.       // Add the timestep to the elapsed time for each cell and find
  1439.       //  minimum elapsed time step in this row
  1440.  
  1441.       ttmin = huge8;
  1442.       for (i = my_fields->grid_start[0] + 1; i<=(my_fields->grid_end[0] + 1); i++) {
  1443.         ttot[i-1] = std::fmin(ttot[i-1] + dtit[i-1], (*dt));
  1444.         if (std::fabs((*dt)-ttot[i-1]) <
  1445.              tolerance*(*dt)) { itmask[i-1] = MASK_FALSE; }
  1446.         if (ttot[i-1]<ttmin) { ttmin = ttot[i-1]; }
  1447.       }
  1448.  
  1449.       // If all cells are done (on this slice), then exit
  1450.  
  1451.       if (std::fabs((*dt)-ttmin) < tolerance*(*dt)) { goto label_9999; }
  1452.  
  1453.       // Next subcycle iteration
  1454.  
  1455.     }
  1456.  
  1457. label_9999:
  1458.  
  1459.     // Abort if iteration count exceeds maximum
  1460.  
  1461.     if (iter > my_chemistry->max_iterations)  {
  1462.       OMP_PRAGMA_CRITICAL
  1463.       {
  1464.         printf("inside if statement solve rate cool: %d %d\n",
  1465.                my_fields->grid_start[0],
  1466.                my_fields->grid_end[0]);
  1467.         eprintf("MULTI_COOL iter >  %d  at j,k = %d %d\n",
  1468.                 my_chemistry->max_iterations,
  1469.                 j,
  1470.                 k);
  1471.         printf("FATAL error (2) in MULTI_COOL\n");
  1472.   //_// PORT:             write(0,'(" dt = ",1pe10.3," ttmin = ",1pe10.3)') dt, ttmin
  1473.   //_// PORT:             write(0,'((16(1pe8.1)))') (dtit(i),i=is+1,ie+1)
  1474.   //_// PORT:             write(0,'((16(1pe8.1)))') (ttot(i),i=is+1,ie+1)
  1475.   //_// PORT:             write(0,'((16(1pe8.1)))') (edot(i),i=is+1,ie+1)
  1476.   //_// PORT:             write(0,'((16(I3)))') (itmask(i),i=is+1,ie+1)
  1477.  
  1478.         if (my_chemistry->exit_after_iterations_exceeded == 1)  {
  1479.           (*ierr) = 0;
  1480.         }
  1481.       }
  1482.       // WARNING_MESSAGE
  1483.     }
  1484.  
  1485.     if (iter > my_chemistry->max_iterations/2)  {
  1486.       OMP_PRAGMA_CRITICAL
  1487.       {
  1488.         eprintf("MULTI_COOL iter,j,k = %d %d %d\n", iter, j, k);
  1489.       }
  1490.     }
  1491.    
  1492.     // Next j,k
  1493.   }
  1494.   //_// PORT: #ifdef _OPENMP
  1495.   //_// PORT: !$omp end parallel do
  1496.   //_// PORT: #endif
  1497.  
  1498.   // If an error has been produced, return now.
  1499.  
  1500.   if ((*ierr) == 0)  {
  1501.     return;
  1502.   }
  1503.  
  1504.   // Convert densities back to comoving from proper
  1505.  
  1506.   if (my_units->comoving_coordinates == 1)  {
  1507.  
  1508.     factor = (gr_float)(std::pow(my_units->a_value,3) );
  1509.  
  1510.      FORTRAN_NAME(scale_fields_g)(
  1511.       &my_chemistry->primordial_chemistry, imetal, &my_chemistry->use_dust_density_field, &my_chemistry->metal_chemistry,
  1512.       &my_chemistry->metal_abundances, &my_chemistry->dust_species, &my_chemistry->multi_metals, &my_chemistry->grain_growth, &my_chemistry->dust_sublimation, &factor,
  1513.       &my_fields->grid_start[0], &my_fields->grid_end[0], &my_fields->grid_start[1], &my_fields->grid_end[1], &my_fields->grid_start[2], &my_fields->grid_end[2], &my_fields->grid_dimension[0], &my_fields->grid_dimension[1], &my_fields->grid_dimension[2],
  1514.       d.data(), de.data(), HI.data(), HII.data(), HeI.data(), HeII.data(), HeIII.data(),
  1515.       HM.data(), H2I.data(), H2II.data(), DI.data(), DII.data(), HDI.data(), DM.data(), HDII.data(), HeHII.data(),
  1516.       metal.data(), dust.data(),
  1517.       CI.data(), CII.data(), CO.data(), CO2.data(),
  1518.       OI.data(), OH.data(), H2O.data(), O2.data(),
  1519.       SiI.data(), SiOI.data(), SiO2I.data(),
  1520.       CH.data(), CH2.data(), COII.data(), OII.data(),
  1521.       OHII.data(), H2OII.data(), H3OII.data(), O2II.data(),
  1522.       Mg.data(), Al.data(), S.data(), Fe.data(),
  1523.       SiM.data(), FeM.data(), Mg2SiO4.data(), MgSiO3.data(), Fe3O4.data(),
  1524.       AC.data(), SiO2D.data(), MgO.data(), FeS.data(), Al2O3.data(),
  1525.       reforg.data(), volorg.data(), H2Oice.data(),
  1526.       metal_loc.data(), metal_C13.data(), metal_C20.data(), metal_C25.data(), metal_C30.data(),
  1527.       metal_F13.data(), metal_F15.data(), metal_F50.data(), metal_F80.data(),
  1528.       metal_P170.data(), metal_P200.data(), metal_Y19.data());
  1529.  
  1530.   }
  1531.  
  1532.   if (my_chemistry->primordial_chemistry > 0)  {
  1533.  
  1534.     // Correct the species to ensure consistency (i.e. type conservation)
  1535.  
  1536. #ifdef ABUNDANCE_CORRECTION
  1537.      FORTRAN_NAME(make_consistent_g)(de.data(), HI.data(), HII.data(), HeI.data(), HeII.data(), HeIII.data(),
  1538.                          HM.data(), H2I.data(), H2II.data(), DI.data(), DII.data(), HDI.data(), metal.data(), dust.data(),
  1539.                          d.data(), &my_fields->grid_start[0], &my_fields->grid_end[0], &my_fields->grid_start[1], &my_fields->grid_end[1], &my_fields->grid_start[2], &my_fields->grid_end[2],
  1540.                          &my_fields->grid_dimension[0], &my_fields->grid_dimension[1], &my_fields->grid_dimension[2], &my_chemistry->primordial_chemistry, imetal, &my_chemistry->HydrogenFractionByMass, &my_chemistry->DeuteriumToHydrogenRatio,
  1541.                         &my_chemistry->use_dust_density_field, &my_chemistry->metal_chemistry, &my_chemistry->grain_growth, &dom,
  1542.                         DM.data(), HDII.data(), HeHII.data(),
  1543.                         CI.data(), CII.data(), CO.data(), CO2.data(),
  1544.                         OI.data(), OH.data(), H2O.data(), O2.data(),
  1545.                         SiI.data(), SiOI.data(), SiO2I.data(),
  1546.                         CH.data(), CH2.data(), COII.data(), OII.data(),
  1547.                         OHII.data(), H2OII.data(), H3OII.data(), O2II.data(),
  1548.                         Mg.data(), Al.data(), S.data(), Fe.data(),
  1549.                         SiM.data(), FeM.data(), Mg2SiO4.data(), MgSiO3.data(), Fe3O4.data(),
  1550.                         AC.data(), SiO2D.data(), MgO.data(), FeS.data(), Al2O3.data(),
  1551.                         reforg.data(), volorg.data(), H2Oice.data(),
  1552.                         &my_chemistry->multi_metals, &my_chemistry->metal_abundances, &my_chemistry->dust_species, &my_chemistry->use_multiple_dust_temperatures, &my_chemistry->dust_sublimation,
  1553.                         metal_loc.data(),
  1554.                         metal_C13.data(), metal_C20.data(), metal_C25.data(), metal_C30.data(),
  1555.                         metal_F13.data(), metal_F15.data(), metal_F50.data(), metal_F80.data(),
  1556.                         metal_P170.data(), metal_P200.data(), metal_Y19.data(),
  1557.                         &my_rates->SN0_N,
  1558.                         my_rates->SN0_XC, my_rates->SN0_XO, my_rates->SN0_XMg, my_rates->SN0_XAl, my_rates->SN0_XSi,
  1559.                         my_rates->SN0_XS, my_rates->SN0_XFe,
  1560.                         my_rates->SN0_fC, my_rates->SN0_fO, my_rates->SN0_fMg, my_rates->SN0_fAl, my_rates->SN0_fSi,
  1561.                         my_rates->SN0_fS, my_rates->SN0_fFe
  1562.                           );
  1563.  
  1564.      FORTRAN_NAME(ceiling_species_g)(d.data(), de.data(), HI.data(), HII.data(), HeI.data(), HeII.data(), HeIII.data(),
  1565.                          HM.data(), H2I.data(), H2II.data(), DI.data(), DII.data(), HDI.data(), metal.data(), dust.data(),
  1566.                          &my_fields->grid_start[0], &my_fields->grid_end[0], &my_fields->grid_start[1], &my_fields->grid_end[1], &my_fields->grid_start[2], &my_fields->grid_end[2],
  1567.                          &my_fields->grid_dimension[0], &my_fields->grid_dimension[1], &my_fields->grid_dimension[2], &my_chemistry->primordial_chemistry, imetal, &my_chemistry->use_dust_density_field,
  1568.                         DM.data(), HDII.data(), HeHII.data(),
  1569.                         &my_chemistry->metal_abundances, &my_chemistry->metal_chemistry, &my_chemistry->dust_species, &my_chemistry->multi_metals,
  1570.                         &my_chemistry->grain_growth, &my_chemistry->dust_sublimation,
  1571.                         CI.data(), CII.data(), CO.data(), CO2.data(),
  1572.                         OI.data(), OH.data(), H2O.data(), O2.data(),
  1573.                         SiI.data(), SiOI.data(), SiO2I.data(),
  1574.                         CH.data(), CH2.data(), COII.data(), OII.data(),
  1575.                         OHII.data(), H2OII.data(), H3OII.data(), O2II.data(),
  1576.                         Mg.data(), Al.data(), S.data(), Fe.data(),
  1577.                         SiM.data(), FeM.data(), Mg2SiO4.data(), MgSiO3.data(), Fe3O4.data(),
  1578.                         AC.data(), SiO2D.data(), MgO.data(), FeS.data(), Al2O3.data(),
  1579.                         reforg.data(), volorg.data(), H2Oice.data(),
  1580.                         metal_loc.data(),
  1581.                         metal_C13.data(), metal_C20.data(), metal_C25.data(), metal_C30.data(),
  1582.                         metal_F13.data(), metal_F15.data(), metal_F50.data(), metal_F80.data(),
  1583.                         metal_P170.data(), metal_P200.data(), metal_Y19.data());
  1584. #endif
  1585.  
  1586.   }
  1587.  
  1588.   return;
  1589. }
  1590.  
  1591. }  // extern "C"
  1592.  
Add Comment
Please, Sign In to add comment