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
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
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
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)
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
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
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
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
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)
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
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
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})
#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)