This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

How to apply DirichletBC on selected nodes for a 3D Mesh

0 votes

Hello,

I would like to apply DirichletBC on selected nodes for a 3D mesh. The problem is that FENICS expect facets and not vertices. So around this problem I implemented three functions.

def DirichletBC_On_Vertices(mesh,group,V,c,num):
bc=[]
for vertex in vertices(mesh):
    if group[vertex]==num:
        bc.append(DirichletBC(V,c,"near(x[0],"+str(vertex.point().x())+") && near(x[1],"+str(vertex.point().y())+") && near(x[2],"+str(vertex.point().z())+")",method="pointwise"))
return bc

def DirichletBC_On_Faces(mesh,group,V,c,num):
bc=[]
for face in faces(mesh):
    if group[face]==num:
        for vertex in vertices(face):
            bc.append(DirichletBC(V,c,"near(x[0],"+str(vertex.point().x())+") && near(x[1],"+str(vertex.point().y())+") && near(x[2],"+str(vertex.point().z())+")",method="pointwise"))
return bc

def DirichletBC_On_Edges(mesh,group,V,c,num):
bc=[]
#bc1=[]
for edge in edges(mesh):
    if group[edge]==num:
        for vertex in vertices(edge):
            bc.append(DirichletBC(V,c,"near(x[0],"+str(vertex.point().x())+") && near(x[1],"+str(vertex.point().y())+") && near(x[2],"+str(vertex.point().z())+")",method="pointwise"))
return bc

Theses functions seems to work for a little mesh. When I used a big mesh, ii have a problem with python ( infinity of Calling DOLFIN just-in-time (JIT) compiler, this may take some time). I think the problem is related to the repetition of this line:
DirichletBC(V,c,"near(x[0],"+str(vertex.point().x())+") && near(x[1],"+str(vertex.point().y())+") && near(x[2],"+str(vertex.point().z())+")",method="pointwise"

Do you have a solution to optimize this code ?
In my case i have a mark on my nodes is it possible to apply directly values on nodes without using facets?

Thank you very much !

Arnaud

asked Jun 6, 2016 by Arnaud FEniCS Novice (190 points)
edited Jun 7, 2016 by Arnaud

Please format your question properly.

I hope that you could use an Expression, but this is not allowed, so disregard the following

If you replace

DirichletBC(V,c,"near(x[0],"+str(vertex.point().x())+") && near(x[1],"+str(vertex.point().y())+") && near(x[2],"+str(vertex.point().z())+")",method="pointwise")

with

DirichletBC(V,c,Expression("near(x[0],x0) && near(x[1],y0) && near(x[2],z0)",x0=vertex.point().x(), y0=vertex.point().y(),z0 = vertex.point().z()),method="pointwise")

it should work. If it does not, try

DirichletBC(V,c,Expression("near(x[0],x0) && near(x[1],y0) && near(x[2],z0)",x0=Constant(vertex.point().x()), y0=Constant(vertex.point().y()),z0 = Constant(vertex.point().z())),method="pointwise")

Unfortunately i have no expression. I only have a special marker on selected nodes.

2 Answers

0 votes

Why do you not use a boolean function, i.e.

def bnd_func(x,on_boundary):
   return near(x[0],vertex.point().x()) and near(x[1],vertex.point().y()) and near(x[2],vertex.point().z())

bc.append(DirichletBC(V,c,bnd_func,method="pointwise"))

?

answered Jun 7, 2016 by KristianE FEniCS Expert (12,900 points)

Thank you for your answer.

I just implement your code but it does not work. The line JIT disappeared but the terminal displays "solving linear variational problem " without solution and the cpu is constantly maximum.
I also tried your code with a little mesh. The computed displacement (elasticity problem) is not right.I think that your code is not equivalent.

Is it possible modify the initial DirichletBC in order to add this type of constraint. I have the master version. I found this class but i have trouble understanding it. .. It may be easier to apply BC after assembly matrix with petsc function ?

0 votes

Arnaud,
Hi!
When you say nodes, did you mean you want to apply DirichletBC on one of the point on surface, except for the DirichletBC applied on specific surface?
I used some function like this to apply DirichletBC on my mode, and it works...

self.gamma1 = self._dirichlet_bottom_point_boundary()
self.gamma1.mark(self.boundary_parts, 1)

u_moveless = Constant([0.0]*self.dim)
bc_bottom_point = DirichletBC(V, u_moveless, self.gamma2, method="pointwise")
self.bcs.append(bc_bottom_point)

class _dirichlet_bottom_point_boundary(SubDomain):

    # Apply Dirichlet BC at one fixed point at bottom

    def __init__(self):
        SubDomain.__init__(self)

    def inside(self, x, on_boundary):

        # This tolorance is used to find the fixed point at the bottom.

        tol = 0.01
        return x[2] < tol and ((x[0])**2 + x[1]**2) < tol  # If the point I want to fix is at z=0, x=0, and y=0
answered Jun 7, 2016 by xiyang FEniCS Novice (410 points)

KristianE, xiyang
Thank you very much for your help!

I found a not too bad solution pending a more direct method to apply Dirichlet BC on different entities. The trick is to build a very big string in which we put all the vertex. Then i use once Dirichlet BC. Finally the compute is very fast with a big mesh. Here is the code :

def DirichletBC_On_Vertices(mesh,group,V,c,num):
StringList=""
for vertex in vertices(mesh):
    if group[vertex]==num:
        StringList=StringList+"near(x[0],"+\
                str(vertex.point().x())+\
                ") && near(x[1],"\
                +str(vertex.point().y())+\
                ") && near(x[2],"+\
                str(vertex.point().z())+") || "
return DirichletBC(V,c,StringList[0:-3],method="pointwise")

Arnaud

Hi Arnaud,

Can you take a look at my recent post 'Problem in setting BC'.

I found out that fenics is not selecting all the nodes properly which are specified in the domain.

Any help is highly appreciated.

Yours sincerely,
Shankha

...