Skip to content

File ProcessFactory_Mod.F90

File List > core > ProcessFactory_Mod.F90

Go to the documentation of this file

module processfactory_mod
   use precision_mod
   use statemanager_mod, only : statemanagertype
   use metstate_mod, only : metstatetype
   use error_mod
   use processinterface_mod
   use processregistry_mod

   implicit none
   private

   public :: processfactorytype
   public :: create_process

   type :: processfactorytype
      private
      type(ProcessRegistryType) :: registry
   contains
      procedure :: init => factory_init
      procedure :: create_process => factory_create_process
      procedure :: list_available => factory_list_available
      procedure :: register_process => factory_register_process
      procedure, private :: register_builtin_processes
   end type processfactorytype

contains

   subroutine factory_init(this, rc)
      class(ProcessFactoryType), intent(inout) :: this
      integer, intent(out) :: rc

      call this%registry%init(rc)
      if (rc /= cc_success) return

      ! Register built-in processes
      call this%register_builtin_processes(rc)
   end subroutine factory_init

   subroutine factory_create_process(this, process_name, container, process, rc)
      class(ProcessFactoryType), intent(inout) :: this
      character(len=*), intent(in) :: process_name
      type(StateManagerType), intent(inout) :: container
      class(ProcessInterface), allocatable, intent(out) :: process
      integer, intent(out) :: rc

      type(ErrorManagerType), pointer :: error_mgr
      character(len=32), allocatable :: met_fields(:)
      integer :: i, alloc_rc
      type(MetStateType), pointer :: met_state

      error_mgr => container%get_error_manager()
      call error_mgr%push_context('factory_create_process', &
         'creating process: ' // trim(process_name))

      ! Create process from registry (scheme is read from process configuration)
      call this%registry%create_process(process_name, process, rc)
      if (rc /= cc_success) then
         call error_mgr%report_error(error_invalid_config, &
            'Unknown process: ' // trim(process_name), rc, &
            'factory_create_process', &
            'Check available processes with list_available()')
         call error_mgr%pop_context()
         return
      endif

      ! Allocate only required met fields for this process
      met_fields = process%get_required_met_fields()
      met_state => container%get_met_state_ptr()
      if (associated(met_state) .and. allocated(met_fields)) then
         do i = 1, size(met_fields)
            call met_state%allocate_field(met_fields(i), alloc_rc)
            ! Optionally handle alloc_rc errors here
         end do
      endif

      call error_mgr%pop_context()
   end subroutine factory_create_process

   subroutine factory_list_available(this, process_names, rc)
      class(ProcessFactoryType), intent(in) :: this
      character(len=64), allocatable, intent(out) :: process_names(:)
      integer, intent(out) :: rc

      call this%registry%list_processes(process_names, rc)
   end subroutine factory_list_available

   subroutine factory_register_process(this, name, category, description, creator, rc)
      class(ProcessFactoryType), intent(inout) :: this
      character(len=*), intent(in) :: name, category, description
      procedure(ProcessCreatorInterface) :: creator
      integer, intent(out) :: rc

      call this%registry%register_process(name, category, description, creator, rc)
   end subroutine factory_register_process

   subroutine register_builtin_processes(this, rc)
      class(ProcessFactoryType), intent(inout) :: this
      integer, intent(out) :: rc

      rc = cc_success

      ! Core processes would be registered here, but in the current
      ! architecture, processes register themselves during module
      ! initialization. This method is kept for future core processes
      ! that might be built directly into the factory.

      ! Note: Process modules (dust, seasalt, etc.) should register
      ! themselves using the public register_process method during
      ! their initialization phase.

   end subroutine register_builtin_processes

   function create_process(process_name, container, rc) result(process)
      character(len=*), intent(in) :: process_name
      type(StateManagerType), intent(inout) :: container
      integer, intent(out) :: rc
      class(ProcessInterface), allocatable :: process

      type(ProcessFactoryType) :: factory

      call factory%init(rc)
      if (rc /= cc_success) return

      call factory%create_process(process_name, container, process, rc)
   end function create_process

end module processfactory_mod