def get_projection_error_function(self, mu_src, mu_dest, reference_degree, refine_mesh=0): """Construct projection error function by projecting mu_src vector to mu_dest space of dest_degree. From this, the projection of mu_src onto the mu_dest space, then to the mu_dest space of dest_degree is subtracted. If refine_mesh > 0, the destination mesh is refined uniformly n times.""" from spuq.fem.fenics.fenics_utils import create_joint_mesh from dolfin import FunctionSpace, VectorFunctionSpace from spuq.fem.fenics.fenics_basis import FEniCSBasis # get joint mesh based on destination space basis_src = self[mu_src].basis basis_dest = self[mu_dest].basis mesh_reference, parents = create_joint_mesh([basis_src.mesh], basis_dest.mesh) # create function space on destination mesh if basis_dest._fefs.num_sub_spaces() > 0: fs_reference = VectorFunctionSpace(mesh_reference, basis_dest._fefs.ufl_element().family(), reference_degree) else: fs_reference = FunctionSpace(mesh_reference, basis_dest._fefs.ufl_element().family(), reference_degree) basis_reference = FEniCSBasis(fs_reference, basis_dest._ptype) # project both vectors to reference space w_reference = basis_reference.project_onto(self[mu_src]) w_dest = self.get_projection(mu_src, mu_dest) w_dest = basis_reference.project_onto(w_dest) # define summation function to get values on original destination mesh from function space on joint mesh def sum_up(vals): sum_vals = [sum(vals[v]) for _, v in parents.iteritems()] return np.array(sum_vals) return w_dest - w_reference, sum_up
def get_projection_error_function_old(self, mu_src, mu_dest, reference_degree, refine_mesh=0): """Construct projection error function by projecting mu_src vector to mu_dest space of dest_degree. From this, the projection of mu_src onto the mu_dest space, then to the mu_dest space of dest_degree is subtracted. If refine_mesh > 0, the destination mesh is refined uniformly n times.""" # TODO: If refine_mesh is True, the destination space of mu_dest is ensured to include the space of mu_src by mesh refinement # TODO: proper description # TODO: separation of fenics specific code from dolfin import refine, FunctionSpace, VectorFunctionSpace from spuq.fem.fenics.fenics_basis import FEniCSBasis if not refine_mesh: w_reference = self.get_projection(mu_src, mu_dest, reference_degree) w_dest = self.get_projection(mu_src, mu_dest) w_dest = w_reference.basis.project_onto(w_dest) sum_up = lambda vals: vals else: # uniformly refine destination mesh # NOTE: the cell_marker based refinement used in FEniCSBasis is a bisection of elements # while refine(mesh) carries out a red-refinement of all cells (split into 4) # basis_src = self[mu_src].basis basis_dest = self[mu_dest].basis mesh_reference = basis_dest.mesh for _ in range(refine_mesh): mesh_reference = refine(mesh_reference) # print "multi_vector::get_projection_error_function" # print type(basis_src._fefs), type(basis_dest._fefs) # print basis_src._fefs.num_sub_spaces(), basis_dest._fefs.num_sub_spaces() # if isinstance(basis_dest, VectorFunctionSpace): if basis_dest._fefs.num_sub_spaces() > 0: fs_reference = VectorFunctionSpace(mesh_reference, basis_dest._fefs.ufl_element().family(), reference_degree) else: fs_reference = FunctionSpace(mesh_reference, basis_dest._fefs.ufl_element().family(), reference_degree) basis_reference = FEniCSBasis(fs_reference, basis_dest._ptype) # project both vectors to reference space w_reference = basis_reference.project_onto(self[mu_src]) w_dest = self.get_projection(mu_src, mu_dest) w_dest = basis_reference.project_onto(w_dest) sum_up = lambda vals: np.array([sum(vals[i * 4:(i + 1) * 4]) for i in range(len(vals) / 4 ** refine_mesh)]) return w_dest - w_reference, sum_up