diff --git a/KIM/CMakeLists.txt b/KIM/CMakeLists.txt index 5d0a6bc7..5f19f1ee 100644 --- a/KIM/CMakeLists.txt +++ b/KIM/CMakeLists.txt @@ -25,8 +25,6 @@ include_directories("${CMAKE_Fortran_MODULE_DIRECTORY}") enable_testing() -include(FetchZeal) - add_subdirectory(src) # slatec is provided by the top-level cmake/Dependencies.cmake; do not add its subdir here add_subdirectory(src/math/libcerf-main) diff --git a/KIM/README.md b/KIM/README.md index 4350da15..160d1668 100644 --- a/KIM/README.md +++ b/KIM/README.md @@ -12,7 +12,6 @@ This is the integral plasma response model based on the code and model Kinetic L ### Auto-fetched Dependencies The following are automatically downloaded during build: -- **ZEAL** - Complex root finder ([Kravanja et al., 2000](#references)) - **QUADPACK** - Adaptive quadrature (from Netlib) - **libcerf** - Complex error function - **SLATEC** - Mathematical library @@ -30,8 +29,6 @@ To compile the code: make ``` -The build process downloads the ZEAL package (complex root finder) which requires a working LAPACK installation. - ## WKB Dispersion Solver Solves the kinetic dispersion relation D(k_r) = 0 for complex radial wavenumber k_r at each radial grid point. @@ -40,33 +37,21 @@ Solves the kinetic dispersion relation D(k_r) = 0 for complex radial wavenumber ```fortran &WKB_dispersion - WKB_dispersion_solver = 'Muller' ! 'Muller' or 'ZEAL' + WKB_dispersion_solver = 'Muller' ! 'Muller' WKB_dispersion_mode = 'KIM' ! 'KIM' (full Bessel) or 'FLRE' (finite Larmor radius expansion) / ``` ### Solvers -**Muller** (recommended): Iterative root finder using previous root as initial guess. Reliable branch tracking. - -**ZEAL**: Contour integration + Newton refinement. Per-branch tracking with configurable parameters in `zeal_input.f90`: -- `MAX_TRACKED_BRANCHES = 4` - Maximum simultaneous branches -- `BRANCH_SEARCH_HALFWIDTH = 1.5` - Search window per branch -- `BROAD_SEARCH_HALFWIDTH = 5.0` - Initial discovery window +**Muller**: Iterative root finder using previous root as initial guess. Reliable branch tracking. ### Output Results written to `out/m*_n*/dispersion/` directory: -- `muller_branches_*.dat` or `zeal_branches_*.dat` - Branch-tracked roots +- `muller_branches_*.dat` - Branch-tracked roots - HDF5 files with same data for post-processing ### Python Alternative Python implementation using cxroots: `python/KIMpy/WKB-dispersion/wkb.py` - -## References - -P. Kravanja, M. Van Barel, O. Ragos, M.N. Vrahatis, F.A. Zafiropoulos, -*ZEAL: A mathematical software package for computing zeros of analytic functions*, -Computer Physics Communications **124** (2000) 212-232. -[doi:10.1016/S0010-4655(99)00429-4](https://doi.org/10.1016/S0010-4655(99)00429-4) diff --git a/KIM/nmls/KIM_config.nml b/KIM/nmls/KIM_config.nml index 41f564b1..02938ac5 100644 --- a/KIM/nmls/KIM_config.nml +++ b/KIM/nmls/KIM_config.nml @@ -16,14 +16,14 @@ &wkb_dispersion WKB_dispersion_mode = 'KIM' ! 'KIM' (full Bessel) or 'FLRE' (finite Larmor radius) - WKB_dispersion_solver = 'ZEAL' ! 'Muller' or 'ZEAL' + WKB_dispersion_solver = 'Muller' ! 'Muller' WKB_solve_for_kr_squared = .false. ! If true, solve D(kr^2)=0; if false, solve D(kr)=0 - WKB_max_tracked_branches = 4 ! Max branches for ZEAL tracking + WKB_max_tracked_branches = 4 ! Max branches for per-branch tracking WKB_branch_search_halfwidth = 1.5 ! Search half-width per branch WKB_broad_search_halfwidth = 5.0 ! Initial broad search half-width WKB_broad_search_interval = 0 ! Broad search every N points (0=only at start) WKB_root_tolerance = 1.0d-6 ! |f(z)| tolerance for valid roots - WKB_verbose = .false. ! ZEAL verbose output + WKB_verbose = .false. ! Verbose dispersion solver output / &kim_io diff --git a/KIM/nmls/KIM_config_electromagnetic.nml b/KIM/nmls/KIM_config_electromagnetic.nml index 673a6321..68d407c8 100644 --- a/KIM/nmls/KIM_config_electromagnetic.nml +++ b/KIM/nmls/KIM_config_electromagnetic.nml @@ -18,7 +18,7 @@ &wkb_dispersion WKB_dispersion_mode = 'KIM' - WKB_dispersion_solver = 'ZEAL' + WKB_dispersion_solver = 'Muller' WKB_solve_for_kr_squared = .false. WKB_max_tracked_branches = 4 WKB_branch_search_halfwidth = 1.5 diff --git a/KIM/src/CMakeLists.txt b/KIM/src/CMakeLists.txt index f89be4c2..c6ecbd86 100644 --- a/KIM/src/CMakeLists.txt +++ b/KIM/src/CMakeLists.txt @@ -16,7 +16,6 @@ add_library(KIM_lib STATIC "${KIM_setup}" "${KIM_WKB_dispersion}" "${KIM_asymptotics}" "${KIM_electromagnetic}" - "${external_zeal}" ) set_target_properties(KIM_lib PROPERTIES @@ -67,8 +66,6 @@ add_library(quadpack_netlib STATIC ${QUADPACK_DIR}/dqk15i.f ) set_target_properties(quadpack_netlib PROPERTIES POSITION_INDEPENDENT_CODE ON) -# Add dqagx from zeal (not available on netlib, required by zeros.f90) -target_sources(quadpack_netlib PRIVATE ${CMAKE_BINARY_DIR}/_deps/zeal-src/dqagx.f) target_link_libraries(KIM_lib PUBLIC quadpack_netlib) # Optionally provide minimal XERROR compatibility if SLATEC doesn't provide it diff --git a/KIM/src/CMakeSources.in b/KIM/src/CMakeSources.in index df60668c..8de92307 100644 --- a/KIM/src/CMakeSources.in +++ b/KIM/src/CMakeSources.in @@ -80,18 +80,3 @@ set(KIM_electromagnetic electromagnetic/electromagnetic_kernel.f90 electromagnetic/ampere_matrices.f90 electromagnetic/electromagnetic_solver.f90 ) - -# Keep Zeal sources for root finding, but do not use its QUADPACK copies -# Use local modified copy of zeal_input.f90 instead of original form Zeal -set(external_dir ${CMAKE_BINARY_DIR}/_deps/zeal-src/) -set(external_zeal - ${external_dir}/prec.f90 - dispersion/zeal_input.f90 - ${external_dir}/integr_input.f90 - ${external_dir}/error.f90 - ${external_dir}/quad.f90 - ${external_dir}/split.f90 - ${external_dir}/refine.f90 - ${external_dir}/zeal.f90 - ${external_dir}/zeros.f90 - ) diff --git a/KIM/src/dispersion/fun_input.f90 b/KIM/src/dispersion/fun_input.f90 index 1dfc02ac..fa2d35d0 100644 --- a/KIM/src/dispersion/fun_input.f90 +++ b/KIM/src/dispersion/fun_input.f90 @@ -4,7 +4,7 @@ MODULE Function_Input_Module ! Module for dispersion function input. ! Keep this name, since ZEAL uses it. - USE Precision_Module, only: DP + USE KIM_kinds_m, only: DP IMPLICIT NONE diff --git a/KIM/src/dispersion/wkb_dispersion.f90 b/KIM/src/dispersion/wkb_dispersion.f90 index a6d82391..ad97dea9 100644 --- a/KIM/src/dispersion/wkb_dispersion.f90 +++ b/KIM/src/dispersion/wkb_dispersion.f90 @@ -2,7 +2,7 @@ module rt_WKB_dispersion_m !========================================================================================== ! module for running the WKB dispersion relation solver - ! Algorithms for root finding are Muller and ZEAL, both with per-branch tracking + ! Root finding uses Muller with per-branch tracking ! Dispersion functions implemented: KIM and FLRE to second order ! ! Configuration namelist is in KIM_config.nml named &wkb_dispersion @@ -79,8 +79,6 @@ subroutine run_wkb_dispersion(this) call write_complex_profile_abs(rg_grid%xb, found_roots(:,i), rg_grid%npts_b, & trim(out_str), "WKB dispersion relation", "cm^{-2}", dispersion_output_path) end do - case ('ZEAL') - call run_ZEAL_dispersion() case default stop "Unknown WKB dispersion solver" end select @@ -405,326 +403,5 @@ subroutine test_dispersion_KIM(kr, f) end subroutine test_dispersion_KIM - subroutine run_ZEAL_dispersion() - !----------------------------------------------------------------------- - ! Per-branch tracking ZEAL dispersion solver. - ! Tracks up to WKB_max_tracked_branches branches, each with its own search window. - ! - ! The search window of the grid point j>1 is based on the roots found at grid point j-1. - ! It is centered around the roots with a specified half width. - ! Additional branches within this window might be found. Set 'do_broad_search = true' in - ! KIM_config.nml to perform a broad search at certain grid points to find new branches. - !----------------------------------------------------------------------- - use Zeal_Module - use KIM_kinds_m, only: dp - use Function_Input_Module, only: rg_index, test_FDF_derivative, init_dispersion_mode - use grid_m, only: rg_grid - use IO_collection_m, only: write_tracked_roots - use Zeal_Input_Module, only: set_zeal_search_region - use config_m, only: WKB_max_tracked_branches, WKB_branch_search_halfwidth, & - WKB_broad_search_halfwidth, WKB_broad_search_interval, WKB_root_tolerance, & - WKB_dispersion_mode, dispersion_output_path, WKB_solve_for_kr_squared - - implicit none - - integer :: j, i, b, k - integer :: totalnumber, distinctnumber, refinednumber - integer, dimension(:), pointer :: multiplicities => null() - logical, dimension(:), pointer :: refinement_ok => null() - complex(kind=dp), dimension(:), pointer :: zeros => null() - complex(kind=dp), dimension(:), pointer :: fzeros => null() - - ! Per-branch tracking data - complex(dp), allocatable :: branch_center(:) ! Last known root position for each branch - complex(dp), allocatable :: branch_fvalue(:) ! Function value at branch root - integer, allocatable :: branch_mult(:) ! Multiplicity of each branch - logical, allocatable :: branch_active(:) ! Is branch currently being tracked? - integer, allocatable :: branch_miss_count(:) ! Consecutive misses (no root found) - integer :: n_active_branches - - ! Storage arrays for all grid points (one root per branch per grid point) - complex(dp), allocatable :: all_zeros(:,:) ! (max_branches, n_grid) - complex(dp), allocatable :: all_fzeros(:,:) - integer, allocatable :: all_multiplicities(:,:) - integer, allocatable :: all_branch_ids(:,:) ! Branch ID for each stored root - integer, allocatable :: n_roots_per_point(:) - - ! Temporary storage for ZEAL results - complex(dp), allocatable :: temp_zeros(:) - complex(dp), allocatable :: temp_fzeros(:) - integer, allocatable :: temp_mults(:) - logical, allocatable :: temp_valid(:) - integer :: n_temp_valid - - ! Working variables - real(dp) :: search_center_re, search_center_im - real(dp) :: dist - integer :: best_idx - logical :: do_broad_search - integer, parameter :: MAX_MISS_COUNT = 3 ! Deactivate branch after this many consecutive misses - - ! Allocate branch tracking arrays - allocate(branch_center(WKB_max_tracked_branches)) - allocate(branch_fvalue(WKB_max_tracked_branches)) - allocate(branch_mult(WKB_max_tracked_branches)) - allocate(branch_active(WKB_max_tracked_branches)) - allocate(branch_miss_count(WKB_max_tracked_branches)) - - ! Allocate storage for results - allocate(all_zeros(WKB_max_tracked_branches, rg_grid%npts_b)) - allocate(all_fzeros(WKB_max_tracked_branches, rg_grid%npts_b)) - allocate(all_multiplicities(WKB_max_tracked_branches, rg_grid%npts_b)) - allocate(all_branch_ids(WKB_max_tracked_branches, rg_grid%npts_b)) - allocate(n_roots_per_point(rg_grid%npts_b)) - - ! Temporary arrays for broad search - allocate(temp_zeros(20)) - allocate(temp_fzeros(20)) - allocate(temp_mults(20)) - allocate(temp_valid(20)) - - ! Initialize - branch_center = (0.0_dp, 0.0_dp) - branch_fvalue = (0.0_dp, 0.0_dp) - branch_mult = 1 - branch_active = .false. - branch_miss_count = 0 - n_active_branches = 0 - - all_zeros = (0.0_dp, 0.0_dp) - all_fzeros = (0.0_dp, 0.0_dp) - all_multiplicities = 0 - all_branch_ids = 0 - n_roots_per_point = 0 - - ! Initialize dispersion function pointer (KIM or FLRE) - call init_dispersion_mode() - - ! Test derivative at first grid point - rg_index = 1 - print *, 'Testing FDF derivative at grid point 1...' - call test_FDF_derivative(cmplx(1.0d0, 0.5d0, dp)) - - print * - print *, '=== Per-Branch ZEAL Tracking ===' - print *, 'Dispersion mode: ', trim(WKB_dispersion_mode) - if (WKB_solve_for_kr_squared) then - print *, 'Solver variable: kr^2 (solving D(kr^2)=0)' - else - print *, 'Solver variable: kr (solving D(kr)=0)' - end if - print *, 'Max tracked branches: ', WKB_max_tracked_branches - print *, 'Branch search half-width: ', WKB_branch_search_halfwidth - print *, 'Broad search half-width: ', WKB_broad_search_halfwidth - print * - - ! Main loop over grid points - do j = 1, rg_grid%npts_b - - print * - print *, '--- Grid point ', j, ' at x = ', rg_grid%xb(j), ' ---' - - rg_index = j - - ! Decide whether to do broad search - do_broad_search = (j == 1) ! Always at first point - if (WKB_broad_search_interval > 0 .and. j > 1) then - if (mod(j-1, WKB_broad_search_interval) == 0) do_broad_search = .true. - end if - ! Also do broad search if we have no active branches - if (n_active_branches == 0) do_broad_search = .true. - - !------------------------------------------------------------------- - ! Step 1: Track existing branches with focused searches - !------------------------------------------------------------------- - do b = 1, WKB_max_tracked_branches - if (.not. branch_active(b)) cycle - - ! Set small search window centered on this branch's last position - search_center_re = real(branch_center(b), dp) - search_center_im = aimag(branch_center(b)) - call set_zeal_search_region(search_center_re, search_center_im, WKB_branch_search_halfwidth) - - print *, ' Branch ', b, ': searching near (', search_center_re, ',', search_center_im, ')' - - ! Run ZEAL - nullify(zeros, fzeros, multiplicities, refinement_ok) - call zeal(totalnumber, distinctnumber, zeros, fzeros, multiplicities, refinednumber, refinement_ok) - - ! Find best valid root (smallest |f(z)|) - best_idx = 0 - if (distinctnumber > 0 .and. associated(zeros)) then - do i = 1, distinctnumber - if (abs(fzeros(i)) < WKB_root_tolerance .or. refinement_ok(i)) then - if (best_idx == 0) then - best_idx = i - else if (abs(fzeros(i)) < abs(fzeros(best_idx))) then - best_idx = i - end if - end if - end do - end if - - if (best_idx > 0) then - ! Found valid root - update branch - branch_center(b) = zeros(best_idx) - branch_fvalue(b) = fzeros(best_idx) - branch_mult(b) = multiplicities(best_idx) - branch_miss_count(b) = 0 - - ! Store in results - n_roots_per_point(j) = n_roots_per_point(j) + 1 - all_zeros(n_roots_per_point(j), j) = zeros(best_idx) - all_fzeros(n_roots_per_point(j), j) = fzeros(best_idx) - all_multiplicities(n_roots_per_point(j), j) = multiplicities(best_idx) - all_branch_ids(n_roots_per_point(j), j) = b - - print *, ' Found: z = (', real(zeros(best_idx)), ',', aimag(zeros(best_idx)), & - '), |f| = ', abs(fzeros(best_idx)) - else - ! No valid root found - branch_miss_count(b) = branch_miss_count(b) + 1 - print *, ' No valid root found (miss count: ', branch_miss_count(b), ')' - - if (branch_miss_count(b) >= MAX_MISS_COUNT) then - branch_active(b) = .false. - n_active_branches = n_active_branches - 1 - print *, ' Branch ', b, ' deactivated after ', MAX_MISS_COUNT, ' consecutive misses' - end if - end if - end do - - !------------------------------------------------------------------- - ! Step 2: Broad search to find new branches (if needed) - !------------------------------------------------------------------- - if (do_broad_search) then - print *, ' Running broad search...' - - ! Use broad search window (centered at origin or average of active branches) - if (n_active_branches > 0) then - search_center_re = 0.0_dp - search_center_im = 0.0_dp - k = 0 - do b = 1, WKB_max_tracked_branches - if (branch_active(b)) then - search_center_re = search_center_re + real(branch_center(b), dp) - search_center_im = search_center_im + aimag(branch_center(b)) - k = k + 1 - end if - end do - if (k > 0) then - search_center_re = search_center_re / real(k, dp) - search_center_im = search_center_im / real(k, dp) - end if - else - search_center_re = 0.0_dp - search_center_im = -1.0_dp ! Default center - end if - - call set_zeal_search_region(search_center_re, search_center_im, WKB_broad_search_halfwidth) - print *, ' Broad search centered at (', search_center_re, ',', search_center_im, & - '), half-width = ', WKB_broad_search_halfwidth - - ! Run ZEAL - nullify(zeros, fzeros, multiplicities, refinement_ok) - call zeal(totalnumber, distinctnumber, zeros, fzeros, multiplicities, refinednumber, refinement_ok) - - print *, ' Broad search found ', distinctnumber, ' zeros' - - ! Collect valid roots - n_temp_valid = 0 - if (distinctnumber > 0 .and. associated(zeros)) then - do i = 1, min(distinctnumber, 20) - if (abs(fzeros(i)) < WKB_root_tolerance .or. refinement_ok(i)) then - n_temp_valid = n_temp_valid + 1 - temp_zeros(n_temp_valid) = zeros(i) - temp_fzeros(n_temp_valid) = fzeros(i) - temp_mults(n_temp_valid) = multiplicities(i) - temp_valid(n_temp_valid) = .true. - end if - end do - end if - - print *, ' Valid roots from broad search: ', n_temp_valid - - ! Try to assign new roots to inactive branch slots - do i = 1, n_temp_valid - if (.not. temp_valid(i)) cycle - - ! Check if this root is already tracked by an active branch - do b = 1, WKB_max_tracked_branches - if (branch_active(b)) then - dist = abs(temp_zeros(i) - branch_center(b)) - if (dist < WKB_branch_search_halfwidth) then - temp_valid(i) = .false. ! Already tracked - exit - end if - end if - end do - - if (.not. temp_valid(i)) cycle - - ! Find an inactive branch slot - do b = 1, WKB_max_tracked_branches - if (.not. branch_active(b)) then - ! Activate new branch - branch_active(b) = .true. - branch_center(b) = temp_zeros(i) - branch_fvalue(b) = temp_fzeros(i) - branch_mult(b) = temp_mults(i) - branch_miss_count(b) = 0 - n_active_branches = n_active_branches + 1 - - ! Store in results (if not already stored by focused search) - n_roots_per_point(j) = n_roots_per_point(j) + 1 - all_zeros(n_roots_per_point(j), j) = temp_zeros(i) - all_fzeros(n_roots_per_point(j), j) = temp_fzeros(i) - all_multiplicities(n_roots_per_point(j), j) = temp_mults(i) - all_branch_ids(n_roots_per_point(j), j) = b - - print *, ' New branch ', b, ' at (', real(temp_zeros(i)), ',', & - aimag(temp_zeros(i)), ')' - temp_valid(i) = .false. - exit - end if - end do - end do - end if - - print *, ' Active branches: ', n_active_branches, ', Roots stored: ', n_roots_per_point(j) - - end do ! End grid loop - - !----------------------------------------------------------------------- - ! Summary and output - !----------------------------------------------------------------------- - print * - print *, '=== ZEAL Per-Branch Tracking Summary ===' - print *, 'Total grid points: ', rg_grid%npts_b - print *, 'Final active branches: ', n_active_branches - print *, 'Total roots stored: ', sum(n_roots_per_point) - - do b = 1, WKB_max_tracked_branches - if (branch_active(b)) then - print *, ' Branch ', b, ': final position (', real(branch_center(b)), ',', & - aimag(branch_center(b)), ')' - end if - end do - - ! Write tracked branches to file - call write_tracked_roots(rg_grid%xb, rg_grid%npts_b, & - all_zeros, all_fzeros, all_multiplicities, & - n_roots_per_point, all_branch_ids, WKB_max_tracked_branches, & - 'zeal_branches', 'ZEAL per-branch tracked dispersion', dispersion_output_path) - - print * - print *, 'Tracked branches written to output files.' - - ! Clean up - deallocate(branch_center, branch_fvalue, branch_mult, branch_active, branch_miss_count) - deallocate(all_zeros, all_fzeros, all_multiplicities, all_branch_ids, n_roots_per_point) - deallocate(temp_zeros, temp_fzeros, temp_mults, temp_valid) - - end subroutine end module diff --git a/KIM/src/dispersion/zeal_input.f90 b/KIM/src/dispersion/zeal_input.f90 deleted file mode 100644 index bdce5d19..00000000 --- a/KIM/src/dispersion/zeal_input.f90 +++ /dev/null @@ -1,100 +0,0 @@ -!----------------------------------------------------------------------- -! File copied from ZEAL package. Adapted for KIM. -! Comments kept from the original. -!----------------------------------------------------------------------- - -module Zeal_Input_Module - - use Precision_Module - use config_m, only: VERBOSE => WKB_verbose - - implicit none - - public - -!----------------------------------------------------------------------- -! specify the geometry of the rectangular region. -! the lower left vertex has coordinates lv(1) and lv(2). the stepsizes -! along the x- and y-direction are h(1) and h(2), respectively. -! -! note: these are now variables (not parameters) to allow adaptive -! search regions centered on previous roots. -! - real(kind=dp), dimension(2) :: LV = (/-5.0_dp, -5.0_dp/) - real(kind=dp), dimension(2) :: H = (/ 5.0_dp, 5.0_dp/) - -!----------------------------------------------------------------------- -! The value of M determines the maximum number of zeros -! (counting multiplicities) that are considered within a subregion. -! M has to be larger than the maximum of the multiplicities of the -! zeros. A recommended value is 5. -! - integer, parameter :: M = 5 - -!----------------------------------------------------------------------- -! Specify the values of ICON and NR. -! The parameter ICON may take the values 1, 2, 3 and 4. -! -! 1 => calculation of the total number of zeros, only. -! -! 2 => calculation of the total number of zeros and isolation -! of subregions that contain at most M zeros. -! -! 3 => calculation of the total number of zeros, isolation of -! subregions that contain at most M zeros, and computation -! of all the zeros and their multiplicity. -! -! 4 => calculation of the total number of zeros, isolation of -! subregions that contain at most M zeros, and computation -! of NR mutually distinct zeros and their multiplicity. -! - integer, parameter :: ICON = 3 ! Find ALL zeros (not just NR) - integer :: NR = 2 ! Only used if ICON=4 (ZEAL modifies this internally) - -!----------------------------------------------------------------------- -! VERBOSE is imported from config_m (WKB_verbose) and controlled via -! the WKB_DISPERSION namelist in KIM_config.nml. - -!----------------------------------------------------------------------- -! Specify the value of FILES. -! If FILES is set equal to .TRUE. then ZEAL generates the files -! "zeros.dat" and "mult.dat". They contain the computed approximations -! for the zeros as well as their respective multiplicities. ZEAL also -! writes the file "fzeros.dat", which contains the values that the -! function takes at the computed approximations for the zeros. -! - logical, parameter :: FILES = .FALSE. - -!----------------------------------------------------------------------- -! Specify the value of IFAIL. -! This variable determines how errors are to be handled. -! We follow the NAG convention: -! -! 1 => "soft silent error" -! Control returned to calling program. -! -! -1 => "soft noisy error" -! Error message is printed. -! Control returned to calling program. -! -! 0 => "hard noisy error" -! Error message is printed and program is stopped. -! - integer, parameter :: IFAIL = -1 - - -contains - - subroutine set_zeal_search_region(center_re, center_im, halfwidth) - !> Set the ZEAL search region centered on a given point. - real(kind=dp), intent(in) :: center_re, center_im - real(kind=dp), intent(in) :: halfwidth - - ! Set lower-left vertex and box size - LV(1) = center_re - halfwidth - LV(2) = center_im - halfwidth - H(1) = 2.0_DP * halfwidth - H(2) = 2.0_DP * halfwidth - end subroutine set_zeal_search_region - -end module Zeal_Input_Module diff --git a/KIM/src/setup/config_mod.f90 b/KIM/src/setup/config_mod.f90 index 1883fb1b..dd3fc219 100644 --- a/KIM/src/setup/config_mod.f90 +++ b/KIM/src/setup/config_mod.f90 @@ -21,14 +21,14 @@ module config_m ! WKB_DISPERSION namelist variables character(20) :: WKB_dispersion_mode = 'KIM' ! 'KIM' (full Bessel) or 'FLRE' (finite Larmor radius) - character(20) :: WKB_dispersion_solver = 'Muller' ! 'Muller' or 'ZEAL' + character(20) :: WKB_dispersion_solver = 'Muller' ! 'Muller' logical :: WKB_solve_for_kr_squared = .false. ! If true, solve for kr^2; if false, solve for kr - integer :: WKB_max_tracked_branches = 4 ! Max branches for ZEAL per-branch tracking + integer :: WKB_max_tracked_branches = 4 ! Max branches for per-branch root tracking real(dp) :: WKB_branch_search_halfwidth = 1.5_dp ! Search window half-width for tracking real(dp) :: WKB_broad_search_halfwidth = 5.0_dp ! Broad search window half-width integer :: WKB_broad_search_interval = 0 ! Run broad search every N points (0=only at start) real(dp) :: WKB_root_tolerance = 1.0d-6 ! |f(z)| tolerance for valid roots - logical :: WKB_verbose = .true. ! ZEAL verbose output + logical :: WKB_verbose = .true. ! Verbose dispersion solver output ! KIM_IO namelist variables character(256) :: profile_location ! path to profile directory diff --git a/KIM/src/tests/test_zeal.f90 b/KIM/src/tests/test_zeal.f90 deleted file mode 100644 index 5ed3eb43..00000000 --- a/KIM/src/tests/test_zeal.f90 +++ /dev/null @@ -1,42 +0,0 @@ -program test_zeal - - USE Precision_Module - USE Zeal_Module - - implicit none - - integer :: J - logical :: OUTPUT - - integer :: TOTALNUMBER, DISTINCTNUMBER, REFINEDNUMBER - integer, dimension(:), POINTER :: MULTIPLICITIES - logical, dimension(:), POINTER :: REFINEMENT_OK - COMPLEX(KIND=DP), DIMENSION(:), POINTER :: ZEROS, FZEROS - - CALL ZEAL(TOTALNUMBER,DISTINCTNUMBER,ZEROS,FZEROS, & - MULTIPLICITIES,REFINEDNUMBER,REFINEMENT_OK) - - OUTPUT = .true. - IF ( OUTPUT ) THEN - PRINT * - PRINT * - PRINT *, 'Total number of zeros = ', TOTALNUMBER - PRINT * - PRINT *, 'Number of mutually distinct zeros = ', DISTINCTNUMBER - PRINT * - PRINT *, 'Approximations for the zeros and verification:' - DO J = 1, DISTINCTNUMBER - PRINT 1, REAL(ZEROS(J),DP), AIMAG(ZEROS(J)), & - REAL(FZEROS(J),DP), AIMAG(FZEROS(J)), & - MULTIPLICITIES(J) - IF ( .NOT. REFINEMENT_OK(J) ) PRINT 2 - END DO - END IF - - 1 FORMAT (/3X, 'z = (', G22.15, ',', G22.15, ' )', & - /3X, 'f(z) = (', G22.15, ',', G22.15, ' )', & - /3X, 'multiplicity = ', I5) - 2 FORMAT (3X,'refinement not succesful') - - -end program diff --git a/README.md b/README.md index 4af23001..ecbb10f0 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,6 @@ The following are automatically downloaded and built if not found on the system: - **SuiteSparse** - Sparse matrix operations (UMFPACK) - **SUNDIALS** - Numerical differential equation solvers - **NetCDF** - Network Common Data Form (with Fortran bindings) -- **Zeal** - Mathematical special functions (zero finding) - **LAPACK/BLAS** - Fallback if not found on system ### Bundled Libraries (built from source) @@ -110,13 +109,6 @@ make test - `/python/` - Python interface (KAMELpy) for all codes - `/common/` - Shared utilities: equilibrium handling, math libraries, logger -## References - -P. Kravanja, M. Van Barel, O. Ragos, M.N. Vrahatis, F.A. Zafiropoulos, -*ZEAL: A mathematical software package for computing zeros of analytic functions*, -Computer Physics Communications **124** (2000) 212-232. -[doi:10.1016/S0010-4655(99)00429-4](https://doi.org/10.1016/S0010-4655(99)00429-4) - ## Contributing Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index fe3eb36d..9eb1951c 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -10,7 +10,6 @@ include(FetchLapack) include(FetchNetcdf) include(FetchSuiteSparse) include(FetchSUNDIALS) -include(FetchZeal) # QL-Balance sparse module (shared dependency) set(QLBALANCE_BASE "${CMAKE_SOURCE_DIR}/QL-Balance/src/base") diff --git a/cmake/FetchZeal.cmake b/cmake/FetchZeal.cmake deleted file mode 100644 index cac104e0..00000000 --- a/cmake/FetchZeal.cmake +++ /dev/null @@ -1,21 +0,0 @@ -include(FetchContent) - -find_program(GFORTRAN_EXECUTABLE gfortran REQUIRED - DOC "Plain gfortran for building Zeal" -) - -FetchContent_Declare(zeal - URL https://elsevier.digitalcommonsdata.com/public-files/datasets/yc9vv7rwyj/files/be55b15b-6d9c-4f0e-b5f7-09b300cfb806/file_downloaded - URL_HASH MD5=5450326083c6114b026fd765a9733928 -) - -# Download & extract Zeal sources, making them available -FetchContent_MakeAvailable(zeal) - -# Patch zeros.f90 to use modern ZGGEV instead of deprecated ZGEGV -# (ZGEGV was deprecated in LAPACK 3.0 and removed from modern distributions) -file(READ "${zeal_SOURCE_DIR}/zeros.f90" ZEROS_CONTENT) -string(REPLACE "ZGEGV" "ZGGEV" ZEROS_CONTENT "${ZEROS_CONTENT}") -file(WRITE "${zeal_SOURCE_DIR}/zeros.f90" "${ZEROS_CONTENT}") - -# Now `zeal_SOURCE_DIR` is set and sources can be compiled by subprojects