subroutine write_chemistry_diagnostics_row(flow, params, step, chemistry_dt, owned_local, active_local, &
skipped_local, total_time_local, reactor_time_local, &
max_dT_local, max_dY_local, max_rel_drho_local, min_source_alpha_local, &
raw_max_dT_local, raw_max_dY_local, raw_max_rel_drho_local, &
max_qdot_local, integrated_qdot_local)
type(flow_mpi_t), intent(in) :: flow
type(case_params_t), intent(in) :: params
integer, intent(in) :: step
real(rk), intent(in) :: chemistry_dt
integer, intent(in) :: owned_local, active_local, skipped_local
real(rk), intent(in) :: total_time_local, reactor_time_local
real(rk), intent(in), optional :: max_dT_local, max_dY_local, max_rel_drho_local, min_source_alpha_local
real(rk), intent(in), optional :: raw_max_dT_local, raw_max_dY_local, raw_max_rel_drho_local
real(rk), intent(in), optional :: max_qdot_local, integrated_qdot_local
integer :: ierr, unit_id, ios
integer :: local_counts(4), sum_counts(4)
integer :: local_min_counts(2), min_counts(2), max_counts(2)
real(rk) :: local_times(2), sum_times(2), min_times(2), max_times(2)
real(rk) :: local_chem_metrics(3), max_chem_metrics(3)
real(rk) :: local_raw_chem_metrics(3), max_raw_chem_metrics(3)
real(rk) :: local_qdot_metrics(2), sum_qdot_metrics(2), max_qdot_metric
real(rk) :: local_alpha, min_alpha
real(rk) :: avg_total_time, avg_reactor_time, avg_reactor_time_per_call
character(len=1024) :: filename
if (.not. params%write_diagnostics) return
if (mod(step, params%output_interval) /= 0 .and. step /= params%nsteps .and. step /= 0) return
local_counts = [owned_local, active_local, skipped_local, active_local]
local_min_counts = [active_local, skipped_local]
local_times = [total_time_local, reactor_time_local]
local_chem_metrics = zero
local_raw_chem_metrics = zero
local_qdot_metrics = zero
if (present(max_dT_local)) local_chem_metrics(1) = max(zero, max_dT_local)
if (present(max_dY_local)) local_chem_metrics(2) = max(zero, max_dY_local)
if (present(max_rel_drho_local)) local_chem_metrics(3) = max(zero, max_rel_drho_local)
if (present(raw_max_dT_local)) local_raw_chem_metrics(1) = max(zero, raw_max_dT_local)
if (present(raw_max_dY_local)) local_raw_chem_metrics(2) = max(zero, raw_max_dY_local)
if (present(raw_max_rel_drho_local)) local_raw_chem_metrics(3) = max(zero, raw_max_rel_drho_local)
if (present(max_qdot_local)) local_qdot_metrics(1) = max(zero, max_qdot_local)
if (present(integrated_qdot_local)) local_qdot_metrics(2) = integrated_qdot_local
local_alpha = 1.0_rk
if (present(min_source_alpha_local)) local_alpha = min(1.0_rk, max(zero, min_source_alpha_local))
call MPI_Reduce(local_counts, sum_counts, 4, MPI_INTEGER, MPI_SUM, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry count sums')
call MPI_Reduce(local_min_counts, min_counts, 2, MPI_INTEGER, MPI_MIN, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry count minima')
call MPI_Reduce(local_min_counts, max_counts, 2, MPI_INTEGER, MPI_MAX, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry count maxima')
call MPI_Reduce(local_times, sum_times, 2, MPI_DOUBLE_PRECISION, MPI_SUM, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry time sums')
call MPI_Reduce(local_times, min_times, 2, MPI_DOUBLE_PRECISION, MPI_MIN, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry time minima')
call MPI_Reduce(local_times, max_times, 2, MPI_DOUBLE_PRECISION, MPI_MAX, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry time maxima')
call MPI_Reduce(local_chem_metrics, max_chem_metrics, 3, MPI_DOUBLE_PRECISION, MPI_MAX, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry source maxima')
call MPI_Reduce(local_raw_chem_metrics, max_raw_chem_metrics, 3, MPI_DOUBLE_PRECISION, MPI_MAX, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for raw chemistry source maxima')
call MPI_Reduce(local_alpha, min_alpha, 1, MPI_DOUBLE_PRECISION, MPI_MIN, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry source alpha minimum')
call MPI_Reduce(local_qdot_metrics, sum_qdot_metrics, 2, MPI_DOUBLE_PRECISION, MPI_SUM, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry heat-release sums')
call MPI_Reduce(local_qdot_metrics(1), max_qdot_metric, 1, MPI_DOUBLE_PRECISION, MPI_MAX, 0, flow%comm, ierr)
if (ierr /= MPI_SUCCESS) call fatal_error('chemistry', 'MPI_Reduce failed for chemistry heat-release maximum')
if (flow%rank /= 0) return
avg_total_time = sum_times(1) / real(max(1, flow%nprocs), rk)
avg_reactor_time = sum_times(2) / real(max(1, flow%nprocs), rk)
if (sum_counts(4) > 0) then
avg_reactor_time_per_call = sum_times(2) / real(sum_counts(4), rk)
else
avg_reactor_time_per_call = zero
end if
filename = trim(params%output_dir) // '/diagnostics/chemistry_diagnostics.csv'
open(newunit=unit_id, file=trim(filename), status='old', position='append', action='write', iostat=ios)
if (ios /= 0) return
write(unit_id,'(i0,a,es16.8,a,i0,a,i0,a,i0,a,i0,a,i0,a,i0,a,i0,a,i0,a,i0,a,'// &
'es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,'// &
'es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,'// &
'es16.8,a,es16.8,a,l1)') &
step, ',', chemistry_dt, ',', flow%nprocs, ',', sum_counts(1), ',', sum_counts(2), ',', &
sum_counts(3), ',', sum_counts(4), ',', min_counts(1), ',', max_counts(1), ',', &
min_counts(2), ',', max_counts(2), ',', min_times(1), ',', max_times(1), ',', &
avg_total_time, ',', min_times(2), ',', max_times(2), ',', avg_reactor_time, ',', &
avg_reactor_time_per_call, ',', max_chem_metrics(1), ',', max_chem_metrics(2), ',', &
max_chem_metrics(3), ',', min_alpha, ',', max_raw_chem_metrics(1), ',', &
max_raw_chem_metrics(2), ',', max_raw_chem_metrics(3), ',', max_qdot_metric, ',', &
sum_qdot_metrics(2), ',', params%chemistry_energy_enabled
close(unit_id)
end subroutine write_chemistry_diagnostics_row