subroutine write_gmbe_pie_json_impl(data)
!! Write GMBE PIE calculation results to output JSON file
type(json_output_data_t), intent(in) :: data
type(json_core) :: json
type(json_value), pointer :: root, main_obj, pie_obj, terms_arr, term_obj
integer :: j, max_atoms, n_atoms, iunit, io_stat
integer(int64) :: i, n_nonzero_terms
integer, allocatable :: atom_indices(:)
character(len=256) :: output_file, basename
output_file = get_output_json_filename()
basename = get_basename()
call json%initialize(real_format=JSON_REAL_FORMAT)
call json%create_object(root, '')
call json%create_object(main_obj, trim(basename))
call json%add(root, main_obj)
call json%add(main_obj, 'total_energy', data%total_energy)
if (data%has_gradient .and. allocated(data%gradient)) then
call json%add(main_obj, 'gradient_norm', sqrt(sum(data%gradient**2)))
end if
if (data%has_hessian .and. allocated(data%hessian)) then
call json%add(main_obj, 'hessian_frobenius_norm', sqrt(sum(data%hessian**2)))
end if
! Count non-zero coefficient terms
if (allocated(data%pie_coefficients)) then
n_nonzero_terms = count(data%pie_coefficients(1:data%n_pie_terms) /= 0)
else
n_nonzero_terms = 0
end if
! PIE terms section
call json%create_object(pie_obj, 'pie_terms')
call json%add(main_obj, pie_obj)
call json%add(pie_obj, 'count', int(n_nonzero_terms))
call json%create_array(terms_arr, 'terms')
call json%add(pie_obj, terms_arr)
if (allocated(data%pie_atom_sets) .and. allocated(data%pie_coefficients) .and. &
allocated(data%pie_energies)) then
max_atoms = size(data%pie_atom_sets, 1)
do i = 1_int64, data%n_pie_terms
if (data%pie_coefficients(i) == 0) cycle
call json%create_object(term_obj, '')
call json%add(terms_arr, term_obj)
! Extract atom list size (atoms until negative sentinel)
n_atoms = 0
do while (n_atoms < max_atoms .and. data%pie_atom_sets(n_atoms + 1, i) >= 0)
n_atoms = n_atoms + 1
end do
allocate (atom_indices(n_atoms))
atom_indices = data%pie_atom_sets(1:n_atoms, i)
call json%add(term_obj, 'atom_indices', atom_indices)
deallocate (atom_indices)
call json%add(term_obj, 'coefficient', data%pie_coefficients(i))
call json%add(term_obj, 'energy', data%pie_energies(i))
call json%add(term_obj, 'weighted_energy', real(data%pie_coefficients(i), dp)*data%pie_energies(i))
end do
end if
! Write to file
call logger%info("Writing GMBE PIE JSON output to "//trim(output_file))
open (newunit=iunit, file=trim(output_file), status='replace', action='write', iostat=io_stat)
if (io_stat /= 0) then
call logger%error("Failed to open "//trim(output_file)//" for writing")
call json%destroy(root)
return
end if
call json%print(root, iunit)
close (iunit)
call json%destroy(root)
call logger%info("GMBE PIE JSON output written successfully to "//trim(output_file))
end subroutine write_gmbe_pie_json_impl