write_mbe_breakdown_json_impl Subroutine

private subroutine write_mbe_breakdown_json_impl(data)

Write detailed MBE energy breakdown to JSON file

Arguments

Type IntentOptional Attributes Name
type(json_output_data_t), intent(in) :: data

Calls

proc~~write_mbe_breakdown_json_impl~~CallsGraph proc~write_mbe_breakdown_json_impl write_mbe_breakdown_json_impl add add proc~write_mbe_breakdown_json_impl->add create_array create_array proc~write_mbe_breakdown_json_impl->create_array create_object create_object proc~write_mbe_breakdown_json_impl->create_object destroy destroy proc~write_mbe_breakdown_json_impl->destroy error error proc~write_mbe_breakdown_json_impl->error info info proc~write_mbe_breakdown_json_impl->info initialize initialize proc~write_mbe_breakdown_json_impl->initialize proc~get_basename get_basename proc~write_mbe_breakdown_json_impl->proc~get_basename proc~get_frag_level_name get_frag_level_name proc~write_mbe_breakdown_json_impl->proc~get_frag_level_name proc~get_output_json_filename get_output_json_filename proc~write_mbe_breakdown_json_impl->proc~get_output_json_filename warning warning proc~write_mbe_breakdown_json_impl->warning

Called by

proc~~write_mbe_breakdown_json_impl~~CalledByGraph proc~write_mbe_breakdown_json_impl write_mbe_breakdown_json_impl proc~write_json_output write_json_output proc~write_json_output->proc~write_mbe_breakdown_json_impl proc~run_calculation run_calculation proc~run_calculation->proc~write_json_output proc~compute_energy_and_forces compute_energy_and_forces proc~compute_energy_and_forces->proc~run_calculation proc~run_multi_molecule_calculations run_multi_molecule_calculations proc~run_multi_molecule_calculations->proc~run_calculation program~main main program~main->proc~run_calculation program~main->proc~run_multi_molecule_calculations

Variables

Type Visibility Attributes Name Initial
character(len=256), private :: basename
integer(kind=int64), private :: count_by_level
type(json_value), private, pointer :: dipole_obj
integer, private :: frag_level
type(json_value), private, pointer :: frag_obj
integer, private :: fragment_size
type(json_value), private, pointer :: frags_arr
integer(kind=int64), private :: i
integer, private, allocatable :: indices(:)
integer, private :: io_stat
integer, private :: iunit
integer, private :: j
type(json_core), private :: json
character(len=32), private :: level_name
type(json_value), private, pointer :: level_obj
type(json_value), private, pointer :: levels_arr
type(json_value), private, pointer :: main_obj
character(len=256), private :: output_file
type(json_value), private, pointer :: root

Source Code

   subroutine write_mbe_breakdown_json_impl(data)
      !! Write detailed MBE energy breakdown to JSON file
      type(json_output_data_t), intent(in) :: data

      type(json_core) :: json
      type(json_value), pointer :: root, main_obj, levels_arr, level_obj, frags_arr, frag_obj
      type(json_value), pointer :: dipole_obj
      integer(int64) :: i, count_by_level
      integer :: fragment_size, j, frag_level, iunit, io_stat
      integer, allocatable :: indices(:)
      character(len=32) :: level_name
      character(len=256) :: output_file, basename

      output_file = get_output_json_filename()
      basename = get_basename()

      if (data%max_level > 10) then
         call logger%warning("Fragment levels exceed decamers (10-mers). JSON will use generic N-mers notation.")
      end if

      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)

      ! Build levels array
      call json%create_array(levels_arr, 'levels')
      call json%add(main_obj, levels_arr)

      do frag_level = 1, data%max_level
         count_by_level = 0_int64
         do i = 1_int64, data%fragment_count
            fragment_size = count(data%polymers(i, :) > 0)
            if (fragment_size == frag_level) count_by_level = count_by_level + 1_int64
         end do

         if (count_by_level > 0_int64) then
            call json%create_object(level_obj, '')
            call json%add(levels_arr, level_obj)

            level_name = get_frag_level_name(frag_level)
            call json%add(level_obj, 'frag_level', frag_level)
            call json%add(level_obj, 'name', trim(level_name))
            call json%add(level_obj, 'count', int(count_by_level))
            if (allocated(data%sum_by_level)) then
               call json%add(level_obj, 'total_energy', data%sum_by_level(frag_level))
            end if

            call json%create_array(frags_arr, 'fragments')
            call json%add(level_obj, frags_arr)

            do i = 1_int64, data%fragment_count
               fragment_size = count(data%polymers(i, :) > 0)
               if (fragment_size == frag_level) then
                  call json%create_object(frag_obj, '')
                  call json%add(frags_arr, frag_obj)

                  allocate (indices(fragment_size))
                  indices = data%polymers(i, 1:fragment_size)
                  call json%add(frag_obj, 'indices', indices)
                  deallocate (indices)

                  if (allocated(data%fragment_energies)) then
                     call json%add(frag_obj, 'energy', data%fragment_energies(i))
                  end if

                  if (allocated(data%fragment_distances)) then
                     call json%add(frag_obj, 'distance', data%fragment_distances(i))
                  end if

                  if (frag_level > 1 .and. allocated(data%delta_energies)) then
                     call json%add(frag_obj, 'delta_energy', data%delta_energies(i))
                  end if
               end if
            end do
         end if
      end do

      ! Add dipole if computed
      if (data%has_dipole .and. allocated(data%dipole)) then
         call json%create_object(dipole_obj, 'dipole')
         call json%add(main_obj, dipole_obj)
         call json%add(dipole_obj, 'x', data%dipole(1))
         call json%add(dipole_obj, 'y', data%dipole(2))
         call json%add(dipole_obj, 'z', data%dipole(3))
         call json%add(dipole_obj, 'magnitude_debye', norm2(data%dipole)*AU_TO_DEBYE)
      end if

      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

      ! Write to file
      call logger%info("Writing 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("JSON output written successfully to "//trim(output_file))

   end subroutine write_mbe_breakdown_json_impl