def acoustic_main(theta, plot=False, level=0):
    """
    
    
    theta is the parameter vector. here we have 
    
    
    theta 0 = x1
    theta 1 = x2
    theta 2 = alpha
    theta 3 = beta
    
    
    """

    x1 = theta[0]
    x2 = theta[1]
    alpha = theta[2]**2.0
    beta = theta[3]**2.0

    ML = 2**level
    #c=500
    Nx = 40 * ML
    Ny = 40 * ML
    p0 = dl.Point(0., 0.)
    p1 = dl.Point(3, 2)

    rx = [1., 1.5, 2.]
    ry = [1.99, 1.99, 1.99]

    Nrx = len(rx)
    Nry = len(ry)
    Nr = Nry
    t0 = time.time()

    #beta/alpha=c^2=500**2
    #beta=5000**2
    #alpha=10**2

    #defines the source model
    def source(t, x1, x2):
        delta = dl.Expression(
            'M*exp(-(x[0]-x1)*(x[0]-x1)/(a*a)-(x[1]-x2)*(x[1]-x2)/(a*a))/a*(1-2*pi2*f02*t*t)*exp(-pi2*f02*t*t)',
            pi2=np.pi**2,
            a=1E-1,
            f02=f02,
            M=1E10,
            x1=x1,
            x2=x2,
            t=t,
            degree=1)
        return delta

    B = dl.Constant(beta)
    A = dl.Constant(alpha)

    mesh = dl.RectangleMesh(p0, p1, Nx, Ny)
    V = dl.FunctionSpace(mesh, "Lagrange", 1)
    c2 = beta / alpha
    hmin = mesh.hmin()

    dt = 0.15 * hmin / (c2**0.5)

    # Time variables

    t = 0
    T = 0.003
    Nt = int(np.ceil(T / dt))
    if plot:
        print('value of Nt is ' + str(Nt))
        print('dt is ' + str(dt))

    time_ = np.zeros(Nt)

    U_wave = np.zeros((Nt, Nr))
    # Previous and current solution
    u1 = dl.interpolate(dl.Constant(0.0), V)
    u0 = dl.interpolate(dl.Constant(0.0), V)

    # Variational problem at each time
    u = dl.TrialFunction(V)
    v = dl.TestFunction(V)
    M, K = dl.PETScMatrix(), dl.PETScMatrix()  # Assembles matrices
    M = dl.assemble(A * u * v * dl.dx, tensor=M)
    f02 = 1000**2.0
    K = dl.assemble(dl.inner(B * dl.grad(u), dl.grad(v)) * dl.dx, tensor=K)

    # M=dl.assemble(u*v*dl.dx)
    # K=dl.assemble(dl.inner(dl.grad(u),dl.grad(v))*dl.dx)
    delta = source(t, x1, x2)

    f = dl.interpolate(delta, V)

    # ABC
    class ABCdom(dl.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and (x[1] < 2.0)

    abc_boundaryparts = dl.MeshFunction("size_t", mesh,
                                        mesh.topology().dim() - 1)
    ABCdom().mark(abc_boundaryparts, 1)
    #self.ds = Measure("ds")[abc_boundaryparts]
    ds = dl.Measure('ds', domain=mesh, subdomain_data=abc_boundaryparts)
    weak_d = dl.inner((A * B)**0.5 * u, v) * ds(1)
    class_bc_abc = ABCdom()  # to make copies
    # builds the ABS matrix
    D = dl.assemble(weak_d)

    #saves
    if plot:

        ofile = dl.File('output/ud_.pvd')

    u = dl.Function(V)
    ti = 0
    while t <= T:
        fv = dl.assemble(f * v * dl.dx)
        Kun = K * u1.vector()
        Dun = D * (u1.vector() - u0.vector()) / dt
        b = fv - Kun - Dun
        dl.solve(M, u.vector(), b)
        # dl.plot(u);plt.show()
        # import pdb
        # pdb.set_trace()
        u.vector(
        )[:] = dt**2.0 * u.vector()[:] + 2.0 * u1.vector()[:] - u0.vector()[:]
        #u=dt**2*u+2.0*u1-u0
        u0.assign(u1)
        u1.assign(u)

        for rec in range(Nr):
            U_wave[ti, rec] = u([rx[rec], ry[rec]])
        time_[ti] = t
        t += dt
        ti += 1

        delta = source(t, x1, x2)

        f = dl.interpolate(delta, V)
        # Reduce the range of the solution so that we can see the waves
        if plot:
            ofile << (u, t)

    #print('Total time '+str(round(time.time()-t0,3)))

    return U_wave, time_
Пример #2
0
    def __init__(self, box, sponge, nx, ny):
        """
        Constructor
        
        INPUTS:
        - box = [x_min, x_max, y_min, y_max]: the bounding box of the computational domain
        - nx, ny: number of elements in the horizontal (axial) and vertical (transversal) direction
        """
        self.box = box
        self.mesh = dl.UnitSquareMesh(nx, ny)
        box_sponge = [box[0], box[1] + sponge[0], box[2], box[3] + sponge[1]]

        grade = GradingFunctionLin(coordinate=1, cut_point=[.6, .7], slope=6)
        remap = Remap(box=box_sponge)

        self.mesh.move(grade)
        self.mesh.move(remap)

        class InletBoundary(dl.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and abs(x[0] -
                                           box_sponge[0]) < dl.DOLFIN_EPS

        class SymmetryBoundary(dl.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and abs(x[1] -
                                           box_sponge[2]) < dl.DOLFIN_EPS

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

        class TopBoundary(dl.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and abs(x[1] -
                                           box_sponge[3]) < dl.DOLFIN_EPS

        self.boundary_parts = dl.FacetFunction("size_t", self.mesh)
        self.boundary_parts.set_all(0)

        Gamma_inlet = InletBoundary()
        Gamma_inlet.mark(self.boundary_parts, self.INLET)
        Gamma_axis = SymmetryBoundary()
        Gamma_axis.mark(self.boundary_parts, self.AXIS)
        Gamma_outlet = OutletBoundary()
        Gamma_outlet.mark(self.boundary_parts, self.OUTLET)
        Gamma_top = TopBoundary()
        Gamma_top.mark(self.boundary_parts, self.TOP)

        self.ds = dl.Measure("ds")[self.boundary_parts]

        class PhysicalDomain(dl.SubDomain):
            def inside(self, x, on_boundary):
                return x[0] < box[1] + dl.DOLFIN_EPS and x[
                    1] < box[3] + dl.DOLFIN_EPS

        self.domain_parts = dl.CellFunction("size_t", self.mesh)
        self.domain_parts.set_all(self.SPONGE)

        P_Domain = PhysicalDomain()
        P_Domain.mark(self.domain_parts, self.PHYSICAL)

        self.dx = dl.Measure("dx")[self.domain_parts]

        self.xfun, self.yfun = dl.MeshCoordinates(self.mesh)
        self.x_start = dl.Constant(box[1] + .5 * sponge[0])
        self.x_width = dl.Constant(.5 * sponge[0])
        self.y_start = dl.Constant(box[3] + .5 * sponge[1])
        self.y_width = dl.Constant(.5 * sponge[1])

        self.s_x = dl.Constant(1.) + (
            (dl.Constant(100) / self.x_width) *
            dl.max_value(self.xfun - self.x_start, dl.Constant(0.)))**2
        self.s_y = dl.Constant(1.) + (
            (dl.Constant(100) / self.y_width) *
            dl.max_value(self.yfun - self.y_start, dl.Constant(0.)))**2
        self.sponge_fun = self.s_x * self.s_y
Пример #3
0
#
f1 = [df.XDMFFile(comm, '../data/{}/uf{}.xdmf'.format(data_dir, i)) for i in range(N)]
f2 = df.XDMFFile(comm, '../data/{}/mf.xdmf'.format(data_dir))
f3 = [df.XDMFFile(comm, '../data/{}/p{}.xdmf'.format(data_dir, i)) for i in range(N)]
f4 = df.XDMFFile(comm, '../data/{}/du.xdmf'.format(data_dir))
#
# Initialize 'set_xdmf_parameters' for XDMFFiles to be created
#
[set_xdmf_parameters(f1[i]) for i in range(N)]
set_xdmf_parameters(f2)
[set_xdmf_parameters(f3[i]) for i in range(N)]
set_xdmf_parameters(f4)
#
#
# Define new measures associated with exterior boundaries.
dx = df.Measure("dx")
ds = df.Measure("ds")(subdomain_data=boundaries)
#
# Set start variables for the calculations
sum_fluid_mass = 0
theor_fluid_mass = 0
sum_disp = 0
domain_area = 1.0
#
#
phi = params.p['Parameter']["phi"]
rho = params.p['Parameter']["rho"]
qi = params.p['Parameter']["qi"]
dt = params.p['Parameter']["dt"]
tf = params.p['Parameter']["tf"]
#
Пример #4
0
boundaries.set_all(mark["Internal"])
wall = Noslip()
wall.mark(boundaries, mark["wall"])
left = Left()
left.mark(boundaries, mark["inlet"])
right = Right()
right.mark(boundaries, mark["outlet"])

#read viscosity coefficient from file
mu = Constant(0.001)

#Define HDG element and function space
element_cls = geopart.stokes.incompressible.HDG2()
W = element_cls.function_space(mesh)

ds = dolfin.Measure('ds', domain=mesh, subdomain_data=boundaries)
n = dolfin.FacetNormal(mesh)

#Define boundary condition
U = element_cls.create_solution_variable(W)

p_in = dolfin.Constant(1.0)  # pressure inlet
p_out = dolfin.Constant(0.0)  # pressure outlet
noslip = dolfin.Constant([0.0] * mesh.geometry().dim())  # no-slip wall

#Boundary conditions
gN1 = (-p_out * dolfin.Identity(mesh.geometry().dim())) * n
Neumann_outlet = dg.DGNeumannBC(ds(mark["outlet"]), gN1)
gN2 = (-p_in * dolfin.Identity(mesh.geometry().dim())) * n
Neumann_inlet = dg.DGNeumannBC(ds(mark["inlet"]), gN2)
Dirichlet_wall = dg.DGDirichletBC(ds(mark["wall"]), noslip)
Пример #5
0
extH1 = dlfn.FunctionSpace(subMeshes[extId], P1)
# size of function spaces
m = intHCurl.dim()
nn = intH1.dim()
n = extH1.dim()
# test and trial functions
A = dlfn.TrialFunction(intHCurl)
B = dlfn.TestFunction(intHCurl)
u = dlfn.TrialFunction(intH1)
phi = dlfn.TrialFunction(extH1)
psi = dlfn.TestFunction(extH1)
# measures and normal vectors
dA, dV, normals = dict(), dict(), dict()
for i in subIds:
    dA[i] = dlfn.Measure("ds",
                         subMeshes[i],
                         subdomain_data=facetSubMeshFuns[i])
    dV[i] = dlfn.Measure("dx", subMeshes[i])
    normals[i] = dlfn.FacetNormal(subMeshes[i])
intV = dlfn.assemble(dlfn.Constant(1.0) * dV[intId])
extV = dlfn.assemble(dlfn.Constant(1.0) * dV[extId])
#------------------------------------------------------------------------------#
# solution functions
#------------------------------------------------------------------------------#
sol_A = dlfn.Function(intHCurl)
sol_A0 = dlfn.Function(intHCurl)
sol_phi = dlfn.Function(extH1)
#------------------------------------------------------------------------------#
# weak forms and assembly in interior
#------------------------------------------------------------------------------#
# linear forms in interior domain
def forward(theta,l=0,plot=False):
    # discretization
    Nx=int(28*2.**l)
    Ny=int(28*2.**l)
    
    #domain
    p0=dl.Point(0.,0.)
    p1=dl.Point(3,2)
    # creates mesh and function space
    mesh = dl.RectangleMesh(p0,p1,Nx,Ny)
    V=dl.FunctionSpace(mesh, "Lagrange", 1)
    
    
    #receiver location
    N_rec_x=5
    rx=np.linspace(1,2,N_rec_x)
    ry=2*np.ones(len(rx))
    
    # Source location
    x1=1.5
    x2=1.
    
    cm=4
    c_mult=0.1*cm
    #Obtains C2
    
    #PRIOR=prior.prior_measure(mesh)
    
    
    #C2=PRIOR.sample(exp=True)
    #C2=cm+c_mult*np.exp(theta)
    
    C2=(theta)
    c=dl.Function(V)
    c.vector()[:]=C2[:]
    #dl.plot(c)
    
    A=dl.Constant(1.0)
    
    #PRIOR.plot_prior(C2)
    
    
    
    hmin=mesh.hmin()
    
    
    dt=0.1*hmin/(cm**2.0)
    #%%
    B=10.+c*c
    
    
    Nrx=len(rx)
    Nry=len(ry)
    Nr=Nry
    
    #beta/alpha=c^2=500**2
    #beta=5000**2
    #alpha=10**2
        
    #defines the source model 
    def source(t,x1,x2):
        delta =dl.Expression('M*exp(-(x[0]-x1)*(x[0]-x1)/(a*a)-(x[1]-x2)*(x[1]-x2)/(a*a))/a*(1-2*pi2*f02*t*t)*exp(-pi2*f02*t*t)'
                         ,pi2=np.pi**2,a=6E-2, f02=f02, M=1E5,x1=x1,x2=x2,t=t,degree=1)
        return delta
        
    
    
    # Time variables
    
    t = 0; T =0.6
    Nt=int(np.ceil(T/dt))
    if plot:
        print('value of Nt is '+str(Nt))
        print('dt is '+str(dt))
    
    time_=np.zeros(Nt)
    
    U_wave=np.zeros((Nt,Nr))
    # Previous and current solution
    u1= dl.interpolate(dl.Constant(0.0), V)
    u0= dl.interpolate(dl.Constant(0.0), V)
    
    # Variational problem at each time
    u = dl.TrialFunction(V)
    v = dl.TestFunction(V)
    M, K = dl.PETScMatrix(), dl.PETScMatrix()# Assembles matrices
    M=dl.assemble(A*u*v*dl.dx,tensor=M)
    f02=1000**2.0
    K=dl.assemble(dl.inner(B*dl.grad(u),dl.grad(v))*dl.dx,tensor=K)
    
    # mass_form = A*u*v*dl.dx
    # mass_action_form = dl.action(mass_form, dl.Constant(1))
    
    # M_consistent = dl.assemble(mass_form)
    # print("Consistent mass matrix:\n", np.array_str(M_consistent.array(), precision=3))
    
    # M_lumped = dl.assemble(mass_form)
    # M_lumped.zero()
    # M_lumped.set_diagonal(dl.assemble(mass_action_form))
    # print("Lumped mass matrix:\n", np.array_str(M_lumped.array(), precision=3))
    # M=M_lumped
    
    if plot:
        
        ofile=dl.File('output/ud_.pvd')
    
    # M=dl.assemble(u*v*dl.dx)
    # K=dl.assemble(dl.inner(dl.grad(u),dl.grad(v))*dl.dx)
    delta =source(t,x1,x2)
    
    
    f=dl.interpolate(delta,V)
    # ABC
    class ABCdom(dl.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and (x[1] < 2.0)
    
    abc_boundaryparts = dl.MeshFunction("size_t", mesh, mesh.topology().dim()-1)
    ABCdom().mark(abc_boundaryparts, 1)
    #self.ds = Measure("ds")[abc_boundaryparts]
    ds = dl.Measure('ds', domain=mesh, subdomain_data=abc_boundaryparts)
    weak_d = dl.inner((A*B)**0.5*u,v)*ds(1)
    #class_bc_abc = ABCdom()    # to make copies
    # builds the ABS matrix 
    D = dl.assemble(weak_d)
    
    # Find inverse
    mm=sp.csc_matrix(M.array())
    I=sp.csc_matrix(np.eye(len(M.array())))
    Minv=spsolve(mm, I)
    
    #%%
    
    qoi=0
    
    #saves
    if plot:
        
        ofile=dl.File('output/ud_.pvd')
    
    u=dl.Function(V)
    ti=0
    while t <= T:
        # if ti%100==0:
        #     print('time step '+str(ti)+' out of '+str(Nt))
        fv=dl.assemble(f*v*dl.dx)
        Kun=K*u1.vector()
        Dun=D*(u1.vector()-u0.vector())/dt
        b=fv-Kun-Dun
        #B=dl.Function(V)
        #B.vector()[:]=b[
        u.vector()[:]=Minv@b[:]
        #dl.solve(M, u.vector(), b)
        
        # M_vect = dl.assemble(mass_action_form)
        # u = dl.Function(V)
        # u.vector().set_local(B.vector().get_local()/M_vect.get_local())    
        
        # dl.plot(u);plt.show()
        # import pdb
        # pdb.set_trace()
        u.vector()[:]=dt**2.0*u.vector()[:]+2.0*u1.vector()[:]-u0.vector()[:]
        #u=dt**2*u+2.0*u1-u0
        u0.assign(u1)
        u1.assign(u)
        
        for rec in range(Nr):
            U_wave[ti,rec]=u([rx[rec],ry[rec]])
        time_[ti]=t
        t += dt
        ti+=1
        
        f =source(t,x1,x2)
        
    
        #f=dl.interpolate(delta,V)
        # Reduce the range of the solution so that we can see the waves
        if plot:
            ofile << (u, t)
    qoi1=dl.exp(dl.assemble(c*dl.dx))
    qoi2=dl.assemble(dl.exp(c)*dl.dx)
    qoi3=dl.assemble(B*dl.dx)
    qoi4=6.0+dl.assemble(c*dl.dx)
    qoi5=np.max(c.vector()[:])
    qoi6=10.0-c([1.5,1])
    qoi7=np.exp(c([1.5,1]))
    
    
    # import pdb
    # pdb.set_trace()
    
    qoi=np.array((qoi1,qoi2,qoi3,qoi4,qoi5,qoi6,qoi7))
    
    
    
    
    #np.save('wave.npy',U_wave)
    return U_wave,    qoi
Пример #7
0
def get_measure(mesh, boundaries):
    return df.Measure("ds", domain=mesh, subdomain_data=boundaries)
def gen_bccont_fems(scheme='TH', bccontrol=True, verbose=False,
                    strtomeshfile='', strtophysicalregions='',
                    inflowvel=1., inflowprofile='parabola',
                    movingwallcntrl=False,
                    strtobcsobs=''):
    """
    dictionary for the fem items for a general 2D flow setup

    with
     * inflow/outflow
     * boundary control

    Parameters
    ----------
    scheme : {None, 'CR', 'TH'}
        the finite element scheme to be applied, 'CR' for Crouzieux-Raviart,\
        'TH' for Taylor-Hood, overrides `pdgree`, `vdgree`, defaults to `None`
    bccontrol : boolean, optional
        whether to consider boundary control via penalized Robin \
        defaults to `True`
    movingwallcntrl : boolean, optional
        whether control is via moving boundaries

    Returns
    -------
    femp : a dictionary with the keys:
         * `V`: FEM space of the velocity
         * `Q`: FEM space of the pressure
         * `diribcs`: list of the (Dirichlet) boundary conditions
         * `dbcsinds`: list vortex indices with (Dirichlet) boundary conditions
         * `dbcsvals`: list of values of the (Dirichlet) boundary conditions
         * `dirip`: list of the (Dirichlet) boundary conditions \
                 for the pressure
         * `fv`: right hand side of the momentum equation
         * `fp`: right hand side of the continuity equation
         * `charlen`: characteristic length of the setup
         * `odcoo`: dictionary with the coordinates of the \
                 domain of observation

    """

    # Load mesh
    mesh = dolfin.Mesh(strtomeshfile)

    if scheme == 'CR':
        V = dolfin.VectorFunctionSpace(mesh, "CR", 1)
        Q = dolfin.FunctionSpace(mesh, "DG", 0)
    elif scheme == 'TH':
        V = dolfin.VectorFunctionSpace(mesh, "CG", 2)
        Q = dolfin.FunctionSpace(mesh, "CG", 1)

    boundaries = dolfin.MeshFunction('size_t', mesh, strtophysicalregions)

    with open(strtobcsobs) as f:
        cntbcsdata = json.load(f)

    inflowgeodata = cntbcsdata['inflow']
    inflwpe = inflowgeodata['physical entity']
    inflwin = np.array(inflowgeodata['inward normal'])
    inflwxi = np.array(inflowgeodata['xone'])
    inflwxii = np.array(inflowgeodata['xtwo'])

    leninflwb = np.linalg.norm(inflwxi-inflwxii)

    if inflowprofile == 'block':
        inflwprfl = dolfin.\
            Expression(('cv*no', 'cv*nt'), cv=inflowvel,
                       no=inflwin[0], nt=inflwin[1],
                       element=V.ufl_element())
    elif inflowprofile == 'parabola':
        inflwprfl = InflowParabola(degree=2, lenb=leninflwb, xone=inflwxi,
                                   normalvec=inflwin, inflowvel=inflowvel)
    bcin = dolfin.DirichletBC(V, inflwprfl, boundaries, inflwpe)
    diribcu = [bcin]

    # ## THE WALLS
    wallspel = cntbcsdata['walls']['physical entity']
    gzero = dolfin.Constant((0, 0))
    for wpe in wallspel:
        diribcu.append(dolfin.DirichletBC(V, gzero, boundaries, wpe))
        bcdict = diribcu[-1].get_boundary_values()

    if not bccontrol:  # treat the control boundaries as walls
        try:
            for cntbc in cntbcsdata['controlbcs']:
                diribcu.append(dolfin.DirichletBC(V, gzero, boundaries,
                                                  cntbc['physical entity']))
        except KeyError:
            pass  # no control boundaries

    mvwdbcs = []
    mvwtvs = []
    try:
        for cntbc in cntbcsdata['moving walls']:
            center = np.array(cntbc['geometry']['center'])
            radius = cntbc['geometry']['radius']
            if cntbc['type'] == 'circle':
                omega = 1. if movingwallcntrl else 0.
                rotcyl = RotatingCircle(degree=2, radius=radius,
                                        xcenter=center, omega=omega)
            else:
                raise NotImplementedError()
            mvwdbcs.append(dolfin.DirichletBC(V, rotcyl, boundaries,
                                              cntbc['physical entity']))
    except KeyError:
        pass  # no moving walls defined
    if not movingwallcntrl:
        diribcu.extend(mvwdbcs)  # add the moving walls to the diri bcs
        mvwdbcs = []

    # Create outflow boundary condition for pressure
    # TODO XXX why zero pressure?? is this do-nothing???
    outflwpe = cntbcsdata['outflow']['physical entity']
    g2 = dolfin.Constant(0)
    bc2 = dolfin.DirichletBC(Q, g2, boundaries, outflwpe)

    # Collect boundary conditions
    bcp = [bc2]

    # Create right-hand side function
    fv = dolfin.Constant((0, 0))
    fp = dolfin.Constant(0)

    def initial_conditions(self, V, Q):
        u0 = dolfin.Constant((0, 0))
        p0 = dolfin.Constant(0)
        return u0, p0

    dbcinds, dbcvals = [], []
    for bc in diribcu:
        bcdict = bc.get_boundary_values()
        dbcvals.extend(list(bcdict.values()))
        dbcinds.extend(list(bcdict.keys()))

    mvwbcinds, mvwbcvals = [], []
    for bc in mvwdbcs:
        bcdict = bc.get_boundary_values()
        mvwbcvals.extend(list(bcdict.values()))
        mvwbcinds.extend(list(bcdict.keys()))

    # ## Control boundaries
    bcpes, bcshapefuns, bcds = [], [], []
    if bccontrol:
        for cbc in cntbcsdata['controlbcs']:
            cpe = cbc['physical entity']
            cxi, cxii = np.array(cbc['xone']), np.array(cbc['xtwo'])
            csf = _get_cont_shape_fun2D(xi=cxi, xii=cxii,
                                        element=V.ufl_element())
            bcshapefuns.append(csf)
            bcpes.append(cpe)
            bcds.append(dolfin.Measure("ds", subdomain_data=boundaries)(cpe))

    # ## Lift Drag Computation
    try:
        ldsurfpe = cntbcsdata['lift drag surface']['physical entity']
        liftdragds = dolfin.Measure("ds", subdomain_data=boundaries)(ldsurfpe)
        bclds = dolfin.DirichletBC(V, gzero, boundaries, ldsurfpe)
        bcldsdict = bclds.get_boundary_values()
        ldsbcinds = list(bcldsdict.keys())
    except KeyError:
        liftdragds = None  # no domain specified for lift/drag
        ldsbcinds = None
    try:
        outflwpe = cntbcsdata['outflow']['physical entity']
        outflowds = dolfin.Measure("ds", subdomain_data=boundaries)(outflwpe)
    except KeyError:
        outflowds = None  # no domain specified for outflow

    try:
        odcoo = cntbcsdata['observation-domain-coordinates']
    except KeyError:
        odcoo = None

    gbcfems = dict(V=V,
                   Q=Q,
                   dbcinds=dbcinds,
                   dbcvals=dbcvals,
                   mvwbcinds=mvwbcinds,
                   mvwbcvals=mvwbcvals,
                   mvwtvs=mvwtvs,
                   dirip=bcp,
                   outflowds=outflowds,
                   # contrbcssubdomains=bcsubdoms,
                   liftdragds=liftdragds,
                   ldsbcinds=ldsbcinds,
                   contrbcmeshfunc=boundaries,
                   contrbcspes=bcpes,
                   contrbcsshapefuns=bcshapefuns,
                   cntrbcsds=bcds,
                   odcoo=odcoo,
                   fv=fv,
                   fp=fp,
                   charlen=cntbcsdata['characteristic length'],
                   mesh=mesh)

    return gbcfems
id_subdomain_fix = 1  # Fixed boundary id
id_subdomain_msr = 2  # Loaded boundary id
id_subdomains_dic = 3  # displacement field measurement boundary id

boundary_fix.mark(boundary_markers, id_subdomain_fix)
boundary_msr.mark(boundary_markers, id_subdomain_msr)
boundary_dic.mark(boundary_markers, id_subdomains_dic)

### Integration measures

dx = dolfin.dx(domain=mesh)  # for the whole domain
ds = dolfin.ds(domain=mesh)  # for the entire boundary

ds_msr_T = dolfin.Measure('ds',
                          mesh,
                          subdomain_id=id_subdomain_msr,
                          subdomain_data=boundary_markers)

ds_msr_u = dolfin.Measure('ds',
                          mesh,
                          subdomain_id=id_subdomains_dic,
                          subdomain_data=boundary_markers)

### Finite element function spaces

V = dolfin.VectorFunctionSpace(mesh, 'CG', FINITE_ELEMENT_DEGREE)

# Displacement field
u = Function(V)

### Dirichlet boundary conditions
Пример #10
0
def comp_modeshape(mat_obj, mesh_obj, bc, save_path, neig):
    E = mat_obj.E
    rho = mat_obj.rho
    nu = mat_obj.nu

    Rext = mesh_obj.Rext
    Rint = mesh_obj.Rint

    if mesh_obj.h == 0.0:
        mesh = mesh_obj.create()
    elif mesh_obj.h > 0.0:
        mesh, cell_markers, facet_markers, tag_map = mesh_obj.load()

    cell_markers, facet_markers = define_markers(mesh, Rext, Rint)

    # save marker functions into files readable with Paraview
    df.File(save_path + "Marker_Functions/" +
            "cell_markers.pvd") << cell_markers
    df.File(save_path + "Marker_Functions/" +
            "facet_markers.pvd") << facet_markers

    # define subdomains and cell measurement
    dx = df.Measure("dx", domain=mesh, subdomain_data=cell_markers)

    # Parameters
    # Lame coefficient for constitutive relation
    def mu_func(E, nu):
        return E / 2.0 / (1.0 + nu)

    def lmbda_func(E, nu):
        return E * nu / (1.0 + nu) / (1.0 - 2.0 * nu)

    def E_func(mu, lmbda):
        return mu * (3.0 * lmbda + 2.0 * mu) / (lmbda + mu)

    def nu_func(mu, lmbda):
        return lmbda / (2.0 * (lmbda + mu))

    s_unit = "m"
    t_unit = "ms"
    w_unit = "kg"

    E = E * convert_unit(1.0, "kg", w_unit) / (
        convert_unit(1.0, "m", s_unit) * convert_unit(1.0, "s", t_unit)**2)
    rho = rho * convert_unit(1.0, "kg", w_unit) / (convert_unit(
        1.0, "m", s_unit)**3)

    mu = mu_func(E, nu)
    lmbda = lmbda_func(E, nu)

    # dimention
    dim = mesh.topology().dim()

    # mesh coordinate
    x_coord = mesh.coordinates()

    # strain tensor
    def eps(v):
        return df.sym(df.grad(v))

    # isotropic stress tensor
    def sigma(v):
        dim = v.geometric_dimension()
        return 2.0 * mu * eps(v) + lmbda * df.tr(eps(v)) * df.Identity(dim)

    # Define function space
    V = df.VectorFunctionSpace(mesh, "Lagrange", degree=1)
    du = df.TrialFunction(V)
    tu = df.TestFunction(V)

    # =========================== define eigenvalue problem ===========================
    # eigenvalue problem: [K]\{U\}=\lambda[M]\{U\}
    # eigenfrequency: \lambda=\omega^2
    k_form = df.inner(sigma(du), eps(tu)) * dx
    l_form = df.Constant(1.0) * tu[0] * dx
    m_form = rho * df.dot(du, tu) * dx

    # =========================== Dirichlet Boundary Conditions ===========================

    if dim == 2:
        zero = df.Constant((0.0, 0.0))
    elif dim == 3:
        zero = df.Constant((0.0, 0.0, 0.0))

    # clamped outside
    dbc1 = df.DirichletBC(V, zero, facet_markers, 1)

    # clamped inside
    dbc2 = df.DirichletBC(V, zero, facet_markers, 2)

    # clamped inside and outside
    dbc3 = [dbc1, dbc2]

    def simulation_isotropic_c(save_path, Dbc, neig):
        df.File(save_path + "Marker_Functions/" +
                "cell_markers.pvd") << cell_markers
        df.File(save_path + "Marker_Functions/" +
                "facet_markers.pvd") << facet_markers

        eigensolver, K, M = define_eigen_solver(k_form, l_form, m_form, Dbc,
                                                "c")

        eigensolver.solve(neig)

        # converged eigenvalues and number of iterations
        conv = eigensolver.get_number_converged()
        # no_of_iterations = eigensolver.get_iteration_number() # does not have this function

        if mpi_rank == 0:
            print("\nNumber of converged eigenvalues: {:3d}".format(conv))
            # print('\nNumber of iterations: {:3d}'.format(no_of_iterations))

        freqs = get_mode_shape_and_frequency(
            save_path,
            eigensolver,
            V,
            s_unit,
            t_unit,
            w_unit,
            E,
            nu,
            rho,
            neig,
            K,
            M,
            m_form,
            k_form,
        )
        return freqs

    def simulation_isotropic_ff(save_path, k_form, m_form, neig):
        df.File(save_path + "Marker_Functions/" +
                "cell_markers.pvd") << cell_markers
        df.File(save_path + "Marker_Functions/" +
                "facet_markers.pvd") << facet_markers
        eigensolver, K, M = define_eigen_solver(k_form, l_form, m_form, [],
                                                "ff")
        eigensolver.solve(neig)

        freqs = get_mode_shape_and_frequency(
            save_path,
            eigensolver,
            V,
            s_unit,
            t_unit,
            w_unit,
            E,
            nu,
            rho,
            neig,
            K,
            M,
            m_form,
            k_form,
        )
        return freqs

    if bc == "FF":
        save_path_1 = save_path + "free_free/"
        freqs = simulation_isotropic_ff(save_path_1, k_form, m_form, neig)

    if bc == "CF":
        save_path_1 = save_path + "clamped_free/"
        freqs = simulation_isotropic_c(save_path_1, dbc2, neig)

    if bc == "FC":
        save_path_1 = save_path + "free_clamped/"
        freqs = simulation_isotropic_c(save_path_1, dbc1, neig)

    if bc == "CC":
        save_path_1 = save_path + "clamped_clamped/"
        freqs = simulation_isotropic_c(save_path_1, dbc3, neig)

    return freqs
Пример #11
0
    def variational_forms(self, dt: df.Constant) -> Tuple[Any, Any]:
        """Create the variational forms corresponding to the given
        discretization of the given system of equations.

        *Arguments*
          kn (:py:class:`ufl.Expr` or float)
            The time step

        *Returns*
          (lhs, rhs) (:py:class:`tuple` of :py:class:`ufl.Form`)

        """
        # Extract theta parameter and conductivities
        theta = self._parameters.theta
        Mi = self._intracellular_conductivity
        Me = self._extracellular_conductivity

        # Define variational formulation
        if self._parameters.linear_solver_type == "direct":
            v, u, multiplier = df.TrialFunctions(self._VUR)
            v_test, u_test, multiplier_test = df.TestFunctions(self._VUR)
        else:
            v, u = df.TrialFunctions(self._VUR)
            v_test, u_test = df.TestFunctions(self._VUR)

        Dt_v = (v - self._v_prev)/dt
        Dt_v *= self._chi_cm                # Chi is surface to volume aration. Cm is capacitance
        v_mid = theta*v + (1.0 - theta)*self._v_prev

        # Set-up measure and rhs from stimulus
        dOmega = df.Measure("dx", domain=self._mesh, subdomain_data=self._cell_function)
        dGamma = df.Measure("ds", domain=self._mesh, subdomain_data=self._interface_function)

        # Loop over all domains
        G = Dt_v*v_test*dOmega()
        for key in self._cell_tags - self._restrict_tags:
            G += df.inner(Mi[key]*df.grad(v_mid), df.grad(v_test))*dOmega(key)
            G += df.inner(Mi[key]*df.grad(v_mid), df.grad(u_test))*dOmega(key)

        for key in self._cell_tags:
            G += df.inner(Mi[key]*df.grad(u), df.grad(v_test))*dOmega(key)
            G += df.inner((Mi[key] + Me[key])*df.grad(u), df.grad(u_test))*dOmega(key)
            # If Lagrangian multiplier
            if self._parameters.linear_solver_type == "direct":
                G += (multiplier_test*u + multiplier*u_test)*dOmega(key)

        for key in set(self._interface_tags):
            # Default to 0 if not defined for tag
            G += self._neumann_bc.get(key, df.Constant(0))*u_test*dGamma(key)

        # Interface conditions
        csf_gm = 2
        gm_wm = 1

        csf = 3
        gm = 2
        wm = 1

        csf_gm_interface = df.inner((Me[gm] - Me[csf])*df.grad(u), df.grad(u_test))*dGamma(csf_gm)
        gm_wm_interface = df.inner((Me[gm] - Me[wm])*df.grad(u), df.grad(u_test))*dGamma(gm_wm)

        G += csf_gm_interface
        G += gm_wm_interface

        a, L = df.system(G)
        return a, L
Пример #12
0
def simulate_FEM():

    import dolfin as df
    df.parameters['allow_extrapolation'] = False

    # Define mesh
    mesh = df.Mesh(join(mesh_folder, "{}.xml".format(mesh_name)))
    subdomains = df.MeshFunction("size_t", mesh, join(mesh_folder,
                          "{}_physical_region.xml".format(mesh_name)))
    boundaries = df.MeshFunction("size_t", mesh, join(mesh_folder,
                          "{}_facet_region.xml".format(mesh_name)))

    print("Number of cells in mesh: ", mesh.num_cells())

    np.save(join(out_folder, "mesh_coordinates.npy"), mesh.coordinates())

    sigma_vec = df.Constant(sigma)

    V = df.FunctionSpace(mesh, "CG", 2)
    v = df.TestFunction(V)
    u = df.TrialFunction(V)

    ds = df.Measure("ds", domain=mesh, subdomain_data=boundaries)
    dx = df.Measure("dx", domain=mesh, subdomain_data=subdomains)

    a = df.inner(sigma_vec * df.grad(u), df.grad(v)) * dx(1)

    # This corresponds to Neumann boundary conditions zero, i.e.
    # all outer boundaries are insulating.
    L = df.Constant(0) * v * dx

    # Define Dirichlet boundary conditions outer cylinder boundaries (ground)
    bcs = [df.DirichletBC(V, 0.0, boundaries, 1)]

    for t_idx in range(num_tsteps):

        f_name = join(out_folder, "phi_xz_t_vec_{}.npy".format(t_idx))
        # if os.path.isfile(f_name):
        #     print("skipping ", f_name)
        #     continue

        print("Time step {} of {}".format(t_idx, num_tsteps))
        phi = df.Function(V)
        A = df.assemble(a)
        b = df.assemble(L)

        [bc.apply(A, b) for bc in bcs]

        # Adding point sources from neural simulation
        for s_idx, s_pos in enumerate(source_pos):

            point = df.Point(s_pos[0], s_pos[1], s_pos[2])
            delta = df.PointSource(V, point, imem[s_idx, t_idx])
            delta.apply(b)

        df.solve(A, phi.vector(), b, 'cg', "ilu")

        # df.File(join(out_folder, "phi_t_vec_{}.xml".format(t_idx))) << phi
        # np.save(join(out_folder, "phi_t_vec_{}.npy".format(t_idx)), phi.vector())

        plot_and_save_simulation_results(phi, t_idx)
Пример #13
0
    df.CellType.Type.quadrilateral,
)

'''
2. Define the traction boundary conditions
'''
# here traction force is applied on the middle of the right edge
class TractionBoundary(df.SubDomain):
    def inside(self, x, on_boundary):
        return ((abs(x[1] - LENGTH_Y/2) < LENGTH_Y/NUM_ELEMENTS_Y + df.DOLFIN_EPS) and (abs(x[0] - LENGTH_X ) < df.DOLFIN_EPS*1.5e15))

# Define the traction boundary
sub_domains = df.MeshFunction('size_t', mesh, mesh.topology().dim() - 1)
upper_edge = TractionBoundary()
upper_edge.mark(sub_domains, 6)
dss = df.Measure('ds')(subdomain_data=sub_domains)
f = df.Constant((0, -1. / 4 ))

'''
3. Setup the PDE problem
'''
# PDE problem
pde_problem = PDEProblem(mesh)

# Add input to the PDE problem:
# name = 'density', function = density_function (function is the solution vector here)
density_function_space = df.FunctionSpace(mesh, 'DG', 0)
density_function = df.Function(density_function_space)
pde_problem.add_input('density', density_function)

# Add states to the PDE problem (line 58):
Пример #14
0
    def __init__(
        self,
        time: df.Constant,
        mesh: df.Mesh,
        conductivity: Dict[int, df.Expression],
        conductivity_ratio: Dict[int, df.Expression],
        cell_function: df.MeshFunction,
        cell_tags: CellTags,
        interface_function: df.MeshFunction,
        interface_tags: InterfaceTags,
        parameters: CoupledMonodomainParameters,
        neumann_boundary_condition: Dict[int, df.Expression] = None,
        v_prev: df.Function = None
    ) -> None:
        self._time = time
        self._mesh = mesh
        self._conductivity = conductivity
        self._cell_function = cell_function
        self._cell_tags = cell_tags
        self._interface_function = interface_function
        self._interface_tags = interface_tags
        self._parameters = parameters

        if neumann_boundary_condition is None:
            self._neumann_boundary_condition: Dict[int, df.Expression] = dict()
        else:
            self._neumann_boundary_condition = neumann_boundary_condition

        if not set(conductivity.keys()) == set(conductivity_ratio.keys()):
            raise ValueError("intracellular conductivity and lambda does not have natching keys.")
        self._lambda = conductivity_ratio

        # Function spaces
        self._function_space = df.FunctionSpace(mesh, "CG", 1)

        # Test and trial and previous functions
        self._v_trial = df.TrialFunction(self._function_space)
        self._v_test = df.TestFunction(self._function_space)

        self._v = df.Function(self._function_space)
        if v_prev is None:
            self._v_prev = df.Function(self._function_space)
        else:
            # v_prev is shipped from an odesolver.
            self._v_prev = v_prev

        _cell_tags = set(self._cell_tags)
        _cell_function_values = set(self._cell_function.array())
        if not _cell_tags <= _cell_function_values:
            msg = f"Cell function does not contain {_cell_tags - _cell_function_values}"
            raise ValueError(msg)

        _interface_tags = set(self._interface_tags)
        _interface_function_values = {*set(self._interface_function.array()), None}
        if not _interface_tags <= _interface_function_values:
            msg = f"interface function does not contain {_interface_tags - _interface_function_values}."
            raise ValueError(msg)

        # Crete integration measures -- Interfaces
        self._dGamma = df.Measure("ds", domain=self._mesh, subdomain_data=self._interface_function)

        # Crete integration measures -- Cells
        self._dOmega = df.Measure("dx", domain=self._mesh, subdomain_data=self._cell_function)

        # Create variational forms
        self._timestep = df.Constant(self._parameters.timestep)
        self._lhs, self._rhs = self._variational_forms()

        # Preassemble left-hand side (will be updated if time-step changes)
        self._lhs_matrix = df.assemble(self._lhs)
        self._rhs_vector = df.Vector(mesh.mpi_comm(), self._lhs_matrix.size(0))
        self._lhs_matrix.init_vector(self._rhs_vector, 0)

        self._linear_solver = create_linear_solver(self._lhs_matrix, self._parameters)
Пример #15
0
    def step(self, t0: float, t1: float) -> None:
        r"""Solve on the given time interval (t0, t1).

        *Arguments*
          interval (:py:class:`tuple`)
            The time interval (t0, t1) for the step

        *Invariants*
          Assuming that v\_ is in the correct state for t0, gives
          self.v in correct state at t1.
        """
        # Extract interval and thus time-step
        k_n = df.Constant(t1 - t0)

        # Extract theta parameter and conductivities
        theta = self.parameters["theta"]
        M_i = self._M_i

        # Set time
        t = t0 + theta * (t1 - t0)
        self.time.assign(t)

        # Get physical parameters
        chi = self.parameters["Chi"]
        capacitance = self.parameters["Cm"]
        lam = self.parameters["lambda"]
        lam_frac = df.Constant(lam / (1 + lam))

        # Define variational formulation
        v = df.TrialFunction(self.V)
        w = df.TestFunction(self.V)
        Dt_v_k_n = (v - self.v_) / k_n
        Dt_v_k_n *= chi * capacitance
        v_mid = theta * v + (1.0 - theta) * self.v_

        dz = df.Measure("dx",
                        domain=self._mesh,
                        subdomain_data=self._cell_domains)
        db = df.Measure("ds",
                        domain=self._mesh,
                        subdomain_data=self._facet_domains)
        # dz, rhs = rhs_with_markerwise_field(self._I_s, self._mesh, w)
        cell_tags = map(int, set(
            self._cell_domains.array()))  # np.int64 does not work
        facet_tags = map(int, set(self._facet_domains.array()))

        for key in cell_tags:
            G = Dt_v_k_n * w * dz(key)
            G += lam_frac * df.inner(M_i[key] * df.grad(v_mid),
                                     df.grad(w)) * dz(key)

            if self._I_s is None:
                G -= chi * df.Constant(0) * w * dz(key)
            else:
                G -= chi * self._I_s * w * dz(key)

        # Define variational problem
        a, L = df.system(G)
        pde = df.LinearVariationalProblem(a, L, self.v)

        # Set-up solver
        solver_type = self.parameters["linear_solver_type"]
        solver = df.LinearVariationalSolver(pde)
        solver.solve()
Пример #16
0
def closed_loop(parameters, advanced_parameters, CL_parameters):
    
    
    ####################
    ### Gernal setup ###
    ####################
    setup_general_parameters()
    
    df.PETScOptions.set('ksp_type', 'preonly')
    df.PETScOptions.set('pc_factor_mat_solver_package', 'mumps')
    df.PETScOptions.set("mat_mumps_icntl_7", 6)    
    
    
    ############
    ### MESH ###
    ############
    patient = parameters['patient']
    meshname = parameters['mesh_name']
    mesh = parameters['mesh']
    mesh = patient.mesh
    X = df.SpatialCoordinate(mesh)
    N = df.FacetNormal(mesh)
    
    
    
    # Cycle lenght
    BCL = CL_parameters['BCL']
    t = CL_parameters['t']
    # Time increment
    dt = CL_parameters['dt']
    
    # End-Diastolic volume
    ED_vol = CL_parameters['ED_vol']
    
    #####################################
    # Parameters for Windkessel model ###
    #####################################
    
    # Aorta compliance (reduce)
    Cao = CL_parameters['Cao']
    # Venous compliace
    Cven = CL_parameters['Cven']
    # Dead volume
    Vart0 = CL_parameters['Vart0']
    Vven0 = CL_parameters['Vven0']
    # Aortic resistance
    Rao = CL_parameters['Rao']
    Rven = CL_parameters['Rven']
    # Peripheral resistance (increase)
    Rper = CL_parameters['Rper']
    
    V_ven = CL_parameters['V_ven']
    V_art = CL_parameters['V_art']
    
    # scale geometry to match hemodynamics parameters
    mesh.coordinates()[:] *= CL_parameters['mesh_scaler']
    
    
    ######################
    ### Material model ###
    ######################
    material_model =  advanced_parameters['material_model']
    
    ####################
    ### Active model ###
    ####################
    active_model = advanced_parameters['active_model']
    T_ref = advanced_parameters['T_ref']
    
    # These can be used to adjust the contractility
    gamma_base = parameters['gamma']['gamma_base']
    gamma_mid =  parameters['gamma']['gamma_mid']
    gamma_apical =  parameters['gamma']['gamma_apical']
    gamma_apex = parameters['gamma']['gamma_apex']
    gamma_arr = np.array(gamma_base + gamma_mid + gamma_apical + gamma_apex)
    # gamma_arr = np.ones(17)
    
    
    ##############
    ### OUTPUT ###
    ##############
    dir_results = "results"
    if not os.path.exists(dir_results):
        os.makedirs(dir_results)
    
    disp_file = df.XDMFFile(df.mpi_comm_world(), "{}/displacement.xdmf".format(dir_results))

    pv_data  = {"pressure":[], "volume":[]}
    output = "/".join([dir_results, "output_{}_ed{}.h5".format(meshname, ED_vol)])
    
    
    G = RegionalParameter(patient.sfun)
    G.vector()[:] = gamma_arr
    G_ = df.project(G.get_function(), G.get_ind_space())
    f_gamma = df.XDMFFile(df.mpi_comm_world(), "{}/activation.xdmf".format(dir_results))
    f_gamma.write(G_)
    
    
    
    ########################
    ### Setup Parameters ###
    ########################
    params = setup_application_parameters(material_model)
    params.remove("Material_parameters")
    matparams = df.Parameters("Material_parameters")
    for k, v in  advanced_parameters['mat_params'].iteritems():
        matparams.add(k,v)
    params.add(matparams)
   
   
   
    params["base_bc"] = parameters['BC_type']
    params["base_spring_k"] = advanced_parameters['spring_constant']
    # params["base_bc"] = "fixed"
    params["active_model"] = active_model
    params["T_ref"] = T_ref
    params["gamma_space"] = "regional"
    
    
    ######################
    ### Initialization ###
    ######################
    
    # Solver paramters
    check_patient_attributes(patient)
    solver_parameters, _, _ = make_solver_params(params, patient)
    
    # Cavity volume
    V0 = df.Expression("vol",vol = 0, name = "Vtarget", degree=1)
    solver_parameters["volume"] = V0
    
    # Solver
    solver = LVSolver3Field(solver_parameters, use_snes=True)
    df.set_log_active(True)
    solver.parameters["solve"]["snes_solver"]["report"] =True
    solver.parameters["solve"]["snes_solver"]['maximum_iterations'] = 50
    
    # Surface measure
    ds = df.Measure("exterior_facet", domain = solver.parameters["mesh"],
                 subdomain_data = solver.parameters["facet_function"])
    dsendo = ds(solver.parameters["markers"]["ENDO"][0])
    
    # Set cavity volume
    V0.vol = df.assemble(solver._V_u*dsendo)
    
    print V0.vol
    
    # Initial solve
    solver.solve()
    
    # Save initial state
    w = solver.get_state()
    u, p, pinn = w.split(deepcopy=True)
    U_save = df.Function(u.function_space(), name = "displacement")
    U_save.assign(u)
    disp_file.write(U_save)      
    
    file_format = "a" if os.path.isfile('pv_data_plot.txt') else "w"
    pv_data_plot = open('pv_data_plot.txt', file_format)
    pv_data_plot.write('{},'.format(float(pinn)/1000.0))
    pv_data_plot.write('{}\n'.format(V0.vol))

    pv_data["pressure"].append(float(pinn)/1000.0)
    pv_data["volume"].append(V0.vol)
    
    
    
    # Active contraction
    from force import ca_transient
    V_real = df.FunctionSpace(mesh, "R", 0)
    gamma = solver.parameters["material"].get_gamma()
    
    # times = np.linspace(0,200,200)
    # target_gamma = ca_transient(times)
    # plt.plot(target_gamma)
    # plt.show()
    # exit()g
    
    #######################
    ### Inflation Phase ###
    #######################
    inflate = True
    # Check if inflation allready exist
    if os.path.isfile(output):
        
        with df.HDF5File(df.mpi_comm_world(), output, "r") as h5file:
            if h5file.has_dataset("inflation"):
                h5file.read(solver.get_state(), "inflation")
                print ("\nInflation phase fetched from output file.")
                inflate = False
    
    if inflate:
        print ("\nInflate geometry to volume : {}\n".format(ED_vol))
        initial_step =  int((ED_vol - V0.vol) / 10.0) +1
        control_values, prev_states = iterate("expression", solver, V0, "vol",
                                              ED_vol, continuation=False,
                                              initial_number_of_steps=initial_step,
                                              log_level=10)
    
        # Store outout
        for i, wi in enumerate(prev_states):
            ui, pi, pinni = wi.split(deepcopy=True)
            U_save.assign(ui)
            disp_file.write(U_save)
    
            print ("V = {}".format(control_values[i]))
            print ("P = {}".format(float(pinni)/1000.0))
            
            pv_data_plot.write('{},'.format(float(pinni)/1000.0))
            pv_data_plot.write('{}\n'.format(control_values[i]))
            pv_data["pressure"].append(float(pinni)/1000.0)
            pv_data["volume"].append(control_values[i])
    
        
        with df.HDF5File(df.mpi_comm_world(), output, "w") as h5file:
            h5file.write(solver.get_state(), "inflation")
            
    
    # Store ED solution
    w = solver.get_state()
    u, p, pinn = w.split(deepcopy=True)
    U_save.assign(u)
    disp_file.write(U_save)
    
    pv_data_plot.write('{},'.format(float(pinn)/1000.0))
    pv_data_plot.write('{}\n'.format(ED_vol))
    pv_data["pressure"].append(float(pinn)/1000.0)
    pv_data["volume"].append(ED_vol)
      
    print ("\nInflation succeded! Current pressure: {} kPa\n\n".format(float(pinn)/1000.0))
    
    pv_data_plot.close()
        
    #########################
    ### Closed loop cycle ###
    #########################
    
    while (t < BCL):
    
        w = solver.get_state()
        u, p, pinn = w.split(deepcopy=True)
        
        p_cav = float(pinn)
        V_cav = df.assemble(solver._V_u*dsendo)
        if t + dt > BCL:
            dt = BCL - t
        t = t + dt
    
        target_gamma = ca_transient(t)
    
    
        # Update windkessel model
        Part = 1.0/Cao*(V_art - Vart0);
        Pven = 1.0/Cven*(V_ven - Vven0);
        PLV = float(p_cav);
    
        print ("PLV = {}".format(PLV))
        print ("Part = {}".format(Part))
        # Flux trough aortic valve
        if(PLV <= Part):
             Qao = 0.0;
        else:
             Qao = 1.0/Rao*(PLV - Part);
        
        # Flux trough mitral valve
        if(PLV >= Pven):
            Qmv = 0.0;
        else: 
            Qmv = 1.0/Rven*(Pven - PLV);
        
    
        Qper = 1.0/Rper*(Part - Pven);
    
        V_cav = V_cav + dt*(Qmv - Qao);
        V_art = V_art + dt*(Qao - Qper);
        V_ven = V_ven + dt*(Qper - Qmv);
    
        
    
        # Update cavity volume
        V0.vol = V_cav 
    
    
        # Iterate active contraction
        if t <= 150:
            target_gamma_ = target_gamma * gamma_arr
            _, states = iterate("gamma", solver, target_gamma_, gamma, initial_number_of_steps = 1)
        else:
            solver.solve()
        
    
        # Adapt time step
        if len(states) == 1:
            dt *= 1.7
        else:
            dt *= 0.5
              
        dt = min(dt, 10)
    
        # Store data 
        ui, pi, pinni = solver.get_state().split(deepcopy=True)
        U_save.assign(ui)
        disp_file.write(U_save)
    
        Pcav = float(pinni)/1000.0
        pv_data_plot = open('pv_data_plot.txt', 'a')
        pv_data_plot.write('{},'.format(Pcav))
        pv_data_plot.write('{}\n'.format(V_cav))
        pv_data_plot.close()
        pv_data["pressure"].append(Pcav)
        pv_data["volume"].append(V_cav)
        
        msg = ("\n\nTime:\t{}".format(t) + \
               "\ndt:\t{}".format(dt) +\
               "\ngamma:\t{}".format(target_gamma) +\
               "\nV_cav:\t{}".format(V_cav) + \
               "\nV_art:\t{}".format(V_art) + \
               "\nV_ven:\t{}".format(V_ven) + \
               "\nPart:\t{}".format(Part) + \
               "\nPven:\t{}".format(Pven) + \
               "\nPLV:\t{}".format(Pcav) + \
               "\nQper:\t{}".format(Qper) + \
               "\nQao:\t{}".format(Qao) + \
               "\nQmv:\t{}\n\n".format(Qmv))
        print ((msg))        
    
#==============================================================================
#     fig = plt.figure()
#     ax = fig.gca()
#     ax.plot(pv_data["volume"], pv_data["pressure"])
#     ax.set_ylabel("Pressure (kPa)")
#     ax.set_xlabel("Volume (ml)")
#     
#     
#     fig.savefig("/".join([dir_results, "pv_loop.png"]))
#     plt.show()
#==============================================================================
    return
#import threading
#thread1 = threading.Thread(target = closed_loop)
#thread1.start()

    
Пример #17
0
        def inside(self, x, on_boundary):
            return df.between(x[0]**2 + x[1]**2,
                              (0, 1)) and df.between(x[1], (0, 1))

    quantumDot = QuantumDot()

    domains = df.CellFunction("size_t", mesh)
    domains.set_all(0)
    quantumDot.mark(domains, 1)

    V = df.FunctionSpace(mesh, "CG", 1)

    u = df.TrialFunction(V)
    v = df.TestFunction(V)

    drdz = df.Measure("dx")[domains]
    r = df.Expression("x[0]")

    # Confining potential
    potential = df.Constant(100)

    # Partial derivatives of trial and test functions
    u_r = u.dx(0)
    v_r = v.dx(0)
    u_z = u.dx(1)
    v_z = v.dx(1)

    # Initial guess of ground state is 1 inside dot, 0 outside dot
    psi0 = v * r * drdz(1)
    Psi0 = df.PETScVector()
    df.assemble(psi0, tensor=Psi0)
Пример #18
0
boundary_markers = df.MeshFunction("size_t", mesh, dim=1, value=0)
left_bnd.mark(boundary_markers, 1)
right_bnd.mark(boundary_markers, 2)

# Define boundary conditions
bcL = df.DirichletBC(Uh, df.Constant((0.0, 0.0)), boundary_markers, 1)
ty = -0.01
traction = df.Constant((0.0, ty))

# Trial and test functions
uh = df.TrialFunction(Uh)
vh = df.TestFunction(Uh)

# Define measures
dx = df.dx
ds = df.Measure("ds", domain=mesh, subdomain_data=boundary_markers)

# ~~~ PART I: single scale constitutive law ~~~ #

# Define single scale constitutive parameters
fac_avg = 4.0  # roughly to approximate single scale to mulsticale results
lamb = fac_avg * 1.0
mu = fac_avg * 0.5


# Define single scale constitutive law
def sigma(u):
    return lamb * ufl.nabla_div(u) * df.Identity(2) + 2 * mu * symgrad(u)


# Define single scale variational problem
Пример #19
0
def calculate_fiber_strain(fib, e_circ, e_rad, e_long, strain_markers, mesh,
                           strains):

    import dolfin
    from dolfin import (
        Measure,
        Function,
        TensorFunctionSpace,
        VectorFunctionSpace,
        TrialFunction,
        TestFunction,
        inner,
        assemble_system,
        solve,
    )

    dX = dolfin.Measure("dx", subdomain_data=strain_markers, domain=mesh)

    fiber_space = fib.function_space()
    strain_space = dolfin.VectorFunctionSpace(mesh, "R", 0, dim=3)

    full_strain_space = dolfin.TensorFunctionSpace(mesh, "R", 0)

    fib1 = dolfin.Function(strain_space)
    e_c1 = dolfin.Function(strain_space)
    e_r1 = dolfin.Function(strain_space)
    e_l1 = dolfin.Function(strain_space)

    mean_coords, coords = get_regional_midpoints(strain_markers, mesh)
    # ax = plt.subplot(111, projection='3d')

    region = 1
    fiber_strain = []

    for region in range(1, 18):
        # For each region

        # Find the average unit normal in the fiber direction
        u = dolfin.TrialFunction(strain_space)
        v = TestFunction(strain_space)
        a = inner(u, v) * dX(region)
        L_fib = inner(fib, v) * dX(region)
        A, b = assemble_system(a, L_fib)
        solve(A, fib1.vector(), b)
        fib1_norm = np.linalg.norm(fib1.vector().array())
        # Unit normal
        fib1_arr = fib1.vector().array() / fib1_norm

        # Find the average unit normal in Circumferential direction
        u = TrialFunction(strain_space)
        v = TestFunction(strain_space)
        a = inner(u, v) * dX(region)
        L_c = inner(e_circ, v) * dX(region)
        A, b = assemble_system(a, L_c)
        solve(A, e_c1.vector(), b)
        e_c1_norm = np.linalg.norm(e_c1.vector().array())
        # Unit normal
        e_c1_arr = e_c1.vector().array() / e_c1_norm

        # Find the averag unit normal in Radial direction
        u = TrialFunction(strain_space)
        v = TestFunction(strain_space)
        a = inner(u, v) * dX(region)
        L_r = inner(e_rad, v) * dX(region)
        A, b = assemble_system(a, L_r)
        solve(A, e_r1.vector(), b)
        e_r1_norm = np.linalg.norm(e_r1.vector().array())
        # Unit normal
        e_r1_arr = e_r1.vector().array() / e_r1_norm

        # Find the average unit normal in Longitudinal direction
        u = TrialFunction(strain_space)
        v = TestFunction(strain_space)
        a = inner(u, v) * dX(region)
        L_l = inner(e_long, v) * dX(region)
        A, b = assemble_system(a, L_l)
        solve(A, e_l1.vector(), b)
        e_l1_norm = np.linalg.norm(e_l1.vector().array())
        # Unit normal
        e_l1_arr = e_l1.vector().array() / e_l1_norm

        # ax.plot([mean_coords[region][0], mean_coords[region][0]+e_c1_arr[0]],[mean_coords[region][1], mean_coords[region][1]+e_c1_arr[1]], [mean_coords[region][2],mean_coords[region][2]+e_c1_arr[2]], 'b', label = "circ")
        # ax.plot([mean_coords[region][0],mean_coords[region][0]+e_r1_arr[0]],[mean_coords[region][1], mean_coords[region][1]+e_r1_arr[1]], [mean_coords[region][2],mean_coords[region][2]+e_r1_arr[2]] , 'r',label = "rad")
        # ax.plot([mean_coords[region][0],mean_coords[region][0]+e_l1_arr[0]],[mean_coords[region][1], mean_coords[region][1]+e_l1_arr[1]], [mean_coords[region][2],mean_coords[region][2]+e_l1_arr[2]] , 'g',label = "long")
        # ax.plot([mean_coords[region][0],mean_coords[region][0]+fib1_arr[0]],[mean_coords[region][1], mean_coords[region][1]+fib1_arr[1]], [mean_coords[region][2],mean_coords[region][2]+fib1_arr[2]] , 'y', label = "fib")

        fiber_strain_region = []

        for strain in strains[region]:

            mat = np.array([
                strain[0] * e_c1_arr, strain[1] * e_r1_arr,
                strain[2] * e_l1_arr
            ]).T
            fiber_strain_region.append(np.linalg.norm(np.dot(mat, fib1_arr)))

        fiber_strain.append(fiber_strain_region)

    # for i in range(18):
    #     ax.scatter3D(coords[i][0], coords[i][1], coords[i][2], s = 0.1)

    # plt.show()

    return fiber_strain
Пример #20
0
if args.onlyflow:
    exit("Only flow!")

#calculate normal vector of boundary
n = df.FacetNormal(mesh)

#calculate Peclet number
Pe = df.Constant(1.0)

#define trial and test functions using mesh for B-field (S)
chi = df.TrialFunction(S)
chi_ = df.Function(S)
psi = df.TestFunction(S)

#define surface integral
ds = df.Measure("ds", domain=mesh, subdomain_data=subd)

#variational problem for Brenner field, where the Neumann BCs are included
F_chi = (n[0] * psi * ds(1) + df.inner(df.grad(chi), df.grad(psi)) * df.dx +
         Pe * psi * df.dot(U_, df.grad(chi)) * df.dx + Pe *
         (U_[0] - df.Constant(1.)) * psi * df.dx)

#define left and right hand side
a_chi, L_chi = df.lhs(F_chi), df.rhs(F_chi)

#define problem and solver
problem_chi2 = df.LinearVariationalProblem(a_chi, L_chi, chi_, bcs=[])
solver_chi2 = df.LinearVariationalSolver(problem_chi2)
solver_chi2.parameters["krylov_solver"]["absolute_tolerance"] = 1e-15

#array of Peclet numbers to investigate
Пример #21
0
def numerical_test(user_parameters):
    time_data = []
    time_data_pd = []
    spacetime = []
    lmbda_min_prev = 1e-6
    bifurcated = False
    bifurcation_loads = []
    save_current_bifurcation = False
    bifurc_i = 0
    bifurcation_loads = []

    # Create mesh and define function space
    # Define Dirichlet boundaries
    comm = MPI.comm_world

    default_parameters = getDefaultParameters()
    default_parameters.update(user_parameters)
    # FIXME: Not nice
    parameters = default_parameters
    parameters['code']['script'] = __file__
    # import pdb; pdb.set_trace()

    signature = hashlib.md5(str(parameters).encode('utf-8')).hexdigest()
    outdir = '../output/traction/{}-{}CPU'.format(signature, size)
    Path(outdir).mkdir(parents=True, exist_ok=True)

    log(LogLevel.INFO, 'INFO: Outdir is: ' + outdir)
    BASE_DIR = os.path.dirname(os.path.realpath(__file__))
    print(parameters['geometry'])
    d = {
        'Lx': parameters['geometry']['Lx'],
        'Ly': parameters['geometry']['Ly'],
        'h': parameters['material']['ell'] / parameters['geometry']['n']
    }

    geom_signature = hashlib.md5(str(d).encode('utf-8')).hexdigest()

    # --------------------------------------------------------
    # Mesh creation with gmsh
    Lx = parameters['geometry']['Lx']
    Ly = parameters['geometry']['Ly']
    n = parameters['geometry']['n']
    ell = parameters['material']['ell']
    fname = os.path.join('../meshes', 'strip-{}'.format(geom_signature))

    resolution = max(parameters['geometry']['n'] * Lx / ell, 5 / (Ly * 10))
    resolution = 3

    geom = mshr.Rectangle(dolfin.Point(-Lx / 2., -Ly / 2.),
                          dolfin.Point(Lx / 2., Ly / 2.))
    # mesh = mshr.generate_mesh(geom, n * int(float(Lx / ell)))
    mesh = mshr.generate_mesh(geom, resolution)

    log(
        LogLevel.INFO, 'Number of dofs: {}'.format(
            mesh.num_vertices() * (1 + parameters['general']['dim'])))
    if size == 1:
        meshf = dolfin.File(os.path.join(outdir, "mesh.xml"))
        plot(mesh)
        plt.savefig(os.path.join(outdir, "mesh.pdf"), bbox_inches='tight')

    with open(os.path.join(outdir, 'parameters.yaml'), "w") as f:
        yaml.dump(parameters, f, default_flow_style=False)

    Lx = parameters['geometry']['Lx']
    ell = parameters['material']['ell']
    savelag = 1
    # mf = dolfin.MeshFunction("size_t", mesh, 1, 0)

    # Function Spaces
    V_u = dolfin.VectorFunctionSpace(mesh, "CG", 1)
    V_alpha = dolfin.FunctionSpace(mesh, "CG", 1)
    L2 = dolfin.FunctionSpace(mesh, "DG", 0)
    u = dolfin.Function(V_u, name="Total displacement")
    u.rename('u', 'u')
    alpha = Function(V_alpha)
    alpha_old = dolfin.Function(alpha.function_space())
    alpha.rename('alpha', 'alpha')
    dalpha = TrialFunction(V_alpha)
    alpha_bif = dolfin.Function(V_alpha)
    alpha_bif_old = dolfin.Function(V_alpha)

    state = {'u': u, 'alpha': alpha}
    Z = dolfin.FunctionSpace(
        mesh, dolfin.MixedElement([u.ufl_element(),
                                   alpha.ufl_element()]))
    z = dolfin.Function(Z)
    v, beta = dolfin.split(z)
    left = dolfin.CompiledSubDomain("near(x[0], -Lx/2.)", Lx=Lx)
    right = dolfin.CompiledSubDomain("near(x[0], Lx/2.)", Lx=Lx)
    bottom = dolfin.CompiledSubDomain("near(x[1],-Ly/2.)", Ly=Ly)
    top = dolfin.CompiledSubDomain("near(x[1],Ly/2.)", Ly=Ly)
    left_bottom_pt = dolfin.CompiledSubDomain(
        "near(x[0],-Lx/2.) && near(x[1],-Ly/2.)", Lx=Lx, Ly=Ly)

    mf = dolfin.MeshFunction("size_t", mesh, 1, 0)
    right.mark(mf, 1)
    left.mark(mf, 2)
    bottom.mark(mf, 3)
    ut = dolfin.Expression("t", t=0.0, degree=0)
    bcs_u = [
        dolfin.DirichletBC(V_u.sub(0), dolfin.Constant(0), left),
        dolfin.DirichletBC(V_u.sub(0), ut, right),
        dolfin.DirichletBC(V_u, (0, 0), left_bottom_pt, method="pointwise")
    ]
    bcs_alpha = []

    bcs = {"damage": bcs_alpha, "elastic": bcs_u}

    ds = dolfin.Measure("ds", subdomain_data=mf)
    dx = dolfin.Measure("dx", metadata=parameters['compiler'], domain=mesh)

    ell = parameters['material']['ell']

    # -----------------------
    # Problem definition
    k_res = parameters['material']['k_res']
    a = (1 - alpha)**2. + k_res
    w_1 = parameters['material']['sigma_D0']**2 / parameters['material']['E']
    w = w_1 * alpha
    eps = sym(grad(u))
    eps0t = Expression([['t', 0.], [0., 't']], t=0., degree=0)
    lmbda0 = parameters['material']['E'] * parameters['material']['nu'] / (
        1. - parameters['material']['nu'])**2.
    mu0 = parameters['material']['E'] / 2. / (1.0 +
                                              parameters['material']['nu'])
    nu = parameters['material']['nu']
    sigma0 = lmbda0 * tr(eps) * dolfin.Identity(
        parameters['general']['dim']) + 2 * mu0 * eps
    e1 = Constant((1., 0))
    _sigma = ((1 - alpha)**2. + k_res) * sigma0
    _snn = dolfin.dot(dolfin.dot(_sigma, e1), e1)

    # -------------------

    ell = parameters['material']['ell']
    E = parameters['material']['E']

    def elastic_energy(u, alpha, E=E, nu=nu, eps0t=eps0t, k_res=k_res):
        a = (1 - alpha)**2. + k_res
        eps = sym(grad(u))
        Wt = a*E*nu/(2*(1-nu**2.)) * tr(eps)**2.                                \
            + a*E/(2.*(1+nu))*(inner(eps, eps))
        return Wt * dx

    def dissipated_energy(alpha, w_1=w_1, ell=ell):
        return w_1 * (alpha + ell**2. * inner(grad(alpha), grad(alpha))) * dx

    def total_energy(u,
                     alpha,
                     k_res=k_res,
                     w_1=w_1,
                     E=E,
                     nu=nu,
                     ell=ell,
                     eps0t=eps0t):
        elastic_energy_ = elastic_energy(u,
                                         alpha,
                                         E=E,
                                         nu=nu,
                                         eps0t=eps0t,
                                         k_res=k_res)
        dissipated_energy_ = dissipated_energy(alpha, w_1=w_1, ell=ell)
        return elastic_energy_ + dissipated_energy_

    energy = total_energy(u, alpha)

    # Hessian = derivative(derivative(Wppt*dx, z, TestFunction(Z)), z, TrialFunction(Z))

    def create_output(outdir):
        file_out = dolfin.XDMFFile(os.path.join(outdir, "output.xdmf"))
        file_out.parameters["functions_share_mesh"] = True
        file_out.parameters["flush_output"] = True
        file_postproc = dolfin.XDMFFile(
            os.path.join(outdir, "postprocess.xdmf"))
        file_postproc.parameters["functions_share_mesh"] = True
        file_postproc.parameters["flush_output"] = True
        file_eig = dolfin.XDMFFile(os.path.join(outdir, "perturbations.xdmf"))
        file_eig.parameters["functions_share_mesh"] = True
        file_eig.parameters["flush_output"] = True
        file_bif = dolfin.XDMFFile(os.path.join(outdir, "bifurcation.xdmf"))
        file_bif.parameters["functions_share_mesh"] = True
        file_bif.parameters["flush_output"] = True
        file_bif_postproc = dolfin.XDMFFile(
            os.path.join(outdir, "bifurcation_postproc.xdmf"))
        file_bif_postproc.parameters["functions_share_mesh"] = True
        file_bif_postproc.parameters["flush_output"] = True
        file_ealpha = dolfin.XDMFFile(os.path.join(outdir, "elapha.xdmf"))
        file_ealpha.parameters["functions_share_mesh"] = True
        file_ealpha.parameters["flush_output"] = True

        files = {
            'output': file_out,
            'postproc': file_postproc,
            'eigen': file_eig,
            'bifurcation': file_bif,
            'ealpha': file_ealpha
        }

        return files

    files = create_output(outdir)

    solver = EquilibriumAM(energy, state, bcs, parameters=parameters)
    stability = StabilitySolver(energy, state, bcs, parameters=parameters)
    linesearch = LineSearch(energy, state)

    load_steps = np.linspace(parameters['loading']['load_min'],
                             parameters['loading']['load_max'],
                             parameters['loading']['n_steps'])

    time_data = []
    time_data_pd = []
    spacetime = []
    lmbda_min_prev = 1e-6
    bifurcated = False
    bifurcation_loads = []
    save_current_bifurcation = False
    bifurc_i = 0
    alpha_bif = dolfin.Function(V_alpha)
    alpha_bif_old = dolfin.Function(V_alpha)
    bifurcation_loads = []
    to_remove = []

    perturb = False
    from matplotlib import cm

    log(LogLevel.INFO, '{}'.format(parameters))
    for step, load in enumerate(load_steps):
        plt.clf()
        mineigs = []
        exhaust_modes = []

        log(LogLevel.CRITICAL,
            '====================== STEPPING ==========================')
        log(LogLevel.CRITICAL,
            'CRITICAL: Solving load t = {:.2f}'.format(load))
        alpha_old.assign(alpha)
        ut.t = load
        # (time_data_i, am_iter) = solver.solve(outdir)
        (time_data_i, am_iter) = solver.solve()

        # Second order stability conditions
        (stable, negev) = stability.solve(solver.damage.problem.lb)

        log(LogLevel.CRITICAL,
            'Current state is{}stable'.format(' ' if stable else ' un'))

        mineig = stability.mineig if hasattr(stability, 'mineig') else 0.0
        # log(LogLevel.INFO, 'INFO: lmbda min {}'.format(lmbda_min_prev))
        log(LogLevel.INFO, 'INFO: mineig {:.5e}'.format(mineig))
        Deltav = (mineig - lmbda_min_prev) if hasattr(stability, 'eigs') else 0

        if (mineig + Deltav) * (lmbda_min_prev +
                                dolfin.DOLFIN_EPS) < 0 and not bifurcated:
            bifurcated = True

            # save 3 bif modes
            log(
                LogLevel.INFO,
                'INFO: About to bifurcate load {:.3f} step {}'.format(
                    load, step))
            bifurcation_loads.append(load)
            modes = np.where(stability.eigs < 0)[0]

            bifurc_i += 1

        lmbda_min_prev = mineig if hasattr(stability, 'mineig') else 0.

        # we postpone the update after the stability check
        if stable:
            solver.update()
            log(
                LogLevel.INFO, '    Current state is{}stable'.format(
                    ' ' if stable else ' un'))
        else:
            # Continuation
            iteration = 1
            mineigs.append(stability.mineig)

            while stable == False:
                log(LogLevel.INFO,
                    'Continuation iteration {}'.format(iteration))
                plt.close('all')
                pert = [(_v, _b) for _v, _b in zip(
                    stability.perturbations_v, stability.perturbations_beta)]
                _nmodes = len(pert)
                en_vars = []
                h_opts = []
                hbounds = []
                en_perts = []

                for i, mode in enumerate(pert):
                    h_opt, bounds, enpert, en_var = linesearch.search(
                        {
                            'u': u,
                            'alpha': alpha,
                            'alpha_old': alpha_old
                        }, mode[0], mode[1])
                    h_opts.append(h_opt)
                    en_vars.append(en_var)
                    hbounds.append(bounds)
                    en_perts.append(enpert)

                if rank == 0:
                    # fig = plt.figure(dpi=80, facecolor='w', edgecolor='k')
                    # plt.subplot(1, 4, 1)
                    # plt.set_cmap('binary')
                    # # dolfin.plot(mesh, alpha = 1.)
                    # dolfin.plot(
                    #     project(stability.inactivemarker1, L2), alpha = 1., vmin=0., vmax=1.)
                    # plt.title('derivative zero')
                    # plt.subplot(1, 4, 2)
                    # # dolfin.plot(mesh, alpha = .5)
                    # dolfin.plot(
                    #     project(stability.inactivemarker2, L2), alpha = 1., vmin=0., vmax=1.)
                    # plt.title('ub tolerance')
                    # plt.subplot(1, 4, 3)
                    # # dolfin.plot(mesh, alpha = .5)
                    # dolfin.plot(
                    #     project(stability.inactivemarker3, L2), alpha = 1., vmin=0., vmax=1.)
                    # plt.title('alpha-alpha_old')
                    # plt.subplot(1, 4, 4)
                    # # dolfin.plot(mesh, alpha = .5)
                    # dolfin.plot(
                    #     project(stability.inactivemarker4, L2), alpha = 1., vmin=0., vmax=1.)
                    # plt.title('intersec deriv, ub')
                    # plt.savefig(os.path.join(outdir, "inactivesets-{:.3f}-{:d}.pdf".format(load, iteration)))

                    # plt.set_cmap('hot')

                    fig = plt.figure(dpi=80, facecolor='w', edgecolor='k')

                    for i, mode in enumerate(pert):
                        plt.subplot(2, _nmodes + 1, i + 2)
                        plt.axis('off')
                        plot(mode[1], cmap=cm.ocean)

                        plt.title(
                            'mode {} $h^*$={:.3f}\n $\\lambda_{}$={:.3e} \n $\\Delta E$={:.3e}'
                            .format(i, h_opts[i], i, stability.eigs[i],
                                    en_vars[i]),
                            fontsize=15)

                        # plt.title('mode {}'
                        #     .format(i), fontsize= 15)

                        plt.subplot(2, _nmodes + 1, _nmodes + 2 + 1 + i)
                        plt.axis('off')
                        _pert_beta = mode[1]
                        _pert_v = mode[0]

                        if hbounds[i][0] == hbounds[i][1] == 0:
                            plt.plot(hbounds[i][0], 0)
                        else:
                            hs = np.linspace(hbounds[i][0], hbounds[i][1], 100)
                            z = np.polyfit(
                                np.linspace(hbounds[i][0], hbounds[i][1],
                                            len(en_perts[i])), en_perts[i],
                                parameters['stability']['order'])
                            p = np.poly1d(z)
                            plt.plot(hs, p(hs), c='k')
                            plt.plot(np.linspace(hbounds[i][0], hbounds[i][1],
                                                 len(en_perts[i])),
                                     en_perts[i],
                                     marker='o',
                                     markersize=10,
                                     c='k')
                            # import pdb; pdb.set_trace()
                            plt.plot(hs,
                                     stability.eigs[i] * hs**2,
                                     c='r',
                                     lw=.3)
                            plt.axvline(h_opts[i], lw=.3, c='k')
                            plt.axvline(0, lw=2, c='k')
                        # plt.title('{}'.format(i))
                        plt.tight_layout(h_pad=1.5, pad=1.5)
                    # plt.legend()
                    plt.savefig(
                        os.path.join(
                            outdir,
                            "modes-{:.3f}-{}.pdf".format(load, iteration)))
                    plt.close(fig)
                    plt.clf()
                    log(LogLevel.INFO, 'plotted modes')

                cont_data_pre = compile_continuation_data(state, energy)

                log(LogLevel.INFO,
                    'Estimated energy variation {:.3e}'.format(en_var))

                Ealpha = Function(V_alpha)
                Ealpha.vector()[:] = assemble(stability.inactiveEalpha)[:]
                Ealpha.rename('Ealpha-{}'.format(iteration),
                              'Ealpha-{}'.format(iteration))

                with files['ealpha'] as file:
                    file.write(Ealpha, load)

                save_current_bifurcation = True

                # pick the first of the non exhausted modes-
                non_zero_h = np.where(abs(np.array(h_opts)) > DOLFIN_EPS)[0]
                log(LogLevel.INFO, 'Nonzero h {}'.format(non_zero_h))
                avail_modes = set(non_zero_h) - set(exhaust_modes)

                opt_mode = 0
                # opt_mode = np.argmin(en_vars)
                log(LogLevel.INFO, 'Energy vars {}'.format(en_vars))
                log(
                    LogLevel.INFO, 'Pick bifurcation mode {} out of {}'.format(
                        opt_mode, len(en_vars)))
                # h_opt = min(h_opts[opt_mode],1.e-2)
                h_opt = h_opts[opt_mode]
                perturbation_v = stability.perturbations_v[opt_mode]
                perturbation_beta = stability.perturbations_beta[opt_mode]
                minmode = stability.minmode
                (perturbation_v,
                 perturbation_beta) = minmode.split(deepcopy=True)

                # (perturbation_v, perturbation_beta) = stability.perturbation_v, stability.perturbation_beta

                def energy_1d(h):
                    #return assemble(energy_functional(u + h * perturbation_v, alpha + h * perturbation_beta))
                    u_ = Function(u.function_space())
                    alpha_ = Function(alpha.function_space())
                    u_.vector(
                    )[:] = u.vector()[:] + h * perturbation_v.vector()[:]
                    alpha_.vector()[:] = alpha.vector(
                    )[:] + h * perturbation_beta.vector()[:]
                    u_.vector().vec().ghostUpdate()
                    alpha_.vector().vec().ghostUpdate()
                    return assemble(total_energy(u_, alpha_))

                (hmin, hmax) = linesearch.admissible_interval(
                    alpha, alpha_old, perturbation_beta)
                hs = np.linspace(hmin, hmax, 20)
                energy_vals = np.array([energy_1d(h) for h in hs])
                stability.solve(solver.damage.problem.lb)

                Hzz = assemble(stability.H * minmode * minmode)
                Gz = assemble(stability.J * minmode)
                mineig_z = Hzz / assemble(dot(minmode, minmode) * dx)

                energy_vals_quad = energy_1d(0) + hs * Gz + hs**2 * Hzz / 2
                # h_opt = hs[np.argmin(energy_vals)]
                print('computed h_opt {}'.format(hs[np.argmin(energy_vals)]))
                print("%%%%%%%%% ", mineig_z, "-", mineig)

                if rank == 0:
                    plt.figure()
                    # plt.plot(hs,energy_vals, marker = 'o')
                    plt.plot(hs, energy_vals, marker='o', label="exact")
                    plt.plot(hs,
                             energy_vals_quad,
                             label="quadratic approximation")
                    plt.legend()
                    plt.title("eig {:.4f} vs {:.4f} expected".format(
                        mineig_z, mineig))
                    plt.axvline(h_opt)
                    # import pdb; pdb.set_trace()
                    plt.savefig(
                        os.path.join(outdir,
                                     "energy1d-{:.3f}.pdf".format(load)))

                iteration += 1
                log(LogLevel.CRITICAL, 'Bifurcating')

                save_current_bifurcation = True
                alpha_bif.assign(alpha)
                alpha_bif_old.assign(alpha_old)

                # admissible perturbation
                uval = u.vector()[:] + h_opt * perturbation_v.vector()[:]
                aval = alpha.vector(
                )[:] + h_opt * perturbation_beta.vector()[:]

                u.vector()[:] = uval
                alpha.vector()[:] = aval
                u.vector().vec().ghostUpdate()
                alpha.vector().vec().ghostUpdate()

                log(LogLevel.INFO,
                    'min a+h_opt beta_{} = {}'.format(opt_mode, min(aval)))
                log(LogLevel.INFO,
                    'max a+h_opt beta_{} = {}'.format(opt_mode, max(aval)))
                log(LogLevel.INFO, 'Solving equilibrium from perturbed state')
                (time_data_i, am_iter) = solver.solve(outdir)
                # (time_data_i, am_iter) = solver.solve()
                log(LogLevel.INFO, 'Checking stability of new state')
                (stable, negev) = stability.solve(solver.damage.problem.lb)
                mineigs.append(stability.mineig)

                log(
                    LogLevel.INFO,
                    'Continuation iteration {}, current state is{}stable'.
                    format(iteration, ' ' if stable else ' un'))

                cont_data_post = compile_continuation_data(state, energy)
                DeltaE = (cont_data_post['energy'] - cont_data_pre['energy'])
                relDeltaE = (cont_data_post['energy'] -
                             cont_data_pre['energy']) / cont_data_pre['energy']
                release = DeltaE < 0 and np.abs(
                    DeltaE) > parameters['stability']['cont_rtol']

                log(
                    LogLevel.INFO,
                    'Continuation: post energy {} - pre energy {}'.format(
                        cont_data_post['energy'], cont_data_pre['energy']))
                log(
                    LogLevel.INFO,
                    'Actual absolute energy variation Delta E = {:.7e}'.format(
                        DeltaE))
                log(
                    LogLevel.INFO,
                    'Actual relative energy variation relDelta E = {:.7e}'.
                    format(relDeltaE))
                log(LogLevel.INFO,
                    'Iter {} mineigs = {}'.format(iteration, mineigs))

                if rank == 0:
                    plt.figure()
                    plt.plot(mineigs, marker='o')
                    plt.axhline(0.)
                    plt.savefig(
                        os.path.join(outdir,
                                     "mineigs-{:.3f}.pdf".format(load)))

                # continuation criterion
                if abs(np.diff(mineigs)[-1]) > 1e-10:
                    log(LogLevel.INFO,
                        'Min eig change = {:.3e}'.format(np.diff(mineigs)[-1]))
                    log(LogLevel.INFO, 'Continuing perturbations')
                else:
                    log(LogLevel.INFO,
                        'Min eig change = {:.3e}'.format(np.diff(mineigs)[-1]))
                    log(LogLevel.CRITICAL, 'We are stuck in the matrix')
                    log(LogLevel.WARNING, 'Exploring next mode')
                    exhaust_modes.append(opt_mode)
                    # import pdb; pdb.set_trace()
                    log(LogLevel.WARNING, 'Continuing load program')
                    break
                    #
                # if not release:
                # log(LogLevel.CRITICAL, 'Small nergy release , we are stuck in the matrix')
                # log(LogLevel.CRITICAL, 'No decrease in energy, we are stuck in the matrix')
                # log(LogLevel.WARNING, 'Continuing load program')
                # import pdb; pdb.set_trace()
                # break
                # else:
                #     # warn
                #     log(LogLevel.CRITICAL, 'Found zero increment, we are stuck in the matrix')
                #     log(LogLevel.WARNING, 'Exploring next mode')
                #     exhaust_modes.append(opt_mode)
                #     import pdb; pdb.set_trace()
                #     # log(LogLevel.WARNING, 'Continuing load program')
                #     # break

            solver.update()
            log(LogLevel.INFO,
                'bifurcation loads : {}'.format(bifurcation_loads))
            np.save(os.path.join(outdir, 'bifurcation_loads'),
                    bifurcation_loads,
                    allow_pickle=True,
                    fix_imports=True)

            if save_current_bifurcation:
                time_data_i['h_opt'] = h_opt
                time_data_i['max_h'] = hbounds[opt_mode][1]
                time_data_i['min_h'] = hbounds[opt_mode][0]

                modes = np.where(stability.eigs < 0)[0]
                leneigs = len(modes)
                maxmodes = min(3, leneigs)

                with files['bifurcation'] as file:
                    for n in range(len(pert)):
                        mode = dolfin.project(stability.perturbations_beta[n],
                                              V_alpha)
                        modename = 'beta-%d' % n
                        mode.rename(modename, modename)
                        log(LogLevel.INFO, 'Saved mode {}'.format(modename))
                        file.write(mode, load)

                # with files['file_bif_postproc'] as file:
                # leneigs = len(modes)
                # maxmodes = min(3, leneigs)
                # beta0v = dolfin.project(stability.perturbation_beta, V_alpha)
                # log(LogLevel.DEBUG, 'DEBUG: irrev {}'.format(alpha.vector()-alpha_old.vector()))
                # file.write_checkpoint(beta0v, 'beta0', 0, append = True)
                # file.write_checkpoint(alpha_bif_old, 'alpha-old', 0, append=True)
                # file.write_checkpoint(alpha_bif, 'alpha-bif', 0, append=True)
                # file.write_checkpoint(alpha, 'alpha', 0, append=True)

                np.save(os.path.join(outdir, 'energy_perturbations'),
                        en_perts,
                        allow_pickle=True,
                        fix_imports=True)

                with files['eigen'] as file:
                    _v = dolfin.project(
                        dolfin.Constant(h_opt) * perturbation_v, V_u)
                    _beta = dolfin.project(
                        dolfin.Constant(h_opt) * perturbation_beta, V_alpha)
                    _v.rename('perturbation displacement',
                              'perturbation displacement')
                    _beta.rename('perturbation damage', 'perturbation damage')
                    file.write(_v, load)
                    file.write(_beta, load)

                # save_current_bifurcation = False

        time_data_i["load"] = load
        time_data_i["alpha_max"] = max(alpha.vector()[:])
        time_data_i["elastic_energy"] = dolfin.assemble(
            elastic_energy(u, alpha, E=E, nu=nu, eps0t=eps0t, k_res=k_res))
        time_data_i["dissipated_energy"] = dolfin.assemble(
            (w + w_1 * parameters['material']['ell']**2. *
             inner(grad(alpha), grad(alpha))) * dx)
        time_data_i["stable"] = stability.stable
        time_data_i["# neg ev"] = stability.negev
        time_data_i["eigs"] = stability.eigs if hasattr(stability,
                                                        'eigs') else np.inf
        time_data_i["sigma"] = 1 / Ly * dolfin.assemble(_snn * ds(1))
        # import pdb; pdb.set_trace()

        log(
            LogLevel.INFO,
            "Load/time step {:.4g}: converged in iterations: {:3d}, err_alpha={:.4e}"
            .format(time_data_i["load"], time_data_i["iterations"][0],
                    time_data_i["alpha_error"][0]))

        time_data.append(time_data_i)
        time_data_pd = pd.DataFrame(time_data)

        with files['output'] as file:
            file.write(alpha, load)
            file.write(u, load)

        with files['postproc'] as file:
            file.write_checkpoint(alpha,
                                  "alpha-{}".format(step),
                                  step,
                                  append=True)
            file.write_checkpoint(u, "u-{}".format(step), step, append=True)
            log(LogLevel.INFO,
                'INFO: written postprocessing step {}'.format(step))

        time_data_pd.to_json(os.path.join(outdir, "time_data.json"))

        if rank == 0:
            # plt.clf()
            # if load>1.1:
            # import pdb; pdb.set_trace()
            # plt.plot(time_data_i["alpha_error"],  marker='o')
            # plt.title('error, criterion: {}'.format(parameters['equilibrium']['criterion']))
            # plt.axhline(parameters['equilibrium']['tol'])
            # plt.savefig(os.path.join(outdir, 'errors-{}.pdf'.format(step)))
            # plt.clf()
            # plt.colorbar(plot(alpha))
            # fig = plt.figure()
            # plot(alpha)
            # plt.savefig(os.path.join(outdir, 'alpha.pdf'))
            # log(LogLevel.INFO, "Saved figure: {}".format(os.path.join(outdir, 'alpha.pdf')))
            plt.close('all')

            fig = plt.figure()
            for i, d in enumerate(time_data_pd['eigs']):
                # if d is not (np.inf or np.nan or float('inf')):
                if np.isfinite(d).all():
                    lend = len(d) if isinstance(d, np.ndarray) else 1
                    plt.scatter([(time_data_pd['load'].values)[i]] * lend,
                                d,
                                c=np.where(np.array(d) < 0., 'red', 'black'))

            plt.axhline(0, c='k', lw=2.)
            plt.xlabel('t')
            # [plt.axvline(b) for b in bifurcation_loads]
            # import pdb; pdb.set_trace()
            log(LogLevel.INFO,
                'Spectrum bifurcation loads : {}'.format(bifurcation_loads))
            plt.xticks(list(plt.xticks()[0]) + bifurcation_loads)
            [plt.axvline(bif, lw=2, c='k') for bif in bifurcation_loads]
            plt.savefig(os.path.join(outdir, "spectrum.pdf"),
                        bbox_inches='tight')
        # plt.plot()

    return time_data_pd, outdir
def traction_test(
    ell=0.1,
    degree=1,
    n=3,
    nu=0.0,
    load_min=0,
    load_max=2,
    loads=None,
    nsteps=20,
    Lx=1,
    Ly=0.1,
    outdir="outdir",
    savelag=1,
):
    # constants
    ell = ell
    Lx = Lx
    Ly = Ly
    load_min = load_min
    load_max = load_max
    nsteps = nsteps
    loads=loads

    savelag = 1
    nu = dolfin.Constant(nu)
    ell = dolfin.Constant(ell)
    E0 = dolfin.Constant(1.0)
    sigma_D0 = E0
    n = n


    params =  { 
    'material': {
        "ell":   ell.values()[0],
        "E": E0.values()[0],
        "nu": nu.values()[0],
        "sigma_D0": sigma_D0.values()[0]},
    'geometry': {
        'Lx': Lx,
        'Ly': Ly,
        'n': n,
        },
    'load':{
        'min': load_min,
        'max': load_max,
        'nsteps':  nsteps
    } }

    print(params)
    geom = mshr.Rectangle(dolfin.Point(-Lx/2., -Ly/2.), dolfin.Point(Lx/2., Ly/2.))

    nel = max(int(n * float(Lx / ell)), int(Ly/3.))
    mesh = mshr.generate_mesh(geom, nel)

    left = dolfin.CompiledSubDomain("near(x[0], -Lx/2.)", Lx=Lx)
    right = dolfin.CompiledSubDomain("near(x[0], Lx/2.)", Lx=Lx)
    right_bottom_pt = dolfin.CompiledSubDomain("near(x[1], Lx/2.) && near(x[0],-Ly/2.)", Lx=Lx, Ly=Ly)

    mf = dolfin.MeshFunction("size_t", mesh, 1, 0)
    right.mark(mf, 1)
    left.mark(mf, 2)
    ds = dolfin.Measure("ds", subdomain_data=mf)
    dx = dolfin.Measure("dx", metadata=form_compiler_parameters, domain=mesh)

    V_u = dolfin.VectorFunctionSpace(mesh, "CG", 1)
    V_alpha = dolfin.FunctionSpace(mesh, "CG", 1)
    u = dolfin.Function(V_u, name="Total displacement")
    alpha = dolfin.Function(V_alpha, name="Damage")
    state = [u, alpha]

    Z = dolfin.FunctionSpace(mesh, dolfin.MixedElement([u.ufl_element(),alpha.ufl_element()]))
    z = dolfin.Function(Z)

    v, beta = dolfin.split(z)

    ut = dolfin.Expression("t", t=0.0, degree=0)
    bcs_u = [dolfin.DirichletBC(V_u.sub(0), dolfin.Constant(0), left),
             dolfin.DirichletBC(V_u.sub(0), ut, right),
             dolfin.DirichletBC(V_u, (0, 0), right_bottom_pt, method="pointwise")]

    bcs_alpha = []

    # Problem definition
    model = DamageElasticityModel(state, E0, nu, ell, sigma_D0)
    energy = model.total_energy_density(u, alpha)*dx

    # Alternate minimization solver
    solver = solvers.AlternateMinimizationSolver(
        energy, [u, alpha], [bcs_u, bcs_alpha], parameters = alt_min_parameters)

    rP = model.rP(u, alpha, v, beta)*dx
    rN = model.rN(u, alpha, beta)*dx

    stability = StabilitySolver(mesh, energy,
        [u, alpha], [bcs_u, bcs_alpha], z, rayleigh=[rP, rN], parameters = stability_parameters)

    # Time iterations
    time_data = []
    load_steps = np.linspace(load_min, load_max, nsteps)
    alpha_old = dolfin.Function(V_alpha)

    for it, load in enumerate(load_steps):
        stable = None; negev = 0; mineig = np.inf; iteration = 0
        ut.t = load
        ColorPrint.print_pass('load: {:4f} step {:d} ell {:f}'.format(load, it, ell.values()[0]))
        alpha_old.assign(alpha)
        time_data_i, am_iter = solver.solve()
        solver.update()
        (stable, negev) = stability.solve(alpha_old)

        time_data_i["load"] = load
        time_data_i["stable"] = stable
        time_data_i["# neg ev"] = negev
        time_data_i["elastic_energy"] = dolfin.assemble(
            model.elastic_energy_density(model.eps(u), alpha)*dx)
        time_data_i["dissipated_energy"] = dolfin.assemble(
            model.damage_dissipation_density(alpha)*dx)
        time_data_i["eigs"] = stability.eigs if hasattr(stability, 'eigs') else np.inf
        time_data_i["max alpha"] = np.max(alpha.vector()[:])
        time_data.append(time_data_i)
        time_data_pd = pd.DataFrame(time_data)

        if stable == False:
            break

    return time_data_pd
Пример #23
0
    def __init__(self, mesh, Vh, t_init, t_final, t_1, dt, wind_velocity,
                 gls_stab, Prior):
        self.mesh = mesh
        self.Vh = Vh
        self.t_init = t_init
        self.t_final = t_final
        self.t_1 = t_1
        self.dt = dt
        self.sim_times = np.arange(self.t_init, self.t_final + .5 * self.dt,
                                   self.dt)

        u = dl.TrialFunction(Vh[STATE])
        v = dl.TestFunction(Vh[STATE])

        kappa = dl.Constant(.001)
        dt_expr = dl.Constant(self.dt)

        r_trial = u + dt_expr * (-dl.div(kappa * dl.nabla_grad(u)) +
                                 dl.inner(wind_velocity, dl.nabla_grad(u)))
        r_test = v + dt_expr * (-dl.div(kappa * dl.nabla_grad(v)) +
                                dl.inner(wind_velocity, dl.nabla_grad(v)))

        h = dl.CellSize(mesh)
        vnorm = dl.sqrt(dl.inner(wind_velocity, wind_velocity))
        if gls_stab:
            tau = dl.Min((h * h) / (dl.Constant(2.) * kappa), h / vnorm)
        else:
            tau = dl.Constant(0.)

        self.M = dl.assemble(dl.inner(u, v) * dl.dx)
        self.M_stab = dl.assemble(dl.inner(u, v + tau * r_test) * dl.dx)
        self.Mt_stab = dl.assemble(dl.inner(u + tau * r_trial, v) * dl.dx)
        Nvarf = (dl.inner(kappa * dl.nabla_grad(u), dl.nabla_grad(v)) +
                 dl.inner(wind_velocity, dl.nabla_grad(u)) * v) * dl.dx
        Ntvarf = (dl.inner(kappa * dl.nabla_grad(v), dl.nabla_grad(u)) +
                  dl.inner(wind_velocity, dl.nabla_grad(v)) * u) * dl.dx
        self.N = dl.assemble(Nvarf)
        self.Nt = dl.assemble(Ntvarf)
        stab = dl.assemble(tau * dl.inner(r_trial, r_test) * dl.dx)
        self.L = self.M + dt * self.N + stab
        self.Lt = self.M + dt * self.Nt + stab

        boundaries = dl.FacetFunction("size_t", mesh)
        boundaries.set_all(0)

        class InsideBoundary(dl.SubDomain):
            def inside(self, x, on_boundary):
                x_in = x[0] > dl.DOLFIN_EPS and x[0] < 1 - dl.DOLFIN_EPS
                y_in = x[1] > dl.DOLFIN_EPS and x[1] < 1 - dl.DOLFIN_EPS
                return on_boundary and x_in and y_in

        Gamma_M = InsideBoundary()
        Gamma_M.mark(boundaries, 1)
        ds_marked = dl.Measure("ds", subdomain_data=boundaries)

        self.Q = dl.assemble(self.dt * dl.inner(u, v) * ds_marked(1))

        self.Prior = Prior

        if dlversion() <= (1, 6, 0):
            self.solver = dl.PETScLUSolver()
        else:
            self.solver = dl.PETScLUSolver(self.mesh.mpi_comm())
        self.solver.set_operator(self.L)

        if dlversion() <= (1, 6, 0):
            self.solvert = dl.PETScLUSolver()
        else:
            self.solvert = dl.PETScLUSolver(self.mesh.mpi_comm())
        self.solvert.set_operator(self.Lt)

        self.ud = self.generate_vector(STATE)
        self.noise_variance = 0
        # Part of model public API
        self.gauss_newton_approx = False
Пример #24
0
def run_model(kappa, forcing, function_space, boundary_conditions=None):
    """
    Solve complex valued Helmholtz equation by solving coupled system, one
    for the real part of the solution one for the imaginary part.

    """
    mesh = function_space.mesh()
    kappa_sq = kappa**2

    if boundary_conditions == None:
        bndry_obj = dl.CompiledSubDomain("on_boundary")
        boundary_conditions = [['dirichlet', bndry_obj, [0, 0]]]

    num_bndrys = len(boundary_conditions)
    boundaries = mark_boundaries(mesh, boundary_conditions)
    dirichlet_bcs = collect_dirichlet_boundaries(function_space,
                                                 boundary_conditions,
                                                 boundaries)

    # To express integrals over the boundary parts using ds(i), we must first
    # redefine the measure ds in terms of our boundary markers:
    ds = dl.Measure('ds', domain=mesh, subdomain_data=boundaries)
    #dx = dl.Measure('dx', domain=mesh)
    dx = dl.dx

    (pr, pi) = dl.TrialFunction(function_space)
    (vr, vi) = dl.TestFunction(function_space)

    # real part
    bilinear_form = kappa_sq * (pr * vr - pi * vi) * dx
    bilinear_form += (-dl.inner(dl.nabla_grad(pr), dl.nabla_grad(vr)) +
                      dl.inner(dl.nabla_grad(pi), dl.nabla_grad(vi))) * dx
    # imaginary part
    bilinear_form += kappa_sq * (pr * vi + pi * vr) * dx
    bilinear_form += -(dl.inner(dl.nabla_grad(pr), dl.nabla_grad(vi)) +
                       dl.inner(dl.nabla_grad(pi), dl.nabla_grad(vr))) * dx

    for ii in range(num_bndrys):
        if (boundary_conditions[ii][0] == 'robin'):
            alpha_real, alpha_imag = boundary_conditions[ii][3]
            bilinear_form -= alpha_real * (pr * vr - pi * vi) * ds(ii)
            bilinear_form -= alpha_imag * (pr * vi + pi * vr) * ds(ii)

    forcing_real, forcing_imag = forcing
    rhs = (forcing_real * vr + forcing_real * vi + forcing_imag * vr -
           forcing_imag * vi) * dx

    for ii in range(num_bndrys):
        if ((boundary_conditions[ii][0] == 'robin')
                or (boundary_conditions[ii][0] == 'neumann')):
            beta_real, beta_imag = boundary_conditions[ii][2]
            # real part of robin boundary conditions
            rhs += (beta_real * vr - beta_imag * vi) * ds(ii)
            # imag part of robin boundary conditions
            rhs += (beta_real * vi + beta_imag * vr) * ds(ii)

    # compute solution
    p = dl.Function(function_space)
    #solve(a == L, p)
    dl.solve(bilinear_form == rhs, p, bcs=dirichlet_bcs)

    return p
Пример #25
0
    import dolfin
    import ufl
    import numpy as np
    import matplotlib.pyplot as plt
    dolfin.parameters["use_petsc_signal_handler"] = True
    dolfin.parameters["form_compiler"]["cpp_optimize"] = True
    dolfin.parameters["form_compiler"]["representation"] = "uflacs"

    n = 100
    mesh = dolfin.UnitSquareMesh(n, n)
    V = dolfin.FunctionSpace(mesh, 'CG', 1)
    u = dolfin.Function(V)
    ut = dolfin.TestFunction(V)
    v = dolfin.TrialFunction(V)
    dx = dolfin.Measure("dx", domain=mesh)
    bc = dolfin.DirichletBC(V, 0, "on_boundary")
    a_k = ufl.dot(ufl.grad(ut), ufl.grad(v)) * dx
    a_m = ut * v * dx
    eig_solver = EigenSolver(a_k, u, a_m, [bc])
    #eig_solver = EigenSolver(a_k, u, bcs=[bc])
    plt.savefig("operators.png")
    ncv, it = eig_solver.solve(10)
    eigs = eig_solver.get_eigenvalues(ncv)
    plt.figure()
    plt.plot(eigs, 'o')
    plt.title("Eigenvalues")
    plt.savefig("eigenvalues.png")

    eig_solver.save_eigenvectors(ncv)
    for i in range(ncv):
Пример #26
0
    def solve_nonlinear(self, inputs, outputs):
        pde_problem = self.options['pde_problem']
        state_name = self.options['state_name']
        problem_type = self.options['problem_type']
        visualization = self.options['visualization']
        state_function = pde_problem.states_dict[state_name]['function']
        for argument_name, argument_function in iteritems(self.argument_functions_dict):
            density_func = argument_function
        mesh = state_function.function_space().mesh()
        sub_domains = df.MeshFunction('size_t', mesh, mesh.topology().dim() - 1)
        upper_edge = TractionBoundary()
        upper_edge.mark(sub_domains, 6)
        dss = df.Measure('ds')(subdomain_data=sub_domains)
        tractionBC = dss(6)

        
        self.itr = self.itr + 1

        state_function = pde_problem.states_dict[state_name]['function']
        residual_form = get_residual_form(
            state_function, 
            df.TestFunction(state_function.function_space()), 
            density_func,
            density_func.function_space(),
            tractionBC,
            # df.Constant((0.0, -9.e-1))
            df.Constant((0.0, -9.e-1)),
            int(self.itr)
            )      

        self._set_values(inputs, outputs)

        self.derivative_form = df.derivative(residual_form, state_function)
        df.set_log_level(df.LogLevel.ERROR)
        df.set_log_active(True)
        # df.solve(residual_form==0, state_function, bcs=pde_problem.bcs_list, J=self.derivative_form)
        if problem_type == 'linear_problem':
            df.solve(residual_form==0, state_function, bcs=pde_problem.bcs_list, J=self.derivative_form,
                solver_parameters={"newton_solver":{"maximum_iterations":60, "error_on_nonconvergence":False}})
        elif problem_type == 'nonlinear_problem':
            problem = df.NonlinearVariationalProblem(residual_form, state_function, pde_problem.bcs_list, self.derivative_form)
            solver  = df.NonlinearVariationalSolver(problem)
            solver.parameters['nonlinear_solver_']='snes' 
            solver.parameters["snes_solver"]["line_search"] = 'bt' 
            solver.parameters["snes_solver"]["linear_solver_"]='mumps' # "cg" "gmres"
            solver.parameters["snes_solver"]["maximum_iterations"]=500
            solver.parameters["snes_solver"]["relative_tolerance"]=5e-13
            solver.parameters["snes_solver"]["absolute_tolerance"]=5e-13

            # solver.parameters["snes_solver"]["linear_solver_"]["maximum_iterations"]=1000
            solver.parameters["snes_solver"]["error_on_nonconvergence"] = False
            solver.solve()

        elif problem_type == 'nonlinear_problem_load_stepping':
            num_steps = 3
            state_function.vector().set_local(np.zeros((state_function.function_space().dim())))
            for i in range(num_steps):
                v = df.TestFunction(state_function.function_space())
                if i < (num_steps-1):
                    residual_form = get_residual_form(
                        state_function, 
                        v, 
                        density_func,
                        density_func.function_space(),
                        tractionBC,
                        # df.Constant((0.0, -9.e-1))
                        df.Constant((0.0, -9.e-1/num_steps*(i+1))),
                        int(self.itr)
                        ) 
                else:
                    residual_form = get_residual_form(
                        state_function, 
                        v, 
                        density_func,
                        density_func.function_space(),
                        tractionBC,
                        # df.Constant((0.0, -9.e-1))
                        df.Constant((0.0, -9.e-1/num_steps*(i+1))),
                        int(self.itr)
                        ) 
                problem = df.NonlinearVariationalProblem(residual_form, state_function, pde_problem.bcs_list, self.derivative_form)
                solver  = df.NonlinearVariationalSolver(problem)
                solver.parameters['nonlinear_solver_']='snes' 
                solver.parameters["snes_solver"]["line_search"] = 'bt' 
                solver.parameters["snes_solver"]["linear_solver_"]='mumps' # "cg" "gmres"
                solver.parameters["snes_solver"]["maximum_iterations"]=500
                solver.parameters["snes_solver"]["relative_tolerance"]=1e-15
                solver.parameters["snes_solver"]["absolute_tolerance"]=1e-15

                # solver.parameters["snes_solver"]["linear_solver_"]["maximum_iterations"]=1000
                solver.parameters["snes_solver"]["error_on_nonconvergence"] = False
                solver.solve()

        # option to store the visualization results
        if visualization == 'True':
            for argument_name, argument_function in iteritems(self.argument_functions_dict):
                df.File('solutions_iterations_3d/{}_{}.pvd'.format(argument_name, self.itr)) << argument_function

        self.L = -residual_form
        self.itr = self.itr+1
        outputs[state_name] = state_function.vector().get_local()
Пример #27
0
    pde.solver = dl.PETScKrylovSolver(mesh.mpi_comm(), "cg", amg_method())
    pde.solver_fwd_inc = dl.PETScKrylovSolver(mesh.mpi_comm(), "cg",
                                              amg_method())
    pde.solver_adj_inc = dl.PETScKrylovSolver(mesh.mpi_comm(), "cg",
                                              amg_method())
pde.solver.parameters["relative_tolerance"] = 1e-15
pde.solver.parameters["absolute_tolerance"] = 1e-20
pde.solver_fwd_inc.parameters = pde.solver.parameters
pde.solver_adj_inc.parameters = pde.solver.parameters

# define the QOI
GC = GammaBottom()
marker = dl.FacetFunction("size_t", mesh)
marker.set_all(0)
GC.mark(marker, 1)
dss = dl.Measure("ds", subdomain_data=marker)
qoi = FluxQOI(Vh, dss(1))

# qoi = QoI(Vh)

# define the misfit
n1d = 7
ntargets = n1d**2
targets = np.zeros((ntargets, 2))
x1d = np.array(range(n1d)) / float(n1d + 1) + 1 / float(n1d + 1)
for i in range(n1d):
    for j in range(n1d):
        targets[i * n1d + j, 0] = x1d[i]
        targets[i * n1d + j, 1] = x1d[j]
if rank == 0:
    print("Number of observation points: {0}".format(ntargets))
Пример #28
0
    def solve_linear(self, d_outputs, d_residuals, mode):
        linear_solver_ = self.options['linear_solver_']
        pde_problem = self.options['pde_problem']
        state_name = self.options['state_name']

        state_function = pde_problem.states_dict[state_name]['function']
        for argument_name, argument_function in iteritems(self.argument_functions_dict):
            density_func = argument_function
        mesh = state_function.function_space().mesh()
        sub_domains = df.MeshFunction('size_t', mesh, mesh.topology().dim() - 1)
        upper_edge = TractionBoundary()
        upper_edge.mark(sub_domains, 6)
        dss = df.Measure('ds')(subdomain_data=sub_domains)
        tractionBC = dss(6)

        residual_form = get_residual_form(
            state_function, 
            df.TestFunction(state_function.function_space()), 
            density_func,
            density_func.function_space(),
            tractionBC,
            # df.Constant((0.0, -9.e-1))
            df.Constant((0.0, -9.e-1)),
            int(self.itr)
            )
            
        A, _ = df.assemble_system(self.derivative_form, - residual_form, pde_problem.bcs_list)

        if linear_solver_=='fenics_direct':

            rhs_ = df.Function(state_function.function_space())
            dR = df.Function(state_function.function_space())

            rhs_.vector().set_local(d_outputs[state_name])

            for bc in pde_problem.bcs_list:
                bc.apply(A)
            Am = df.as_backend_type(A).mat()
            ATm = Am.transpose()
            AT =  df.PETScMatrix(ATm)

            df.solve(AT,dR.vector(),rhs_.vector()) 
            d_residuals[state_name] =  dR.vector().get_local()

        elif linear_solver_=='scipy_splu':
            for bc in pde_problem.bcs_list:
                bc.apply(A)
            Am = df.as_backend_type(A).mat()
            ATm = Am.transpose()
            ATm_csr = csr_matrix(ATm.getValuesCSR()[::-1], shape=Am.size)
            lu = splu(ATm_csr.tocsc())
            d_residuals[state_name] = lu.solve(d_outputs[state_name],trans='T')


        elif linear_solver_=='fenics_Krylov':

            rhs_ = df.Function(state_function.function_space())
            dR = df.Function(state_function.function_space())

            rhs_.vector().set_local(d_outputs[state_name])

            for bc in pde_problem.bcs_list:
                bc.apply(A)
            Am = df.as_backend_type(A).mat()
            ATm = Am.transpose()
            AT =  df.PETScMatrix(ATm)

            solver = df.KrylovSolver('gmres', 'ilu')
            prm = solver.parameters          
            prm["maximum_iterations"]=1000000
            prm["divergence_limit"] = 1e2
            solver.solve(AT,dR.vector(),rhs_.vector())

            d_residuals[state_name] =  dR.vector().get_local()

        elif linear_solver_=='petsc_gmres_ilu':
            ksp = PETSc.KSP().create() 
            ksp.setType(PETSc.KSP.Type.GMRES)
            ksp.setTolerances(rtol=5e-11)

            for bc in pde_problem.bcs_list:
                bc.apply(A)
            Am = df.as_backend_type(A).mat()

            ksp.setOperators(Am)

            ksp.setFromOptions()
            pc = ksp.getPC()
            pc.setType("ilu")

            size = state_function.function_space().dim()

            dR = PETSc.Vec().create()
            dR.setSizes(size)
            dR.setType('seq')
            dR.setValues(range(size), d_residuals[state_name])
            dR.setUp()

            du = PETSc.Vec().create()
            du.setSizes(size)
            du.setType('seq')
            du.setValues(range(size), d_outputs[state_name])
            du.setUp()

            if mode == 'fwd':
                ksp.solve(dR,du)
                d_outputs[state_name] = du.getValues(range(size))
            else:
                ksp.solveTranspose(du,dR)
                d_residuals[state_name] = dR.getValues(range(size))
def numerical_test(
    user_parameters,
    ell=0.05,
    nu=0.,
):
    time_data = []
    time_data_pd = []
    spacetime = []
    lmbda_min_prev = 1e-6
    bifurcated = False
    bifurcation_loads = []
    save_current_bifurcation = False
    bifurc_i = 0
    bifurcation_loads = []

    # Create mesh and define function space
    geometry_parameters = {'Lx': 1., 'Ly': .1, 'n': 5}

    # Define Dirichlet boundaries
    outdir = '../test/output/test_secondorderevo'
    Path(outdir).mkdir(parents=True, exist_ok=True)

    with open('../parameters/form_compiler.yml') as f:
        form_compiler_parameters = yaml.load(f, Loader=yaml.FullLoader)

    with open('../parameters/solvers_default.yml') as f:
        solver_parameters = yaml.load(f, Loader=yaml.FullLoader)

    with open('../parameters/model1d.yaml') as f:
        material_parameters = yaml.load(f, Loader=yaml.FullLoader)['material']

    with open('../parameters/loading.yaml') as f:
        loading_parameters = yaml.load(f, Loader=yaml.FullLoader)['loading']

    with open('../parameters/stability.yaml') as f:
        stability_parameters = yaml.load(f,
                                         Loader=yaml.FullLoader)['stability']

    Path(outdir).mkdir(parents=True, exist_ok=True)

    print('Outdir is: ' + outdir)

    default_parameters = {
        'code': {
            **code_parameters
        },
        'compiler': {
            **form_compiler_parameters
        },
        'geometry': {
            **geometry_parameters
        },
        'loading': {
            **loading_parameters
        },
        'material': {
            **material_parameters
        },
        'solver': {
            **solver_parameters
        },
        'stability': {
            **stability_parameters
        },
    }

    default_parameters.update(user_parameters)
    # FIXME: Not nice
    parameters = default_parameters

    with open(os.path.join(outdir, 'parameters.yaml'), "w") as f:
        yaml.dump(parameters, f, default_flow_style=False)

    Lx = parameters['geometry']['Lx']
    Ly = parameters['geometry']['Ly']
    ell = parameters['material']['ell']
    comm = MPI.comm_world
    geom = mshr.Rectangle(dolfin.Point(-Lx / 2., -Ly / 2.),
                          dolfin.Point(Lx / 2., Ly / 2.))
    # import pdb; pdb.set_trace()
    # resolution = max(geometry_parameters['n'] * Lx / ell, 1/(Ly*10))
    resolution = max(geometry_parameters['n'] * Lx / ell, 5 / (Ly * 10))
    resolution = 50
    mesh = mshr.generate_mesh(geom, resolution)
    meshf = dolfin.File(os.path.join(outdir, "mesh.xml"))
    meshf << mesh
    plot(mesh)
    plt.savefig(os.path.join(outdir, "mesh.pdf"), bbox_inches='tight')

    savelag = 1
    left = dolfin.CompiledSubDomain("near(x[0], -Lx/2.)", Lx=Lx)
    right = dolfin.CompiledSubDomain("near(x[0], Lx/2.)", Lx=Lx)
    left_bottom_pt = dolfin.CompiledSubDomain(
        "near(x[0],-Lx/2.) && near(x[1],-Ly/2.)", Lx=Lx, Ly=Ly)

    mf = dolfin.MeshFunction("size_t", mesh, 1, 0)
    right.mark(mf, 1)
    left.mark(mf, 2)

    ds = dolfin.Measure("ds", subdomain_data=mf)
    dx = dolfin.Measure("dx", metadata=form_compiler_parameters, domain=mesh)

    # Function Spaces
    V_u = dolfin.VectorFunctionSpace(mesh, "CG", 1)
    V_alpha = dolfin.FunctionSpace(mesh, "CG", 1)
    u = dolfin.Function(V_u, name="Total displacement")
    alpha = Function(V_alpha)
    dalpha = TrialFunction(V_alpha)
    alpha_bif = dolfin.Function(V_alpha)
    alpha_bif_old = dolfin.Function(V_alpha)

    state = {'u': u, 'alpha': alpha}
    Z = dolfin.FunctionSpace(
        mesh, dolfin.MixedElement([u.ufl_element(),
                                   alpha.ufl_element()]))
    z = dolfin.Function(Z)
    v, beta = dolfin.split(z)

    ut = dolfin.Expression("t", t=0.0, degree=0)
    bcs_u = [
        dolfin.DirichletBC(V_u.sub(0), dolfin.Constant(0), left),
        dolfin.DirichletBC(V_u.sub(0), ut, right),
        dolfin.DirichletBC(V_u, (0, 0), left_bottom_pt, method="pointwise")
    ]

    bcs_alpha_l = DirichletBC(V_alpha, Constant(0.0), left)
    bcs_alpha_r = DirichletBC(V_alpha, Constant(0.0), right)
    # bcs_alpha =[bcs_alpha_l, bcs_alpha_r]
    bcs_alpha = []

    bcs = {"damage": bcs_alpha, "elastic": bcs_u}

    # import pdb; pdb.set_trace()

    ell = parameters['material']['ell']

    # Problem definition
    # Problem definition
    k_res = parameters['material']['k_res']
    a = (1 - alpha)**2. + k_res
    w_1 = parameters['material']['sigma_D0']**2 / parameters['material']['E']
    w = w_1 * alpha
    eps = sym(grad(u))
    lmbda0 = parameters['material']['E'] * parameters['material']['nu'] / (
        1. - parameters['material']['nu'])**2.
    mu0 = parameters['material']['E'] / 2. / (1.0 +
                                              parameters['material']['nu'])
    Wu = 1. / 2. * lmbda0 * tr(eps)**2. + mu0 * inner(eps, eps)

    energy = a * Wu * dx + w_1 *( alpha + \
            parameters['material']['ell']** 2.*inner(grad(alpha), grad(alpha)))*dx

    eps_ = variable(eps)
    sigma = diff(a * Wu, eps_)
    e1 = dolfin.Constant([1, 0])

    file_out = dolfin.XDMFFile(os.path.join(outdir, "output.xdmf"))
    file_out.parameters["functions_share_mesh"] = True
    file_out.parameters["flush_output"] = True
    file_postproc = dolfin.XDMFFile(
        os.path.join(outdir, "output_postproc.xdmf"))
    file_postproc.parameters["functions_share_mesh"] = True
    file_postproc.parameters["flush_output"] = True
    file_eig = dolfin.XDMFFile(os.path.join(outdir, "modes.xdmf"))
    file_eig.parameters["functions_share_mesh"] = True
    file_eig.parameters["flush_output"] = True
    file_bif = dolfin.XDMFFile(os.path.join(outdir, "bifurcation.xdmf"))
    file_bif.parameters["functions_share_mesh"] = True
    file_bif.parameters["flush_output"] = True
    file_bif_postproc = dolfin.XDMFFile(
        os.path.join(outdir, "bifurcation_postproc.xdmf"))
    file_bif_postproc.parameters["functions_share_mesh"] = True
    file_bif_postproc.parameters["flush_output"] = True

    solver = EquilibriumAM(energy, state, bcs, parameters=parameters['solver'])
    stability = StabilitySolver(energy,
                                state,
                                bcs,
                                parameters=parameters['stability'])
    linesearch = LineSearch(energy, state)

    xs = np.linspace(-parameters['geometry']['Lx'] / 2.,
                     parameters['geometry']['Lx'] / 2, 50)

    load_steps = np.linspace(parameters['loading']['load_min'],
                             parameters['loading']['load_max'],
                             parameters['loading']['n_steps'])
    log(LogLevel.INFO, '====================== EVO ==========================')
    log(LogLevel.INFO, '{}'.format(parameters))

    for it, load in enumerate(load_steps):
        log(LogLevel.CRITICAL,
            '====================== STEPPING ==========================')
        log(LogLevel.CRITICAL,
            'CRITICAL: Solving load t = {:.2f}'.format(load))
        ut.t = load
        (time_data_i, am_iter) = solver.solve()

        # Second order stability conditions

        (stable, negev) = stability.solve(solver.damage.problem.lb)
        log(LogLevel.CRITICAL,
            'Current state is{}stable'.format(' ' if stable else ' un'))

        # we postpone the update after the stability check
        solver.update()

        mineig = stability.mineig if hasattr(stability, 'mineig') else 0.0
        log(LogLevel.INFO, 'INFO: lmbda min {}'.format(lmbda_min_prev))
        log(LogLevel.INFO, 'INFO: mineig {}'.format(mineig))
        Deltav = (mineig - lmbda_min_prev) if hasattr(stability, 'eigs') else 0

        if (mineig + Deltav) * (lmbda_min_prev +
                                dolfin.DOLFIN_EPS) < 0 and not bifurcated:
            bifurcated = True

            # save 3 bif modes
            print('About to bifurcate load ', load, 'step', it)
            bifurcation_loads.append(load)
            modes = np.where(stability.eigs < 0)[0]

            with dolfin.XDMFFile(os.path.join(outdir,
                                              "postproc.xdmf")) as file:
                leneigs = len(modes)
                maxmodes = min(3, leneigs)
                for n in range(maxmodes):
                    mode = dolfin.project(stability.linsearch[n]['beta_n'],
                                          V_alpha)
                    modename = 'beta-%d' % n
                    print(modename)
                    file.write_checkpoint(mode, modename, 0, append=True)

            bifurc_i += 1

        lmbda_min_prev = mineig if hasattr(stability, 'mineig') else 0.

        time_data_i["load"] = load
        time_data_i["alpha_max"] = max(alpha.vector()[:])
        time_data_i["elastic_energy"] = dolfin.assemble(
            1. / 2. * material_parameters['E'] * a * eps**2. * dx)
        time_data_i["dissipated_energy"] = dolfin.assemble(
            (w + w_1 * material_parameters['ell']**2. *
             inner(grad(alpha), grad(alpha))) * dx)
        time_data_i["stable"] = stability.stable
        time_data_i["# neg ev"] = stability.negev
        time_data_i["eigs"] = stability.eigs if hasattr(stability,
                                                        'eigs') else np.inf

        snn = dolfin.dot(dolfin.dot(sigma, e1), e1)
        time_data_i["sigma"] = 1 / parameters['geometry'][
            'Ly'] * dolfin.assemble(snn * ds(1))

        log(
            LogLevel.INFO,
            "Load/time step {:.4g}: iteration: {:3d}, err_alpha={:.4g}".format(
                time_data_i["load"], time_data_i["iterations"][0],
                time_data_i["alpha_error"][0]))

        time_data.append(time_data_i)
        time_data_pd = pd.DataFrame(time_data)

        if np.mod(it, savelag) == 0:
            with file_out as f:
                f.write(alpha, load)
                f.write(u, load)
            with dolfin.XDMFFile(os.path.join(outdir,
                                              "output_postproc.xdmf")) as f:
                f.write_checkpoint(alpha,
                                   "alpha-{}".format(it),
                                   0,
                                   append=True)
                log(LogLevel.PROGRESS, 'PROGRESS: written step {}'.format(it))

            time_data_pd.to_json(os.path.join(outdir, "time_data.json"))

        spacetime.append(get_trace(alpha))

        if save_current_bifurcation:
            # modes = np.where(stability.eigs < 0)[0]

            time_data_i['h_opt'] = h_opt
            time_data_i['max_h'] = hmax
            time_data_i['min_h'] = hmin

            with file_bif_postproc as file:
                # leneigs = len(modes)
                # maxmodes = min(3, leneigs)
                beta0v = dolfin.project(stability.perturbation_beta, V_alpha)
                log(
                    LogLevel.DEBUG,
                    'DEBUG: irrev {}'.format(alpha.vector() -
                                             alpha_old.vector()))
                file.write_checkpoint(beta0v, 'beta0', 0, append=True)
                file.write_checkpoint(alpha_bif_old,
                                      'alpha-old',
                                      0,
                                      append=True)
                file.write_checkpoint(alpha_bif, 'alpha-bif', 0, append=True)
                file.write_checkpoint(alpha, 'alpha', 0, append=True)

                np.save(os.path.join(outdir, 'energy_perturbations'),
                        energy_perturbations,
                        allow_pickle=True,
                        fix_imports=True)

            with file_eig as file:
                _v = dolfin.project(
                    dolfin.Constant(h_opt) * perturbation_v, V_u)
                _beta = dolfin.project(
                    dolfin.Constant(h_opt) * perturbation_beta, V_alpha)
                _v.rename('perturbation displacement',
                          'perturbation displacement')
                _beta.rename('perturbation damage', 'perturbation damage')
                # import pdb; pdb.set_trace()
                f.write(_v, load)
                f.write(_beta, load)

    _spacetime = pd.DataFrame(spacetime)
    spacetime = _spacetime.fillna(0)
    mat = np.matrix(spacetime)
    plt.imshow(mat, cmap='Greys', vmin=0., vmax=1., aspect=.1)
    plt.colorbar()

    def format_space(x, pos, xresol=100):
        return '$%1.1f$' % ((-x + xresol / 2) / xresol)

    def format_time(t, pos, xresol=100):
        return '$%1.1f$' % ((t - parameters['loading']['load_min']) /
                            parameters['loading']['n_steps'] *
                            parameters['loading']['load_max'])

    from matplotlib.ticker import FuncFormatter, MaxNLocator

    ax = plt.gca()

    ax.yaxis.set_major_formatter(FuncFormatter(format_space))
    ax.xaxis.set_major_formatter(FuncFormatter(format_time))

    plt.xlabel('$x$')
    plt.ylabel('$t$')
    plt.savefig(os.path.join(outdir, "spacetime.pdf".format(load)),
                bbox_inches="tight")

    spacetime.to_json(os.path.join(outdir + "/spacetime.json"))

    from matplotlib.ticker import FuncFormatter, MaxNLocator
    plot(alpha)
    plt.savefig(os.path.join(outdir, 'alpha.pdf'))
    log(LogLevel.INFO,
        "Saved figure: {}".format(os.path.join(outdir, 'alpha.pdf')))

    xs = np.linspace(-Lx / 2., Lx / 2., 100)
    profile = np.array([alpha(x, 0) for x in xs])
    plt.figure()
    plt.plot(xs, profile, marker='o')
    plt.plot(xs, np.array([u(x, 0) for x in xs]))
    # plt.ylim(0., 1.)
    plt.savefig(os.path.join(outdir, 'profile.pdf'))

    return time_data_pd, outdir
Пример #30
0
    def compute(self, t_end=Q_(10.0, 's'), num_steps=500):
        r"""For incompressible flow, the continuity equation is:

        .. math::  \nabla\cdot \mathbf{u} = 0

        and the Navier-Stokes equation becomes:

        .. math:: \rho\left(\frac{\partial\mathbf{u}}{\partial t} +
            \mathbf{u}\cdot\nabla \mathbf{u}\right) =
            \nabla\cdot\bar{\pi} + \mathbf{F}

        where :math:`\mathbf{u}` is the fluid velocity,  :math:`p` is the
        pressure and where :math:`\mathbf{F}=\rho\mathbf{g}` is the volume
        force due to gravity. The molecular stress tensor :math:`\bar{\pi}` is
        denoted by:

        .. math:: \bar{\pi} = \bar{\tau} - p\bar{I}, \quad \bar{I}\textrm{ is
            the unit tensor}

        where :math:`\bar{\tau}` is the viscous stress tensor defined by:

        .. math:: \bar{\tau} = 2\mu\bar{\epsilon}

        and where

        .. math:: \bar{\epsilon} = \frac{1}{2}\left(\nabla \mathbf{u} +
            (\nabla\mathbf{u})^T \right)

        is the strain-rate tensor.

        The variational formulation of the viscous term is:

        .. math:: \int_\Omega \left(\nabla\cdot\bar{\pi}\right)\cdot
            \mathbf{v}d\mathbf{x}

        Since the term :math:`\nabla\cdot\bar{\pi}` contains second-order
        derivatives of the velocity field :math:`\mathbf{u}`, we integrate this
        term by parts:

        .. math:: -\int_\Omega\left(\nabla\cdot\bar{\pi}\right)\cdot
            \mathbf{v}d\mathbf{x} = \int_\Omega \bar{\pi}:\nabla
            \mathbf{v}d\mathbf{x}-\int_{\delta\Omega}\left(\bar{\pi}
            \cdot\hat{\mathbf{n}}\right)\cdot\mathbf{v}ds

        where the colon operator is the inner product (Frobenius inner-product)
        between tensors, and :math:`\hat{\mathbf{n}}` is the outward unit
        normal at the boundary (traction, or stress vector).

        In cylindrical coordinates (:math:`r,~ \theta,~ z`), the gradient of
        the velocity field :math:`\mathbf{u}` writes

        .. math:: \nabla\cdot{\mathbf{u}} = \left(
            \begin{array}{ccc}
              \frac{\partial u_r}{\partial r} &
              \frac{\partial u_\theta}{\partial r} &
              \frac{\partial u_z}{\partial r}\\
              \frac{1}{r}\frac{\partial u_r}{\partial \theta}-
              \frac{u_\theta}{r}&
              \frac{1}{r}\frac{\partial u_\theta}{\partial \theta}+
               \frac{u_r}{r}&
              \frac{1}{r}\frac{\partial u_z}{\partial \theta}\\
              \frac{\partial u_r}{\partial z} &
              \frac{\partial u_\theta}{\partial z} &
              \frac{\partial u_z}{\partial z}
            \end{array}
            \right)

        The strain-rate tensor :math:`\bar{\epsilon}` is then:

        .. math:: \bar{\epsilon} = \left(
            \begin{array}{ccc}
              \frac{\partial u_r}{\partial r} &
              \frac{1}{2}\left(\frac{\partial u_\theta}{\partial r} +
              \frac{1}{r}\frac{\partial u_\theta}{\partial \theta}-
               \frac{u_\theta}{r}\right)&
              \frac{1}{2}\left(\frac{\partial u_z}{\partial r}+
              \frac{\partial u_r}{\partial z}\right)\\
              \frac{1}{2}\left(\frac{1}{r}\frac{\partial u_r}{\partial \theta}-
              \frac{u_\theta}{r}+\frac{\partial u_\theta}{\partial r}\right)&
              \frac{1}{r}\frac{\partial u_\theta}{\partial \theta}+
               \frac{u_r}{r}&
              \frac{1}{2}\left(\frac{1}{r}\frac{\partial u_z}{\partial
              \theta}+\frac{\partial u_\theta}{\partial z}\right)\\
              \frac{1}{2}\left(\frac{\partial u_r}{\partial z}
              +\frac{\partial u_z}{\partial r}\right)&
              \frac{1}{2}\left(\frac{\partial u_\theta}{\partial z}
              +\frac{1}{r}\frac{\partial u_z}{\partial \theta}\right)&
              \frac{\partial u_z}{\partial z}
            \end{array}
            \right)

        From the definition above, the viscous stress tensor :math:`\bar{\tau}`
        is:

        .. math:: \bar{\tau} = \mu\left(
            \begin{array}{ccc}
              2\frac{\partial u_r}{\partial r} &
              \frac{\partial u_\theta}{\partial r} +
              \frac{1}{r}\frac{\partial u_\theta}{\partial \theta}-
               \frac{u_\theta}{r}&
              \frac{\partial u_z}{\partial r}+
              \frac{\partial u_r}{\partial z}\\
              \frac{1}{r}\frac{\partial u_r}{\partial \theta}-
              \frac{u_\theta}{r}+\frac{\partial u_\theta}{\partial r}&
              2\left(\frac{1}{r}\frac{\partial u_\theta}{\partial \theta}+
               \frac{u_r}{r}\right)&
              \frac{1}{r}\frac{\partial u_z}{\partial
              \theta}+\frac{\partial u_\theta}{\partial z}\\
              \frac{\partial u_r}{\partial z}
              +\frac{\partial u_z}{\partial r}&
              \frac{\partial u_\theta}{\partial z}
              +\frac{1}{r}\frac{\partial u_z}{\partial \theta}&
              2\frac{\partial u_z}{\partial z}
            \end{array}
            \right)

        and the molecular stress tensor :math:`\bar{\pi}` is:

        .. math:: \bar{\pi} = \mu\left(
            \begin{array}{ccc}
              2\frac{\partial u_r}{\partial r} -\frac{p}{\mu}&
              \frac{\partial u_\theta}{\partial r} +
              \frac{1}{r}\frac{\partial u_\theta}{\partial \theta}-
               \frac{u_\theta}{r}&
              \frac{\partial u_z}{\partial r}+
              \frac{\partial u_r}{\partial z}\\
              \frac{1}{r}\frac{\partial u_r}{\partial \theta}-
              \frac{u_\theta}{r}+\frac{\partial u_\theta}{\partial r}&
              2\left(\frac{1}{r}\frac{\partial u_\theta}{\partial \theta}+
               \frac{u_r}{r}\right) -\frac{p}{\mu} &
              \frac{1}{r}\frac{\partial u_z}{\partial
              \theta}+\frac{\partial u_\theta}{\partial z}\\
              \frac{\partial u_r}{\partial z}
              +\frac{\partial u_z}{\partial r}&
              \frac{\partial u_\theta}{\partial z}
              +\frac{1}{r}\frac{\partial u_z}{\partial \theta}&
              2\frac{\partial u_z}{\partial z} -\frac{p}{\mu}
            \end{array}
            \right)

        The scalar product (or double dot product) of two tensors is the
        summed pairwise product of all element of the tensors, i.e.

        .. math:: \bar{\pi}:\nabla\mathbf{v} =
            \pi_{rr}\frac{\partial v_r}{\partial r}+
            \pi_{r\theta}\frac{\partial v_\theta}{\partial r}+\ldots +
            \pi_{zz}\frac{\partial v_z}{\partial z}

        and the vector product (or dot product) of a tensor with a vector is
        just the regular product between a matrix and a vector.

        .. math:: \bar{\pi}\cdot \hat{\mathbf{n}} = \left(\pi_{rr}n_r+
            \pi_{r\theta}n_\theta + \pi_{rz}nz\right) \hat{\mathbf{e}}_r +
            \left(\pi_{\theta r}n_r + \dots\right)\hat{\mathbf{e}}_\theta +
            \left(\ldots + \pi_{r\theta}n_\theta\right)\hat{\mathbf{e}}_z

        **Axisymmetric Formulation**

        We consider a solid of revolution around a fixed axis (Oz), the
        loading, boundary conditions and material properties are invariant
        with respect to a rotation along the symmetry axis. The solid
        cross-section in a plane :math:`\Theta=` cst is represented by
        a two-dimensional domain :math:`\omega` for which the first spatial
        variable (x[0] in FEniCS) will represent the radial coordinate
        :math:`r` whereas the second spatial variable will denote the axial
        variable :math:`z`.

        In axisymmetric conditions, the full 3D domain :math:`\Omega` can be
        decomposed as :math:`\Omega=\omega\times[0;2\pi]` where the interval
        represents the :math:`\theta` variable. The integration measures
        therefore reduce to :math:`dx=d\omega\cdot(rd\theta)` and
        :math:`dS=ds\cdot(rd\theta)` where :math:`dS` is the surface
        integration measure on the 3D domain :math:`\Omega` and :math:`ds` its
        counterpart on the cross-section boundary :math:`\partial\omega`.

        Exploiting the invariance of all fields with respect to :math:`\theta`,
        we get the variational formulation of the viscous term as:

         .. math:: -\int_\Omega\left(\nabla\cdot\bar{\pi}\right)\cdot
            \mathbf{v}d\mathbf{x} = 2\pi\int_\omega \bar{\pi}:\nabla
            \mathbf{v}rd\omega-2\pi\int_{\delta\omega}\left(\bar{\pi}
            \cdot\hat{\mathbf{n}}\right)\cdot\mathbf{v}r ds

        For an axisymmetric model there is no gradient in the azimuthal
        direction :math:`\theta`. If we also assume that the
        :math:`\theta`-component of the velocity field is zero, we obtain
        the gradient of the velocity field:

        .. math:: \nabla\cdot{\mathbf{u}} = \left(
            \begin{array}{ccc}
              \frac{\partial u_r}{\partial r} &
              0 &
              \frac{\partial u_z}{\partial r}\\
              0&
               \frac{u_r}{r}&
              0\\
              \frac{\partial u_r}{\partial z} &
              0&
              \frac{\partial u_z}{\partial z}
            \end{array}
            \right)

        and the following strain-rate tensor:

        .. math:: \bar{\epsilon} = \left(
            \begin{array}{ccc}
              \frac{\partial u_r}{\partial r} &
              0&
              \frac{1}{2}\left(\frac{\partial u_z}{\partial r}+
              \frac{\partial u_r}{\partial z}\right)\\
              0&
               \frac{u_r}{r}&
              0\\
              \frac{1}{2}\left(\frac{\partial u_r}{\partial z}
              +\frac{\partial u_z}{\partial r}\right)&
              0&
              \frac{\partial u_z}{\partial z}
            \end{array}
            \right)

        *Note*: The vector function space dimension is now two-dimensional.
        We can keep the 3D tensor notation if we perform the integrands
        manually before assembling the bilinear and linear forms.

        *Note*: The factor :math:`u_r/r` is problematic for
        :math:`r\approx 0`. One solution is to ...

        for axisymmetric flow, the velocity field is composed of two
        components, i.e.

        .. math:: \mathbf{u} = u_r\hat{\mathbf{e}}_r+u_z\hat{\mathbf{e}}_z

        **Splitting Method**:

        To overcome the saddle-point problems resulting from a direct
        discretization of the Navier-Stokes equations we use a splitting scheme
        where the velocity and pressure variables are computed in a sequence of
        predictor-corrector type steps.

        Incremental Pressure Correction Scheme (IPCS) -- see :cite:`Logg2012`
        for details of the algorithm.

        In summary, we may thus solve the incompressible Navier-Stokes
        equations efficiently by solving a sequence of three linear
        variational problems in each time step.

        In order to simulate steady-state use t_end = large number

        :param t_end: Final time, default = 10 s.
        :type t_end: ureg.Quantity
        :param num_steps: Number of time steps, default = 500.
        :type num_steps: int
        :return: The solution.
        """
        out = None
        dt = t_end.to('s').magnitude / num_steps
        radius = self._size[0].magnitude
        length = self._size[1].magnitude
        mu = self._mu.magnitude
        rho = self._rho.magnitude
        pin = self._pin.magnitude

        # TODO: something is odd with this mesh, needs investigations
        mesh = self._mesh

        dom = dolfin.cpp.mesh.MeshFunctionSizet(mesh, mesh.mvc_dom())
        bnd = dolfin.cpp.mesh.MeshFunctionSizet(mesh, mesh.mvc_bnd())
        dx = dolfin.Measure("dx", domain=mesh, subdomain_data=dom)
        ds = dolfin.Measure("ds", domain=mesh, subdomain_data=bnd)
        return out