def restrict(self, gf, gc): """Restrict a dual function. :arg gf: The source (fine grid) dual function. :arg gc: The target (coarse grid) dual function. """ Vc = gc.function_space() Vf = gf.function_space() dgf = self.DG_work(Vf) dgc = self.DG_work(Vc) VDGf = dgf.function_space() VDGc = dgc.function_space() work = self.work_vec(Vf) dgwork = self.work_vec(VDGc) # g \in Vf^* -> g \in VDGf^* with gf.dat.vec_ro as gfv, dgf.dat.vec_wo as dgscratch: if self.use_fortin_interpolation: work.pointwiseDivide(gfv, self.V_dof_weights(Vf)) self.V_approx_inv_mass(Vf, VDGf).multTranspose(work, dgscratch) else: self.V_inv_mass_ksp(Vf).solve(gfv, work) self.V_DG_mass(Vf, VDGf).mult(work, dgscratch) # g \in VDGf^* -> g \in VDGc^* firedrake.restrict(dgf, dgc) # g \in VDGc^* -> g \in Vc^* with dgc.dat.vec_ro as dgscratch, gc.dat.vec_wo as gcv: self.DG_inv_mass(VDGc).mult(dgscratch, dgwork) self.V_DG_mass(Vc, VDGc).multTranspose(dgwork, gcv)
def multTranspose(self, mat, x, y, inc=False): with self.ffn.dat.vec as v: x.copy(v) firedrake.restrict(self.ffn, self.cfn) for bc in self.cbcs: bc.zero(self.cfn) with self.cfn.dat.vec_ro as v: if inc: y.axpy(1.0, v) else: v.copy(y)
def restrict(f, c): return firedrake.restrict(f, c)
def restrict(self, residual, out): Tf = residual for Tinter in reversed(self.intermediate_Ts): fd.restrict(Tf, Tinter) Tf = Tinter fd.restrict(Tf, out.fun)