Hi all, 1) How do I define a volumetric source/sink for a specific region? For example, if I am solving a diffusion equation with homogeneous BCs and have a volumetric source f(x,y) such that if (x[0] >= 0.25 && x[0] <= 0.30 && x[1] >= 0.25 && x[1] <= 0.30): f == 1 else: f == 0 2) I want to play around with PETSc's Variational Inequality <http://www.mcs.anl.gov/petsc/petsc-dev/docs/manualpages/SNES/SNESVINEWTONSSLS.html> solver. In my own PETSc code all I had to do was provide a Jacobian matrix, a residual vector, pass in the options -snes_type vinewtonssls (or it might be vinewotnrsls), and pass in SNESVINEWTONSSLS <http://www.mcs.anl.gov/petsc/petsc-dev/docs/manualpages/SNES/SNESVINEWTONSSLS.html> .
From my last discussion with some PETSc folks it seems this VI feature is relatively now, so I was wondering if that last item can be invoked through the version of petsc4py you guys are using?
3) Is it possible to employ the SUPG formulation for advection-diffusion problems in firedrake? Thanks, Justin
On 31 Aug 2015, at 22:31, Justin Chang <jychang48@gmail.com> wrote:
Hi all,
2) I want to play around with PETSc's Variational Inequality solver. In my own PETSc code all I had to do was provide a Jacobian matrix, a residual vector, pass in the options -snes_type vinewtonssls (or it might be vinewotnrsls), and pass in SNESVINEWTONSSLS . From my last discussion with some PETSc folks it seems this VI feature is relatively now, so I was wondering if that last item can be invoked through the version of petsc4py you guys are using?
If it's just as simple as passing -snes_type vinewtonssls, then I think you're good to go. But presumably you also need to provide the SNES with the variable bounds. I think the DOLFIN interface for this (which we should mimic) is to do: solver = NLVSolver(...) solver.solve(lower_bound, upper_bound) where you provide Functions in the solution space defining your variable bounds (and can omit one or the other if you don't have a bound in that direction). The SNES solver needs to be informed of these, so if they're provided one must do: solver.snes.setVariableBounds(lb, ub) Here's a sketch patch (untested): Use it like: solver = ... lb = Function(V) lb.assign(-10) # Ensure solution is bounded below by -10. solver.solve(lb=lb) diff --git a/firedrake/variational_solver.py b/firedrake/variational_solver.py index ec47ce7..342c3e9 100644 --- a/firedrake/variational_solver.py +++ b/firedrake/variational_solver.py @@ -155,7 +155,18 @@ class NonlinearVariationalSolver(object): @timed_function("SNES solver execution") @profile - def solve(self): + def solve(self, lb=None, ub=None): + """Solve the variational problem. + + You can provide optional lower and upper bounds on the + solution vector if using PETSc's variational inequality + solvers. + + :arg lb: An optional lower bound on the solution vector. If + not provided, use -inf. + :arg ub: An optional upper bound on the solution vector. If + not provided, use +inf. + """ dm = self.snes.getDM() dm.setAppCtx(weakref.proxy(self._ctx)) dm.setCreateMatrix(self._ctx.create_matrix) @@ -168,6 +179,20 @@ class NonlinearVariationalSolver(object): # solve, ensure these are passed through to the snes. solving_utils.update_parameters(self, self.snes) + if lb is not None or ub is not None: + if ub: + with ub.dat.vec_ro as v: + ub_vec = v + else: + ub_vec = dm.createGlobalVector() + ub_vec.set(PETSc.INFINITY) + if lb: + with lb.dat.vec_ro as v: + lb_vec = v + else: + lb_vec = dm.createGlobalVector() + lb_vec.set(PETSc.NINFINITY) + self.snes.setVariableBounds(lb_vec, ub_vec) with self._problem.u.dat.vec as v: self.snes.solve(None, v)
Hi Lawrence, Ah yes I meant to say pass in SNESVISetVariableBounds <http://www.mcs.anl.gov/petsc/petsc-dev/docs/manualpages/SNES/SNESVISetVariableBounds.html> if that's what you're patch handles. I will try this out. And thanks Andrew for your help. I ended up porting the undocumented SUPG advection-diffusion FEniCS example to Firedrake. One more question: 4 I also want to work with a tensor diffusion coefficient. In FEniCS I could normally do something like D = as_matrix([[1.0],[0,1]]) but i specifically want tensorial dispersion from velocity. E.g., D = alpha_t*norm(velocity)*Identity + (alpha_L-alpha_t)*outer(v,v)/norm(v) Where alpha_t and alpha_L are the transverse and longitudinal dispersivity respectively (ignoring molecular diffusion for the moment). How would do I express this D matrix? Thanks, Justin On Tue, Sep 1, 2015 at 1:39 AM, Lawrence Mitchell < lawrence.mitchell@imperial.ac.uk> wrote:
On 31 Aug 2015, at 22:31, Justin Chang <jychang48@gmail.com> wrote:
Hi all,
2) I want to play around with PETSc's Variational Inequality solver. In my own PETSc code all I had to do was provide a Jacobian matrix, a residual vector, pass in the options -snes_type vinewtonssls (or it might be vinewotnrsls), and pass in SNESVINEWTONSSLS . From my last discussion with some PETSc folks it seems this VI feature is relatively now, so I was wondering if that last item can be invoked through the version of petsc4py you guys are using?
If it's just as simple as passing -snes_type vinewtonssls, then I think you're good to go. But presumably you also need to provide the SNES with the variable bounds. I think the DOLFIN interface for this (which we should mimic) is to do:
solver = NLVSolver(...)
solver.solve(lower_bound, upper_bound)
where you provide Functions in the solution space defining your variable bounds (and can omit one or the other if you don't have a bound in that direction).
The SNES solver needs to be informed of these, so if they're provided one must do:
solver.snes.setVariableBounds(lb, ub)
Here's a sketch patch (untested):
Use it like:
solver = ...
lb = Function(V) lb.assign(-10)
# Ensure solution is bounded below by -10. solver.solve(lb=lb)
diff --git a/firedrake/variational_solver.py b/firedrake/variational_solver.py index ec47ce7..342c3e9 100644 --- a/firedrake/variational_solver.py +++ b/firedrake/variational_solver.py @@ -155,7 +155,18 @@ class NonlinearVariationalSolver(object):
@timed_function("SNES solver execution") @profile - def solve(self): + def solve(self, lb=None, ub=None): + """Solve the variational problem. + + You can provide optional lower and upper bounds on the + solution vector if using PETSc's variational inequality + solvers. + + :arg lb: An optional lower bound on the solution vector. If + not provided, use -inf. + :arg ub: An optional upper bound on the solution vector. If + not provided, use +inf. + """ dm = self.snes.getDM() dm.setAppCtx(weakref.proxy(self._ctx)) dm.setCreateMatrix(self._ctx.create_matrix) @@ -168,6 +179,20 @@ class NonlinearVariationalSolver(object): # solve, ensure these are passed through to the snes. solving_utils.update_parameters(self, self.snes)
+ if lb is not None or ub is not None: + if ub: + with ub.dat.vec_ro as v: + ub_vec = v + else: + ub_vec = dm.createGlobalVector() + ub_vec.set(PETSc.INFINITY) + if lb: + with lb.dat.vec_ro as v: + lb_vec = v + else: + lb_vec = dm.createGlobalVector() + lb_vec.set(PETSc.NINFINITY) + self.snes.setVariableBounds(lb_vec, ub_vec) with self._problem.u.dat.vec as v: self.snes.solve(None, v)
_______________________________________________ firedrake mailing list firedrake@imperial.ac.uk https://mailman.ic.ac.uk/mailman/listinfo/firedrake
On 1 Sep 2015, at 09:09, Justin Chang <jychang48@gmail.com> wrote:
try this out.
And thanks Andrew for your help. I ended up porting the undocumented SUPG advection-diffusion FEniCS example to Firedrake.
One more question:
4 I also want to work with a tensor diffusion coefficient. In FEniCS I could normally do something like
D = as_matrix([[1.0],[0,1]])
but i specifically want tensorial dispersion from velocity. E.g.,
D = alpha_t*norm(velocity)*Identity + (alpha_L-alpha_t)*outer(v,v)/norm(v)
Where alpha_t and alpha_L are the transverse and longitudinal dispersivity respectively (ignoring molecular diffusion for the moment). How would do I express this D matrix?
Assuming alpha_t and alpha_L are just scalars. I think you just do: Id = Identity(mesh.ufl_cell().geometric_dimension()) alpha_t = Constant(val_t) alpha_L = Constant(val_L) norm_v = inner(velocity, velocity) D = alpha_t * norm_v * Id + (alpha_L - alpha_t) * outer(v, v) / norm_v Then use D as normal in your variational form. A word of warning, D is not polynomial, so UFL try and guess a quadrature degree that will be quite high. You probably want to end up specifying the quad degree manually. For example: a = D[i, i] * trial * test*dx(degree=chosen_quad_degree) Cheers, Lawrence
participants (2)
- 
                
                Justin Chang
- 
                
                Lawrence Mitchell