def solve(self, N=None, **kwargs): N, kwargs = self._online_size_from_kwargs(N, **kwargs) N += self.N_bc self._latest_solve_kwargs = kwargs self._solution = OnlineFunction(N) self._solution_over_time.clear() self._solution_dot = OnlineFunction(N) self._solution_dot_over_time.clear() if N == 0: # trivial case self._solution_over_time.extend([ self._solution for _ in self._solution_over_time.expected_times() ]) self._solution_dot_over_time.extend([ self._solution_dot for _ in self._solution_dot_over_time.expected_times() ]) return self._solution_over_time try: assign(self._solution_over_time, self._solution_over_time_cache[self.mu, N, kwargs]) # **kwargs is not supported by __getitem__ assign(self._solution_dot_over_time, self._solution_dot_over_time_cache[self.mu, N, kwargs]) except KeyError: assert not hasattr(self, "_is_solving") self._is_solving = True self._solve(N, **kwargs) delattr(self, "_is_solving") assign(self._solution, self._solution_over_time[-1]) assign(self._solution_dot, self._solution_dot_over_time[-1]) return self._solution_over_time
def solve(self, N=None, **kwargs): N, kwargs = self._online_size_from_kwargs(N, **kwargs) N += self.N_bc self._solution = OnlineFunction(N) self._solution_dot = OnlineFunction(N) cache_key = self._cache_key_from_N_and_kwargs(N, **kwargs) assert ((cache_key in self._solution_cache) == (cache_key in self._solution_dot_cache) == (cache_key in self._solution_over_time_cache) == (cache_key in self._solution_dot_over_time_cache)) if "RAM" in self.cache_config and cache_key in self._solution_cache: log(PROGRESS, "Loading reduced solution from cache") assign(self._solution, self._solution_cache[cache_key]) assign(self._solution_dot, self._solution_dot_cache[cache_key]) assign(self._solution_over_time, self._solution_over_time_cache[cache_key]) assign(self._solution_dot_over_time, self._solution_dot_over_time_cache[cache_key]) else: log(PROGRESS, "Solving reduced problem") assert not hasattr(self, "_is_solving") self._is_solving = True self._solve(N, **kwargs) delattr(self, "_is_solving") if "RAM" in self.cache_config: self._solution_cache[cache_key] = copy(self._solution) self._solution_dot_cache[cache_key] = copy( self._solution_dot) self._solution_over_time_cache[cache_key] = copy( self._solution_over_time) self._solution_dot_over_time_cache[cache_key] = copy( self._solution_dot_over_time) return self._solution_over_time
def solve(self, mu, c, snapshot): print("Performing L^2 projection for mu =", mu, "and component", c) #quit() projected_snapshot_N = OnlineFunction(self.N) solver = OnlineLinearSolver( self.inner_product_N, projected_snapshot_N, transpose(self.basis_functions) * self.inner_product * snapshot) solver.solve() return projected_snapshot_N.vector().__array__()
def ic_eval(self): problem = self.problem N = self.N if len(problem.components) > 1: all_initial_conditions = list() all_initial_conditions_thetas = list() for component in problem.components: if problem.initial_condition[ component] and not problem.initial_condition_is_homogeneous[ component]: all_initial_conditions.extend( problem.initial_condition[component][:N]) all_initial_conditions_thetas.extend( problem.compute_theta("initial_condition_" + component)) if len(all_initial_conditions) > 0: all_initial_conditions = tuple(all_initial_conditions) all_initial_conditions = OnlineAffineExpansionStorage( all_initial_conditions) all_initial_conditions_thetas = tuple( all_initial_conditions_thetas) else: all_initial_conditions = None all_initial_conditions_thetas = None else: if problem.initial_condition and not problem.initial_condition_is_homogeneous: all_initial_conditions = problem.initial_condition[:N] all_initial_conditions_thetas = problem.compute_theta( "initial_condition") else: all_initial_conditions = None all_initial_conditions_thetas = None assert (all_initial_conditions is None) == (all_initial_conditions_thetas is None) if all_initial_conditions is not None: inner_product_N = problem._combined_projection_inner_product[: N, : N] projected_initial_condition = OnlineFunction(N) solver = OnlineLinearSolver( inner_product_N, projected_initial_condition, sum( product(all_initial_conditions_thetas, all_initial_conditions))) solver.set_parameters(problem._linear_solver_parameters) solver.solve() return projected_initial_condition else: return OnlineFunction(N)
def _multiply(tensors_list: AbstractTensorsList, online_function: OnlineFunction.Type(), output: backend.Matrix.Type()): output.zero() for (i, matrix_i) in enumerate(tensors_list._list): online_vector_i = online_function.vector()[i] output += matrix_i * online_vector_i
def solve(self, N=None, **kwargs): """ Perform an online solve. self.N will be used as matrix dimension if the default value is provided for N. :param N : Dimension of the reduced problem :type N : integer :return: reduced solution """ N, kwargs = self._online_size_from_kwargs(N, **kwargs) N += self.N_bc self._latest_solve_kwargs = kwargs self._solution = OnlineFunction(N) if N == 0: # trivial case return self._solution try: assign(self._solution, self._solution_cache[ self.mu, N, kwargs]) # **kwargs is not supported by __getitem__ except KeyError: assert not hasattr(self, "_is_solving") self._is_solving = True self._solve(N, **kwargs) delattr(self, "_is_solving") self._solution_cache[self.mu, N, kwargs] = copy(self._solution) return self._solution
def get_initial_error_estimate_squared(self): self._solution = self._solution_over_time[0] N = self._solution.N at_least_one_non_homogeneous_initial_condition = False addend_0 = 0. addend_1_right = OnlineFunction(N) if len(self.components) > 1: for component in self.components: if self.initial_condition[component] and not self.initial_condition_is_homogeneous[component]: at_least_one_non_homogeneous_initial_condition = True theta_ic_component = self.compute_theta("initial_condition_" + component) addend_0 += sum(product(theta_ic_component, self.initial_condition_product[component, component], theta_ic_component)) addend_1_right += sum(product(theta_ic_component, self.initial_condition[:N])) else: if self.initial_condition and not self.initial_condition_is_homogeneous: at_least_one_non_homogeneous_initial_condition = True theta_ic = self.compute_theta("initial_condition") addend_0 += sum(product(theta_ic, self.initial_condition_product, theta_ic)) addend_1_right += sum(product(theta_ic, self.initial_condition[:N])) if at_least_one_non_homogeneous_initial_condition: inner_product_N = self._combined_projection_inner_product[:N, :N] addend_1_left = self._solution addend_2 = transpose(self._solution)*inner_product_N*self._solution return addend_0 - 2.0*(transpose(addend_1_left)*addend_1_right) + addend_2 else: return 0.
def project(self, snapshot, on_dirichlet_bc=True, N=None, **kwargs): N, kwargs = self._online_size_from_kwargs(N, **kwargs) N += self.N_bc # Get truth and reduced inner product matrices for projection inner_product = self.truth_problem._combined_projection_inner_product inner_product_N = self._combined_projection_inner_product[:N, :N] # Get basis basis_functions = self.basis_functions[:N] # Define storage for projected solution projected_snapshot_N = OnlineFunction(N) # Project on reduced basis if on_dirichlet_bc: solver = OnlineLinearSolver( inner_product_N, projected_snapshot_N, transpose(basis_functions) * inner_product * snapshot) else: solver = OnlineLinearSolver( inner_product_N, projected_snapshot_N, transpose(basis_functions) * inner_product * snapshot, self._combined_and_homogenized_dirichlet_bc) solver.set_parameters(self._linear_solver_parameters) solver.solve() return projected_snapshot_N
def _solve(self, rhs_, N=None): if N is None: N = self.N if N > 0: self._interpolation_coefficients = OnlineFunction(N) # Evaluate the parametrized expression at interpolation locations rhs = evaluate(rhs_, self.interpolation_locations[:N]) (max_abs_rhs, _) = max(abs(rhs)) if max_abs_rhs == 0.: # If the rhs is zero, then we are interpolating the zero function # and the default zero coefficients are enough. pass else: # Extract the interpolation matrix lhs = self.interpolation_matrix[0][:N, :N] # Solve the interpolation problem solver = OnlineLinearSolver(lhs, self._interpolation_coefficients, rhs) solver.solve() else: self._interpolation_coefficients = None # OnlineFunction
def _multiply(tensors_list: AbstractTensorsList, online_function: OnlineFunction.Type(), output: backend.Vector.Type()): output.zero() for (i, vector_i) in enumerate(tensors_list._list): online_vector_i = online_function.vector()[i] output.add_local(vector_i.get_local() * online_vector_i) output.apply("add")
def solve(self): print("solving mock reduced problem at mu =", self.mu) assert not hasattr(self, "_is_solving") self._is_solving = True f = self.truth_problem.solve() f_N = transpose(self.basis_functions)*self.truth_problem.inner_product*f # Return the reduced solution self._solution = OnlineFunction(f_N) delattr(self, "_is_solving") return self._solution
def solve(self, N=None, **kwargs): N, kwargs = self.reduced_problem._online_size_from_kwargs(N, **kwargs) N += self.reduced_problem.N_bc self._eigenvector = OnlineFunction(N) cache_key = self._cache_key(**kwargs) try: self._eigenvalue = self._eigenvalue_cache[cache_key] assign(self._eigenvector, self._eigenvector_cache[cache_key]) except KeyError: self._solve(N, **kwargs) self._eigenvalue_cache[cache_key] = self._eigenvalue self._eigenvector_cache[cache_key] = copy(self._eigenvector) return (self._eigenvalue, self._eigenvector)
def reduced_solve(mu, N): normalize_inputs = NormalizeInputs(mu_range) mu_torch = normalize_inputs(mu) mu_torch = mu_torch.view(mu_torch.shape[1], -1) reduced_solution = dict() for c in components: network = Network(len(mu), c, N) network.load_state_dict( torch.load(os.path.join("networks", "network_" + c + "_" + str(N)))) normalize_outputs = NormalizeOutputs( os.path.join("networks", "output_normalization_" + c + "_" + str(N))) reduced_solution_c = OnlineFunction(N) reduced_solution_c.vector()[:] = normalize_outputs.inv( network(mu_torch).detach().numpy()[0]) reduced_solution[c] = reduced_solution_c return reduced_solution
def solve_supremizer(self, solution): N_us = OnlineSizeDict(solution.N) # create a copy del N_us["p"] kwargs = self._latest_solve_kwargs self._supremizer = OnlineFunction(N_us) try: assign(self._supremizer, self._supremizer_cache[ self.mu, N_us, kwargs]) # **kwargs is not supported by __getitem__ except KeyError: self._solve_supremizer(solution) self._supremizer_cache[self.mu, N_us, kwargs] = copy(self._supremizer) return self._supremizer
def solve_supremizer(self, solution): N_us = OnlineSizeDict(solution.N) # create a copy del N_us["p"] cache_key = self._supremizer_cache_key_from_N_and_kwargs(N_us) self._supremizer = OnlineFunction(N_us) if "RAM" in self.cache_config and cache_key in self._supremizer_cache: log(PROGRESS, "Loading reduced supremizer from cache") assign(self._supremizer, self._supremizer_cache[cache_key]) else: log(PROGRESS, "Solving supremizer reduced problem") self._solve_supremizer(solution) if "RAM" in self.cache_config: self._supremizer_cache[cache_key] = copy(self._supremizer) return self._supremizer
def _solve(self, N, **kwargs): EllipticCoerciveReducedProblem_DerivedClass._solve( self, N, **kwargs) if kwargs["online_rectification"]: q = self.online_solve_kwargs_with_rectification.index(kwargs) intermediate_solution = OnlineFunction(N) solver = LinearSolver( self.operator["projection_reduced_snapshots"][:N, :N][q], intermediate_solution, self._solution.vector()) solver.set_parameters(self._linear_solver_parameters) solver.solve() self._solution.vector( )[:] = self.operator["projection_truth_snapshots"][:N, :N][ 0] * intermediate_solution
def solve(self, N=None, **kwargs): N, kwargs = self._online_size_from_kwargs(N, **kwargs) N += self.N_bc self._latest_solve_kwargs = kwargs self._solution = OnlineFunction(N) self._solution_dot = OnlineFunction(N) if N == 0: # trivial case time_interval = linspace(self.t0, self.T, (self.T - self.t0) / self.dt) self._solution_over_time = [ self._solution for _ in time_interval ] self._solution_dot_over_time = [ self._solution_dot for _ in time_interval ] return self._solution_over_time try: assign(self._solution_over_time, self._solution_over_time_cache[ self.mu, N, kwargs]) # **kwargs is not supported by __getitem__ assign(self._solution_dot_over_time, self._solution_dot_over_time_cache[self.mu, N, kwargs]) except KeyError: assert not hasattr(self, "_is_solving") self._is_solving = True self._solve(N, **kwargs) delattr(self, "_is_solving") self._solution_over_time_cache[self.mu, N, kwargs] = copy( self._solution_over_time) self._solution_dot_over_time_cache[self.mu, N, kwargs] = copy( self._solution_dot_over_time) else: assign(self._solution, self._solution_over_time[-1]) assign(self._solution_dot, self._solution_dot_over_time[-1]) return self._solution_over_time
def plot(obj, *args, **kwargs): if isinstance(obj, OnlineFunction.Type()): assert "reduced_problem" in kwargs, "Please use this method as plot(reduced_solution, reduced_problem=my_reduced_problem) when plotting a reduced solution" N = obj.N reduced_problem = kwargs["reduced_problem"] del kwargs["reduced_problem"] basis_functions = reduced_problem.basis_functions[:N] truth_problem = reduced_problem.truth_problem obj = basis_functions * obj elif "truth_problem" in kwargs: truth_problem = kwargs["truth_problem"] del kwargs["truth_problem"] else: truth_problem = None if truth_problem is not None and hasattr(truth_problem, "mesh_motion"): truth_problem.mesh_motion.move_mesh() original_plot(obj, *args, **kwargs) if truth_problem is not None and hasattr(truth_problem, "mesh_motion"): truth_problem.mesh_motion.reset_reference()
def _solve(self, N, **kwargs): # Temporarily change value of stabilized attribute in truth problem bak_stabilized = self.truth_problem.stabilized self.truth_problem.stabilized = kwargs["online_stabilization"] # Solve reduced problem if kwargs["online_vanishing_viscosity"]: assembled_operator = dict() assembled_operator["a"] = ( sum(product(self.compute_theta("a"), self.operator["a"][:N, :N])) + self.operator["vanishing_viscosity"][:N, :N][0] ) assembled_operator["f"] = sum(product(self.compute_theta("f"), self.operator["f"][:N])) self._solution = OnlineFunction(N) solver = LinearSolver(assembled_operator["a"], self._solution, assembled_operator["f"]) solver.set_parameters(self._linear_solver_parameters) solver.solve() else: EllipticCoerciveReducedProblem_DerivedClass._solve(self, N, **kwargs) # Restore original value of stabilized attribute in truth problem self.truth_problem.stabilized = bak_stabilized
def solve(self, N=None, **kwargs): """ Perform an online solve. self.N will be used as matrix dimension if the default value is provided for N. :param N : Dimension of the reduced problem :type N : integer :return: reduced solution """ N, kwargs = self._online_size_from_kwargs(N, **kwargs) N += self.N_bc cache_key = self._cache_key_from_N_and_kwargs(N, **kwargs) self._solution = OnlineFunction(N) if "RAM" in self.cache_config and cache_key in self._solution_cache: log(PROGRESS, "Loading reduced solution from cache") assign(self._solution, self._solution_cache[cache_key]) else: log(PROGRESS, "Solving reduced problem") assert not hasattr(self, "_is_solving") self._is_solving = True self._solve(N, **kwargs) delattr(self, "_is_solving") if "RAM" in self.cache_config: self._solution_cache[cache_key] = copy(self._solution) return self._solution
def plot(obj, *args, **kwargs): if isinstance(obj, TimeSeries): is_time_series = True else: is_time_series = False if not is_time_series and isinstance(obj, OnlineFunction.Type()): is_truth_solution = False elif is_time_series and isinstance(obj[0], OnlineFunction.Type()): assert all(isinstance(obj_, OnlineFunction.Type()) for obj_ in obj) is_truth_solution = False else: is_truth_solution = True if is_time_series: if "every" in kwargs: obj = obj[::kwargs["every"]] del kwargs["every"] if "interval" in kwargs: anim_interval = kwargs["interval"] del kwargs["interval"] else: anim_interval = None if not is_truth_solution: assert "reduced_problem" in kwargs, ( "Please use this method as plot(reduced_solution, reduced_problem=my_reduced_problem)" + " when plotting a reduced solution") if not is_time_series: N = obj.N else: N = obj[0].N assert all(obj_.N == N for obj_ in obj) reduced_problem = kwargs["reduced_problem"] del kwargs["reduced_problem"] basis_functions = reduced_problem.basis_functions[:N] truth_problem = reduced_problem.truth_problem if not is_time_series: obj = basis_functions * obj else: obj = [basis_functions * obj_ for obj_ in obj] elif "truth_problem" in kwargs: truth_problem = kwargs["truth_problem"] del kwargs["truth_problem"] else: truth_problem = None if "component" in kwargs: component = kwargs["component"] del kwargs["component"] if not is_time_series: obj = obj.sub(component) else: obj = [obj_.sub(component) for obj_ in obj] if truth_problem is not None and hasattr(truth_problem, "mesh_motion"): truth_problem.mesh_motion.move_mesh() if not is_time_series: output = original_plot(obj, *args, **kwargs) else: def animate(i): return original_plot(obj[i], *args, **kwargs).collections fig = plt.figure() output = matplotlib.animation.FuncAnimation( fig, animate, frames=len(obj), interval=anim_interval, repeat=False) try: from IPython.display import HTML except ImportError: pass else: output = HTML(output.to_html5_video()) plt.close() if truth_problem is not None and hasattr(truth_problem, "mesh_motion"): truth_problem.mesh_motion.reset_reference() return output
def assemble_operator(self, term, current_stage="online"): if term == "projection_truth_snapshots": assert current_stage in ( "online", "offline_rectification_postprocessing") if current_stage == "online": # load from file self.operator["projection_truth_snapshots"].load( self.folder["reduced_operators"], "projection_truth_snapshots") return self.operator["projection_truth_snapshots"] elif current_stage == "offline_rectification_postprocessing": assert len( self.truth_problem.inner_product ) == 1 # the affine expansion storage contains only the inner product matrix inner_product = self.truth_problem.inner_product[0] for n in range(1, self.N + 1): assert len( self.inner_product ) == 1 # the affine expansion storage contains only the inner product matrix inner_product_n = self.inner_product[:n, :n][0] basis_functions_n = self.basis_functions[:n] projection_truth_snapshots_expansion = OnlineAffineExpansionStorage( 1) projection_truth_snapshots = OnlineMatrix(n, n) for (i, snapshot_i) in enumerate(self.snapshots[:n]): projected_truth_snapshot_i = OnlineFunction(n) solver = LinearSolver( inner_product_n, projected_truth_snapshot_i, transpose(basis_functions_n) * inner_product * snapshot_i) solver.set_parameters( self._linear_solver_parameters) solver.solve() for j in range(n): projection_truth_snapshots[ j, i] = projected_truth_snapshot_i.vector()[j] projection_truth_snapshots_expansion[ 0] = projection_truth_snapshots print("\tcondition number for n = " + str(n) + ": " + str(cond(projection_truth_snapshots))) self.operator[ "projection_truth_snapshots"][:n, : n] = projection_truth_snapshots_expansion # Save self.operator["projection_truth_snapshots"].save( self.folder["reduced_operators"], "projection_truth_snapshots") return self.operator["projection_truth_snapshots"] else: raise ValueError("Invalid stage in assemble_operator().") elif term == "projection_reduced_snapshots": assert current_stage in ( "online", "offline_rectification_postprocessing") if current_stage == "online": # load from file self.operator["projection_reduced_snapshots"].load( self.folder["reduced_operators"], "projection_reduced_snapshots") return self.operator["projection_reduced_snapshots"] elif current_stage == "offline_rectification_postprocessing": # Backup mu bak_mu = self.mu # Prepare rectification for all possible online solve arguments for n in range(1, self.N + 1): print("\tcondition number for n = " + str(n)) projection_reduced_snapshots_expansion = OnlineAffineExpansionStorage( len(self.online_solve_kwargs_without_rectification) ) for (q, online_solve_kwargs) in enumerate( self.online_solve_kwargs_without_rectification ): projection_reduced_snapshots = OnlineMatrix(n, n) for (i, mu_i) in enumerate(self.snapshots_mu[:n]): self.set_mu(mu_i) projected_reduced_snapshot_i = self.solve( n, **online_solve_kwargs) for j in range(n): projection_reduced_snapshots[ j, i] = projected_reduced_snapshot_i.vector( )[j] projection_reduced_snapshots_expansion[ q] = projection_reduced_snapshots print("\t\tonline solve options " + str( dict(self. online_solve_kwargs_with_rectification[q]) ) + ": " + str(cond(projection_reduced_snapshots))) self.operator[ "projection_reduced_snapshots"][:n, : n] = projection_reduced_snapshots_expansion # Save and restore previous mu self.set_mu(bak_mu) self.operator["projection_reduced_snapshots"].save( self.folder["reduced_operators"], "projection_reduced_snapshots") return self.operator["projection_reduced_snapshots"] else: raise ValueError("Invalid stage in assemble_operator().") else: return EllipticCoerciveReducedProblem_DerivedClass.assemble_operator( self, term, current_stage)