Run GULP using the gin as input

        Args:
            gin: GULP input string

        Returns:
            gout: GULP output string

def run(self, gin):
        """
        Run GULP using the gin as input

        Args:
            gin: GULP input string

        Returns:
            gout: GULP output string
        """
        with ScratchDir("."):
            p = subprocess.Popen(
                self._gulp_cmd, stdout=subprocess.PIPE,
                stdin=subprocess.PIPE, stderr=subprocess.PIPE
            )

            out, err = p.communicate(bytearray(gin, "utf-8"))
            out = out.decode("utf-8")
            err = err.decode("utf-8")

            if "Error" in err or "error" in err:
                print(gin)
                print("----output_0---------")
                print(out)
                print("----End of output_0------\n\n\n")
                print("----output_1--------")
                print(out)
                print("----End of output_1------")
                raise GulpError(err)

            # We may not need this
            if "ERROR" in out:
                raise GulpError(out)

            # Sometimes optimisation may fail to reach convergence
            conv_err_string = "Conditions for a minimum have not been satisfied"
            if conv_err_string in out:
                raise GulpConvergenceError()

            gout = ""
            for line in out.split("\n"):
                gout = gout + line + "\n"
            return gout