forclust.f90 Source File


Files dependent on this one

sourcefile~~forclust.f90~~AfferentGraph sourcefile~forclust.f90 forclust.f90 sourcefile~test_backlight.f90 test_backlight.f90 sourcefile~test_backlight.f90->sourcefile~forclust.f90 sourcefile~test_get_base_freq.f90 test_get_base_freq.f90 sourcefile~test_get_base_freq.f90->sourcefile~forclust.f90 sourcefile~test_get_cpuinfo_max_freq.f90 test_get_cpuinfo_max_freq.f90 sourcefile~test_get_cpuinfo_max_freq.f90->sourcefile~forclust.f90 sourcefile~test_get_cpuinfo_min_freq.f90 test_get_cpuinfo_min_freq.f90 sourcefile~test_get_cpuinfo_min_freq.f90->sourcefile~forclust.f90 sourcefile~test_get_energy_performance.f90 test_get_energy_performance.f90 sourcefile~test_get_energy_performance.f90->sourcefile~forclust.f90 sourcefile~test_get_scaling_cur_freq.f90 test_get_scaling_cur_freq.f90 sourcefile~test_get_scaling_cur_freq.f90->sourcefile~forclust.f90 sourcefile~test_get_scaling_governor.f90 test_get_scaling_governor.f90 sourcefile~test_get_scaling_governor.f90->sourcefile~forclust.f90 sourcefile~test_get_scaling_max_freq.f90 test_get_scaling_max_freq.f90 sourcefile~test_get_scaling_max_freq.f90->sourcefile~forclust.f90 sourcefile~test_get_scaling_min_freq.f90 test_get_scaling_min_freq.f90 sourcefile~test_get_scaling_min_freq.f90->sourcefile~forclust.f90 sourcefile~test_get_turbo.f90 test_get_turbo.f90 sourcefile~test_get_turbo.f90->sourcefile~forclust.f90 sourcefile~test_is_cpu_online.f90 test_is_cpu_online.f90 sourcefile~test_is_cpu_online.f90->sourcefile~forclust.f90 sourcefile~test_print_info.f90 test_print_info.f90 sourcefile~test_print_info.f90->sourcefile~forclust.f90 sourcefile~test_select_cluster.f90 test_select_cluster.f90 sourcefile~test_select_cluster.f90->sourcefile~forclust.f90 sourcefile~test_select_node.f90 test_select_node.f90 sourcefile~test_select_node.f90->sourcefile~forclust.f90 sourcefile~test_set.f90 test_set.f90 sourcefile~test_set.f90->sourcefile~forclust.f90 sourcefile~test_set_cpu_debug_off.f90 test_set_cpu_debug_off.f90 sourcefile~test_set_cpu_debug_off.f90->sourcefile~forclust.f90 sourcefile~test_set_cpu_debug_on.f90 test_set_cpu_debug_on.f90 sourcefile~test_set_cpu_debug_on.f90->sourcefile~forclust.f90 sourcefile~test_set_node_debug_off.f90 test_set_node_debug_off.f90 sourcefile~test_set_node_debug_off.f90->sourcefile~forclust.f90 sourcefile~test_set_node_debug_on.f90 test_set_node_debug_on.f90 sourcefile~test_set_node_debug_on.f90->sourcefile~forclust.f90

Contents

Source Code


Source Code

!> author: Seyed Ali Ghasemi
module forclust

   implicit none

   private

   public :: cluster

   !===============================================================================
   type :: linux_backlight
      character(len=:), allocatable :: debug
      character(len=:), allocatable :: path_backlight
      integer                       :: actual_brightness
      integer                       :: brightness
      integer                       :: max_brightness
   contains
      procedure :: set_debug              => set_backlight_debug_switch
      procedure :: select                 => select_backlight
      procedure :: get_actual_brightness  => get_backlight_actual_brightness
      procedure :: get_max_brightness     => get_backlight_max_brightness
      procedure :: set_brightness         => set_backlight_brightness

      procedure :: deselect               => deallocate_linux_backlight
   end type linux_backlight
   !===============================================================================


   !===============================================================================
   type :: linux_cpu
      character(len=:), allocatable :: debug
      character(len=:), allocatable :: path_cpu
      integer                       :: online
      integer                       :: base_frequency
      integer                       :: cpuinfo_max_freq
      integer                       :: cpuinfo_min_freq
      integer                       :: scaling_cur_freq
      integer                       :: scaling_max_freq
      integer                       :: scaling_min_freq
      character(len=:), allocatable :: scaling_governor
      character(len=:), allocatable :: energy_performance_preference
   contains
      procedure :: set_debug              => set_cpu_debug_switch
      procedure :: is_online              => is_cpu_online
      procedure :: get_base_freq          => get_cpu_base_frequency
      procedure :: get_cpuinfo_max_freq   => get_cpuinfo_max_frequency
      procedure :: get_cpuinfo_min_freq   => get_cpuinfo_min_frequency
      procedure :: get_scaling_cur_freq   => get_cpu_scaling_cur_frequency
      procedure :: get_scaling_max_freq   => get_cpu_scaling_max_frequency
      procedure :: get_scaling_min_freq   => get_cpu_scaling_min_frequency
      procedure :: get_scaling_governor   => get_cpu_scaling_governor
      procedure :: get_energy_performance => get_cpu_energy_performance_preference
      procedure :: set_offline            => set_cpu_offline
      procedure :: set_online             => set_cpu_online
      procedure :: set_scaling_max_freq   => set_cpu_scaling_max_freq
      procedure :: set_scaling_min_freq   => set_cpu_scaling_min_freq
      procedure :: set_scaling_governor   => set_cpu_scaling_governor
      procedure :: set_energy_performance => set_cpu_energy_performance_preference

      procedure :: deselect               => deallocate_linux_cpu
   end type linux_cpu
   !===============================================================================


   !===============================================================================
   type :: linux_nodes
      character(len=:),               allocatable :: debug
      character(len=:),               allocatable :: path_node
      type(linux_cpu),  dimension(:), allocatable :: cpu
      integer                                     :: ncpus
      character(len=:),               allocatable :: turbo
      integer                                     :: is_intel_pstate
   contains
      procedure          :: set_debug                 => set_node_debug_switch
      procedure          :: select                    => select_node
      procedure, private :: find_number_of_cpus
      procedure, private :: is_intel_pstate_available
      procedure          :: get_turbo                 => get_intel_turbo
      procedure          :: set_turbo                 => set_intel_turbo

      procedure          :: deselect                  => deallocate_linux_nodes
   end type linux_nodes
   !===============================================================================


   !===============================================================================
   type :: cluster
      type(linux_nodes),  dimension(:), allocatable :: node
      integer                                       :: nnodes
      type(linux_backlight)                         :: backlight
   contains
      procedure          :: select => select_linux
      procedure, private :: find_number_of_nodes
      procedure          :: print_info            => print_all_cluster_info

      procedure          :: deselect              => deallocate_cluster
   end type cluster
   !===============================================================================


contains


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine find_number_of_nodes(this)
      use :: popen_module, only: get_command_as_string
      class(cluster), intent(inout) :: this
      character(len=:), allocatable :: nnodes_char

      nnodes_char = get_command_as_string("lscpu | grep 'NUMA node(s):' | awk '{print $3}'")
      read(nnodes_char,*) this%nnodes
   end subroutine find_number_of_nodes
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine select_linux(this)
      class(cluster), intent(inout) :: this
      character(len=100)            :: current_node_path
      character(len=100)            :: backlight_path
      integer                       :: i

      call this%find_number_of_nodes()
      if (.not. allocated(this%node)) allocate(this%node(this%nnodes))

      do concurrent (i = 1:this%nnodes)
         write (current_node_path, "(a,i0,a)") "/sys/devices/system/node/node",i-1,"/"
         this%node(i)%path_node=adjustl(trim(current_node_path))
      end do

      write (backlight_path, "(a,i0,a)") "/sys/class/backlight/intel_backlight"
      this%backlight%path_backlight=adjustl(trim(backlight_path))
   end subroutine select_linux
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine find_number_of_cpus(this)
      use :: popen_module, only: get_command_as_string
      class(linux_nodes), intent(inout) :: this
      character(len=:), allocatable     :: ncpu_char

      ncpu_char = get_command_as_string('nproc --all')
      read(ncpu_char,*) this%ncpus
   end subroutine find_number_of_cpus
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine select_node(this)
      class(linux_nodes), intent(inout) :: this
      character(len=100)                :: current_cpu_path
      integer                           :: nunit, stat, i
      integer                           :: temp
      character(len=100)                :: temp_char
      logical                           :: ex
      character(len=:), allocatable     :: file_name

      ! check if intel_pstate exists
      call this%is_intel_pstate_available()
      if (this%is_intel_pstate == 1) then
         ! read turbo
         open(newunit=nunit, file='/sys/devices/system/cpu/intel_pstate/no_turbo', iostat=stat)
         read(nunit, *) temp
         close(nunit)
         if (temp==1) this%turbo = 'off'
         if (temp==0) this%turbo = 'on'
      else
         this%turbo = 'off'
      end if

      call this%find_number_of_cpus()
      if (.not. allocated(this%cpu)) allocate(this%cpu(this%ncpus))

      do concurrent (i = 1:this%ncpus)
         ! path cpu
         write (current_cpu_path, "(a,a,i0)") adjustl(trim(this%path_node)),"cpu",i-1
         this%cpu(i)%path_cpu = adjustl(trim(current_cpu_path))

         ! read base frequency
         file_name = this%cpu(i)%path_cpu//"/cpufreq/base_frequency"
         inquire(file=file_name, exist=ex)
         if (ex) then
            open(newunit=nunit, file=file_name, iostat=stat)
            read(nunit, *) this%cpu(i)%base_frequency
            close(nunit)
         else
            this%cpu(i)%base_frequency = 0
            ! error stop "file not found: "//file_name
         endif

         ! read cpuinfo max frequency
         file_name = this%cpu(i)%path_cpu//"/cpufreq/cpuinfo_max_freq"
         inquire(file=file_name, exist=ex)
         if (ex) then
            open(newunit=nunit, file=file_name, iostat=stat)
            read(nunit, *) this%cpu(i)%cpuinfo_max_freq
            close(nunit)
         else
            this%cpu(i)%cpuinfo_max_freq = 0
            ! error stop "file not found: "//file_name
         endif
         
         ! read cpuinfo min frequency
         file_name = this%cpu(i)%path_cpu//"/cpufreq/cpuinfo_min_freq"
         inquire(file=file_name, exist=ex)
         if (ex) then
            open(newunit=nunit, file=file_name, iostat=stat)
            read(nunit, *) this%cpu(i)%cpuinfo_min_freq
            close(nunit)
         else
            this%cpu(i)%cpuinfo_min_freq = 0
            ! error stop "file not found: "//file_name
         endif

         ! read scaling cur frequency
         file_name = this%cpu(i)%path_cpu//"/cpufreq/scaling_cur_freq"
         inquire(file=file_name, exist=ex)
         if (ex) then
            open(newunit=nunit, file=file_name, iostat=stat)
            read(nunit, *) this%cpu(i)%scaling_cur_freq
            close(nunit)
         else
            this%cpu(i)%scaling_cur_freq = 0
            ! error stop "file not found: "//file_name
         endif

         ! read scaling max frequency
         file_name = this%cpu(i)%path_cpu//"/cpufreq/scaling_max_freq"
         inquire(file=file_name, exist=ex)
         if (ex) then
            open(newunit=nunit, file=this%cpu(i)%path_cpu//"/cpufreq/scaling_max_freq", iostat=stat)
            read(nunit, *) this%cpu(i)%scaling_max_freq
            close(nunit)
         else
            this%cpu(i)%scaling_max_freq = 0
            ! error stop "file not found: "//file_name
         endif

         ! read scaling min frequency
         file_name = this%cpu(i)%path_cpu//"/cpufreq/scaling_min_freq"
         inquire(file=file_name, exist=ex)
         if (ex) then
            open(newunit=nunit, file=file_name, iostat=stat)
            read(nunit, *) this%cpu(i)%scaling_min_freq
            close(nunit)
         else
            this%cpu(i)%scaling_min_freq = 0
            ! error stop "file not found: "//file_name
         endif

         ! read scaling governor
         file_name = this%cpu(i)%path_cpu//"/cpufreq/scaling_governor"
         inquire(file=file_name, exist=ex)
         if (ex) then
            open(newunit=nunit, file=file_name, iostat=stat)
            read(nunit, *) temp_char
            this%cpu(i)%scaling_governor = adjustl(trim(temp_char))
            close(nunit)
         else
            this%cpu(i)%scaling_governor = "not found"
            ! error stop "file not found: "//file_name
         endif

         ! read energy performance preference
         file_name = this%cpu(i)%path_cpu//"/cpufreq/energy_performance_preference"
         inquire(file=file_name, exist=ex)
         if (ex) then
            open(newunit=nunit, file=file_name, iostat=stat)
            read(nunit, *) temp_char
            this%cpu(i)%energy_performance_preference = adjustl(trim(temp_char))
            close(nunit)
         else
            this%cpu(i)%energy_performance_preference = "not found"
            ! error stop "file not found: "//file_name
         endif
      end do

      ! read online
      this%cpu(1)%online = 1
      do concurrent (i = 2:this%ncpus)
         file_name = this%cpu(i)%path_cpu//"/online"
         inquire(file=file_name, exist=ex)
         if (ex) then
            open(newunit=nunit, file=this%cpu(i)%path_cpu//"/online", iostat=stat)
            read(nunit, *) this%cpu(i)%online
            close(nunit)
         else
            this%cpu(i)%online = 0
            ! error stop "file not found: "//file_name
         endif
      end do
   end subroutine select_node
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine is_cpu_online(this, online)
      class(linux_cpu), intent(inout) :: this
      integer, intent(out), optional  :: online

      if (present(online)) online = this%online
      if (this%debug=='on') print'(a,i0)', 'online:                 ',this%online
   end subroutine is_cpu_online
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_cpu_base_frequency(this, base_frequency)
      class(linux_cpu), intent(inout) :: this
      integer, intent(out), optional  :: base_frequency

      if (present(base_frequency)) base_frequency = this%base_frequency
      if (this%debug=='on') print'(a,i0)', 'base frequency:         ', this%base_frequency
   end subroutine get_cpu_base_frequency
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_cpuinfo_max_frequency(this, cpuinfo_max_freq)
      class(linux_cpu), intent(inout) :: this
      integer, intent(out), optional  :: cpuinfo_max_freq

      if (present(cpuinfo_max_freq)) cpuinfo_max_freq = this%cpuinfo_max_freq
      if (this%debug=='on') print'(a,i0)', 'cpuinfo max frequency:  ',this%cpuinfo_max_freq
   end subroutine get_cpuinfo_max_frequency
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_cpuinfo_min_frequency(this, cpuinfo_min_freq)
      class(linux_cpu), intent(inout) :: this
      integer, intent(out), optional  :: cpuinfo_min_freq

      if (present(cpuinfo_min_freq)) cpuinfo_min_freq = this%cpuinfo_min_freq
      if (this%debug=='on') print'(a,i0)', 'cpuinfo min frequency:  ',this%cpuinfo_min_freq
   end subroutine get_cpuinfo_min_frequency
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_cpu_scaling_cur_frequency(this, scaling_cur_freq)
      class(linux_cpu), intent(inout) :: this
      integer, intent(out), optional  :: scaling_cur_freq

      if (present(scaling_cur_freq)) scaling_cur_freq = this%scaling_cur_freq
      if (this%debug=='on') print'(a,i0)', 'scaling cur frequency:  ',this%scaling_cur_freq
   end subroutine get_cpu_scaling_cur_frequency
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_cpu_scaling_max_frequency(this, scaling_max_freq)
      class(linux_cpu), intent(inout) :: this
      integer, intent(out), optional  :: scaling_max_freq

      if (present(scaling_max_freq)) scaling_max_freq = this%scaling_max_freq
      if (this%debug=='on') print'(a,i0)', 'scaling max frequency:  ',this%scaling_max_freq
   end subroutine get_cpu_scaling_max_frequency
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_cpu_scaling_min_frequency(this, scaling_min_freq)
      class(linux_cpu), intent(inout) :: this
      integer, intent(out), optional  :: scaling_min_freq

      if (present(scaling_min_freq)) scaling_min_freq = this%scaling_min_freq
      if (this%debug=='on') print'(a,i0)', 'scaling min frequency:  ' ,this%scaling_min_freq
   end subroutine get_cpu_scaling_min_frequency
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_cpu_scaling_governor(this, scaling_governor)
      class(linux_cpu), intent(inout)         :: this
      character(len=*), intent(out), optional :: scaling_governor

      if (present(scaling_governor)) scaling_governor = this%scaling_governor
      if (this%debug=='on') print'(a,a)', 'scaling governor:       ' ,this%scaling_governor
   end subroutine get_cpu_scaling_governor
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_cpu_energy_performance_preference(this, energy_performance_preference)
      class(linux_cpu), intent(inout) :: this
      character(len=*), intent(out), optional    :: energy_performance_preference

      if (present(energy_performance_preference)) energy_performance_preference = this%energy_performance_preference
      if (this%debug=='on') print'(a,a)', 'energy perf preference: ' ,this%energy_performance_preference
   end subroutine get_cpu_energy_performance_preference
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine set_cpu_offline(this)
      class(linux_cpu), intent(inout) :: this
      integer                         :: nunit, stat
      logical                         :: ex
      character(len=:), allocatable   :: file_name

      this%online = 0

      file_name = this%path_cpu//"/online"
      inquire(file=file_name, exist=ex)
      if (ex) then
         open(newunit=nunit, file=file_name, iostat=stat)
         write(nunit, '(i0)') this%online
         close(nunit)
      else
         ! error stop "file not found: "//file_name
      endif
   end subroutine set_cpu_offline
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine set_cpu_online(this)
      class(linux_cpu), intent(inout) :: this
      integer                         :: nunit, stat
      logical                         :: ex
      character(len=:), allocatable   :: file_name

      this%online = 1

      file_name = this%path_cpu//"/online"
      inquire(file=file_name, exist=ex)
      if (ex) then
         open(newunit=nunit, file=file_name, iostat=stat)
         write(nunit, '(i0)') this%online
         close(nunit)
      else
         ! error stop "file not found: "//file_name
      endif
   end subroutine set_cpu_online
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine set_cpu_scaling_max_freq(this,max_freq)
      class(linux_cpu), intent(inout) :: this
      integer, intent(in)             :: max_freq
      integer                         :: nunit, stat
      logical                         :: ex
      character(len=:), allocatable   :: file_name

      this%scaling_max_freq = max_freq

      file_name = this%path_cpu//"/cpufreq/scaling_max_freq"
      inquire(file=file_name, exist=ex)
      if (ex) then
         open(newunit=nunit, file=file_name, iostat=stat)
         write(nunit, '(i0)') this%scaling_max_freq
         close(nunit)
      else
         ! error stop "file not found: "//file_name
      endif
   end subroutine set_cpu_scaling_max_freq
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine set_cpu_scaling_min_freq(this,min_freq)
      class(linux_cpu), intent(inout) :: this
      integer, intent(in)             :: min_freq
      integer                         :: nunit, stat
      logical                         :: ex
      character(len=:), allocatable   :: file_name

      this%scaling_min_freq = min_freq

      file_name = this%path_cpu//"/cpufreq/scaling_min_freq"
      inquire(file=file_name, exist=ex)
      if (ex) then
         open(newunit=nunit, file=file_name, iostat=stat)
         write(nunit, '(i0)') this%scaling_min_freq
         close(nunit)
      else
         ! error stop "file not found: "//file_name
      endif
   end subroutine set_cpu_scaling_min_freq
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine set_cpu_scaling_governor(this,scaling_governor)
      class(linux_cpu), intent(inout) :: this
      character(len=*), intent(in)    :: scaling_governor
      integer                         :: nunit, stat
      logical                         :: ex
      character(len=:), allocatable   :: file_name

      this%scaling_governor = scaling_governor

      file_name = this%path_cpu//"/cpufreq/scaling_governor"
      inquire(file=file_name, exist=ex)
      if (ex) then
         open(newunit=nunit, file=this%path_cpu//"/cpufreq/scaling_governor", iostat=stat)
         write(nunit, '(a)') this%scaling_governor
         close(nunit)
      else
         ! error stop "file not found: "//file_name
      endif
   end subroutine set_cpu_scaling_governor
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine set_cpu_energy_performance_preference(this,energy_performance_preference)
      class(linux_cpu), intent(inout) :: this
      character(len=*), intent(in)    :: energy_performance_preference
      integer                         :: nunit, stat
      logical                         :: ex
      character(len=:), allocatable   :: file_name

      this%energy_performance_preference = energy_performance_preference

      file_name = this%path_cpu//"/cpufreq/energy_performance_preference"
      inquire(file=file_name, exist=ex)
      if (ex) then
         open(newunit=nunit, file=file_name, iostat=stat)
         write(nunit, '(a)') this%energy_performance_preference
         close(nunit)
      else
         ! error stop "file not found: "//file_name
      endif
   end subroutine set_cpu_energy_performance_preference
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine is_intel_pstate_available(this)
      ! bug: it does not depend on a node
      class(linux_nodes), intent(inout) :: this
      integer                           :: is_intel_pstate
      logical                           :: ex

      inquire(file='/sys/devices/system/cpu/intel_pstate', exist=ex)
      if (ex)       is_intel_pstate = 1
      if (.not. ex) is_intel_pstate = 0
      this%is_intel_pstate = is_intel_pstate
      ! if (this%debug=='on') print'(a,i0)', 'intel pstate avail:     ',this%is_intel_pstate
   end subroutine is_intel_pstate_available
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_intel_turbo(this,turbo)
      class(linux_nodes), intent(inout)         :: this
      character(len=*),   intent(out), optional :: turbo

      if (present(turbo)) turbo = this%turbo
      if (this%debug=='on') print'(a,a)', 'intel turbo:            ',this%turbo
   end subroutine get_intel_turbo
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine set_intel_turbo(this,turbo)
      ! bug: it does not depend on a node
      class(linux_nodes), intent(inout) :: this
      character(len=*),   intent(in)    :: turbo
      integer                           :: nunit, stat

      call this%is_intel_pstate_available()
      if (this%is_intel_pstate == 1) then

         this%turbo = turbo

         open(newunit=nunit, file='/sys/devices/system/cpu/intel_pstate/no_turbo', iostat=stat)
         if (turbo == 'on' ) write(nunit,'(i0)') 0
         if (turbo == 'off') write(nunit,'(i0)') 1
         close(nunit)
      end if
   end subroutine set_intel_turbo
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental pure subroutine set_cpu_debug_switch(this,debug)
      class(linux_cpu), intent(inout) :: this
      character(len=*),   intent(in)  :: debug

      this%debug = debug
   end subroutine set_cpu_debug_switch
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental pure subroutine set_node_debug_switch(this,debug)
      class(linux_nodes), intent(inout) :: this
      character(len=*),   intent(in)    :: debug

      this%debug = debug
   end subroutine set_node_debug_switch
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine print_all_cluster_info(this)
      class(cluster), intent(inout) :: this
      integer                       :: n, c

      do n = 1, this%nnodes; print'(a,i0)', 'NODE: ',n; print'(a)','=============================='
         call this%node(n)%select()
         call this%node(n)%set_debug('on')
         call this%node(n)%get_turbo()
         print'(a)','------------------------------'

         do c = 1, this%node(n)%ncpus
            print'(a,i0)', 'CPU: ',c
            call this%node(n)%cpu(c)%set_debug('on')
            call this%node(n)%cpu(c)%is_online()
            call this%node(n)%cpu(c)%get_base_freq()
            call this%node(n)%cpu(c)%get_cpuinfo_max_freq()
            call this%node(n)%cpu(c)%get_cpuinfo_min_freq()
            call this%node(n)%cpu(c)%get_scaling_cur_freq()
            call this%node(n)%cpu(c)%get_scaling_max_freq()
            call this%node(n)%cpu(c)%get_scaling_min_freq()
            call this%node(n)%cpu(c)%get_scaling_governor()
            call this%node(n)%cpu(c)%get_energy_performance()
            print'(a)','------------------------------'
         end do
      end do

   end subroutine print_all_cluster_info
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine select_backlight(this)
      class(linux_backlight), intent(inout) :: this
      integer                               :: nunit, stat
      logical                               :: ex
      character(len=:), allocatable         :: file_name

      ! read actual brightness
      file_name = this%path_backlight//"/actual_brightness"
      inquire(file=file_name, exist=ex)
      if (ex) then
         open(newunit=nunit, file=file_name, iostat=stat)
         read(nunit, *) this%actual_brightness
         close(nunit)
      else
         this%actual_brightness = 0
         ! error stop "file not found: "//file_name
      endif

      ! read max brightness
      file_name = this%path_backlight//"/max_brightness"
      inquire(file=file_name, exist=ex)
      if (ex) then
         open(newunit=nunit, file=file_name, iostat=stat)
         read(nunit, *) this%max_brightness
         close(nunit)
      else
         this%max_brightness = 0
         ! error stop "file not found: "//file_name
      endif

   end subroutine select_backlight
   !===============================================================================
   

   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental pure subroutine set_backlight_debug_switch(this,debug)
      class(linux_backlight), intent(inout) :: this
      character(len=*),       intent(in)    :: debug

      this%debug = debug
   end subroutine set_backlight_debug_switch
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_backlight_actual_brightness(this, actual_brightness)
      class(linux_backlight), intent(inout)          :: this
      integer,                intent(out),  optional :: actual_brightness

      if (present(actual_brightness)) actual_brightness = this%actual_brightness
      if (this%debug=='on') print'(a,i0)', 'actual brightness:         ', this%actual_brightness
   end subroutine get_backlight_actual_brightness
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine get_backlight_max_brightness(this, max_brightness)
      class(linux_backlight), intent(inout)          :: this
      integer,                intent(out),  optional :: max_brightness

      if (present(max_brightness)) max_brightness = this%max_brightness
      if (this%debug=='on') print'(a,i0)', 'max brightness:         ', this%max_brightness
   end subroutine get_backlight_max_brightness
   !===============================================================================

   
   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental impure subroutine set_backlight_brightness(this,brightness)
      class(linux_backlight), intent(inout) :: this
      integer,                intent(in)    :: brightness
      integer                               :: nunit, stat
      logical                               :: ex
      character(len=:), allocatable         :: file_name

      this%brightness = brightness

      file_name = this%path_backlight//"/brightness"
      inquire(file=file_name, exist=ex)
      if (ex) then
         open(newunit=nunit, file=file_name, iostat=stat)
         write(nunit, '(i0)') this%brightness
         close(nunit)
      else
         ! error stop "file not found: "//file_name
      endif
   end subroutine set_backlight_brightness
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental pure subroutine deallocate_linux_backlight(this)
      class(linux_backlight), intent(inout) :: this

      if (allocated(this%debug))          deallocate(this%debug)
      if (allocated(this%path_backlight)) deallocate(this%path_backlight)
   end subroutine deallocate_linux_backlight
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental pure subroutine deallocate_linux_cpu(this)
      class(linux_cpu), intent(inout) :: this

      if (allocated(this%debug))                         deallocate(this%debug)
      if (allocated(this%path_cpu))                      deallocate(this%path_cpu)
      if (allocated(this%scaling_governor))              deallocate(this%scaling_governor)
      if (allocated(this%energy_performance_preference)) deallocate(this%energy_performance_preference)
   end subroutine deallocate_linux_cpu
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental pure subroutine deallocate_linux_nodes(this)
      class(linux_nodes), intent(inout) :: this

      if (allocated(this%debug))     deallocate(this%debug)
      if (allocated(this%path_node)) deallocate(this%path_node)
      if (allocated(this%turbo))     deallocate(this%turbo)
      if (allocated(this%cpu))       call this%cpu(:)%deselect()
   end subroutine deallocate_linux_nodes
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   elemental pure subroutine deallocate_cluster(this)
      class(cluster), intent(inout) :: this

      if (allocated(this%node)) call this%node(:)%deselect()
      call this%backlight%deselect()
   end subroutine deallocate_cluster
   !===============================================================================

end module forclust