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("")
예제 #2
0
    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()
예제 #3
0
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()
예제 #4
0
 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()
예제 #5
0
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
예제 #6
0
    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()
예제 #7
0
 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
     })
예제 #8
0
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
예제 #9
0
    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()
예제 #10
0
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
예제 #11
0
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
예제 #12
0
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
예제 #13
0
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
예제 #14
0
파일: __init__.py 프로젝트: kumiori/mec647
    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
예제 #15
0
    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)
예제 #16
0
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:
예제 #17
0
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)
예제 #18
0
파일: test_snes.py 프로젝트: zonca/petsc4py
 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()
예제 #21
0
    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))
예제 #23
0
    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)
예제 #24
0
    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("")
예제 #25
0
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)
예제 #26
0
    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)
예제 #27
0
    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'])
예제 #29
0
    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()
예제 #30
0
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)