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

Verifying linear elasticity solver with known benchmark periodic structure and Neumann boundary conditions

0 votes

From an old, wise engineering book I've got the following problem: Elasticity example
There is 2D infinite periodic structure with round holes of radius r with tension applied to it. The relation of maximum stress in the body to the applied one should follow nice 1/x like curve, see the picture. While I'm trying to reproduce this example, I'm getting anything but it.

I use displacement based weak formulation for elasticity with periodic boundary conditions remaping top to bottom and left to right, with exception of corners (0,0), (0,1), (1,0), (1,1).
For problem to be well-posed I've fixed displacement vector in one point (0,0) to be equal (0,0).
Am I right? Is fixing one point enough? I still can rotate the unit square though. Do I need to fix an additional point?

The tension is applied via Neumann boundary conditions with tension applied in the following way:

 g  = Expression(('1.0','0.0'), degree = 2)
 dot(g,v)*ds(2) +  dot(-g,v)*ds(1) 

This is the place I'm most doubted about applying tension correctly. The rest of the code follows (it produces almost constant max stress equal to 0.4).

from __future__ import print_function
import pickle 
from dolfin import *
from dolfin_adjoint import *

n = 64
mesh  = UnitSquareMesh(n, n)
p = Constant(5)        
eps = Constant(1.0e-2) 

class HoleExpression(Expression):
    def eval(self, values, x):
        values[0] = 1.0

        if (x[0]-0.5)**2 + (x[1]-0.5)**2 <  rr**2:
            values[0] = 0
        return values

class PeriodicBoundary(SubDomain):
    def inside(self, x, on_boundary):
        return bool((near(x[0],0) or near(x[1], 0)) and not ((near(x[0], 0) and (near(x[1], 0))) or (near(x[0], 0) and (near(x[1], 1))) or (near(x[0], 1) and (near(x[1], 0))) or (near(x[0], 1) and (near(x[1], 1)))  ))

    def map(self, x, y):
        if near(x[0], 1):
            y[0] = x[0] - 1.
            y[1] = x[1]
        elif near(x[1], 1):
            y[0] = x[0]
            y[1] = x[1] - 1.
        else:
            y[0] = -1000
            y[1] = -1000

cor1 = CompiledSubDomain("near(x[0], 0.0) && near(x[1], 0.0)")

left  =  CompiledSubDomain("near(x[0], side) && on_boundary", side = 0.0)
right =  CompiledSubDomain("near(x[0], side) && on_boundary", side = 1.0)

boundary_parts = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
boundary_parts.set_all(0)
right.mark(boundary_parts, 1)
left.mark(boundary_parts, 2)
ds = Measure("ds")[boundary_parts]

norm = FacetNormal(mesh)
tang = as_vector([norm[1], -norm[0]])

g  = Expression(('1.0','0.0'), degree = 2)# traction 

A = FunctionSpace(mesh, "CG", 1)  
PP = VectorFunctionSpace(mesh, "CG", 1, constrained_domain=PeriodicBoundary())
PN = VectorFunctionSpace(mesh, "CG", 1)

bc1 = DirichletBC(PP, Constant((0.0, 0.0)), cor1, method='pointwise')
bcs = [bc1]

parameters["std_out_all_processes"] = False

def k(a):
    return eps + (1 - eps) * a**p

E, nu = 10.0, 0.3
mu, lmbda = Constant(E/(2*(1 + nu))), Constant(E*nu/((1 + nu)*(1 - 2*nu)))

def sigma(rho, v):
    return 2.0*mu*rho*sym(grad(v)) + lmbda*rho*tr(sym(grad(v)))*Identity(len(v))


def get_u_star(a):
    u = TrialFunction(PP)
    v = TestFunction(PP)
    frm = inner(sigma(k(a), u), sym(grad(v)))*dx
    rhs = dot(g,v)*ds(2) +  dot(-g,v)*ds(1) 
    u = Function(PP)
    problem = LinearVariationalProblem(frm, rhs, u, bcs)
    solver = LinearVariationalSolver(problem)
    solver.parameters["linear_solver"] ="bicgstab"
    solver.solve()
    return u

if __name__ == "__main__":
    _sigma_max = []
    ligament_eff = []
    TTT = TensorFunctionSpace(mesh, "CG", 1)
    for _i in range(10):
        rr = 0.05*_i
        le = 1-2*rr
        ligament_eff.append(le)
        a = interpolate(HoleExpression(degree = 2), A, name="Control") 
        u_star = get_u_star(a)
        sg = sigma(k(a), u_star)
        sigma_TTT = project(sg, TTT)
        _sm = max(sigma_TTT.vector().array()) 
        _sigma_max.append(_sm)
        print(rr, le, _sm)
    pickle.dump([_sigma_max, ligament_eff], open("data.pkl", "w"))
asked May 14, 2017 by gtt FEniCS Novice (630 points)
edited May 14, 2017 by gtt
...