function setupParallelPool(obj)
% setupParallelPool

%   Copyright 2019-2021 The MathWorks, Inc.

    if (false == obj.useParallel)
        return;
    end

    % As of now, parallel simulation is not supported in XIL mode. So, turn off
    % this flag forcefully until it's supported
    if obj.IsXilMode
        obj.useParallel = false;
        obj.handleMsg('warning', message('Sldv:RunTestCase:UnabletoUseParPoolXILMode'));
        return;
    end

    % If the model is an internal harness, we will fall back to sequential
    % simulations. This is because parallel pool setup fails while trying
    % to load internal harnesses
    isHarness = Simulink.harness.isHarnessBD(obj.Model);
    if isHarness
        harnessOwner = Simulink.harness.internal.getHarnessOwnerBD(obj.Model);
        harnessProperties = Simulink.harness.find(harnessOwner, 'Name', obj.Model);
        isInternalHarness = ~harnessProperties.saveExternally;
        if isInternalHarness
            % Disable the use of parallel simulations
            obj.useParallel = false;
            obj.handleMsg('warning', message('Sldv:RunTestCase:UnabletoUseParPoolInternalHarness'));
            return;
        end
    end

    % If the model contains ToFile blocks, we will fall back to sequential
    % simulations when obj.useParallel is true.
    % Here, we check only the top model since model references cannot have
    % ToFile block (g1569858)
    % @todo update the usage of edit-time filter filterOutInactiveVariantSubsystemChoices()
    % instead use the post-compile filter activeVariants() - g2603143
    hasToFile = ~isempty(find_system(obj.ModelH,'MatchFilter',@Simulink.match.internal.filterOutInactiveVariantSubsystemChoices, 'BlockType', 'ToFile')); % look only inside active choice of VSS
    if hasToFile
        obj.useParallel = false;
        obj.handleMsg('warning', message('Sldv:RunTestCase:UnabletoUseParPoolToFileBlock'));
        return;
    end

    % Parallel simulations cannot be performed if the any of the model
    % in the model hierarchy tree is dirty. So, we will fall back to
    % sequential simulations.
    isMdlDirty = obj.checkDirtyState;
    if isMdlDirty
        obj.useParallel = false;
        obj.handleMsg('warning', message('Sldv:RunTestCase:DirtyMdlParSim', obj.Model));
        return;
    end

    % Finally, if we decide to use parallel pool for simulation; check for
    % any existing pool. Here, first we will check whether or not parallel
    % pool can be used.
    % If parllel pool can be used and no such pool exists, a new pool will
    % be created by 'parfor' construct depending upon whether or not
    % user has enabled the following option in 'Parallel Preferences'
    %    "Automatically create a parallel pool (if one doesn't already exist)..."
    % So, warn user about the fact that simulation may or may not use 
    % parallel pool depending upon 'Parallel Preferences'
    %
    % TopTester: matlab/test/toolbox/sldv/parallel/analysis/testgen/tParallelSim.m -testspec:lvlTwoParSimWithExistingParPool
    % TopTester: matlab/test/toolbox/sldv/parallel/analysis/testgen/tParallelSim.m -testspec:lvlTwoParSimWithNoParPoolAutoCreate
    % TopTester: matlab/test/toolbox/sldv/parallel/analysis/testgen/tParallelSim.m -testspec:lvlTwoParSimWithNoParPoolNoAutoCreate
    
    poolSize = 0;
    canUseParPool = matlab.internal.parallel.isPCTInstalled() && ...
        matlab.internal.parallel.isPCTLicensed();
    if canUseParPool
        try
            parallelCluster = parcluster;
        catch MEx
            obj.useParallel = false;
            obj.handleMsg('warning', message('Sldv:RunTestCase:ParPoolSetupFailed'));
            return;
        end

        if (isa(parallelCluster, 'parallel.cluster.Local'))
            % If no parallel pool exists, try to create a new one depending upon parallel preferences
            pool = gcp();
            if ~isempty(pool)
                poolSize = pool.NumWorkers;
            end
            if (0 == poolSize)
                obj.useParallel = false;
                obj.handleMsg('warning', message('Sldv:RunTestCase:ParPoolCreationFailed'));
                return;
            end
        else
            obj.useParallel = false;
            obj.handleMsg('warning', message('Sldv:RunTestCase:ParPoolSetupFailed'));
            return;
        end
    else
        obj.useParallel = false;
    end

    return;

end
