Esempio n. 1
0
    def __new__(cls, mesh, tolerance=1e-12):
        dim = mesh.geometry().dim()
        X = MeshPool._X[dim - 1]

        test = assemble(dot(X, X) * CellVolume(mesh)**(0.25) *
                        dx()) * assemble(Constant(1) * dx(domain=mesh))
        assert test > 0.0
        assert test < np.inf

        # Do a garbage collect to collect any garbage references
        # Needed for full parallel compatibility
        gc.collect()
        keys = np.array(MeshPool._existing.keys())
        self = None
        if len(keys) > 0:
            diff = np.abs(keys - test) / np.abs(test)
            idx = np.argmin(np.abs(keys - test))

            if diff[idx] <= tolerance and isinstance(
                    mesh, type(MeshPool._existing[keys[idx]])):
                self = MeshPool._existing[keys[idx]]

        if self is None:
            self = mesh
            MeshPool._existing[test] = self
        return self
Esempio n. 2
0
    def expr2function(self, expr, function):
        """ Convert an expression into a function. How this is done is
        determined by the parameters (assemble, project or interpolate).
        """
        space = function.function_space()

        if self.params.expr2function == "assemble":
            # Compute average values of expr for each cell and place in a DG0 space
            test = TestFunction(space)
            scale = 1.0 / CellVolume(space.mesh())
            assemble(scale * inner(expr, test) * dx, tensor=function.vector())
            return function

        elif self.params.expr2function == "project":
            # TODO: Avoid superfluous function creation with fenics-dev/1.5 by using:
            #project(expr, space, function=function)
            function.assign(project(expr, space))
            return function

        elif self.params.expr2function == "interpolate":
            # TODO: Need interpolation with code generated from expr, waiting for uflacs work.
            function.interpolate(
                expr)  # Currently only works if expr is a single Function
            return function

        else:
            error(
                "No action selected, need to choose either assemble, project or interpolate."
            )
Esempio n. 3
0
 def before_first_compute(self, get):
     u = get("Velocity")
     mesh = u.function_space().mesh()
     spaces = SpacePool(mesh)
     DG0 = spaces.get_space(0, 0)
     self._v = TestFunction(DG0)
     self._cfl = Function(DG0)
     self._hF = Circumradius(mesh)
     self._hK = CellVolume(mesh)
Esempio n. 4
0
def extrapolate_setup(F_fluid_linear, extype, mesh_file, d_, phi, gamma, dx_f,
                      **semimp_namespace):
    def F_(U):
        return Identity(len(U)) + grad(U)

    def J_(U):
        return det(F_(U))

    def eps(U):
        return 0.5 * (grad(U) * inv(F_(U)) + inv(F_(U)).T * grad(U).T)

    def STVK(U, alfa_mu, alfa_lam):
        return alfa_lam * tr(eps(U)) * Identity(
            len(U)) + 2.0 * alfa_mu * eps(U)
        #return F_(U)*(alfa_lam*tr(eps(U))*Identity(len(U)) + 2.0*alfa_mu*eps(U))

    alfa = 1.0  # holder value if linear is chosen
    if extype == "det":
        #alfa = inv(J_(d_["n"]))
        alfa = 1. / (J_(d_["n"]))
    if extype == "smallconst":
        alfa = 0.01 * (mesh_file.hmin())**2
    if extype == "const":
        alfa = 1.0

    F_extrapolate = alfa * inner(grad(d_["n"]), grad(phi)) * dx_f

    if extype == "linear":
        hmin = mesh_file.hmin()
        #E_y =  1./(J_(d_["n"]))
        #nu = -0.2 #(-1, 0.5)
        E_y = 1. / CellVolume(mesh_file)
        nu = 0.25
        alfa_lam = nu * E_y / ((1. + nu) * (1. - 2. * nu))
        alfa_mu = E_y / (2. * (1. + nu))
        #alfa_lam = hmin*hmin ; alfa_mu = hmin*hmin
        F_extrapolate = inner(
            J_(d_["n"]) * STVK(d_["n"], alfa_mu, alfa_lam) *
            inv(F_(d_["n"])).T, grad(phi)) * dx_f
        #F_extrapolate = inner(STVK(d_["n"],alfa_mu,alfa_lam) , grad(phi))*dx_f

    F_fluid_linear += F_extrapolate

    return dict(F_fluid_linear=F_fluid_linear)
Esempio n. 5
0
def extrapolate_setup(F_fluid_linear, mesh, d_, phi, gamma, dx_f, **namespace):
    """
    Elastic lifting operator solving the equation of linear elasticity.

    div(sigma(d)) = 0   in the fluid domain
    d = 0               on the fluid boundaries other than FSI interface
    d = solid_d         on the FSI interface
    """
    E_y = 1.0 / CellVolume(mesh)
    nu = 0.25
    alpha_lam = nu * E_y / ((1.0 + nu) * (1.0 - 2.0 * nu))
    alpha_mu = E_y / (2.0 * (1.0 + nu))
    F_extrapolate = inner(
        J_(d_["n"]) * S_linear(d_["n"], alpha_mu, alpha_lam) *
        inv(F_(d_["n"])).T, grad(phi)) * dx_f

    F_fluid_linear += F_extrapolate

    return dict(F_fluid_linear=F_fluid_linear)
Esempio n. 6
0
def extrapolate_setup(F_fluid_linear, extrapolation_sub_type, mesh, d_, phi,
                      dx_f, **namespace):
    """
    Laplace lifting operator. Can be used for small to moderate deformations.
    The diffusion parameter "alfa", which is specified by "extrapolation_sub_type",
    can be used to control the deformation field from the wall boundaries to the
    fluid domain. "alfa" is assumed constant within elements.

    - alfa * laplace(d) = 0   in the fluid domain
    d = 0                     on the fluid boundaries other than FSI interface
    d = solid_def             on the FSI interface

    References:

    Slyngstad, Andreas Strøm. Verification and Validation of a Monolithic
        Fluid-Structure Interaction Solver in FEniCS. A comparison of mesh lifting
        operators. MS thesis. 2017.

    Gjertsen, Sebastian. Development of a Verified and Validated Computational
        Framework for Fluid-Structure Interaction: Investigating Lifting Operators
        and Numerical Stability. MS thesis. 2017.
    """

    if extrapolation_sub_type == "volume_change":
        alfa = 1.0 / (J_(d_["n"]))
    elif extrapolation_sub_type == "volume":
        alfa = 1.0 / CellVolume(mesh)
    elif extrapolation_sub_type == "small_constant":
        alfa = 0.01 * (mesh.hmin())**2
    elif extrapolation_sub_type == "constant":
        alfa = 1.0
    else:
        raise RuntimeError("Could not find extrapolation method {}".format(
            extrapolation_sub_type))

    F_extrapolate = alfa * inner(grad(d_["n"]), grad(phi)) * dx_f
    F_fluid_linear += F_extrapolate

    return dict(F_fluid_linear=F_fluid_linear)
Esempio n. 7
0
def les_setup(u_, mesh, assemble_matrix, CG1Function, nut_krylov_solver, bcs,
              **NS_namespace):
    """
    Set up for solving the Germano Dynamic LES model applying
    Lagrangian Averaging.
    """

    # Create function spaces
    CG1 = FunctionSpace(mesh, "CG", 1)
    p, q = TrialFunction(CG1), TestFunction(CG1)
    dim = mesh.geometry().dim()

    # Define delta and project delta**2 to CG1
    delta = pow(CellVolume(mesh), 1. / dim)
    delta_CG1_sq = project(delta, CG1)
    delta_CG1_sq.vector().set_local(delta_CG1_sq.vector().array()**2)
    delta_CG1_sq.vector().apply("insert")

    # Define nut_
    Sij = sym(grad(u_))
    magS = sqrt(2 * inner(Sij, Sij))
    Cs = Function(CG1)
    nut_form = Cs**2 * delta**2 * magS
    # Create nut_ BCs
    ff = FacetFunction("size_t", mesh, 0)
    bcs_nut = []
    for i, bc in enumerate(bcs['u0']):
        bc.apply(u_[0].vector())  # Need to initialize bc
        m = bc.markers()  # Get facet indices of boundary
        ff.array()[m] = i + 1
        bcs_nut.append(DirichletBC(CG1, Constant(0), ff, i + 1))
    nut_ = CG1Function(nut_form,
                       mesh,
                       method=nut_krylov_solver,
                       bcs=bcs_nut,
                       bounded=True,
                       name="nut")

    # Create functions for holding the different velocities
    u_CG1 = as_vector([Function(CG1) for i in range(dim)])
    u_filtered = as_vector([Function(CG1) for i in range(dim)])
    dummy = Function(CG1)
    ll = LagrangeInterpolator()

    # Assemble required filter matrices and functions
    G_under = Function(CG1, assemble(TestFunction(CG1) * dx))
    G_under.vector().set_local(1. / G_under.vector().array())
    G_under.vector().apply("insert")
    G_matr = assemble(inner(p, q) * dx)

    # Set up functions for Lij and Mij
    Lij = [Function(CG1) for i in range(dim * dim)]
    Mij = [Function(CG1) for i in range(dim * dim)]
    # Check if case is 2D or 3D and set up uiuj product pairs and
    # Sij forms, assemble required matrices
    Sijcomps = [Function(CG1) for i in range(dim * dim)]
    Sijfcomps = [Function(CG1) for i in range(dim * dim)]
    # Assemble some required matrices for solving for rate of strain terms
    Sijmats = [assemble_matrix(p.dx(i) * q * dx) for i in range(dim)]
    if dim == 3:
        tensdim = 6
        uiuj_pairs = ((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2))
    else:
        tensdim = 3
        uiuj_pairs = ((0, 0), (0, 1), (1, 1))

    # Set up Lagrange functions
    JLM = Function(CG1)
    JLM.vector()[:] += 1E-32
    JMM = Function(CG1)
    JMM.vector()[:] += 1

    return dict(Sij=Sij,
                nut_form=nut_form,
                nut_=nut_,
                delta=delta,
                bcs_nut=bcs_nut,
                delta_CG1_sq=delta_CG1_sq,
                CG1=CG1,
                Cs=Cs,
                u_CG1=u_CG1,
                u_filtered=u_filtered,
                ll=ll,
                Lij=Lij,
                Mij=Mij,
                Sijcomps=Sijcomps,
                Sijfcomps=Sijfcomps,
                Sijmats=Sijmats,
                JLM=JLM,
                JMM=JMM,
                dim=dim,
                tensdim=tensdim,
                G_matr=G_matr,
                G_under=G_under,
                dummy=dummy,
                uiuj_pairs=uiuj_pairs)
def transport_linear(integrator_type, mesh, subdomains, boundaries, t_start, dt, T, solution0, \
                 alpha_0, K_0, mu_l_0, lmbda_l_0, Ks_0, \
                 alpha_1, K_1, mu_l_1, lmbda_l_1, Ks_1, \
                 alpha, K, mu_l, lmbda_l, Ks, \
                 cf_0, phi_0, rho_0, mu_0, k_0,\
                 cf_1, phi_1, rho_1, mu_1, k_1,\
                 cf, phi, rho, mu, k, \
                 d_0, d_1, d_t,
                 vel_c, p_con, A_0, Temp, c_extrapolate):
    # Create mesh and define function space
    parameters["ghost_mode"] = "shared_facet"  # required by dS

    dx = Measure('dx', domain=mesh, subdomain_data=subdomains)
    ds = Measure('ds', domain=mesh, subdomain_data=boundaries)
    dS = Measure('dS', domain=mesh, subdomain_data=boundaries)

    C_cg = FiniteElement("CG", mesh.ufl_cell(), 1)
    C_dg = FiniteElement("DG", mesh.ufl_cell(), 0)
    mini = C_cg + C_dg
    C = FunctionSpace(mesh, mini)
    C = BlockFunctionSpace([C])
    TM = TensorFunctionSpace(mesh, 'DG', 0)
    PM = FunctionSpace(mesh, 'DG', 0)
    n = FacetNormal(mesh)
    vc = CellVolume(mesh)
    fc = FacetArea(mesh)

    h = vc / fc
    h_avg = (vc('+') + vc('-')) / (2 * avg(fc))

    penalty1 = Constant(1.0)

    tau = Function(PM)
    tau = tau_cal(tau, phi, -0.5)

    tuning_para = 0.25

    vel_norm = (dot(vel_c, n) + abs(dot(vel_c, n))) / 2.0

    cell_size = CellDiameter(mesh)
    vnorm = sqrt(dot(vel_c, vel_c))

    I = Identity(mesh.topology().dim())
    d_eff = Function(TM)
    d_eff = diff_coeff_cal_rev(d_eff, d_0, tau,
                               phi) + tuning_para * cell_size * vnorm * I

    monitor_dt = dt

    # Define variational problem
    dc, = BlockTrialFunction(C)
    dc_dot, = BlockTrialFunction(C)
    psic, = BlockTestFunction(C)
    block_c = BlockFunction(C)
    c, = block_split(block_c)
    block_c_dot = BlockFunction(C)
    c_dot, = block_split(block_c_dot)

    theta = -1.0

    a_time = phi * rho * inner(c_dot, psic) * dx

    a_dif = dot(rho*d_eff*grad(c),grad(psic))*dx \
        - dot(avg_w(rho*d_eff*grad(c),weight_e(rho*d_eff,n)), jump(psic, n))*dS \
        + theta*dot(avg_w(rho*d_eff*grad(psic),weight_e(rho*d_eff,n)), jump(c, n))*dS \
        + penalty1/h_avg*k_e(rho*d_eff,n)*dot(jump(c, n), jump(psic, n))*dS

    a_adv = -dot(rho*vel_c*c,grad(psic))*dx \
        + dot(jump(psic), rho('+')*vel_norm('+')*c('+') - rho('-')*vel_norm('-')*c('-') )*dS \
        + dot(psic, rho*vel_norm*c)*ds(3)

    R_c = R_c_cal(c_extrapolate, p_con, Temp)
    c_D1 = Constant(0.5)
    rhs_c = R_c * A_s_cal(phi, phi_0, A_0) * psic * dx - dot(
        rho * phi * vel_c, n) * c_D1 * psic * ds(1)

    r_u = [a_dif + a_adv]
    j_u = block_derivative(r_u, [c], [dc])

    r_u_dot = [a_time]
    j_u_dot = block_derivative(r_u_dot, [c_dot], [dc_dot])
    r = [r_u_dot[0] + r_u[0] - rhs_c]

    # this part is not applied.
    exact_solution_expression1 = Expression("1.0",
                                            t=0,
                                            element=C[0].ufl_element())

    def bc(t):
        p5 = DirichletBC(C.sub(0),
                         exact_solution_expression1,
                         boundaries,
                         1,
                         method="geometric")
        return BlockDirichletBC([p5])

    # Define problem wrapper
    class ProblemWrapper(object):
        def set_time(self, t):
            pass

        # Residual and jacobian functions
        def residual_eval(self, t, solution, solution_dot):
            return r

        def jacobian_eval(self, t, solution, solution_dot,
                          solution_dot_coefficient):
            return [[
                Constant(solution_dot_coefficient) * j_u_dot[0, 0] + j_u[0, 0]
            ]]

        # Define boundary condition
        def bc_eval(self, t):
            pass

        # Define initial condition
        def ic_eval(self):
            return solution0

        # Define custom monitor to plot the solution
        def monitor(self, t, solution, solution_dot):
            pass

    problem_wrapper = ProblemWrapper()
    (solution, solution_dot) = (block_c, block_c_dot)
    solver = TimeStepping(problem_wrapper, solution, solution_dot)
    solver.set_parameters({
        "initial_time": t_start,
        "time_step_size": dt,
        "monitor": {
            "time_step_size": monitor_dt,
        },
        "final_time": T,
        "exact_final_time": "stepover",
        "integrator_type": integrator_type,
        "problem_type": "linear",
        "linear_solver": "mumps",
        "report": True
    })
    export_solution = solver.solve()

    return export_solution, T
def test(path, type='mf'):
    '''Evolve the tile in (n, n) pattern checking volume/surface properties'''

    comm = mpi_comm_world()
    h5 = HDF5File(comm, path, 'r')
    tile = Mesh()
    h5.read(tile, 'mesh', False)

    init_container = lambda type, dim: (
        MeshFunction('size_t', tile, dim, 0)
        if type == 'mf' else MeshValueCollection('size_t', tile, dim))

    for n in (2, 4):
        data = {}
        checks = {}
        for dim, name in zip((2, 3), ('surfaces', 'volumes')):
            # Get the collection
            collection = init_container(type, dim)
            h5.read(collection, name)

            if type == 'mvc': collection = as_meshf(collection)

            # Data to evolve
            tile.init(dim, 0)
            e2v = tile.topology()(dim, 0)
            # Only want to evolve tag 1 (interfaces) for the facets.
            data[(dim, 1)] = np.array(
                [e2v(e.index()) for e in SubsetIterator(collection, 1)],
                dtype='uintp')

            if dim == 2:
                check = lambda m, f: assemble(
                    FacetArea(m) * ds(domain=m,
                                      subdomain_data=f,
                                      subdomain_id=1) + avg(FacetArea(m)) *
                    dS(domain=m, subdomain_data=f, subdomain_id=1))
            else:
                check = lambda m, f: assemble(
                    CellVolume(m) * dx(
                        domain=m, subdomain_data=f, subdomain_id=1))

            checks[
                dim] = lambda m, f, t=tile, c=collection, n=n, check=check: abs(
                    check(m, f) - n**2 * check(t, c)) / (n**2 * check(t, c))

        t = Timer('x')
        mesh, mesh_data = TileMesh(tile, (n, n), mesh_data=data)
        info('\tTiling took %g s. Ncells %d, nvertices %d, \n' %
             (t.stop(), mesh.num_vertices(), mesh.num_cells()))

        foos = mf_from_data(mesh, mesh_data)
        # Mesh Functions
        from_mf = np.array([checks[dim](mesh, foos[dim]) for dim in (2, 3)])

        mvcs = mvc_from_data(mesh, mesh_data)
        foos = as_meshf(mvcs)
        # Mesh ValueCollections
        from_mvc = np.array([checks[dim](mesh, foos[dim]) for dim in (2, 3)])

        assert np.linalg.norm(from_mf - from_mvc) < 1E-13
        # I ignore shared facets so there is bound to be some error in facets
        # Volume should match well
        print from_mf
def m_linear(integrator_type, mesh, subdomains, boundaries, t_start, dt, T, solution0, \
                 alpha_0, K_0, mu_l_0, lmbda_l_0, Ks_0, \
                 alpha_1, K_1, mu_l_1, lmbda_l_1, Ks_1, \
                 alpha, K, mu_l, lmbda_l, Ks, \
                 cf_0, phi_0, rho_0, mu_0, k_0,\
                 cf_1, phi_1, rho_1, mu_1, k_1,\
                 cf, phi, rho, mu, k, \
                 pressure_freeze):
    # Create mesh and define function space
    parameters["ghost_mode"] = "shared_facet" # required by dS

    dx = Measure('dx', domain=mesh, subdomain_data=subdomains)
    ds = Measure('ds', domain=mesh, subdomain_data=boundaries)
    dS = Measure('dS', domain=mesh, subdomain_data=boundaries)

    C = VectorFunctionSpace(mesh, "CG", 2)
    C = BlockFunctionSpace([C])
    TM = TensorFunctionSpace(mesh, 'DG', 0)
    PM = FunctionSpace(mesh, 'DG', 0)
    n = FacetNormal(mesh)
    vc = CellVolume(mesh)
    fc = FacetArea(mesh)

    h = vc/fc
    h_avg = (vc('+') + vc('-'))/(2*avg(fc))

    monitor_dt = dt

    f_stress_x = Constant(-1.e3)
    f_stress_y = Constant(-20.0e6)

    f = Constant((0.0, 0.0)) #sink/source for displacement

    I = Identity(mesh.topology().dim())

    # Define variational problem
    psiu, = BlockTestFunction(C)
    block_u = BlockTrialFunction(C)
    u, = block_split(block_u)
    w = BlockFunction(C)

    theta = -1.0

    a_time = inner(-alpha*pressure_freeze*I,sym(grad(psiu)))*dx #quasi static

    a = inner(2*mu_l*strain(u)+lmbda_l*div(u)*I, sym(grad(psiu)))*dx

    rhs_a = inner(f,psiu)*dx \
        + dot(f_stress_y*n,psiu)*ds(2)


    r_u = [a]

    #DirichletBC
    bcd1 = DirichletBC(C.sub(0).sub(0), 0.0, boundaries, 1) # No normal displacement for solid on left side
    bcd3 = DirichletBC(C.sub(0).sub(0), 0.0, boundaries, 3) # No normal displacement for solid on right side
    bcd4 = DirichletBC(C.sub(0).sub(1), 0.0, boundaries, 4) # No normal displacement for solid on bottom side
    bcs = BlockDirichletBC([bcd1,bcd3,bcd4])

    AA = block_assemble([r_u])
    FF = block_assemble([rhs_a - a_time])
    bcs.apply(AA)
    bcs.apply(FF)

    block_solve(AA, w.block_vector(), FF, "mumps")

    export_solution = w

    return export_solution, T
Esempio n. 11
0
    dx = Measure("dx", domain=mesh, subdomain_data=subdomains)
    ds = Measure("ds", domain=mesh, subdomain_data=boundaries)
    dS = Measure("dS", domain=mesh, subdomain_data=boundaries)

    # Test and trial functions
    vq = BlockTestFunction(W)
    (v, q) = block_split(vq)
    up = BlockTrialFunction(W)
    (u, p) = block_split(up)

    w = BlockFunction(W)
    w0 = BlockFunction(W)
    (u0, p0) = block_split(w0)

    n = FacetNormal(mesh)
    vc = CellVolume(mesh)
    fc = FacetArea(mesh)

    h = vc / fc
    h_avg = (vc("+") + vc("-")) / (2 * avg(fc))

    penalty1 = 1.0
    penalty2 = 10.0
    theta = 1.0

    # Constitutive parameters
    K = 1000.e3
    nu = 0.25
    E = K_nu_to_E(K, nu)  # Pa 14

    (mu_l, lmbda_l) = E_nu_to_mu_lmbda(E, nu)
Esempio n. 12
0
def h_linear(integrator_type, mesh, subdomains, boundaries, t_start, dt, T, solution0, \
                 alpha_0, K_0, mu_l_0, lmbda_l_0, Ks_0, \
                 alpha_1, K_1, mu_l_1, lmbda_l_1, Ks_1, \
                 alpha, K, mu_l, lmbda_l, Ks, \
                 cf_0, phi_0, rho_0, mu_0, k_0,\
                 cf_1, phi_1, rho_1, mu_1, k_1,\
                 cf, phi, rho, mu, k, \
                 sigma_v_freeze, dphi_c_dt):
    # Create mesh and define function space
    parameters["ghost_mode"] = "shared_facet"  # required by dS

    dx = Measure('dx', domain=mesh, subdomain_data=subdomains)
    ds = Measure('ds', domain=mesh, subdomain_data=boundaries)
    dS = Measure('dS', domain=mesh, subdomain_data=boundaries)

    BDM = FiniteElement("BDM", mesh.ufl_cell(), 1)
    PDG = FiniteElement("DG", mesh.ufl_cell(), 0)

    BDM_F = FunctionSpace(mesh, BDM)
    PDG_F = FunctionSpace(mesh, PDG)

    W = BlockFunctionSpace([BDM_F, PDG_F], restrict=[None, None])

    TM = TensorFunctionSpace(mesh, 'DG', 0)
    PM = FunctionSpace(mesh, 'DG', 0)
    n = FacetNormal(mesh)
    vc = CellVolume(mesh)
    fc = FacetArea(mesh)

    h = vc / fc
    h_avg = (vc('+') + vc('-')) / (2 * avg(fc))

    I = Identity(mesh.topology().dim())

    monitor_dt = dt

    p_outlet = 0.1e6
    p_inlet = 1000.0

    M_inv = phi_0 * cf + (alpha - phi_0) / Ks

    # Define variational problem
    trial = BlockTrialFunction(W)
    dv, dp = block_split(trial)

    trial_dot = BlockTrialFunction(W)
    dv_dot, dp_dot = block_split(trial_dot)

    test = BlockTestFunction(W)
    psiv, psip = block_split(test)

    block_w = BlockFunction(W)
    v, p = block_split(block_w)

    block_w_dot = BlockFunction(W)
    v_dot, p_dot = block_split(block_w_dot)

    a_time = Constant(0.0) * inner(v_dot, psiv) * dx  #quasi static

    # k is a function of phi
    #k = perm_update_rutqvist_newton(p,p0,phi0,phi,coeff)
    lhs_a = inner(dot(v, mu * inv(k)), psiv) * dx - p * div(
        psiv
    ) * dx  #+ 6.0*inner(psiv,n)*ds(2)  # - inner(gravity*(rho-rho0), psiv)*dx

    b_time = (M_inv + pow(alpha, 2.) / K) * p_dot * psip * dx

    lhs_b = div(v) * psip * dx  #div(rho*v)*psip*dx #TODO rho

    rhs_v = -p_outlet * inner(psiv, n) * ds(3)

    rhs_p = -alpha / K * sigma_v_freeze * psip * dx - dphi_c_dt * psip * dx

    r_u = [lhs_a, lhs_b]

    j_u = block_derivative(r_u, block_w, trial)

    r_u_dot = [a_time, b_time]

    j_u_dot = block_derivative(r_u_dot, block_w_dot, trial_dot)

    r = [r_u_dot[0] + r_u[0] - rhs_v, \
         r_u_dot[1] + r_u[1] - rhs_p]

    def bc(t):
        #bc_v = [DirichletBC(W.sub(0), (.0, .0), boundaries, 4)]
        v1 = DirichletBC(W.sub(0), (1.e-4 * 2.0, 0.0), boundaries, 1)
        v2 = DirichletBC(W.sub(0), (0.0, 0.0), boundaries, 2)
        v4 = DirichletBC(W.sub(0), (0.0, 0.0), boundaries, 4)
        bc_v = [v1, v2, v4]

        return BlockDirichletBC([bc_v, None])

    # Define problem wrapper
    class ProblemWrapper(object):
        def set_time(self, t):
            pass
            #g.t = t

        # Residual and jacobian functions
        def residual_eval(self, t, solution, solution_dot):
            #print(as_backend_type(assemble(p_time - p_time_error)).vec().norm())
            #print("gravity effect", as_backend_type(assemble(inner(gravity*(rho-rho0), psiv)*dx)).vec().norm())

            return r

        def jacobian_eval(self, t, solution, solution_dot,
                          solution_dot_coefficient):
            return [[Constant(solution_dot_coefficient)*j_u_dot[0, 0] + j_u[0, 0], \
                     Constant(solution_dot_coefficient)*j_u_dot[0, 1] + j_u[0, 1]], \
                    [Constant(solution_dot_coefficient)*j_u_dot[1, 0] + j_u[1, 0], \
                     Constant(solution_dot_coefficient)*j_u_dot[1, 1] + j_u[1, 1]]]

        # Define boundary condition
        def bc_eval(self, t):
            return bc(t)

        # Define initial condition
        def ic_eval(self):
            return solution0

        # Define custom monitor to plot the solution
        def monitor(self, t, solution, solution_dot):
            pass

    # Solve the time dependent problem
    problem_wrapper = ProblemWrapper()
    (solution, solution_dot) = (block_w, block_w_dot)
    solver = TimeStepping(problem_wrapper, solution, solution_dot)
    solver.set_parameters({
        "initial_time": t_start,
        "time_step_size": dt,
        "monitor": {
            "time_step_size": monitor_dt,
        },
        "final_time": T,
        "exact_final_time": "stepover",
        "integrator_type": integrator_type,
        "problem_type": "linear",
        "linear_solver": "mumps",
        "report": True
    })
    export_solution = solver.solve()

    return export_solution, T
Esempio n. 13
0
    def model(self, parameters=None, logger=None):
        def format(arr):
            return np.array(arr)

        # Setup parameters, logger
        self.set_parameters(parameters)
        self.set_logger(logger)

        # Get parameters
        parameters = self.get_parameters()

        #SS#if not parameters.get('simulate'):
        #SS#	return

        # Setup data
        self.set_data(reset=True)
        self.set_observables(reset=True)

        # Show simulation settings
        self.get_logger()('\n\t'.join([
            'Simulating:', *[
                '%s : %r' % (param, parameters[param] if not isinstance(
                    parameters[param], dict) else list(parameters[param]))
                for param in
                ['fields', 'num_elem', 'N', 'dt', 'D', 'alpha', 'tol']
            ]
        ]))

        # Data mesh
        mesh = IntervalMesh(MPI.comm_world, parameters['num_elem'],
                            parameters['L_0'], parameters['L_1'])

        # Fields
        V = {}
        W = {}
        fields_n = {}
        fields = {}
        w = {}
        fields_0 = {}
        potential = {}
        potential_derivative = {}
        bcs = {}
        R = {}
        J = {}
        # v2d_vector = {}
        observables = {}
        for field in parameters['fields']:

            # Define functions
            V[field] = {}
            w[field] = {}
            for space in parameters['spaces']:
                V[field][space] = getattr(
                    dolfin, parameters['spaces'][space]['type'])(
                        mesh, parameters['spaces'][space]['family'],
                        parameters['spaces'][space]['degree'])
                w[field][space] = TestFunction(V[field][space])

            space = V[field][parameters['fields'][field]['space']]
            test = w[field][parameters['fields'][field]['space']]

            fields_n[field] = Function(space, name='%sn' % (field))
            fields[field] = Function(space, name=field)

            # Inital condition
            fields_0[field] = Expression(
                parameters['fields'][field]['initial'],
                element=space.ufl_element())
            fields_n[field] = project(fields_0[field], space)
            fields[field].assign(fields_n[field])

            # Define potential
            if parameters['potential'].get('kwargs') is None:
                parameters['potential']['kwargs'] = {}
            for k in parameters['potential']['kwargs']:
                if parameters['potential']['kwargs'][k] is None:
                    parameters['potential']['kwargs'][k] = fields[k]

            potential[field] = Expression(
                parameters['potential']['expression'],
                degree=parameters['potential']['degree'],
                **parameters['potential']['kwargs'])
            potential_derivative[field] = Expression(
                parameters['potential']['derivative'],
                degree=parameters['potential']['degree'] - 1,
                **parameters['potential']['kwargs'])

            #Subdomain for defining Positive grain
            sub_domains = MeshFunction('size_t', mesh,
                                       mesh.topology().dim(), 0)

            #BC condition
            bcs[field] = []
            if parameters['fields'][field]['bcs'] == 'dirichlet':
                BC_l = CompiledSubDomain('near(x[0], side) && on_boundary',
                                         side=parameters['L_0'])
                BC_r = CompiledSubDomain('near(x[0], side) && on_boundary',
                                         side=parameters['L_1'])
                bcl = DirichletBC(V, fields_n[field], BC_l)
                bcr = DirichletBC(V, fields_n[field], BC_r)
                bcs[field].extend([bcl, bcr])
            elif parameters['fields'][field]['bcs'] == 'neumann':
                bcs[field].extend([])

            # Residual and Jacobian
            R[field] = (
                ((fields[field] - fields_n[field]) / parameters['dt'] * test *
                 dx) +
                (inner(parameters['D'] * grad(test), grad(fields[field])) * dx)
                + (parameters['alpha'] * potential_derivative[field] * test *
                   dx))

            J[field] = derivative(R[field], fields[field])

            # Observables
            observables[field] = {}

        files = {
            'xdmf': XDMFFile(MPI.comm_world,
                             self.get_paths()['xdmf']),
            'hdf5': HDF5File(MPI.comm_world,
                             self.get_paths()['hdf5'], 'w'),
        }

        files['hdf5'].write(mesh, '/mesh')
        eps = lambda n, key, field, observables, tol: (
            n == 0) or (abs(observables[key]['total_energy'][n] - observables[
                key]['total_energy'][n - 1]) /
                        (observables[key]['total_energy'][0]) > tol)
        flag = {field: True for field in parameters['fields']}
        tol = {
            field: parameters['tol'][field] if isinstance(
                parameters['tol'], dict) else parameters['tol']
            for field in parameters['fields']
        }
        phases = {'p': 1, 'm': 2}
        n = 0
        problem = {}
        solver = {}
        while (n < parameters['N']
               and any([flag[field] for field in parameters['fields']])):

            self.get_logger()('Time: %d' % (n))

            for field in parameters['fields']:

                if not flag[field]:
                    continue

                # Solve
                problem[field] = NonlinearVariationalProblem(
                    R[field], fields[field], bcs[field], J[field])
                solver[field] = NonlinearVariationalSolver(problem[field])
                solver[field].solve()

                # Get field array
                array = assemble(
                    (1 / CellVolume(mesh)) *
                    inner(fields[field], w[field]['Z']) * dx).get_local()

                # Observables
                observables[field]['Time'] = parameters['dt'] * n

                # observables[field]['energy_density'] = format(0.5*dot(grad(fields[field]),grad(fields[field]))*dx)
                observables[field]['gradient_energy'] = format(
                    assemble(0.5 *
                             dot(grad(fields[field]), grad(fields[field])) *
                             dx(domain=mesh)))
                observables[field]['landau_energy'] = format(
                    assemble(potential[field] * dx(domain=mesh)))
                observables[field]['diffusion_energy'] = format(
                    assemble(
                        project(
                            div(project(grad(fields[field]), V[field]['W'])),
                            V[field]['Z']) * dx(domain=mesh))
                )  #Diffusion part of chemical potential
                observables[field]['spinodal_energy'] = format(
                    assemble(
                        potential_derivative[field] *
                        dx(domain=mesh)))  #Spinodal part of chemical potential

                observables[field]['total_energy'] = parameters[
                    'D'] * observables[field]['gradient_energy'] + parameters[
                        'alpha'] * observables[field]['landau_energy']
                observables[field]['chi'] = parameters['alpha'] * observables[
                    field]['diffusion_energy'] - parameters['D'] * observables[
                        field]['spinodal_energy']

                # Phase observables
                sub_domains.set_all(0)
                sub_domains.array()[:] = np.where(array > 0.0, phases['p'],
                                                  phases['m'])

                phases_dxp = Measure('dx',
                                     domain=mesh,
                                     subdomain_data=sub_domains)
                for phase in phases:
                    dxp = phases_dxp(phases[phase])

                    observables[field]['Phi_0%s' % (phase)] = format(
                        assemble(1 * dxp))
                    observables[field]['Phi_1%s' % (phase)] = format(
                        assemble(fields[field] * dxp))
                    observables[field]['Phi_2%s' % (phase)] = format(
                        assemble(fields[field] * fields[field] * dxp))
                    observables[field]['Phi_3%s' % (phase)] = format(
                        assemble(fields[field] * fields[field] *
                                 fields[field] * dxp))
                    observables[field]['Phi_4%s' % (phase)] = format(
                        assemble(fields[field] * fields[field] *
                                 fields[field] * fields[field] * dxp))
                    observables[field]['Phi_5%s' % (phase)] = format(
                        assemble(fields[field] * fields[field] *
                                 fields[field] * fields[field] *
                                 fields[field] * dxp))

                    observables[field]['gradient_energy_%s' %
                                       (phase)] = format(
                                           assemble(
                                               0.5 *
                                               dot(grad(fields[field]),
                                                   grad(fields[field])) * dxp))
                    observables[field]['landau_energy_%s' % (phase)] = format(
                        assemble(potential[field] * dxp))
                    observables[field][
                        'total_energy_%s' %
                        (phase)] = parameters['D'] * observables[field][
                            'gradient_energy_%s' %
                            (phase)] + parameters['alpha'] * observables[
                                field]['landau_energy_%s' % (phase)]

                    observables[field][
                        'diffusion_energy_%s' % (phase)] = format(
                            assemble(
                                project(
                                    div(
                                        project(grad(fields[field]),
                                                V[field]['W'])), V[field]['Z'])
                                * dxp))  #Diffusion part of chemical potential
                    observables[field][
                        'spinodal_energy_%s' % (phase)] = format(
                            assemble(
                                potential_derivative[field] *
                                dxp))  #Spinodal part of chemical potential

                    observables[field][
                        'chi_%s' %
                        (phase)] = parameters['alpha'] * observables[field][
                            'spinodal_energy_%s' %
                            (phase)] - parameters['D'] * observables[field][
                                'diffusion_energy_%s' % (phase)]

                files['hdf5'].write(fields[field], '/%s' % (field), n)
                files['xdmf'].write(fields[field], n)

                fields_n[field].assign(fields[field])

                self.set_data({field: array})
                self.set_observables({field: observables[field]})

                flag[field] = eps(n, field, fields[field],
                                  self.get_observables(), tol[field])

            n += 1

        for file in files:
            files[file].close()

        return