Clarification on conditional expressions

Asked by Yaakoub El Khamra

Greetings
I have an inquiry regarding conditional expressions. I apologize in advance if this is more of a UFL issue than a Dolfin issue. I am trying to enforce limits on an expression (physically: species saturation). I am using something simple as follows:

f_limited = conditional(ge(f, limit), limit, f)

What I have noticed is that if I project f_limited for a quick plot, the conditional is not strictly honored. I am assuming this is due to the projection and nothing more, but I just want to check. The following is example code setup to replicate the issue, the limit is set to 5.0 but the maximum value of f_limited_projected turned out to be 5.03624. Is there a recommended method to inspect the limits (min/max) of an expression? Thank you very much in advance.

from dolfin import *
import numpy as np

# Create mesh and define function space
mesh = UnitSquare(32, 32)
V = FunctionSpace(mesh, "CG", 3)

f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)")

f_projected = project(f,V)

print "the maximum value of f is: %g"% np.max(f_projected.vector().array())

print "establishing a limit of 5 on the value of f"
limit = Constant(5.0)
f_limited = conditional(ge(f, limit), limit, f)

f_limited_projected = project(f_limited, V)

print "the maximum value of f_limited is: %g"% np.max(f_limited_projected.vector().array())

Question information

Language:
English Edit question
Status:
Solved
For:
DOLFIN Edit question
Assignee:
No assignee Edit question
Solved by:
Johan Hake
Solved:
Last query:
Last reply:
Revision history for this message
Best Johan Hake (johan-hake) said :
#1

You can try generating a complex expression:

ccode = """
class Conditional: public Expression
{
public:
       double limit;
       Conditional():Expression()
       {
         limit = 5.0;
       }

       void eval(dolfin::Array<double>& values, const
dolfin::Array<double>& x) const
       {
         values[0] = 10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) /
0.02);
         values[0] = values[0]>limit ? limit : values[0];
       }
     };
"""
f = Expression(ccode)
f_projected = project(f,V)

print "the maximum value of f is: %g"% np.max(f_projected.vector().array())

Here you see that the projected maximal value is much closer to the
limit. This might be a bug in UFL expressions?

Johan

On 07/12/2012 05:41 PM, Yaakoub El Khamra wrote:
> New question #202953 on DOLFIN:
> https://answers.launchpad.net/dolfin/+question/202953
>
> Greetings
> I have an inquiry regarding conditional expressions. I apologize in advance if this is more of a UFL issue than a Dolfin issue. I am trying to enforce limits on an expression (physically: species saturation). I am using something simple as follows:
>
> f_limited = conditional(ge(f, limit), limit, f)
>
> What I have noticed is that if I project f_limited for a quick plot, the conditional is not strictly honored. I am assuming this is due to the projection and nothing more, but I just want to check. The following is example code setup to replicate the issue, the limit is set to 5.0 but the maximum value of f_limited_projected turned out to be 5.03624. Is there a recommended method to inspect the limits (min/max) of an expression? Thank you very much in advance.
>
>
> from dolfin import *
> import numpy as np
>
> # Create mesh and define function space
> mesh = UnitSquare(32, 32)
> V = FunctionSpace(mesh, "CG", 3)
>
> f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)")
>
> f_projected = project(f,V)
>
> print "the maximum value of f is: %g"% np.max(f_projected.vector().array())
>
> print "establishing a limit of 5 on the value of f"
> limit = Constant(5.0)
> f_limited = conditional(ge(f, limit), limit, f)
>
> f_limited_projected = project(f_limited, V)
>
> print "the maximum value of f_limited is: %g"% np.max(f_limited_projected.vector().array())
>

Revision history for this message
Yaakoub El Khamra (yelkhamra) said :
#2

Thank you very, very much sir! It works perfectly!

Regards
Yaakoub

Revision history for this message
Yaakoub El Khamra (yelkhamra) said :
#3

One last question regarding this: if I want to impose conditional limits on f such that:
f = conditional(ge(u, constant(5.0)), constant(5.0), u)

where u is the solution to a problem (essentially limiting a solution), how would I do it?

Revision history for this message
Yaakoub El Khamra (yelkhamra) said :
#4

Thanks Johan Hake, that solved my question.

Revision history for this message
Johan Hake (johan-hake) said :
#5

On 07/13/2012 09:41 PM, Yaakoub El Khamra wrote:
> Question #202953 on DOLFIN changed:
> https://answers.launchpad.net/dolfin/+question/202953
>
> Yaakoub El Khamra posted a new comment:
>
> One last question regarding this: if I want to impose conditional limits on f such that:
> f = conditional(ge(u, constant(5.0)), constant(5.0), u)
>
> where u is the solution to a problem (essentially limiting a solution),
> how would I do it?

  You should be able to use the above syntax, but given that this might
give you some flacky results you can either do it the dirty way:

   u.vector()[u.vector()>5] = 5

which wont work in parallel. You should also be able to wrap your
Function in an Expression:

ccode = """
  class Conditional: public Expression
  {
  public:
         boost::shared_ptr<GenericFunction> u;
         double limit;
         Conditional():Expression()
         {
           limit = 5.0;
         }

        void eval(dolfin::Array<double>& values, const
  dolfin::Array<double>& x, const ufc::cell& cell) const
         {
           assert(u);
           u->eval(values, x, cell);
           values[0] = values[0]>limit ? limit : values[0];
         }
       };
"""
f = Expression(ccode)
f.u = u

Johan

Revision history for this message
Yaakoub El Khamra (yelkhamra) said :
#6

Johan, thank you very, very much.