How to apply the same heat flux in corner of plate

Hello everybody

I am using FEniCS to solve the heat transfer equation by applying the same heat flow q to the left side and the bottom of a square plate. At the coordinate point (0,0), I get the double flow (2 * q).
How I can apply the flux to get the same flux q at the coordinate point (0,0)
Preformatted text
solide

the code I wrote to design the two edges is as follows

l   = 73.2*e-3
numElems =1
mesh = RectangleMesh(Point(0,0),Point(l,l), numElems, numElems,"left") 
.....  
class Vertical_horizontal(SubDomain):
    def inside(self, x, on_boundary):
          #if x[0,0] !=0:
           #print(x)
           return on_boundary and ((abs(x[0] - 0.) < DOLFIN_EPS))or (abs(x[1] - 0) < DOLFIN_EPS))   


As you have not shown how you are actually applying the heat flux, there isn’t much one can to tell you what you have done wrong. Please supply a code illustrating how you apply the flux the code should be minimal, meaning that all parameters, functions and modules not needed to reproduce the issue should be removed

Hi dokken,
Here is the reduced code I am using to apply the flux at the left and the bottom side of the mesh:

from __future__ import print_function
from dolfin import *
from fenics import *
sf = 1.0e-3                #    length scale factor (mm to m)
l   = 73.2*sf                   
numElems =1             
mesh = RectangleMesh(Point(0,0),Point(l,l), numElems, numElems,"left") 
V = FunctionSpace(mesh, "Lagrange", 1)

K = as_matrix([[ 0.3,0.10 ,[0.10,0.2]])                             
Q_heat    = 0.4*e3                                       

g = Expression('Q_heat', degree=1, Q_heat=Constant(Q_heat))    
  
class Left_bottom(SubDomain):
    def inside(self, x, on_boundary):
           return on_boundary and ((abs(x[0] - 0.) < DOLFIN_EPS))or (abs(x[1] - 0) < DOLFIN_EPS))

vertical = Left_bottom()
tdim = mesh.topology().dim()     

boundaries = MeshFunction('size_t', mesh, tdim-1)      
boundaries.set_all(0)       
vertical.mark(boundaries, 1) 
dsB = Measure("ds", subdomain_id=2, subdomain_data=boundaries) 
def operator(u, v):
    return ( inner(grad(v), K*grad(u)) - f*v)*dx - g*v*dsB  

u = TrialFunction(V)                      
v = TestFunction(V)                         
u0 = Function(V) 
dt = 4
theta = Constant(2.0/3.0)                     
F = rhoC*inner((u-u0), v)*dx +dt*theta*operator(u, v) + dt*(1.0-theta)*operator(u0, v)  
a , L = lhs(F), rhs(F)            
u = Function(V) 
A = assemble(a)    
b = None    

u0.interpolate(u_0)     

vtkfile = File('direct/solution.pvd')        

u.interpolate(u_0)    
t = 0.0
vtkfile << (u, t) 
while t <= t_end:            

                        
    A = assemble(a)
    b = assemble(L)
    u = Function(V)
    solve(A,u, b)  
    vtkfile << (u, t)         
     

The two lines below translate the way I apply the flow in the code

def operator(u, v):
    return ( inner(grad(v), K*grad(u)) - f*v)*dx - g*v*dsB  

Then I call the function operator in

F = rhoC*inner((u-u0), v)*dx +dt*theta*operator(u, v) + dt*(1.0-theta)*operator(u0, v)

But at the coordinate point (0,0), I get the double flow (2 * q) instead of obtaining a flow that value is q.
How I can apply the flux to get the same flux q at the coordinate point (0,0)?

I hope that I have made more sens now.
Thanks.

Several parameters are missing from the code above, so I cannot run your problem as it is.

This will not give you a double contribution at the corner, as it is a line integral.
Let us for a minute consider the fundamentals of your problem, namely your boundary marker:

from fenics import *
numElems = 1
l = 1
mesh = RectangleMesh(Point(0,0),Point(l,l), numElems, numElems,"left")

Q_heat    = 0.4e3

g = Expression('Q_heat', degree=1, Q_heat=Constant(Q_heat))

class Left_bottom(SubDomain):
    def inside(self, x, on_boundary):
           return on_boundary and ((abs(x[0] - 0.) < DOLFIN_EPS))or (abs(x[1] - 0) < DOLFIN_EPS)

vertical = Left_bottom()
tdim = mesh.topology().dim()

boundaries = MeshFunction('size_t', mesh, tdim-1)
boundaries.set_all(0)
vertical.mark(boundaries, 1)
File("marker.pvd") << boundaries

This can be visualized as

In your code you will therefore integrate over the yellow lines, getting the correct contributions.

Hi dokken
I took over the code and applied the flow integrating following the yellow line you indicated.

from fenics import *
numElems = 1
l = 1
mesh = RectangleMesh(Point(0,0),Point(l,l), numElems, numElems,"left")

Q_heat    = 0.4e3

g = Expression('Q_heat', degree=1, Q_heat=Constant(Q_heat))

class Left_bottom(SubDomain):
    def inside(self, x, on_boundary):
           return on_boundary and ((abs(x[0] - 0.) < DOLFIN_EPS))or (abs(x[1] - 0) < DOLFIN_EPS)

vertical = Left_bottom()
tdim = mesh.topology().dim()

boundaries = MeshFunction('size_t', mesh, tdim-1)
boundaries.set_all(0)
vertical.mark(boundaries, 1)
dsB = Measure("ds", subdomain_id=1  subdomain_data=boundaries)
flux =  g*v*dsB
Flux = assemble(flux)

The calculation of of the flux is given by the two lines below:

flux =  g*v*dsB
Flux = assemble(flux)

I have the vector

Flux =[400, 200 ,200, 0.0 ]

I got the flow values ​​back, instead of having 400 at the coordinate point (0,0), I want to have 200.
How to obtain the correct vector below?

Flux =[200 ,200, 200, 0.0]

You Need to Remember that you are integrating a function that has contributions on each interval, (a piecewise linear function going from q1 to Zero from on vertex to another, and you take the integrated contribution of this). That is why you Get a double contributions at that degree of freedom.

I understood your explanation.
I tried to remove the point of coordinate (0,0) at the level of an interval so as not to have the double flow at this degree of freedom.
How I can write it.
I used a fragment of code that is below but it doesn’t work;
please see why or propose me another way to do the same work

class Vertical_horizontal(SubDomain):
    def inside(self, x, on_boundary):
          if x[0] !=0:
            
           return on_boundary and ((abs(x[0] - 0.) < DOLFIN_EPS) or (abs(x[1] - 0) < DOLFIN_EPS)) ``

or is there a possibility to apply the flux at this point only?

I still think you are not fully understanding what you are doing.
Your problem can be written as find
u=sum_{i=1}u_i\phi_(x,y) such that
a(u, \phi_j) =l(\phi_j) for j=1,\dots,N where \phi_k is the kth basis function, u_k the kth degree of freedom (N degrees of freedom).
Lets say l(v)=\int_{\partial \Omega} g l(v)~\mathrm{d}s.
Thus for l(\phi_j) Where j is the corner node in the middle of the interval, you get contributions from each of the intervals of \partial\Omega Where \phi_j\neq 0. Giving it double contributions when compared with the end nodes of the line integral.

Thank you
I understand very well your explanation and what I am doing.
What I ask you is to rewrite the code to avoid the double contributions to the nodes of coordinate (0,0)
Please have any idea how I can write it

Change the magnitude of g, (for instance by divinding the value at this node 2. make g a ufl conditional, see for instance Reaction Diffusion - Mixed Element time loop issues

Thank you
To be honest, I am a newbie in FEniCS programming, I tried to access the test function value v at the coordinate node (0,0) where there is double contribution of heat flow.
I want to ask you, if you can offer me a fraction of code allowing to divide the value of g at this node?

You can directly modify the assembled vector, as follows:

from fenics import *
numElems = 1
l = 1
mesh = RectangleMesh(Point(0,0),Point(l,l), numElems, numElems,"left")

Q_heat    = 0.4e3

g = Expression('Q_heat', degree=1, Q_heat=Constant(Q_heat))
x = SpatialCoordinate(mesh)
class Left_bottom(SubDomain):
    def inside(self, x, on_boundary):
           return on_boundary and (abs(x[0] - 0.) < DOLFIN_EPS) or (abs(x[1] - 0) < DOLFIN_EPS)

vertical = Left_bottom()
tdim = mesh.topology().dim()

boundaries = MeshFunction('size_t', mesh, tdim-1)
boundaries.set_all(0)
vertical.mark(boundaries, 1)
dsB = Measure("ds", subdomain_id=1, subdomain_data=boundaries)
V = FunctionSpace(mesh, "CG", 1)
v = TestFunction(V)
flux =  g*v*dsB
Flux = assemble(flux)
Flux[3]/=2
print(Flux.get_local())

However, I still think you are not fully grasping what you are doing. g is the flux. \int_{\partial\Omega} gv\mathrm{d} s gives you the array b with the i th entry b_i=\int_{\partial \Omega} g \phi_i(x)\mathrm{d} s, which should have a double contribution for the middle node.
You can see this by using more than 1 element per side (use for instance 2 and look at the vector).

Thank you
I resumed the calculation with finite element calculations. For mathematical calculation, there is a double flow at the coordinate point (0,0). This is what the code does according to mathematical theory. For what I’m doing is adapting this code to the experimental, i.e. passing the same electric wire on both edges as well as in the corner, so that there is no the double flow at point (0,0)?
How to rewrite the boundary conditions of flow to insert it into the variational formulation?

from __future__ import print_function
from dolfin import *
from fenics import *
#from ufl import *
from dolfin import cpp
import numpy as np
from numpy import cos, sin, pi, exp
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

#"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

#Constants (atous en  SI unités)
sf = 1.0e-3                   
l   = 1    
numElems =1                 
numNoeudx= numElems+1             
numNoeudy= numElems+1             

nt=(numNoeudx)*(numNoeudy)-1
 

mesh = RectangleMesh(Point(0,0),Point(l,l), numElems, numElems,"left")  

 

V = FunctionSpace(mesh, "Lagrange", 1)          
                                               
 
  

class Left_bottom(SubDomain):
    def inside(self, x, on_boundary):
           return on_boundary and ((abs(x[0] - 0.) < DOLFIN_EPS)) or (abs(x[1] - 0) < DOLFIN_EPS)
 

vertical = Left_bottom()
 

tdim = mesh.topology().dim()     

#print(tdim)

boundaries = MeshFunction('size_t', mesh, tdim-1)        

 

boundaries.set_all(0)                                        
 
vertical.mark(boundaries, 1)                                          

File("bord/marker.pvd") << boundaries 
 
u_0 = Expression("20",degree=1)                           

f = Expression("0",degree=1)    

# Equation coefficients
File("marker.pvd") << boundaries

K = as_matrix([[ 0.3,0.],[0.,0.2]])                              

Q_heat    = 0.4e3                                             

g = Expression('Q_heat', degree=1, Q_heat=Constant(Q_heat))   #
  
#g= Constant(0.4e3) 


rhoC = Constant(1.46555e6)          # constant   J/m³/°C 

 
dsB = Measure("ds", subdomain_id=1, subdomain_data=boundaries) # 



#print(coor.shape[0] )

def operator(u, v):
    return ( inner(grad(v), K*grad(u)) ) #- f*v)*dx #     - g*v*dsB  #g*v*dsC # 


 

u = TrialFunction(V)                       

v = TestFunction(V)                            

u0 = Function(V)                              

t_end =36                                     

#num_steps =10                               #  nombres de pas de temps( number of time steps)

#dt = t_end/ num_steps                            

dt = 4
theta = Constant(2.0/3.0) 

#F = rhoC*inner((u-u0), v)*dx +dt*theta*operator(u, v) + dt*(1.0-theta)*operator(u0, v) -dt*theta*fe -dt*(1.0-theta)*fe # 
 
File("bord/marker.pvd") << boundaries
 

ke = inner(grad(v),K*grad(u))*dx     

ce = rhoC*inner(u,v)*dx               

fe =  dt*g*v*dsB               
 
 

C = assemble(ce)                       

KE = assemble(ke)

  

a = ce + dt*theta*ke 

L = rhoC*inner(u0, v)*dx - dt*(1.0-theta)*inner(grad(v),K*grad(u0))*dx +fe

  

u = Function(V)                                             
 
problem = LinearVariationalProblem(a, L, u)                        
solver  = LinearVariationalSolver(problem)                         # 
solver.parameters['linear_solver'] = 'cg'                                 

solver.parameters['preconditioner'] = 'ilu'


A = assemble(a)   #   
#print (A.array())
b = None

u0.interpolate(u_0)      #    

Flux = assemble(fe) 
Flux[nt]/=2
 
print(Flux.get_local()) 

 

vtkfile = File('janvier01/solution.pvd')        


u.rename("Temerature", "temperature")             

u.interpolate(u_0)  #      
t = 0.0
vtkfile << (u, t)           

td = 0.0 #    le compteur

 

while t <= t_end:             #tant que ( boucle while)

    
    b = (assemble(rhoC*inner(u0, v)*dx - dt*(1.0-theta)*inner(grad(v),K*grad(u0))*dx) + Flux )
                              
    #b = assemble(L, tensor=b)
    A= assemble(a)                            
    
    
    
  
     
    solver.solve()  
    
    vtkfile << (u, t)       
   
    u0.assign(u)           
    t += dt
    td += 1
    #L  = rhs(F)
 
print(u.compute_vertex_values(mesh) ,t)
plt.figure(1)
P = plot(u,title='temperature à t = %g' % t)
plt.colorbar(P)
#plt.show() 

plt.figure(2)
p = plot(u,mode ="color", title='temperature à t = %g' % t)
plt.colorbar(p)
plot(mesh) 			
plt.show()                                      
 

j’ai assemblé le flux seul comme vous l’avez dit et l’intégrant dans la formulation variationnelle mais ça ne fonctionne pas, ça n’agit pas dans le calcul.

flux =  dt*g*v*dsB
Flux = assemble(fe) 
Flux[nt]/=2

je l’ai mis dans la forme ci dessous

 b = (assemble(rhoC*inner(u0, v)*dx - dt*(1.0-theta)*inner(grad(v),K*grad(u0))*dx) + Flux )

How to write it so that the variational formulation for the solution?

I do not understand your latest post. I have given you a throughout explaination of how I believe this problem should be solved.

You keep on posting a lengthy example code, and have not attempted to reduce it to a minimal example.