def __init__(self, cfgfile, runid=None, cfg=None): super().__init__(cfgfile, runid, cfg) if PETSc.COMM_WORLD.getRank() == 0: print("Creating solver objects.") # create solver objects # self.vlasov_solver = self.vlasov_object.PETScVlasovSolver( self.vlasov_solver = PETScVlasovSolver(self.da1, self.grid, self.h0, self.h1c, self.h1h, self.h2c, self.h2h, self.charge, coll_freq=self.coll_freq) self.vlasov_solver.set_moments(self.nc, self.uc, self.ec, self.ac, self.nh, self.uh, self.eh, self.ah) # initialise Jacobian self.J = self.da1.createMat() self.J.setOption(self.J.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.J.setUp() # create nonlinear predictor solver self.snes = PETSc.SNES().create() self.snes.setType('ksponly') self.snes.setFunction(self.vlasov_solver.function_snes_mult, self.fb) self.snes.setJacobian(self.updateVlasovJacobian, self.J) self.snes.setFromOptions() self.snes.getKSP().setType('preonly') self.snes.getKSP().getPC().setType('lu') self.snes.getKSP().getPC().setFactorSolverPackage( self.cfg['solver']['lu_package']) # create Poisson matrix and object self.poisson_matrix = self.dax.createMat() self.poisson_matrix.setUp() self.poisson_matrix.setNullSpace(self.p_nullspace) self.poisson_solver = self.poisson_object.PETScPoissonSolver( self.dax, self.grid.nx, self.grid.hx, self.charge) self.poisson_solver.formMat(self.poisson_matrix) # create linear Poisson solver self.poisson_ksp = PETSc.KSP().create() self.poisson_ksp.setFromOptions() self.poisson_ksp.setOperators(self.poisson_matrix) self.poisson_ksp.setType('preonly') self.poisson_ksp.getPC().setType('lu') self.poisson_ksp.getPC().setFactorSolverPackage( self.cfg['solver']['lu_package']) if PETSc.COMM_WORLD.getRank() == 0: print("Run script initialisation done.") print("")
def blocked_solve(): """Blocked version""" Jmat = create_matrix_block(J) Fvec = create_vector_block(F) snes = PETSc.SNES().create(MPI.COMM_WORLD) snes.setTolerances(rtol=1.0e-15, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().getPC().setType("lu") problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs) snes.setFunction(problem.F_block, Fvec) snes.setJacobian(problem.J_block, J=Jmat, P=None) u.interpolate(initial_guess_u) p.interpolate(initial_guess_p) x = create_vector_block(F) scatter_local_vectors(x, [u.vector.array_r, p.vector.array_r], [(u.function_space.dofmap.index_map, u.function_space.dofmap.index_map_bs), (p.function_space.dofmap.index_map, p.function_space.dofmap.index_map_bs)]) x.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) snes.solve(None, x) assert snes.getKSP().getConvergedReason() > 0 assert snes.getConvergedReason() > 0 return x.norm()
def help(args=None): import sys, shlex # program name try: prog = sys.argv[0] except Exception: prog = getattr(sys, 'executable', 'python') # arguments if args is None: args = sys.argv[1:] elif isinstance(args, str): args = shlex.split(args) else: args = [str(a) for a in args] # import and initialize import petsc4py petsc4py.init([prog, '-help'] + args) from petsc4py import PETSc # help dispatcher COMM = PETSc.COMM_SELF if 'vec' in args: vec = PETSc.Vec().create(comm=COMM) vec.setSizes(0) vec.setFromOptions() vec.destroy() if 'mat' in args: mat = PETSc.Mat().create(comm=COMM) mat.setSizes([0, 0]) mat.setFromOptions() mat.destroy() if 'pc' in args: pc = PETSc.PC().create(comm=COMM) pc.setFromOptions() pc.destroy() if 'ksp' in args: ksp = PETSc.KSP().create(comm=COMM) ksp.setFromOptions() ksp.destroy() if 'snes' in args: snes = PETSc.SNES().create(comm=COMM) snes.setFromOptions() snes.destroy() if 'ts' in args: ts = PETSc.TS().create(comm=COMM) ts.setFromOptions() ts.destroy() if 'tao' in args: tao = PETSc.TAO().create(comm=COMM) tao.setFromOptions() tao.destroy() if 'dmda' in args: dmda = PETSc.DMDA().create(comm=COMM) dmda.setFromOptions() dmda.destroy() if 'dmplex' in args: dmplex = PETSc.DMPlex().create(comm=COMM) dmplex.setFromOptions() dmplex.destroy()
def __init__(self, scheme): self.model = scheme.model self.res = scheme.space.interpolate([0],name="residual") self.scheme = scheme self.jacobian = linearOperator(self.scheme) self.snes = PETSc.SNES().create() self.snes.setFunction(self.f, self.res.as_petsc.duplicate()) self.snes.setUseMF(False) self.snes.setJacobian(self.Df, self.jacobian.as_petsc, self.jacobian.as_petsc) self.snes.getKSP().setType("cg") self.snes.setFromOptions()
def test_nonlinear_pde_snes(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 12, 15) V = function.FunctionSpace(mesh, ("Lagrange", 1)) u = function.Function(V) v = TestFunction(V) F = inner(5.0, v) * dx - ufl.sqrt(u * u) * inner( grad(u), grad(v)) * dx - inner(u, v) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[0] < 1.0e-8, x[0] > 1.0 - 1.0e-8) u_bc = function.Function(V) u_bc.vector.set(1.0) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) bc = fem.DirichletBC(u_bc, fem.locate_dofs_geometrical(V, boundary)) # Create nonlinear problem problem = NonlinearPDE_SNESProblem(F, u, bc) u.vector.set(0.9) u.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) b = dolfinx.cpp.la.create_vector(V.dofmap.index_map) J = dolfinx.cpp.fem.create_matrix(problem.a_comp._cpp_object) # Create Newton solver and solve snes = PETSc.SNES().create() snes.setFunction(problem.F, b) snes.setJacobian(problem.J, J) snes.setTolerances(rtol=1.0e-9, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().setTolerances(rtol=1.0e-9) snes.getKSP().getPC().setType("lu") snes.getKSP().getPC().setFactorSolverType("superlu_dist") snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6 # Modify boundary condition and solve again u_bc.vector.set(0.5) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6
def monolithic_solve(): """Monolithic version""" E = P * P W = FunctionSpace(mesh, E) U = Function(W) dU = ufl.TrialFunction(W) u0, u1 = ufl.split(U) v0, v1 = ufl.TestFunctions(W) F = inner((u0**2 + 1) * ufl.grad(u0), ufl.grad(v0)) * dx \ + inner((u1**2 + 1) * ufl.grad(u1), ufl.grad(v1)) * dx \ - inner(f, v0) * ufl.dx - inner(g, v1) * dx J = derivative(F, U, dU) F, J = form(F), form(J) u0_bc = Function(V0) u0_bc.interpolate(bc_val_0) u1_bc = Function(V1) u1_bc.interpolate(bc_val_1) bdofsW0_V0 = locate_dofs_topological((W.sub(0), V0), facetdim, bndry_facets) bdofsW1_V1 = locate_dofs_topological((W.sub(1), V1), facetdim, bndry_facets) bcs = [ dirichletbc(u0_bc, bdofsW0_V0, W.sub(0)), dirichletbc(u1_bc, bdofsW1_V1, W.sub(1)) ] Jmat = create_matrix(J) Fvec = create_vector(F) snes = PETSc.SNES().create(MPI.COMM_WORLD) snes.setTolerances(rtol=1.0e-15, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().getPC().setType("lu") problem = NonlinearPDE_SNESProblem(F, J, U, bcs) snes.setFunction(problem.F_mono, Fvec) snes.setJacobian(problem.J_mono, J=Jmat, P=None) U.sub(0).interpolate(initial_guess_u) U.sub(1).interpolate(initial_guess_p) x = create_vector(F) x.array = U.vector.array_r snes.solve(None, x) assert snes.getKSP().getConvergedReason() > 0 assert snes.getConvergedReason() > 0 return x.norm()
def __init__(self, problem, solution): self.problem = problem self.solution = solution # Create SNES object self.snes = PETSc.SNES().create(wrapping.get_mpi_comm(solution)) # ... and associate residual and jacobian self.snes.setFunction(self.problem.residual_vector_eval, wrapping.to_petsc4py(self.problem.residual_vector)) self.snes.setJacobian(self.problem.jacobian_matrix_eval, wrapping.to_petsc4py(self.problem.jacobian_matrix)) # Set sensible default values to parameters self._report = None self.set_parameters({ "report": True })
def help(args=None): import sys, shlex # program name try: prog = sys.argv[0] except Exception: prog = getattr(sys, 'executable', 'python') if args is None: args = sys.argv[1:] elif isinstance(args, str): args = shlex.split(args) else: args = [str(a) for a in args] import petsc4py petsc4py.init([prog, '-help'] + args) from petsc4py import PETSc COMM = PETSc.COMM_SELF if 'vec' in args: vec = PETSc.Vec().create(comm=COMM) vec.setSizes(0) vec.setFromOptions() del vec if 'mat' in args: mat = PETSc.Mat().create(comm=COMM) mat.setSizes([0, 0]) mat.setFromOptions() del mat if 'ksp' in args: ksp = PETSc.KSP().create(comm=COMM) ksp.setFromOptions() del ksp if 'pc' in args: pc = PETSc.PC().create(comm=COMM) pc.setFromOptions() del pc if 'snes' in args: snes = PETSc.SNES().create(comm=COMM) snes.setFromOptions() del snes if 'ts' in args: ts = PETSc.TS().create(comm=COMM) ts.setFromOptions() del ts if 'da' in args: da = PETSc.DA().create(comm=COMM) da.setFromOptions() del da
def nested_solve(): """Nested version""" Jmat = create_matrix_nest(J) assert Jmat.getType() == "nest" Fvec = create_vector_nest(F) assert Fvec.getType() == "nest" snes = PETSc.SNES().create(MPI.COMM_WORLD) snes.setTolerances(rtol=1.0e-15, max_it=10) nested_IS = Jmat.getNestISs() snes.getKSP().setType("gmres") snes.getKSP().setTolerances(rtol=1e-12) snes.getKSP().getPC().setType("fieldsplit") snes.getKSP().getPC().setFieldSplitIS(["u", nested_IS[0][0]], ["p", nested_IS[1][1]]) ksp_u, ksp_p = snes.getKSP().getPC().getFieldSplitSubKSP() ksp_u.setType("preonly") ksp_u.getPC().setType('lu') ksp_p.setType("preonly") ksp_p.getPC().setType('lu') problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs) snes.setFunction(problem.F_nest, Fvec) snes.setJacobian(problem.J_nest, J=Jmat, P=None) u.interpolate(initial_guess_u) p.interpolate(initial_guess_p) x = create_vector_nest(F) assert x.getType() == "nest" for x_soln_pair in zip(x.getNestSubVecs(), (u, p)): x_sub, soln_sub = x_soln_pair soln_sub.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) soln_sub.vector.copy(result=x_sub) x_sub.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) snes.solve(None, x) assert snes.getKSP().getConvergedReason() > 0 assert snes.getConvergedReason() > 0 return x.norm()
def test_nonlinear_pde_snes(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 12, 15) V = FunctionSpace(mesh, ("Lagrange", 1)) u = Function(V) v = TestFunction(V) F = inner(5.0, v) * dx - ufl.sqrt(u * u) * inner( grad(u), grad(v)) * dx - inner(u, v) * dx u_bc = Function(V) u_bc.x.array[:] = 1.0 bc = dirichletbc( u_bc, locate_dofs_geometrical( V, lambda x: np.logical_or(np.isclose(x[0], 0.0), np.isclose(x[0], 1.0)))) # Create nonlinear problem problem = NonlinearPDE_SNESProblem(F, u, bc) u.x.array[:] = 0.9 b = la.create_petsc_vector(V.dofmap.index_map, V.dofmap.index_map_bs) J = create_matrix(problem.a) # Create Newton solver and solve snes = PETSc.SNES().create() snes.setFunction(problem.F, b) snes.setJacobian(problem.J, J) snes.setTolerances(rtol=1.0e-9, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().setTolerances(rtol=1.0e-9) snes.getKSP().getPC().setType("lu") snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6 # Modify boundary condition and solve again u_bc.x.array[:] = 0.6 snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6
def create(use_multigrid=False, use_newton=True): snes = PETSc.SNES().create() options = PETSc.Options() options.clear() if use_multigrid: options.setValue('pc_type', 'gamg') options.setValue('pc_gamg_reuse_interpolation', 'True') else: options.setValue('pc_type', 'ilu') options.setValue('ksp_type', 'gmres') if use_newton: options.setValue('snes_type', 'newtonls') else: options.setValue('snes_type', 'ksponly') options.setValue('ksp_atol', 1e-7) snes.setFromOptions() return snes
def cavity_flow2D(nx, ny, lidvelocity, grashof, prandtl): # create application context # and PETSc nonlinear solver snes = PETSc.SNES().create() da = PETSc.DMDA().create([nx,ny],dof=4, stencil_width=1, stencil_type='star') # set up solution vector F = da.createGlobalVec() snes.setFunction(CavityFlow2D.formFunction, F, args=(da, lidvelocity, prandtl, grashof)) x = da.createGlobalVec() CavityFlow2D.formInitGuess(x, da, lidvelocity, prandtl, grashof) snes.setDM(da) snes.setFromOptions() # solve the nonlinear problem snes.solve(None, x) return x
def test_nonlinear_pde_snes(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 12, 15) V = dolfin.function.FunctionSpace(mesh, ("Lagrange", 1)) u = dolfin.function.Function(V) v = function.TestFunction(V) F = inner(2.0, v) * dx - ufl.sqrt(u * u) * inner( grad(u), grad(v)) * dx - inner(u, v) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[:, 0] < 1.0e-8, x[:, 0] > 1.0 - 1.0e-8) u_bc = function.Function(V) u_bc.vector().set(1.0) u_bc.vector().update_ghosts() bc = fem.DirichletBC(V, u_bc, boundary) # Create nonlinear problem problem = NonlinearPDE_SNESProblem(F, u, bc) u.vector().set(0.9) u.vector().update_ghosts() b = dolfin.cpp.la.PETScVector(V.dofmap().index_map()) J = dolfin.cpp.fem.init_matrix(problem.a_comp._cpp_object) # Create Newton solver and solve snes = PETSc.SNES().create() snes.setFunction(problem.F, b.vec()) snes.setJacobian(problem.J, J.mat()) snes.setTolerances(rtol=1.0e-9, max_it=10) snes.setFromOptions() snes.getKSP().setTolerances(rtol=1.0e-9) snes.solve(None, u.vector().vec()) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6
def solver_setup(self): # Create nonlinear solver snes = PETSc.SNES().create(self.comm) # Set options snes.setOptionsPrefix(self.prefix) self.set_petsc_options() snes.setFunction(self.F, self.b) snes.setJacobian(self.J, self.a) # We set the bound (Note: they are passed as reference and not as values) if self.monitor is not None: snes.setMonitor(self.monitor) if self.bounds is not None: snes.setVariableBounds(self.lb.vector, self.ub.vector) snes.setFromOptions() return snes
def _setup_snes(self, pressure_mesh, residual_size): # Creates the Jacobian matrix structure. j_structure = _calculate_jacobian_mask(pressure_mesh.nx, pressure_mesh.ny, 3) logger.info("Jacobian NNZ=%s" % (j_structure.nnz,)) csr = (j_structure.indptr, j_structure.indices, j_structure.data) self._petsc_jacobian = PETSc.Mat().createAIJWithArrays(j_structure.shape, csr) self._petsc_jacobian.assemble(assembly=self._petsc_jacobian.AssemblyType.FINAL_ASSEMBLY) self._comm = PETSc.COMM_WORLD self._dm = PETSc.DMShell().create(comm=self._comm) self._dm.setMatrix(self._petsc_jacobian) # residual vector self._r = PETSc.Vec().createSeq(residual_size) self._snes = PETSc.SNES().create(comm=self._comm) self._snes.setFunction(self.residual_function_for_petsc, self._r) self._snes.setDM(self._dm) self._snes.setConvergenceHistory() self._snes.setFromOptions() self._snes.setUseFD(True) self._snes.setMonitor(self._solver_monitor) self._snes.ksp.setMonitor(self._linear_solver_monitor) self._snes.setTolerances(rtol=1e-4, atol=1e-4, stol=1e-4, max_it=50)
dm = PETSc.DMDA().create(dim=3, sizes = (M,N,P), proc_sizes=(m,n,p), boundary_type=(bx,by,bz), stencil_type=stype, stencil_width = 1, dof = 1, comm = comm, setup = False) dm.setFromOptions() dm.setUp() # steady state sine-Gordon (or NLS?!?) equation... # prepare the g(x,y) term mass = OptDB.getScalar("mass", 1.0) sineGordon = sineGordon(dm, {"dx":0.1, "dy":0.1e+1, "dz":0.1e+1}, mass) # prepare the initial conditions rhs = dm.createGlobalVector() # go do fun things with sine-Gordon # set up the SNES context snes = PETSc.SNES().create() snes.setDM(dm) snes.setFunction(sineGordon.rhs, rhs) snes.setMonitor(sineGordon.monitor) # check the interplay of -snes_mf, -snes_fd, and nothing at all! # PETSc has a complicated defaults system, so we deal with it here # Normally you do not need to do this as you are only likely to use one or the other # option but in this example we want them all. if (OptDB.hasName("snes_mf")): mf=OptDB.getBool("snes_mf") else: mf=None if (OptDB.hasName("snes_fd")): fd=OptDB.getBool("snes_fd") else:
def test_assembly_solve_block(): """Solve a two-field nonlinear diffusion like problem with block matrix approaches and test that solution is the same. """ mesh = dolfinx.generation.UnitSquareMesh(dolfinx.MPI.comm_world, 12, 11) p = 1 P = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p) V0 = dolfinx.function.FunctionSpace(mesh, P) V1 = V0.clone() def bc_val_0(x): return x[0]**2 + x[1]**2 def bc_val_1(x): return numpy.sin(x[0]) * numpy.cos(x[1]) def initial_guess_u(x): return numpy.sin(x[0]) * numpy.sin(x[1]) def initial_guess_p(x): return -x[0]**2 - x[1]**3 def boundary(x): return numpy.logical_or(x[0] < 1.0e-6, x[0] > 1.0 - 1.0e-6) facetdim = mesh.topology.dim - 1 mf = dolfinx.MeshFunction("size_t", mesh, facetdim, 0) mf.mark(boundary, 1) bndry_facets = numpy.where(mf.values == 1)[0] u_bc0 = dolfinx.function.Function(V0) u_bc0.interpolate(bc_val_0) u_bc1 = dolfinx.function.Function(V1) u_bc1.interpolate(bc_val_1) bdofs0 = dolfinx.fem.locate_dofs_topological(V0, facetdim, bndry_facets) bdofs1 = dolfinx.fem.locate_dofs_topological(V1, facetdim, bndry_facets) bcs = [ dolfinx.fem.dirichletbc.DirichletBC(u_bc0, bdofs0), dolfinx.fem.dirichletbc.DirichletBC(u_bc1, bdofs1) ] # Block and Nest variational problem u, p = dolfinx.function.Function(V0), dolfinx.function.Function(V1) du, dp = ufl.TrialFunction(V0), ufl.TrialFunction(V1) v, q = ufl.TestFunction(V0), ufl.TestFunction(V1) f = 1.0 g = -3.0 F = [ inner((u**2 + 1) * ufl.grad(u), ufl.grad(v)) * dx - inner(f, v) * dx, inner((p**2 + 1) * ufl.grad(p), ufl.grad(q)) * dx - inner(g, q) * dx ] J = [[derivative(F[0], u, du), derivative(F[0], p, dp)], [derivative(F[1], u, du), derivative(F[1], p, dp)]] # -- Blocked version Jmat0 = dolfinx.fem.create_matrix_block(J) Fvec0 = dolfinx.fem.create_vector_block(F) snes = PETSc.SNES().create(dolfinx.MPI.comm_world) snes.setTolerances(rtol=1.0e-15, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().getPC().setType("lu") snes.getKSP().getPC().setFactorSolverType("mumps") problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs) snes.setFunction(problem.F_block, Fvec0) snes.setJacobian(problem.J_block, J=Jmat0, P=None) u.interpolate(initial_guess_u) p.interpolate(initial_guess_p) x0 = dolfinx.fem.create_vector_block(F) dolfinx.cpp.la.scatter_local_vectors( x0, [u.vector.array_r, p.vector.array_r], [u.function_space.dofmap.index_map, p.function_space.dofmap.index_map]) x0.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) snes.solve(None, x0) assert snes.getKSP().getConvergedReason() > 0 assert snes.getConvergedReason() > 0 J0norm = Jmat0.norm() F0norm = Fvec0.norm() x0norm = x0.norm() # -- Nested (MatNest) Jmat1 = dolfinx.fem.create_matrix_nest(J) Fvec1 = dolfinx.fem.create_vector_nest(F) snes = PETSc.SNES().create(dolfinx.MPI.comm_world) snes.setTolerances(rtol=1.0e-15, max_it=10) nested_IS = Jmat1.getNestISs() snes.getKSP().setType("fgmres") snes.getKSP().setTolerances(rtol=1e-12) snes.getKSP().getPC().setType("fieldsplit") snes.getKSP().getPC().setFieldSplitIS(["u", nested_IS[0][0]], ["p", nested_IS[1][1]]) ksp_u, ksp_p = snes.getKSP().getPC().getFieldSplitSubKSP() ksp_u.setType("preonly") ksp_u.getPC().setType('lu') ksp_u.getPC().setFactorSolverType('mumps') ksp_p.setType("preonly") ksp_p.getPC().setType('lu') ksp_p.getPC().setFactorSolverType('mumps') problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs) snes.setFunction(problem.F_nest, Fvec1) snes.setJacobian(problem.J_nest, J=Jmat1, P=None) u.interpolate(initial_guess_u) p.interpolate(initial_guess_p) x1 = dolfinx.fem.create_vector_nest(F) for x1_soln_pair in zip(x1.getNestSubVecs(), (u, p)): x1_sub, soln_sub = x1_soln_pair soln_sub.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) soln_sub.vector.copy(result=x1_sub) x1_sub.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) snes.solve(None, x1) assert snes.getKSP().getConvergedReason() > 0 assert snes.getConvergedReason() > 0 assert x1.getType() == "nest" assert Jmat1.getType() == "nest" assert Fvec1.getType() == "nest" J1norm = nest_matrix_norm(Jmat1) F1norm = Fvec1.norm() x1norm = x1.norm() assert J1norm == pytest.approx(J0norm, 1.0e-12) assert F1norm == pytest.approx(F0norm, 1.0e-12) assert x1norm == pytest.approx(x0norm, 1.0e-12) # -- Monolithic version E = P * P W = dolfinx.function.FunctionSpace(mesh, E) U = dolfinx.function.Function(W) dU = ufl.TrialFunction(W) u0, u1 = ufl.split(U) v0, v1 = ufl.TestFunctions(W) F = inner((u0**2 + 1) * ufl.grad(u0), ufl.grad(v0)) * dx \ + inner((u1**2 + 1) * ufl.grad(u1), ufl.grad(v1)) * dx \ - inner(f, v0) * ufl.dx - inner(g, v1) * dx J = derivative(F, U, dU) u0_bc = dolfinx.function.Function(V0) u0_bc.interpolate(bc_val_0) u1_bc = dolfinx.function.Function(V1) u1_bc.interpolate(bc_val_1) bdofsW0_V0 = dolfinx.fem.locate_dofs_topological((W.sub(0), V0), facetdim, bndry_facets) bdofsW1_V1 = dolfinx.fem.locate_dofs_topological((W.sub(1), V1), facetdim, bndry_facets) bcs = [ dolfinx.fem.dirichletbc.DirichletBC(u0_bc, bdofsW0_V0, W.sub(0)), dolfinx.fem.dirichletbc.DirichletBC(u1_bc, bdofsW1_V1, W.sub(1)) ] Jmat2 = dolfinx.fem.create_matrix(J) Fvec2 = dolfinx.fem.create_vector(F) snes = PETSc.SNES().create(dolfinx.MPI.comm_world) snes.setTolerances(rtol=1.0e-15, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().getPC().setType("lu") snes.getKSP().getPC().setFactorSolverType("mumps") problem = NonlinearPDE_SNESProblem(F, J, U, bcs) snes.setFunction(problem.F_mono, Fvec2) snes.setJacobian(problem.J_mono, J=Jmat2, P=None) U.interpolate(lambda x: numpy.row_stack( (initial_guess_u(x), initial_guess_p(x)))) x2 = dolfinx.fem.create_vector(F) x2.array = U.vector.array_r snes.solve(None, x2) assert snes.getKSP().getConvergedReason() > 0 assert snes.getConvergedReason() > 0 J2norm = Jmat2.norm() F2norm = Fvec2.norm() x2norm = x2.norm() assert J2norm == pytest.approx(J0norm, 1.0e-12) assert F2norm == pytest.approx(F0norm, 1.0e-12) assert x2norm == pytest.approx(x0norm, 1.0e-12)
def setUp(self): snes = PETSc.SNES() snes.create(PETSc.COMM_SELF) if self.SNES_TYPE: snes.setType(self.SNES_TYPE) self.snes = snes
def __init__(self, problem_params, dtype_u=petsc_data, dtype_f=rhs_2comp_petsc_data): """ Initialization routine Args: problem_params: custom parameters for the example dtype_u: PETSc data type (will be passed to parent class) dtype_f: PETSc data type with 2 components (will be passed to parent class) """ # define the Dirichlet boundary if 'comm' not in problem_params: problem_params['comm'] = PETSc.COMM_WORLD if 'sol_tol' not in problem_params: problem_params['sol_tol'] = 1E-10 if 'sol_maxiter' not in problem_params: problem_params['sol_maxiter'] = None # these parameters will be used later, so assert their existence essential_keys = ['nvars', 'Du', 'Dv', 'A', 'B'] for key in essential_keys: if key not in problem_params: msg = 'need %s to instantiate problem, only got %s' % ( key, str(problem_params.keys())) raise ParameterError(msg) # create DMDA object which will be used for all grid operations (boundary_type=3 -> periodic BC) da = PETSc.DMDA().create( [problem_params['nvars'][0], problem_params['nvars'][1]], dof=2, boundary_type=3, stencil_width=1, comm=problem_params['comm']) # invoke super init, passing number of dofs, dtype_u and dtype_f super(petsc_grayscott_multiimplicit, self).__init__(init=da, dtype_u=dtype_u, dtype_f=dtype_f, params=problem_params) # compute dx, dy and get local ranges self.dx = 100.0 / (self.params.nvars[0]) self.dy = 100.0 / (self.params.nvars[1]) (self.xs, self.xe), (self.ys, self.ye) = self.init.getRanges() # compute discretization matrix A and identity self.A = self.__get_A() self.Id = self.__get_Id() self.localX = self.init.createLocalVec() # setup linear solver self.ksp = PETSc.KSP() self.ksp.create(comm=self.params.comm) self.ksp.setType('cg') pc = self.ksp.getPC() pc.setType('none') self.ksp.setInitialGuessNonzero(True) self.ksp.setFromOptions() self.ksp.setTolerances(rtol=self.params.lsol_tol, atol=self.params.lsol_tol, max_it=self.params.lsol_maxiter) self.ksp_itercount = 0 self.ksp_ncalls = 0 # setup nonlinear solver self.snes = PETSc.SNES() self.snes.create(comm=self.params.comm) # self.snes.getKSP().setType('cg') # self.snes.setType('ngmres') self.snes.setFromOptions() self.snes.setTolerances(rtol=self.params.nlsol_tol, atol=self.params.nlsol_tol, stol=self.params.nlsol_tol, max_it=self.params.nlsol_maxiter) self.snes_itercount = 0 self.snes_ncalls = 0
def __init__(self, problem_params, dtype_u=petsc_data, dtype_f=rhs_2comp_petsc_data): """ Initialization routine Args: problem_params: custom parameters for the example dtype_u: PETSc data type (will be passed to parent class) dtype_f: PETSc data type with 2 components (will be passed to parent class) """ # define optional parameters if 'comm' not in problem_params: problem_params['comm'] = PETSc.COMM_WORLD if 'lsol_tol' not in problem_params: problem_params['lsol_tol'] = 1E-10 if 'nlsol_tol' not in problem_params: problem_params['nlsol_tol'] = 1E-10 if 'lsol_maxiter' not in problem_params: problem_params['lsol_maxiter'] = None if 'nlsol_maxiter' not in problem_params: problem_params['nlsol_maxiter'] = None # these parameters will be used later, so assert their existence essential_keys = ['nvars', 'lambda0', 'nu', 'interval'] for key in essential_keys: if key not in problem_params: msg = 'need %s to instantiate problem, only got %s' % (key, str(problem_params.keys())) raise ParameterError(msg) # create DMDA object which will be used for all grid operations da = PETSc.DMDA().create([problem_params['nvars']], dof=1, stencil_width=1, comm=problem_params['comm']) # invoke super init, passing number of dofs, dtype_u and dtype_f super(petsc_fisher_multiimplicit, self).__init__(init=da, dtype_u=dtype_u, dtype_f=dtype_f, params=problem_params) # compute dx and get local ranges self.dx = (self.params.interval[1] - self.params.interval[0]) / (self.params.nvars - 1) (self.xs, self.xe) = self.init.getRanges()[0] # compute discretization matrix A and identity self.A = self.__get_A() self.localX = self.init.createLocalVec() # setup linear solver self.ksp = PETSc.KSP() self.ksp.create(comm=self.params.comm) self.ksp.setType('cg') pc = self.ksp.getPC() pc.setType('ilu') self.ksp.setInitialGuessNonzero(True) self.ksp.setFromOptions() self.ksp.setTolerances(rtol=self.params.lsol_tol, atol=self.params.lsol_tol, max_it=self.params.lsol_maxiter) self.ksp_itercount = 0 self.ksp_ncalls = 0 # setup nonlinear solver self.snes = PETSc.SNES() self.snes.create(comm=self.params.comm) if self.params.nlsol_maxiter <= 1: self.snes.setType('ksponly') self.snes.getKSP().setType('cg') pc = self.snes.getKSP().getPC() pc.setType('ilu') # self.snes.setType('ngmres') self.snes.setFromOptions() self.snes.setTolerances(rtol=self.params.nlsol_tol, atol=self.params.nlsol_tol, stol=self.params.nlsol_tol, max_it=self.params.nlsol_maxiter) self.snes_itercount = 0 self.snes_ncalls = 0 self.F = self.init.createGlobalVec() self.J = self.init.createMatrix()
def __init__(self, cfgfile): ''' Constructor ''' # stencil = 1 stencil = 2 # load run config file cfg = Config(cfgfile) # set some PETSc options OptDB = PETSc.Options() # OptDB.setValue('snes_lag_preconditioner', 5) OptDB.setValue('snes_atol', cfg['solver']['petsc_residual']) OptDB.setValue('snes_rtol', 1E-16) OptDB.setValue('snes_stol', 1E-18) OptDB.setValue('snes_max_it', 10) OptDB.setValue('ksp_atol', cfg['solver']['petsc_residual'] * 1E-1) OptDB.setValue('ksp_rtol', 1E-10) OptDB.setValue('ksp_max_it', 10) # OptDB.setValue('ksp_convergence_test', 'skip') OptDB.setValue('snes_monitor', '') OptDB.setValue('ksp_monitor', '') # timestep setup self.ht = cfg['grid']['ht'] # timestep size self.nt = cfg['grid']['nt'] # number of timesteps self.nsave = cfg['io']['nsave'] # save only every nsave'th timestep # grid setup nx = cfg['grid']['nx'] # number of points in x ny = cfg['grid']['ny'] # number of points in y Lx = cfg['grid']['Lx'] # spatial domain in x x1 = cfg['grid']['x1'] # x2 = cfg['grid']['x2'] # Ly = cfg['grid']['Ly'] # spatial domain in y y1 = cfg['grid']['y1'] # y2 = cfg['grid']['y2'] # self.nx = nx self.ny = ny if x1 != x2: Lx = x2-x1 else: x1 = 0.0 x2 = Lx if y1 != y2: Ly = y2-y1 else: y1 = 0.0 y2 = Ly self.hx = Lx / nx # gridstep size in x self.hy = Ly / ny # gridstep size in y if PETSc.COMM_WORLD.getRank() == 0: print() print("nt = %i" % (self.nt)) print("nx = %i" % (self.nx)) print("ny = %i" % (self.ny)) print() print("ht = %e" % (self.ht)) print("hx = %e" % (self.hx)) print("hy = %e" % (self.hy)) print() print("Lx = %e" % (Lx)) print("Ly = %e" % (Ly)) print() self.time = PETSc.Vec().createMPI(1, PETSc.DECIDE, comm=PETSc.COMM_WORLD) self.time.setName('t') if PETSc.COMM_WORLD.getRank() == 0: self.time.setValue(0, 0.0) # create DA with single dof self.da1 = PETSc.DA().create(dim=2, dof=1, sizes=[nx, ny], proc_sizes=[PETSc.DECIDE, PETSc.DECIDE], boundary_type=('periodic', 'periodic'), stencil_width=stencil, stencil_type='box') # create DA (dof = 4 for Bx, By, Vx, Vy) self.da4 = PETSc.DA().create(dim=2, dof=4, sizes=[nx, ny], proc_sizes=[PETSc.DECIDE, PETSc.DECIDE], boundary_type=('periodic', 'periodic'), stencil_width=stencil, stencil_type='box') # create DA (dof = 5 for Bx, By, Vx, Vy, P) self.da5 = PETSc.DA().create(dim=2, dof=5, sizes=[nx, ny], proc_sizes=[PETSc.DECIDE, PETSc.DECIDE], boundary_type=('periodic', 'periodic'), stencil_width=stencil, stencil_type='box') # create DA for x grid self.dax = PETSc.DA().create(dim=1, dof=1, sizes=[nx], proc_sizes=[PETSc.DECIDE], boundary_type=('periodic')) # create DA for y grid self.day = PETSc.DA().create(dim=1, dof=1, sizes=[ny], proc_sizes=[PETSc.DECIDE], boundary_type=('periodic')) # initialise grid self.da1.setUniformCoordinates(xmin=x1, xmax=x2, ymin=y1, ymax=y2) self.da4.setUniformCoordinates(xmin=x1, xmax=x2, ymin=y1, ymax=y2) self.da5.setUniformCoordinates(xmin=x1, xmax=x2, ymin=y1, ymax=y2) self.dax.setUniformCoordinates(xmin=x1, xmax=x2) self.day.setUniformCoordinates(xmin=y1, xmax=y2) # create solution and RHS vector self.f = self.da5.createGlobalVec() self.x = self.da5.createGlobalVec() self.b = self.da5.createGlobalVec() # create global RK4 vectors self.Y = self.da5.createGlobalVec() self.X0 = self.da5.createGlobalVec() self.X1 = self.da5.createGlobalVec() self.X2 = self.da5.createGlobalVec() self.X3 = self.da5.createGlobalVec() self.X4 = self.da5.createGlobalVec() # create local RK4 vectors self.localX0 = self.da5.createLocalVec() self.localX1 = self.da5.createLocalVec() self.localX2 = self.da5.createLocalVec() self.localX3 = self.da5.createLocalVec() self.localX4 = self.da5.createLocalVec() # self.localP = self.da1.createLocalVec() # create vectors for magnetic and velocity field self.Bx = self.da1.createGlobalVec() self.By = self.da1.createGlobalVec() self.Vx = self.da1.createGlobalVec() self.Vy = self.da1.createGlobalVec() self.P = self.da1.createGlobalVec() # create local vectors for initialisation of pressure self.localBx = self.da1.createLocalVec() self.localBy = self.da1.createLocalVec() self.localVx = self.da1.createLocalVec() self.localVy = self.da1.createLocalVec() # set variable names self.Bx.setName('Bx') self.By.setName('By') self.Vx.setName('Vx') self.Vy.setName('Vy') self.P.setName('P') # create Matrix object self.petsc_matrix = PETScMatrix (self.da1, self.da5, nx, ny, self.ht, self.hx, self.hy) self.petsc_jacobian = PETScJacobian(self.da1, self.da5, nx, ny, self.ht, self.hx, self.hy) self.petsc_function = PETScFunction(self.da1, self.da5, nx, ny, self.ht, self.hx, self.hy) # self.petsc_jacobian_4d = PETSc_MHD_NL_Jacobian_Matrix.PETScJacobian(self.da1, self.da5, nx, ny, self.ht, self.hx, self.hy) # initialise matrix self.A = self.da5.createMat() self.A.setOption(self.A.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.A.setUp() # create jacobian self.J = self.da5.createMat() self.J.setOption(self.J.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.J.setUp() # create nonlinear solver self.snes = PETSc.SNES().create() self.snes.setFunction(self.petsc_function.snes_mult, self.f) self.snes.setJacobian(self.updateJacobian, self.J) self.snes.setFromOptions() self.snes.getKSP().setType('preonly') # self.snes.getKSP().setType('gmres') self.snes.getKSP().getPC().setType('lu') # self.snes.getKSP().getPC().setFactorSolverPackage('superlu_dist') self.snes.getKSP().getPC().setFactorSolverPackage('mumps') self.ksp = None # set initial data (xs, xe), (ys, ye) = self.da1.getRanges() coords = self.da1.getCoordinatesLocal() Bx_arr = self.da1.getVecArray(self.Bx) By_arr = self.da1.getVecArray(self.By) Vx_arr = self.da1.getVecArray(self.Vx) Vy_arr = self.da1.getVecArray(self.Vy) if cfg['initial_data']['magnetic_python'] != None: init_data = __import__("runs." + cfg['initial_data']['magnetic_python'], globals(), locals(), ['magnetic_x', 'magnetic_y'], 0) for i in range(xs, xe): for j in range(ys, ye): Bx_arr[i,j] = init_data.magnetic_x(coords[i,j][0], coords[i,j][1] + 0.5 * self.hy, Lx, Ly) By_arr[i,j] = init_data.magnetic_y(coords[i,j][0] + 0.5 * self.hx, coords[i,j][1], Lx, Ly) else: Bx_arr[xs:xe, ys:ye] = cfg['initial_data']['magnetic'] By_arr[xs:xe, ys:ye] = cfg['initial_data']['magnetic'] if cfg['initial_data']['velocity_python'] != None: init_data = __import__("runs." + cfg['initial_data']['velocity_python'], globals(), locals(), ['velocity_x', 'velocity_y'], 0) for i in range(xs, xe): for j in range(ys, ye): Vx_arr[i,j] = init_data.velocity_x(coords[i,j][0], coords[i,j][1] + 0.5 * self.hy, Lx, Ly) Vy_arr[i,j] = init_data.velocity_y(coords[i,j][0] + 0.5 * self.hx, coords[i,j][1], Lx, Ly) else: Vx_arr[xs:xe, ys:ye] = cfg['initial_data']['velocity'] Vy_arr[xs:xe, ys:ye] = cfg['initial_data']['velocity'] if cfg['initial_data']['pressure_python'] != None: init_data = __import__("runs." + cfg['initial_data']['pressure_python'], globals(), locals(), ['pressure', ''], 0) x_arr = self.da5.getVecArray(self.x) x_arr[xs:xe, ys:ye, 0] = Vx_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 1] = Vy_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 2] = Bx_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 3] = By_arr[xs:xe, ys:ye] self.da1.globalToLocal(self.Bx, self.localBx) self.da1.globalToLocal(self.By, self.localBy) self.da1.globalToLocal(self.Vx, self.localVx) self.da1.globalToLocal(self.Vy, self.localVy) Bx_arr = self.da1.getVecArray(self.localBx) By_arr = self.da1.getVecArray(self.localBy) Vx_arr = self.da1.getVecArray(self.localVx) Vy_arr = self.da1.getVecArray(self.localVy) P_arr = self.da1.getVecArray(self.P) for i in range(xs, xe): for j in range(ys, ye): P_arr[i,j] = init_data.pressure(coords[i,j][0] + 0.5 * self.hx, coords[i,j][1] + 0.5 * self.hy, Lx, Ly) # P_arr[i,j] = init_data.pressure(coords[i,j][0] + 0.5 * self.hx, coords[i,j][1] + 0.5 * self.hy, Lx, Ly) \ # + 0.5 * (0.25 * (Bx_arr[i,j] + Bx_arr[i+1,j])**2 + 0.25 * (By_arr[i,j] + By_arr[i,j+1])**2) # P_arr[i,j] = init_data.pressure(coords[i,j][0] + 0.5 * self.hx, coords[i,j][1] + 0.5 * self.hy, Lx, Ly) \ # + 0.5 * (0.25 * (Vx_arr[i,j] + Vx_arr[i+1,j])**2 + 0.25 * (Vy_arr[i,j] + Vy_arr[i,j+1])**2) # P_arr[i,j] = init_data.pressure(coords[i,j][0] + 0.5 * self.hx, coords[i,j][1] + 0.5 * self.hy, Lx, Ly) \ # + 0.5 * (0.25 * (Vx_arr[i,j] + Vx_arr[i+1,j])**2 + 0.25 * (Vy_arr[i,j] + Vy_arr[i,j+1])**2) \ # - 1.0 * (0.25 * (Bx_arr[i,j] + Bx_arr[i+1,j])**2 + 0.25 * (By_arr[i,j] + By_arr[i,j+1])**2) # copy distribution function to solution vector x_arr = self.da5.getVecArray(self.x) x_arr[xs:xe, ys:ye, 4] = P_arr [xs:xe, ys:ye] # update solution history self.petsc_matrix.update_history(self.x) self.petsc_jacobian.update_history(self.x) self.petsc_function.update_history(self.x) # create HDF5 output file self.hdf5_viewer = PETSc.ViewerHDF5().create(cfg['io']['hdf5_output'], mode=PETSc.Viewer.Mode.WRITE, comm=PETSc.COMM_WORLD) self.hdf5_viewer.pushGroup("/") # write grid data to hdf5 file coords_x = self.dax.getCoordinates() coords_y = self.day.getCoordinates() coords_x.setName('x') coords_y.setName('y') self.hdf5_viewer(coords_x) self.hdf5_viewer(coords_y) # write initial data to hdf5 file self.hdf5_viewer.setTimestep(0) self.save_hdf5_vectors()
def run(self): OptDB = PETSc.Options() OptDB.setValue('ksp_monitor', '') OptDB.setValue('snes_monitor', '') # OptDB.setValue('snes_lag_preconditioner', 3) # OptDB.setValue('snes_ls', 'basic') # initialise matrix self.A = self.da2.createMat() self.A.setOption(self.A.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.A.setUp() self.A.setNullSpace(self.nullspace) # initialise Jacobian self.J = self.da2.createMat() self.J.setOption(self.J.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.J.setUp() self.J.setNullSpace(self.nullspace) # create Jacobian, Function, and linear Matrix objects # self.petsc_jacobian_mf = PETScJacobianMatrixFree(self.da1, self.da2, self.dax, # self.h0, self.vGrid, # self.nx, self.nv, self.ht, self.hx, self.hv, # self.charge, coll_freq=self.coll_freq) self.petsc_solver = PETScSolver(self.da1, self.da2, self.dax, self.h0, self.vGrid, self.nx, self.nv, self.ht, self.hx, self.hv, self.charge, coll_freq=self.coll_freq) # self.petsc_function = PETScFunction(self.da1, self.da2, self.dax, # self.h0, self.vGrid, # self.nx, self.nv, self.ht, self.hx, self.hv, # self.charge, coll_freq=self.coll_freq) # # self.petsc_matrix = PETScMatrix(self.da1, self.da2, self.dax, # self.h0, self.vGrid, # self.nx, self.nv, self.ht, self.hx, self.hv, # self.charge)#, coll_freq=self.coll_freq) # self.poisson_ksp = PETSc.KSP().create() # self.poisson_ksp.setFromOptions() # self.poisson_ksp.setOperators(self.poisson_A) # self.poisson_ksp.setType('cg') # self.poisson_ksp.getPC().setType('none') # # self.poisson_ksp.setType('preonly') # # self.poisson_ksp.getPC().setType('lu') # # self.poisson_ksp.getPC().setFactorSolverPackage(self.solver_package) # copy external potential self.petsc_solver.update_external(self.p_ext) # self.petsc_matrix.update_external(self.p_ext) # update solution history self.petsc_solver.update_history(self.x) # self.petsc_matrix.update_history(self.f, self.h1, self.p, self.n, self.nu, self.ne, self.u, self.e, self.a) # initialise matrixfree Jacobian # self.Jmf = PETSc.Mat().createPython([self.x.getSizes(), self.b.getSizes()], # context=self.petsc_jacobian_mf, # comm=PETSc.COMM_WORLD) # self.Jmf.setUp() # # create linear solver # self.snes_linear = PETSc.SNES().create() # self.snes_linear.setType('ksponly') # self.snes_linear.setFunction(self.petsc_matrix.snes_mult, self.b) # self.snes_linear.setJacobian(self.updateMatrix, self.A) # self.snes_linear.setFromOptions() # # self.snes_linear.getKSP().setType('gmres') # # self.snes_linear.getKSP().getPC().setType('bjacobi') # # self.snes_linear.getKSP().getPC().setFactorSolverPackage(self.solver_package) # self.snes_linear.getKSP().setType('preonly') # self.snes_linear.getKSP().getPC().setType('lu') # self.snes_linear.getKSP().getPC().setFactorSolverPackage(self.solver_package) # create nonlinear solver self.snes = PETSc.SNES().create() self.snes.setFunction(self.petsc_solver.function_snes_mult, self.b) # self.snes.setJacobian(self.updateJacobian, self.Jmf, self.J) self.snes.setJacobian(self.updateJacobian, self.J) self.snes.setFromOptions() # self.snes.getKSP().setType('gmres') # self.snes.getKSP().getPC().setType('bjacobi') self.snes.getKSP().setType('preonly') self.snes.getKSP().getPC().setType('lu') self.snes.getKSP().getPC().setFactorSolverPackage(self.solver_package) # self.snes_nsp = PETSc.NullSpace().create(vectors=(self.x_nvec,)) # self.snes.getKSP().setNullSpace(self.snes_nsp) for itime in range(1, self.nt + 1): current_time = self.ht * itime if PETSc.COMM_WORLD.getRank() == 0: localtime = time.asctime(time.localtime(time.time())) print("\nit = %4d, t = %10.4f, %s" % (itime, current_time, localtime)) print self.time.setValue(0, current_time) # calculate external field and copy to matrix, jacobian and function self.calculate_external(current_time) # self.petsc_jacobian_mf.update_external(self.p_ext) self.petsc_solver.update_external(self.p_ext) # self.petsc_jacobian.update_external(self.p_ext) # self.petsc_function.update_external(self.p_ext) # self.petsc_matrix.update_external(self.p_ext) self.x.copy(self.xh) self.petsc_solver.function_mult(self.x, self.b) prev_norm = self.b.norm() if PETSc.COMM_WORLD.getRank() == 0: print( " Previous Step: funcnorm = %24.16E" % (prev_norm)) # calculate initial guess via RK4 # self.initial_guess_rk4() # calculate initial guess via Gear self.initial_guess_gear(itime) # check if residual went down # self.petsc_function.mult(self.x, self.b) # ig_norm = self.b.norm() # # if ig_norm > prev_norm: # self.xh.copy(self.x) # calculate initial guess via linear solver # self.initial_guess() # nonlinear solve self.snes.solve(None, self.x) # output some solver info if PETSc.COMM_WORLD.getRank() == 0: print( " Nonlin Solver: %5i iterations, funcnorm = %24.16E" % (self.snes.getIterationNumber(), self.snes.getFunctionNorm())) print() if self.snes.getConvergedReason() < 0: if PETSc.COMM_WORLD.getRank() == 0: print() print("Solver not converging... %i" % (self.snes.getConvergedReason())) print() # if PETSc.COMM_WORLD.getRank() == 0: # mat_viewer = PETSc.Viewer().createDraw(size=(800,800), comm=PETSc.COMM_WORLD) # mat_viewer(self.J) # # print # input('Hit any key to continue.') # print # update data vectors self.copy_x_to_data() # update history self.petsc_solver.update_history(self.x) # self.petsc_matrix.update_history(self.f, self.h1, self.p, self.n, self.nu, self.ne, self.u, self.e, self.a) self.arakawa_gear.update_history(self.f, self.h1) # save to hdf5 self.save_to_hdf5(itime) # # some solver output phisum = self.p.sum() # # if PETSc.COMM_WORLD.getRank() == 0: # print(" Solver") print(" sum(phi) = %24.16E" % (phisum))
def __init__(self, cfgfile): ''' Constructor ''' # load run config file cfg = Config(cfgfile) # timestep setup self.ht = cfg['grid']['ht'] # timestep size self.nt = cfg['grid']['nt'] # number of timesteps self.nsave = cfg['io']['nsave'] # save only every nsave'th timestep # grid setup nx = cfg['grid']['nx'] # number of points in x ny = cfg['grid']['ny'] # number of points in y Lx = cfg['grid']['Lx'] # spatial domain in x x1 = cfg['grid']['x1'] # x2 = cfg['grid']['x2'] # Ly = cfg['grid']['Ly'] # spatial domain in y y1 = cfg['grid']['y1'] # y2 = cfg['grid']['y2'] # if x1 != x2: Lx = x2-x1 else: x1 = 0.0 x2 = Lx if y1 != y2: Ly = y2-y1 else: y1 = 0.0 y2 = Ly self.hx = Lx / nx # gridstep size in x self.hy = Ly / ny # gridstep size in y self.time = PETSc.Vec().createMPI(1, PETSc.DECIDE, comm=PETSc.COMM_WORLD) self.time.setName('t') if PETSc.COMM_WORLD.getRank() == 0: self.time.setValue(0, 0.0) # set some PETSc options OptDB = PETSc.Options() OptDB.setValue('ksp_rtol', cfg['solver']['petsc_residual']) # OptDB.setValue('snes_rtol', 1E-2) # OptDB.setValue('ksp_max_it', 100) OptDB.setValue('ksp_max_it', 200) # OptDB.setValue('ksp_max_it', 1000) # OptDB.setValue('ksp_max_it', 2000) # OptDB.setValue('ksp_monitor', '') # OptDB.setValue('log_info', '') # OptDB.setValue('log_summary', '') # create DA with single dof self.da1 = PETSc.DA().create(dim=2, dof=1, sizes=[nx, ny], proc_sizes=[PETSc.DECIDE, PETSc.DECIDE], boundary_type=('periodic', 'periodic'), stencil_width=1, stencil_type='box') # create DA (dof = 5 for Bx, By, Vx, Vy, P) self.da4 = PETSc.DA().create(dim=2, dof=5, sizes=[nx, ny], proc_sizes=[PETSc.DECIDE, PETSc.DECIDE], boundary_type=('periodic', 'periodic'), stencil_width=1, stencil_type='box') # create DA for x grid self.dax = PETSc.DA().create(dim=1, dof=1, sizes=[nx], proc_sizes=[PETSc.DECIDE], boundary_type=('periodic')) # create DA for y grid self.day = PETSc.DA().create(dim=1, dof=1, sizes=[ny], proc_sizes=[PETSc.DECIDE], boundary_type=('periodic')) # initialise grid self.da1.setUniformCoordinates(xmin=x1, xmax=x2, ymin=y1, ymax=y2) self.da4.setUniformCoordinates(xmin=x1, xmax=x2, ymin=y1, ymax=y2) self.dax.setUniformCoordinates(xmin=x1, xmax=x2) self.day.setUniformCoordinates(xmin=y1, xmax=y2) # create solution and RHS vector self.dx = self.da4.createGlobalVec() self.x = self.da4.createGlobalVec() self.b = self.da4.createGlobalVec() self.f = self.da4.createGlobalVec() self.Pb = self.da1.createGlobalVec() self.localX = self.da4.createLocalVec() # create global RK4 vectors self.X1 = self.da4.createGlobalVec() self.X2 = self.da4.createGlobalVec() self.X3 = self.da4.createGlobalVec() self.X4 = self.da4.createGlobalVec() # create local RK4 vectors self.localX1 = self.da4.createLocalVec() self.localX2 = self.da4.createLocalVec() self.localX3 = self.da4.createLocalVec() self.localX4 = self.da4.createLocalVec() # create vectors for magnetic and velocity field self.Bx = self.da1.createGlobalVec() self.By = self.da1.createGlobalVec() self.Vx = self.da1.createGlobalVec() self.Vy = self.da1.createGlobalVec() self.P = self.da1.createGlobalVec() # set variable names self.x.setName('solver_x') self.b.setName('solver_b') self.Bx.setName('Bx') self.By.setName('By') self.Vx.setName('Vx') self.Vy.setName('Vy') self.P.setName('P') # create Matrix object self.petsc_matrix = PETScSolver (self.da1, self.da4, nx, ny, self.ht, self.hx, self.hy) self.petsc_function = PETScFunction(self.da1, self.da4, nx, ny, self.ht, self.hx, self.hy) self.petsc_jacobian = PETScJacobian(self.da1, self.da4, nx, ny, self.ht, self.hx, self.hy) # create sparse matrix self.J = PETSc.Mat().createPython([self.dx.getSizes(), self.b.getSizes()], comm=PETSc.COMM_WORLD) self.J.setPythonContext(self.petsc_jacobian) self.J.setUp() # create nonlinear solver self.snes = PETSc.SNES().create() self.snes.setFunction(self.petsc_function.snes_mult, self.f) self.snes.setJacobian(self.updateJacobian, self.J) # self.snes.setUseMF() self.snes.setFromOptions() self.snes.getKSP().setType('gmres') self.snes.getKSP().getPC().setType('none') # create Preconditioner matrix and solver self.pc_mat = PETScPreconditioner(self.da1, self.da4, self.P, nx, ny, self.ht, self.hx, self.hy) # create sparse matrix self.pc_A = PETSc.Mat().createPython([self.x.getSizes(), self.b.getSizes()], comm=PETSc.COMM_WORLD) self.pc_A.setPythonContext(self.pc_mat) self.pc_A.setUp() # create linear solver and preconditioner self.pc_ksp = PETSc.KSP().create() self.pc_ksp.setFromOptions() self.pc_ksp.setOperators(self.pc_A) self.pc_ksp.setType(cfg['solver']['petsc_ksp_type']) self.pc_ksp.setInitialGuessNonzero(True) self.pc_pc = self.pc_ksp.getPC() self.pc_pc.setType('none') # create Poisson matrix and solver self.poisson_mat = PETScPoissonSolver(self.da1, self.da4, self.x, nx, ny, self.ht, self.hx, self.hy) self.poisson_A = PETSc.Mat().createPython([self.P.getSizes(), self.Pb.getSizes()], comm=PETSc.COMM_WORLD) self.poisson_A.setPythonContext(self.poisson_mat) self.poisson_A.setUp() self.poisson_ksp = PETSc.KSP().create() self.poisson_ksp.setFromOptions() self.poisson_ksp.setOperators(self.poisson_A) self.poisson_ksp.setType(cfg['solver']['petsc_ksp_type']) # self.poisson_ksp.setInitialGuessNonzero(True) self.poisson_pc = self.poisson_ksp.getPC() self.poisson_pc.setType('none') # create Arakawa solver object # self.mhd_rk4 = PETScRK4(self.da4, nx, ny, self.ht, self.hx, self.hy) # set initial data (xs, xe), (ys, ye) = self.da1.getRanges() coords = self.da1.getCoordinateDA().getVecArray(self.da1.getCoordinates()) # print # print(self.hx) # print(coords[1,0][0] - coords[0,0][0]) # print # print(self.hy) # print(coords[0,1][1] - coords[0,0][1]) # print # print(Lx) # print(coords[-1,0][0]+self.hx) # print # print(Ly) # print(coords[0,-1][1]+self.hy) # print x_arr = self.da4.getVecArray(self.x) Bx_arr = self.da1.getVecArray(self.Bx) By_arr = self.da1.getVecArray(self.By) Vx_arr = self.da1.getVecArray(self.Vx) Vy_arr = self.da1.getVecArray(self.Vy) P_arr = self.da1.getVecArray(self.P) if cfg['initial_data']['magnetic_python'] != None: init_data = __import__("runs." + cfg['initial_data']['magnetic_python'], globals(), locals(), ['magnetic_x', 'magnetic_y'], 0) for i in range(xs, xe): for j in range(ys, ye): Bx_arr[i,j] = init_data.magnetic_x(coords[i,j][0], coords[i,j][1], Lx, Ly) By_arr[i,j] = init_data.magnetic_y(coords[i,j][0], coords[i,j][1], Lx, Ly) else: Bx_arr[xs:xe, ys:ye] = cfg['initial_data']['magnetic'] By_arr[xs:xe, ys:ye] = cfg['initial_data']['magnetic'] if cfg['initial_data']['velocity_python'] != None: init_data = __import__("runs." + cfg['initial_data']['velocity_python'], globals(), locals(), ['velocity_x', 'velocity_y'], 0) for i in range(xs, xe): for j in range(ys, ye): Vx_arr[i,j] = init_data.velocity_x(coords[i,j][0], coords[i,j][1], Lx, Ly) Vy_arr[i,j] = init_data.velocity_y(coords[i,j][0], coords[i,j][1], Lx, Ly) else: Vx_arr[xs:xe, ys:ye] = cfg['initial_data']['velocity'] Vy_arr[xs:xe, ys:ye] = cfg['initial_data']['velocity'] if cfg['initial_data']['pressure_python'] != None: init_data = __import__("runs." + cfg['initial_data']['pressure_python'], globals(), locals(), ['pressure', ''], 0) for i in range(xs, xe): for j in range(ys, ye): P_arr[i,j] = init_data.pressure(coords[i,j][0], coords[i,j][1], Lx, Ly) #+ 0.5 * (Bx_arr[i,j]**2 + By_arr[i,j]**2) # copy distribution function to solution vector x_arr[xs:xe, ys:ye, 0] = Bx_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 1] = By_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 2] = Vx_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 3] = Vy_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 4] = P_arr [xs:xe, ys:ye] # update solution history self.petsc_matrix.update_history(self.x) self.petsc_function.update_history(self.x) self.petsc_jacobian.update_history(self.x) # create HDF5 output file self.hdf5_viewer = PETSc.Viewer().createHDF5(cfg['io']['hdf5_output'], mode=PETSc.Viewer.Mode.WRITE, comm=PETSc.COMM_WORLD) self.hdf5_viewer.HDF5PushGroup("/") # write grid data to hdf5 file coords_x = self.dax.getCoordinates() coords_y = self.day.getCoordinates() coords_x.setName('x') coords_y.setName('y') self.hdf5_viewer(coords_x) self.hdf5_viewer(coords_y) # write initial data to hdf5 file self.hdf5_viewer.HDF5SetTimestep(0) self.hdf5_viewer(self.time) # self.hdf5_viewer(self.x) # self.hdf5_viewer(self.b) self.hdf5_viewer(self.Bx) self.hdf5_viewer(self.By) self.hdf5_viewer(self.Vx) self.hdf5_viewer(self.Vy) self.hdf5_viewer(self.P)
def __init__(self, cfgfile, runid=None, cfg=None): super(viVlasov1Drunscript, self).__init__(cfgfile, runid, cfg) if PETSc.COMM_WORLD.getRank() == 0: print("Creating solver objects.") # create solver objects # self.vlasov_solver = PETScVlasovSolver( self.vlasov_solver = self.vlasov_object.PETScVlasovSolver( self.cfg, self.da1, self.dax, self.grid, self.h0, self.h1c, self.h1h, self.h2c, self.h2h, self.pc_int, self.charge, coll_freq=self.coll_freq, coll_drag=self.coll_drag, coll_diff=self.coll_diff) self.vlasov_solver.set_moments(self.nc, self.uc, self.ec, self.ac, self.nh, self.uh, self.eh, self.ah) # initialise matrixfree Jacobian self.Jmf.setPythonContext(self.vlasov_solver) self.Jmf.setUp() # create nonlinear predictor solver self.snes = PETSc.SNES().create() self.snes.setType('ksponly') self.snes.setFunction(self.vlasov_solver.function_snes_mult, self.fb) self.snes.setJacobian(self.updateVlasovJacobian, self.Jmf) self.snes.setFromOptions() self.snes.getKSP().setType('gmres') self.snes.getKSP().getPC().setType('none') # create Poisson matrix and object self.poisson_matrix = self.dax.createMat() self.poisson_matrix.setUp() self.poisson_matrix.setNullSpace(self.p_nullspace) self.poisson_solver = self.poisson_object.PETScPoissonSolver( self.dax, self.grid.nx, self.grid.hx, self.charge) self.poisson_solver.formMat(self.poisson_matrix) self.poisson_mf = PETSc.Mat().createPython( [self.pc_int.getSizes(), self.pb.getSizes()], context=self.poisson_solver, comm=PETSc.COMM_WORLD) self.poisson_mf.setUp() # create linear Poisson solver self.poisson_ksp = PETSc.KSP().create() self.poisson_ksp.setFromOptions() self.poisson_ksp.setTolerances(rtol=1E-13) self.poisson_ksp.setOperators(self.poisson_mf, self.poisson_matrix) self.poisson_ksp.setType('cg') # self.poisson_ksp.setType('bcgs') # self.poisson_ksp.setType('ibcgs') # self.poisson_ksp.getPC().setType('hypre') self.poisson_ksp.getPC().setType('lu') self.poisson_ksp.getPC().setFactorSolverPackage('superlu_dist') if PETSc.COMM_WORLD.getRank() == 0: print("Run script initialisation done.") print("")
def test_assembly_solve_taylor_hood_nl(mesh): """Assemble Stokes problem with Taylor-Hood elements and solve.""" gdim = mesh.geometry.dim P2 = VectorFunctionSpace(mesh, ("Lagrange", 2)) P1 = FunctionSpace(mesh, ("Lagrange", 1)) def boundary0(x): """Define boundary x = 0""" return np.isclose(x[0], 0.0) def boundary1(x): """Define boundary x = 1""" return np.isclose(x[0], 1.0) def initial_guess_u(x): u_init = np.row_stack( (np.sin(x[0]) * np.sin(x[1]), np.cos(x[0]) * np.cos(x[1]))) if gdim == 3: u_init = np.row_stack((u_init, np.cos(x[2]))) return u_init def initial_guess_p(x): return -x[0]**2 - x[1]**3 u_bc_0 = Function(P2) u_bc_0.interpolate( lambda x: np.row_stack(tuple(x[j] + float(j) for j in range(gdim)))) u_bc_1 = Function(P2) u_bc_1.interpolate( lambda x: np.row_stack(tuple(np.sin(x[j]) for j in range(gdim)))) facetdim = mesh.topology.dim - 1 bndry_facets0 = locate_entities_boundary(mesh, facetdim, boundary0) bndry_facets1 = locate_entities_boundary(mesh, facetdim, boundary1) bdofs0 = locate_dofs_topological(P2, facetdim, bndry_facets0) bdofs1 = locate_dofs_topological(P2, facetdim, bndry_facets1) bcs = [dirichletbc(u_bc_0, bdofs0), dirichletbc(u_bc_1, bdofs1)] u, p = Function(P2), Function(P1) du, dp = ufl.TrialFunction(P2), ufl.TrialFunction(P1) v, q = ufl.TestFunction(P2), ufl.TestFunction(P1) F = [ inner(ufl.grad(u), ufl.grad(v)) * dx + inner(p, ufl.div(v)) * dx, inner(ufl.div(u), q) * dx ] J = [[derivative(F[0], u, du), derivative(F[0], p, dp)], [derivative(F[1], u, du), derivative(F[1], p, dp)]] P = [[J[0][0], None], [None, inner(dp, q) * dx]] F, J, P = form(F), form(J), form(P) # -- Blocked and monolithic Jmat0 = create_matrix_block(J) Pmat0 = create_matrix_block(P) Fvec0 = create_vector_block(F) snes = PETSc.SNES().create(MPI.COMM_WORLD) snes.setTolerances(rtol=1.0e-15, max_it=10) snes.getKSP().setType("minres") snes.getKSP().getPC().setType("lu") problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs, P=P) snes.setFunction(problem.F_block, Fvec0) snes.setJacobian(problem.J_block, J=Jmat0, P=Pmat0) u.interpolate(initial_guess_u) p.interpolate(initial_guess_p) x0 = create_vector_block(F) with u.vector.localForm() as _u, p.vector.localForm() as _p: scatter_local_vectors(x0, [_u.array_r, _p.array_r], [(u.function_space.dofmap.index_map, u.function_space.dofmap.index_map_bs), (p.function_space.dofmap.index_map, p.function_space.dofmap.index_map_bs)]) x0.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) snes.solve(None, x0) assert snes.getConvergedReason() > 0 # -- Blocked and nested Jmat1 = create_matrix_nest(J) Pmat1 = create_matrix_nest(P) Fvec1 = create_vector_nest(F) snes = PETSc.SNES().create(MPI.COMM_WORLD) snes.setTolerances(rtol=1.0e-15, max_it=10) nested_IS = Jmat1.getNestISs() snes.getKSP().setType("minres") snes.getKSP().setTolerances(rtol=1e-12) snes.getKSP().getPC().setType("fieldsplit") snes.getKSP().getPC().setFieldSplitIS(["u", nested_IS[0][0]], ["p", nested_IS[1][1]]) ksp_u, ksp_p = snes.getKSP().getPC().getFieldSplitSubKSP() ksp_u.setType("preonly") ksp_u.getPC().setType('lu') ksp_p.setType("preonly") ksp_p.getPC().setType('lu') problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs, P=P) snes.setFunction(problem.F_nest, Fvec1) snes.setJacobian(problem.J_nest, J=Jmat1, P=Pmat1) u.interpolate(initial_guess_u) p.interpolate(initial_guess_p) x1 = create_vector_nest(F) for x1_soln_pair in zip(x1.getNestSubVecs(), (u, p)): x1_sub, soln_sub = x1_soln_pair soln_sub.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) soln_sub.vector.copy(result=x1_sub) x1_sub.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) x1.set(0.0) snes.solve(None, x1) assert snes.getConvergedReason() > 0 assert nest_matrix_norm(Jmat1) == pytest.approx(Jmat0.norm(), 1.0e-12) assert Fvec1.norm() == pytest.approx(Fvec0.norm(), 1.0e-12) assert x1.norm() == pytest.approx(x0.norm(), 1.0e-12) # -- Monolithic P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2) P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) TH = P2_el * P1_el W = FunctionSpace(mesh, TH) U = Function(W) dU = ufl.TrialFunction(W) u, p = ufl.split(U) du, dp = ufl.split(dU) v, q = ufl.TestFunctions(W) F = inner(ufl.grad(u), ufl.grad(v)) * dx + inner(p, ufl.div(v)) * dx \ + inner(ufl.div(u), q) * dx J = derivative(F, U, dU) P = inner(ufl.grad(du), ufl.grad(v)) * dx + inner(dp, q) * dx F, J, P = form(F), form(J), form(P) bdofsW0_P2_0 = locate_dofs_topological((W.sub(0), P2), facetdim, bndry_facets0) bdofsW0_P2_1 = locate_dofs_topological((W.sub(0), P2), facetdim, bndry_facets1) bcs = [ dirichletbc(u_bc_0, bdofsW0_P2_0, W.sub(0)), dirichletbc(u_bc_1, bdofsW0_P2_1, W.sub(0)) ] Jmat2 = create_matrix(J) Pmat2 = create_matrix(P) Fvec2 = create_vector(F) snes = PETSc.SNES().create(MPI.COMM_WORLD) snes.setTolerances(rtol=1.0e-15, max_it=10) snes.getKSP().setType("minres") snes.getKSP().getPC().setType("lu") problem = NonlinearPDE_SNESProblem(F, J, U, bcs, P=P) snes.setFunction(problem.F_mono, Fvec2) snes.setJacobian(problem.J_mono, J=Jmat2, P=Pmat2) U.sub(0).interpolate(initial_guess_u) U.sub(1).interpolate(initial_guess_p) x2 = create_vector(F) x2.array = U.vector.array_r snes.solve(None, x2) assert snes.getConvergedReason() > 0 assert Jmat2.norm() == pytest.approx(Jmat0.norm(), 1.0e-12) assert Fvec2.norm() == pytest.approx(Fvec0.norm(), 1.0e-12) assert x2.norm() == pytest.approx(x0.norm(), 1.0e-12)
def __init__(self, cfgfile): ''' Constructor ''' super().__init__(cfgfile, mode="lu") OptDB = PETSc.Options() OptDB.setValue('ksp_monitor', '') OptDB.setValue('snes_monitor', '') # OptDB.setValue('log_info', '') # OptDB.setValue('log_summary', '') OptDB.setValue('snes_ls', 'basic') # OptDB.setValue('snes_ls', 'quadratic') OptDB.setValue('snes_rtol', self.cfg['solver']['petsc_snes_rtol']) OptDB.setValue('snes_atol', self.cfg['solver']['petsc_snes_atol']) OptDB.setValue('snes_stol', self.cfg['solver']['petsc_snes_stol']) OptDB.setValue('snes_max_it', self.cfg['solver']['petsc_snes_max_iter']) OptDB.setValue('ksp_rtol', self.cfg['solver']['petsc_ksp_rtol']) OptDB.setValue('ksp_atol', self.cfg['solver']['petsc_ksp_atol']) OptDB.setValue('ksp_max_it', self.cfg['solver']['petsc_ksp_max_iter']) # OptDB.setValue('mat_superlu_dist_matinput', 'DISTRIBUTED') # OptDB.setValue('mat_superlu_dist_rowperm', 'NATURAL') OptDB.setValue('mat_superlu_dist_colperm', 'PARMETIS') OptDB.setValue('mat_superlu_dist_parsymbfact', 1) # create Jacobian, Function, and linear Matrix objects self.petsc_solver = PETScSolver(self.da1, self.da4, self.nx, self.ny, self.ht, self.hx, self.hy) # initialise linear matrix self.M = self.da4.createMat() self.M.setOption(PETSc.Mat.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.M.setUp() # initialise Jacobian self.Jac = self.da4.createMat() self.Jac.setOption(PETSc.Mat.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.Jac.setUp() # initialise matrixfree Jacobian self.Jmf = PETSc.Mat().createPython( [self.x.getSizes(), self.b.getSizes()], context=self.petsc_solver, comm=PETSc.COMM_WORLD) self.Jmf.setUp() # create nonlinear solver self.snes = PETSc.SNES().create() self.snes.setFunction(self.petsc_solver.snes_function, self.f) self.snes.setJacobian(self.updateJacobian, self.Jmf, self.Jac) self.snes.setFromOptions() self.snes.getKSP().setType('preonly') self.snes.getKSP().getPC().setType('lu') self.snes.getKSP().getPC().setFactorSolverType(self.solver_package) # update solution history self.petsc_solver.update_previous(self.x)
def __init__(self, cfgfile): ''' Constructor ''' # load run config file cfg = Config(cfgfile) # timestep setup self.ht = cfg['grid']['ht'] # timestep size self.nt = cfg['grid']['nt'] # number of timesteps self.nsave = cfg['io']['nsave'] # save only every nsave'th timestep # grid setup self.nx = cfg['grid']['nx'] # number of points in x self.ny = cfg['grid']['ny'] # number of points in y Lx = cfg['grid']['Lx'] # spatial domain in x x1 = cfg['grid']['x1'] # x2 = cfg['grid']['x2'] # Ly = cfg['grid']['Ly'] # spatial domain in y y1 = cfg['grid']['y1'] # y2 = cfg['grid']['y2'] # if x1 != x2: Lx = x2 - x1 else: x1 = 0.0 x2 = Lx if y1 != y2: Ly = y2 - y1 else: y1 = 0.0 y2 = Ly self.hx = Lx / self.nx # gridstep size in x self.hy = Ly / self.ny # gridstep size in y self.time = PETSc.Vec().createMPI(1, PETSc.DECIDE, comm=PETSc.COMM_WORLD) self.time.setName('t') if PETSc.COMM_WORLD.getRank() == 0: self.time.setValue(0, 0.0) OptDB = PETSc.Options() OptDB.setValue('snes_rtol', cfg['solver']['petsc_snes_rtol']) OptDB.setValue('snes_atol', cfg['solver']['petsc_snes_atol']) OptDB.setValue('snes_stol', cfg['solver']['petsc_snes_stol']) OptDB.setValue('snes_max_it', cfg['solver']['petsc_snes_max_iter']) OptDB.setValue('ksp_rtol', cfg['solver']['petsc_ksp_rtol']) OptDB.setValue('ksp_atol', cfg['solver']['petsc_ksp_atol']) OptDB.setValue('ksp_max_it', cfg['solver']['petsc_ksp_max_iter']) # OptDB.setValue('ksp_monitor', '') # OptDB.setValue('snes_monitor', '') # # OptDB.setValue('log_info', '') # OptDB.setValue('log_summary', '') self.snes_rtol = cfg['solver']['petsc_snes_rtol'] self.snes_atol = cfg['solver']['petsc_snes_atol'] self.snes_max_iter = cfg['solver']['petsc_snes_max_iter'] # create DA with single dof self.da1 = PETSc.DA().create(dim=2, dof=1, sizes=[self.nx, self.ny], proc_sizes=[PETSc.DECIDE, PETSc.DECIDE], boundary_type=('periodic', 'periodic'), stencil_width=2, stencil_type='box') # create DA (dof = 4 for A, J, P, O) self.da4 = PETSc.DA().create(dim=2, dof=4, sizes=[self.nx, self.ny], proc_sizes=[PETSc.DECIDE, PETSc.DECIDE], boundary_type=('periodic', 'periodic'), stencil_width=2, stencil_type='box') # create DA for x grid self.dax = PETSc.DA().create(dim=1, dof=1, sizes=[self.nx], proc_sizes=[PETSc.DECIDE], boundary_type=('periodic')) # create DA for y grid self.day = PETSc.DA().create(dim=1, dof=1, sizes=[self.ny], proc_sizes=[PETSc.DECIDE], boundary_type=('periodic')) # initialise grid self.da1.setUniformCoordinates(xmin=x1, xmax=x2, ymin=y1, ymax=y2) self.da4.setUniformCoordinates(xmin=x1, xmax=x2, ymin=y1, ymax=y2) self.dax.setUniformCoordinates(xmin=x1, xmax=x2) self.day.setUniformCoordinates(xmin=y1, xmax=y2) # create RHS vector self.Ab = self.da1.createGlobalVec() self.Ob = self.da1.createGlobalVec() self.Pb = self.da1.createGlobalVec() # create vectors for magnetic and velocity field self.A = self.da1.createGlobalVec() # magnetic vector potential A self.J = self.da1.createGlobalVec() # current density J self.P = self.da1.createGlobalVec() # streaming function psi self.O = self.da1.createGlobalVec() # vorticity omega self.Bx = self.da1.createGlobalVec() self.By = self.da1.createGlobalVec() self.Vx = self.da1.createGlobalVec() self.Vy = self.da1.createGlobalVec() # set variable names self.A.setName('A') self.J.setName('J') self.P.setName('P') self.O.setName('O') self.Bx.setName('Bx') self.By.setName('By') self.Vx.setName('Vx') self.Vy.setName('Vy') # create nullspace self.poisson_nullspace = PETSc.NullSpace().create(constant=True) # create jacobian and matrix objects self.petsc_vorticity = PETScVorticity(self.da1, self.nx, self.ny, self.ht, self.hx, self.hy) self.petsc_ohmslaw = PETScOhmsLaw(self.da1, self.nx, self.ny, self.ht, self.hx, self.hy) self.petsc_poisson = PETScPoisson(self.da1, self.nx, self.ny, self.hx, self.hy) # initialise vorticity matrix self.vorticity_matrix = self.da1.createMat() self.vorticity_matrix.setOption( self.vorticity_matrix.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.vorticity_matrix.setUp() # initialise Ohms's law matrix self.ohmslaw_matrix = self.da1.createMat() self.ohmslaw_matrix.setOption( self.ohmslaw_matrix.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.ohmslaw_matrix.setUp() # initialise Poisson matrix self.poisson_matrix = self.da1.createMat() self.poisson_matrix.setOption( self.poisson_matrix.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.poisson_matrix.setUp() self.poisson_matrix.setNullSpace(self.poisson_nullspace) # create nonlinear vorticity solver self.vorticity_snes = PETSc.SNES().create() self.vorticity_snes.setType('ksponly') self.vorticity_snes.setFunction(self.petsc_vorticity.snes_mult, self.Ob) self.vorticity_snes.setJacobian(self.update_vorticity_jacobian, self.vorticity_matrix) self.vorticity_snes.setFromOptions() # self.vorticity_snes.getKSP().setType('gmres') self.vorticity_snes.getKSP().setType('preonly') self.vorticity_snes.getKSP().getPC().setType('lu') self.vorticity_snes.getKSP().getPC().setFactorSolverPackage( solver_package) # create nonlinear Ohms's law solver self.ohmslaw_snes = PETSc.SNES().create() self.ohmslaw_snes.setType('ksponly') self.ohmslaw_snes.setFunction(self.petsc_ohmslaw.snes_mult, self.Ab) self.ohmslaw_snes.setJacobian(self.update_ohmslaw_jacobian, self.ohmslaw_matrix) self.ohmslaw_snes.setFromOptions() # self.ohmslaw_snes.getKSP().setType('gmres') self.ohmslaw_snes.getKSP().setType('preonly') self.ohmslaw_snes.getKSP().getPC().setType('lu') self.ohmslaw_snes.getKSP().getPC().setFactorSolverPackage( solver_package) # create linear Poisson solver self.poisson_ksp = PETSc.KSP().create() self.poisson_ksp.setFromOptions() self.poisson_ksp.setOperators(self.poisson_matrix) self.poisson_ksp.setType('preonly') self.poisson_ksp.getPC().setType('lu') self.poisson_ksp.getPC().setFactorSolverPackage(solver_package) # self.poisson_ksp.setNullSpace(self.poisson_nullspace) self.petsc_poisson.formMat(self.poisson_matrix) # create derivatives object self.derivatives = PETScDerivatives(self.da1, self.nx, self.ny, self.ht, self.hx, self.hy) # get coordinate vectors coords_x = self.dax.getCoordinates() coords_y = self.day.getCoordinates() # save x coordinate arrays scatter, xVec = PETSc.Scatter.toAll(coords_x) scatter.begin(coords_x, xVec, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) scatter.end(coords_x, xVec, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) xGrid = xVec.getValues(range(0, self.nx)).copy() scatter.destroy() xVec.destroy() # save y coordinate arrays scatter, yVec = PETSc.Scatter.toAll(coords_y) scatter.begin(coords_y, yVec, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) scatter.end(coords_y, yVec, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) yGrid = yVec.getValues(range(0, self.ny)).copy() scatter.destroy() yVec.destroy() # set initial data (xs, xe), (ys, ye) = self.da1.getRanges() A_arr = self.da1.getVecArray(self.A) P_arr = self.da1.getVecArray(self.P) init_data = __import__("runs." + cfg['initial_data']['python'], globals(), locals(), ['magnetic_A', 'velocity_P'], 0) for i in range(xs, xe): for j in range(ys, ye): A_arr[i, j] = init_data.magnetic_A(xGrid[i], yGrid[j], Lx, Ly) P_arr[i, j] = init_data.velocity_P(xGrid[i], yGrid[j], Lx, Ly) # Fourier Filtering self.nfourier = cfg['initial_data']['nfourier'] if self.nfourier >= 0: # obtain whole A vector everywhere scatter, Aglobal = PETSc.Scatter.toAll(self.A) scatter.begin(self.A, Aglobal, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) scatter.end(self.A, Aglobal, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) petsc_indices = self.da1.getAO().app2petsc( np.arange(self.nx * self.ny, dtype=np.int32)) Ainit = Aglobal.getValues(petsc_indices).copy().reshape( (self.ny, self.nx)) scatter.destroy() Aglobal.destroy() # compute FFT, cut, compute inverse FFT from scipy.fftpack import rfft, irfft Afft = rfft(Ainit, axis=1) Afft[:, 0] = 0. Afft[:, self.nfourier + 1:] = 0. A_arr = self.da1.getVecArray(self.A) A_arr[:, :] = irfft(Afft).T[xs:xe, ys:ye] # compute current and vorticity self.derivatives.laplace_vec(self.A, self.J, -1.) self.derivatives.laplace_vec(self.P, self.O, -1.) J_arr = self.da1.getVecArray(self.J) O_arr = self.da1.getVecArray(self.O) # add perturbations for i in range(xs, xe): for j in range(ys, ye): J_arr[i, j] += init_data.current_perturbation( xGrid[i], yGrid[j], Lx, Ly) O_arr[i, j] += init_data.vorticity_perturbation( xGrid[i], yGrid[j], Lx, Ly) # create HDF5 output file self.hdf5_viewer = PETSc.ViewerHDF5().create( cfg['io']['hdf5_output'], mode=PETSc.Viewer.Mode.WRITE, comm=PETSc.COMM_WORLD) self.hdf5_viewer.pushGroup("/") # write grid data to hdf5 file coords_x = self.dax.getCoordinates() coords_y = self.day.getCoordinates() coords_x.setName('x') coords_y.setName('y') self.hdf5_viewer(coords_x) self.hdf5_viewer(coords_y) # write initial data to hdf5 file self.save_to_hdf5(0)
def __init__(self, cfgfile, runid): super().__init__(cfgfile, runid) OptDB = PETSc.Options() # OptDB.setValue('snes_ls', 'basic') # OptDB.setValue('ksp_monitor', '') # OptDB.setValue('snes_monitor', '') # OptDB.setValue('log_info', '') # OptDB.setValue('log_summary', '') # initialise predictor Jacobian self.J = self.da1.createMat() self.J.setOption(self.J.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.J.setUp() # create solver objects self.vlasov_solver = PETScVlasovSolver(self.da1, self.dax, self.h0, self.vGrid, self.nx, self.nv, self.ht, self.hx, self.hv, self.charge, coll_freq=self.coll_freq) # update solution history self.vlasov_solver.update_history(self.f, self.p, self.p_ext, self.n, self.u, self.e) # create nonlinear predictor solver self.snes = PETSc.SNES().create() self.snes.setType('ksponly') self.snes.setFunction(self.vlasov_solver.function_snes_mult, self.fb) self.snes.setJacobian(self.updateVlasovJacobian, self.J) self.snes.setFromOptions() self.snes.getKSP().setType('gmres') self.snes.getKSP().getPC().setType('none') self.poisson_mf = PETSc.Mat().createPython( [self.p.getSizes(), self.pb.getSizes()], context=self.poisson_solver, comm=PETSc.COMM_WORLD) self.poisson_mf.setUp() del self.poisson_ksp OptDB.setValue('ksp_rtol', 1E-13) self.poisson_ksp = PETSc.KSP().create() self.poisson_ksp.setFromOptions() self.poisson_ksp.setOperators(self.poisson_mf, self.poisson_matrix) self.poisson_ksp.setType('cg') # self.poisson_ksp.setType('bcgs') # self.poisson_ksp.setType('ibcgs') self.poisson_ksp.getPC().setType('hypre') OptDB.setValue('ksp_rtol', self.cfg['solver']['petsc_ksp_rtol'])
def __init__(self, cfgfile): ''' Constructor ''' # stencil = 1 stencil = 2 # load run config file cfg = Config(cfgfile) self.cfg = cfg cfg.set_petsc_options() # timestep setup self.ht = cfg['grid']['ht'] # timestep size self.nt = cfg['grid']['nt'] # number of timesteps self.nsave = cfg['io']['nsave'] # save only every nsave'th timestep # grid setup nx = cfg['grid']['nx'] # number of points in x ny = cfg['grid']['ny'] # number of points in y Lx = cfg['grid']['Lx'] # spatial domain in x x1 = cfg['grid']['x1'] # x2 = cfg['grid']['x2'] # Ly = cfg['grid']['Ly'] # spatial domain in y y1 = cfg['grid']['y1'] # y2 = cfg['grid']['y2'] # self.nx = nx self.ny = ny if x1 != x2: Lx = x2 - x1 else: x1 = 0.0 x2 = Lx if y1 != y2: Ly = y2 - y1 else: y1 = 0.0 y2 = Ly self.hx = Lx / nx # gridstep size in x self.hy = Ly / ny # gridstep size in y # friction, viscosity and resistivity mu = cfg['initial_data']['mu'] # friction nu = cfg['initial_data']['nu'] # viscosity eta = cfg['initial_data']['eta'] # resistivity de = cfg['initial_data']['de'] # electron skin depth # self.update_jacobian = True if PETSc.COMM_WORLD.getRank() == 0: print() print("nt = %i" % (self.nt)) print("nx = %i" % (self.nx)) print("ny = %i" % (self.ny)) print() print("ht = %e" % (self.ht)) print("hx = %e" % (self.hx)) print("hy = %e" % (self.hy)) print() print("Lx = %e" % (Lx)) print("Ly = %e" % (Ly)) print() print("mu = %e" % (mu)) print("nu = %e" % (nu)) print("eta = %e" % (eta)) print() self.time = PETSc.Vec().createMPI(1, PETSc.DECIDE, comm=PETSc.COMM_WORLD) self.time.setName('t') if PETSc.COMM_WORLD.getRank() == 0: self.time.setValue(0, 0.0) # create derivatives object self.derivatives = MHD_Derivatives(nx, ny, self.ht, self.hx, self.hy) # create DA with single dof self.da1 = PETSc.DA().create(dim=2, dof=1, sizes=[nx, ny], proc_sizes=[PETSc.DECIDE, PETSc.DECIDE], boundary_type=('periodic', 'periodic'), stencil_width=stencil, stencil_type='box') # create DA (dof = 7 for Vx, Vy, Bx, By, Bix, Biy, P) self.da7 = PETSc.DA().create(dim=2, dof=7, sizes=[nx, ny], proc_sizes=[PETSc.DECIDE, PETSc.DECIDE], boundary_type=('periodic', 'periodic'), stencil_width=stencil, stencil_type='box') # create DA for x grid self.dax = PETSc.DA().create(dim=1, dof=1, sizes=[nx], proc_sizes=[PETSc.DECIDE], boundary_type=('periodic')) # create DA for y grid self.day = PETSc.DA().create(dim=1, dof=1, sizes=[ny], proc_sizes=[PETSc.DECIDE], boundary_type=('periodic')) # initialise grid self.da1.setUniformCoordinates(xmin=x1, xmax=x2, ymin=y1, ymax=y2) self.da7.setUniformCoordinates(xmin=x1, xmax=x2, ymin=y1, ymax=y2) self.dax.setUniformCoordinates(xmin=x1, xmax=x2) self.day.setUniformCoordinates(xmin=y1, xmax=y2) # create solution and RHS vector self.f = self.da7.createGlobalVec() self.x = self.da7.createGlobalVec() self.b = self.da7.createGlobalVec() # create global RK4 vectors self.Y = self.da7.createGlobalVec() self.X0 = self.da7.createGlobalVec() self.X1 = self.da7.createGlobalVec() self.X2 = self.da7.createGlobalVec() self.X3 = self.da7.createGlobalVec() self.X4 = self.da7.createGlobalVec() # create local RK4 vectors self.localX0 = self.da7.createLocalVec() self.localX1 = self.da7.createLocalVec() self.localX2 = self.da7.createLocalVec() self.localX3 = self.da7.createLocalVec() self.localX4 = self.da7.createLocalVec() # self.localP = self.da1.createLocalVec() # create vectors for magnetic and velocity field self.Bix = self.da1.createGlobalVec() self.Biy = self.da1.createGlobalVec() self.Bx = self.da1.createGlobalVec() self.By = self.da1.createGlobalVec() self.Vx = self.da1.createGlobalVec() self.Vy = self.da1.createGlobalVec() self.P = self.da1.createGlobalVec() self.xcoords = self.da1.createGlobalVec() self.ycoords = self.da1.createGlobalVec() # create local vectors for initialisation of pressure self.localBix = self.da1.createLocalVec() self.localBiy = self.da1.createLocalVec() self.localBx = self.da1.createLocalVec() self.localBy = self.da1.createLocalVec() self.localVx = self.da1.createLocalVec() self.localVy = self.da1.createLocalVec() # set variable names self.Bix.setName('Bix') self.Biy.setName('Biy') self.Bx.setName('Bx') self.By.setName('By') self.Vx.setName('Vx') self.Vy.setName('Vy') self.P.setName('P') # create Matrix object self.petsc_matrix = PETScMatrix(self.da1, self.da7, nx, ny, self.ht, self.hx, self.hy, mu, nu, eta, de) self.petsc_function = PETScFunction(self.da1, self.da7, nx, ny, self.ht, self.hx, self.hy, mu, nu, eta, de) # initialise matrix self.A = self.da7.createMat() self.A.setOption(self.A.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.A.setUp() # create jacobian self.J = self.da7.createMat() self.J.setOption(self.J.Option.NEW_NONZERO_ALLOCATION_ERR, False) self.J.setUp() # create nonlinear solver self.snes = PETSc.SNES().create() self.snes.setFunction(self.petsc_function.snes_mult, self.f) self.snes.setJacobian(self.updateJacobian, self.J) self.snes.setFromOptions() # self.snes.getKSP().setInitialGuessNonzero(True) # self.snes.getKSP().getPC().setReusePreconditioner(True) self.ksp = None # set initial data (xs, xe), (ys, ye) = self.da1.getRanges() # coords = self.da1.getCoordinatesLocal() xc_arr = self.da1.getVecArray(self.xcoords) yc_arr = self.da1.getVecArray(self.ycoords) for i in range(xs, xe): for j in range(ys, ye): xc_arr[i, j] = x1 + i * self.hx yc_arr[i, j] = y1 + j * self.hy if cfg['io']['hdf5_input'] != None: hdf5_filename = self.cfg["io"]["hdf5_input"] if PETSc.COMM_WORLD.getRank() == 0: print(" Input: %s" % hdf5_filename) hdf5in = h5py.File(hdf5_filename, "r", driver="mpio", comm=PETSc.COMM_WORLD.tompi4py()) # assert self.nx == hdf5in.attrs["grid.nx"] # assert self.ny == hdf5in.attrs["grid.ny"] # assert self.hx == hdf5in.attrs["grid.hx"] # assert self.hy == hdf5in.attrs["grid.hy"] # assert self.Lx == hdf5in.attrs["grid.Lx"] # assert self.Ly == hdf5in.attrs["grid.Ly"] # # assert self.de == hdf5in.attrs["initial_data.skin_depth"] timestep = len(hdf5in["t"][...].flatten()) - 1 hdf5in.close() hdf5_viewer = PETSc.ViewerHDF5().create( cfg['io']['hdf5_input'], mode=PETSc.Viewer.Mode.READ, comm=PETSc.COMM_WORLD) hdf5_viewer.setTimestep(timestep) self.Bix.load(hdf5_viewer) self.Biy.load(hdf5_viewer) self.Bx.load(hdf5_viewer) self.By.load(hdf5_viewer) self.Vx.load(hdf5_viewer) self.Vy.load(hdf5_viewer) self.P.load(hdf5_viewer) hdf5_viewer.destroy() # copy modified magnetic induction to solution vector Bx_arr = self.da1.getVecArray(self.Bx) By_arr = self.da1.getVecArray(self.By) Vx_arr = self.da1.getVecArray(self.Vx) Vy_arr = self.da1.getVecArray(self.Vy) Bix_arr = self.da1.getVecArray(self.Bix) Biy_arr = self.da1.getVecArray(self.Biy) P_arr = self.da1.getVecArray(self.P) x_arr = self.da7.getVecArray(self.x) x_arr[xs:xe, ys:ye, 0] = Vx_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 1] = Vy_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 2] = Bx_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 3] = By_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 4] = Bix_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 5] = Biy_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 6] = P_arr[xs:xe, ys:ye] else: Bx_arr = self.da1.getVecArray(self.Bx) By_arr = self.da1.getVecArray(self.By) Vx_arr = self.da1.getVecArray(self.Vx) Vy_arr = self.da1.getVecArray(self.Vy) xc_arr = self.da1.getVecArray(self.xcoords) yc_arr = self.da1.getVecArray(self.ycoords) if cfg['initial_data']['magnetic_python'] != None: init_data = __import__( "examples." + cfg['initial_data']['magnetic_python'], globals(), locals(), ['magnetic_x', 'magnetic_y'], 0) for i in range(xs, xe): for j in range(ys, ye): Bx_arr[i, j] = init_data.magnetic_x( xc_arr[i, j], yc_arr[i, j] + 0.5 * self.hy, self.hx, self.hy) By_arr[i, j] = init_data.magnetic_y( xc_arr[i, j] + 0.5 * self.hx, yc_arr[i, j], self.hx, self.hy) else: Bx_arr[xs:xe, ys:ye] = cfg['initial_data']['magnetic'] By_arr[xs:xe, ys:ye] = cfg['initial_data']['magnetic'] if cfg['initial_data']['velocity_python'] != None: init_data = __import__( "examples." + cfg['initial_data']['velocity_python'], globals(), locals(), ['velocity_x', 'velocity_y'], 0) for i in range(xs, xe): for j in range(ys, ye): Vx_arr[i, j] = init_data.velocity_x( xc_arr[i, j], yc_arr[i, j] + 0.5 * self.hy, self.hx, self.hy) Vy_arr[i, j] = init_data.velocity_y( xc_arr[i, j] + 0.5 * self.hx, yc_arr[i, j], self.hx, self.hy) else: Vx_arr[xs:xe, ys:ye] = cfg['initial_data']['velocity'] Vy_arr[xs:xe, ys:ye] = cfg['initial_data']['velocity'] if cfg['initial_data']['pressure_python'] != None: init_data = __import__( "examples." + cfg['initial_data']['pressure_python'], globals(), locals(), ['pressure', ''], 0) # Fourier Filtering from scipy.fftpack import rfft, irfft nfourier_x = cfg['initial_data']['nfourier_Bx'] nfourier_y = cfg['initial_data']['nfourier_By'] if nfourier_x >= 0 or nfourier_y >= 0: print("Fourier Filtering B") # obtain whole Bx vector everywhere scatter, Xglobal = PETSc.Scatter.toAll(self.Bx) scatter.begin(self.Bx, Xglobal, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) scatter.end(self.Bx, Xglobal, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) petsc_indices = self.da1.getAO().app2petsc( np.arange(self.nx * self.ny, dtype=np.int32)) BxTmp = Xglobal.getValues(petsc_indices).copy().reshape( (self.ny, self.nx)).T scatter.destroy() Xglobal.destroy() # obtain whole By vector everywhere scatter, Xglobal = PETSc.Scatter.toAll(self.By) scatter.begin(self.By, Xglobal, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) scatter.end(self.By, Xglobal, PETSc.InsertMode.INSERT, PETSc.ScatterMode.FORWARD) petsc_indices = self.da1.getAO().app2petsc( np.arange(self.nx * self.ny, dtype=np.int32)) ByTmp = Xglobal.getValues(petsc_indices).copy().reshape( (self.ny, self.nx)).T scatter.destroy() Xglobal.destroy() if nfourier_x >= 0: # compute FFT, cut, compute inverse FFT BxFft = rfft(BxTmp, axis=1) ByFft = rfft(ByTmp, axis=1) BxFft[:, nfourier_x + 1:] = 0. ByFft[:, nfourier_x + 1:] = 0. BxTmp = irfft(BxFft, axis=1) ByTmp = irfft(ByFft, axis=1) if nfourier_y >= 0: BxFft = rfft(BxTmp, axis=0) ByFft = rfft(ByTmp, axis=0) BxFft[nfourier_y + 1:, :] = 0. ByFft[nfourier_y + 1:, :] = 0. BxTmp = irfft(BxFft, axis=0) ByTmp = irfft(ByFft, axis=0) Bx_arr = self.da1.getVecArray(self.Bx) By_arr = self.da1.getVecArray(self.By) Bx_arr[:, :] = BxTmp[xs:xe, ys:ye] By_arr[:, :] = ByTmp[xs:xe, ys:ye] Bx_arr = self.da1.getVecArray(self.Bx) By_arr = self.da1.getVecArray(self.By) Vx_arr = self.da1.getVecArray(self.Vx) Vy_arr = self.da1.getVecArray(self.Vy) x_arr = self.da7.getVecArray(self.x) x_arr[xs:xe, ys:ye, 0] = Vx_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 1] = Vy_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 2] = Bx_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 3] = By_arr[xs:xe, ys:ye] # compure generalised magnetic induction self.da1.globalToLocal(self.Bx, self.localBx) self.da1.globalToLocal(self.By, self.localBy) self.da1.globalToLocal(self.Vx, self.localVx) self.da1.globalToLocal(self.Vy, self.localVy) Bx_arr = self.da1.getVecArray(self.localBx) By_arr = self.da1.getVecArray(self.localBy) Vx_arr = self.da1.getVecArray(self.localVx) Vy_arr = self.da1.getVecArray(self.localVy) Bix_arr = self.da1.getVecArray(self.Bix) Biy_arr = self.da1.getVecArray(self.Biy) for i in range(xs, xe): for j in range(ys, ye): Bix_arr[i, j] = self.derivatives.Bix(Bx_arr[...], By_arr[...], i - xs + 2, j - ys + 2, de) Biy_arr[i, j] = self.derivatives.Biy(Bx_arr[...], By_arr[...], i - xs + 2, j - ys + 2, de) # copy modified magnetic induction to solution vector x_arr = self.da7.getVecArray(self.x) x_arr[xs:xe, ys:ye, 4] = Bix_arr[xs:xe, ys:ye] x_arr[xs:xe, ys:ye, 5] = Biy_arr[xs:xe, ys:ye] # compute pressure self.da1.globalToLocal(self.Bix, self.localBix) self.da1.globalToLocal(self.Biy, self.localBiy) Bix_arr = self.da1.getVecArray(self.localBix) Biy_arr = self.da1.getVecArray(self.localBiy) P_arr = self.da1.getVecArray(self.P) for i in range(xs, xe): for j in range(ys, ye): P_arr[i,j] = init_data.pressure(xc_arr[i,j] + 0.5 * self.hx, yc_arr[i,j] + 0.5 * self.hy, self.hx, self.hy) \ - 0.5 * 0.25 * (Bix_arr[i,j] + Bix_arr[i+1,j]) * (Bx_arr[i,j] + Bx_arr[i+1,j]) \ - 0.5 * 0.25 * (Biy_arr[i,j] + Biy_arr[i,j+1]) * (By_arr[i,j] + By_arr[i,j+1]) \ # - 0.5 * (0.25 * (Vx_arr[i,j] + Vx_arr[i+1,j])**2 + 0.25 * (Vy_arr[i,j] + Vy_arr[i,j+1])**2) # copy pressure to solution vector x_arr = self.da7.getVecArray(self.x) x_arr[xs:xe, ys:ye, 6] = P_arr[xs:xe, ys:ye] # update solution history self.petsc_matrix.update_history(self.x) self.petsc_function.update_history(self.x) hdf5_filename = cfg['io']['hdf5_output'] if PETSc.COMM_WORLD.getRank() == 0: print(" Output: %s" % hdf5_filename) hdf5out = h5py.File(hdf5_filename, "w", driver="mpio", comm=PETSc.COMM_WORLD.tompi4py()) for cfg_group in self.cfg: for cfg_item in self.cfg[cfg_group]: if self.cfg[cfg_group][cfg_item] != None: value = self.cfg[cfg_group][cfg_item] else: value = "" hdf5out.attrs[cfg_group + "." + cfg_item] = value # if self.cfg["initial_data"]["python"] != None and self.cfg["initial_data"]["python"] != "": # python_input = open("runs/" + self.cfg['initial_data']['python'] + ".py", 'r') # python_file = python_input.read() # python_input.close() # else: # python_file = "" # hdf5out.attrs["initial_data.python_file"] = python_file hdf5out.close() # create HDF5 output file self.hdf5_viewer = PETSc.ViewerHDF5().create( hdf5_filename, mode=PETSc.Viewer.Mode.WRITE, comm=PETSc.COMM_WORLD) self.hdf5_viewer.pushGroup("/") # write grid data to hdf5 file coords_x = self.dax.getCoordinates() coords_y = self.day.getCoordinates() coords_x.setName('x') coords_y.setName('y') self.hdf5_viewer(coords_x) self.hdf5_viewer(coords_y) # write initial data to hdf5 file self.hdf5_viewer.setTimestep(0) self.save_hdf5_vectors()
def main(): # 'linear;, 'quadratic' or 'cubic' elementType = 'cubic' # '2pt','3pt', '4pt' quadratureRule = '4pt' # meshType = 'uniform' or 'adaptive' meshType = 'uniform' # FIXME: generalize later numAtoms = 1 if(numAtoms == 1): # define number of elements numberElements = 52 # define domain size in 1D domainStart = -17.5 domainEnd = 17.5 #define parameters for adaptive Mesh innerDomainSize = 8 innerMeshSize = 0.25 #read the external potental from matlab if(meshType == 'uniform'): pot = open('vpotOneAtomUniform52Elem.txt','r') else : pot = open('vpotOneAtomAdaptive52Elem.txt','r') else: # define number of elements numberElements = 84 # define domain size in 1D domainStart = -17.5 domainEnd = 17.5 #define parameters for adaptive Mesh innerDomainSize = 16 innerMeshSize = 0.25 #read the external potental from matlab if(meshType =='uniform'): pot = open('vpot14AtomUniform84Elem.txt','r') else : pot = open('vpot14AtomAdaptive84Elem.txt','r') # create FEM object fem=FEM.FEM(numberElements, quadratureRule, elementType, domainStart, domainEnd, innerDomainSize, innerMeshSize, meshType) # mesh the domain in 1D globalNodalCoordinates = fem.generateNodes() # generate Adaptive Mesh numberNodes = fem.numberNodes #get number quadrature points numberQuadraturePoints = fem.getNumberQuadPointsPerElement() totalnumberQuadraturePoints = numberElements*numberQuadraturePoints v= [] for line in pot: v.append(float(line)) v = np.array(v) data= np.reshape(v,(totalnumberQuadraturePoints,totalnumberQuadraturePoints,totalnumberQuadraturePoints)) # reducedRank rankVeff = 5 reducedRank = (rankVeff, rankVeff, rankVeff) #perform tensor decomposition of effective potential time_tensorStart = time.clock() #convert to a tensor fTensor = tensor.tensor(data) [a,b] = DTA.DTA(fTensor,reducedRank) time_tensorEnd = time.clock() print 'time elapsed for tensor decomposition of Veff (s)',time_tensorEnd-time_tensorStart sigma_core = a.core sigma = sigma_core.tondarray() umat = a.u[0].real vmat = a.u[1].real wmat = a.u[2].real sigma = sigma.real sigma2D = sigma.reshape((rankVeff**2,rankVeff)) # done to reduce cost while contracting functional = FunctionalRayleighQuotientSeparable.FEMFunctional(fem, rankVeff, sigma2D, [umat,vmat,wmat]) # initial guess for psix, psiy, psiz xx = globalNodalCoordinates yy = xx.copy() zz = xx.copy() X, Y, Z = meshgrid2(xx,yy,zz) psixyz = (1/np.sqrt(np.pi))*np.exp(-np.sqrt(X**2 + Y**2 + Z**2)) igTensor = tensor.tensor(psixyz) # generate tensor decomposition of above guess of rank 1 time_tensorStart = time.clock() rankIG = (1,1,1) [Psi,Xi] = DTA.DTA(igTensor,rankIG) time_tensorEnd = time.clock() print 'time elapsed(s) for DTA of initial guess',time_tensorEnd-time_tensorStart guessPsix = Psi.u[0].real guessPsiy = Psi.u[1].real guessPsiz = Psi.u[2].real guessLM = 0.2 guessFields = np.concatenate((guessPsix[1:-1],guessPsiy[1:-1],guessPsiz[1:-1])) #append the initial guess for lagrange multiplier guessFields = np.append(guessFields,guessLM) petsc = True if (petsc == False): t0 = time.clock() print 'Method fsolve' [result,infodict,ier,mesg] = scipy.optimize.fsolve(residual,guessFields,args=(functional),full_output=1,xtol=1.0e-8,maxfev=20000) print 'Number of Function Evaluations: ',infodict['nfev'] print 'Ground State Energy: ',result[-1] print 'numberElements ',numberElements print mesg t1 = time.clock() print 'time elapsed(s) for minimization problem',t1-t0 else: t0 = time.clock() snes = PETSc.SNES().create() pde = SeparableHamiltonian(functional) n = len(guessFields) F = PETSc.Vec().createSeq(n) snes.setFunction(pde.residualPetsc,F) snes.setUseMF() snes.getKSP().setType('gmres') snes.setFromOptions() X = PETSc.Vec().createSeq(n) pde.formInitGuess(snes, X,guessFields) snes.solve(None, X) print X[n-1] t1 = time.clock() print 'time elapsed(s) for minimization problem',t1-t0 result = pde.copySolution(X,guessFields)