示例#1
0
    def _run_newton_solver(self, sol):
        num = self.num
        options = self.options

        solver = get_solver(options["solver"])
        ls_class = get_line_search_class(options["line_search"])

        total_size = int(num["dof"])
        rhs = np.zeros((total_size, num["y"]))
        d_sol = np.zeros((total_size, num["y"]))

        p = self.options["approx_order"]
        for ind_y in range(rhs.shape[1]):

            with self.printer._timed_context("Solving for output %i" % ind_y):

                yt_dict = self._get_yt_dict(ind_y)

                norm = self._opt_norm(sol[:, ind_y], p, yt_dict)
                fval = self._opt_func(sol[:, ind_y], p, yt_dict)
                self.printer(
                    "Iteration (num., iy, grad. norm, func.) : %3i %3i %15.9e %15.9e"
                    % (0, ind_y, norm, fval)
                )

                iter_count = 0
                while (
                    iter_count < options["nonlinear_maxiter"]
                    and norm > options["solver_tolerance"]
                ):
                    with self.printer._timed_context():
                        with self.printer._timed_context("Assembling linear system"):
                            mtx = self._opt_hess(sol[:, ind_y], p, yt_dict)
                            rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], p, yt_dict)

                        with self.printer._timed_context("Initializing linear solver"):
                            solver._setup(mtx, self.printer)

                        with self.printer._timed_context("Solving linear system"):
                            solver._solve(rhs[:, ind_y], d_sol[:, ind_y], ind_y=ind_y)

                        func = lambda x: self._opt_func(x, p, yt_dict)
                        grad = lambda x: self._opt_grad(x, p, yt_dict)

                        # sol[:, ind_y] += d_sol[:, ind_y]

                        ls = ls_class(sol[:, ind_y], d_sol[:, ind_y], func, grad)
                        with self.printer._timed_context("Performing line search"):
                            sol[:, ind_y] = ls(1.0)

                    norm = self._opt_norm(sol[:, ind_y], p, yt_dict)
                    fval = self._opt_func(sol[:, ind_y], p, yt_dict)
                    self.printer(
                        "Iteration (num., iy, grad. norm, func.) : %3i %3i %15.9e %15.9e"
                        % (iter_count, ind_y, norm, fval)
                    )

                    self.mtx = mtx

                    iter_count += 1
示例#2
0
文件: rmts.py 项目: zeta1999/smt
    def _solve(self):
        num = self.num
        options = self.options

        solver = get_solver(options["solver"])
        ls_class = get_line_search_class(options["line_search"])

        total_size = int(num["dof"])
        rhs = np.zeros((total_size, num["y"]))
        sol = np.zeros((total_size, num["y"]))
        d_sol = np.zeros((total_size, num["y"]))

        with self.printer._timed_context(
                "Solving initial startup problem (n=%i)" % total_size):

            approx_order = options["approx_order"]
            nonlinear_maxiter = options["nonlinear_maxiter"]
            options["approx_order"] = 2
            options["nonlinear_maxiter"] = 1

            self._run_newton_solver(sol)

            options["approx_order"] = approx_order
            options["nonlinear_maxiter"] = nonlinear_maxiter

        with self.printer._timed_context("Solving nonlinear problem (n=%i)" %
                                         total_size):

            self._run_newton_solver(sol)

        return sol
示例#3
0
    def _solve(self, full_hess, full_jac_dict, mg_matrices):
        num = self.num
        options = self.options

        solver = get_solver(options['solver'])
        ls_class = get_line_search_class(options['line_search'])

        total_size = int(num['dof'])
        rhs = np.zeros((total_size, num['y']))
        sol = np.zeros((total_size, num['y']))
        d_sol = np.zeros((total_size, num['y']))

        with self.printer._timed_context('Solving initial linear problem (n=%i)' % total_size):

            with self.printer._timed_context('Assembling linear system'):
                mtx = self._opt_hess_2(full_hess, full_jac_dict)
                for ind_y in range(num['y']):
                    yt_dict = self._get_yt_dict(ind_y)
                    rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], 2, full_hess,
                                                    full_jac_dict, yt_dict)

            with self.printer._timed_context('Initializing linear solver'):
                solver._initialize(mtx, self.printer, mg_matrices=mg_matrices)

            for ind_y in range(rhs.shape[1]):
                with self.printer._timed_context('Solving linear system (col. %i)' % ind_y):
                    solver._solve(rhs[:, ind_y], sol[:, ind_y], ind_y=ind_y)

        p = self.options['approx_order']
        for ind_y in range(rhs.shape[1]):

            with self.printer._timed_context('Solving nonlinear problem (col. %i)' % ind_y):

                yt_dict = self._get_yt_dict(ind_y)

                if options['nln_max_iter'] > 0:
                    norm = self._opt_norm(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict)
                    fval = self._opt_func(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict)
                    self.printer(
                        'Nonlinear (itn, iy, grad. norm, func.) : %3i %3i %15.9e %15.9e'
                        % (0, ind_y, norm, fval))

                for nln_iter in range(options['nln_max_iter']):
                    with self.printer._timed_context():
                        with self.printer._timed_context('Assembling linear system'):
                            mtx = self._opt_hess(sol[:, ind_y], p, full_hess,
                                                    full_jac_dict, yt_dict)
                            rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], p, full_hess,
                                                            full_jac_dict, yt_dict)

                        with self.printer._timed_context('Initializing linear solver'):
                            solver._initialize(mtx, self.printer, mg_matrices=mg_matrices)

                        with self.printer._timed_context('Solving linear system'):
                            solver._solve(rhs[:, ind_y], d_sol[:, ind_y], ind_y=ind_y)

                        func = lambda x: self._opt_func(x, p, full_hess,
                                                        full_jac_dict, yt_dict)
                        grad = lambda x: self._opt_grad(x, p, full_hess,
                                                        full_jac_dict, yt_dict)

                        ls = ls_class(sol[:, ind_y], d_sol[:, ind_y], func, grad)
                        with self.printer._timed_context('Performing line search'):
                            sol[:, ind_y] = ls(1.0)

                    norm = self._opt_norm(sol[:, ind_y], p, full_hess,
                                          full_jac_dict, yt_dict)
                    fval = self._opt_func(sol[:, ind_y], p, full_hess,
                                          full_jac_dict, yt_dict)
                    self.printer(
                        'Nonlinear (itn, iy, grad. norm, func.) : %3i %3i %15.9e %15.9e'
                        % (nln_iter + 1, ind_y, norm, fval))

                    if norm < 1e-16:
                        break

        return sol
示例#4
0
    def _fit(self):
        """
        Train the model
        """
        sm_options = self.sm_options

        num = {}
        # number of inputs and outputs
        num['x'] = self.training_pts['exact'][0][0].shape[1]
        num['y'] = self.training_pts['exact'][0][1].shape[1]
        # number of elements
        num['elem_list'] = np.array(sm_options['num_elem'], int)
        num['elem'] = np.prod(num['elem_list'])
        # number of terms/coefficients per element
        num['term_list'] = 4 * np.ones(num['x'], int)
        num['term'] = np.prod(num['term_list'])
        # number of nodes
        num['uniq_list'] = num['elem_list'] + 1
        num['uniq'] = np.prod(num['uniq_list'])
        # total number of training points (function values and derivatives)
        num['t'] = 0
        for kx in self.training_pts['exact']:
            num['t'] += self.training_pts['exact'][kx][0].shape[0]

        if len(sm_options['smoothness']) == 0:
            sm_options['smoothness'] = [1.0] * num['x']

        self.num = num

        self.printer.max_print_depth = sm_options['max_print_depth']

        with self.printer._timed_context('Pre-computing matrices'):

            with self.printer._timed_context('Computing uniq2coeff'):
                full_uniq2coeff = self._compute_uniq2coeff(
                    num['x'], num['elem_list'], num['elem'], num['term'], num['uniq'])

            with self.printer._timed_context('Computing local energy terms'):
                elem_hess = self._compute_local_hess()

            with self.printer._timed_context('Computing global energy terms'):
                full_hess = self._compute_global_hess(elem_hess, full_uniq2coeff)

            with self.printer._timed_context('Computing approximation terms'):
                full_jac_dict, reg_cons_dict = self._compute_approx_terms(full_uniq2coeff)

            if sm_options['solver'] == 'mg':
                mg_matrices = self._compute_mg_matrices()
            else:
                mg_matrices = []

        block_names = ['dv']
        block_sizes = [num['uniq'] * 2 ** num['x']]
        if sm_options['mode'] == 'exact':
            block_names += ['con_%s'%kx for kx in self.training_pts['exact']]
            block_sizes += [self.training_pts['exact'][kx][0].shape[0]
                            for kx in self.training_pts['exact']]

        with self.printer._timed_context('Solving for degrees of freedom'):

            solver = get_solver(sm_options['solver'])
            ls_class = get_line_search_class(sm_options['line_search'])

            total_size = int(np.sum(block_sizes))
            rhs = np.zeros((total_size, num['y']))
            sol = np.zeros((total_size, num['y']))
            d_sol = np.zeros((total_size, num['y']))

            with self.printer._timed_context('Solving initial linear problem'):

                with self.printer._timed_context('Assembling linear system'):
                    if sm_options['mode'] == 'approx':
                        mtx = self._opt_hess_2(full_hess, full_jac_dict)
                        for ind_y in range(num['y']):
                            yt_dict = self._get_yt_dict(ind_y)
                            rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], 2, full_hess,
                                                            full_jac_dict, yt_dict)
                    elif sm_options['mode'] == 'exact':
                        sub_mtx_dict = {}
                        sub_rhs_dict = {}
                        sub_mtx_dict['dv', 'dv'] = scipy.sparse.csc_matrix(full_hess)
                        sub_rhs_dict['dv'] = -full_hess * sol
                        for kx in self.training_pts['exact']:
                            full_jac = full_jac_dict[kx]
                            xt, yt = self.training_pts['exact'][kx]

                            reg_cons = reg_cons_dict[kx]
                            sub_mtx_dict['con_%s'%kx, 'dv'] = full_jac
                            sub_mtx_dict['dv', 'con_%s'%kx] = full_jac.T
                            sub_mtx_dict['con_%s'%kx, 'con_%s'%kx] = reg_cons
                            sub_rhs_dict['con_%s'%kx] = yt

                        mtx, rhs = assemble_sparse_mtx(
                            block_names, block_sizes, sub_mtx_dict, sub_rhs_dict)

                with self.printer._timed_context('Initializing linear solver'):
                    solver._initialize(mtx, self.printer, mg_matrices=mg_matrices)

                for ind_y in range(rhs.shape[1]):
                    with self.printer._timed_context('Solving linear system (col. %i)' % ind_y):
                        solver._solve(rhs[:, ind_y], sol[:, ind_y], ind_y=ind_y)

            p = self.sm_options['approx_norm']
            for ind_y in range(rhs.shape[1]):

                with self.printer._timed_context('Solving nonlinear problem (col. %i)' % ind_y):

                    yt_dict = self._get_yt_dict(ind_y)

                    if sm_options['max_nln_iter'] > 0:
                        norm = self._opt_norm(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict)
                        fval = self._opt_func(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict)
                        self.printer(
                            'Nonlinear (itn, iy, grad. norm, func.) : %3i %3i %15.9e %15.9e'
                            % (0, ind_y, norm, fval))

                    for nln_iter in range(sm_options['max_nln_iter']):
                        with self.printer._timed_context():
                            with self.printer._timed_context('Assembling linear system'):
                                mtx = self._opt_hess(sol[:, ind_y], p, full_hess,
                                                     full_jac_dict, yt_dict)
                                rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], p, full_hess,
                                                                full_jac_dict, yt_dict)

                            with self.printer._timed_context('Initializing linear solver'):
                                solver._initialize(mtx, self.printer, mg_matrices=mg_matrices)

                            with self.printer._timed_context('Solving linear system'):
                                solver._solve(rhs[:, ind_y], d_sol[:, ind_y], ind_y=ind_y)

                            func = lambda x: self._opt_func(x, p, full_hess,
                                                            full_jac_dict, yt_dict)
                            grad = lambda x: self._opt_grad(x, p, full_hess,
                                                            full_jac_dict, yt_dict)

                            ls = ls_class(sol[:, ind_y], d_sol[:, ind_y], func, grad)
                            with self.printer._timed_context('Performing line search'):
                                sol[:, ind_y] = ls(1.0)

                        norm = self._opt_norm(sol[:, ind_y], p, full_hess,
                                              full_jac_dict, yt_dict)
                        fval = self._opt_func(sol[:, ind_y], p, full_hess,
                                              full_jac_dict, yt_dict)
                        self.printer(
                            'Nonlinear (itn, iy, grad. norm, func.) : %3i %3i %15.9e %15.9e'
                            % (nln_iter + 1, ind_y, norm, fval))

                        if norm < 1e-3:
                            break

        self.sol = full_uniq2coeff * sol[:num['uniq'] * 2 ** num['x'], :]