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
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
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
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'], :]