def init(self):
        # Store the left and right hand side operators
        if self.operator[
                "stability_factor_left_hand_matrix"] is None:  # init was not called already
            if self.expansion_index is None:
                self.operator[
                    "stability_factor_left_hand_matrix"] = self.truth_problem.operator[
                        "stability_factor_left_hand_matrix"]
            else:
                self.operator[
                    "stability_factor_left_hand_matrix"] = AffineExpansionStorage(
                        (self.truth_problem.
                         operator["stability_factor_left_hand_matrix"][
                             self.expansion_index], ))
        if self.operator[
                "stability_factor_right_hand_matrix"] is None:  # init was not called already
            self.operator[
                "stability_factor_right_hand_matrix"] = self.truth_problem.operator[
                    "stability_factor_right_hand_matrix"]
            assert len(
                self.operator["stability_factor_right_hand_matrix"]) == 1

        # Store Dirichlet boundary conditions
        if self.dirichlet_bc is None:  # init was not called already (or raised a trivial error)
            try:
                self.dirichlet_bc = AffineExpansionStorage(
                    self.truth_problem.assemble_operator(
                        "stability_factor_dirichlet_bc")
                )  # need to call assemble_operator because this special bc is not stored among the ones in self.truth_problem.dirichlet_bc
            except ValueError:  # there were no Dirichlet BCs
                self.dirichlet_bc = None

        # Also make sure to create folder for cache
        self.folder.create()
 def _init_operators(self, current_stage="online"):
     # The difference between this method and the parent one is that non-hierarchical affine
     # expansion storage is requested during the online stage and during the postprocessing
     # of the offline stage.
     if current_stage == "online":
         # Initialize all terms using a non-hierarchical affine expansion storage, and then loading from file
         for term in self.terms:
             self.operator[term] = OnlineNonHierarchicalAffineExpansionStorage(0) # it will be resized by assemble_operator
             self.assemble_operator(term, "online")
             self.Q[term] = len(self.operator[term])
         # Initialize additional reduced operator related to vanishing viscosity
         self.operator["vanishing_viscosity"] = OnlineNonHierarchicalAffineExpansionStorage(1)
         self.assemble_operator("vanishing_viscosity", "online")
     elif current_stage == "offline":
         # Call Parent
         EllipticCoerciveReducedProblem_DerivedClass._init_operators(self, current_stage)
     elif current_stage == "offline_vanishing_viscosity_postprocessing":
         # Initialize additional truth operators
         self.truth_problem.operator["k"] = AffineExpansionStorage(self.truth_problem.assemble_operator("k"))
         self.truth_problem.operator["m"] = AffineExpansionStorage(self.truth_problem.assemble_operator("m"))
         # Initialize all terms using a non-hierarchical affine expansion storage
         for term in self.terms:
             self.Q[term] = self.truth_problem.Q[term]
             self.operator[term] = OnlineNonHierarchicalAffineExpansionStorage(self.Q[term])
         # Initialize additional reduced operator related to vanishing viscosity
         self.operator["vanishing_viscosity"] = OnlineNonHierarchicalAffineExpansionStorage(1)
     else:
         # Call Parent, which may eventually raise an error
         EllipticCoerciveReducedProblem_DerivedClass._init_operators(self, current_stage)
Beispiel #3
0
 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()
Beispiel #4
0
 def init(self):
     # Store the symmetric part of the required term
     if self.operator is None: # init was not called already
         if isinstance(self.term, tuple):
             forms = (self.truth_problem.assemble_operator(self.term[0])[self.term[1]], )
         else:
             assert isinstance(self.term, str)
             forms = self.truth_problem.assemble_operator(self.term)
         self.operator = AffineExpansionStorage(tuple(0.5*(f + adjoint(f)) for f in forms))
     
     # Store the inner product matrix
     if self.inner_product is None: # init was not called already
         self.inner_product = AffineExpansionStorage(self.truth_problem.assemble_operator("inner_product"))
         
     # Also make sure to create folder for cache
     self.folder.create()
 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)
Beispiel #6
0
 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
Beispiel #7
0
 def _init_inner_products(self):
     """
     Initialize inner products required for the offline phase. Internal method.
     """
     # Get helper strings depending on the number of basis components
     n_components = len(self.components)
     assert n_components > 0
     if n_components > 1:
         inner_product_string = "inner_product_{c}"
     else:
         inner_product_string = "inner_product"
     # Assemble inner products
     if self.inner_product is None:  # init was not called already
         inner_product = dict()
         for component in self.components:
             inner_product[component] = AffineExpansionStorage(
                 self.assemble_operator(
                     inner_product_string.format(c=component)))
         if n_components == 1:
             self.inner_product = inner_product[self.components[0]]
         else:
             self.inner_product = inner_product
         assert self._combined_inner_product is None
         self._combined_inner_product = self._combine_all_inner_products()
     # Assemble inner product to be used for projection
     if self.projection_inner_product is None:  # init was not called already
         projection_inner_product = dict()
         for component in self.components:
             try:
                 projection_inner_product[
                     component] = AffineExpansionStorage(
                         self.assemble_operator("projection_" +
                                                inner_product_string.format(
                                                    c=component)))
             except ValueError:  # no projection_inner_product specified, revert to inner_product
                 projection_inner_product[
                     component] = AffineExpansionStorage(
                         self.assemble_operator(
                             inner_product_string.format(c=component)))
         if n_components == 1:
             self.projection_inner_product = projection_inner_product[
                 self.components[0]]
         else:
             self.projection_inner_product = projection_inner_product
         assert self._combined_projection_inner_product is None
         self._combined_projection_inner_product = self._combine_all_projection_inner_products(
         )
Beispiel #8
0
    def _init_dirichlet_bc(self):
        """
        Initialize boundary conditions required for the offline phase. Internal method.
        """
        # Get helper strings depending on the number of basis components
        n_components = len(self.components)
        assert n_components > 0
        if n_components > 1:
            dirichlet_bc_string = "dirichlet_bc_{c}"
        else:
            dirichlet_bc_string = "dirichlet_bc"
        # Assemble Dirichlet BCs
        # we do not assert for
        # (self.dirichlet_bc is None) == (self.dirichlet_bc_are_homogeneous is None)
        # because self.dirichlet_bc may still be None after initialization, if there
        # were no Dirichlet BCs at all and the problem had only one component
        if self.dirichlet_bc_are_homogeneous is None:  # init was not called already
            dirichlet_bc = dict()
            dirichlet_bc_are_homogeneous = dict()
            for component in self.components:
                try:
                    operator_bc = AffineExpansionStorage(
                        self.assemble_operator(dirichlet_bc_string.format(c=component)))
                except ValueError:  # there were no Dirichlet BCs
                    dirichlet_bc[component] = None
                    dirichlet_bc_are_homogeneous[component] = False
                else:
                    dirichlet_bc[component] = operator_bc
                    try:
                        self.compute_theta(dirichlet_bc_string.format(c=component))
                    except ValueError:  # there were no theta functions
                        # We provide in this case a shortcut for the case of homogeneous Dirichlet BCs,
                        # that do not require an additional lifting functions.
                        # The user needs to implement the dirichlet_bc case for assemble_operator,
                        # but not the one in compute_theta (since theta would not matter, being multiplied by zero)
                        def generate_modified_compute_theta(component, operator_bc):
                            standard_compute_theta = self.compute_theta

                            def modified_compute_theta(self_, term):
                                if term == dirichlet_bc_string.format(c=component):
                                    return (0., ) * len(operator_bc)
                                else:
                                    return standard_compute_theta(term)

                            return modified_compute_theta

                        PatchInstanceMethod(
                            self, "compute_theta", generate_modified_compute_theta(component, operator_bc)).patch()
                        dirichlet_bc_are_homogeneous[component] = True
                    else:
                        dirichlet_bc_are_homogeneous[component] = False
            if n_components == 1:
                self.dirichlet_bc = dirichlet_bc[self.components[0]]
                self.dirichlet_bc_are_homogeneous = dirichlet_bc_are_homogeneous[self.components[0]]
            else:
                self.dirichlet_bc = dirichlet_bc
                self.dirichlet_bc_are_homogeneous = dirichlet_bc_are_homogeneous
            assert self._combined_and_homogenized_dirichlet_bc is None
            self._combined_and_homogenized_dirichlet_bc = self._combine_and_homogenize_all_dirichlet_bcs()
 def generate_random(self):
     f = ()
     for i in range(self.Q):
         # Generate random vector
         g = RandomDolfinFunction(self.V)
         # Generate random form
         f += (self.f(g), )
     F = AffineExpansionStorage(f)
     # Genereate random theta
     theta = RandomTuple(self.Q)
     # Return
     return (theta, F)
 def generate_random(self):
     a = ()
     for i in range(self.Q):
         # Generate random vector
         k = RandomDolfinFunction(self.V)
         # Generate random form
         a += (self.a(k), )
     A = AffineExpansionStorage(a)
     # Genereate random theta
     theta = RandomTuple(self.Q)
     # Return
     return (theta, A)
Beispiel #11
0
 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))
Beispiel #12
0
 def _combine_and_homogenize_all_dirichlet_bcs(self):
     if len(self.components) > 1:
         all_dirichlet_bcs = list()
         for component in self.components:
             if self.dirichlet_bc[component] is not None:
                 all_dirichlet_bcs.extend(self.dirichlet_bc[component])
         if len(all_dirichlet_bcs) > 0:
             all_dirichlet_bcs = tuple(all_dirichlet_bcs)
             all_dirichlet_bcs = AffineExpansionStorage(all_dirichlet_bcs)
         else:
             all_dirichlet_bcs = None
     else:
         all_dirichlet_bcs = self.dirichlet_bc
     if all_dirichlet_bcs is not None:
         all_dirichlet_bcs_thetas = (0., ) * len(all_dirichlet_bcs)
         return sum(product(all_dirichlet_bcs_thetas, all_dirichlet_bcs))
     else:
         return None
 def _init_initial_condition(self):
     # Get helper strings depending on the number of basis components
     n_components = len(self.components)
     assert n_components > 0
     if n_components > 1:
         initial_condition_string = "initial_condition_{c}"
     else:
         initial_condition_string = "initial_condition"
     # Assemble initial condition
     # we do not assert for
     # (self.initial_condition is None) == (self.initial_condition_is_homogeneous is None)
     # because self.initial_condition may still be None after initialization, if there
     # were no initial condition at all and the problem had only one component
     if self.initial_condition_is_homogeneous is None: # init was not called already
         initial_condition = dict()
         initial_condition_is_homogeneous = dict()
         for component in self.components:
             try:
                 operator_ic = AffineExpansionStorage(self.assemble_operator(initial_condition_string.format(c=component)))
             except ValueError: # there were no initial condition: assume homogeneous one
                 initial_condition[component] = None
                 initial_condition_is_homogeneous[component] = True
             else:
                 initial_condition[component] = operator_ic
                 initial_condition_is_homogeneous[component] = False
         if n_components == 1:
             self.initial_condition = initial_condition[self.components[0]]
             self.initial_condition_is_homogeneous = initial_condition_is_homogeneous[self.components[0]]
         else:
             self.initial_condition = initial_condition
             self.initial_condition_is_homogeneous = initial_condition_is_homogeneous
         # We enforce consistency between Dirichlet BCs and IC, as in the following cases:
         # a) (homogeneous Dirichlet BCs, homogeneous IC): nothing to be enforced
         # b) (non homogeneous Dirichlet BCs, homogeneous IC): we enforce that the theta
         #     term of each Dirichlet BC is zero at t = 0, resulting in homogeneous Dirichlet BCs
         #     at t = 0. This is needed e.g. in order to make sure that while post processing a snapshot
         #     subtracting the lifting at t = 0 doesn't change the solution (which must remain zero)
         # c) (homogeneous Dirichlet BCs, non homogeneous IC): we trust that the non homogeneous IC
         #     provided by the user is actually zero on the Dirichlet boundaries, otherwise there will
         #     be no way to accurately recover it by projecting on a space which only has bases equal
         #     to zero on the Dirichlet boundary.
         # d) (non homogeneous Dirichlet BCs, non homogeneous IC): we trust that the restriction of IC
         #     on the Dirichlet boundary is equal to the evaluation of the Dirichlet BCs at t = 0.
         #     If that were not true, than post processing a snapshot subtracting the lifting at t = 0
         #     would result in a postprocessed snapshot which is not zero on the Dirichlet boundary, thus
         #     adding an element with non zero value on the Dirichlet boundary to the basis
         for component in self.components:
             if len(self.components) > 1:
                 has_homogeneous_dirichlet_bc = self.dirichlet_bc_are_homogeneous[component]
                 has_homogeneous_initial_condition = self.initial_condition_is_homogeneous[component]
                 dirichlet_bc_string = "dirichlet_bc_{c}"
             else:
                 has_homogeneous_dirichlet_bc = self.dirichlet_bc_are_homogeneous
                 has_homogeneous_initial_condition = self.initial_condition_is_homogeneous
                 dirichlet_bc_string = "dirichlet_bc"
             if has_homogeneous_dirichlet_bc and has_homogeneous_initial_condition: # case a)
                 pass
             elif not has_homogeneous_dirichlet_bc and has_homogeneous_initial_condition: # case b)
                 def generate_modified_compute_theta(component):
                     standard_compute_theta = self.compute_theta
                     def modified_compute_theta(self_, term):
                         if term == dirichlet_bc_string.format(c=component):
                             theta_bc = standard_compute_theta(term)
                             if self_.t == 0.:
                                 return (0.,)*len(theta_bc)
                             else:
                                 return theta_bc
                         else:
                             return standard_compute_theta(term)
                     return modified_compute_theta
                 PatchInstanceMethod(self, "compute_theta", generate_modified_compute_theta(component)).patch()
             elif has_homogeneous_dirichlet_bc and not has_homogeneous_initial_condition: # case c)
                 pass
             elif not has_homogeneous_dirichlet_bc and not has_homogeneous_initial_condition: # case d)
                 pass
             else:
                 raise RuntimeError("Impossible to arrive here.")