Exemplo n.º 1
0
    def _initialise_runner(self, system0, system1):
        """Internal helper function to initialise the process runner.

           Parameters
           ----------

           system0 : :class:`System <BioSimSpace._SireWrappers.System>`
               The system for the first free energy leg.

           system1 : :class:`System <BioSimSpace._SireWrappers.System>`
               The system for the second free energy leg.
        """

        if type(system0) is not _System:
            raise TypeError(
                "'system0' must be of type 'BioSimSpace._SireWrappers.System'")

        if type(system1) is not _System:
            raise TypeError(
                "'system1' must be of type 'BioSimSpace._SireWrappers.System'")

        # Initialise lists to store the processes for each leg.
        leg0 = []
        leg1 = []

        # Get the simulation type.
        sim_type = self.__class__.__name__

        # Store the working directories for the legs.

        if sim_type == "Solvation":
            self._dir0 = "%s/free" % self._work_dir
            if self._is_dual:
                self._dir1 = "%s/vacuum" % self._work_dir
        elif sim_type == "Binding":
            self._dir0 = "%s/bound" % self._work_dir
            if self._is_dual:
                self._dir1 = "%s/free" % self._work_dir
        else:
            raise TypeError("Unsupported FreeEnergy simulation: '%s'" %
                            sim_type)

        # Convert to an appropriate AMBER topology. (Required by SOMD.)
        if self._engine == "SOMD":
            # Try to get the water model used to solvate the system.
            try:
                water_model = system0._sire_object.property(
                    "water_model").toString()
                waters0 = _SireIO.setAmberWater(
                    system0._sire_object.search("water"), water_model)
                if self._is_dual:
                    waters1 = _SireIO.setAmberWater(
                        system1._sire_object.search("water"), water_model)

            # If the system wasn't solvated by BioSimSpace, e.g. read from file, then try
            # to guess the water model from the topology.
            except:
                num_point = system0.getWaterMolecules()[0].nAtoms()

                if num_point == 3:
                    # TODO: Assume TIP3P. Not sure how to detect SPC/E.
                    waters0 = _SireIO.setAmberWater(
                        system0._sire_object.search("water"), "TIP3P")
                    if self._is_dual:
                        waters1 = _SireIO.setAmberWater(
                            system1._sire_object.search("water"), "TIP3P")
                    water_model = "tip3p"
                elif num_point == 4:
                    waters0 = _SireIO.setAmberWater(
                        system0._sire_object.search("water"), "TIP4P")
                    if self._is_dual:
                        waters1 = _SireIO.setAmberWater(
                            system1._sire_object.search("water"), "TIP4P")
                    water_model = "tip4p"
                elif num_point == 5:
                    waters0 = _SireIO.setAmberWater(
                        system0._sire_object.search("water"), "TIP5P")
                    if self._is_dual:
                        waters1 = _SireIO.setAmberWater(
                            system1._sire_object.search("water"), "TIP5P")
                    water_model = "tip5p"
                else:
                    raise RuntimeError("Unsupported %d-point water model!" %
                                       num_point)

                # Warn the user that we've guessed the water topology.
                _warnings.warn("Guessed water topology: %r" % water_model)

            # Remove the existing water molecules from the systems.
            system0.removeWaterMolecules()
            if self._is_dual:
                system1.removeWaterMolecules()

            # Convert the waters to BioSimSpace molecule containers.
            waters0 = _Molecules(waters0.toMolecules())
            if self._is_dual:
                waters1 = _Molecules(waters1.toMolecules())

            # Add the updated water topology back into the systems.
            system0.addMolecules(waters0)
            if self._is_dual:
                system1.addMolecules(waters1)

        # Get the lambda values from the protocol.
        lam_vals = self._protocol.getLambdaValues()

        # Loop over all of the lambda values.
        for lam in lam_vals:
            # Update the protocol lambda values.
            self._protocol.setLambdaValues(lam=lam, lam_vals=lam_vals)

            # Create and append the required processes for each leg.
            # Nest the working directories inside self._work_dir.

            # SOMD.
            if self._engine == "SOMD":
                # Check for GPU support.
                if "CUDA_VISIBLE_DEVICES" in _os.environ:
                    platform = "CUDA"
                else:
                    platform = "CPU"

                leg0.append(
                    _Process.Somd(system0,
                                  self._protocol,
                                  platform=platform,
                                  work_dir="%s/lambda_%5.4f" %
                                  (self._dir0, lam)))

                if self._is_dual:
                    leg1.append(
                        _Process.Somd(system1,
                                      self._protocol,
                                      platform=platform,
                                      work_dir="%s/lambda_%5.4f" %
                                      (self._dir1, lam)))

            # GROMACS.
            elif self._engine == "GROMACS":
                leg0.append(
                    _Process.Gromacs(system0,
                                     self._protocol,
                                     work_dir="%s/lambda_%5.4f" %
                                     (self._dir0, lam)))

                if self._is_dual:
                    leg1.append(
                        _Process.Gromacs(system1,
                                         self._protocol,
                                         work_dir="%s/lambda_%5.4f" %
                                         (self._dir1, lam)))

        # Initialise the process runner. All processes have already been nested
        # inside the working directory so no need to re-nest.
        self._runner = _Process.ProcessRunner(leg0 + leg1,
                                              work_dir=self._work_dir,
                                              nest_dirs=False)
Exemplo n.º 2
0
    def _initialise_runner(self, system0, system1):
        """Internral helper function to initialise the process runner.

           Parameters
           ----------

           system0 : :class:`System <BioSimSpace._SireWrappers.System>`
               The system for the first free energy leg.

           system1 : :class:`System <BioSimSpace._SireWrappers.System>`
               The system for the second free energy leg.
        """

        if type(system0) is not _System:
            raise TypeError(
                "'system0' must be of type 'BioSimSpace._SireWrappers.System'")

        if type(system1) is not _System:
            raise TypeError(
                "'system1' must be of type 'BioSimSpace._SireWrappers.System'")

        # Initialise lists to store the processes for each leg.
        leg0 = []
        leg1 = []

        # Get the simulation type.
        sim_type = self.__class__.__name__

        # Store the working directories for the legs.

        if sim_type == "Solvation":
            self._dir0 = "%s/free" % self._work_dir
            self._dir1 = "%s/vacuum" % self._work_dir
        elif sim_type == "Binding":
            self._dir0 = "%s/bound" % self._work_dir
            self._dir1 = "%s/free" % self._work_dir
        else:
            raise TypeError("Unsupported FreeEnergy simulation: '%s'" %
                            sim_type)

        # Try to get the water model property of the system.
        try:
            water_model = system0._sire_system.property(
                "water_model").toString()
        # Default to TIP3P.
        except:
            water_model = "tip3p"

        if self._engine == "SOMD":
            # Reformat all of the water molecules so that they match the expected
            # AMBER topology template. (Required by SOMD.)
            waters0 = _SireIO.setAmberWater(
                system0._sire_system.search("water"), water_model)
            waters1 = _SireIO.setAmberWater(
                system1._sire_system.search("water"), water_model)

            # Loop over all of the renamed water molecules, delete the old one
            # from the system, then add the renamed one back in.
            # TODO: This is a hack since the "update" method of Sire.System
            # doesn't work properly at present.
            system0.removeWaterMolecules()
            system1.removeWaterMolecules()
            for wat in waters0:
                system0._sire_system.add(wat, _SireMol.MGName("all"))
            for wat in waters1:
                system1._sire_system.add(wat, _SireMol.MGName("all"))

        # Get the lambda values from the protocol.
        lam_vals = self._protocol.getLambdaValues()

        # Loop over all of the lambda values.
        for lam in lam_vals:
            # Update the protocol lambda values.
            self._protocol.setLambdaValues(lam=lam, lam_vals=lam_vals)

            # Create and append the required processes for each leg.
            # Nest the working directories inside self._work_dir.

            # SOMD.
            if self._engine == "SOMD":
                # TODO: This is currently hard-coded to use SOMD with the CUDA platform.
                leg0.append(
                    _Process.Somd(system0,
                                  self._protocol,
                                  platform="CUDA",
                                  work_dir="%s/lambda_%5.4f" %
                                  (self._dir0, lam)))

                leg1.append(
                    _Process.Somd(system1,
                                  self._protocol,
                                  platform="CUDA",
                                  work_dir="%s/lambda_%5.4f" %
                                  (self._dir1, lam)))

            # GROMACS.
            elif self._engine == "GROMACS":
                # TODO: This is currently hard-coded to use SOMD with the CUDA platform.
                leg0.append(
                    _Process.Gromacs(system0,
                                     self._protocol,
                                     work_dir="%s/lambda_%5.4f" %
                                     (self._dir0, lam)))

                leg1.append(
                    _Process.Gromacs(system1,
                                     self._protocol,
                                     work_dir="%s/lambda_%5.4f" %
                                     (self._dir1, lam)))

        # Initialise the process runner. All processes have already been nested
        # inside the working directory so no need to re-nest.
        self._runner = _Process.ProcessRunner(leg0 + leg1,
                                              work_dir=self._work_dir,
                                              nest_dirs=False)