Esempio n. 1
0
def initialise(dem, bounds, res):
    """
    Function to initialise the model space

    :param dem: 0 = no input DEM; 1 = input DEM
    :param bounds: west, south, east, north - if no DEM [0, 0, lx, ly]; if DEM [west, south, east, north]
    :param res: model resolution along the y-axis.
    :return model_space, u_n, mesh, V, bc:
    """

    if dem == 0:
        lx = bounds[1]
        ly = bounds[3]

        # Create mesh and define function space
        domain = Rectangle(Point(0, 0), Point(lx / ly, ly / ly))
        mesh = generate_mesh(domain, res)

        V = FunctionSpace(mesh, 'P', 1)

        # Define initial value
        u_D = Constant(0)
        eps = 10 / ly
        u_n = interpolate(u_D, V)
        u_n.vector().set_local(u_n.vector().get_local() +
                               eps * np.random.random(u_n.vector().size()))

    if dem == 1:
        u_n, lx, ly, mesh, V = read_dem(bounds, res)

    # boundary conditions

    class East(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], lx / ly)

    class West(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], 0.0)

    class North(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], ly / ly)

    class South(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], 0.0)

    # Should make this into an option!

    bc = [DirichletBC(V, u_n, West()), DirichletBC(V, u_n, East())]

    # def boundary(x, on_boundary):
    #   return on_boundary
    # bc = DirichletBC(V, u_n, boundary)

    model_space = [lx, ly, res]

    return model_space, u_n, mesh, V, bc
Esempio n. 2
0
    def solve(self, **arguments):

        t_start = time.clock()

        # definig Function space on this mesh using Lagrange
        #polynoimals of degree 1.
        H = FunctionSpace(self.mesh, "CG", 1)

        # Setting up the variational problem
        v = TrialFunction(H)
        w = TestFunction(H)

        coeff_dx2 = Constant(1)
        coeff_v = Constant(1)

        f = Expression("(4*pow(pi,2))*exp(-(1/coeff_v)*t)*sin(2*pi*x[0])",
                       {'coeff_v': coeff_v},
                       degree=2)

        v0 = Expression("sin(2*pi*x[0])", degree=2)

        f.t = 0

        def boundary(x, on_boundary):
            return on_boundary

        bc = DirichletBC(H, v0, boundary)

        v1 = interpolate(v0, H)
        dt = self.steps.time

        a = (dt * inner(grad(v), grad(w)) + dt * coeff_v * inner(v, w)) * dx
        L = (f * dt - coeff_v * v1) * w * dx

        A = assemble(a)
        v = Function(H)

        T = self.domain.time[-1]
        t = dt

        # solving the variational problem.
        while t <= T:
            b = assemble(L, tensor=b)
            vo.t = t
            bc.apply(A, b)

            solve(A, v.vector(), b)
            t += dt

            v1.assign(v)

        self.solution.extend(v.vector().array())

        return [self.solution, time.clock() - t_start]
Esempio n. 3
0
def dual_error_estimates(resolution):
    mesh = UnitSquareMesh(resolution, resolution)

    def all_boundary(_, on_boundary):
        return on_boundary

    zero = Constant(0.0)

    def a(u, v):
        return inner(grad(u), grad(v)) * dx

    def L(f, v):
        return f * v * dx

    # Primal problem
    f = Expression("32.*x[0]*(1. - x[0])+32.*x[1]*(1. - x[1])",
                   domain=mesh,
                   degree=5)
    ue = Expression("16.*x[0]*(1. - x[0])*x[1]*(1. - x[1])",
                    domain=mesh,
                    degree=5)

    Qp = FunctionSpace(mesh, 'CG', 1)
    bcp = DirichletBC(Qp, zero, all_boundary)

    u = TrialFunction(Qp)
    v = TestFunction(Qp)

    U = Function(Qp)
    solve(a(u, v) == L(f, v), U, bcp)

    # Dual problem
    Qd = FunctionSpace(mesh, 'CG', 2)
    psi = Constant(1.0)
    bcd = DirichletBC(Qd, zero, all_boundary)

    w = TestFunction(Qd)
    phi = TrialFunction(Qd)
    Phi = Function(Qd)
    solve(a(w, phi) == L(psi, w), Phi, bcd)

    # Compute errors
    e1 = compute_error(ue, U)
    e2 = assemble((inner(grad(U), grad(Phi)) - f * Phi) * dx)
    print("e1 = {}".format(e1))
    print("e2 = {}".format(e2))
def solve_wave_equation(u0, u1, u_boundary, f, domain, mesh, degree):
    """Solving the wave equation using CG-CG method.

    Args:
        u0: Initial data.
        u1: Initial velocity.
        u_boundary: Dirichlet boundary condition.
        f: Right-hand side.
        domain: Space-time domain.
        mesh: Computational mesh.
        degree: CG(degree) will be used as the finite element.
    Outputs:
        uh: Numerical solution.
    """
    # Element
    V = FunctionSpace(mesh, "CG", degree)
    # Measures on the initial and terminal slice
    mask = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0)
    domain.get_initial_slice().mark(mask, 1)
    ends = ds(subdomain_data=mask)
    # Form
    g = Constant(((-1.0, 0.0), (0.0, 1.0)))
    u = TrialFunction(V)
    v = TestFunction(V)
    a = dot(grad(v), dot(g, grad(u))) * dx
    L = f * v * dx + u1 * v * ends(1)
    # Assembled matrices
    A = assemble(a, keep_diagonal=True)
    b = assemble(L, keep_diagonal=True)
    # Spatial boundary condition
    bc = DirichletBC(V, u_boundary, domain.get_spatial_boundary())
    bc.apply(A, b)
    # Temporal boundary conditions (by hand)
    (A, b) = apply_time_boundary_conditions(domain, V, u0, A, b)
    # Solve
    solver = LUSolver()
    solver.set_operator(A)
    uh = Function(V)
    solver.solve(uh.vector(), b)
    return uh
Esempio n. 5
0
    def __init__(self,
                 grid_shape,
                 f,
                 init_z,
                 dirichlet,
                 degree=1,
                 polynomial_type='P',
                 reparam=True):
        """Parameters
        ----------
        grid_shape : numpy.array or list
            Defines the grid dimensions of the mesh used to solve the problem.
        f : str
            Source term of the Poisson equation in a form accepted by FEniCS (C++ style string)
        init_z : numpy.ndarray
            Placeholder value(s) for parameters of the model.
        dirichlet : str
            Dirichlet boundary conditions in string form accepted by FEniCS.
        degree : int, default 1
            Polynomial degree for the functional space.
        polynomial_type : str, default 'P'
            String encoding the type of polynomials in the functional space, according to FEniCS conventions
            (defaults to Lagrange polynomials).
        reparam: bool, default True
            Boolean indicating whether input parameters are to be reparametrized according to
            an inverse-logit transform.
        """
        def boundary(x, on_boundary):
            return on_boundary

        self.grid_shape = grid_shape
        self.mesh = UnitSquareMesh(*grid_shape)

        self.V = FunctionSpace(self.mesh, polynomial_type, degree)
        self.dirichlet = DirichletBC(self.V,
                                     Expression(dirichlet, degree=degree + 3),
                                     boundary)
        self._paramnames = ['param{}'.format(i) for i in range(len(init_z))]
        self.f = Expression(f,
                            degree=degree,
                            **dict(zip(self._paramnames, init_z)))
        u = TrialFunction(self.V)
        v = TestFunction(self.V)

        self.a = dot(grad(u), grad(v)) * dx
        self.L = self.f * v * dx
        self.u = Function(self.V)
        self.reparam = reparam
        self.solver = CountIt(solve)
#alpha method parameters

alpha_m = Constant(0.2)
alpha_f = Constant(0.4)
gamma = Constant(0.5 + alpha_f - alpha_m)
beta = Constant((gamma + 0.5)**2 / 4.)

#Loading by an Expression: sinus loading dependend on x_0
#p = Expression(('1*sin(2*pi*t) * x[0]','0'),degree=1, t=0)
#p = Expression( ('t<1 ? 0.01 : 0.01','0'),degree=1, t=0) #now precice coupling instead

force_boundary = AutoSubDomain(Neumann_Boundary)

# clamp the beam at the bottom
bc = DirichletBC(V, Constant((0, 0)), clamped_boundary)


#Define strain
def epsilon(u):
    return 0.5 * (nabla_grad(u) + nabla_grad(u).T)


# Define Stress tensor
def sigma(u):
    return lambda_ * nabla_div(u) * Identity(d) + 2 * mu * epsilon(u)


# Define Mass form
def m(u, v):
    return rho * inner(u, v) * dx
Esempio n. 7
0
    precice = Adapter(adapter_config_filename="precice-adapter-config-N.json")
    precice_dt = precice.initialize(coupling_boundary, read_function_space=V_g, write_object=u_D_function)

boundary_marker = False

dt = Constant(0)
dt.assign(np.min([fenics_dt, precice_dt]))

# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
f = Expression('beta + gamma*x[0]*x[0] - 2*gamma*t - 2*(1-gamma) - 2*alpha', degree=2, alpha=alpha,
               beta=beta, gamma=gamma, t=0)
F = u * v / dt * dx + dot(grad(u), grad(v)) * dx - (u_n / dt + f) * v * dx

bcs = [DirichletBC(V, u_D, remaining_boundary)]

# Set boundary conditions at coupling interface once wrt to the coupling expression
coupling_expression = precice.create_coupling_expression()
if problem is ProblemType.DIRICHLET:
    # modify Dirichlet boundary condition on coupling interface
    bcs.append(DirichletBC(V, coupling_expression, coupling_boundary))
if problem is ProblemType.NEUMANN:
    # modify Neumann boundary condition on coupling interface, modify weak form correspondingly
    if not boundary_marker:  # there is only 1 Neumann-BC which is at the coupling boundary -> integration over whole boundary
        if coupling_expression.is_scalar_valued():
            F += v * coupling_expression * dolfin.ds  # this term has to be added to weak form to add a Neumann BC (see e.g. p. 83ff Langtangen, Hans Petter, and Anders Logg. "Solving PDEs in Python The FEniCS Tutorial Volume I." (2016).)
        elif coupling_expression.is_vector_valued():
            normal = FacetNormal(mesh)
            F += -v * dot(normal, coupling_expression) * dolfin.ds
        else:
Esempio n. 8
0
def solve_linear_pde(
    u_D_array,
    T,
    D=1,
    C1=0,
    num_r=100,
    min_r=0.001,
    tol=1e-14,
    degree=1,
):
    # disable logging
    set_log_active(False)

    num_t = len(u_D_array)
    dt = T / num_t  # time step size

    mesh = IntervalMesh(num_r, min_r, 1)
    r = mesh.coordinates().flatten()
    r_args = np.argsort(r)
    V = FunctionSpace(mesh, "P", 1)

    # Define boundary conditions
    # Dirichlet condition at R
    def boundary_at_R(x, on_boundary):
        return on_boundary and near(x[0], 1, tol)

    D = Constant(D)
    u_D = Constant(u_D_array[0])
    bc_at_R = DirichletBC(V, u_D, boundary_at_R)

    # Define initial values for free c
    c_0 = Expression("C1", C1=C1, degree=degree)
    c_n = interpolate(c_0, V)

    # Define variational problem
    c = TrialFunction(V)
    v = TestFunction(V)

    # define Constants
    r_squ = Expression("4*pi*pow(x[0],2)", degree=degree)

    F_tmp = (D * dt * inner(grad(c), grad(v)) * r_squ * dx +
             c * v * r_squ * dx - c_n * v * r_squ * dx)
    a, L = lhs(F_tmp), rhs(F_tmp)
    u = Function(V)

    data_c = np.zeros((num_t, len(r)), dtype=np.double)

    for n in range(num_t):
        u_D.assign(u_D_array[n])

        # Compute solution
        solve(a == L, u, bc_at_R)
        data_c[n, :] = u.vector().vec().array

        c_n.assign(u)

    data_c = data_c[:, r_args[::-1]]
    r = r[r_args]

    return data_c, r
    def __init__(
            self, eval_times, n=10, lx=1., ly=.1, lz=.1,
            f=(0.0, 0.0, -50.), time=1., timestep=.1,
            tol=1e-5, max_iter=30, rel_tol=1e-10, param_remapper=None):
        """Parameters
        ----------
        eval_times: numpy.ndarray
            Times at which evaluation (interpolation) of the solution is required.
        n: int, default 10
            Dimension of the grid along the smallest side of the beam
            (the grid size along all other dimensions will be scaled proportionally.
        lx: float, default 1.
            Length of the beam along the x axis.
        ly: float, default .1
            Length of the beam along the y axis.
        lz: float, default .1
            Length of the beam along the z axis.
        f: tuple or numpy.ndarray, default (0.0, 0.0, -50.)
            Force per unit volume acting on the beam.
        time: float, default 1.
            Final time of the simulation.
        timestep: float, default 1.
            Time discretization step to solve the problem.
        tol: float, default 1e-5
            Tolerance parameter to ensure the last time step is included in the solution.
        max_iter: int, default 30
            Maximum iterations for the SNES solver.
        rel_tol: int,
            Relative tolerance for the convergence of the SNES solver.
        param_remapper: object, default None
            Either None (no remapping of the parameters), or a function remapping
            the parameter of the problem (Young's modulus) to values suitable for the
            definition of the solution.
        """
        # solver parameters
        self.solver = CountIt(solve)
        self.solver_parameters = {
            'nonlinear_solver': 'snes',
            'snes_solver': {
                'linear_solver': 'lu',
                'line_search': 'basic',
                'maximum_iterations': max_iter,
                'relative_tolerance': rel_tol,
                'report': False,
                'error_on_nonconvergence': False}}
        self.param_remapper = param_remapper

        # mesh creation
        self.n = n
        self.lx = lx
        self.ly = ly
        self.lz = lz

        min_len = min(lx, ly, lz)
        mesh_dims = (int(n * lx / min_len), int(n * ly / min_len), int(n * lz / min_len))
        self.mesh = BoxMesh(Point(0, 0, 0), Point(lx, ly, lz), *mesh_dims)
        self.V = VectorFunctionSpace(self.mesh, 'Lagrange', 1)

        # boundary conditions
        self.left = CompiledSubDomain('near(x[0], side) && on_boundary', side=0.0)
        self.right = CompiledSubDomain('near(x[0], side) && on_boundary', side=lx)
        self.top = CompiledSubDomain('near(x[2], side) && on_boundary', side=lz)

        self.boundaries = MeshFunction('size_t', self.mesh, self.mesh.topology().dim() - 1, 0)
        self.boundaries.set_all(0)
        self.left.mark(self.boundaries, 1)
        self.right.mark(self.boundaries, 2)
        self.top.mark(self.boundaries, 3)

        self.bcs1 = DirichletBC(self.V, Constant([0.0, 0.0, 0.0]), self.boundaries, 1)
        self.bcs2 = DirichletBC(self.V, Constant([0.0, 0.0, 0.0]), self.boundaries, 2)
        self.bcs = [self.bcs1, self.bcs2]

        # surface force
        self.f = Constant(f)
        self.ds = Measure('ds', domain=self.mesh, subdomain_data=self.boundaries)

        # evaluation times
        self.eval_times = eval_times
        self.dt = timestep
        self.T = time + tol
        self.times = np.arange(self.dt, self.T, self.dt)
        self.time = Expression('t', t=self.dt, degree=0)
Esempio n. 10
0
    inclusion = Inclusion_3d()
    point0 = "near(x[0], 0) && near(x[1], 0) && near(x[2], 0)"

V = FunctionSpace(mesh, "CG", order, constrained_domain=PeriodicBoundary(dim))

# setting the elements that lies in inclusion and in matrix phase
domains = MeshFunction("size_t", mesh, dim)
domains.set_all(0)
inclusion.mark(domains, 1)
dx = Measure('dx', subdomain_data=domains)


def bilf(up, vp):  # bilinear form
    return inner(mat * up, vp) * dx(0) + inner(inc * up, vp) * dx(1)


bc0 = DirichletBC(V, Constant(0.), point0, method='pointwise')

# SOLVER
u = TrialFunction(V)
v = TestFunction(V)
uE = Function(V)

solve(bilf(grad(u), grad(v)) == -bilf(E, grad(v)), uE, bcs=[bc0])

# POSTPROCESSING evaluation of guaranteed bound
AH11 = assemble(bilf(grad(uE) + E, grad(uE) + E))
print('homogenised component A11 = {} (FEM)'.format(AH11))

print('END')
Esempio n. 11
0
    def __init__(self,
                 mesh=None,
                 width=1.0,
                 dim=1,
                 nelements=8,
                 degree=2,
                 parameters={},
                 param_funcs={},
                 V=(lambda U, params={}: sum(U)),
                 U0=[],
                 rho0=None,
                 t0=0.0,
                 debug=False,
                 solver_type='petsc',
                 preconditioner_type='default',
                 periodic=True,
                 ligands=None):
        """Discontinuous Galerkin solver for the Keller-Segel PDE system

        Like KSDGSolverVariable, but with periodic boundary conditions.
        """
        logVARIABLE('creating KSDGSolverVariablePeriodic')
        if not ligands:
            ligands = LigandGroups()
        else:
            ligands = copy.deepcopy(ligands)
        self.args = dict(mesh=mesh,
                         width=width,
                         dim=dim,
                         nelements=nelements,
                         degree=degree,
                         parameters=parameters,
                         param_funcs=param_funcs,
                         V=V,
                         U0=U0,
                         rho0=rho0,
                         t0=t0,
                         debug=debug,
                         solver_type=solver_type,
                         preconditioner_type=preconditioner_type,
                         periodic=True,
                         ligands=ligands)
        self.t0 = t0
        self.debug = debug
        self.solver_type = solver_type
        self.preconditioner_type = preconditioner_type
        self.periodic = True
        self.ligands = ligands
        self.nligands = ligands.nligands()
        self.init_params(parameters, param_funcs)
        if nelements is None:
            self.nelements = 8
        else:
            self.nelements = nelements
        if (mesh):
            self.omesh = self.mesh = mesh
        else:
            self.omesh = self.mesh = box_mesh(width=width,
                                              dim=dim,
                                              nelements=self.nelements)
            self.nelements = nelements
        omeshstats = mesh_stats(self.omesh)
        try:
            comm = self.omesh.mpi_comm().tompi4py()
        except AttributeError:
            comm = self.omesh.mpi_comm()
        self.lmesh = gather_mesh(self.omesh)
        logVARIABLE('omeshstats', omeshstats)
        self.xmin = omeshstats['xmin']
        self.xmax = omeshstats['xmax']
        self.xmid = omeshstats['xmid']
        self.delta_ = omeshstats['dx']
        if nelements is None:
            self.nelements = (self.xmax - self.xmin) / self.delta_
        self.mesh = corner_submesh(self.lmesh)
        meshstats = mesh_stats(self.mesh)
        self.degree = degree
        self.dim = self.mesh.geometry().dim()
        #
        # Solution spaces and Functions
        #
        self.symmetries = evenodd_symmetries(self.dim)
        self.signs = [
            fe.as_matrix(np.diagflat(1.0 - 2.0 * eo)) for eo in self.symmetries
        ]
        self.eomat = evenodd_matrix(self.symmetries)
        fss = self.make_function_space()
        (self.SE, self.SS, self.VE,
         self.VS) = [fss[fs] for fs in ('SE', 'SS', 'VE', 'VS')]
        logVARIABLE('self.VS', self.VS)
        self.sol = Function(self.VS)  # sol, current soln
        logVARIABLE('self.sol', self.sol)
        splitsol = self.sol.split()
        self.srhos = splitsol[:2**self.dim]
        self.sUs = splitsol[2**self.dim:]
        splitsol = list(fe.split(self.sol))
        self.irhos = splitsol[:2**self.dim]
        self.iUs = splitsol[2**self.dim:]
        self.iPs = list(fe.split(self.PSf))
        self.iparams = collections.OrderedDict(zip(self.param_names, self.iPs))
        self.iligands = copy.deepcopy(self.ligands)
        self.iligand_params = ParameterList(
            [p for p in self.iligands.params() if p[0] in self.param_numbers])
        for k in self.iligand_params.keys():
            i = self.param_numbers[k]
            self.iligand_params[k] = self.iPs[i]
        tfs = list(TestFunctions(self.VS))
        self.wrhos, self.wUs = tfs[:2**self.dim], tfs[2**self.dim:]
        tfs = list(TrialFunctions(self.VS))
        self.tdrhos, self.tdUs = tfs[:2**self.dim], tfs[2**self.dim:]
        bc_method = 'geometric' if self.dim > 1 else 'pointwise'
        rhobcs = [
            DirichletBC(self.VS.sub(i),
                        Constant(0),
                        FacesDomain(self.mesh, self.symmetries[i]),
                        method=bc_method) for i in range(2**self.dim)
            if np.any(self.symmetries[i] != 0.0)
        ]
        Ubcs = list(
            itertools.chain(*[[
                DirichletBC(self.VS.sub(i + (lig + 1) * 2**self.dim),
                            Constant(0),
                            FacesDomain(self.mesh, self.symmetries[i]),
                            method=bc_method) for i in range(2**self.dim)
                if np.any(self.symmetries[i] != 0.0)
            ] for lig in range(self.nligands)]))
        self.bcs = rhobcs + Ubcs
        self.n = FacetNormal(self.mesh)
        self.h = CellDiameter(self.mesh)
        self.havg = fe.avg(self.h)
        self.dx = fe.dx
        self.dS = fe.dS
        #
        # record initial state
        #
        if not U0:
            U0 = [Constant(0.0)] * self.nligands
        self.U0s = [Constant(0.0)] * self.nligands
        for i, U0i in enumerate(U0):
            if isinstance(U0i, ufl.coefficient.Coefficient):
                self.U0s[i] = U0i
            else:
                self.U0s[i] = Expression(U0i,
                                         **self.params,
                                         degree=self.degree,
                                         domain=self.mesh)
        if not rho0:
            rho0 = Constant(0.0)
        if isinstance(rho0, ufl.coefficient.Coefficient):
            self.rho0 = rho0
        else:
            self.rho0 = Expression(rho0,
                                   **self.params,
                                   degree=self.degree,
                                   domain=self.mesh)
        self.set_time(t0)
        #
        # work out how to call V
        #
        try:
            V(self.U0s, self.rho0, params=self.iparams)

            def realV(Us, rho):
                return V(Us, rho, params=self.iparams)
        except TypeError:

            def realV(Us, rho):
                return V(Us, self.iparams)

        self.V = realV
        #
        # initialize state
        #
        self.restart()
        return None
    mesh = UnitSquareMesh(*grid_shape)
    V = FunctionSpace(mesh, 'P', poly_degree)
    # creates a grid_shape[0+1 x grid_shape[1]+1 vertices mesh with Lagrange polynomials of order order_degree

    # Define boundary condition
    u_D = Expression('1 + x[0]*x[0] + 2*x[1]*x[1]', degree=poly_degree + 3)

    # the expression accepts a string with commands in C++ style, that is then compiled for efficiency
    # the degree parameter specifies the polynomial degree for interpolation of the solution
    # if using the exact solution, the order should be at least a few units more than the functional space's elements


    def boundary(x, on_boundary):
        return on_boundary

    bc = DirichletBC(V, u_D, boundary)

    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    f = Constant(-6.0)
    a = dot(grad(u), grad(v)) * dx
    L = f * v * dx

    # Compute solution
    u = Function(V)
    solve(a == L, u, bc)
    # since u is created as a Function object, it can be evaluated at any new point - although
    # this is an expensive operation!

    # Compute error in L2 norm
Esempio n. 13
0
 def make_bcs(cls, V, surface_val, ground_val) -> List[DirichletBC]:
     bc1 = DirichletBC(V, Constant(ground_val), cls.ground_boundary)
     bc2 = DirichletBC(V, Constant(surface_val), cls.surface_boundary)
     return [bc1, bc2]
Esempio n. 14
0
def solid_problem(u_f, v_f, u_s, v_s,
                  fluid, solid, param, save = False):

    # Store old solutions
    u_s_n_K = Function(solid.V_split[0])
    v_s_n_K = Function(solid.V_split[1])
    u_s_n_K.assign(u_s.old)
    v_s_n_K.assign(v_s.old)
        
    # Store old boundary values
    v_s_n_i_K = Function(solid.V_split[1])
    v_s_n_i_K.assign(v_s.i_old)
    
    # Initialize interface values
    v_s_i = Function(solid.V_split[1])
    
    # Define Dirichlet boundary conditions
    bc_u_s_0 = DirichletBC(solid.V.sub(0), Constant(0.0), boundary)
    bc_v_s_0 = DirichletBC(solid.V.sub(1), Constant(0.0), boundary)
    bcs_s = [bc_u_s_0, bc_v_s_0]
            
    # Compute fractional steps for solid problem
    for k in range(param.K):
            
        # Update boundary values
        v_s_i.assign(project((param.K - k - 1.0)/param.K*v_s.i_old +
              + (k + 1.0)/param.K*fluid_to_solid(v_f.new,
              fluid, solid, param, 1), solid.V_split[1]))
                
        # Define trial and test functions
        U_s_new = TrialFunction(solid.V)
        (u_s_new, v_s_new) = split(U_s_new)
        Phi_s = TestFunction(solid.V)
        (phi_s, psi_s) = split(Phi_s)
                
        # Define scheme
        A_s = (v_s_new*phi_s*solid.dx
            + u_s_new*psi_s*solid.dx
            + 0.5*param.dt/param.K*a_s(u_s_new, v_s_new, phi_s, psi_s,
                                       solid, param))
        L_s = (v_s_n_K*phi_s*solid.dx 
            + u_s_n_K*psi_s*solid.dx 
            - 0.5*param.dt/param.K*a_s(u_s_n_K, v_s_n_K, phi_s, psi_s, 
                                       solid, param) 
            + 0.5*param.dt/param.K*param.nu*dot(grad(v_s_i), 
                                                solid.n)*phi_s*solid.ds 
            + 0.5*param.dt/param.K*param.nu*dot(grad(v_s_n_i_K),
                                                solid.n)*phi_s*solid.ds) 
                
        # Solve solid problem
        U_s_new = Function(solid.V)
        solve(A_s == L_s, U_s_new, bcs_s)
        (u_s_new, v_s_new) = U_s_new.split(U_s_new)
        
        # Append solutions to the arrays
        if save:
            
            u_s.array.append(u_s_new.copy(deepcopy = True))
            v_s.array.append(v_s_new.copy(deepcopy = True))
            
        # Update solid solution
        u_s_n_K.assign(u_s_new)
        v_s_n_K.assign(v_s_new)
                
        # Update boundary condition
        v_s_n_i_K.assign(project(v_s_i, solid.V_split[1]))
        
    # Save final values
    u_s.new.assign(u_s_new)
    v_s.new.assign(v_s_new)
    v_s.i_new.assign(v_s_i)
    
    return 
Esempio n. 15
0
def problem_mix(T, dt, E, coupling, VV, boundaries, rho_s, lambda_, mu_s, f,
                **Solid_namespace):
    # Temporal parameters
    t = 0
    k = Constant(dt)

    # Split problem to two 1.order differential equations
    psi, phi = TestFunctions(VV)

    # BCs
    bc1 = DirichletBC(VV.sub(0), ((0, 0)), boundaries, 1)
    bc2 = DirichletBC(VV.sub(1), ((0, 0)), boundaries, 1)
    bcs = [bc1, bc2]

    # Functions, wd is for holding the solution
    d_ = {}
    w_ = {}
    wd_ = {}
    for time in ["n", "n-1", "n-2", "n-3"]:
        if time == "n" and E not in [None, reference]:
            tmp_wd = Function(VV)
            wd_[time] = tmp_wd
            wd = TrialFunction(VV)
            w, d = split(wd)
        else:
            wd = Function(VV)
            wd_[time] = wd
            w, d = split(wd)

        d_[time] = d
        w_[time] = w

    # Time derivative
    if coupling == "center":
        G = rho_s / (2 * k) * inner(w_["n"] - w_["n-2"], psi) * dx
    else:
        G = rho_s / k * inner(w_["n"] - w_["n-1"], psi) * dx

    # Stress tensor
    G += inner(Piola2(d_, w_, k, lambda_, mu_s, E_func=E), grad(psi)) * dx

    # External forces, like gravity
    G -= inner(f, psi) * dx

    # d-w coupling
    if coupling == "CN":
        G += inner(d_["n"] - d_["n-1"] - k * 0.5 *
                   (w_["n"] + w_["n-1"]), phi) * dx
    elif coupling == "imp":
        G += inner(d_["n"] - d_["n-1"] - k * w_["n"], phi) * dx
    elif coupling == "exp":
        G += inner(d_["n"] - d_["n-1"] - k * w_["n-1"], phi) * dx
    elif coupling == "center":
        G += innter(d_["n"] - d_["n-2"] - 2 * k * w["n-1"], phi) * dx
    else:
        print "The coupling %s is not implemented, 'CN', 'imp', and 'exp' are the only valid choices."
        sys.exit(0)

    # Solve
    if E in [None, reference]:
        solver_nonlinear(G, d_, w_, wd_, bcs, T, dt, **Solid_namespace)
    else:
        solver_linear(G, d_, w_, wd_, bcs, T, dt, **Solid_namespace)
Esempio n. 16
0
fixed_boundary = AutoSubDomain(clamped_boundary)

precice = Adapter(adapter_config_filename="precice-adapter-config-fsi-s.json")

# Initialize the coupling interface
precice_dt = precice.initialize(coupling_boundary,
                                read_function_space=V,
                                write_object=V,
                                fixed_boundary=fixed_boundary)

fenics_dt = precice_dt  # if fenics_dt == precice_dt, no subcycling is applied
# fenics_dt = 0.02  # if fenics_dt < precice_dt, subcycling is applied
dt = Constant(np.min([precice_dt, fenics_dt]))

# clamp the beam at the bottom
bc = DirichletBC(V, Constant((0, 0)), fixed_boundary)

# alpha method parameters
alpha_m = Constant(0)
alpha_f = Constant(0)
gamma = Constant(0.5 + alpha_f - alpha_m)
beta = Constant((gamma + 0.5)**2 / 4.)


# Define strain
def epsilon(u):
    return 0.5 * (nabla_grad(u) + nabla_grad(u).T)


# Define Stress tensor
def sigma(u):
Esempio n. 17
0
# Create a FEniCS Expression to define and control the coupling boundary values
coupling_expression = precice.create_coupling_expression()

# Assigning appropriate dt
dt = Constant(0)
dt.assign(np.min([fenics_dt, precice_dt]))

# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
F = u * v / dt * dx + alpha * dot(grad(u), grad(v)) * dx - u_n * v / dt * dx

# apply constant Dirichlet boundary condition at bottom edge
# apply Dirichlet boundary condition on coupling interface
bcs = [
    DirichletBC(V, coupling_expression, coupling_boundary),
    DirichletBC(V, u_D, bottom_boundary)
]

a, L = lhs(F), rhs(F)

# Time-stepping
u_np1 = Function(V)
t = 0
u_D.t = t + dt

# mark mesh w.r.t ranks
ranks = File("output/ranks%s.pvd.pvd" % precice.get_participant_name())
mesh_rank = MeshFunction("size_t", mesh, mesh.topology().dim())
mesh_rank.set_all(MPI.rank(MPI.comm_world))
mesh_rank.rename("myRank", "")
Esempio n. 18
0
    # namely we iterate over (small) timesteps, each time solving a Poisson equation via finite elements

    T = 2.0  # final time
    num_steps = 50  # number of time steps
    dt = T / num_steps  # time step size

    # Create mesh and define function space
    nx = ny = 30
    mesh = RectangleMesh(Point(-2, -2), Point(2, 2), nx, ny)
    V = FunctionSpace(mesh, 'P', 1)

    # Define boundary condition
    def boundary(x, on_boundary):
        return on_boundary

    bc = DirichletBC(V, Constant(0), boundary)  # null Dirichlet conditions

    # Define initial value
    u_0 = Expression('exp(-a*pow(x[0], 2) - a*pow(x[1], 2))', degree=2, a=5)
    # the initial condition here is a "gaussian hill" of parameter alpha centered in the origin
    u_n = interpolate(u_0, V)
    # since we will be using iteratively the solution from the previous time step to compute the one
    # at the current time step, we need to convert the initial datum's expression to a Function object:
    # there are two ways to do this: either via the project() method or the interpolate() method;
    # projecy() is very popular, but since we have a closed form solution here we want to use interpolate()
    # in order to recover the exact solution within machine-error precision

    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    f = Constant(0)
Esempio n. 19
0
    def __init__(
            self,
            mesh=None,
            width=1.0,
            dim=1,
            nelements=8,
            degree=2,
            parameters={},
            V=(lambda U: U),
            U0=None,
            rho0=None,
            t0=0.0,
            debug=False,
            solver_type = 'lu',
            preconditioner_type = 'default',
            periodic=True,
            ligands=None
            ):
        """DG solver for the periodic Keller-Segel PDE system

        Keyword parameters:
        mesh=None: the mesh on which to solve the problem
        width=1.0: the width of the domain
        dim=1: # of spatial dimensions.
        nelements=8: If mesh is not supplied, one will be
        contructed using UnitIntervalMesh, UnitSquareMesh, or
        UnitCubeMesh (depending on dim). dim and nelements are not
        needed if mesh is supplied.
        degree=2: degree of the polynomial approximation
        parameters={}: a dict giving the values of scalar parameters of
            .V, U0, and rho0 Expressions. This dict needs to also
            define numerical parameters that appear in the PDE. Some
            of these have defaults:
            dim = dim: # of spatial dimensions
            sigma: organism movement rate
            s: attractant secretion rate
            gamma: attractant decay rate
            D: attractant diffusion constant
            rho_min=10.0**-7: minimum feasible worm density
            U_min=10.0**-7: minimum feasible attractant concentration
            rhopen=10: penalty for discontinuities in rho
            Upen=1: penalty for discontinuities in U
            grhopen=1, gUpen=1: penalties for discontinuities in gradients
        V=(lambda U: U): a callable taking two numerical arguments, U
            and rho, or a single argument, U, and returning a single
            number, V, the potential corresponding to U. Use fenics
            versions of mathematical functions, e.g. fe.ln, abs,
            fe.exp.
        U0, rho0: Expressions, Functions, or strs specifying the
            initial condition.
        t0=0.0: initial time
        solver_type='lu'
        preconditioner_type='default'
        periodic=True: Allowed for compatibility, but ignored
        ligands=None: ignored for compatibility
        """
        logPERIODIC('creating KSDGSolverPeriodic')
        self.args = dict(
            mesh=mesh,
            width=width,
            dim=dim,
            nelements=nelements,
            degree=degree,
            parameters=parameters,
            V=V,
            U0=U0,
            rho0=rho0,
            t0=t0,
            debug=debug,
            solver_type = solver_type,
            preconditioner_type = preconditioner_type,
            periodic=True,
            ligands=ligands
        )
        self.debug = debug
        self.solver_type = solver_type
        self.preconditioner_type = preconditioner_type
        self.periodic = True
        self.params = self.default_params.copy()
        #
        # Store the original mesh in self.omesh. self.mesh will be the
        # corner mesh.
        #
        if (mesh):
            self.omesh = mesh
        else:
            self.omesh = box_mesh(width=width, dim=dim, nelements=nelements)
            self.nelements = nelements
        try:
            comm = self.omesh.mpi_comm().tompi4py()
        except AttributeError:
            comm = self.omesh.mpi_comm()
        self.lmesh = gather_mesh(self.omesh)
        omeshstats = mesh_stats(self.omesh)
        logPERIODIC('omeshstats', omeshstats)
        self.xmin = omeshstats['xmin']
        self.xmax = omeshstats['xmax']
        self.xmid = omeshstats['xmid']
        self.delta_ = omeshstats['dx']
        self.mesh = corner_submesh(self.lmesh)
        meshstats = mesh_stats(self.mesh)
        logPERIODIC('meshstats', meshstats)
        logPERIODIC('self.omesh', self.omesh)
        logPERIODIC('self.mesh', self.mesh)
        logPERIODIC('self.mesh.mpi_comm().size', self.mesh.mpi_comm().size)
        self.nelements = nelements
        self.degree = degree
        self.dim = self.mesh.geometry().dim()
        self.params['dim'] = self.dim
        self.params.update(parameters)
        # 
        # Solution spaces and Functions
        #
        # The solution function space is a vector space with
        # 2*(2**dim) elements. The first 2**dim components are even
        # and odd parts of rho; These are followed by even and
        # odd parts of U. The array self.evenodd identifies even
        # and odd components. Each row is a length dim sequence 0s and
        # 1s and represnts one component. For instance, if evenodd[i]
        # is [0, 1, 0], then component i of the vector space is even
        # in dimensions 0 and 2 (x and z conventionally) and off in
        # dimension 1 (y).
        #
        self.symmetries = evenodd_symmetries(self.dim)
        self.signs = [fe.as_matrix(np.diagflat(1.0 - 2.0*eo))
                      for eo in self.symmetries]
        self.eomat = evenodd_matrix(self.symmetries)
        fss = self.make_function_space()
        (self.SE, self.SS, self.VE, self.VS) = [
            fss[fs] for fs in ('SE', 'SS', 'VE', 'VS')
        ]
        (self.SE, self.SS, self.VE, self.VS) = self.make_function_space()
        self.sol = Function(self.VS)                  # sol, current soln
        logPERIODIC('self.sol', self.sol)
        # srhos and sUs are fcuntions defiend on subspaces
        self.srhos = self.sol.split()[:2**self.dim]
        self.sUs = self.sol.split()[2**self.dim:]
        # irhos and iUs are Indexed UFL expressions
        self.irhos = fe.split(self.sol)[:2**self.dim]
        self.iUs = fe.split(self.sol)[2**self.dim:]
        self.wrhos = TestFunctions(self.VS)[: 2**self.dim]
        self.wUs = TestFunctions(self.VS)[2**self.dim :]
        self.tdsol = TrialFunction(self.VS) # time derivatives
        self.tdrhos = fe.split(self.tdsol)[: 2**self.dim]
        self.tdUs = fe.split(self.tdsol)[2**self.dim :]
        bc_method = 'geometric' if self.dim > 1 else 'pointwise'
        rhobcs = [DirichletBC(
            self.VS.sub(i),
            Constant(0),
            FacesDomain(self.mesh, self.symmetries[i]),
            method=bc_method
        ) for i in range(2**self.dim) if np.any(self.symmetries[i] != 0.0)]
        Ubcs = [DirichletBC(
            self.VS.sub(i + 2**self.dim),
            Constant(0),
            FacesDomain(self.mesh, self.symmetries[i]),
            method=bc_method
        ) for i in range(2**self.dim)  if np.any(self.symmetries[i] != 0.0)]
        self.bcs = rhobcs + Ubcs
        self.n = FacetNormal(self.mesh)
        self.h = CellDiameter(self.mesh)
        self.havg = fe.avg(self.h)
        self.dx = fe.dx
        self.dS = fe.dS
        #
        # record initial state
        #
        if not U0:
            U0 = Constant(0.0)
        if isinstance(U0, ufl.coefficient.Coefficient):
            self.U0 = U0
        else:
            self.U0 = Expression(U0, **self.params,
                                 degree=self.degree, domain=self.mesh)
        if not rho0:
            rho0 = Constant(0.0)
        if isinstance(rho0, ufl.coefficient.Coefficient):
            self.rho0 = rho0
        else:
            self.rho0 = Expression(rho0, **self.params,
                                   degree=self.degree, domain=self.mesh)
        try:
            V(self.U0, self.rho0)
            def realV(U, rho):
                return V(U, rho)
        except TypeError:
            def realV(U, rho):
                return V(U)
        self.V = realV
        self.t0 = t0
        #
        # initialize state
        #
        # cache assigners
        logPERIODIC('restarting')
        self.restart()
        logPERIODIC('restart returned')
        return(None)
Esempio n. 20
0
                                u_n=u_n,
                                dimension=dim,
                                dirichlet_boundary=clamped_boundary_domain)

fenics_dt = precice_dt  # if fenics_dt == precice_dt, no subcycling is applied
#fenics_dt = 0.02  # if fenics_dt < precice_dt, subcycling is applied
dt = Constant(np.min([precice_dt, fenics_dt]))

# generalized alpha method (time stepping) parameters
alpha_m = Constant(0.2)
alpha_f = Constant(0.4)
gamma = Constant(0.5 + alpha_f - alpha_m)
beta = Constant((gamma + 0.5)**2 * 0.25)

# clamp (u == 0) the beam at the left
bc = DirichletBC(V, Constant((0, 0)), left_boundary)


# Define strain
def epsilon(u):
    return 0.5 * (nabla_grad(u) + nabla_grad(u).T)


# Define Stress tensor
def sigma(u):
    return lambda_ * nabla_div(u) * Identity(dim) + 2 * mu * epsilon(u)


# Define Mass form
def m(u, v):
    return rho * inner(u, v) * dx
args = parser.parse_args()

if args.source:
    precice = Adapter(adapter_config_filename="precice-adapter-config-source.json")
elif args.drain:
    precice = Adapter(adapter_config_filename="precice-adapter-config-drain.json")

mesh = UnitSquareMesh(10, 10)
V = FunctionSpace(mesh, "P", 1)

u = TrialFunction(V)
v = TestFunction(V)
u_n = Function(V)
if args.source:
    u_ini = Expression("1", degree=1)
    bc = DirichletBC(V, u_ini, AllBoundary())
elif args.drain:
    u_ini = Expression("0", degree=1)
    bc = DirichletBC(V, u_ini, RightBoundary())


u_n = interpolate(u_ini, V)


dt = precice.initialize(AllDomain(), read_function_space=V, write_object=u_n)
volume_term = precice.create_coupling_expression()
f = Function(V)


dt_inv = Constant(1 / dt)
Esempio n. 22
0
f_N = Constant('0')
f_N_function = interpolate(f_N, V)

coupling_boundary = TopBoundary()
bottom_boundary = BottomBoundary()

# Define initial value
u_n = interpolate(u_D, V)
u_n.rename("T", "")

#start preCICE adapter
precice = Adapter()
precice_dt = precice.initialize(coupling_subdomain=coupling_boundary, mesh=mesh, read_field=u_D_function, write_field=f_N_function,
                   u_n=u_n)
dt = np.min([fenics_dt, precice_dt])  # todo we could also consider deciding on time stepping size inside the adapter
bcs = [DirichletBC(V, u_D, bottom_boundary)]

# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
F = u * v / dt * dx + alpha * dot(grad(u), grad(v)) * dx - u_n * v / dt * dx

# apply Dirichlet boundary condition on coupling interface
bcs.append(precice.create_coupling_dirichlet_boundary_condition(V))

a, L = lhs(F), rhs(F)

# Time-stepping
u_np1 = Function(V)
F_known_u = u_np1 * v / dt * dx + alpha * dot(grad(u_np1), grad(v)) * dx - u_n * v / dt * dx
t = 0
Esempio n. 23
0
    alpha=alpha,
    beta=beta,
    gamma=gamma,
    t=0)
u_D_function = interpolate(u_D, V)
# Define flux in x direction on coupling interface (grad(u_D) in normal direction)
f_N = Expression('2 * gamma*t*x[0] + 2 * (1-gamma)*x[0] ',
                 degree=1,
                 gamma=gamma,
                 t=0)
f_N_function = interpolate(f_N, V)

coupling_boundary = CouplingBoundary()
remaining_boundary = OuterBoundary()

bcs = [DirichletBC(V, u_D, remaining_boundary)]
# Define initial value
u_n = interpolate(u_D, V)
u_n.rename("Temperature", "")

precice = Adapter(adapter_config_filename,
                  interpolation_strategy=interpolation_strategy)

if problem is ProblemType.DIRICHLET:
    precice_dt = precice.initialize(coupling_subdomain=coupling_boundary,
                                    mesh=mesh,
                                    read_field=u_D_function,
                                    write_field=f_N_function,
                                    u_n=u_n)
elif problem is ProblemType.NEUMANN:
    precice_dt = precice.initialize(coupling_subdomain=coupling_boundary,
Esempio n. 24
0
def fluid_problem(u_f, v_f, u_s, v_s, fluid, solid, param, t, save=False):

    # Store old solutions
    u_f_n_M = Function(fluid.V_split[0])
    v_f_n_M = Function(fluid.V_split[1])
    u_f_n_M.assign(u_f.old)
    v_f_n_M.assign(v_f.old)

    # Store old boundary values
    u_f_n_i_M = Function(fluid.V_split[0])
    v_f_n_i_M = Function(fluid.V_split[1])
    u_f_n_i_M.assign(u_f.i_old)
    v_f_n_i_M.assign(v_f.i_old)

    # Initialize interface values
    u_f_i = Function(fluid.V_split[0])
    v_f_i = Function(fluid.V_split[1])

    # Define Dirichlet boundary conditions
    bc_u_f_0 = DirichletBC(fluid.V.sub(0), Constant(0.0), boundary)
    bc_v_f_0 = DirichletBC(fluid.V.sub(1), Constant(0.0), boundary)
    bcs_f = [bc_u_f_0, bc_v_f_0]

    # Compute fractional steps for fluid problem
    for m in range(param.M):

        # Update boundary values
        u_f_i.assign(
            project((param.M - m - 1.0) / param.M * u_f.i_old + (m + 1.0) /
                    param.M * solid_to_fluid(u_s.new, fluid, solid, param, 0),
                    fluid.V_split[0]))
        v_f_i.assign(
            project((param.M - m - 1.0) / param.M * v_f.i_old + (m + 1.0) /
                    param.M * solid_to_fluid(v_s.new, fluid, solid, param, 1),
                    fluid.V_split[1]))

        # Define trial and test functions
        U_f_new = TrialFunction(fluid.V)
        (u_f_new, v_f_new) = split(U_f_new)
        Phi_f = TestFunction(fluid.V)
        (phi_f, psi_f) = split(Phi_f)

        # Define scheme
        A_f = (v_f_new * phi_f * fluid.dx + 0.5 * param.dt / param.M *
               a_f(u_f_new, v_f_new, phi_f, psi_f, fluid, param))
        L_f = (v_f_n_M * phi_f * fluid.dx - 0.5 * param.dt / param.M *
               a_f(u_f_n_M, v_f_n_M, phi_f, psi_f, fluid, param) +
               0.5 * param.dt / param.M * param.gamma / fluid.h * u_f_i *
               psi_f * fluid.ds + 0.5 * param.dt / param.M * param.gamma /
               fluid.h * v_f_i * phi_f * fluid.ds + 0.5 * param.dt / param.M *
               param.gamma / fluid.h * u_f_n_i_M * psi_f * fluid.ds +
               0.5 * param.dt / param.M * param.gamma / fluid.h * v_f_n_i_M *
               phi_f * fluid.ds + param.dt / param.M * f(t) * phi_f * fluid.dx)

        # Solve fluid problem
        U_f_new = Function(fluid.V)
        solve(A_f == L_f, U_f_new, bcs_f)
        (u_f_new, v_f_new) = U_f_new.split(U_f_new)

        # Append solutions to the arrays
        if save:

            u_f.array.append(u_f_new.copy(deepcopy=True))
            v_f.array.append(v_f_new.copy(deepcopy=True))

        # Update fluid solution
        u_f_n_M.assign(u_f_new)
        v_f_n_M.assign(v_f_new)

        # Update boundary conditions
        u_f_n_i_M.assign(project(u_f_i, fluid.V_split[0]))
        v_f_n_i_M.assign(project(v_f_i, fluid.V_split[1]))

    # Save final values
    u_f.new.assign(u_f_new)
    v_f.new.assign(v_f_new)
    u_f.i_new.assign(u_f_i)
    v_f.i_new.assign(v_f_i)

    return