Esempio n. 1
0
def _solve_varproblem(*args, **kwargs):
    "Solve variational problem a == L or F == 0"

    # Extract arguments
    eq, u, bcs, J, Jp, M, form_compiler_parameters, solver_parameters, nullspace \
        = _extract_args(*args, **kwargs)

    # Solve linear variational problem
    if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form):

        # Create problem
        problem = vs.LinearVariationalProblem(eq.lhs, eq.rhs, u, bcs, Jp,
                                              form_compiler_parameters=form_compiler_parameters)

        # Create solver and call solve
        solver = vs.LinearVariationalSolver(problem, solver_parameters=solver_parameters,
                                            nullspace=nullspace)
        with progress(INFO, 'Solving linear variational problem'):
            solver.solve()

    # Solve nonlinear variational problem
    else:

        # Create problem
        problem = vs.NonlinearVariationalProblem(eq.lhs, u, bcs, J, Jp,
                                                 form_compiler_parameters=form_compiler_parameters)

        # Create solver and call solve
        solver = vs.NonlinearVariationalSolver(problem, solver_parameters=solver_parameters,
                                               nullspace=nullspace)
        with progress(INFO, 'Solving nonlinear variational problem'):
            solver.solve()

    # destroy snes part of solver so everything can be gc'd
    solver.destroy()
Esempio n. 2
0
def _solve_varproblem(*args, **kwargs):
    "Solve variational problem a == L or F == 0"

    # Extract arguments
    eq, u, bcs, J, Jp, M, form_compiler_parameters, \
        solver_parameters, nullspace, nullspace_T, options_prefix, \
        nest = _extract_args(*args, **kwargs)

    # Solve linear variational problem
    if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form):

        # Create problem
        problem = vs.LinearVariationalProblem(
            eq.lhs,
            eq.rhs,
            u,
            bcs,
            Jp,
            form_compiler_parameters=form_compiler_parameters,
            nest=nest)

        # Create solver and call solve
        solver = vs.LinearVariationalSolver(
            problem,
            solver_parameters=solver_parameters,
            nullspace=nullspace,
            transpose_nullspace=nullspace_T,
            options_prefix=options_prefix)
        with progress(INFO, 'Solving linear variational problem'):
            solver.solve()

    # Solve nonlinear variational problem
    else:

        if eq.rhs != 0:
            raise TypeError(
                "Only '0' support on RHS of nonlinear Equation, not %r" %
                eq.rhs)
        # Create problem
        problem = vs.NonlinearVariationalProblem(
            eq.lhs,
            u,
            bcs,
            J,
            Jp,
            form_compiler_parameters=form_compiler_parameters,
            nest=nest)

        # Create solver and call solve
        solver = vs.NonlinearVariationalSolver(
            problem,
            solver_parameters=solver_parameters,
            nullspace=nullspace,
            transpose_nullspace=nullspace_T,
            options_prefix=options_prefix)
        with progress(INFO, 'Solving nonlinear variational problem'):
            solver.solve()
Esempio n. 3
0
def _solve_varproblem(*args, **kwargs):
    "Solve variational problem a == L or F == 0"

    # Extract arguments
    eq, u, bcs, J, Jp, M, form_compiler_parameters, \
        solver_parameters, nullspace, nullspace_T, options_prefix, \
        nest = _extract_args(*args, **kwargs)

    # Solve linear variational problem
    if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form):

        # Create problem
        problem = vs.LinearVariationalProblem(eq.lhs, eq.rhs, u, bcs, Jp,
                                              form_compiler_parameters=form_compiler_parameters,
                                              nest=nest)

        # Create solver and call solve
        solver = vs.LinearVariationalSolver(problem, solver_parameters=solver_parameters,
                                            nullspace=nullspace,
                                            transpose_nullspace=nullspace_T,
                                            options_prefix=options_prefix)
        with progress(INFO, 'Solving linear variational problem'):
            solver.solve()

    # Solve nonlinear variational problem
    else:

        if eq.rhs != 0:
            raise TypeError("Only '0' support on RHS of nonlinear Equation, not %r" % eq.rhs)
        # Create problem
        problem = vs.NonlinearVariationalProblem(eq.lhs, u, bcs, J, Jp,
                                                 form_compiler_parameters=form_compiler_parameters,
                                                 nest=nest)

        # Create solver and call solve
        solver = vs.NonlinearVariationalSolver(problem, solver_parameters=solver_parameters,
                                               nullspace=nullspace,
                                               transpose_nullspace=nullspace_T,
                                               options_prefix=options_prefix)
        with progress(INFO, 'Solving nonlinear variational problem'):
            solver.solve()
Esempio n. 4
0
    def get_so(self, src, extension):
        """Build a shared library and load it

        :arg src: The source string to compile.
        :arg extension: extension of the source file (c, cpp).

        Returns a :class:`ctypes.CDLL` object of the resulting shared
        library."""

        # Determine cache key
        hsh = md5(src.encode())
        hsh.update(self._cc.encode())
        if self._ld:
            hsh.update(self._ld.encode())
        hsh.update("".join(self._cppargs).encode())
        hsh.update("".join(self._ldargs).encode())

        basename = hsh.hexdigest()

        cachedir = configuration['cache_dir']
        pid = os.getpid()
        cname = os.path.join(cachedir, "%s_p%d.%s" % (basename, pid, extension))
        oname = os.path.join(cachedir, "%s_p%d.o" % (basename, pid))
        soname = os.path.join(cachedir, "%s.so" % basename)
        # Link into temporary file, then rename to shared library
        # atomically (avoiding races).
        tmpname = os.path.join(cachedir, "%s_p%d.so.tmp" % (basename, pid))

        if configuration['check_src_hashes'] or configuration['debug']:
            matching = self.comm.allreduce(basename, op=_check_op)
            if matching != basename:
                # Dump all src code to disk for debugging
                output = os.path.join(cachedir, "mismatching-kernels")
                srcfile = os.path.join(output, "src-rank%d.c" % self.comm.rank)
                if self.comm.rank == 0:
                    if not os.path.exists(output):
                        os.makedirs(output, exist_ok=True)
                self.comm.barrier()
                with open(srcfile, "w") as f:
                    f.write(src)
                self.comm.barrier()
                raise CompilationError("Generated code differs across ranks (see output in %s)" % output)
        try:
            # Are we in the cache?
            return ctypes.CDLL(soname)
        except OSError:
            # No, let's go ahead and build
            if self.comm.rank == 0:
                # No need to do this on all ranks
                if not os.path.exists(cachedir):
                    os.makedirs(cachedir, exist_ok=True)
                logfile = os.path.join(cachedir, "%s_p%d.log" % (basename, pid))
                errfile = os.path.join(cachedir, "%s_p%d.err" % (basename, pid))
                with progress(INFO, 'Compiling wrapper'):
                    with open(cname, "w") as f:
                        f.write(src)
                    # Compiler also links
                    if self._ld is None:
                        cc = [self._cc] + self._cppargs + \
                             ['-o', tmpname, cname] + self._ldargs
                        debug('Compilation command: %s', ' '.join(cc))
                        with open(logfile, "w") as log:
                            with open(errfile, "w") as err:
                                log.write("Compilation command:\n")
                                log.write(" ".join(cc))
                                log.write("\n\n")
                                try:
                                    if configuration['no_fork_available']:
                                        cc += ["2>", errfile, ">", logfile]
                                        cmd = " ".join(cc)
                                        status = os.system(cmd)
                                        if status != 0:
                                            raise subprocess.CalledProcessError(status, cmd)
                                    else:
                                        subprocess.check_call(cc, stderr=err,
                                                              stdout=log)
                                except subprocess.CalledProcessError as e:
                                    raise CompilationError(
                                        """Command "%s" return error status %d.
Unable to compile code
Compile log in %s
Compile errors in %s""" % (e.cmd, e.returncode, logfile, errfile))
                    else:
                        cc = [self._cc] + self._cppargs + \
                             ['-c', '-o', oname, cname]
                        ld = self._ld.split() + ['-o', tmpname, oname] + self._ldargs
                        debug('Compilation command: %s', ' '.join(cc))
                        debug('Link command: %s', ' '.join(ld))
                        with open(logfile, "w") as log:
                            with open(errfile, "w") as err:
                                log.write("Compilation command:\n")
                                log.write(" ".join(cc))
                                log.write("\n\n")
                                log.write("Link command:\n")
                                log.write(" ".join(ld))
                                log.write("\n\n")
                                try:
                                    if configuration['no_fork_available']:
                                        cc += ["2>", errfile, ">", logfile]
                                        ld += ["2>", errfile, ">", logfile]
                                        cccmd = " ".join(cc)
                                        ldcmd = " ".join(ld)
                                        status = os.system(cccmd)
                                        if status != 0:
                                            raise subprocess.CalledProcessError(status, cccmd)
                                        status = os.system(ldcmd)
                                        if status != 0:
                                            raise subprocess.CalledProcessError(status, ldcmd)
                                    else:
                                        subprocess.check_call(cc, stderr=err,
                                                              stdout=log)
                                        subprocess.check_call(ld, stderr=err,
                                                              stdout=log)
                                except subprocess.CalledProcessError as e:
                                    raise CompilationError(
                                        """Command "%s" return error status %d.
Unable to compile code
Compile log in %s
Compile errors in %s""" % (e.cmd, e.returncode, logfile, errfile))
                    # Atomically ensure soname exists
                    os.rename(tmpname, soname)
            # Wait for compilation to complete
            self.comm.barrier()
            # Load resulting library
            return ctypes.CDLL(soname)
Esempio n. 5
0
    def get_so(self, jitmodule, extension):
        """Build a shared library and load it

        :arg jitmodule: The JIT Module which can generate the code to compile.
        :arg extension: extension of the source file (c, cpp).

        Returns a :class:`ctypes.CDLL` object of the resulting shared
        library."""

        # Determine cache key
        hsh = md5(str(jitmodule.cache_key).encode())
        hsh.update(self._cc.encode())
        if self._ld:
            hsh.update(self._ld.encode())
        hsh.update("".join(self._cppargs).encode())
        hsh.update("".join(self._ldargs).encode())

        basename = hsh.hexdigest()

        cachedir = configuration['cache_dir']

        dirpart, basename = basename[:2], basename[2:]
        cachedir = os.path.join(cachedir, dirpart)
        pid = os.getpid()
        cname = os.path.join(cachedir, "%s_p%d.%s" % (basename, pid, extension))
        oname = os.path.join(cachedir, "%s_p%d.o" % (basename, pid))
        soname = os.path.join(cachedir, "%s.so" % basename)
        # Link into temporary file, then rename to shared library
        # atomically (avoiding races).
        tmpname = os.path.join(cachedir, "%s_p%d.so.tmp" % (basename, pid))

        if configuration['check_src_hashes'] or configuration['debug']:
            matching = self.comm.allreduce(basename, op=_check_op)
            if matching != basename:
                # Dump all src code to disk for debugging
                output = os.path.join(cachedir, "mismatching-kernels")
                srcfile = os.path.join(output, "src-rank%d.c" % self.comm.rank)
                if self.comm.rank == 0:
                    os.makedirs(output, exist_ok=True)
                self.comm.barrier()
                with open(srcfile, "w") as f:
                    f.write(jitmodule.code_to_compile)
                self.comm.barrier()
                raise CompilationError("Generated code differs across ranks (see output in %s)" % output)
        try:
            # Are we in the cache?
            return ctypes.CDLL(soname)
        except OSError:
            # No, let's go ahead and build
            if self.comm.rank == 0:
                # No need to do this on all ranks
                os.makedirs(cachedir, exist_ok=True)
                logfile = os.path.join(cachedir, "%s_p%d.log" % (basename, pid))
                errfile = os.path.join(cachedir, "%s_p%d.err" % (basename, pid))
                with progress(INFO, 'Compiling wrapper'):
                    with open(cname, "w") as f:
                        f.write(jitmodule.code_to_compile)
                    # Compiler also links
                    if self._ld is None:
                        cc = [self._cc] + self._cppargs + \
                             ['-o', tmpname, cname] + self._ldargs
                        debug('Compilation command: %s', ' '.join(cc))
                        with open(logfile, "w") as log:
                            with open(errfile, "w") as err:
                                log.write("Compilation command:\n")
                                log.write(" ".join(cc))
                                log.write("\n\n")
                                try:
                                    if configuration['no_fork_available']:
                                        cc += ["2>", errfile, ">", logfile]
                                        cmd = " ".join(cc)
                                        status = os.system(cmd)
                                        if status != 0:
                                            raise subprocess.CalledProcessError(status, cmd)
                                    else:
                                        subprocess.check_call(cc, stderr=err,
                                                              stdout=log)
                                except subprocess.CalledProcessError as e:
                                    raise CompilationError(
                                        """Command "%s" return error status %d.
Unable to compile code
Compile log in %s
Compile errors in %s""" % (e.cmd, e.returncode, logfile, errfile))
                    else:
                        cc = [self._cc] + self._cppargs + \
                             ['-c', '-o', oname, cname]
                        ld = self._ld.split() + ['-o', tmpname, oname] + self._ldargs
                        debug('Compilation command: %s', ' '.join(cc))
                        debug('Link command: %s', ' '.join(ld))
                        with open(logfile, "w") as log:
                            with open(errfile, "w") as err:
                                log.write("Compilation command:\n")
                                log.write(" ".join(cc))
                                log.write("\n\n")
                                log.write("Link command:\n")
                                log.write(" ".join(ld))
                                log.write("\n\n")
                                try:
                                    if configuration['no_fork_available']:
                                        cc += ["2>", errfile, ">", logfile]
                                        ld += ["2>", errfile, ">", logfile]
                                        cccmd = " ".join(cc)
                                        ldcmd = " ".join(ld)
                                        status = os.system(cccmd)
                                        if status != 0:
                                            raise subprocess.CalledProcessError(status, cccmd)
                                        status = os.system(ldcmd)
                                        if status != 0:
                                            raise subprocess.CalledProcessError(status, ldcmd)
                                    else:
                                        subprocess.check_call(cc, stderr=err,
                                                              stdout=log)
                                        subprocess.check_call(ld, stderr=err,
                                                              stdout=log)
                                except subprocess.CalledProcessError as e:
                                    raise CompilationError(
                                        """Command "%s" return error status %d.
Unable to compile code
Compile log in %s
Compile errors in %s""" % (e.cmd, e.returncode, logfile, errfile))
                    # Atomically ensure soname exists
                    os.rename(tmpname, soname)
            # Wait for compilation to complete
            self.comm.barrier()
            # Load resulting library
            return ctypes.CDLL(soname)
Esempio n. 6
0
def _la_solve(A, x, b, bcs=None, parameters=None,
              nullspace=None):
    """Solves a linear algebra problem.

    :arg A: the assembled bilinear form, a :class:`.Matrix`.
    :arg x: the :class:`.Function` to write the solution into.
    :arg b: the :class:`.Function` defining the right hand side values.
    :arg bcs: an optional list of :class:`.DirichletBC`\s to apply.
    :arg parameters: optional solver parameters.
    :arg nullspace: an optional :class:`.VectorSpaceBasis` (or
         :class:`.MixedVectorSpaceBasis`) spanning the null space of
         the operator.
    .. note::
        Any boundary conditions passed in as an argument here override the
        boundary conditions set when the bilinear form was assembled.
        That is, in the following example:
        .. code-block:: python

           A = assemble(a, bcs=[bc1])
           solve(A, x, b, bcs=[bc2])

        the boundary conditions in `bc2` will be applied to the problem
        while `bc1` will be ignored.

    Example usage:

    .. code-block:: python

        _la_solve(A, x, b, parameters=parameters_dict)

    The linear solver and preconditioner are selected by looking at
    the parameters dict, if it is empty, the defaults are taken from
    PyOP2 (see :var:`pyop2.DEFAULT_SOLVER_PARAMETERS`)."""

    # Make sure we don't stomp on a dict the user has passed in.
    parameters = copy(parameters) if parameters is not None else {}
    parameters.setdefault('ksp_type', 'gmres')
    parameters.setdefault('pc_type', 'ilu')
    if A._M.sparsity.shape != (1, 1):
        parameters.setdefault('pc_type', 'jacobi')
    solver = op2.Solver(parameters=parameters)
    if A.has_bcs and bcs is None:
        # Pick up any BCs on the linear operator
        bcs = A.bcs
    elif bcs is not None:
        # Override using bcs from solve call
        A.bcs = _extract_bcs(bcs)
    if bcs is not None:
        # Solving A x = b - action(a, u_bc)
        u_bc = function.Function(b.function_space())
        for bc in bcs:
            bc.apply(u_bc)
        # rhs = b - action(A, u_bc)
        u_bc.assign(b - A._form_action(u_bc))
        # Now we need to apply the boundary conditions to the "RHS"
        for bc in bcs:
            bc.apply(u_bc)
        # don't want to write into b itself, because that would confuse user
        b = u_bc
    if nullspace is not None:
        nullspace._apply(A._M)
    with progress(INFO, 'Solving linear system'):
        solver.solve(A.M, x.dat, b.dat)
    x.dat.halo_exchange_begin()
    x.dat.halo_exchange_end()