Regarding the project command

Hello everyone,
I am new to the FEniCS. I am trying to compute a field (f_a_2) that is based on the line integral of displacement in a particular section of the mesh. The field (f_a_2) also depends on its value from previous iteration. To save the field, I project the field on functionspace and use assign command to use in next iteration. I noticed that during projection there are some negative values, which I supposed that are not possible (due to the use conditional command). Please, help me to understand the reason of these negative values. I attached the minimal code.

Thank you. :slight_smile:

from fenics import *    
from mshr import *
import matplotlib.pyplot as plt
from ufl import nabla_div
import numpy as np
from ufl import replace
import sys, os, shutil, math
from numpy.linalg import eig
from dolfin import *
from numpy import array
import time
from ufl import eq
from ufl import le
from ufl import ge, ne


#Compiler parameter
parameters["form_compiler"]["cpp_optimize"] = True
ffc_options = {"optimize": True, \
               "eliminate_zeros": True, \
               "precompute_basis_const": True, \
               "precompute_ip_const": True}
# Define Data
mu = 80770.     
lmbda = 121150.    

gamma_val = 0.002194
beta_val = 23.649
del_f = 0.01
del_c = 0.0036
# Mesh Data
mesh = Mesh('mesh_2.xml')     
ndim = mesh.topology().dim()   
remain = CompiledSubDomain("x[1] >= 1.0 - tol",tol = 1E-14) 
boundaries = MeshFunction("size_t", mesh,mesh.topology().dim()-1) 
boundaries.set_all(0)
remain.mark(boundaries, 1)                      
ds = Measure("ds",subdomain_data=boundaries)    

V_u = VectorFunctionSpace(mesh, 'CG', 1) 
V_alpha = FunctionSpace(mesh, 'CG', 1)        
u, du, v = Function(V_u), TrialFunction(V_u), TestFunction(V_u)
u_0 = Function(V_u)
jump_0 = Function(V_alpha)
f_a = Function(V_alpha)
f_a_2 = Function(V_alpha)
f_a_0 = Function(V_alpha)
zero_1 = Constant(0.0)
f_a_0 = project(zero_1,V_alpha)
u.rename('displacement','displacement')



f_a_T1 = Constant(2.2e-70)
f_a = project(f_a_T1, V_alpha)     
fdf_p = Function(V_alpha)    


tol = 1E-10        
tol_v = 1e-18      
def boundary_D_l(x, on_boundary):  
    return x[1] <= 0.0 + tol

def boundary_D_o(x, on_boundary):    
    return x[0] <= 0.0 + tol and x[1] <= 0.0 + tol

def boundary_D_t(x, on_boundary):    
    return x[1] >= 1.0 - tol 
        
bcl = DirichletBC(V_u.sub(1), Constant(0.0), boundary_D_l, method='pointwise')  

bco = DirichletBC(V_u, Constant((0.0 ,0.0)), boundary_D_o, method='pointwise')    

# Calculation of positive part of strain

def eps(u):
    return sym(grad(u))

def sigma(u):
    return 2.0*mu*(eps(u)) + lmbda*tr(eps(u))*Identity(ndim)

def line_integral(field, a,b,n): 
    assert n > 0
    
    A = np.array([a, b-0.006])
    B = np.array([a, b+0.006])

    mesh_points = [A + t*(B-A) for t in np.linspace(0, 1, n+1)]

    tdim, gdim = 1, len(A)
    mesh_l = Mesh()
    editor = MeshEditor()
    editor.open(mesh_l, 'interval', tdim, gdim)
    editor.init_vertices(n+1)
    editor.init_cells(n)

    for vi, v in enumerate(mesh_points):
        editor.add_vertex(vi, v) 
        
    for ci in range(n): editor.add_cell(ci, np.array([ci, ci+1], dtype='uintp'))

    editor.close()    

    V_l = FunctionSpace(mesh_l, 'Lagrange',1)
    v = interpolate(field, V_l)

    return assemble(v*dx)


energy = 0.5 * inner(sigma(u), eps(u)) * dx                             



E_u = derivative(energy,u,v)   
Jd = derivative(E_u, u, du)         


num_steps = 25               
num_of_large_load_step = 25     
total_disp = 0.01               


u_R = Expression(('disp_A + disp_app*(n+1-B)'),disp_A = 0.0, disp_app = total_disp/(num_of_large_load_step), n=0., B=0., degree=0)  
bct = DirichletBC(V_u.sub(1), u_R, boundary_D_t, method='pointwise')       
bc_disp = [bcl, bco, bct]         


problem_u = NonlinearVariationalProblem(E_u, u, bc_disp, Jd)
solver_u = NonlinearVariationalSolver(problem_u)
prm = solver_u.parameters

prm["newton_solver"]["relative_tolerance"] = 5E-3
prm["newton_solver"]["absolute_tolerance"] = 8E-3
prm["newton_solver"]["convergence_criterion"] = "residual"
prm["newton_solver"]["error_on_nonconvergence"] = True
prm["newton_solver"]["linear_solver"] = 'mumps'
prm["newton_solver"]["lu_solver"]["symmetric"] = False 
prm["newton_solver"]["maximum_iterations"] = 5000
prm["newton_solver"]["relaxation_parameter"] = 1.0

prm["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = True 



class MyFunctionExpression(UserExpression):
    def __init__(self, n,u_sol, **kwargs):
        super().__init__(**kwargs)
        self.n = n
        self.u_sol = u_sol
        
    def eval(self, value, x):
        x_c = x[0]
        y_c = x[1]
        if y_c <= 0.501 and y_c >= 0.497:
            q = line_integral(self.u_sol,x_c,y_c,self.n)
            value[0]= q
        else:
            value[0]= 0.
   
    def value_shape(self):
        return (1,)

def alternate_minimization(u):
    print('Solution for displacement')
    solver_u.solve()
    jump = MyFunctionExpression(n=10,u_sol=project(sym(grad(u))[1,1],V_alpha),element = V_alpha.ufl_element()) 

    jump_sign = conditional(ge(jump,0.),1.,0.)

    jump_rate = jump-MyFunctionExpression(n=10,u_sol=project(sym(grad(u_0))[1,1],V_alpha),element = V_alpha.ufl_element())

    jump_rate_sign = conditional(ge(jump_rate,0.),1.,0.)
        
    jump_star = conditional(ge(jump,del_c),(del_f - del_c)*f_a_0 + del_c,del_c)
    alpha_fun = (f_a_0 + gamma_val)*pow((abs(jump_rate)/jump_star),beta_val)
    alpha_fun_1 = conditional(lt(alpha_fun,0.),0.,alpha_fun)
    f_a_2 = f_a_0 + alpha_fun_1
    f_a = conditional(lt(f_a_2, f_a_T1), f_a_T1, f_a_2)
    fdf = (2*f_a_T1)/(f_a + f_a_T1)
       
    f_a_0.assign(project(f_a_2,V_alpha))
    fdf_p = project(fdf, V_alpha)
    file_f_a << (f_a_0,n)
    file_fdf << (fdf_p,n)       
    u_0.assign(u)
    
    return ()
  
savedir =  "results/"
if os.path.isdir(savedir):
    shutil.rmtree(savedir)
file_u = File(savedir+"/u.pvd")        
file_f_a = File(savedir+"/f_a.pvd")    
file_fdf = File(savedir+"/fdf.pvd")   
def postprocessing():
    file_u << (u,n)
 
for n in range(num_steps):
    u_R.n = n
    alternate_minimization(u)
    postprocessing()

Your code is quite far from a minimal example, so with a quick glance I can only give some pointers.
Are you sure that the output field is in “CG” 1 function space?
I see that during your solution process you are projecting

which is not in

But in “DG”, 0.

1 Like

Thank you Dokken for the prompt response,

I got the error with you help. By project the field on "DG"0 it works.
Thanks a lot.

P.S.: Can you suggest me any reading material of FEniCS to strengthen my concepts? I know about only ‘Solving PDEs in Python The FEniCS Tutorials I’.

There are plenty of tutorials on different aspects out there, such as:

If you want to learn more about the concepts behind fenics, namely the finite element method, I would suggest considering any of the books on the list: An overview of the FEniCS Project — FEniCSx tutorial

1 Like

Thank you Dokken for the information and your time.