def _solve(self): if self.multiply_by_theta: assert isinstance(self.term, str) # method untested otherwise O = sum(product(self.truth_problem.compute_theta(self.term), self.operator)) # noqa else: assert isinstance(self.term, tuple) # method untested otherwise assert len(self.operator) == 1 O = self.operator[0] # noqa assert len(self.inner_product) == 1 inner_product = self.inner_product[0] if self.truth_problem.dirichlet_bc is not None: dirichlet_bcs_sum = sum(product((0., )*len(self.truth_problem.dirichlet_bc), self.truth_problem.dirichlet_bc)) eigensolver = EigenSolver(self.truth_problem.V, O, inner_product, dirichlet_bcs_sum) else: eigensolver = EigenSolver(self.truth_problem.V, O, inner_product) eigensolver_parameters = dict() eigensolver_parameters["problem_type"] = "gen_hermitian" assert self.spectrum is "largest" or self.spectrum is "smallest" eigensolver_parameters["spectrum"] = self.spectrum + " real" if self.eigensolver_parameters is not None: if "spectral_transform" in self.eigensolver_parameters and self.eigensolver_parameters["spectral_transform"] == "shift-and-invert": eigensolver_parameters["spectrum"] = "target real" eigensolver_parameters.update(self.eigensolver_parameters) eigensolver.set_parameters(eigensolver_parameters) eigensolver.solve(1) r, c = eigensolver.get_eigenvalue(0) # real and complex part of the eigenvalue r_vector, c_vector = eigensolver.get_eigenvector(0) # real and complex part of the eigenvectors assert isclose(c, 0), "The required eigenvalue is not real" self._eigenvalue = r assign(self._eigenvector, r_vector)
def _solve(self): assert self.operator["stability_factor_left_hand_matrix"] is not None if self.expansion_index is None: A = sum(product( self.truth_problem.compute_theta("stability_factor_left_hand_matrix"), self.operator["stability_factor_left_hand_matrix"])) else: assert len(self.operator["stability_factor_left_hand_matrix"]) == 1 A = self.operator["stability_factor_left_hand_matrix"][0] assert self.operator["stability_factor_right_hand_matrix"] is not None assert len(self.operator["stability_factor_right_hand_matrix"]) == 1 B = self.operator["stability_factor_right_hand_matrix"][0] if self.dirichlet_bc is not None: dirichlet_bcs_sum = sum(product((0., ) * len(self.dirichlet_bc), self.dirichlet_bc)) eigensolver = EigenSolver(self.truth_problem.stability_factor_V, A, B, dirichlet_bcs_sum) else: eigensolver = EigenSolver(self.truth_problem.stability_factor_V, A, B) eigensolver_parameters = dict() assert self.spectrum == "largest" or self.spectrum == "smallest" eigensolver_parameters["spectrum"] = self.spectrum + " real" eigensolver_parameters.update(self.eigensolver_parameters) eigensolver.set_parameters(eigensolver_parameters) eigensolver.solve(1) r, c = eigensolver.get_eigenvalue(0) # real and complex part of the eigenvalue r_vector, c_vector = eigensolver.get_eigenvector(0) # real and complex part of the eigenvectors assert isclose(c, 0.), "The required eigenvalue is not real" self._eigenvalue = r assign(self._eigenvector, r_vector)
def residual_eval(self, solution): problem = self.problem assembled_operator = dict() assembled_operator["a"] = sum(product(problem.compute_theta("a"), problem.operator["a"])) assembled_operator["c"] = sum(product(problem.compute_theta("c"), problem.operator["c"])) assembled_operator["f"] = sum(product(problem.compute_theta("f"), problem.operator["f"])) return assembled_operator["a"]*solution + assembled_operator["c"] - assembled_operator["f"]
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 get_residual_norm_squared(self): residual_norm_squared_over_time = TimeSeries(self._solution_over_time) assert len(self._solution_over_time) == len(self._solution_dot_over_time) for (k, t) in enumerate(self._solution_over_time.stored_times()): if not isclose(t, self.t0, self.dt/2.): # Set current time self.set_time(t) # Set current solution and solution_dot assign(self._solution, self._solution_over_time[k]) assign(self._solution_dot, self._solution_dot_over_time[k]) # Compute the numerator of the error bound at the current time, first # by computing residual of elliptic part elliptic_residual_norm_squared = ParabolicCoerciveRBReducedProblem_Base.get_residual_norm_squared(self) # ... and then adding terms related to time derivative N = self._solution.N theta_m = self.compute_theta("m") theta_a = self.compute_theta("a") theta_f = self.compute_theta("f") residual_norm_squared_over_time.append( elliptic_residual_norm_squared + 2.0*(transpose(self._solution_dot)*sum(product(theta_m, self.error_estimation_operator["m", "f"][:N], theta_f))) + 2.0*(transpose(self._solution_dot)*sum(product(theta_m, self.error_estimation_operator["m", "a"][:N, :N], theta_a))*self._solution) + transpose(self._solution_dot)*sum(product(theta_m, self.error_estimation_operator["m", "m"][:N, :N], theta_m))*self._solution_dot ) else: # Error estimator on initial condition does not use the residual residual_norm_squared_over_time.append(0.) return residual_norm_squared_over_time
def jacobian_eval(self, solution): problem = self.problem N = self.N assembled_operator = dict() assembled_operator["a"] = sum(product(problem.compute_theta("a"), problem.operator["a"][:N, :N])) assembled_operator["dc"] = sum(product(problem.compute_theta("dc"), problem.operator["dc"][:N, :N])) return assembled_operator["a"] + assembled_operator["dc"]
def __call__(self, thetas, operators, thetas2): from rbnics.backends import product, sum, transpose assert operators._type in ("error_estimation_operators_11", "error_estimation_operators_21", "error_estimation_operators_22", "operators") if operators._type.startswith("error_estimation_operators"): assert operators.order() == 2 assert thetas2 is not None assert "inner_product_matrix" in operators._content assert "delayed_functions" in operators._content delayed_functions = operators._content["delayed_functions"] assert len(delayed_functions) == 2 output = transpose( sum(product(thetas, delayed_functions[0]) )) * operators._content["inner_product_matrix"] * sum( product(thetas2, delayed_functions[1])) # Return assert not isinstance(output, DelayedTranspose) return ProductOutput(output) elif operators._type == "operators": assert operators.order() == 1 assert thetas2 is None assert "truth_operators_as_expansion_storage" in operators._content sum_product_truth_operators = sum( product( thetas, operators. _content["truth_operators_as_expansion_storage"])) assert "basis_functions" in operators._content basis_functions = operators._content["basis_functions"] assert len(basis_functions) in (0, 1, 2) if len(basis_functions) == 0: assert (isinstance(sum_product_truth_operators, Number) or (isinstance(sum_product_truth_operators, AbstractParametrizedTensorFactory) and len(sum_product_truth_operators._spaces) == 0)) output = sum_product_truth_operators elif len(basis_functions) == 1: assert isinstance(sum_product_truth_operators, AbstractParametrizedTensorFactory) output = transpose( basis_functions[0]) * sum_product_truth_operators assert isinstance(output, DelayedTranspose) output = wrapping.DelayedTransposeWithArithmetic(output) elif len(basis_functions) == 2: assert isinstance(sum_product_truth_operators, AbstractParametrizedTensorFactory) output = transpose( basis_functions[0] ) * sum_product_truth_operators * basis_functions[1] assert isinstance(output, DelayedTranspose) output = wrapping.DelayedTransposeWithArithmetic(output) else: raise ValueError("Invalid length") # Return return ProductOutput(output) else: raise ValueError("Invalid type")
def jacobian_eval(self, t, solution, solution_dot, solution_dot_coefficient): problem = self.problem assembled_operator = dict() assembled_operator["m"] = sum(product(problem.compute_theta("m"), problem.operator["m"])) assembled_operator["a"] = sum(product(problem.compute_theta("a"), problem.operator["a"])) assembled_operator["dc"] = sum(product(problem.compute_theta("dc"), problem.operator["dc"])) return (assembled_operator["m"] * solution_dot_coefficient + assembled_operator["a"] + assembled_operator["dc"])
def get_residual_norm_squared(self): N = self._solution.N theta_a = self.compute_theta("a") theta_f = self.compute_theta("f") return ( sum(product(theta_f, self.error_estimation_operator["f", "f"], theta_f)) + 2.0*(transpose(self._solution)*sum(product(theta_a, self.error_estimation_operator["a", "f"][:N], theta_f))) + transpose(self._solution)*sum(product(theta_a, self.error_estimation_operator["a", "a"][:N, :N], theta_a))*self._solution )
def get_residual_norm_squared(self): N = self._solution.N theta_a = self.compute_theta("a") theta_b = self.compute_theta("b") theta_bt = self.compute_theta("bt") theta_f = self.compute_theta("f") theta_g = self.compute_theta("g") return ( sum( product(theta_f, self.error_estimation_operator["f", "f"], theta_f)) + sum( product(theta_g, self.error_estimation_operator["g", "g"], theta_g)) + 2.0 * (transpose(self._solution) * sum( product(theta_a, self.error_estimation_operator["a", "f"][:N], theta_f))) + 2.0 * (transpose(self._solution) * sum( product(theta_bt, self.error_estimation_operator["bt", "f"] [:N], theta_f))) + 2.0 * (transpose(self._solution) * sum( product(theta_b, self.error_estimation_operator["b", "g"][:N], theta_g))) + transpose(self._solution) * sum( product(theta_a, self.error_estimation_operator["a", "a"] [:N, :N], theta_a)) * self._solution + 2.0 * (transpose(self._solution) * sum( product(theta_a, self.error_estimation_operator["a", "bt"] [:N, :N], theta_bt)) * self._solution) + transpose(self._solution) * sum( product(theta_bt, self.error_estimation_operator["bt", "bt"] [:N, :N], theta_bt)) * self._solution + transpose(self._solution) * sum( product(theta_b, self.error_estimation_operator["b", "b"] [:N, :N], theta_b)) * self._solution)
def residual_eval(self, t, solution, solution_dot): problem = self.problem assembled_operator = dict() assembled_operator["m"] = sum( product(problem.compute_theta("m"), problem.operator["m"])) assembled_operator["a"] = sum( product(problem.compute_theta("a"), problem.operator["a"])) assembled_operator["f"] = sum( product(problem.compute_theta("f"), problem.operator["f"])) return (assembled_operator["m"] * solution_dot + assembled_operator["a"] * solution - assembled_operator["f"])
def jacobian_eval(self, solution): problem = self.problem assembled_operator = dict() for term in ("a", "b", "bt", "dc"): assembled_operator[term] = sum(product(problem.compute_theta(term), problem.operator[term])) return (assembled_operator["a"] + assembled_operator["b"] + assembled_operator["bt"] + assembled_operator["dc"])
def _compute_relative_error(self, absolute_error, **kwargs): inner_product = dict() inner_product["u"] = sum(product( self.truth_problem.compute_theta("a"), self.truth_problem.operator["a"])) # use the energy norm assert "inner_product" not in kwargs kwargs["inner_product"] = inner_product return EllipticCoerciveCompliantReducedProblem_Base._compute_relative_error(self, absolute_error, **kwargs)
def solve(self): from rbnics.backends import AffineExpansionStorage, evaluate, LinearSolver, product, sum assert self._lhs is not None assert self._solution is not None assert isinstance(self._rhs, DelayedSum) thetas = list() operators = list() for addend in self._rhs._args: assert isinstance(addend, DelayedProduct) assert len(addend._args) in (2, 3) assert isinstance(addend._args[0], Number) assert isinstance(addend._args[1], AbstractParametrizedTensorFactory) thetas.append(addend._args[0]) if len(addend._args) is 2: operators.append(addend._args[1]) elif len(addend._args) is 3: operators.append(addend._args[1] * addend._args[2]) else: raise ValueError("Invalid addend") thetas = tuple(thetas) operators = AffineExpansionStorage( tuple(evaluate(op) for op in operators)) rhs = sum(product(thetas, operators)) solver = LinearSolver(self._lhs, self._solution, rhs, self._bcs) solver.set_parameters(self._parameters) solver.solve()
def jacobian_eval(self, t, solution, solution_dot, solution_dot_coefficient): problem = self.problem assembled_operator = dict() for term in ("m", "a", "b", "bt"): assembled_operator[term] = sum(product(problem.compute_theta(term), problem.operator[term])) return (assembled_operator["m"] * solution_dot_coefficient + assembled_operator["a"] + assembled_operator["b"] + assembled_operator["bt"])
def _compute_output(self, N): assembled_operator = dict() for term in ("m", "n", "g", "h"): assert self.terms_order[term] in (0, 1, 2) if self.terms_order[term] == 2: assembled_operator[term] = sum(product(self.compute_theta(term), self.operator[term][:N, :N])) elif self.terms_order[term] == 1: assembled_operator[term] = sum(product(self.compute_theta(term), self.operator[term][:N])) elif self.terms_order[term] == 0: assembled_operator[term] = sum(product(self.compute_theta(term), self.operator[term])) else: raise ValueError("Invalid value for order of term " + term) self._output = (0.5 * (transpose(self._solution) * assembled_operator["m"] * self._solution) + 0.5 * (transpose(self._solution) * assembled_operator["n"] * self._solution) - transpose(assembled_operator["g"]) * self._solution + 0.5 * assembled_operator["h"])
def _solve_supremizer(self, solution): N_us = self._supremizer.N N_usp = solution.N assert len( self.inner_product["s"] ) == 1 # the affine expansion storage contains only the inner product matrix assembled_operator_lhs = self.inner_product["s"][0][:N_us, :N_us] assembled_operator_bt = sum( product(self.compute_theta("bt_restricted"), self.operator["bt_restricted"][:N_us, :N_usp])) assembled_operator_rhs = assembled_operator_bt * solution if self.dirichlet_bc[ "u"] and not self.dirichlet_bc_are_homogeneous["u"]: assembled_dirichlet_bc = dict() assert self.dirichlet_bc["s"] assert self.dirichlet_bc_are_homogeneous["s"] assembled_dirichlet_bc["u"] = self.compute_theta( "dirichlet_bc_s") else: assembled_dirichlet_bc = None solver = OnlineLinearSolver(assembled_operator_lhs, self._supremizer, assembled_operator_rhs, assembled_dirichlet_bc) solver.set_parameters(self._linear_solver_parameters) solver.solve()
def matrix_eval(self): problem = self.problem N = self.N assembled_operator = dict() for term in ("a", "b", "bt"): assembled_operator[term] = sum(product(problem.compute_theta(term), problem.operator[term][:N, :N])) return assembled_operator["a"] + assembled_operator["b"] + assembled_operator["bt"]
def ic_eval(self): problem = self.problem if len(problem.components) > 1: all_initial_conditions = list() all_initial_conditions_thetas = list() for component in problem.components: if problem.initial_condition[component] is not None: all_initial_conditions.extend(problem.initial_condition[component]) 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 = AffineExpansionStorage(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 is not None: all_initial_conditions = problem.initial_condition 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: return sum(product(all_initial_conditions_thetas, all_initial_conditions)) else: return Function(problem.V)
def vector_eval(self): problem = self.problem N = self.N assembled_operator = dict() for term in ("f", "g"): assembled_operator[term] = sum(product(problem.compute_theta(term), problem.operator[term][:N])) return assembled_operator["f"] + assembled_operator["g"]
def bc_eval(self): problem = self.problem if len(problem.components) > 1: all_dirichlet_bcs = list() all_dirichlet_bcs_thetas = list() for component in problem.components: if problem.dirichlet_bc[component] is not None: all_dirichlet_bcs.extend( problem.dirichlet_bc[component]) all_dirichlet_bcs_thetas.extend( problem.compute_theta("dirichlet_bc_" + component)) if len(all_dirichlet_bcs) > 0: all_dirichlet_bcs = tuple(all_dirichlet_bcs) all_dirichlet_bcs = AffineExpansionStorage( all_dirichlet_bcs) all_dirichlet_bcs_thetas = tuple(all_dirichlet_bcs_thetas) else: all_dirichlet_bcs = None all_dirichlet_bcs_thetas = None else: if problem.dirichlet_bc is not None: all_dirichlet_bcs = problem.dirichlet_bc all_dirichlet_bcs_thetas = problem.compute_theta( "dirichlet_bc") else: all_dirichlet_bcs = None all_dirichlet_bcs_thetas = None assert (all_dirichlet_bcs is None) == (all_dirichlet_bcs_thetas is None) if all_dirichlet_bcs is not None: return sum(product(all_dirichlet_bcs_thetas, all_dirichlet_bcs)) else: return None
def _compute_output(self): assembled_operator = dict() for term in ("m", "n", "g", "h"): assembled_operator[term] = sum(product(self.compute_theta(term), self.operator[term])) self._output = (0.5 * (transpose(self._solution) * assembled_operator["m"] * self._solution) + 0.5 * (transpose(self._solution) * assembled_operator["n"] * self._solution) - transpose(assembled_operator["g"]) * self._solution + 0.5 * assembled_operator["h"])
def _solve_supremizer(self, solution): assert len(self.inner_product["s"]) == 1 # the affine expansion storage contains only the inner product matrix assembled_operator_lhs = self.inner_product["s"][0] assembled_operator_bt = sum(product(self.compute_theta("bt_restricted"), self.operator["bt_restricted"])) assembled_operator_rhs = assembled_operator_bt*solution if self.dirichlet_bc["s"] is not None: assembled_dirichlet_bc = sum(product(self.compute_theta("dirichlet_bc_s"), self.dirichlet_bc["s"])) else: assembled_dirichlet_bc = None solver = LinearSolver( assembled_operator_lhs, self._supremizer, assembled_operator_rhs, assembled_dirichlet_bc ) solver.set_parameters(self._linear_solver_parameters) solver.solve()
def residual_eval(self, solution): problem = self.problem assembled_operator = dict() for term in ("a", "b", "bt", "c", "f", "g"): assembled_operator[term] = sum(product(problem.compute_theta(term), problem.operator[term])) return ((assembled_operator["a"] + assembled_operator["b"] + assembled_operator["bt"]) * solution + assembled_operator["c"] - assembled_operator["f"] - assembled_operator["g"])
def residual_eval(self, solution): problem = self.problem N = self.N assembled_operator = dict() for term in ("a", "b", "bt", "c", "f", "g"): assert problem.terms_order[term] in (1, 2) if problem.terms_order[term] == 2: assembled_operator[term] = sum(product(problem.compute_theta(term), problem.operator[term][:N, :N])) elif problem.terms_order[term] == 1: assembled_operator[term] = sum(product(problem.compute_theta(term), problem.operator[term][:N])) else: raise ValueError("Invalid value for order of term " + term) return ( (assembled_operator["a"] + assembled_operator["b"] + assembled_operator["bt"])*solution + assembled_operator["c"] - assembled_operator["f"] - assembled_operator["g"] )
def matrix_eval(self): problem = self.problem assembled_operator = dict() for term in ("a", "a*", "c", "c*", "m", "n"): assembled_operator[term] = sum(product(problem.compute_theta(term), problem.operator[term])) return (assembled_operator["m"] + assembled_operator["a*"] + assembled_operator["n"] - assembled_operator["c*"] + assembled_operator["a"] - assembled_operator["c"])
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 _compute_output(self, dual_N): primal_solution = self.primal_reduced_problem._solution primal_N = primal_solution.N dual_solution = self._solution assembled_output_correction_and_estimation_operator = dict() assembled_output_correction_and_estimation_operator["a"] = sum( product( self.primal_reduced_problem.compute_theta("a"), self.output_correction_and_estimation["a"] [:dual_N, :primal_N])) assembled_output_correction_and_estimation_operator["f"] = sum( product(self.primal_reduced_problem.compute_theta("f"), self.output_correction_and_estimation["f"][:dual_N])) self._output = transpose( dual_solution ) * assembled_output_correction_and_estimation_operator[ "f"] - transpose( dual_solution ) * assembled_output_correction_and_estimation_operator[ "a"] * primal_solution
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 _combine_all_inner_products(self): if len(self.components) > 1: all_inner_products = list() for component in self.components: # the affine expansion storage contains only the inner product matrix assert len(self.inner_product[component]) == 1 all_inner_products.append(self.inner_product[component][0]) all_inner_products = tuple(all_inner_products) else: # the affine expansion storage contains only the inner product matrix assert len(self.inner_product) == 1 all_inner_products = (self.inner_product[0], ) all_inner_products = AffineExpansionStorage(all_inner_products) all_inner_products_thetas = (1., ) * len(all_inner_products) return sum(product(all_inner_products_thetas, all_inner_products))