def assemble_operator(self, term, current_stage="online"):
     if term == "vanishing_viscosity":
         assert current_stage in ("online", "offline_vanishing_viscosity_postprocessing")
         if current_stage == "online": # load from file
             self.operator["vanishing_viscosity"].load(self.folder["reduced_operators"], "operator_vanishing_viscosity")
             return self.operator["vanishing_viscosity"]
         elif current_stage == "offline_vanishing_viscosity_postprocessing":
             assert len(self.vanishing_viscosity_eigenvalues) is self.N
             assert all([len(vanishing_viscosity_eigenvalues_n) is n + 1 for (n, vanishing_viscosity_eigenvalues_n) in enumerate(self.vanishing_viscosity_eigenvalues)])
             print("build reduced vanishing viscosity operator")
             for n in range(1, self.N + 1):
                 vanishing_viscosity_expansion = OnlineAffineExpansionStorage(1)
                 vanishing_viscosity_eigenvalues = self.vanishing_viscosity_eigenvalues[n - 1]
                 vanishing_viscosity_operator = OnlineMatrix(n, n)
                 n_min = int(n*self._N_threshold_min)
                 n_max = int(n*self._N_threshold_max)
                 lambda_n_min = vanishing_viscosity_eigenvalues[n_min]
                 lambda_n_max = vanishing_viscosity_eigenvalues[n_max]
                 for i in range(n):
                     lambda_i = vanishing_viscosity_eigenvalues[i]
                     if i < n_min:
                         viscosity_i = 0.
                     elif i < n_max:
                         viscosity_i = (
                             self._viscosity *
                             (lambda_i - lambda_n_min)**2/(lambda_n_max - lambda_n_min)**3 *
                             (2*lambda_n_max**2 - (lambda_n_min + lambda_n_max)*lambda_i)
                         )
                     else:
                         viscosity_i = self._viscosity*lambda_i
                     vanishing_viscosity_operator[i, i] = viscosity_i*lambda_i
                 vanishing_viscosity_expansion[0] = vanishing_viscosity_operator
                 self.operator["vanishing_viscosity"][:n, :n] = vanishing_viscosity_expansion
             # Save to file
             self.operator["vanishing_viscosity"].save(self.folder["reduced_operators"], "operator_vanishing_viscosity")
             return self.operator["vanishing_viscosity"]
         else:
             raise ValueError("Invalid stage in assemble_operator().")
     else:
         if current_stage == "offline_vanishing_viscosity_postprocessing":
             if term in self.terms:
                 for n in range(1, self.N + 1):
                     assert self.Q[term] == self.truth_problem.Q[term]
                     term_expansion = OnlineAffineExpansionStorage(self.Q[term])
                     assert self.terms_order[term] in (1, 2)
                     if self.terms_order[term] == 2:
                         for q in range(self.Q[term]):
                             term_expansion[q] = transpose(self.basis_functions[:n])*self.truth_problem.operator[term][q]*self.basis_functions[:n]
                         self.operator[term][:n, :n] = term_expansion
                     elif self.terms_order[term] == 1:
                         for q in range(self.Q[term]):
                             term_expansion[q] = transpose(self.basis_functions[:n])*self.truth_problem.operator[term][q]
                         self.operator[term][:n] = term_expansion
                     else:
                         raise ValueError("Invalid value for order of term " + term)
                 self.operator[term].save(self.folder["reduced_operators"], "operator_" + term)
                 return self.operator[term]
             elif term.startswith("inner_product"):
                 assert len(self.inner_product) == 1 # the affine expansion storage contains only the inner product matrix
                 assert len(self.truth_problem.inner_product) == 1 # the affine expansion storage contains only the inner product matrix
                 for n in range(1, self.N + 1):
                     inner_product_expansion = OnlineAffineExpansionStorage(1)
                     inner_product_expansion[0] = transpose(self.basis_functions[:n])*self.truth_problem.inner_product[0]*self.basis_functions[:n]
                     self.inner_product[:n, :n] = inner_product_expansion
                 self.inner_product.save(self.folder["reduced_operators"], term)
                 return self.inner_product
             elif term.startswith("projection_inner_product"):
                 assert len(self.projection_inner_product) == 1 # the affine expansion storage contains only the inner product matrix
                 assert len(self.truth_problem.projection_inner_product) == 1 # the affine expansion storage contains only the inner product matrix
                 for n in range(1, self.N + 1):
                     projection_inner_product_expansion = OnlineAffineExpansionStorage(1)
                     projection_inner_product_expansion[0] = transpose(self.basis_functions[:n])*self.truth_problem.projection_inner_product[0]*self.basis_functions[:n]
                     self.projection_inner_product[:n, :n] = projection_inner_product_expansion
                 self.projection_inner_product.save(self.folder["reduced_operators"], term)
                 return self.projection_inner_product
             elif term.startswith("dirichlet_bc"):
                 raise ValueError("There should be no need to assemble Dirichlet BCs when querying the offline vanishing viscosity postprocessing stage.")
             else:
                 raise ValueError("Invalid term for assemble_operator().")
         else:
             return EllipticCoerciveReducedProblem_DerivedClass.assemble_operator(self, term, current_stage)
Esempio n. 2
0
 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)