def to_shell_manager(self, mpi_procs=1):
        """
        Returns a new `TaskManager` with the same parameters as self but replace the :class:`QueueAdapter`
        with a :class:`ShellAdapter` with mpi_procs so that we can submit the job without passing through the queue.
        """
        my_kwargs = copy.deepcopy(self._kwargs)
        my_kwargs["policy"] = TaskPolicy(autoparal=0)

        # On BlueGene we need at least two qadapters.
        # One for running jobs on the computing nodes and another one
        # for running small jobs on the fronted. These two qadapters
        # will have different enviroments and different executables.
        # If None of the q-adapters has qtype==shell, we change qtype to shell
        # and we return a new Manager for sequential jobs with the same parameters as self.
        # If the list contains a qadapter with qtype == shell, we ignore the remaining qadapters
        # when we build the new Manager.
        has_shell_qad = False
        for d in my_kwargs["qadapters"]:
            if d["queue"]["qtype"] == "shell": has_shell_qad = True
        if has_shell_qad:
            my_kwargs["qadapters"] = [d for d in my_kwargs["qadapters"] if d["queue"]["qtype"] == "shell"]

        for d in my_kwargs["qadapters"]:
            d["queue"]["qtype"] = "shell"
            d["limits"]["min_cores"] = mpi_procs
            d["limits"]["max_cores"] = mpi_procs

            # If shell_runner is specified, replace mpi_runner with shell_runner
            # in the script used to run jobs on the frontend.
            # On same machines based on Slurm, indeed, mpirun/mpiexec is not available
            # and jobs should be executed with `srun -n4 exec` when running on the computing nodes
            # or with `exec` when running in sequential on the frontend.
            if "job" in d and "shell_runner" in d["job"]:
                shell_runner = d["job"]["shell_runner"]
                #print("shell_runner:", shell_runner, type(shell_runner))
                if not shell_runner or shell_runner == "None": shell_runner = ""
                d["job"]["mpi_runner"] = shell_runner
                #print("shell_runner:", shell_runner)

        #print(my_kwargs)
        new = self.__class__(**my_kwargs)
        new.set_mpi_procs(mpi_procs)

        return new
Returns a new `TaskManager` with the same parameters as self but replace the :class:`QueueAdapter`
        with a :class:`ShellAdapter` with mpi_procs so that we can submit the job without passing through the queue.