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)
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)