Integrating FEniCS solution up to some point

As a part of a bigger problem there is a first order equation u'(x) = f(x) on [0,1] coupled with integration condition \int_{[0,1]}u(x)dx = 1 which has to be solved in every step. RHS f is a solution of some other equation. This equation can be solved by pure integration but question is how to do that in FEniCS.

As far as I know we can integrate on a whole domain or on subdomains but how can we say something like u(x)=\int_0^xf(s)ds?

Pick points from mesh, define step functions and then integrate product f\cdot\text{step} and later interpolate to starting function space?

Do you maybe know some tutorial about similar problem?

Did you find a solution for your problem? I’m facing a similar situation.

I would suggest implementing your own integration scheme with quadrature points. As you can evaluate a function at any point, i.e. u(x_p), where x_p is the point of interest, you have that \int_{0}^{x}u(x)\mathrm{ds}=\sum_q w_q u(p_q) where p_q are the quadrature points and w_q the weights on the interval [0, x]

Thank you for the reply. So, considering your comment, an attempt to include the term f(x)\cdot v \Bigg|^{x_1}_{x_0} in the variational form of the problem can be done by evaluating:

f(x)\cdot v \Bigg|^{x_1}_{x_0} = f(x_1)*v(x_1) - f(x_0)*v(x_0)

In that case, how could one access the values of the weights in x = x_1 and x = x_0?

You can find quadrature points and weights for the interval [0,1] at wikipedia: Gaussian quadrature - Wikipedia

You could also, as suggested in the original post, create a step function, (for instance using ufl.conditional), as shown in What is the syntax to import conditional operators from ufl package? - #4 by dokken

from dolfin import *
N = 10
mesh = UnitIntervalMesh(N)
V = FunctionSpace(mesh, "CG", 1)
x = SpatialCoordinate(mesh)
f = project(x[0], V)
def u(x0, degree):    
    step = conditional(lt(x[0], x0), 1, 0)
    return  assemble(step*f*dx(domain=mesh, degree=degree))
for p in [0.05, 0.1, 0.23, 0.28]:
    for degree in [2**i for i in range(1,6)]:
        exact = 1/2*(p**2)
        approx = u(p, degree)
        print(p, degree, exact, approx, (exact-approx)/exact )

giving the following for N=10

0.05 2 0.0012500000000000002 0.0010566243270259353 0.15470053837925188
0.05 4 0.0012500000000000002 0.0003130601816090507 0.7495518547127595
0.05 8 0.0012500000000000002 0.0006078258433900407 0.5137393252879675
0.05 16 0.0012500000000000002 0.0008600886103124731 0.31192911175002164
0.05 32 0.0012500000000000002 0.0010324149186984053 0.17406806504127595
0.1 2 0.005000000000000001 0.0049999999999999975 6.938893903907227e-16
0.1 4 0.005000000000000001 0.004999999999999996 1.040834085586084e-15
0.1 8 0.005000000000000001 0.0049999999999999975 6.938893903907227e-16
0.1 16 0.005000000000000001 0.004999999999999997 8.6736173798840335e-16
0.1 32 0.005000000000000001 0.004999999999999999 3.4694469519536137e-16
0.23 2 0.02645 0.031056624327025925 -0.17416349062479863
0.23 4 0.02645 0.025868615737164594 0.021980501430450168
0.23 8 0.02645 0.027763381398945595 -0.04965525137790526
0.23 16 0.02645 0.025557752394857115 0.03373336881447584
0.23 32 0.02645 0.02605440254041938 0.014956425693029152
0.28 2 0.039200000000000006 0.044999999999999984 -0.14795918367346883
0.28 4 0.039200000000000006 0.036979726848275704 0.056639621217456665
0.28 8 0.039200000000000006 0.041501668016300265 -0.058716020823986206
0.28 16 0.039200000000000006 0.037494421258372934 0.043509661776200796
0.28 32 0.039200000000000006 0.03903467013137407 0.004217598689437088

For N=20

0.05 2 0.0012500000000000002 0.0012499999999999994 6.938893903907227e-16
0.05 4 0.0012500000000000002 0.001249999999999999 1.040834085586084e-15
0.05 8 0.0012500000000000002 0.0012499999999999994 6.938893903907227e-16
0.05 16 0.0012500000000000002 0.0012499999999999992 8.6736173798840335e-16
0.05 32 0.0012500000000000002 0.0012499999999999998 3.4694469519536137e-16
0.1 2 0.005000000000000001 0.004999999999999998 5.20417042793042e-16
0.1 4 0.005000000000000001 0.0049999999999999975 6.938893903907227e-16
0.1 8 0.005000000000000001 0.004999999999999999 3.4694469519536137e-16
0.1 16 0.005000000000000001 0.004999999999999998 5.20417042793042e-16
0.1 32 0.005000000000000001 0.005000000000000001 0.0
0.23 2 0.02645 0.025264156081756483 0.04483341845911222
0.23 4 0.02645 0.027856042823180036 -0.053158518834783904
0.23 8 0.02645 0.026929734238625287 -0.01813740032609774
0.23 16 0.02645 0.02624702013695705 0.007674096901434859
0.23 32 0.02645 0.026831735198445915 -0.01443233264445798
0.28 2 0.039200000000000006 0.03776415608175648 0.03662867138376349
0.28 4 0.039200000000000006 0.04091159837873558 -0.04366322394733602
0.28 8 0.039200000000000006 0.039785289794180834 -0.014930862096449692
0.28 16 0.039200000000000006 0.03895341973383283 0.0062903129124279285
0.28 32 0.039200000000000006 0.039664592624127276 -0.011851852656307919

Note that as long as the point x0 does not align with the interval, you do not obtain an exact value.

1 Like

Thank you, dokken. The model I’m developing relies on a second-order stress equation on a boundary of a 2D (rectangle) domain.

I integrate the equation by parts to reduce the order, and the process yields the term t \cdot \phi \Big |^{S_f}_{S_i}, in which t is the tangent vector, \phi is a test function from a vector function space and S_f and S_i are the end and begin of the boundary S, respectively.

Considering the value of \phi(S_f)= \phi(S_i) = 1, the terms t \cdot \phi (S_f) and - t \cdot \phi (S_i) should be included in the residual of the element located at S_f and S_i. I’ve been struggling to find a solution to this problem, as I don’t know how to mark an edge using a MeshFunction and I still don’t know how could I work with the residual of an element alongside the weighted residual from the problem formulation. I defined a dummy function t_edges that takes the tangent value on the edges and is zero everywhere else, and the I add the term inner(t_edges, phi)*ds(marker) into the variational formulation. However this approach is not working. Do you have any thoughts on how I could do this?