Пример #1
0
    def _forward_solve(self, lhs, rhs, func, bcs, **kwargs):
        solver = self.block_helper.forward_solver
        if solver is None:
            solver = backend.KrylovSolver(self.method, self.preconditioner)
            if self.assemble_system:
                A, _ = backend.assemble_system(lhs, rhs, bcs)
                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P, _ = backend.assemble_system(P, rhs, bcs)
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)
            else:
                A = compat.assemble_adjoint_value(lhs)
                [bc.apply(A) for bc in bcs]
                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P = compat.assemble_adjoint_value(P)
                    [bc.apply(P) for bc in bcs]
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)
            self.block_helper.forward_solver = solver

        if self.assemble_system:
            system_assembler = backend.SystemAssembler(lhs, rhs, bcs)
            b = backend.Function(self.function_space).vector()
            system_assembler.assemble(b)
        else:
            b = compat.assemble_adjoint_value(rhs)
            [bc.apply(b) for bc in bcs]

        solver.parameters.update(self.krylov_solver_parameters)
        solver.solve(func.vector(), b)
        return func
Пример #2
0
    def _assemble_and_solve_adj_eq(self, dFdu_adj_form, dJdu, compute_bdy):
        dJdu_copy = dJdu.copy()
        bcs = self._homogenize_bcs()

        solver = self.block_helper.adjoint_solver
        if solver is None:
            solver = backend.KrylovSolver(self.method, self.preconditioner)

            if self.assemble_system:
                rhs_bcs_form = backend.inner(
                    backend.Function(self.function_space),
                    dFdu_adj_form.arguments()[0]) * backend.dx
                A, _ = backend.assemble_system(dFdu_adj_form, rhs_bcs_form,
                                               bcs)

                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P, _ = backend.assemble_system(P, rhs_bcs_form, bcs)
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)
            else:
                A = compat.assemble_adjoint_value(dFdu_adj_form)
                [bc.apply(A) for bc in bcs]

                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P = compat.assemble_adjoint_value(P)
                    [bc.apply(P) for bc in bcs]
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)

            self.block_helper.adjoint_solver = solver

        solver.parameters.update(self.krylov_solver_parameters)
        [bc.apply(dJdu) for bc in bcs]

        adj_sol = backend.Function(self.function_space)
        solver.solve(adj_sol.vector(), dJdu)

        adj_sol_bdy = None
        if compute_bdy:
            adj_sol_bdy = compat.function_from_vector(
                self.function_space, dJdu_copy - compat.assemble_adjoint_value(
                    backend.action(dFdu_adj_form, adj_sol)))

        return adj_sol, adj_sol_bdy
Пример #3
0
def _assemble_petsc_system(A_form, b_form, bcs=None):
	"""Assembles a system symmetrically and converts objects to PETSc format.

	Parameters
	----------
	A_form : ufl.form.Form
		The UFL form for the left-hand side of the linear equation.
	b_form : ufl.form.Form
		The UFL form for the right-hand side of the linear equation.
	bcs : None or dolfin.fem.dirichletbc.DirichletBC or list[dolfin.fem.dirichletbc.DirichletBC]
		A list of Dirichlet boundary conditions.

	Returns
	-------
	petsc4py.PETSc.Mat
		The petsc matrix for the left-hand side of the linear equation.
	petsc4py.PETSc.Vec
		The petsc vector for the right-hand side of the linear equation.

	Notes
	-----
	This function always uses the ident_zeros method of the matrix in order to add a one to the diagonal
	in case the corresponding row only consists of zeros. This allows for well-posed problems on the
	boundary etc.
	"""

	A, b = fenics.assemble_system(A_form, b_form, bcs, keep_diagonal=True)
	A.ident_zeros()

	A = fenics.as_backend_type(A).mat()
	b = fenics.as_backend_type(b).vec()

	return A, b
Пример #4
0
    def eva(self, num):
        # construct basis functions, Set num points corresponding to num basis functions
        basPoints = np.linspace(0, 1, num)
        dx = basPoints[1] - basPoints[0]
        aa, bb, cc = -dx, 0.0, dx
        for x_p in basPoints:
            self.theta.append(
                fe.interpolate(
                    fe.Expression(
                        'x[0] < a || x[0] > c ? 0 : (x[0] >=a && x[0] <= b ? (x[0]-a)/(b-a) : 1-(x[0]-b)/(c-b))',
                        degree=2,
                        a=aa,
                        b=bb,
                        c=cc), self.Vc))
            aa, bb, cc = aa + dx, bb + dx, cc + dx

        u_trial, u_test = fe.TrialFunction(self.Vu), fe.TestFunction(self.Vu)
        left = fe.inner(self.al * fe.nabla_grad(u_trial),
                        fe.nabla_grad(u_test)) * fe.dx
        right = self.f * u_test * fe.dx

        def boundaryD(x, on_boundary):
            return on_boundary and fe.near(x[1], 1.0)

        for i in range(num):
            uH = fe.Function(self.Vu)
            bcD = fe.DirichletBC(self.Vu, self.theta[i], boundaryD)
            left_m, right_m = fe.assemble_system(left, right, bcD)
            fe.solve(left_m, uH.vector(), right_m)
            self.sol.append(uH)
Пример #5
0
    def _assemble_and_solve_adj_eq(self, dFdu_adj_form, dJdu, compute_bdy):
        dJdu_copy = dJdu.copy()
        bcs = self._homogenize_bcs()

        solver = self.block_helper.adjoint_solver
        if solver is None:
            if self.assemble_system:
                rhs_bcs_form = backend.inner(backend.Function(self.function_space),
                                             dFdu_adj_form.arguments()[0]) * backend.dx
                A, _ = backend.assemble_system(dFdu_adj_form, rhs_bcs_form, bcs)
            else:
                A = compat.assemble_adjoint_value(dFdu_adj_form)
                [bc.apply(A) for bc in bcs]

            solver = backend.LUSolver(A, self.method)
            self.block_helper.adjoint_solver = solver

        solver.parameters.update(self.lu_solver_parameters)
        [bc.apply(dJdu) for bc in bcs]

        adj_sol = backend.Function(self.function_space)
        solver.solve(adj_sol.vector(), dJdu)

        adj_sol_bdy = None
        if compute_bdy:
            adj_sol_bdy = compat.function_from_vector(self.function_space, dJdu_copy - compat.assemble_adjoint_value(
                backend.action(dFdu_adj_form, adj_sol)))

        return adj_sol, adj_sol_bdy
Пример #6
0
    def _forward_solve(self, lhs, rhs, func, bcs, **kwargs):
        solver = self.block_helper.forward_solver
        if solver is None:
            if self.assemble_system:
                A, _ = backend.assemble_system(lhs, rhs, bcs,
                                               **self.assemble_kwargs)
            else:
                A = compat.assemble_adjoint_value(lhs, **self.assemble_kwargs)
                [bc.apply(A) for bc in bcs]

            solver = backend.LUSolver(A, self.method)
            self.block_helper.forward_solver = solver

        if self.assemble_system:
            system_assembler = backend.SystemAssembler(lhs, rhs, bcs)
            b = backend.Function(self.function_space).vector()
            system_assembler.assemble(b)
        else:
            b = compat.assemble_adjoint_value(rhs)
            [bc.apply(b) for bc in bcs]

        if self.ident_zeros_tol is not None:
            A.ident_zeros(self.ident_zeros_tol)

        solver.parameters.update(self.lu_solver_parameters)
        solver.solve(func.vector(), b)
        return func
Пример #7
0
 def __init__(self, problem: ProblemForm, fields: Fields,
              boundary_conditions: List[fenics.DirichletBC]):
     super().__init__(problem, fields, boundary_conditions)
     self.a_form = problem.get_weak_form_lhs(fields=fields)
     self.L_form = problem.get_weak_form_rhs(fields=fields)
     self.boundary_conditions = boundary_conditions
     self.K, _ = fenics.assemble_system(self.a_form, self.L_form,
                                        self.boundary_conditions)
     self.solver = fenics.LUSolver(self.K, "mumps")
     self.solver.parameters["symmetric"] = True
Пример #8
0
def calTrueSol(para):
    nx, ny = para['mesh_N'][0], para['mesh_N'][1]
    mesh = fe.UnitSquareMesh(nx, ny)
    Vu = fe.FunctionSpace(mesh, 'P', para['P'])
    Vc = fe.FunctionSpace(mesh, 'P', para['P'])
    al = fe.Constant(para['alpha'])
    f = fe.Expression(para['f'], degree=5)
    q1 = fe.interpolate(fe.Expression(para['q1'], degree=5), Vc)
    q2 = fe.interpolate(fe.Expression(para['q2'], degree=5), Vc)
    q3 = fe.interpolate(fe.Expression(para['q3'], degree=5), Vc)
    theta = fe.interpolate(fe.Expression(para['q4'], degree=5), Vc)

    class BoundaryX0(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[0], 0.0)

    class BoundaryX1(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[0], 1.0)

    class BoundaryY0(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[1], 0.0)

    class BoundaryY1(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[1], 1.0)

    boundaries = fe.MeshFunction('size_t', mesh, mesh.topology().dim() - 1)
    boundaries.set_all(0)
    bc0, bc1, bc2, bc3 = BoundaryX0(), BoundaryX1(), BoundaryY0(), BoundaryY1()
    bc0.mark(boundaries, 1)
    bc1.mark(boundaries, 2)
    bc2.mark(boundaries, 3)
    bc3.mark(boundaries, 4)

    domains = fe.MeshFunction("size_t", mesh, mesh.topology().dim())
    domains.set_all(0)

    bcD = fe.DirichletBC(Vu, theta, boundaries, 4)
    dx = fe.Measure('dx', domain=mesh, subdomain_data=domains)
    ds = fe.Measure('ds', domain=mesh, subdomain_data=boundaries)

    u_trial, u_test = fe.TrialFunction(Vu), fe.TestFunction(Vu)
    u = fe.Function(Vu)
    left = fe.inner(al * fe.nabla_grad(u_trial), fe.nabla_grad(u_test)) * dx
    right = f * u_test * dx + (q1 * u_test * ds(1) + q2 * u_test * ds(2) +
                               q3 * u_test * ds(3))

    left_m, right_m = fe.assemble_system(left, right, bcD)
    fe.solve(left_m, u.vector(), right_m)

    return u
Пример #9
0
    def eva(self):
        # construct solutions corresponding to the basis functions
        class BoundaryX0(fe.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and fe.near(x[0], 0.0)

        class BoundaryX1(fe.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and fe.near(x[0], 1.0)

        class BoundaryY0(fe.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and fe.near(x[1], 0.0)

        class BoundaryY1(fe.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and fe.near(x[1], 1.0)

        boundaries = fe.MeshFunction('size_t', self.mesh,
                                     self.mesh.topology().dim() - 1)
        boundaries.set_all(0)
        bc0, bc1, bc2, bc3 = BoundaryX0(), BoundaryX1(), BoundaryY0(
        ), BoundaryY1()
        bc0.mark(boundaries, 1)
        bc1.mark(boundaries, 2)
        bc2.mark(boundaries, 3)
        bc3.mark(boundaries, 4)

        domains = fe.MeshFunction("size_t", self.mesh,
                                  self.mesh.topology().dim())
        domains.set_all(0)

        dx = fe.Measure('dx', domain=self.mesh, subdomain_data=domains)
        ds = fe.Measure('ds', domain=self.mesh, subdomain_data=boundaries)

        u_trial, u_test = fe.TrialFunction(self.Vu), fe.TestFunction(self.Vu)
        left = fe.inner(fe.nabla_grad(u_trial), fe.nabla_grad(u_test)) * dx
        right = self.f * u_test * dx + (self.q1 * u_test * ds(1) +
                                        self.q2 * u_test * ds(2) +
                                        self.q3 * u_test * ds(3))
        bcD = fe.DirichletBC(self.Vu, self.theta, boundaries, 4)
        left_m, right_m = fe.assemble_system(left, right, bcD)
        fe.solve(left_m, self.u.vector(), right_m)
Пример #10
0
 def _get_solvers_and_y():
     if not bilinear_form_is_symmetric:
         # Homogenized and original boundary conditions have equivalent effect on matrix
         # corresponding to assembled bilinear form
         A_solver = construct_solver(A, boundary_conditions)
         b_vector = fenics.assemble(b)
         adjoint_A_solver = construct_solver(
             adjoint_A, homogenized_boundary_conditions)
         solve_with_boundary_conditions(A_solver, boundary_conditions,
                                        b_vector, x)
     else:
         A_matrix, b_vector = fenics.assemble_system(
             A, b, boundary_conditions)
         A_solver = fenics.LUSolver(A_matrix)
         A_solver.parameters["symmetric"] = True
         adjoint_A_solver = A_solver  # A is symmetric therefore adjoint(A) == A
         A_solver.solve(x.vector(), b_vector)
     y = (x.vector()).get_local()[observation_dof_indices]
     return A_solver, adjoint_A_solver, y
Пример #11
0
u_np1.rename("Displacement", "")
displacement_out << u_n

while precice.is_coupling_ongoing():

    if precice.is_action_required(
            precice.action_write_iteration_checkpoint()):  # write checkpoint
        precice.store_checkpoint(u_n, t, n)

    # read data from preCICE and get a new coupling expression
    read_data = precice.read_data()

    # Update the point sources on the coupling boundary with the new read data
    Forces_x, Forces_y = precice.get_point_sources(read_data)

    A, b = assemble_system(a_form, L_form, bc)

    b_forces = b.copy(
    )  # b is the same for every iteration, only forces change

    for ps in Forces_x:
        ps.apply(b_forces)
    for ps in Forces_y:
        ps.apply(b_forces)

    assert (b is not b_forces)
    solve(A, u_np1.vector(), b_forces)

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

    # Write new displacements to preCICE
Пример #12
0
def navierStokes(projectId, mesh, faceSets, boundarySets, config):

    log("Navier Stokes Analysis has started")

    # this is the default directory, when user request for download all files in this directory is being compressed and sent to the user
    resultDir = "./Results/"

    if len(config["steps"]) > 1:
        return "more than 1 step is not supported yet"

    # config is a dictionary containing all the user inputs for solver configurations
    t_init = 0.0
    t_final = float(config['steps'][0]["finalTime"])
    t_num = int(config['steps'][0]["iterationNo"])
    dt = ((t_final - t_init) / t_num)
    t = t_init

    #
    #  Viscosity coefficient.
    #
    nu = float(config['materials'][0]["viscosity"])
    rho = float(config['materials'][0]["density"])

    #
    #  Declare Finite Element Spaces
    # do not use triangle directly
    P2 = fn.VectorElement("P", mesh.ufl_cell(), 2)
    P1 = fn.FiniteElement("P", mesh.ufl_cell(), 1)
    TH = fn.MixedElement([P2, P1])
    V = fn.VectorFunctionSpace(mesh, "P", 2)
    Q = fn.FunctionSpace(mesh, "P", 1)
    W = fn.FunctionSpace(mesh, TH)

    #
    #  Declare Finite Element Functions
    #
    (u, p) = fn.TrialFunctions(W)
    (v, q) = fn.TestFunctions(W)
    w = fn.Function(W)
    u0 = fn.Function(V)
    p0 = fn.Function(Q)

    #
    # Macros needed for weak formulation.
    #
    def contract(u, v):
        return fn.inner(fn.nabla_grad(u), fn.nabla_grad(v))

    def b(u, v, w):
        return 0.5 * (fn.inner(fn.dot(u, fn.nabla_grad(v)), w) -
                      fn.inner(fn.dot(u, fn.nabla_grad(w)), v))

    # Define boundaries
    bcs = []
    for BC in config['BCs']:
        if BC["boundaryType"] == "wall":
            for edge in json.loads(BC["edges"]):
                bcs.append(
                    fn.DirichletBC(W.sub(0),
                                   fn.Constant((0.0, 0.0, 0.0)),
                                   boundarySets,
                                   int(edge),
                                   method='topological'))
        if BC["boundaryType"] == "inlet":
            vel = json.loads(BC['value'])
            for edge in json.loads(BC["edges"]):
                bcs.append(
                    fn.DirichletBC(W.sub(0),
                                   fn.Expression(
                                       (str(vel[0]), str(vel[1]), str(vel[2])),
                                       degree=2),
                                   boundarySets,
                                   int(edge),
                                   method='topological'))
        if BC["boundaryType"] == "outlet":
            for edge in json.loads(BC["edges"]):
                bcs.append(
                    fn.DirichletBC(W.sub(1),
                                   fn.Constant(float(BC['value'])),
                                   boundarySets,
                                   int(edge),
                                   method='topological'))

    f = fn.Constant((0.0, 0.0, 0.0))

    #  weak form NSE
    NSE = (1.0/dt)*fn.inner(u, v)*fn.dx + b(u0, u, v)*fn.dx + nu * \
        contract(u, v)*fn.dx - fn.div(v)*p*fn.dx + q*fn.div(u)*fn.dx
    LNSE = fn.inner(f, v) * fn.dx + (1. / dt) * fn.inner(u0, v) * fn.dx

    velocity_file = fn.XDMFFile(resultDir + "/vel.xdmf")
    pressure_file = fn.XDMFFile(resultDir + "/pressure.xdmf")
    velocity_file.parameters["flush_output"] = True
    velocity_file.parameters["functions_share_mesh"] = True
    pressure_file.parameters["flush_output"] = True
    pressure_file.parameters["functions_share_mesh"] = True
    #
    # code for projecting a boundary condition into a file for visualization
    #
    # for bc in bcs:
    #     bc.apply(w.vector())
    # fn.File("para_plotting/bc.pvd") << w.sub(0)

    for jj in range(0, t_num):
        t = t + dt
        # print('t = ' + str(t))
        A, b = fn.assemble_system(NSE, LNSE, bcs)
        fn.solve(A, w.vector(), b)
        # fn.solve(NSE==LNSE,w,bcs)
        fn.assign(u0, w.sub(0))
        fn.assign(p0, w.sub(1))
        # Save Solutions to Paraview File
        if (jj % 20 == 0):
            velocity_file.write(u0, t)
            pressure_file.write(p0, t)
            sendFile(projectId, resultDir + "vel.xdmf")
            sendFile(projectId, resultDir + "vel.h5")
            sendFile(projectId, resultDir + "pressure.xdmf")
            sendFile(projectId, resultDir + "pressure.h5")
            statusUpdate(projectId, "STARTED", {"progress": jj / t_num * 100})
Пример #13
0
#Tiempos intermedio entre tn y tn+1 utilizando modelo alfa generalizado
def avg(x_old, x_new, alpha):
    return alpha * x_old + (1 - alpha) * x_new


#Formulación variacional
a_new = update_a(du, u_old, v_old, a_old, ufl=True)
v_new = update_v(a_new, u_old, v_old, a_old, ufl=True)
res = m(avg(a_old, a_new, alpha_m), w) + c(avg(v_old, v_new, alpha_f), w) + k(
    avg(u_old, du, alpha_f), w) - Wext(w)
a_form = fnc.lhs(res)
L_form = fnc.rhs(res)

#Solvers (veremos luego)
K, res = fnc.assemble_system(a_form, L_form, bc)
solver = fnc.LUSolver(K, 'default')  #"mumps")
solver.parameters["symmetric"] = True

# We now initiate the time stepping loop. We will keep track of the beam vertical tip
# displacement over time as well as the different parts of the system total energy. We
# will also compute the stress field and save it, along with the displacement field, in
# a ``XDMFFile``.
# The option `flush_ouput` enables to open the result file before the loop is finished,
# the ``function_share_mesh`` option tells that only one mesh is used for all functions
# of a given time step (displacement and stress) while the ``rewrite_function_mesh`` enforces
# that the same mesh is used for all time steps. These two options enables writing the mesh
# information only once instead of :math:`2N_{steps}` times::

# Time-stepping
time = np.linspace(0, T, Nsteps + 1)