Page 1 of 1

Applying boundary condition to large number of nodes

Posted: 05 Mar 2019, 20:20
by eriksson
Hi!
I've recently started using Elmer, and so far I'm impressed with the capabilities of the software. I'm planning to use ElmerGrid and ElmerSolver for 3D linearly elastic mechanical problems. I'm writing a Python code, with the goal of optimizing parameters in CAD files with respect to stresses, as part of my master's thesis. I use GMSH as mesher.

I've successfully managed to run some simple analyses, where I've used the Boundary Condition sections in the .sif-file to fix certains boundaries (keyword Target Boundaries) or nodes (keyword Target Nodes), and apply a force to other places. My goal is to be able to set forces and lock nodes in certain regions, e.g. lock (displacement=0) all nodes where x^2+y^2+z^2>r_1 and apply z-force to all nodes x^2+y^2+z^2<r_2.


My first thought was to use conditions in the .sif-file, with MATC-expressions. However, as far as I understand you still have to specify which nodes/boundaries that the condition is tested for through the "Target Nodes/Boundaries" keywords, and it's not possible to list the same node in several boundary conditions, so I can't just set all nodes as target nodes in every Boundary Condition-section, and let the MATC-expression do the actual sorting. So instead I went for finding the numbers of the nodes that satisfy my condition in my Python code, by collecting node numbers and coordinates and doing some math on them. However, I don't get the results that I expect. If I lock 284 nodes on the outer perimeter of my mesh, it works as expected. If I then lock one more node, which also is on the outer perimeter and therefore more or less undeformed in the previous case, I get a completely different result.

I attach pictures where both the results are shown, and the additional node is shown with its number (visualized with ParaView). The pink shape is undeformed, and the grey is deformed. I also attach the .sif-file, where the first Boundary Condition contains two Target Nodes-keywords, one commented out which creates the working result, and the non-commented gives the weird result.

I've considered the possibility that the node numbering system gets changed somehow along the way. But it seems unreasonable that the node numbering in the .vtu result file that I view in ParaView (and there I can search for specific nodes using "Find Data") is different from the one I set in the .sif-file. So now I'm leaning towards there being some sort of limitation on how many nodes one can set as Target Nodes. I've tried splitting the BC into several Boundary Condition sections to no avail.

Re: Applying boundary condition to large number of nodes

Posted: 06 Mar 2019, 11:24
by raback
Hi

You can set the displacements & related condition whether to apply them in BCs or body forces, for example

Code: Select all

Boundary Condition 1
  Name = "MoveSphere"
  Target Boundaries(1) = 1
  Displacement 1 = 0.0
  Displacement 2 = 0.0
  Displacement 3 = 1.0
  $r = 1.0
  Displacement 1 Condition = Variable "Coordinate" 
    Real MATC "r^2-tx(0)^2-tx(1)^2-tx(2)^2"
  Displacement 2 Condition = Variable "Coordinate" 
    Real MATC "r^2-tx(0)^2-tx(1)^2-tx(2)^2"
  Displacement 3 Condition = Variable "Coordinate" 
    Real MATC "r^2-tx(0)^2-tx(1)^2-tx(2)^2"
End    

This is a little cumbersome and certainly not the fastest as MATC is very slow but at least quite easy to use.

This uses the generic feature of any Dirichlet condition that if we set "Varname = a" it is only applied if in "Varname Condition = b", b > 0.

-Peter

Re: Applying boundary condition to large number of nodes

Posted: 06 Mar 2019, 12:15
by eriksson
Hi and thanks for the reply!
I did try using MATC expressions, but the problem with that for my application seems to be that I still have to specify which boundaries the BC will (conditionally) apply to. I want to set several boundary conditions, and it doesn't seem allowed to list the same boundary in two different Boundary Condition sections, so I can't just set all boundaries in my mesh as target boundaries for all BCs. So I have to know which boundaries pertain to which region in my model, which I don't see any simpler solution to than to parse the ELMER mesh boundary file and use the nodal coordinate data and let my Python code sort out the boundaries with the right coordinates, but then I wouldn't need the MATC sorting anyway.

Re: Applying boundary condition to large number of nodes

Posted: 06 Mar 2019, 18:22
by raback
Hi

You could use the "Body Force" section as well if you want to fix all the nodes in some region.

Also you could use "Defaul Target" that sets all boundaries not otherwise set as follows:

Code: Select all

Boundary Condition 1
  Name = "fixed"
  Target Boundaries(1) = 1
  Displacement 1 = 0.0
  Displacement 2 = 0.0
  Displacement 3 = 1.0
End 

Boundary Condition 2
  Name = "MoveSphere"

  Default Target = Logical True
  Displacement 1 = 0.0
  Displacement 2 = 0.0
  Displacement 3 = 1.0
  $r = 1.0
  Displacement 1 Condition = Variable "Coordinate" 
    Real MATC "r^2-tx(0)^2-tx(1)^2-tx(2)^2"
  Displacement 2 Condition = Variable "Coordinate" 
    Real MATC "r^2-tx(0)^2-tx(1)^2-tx(2)^2"
  Displacement 3 Condition = Variable "Coordinate" 
    Real MATC "r^2-tx(0)^2-tx(1)^2-tx(2)^2"
End    
-Peter

Re: Applying boundary condition to large number of nodes

Posted: 07 Mar 2019, 12:54
by eriksson
Hi again,

Thanks for your help! I was not aware that displacements also could be set in the Body Force section. It works well when I set my displacement condition there. However, I can't get the force I want to apply to the center of my geometry to work as a Body Force, if I move that force from Boundary Condition to Body Force I get a solution that's trivially zero everywhere.

This is the definition of the force, that I've put in either Body Force or Boundary Condition-sections:

Code: Select all

  Force 3 = Real 100000000000
  Force 3 Condition = Variable Coorinate 1, Coordinate 2
	Real MATC "-(tx(0)*tx(0)+tx(1)*tx(1))+0.000004" !innerradie på fjäder = 0.00125, låst radie < 0.002, 0.002^2 = 0.000004
I've tried putting it in the same Body Force-section as I set the displacement in, and also to put it in a separate Body Force-section, and setting

Code: Select all

Body Force = 1 2
in the Body-section. I also tried separating 1 and 2 with a comma, with no change in results.

Another quick question referring back to my original post: Is there a limitation to the number of nodes that one can set as "Target Nodes" in the BC-section, so that option is out of the question?

I much appreciate your kind help, I wouldn't have been able to get this far without all the information on this forum :D

Re: Applying boundary condition to large number of nodes

Posted: 07 Mar 2019, 22:45
by raback
Hi

The Neumann conditions and Dirichlet conditions are quite different. In Dirichlet condition we directly set a value of the variable. You can generalize this quite easily from boundaries to bodies. The SI unit is m. Also the "condition" makes sense since it is either on or off.

The Neumann condition, on the other hand has unit N/m^2. The corresponding body force has unit N/m^3. Also it does not as much make sense to have a condition since you can as well multiply the force with a distribution function. When Neumann condition goes to zero then there is no condition. If Dirichlet condition goes to zero, it is still a Dirichlet condition.

Look at the documentation how to set body force in units of N/m^3. I would think its called "Stress Bodyforce 1" etc. or something like that.

-Peter

Re: Applying boundary condition to large number of nodes

Posted: 08 Mar 2019, 17:11
by eriksson
Hi again and thanks for the reply!

I'm somewhat familiar with Neumann and Dirichlet conditions and the differences between them, but not knowledgeable enough to feel completely confident swimming around these waters. The ElmerSolver manual seems to indicate that the Boundary Condition-section is for Dirichlet conditions, if looking at the explanation for the Boundary Condition section:

Code: Select all

Boundary Condition bc id
     Target Boundaries(n) Integer
     The set of boundaries on which the Dirichlet conditions will be applied
but obviously it's also possible to set forces in this section, which, to my understanding, is a Neumann type condition since I'm specifying a force, which is related to the derivative of the variable the solver is treating (displacement). My end goal is to apply a known net force, evenly distributed across a set of nodes. Now I'm leaning towards reading the mesh.boundary-file and finding the boundary numbers of the boundaries containing my node set. But then I have (at least ;) ) one more question: if I set a force on a specified Target Boundary, like:

Code: Select all

Boundary Condition 1
  Target Boundaries(1) = 48
  Force 3 = 1
End
does this mean that I set a force of 1 N (I use SI units for everything) on every node in boundary 48, or a force of 1/(# of nodes in boundary) N on every node?

Re: Applying boundary condition to large number of nodes

Posted: 08 Mar 2019, 17:41
by raback
Hi

The Dirichlet conditions is always done by library subroutines and hence is explained in the ElmerSolver manual.

The Neumann conditions are module specific and are explained in Elmer Models Manual under the correct module.

-Peter

Re: Applying boundary condition to large number of nodes

Posted: 25 Mar 2019, 13:25
by eriksson
Hi and thanks for your answer!

To answer my own question about force setting,

Code: Select all

Boundary Condition 1
  Target Boundaries(1) = 48
  Force 3 = 1
End
results in a force of 1 N/m^2 on boundary 48 (if one has been using SI units in the model). Adding the keyword

Code: Select all

Force 3 Normalize by Area = Logical True
gives a net force of 1 N on the boundary, as I wished.

I ended up parsing the boundary file to find boundary numbers from node numbers. If anyone ever would have the same need, here's my Python code for doing so. Given a set of nodes (object type 'list'), it finds boundaries whose nodes are all in the node set. So the nodeset can include more nodes than only those in the boundaries one wishes to find, but not less.

Code: Select all

def findElmerBoundary(self, nodes):
        # finds the boundary index(ices) of the boundaries that only have node numbers contained within input argument nodes
        if not self.elmerMeshPath:
            print('Error: Elmer mesh path must be created before finding Elmer boundaries. Run convertToElmerMesh or add path to valid Elmer mesh')
            return
        allBndrs = set() # gonna be filled with all boundary indices in mesh
        notBndrs = set() # gonna be filled with those boundary indices that have nodes NOT in inputarg nodes
        
        f = open(self.elmerMeshPath+'\\mesh.boundary', 'r')
        for line in f:
            entries = line.split(' ')
            if int(entries[4]) == 303: # just for safety, only 2D linear triangle elements are observed
                allBndrs.add(int(entries[1]))
                if not ((int(entries[5]) in nodes) and (int(entries[6]) in nodes) and (int(entries[7]) in nodes)):
                    # if any of the nodes in this element are NOT in inputarg nodes, add it to notBndrs
                    notBndrs.add(int(entries[1]))
            else:
                print('warning: boundary element of type that is not 2D triangle found')

        f.close()

        foundBndrs = allBndrs.difference(notBndrs)
        self.allBndrs = allBndrs
        self.notBndrs = notBndrs

        return foundBndrs