예제 #1
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
예제 #2
0
    def _new_train(self):
        num = self.num

        xt, yt = self.training_points[None][0]
        jac = np.empty(num['radial'] * num['dof'])
        self.rbfc.compute_jac(num['radial'], xt.flatten(), jac)
        jac = jac.reshape((num['radial'], num['dof']))

        mtx = np.zeros((num['dof'], num['dof']))
        mtx[:num['radial'], :] = jac
        mtx[:, :num['radial']] = jac.T
        mtx[np.arange(num['radial']), np.arange(num['radial'])] += self.options['reg']

        self.mtx = mtx

        rhs = np.zeros((num['dof'], num['y']))
        rhs[:num['radial'], :] = yt

        sol = np.zeros((num['dof'], num['y']))

        solver = get_solver('dense-lu')
        with self.printer._timed_context('Initializing linear solver'):
            solver._setup(mtx, self.printer)

        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)

        self.sol = sol
예제 #3
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
예제 #4
0
파일: rbf.py 프로젝트: AOE-khkhan/SMT
    def _fit(self):
        options = self.options

        nx = self.training_pts['exact'][0][0].shape[1]
        if isinstance(options['d0'], (int, float)):
            options['d0'] = [options['d0']] * nx
        options['d0'] = np.atleast_1d(options['d0'])

        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 radial function terms
        num['radial'] = self.training_pts['exact'][0][0].shape[0]
        # number of polynomial terms
        if options['poly_degree'] == -1:
            num['poly'] = 0
        elif options['poly_degree'] == 0:
            num['poly'] = 1
        elif options['poly_degree'] == 1:
            num['poly'] = 1 + num['x']
        num['dof'] = num['radial'] + num['poly']

        self.num = num

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

        xt, yt = self.training_pts['exact'][0]
        jac = RBFlib.compute_jac(0, options['poly_degree'], num['x'],
                                 num['radial'], num['radial'], num['dof'],
                                 options['d0'], xt, xt)

        mtx = np.zeros((num['dof'], num['dof']))
        mtx[:num['radial'], :] = jac
        mtx[:, :num['radial']] = jac.T
        mtx[np.arange(num['radial']),
            np.arange(num['radial'])] += options['reg']

        rhs = np.zeros((num['dof'], num['y']))
        rhs[:num['radial'], :] = yt

        sol = np.zeros((num['dof'], num['y']))

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

        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)

        self.sol = sol
예제 #5
0
파일: rmts.py 프로젝트: zeta1999/smt
    def _predict_output_derivatives(self, x):
        # dy_dyt = dy_dw * (dR_dw)^{-1} * dR_dyt

        n = x.shape[0]
        nw = self.mtx.shape[0]
        nx = x.shape[1]
        ny = self.sol.shape[1]

        p = self.options["approx_order"]

        dy_dw = self._compute_prediction_mtx(x, 0)
        if self.full_dof2coeff is not None:
            dy_dw = dy_dw * self.full_dof2coeff
        dy_dw = dy_dw.todense()

        dR_dw = self.mtx

        dy_dyt = {}
        for kx in self.training_points[None]:
            nt = self.training_points[None][kx][0].shape[0]

            dR_dyt = np.zeros((nw, nt, ny))
            for ind_y in range(ny):
                yt_dict = self._get_yt_dict(ind_y)
                dR_dyt[:, :,
                       ind_y] = self._opt_dgrad_dyt(self.sol[:, ind_y], p,
                                                    yt_dict, kx)

            solver = get_solver(self.options["derivative_solver"])
            solver._setup(dR_dw, self.printer)

            dw_dyt = np.zeros((nw, nt, ny))
            for ind_t in range(nt):
                for ind_y in range(ny):
                    solver._solve(dR_dyt[:, ind_t, ind_y],
                                  dw_dyt[:, ind_t, ind_y],
                                  ind_y=ind_y)
                    dw_dyt[:, ind_t, ind_y] *= -1.0

            if kx == 0:
                dy_dyt[None] = np.einsum("ij,jkl->ikl", dy_dw, dw_dyt)
            else:
                dy_dyt[kx - 1] = np.einsum("ij,jkl->ikl", dy_dw, dw_dyt)

        return dy_dyt
예제 #6
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
예제 #7
0
    def _fit(self):
        """
        Train the model
        """
        sm_options = self.sm_options

        nx = self.training_pts['exact'][0][0].shape[1]
        ny = self.training_pts['exact'][0][1].shape[1]

        num = {}
        num['order_list'] = np.array(sm_options['order'], int)
        num['order'] = np.prod(num['order_list'])
        num['ctrl_list'] = np.array(sm_options['num_ctrl_pts'], int)
        num['ctrl'] = np.prod(num['ctrl_list'])
        num['knots_list'] = num['order_list'] + num['ctrl_list']
        num['knots'] = np.sum(num['knots_list'])

        self.num = num

        mtx = scipy.sparse.csc_matrix((num['ctrl'], num['ctrl']))
        rhs = np.zeros((num['ctrl'], ny))
        xlimits = sm_options['xlimits']
        for kx in self.training_pts['exact']:
            xt, yt = self.training_pts['exact'][kx]

            xmin = np.min(xt, axis=0)
            xmax = np.max(xt, axis=0)
            assert np.all(
                xlimits[:, 0] <= xmin), 'Training pts below min for %s' % kx
            assert np.all(
                xlimits[:, 1] >= xmax), 'Training pts above max for %s' % kx

            t = np.zeros(xt.shape)
            for ix in range(nx):
                t[:, ix] = (xt[:, ix] - xlimits[ix, 0]) /\
                    (xlimits[ix, 1] - xlimits[ix, 0])

            nt = xt.shape[0]
            nnz = nt * num['order']
            data, rows, cols = MBRlib.compute_jac(kx, 0, nx, nt, nnz,
                                                  num['order_list'],
                                                  num['ctrl_list'], t)
            if kx > 0:
                data /= xlimits[kx - 1, 1] - xlimits[kx - 1, 0]

            rect_mtx = scipy.sparse.csc_matrix((data, (rows, cols)),
                                               shape=(nt, num['ctrl']))

            mtx = mtx + rect_mtx.T * rect_mtx
            rhs += rect_mtx.T * yt

        diag = sm_options['reg'] * np.ones(num['ctrl'])
        arange = np.arange(num['ctrl'])
        reg = scipy.sparse.csc_matrix((diag, (arange, arange)))
        mtx = mtx + reg

        sol = np.zeros(rhs.shape)

        solver = get_solver(sm_options['solver'])

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

        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)

        self.sol = sol
예제 #8
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'], :]