function run_hybrid_worker_for_phase_boundary(batchParams, batchIdx)
    % Set up local cluster for parallel pool
    cluster                  = parcluster('local');
    nprocs                   = str2double(getenv('SLURM_CPUS_PER_TASK'));
    if isnan(nprocs), nprocs = feature('numcores'); end

    tmpdir                   = fullfile(getenv('TMPDIR'), sprintf('matlab_job_%d', batchIdx));
    if ~exist(tmpdir, 'dir'), mkdir(tmpdir); end
    cluster.JobStorageLocation = tmpdir;

    pool = parpool(cluster, nprocs);

    % Extract single job parameters
    initial_a_s = batchParams(1);
    theta_deg   = batchParams(2);
    phi_deg     = batchParams(3);
    N_atoms     = batchParams(4);

    theta_rad   = deg2rad(theta_deg);
    phi_rad     = deg2rad(phi_deg);

    % Setup save directory
    jobName  = sprintf('aS_%03d_theta_%03d_phi_%03d_N_%d', initial_a_s, theta_deg, phi_deg, N_atoms);
    saveDir  = fullfile('./Results/Data_3D/PhaseDiagram', jobName);
    initfile = fullfile(saveDir, 'psi_init.mat')
    if ~exist(saveDir, 'dir'), mkdir(saveDir); end
    if ~exist(initfile, 'file'), warning('Running without user-provided initial state'); end
    
    % Parallelize attempts
    MaxAttempts = 10;
    parfor attempt = 1:MaxAttempts
        new_a_s = initial_a_s - 0.5 * (attempt - 1);
        
        try
            OptionsStruct = struct;
            OptionsStruct.NumberOfAtoms           = N_atoms;
            OptionsStruct.DipolarPolarAngle       = theta_rad;
            OptionsStruct.DipolarAzimuthAngle     = phi_rad;
            OptionsStruct.ScatteringLength        = new_a_s;
            OptionsStruct.TrapFrequencies         = [50, 20, 150];
            OptionsStruct.TrapPotentialType       = 'Harmonic';
            OptionsStruct.NumberOfGridPoints      = [128, 256, 128];
            OptionsStruct.Dimensions              = [20, 40, 20];
            OptionsStruct.UseApproximationForLHY  = true;
            OptionsStruct.IncludeDDICutOff        = true;
            OptionsStruct.CutoffType              = 'Cylindrical';
            OptionsStruct.SimulationMode          = 'ImaginaryTimeEvolution';
            OptionsStruct.GradientDescentMethod   = 'NonLinearCGD';
            OptionsStruct.MaxIterationsForGD      = 15000;
            OptionsStruct.TimeStepSize            = 1E-3;
            OptionsStruct.MinimumTimeStepSize     = 1E-6;
            OptionsStruct.TimeCutOff              = 2E5;
            OptionsStruct.EnergyTolerance         = 5E-10;
            OptionsStruct.ResidualTolerance       = 1E-04;
            OptionsStruct.NoiseScaleFactor        = 0.010;
            OptionsStruct.PlotLive                = false;
            OptionsStruct.JobNumber               = attempt - 1;
            OptionsStruct.RunOnGPU                = true;
            OptionsStruct.SaveData                = true;
            OptionsStruct.SaveDirectory           = saveDir;

            options = Helper.convertstruct2cell(OptionsStruct);

            sim = Simulator.DipolarGas(options{:});
            pot = Simulator.Potentials(options{:});
            sim.Potential = pot.trap();

            [~, ~, ~, ~, ~] = sim.run();

            fprintf('SUCCESS | Attempt %d: a_s = %.2f\n', attempt, new_a_s);

        catch ME
            fprintf('FAILURE | Attempt %d: %s\n', attempt, getReport(ME, 'basic'));
        end
    end

    delete(pool);
end