subroutine quasisymmetry_random ! N_random = maximum # of successful configurations to keep on each MPI processor. ! random_time = maximum number of seconds to run. ! This subroutine will exit when either of the above limits is reached. use quasisymmetry_variables implicit none include 'mpif.h' integer :: j, k integer*8 :: j_scan, index, attempts integer :: ierr, tag integer*8 :: dummy_long(1), print_summary_stride integer :: mpi_status(MPI_STATUS_SIZE) real(dp), dimension(:), allocatable :: iotas_local, max_elongations_local, mean_elongations_local, rms_curvatures_local, max_curvatures_local, axis_lengths_local real(dp), dimension(:), allocatable :: standard_deviations_of_R_local, standard_deviations_of_Z_local, max_modBinv_sqrt_half_grad_B_colon_grad_Bs_local integer, dimension(:), allocatable :: axis_helicities_local logical, dimension(:), allocatable :: iota_tolerance_achieveds_local, elongation_tolerance_achieveds_local, Newton_tolerance_achieveds_local integer*8, dimension(:), allocatable :: N_solves_kept, attempts_per_proc real(dp), dimension(:), allocatable :: scan_eta_bar_local, scan_sigma_initial_local, scan_B2s_local, scan_B2c_local real(dp), dimension(:,:), allocatable :: scan_R0c_local, scan_R0s_local, scan_Z0c_local, scan_Z0s_local real(dp), dimension(:), allocatable :: max_B2tildes_local, r_singularities_local, d2_volume_d_psi2s_local, B20_variations_local, min_R0s_local logical :: keep_going real(dp) :: thresh, time1, time2 real(dp) :: rand real(dp) :: log_eta_bar_min, log_eta_bar_max, log_sigma_initial_min, log_sigma_initial_max real(dp), dimension(max_axis_nmax+1) :: log_R0s_min, log_R0s_max, log_R0c_min, log_R0c_max, log_Z0s_min, log_Z0s_max, log_Z0c_min, log_Z0c_max real(dp) :: log_B2s_min, log_B2s_max, log_B2c_min, log_B2c_max integer :: random_size integer, allocatable :: random_seed_array(:) call mpi_barrier(MPI_COMM_WORLD,ierr) ! So initial lines printed by proc0 are sure to come first. ! Set seed for random numbers: call random_seed(size=random_size) allocate(random_seed_array(random_size)) call random_seed(get=random_seed_array) print "(a,i5,a,i4,a,16(i13))","on proc",mpi_rank," random_size=",random_size," old seed=",random_seed_array ! Ensure each proc has a different seed: random_seed_array(1) = random_seed_array(1) + mpi_rank call random_seed(put=random_seed_array) call random_seed(get=random_seed_array) print "(a,i5,a,i4,a,16(i13))","on proc",mpi_rank," random_size=",random_size," new seed=",random_seed_array deallocate(random_seed_array) call mpi_barrier(MPI_COMM_WORLD,ierr) ! For clean stdout ! Allocate arrays to store the scan results: allocate(iotas_local(N_random)) allocate(max_elongations_local(N_random)) allocate(mean_elongations_local(N_random)) allocate(rms_curvatures_local(N_random)) allocate(max_curvatures_local(N_random)) allocate(max_modBinv_sqrt_half_grad_B_colon_grad_Bs_local(N_random)) allocate(min_R0s_local(N_random)) allocate(axis_lengths_local(N_random)) allocate(standard_deviations_of_R_local(N_random)) allocate(standard_deviations_of_Z_local(N_random)) allocate(axis_helicities_local(N_random)) allocate(iota_tolerance_achieveds_local(N_random)) allocate(elongation_tolerance_achieveds_local(N_random)) allocate(Newton_tolerance_achieveds_local(N_random)) if (trim(order_r_option) == order_r_option_r1_compute_B2) then allocate(max_B2tildes_local(N_random)) end if if (trim(order_r_option) == order_r_option_r2) then allocate(r_singularities_local(N_random)) allocate(d2_volume_d_psi2s_local(N_random)) allocate(B20_variations_local(N_random)) end if ! Allocate arrays to store the input parameters that correspond to saved results: allocate(scan_eta_bar_local(N_random)) allocate(scan_sigma_initial_local(N_random)) allocate(scan_R0c_local(N_random,axis_nmax+1)) allocate(scan_R0s_local(N_random,axis_nmax+1)) allocate(scan_Z0c_local(N_random,axis_nmax+1)) allocate(scan_Z0s_local(N_random,axis_nmax+1)) if (trim(order_r_option) == order_r_option_r2) then allocate(scan_B2s_local(N_random)) allocate(scan_B2c_local(N_random)) end if log_eta_bar_min = log(abs(eta_bar_min)) log_eta_bar_max = log(abs(eta_bar_max)) log_sigma_initial_min = log(abs(sigma_initial_min)) log_sigma_initial_max = log(abs(sigma_initial_max)) log_R0s_min = log(abs(R0s_min)) log_R0s_max = log(abs(R0s_max)) log_R0c_min = log(abs(R0c_min)) log_R0c_max = log(abs(R0c_max)) log_Z0s_min = log(abs(Z0s_min)) log_Z0s_max = log(abs(Z0s_max)) log_Z0c_min = log(abs(Z0c_min)) log_Z0c_max = log(abs(Z0c_max)) log_B2s_min = log(abs(B2s_min)) log_B2s_max = log(abs(B2s_max)) log_B2c_min = log(abs(B2c_min)) log_B2c_max = log(abs(B2c_max)) call cpu_time(time2) j_scan = 0 attempts = 0 keep_going = .true. do while (keep_going) attempts = attempts + 1 ! If needed, pick a random value for eta_bar. if (eta_bar_max > eta_bar_min) then call random_number(rand) select case (trim(eta_bar_scan_option)) case (eta_bar_scan_option_linear) eta_bar = eta_bar_min + rand * (eta_bar_max - eta_bar_min) case (eta_bar_scan_option_log) eta_bar = exp(log_eta_bar_min + rand * (log_eta_bar_max - log_eta_bar_min)) case (eta_bar_scan_option_2_sided_log) eta_bar = exp(log_eta_bar_min + rand * (log_eta_bar_max - log_eta_bar_min)) call random_number(rand) if (rand > 0.5) eta_bar = -eta_bar ! Flip sign with 50% probability. case default stop "Error! Unrecognized eta_bar_scan_option" end select else eta_bar = eta_bar_max end if ! If needed, pick a random value for sigma_initial. if (sigma_initial_max > sigma_initial_min) then call random_number(rand) select case (trim(sigma_initial_scan_option)) case (sigma_initial_scan_option_linear) sigma_initial = sigma_initial_min + rand * (sigma_initial_max - sigma_initial_min) case (sigma_initial_scan_option_log) sigma_initial = exp(log_sigma_initial_min + rand * (log_sigma_initial_max - log_sigma_initial_min)) case (sigma_initial_scan_option_2_sided_log) sigma_initial = exp(log_sigma_initial_min + rand * (log_sigma_initial_max - log_sigma_initial_min)) call random_number(rand) if (rand > 0.5) sigma_initial = -sigma_initial ! Flip sign with 50% probability. case default stop "Error! Unrecognized sigma_initial_scan_option" end select else sigma_initial = sigma_initial_max end if if (trim(order_r_option) == order_r_option_r2) then ! If needed, pick a random value for B2s. if (B2s_max > B2s_min) then call random_number(rand) select case (trim(B2s_scan_option)) case (B2s_scan_option_linear) B2s = B2s_min + rand * (B2s_max - B2s_min) case (B2s_scan_option_log) B2s = exp(log_B2s_min + rand * (log_B2s_max - log_B2s_min)) case (B2s_scan_option_2_sided_log) B2s = exp(log_B2s_min + rand * (log_B2s_max - log_B2s_min)) call random_number(rand) if (rand > 0.5) B2s = -B2s ! Flip sign with 50% probability. case default stop "Error! Unrecognized B2s_scan_option" end select else B2s = B2s_max end if ! If needed, pick a random value for B2c. if (B2c_max > B2c_min) then call random_number(rand) select case (trim(B2c_scan_option)) case (B2c_scan_option_linear) B2c = B2c_min + rand * (B2c_max - B2c_min) case (B2c_scan_option_log) B2c = exp(log_B2c_min + rand * (log_B2c_max - log_B2c_min)) case (B2c_scan_option_2_sided_log) B2c = exp(log_B2c_min + rand * (log_B2c_max - log_B2c_min)) call random_number(rand) if (rand > 0.5) B2c = -B2c ! Flip sign with 50% probability. case default stop "Error! Unrecognized B2c_scan_option" end select else B2c = B2c_max end if end if ! Set Fourier amplitudes for axis: select case (trim(Fourier_scan_option)) case (Fourier_scan_option_linear) do j = 1, axis_nmax+1 if (R0s_max(j) > R0s_min(j)) then call random_number(rand) R0s(j) = R0s_min(j) + (R0s_max(j) - R0s_min(j)) * rand else R0s(j) = R0s_max(j) end if if (R0c_max(j) > R0c_min(j)) then call random_number(rand) R0c(j) = R0c_min(j) + (R0c_max(j) - R0c_min(j)) * rand else R0c(j) = R0c_max(j) end if if (Z0s_max(j) > Z0s_min(j)) then call random_number(rand) Z0s(j) = Z0s_min(j) + (Z0s_max(j) - Z0s_min(j)) * rand else Z0s(j) = Z0s_max(j) end if if (Z0c_max(j) > Z0c_min(j)) then call random_number(rand) Z0c(j) = Z0c_min(j) + (Z0c_max(j) - Z0c_min(j)) * rand else Z0c(j) = Z0c_max(j) end if end do case (Fourier_scan_option_2_sided_log, Fourier_scan_option_2_sided_log_except_Z0s1) do j = 1, axis_nmax+1 if (R0s_max(j) > R0s_min(j)) then call random_number(rand) R0s(j) = exp(log_R0s_min(j) + (log_R0s_max(j) - log_R0s_min(j)) * rand) call random_number(rand) if (rand > 0.5) R0s(j) = -R0s(j) ! Flip sign with 50% probability. else R0s(j) = R0s_max(j) end if if (R0c_max(j) > R0c_min(j)) then call random_number(rand) R0c(j) = exp(log_R0c_min(j) + (log_R0c_max(j) - log_R0c_min(j)) * rand) call random_number(rand) if (rand > 0.5) R0c(j) = -R0c(j) ! Flip sign with 50% probability. else R0c(j) = R0c_max(j) end if if (Z0s_max(j) > Z0s_min(j)) then call random_number(rand) Z0s(j) = exp(log_Z0s_min(j) + (log_Z0s_max(j) - log_Z0s_min(j)) * rand) if (j>2 .or. trim(Fourier_scan_option)==Fourier_scan_option_2_sided_log) then call random_number(rand) if (rand > 0.5) Z0s(j) = -Z0s(j) ! Flip sign with 50% probability. end if else Z0s(j) = Z0s_max(j) end if if (Z0c_max(j) > Z0c_min(j)) then call random_number(rand) Z0c(j) = exp(log_Z0c_min(j) + (log_Z0c_max(j) - log_Z0c_min(j)) * rand) call random_number(rand) if (rand > 0.5) Z0c(j) = -Z0c(j) ! Flip sign with 50% probability. else Z0c(j) = Z0c_max(j) end if end do case default stop "Error! Unrecognized Fourier_scan_option" end select if (verbose) then print "(a)"," ###################################################################################" print "(a)"," Random scan: trying the following parameters" print *,"eta_bar =",eta_bar print *,"sigma_initial = ",sigma_initial print *,"R0s:",R0s(1:axis_nmax+1) print *,"R0c:",R0c(1:axis_nmax+1) print *,"Z0s:",Z0s(1:axis_nmax+1) print *,"Z0c:",Z0c(1:axis_nmax+1) if (trim(order_r_option) == order_r_option_r2) then print *,"B2s =",B2s,", B2c = ",B2c end if end if call quasisymmetry_single_solve() ! Check whether one of the stopping criteria has been reached. ! We do this before all the 'cycles' in case most of the parameters are rejected call cpu_time(time1) if (time1 - start_time >= random_time) keep_going = .false. ! Periodically print a progress report: if (time1 - time2 > 10) then print "(a,i5,a,i12,a,i10,a)"," Proc",mpi_rank," now has",attempts," attempts and",j_scan," solutions." time2 = time1 end if ! If we can reject this solution, go back and pick new input parameters. if (skipped_solve) cycle ! In case R0 <= 0 or some other reason caused quasisymmetry_single_solve to exit prematurely. if (max_elongation > max_elongation_to_keep) cycle if (abs(iota) < min_iota_to_keep) cycle if (max_modBinv_sqrt_half_grad_B_colon_grad_B > max_max_modBinv_sqrt_half_grad_B_colon_grad_B_to_keep) cycle if (trim(order_r_option) == order_r_option_r1_compute_B2) then if (max_B2tilde > max_B2tilde_to_keep) cycle end if if (trim(order_r_option) == order_r_option_r2) then if (r_singularity < min_r_singularity_to_keep) cycle if (B20_variation > max_B20_variation_to_keep) cycle end if ! If we made it this far, then record the results j_scan = j_scan + 1 scan_eta_bar_local(j_scan) = eta_bar scan_sigma_initial_local(j_scan) = sigma_initial scan_R0c_local(j_scan,:) = R0c(1:axis_nmax+1) scan_R0s_local(j_scan,:) = R0s(1:axis_nmax+1) scan_Z0c_local(j_scan,:) = Z0c(1:axis_nmax+1) scan_Z0s_local(j_scan,:) = Z0s(1:axis_nmax+1) if (trim(order_r_option) == order_r_option_r2) then scan_B2s_local(j_scan) = B2s scan_B2c_local(j_scan) = B2c end if iotas_local(j_scan) = iota max_elongations_local(j_scan) = max_elongation mean_elongations_local(j_scan) = mean_elongation rms_curvatures_local(j_scan) = rms_curvature max_curvatures_local(j_scan) = max_curvature max_modBinv_sqrt_half_grad_B_colon_grad_Bs_local(j_scan) = max_modBinv_sqrt_half_grad_B_colon_grad_B min_R0s_local(j_scan) = min_R0 axis_lengths_local(j_scan) = axis_length standard_deviations_of_R_local(j_scan) = standard_deviation_of_R standard_deviations_of_Z_local(j_scan) = standard_deviation_of_Z axis_helicities_local(j_scan) = axis_helicity iota_tolerance_achieveds_local(j_scan) = iota_tolerance_achieved elongation_tolerance_achieveds_local(j_scan) = elongation_tolerance_achieved Newton_tolerance_achieveds_local(j_scan) = Newton_tolerance_achieved if (trim(order_r_option) == order_r_option_r1_compute_B2) then max_B2tildes_local(j_scan) = max_B2tilde end if if (trim(order_r_option) == order_r_option_r2) then r_singularities_local(j_scan) = r_singularity d2_volume_d_psi2s_local(j_scan) = d2_volume_d_psi2 B20_variations_local(j_scan) = B20_variation end if ! Check whether one of the stopping criteria has been reached if (j_scan >= N_random) keep_going = .false. end do call cpu_time(time1) print "(a,i5,a,es10.3,a)"," Proc",mpi_rank," finished after",time1 - start_time," sec." call mpi_barrier(MPI_COMM_WORLD,ierr) ! So proc0 does not start printing results until all procs have finished. call cpu_time(time1) ! Finally, send all results to proc 0. if (proc0) then if (N_procs > 1) then print "(a)"," ###################################################################################" print *,"Transferring results to proc 0" end if allocate(N_solves_kept(N_procs)) allocate(attempts_per_proc(N_procs)) N_solves_kept(1) = j_scan attempts_per_proc(1) = attempts do j = 1, N_procs-1 ! Use mpi_rank as the tag call mpi_recv(dummy_long,1,MPI_INTEGER8,j,j,MPI_COMM_WORLD,mpi_status,ierr) N_solves_kept(j+1) = dummy_long(1) call mpi_recv(dummy_long,1,MPI_INTEGER8,j,j,MPI_COMM_WORLD,mpi_status,ierr) attempts_per_proc(j+1) = dummy_long(1) attempts = attempts + dummy_long(1) end do print *,"attempted solutions on each proc:",attempts_per_proc print *,"# solves kept on each proc:",N_solves_kept N_scan = sum(N_solves_kept) print *,"Total # of attempts:",attempts print *,"Total # of solves kept:",N_scan ! Now that we know the total number of runs that were kept, we can allocate the arrays for the final results: allocate(iotas(N_scan)) allocate(max_elongations(N_scan)) allocate(mean_elongations(N_scan)) allocate(rms_curvatures(N_scan)) allocate(max_curvatures(N_scan)) allocate(max_modBinv_sqrt_half_grad_B_colon_grad_Bs(N_scan)) allocate(min_R0s(N_scan)) allocate(axis_lengths(N_scan)) allocate(standard_deviations_of_R(N_scan)) allocate(standard_deviations_of_Z(N_scan)) allocate(axis_helicities(N_scan)) allocate(iota_tolerance_achieveds(N_scan)) allocate(elongation_tolerance_achieveds(N_scan)) allocate(Newton_tolerance_achieveds(N_scan)) if (trim(order_r_option) == order_r_option_r1_compute_B2) then allocate(max_B2tildes(N_scan)) end if if (trim(order_r_option) == order_r_option_r2) then allocate(r_singularities(N_scan)) allocate(d2_volume_d_psi2s(N_scan)) allocate(B20_variations(N_scan)) end if allocate(scan_eta_bar(N_scan)) allocate(scan_sigma_initial(N_scan)) allocate(scan_R0c(N_scan,axis_nmax+1)) allocate(scan_R0s(N_scan,axis_nmax+1)) allocate(scan_Z0c(N_scan,axis_nmax+1)) allocate(scan_Z0s(N_scan,axis_nmax+1)) if (trim(order_r_option) == order_r_option_r2) then allocate(scan_B2s(N_scan)) allocate(scan_B2c(N_scan)) end if ! Store results from proc0 in the final arrays: iotas(1:N_solves_kept(1)) = iotas_local(1:N_solves_kept(1)) max_elongations(1:N_solves_kept(1)) = max_elongations_local(1:N_solves_kept(1)) mean_elongations(1:N_solves_kept(1)) = mean_elongations_local(1:N_solves_kept(1)) rms_curvatures(1:N_solves_kept(1)) = rms_curvatures_local(1:N_solves_kept(1)) max_curvatures(1:N_solves_kept(1)) = max_curvatures_local(1:N_solves_kept(1)) max_modBinv_sqrt_half_grad_B_colon_grad_Bs(1:N_solves_kept(1)) = max_modBinv_sqrt_half_grad_B_colon_grad_Bs_local(1:N_solves_kept(1)) min_R0s(1:N_solves_kept(1)) = min_R0s_local(1:N_solves_kept(1)) axis_lengths(1:N_solves_kept(1)) = axis_lengths_local(1:N_solves_kept(1)) standard_deviations_of_R(1:N_solves_kept(1)) = standard_deviations_of_R_local(1:N_solves_kept(1)) standard_deviations_of_Z(1:N_solves_kept(1)) = standard_deviations_of_Z_local(1:N_solves_kept(1)) axis_helicities(1:N_solves_kept(1)) = axis_helicities_local(1:N_solves_kept(1)) iota_tolerance_achieveds(1:N_solves_kept(1)) = iota_tolerance_achieveds_local(1:N_solves_kept(1)) elongation_tolerance_achieveds(1:N_solves_kept(1)) = elongation_tolerance_achieveds_local(1:N_solves_kept(1)) Newton_tolerance_achieveds(1:N_solves_kept(1)) = Newton_tolerance_achieveds_local(1:N_solves_kept(1)) if (trim(order_r_option) == order_r_option_r1_compute_B2) then max_B2tildes(1:N_solves_kept(1)) = max_B2tildes_local(1:N_solves_kept(1)) end if if (trim(order_r_option) == order_r_option_r2) then r_singularities(1:N_solves_kept(1)) = r_singularities_local(1:N_solves_kept(1)) d2_volume_d_psi2s(1:N_solves_kept(1)) = d2_volume_d_psi2s_local(1:N_solves_kept(1)) B20_variations(1:N_solves_kept(1)) = B20_variations_local(1:N_solves_kept(1)) end if scan_eta_bar(1:N_solves_kept(1)) = scan_eta_bar_local(1:N_solves_kept(1)) scan_sigma_initial(1:N_solves_kept(1)) = scan_sigma_initial_local(1:N_solves_kept(1)) scan_R0c(1:N_solves_kept(1),:) = scan_R0c_local(1:N_solves_kept(1),:) scan_R0s(1:N_solves_kept(1),:) = scan_R0s_local(1:N_solves_kept(1),:) scan_Z0c(1:N_solves_kept(1),:) = scan_Z0c_local(1:N_solves_kept(1),:) scan_Z0s(1:N_solves_kept(1),:) = scan_Z0s_local(1:N_solves_kept(1),:) if (trim(order_r_option) == order_r_option_r2) then scan_B2s(1:N_solves_kept(1)) = scan_B2s_local(1:N_solves_kept(1)) scan_B2c(1:N_solves_kept(1)) = scan_B2c_local(1:N_solves_kept(1)) end if index = N_solves_kept(1) + 1 do j = 1, N_procs-1 print "(a,i20,a,i4)"," Proc 0 is receiving results from ",N_solves_kept(j+1)," solves on proc",j call mpi_recv(iotas(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(max_elongations(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(mean_elongations(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(rms_curvatures(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(max_curvatures(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(max_modBinv_sqrt_half_grad_B_colon_grad_Bs(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(min_R0s(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(axis_lengths(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(standard_deviations_of_R(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(standard_deviations_of_Z(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(axis_helicities(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_INT,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(Newton_tolerance_achieveds(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_INT,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(iota_tolerance_achieveds(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_INT,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(elongation_tolerance_achieveds(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_INT,j,j,MPI_COMM_WORLD,mpi_status,ierr) if (trim(order_r_option) == order_r_option_r1_compute_B2) then call mpi_recv(max_B2tildes(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) end if if (trim(order_r_option) == order_r_option_r2) then call mpi_recv(r_singularities(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(d2_volume_d_psi2s(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(B20_variations(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) end if call mpi_recv(scan_eta_bar(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(scan_sigma_initial(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(scan_R0c(index:index+N_solves_kept(j+1)-1,:),N_solves_kept(j+1)*(axis_nmax+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(scan_R0s(index:index+N_solves_kept(j+1)-1,:),N_solves_kept(j+1)*(axis_nmax+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(scan_Z0c(index:index+N_solves_kept(j+1)-1,:),N_solves_kept(j+1)*(axis_nmax+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(scan_Z0s(index:index+N_solves_kept(j+1)-1,:),N_solves_kept(j+1)*(axis_nmax+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) if (trim(order_r_option) == order_r_option_r2) then call mpi_recv(scan_B2s(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) call mpi_recv(scan_B2c(index:index+N_solves_kept(j+1)-1),N_solves_kept(j+1),MPI_DOUBLE,j,j,MPI_COMM_WORLD,mpi_status,ierr) end if index = index + N_solves_kept(j+1) end do else ! Send the number of runs this proc kept: dummy_long(1) = j_scan ! Use mpi_rank as the tag call mpi_send(dummy_long,1,MPI_INTEGER8,0,mpi_rank,MPI_COMM_WORLD,ierr) dummy_long(1) = attempts call mpi_send(dummy_long,1,MPI_INTEGER8,0,mpi_rank,MPI_COMM_WORLD,ierr) ! Send the other results: call mpi_send(iotas_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(max_elongations_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(mean_elongations_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(rms_curvatures_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(max_curvatures_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(max_modBinv_sqrt_half_grad_B_colon_grad_Bs_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(min_R0s_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(axis_lengths_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(standard_deviations_of_R_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(standard_deviations_of_Z_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(axis_helicities_local(1:j_scan),j_scan,MPI_INT,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(Newton_tolerance_achieveds_local(1:j_scan),j_scan,MPI_LOGICAL,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(iota_tolerance_achieveds_local(1:j_scan),j_scan,MPI_LOGICAL,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(elongation_tolerance_achieveds_local(1:j_scan),j_scan,MPI_LOGICAL,0,mpi_rank,MPI_COMM_WORLD,ierr) if (trim(order_r_option) == order_r_option_r1_compute_B2) then call mpi_send(max_B2tildes_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) end if if (trim(order_r_option) == order_r_option_r2) then call mpi_send(r_singularities_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(d2_volume_d_psi2s_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(B20_variations_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) end if call mpi_send(scan_eta_bar_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(scan_sigma_initial_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(scan_R0c_local(1:j_scan,:),j_scan*(axis_nmax+1),MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(scan_R0s_local(1:j_scan,:),j_scan*(axis_nmax+1),MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(scan_Z0c_local(1:j_scan,:),j_scan*(axis_nmax+1),MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(scan_Z0s_local(1:j_scan,:),j_scan*(axis_nmax+1),MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) if (trim(order_r_option) == order_r_option_r2) then call mpi_send(scan_B2s_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) call mpi_send(scan_B2c_local(1:j_scan),j_scan,MPI_DOUBLE,0,mpi_rank,MPI_COMM_WORLD,ierr) end if end if if (proc0) then call cpu_time(time2) print "(a,es10.3,a)"," Time for communication:",time2 - time1," sec." print "(a)"," ###################################################################################" print *,"Scan complete." if (N_scan < 5000) then print "(a,99999(f8.2))"," iotas:",iotas print *," " print "(a,99999(f8.2))"," eta_bar:",scan_eta_bar print *," " print "(a,99999(f8.1))"," elongations:",max_elongations print *," " print "(a,99999(f8.2))"," rms_curvatures:",rms_curvatures print *," " print "(a,99999(f8.2))"," max_curvatures:",max_curvatures print *," " print "(a,99999(f8.2))"," max_modBinv_sqrt_half_grad_B_colon_grad_Bs:",max_modBinv_sqrt_half_grad_B_colon_grad_Bs print *," " if (trim(order_r_option) == order_r_option_r1_compute_B2) then print "(a,99999(f8.2))"," max_B2tildes:",max_B2tildes print *," " end if if (trim(order_r_option) == order_r_option_r2) then print "(a,99999(f8.2))"," r_singularities:",r_singularities print *," " print "(a,99999(f8.2))"," B20_variations:",B20_variations print *," " end if print "(a,99999(f8.2))"," axis_lengths:",axis_lengths print *," " print "(a,99999(i2))"," axis_helicities:",axis_helicities print *," Newton_tolerance_achieveds:",Newton_tolerance_achieveds print *," iota_tolerance_achieveds:",iota_tolerance_achieveds print *,"elongation_tolerance_achieveds:",elongation_tolerance_achieveds end if end if end subroutine quasisymmetry_random