Example #1
0
    def _solve(self):
        """
        Run the iterative solver.
        """
        maxiter = self.options['maxiter']
        atol = self.options['atol']
        rtol = self.options['rtol']
        iprint = self.options['iprint']

        self._mpi_print_header()

        self._iter_count = 0
        norm0, norm = self._iter_initialize()

        self._norm0 = norm0

        self._mpi_print(self._iter_count, norm, norm / norm0)

        while self._iter_count < maxiter and norm > atol and norm / norm0 > rtol:
            with Recording(type(self).__name__, self._iter_count, self) as rec:
                self._single_iteration()
                self._iter_count += 1
                self._run_apply()
                norm = self._iter_get_norm()
                # With solvers, we want to record the norm AFTER the call, but the call needs to
                # be wrapped in the with for stack purposes, so we locally assign  norm & norm0
                # into the class.
                rec.abs = norm
                if norm0 == 0:
                    norm0 = 1
                rec.rel = norm / norm0

            self._mpi_print(self._iter_count, norm, norm / norm0)

        system = self._system()
        if system.comm.rank == 0 or os.environ.get('USE_PROC_FILES'):
            prefix = self._solver_info.prefix + self.SOLVER

            # Solver terminated early because a Nan in the norm doesn't satisfy the while-loop
            # conditionals.
            if np.isinf(norm) or np.isnan(norm):
                msg = "Solver '{}' on system '{}': residuals contain 'inf' or 'NaN' after {} " + \
                      "iterations."
                if iprint > -1:
                    print(prefix + msg.format(self.SOLVER, system.pathname,
                                              self._iter_count))

                # Raise AnalysisError if requested.
                if self.options['err_on_non_converge']:
                    raise AnalysisError(
                        msg.format(self.SOLVER, system.pathname,
                                   self._iter_count))

            # Solver hit maxiter without meeting desired tolerances.
            elif (norm > atol and norm / norm0 > rtol):
                msg = "Solver '{}' on system '{}' failed to converge in {} iterations."

                if iprint > -1:
                    print(prefix + msg.format(self.SOLVER, system.pathname,
                                              self._iter_count))

                # Raise AnalysisError if requested.
                if self.options['err_on_non_converge']:
                    raise AnalysisError(
                        msg.format(self.SOLVER, system.pathname,
                                   self._iter_count))

            # Solver converged
            elif iprint == 1:
                print(prefix +
                      ' Converged in {} iterations'.format(self._iter_count))
            elif iprint == 2:
                print(prefix + ' Converged')
Example #2
0
    def _run_iterator(self):
        """
        Run the iterative solver.

        Returns
        -------
        boolean
            Failure flag; True if failed to converge, False is successful.
        float
            absolute error.
        float
            relative error.
        """
        maxiter = self.options['maxiter']
        atol = self.options['atol']
        rtol = self.options['rtol']
        iprint = self.options['iprint']

        self._mpi_print_header()

        self._iter_count = 0
        norm0, norm = self._iter_initialize()

        self._norm0 = norm0

        self._mpi_print(self._iter_count, norm, norm / norm0)

        while self._iter_count < maxiter and \
                norm > atol and norm / norm0 > rtol:
            with Recording(type(self).__name__, self._iter_count, self) as rec:
                self._iter_execute()
                self._iter_count += 1
                self._run_apply()
                norm = self._iter_get_norm()
                # With solvers, we want to record the norm AFTER the call, but the call needs to
                # be wrapped in the with for stack purposes, so we locally assign  norm & norm0
                # into the class.
                rec.abs = norm
                rec.rel = norm / norm0

            if norm0 == 0:
                norm0 = 1
            self._mpi_print(self._iter_count, norm, norm / norm0)

        fail = (np.isinf(norm) or np.isnan(norm)
                or (norm > atol and norm / norm0 > rtol))

        if self._system.comm.rank == 0 or os.environ.get('USE_PROC_FILES'):
            prefix = self._solver_info.prefix + self.SOLVER
            if fail:
                if iprint > -1:
                    msg = ' Failed to Converge in {} iterations'.format(
                        self._iter_count)
                    print(prefix + msg)

                # Raise AnalysisError if requested.
                if self.options['err_on_maxiter']:
                    msg = "Solver '{}' on system '{}' failed to converge."
                    raise AnalysisError(
                        msg.format(self.SOLVER, self._system.pathname))

            elif iprint == 1:
                print(prefix +
                      ' Converged in {} iterations'.format(self._iter_count))
            elif iprint == 2:
                print(prefix + ' Converged')

        return fail, norm, norm / norm0
Example #3
0
    def solve_nonlinear(self, inputs, outputs):

        solver = self.options['solver']
        ap = self.options['ap']

        if self._do_solve:

            self._set_ap(inputs)
            self._set_geo(inputs, update_jacobian=False)
            ap.solveFailed = False  # might need to clear this out?
            ap.fatalFail = False

            solver(ap)

            if ap.fatalFail:
                if self.comm.rank == 0:
                    print(
                        '###############################################################'
                    )
                    print('# Solve Fatal Fail. Analysis Error')
                    print(
                        '###############################################################'
                    )

                raise AnalysisError('ADFLOW Solver Fatal Fail')

            if ap.solveFailed:  # the mesh was fine, but it didn't converge
                # if the previous iteration was already a clean restart, dont try again
                if self.cleanRestart:
                    print(
                        '###############################################################'
                    )
                    print(
                        '# This was a clean restart. Will not try another one.'
                    )
                    print(
                        '###############################################################'
                    )
                    solver.resetFlow(ap)
                    self.cleanRestart = True
                    raise AnalysisError('ADFLOW Solver Fatal Fail')

                # the previous iteration restarted from another solution, so we can try again
                # with a re-set flowfield for the initial guess.
                else:
                    if self.comm.rank == 0:
                        print(
                            '###############################################################'
                        )
                        print('# Solve Failed, attempting a clean restart!')
                        print(
                            '###############################################################'
                        )

                    ap.solveFailed = False
                    ap.fatalFail = False
                    solver.resetFlow(ap)
                    solver(ap)

                    if ap.solveFailed or ap.fatalFail:  # we tried, but there was no saving it
                        print(
                            '###############################################################'
                        )
                        print(
                            '# Clean Restart failed. There is no saving this one!'
                        )
                        print(
                            '###############################################################'
                        )

                        # re-set the flow for the next iteration:
                        solver.resetFlow(ap)
                        # set the reset flow flag
                        self.cleanRestart = True
                        raise AnalysisError('ADFLOW Solver Fatal Fail')

                    # see comment for the same flag below
                    else:
                        self.cleanRestart = False

            # solve did not fail, therefore we will re-use this converged flowfield for the next iteration.
            # change the flag so that if the next iteration fails with current initial guess, it can retry
            # with a clean restart
            else:
                self.cleanRestart = False

        outputs['states'] = solver.getStates()
Example #4
0
    def run_component(self, command=None):
        """
        Run this component.

        User should call this method from their overriden compute method.

        Parameters
        ----------
        command : List
            Optional command. Otherwise use the command in self.options['command'].
        """
        comp = self._comp

        if not command:
            command = comp.options['command']

        comp.return_code = -12345678

        if not command:
            raise ValueError('Empty command list')

        if comp.options['fail_hard']:
            err_class = RuntimeError
        else:
            err_class = AnalysisError

        return_code = None

        try:
            missing = self._check_for_files(
                comp.options['external_input_files'])
            if missing:
                raise err_class("The following input files are missing: %s" %
                                sorted(missing))
            return_code, error_msg = self._execute_local(command)

            if return_code is None:
                raise AnalysisError('Timed out after %s sec.' %
                                    comp.options['timeout'])

            elif return_code not in comp.options['allowed_return_codes']:
                if isinstance(comp.stderr, str):
                    if os.path.exists(comp.stderr):
                        with open(comp.stderr, 'r') as stderrfile:
                            error_desc = stderrfile.read()
                        err_fragment = "\nError Output:\n%s" % error_desc
                    else:
                        err_fragment = "\n[stderr %r missing]" % comp.stderr
                else:
                    err_fragment = error_msg

                raise err_class('return_code = %d%s' %
                                (return_code, err_fragment))

            missing = self._check_for_files(
                comp.options['external_output_files'])
            if missing:
                raise err_class("The following output files are missing: %s" %
                                sorted(missing))

        finally:
            comp.return_code = -999999 if return_code is None else return_code
Example #5
0
    def _solve(self):
        """
        Run the iterative solver.
        """
        maxiter = self.options['maxiter']
        atol = self.options['atol']
        rtol = self.options['rtol']
        iprint = self.options['iprint']
        stall_limit = self.options['stall_limit']
        stall_tol = self.options['stall_tol']

        self._mpi_print_header()

        self._iter_count = 0
        norm0, norm = self._iter_initialize()

        self._norm0 = norm0

        self._mpi_print(self._iter_count, norm, norm / norm0)

        stalled = False
        if stall_limit > 0:
            stall_count = 0
            stall_norm = norm0

        while self._iter_count < maxiter and norm > atol and norm / norm0 > rtol and not stalled:
            with Recording(type(self).__name__, self._iter_count, self) as rec:
                self._single_iteration()
                self._iter_count += 1
                self._run_apply()
                norm = self._iter_get_norm()

                # Save the norm values in the context manager so they can also be recorded.
                rec.abs = norm
                if norm0 == 0:
                    norm0 = 1
                rec.rel = norm / norm0

                # Check if convergence is stalled.
                if stall_limit > 0:
                    rel_norm = rec.rel
                    norm_diff = np.abs(stall_norm - rel_norm)
                    if norm_diff <= stall_tol:
                        stall_count += 1
                        if stall_count >= stall_limit:
                            stalled = True
                    else:
                        stall_count = 0
                        stall_norm = rel_norm

            self._mpi_print(self._iter_count, norm, norm / norm0)

        system = self._system()
        if system.comm.rank == 0 or os.environ.get('USE_PROC_FILES'):
            prefix = self._solver_info.prefix + self.SOLVER

            # Solver terminated early because a Nan in the norm doesn't satisfy the while-loop
            # conditionals.
            if np.isinf(norm) or np.isnan(norm):
                msg = "Solver '{}' on system '{}': residuals contain 'inf' or 'NaN' after {} " + \
                      "iterations."
                if iprint > -1:
                    print(prefix + msg.format(self.SOLVER, system.pathname,
                                              self._iter_count))

                # Raise AnalysisError if requested.
                if self.options['err_on_non_converge']:
                    raise AnalysisError(msg.format(self.SOLVER, system.pathname,
                                                   self._iter_count))

            # Solver hit maxiter without meeting desired tolerances.
            # Or solver stalled.
            elif (norm > atol and norm / norm0 > rtol) or stalled:

                if stalled:
                    msg = "Solver '{}' on system '{}' stalled after {} iterations."
                else:
                    msg = "Solver '{}' on system '{}' failed to converge in {} iterations."

                if iprint > -1:
                    print(prefix + msg.format(self.SOLVER, system.pathname,
                                              self._iter_count))

                # Raise AnalysisError if requested.
                if self.options['err_on_non_converge']:
                    raise AnalysisError(msg.format(self.SOLVER, system.pathname,
                                                   self._iter_count))

            # Solver converged
            elif iprint == 1:
                print(prefix + ' Converged in {} iterations'.format(self._iter_count))
            elif iprint == 2:
                print(prefix + ' Converged')
Example #6
0
    def _solve(self):
        """
        Run the iterative solver.
        """
        maxiter = self.options['maxiter']
        atol = self.options['atol']
        rtol = self.options['rtol']
        iprint = self.options['iprint']

        self._mpi_print_header()

        self._iter_count = 0
        norm0, norm = self._iter_initialize()

        self._norm0 = norm0

        self._mpi_print(self._iter_count, norm, norm / norm0)

        while self._iter_count < maxiter and norm > atol and norm / norm0 > rtol:
            with Recording(type(self).__name__, self._iter_count, self) as rec:
                self._single_iteration()
                self._iter_count += 1
                self._run_apply()
                norm = self._iter_get_norm()

                # Save the norm values in the context manager so they can also be recorded.
                rec.abs = norm
                if norm0 == 0:
                    norm0 = 1
                rec.rel = norm / norm0

            self._mpi_print(self._iter_count, norm, norm / norm0)

        system = self._system()

        # flag for the print statements. we only print on root if USE_PROC_FILES is not set to True
        print_flag = system.comm.rank == 0 or os.environ.get('USE_PROC_FILES')

        prefix = self._solver_info.prefix + self.SOLVER

        # Solver terminated early because a Nan in the norm doesn't satisfy the while-loop
        # conditionals.
        if np.isinf(norm) or np.isnan(norm):
            msg = "Solver '{}' on system '{}': residuals contain 'inf' or 'NaN' after {} " + \
                  "iterations."
            if iprint > -1 and print_flag:
                print(prefix + msg.format(self.SOLVER, system.pathname,
                                          self._iter_count))

            # Raise AnalysisError if requested.
            if self.options['err_on_non_converge']:
                raise AnalysisError(msg.format(self.SOLVER, system.pathname,
                                               self._iter_count))

        # Solver hit maxiter without meeting desired tolerances.
        elif (norm > atol and norm / norm0 > rtol):
            msg = "Solver '{}' on system '{}' failed to converge in {} iterations."

            if iprint > -1 and print_flag:
                print(prefix + msg.format(self.SOLVER, system.pathname,
                                          self._iter_count))

            # Raise AnalysisError if requested.
            if self.options['err_on_non_converge']:
                raise AnalysisError(msg.format(self.SOLVER, system.pathname,
                                               self._iter_count))

        # Solver converged
        elif iprint == 1 and print_flag:
            print(prefix + ' Converged in {} iterations'.format(self._iter_count))
        elif iprint == 2 and print_flag:
            print(prefix + ' Converged')
Example #7
0
    def _solve(self):
        """
        Run the iterative solver.
        """
        maxiter = self.options['maxiter']
        atol = self.options['atol']
        rtol = self.options['rtol']
        iprint = self.options['iprint']
        stall_limit = self.options['stall_limit']
        stall_tol = self.options['stall_tol']

        self._mpi_print_header()

        self._iter_count = 0
        norm0, norm = self._iter_initialize()

        self._norm0 = norm0

        self._mpi_print(self._iter_count, norm, norm / norm0)

        stalled = False
        stall_count = 0
        if stall_limit > 0:
            stall_norm = norm0

        while self._iter_count < maxiter and norm > atol and norm / norm0 > rtol and not stalled:
            with Recording(type(self).__name__, self._iter_count, self) as rec:

                if stall_count == 3 and not self.linesearch.options['print_bound_enforce']:

                    self.linesearch.options['print_bound_enforce'] = True

                    if self._system().pathname:
                        pathname = f"{self._system().pathname}."
                    else:
                        pathname = ""

                    msg = (f"Your model has stalled three times and may be violating the bounds. "
                           f"In the future, turn on print_bound_enforce in your solver options "
                           f"here: \n{pathname}nonlinear_solver.linesearch.options"
                           f"['print_bound_enforce']=True. "
                           f"\nThe bound(s) being violated now are:\n")
                    simple_warning(msg)

                    self._single_iteration()
                    self.linesearch.options['print_bound_enforce'] = False
                else:
                    self._single_iteration()

                self._iter_count += 1
                self._run_apply()
                norm = self._iter_get_norm()

                # Save the norm values in the context manager so they can also be recorded.
                rec.abs = norm
                if norm0 == 0:
                    norm0 = 1
                rec.rel = norm / norm0

                # Check if convergence is stalled.
                if stall_limit > 0:
                    rel_norm = rec.rel
                    norm_diff = np.abs(stall_norm - rel_norm)
                    if norm_diff <= stall_tol:
                        stall_count += 1
                        if stall_count >= stall_limit:
                            stalled = True
                    else:
                        stall_count = 0
                        stall_norm = rel_norm

            self._mpi_print(self._iter_count, norm, norm / norm0)

        system = self._system()

        # flag for the print statements. we only print on root if USE_PROC_FILES is not set to True
        print_flag = system.comm.rank == 0 or os.environ.get('USE_PROC_FILES')

        prefix = self._solver_info.prefix + self.SOLVER

        # Solver terminated early because a Nan in the norm doesn't satisfy the while-loop
        # conditionals.
        if np.isinf(norm) or np.isnan(norm):
            msg = "Solver '{}' on system '{}': residuals contain 'inf' or 'NaN' after {} " + \
                  "iterations."
            if iprint > -1 and print_flag:
                print(prefix + msg.format(self.SOLVER, system.pathname,
                                          self._iter_count))

            # Raise AnalysisError if requested.
            if self.options['err_on_non_converge']:
                raise AnalysisError(msg.format(self.SOLVER, system.pathname,
                                               self._iter_count))

        # Solver hit maxiter without meeting desired tolerances.
        # Or solver stalled.
        elif (norm > atol and norm / norm0 > rtol) or stalled:

            if stalled:
                msg = "Solver '{}' on system '{}' stalled after {} iterations."
            else:
                msg = "Solver '{}' on system '{}' failed to converge in {} iterations."

            if iprint > -1 and print_flag:
                print(prefix + msg.format(self.SOLVER, system.pathname,
                                          self._iter_count))

            # Raise AnalysisError if requested.
            if self.options['err_on_non_converge']:
                raise AnalysisError(msg.format(self.SOLVER, system.pathname,
                                               self._iter_count))

        # Solver converged
        elif iprint == 1 and print_flag:
            print(prefix + ' Converged in {} iterations'.format(self._iter_count))
        elif iprint == 2 and print_flag:
            print(prefix + ' Converged')
    def _solve(self):
        """
        Run the iterative solver.

        Overrides opendmao/solvers/solver.py to implement _is_rtol_converged
        """
        maxiter = self.options["maxiter"]
        atol = self.options["atol"]
        iprint = self.options["iprint"]

        self._mpi_print_header()

        self._iter_count = 0
        norm0, norm = self._iter_initialize()

        self._norm0 = norm0

        self._mpi_print(self._iter_count, norm, norm / norm0)

        is_rtol_converged = self._is_rtol_converged(norm, norm0)
        while self._iter_count < maxiter and norm > atol and not is_rtol_converged:
            with Recording(type(self).__name__, self._iter_count, self) as rec:
                self._single_iteration()
                self._iter_count += 1
                self._run_apply()
                norm = self._iter_get_norm()
                # With solvers, we want to record the norm AFTER the call, but the call needs to
                # be wrapped in the with for stack purposes, so we locally assign  norm & norm0
                # into the class.
                rec.abs = norm
                rec.rel = norm / norm0

            if norm0 == 0:
                norm0 = 1
            self._mpi_print(self._iter_count, norm, norm / norm0)
            is_rtol_converged = self._is_rtol_converged(norm, norm0)

        if version.parse(OPENMDAO_VERSION) > version.parse("2.9.1"):
            system = self._system()
        else:
            system = self._system
        if system.comm.rank == 0 or os.environ.get("USE_PROC_FILES"):
            prefix = self._solver_info.prefix + self.SOLVER
            is_rtol_converged = self._is_rtol_converged(norm, norm0)
            # Solver terminated early because a Nan in the norm doesn't satisfy the while-loop
            # conditionals.
            if np.isinf(norm) or np.isnan(norm):
                msg = (
                    "Solver '{}' on system '{}': residuals contain 'inf' or 'NaN' after {} "
                    + "iterations."
                )
                if iprint > -1:
                    print(
                        prefix
                        + msg.format(self.SOLVER, system.pathname, self._iter_count)
                    )

                # Raise AnalysisError if requested.
                if self.options["err_on_non_converge"]:
                    raise AnalysisError(
                        msg.format(self.SOLVER, system.pathname, self._iter_count)
                    )

            # Solver hit maxiter without meeting desired tolerances.
            elif norm > atol and not is_rtol_converged:
                msg = "Solver '{}' on system '{}' failed to converge in {} iterations."

                if iprint > -1:
                    print(
                        prefix
                        + msg.format(self.SOLVER, system.pathname, self._iter_count)
                    )

                # Raise AnalysisError if requested.
                if version.parse(OPENMDAO_VERSION) > version.parse("2.9.1"):
                    if self.options["err_on_non_converge"]:
                        raise AnalysisError(
                            msg.format(self.SOLVER, system.pathname, self._iter_count)
                        )
                else:
                    if self.options["err_on_maxiter"]:
                        raise AnalysisError(
                            msg.format(self.SOLVER, system.pathname, self._iter_count)
                        )

            # Solver converged
            elif iprint == 1:
                print(prefix + " Converged in {} iterations".format(self._iter_count))
            elif iprint == 2:
                print(prefix + " Converged")
Example #9
0
    def _solve(self):
        # type: () -> None
        """
        Run the iterative solver.
        """
        maxiter = self.options['maxiter']
        atol = self.options['atol']
        rtol = self.options['rtol']
        iprint = self.options['iprint']

        self._mpi_print_header()

        self._iter_count = 0
        norm0, norm = self._iter_initialize()

        self._norm0 = norm0
        self._objectives = []

        self._mpi_print(self._iter_count, norm, norm0)

        while self._iter_count < maxiter and \
                (norm > atol or isnan(norm)) and (norm0 > rtol or isnan(norm0)):
            with Recording(type(self).__name__, self._iter_count, self) as rec:
                self._single_iteration()
                self._iter_count += 1
                norm0, norm = self._iter_get_norm()
                # With solvers, we want to record the norm AFTER the call, but the call needs to
                # be wrapped in the with for stack purposes, so we locally assign  norm & norm0
                # into the class.
                rec.abs = norm
                rec.rel = norm0

            self._mpi_print(self._iter_count, norm, norm0)
            self._save_history()
            if self.options['print_last_iteration']:
                self._print_last_iteration()
            if self.options['plot_history']:
                self._plot_history()
            self._iter_apply_new_bounds()
            self._untrain_surrogates()

        fail = (np.isinf(norm) or np.isnan(norm)
                or (norm > atol and norm0 > rtol))

        if self._system.comm.rank == 0 or os.environ.get('USE_PROC_FILES'):
            prefix = self._solver_info.prefix + self.SOLVER
            if fail:
                if iprint > -1:
                    msg = ' Failed to Converge in {} iterations'.format(
                        self._iter_count)
                    print(prefix + msg)

                # Raise AnalysisError if requested.
                if self.options['err_on_maxiter']:
                    msg = "Solver '{}' on system '{}' failed to converge."
                    raise AnalysisError(
                        msg.format(self.SOLVER, self._system.pathname))

            elif iprint == 1:
                print(prefix +
                      ' Converged in {} iterations'.format(self._iter_count))
            elif iprint == 2:
                print(prefix + ' Converged')