예제 #1
0
def main(n):
    '''Solves grad-div problem in 2d with HypreAMS preconditioning'''
    # Exact solution
    x, y = sp.symbols('x[0] x[1]')

    sigma = sp.Matrix([sp.cos(pi * y**2), sp.sin(pi * x**2)])

    sp_div = lambda f: f[0].diff(x, 1) + f[1].diff(y, 1)

    sp_grad = lambda f: sp.Matrix([f.diff(x, 1), f.diff(y, 1)])

    f = -sp_grad(sp_div(sigma)) + sigma

    sigma_expr, f_expr = map(as_expression, (sigma, f))

    # The discrete problem
    mesh = UnitSquareMesh(n, n)

    V = FunctionSpace(mesh, 'RT', 1)
    u, v = TrialFunction(V), TestFunction(V)

    a = inner(div(u), div(v)) * dx + inner(u, v) * dx
    L = inner(f_expr, v) * dx

    A, b = assemble_system(a, L)

    # Solve
    Q = FunctionSpace(mesh, 'CG', 1)
    G = DiscreteOperators.build_gradient(V, Q)

    ksp = PETSc.KSP().create(PETSc.COMM_WORLD)
    ksp.setType('cg')
    ksp.setTolerances(rtol=1E-8, atol=1E-12, divtol=1.0E10, max_it=300)

    opts = PETSc.Options()
    opts.setValue("ksp_monitor_true_residual", None)
    ksp.setFromOptions()

    # AMS preconditioner
    pc = ksp.getPC()
    pc.setType('hypre')
    pc.setHYPREType('ams')

    vec = lambda x: as_backend_type(x).vec()
    mat = lambda A: as_backend_type(A).mat()

    # Attach gradient
    pc.setHYPREDiscreteGradient(mat(G))

    # Constant nullspace (in case not mass and bcs)
    constants = [
        vec(interpolate(c, V).vector())
        for c in (Constant((1, 0)), Constant((0, 1)))
    ]

    pc.setHYPRESetEdgeConstantVectors(*constants)
    # NOTE: term mass term is accounted for automatically by Hypre
    # unless pc.setPoissonBetaMatrix(None)

    # Set operator for the linear solver
    ksp.setOperators(mat(A))

    uh = Function(V)

    ksp.solve(vec(b), vec(uh.vector()))

    niters = ksp.getIterationNumber()
    error = errornorm(sigma_expr, uh, 'Hdiv', degree_rise=1)
    hmin = mesh.mpi_comm().tompi4py().allreduce(mesh.hmin(), pyMPI.MIN)

    return hmin, V.dim(), niters, error
예제 #2
0
        uu = Function(W)
        tic()
        AA, bb = assemble_system(a, L1 - RHSform, bcs)
        A, b = CP.Assemble(AA, bb)
        print toc()
        print A
        # b = b.getSubVector(t_is)
        PP = assemble(prec)
        bcc.apply(PP)
        P = CP.Assemble(PP)

        b = bb.array()
        zeros = 0 * b
        bb = IO.arrayToVec(b)
        x = IO.arrayToVec(zeros)
        ksp = PETSc.KSP()
        ksp.create(comm=PETSc.COMM_WORLD)
        # ksp.setTolerances(1e-5)
        ksp.setType('preonly')
        pc = ksp.getPC()

        pc.setType(PETSc.PC.Type.LU)
        # if Solver == "LSC":
        #     pc.setPythonContext(NSprecond.LSCnew(W,A,L,Bd,dBt))
        # elif Solver == "PCD":
        # F = assemble(fp)
        # F = CP.Assemble(F)
        #     pc.setPythonContext(NSprecond.PCD(W, A, Mass, F, L))

        ksp.setOperators(A)
        OptDB = PETSc.Options()
예제 #3
0
    def solve_GenEO_eigmin(self, V0s, tauGenEO_eigmin):
        """
        Solves the local GenEO eigenvalue problem related to the smallest eigenvalue eigmin.

        Parameters
        ==========

        V0s : list of local PETSc .vecs
            V0s may already contain some local coarse vectors. This routine will possibly add more vectors to the list.

        tauGenEO_eigmin: Real.
            Threshold for selecting eigenvectors for the coarse space.

        """
        if tauGenEO_eigmin > 0:
            #to compute the smallest eigenvalues of the preconditioned matrix, Ms must be factorized
            tempksp = PETSc.KSP().create(comm=PETSc.COMM_SELF)
            tempksp.setOperators(self.Ms)
            tempksp.setType('preonly')
            temppc = tempksp.getPC()
            temppc.setType('cholesky')
            temppc.setFactorSolverType('mumps')
            temppc.setFactorSetUpSolverType()
            tempF = temppc.getFactorMatrix()
            tempF.setMumpsIcntl(7, 2)
            tempF.setMumpsIcntl(24, 1)
            tempF.setMumpsCntl(3, self.mumpsCntl3)
            temppc.setUp()
            tempnrb = tempF.getMumpsInfog(28)

            for i in range(tempnrb):
                tempF.setMumpsIcntl(25, i + 1)
                self.works.set(0.)
                tempksp.solve(self.works, self.works)
                V0s.append(self.works.copy())

            tempF.setMumpsIcntl(25, 0)
            if self.verbose:
                PETSc.Sys.Print(
                    'Subdomain number {} contributes {} coarse vectors as zero energy modes of the scaled local operator (in GenEO for eigmin)'
                    .format(mpi.COMM_WORLD.rank, tempnrb),
                    comm=self.comm)

            #Eigenvalue Problem for smallest eigenvalues
            eps = SLEPc.EPS().create(comm=PETSc.COMM_SELF)
            eps.setDimensions(nev=self.nev)

            eps.setProblemType(SLEPc.EPS.ProblemType.GHIEP)
            eps.setOperators(self.Ms, self.Atildes)
            eps.setWhichEigenpairs(SLEPc.EPS.Which.TARGET_REAL)
            eps.setTarget(0.)
            ST = eps.getST()

            ST.setType("sinvert")
            ST.setKSP(tempksp)

            if len(V0s) > 0:
                eps.setDeflationSpace(V0s)
            eps.solve()
            if eps.getConverged() < self.nev:
                PETSc.Sys.Print(
                    'WARNING: Only {} eigenvalues converged for GenEO_eigmin in subdomain {} whereas {} were requested'
                    .format(eps.getConverged(), mpi.COMM_WORLD.rank, self.nev),
                    comm=self.comm)
            for i in range(min(eps.getConverged(), self.maxev)):
                if (abs(eps.getEigenvalue(i)) < tauGenEO_eigmin
                    ):  #TODO tell slepc that the eigenvalues are real
                    V0s.append(self.works.duplicate())
                    eps.getEigenvector(i, V0s[-1])
                    if self.verbose:
                        PETSc.Sys.Print(
                            'GenEO eigenvalue number {} for lambdamin in subdomain {}: {}'
                            .format(i, mpi.COMM_WORLD.rank,
                                    eps.getEigenvalue(i)),
                            comm=self.comm)
                else:
                    if self.verbose:
                        PETSc.Sys.Print(
                            'GenEO eigenvalue number {} for lambdamin in subdomain {}: {} <-- not selected (> {})'
                            .format(i, mpi.COMM_WORLD.rank,
                                    eps.getEigenvalue(i), tauGenEO_eigmin),
                            comm=self.comm)
            self.eps_eigmin = eps  #the only reason for this line is to make sure self.ksp_Atildes and hence PCBNN.ksp is not destroyed
예제 #4
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('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.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 linear solver and preconditioner
        self.ksp = PETSc.KSP().create()
        self.ksp.setFromOptions()
        self.ksp.setOperators(self.J)
        self.ksp.setType(cfg['solver']['petsc_ksp_type'])
        self.ksp.setInitialGuessNonzero(True)

        self.pc = self.ksp.getPC()
        self.pc.setType(cfg['solver']['petsc_pc_type'])

        # 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]

        self.petsc_matrix.formRHSPoisson(self.Pb, self.x)
        self.poisson_ksp.solve(self.Pb, self.P)

        x_arr = self.da4.getVecArray(self.x)
        P_arr = self.da1.getVecArray(self.P)

        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)
예제 #5
0
    def adjoint(self, tao, x, G):
        dx, dy, dz = self.dx, self.dy, self.dz
        nx, ny, nz = self.nx, self.ny, self.nz
        (minX, maxX), (minY, maxY), (minZ, maxZ) = self.mesh.dm.getLocalBoundingBox()

        k_list, H_list, a_list = np.array_split(x.array[:-1], 3)
        q0 = x.array[-1]

        # Unpack vectors onto mesh
        k0, H, a = self.map(k_list, H_list, a_list)
        self.mesh.update_properties(k0, H)
        self.mesh.boundary_condition('maxZ', 298.0, flux=False)
        self.mesh.boundary_condition('minZ', q0, flux=True)
        b = self.mesh.construct_rhs()

        k = [k0]
        T = [None]

        error_local  = np.array([True])
        error_global = np.ones(comm.size, dtype=bool)
        i = 0
        while error_global.any():
            self.mesh.update_properties(k[i], H)
            A = self.mesh.construct_matrix()
            self.ksp.solve(b._gdata, self.temperature)
            self.mesh.dm.globalToLocal(self.temperature, self.mesh.lvec)

            T.append(self.mesh.lvec.array.copy())
            k.append(k0*(298.0/T[-1])**a)

            error_local[0] = np.absolute(k[-1] - k[-2]).max() > 1e-6
            comm.Allgather([error_local, MPI.BOOL], [error_global, MPI.BOOL])
            i += 1


        dT_ad = np.zeros_like(k0)
        dk_ad = np.zeros_like(k0)
        dH_ad = np.zeros_like(k0)
        da_ad = np.zeros_like(k0)
        dq0_ad = np.array(0.0)
        dk_list_ad = np.zeros_like(k_list)
        dH_list_ad = np.zeros_like(H_list)
        da_list_ad = np.zeros_like(a_list)
        dq0_list_ad = np.array(0.0)

        cost = np.array(0.0)
        sum_cost = np.array(0.0)

        # Cost observations
        if self.observation.has_key('q'):
            obs = self.observation['q']

            # Compute heat flux
            gradTz, gradTy, gradTx = np.gradient(T[-1].reshape(self.mesh.n), *self.mesh.grid_coords[::-1])
            heatflux = -k[-1].reshape(self.mesh.n)*(gradTz + gradTy + gradTx)
            q_interp = heatflux.ravel()
            
            if obs[2] is not None:
                self.interp.values = heatflux
                q_interp = self.interp(obs[2], method='nearest')

            cost += self.objective_function(q_interp, obs[0], obs[1], obs[-1])

            ## AD ##
            dcdq = self.objective_function_ad(q_interp, obs[0], obs[1])
            dq_ad = dcdq*1.0
            if obs[2] is not None:
                dq_interp_ad = dcdq*1.0
                dq_ad = self.interp.adjoint(obs[2], dq_interp_ad, method='nearest').ravel()
                # print "ad\n", dq_interp_ad
                self.mesh.lvec.setArray(dq_ad)
                self.mesh.dm.localToGlobal(self.mesh.lvec, self.mesh.gvec)
                self.mesh.dm.globalToLocal(self.mesh.gvec, self.mesh.lvec)
                dq_ad = self.mesh.lvec.array.copy() #/self.ghost_weights
                # print "dq_interp_ad", dq_ad_interp
                # print obs[-1]
                # print "dq_ad\n", dq_ad.min(), dq_ad.mean(), dq_ad.max()
                # print "dq_ad\n", np.hstack([dq_ad[dq_ad>0].reshape(-1,1), self.mesh.coords[dq_ad>0]])
                # print "np.nan", np.where(dq_ad==np.nan)

            dqdTz = -k[-1]/(nz*dz)
            dqdTy = -k[-1]/(ny*dy)
            dqdTx = -k[-1]/(nx*dz)
            dqdk = -(gradTz + gradTy + gradTx).ravel()

            dk_ad += dqdk*dq_ad
            dT_ad += dqdTx*dq_ad + dqdTy*dq_ad + dqdTz*dq_ad
            # print dT_ad.min(), dT_ad.max()

        if self.observation.has_key('T'):
            obs = self.observation['T']
            T_interp = T[-1]
            if obs[2] is not None:
                self.interp.values = T[-1].reshape(self.mesh.n)
                T_interp = self.interp(obs[2], method='nearest')
            cost += self.objective_function(T_interp, obs[0], obs[1], obs[-1])

            ## AD ##
            dcdT = self.objective_function_ad(T_interp, obs[0], obs[1])
            dT_ad2 = dcdT*1.0
            if obs[2] is not None:
                dT_interp_ad = dcdT*1.0
                dT_ad2 = self.interp.adjoint(obs[2], dq_interp_ad, method='nearest').ravel()
            
            self.mesh.lvec.setArray(dT_ad2)
            self.mesh.dm.localToGlobal(self.mesh.lvec, self.mesh.gvec)
            self.mesh.dm.globalToLocal(self.mesh.gvec, self.mesh.lvec)
            dT_ad2 = self.mesh.lvec.array.copy()
            # print "dT_ad\n", dT_ad2.min(), dT_ad2.mean(), dT_ad2.max()

            dT_ad += dT_ad2


        comm.Allreduce([cost, MPI.DOUBLE], [sum_cost, MPI.DOUBLE], op=MPI.SUM)

        # Cost priors
        for key, array, array_ad in [('k', k_list, dk_list_ad),
                                     ('H', H_list, dH_list_ad),
                                     ('a', a_list, da_list_ad),
                                     ('q0', q0, dq0_list_ad)]:
            if self.prior.has_key(key):
                prior = self.prior[key]
                sum_cost += self.objective_function(array, prior[0], prior[1])

                ## AD ##
                dcdp = self.objective_function_ad(array, prior[0], prior[1])
                # array_ad += dcdp*1.0

        # print "dT", comm.rank, dT_ad
        # print "dK", comm.rank, dk_ad

        dk0_ad = np.zeros_like(k0)

        idx_local = np.array([True])
        idx_global = np.ones(comm.size, dtype=bool)

        idx_lowerBC = self.mesh.bc['minZ']['mask']
        idx_upperBC = self.mesh.bc['maxZ']['mask']


        kspT = PETSc.KSP().create(comm)
        kspT.setType('bcgs')
        kspT.setTolerances(1e-12, 1e-12)
        kspT.setFromOptions()
        # kspT.setDM(self.mesh.dm)
        # pc = kspT.getPC()
        # pc.setType('gamg')

        dAdklT = self.mesh.gvec.duplicate()


        for j in range(i):
            dkda = np.log(298.0/T[-1-j])*k0*(298.0/T[-1-j])**a
            dkdk0 = (298.0/T[-1-j])**a
            dkdT = -a*k0/T[-1-j]*(298.0/T[-1-j])**a

            dk0_ad += dkdk0*dk_ad
            dT_ad  += dkdT*dk_ad
            da_ad  += dkda*dk_ad

            dk_ad.fill(0.0)


            self.mesh.update_properties(k[-1-j], H)
            self.mesh.boundary_condition('maxZ', 298.0, flux=False)
            self.mesh.boundary_condition('minZ', q0, flux=True)
            A = self.mesh.construct_matrix()


            AT = self.mesh._initialise_matrix()
            A.transpose(AT)
            self.mesh.lvec.setArray(dT_ad)
            self.mesh.dm.localToGlobal(self.mesh.lvec, b._gdata)

            kspT.setOperators(AT)
            kspT.solve(b._gdata, self.mesh.gvec)
            self.mesh.dm.globalToLocal(self.mesh.gvec, self.mesh.lvec)
            db_ad = self.mesh.lvec.array

            dH_ad += -db_ad
            dH_ad[idx_lowerBC] += db_ad[idx_lowerBC]/dy
            dq0_ad += np.sum(-db_ad[idx_lowerBC]/dy/self.ghost_weights[idx_lowerBC])

            A.scale(-1.0)


            # self.mesh.boundary_condition('maxZ', 0.0, flux=False)
            # self.mesh.diffusivity.fill(1.0)
            # dAdkl = self.mesh.construct_matrix(in_place=False, derivative=True)

            # self.mesh.lvec.setArray(T[-1-j])
            # self.mesh.dm.localToGlobal(self.mesh.lvec, self._temperature)
            # dAdkl.mult(self._temperature, dAdklT)
            # self.ksp.solve(dAdklT, self.mesh.gvec)

            # dk_ad += dT_ad.dot(self.mesh.lvec.array)

            self.mesh.lvec.setArray(T[-1-j])
            self.mesh.dm.localToGlobal(self.mesh.lvec, self._temperature)


            kappa = np.zeros_like(H)

            for l, lith in enumerate(self.lithology_index):
                idx = self.lithology == lith
                idx_dT = dT_ad != 0.0
                idx_n  = np.logical_and(idx, idx_dT)
                idx_local[0] = idx_n.any()
                comm.Allgather([idx_local, MPI.BOOL], [idx_global, MPI.BOOL])
                if idx_global.any():
                    self.mesh.boundary_condition('maxZ', 0.0, flux=False)
                    kappa.fill(0.0)
                    kappa[idx] = 1.0
                    self.mesh.diffusivity[:] = kappa
                    dAdkl = self.mesh.construct_matrix(in_place=False, derivative=True)
                    # diag = dAdkl.getDiagonal()
                    # diag.array[idx_upperBC] = 0.0
                    # dAdkl.setDiagonal(diag)
                    dAdkl.mult(self._temperature, dAdklT)
                    self.ksp.setOperators(A)
                    self.ksp.solve(dAdklT, self.mesh.gvec)
                    self.mesh.dm.globalToLocal(self.mesh.gvec, self.mesh.lvec)
                    if idx_local[0]:
                        dk_ad[idx_n] += dT_ad.dot(self.mesh.lvec.array)/idx_n.sum()
                    # print self.mesh.lvec.array.mean(), dk_ad.mean(), dk0_ad.mean(), idx_n.any(), idx_n.sum()


            dT_ad.fill(0.0)

        dk0_ad += dk_ad

        kspT.destroy()

        dk0_ad /= self.ghost_weights
        dH_ad /= self.ghost_weights
        da_ad /= self.ghost_weights

        for i, index in enumerate(self.lithology_index):
            idx = self.lithology == index
            dk_list_ad[i] += dk0_ad[idx].sum()
            dH_list_ad[i] += dH_ad[idx].sum()
            da_list_ad[i] += da_ad[idx].sum()


        sum_dk_list_ad = np.zeros_like(dk_list_ad)
        sum_dH_list_ad = np.zeros_like(dk_list_ad)
        sum_da_list_ad = np.zeros_like(dk_list_ad)
        sum_dq0_ad = np.array(0.0)

        comm.Allreduce([dk_list_ad, MPI.DOUBLE], [sum_dk_list_ad, MPI.DOUBLE], op=MPI.SUM)
        comm.Allreduce([dH_list_ad, MPI.DOUBLE], [sum_dH_list_ad, MPI.DOUBLE], op=MPI.SUM)
        comm.Allreduce([da_list_ad, MPI.DOUBLE], [sum_da_list_ad, MPI.DOUBLE], op=MPI.SUM)
        comm.Allreduce([dq0_ad, MPI.DOUBLE], [sum_dq0_ad, MPI.DOUBLE], op=MPI.SUM)


        dq0_list_ad += sum_dq0_ad

        # Procs have unique lithololgy, need to communicate the gradients after vectors are all been packed up
        # I think these fellows ought to have their prior sensitivities added at the end since these are global.
        # for i, index in enumerate(self.lithology_index):
        #     idx = self.lithology == index
        #     dk_list_ad[i] += sum_dk0_ad[idx].sum()
        #     dH_list_ad[i] += sum_dH_ad[idx].sum()
        #     da_list_ad[i] += sum_da_ad[idx].sum()

        # procs should have their part of the sensitivities summed. Even if this doesn't result in any difference,
        # performance should be improved by communicating smaller arrays

        for key, array, array_ad in [('k', k_list, sum_dk_list_ad),
                                     ('H', H_list, sum_dH_list_ad),
                                     ('a', a_list, sum_da_list_ad),
                                     ('q0', q0, sum_dq0_ad)]:
            if key in self.prior:
                prior = self.prior[key]
                array_ad += self.objective_function_ad(array, prior[0], prior[1])


        G.setArray(np.concatenate([sum_dk_list_ad, sum_dH_list_ad, sum_da_list_ad, [sum_dq0_ad]]))

        print("cost = {}".format(sum_cost))
        
        return sum_cost
예제 #6
0
              metric=Metric)
PDE.assembly()
PDE.solve()

# getting scipy matrix
A_scipy = PDE.system.get()
PDE.system.save("sys.mtx")

b = np.ones(PDE.size)

A = PETSc.Mat().createAIJ(size=A_scipy.shape,
                          csr=(A_scipy.indptr, A_scipy.indices, A_scipy.data))
# ...

# Initialize ksp solver.
ksp = PETSc.KSP().create()
ksp.setOperators(A)
pc = ksp.getPC()

# Allow for solver choice to be set from command line with -ksp_type <solver>.
# Recommended option: -ksp_type preonly -pc_type lu
ksp.setFromOptions()

ksptype = PETSc.KSP.Type.CG
pctype = None
#ksptype = PETSc.KSP.Type.GMRES          ; pctype = None
#ksptype = PETSc.KSP.Type.BICG           ; pctype = None
#ksptype = PETSc.KSP.Type.BCGS           ; pctype = None
#ksptype = PETSc.KSP.Type.BCGSL          ; pctype = None
#ksptype = PETSc.KSP.Type.CGS            ; pctype = None
#ksptype = PETSc.KSP.Type.STCG           ; pctype = None
예제 #7
0
def solve(A, b, u, IS, Fspace, IterType, OuterTol, InnerTol, HiptmairMatrices,
          KSPlinearfluids, kspF, Fp, MatrixLinearFluids, kspFp):

    if IterType == "Full":
        ksp = PETSc.KSP().create()
        ksp.setTolerances(OuterTol)
        ksp.setType('fgmres')

        u_is = PETSc.IS().createGeneral(range(Fspace[0].dim()))
        p_is = PETSc.IS().createGeneral(
            range(Fspace[0].dim(), Fspace[0].dim() + Fspace[1].dim()))
        b_is = PETSc.IS().createGeneral(
            range(Fspace[0].dim() + Fspace[1].dim(),
                  Fspace[0].dim() + Fspace[1].dim() + Fspace[2].dim()))

        Bt = A.getSubMatrix(u_is, p_is)
        C = A.getSubMatrix(u_is, b_is)
        reshist = {}

        def monitor(ksp, its, fgnorm):
            reshist[its] = fgnorm
            # print "------------------------->>>> ", ksp.buildResidual().array
            print "OUTER:", fgnorm
            return ksp.buildResidual().array

        ksp.setMonitor(monitor)
        pc = ksp.getPC()
        pc.setType(PETSc.PC.Type.KSP)

        ksp.setOperators(A)

        reshist1 = {}

        def monitor(ksp, its, fgnorm):
            reshist1[its] = fgnorm
            print "INNER:", fgnorm

        # ksp.setMonitor(monitor)

        pc = ksp.getPC()
        pc.setType(PETSc.PC.Type.PYTHON)
        pc.setPythonContext(
            MHDstabPrecond.Test(Fspace, kspF, KSPlinearfluids[0],
                                KSPlinearfluids[1], Fp, HiptmairMatrices[3],
                                HiptmairMatrices[4], HiptmairMatrices[2],
                                HiptmairMatrices[0], HiptmairMatrices[1],
                                HiptmairMatrices[6], 1e-3, Bt, C))

        # PP = PETSc.Mat().createPython([A.size[0], A.size[0]])
        # PP.setType('python')
        # p = PrecondMulti.MultiApply(Fspace,A,HiptmairMatrices[6],MatrixLinearFluids[1],MatrixLinearFluids[0],kspFp, HiptmairMatrices[3])

        tic()
        scale = b.norm()
        b = b / scale
        print b.norm()
        ksp.solve(b, u)
        u = u * scale
        print toc()

        # print s.getvalue()
        NSits = ksp.its
        del ksp

        # print u.array
        return u, NSits, 1

    NS_is = IS[0]
    M_is = IS[1]
    kspNS = PETSc.KSP().create()
    kspM = PETSc.KSP().create()
    kspNS.setTolerances(OuterTol)

    kspNS.setOperators(A.getSubMatrix(NS_is, NS_is))
    kspM.setOperators(A.getSubMatrix(M_is, M_is))
    del A

    uNS = u.getSubVector(NS_is)
    bNS = b.getSubVector(NS_is)
    kspNS.setType('gmres')
    pcNS = kspNS.getPC()
    kspNS.setTolerances(OuterTol)
    pcNS.setType(PETSc.PC.Type.PYTHON)
    if IterType == "MD":
        pcNS.setPythonContext(
            NSpreconditioner.NSPCD(MixedFunctionSpace([Fspace[0],
                                                       Fspace[1]]), kspF,
                                   KSPlinearfluids[0], KSPlinearfluids[1], Fp))
    else:
        pcNS.setPythonContext(
            StokesPrecond.MHDApprox(MixedFunctionSpace([Fspace[0], Fspace[1]]),
                                    kspF, KSPlinearfluids[1]))

    scale = bNS.norm()
    bNS = bNS / scale
    start_time = time.time()
    kspNS.solve(bNS, uNS)
    print("{:25}").format("NS, time: "), " ==>  ", (
        "{:4f}").format(time.time() - start_time), (
            "{:9}").format("   Its: "), ("{:4}").format(
                kspNS.its), ("{:9}").format("   time: "), ("{:4}").format(
                    time.strftime('%X %x %Z')[0:5])
    uNS = scale * uNS

    NSits = kspNS.its
    # kspNS.destroy()
    # for line in reshist.values():
    #     print line

    kspM.setFromOptions()
    kspM.setType(kspM.Type.MINRES)
    kspM.setTolerances(InnerTol)
    pcM = kspM.getPC()
    pcM.setType(PETSc.PC.Type.PYTHON)
    pcM.setPythonContext(
        MP.Hiptmair(MixedFunctionSpace([Fspace[2], Fspace[3]]),
                    HiptmairMatrices[3], HiptmairMatrices[4],
                    HiptmairMatrices[2], HiptmairMatrices[0],
                    HiptmairMatrices[1], HiptmairMatrices[6], 1e-6))

    # x = x*scale
    uM = u.getSubVector(M_is)
    bM = b.getSubVector(M_is)

    scale = bM.norm()
    bM = bM / scale
    start_time = time.time()
    kspM.solve(bM, uM)
    print("{:25}").format("Maxwell solve, time: "), " ==>  ", (
        "{:4f}").format(time.time() - start_time), (
            "{:9}").format("   Its: "), ("{:4}").format(
                kspM.its), ("{:9}").format("   time: "), ("{:4}").format(
                    time.strftime('%X %x %Z')[0:5])
    uM = uM * scale

    Mits = kspM.its
    kspM.destroy()
    u = IO.arrayToVec(np.concatenate([uNS.array, uM.array]))

    return u, NSits, Mits
예제 #8
0
def xtest_assembly_solve_block():
    """Solve a two-field mass-matrix like problem with block matrix approaches
    and test that solution is the same.
    """

    mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 32, 31)
    p0, p1 = 1, 1
    P0 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p0)
    P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p1)
    V0 = dolfin.function.functionspace.FunctionSpace(mesh, P0)
    V1 = dolfin.function.functionspace.FunctionSpace(mesh, P1)

    def boundary(x):
        return numpy.logical_or(x[:, 0] < 1.0e-6, x[:, 0] > 1.0 - 1.0e-6)

    u_bc0 = dolfin.function.constant.Constant(50.0)
    u_bc1 = dolfin.function.constant.Constant(20.0)
    bc0 = dolfin.fem.dirichletbc.DirichletBC(V0, u_bc0, boundary)
    bc1 = dolfin.fem.dirichletbc.DirichletBC(V1, u_bc1, boundary)

    # Variational problem
    u, p = dolfin.function.argument.TrialFunction(
        V0), dolfin.function.argument.TrialFunction(V1)
    v, q = dolfin.function.argument.TestFunction(
        V0), dolfin.function.argument.TestFunction(V1)
    f = dolfin.function.constant.Constant(1.0)
    g = dolfin.function.constant.Constant(-3.0)
    zero = dolfin.function.constant.Constant(0.0)

    a00 = inner(u, v) * dx
    a01 = zero * inner(p, v) * dx
    a10 = zero * inner(u, q) * dx
    a11 = inner(p, q) * dx
    L0 = inner(f, v) * dx
    L1 = inner(g, q) * dx

    def monitor(ksp, its, rnorm):
        pass
        # print("Norm:", its, rnorm)

    # Create assembler
    assembler = dolfin.fem.assembling.Assembler([[a00, a01], [a10, a11]],
                                                [L0, L1], [bc0, bc1])

    # Monolithic blocked
    A0, b0 = assembler.assemble(
        mat_type=dolfin.cpp.fem.Assembler.BlockType.monolithic)
    A0norm = A0.mat().norm()
    b0norm = b0.vec().norm()
    x0 = A0.mat().createVecLeft()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setOperators(A0.mat())
    ksp.setTolerances(rtol=1.0e-12)
    ksp.setMonitor(monitor)
    ksp.setType('cg')
    ksp.setFromOptions()
    # ksp.view()
    ksp.solve(b0.vec(), x0)
    x0norm = x0.norm()

    # Nested (MatNest)
    A1, b1 = assembler.assemble(
        mat_type=dolfin.cpp.fem.Assembler.BlockType.nested)
    b1norm = b1.vec().norm()
    assert b1norm == pytest.approx(b0norm, 1.0e-12)

    x1 = dolfin.la.PETScVector(b1)
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setMonitor(monitor)
    ksp.setTolerances(rtol=1.0e-12)
    ksp.setOperators(A1.mat())
    ksp.setType('cg')
    ksp.setFromOptions()
    # ksp.view()
    ksp.solve(b1.vec(), x1.vec())
    x1norm = x1.vec().norm()
    assert x1norm == pytest.approx(x0norm, rel=1.0e-10)

    # Monolithic version
    E = P0 * P1
    W = dolfin.function.functionspace.FunctionSpace(mesh, E)
    u0, u1 = dolfin.function.argument.TrialFunctions(W)
    v0, v1 = dolfin.function.argument.TestFunctions(W)
    a = inner(u0, v0) * dx + inner(u1, v1) * dx
    L = inner(f, v0) * ufl.dx + inner(g, v1) * dx

    u_bc = dolfin.function.constant.Constant((50.0, 20.0))
    bc = dolfin.fem.dirichletbc.DirichletBC(W, u_bc, boundary)
    assembler = dolfin.fem.assembling.Assembler([[a]], [L], [bc])

    A2, b2 = assembler.assemble(
        mat_type=dolfin.cpp.fem.Assembler.BlockType.monolithic)
    A2norm = A2.mat().norm()
    b2norm = b2.vec().norm()
    assert A2norm == pytest.approx(A0norm, 1.0e-12)
    assert b2norm == pytest.approx(b0norm, 1.0e-12)

    x2 = dolfin.cpp.la.PETScVector(b2)
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setMonitor(monitor)
    ksp.setOperators(A2.mat())
    ksp.setType('cg')
    ksp.setTolerances(rtol=1.0e-9)
    ksp.setFromOptions()
    # ksp.view()
    ksp.solve(b2.vec(), x2.vec())
    x2norm = x2.vec().norm()
    assert x2norm == pytest.approx(x0norm, 1.0e-10)

    # Old assembler (reference)
    A3, b3 = dolfin.fem.assembling.assemble_system(a, L, [bc])
    x3 = dolfin.cpp.la.PETScVector(b3)
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setMonitor(monitor)
    ksp.setOperators(A3.mat())
    ksp.setType('cg')
    ksp.setTolerances(rtol=1.0e-9)
    ksp.setFromOptions()
    # ksp.view()
    ksp.solve(b3.vec(), x3.vec())
    x3norm = x3.vec().norm()
    assert x3norm == pytest.approx(x0norm, 1.0e-10)
예제 #9
0
    def __init__(self, da, grid, bdy_type, sparam, verbose=0, solver='gmres', pc=None):
        ''' Setup the PV inversion solver

        Parameters
        ----------
        da : petsc DMDA
            holds the petsc grid
        grid : qgsolver grid object
            grid data holder
        bdy_type : dict
            prescribe vertical and lateral boundary conditions. Examples
                bdy_type = {'bottom': 'D', 'top': 'D'}    for Dirichlet bdy conditions
                bdy_type = {'bottom': 'N_RHO', 'top': 'N_RHO'}    for Neumann bdy conditions with RHO
                bdy_type = {'bottom': 'N_PSI', 'top': 'N_PSI'}    for Neumann bdy conditions using PSI instead of RHO
                bdy_type = {'periodic': None}             for horizontal periodicity
        sparam : ndarray
            numpy array containing f^2/N^2
        verbose : int, optional
            degree of verbosity, 0 means no outputs
        solver : str, optional
            petsc solver: 'gmres' (default), 'bicg', 'cg'
        pc : str, optional
            what is default?
            preconditionner: 'icc', 'bjacobi', 'asm', 'mg', 'none'

        '''

        self._verbose = verbose
        #
        self.bdy_type = bdy_type
        if ('periodic' in self.bdy_type) and (self.bdy_type['periodic']):
            self.petscBoundaryType = 'periodic'
        else:
            self.petscBoundaryType = None

        # create the operator
        self.L = da.createMat()
        #
        if self._verbose>0:
            print('A PV inversion object is being created')
            print('  Operator L declared')

        # Fill in operator values
        if grid._flag_hgrid_uniform and grid._flag_vgrid_uniform:
            self._set_L(self.L, da, grid, sparam)
        else:
            self._set_L_curv(self.L, da, grid, sparam)

        #
        if self._verbose>0:
            print('  Operator L filled')

        # global vector for PV inversion
        self._RHS = da.createGlobalVec()

        # create solver
        self.ksp = PETSc.KSP()
        self.ksp.create(PETSc.COMM_WORLD)
        self.ksp.setOperators(self.L)
        self.ksp.setType(solver)
        self.ksp.setInitialGuessNonzero(True)
        if pc is not None:
            self.ksp.getPC().setType(pc)
        # set tolerances
        self.ksp.setTolerances(rtol=1e-4)
        self.ksp.setTolerances(max_it=100)
        # tests:
        #self.ksp.setPCSide(PETSc.PC.Side.R)
        #self.ksp.setInitialGuessNonzero(False)
        #self.ksp.setTolerances(atol=1e-1)
        #self.ksp.setTolerances(max_it=100)
        #
        for opt in sys.argv[1:]:
            PETSc.Options().setValue(opt, None)
        self.ksp.setFromOptions()
        
        if self._verbose>0:
            print('  PV inversion is set up')
예제 #10
0
    def setUp(self, pc):
        A, P = pc.getOperators()
        print A.size
        self.Ct = A.getSubMatrix(self.u_is, self.b_is)
        self.C = A.getSubMatrix(self.b_is, self.u_is)
        self.D = A.getSubMatrix(self.r_is, self.b_is)
        self.Bt = A.getSubMatrix(self.u_is, self.p_is)
        self.B = A.getSubMatrix(self.p_is, self.u_is)
        self.Dt = A.getSubMatrix(self.b_is, self.r_is)
        # print self.Ct.view()

        #CFC = sp.csr_matrix( (data,(row,column)), shape=(self.W[1].dim(),self.W[1].dim()) )
        #print CFC.shape
        #CFC = PETSc.Mat().createAIJ(size=CFC.shape,csr=(CFC.indptr, CFC.indices, CFC.data))
        #print CFC.size, self.AA.size
        #MX = self.AA+self.F
        MX = self.F  # MO.StoreMatrix(B,"A")
        # print FC.todense()
        self.kspF.setType('preonly')
        self.kspF.getPC().setType('lu')
        self.kspF.setFromOptions()
        self.kspF.setPCSide(0)

        self.kspA.setType('preonly')
        self.kspA.getPC().setType('lu')
        self.kspA.setFromOptions()
        self.kspA.setPCSide(0)

        self.kspQ.setType('preonly')
        self.kspQ.getPC().setType('lu')
        self.kspQ.setFromOptions()
        self.kspQ.setPCSide(0)

        self.kspScalar.setType('preonly')
        self.kspScalar.getPC().setType('lu')
        self.kspScalar.setFromOptions()
        self.kspScalar.setPCSide(0)

        kspMX = PETSc.KSP()
        kspMX.create(comm=PETSc.COMM_WORLD)
        pcMX = kspMX.getPC()
        kspMX.setType('preonly')
        pcMX.setType('lu')
        kspMX.setOperators(MX, MX)
        OptDB = PETSc.Options()
        #OptDB["pc_factor_mat_ordering_type"] = "rcm"
        #OptDB["pc_factor_mat_solver_package"] = "mumps"
        kspMX.setFromOptions()
        self.kspMX = kspMX

        # self.kspCGScalar.setType('preonly')
        # self.kspCGScalar.getPC().setType('lu')
        # self.kspCGScalar.setFromOptions()
        # self.kspCGScalar.setPCSide(0)

        self.kspVector.setType('preonly')
        self.kspVector.getPC().setType('lu')
        self.kspVector.setFromOptions()
        self.kspVector.setPCSide(0)

        print "setup"
예제 #11
0
def test_lifting(get_assemblers):  # noqa: F811
    """
    Test MPC lifting operation on a single cell
    """
    assemble_matrix, assemble_vector = get_assemblers

    # Create mesh and function space
    mesh = create_unit_square(MPI.COMM_WORLD, 1, 1, CellType.quadrilateral)
    V = fem.FunctionSpace(mesh, ("Lagrange", 1))

    # Solve Problem without MPC for reference
    u = ufl.TrialFunction(V)
    v = ufl.TestFunction(V)
    x = ufl.SpatialCoordinate(mesh)
    f = x[1] * ufl.sin(2 * ufl.pi * x[0])
    a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
    rhs = ufl.inner(f, v) * ufl.dx

    bilinear_form = fem.form(a)
    linear_form = fem.form(rhs)

    # Create Dirichlet boundary condition
    u_bc = fem.Function(V)
    with u_bc.vector.localForm() as u_local:
        u_local.set(2.3)

    def dirichletboundary(x):
        return np.isclose(x[0], 1)

    mesh.topology.create_connectivity(2, 1)
    geometrical_dofs = fem.locate_dofs_geometrical(V, dirichletboundary)
    bc = fem.dirichletbc(u_bc, geometrical_dofs)
    bcs = [bc]

    # Generate reference matrices
    A_org = fem.petsc.assemble_matrix(bilinear_form, bcs=bcs)
    A_org.assemble()
    L_org = fem.petsc.assemble_vector(linear_form)
    fem.petsc.apply_lifting(L_org, [bilinear_form], [bcs])
    L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
                      mode=PETSc.ScatterMode.REVERSE)
    fem.petsc.set_bc(L_org, bcs)

    # Create multipoint constraint

    def l2b(li):
        return np.array(li, dtype=np.float64).tobytes()

    s_m_c = {l2b([0, 0]): {l2b([0, 1]): 1}}

    mpc = dolfinx_mpc.MultiPointConstraint(V)
    mpc.create_general_constraint(s_m_c)
    mpc.finalize()

    A = assemble_matrix(bilinear_form, mpc, bcs=bcs)
    b = assemble_vector(linear_form, mpc)
    dolfinx_mpc.apply_lifting(b, [bilinear_form], [bcs], mpc)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
                  mode=PETSc.ScatterMode.REVERSE)

    fem.petsc.set_bc(b, bcs)

    solver = PETSc.KSP().create(MPI.COMM_WORLD)
    solver.setType(PETSc.KSP.Type.PREONLY)
    solver.getPC().setType(PETSc.PC.Type.LU)
    solver.setOperators(A)
    # Solve
    uh = b.copy()
    uh.set(0)
    solver.solve(b, uh)
    uh.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                   mode=PETSc.ScatterMode.FORWARD)
    mpc.backsubstitution(uh)

    V_mpc = mpc.function_space
    u_out = fem.Function(V_mpc)
    u_out.vector.array[:] = uh.array

    root = 0
    comm = mesh.comm
    with Timer("~TEST: Compare"):

        dolfinx_mpc.utils.compare_mpc_lhs(A_org, A, mpc, root=root)
        dolfinx_mpc.utils.compare_mpc_rhs(L_org, b, mpc, root=root)

        # Gather LHS, RHS and solution on one process
        A_csr = dolfinx_mpc.utils.gather_PETScMatrix(A_org, root=root)
        K = dolfinx_mpc.utils.gather_transformation_matrix(mpc, root=root)
        L_np = dolfinx_mpc.utils.gather_PETScVector(L_org, root=root)
        u_mpc = dolfinx_mpc.utils.gather_PETScVector(uh, root=root)
        # constants = dolfinx_mpc.utils.gather_contants(mpc, root=root)
        if MPI.COMM_WORLD.rank == root:
            KTAK = K.T * A_csr * K
            reduced_L = K.T @ (L_np)  # - constants)
            # Solve linear system
            d = scipy.sparse.linalg.spsolve(KTAK, reduced_L)
            # Back substitution to full solution vecto
            uh_numpy = K @ (d)  # + constants)
            assert np.allclose(uh_numpy, u_mpc)

    list_timings(comm, [TimingType.wall])
예제 #12
0
def demo_stacked_cubes(outfile: XDMFFile, theta: float, gmsh: bool = False, ct: CellType = CellType.tetrahedron,
                       compare: bool = True, res: float = 0.1, noslip: bool = False):
    celltype = "hexahedron" if ct == CellType.hexahedron else "tetrahedron"
    type_ext = "no_slip" if noslip else "slip"
    mesh_ext = "_gmsh_" if gmsh else "_"
    log_info(f"Run theta:{theta:.2f}, Cell: {celltype}, GMSH {gmsh}, Noslip: {noslip}")

    # Read in mesh
    if gmsh:
        mesh, mt = gmsh_3D_stacked(celltype, theta, res)
        tdim = mesh.topology.dim
        fdim = tdim - 1
        mesh.topology.create_connectivity(tdim, tdim)
        mesh.topology.create_connectivity(fdim, tdim)
    else:
        mesh_3D_dolfin(theta, ct, celltype, res)
        MPI.COMM_WORLD.barrier()
        with XDMFFile(MPI.COMM_WORLD, f"meshes/mesh_{celltype}_{theta:.2f}.xdmf", "r") as xdmf:
            mesh = xdmf.read_mesh(name="mesh")
            tdim = mesh.topology.dim
            fdim = tdim - 1
            mesh.topology.create_connectivity(tdim, tdim)
            mesh.topology.create_connectivity(fdim, tdim)
            mt = xdmf.read_meshtags(mesh, "facet_tags")
    mesh.name = f"mesh_{celltype}_{theta:.2f}{type_ext}{mesh_ext}"

    # Create functionspaces
    V = fem.VectorFunctionSpace(mesh, ("Lagrange", 1))

    # Define boundary conditions

    # Bottom boundary is fixed in all directions
    bottom_dofs = fem.locate_dofs_topological(V, fdim, mt.find(5))  # type: ignore
    u_bc = np.array((0, ) * mesh.geometry.dim, dtype=PETSc.ScalarType)
    bc_bottom = fem.dirichletbc(u_bc, bottom_dofs, V)

    g_vec = np.array([0, 0, -4.25e-1], dtype=PETSc.ScalarType)
    if not noslip:
        # Helper for orienting traction
        r_matrix = rotation_matrix([1 / np.sqrt(2), 1 / np.sqrt(2), 0], -theta)

        # Top boundary has a given deformation normal to the interface
        g_vec = np.dot(r_matrix, g_vec)

    top_dofs = fem.locate_dofs_topological(V, fdim, mt.find(3))  # type: ignore
    bc_top = fem.dirichletbc(g_vec, top_dofs, V)

    bcs = [bc_bottom, bc_top]

    # Elasticity parameters
    E = PETSc.ScalarType(1.0e3)
    nu = 0
    mu = fem.Constant(mesh, E / (2.0 * (1.0 + nu)))
    lmbda = fem.Constant(mesh, E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)))

    # Stress computation
    def sigma(v):
        return (2.0 * mu * sym(grad(v)) + lmbda * tr(sym(grad(v))) * Identity(len(v)))

    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    a = inner(sigma(u), grad(v)) * dx
    # NOTE: Traction deactivated until we have a way of fixing nullspace
    # g = fem.Constant(mesh, PETSc.ScalarType(g_vec))
    # ds = Measure("ds", domain=mesh, subdomain_data=mt, subdomain_id=3)
    rhs = inner(fem.Constant(mesh, PETSc.ScalarType((0, 0, 0))), v) * dx
    # + inner(g, v) * ds
    bilinear_form = fem.form(a)
    linear_form = fem.form(rhs)

    mpc = MultiPointConstraint(V)
    if noslip:
        with Timer("~~Contact: Create non-elastic constraint"):
            mpc.create_contact_inelastic_condition(mt, 4, 9)
    else:
        with Timer("~Contact: Create contact constraint"):
            nh = create_normal_approximation(V, mt, 4)
            mpc.create_contact_slip_condition(mt, 4, 9, nh)

    with Timer("~~Contact: Add data and finialize MPC"):
        mpc.finalize()

    # Create null-space
    null_space = rigid_motions_nullspace(mpc.function_space)
    num_dofs = V.dofmap.index_map.size_global * V.dofmap.index_map_bs
    with Timer(f"~~Contact: Assemble matrix ({num_dofs})"):
        A = assemble_matrix(bilinear_form, mpc, bcs=bcs)
    with Timer(f"~~Contact: Assemble vector ({num_dofs})"):
        b = assemble_vector(linear_form, mpc)

    apply_lifting(b, [bilinear_form], [bcs], mpc)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE)
    fem.petsc.set_bc(b, bcs)

    # Solve Linear problem
    opts = PETSc.Options()
    opts["ksp_rtol"] = 1.0e-8
    opts["pc_type"] = "gamg"
    opts["pc_gamg_type"] = "agg"
    opts["pc_gamg_coarse_eq_limit"] = 1000
    opts["pc_gamg_sym_graph"] = True
    opts["mg_levels_ksp_type"] = "chebyshev"
    opts["mg_levels_pc_type"] = "jacobi"
    opts["mg_levels_esteig_ksp_type"] = "cg"
    opts["matptap_via"] = "scalable"
    # opts["pc_gamg_square_graph"] = 2
    # opts["pc_gamg_threshold"] = 1e-2
    # opts["help"] = None # List all available options
    # opts["ksp_view"] = None # List progress of solver

    # Create functionspace and build near nullspace
    A.setNearNullSpace(null_space)
    solver = PETSc.KSP().create(mesh.comm)
    solver.setOperators(A)
    solver.setFromOptions()

    u_h = fem.Function(mpc.function_space)
    with Timer("~~Contact: Solve"):
        solver.solve(b, u_h.vector)
        u_h.x.scatter_forward()
    with Timer("~~Contact: Backsubstitution"):
        mpc.backsubstitution(u_h.vector)

    it = solver.getIterationNumber()
    unorm = u_h.vector.norm()
    num_slaves = MPI.COMM_WORLD.allreduce(mpc.num_local_slaves, op=MPI.SUM)
    if mesh.comm.rank == 0:
        num_dofs = V.dofmap.index_map.size_global * V.dofmap.index_map_bs
        print(f"Number of dofs: {num_dofs}")
        print(f"Number of slaves: {num_slaves}")
        print(f"Number of iterations: {it}")
        print(f"Norm of u {unorm:.5e}")

    # Write solution to file
    u_h.name = f"u_{celltype}_{theta:.2f}{mesh_ext}{type_ext}".format(celltype, theta, type_ext, mesh_ext)
    outfile.write_mesh(mesh)
    outfile.write_function(u_h, 0.0, f"Xdmf/Domain/Grid[@Name='{mesh.name}'][1]")
    # Solve the MPC problem using a global transformation matrix
    # and numpy solvers to get reference values
    if not compare:
        return

    log_info("Solving reference problem with global matrix (using scipy)")
    with Timer("~~Contact: Reference problem"):
        A_org = fem.petsc.assemble_matrix(bilinear_form, bcs)
        A_org.assemble()
        L_org = fem.petsc.assemble_vector(linear_form)
        fem.petsc.apply_lifting(L_org, [bilinear_form], [bcs])
        L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE)
        fem.petsc.set_bc(L_org, bcs)

    root = 0
    with Timer("~~Contact: Compare LHS, RHS and solution"):
        compare_mpc_lhs(A_org, A, mpc, root=root)
        compare_mpc_rhs(L_org, b, mpc, root=root)

        # Gather LHS, RHS and solution on one process
        A_csr = gather_PETScMatrix(A_org, root=root)
        K = gather_transformation_matrix(mpc, root=root)
        L_np = gather_PETScVector(L_org, root=root)
        u_mpc = gather_PETScVector(u_h.vector, root=root)

        if MPI.COMM_WORLD.rank == root:
            KTAK = K.T * A_csr * K
            reduced_L = K.T @ L_np
            # Solve linear system
            d = scipy.sparse.linalg.spsolve(KTAK, reduced_L)
            # Back substitution to full solution vector
            uh_numpy = K @ d
            assert np.allclose(uh_numpy, u_mpc)

    list_timings(mesh.comm, [TimingType.wall])
예제 #13
0
    cnt = 0
    for kt in range(2, 3):  #ktv=2
        # Build A and B for eigen-analysis

        A, B = build_AB(kt, r, z, Lap, Pr_b, Qr_b, parms)

        #returns first eigenvector, used as a guess for timestepping
        sn = solve_eigensystem(A, B, nEV, cnt, Nz, N2, guess)

        # Time Stepping
        A = -1j * A
        dt = 1e4
        dto2 = dt / 2
        tol = 1e-7

        ksp = PETSc.KSP().create(PETSc.COMM_WORLD)
        ksp.setOperators(B - dto2 * A)  #Abot
        ksp.setTolerances(1e-9)
        pc = ksp.getPC()
        pc.setType('none')
        # ksp.setFromOptions()

        Atop = B + dto2 * A
        Atop.assemble()

        sntemp = PETSc.Vec().createMPI(sn.getSize())
        sntemp.setUp()

        count = 1
        error = 1
        max_it = 8e5
def test_cell_domains(get_assemblers):  # noqa: F811
    """
    Periodic MPC conditions over integral with different cell subdomains
    """
    assemble_matrix, assemble_vector = get_assemblers
    N = 5
    # Create mesh and function space
    mesh = create_unit_square(MPI.COMM_WORLD, 15, N)
    V = fem.FunctionSpace(mesh, ("Lagrange", 1))

    def left_side(x):
        return x[0] < 0.5

    tdim = mesh.topology.dim
    num_cells = mesh.topology.index_map(tdim).size_local
    cell_midpoints = compute_midpoints(mesh, tdim, range(num_cells))
    values = np.ones(num_cells, dtype=np.intc)
    # All cells on right side marked one, all other with 1
    values += left_side(cell_midpoints.T)
    ct = meshtags(mesh, mesh.topology.dim, np.arange(num_cells,
                                                     dtype=np.int32), values)

    # Solve Problem without MPC for reference
    u = ufl.TrialFunction(V)
    v = ufl.TestFunction(V)
    x = ufl.SpatialCoordinate(mesh)
    c1 = fem.Constant(mesh, PETSc.ScalarType(2))
    c2 = fem.Constant(mesh, PETSc.ScalarType(10))

    dx = ufl.Measure("dx", domain=mesh, subdomain_data=ct)
    a = c1 * ufl.inner(ufl.grad(u), ufl.grad(v)) * dx(1) +\
        c2 * ufl.inner(ufl.grad(u), ufl.grad(v)) * dx(2)\
        + 0.01 * ufl.inner(u, v) * dx(1)

    rhs = ufl.inner(x[1], v) * dx(1) + \
        ufl.inner(fem.Constant(mesh, PETSc.ScalarType(1)), v) * dx(2)
    bilinear_form = fem.form(a)
    linear_form = fem.form(rhs)

    # Generate reference matrices
    A_org = fem.petsc.assemble_matrix(bilinear_form)
    A_org.assemble()
    L_org = fem.petsc.assemble_vector(linear_form)
    L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
                      mode=PETSc.ScatterMode.REVERSE)

    def l2b(li):
        return np.array(li, dtype=np.float64).tobytes()

    s_m_c = {}
    for i in range(0, N + 1):
        s_m_c[l2b([1, i / N])] = {l2b([0, i / N]): 1}
    mpc = dolfinx_mpc.MultiPointConstraint(V)
    mpc.create_general_constraint(s_m_c)
    mpc.finalize()

    # Setup MPC system
    with Timer("~TEST: Assemble matrix old"):
        A = assemble_matrix(bilinear_form, mpc)
    with Timer("~TEST: Assemble vector"):
        b = assemble_vector(linear_form, mpc)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
                  mode=PETSc.ScatterMode.REVERSE)

    solver = PETSc.KSP().create(MPI.COMM_WORLD)
    solver.setType(PETSc.KSP.Type.PREONLY)
    solver.getPC().setType(PETSc.PC.Type.LU)
    solver.setOperators(A)

    # Solve
    uh = b.copy()
    uh.set(0)
    solver.solve(b, uh)
    uh.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                   mode=PETSc.ScatterMode.FORWARD)

    mpc.backsubstitution(uh)

    root = 0
    comm = mesh.comm
    with Timer("~TEST: Compare"):
        dolfinx_mpc.utils.compare_mpc_lhs(A_org, A, mpc, root=root)
        dolfinx_mpc.utils.compare_mpc_rhs(L_org, b, mpc, root=root)

        # Gather LHS, RHS and solution on one process
        A_csr = dolfinx_mpc.utils.gather_PETScMatrix(A_org, root=root)
        K = dolfinx_mpc.utils.gather_transformation_matrix(mpc, root=root)
        L_np = dolfinx_mpc.utils.gather_PETScVector(L_org, root=root)
        u_mpc = dolfinx_mpc.utils.gather_PETScVector(uh, root=root)

        if MPI.COMM_WORLD.rank == root:
            KTAK = K.T * A_csr * K
            reduced_L = K.T @ L_np
            # Solve linear system
            d = scipy.sparse.linalg.spsolve(KTAK, reduced_L)
            # Back substitution to full solution vector
            uh_numpy = K @ d
            assert np.allclose(uh_numpy, u_mpc)
    list_timings(comm, [TimingType.wall])
예제 #15
0
def run_dg_test(mesh, V, degree):
    """ Manufactured Poisson problem, solving u = x[component]**n, where n is the
    degree of the Lagrange function space.
    """
    u, v = TrialFunction(V), TestFunction(V)

    # Exact solution
    x = SpatialCoordinate(mesh)
    u_exact = x[1]**degree

    # Coefficient
    k = Function(V)
    k.vector.set(2.0)
    k.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                         mode=PETSc.ScatterMode.FORWARD)

    # Source term
    f = -div(k * grad(u_exact))

    # Mesh normals and element size
    n = FacetNormal(mesh)
    h = CellDiameter(mesh)
    h_avg = (h("+") + h("-")) / 2.0

    # Penalty parameter
    alpha = 32

    dx_ = dx(metadata={"quadrature_degree": -1})
    ds_ = ds(metadata={"quadrature_degree": -1})
    dS_ = dS(metadata={"quadrature_degree": -1})

    with common.Timer("Compile forms"):
        a = inner(k * grad(u), grad(v)) * dx_ \
            - k("+") * inner(avg(grad(u)), jump(v, n)) * dS_ \
            - k("+") * inner(jump(u, n), avg(grad(v))) * dS_ \
            + k("+") * (alpha / h_avg) * inner(jump(u, n), jump(v, n)) * dS_ \
            - inner(k * grad(u), v * n) * ds_ \
            - inner(u * n, k * grad(v)) * ds_ \
            + (alpha / h) * inner(k * u, v) * ds_
        L = inner(f, v) * dx_ - inner(k * u_exact * n, grad(v)) * ds_ \
            + (alpha / h) * inner(k * u_exact, v) * ds_

    for integral in a.integrals():
        integral.metadata(
        )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(
            a)
    for integral in L.integrals():
        integral.metadata(
        )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(
            L)

    with common.Timer("Assemble vector"):
        b = assemble_vector(L)
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)

    with common.Timer("Assemble matrix"):
        A = assemble_matrix(a, [])
        A.assemble()

    with common.Timer("Solve"):
        # Create LU linear solver
        solver = PETSc.KSP().create(MPI.COMM_WORLD)
        solver.setType(PETSc.KSP.Type.PREONLY)
        solver.getPC().setType(PETSc.PC.Type.LU)
        solver.setOperators(A)

        # Solve
        uh = Function(V)
        solver.solve(b, uh.vector)
        uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                              mode=PETSc.ScatterMode.FORWARD)

    with common.Timer("Error functional compile"):
        # Calculate error
        M = (u_exact - uh)**2 * dx
        M = fem.Form(M)

    with common.Timer("Error assembly"):
        error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM)

    common.list_timings(MPI.COMM_WORLD, [common.TimingType.wall])
    assert np.absolute(error) < 1.0e-14
예제 #16
0
파일: cg.py 프로젝트: gouarin/GenEO
    def solve(self, ksp, b, x):
        """
        Solve of the AMPCG Krylov Subspace Solver.

        Parameters
        ==========

        ksp : FIX

        b : PETSc Vec
            The right hand side for which to solve.

        x : PETSc Vec
            To store the solution.

        """

        self.mpc.proj.project(x)
        xtild = self.mpc.proj.coarse_init(b)
        x += xtild

        A, B = ksp.getOperators()
        r, z, p, Ap = self.work
        comm = ksp.comm

        A.mult(x, r)
        r.aypx(-1, b)
        self.mpc.mult(r, z)

        natural_norm = sqrt(r.dot(z))
        self.natural_norm.append(natural_norm)

        its = ksp.getIterationNumber()

        if self.MPinitit or self.fullMP :
            if self.verbose :
                PETSc.Sys.Print('multipreconditioning initial iteration', comm=comm)
            self.ti.append(0)
            self.mpc.MP_mult(r, p[-1])
        else:
            if self.verbose :
                PETSc.Sys.Print('not multipreconditioning initial iteration', comm=comm)
            self.ti.append(inf)
            p[-1] = z.copy()

        alpha = self.gamma.duplicate()
        beta = self.gamma.duplicate()
        phi = self.gamma.duplicate()

        if self.callback:
            self.callback(locals())

        while not self.loop(ksp, r, z):
            if isinstance(p[-1], list):
                for i in range(self.ndom):
                    self.gamma[i] = p[-1][i].dot(r)
                    Ap[-1][i] = A*p[-1][i]
                    for j in range(i + 1):
                        tmp = Ap[-1][i].dot(p[-1][j])
                        self.Delta[i, j] = tmp
                        self.Delta[j, i] = tmp

                self.Delta.assemble()

                self.ksp_Delta.append(PETSc.KSP().create(comm=PETSc.COMM_SELF))
                self.ksp_Delta[-1].setOperators(self.Delta.copy())
                self.ksp_Delta[-1].setType(ksp.Type.PREONLY)
                pc = self.ksp_Delta[-1].getPC()
                pc.setType(pc.Type.CHOLESKY)
                self.ksp_Delta[-1].solve(self.gamma, alpha)

                for i in range(self.ndom):
                    x.axpy(alpha[i], p[-1][i])
                    r.axpy(-alpha[i], Ap[-1][i])

                ti = self.gamma.dot(alpha)
            else:
                gamma0 = p[-1].dot(r)
                Ap[-1] = A*p[-1]
                delta = Ap[-1].dot(p[-1])

                self.ksp_Delta.append(delta)
                alpha0 = gamma0/delta

                x.axpy(alpha0, p[-1])
                r.axpy(-alpha0, Ap[-1])

                ti = gamma0*alpha0

            self.mpc.mult(r, z)
            natural_norm = r.dot(z)
            ti /= natural_norm
            natural_norm = sqrt(natural_norm)

            self.natural_norm.append(natural_norm)
            self.ti.append(ti)

            if ti < self.tau or self.fullMP:
                if self.verbose :
                    PETSc.Sys.Print('multipreconditioning this iteration', comm=comm)
                p.append(self.add_vectors())
                Ap.append(self.add_vectors())
                self.mpc.MP_mult(r, p[-1])
            else:
                p.append(z.copy())
                Ap.append(z.duplicate())

            if self.callback:
                self.callback(locals())

            its = ksp.getIterationNumber()
            for it in range(its):
                if isinstance(p[-1], list):
                    for i in range(self.ndom):
                        if isinstance(p[it], list):
                            for j in range(self.ndom):
                                phi[j] = Ap[it][j].dot(p[-1][i])
                            self.ksp_Delta[it].solve(phi, beta)
                            for j in range(self.ndom):
                                p[-1][i].axpy(-beta[j], p[it][j])
                        else:
                            phi0 = Ap[it].dot(p[-1][i])
                            beta0 = phi0/self.ksp_Delta[it]
                            p[-1][i].axpy(-beta0, p[it])
                else:
                    if isinstance(p[it], list):
                        for j in range(self.ndom):
                            phi[j] = Ap[it][j].dot(p[-1])
                        self.ksp_Delta[it].solve(phi, beta)
                        for j in range(self.ndom):
                            p[-1].axpy(-beta[j], p[it][j])
                    else:
                        phi0 = Ap[it].dot(p[-1])
                        beta0 = phi0/self.ksp_Delta[it]
                        p[-1].axpy(-beta0, p[it])

            if isinstance(p[-1], list):
                for i in range(self.ndom):
                    self.mpc.proj.project(p[-1][i])
            else:
                self.mpc.proj.project(p[-1])
예제 #17
0
def run_scalar_test(mesh, V, degree):
    """ Manufactured Poisson problem, solving u = x[1]**p, where p is the
    degree of the Lagrange function space.

    """
    u, v = TrialFunction(V), TestFunction(V)
    a = inner(grad(u), grad(v)) * dx

    # Get quadrature degree for bilinear form integrand (ignores effect of non-affine map)
    a = inner(grad(u), grad(v)) * dx(metadata={"quadrature_degree": -1})
    a.integrals()[0].metadata(
    )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(a)

    # Source term
    x = SpatialCoordinate(mesh)
    u_exact = x[1]**degree
    f = -div(grad(u_exact))

    # Set quadrature degree for linear form integrand (ignores effect of non-affine map)
    L = inner(f, v) * dx(metadata={"quadrature_degree": -1})
    L.integrals()[0].metadata(
    )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(L)

    with common.Timer("Linear form compile"):
        L = fem.Form(L)

    with common.Timer("Function interpolation"):
        u_bc = Function(V)
        u_bc.interpolate(lambda x: x[1]**degree)

    # Create Dirichlet boundary condition
    mesh.topology.create_connectivity_all()
    facetdim = mesh.topology.dim - 1
    bndry_facets = np.where(
        np.array(cpp.mesh.compute_boundary_facets(mesh.topology)) == 1)[0]
    bdofs = locate_dofs_topological(V, facetdim, bndry_facets)
    assert (len(bdofs) < V.dim)
    bc = DirichletBC(u_bc, bdofs)

    with common.Timer("Vector assembly"):
        b = assemble_vector(L)
        apply_lifting(b, [a], [[bc]])
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        set_bc(b, [bc])

    with common.Timer("Bilinear form compile"):
        a = fem.Form(a)

    with common.Timer("Matrix assembly"):
        A = assemble_matrix(a, [bc])
        A.assemble()

    # Create LU linear solver
    solver = PETSc.KSP().create(MPI.COMM_WORLD)
    solver.setType(PETSc.KSP.Type.PREONLY)
    solver.getPC().setType(PETSc.PC.Type.LU)
    solver.setOperators(A)

    with common.Timer("Solve"):
        uh = Function(V)
        solver.solve(b, uh.vector)
        uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                              mode=PETSc.ScatterMode.FORWARD)

    with common.Timer("Error functional compile"):
        M = (u_exact - uh)**2 * dx
        M = fem.Form(M)

    with common.Timer("Error assembly"):
        error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM)

    common.list_timings(MPI.COMM_WORLD, [common.TimingType.wall])
    assert np.absolute(error) < 1.0e-14
v = TestFunction(V)

F = inner(grad(u), grad(v)) * dx - k0**2 * inner(u, v) * dx - \
    k_absorb * inner(u, v) * dx \
    + inner(dot(grad(ui), n), v) * ds(1)

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

'''           Assemble matrix and vector and set up direct solver           '''
A = dolfinx.fem.assemble_matrix(a)
A.assemble()
b = dolfinx.fem.assemble_vector(L)
b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)

solver = PETSc.KSP().create(mesh.mpi_comm())
opts = PETSc.Options()
opts["ksp_type"] = "preonly"
opts["pc_type"] = "lu"
opts["pc_factor_mat_solver_type"] = "mumps"
solver.setFromOptions()
solver.setOperators(A)

# Solve linear system
u = Function(V)
start = time.time()
solver.solve(b, u.vector)
end = time.time()
time_elapsed = end - start
print('Solve time: ', time_elapsed)
u.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
예제 #19
0
def reference_periodic(tetra: bool,
                       r_lvl: int = 0,
                       out_hdf5: h5py.File = None,
                       xdmf: bool = False,
                       boomeramg: bool = False,
                       kspview: bool = False,
                       degree: int = 1):
    # Create mesh and finite element
    if tetra:
        # Tet setup
        N = 3
        mesh = create_unit_cube(MPI.COMM_WORLD, N, N, N)
        for i in range(r_lvl):
            mesh.topology.create_entities(mesh.topology.dim - 2)
            mesh = refine(mesh, redistribute=True)
            N *= 2
    else:
        # Hex setup
        N = 3
        for i in range(r_lvl):
            N *= 2
        mesh = create_unit_cube(MPI.COMM_WORLD, N, N, N, CellType.hexahedron)

    V = FunctionSpace(mesh, ("CG", degree))

    # Create Dirichlet boundary condition

    def dirichletboundary(x):
        return np.logical_or(
            np.logical_or(np.isclose(x[1], 0), np.isclose(x[1], 1)),
            np.logical_or(np.isclose(x[2], 0), np.isclose(x[2], 1)))

    mesh.topology.create_connectivity(2, 1)
    geometrical_dofs = locate_dofs_geometrical(V, dirichletboundary)
    bc = dirichletbc(PETSc.ScalarType(0), geometrical_dofs, V)
    bcs = [bc]

    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    a = inner(grad(u), grad(v)) * dx
    x = SpatialCoordinate(mesh)
    dx_ = x[0] - 0.9
    dy_ = x[1] - 0.5
    dz_ = x[2] - 0.1
    f = x[0] * sin(5.0 * pi * x[1]) + 1.0 * exp(
        -(dx_ * dx_ + dy_ * dy_ + dz_ * dz_) / 0.02)
    rhs = inner(f, v) * dx

    # Assemble rhs, RHS and apply lifting
    bilinear_form = form(a)
    linear_form = form(rhs)
    A_org = assemble_matrix(bilinear_form, bcs)
    A_org.assemble()
    L_org = assemble_vector(linear_form)
    apply_lifting(L_org, [bilinear_form], [bcs])
    L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
                      mode=PETSc.ScatterMode.REVERSE)
    set_bc(L_org, bcs)

    # Create PETSc nullspace
    nullspace = PETSc.NullSpace().create(constant=True)
    PETSc.Mat.setNearNullSpace(A_org, nullspace)

    # Set PETSc options
    opts = PETSc.Options()
    if boomeramg:
        opts["ksp_type"] = "cg"
        opts["ksp_rtol"] = 1.0e-5
        opts["pc_type"] = "hypre"
        opts['pc_hypre_type'] = 'boomeramg'
        opts["pc_hypre_boomeramg_max_iter"] = 1
        opts["pc_hypre_boomeramg_cycle_type"] = "v"
        # opts["pc_hypre_boomeramg_print_statistics"] = 1
    else:
        opts["ksp_type"] = "cg"
        opts["ksp_rtol"] = 1.0e-12
        opts["pc_type"] = "gamg"
        opts["pc_gamg_type"] = "agg"
        opts["pc_gamg_sym_graph"] = True

        # Use Chebyshev smoothing for multigrid
        opts["mg_levels_ksp_type"] = "richardson"
        opts["mg_levels_pc_type"] = "sor"
    # opts["help"] = None # List all available options
    # opts["ksp_view"] = None # List progress of solver

    # Initialize PETSc solver, set options and operator
    solver = PETSc.KSP().create(MPI.COMM_WORLD)
    solver.setFromOptions()
    solver.setOperators(A_org)

    # Solve linear problem
    u_ = Function(V)
    start = perf_counter()
    with Timer("Solve"):
        solver.solve(L_org, u_.vector)
    end = perf_counter()
    u_.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                          mode=PETSc.ScatterMode.FORWARD)
    if kspview:
        solver.view()

    it = solver.getIterationNumber()
    num_dofs = V.dofmap.index_map.size_global * V.dofmap.index_map_bs
    if out_hdf5 is not None:
        d_set = out_hdf5.get("its")
        d_set[r_lvl] = it
        d_set = out_hdf5.get("num_dofs")
        d_set[r_lvl] = num_dofs
        d_set = out_hdf5.get("solve_time")
        d_set[r_lvl, MPI.COMM_WORLD.rank] = end - start

    if MPI.COMM_WORLD.rank == 0:
        print("Rlvl {0:d}, Iterations {1:d}".format(r_lvl, it))

    # Output solution to XDMF
    if xdmf:
        ext = "tet" if tetra else "hex"
        fname = "results/reference_periodic_{0:d}_{1:s}.xdmf".format(
            r_lvl, ext)
        u_.name = "u_" + ext + "_unconstrained"
        with XDMFFile(MPI.COMM_WORLD, fname, "w") as out_periodic:
            out_periodic.write_mesh(mesh)
            out_periodic.write_function(
                u_, 0.0,
                "Xdmf/Domain/" + "Grid[@Name='{0:s}'][1]".format(mesh.name))
예제 #20
0
            Aa.eliminate_zeros()
            plt.spy(Aa)
            plt.show()
            A,b = CP.Assemble(AA,bb)
            del AA
            F = assemble(fp)
            F = CP.Assemble(F)
            P = S.ExactPrecond(PP,Q,L,F,FSpaces)
            Mass = CP.Assemble(Q)

            u = b.duplicate()

        NS_is = PETSc.IS().createGeneral(range(Velocity.dim()+Pressure.dim()))
        M_is = PETSc.IS().createGeneral(range(Velocity.dim()+Pressure.dim(),W.dim()))

        kspNS = PETSc.KSP().create()
        kspM = PETSc.KSP().create()
        kspNS.setTolerances(1e-5)
        kspNS.setOperators(A.getSubMatrix(NS_is,NS_is),P.getSubMatrix(NS_is,NS_is))
        kspM.setOperators(A.getSubMatrix(M_is,M_is),P.getSubMatrix(M_is,M_is))
        A.destroy()
        P.destroy()
        OptDB = PETSc.Options()
        OptDB['pc_factor_shift_amount'] = "0.1"
        # OptDB['pc_factor_shift_type'] = 'POSITIVE_DEFINITE'
        OptDB['pc_factor_mat_ordering_type'] = 'amd'
        OptDB['pc_factor_mat_solver_package']  = 'mumps'
        # kspLAMG.max_it = 1
        kspNS.setFromOptions()
        kspNS.setType('gmres')
        pcNS = kspNS.getPC()
예제 #21
0
    def solve_linear(self, d_outputs, d_residuals, mode):
        linear_solver_ = self.options['linear_solver_']
        pde_problem = self.options['pde_problem']
        state_name = self.options['state_name']

        state_function = pde_problem.states_dict[state_name]['function']
        for argument_name, argument_function in iteritems(self.argument_functions_dict):
            density_func = argument_function
        mesh = state_function.function_space().mesh()
        sub_domains = df.MeshFunction('size_t', mesh, mesh.topology().dim() - 1)
        upper_edge = TractionBoundary()
        upper_edge.mark(sub_domains, 6)
        dss = df.Measure('ds')(subdomain_data=sub_domains)
        tractionBC = dss(6)

        residual_form = get_residual_form(
            state_function, 
            df.TestFunction(state_function.function_space()), 
            density_func,
            density_func.function_space(),
            tractionBC,
            # df.Constant((0.0, -9.e-1))
            df.Constant((0.0, -9.e-1)),
            int(self.itr)
            )
            
        A, _ = df.assemble_system(self.derivative_form, - residual_form, pde_problem.bcs_list)

        if linear_solver_=='fenics_direct':

            rhs_ = df.Function(state_function.function_space())
            dR = df.Function(state_function.function_space())

            rhs_.vector().set_local(d_outputs[state_name])

            for bc in pde_problem.bcs_list:
                bc.apply(A)
            Am = df.as_backend_type(A).mat()
            ATm = Am.transpose()
            AT =  df.PETScMatrix(ATm)

            df.solve(AT,dR.vector(),rhs_.vector()) 
            d_residuals[state_name] =  dR.vector().get_local()

        elif linear_solver_=='scipy_splu':
            for bc in pde_problem.bcs_list:
                bc.apply(A)
            Am = df.as_backend_type(A).mat()
            ATm = Am.transpose()
            ATm_csr = csr_matrix(ATm.getValuesCSR()[::-1], shape=Am.size)
            lu = splu(ATm_csr.tocsc())
            d_residuals[state_name] = lu.solve(d_outputs[state_name],trans='T')


        elif linear_solver_=='fenics_Krylov':

            rhs_ = df.Function(state_function.function_space())
            dR = df.Function(state_function.function_space())

            rhs_.vector().set_local(d_outputs[state_name])

            for bc in pde_problem.bcs_list:
                bc.apply(A)
            Am = df.as_backend_type(A).mat()
            ATm = Am.transpose()
            AT =  df.PETScMatrix(ATm)

            solver = df.KrylovSolver('gmres', 'ilu')
            prm = solver.parameters          
            prm["maximum_iterations"]=1000000
            prm["divergence_limit"] = 1e2
            solver.solve(AT,dR.vector(),rhs_.vector())

            d_residuals[state_name] =  dR.vector().get_local()

        elif linear_solver_=='petsc_gmres_ilu':
            ksp = PETSc.KSP().create() 
            ksp.setType(PETSc.KSP.Type.GMRES)
            ksp.setTolerances(rtol=5e-11)

            for bc in pde_problem.bcs_list:
                bc.apply(A)
            Am = df.as_backend_type(A).mat()

            ksp.setOperators(Am)

            ksp.setFromOptions()
            pc = ksp.getPC()
            pc.setType("ilu")

            size = state_function.function_space().dim()

            dR = PETSc.Vec().create()
            dR.setSizes(size)
            dR.setType('seq')
            dR.setValues(range(size), d_residuals[state_name])
            dR.setUp()

            du = PETSc.Vec().create()
            du.setSizes(size)
            du.setType('seq')
            du.setValues(range(size), d_outputs[state_name])
            du.setUp()

            if mode == 'fwd':
                ksp.solve(dR,du)
                d_outputs[state_name] = du.getValues(range(size))
            else:
                ksp.solveTranspose(du,dR)
                d_residuals[state_name] = dR.getValues(range(size))
예제 #22
0
def test_assembly_solve_block(mode):
    """Solve a two-field mass-matrix like problem with block matrix approaches
    and test that solution is the same.
    """
    mesh = UnitSquareMesh(MPI.COMM_WORLD, 32, 31, ghost_mode=mode)
    P = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    V0 = dolfinx.fem.FunctionSpace(mesh, P)
    V1 = V0.clone()

    def boundary(x):
        return numpy.logical_or(x[0] < 1.0e-6, x[0] > 1.0 - 1.0e-6)

    # Locate facets on boundary
    facetdim = mesh.topology.dim - 1
    bndry_facets = dolfinx.mesh.locate_entities_boundary(mesh, facetdim, boundary)

    bdofsV0 = dolfinx.fem.locate_dofs_topological(V0, facetdim, bndry_facets)
    bdofsV1 = dolfinx.fem.locate_dofs_topological(V1, facetdim, bndry_facets)

    u_bc0 = dolfinx.fem.Function(V0)
    u_bc0.vector.set(50.0)
    u_bc0.vector.ghostUpdate(
        addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
    u_bc1 = dolfinx.fem.Function(V1)
    u_bc1.vector.set(20.0)
    u_bc1.vector.ghostUpdate(
        addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
    bcs = [
        dolfinx.fem.dirichletbc.DirichletBC(u_bc0, bdofsV0),
        dolfinx.fem.dirichletbc.DirichletBC(u_bc1, bdofsV1)
    ]

    # Variational problem
    u, p = ufl.TrialFunction(V0), ufl.TrialFunction(V1)
    v, q = ufl.TestFunction(V0), ufl.TestFunction(V1)
    f = 1.0
    g = -3.0
    zero = dolfinx.Function(V0)

    a00 = inner(u, v) * dx
    a01 = zero * inner(p, v) * dx
    a10 = zero * inner(u, q) * dx
    a11 = inner(p, q) * dx
    L0 = inner(f, v) * dx
    L1 = inner(g, q) * dx

    def monitor(ksp, its, rnorm):
        pass
        # print("Norm:", its, rnorm)

    A0 = dolfinx.fem.assemble_matrix_block([[a00, a01], [a10, a11]], bcs)
    b0 = dolfinx.fem.assemble_vector_block([L0, L1], [[a00, a01], [a10, a11]],
                                           bcs)
    A0.assemble()
    A0norm = A0.norm()
    b0norm = b0.norm()
    x0 = A0.createVecLeft()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setOperators(A0)
    ksp.setMonitor(monitor)
    ksp.setType('cg')
    ksp.setTolerances(rtol=1.0e-14)
    ksp.setFromOptions()
    ksp.solve(b0, x0)
    x0norm = x0.norm()

    # Nested (MatNest)
    A1 = dolfinx.fem.assemble_matrix_nest([[a00, a01], [a10, a11]], bcs, diagonal=1.0)
    A1.assemble()
    b1 = dolfinx.fem.assemble_vector_nest([L0, L1])
    dolfinx.fem.apply_lifting_nest(b1, [[a00, a01], [a10, a11]], bcs)
    for b_sub in b1.getNestSubVecs():
        b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    bcs0 = dolfinx.cpp.fem.bcs_rows(dolfinx.fem.assemble._create_cpp_form([L0, L1]), bcs)
    dolfinx.fem.set_bc_nest(b1, bcs0)
    b1.assemble()

    b1norm = b1.norm()
    assert b1norm == pytest.approx(b0norm, 1.0e-12)
    A1norm = nest_matrix_norm(A1)
    assert A0norm == pytest.approx(A1norm, 1.0e-12)

    x1 = b1.copy()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setMonitor(monitor)
    ksp.setOperators(A1)
    ksp.setType('cg')
    ksp.setTolerances(rtol=1.0e-12)
    ksp.setFromOptions()
    ksp.solve(b1, x1)
    x1norm = x1.norm()
    assert x1norm == pytest.approx(x0norm, rel=1.0e-12)

    # Monolithic version
    E = P * P
    W = dolfinx.fem.FunctionSpace(mesh, E)
    u0, u1 = ufl.TrialFunctions(W)
    v0, v1 = ufl.TestFunctions(W)
    a = inner(u0, v0) * dx + inner(u1, v1) * dx
    L = inner(f, v0) * ufl.dx + inner(g, v1) * dx

    u0_bc = dolfinx.fem.Function(V0)
    u0_bc.vector.set(50.0)
    u0_bc.vector.ghostUpdate(
        addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
    u1_bc = dolfinx.fem.Function(V1)
    u1_bc.vector.set(20.0)
    u1_bc.vector.ghostUpdate(
        addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)

    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))
    ]

    A2 = dolfinx.fem.assemble_matrix(a, bcs)
    A2.assemble()
    b2 = dolfinx.fem.assemble_vector(L)
    dolfinx.fem.apply_lifting(b2, [a], [bcs])
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    dolfinx.fem.set_bc(b2, bcs)
    A2norm = A2.norm()
    b2norm = b2.norm()
    assert A2norm == pytest.approx(A0norm, 1.0e-12)
    assert b2norm == pytest.approx(b0norm, 1.0e-12)

    x2 = b2.copy()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setMonitor(monitor)
    ksp.setOperators(A2)
    ksp.setType('cg')
    ksp.getPC().setType('jacobi')
    ksp.setTolerances(rtol=1.0e-12)
    ksp.setFromOptions()
    ksp.solve(b2, x2)
    x2norm = x2.norm()
    assert x2norm == pytest.approx(x0norm, 1.0e-10)
예제 #23
0
    def __init__(self,
                 a: ufl.Form,
                 L: ufl.Form,
                 bcs: typing.List[fem.DirichletBC] = [],
                 u: fem.Function = None,
                 petsc_options={},
                 form_compiler_parameters={},
                 jit_parameters={}):
        """Initialize solver for a linear variational problem.

        Parameters
        ----------
        a
            A bilinear UFL form, the left hand side of the variational problem.

        L
            A linear UFL form, the right hand side of the variational problem.

        bcs
            A list of Dirichlet boundary conditions.

        u
            The solution function. It will be created if not provided.

        petsc_options
            Parameters that is passed to the linear algebra backend PETSc.
            For available choices for the 'petsc_options' kwarg, see the
            `PETSc-documentation <https://www.mcs.anl.gov/petsc/documentation/index.html>`.

        form_compiler_parameters
            Parameters used in FFCX compilation of this form. Run `ffcx --help` at
            the commandline to see all available options. Takes priority over all
            other parameter values, except for `scalar_type` which is determined by
            DOLFINX.

        jit_parameters
            Parameters used in CFFI JIT compilation of C code generated by FFCX.
            See `python/dolfinx/jit.py` for all available parameters.
            Takes priority over all other parameter values.

        .. code-block:: python
            problem = LinearProblem(a, L, [bc0, bc1], petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
        """
        self._a = fem.Form(a,
                           form_compiler_parameters=form_compiler_parameters,
                           jit_parameters=jit_parameters)
        self._A = fem.create_matrix(self._a)

        self._L = fem.Form(L,
                           form_compiler_parameters=form_compiler_parameters,
                           jit_parameters=jit_parameters)
        self._b = fem.create_vector(self._L)

        if u is None:
            # Extract function space from TrialFunction (which is at the
            # end of the argument list as it is numbered as 1, while the
            # Test function is numbered as 0)
            self.u = fem.Function(a.arguments()[-1].ufl_function_space())
        else:
            self.u = u
        self.bcs = bcs

        self._solver = PETSc.KSP().create(
            self.u.function_space.mesh.mpi_comm())
        self._solver.setOperators(self._A)

        # Give PETSc solver options a unique prefix
        solver_prefix = "dolfinx_solve_{}".format(id(self))
        self._solver.setOptionsPrefix(solver_prefix)

        # Set PETSc options
        opts = PETSc.Options()
        opts.prefixPush(solver_prefix)
        for k, v in petsc_options.items():
            opts[k] = v
        opts.prefixPop()
        self._solver.setFromOptions()
예제 #24
0
def test_assembly_solve_block():
    """Solve a two-field mass-matrix like problem with block matrix approaches
    and test that solution is the same.
    """
    mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 32, 31)
    p0, p1 = 1, 1
    P0 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p0)
    P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p1)
    V0 = dolfin.function.functionspace.FunctionSpace(mesh, P0)
    V1 = dolfin.function.functionspace.FunctionSpace(mesh, P1)

    def boundary(x):
        return numpy.logical_or(x[:, 0] < 1.0e-6, x[:, 0] > 1.0 - 1.0e-6)

    u_bc0 = dolfin.function.Function(V0)
    u_bc0.vector.set(50.0)
    u_bc0.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                             mode=PETSc.ScatterMode.FORWARD)
    u_bc1 = dolfin.function.Function(V1)
    u_bc1.vector.set(20.0)
    u_bc1.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                             mode=PETSc.ScatterMode.FORWARD)
    bcs = [
        dolfin.fem.dirichletbc.DirichletBC(V0, u_bc0, boundary),
        dolfin.fem.dirichletbc.DirichletBC(V1, u_bc1, boundary)
    ]

    # Variational problem
    u, p = dolfin.function.TrialFunction(V0), dolfin.function.TrialFunction(V1)
    v, q = dolfin.function.TestFunction(V0), dolfin.function.TestFunction(V1)
    f = 1.0
    g = -3.0
    zero = dolfin.Function(V0)

    a00 = inner(u, v) * dx
    a01 = zero * inner(p, v) * dx
    a10 = zero * inner(u, q) * dx
    a11 = inner(p, q) * dx
    L0 = inner(f, v) * dx
    L1 = inner(g, q) * dx

    def monitor(ksp, its, rnorm):
        pass
        # print("Norm:", its, rnorm)

    A0 = dolfin.fem.assemble_matrix_block([[a00, a01], [a10, a11]], bcs)
    b0 = dolfin.fem.assemble_vector_block([L0, L1], [[a00, a01], [a10, a11]],
                                          bcs)
    A0norm = A0.norm()
    b0norm = b0.norm()
    x0 = A0.createVecLeft()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setOperators(A0)
    ksp.setMonitor(monitor)
    ksp.setType('cg')
    ksp.setTolerances(rtol=1.0e-14)
    ksp.setFromOptions()
    ksp.solve(b0, x0)
    x0norm = x0.norm()

    # Nested (MatNest)
    A1 = dolfin.fem.assemble_matrix_nest([[a00, a01], [a10, a11]], bcs)
    b1 = dolfin.fem.assemble_vector_nest([L0, L1], [[a00, a01], [a10, a11]],
                                         bcs)
    b1norm = b1.norm()
    assert b1norm == pytest.approx(b0norm, 1.0e-12)
    A1norm = nest_matrix_norm(A1)
    assert A0norm == pytest.approx(A1norm, 1.0e-12)

    x1 = b1.copy()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setMonitor(monitor)
    ksp.setOperators(A1)
    ksp.setType('cg')
    ksp.setTolerances(rtol=1.0e-12)
    ksp.setFromOptions()
    ksp.solve(b1, x1)
    x1norm = x1.norm()
    assert x1norm == pytest.approx(x0norm, rel=1.0e-12)

    # Monolithic version
    E = P0 * P1
    W = dolfin.function.functionspace.FunctionSpace(mesh, E)
    u0, u1 = dolfin.function.TrialFunctions(W)
    v0, v1 = dolfin.function.TestFunctions(W)
    a = inner(u0, v0) * dx + inner(u1, v1) * dx
    L = inner(f, v0) * ufl.dx + inner(g, v1) * dx

    V0 = dolfin.function.functionspace.FunctionSpace(mesh, P0)
    V1 = dolfin.function.functionspace.FunctionSpace(mesh, P1)

    u0_bc = dolfin.function.Function(V0)
    u0_bc.vector.set(50.0)
    u0_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                             mode=PETSc.ScatterMode.FORWARD)
    u1_bc = dolfin.function.Function(V1)
    u1_bc.vector.set(20.0)
    u1_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                             mode=PETSc.ScatterMode.FORWARD)

    bcs = [
        dolfin.fem.dirichletbc.DirichletBC(W.sub(0), u0_bc, boundary),
        dolfin.fem.dirichletbc.DirichletBC(W.sub(1), u1_bc, boundary)
    ]

    A2 = dolfin.fem.assemble_matrix(a, bcs)
    A2.assemble()
    b2 = dolfin.fem.assemble_vector(L)
    dolfin.fem.apply_lifting(b2, [a], [bcs])
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    dolfin.fem.set_bc(b2, bcs)
    A2norm = A2.norm()
    b2norm = b2.norm()
    assert A2norm == pytest.approx(A0norm, 1.0e-12)
    assert b2norm == pytest.approx(b0norm, 1.0e-12)

    x2 = b2.copy()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setMonitor(monitor)
    ksp.setOperators(A2)
    ksp.setType('cg')
    ksp.getPC().setType('jacobi')
    ksp.setTolerances(rtol=1.0e-12)
    ksp.setFromOptions()
    ksp.solve(b2, x2)
    x2norm = x2.norm()
    assert x2norm == pytest.approx(x0norm, 1.0e-10)
예제 #25
0
boundary_facets = dolfinx.mesh.locate_entities_boundary(
    mesh, mesh.topology.dim - 1, lambda x: np.full(x.shape[1], True, dtype=bool))
boundary_dofs = dolfinx.fem.locate_dofs_topological(
    (V.sub(1), V_1), mesh.topology.dim - 1, boundary_facets)

bcs = [dirichletbc(zero_u, boundary_dofs, V.sub(1))]

A = assemble_matrix(a, bcs=bcs)
A.assemble()
b = assemble_vector(L)
apply_lifting(b, [a], bcs=[bcs])
b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
set_bc(b, bcs)

# Solve
solver = PETSc.KSP().create(MPI.COMM_WORLD)
PETSc.Options()["ksp_type"] = "preonly"
PETSc.Options()["pc_type"] = "lu"
PETSc.Options()["pc_factor_mat_solver_type"] = "mumps"
solver.setFromOptions()
solver.setOperators(A)

x_h = Function(V)
solver.solve(b, x_h.vector)
x_h.x.scatter_forward()
sigma_h = S(ufl.as_tensor([[x_h[0], x_h[1]], [x_h[2], x_h[3]]]))


# Viz

xvfb.start_xvfb(wait=0.05)
예제 #26
0
def test_assembly_solve_taylor_hood(mesh):
    """Assemble Stokes problem with Taylor-Hood elements and solve."""
    P2 = functionspace.VectorFunctionSpace(mesh, ("Lagrange", 2))
    P1 = functionspace.FunctionSpace(mesh, ("Lagrange", 1))

    def boundary0(x):
        """Define boundary x = 0"""
        return x[:, 0] < 10 * numpy.finfo(float).eps

    def boundary1(x):
        """Define boundary x = 1"""
        return x[:, 0] > (1.0 - 10 * numpy.finfo(float).eps)

    u0 = dolfin.Function(P2)
    u0.vector.set(1.0)
    u0.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                          mode=PETSc.ScatterMode.FORWARD)
    bc0 = dolfin.DirichletBC(P2, u0, boundary0)
    bc1 = dolfin.DirichletBC(P2, u0, boundary1)

    u, p = dolfin.TrialFunction(P2), dolfin.TrialFunction(P1)
    v, q = dolfin.TestFunction(P2), dolfin.TestFunction(P1)

    a00 = inner(ufl.grad(u), ufl.grad(v)) * dx
    a01 = ufl.inner(p, ufl.div(v)) * dx
    a10 = ufl.inner(ufl.div(u), q) * dx
    a11 = None

    p00 = a00
    p01, p10 = None, None
    p11 = inner(p, q) * dx

    # FIXME
    # We need zero function for the 'zero' part of L
    p_zero = dolfin.Function(P1)
    f = dolfin.Function(P2)
    L0 = ufl.inner(f, v) * dx
    L1 = ufl.inner(p_zero, q) * dx

    # -- Blocked and nested

    A0 = dolfin.fem.assemble_matrix_nest([[a00, a01], [a10, a11]], [bc0, bc1])
    A0norm = nest_matrix_norm(A0)
    P0 = dolfin.fem.assemble_matrix_nest([[p00, p01], [p10, p11]], [bc0, bc1])
    P0norm = nest_matrix_norm(P0)
    b0 = dolfin.fem.assemble_vector_nest([L0, L1], [[a00, a01], [a10, a11]],
                                         [bc0, bc1])
    b0norm = b0.norm()

    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setOperators(A0, P0)
    nested_IS = P0.getNestISs()
    ksp.setType("minres")
    pc = ksp.getPC()
    pc.setType("fieldsplit")
    pc.setFieldSplitIS(["u", nested_IS[0][0]], ["p", nested_IS[1][1]])
    ksp_u, ksp_p = pc.getFieldSplitSubKSP()
    ksp_u.setType("preonly")
    ksp_u.getPC().setType('lu')
    ksp_u.getPC().setFactorSolverType('mumps')
    ksp_p.setType("preonly")

    def monitor(ksp, its, rnorm):
        # print("Num it, rnorm:", its, rnorm)
        pass

    ksp.setTolerances(rtol=1.0e-8, max_it=50)
    ksp.setMonitor(monitor)
    ksp.setFromOptions()
    x0 = b0.copy()
    ksp.solve(b0, x0)
    assert ksp.getConvergedReason() > 0

    # -- Blocked and monolithic

    A1 = dolfin.fem.assemble_matrix_block([[a00, a01], [a10, a11]], [bc0, bc1])
    assert A1.norm() == pytest.approx(A0norm, 1.0e-12)
    P1 = dolfin.fem.assemble_matrix_block([[p00, p01], [p10, p11]], [bc0, bc1])
    assert P1.norm() == pytest.approx(P0norm, 1.0e-12)
    b1 = dolfin.fem.assemble_vector_block([L0, L1], [[a00, a01], [a10, a11]],
                                          [bc0, bc1])
    assert b1.norm() == pytest.approx(b0norm, 1.0e-12)

    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setOperators(A1, P1)
    ksp.setType("minres")
    pc = ksp.getPC()
    pc.setType('lu')
    pc.setFactorSolverType('mumps')
    ksp.setTolerances(rtol=1.0e-8, max_it=50)
    ksp.setFromOptions()
    x1 = A1.createVecRight()
    ksp.solve(b1, x1)
    assert ksp.getConvergedReason() > 0
    assert x1.norm() == pytest.approx(x0.norm(), 1e-8)

    # -- Monolithic

    P2 = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
    P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    TH = P2 * P1
    W = dolfin.FunctionSpace(mesh, TH)
    (u, p) = dolfin.TrialFunctions(W)
    (v, q) = dolfin.TestFunctions(W)
    a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
    a01 = ufl.inner(p, ufl.div(v)) * dx
    a10 = ufl.inner(ufl.div(u), q) * dx
    a = a00 + a01 + a10

    p00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
    p11 = ufl.inner(p, q) * dx
    p_form = p00 + p11

    f = dolfin.Function(W.sub(0).collapse())
    p_zero = dolfin.Function(W.sub(1).collapse())
    L0 = inner(f, v) * dx
    L1 = inner(p_zero, q) * dx
    L = L0 + L1

    bc0 = dolfin.DirichletBC(W.sub(0), u0, boundary0)
    bc1 = dolfin.DirichletBC(W.sub(0), u0, boundary1)

    A2 = dolfin.fem.assemble_matrix(a, [bc0, bc1])
    A2.assemble()
    assert A2.norm() == pytest.approx(A0norm, 1.0e-12)
    P2 = dolfin.fem.assemble_matrix(p_form, [bc0, bc1])
    P2.assemble()
    assert P2.norm() == pytest.approx(P0norm, 1.0e-12)

    b2 = dolfin.fem.assemble_vector(L)
    dolfin.fem.apply_lifting(b2, [a], [[bc0, bc1]])
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    dolfin.fem.set_bc(b2, [bc0, bc1])
    b2norm = b2.norm()
    assert b2norm == pytest.approx(b0norm, 1.0e-12)

    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setOperators(A2, P2)
    ksp.setType("minres")
    pc = ksp.getPC()
    pc.setType('lu')
    pc.setFactorSolverType('mumps')

    def monitor(ksp, its, rnorm):
        # print("Num it, rnorm:", its, rnorm)
        pass

    ksp.setTolerances(rtol=1.0e-8, max_it=50)
    ksp.setMonitor(monitor)
    ksp.setFromOptions()
    x2 = A2.createVecRight()
    ksp.solve(b2, x2)
    assert ksp.getConvergedReason() > 0
    assert x0.norm() == pytest.approx(x2.norm(), 1e-8)
예제 #27
0
    def assemble_coarse_operators(self, V0s):
        """
        Assembles the coarse operators from a list of local contributions to the coarse space.

        Parameters
        ==========

        V0s : list of local PETSc .vecs
           list of the coarse vectors contributed by the subdomain.

        Returns
        ==========

        V0 : list of local vectors or None ? FIX
            list of the local contributions to the coarse space numbered globally: V0[i] is either a scaled local vector from V0s or None if coarse vector number i belongs to another subdomain. The scaling that is applied to the coarse vectors ensures that their A-norm is 1.

        AV0 : list of global PETSc.Vecs
            list of the A*V0[i]. These are global vectors so not in the same format as the vectors in V0.

        Delta : PETSc.Mat (local)
            matrix of the coarse problem. As a result of the scaling of the coarse vectors, its diagonal is 1. This matrix is duplicated over all subdomains This matrix is duplicated over all subdomains

        ksp_Delta : PETSc.ksp
            Krylov subspace solver for the coarse problem matrix Delta.

        """
        if self.verbose:
            if self.V0_is_global == False:
                PETSc.Sys.Print(
                    'Subdomain number {} contributes {} coarse vectors in total'
                    .format(mpi.COMM_WORLD.rank, len(V0s)),
                    comm=self.comm)

        if mpi.COMM_WORLD.rank == 0:
            self.gathered_dimV0s = [
            ]  #only for view save dims of V0s from each s
        self.work2 = self.work.duplicate()
        if (self.V0_is_global == False):
            V0 = []
            for i in range(mpi.COMM_WORLD.size):
                nrbl = len(V0s) if i == mpi.COMM_WORLD.rank else None
                nrbl = mpi.COMM_WORLD.bcast(nrbl, root=i)
                if mpi.COMM_WORLD.rank == 0:
                    self.gathered_dimV0s.append(
                        nrbl)  #only for view save dims of V0s from each s
                for irbm in range(nrbl):
                    V0.append(V0s[irbm].copy() if i ==
                              mpi.COMM_WORLD.rank else None)
        else:
            V0 = V0s.copy()

        AV0 = []
        for vec in V0:
            if (self.V0_is_global == False):
                if vec:
                    self.works = vec.copy()
                else:
                    self.works.set(0.)
                self.work.set(0)
                self.scatter_l2g(self.works, self.work,
                                 PETSc.InsertMode.ADD_VALUES)
            else:
                self.work = vec.copy()
            #debug1 = np.sqrt(self.work.dot(self.work))
            #debug4 = self.work.norm()
            #debug3 = np.sqrt(self.works.dot(self.works))
            #debug5 = self.works.norm()
            #print(f'normworks {debug3} = {debug5} normwork {debug1} = {debug4}')
            self.A.mult(self.work, self.work2)
            AV0.append(self.work2.copy())
            tmp = np.sqrt(self.work.dot(self.work2))
            if (self.V0_is_global == False):
                self.scatter_l2g(AV0[-1], self.works,
                                 PETSc.InsertMode.INSERT_VALUES,
                                 PETSc.ScatterMode.SCATTER_REVERSE)
                if vec:
                    vec.scale(1. / tmp)
                    self.works = vec.copy()
                else:
                    self.works.set(0)
                self.work.set(0)
                self.scatter_l2g(self.works, self.work,
                                 PETSc.InsertMode.ADD_VALUES)
                #self.scatter_l2g(self.works, self.work, PETSc.InsertMode.ADD_VALUES)
                #self.A.mult(self.work,self.work2)
                self.A.mult(self.work, AV0[-1])
            else:
                vec.scale(1. / tmp)
                self.A.mult(vec, AV0[-1])
            #self.A.mult(self.work,AV0[-1])
            # AV0[-1] = self.work2.copy()
            # AV0[-1] = xtmp.copy()
            #debug6 = np.sqrt(self.work2.dot(self.work2))
            #debug7 = self.work2.norm()
            #debug2 = np.sqrt(AV0[-1].dot(AV0[-1]))
            #debug5 = AV0[-1].norm()
            # debug6 = np.sqrt(self.work2.dot(self.work2))
            # debug7 = self.work2.norm()
            # debug2 = np.sqrt(AV0[-1].dot(AV0[-1]))
            # debug5 = AV0[-1].norm()


#            if mpi.COMM_WORLD.rank == 0:
#                print(f'norm Acoarsevec {debug2} = {debug5}')
# print(f'norm Acoarsevec {debug2} = {debug5} = {debug6} = {debug7}')

        self.dim = len(V0)
        PETSc.Sys.Print('There are {} vectors in the coarse space.'.format(
            self.dim),
                        comm=mpi.COMM_WORLD)

        #Define, fill and factorize coarse problem matrix
        Delta = PETSc.Mat().create(comm=PETSc.COMM_SELF)
        Delta.setType(PETSc.Mat.Type.SEQDENSE)
        Delta.setSizes([len(V0), len(V0)])
        Delta.setOption(PETSc.Mat.Option.SYMMETRIC, True)
        Delta.setPreallocationDense(None)
        for i, vec in enumerate(V0):
            if (self.V0_is_global == False):
                if vec:
                    self.works = vec.copy()
                else:
                    self.works.set(0)

                self.work.set(0)
                self.scatter_l2g(self.works, self.work,
                                 PETSc.InsertMode.ADD_VALUES)
            else:
                self.work = vec.copy()
            for j in range(i + 1):
                tmp = AV0[j].dot(self.work)
                Delta[i, j] = tmp
                Delta[j, i] = tmp
        Delta.assemble()
        ksp_Delta = PETSc.KSP().create(comm=PETSc.COMM_SELF)
        ksp_Delta.setOperators(Delta)
        ksp_Delta.setType('preonly')
        pc = ksp_Delta.getPC()
        pc.setType('cholesky')
        return V0, AV0, Delta, ksp_Delta
예제 #28
0
def test_cube_contact(generate_hex_boxes, nonslip,
                      get_assemblers):  # noqa: F811
    assemble_matrix, assemble_vector = get_assemblers
    comm = MPI.COMM_WORLD
    root = 0
    # Generate mesh
    mesh_data = generate_hex_boxes
    mesh, mt = mesh_data
    fdim = mesh.topology.dim - 1
    # Create functionspaces
    V = fem.VectorFunctionSpace(mesh, ("Lagrange", 1))

    # Helper for orienting traction

    # Bottom boundary is fixed in all directions
    u_bc = fem.Function(V)
    with u_bc.vector.localForm() as u_local:
        u_local.set(0.0)

    bottom_dofs = fem.locate_dofs_topological(V, fdim, mt.find(5))
    bc_bottom = fem.dirichletbc(u_bc, bottom_dofs)

    g_vec = [0, 0, -4.25e-1]
    if not nonslip:
        # Helper for orienting traction
        r_matrix = dolfinx_mpc.utils.rotation_matrix(
            [1 / np.sqrt(2), 1 / np.sqrt(2), 0], -theta)

        # Top boundary has a given deformation normal to the interface
        g_vec = np.dot(r_matrix, [0, 0, -4.25e-1])

    # Top boundary has a given deformation normal to the interface
    def top_v(x):
        values = np.empty((3, x.shape[1]))
        values[0] = g_vec[0]
        values[1] = g_vec[1]
        values[2] = g_vec[2]
        return values

    u_top = fem.Function(V)
    u_top.interpolate(top_v)

    top_dofs = fem.locate_dofs_topological(V, fdim, mt.find(3))
    bc_top = fem.dirichletbc(u_top, top_dofs)

    bcs = [bc_bottom, bc_top]

    # Elasticity parameters
    E = PETSc.ScalarType(1.0e3)
    nu = 0
    mu = fem.Constant(mesh, E / (2.0 * (1.0 + nu)))
    lmbda = fem.Constant(mesh, E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)))

    # Stress computation
    def sigma(v):
        return (2.0 * mu * ufl.sym(ufl.grad(v)) +
                lmbda * ufl.tr(ufl.sym(ufl.grad(v))) * ufl.Identity(len(v)))

    # Define variational problem
    u = ufl.TrialFunction(V)
    v = ufl.TestFunction(V)
    a = ufl.inner(sigma(u), ufl.grad(v)) * ufl.dx
    rhs = ufl.inner(fem.Constant(mesh, PETSc.ScalarType(
        (0, 0, 0))), v) * ufl.dx
    bilinear_form = fem.form(a)
    linear_form = fem.form(rhs)

    # Create LU solver
    solver = PETSc.KSP().create(comm)
    solver.setType("preonly")
    solver.setTolerances(rtol=1.0e-14)
    solver.getPC().setType("lu")

    # Create MPC contact condition and assemble matrices
    mpc = dolfinx_mpc.MultiPointConstraint(V)
    if nonslip:
        with Timer("~Contact: Create non-elastic constraint"):
            mpc.create_contact_inelastic_condition(mt, 4, 9)
    else:
        with Timer("~Contact: Create contact constraint"):
            nh = dolfinx_mpc.utils.create_normal_approximation(V, mt, 4)
            mpc.create_contact_slip_condition(mt, 4, 9, nh)

    mpc.finalize()

    with Timer("~TEST: Assemble bilinear form"):
        A = assemble_matrix(bilinear_form, mpc, bcs=bcs)
    with Timer("~TEST: Assemble vector"):
        b = assemble_vector(linear_form, mpc)

    dolfinx_mpc.apply_lifting(b, [bilinear_form], [bcs], mpc)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
                  mode=PETSc.ScatterMode.REVERSE)
    fem.petsc.set_bc(b, bcs)

    with Timer("~MPC: Solve"):
        solver.setOperators(A)
        uh = b.copy()
        uh.set(0)
        solver.solve(b, uh)

    uh.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                   mode=PETSc.ScatterMode.FORWARD)
    mpc.backsubstitution(uh)

    # Write solution to file
    # u_h = fem.Function(mpc.function_space)
    # u_h.vector.setArray(uh.array)
    # u_h.x.scatter_forward()
    # u_h.name = "u_{0:.2f}".format(theta)
    # import dolfinx.io as io
    # with io.XDMFFile(comm, "output/rotated_cube3D.xdmf", "w") as outfile:
    #     outfile.write_mesh(mesh)
    #     outfile.write_function(u_h, 0.0, f"Xdmf/Domain/Grid[@Name='{mesh.name}'][1]")

    # Solve the MPC problem using a global transformation matrix
    # and numpy solvers to get reference values
    dolfinx_mpc.utils.log_info(
        "Solving reference problem with global matrix (using numpy)")

    with Timer("~TEST: Assemble bilinear form (unconstrained)"):
        A_org = fem.petsc.assemble_matrix(bilinear_form, bcs)
        A_org.assemble()
        L_org = fem.petsc.assemble_vector(linear_form)
        fem.petsc.apply_lifting(L_org, [bilinear_form], [bcs])
        L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
                          mode=PETSc.ScatterMode.REVERSE)
        fem.petsc.set_bc(L_org, bcs)

    with Timer("~TEST: Compare"):
        dolfinx_mpc.utils.compare_mpc_lhs(A_org, A, mpc, root=root)
        dolfinx_mpc.utils.compare_mpc_rhs(L_org, b, mpc, root=root)

        # Gather LHS, RHS and solution on one process
        A_csr = dolfinx_mpc.utils.gather_PETScMatrix(A_org, root=root)
        K = dolfinx_mpc.utils.gather_transformation_matrix(mpc, root=root)
        L_np = dolfinx_mpc.utils.gather_PETScVector(L_org, root=root)
        u_mpc = dolfinx_mpc.utils.gather_PETScVector(uh, root=root)

        if MPI.COMM_WORLD.rank == root:
            KTAK = K.T * A_csr * K
            reduced_L = K.T @ L_np
            # Solve linear system
            d = scipy.sparse.linalg.spsolve(KTAK, reduced_L)
            # Back substitution to full solution vector
            uh_numpy = K @ d
            assert np.allclose(uh_numpy, u_mpc)

    list_timings(comm, [TimingType.wall])
예제 #29
0
    def assemble_coarse_operators(self, V0s):
        """
        Assembles the coarse operators from a list of local contributions to the coarse space.

        Parameters
        ==========

        V0s : list of local PETSc .vecs
           list of the coarse vectors contributed by the subdomain.

        Returns
        ==========

        V0 : list of local vectors or None ? FIX
            list of the local contributions to the coarse space numbered globally: V0[i] is either a scaled local vector from V0s or None if coarse vector number i belongs to another subdomain. The scaling that is applied to the coarse vectors ensures that their A-norm is 1.

        AV0 : list of global PETSc.Vecs
            list of the A*V0[i]. These are global vectors so not in the same format as the vectors in V0.

        Delta : PETSc.Mat (local)
            matrix of the coarse problem. As a result of the scaling of the coarse vectors, its diagonal is 1. This matrix is duplicated over all subdomains This matrix is duplicated over all subdomains

        ksp_Delta : PETSc.ksp
            Krylov subspace solver for the coarse problem matrix Delta.

        """
        if self.verbose:
            PETSc.Sys.Print(
                'Subdomain number {} contributes {} coarse vectors in total'.
                format(mpi.COMM_WORLD.rank, len(V0s)),
                comm=self.comm)

        V0 = []
        for i in range(mpi.COMM_WORLD.size):
            nrbl = len(V0s) if i == mpi.COMM_WORLD.rank else None
            nrbl = mpi.COMM_WORLD.bcast(nrbl, root=i)
            for irbm in range(nrbl):
                V0.append(V0s[irbm] if i == mpi.COMM_WORLD.rank else None)

        AV0 = []
        work, _ = self.work
        for vec in V0:
            if vec:
                self.works = vec.copy()
            else:
                self.works.set(0.)
            work.set(0)
            self.scatter_l2g(self.works, work, PETSc.InsertMode.ADD_VALUES)
            AV0.append(self.A * work)
            self.scatter_l2g(AV0[-1], self.works,
                             PETSc.InsertMode.INSERT_VALUES,
                             PETSc.ScatterMode.SCATTER_REVERSE)
            if vec:
                vec.scale(1. / np.sqrt(vec.dot(self.works)))
                self.works = vec.copy()
            else:
                self.works.set(0)
            work.set(0)
            self.scatter_l2g(self.works, work, PETSc.InsertMode.ADD_VALUES)
            AV0[-1] = self.A * work

        PETSc.Sys.Print('There are {} vectors in the coarse space.'.format(
            len(V0)),
                        comm=mpi.COMM_WORLD)

        #Define, fill and factorize coarse problem matrix
        Delta = PETSc.Mat().create(comm=PETSc.COMM_SELF)
        Delta.setType(PETSc.Mat.Type.SEQDENSE)
        Delta.setSizes([len(V0), len(V0)])
        Delta.setOption(PETSc.Mat.Option.SYMMETRIC, True)
        Delta.setPreallocationDense(None)
        for i, vec in enumerate(V0):
            if vec:
                self.works = vec.copy()
            else:
                self.works.set(0)

            work.set(0)
            self.scatter_l2g(self.works, work, PETSc.InsertMode.ADD_VALUES)
            for j in range(i + 1):
                tmp = AV0[j].dot(work)
                Delta[i, j] = tmp
                Delta[j, i] = tmp
        Delta.assemble()
        ksp_Delta = PETSc.KSP().create(comm=PETSc.COMM_SELF)
        ksp_Delta.setOperators(Delta)
        ksp_Delta.setType('preonly')
        pc = ksp_Delta.getPC()
        pc.setType('cholesky')
        return V0, AV0, Delta, ksp_Delta
예제 #30
0
    def monolithic_solve():
        """Monolithic (interleaved) solver"""
        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, p) = ufl.TrialFunctions(W)
        (v, q) = ufl.TestFunctions(W)
        a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
        a01 = ufl.inner(p, ufl.div(v)) * dx
        a10 = ufl.inner(ufl.div(u), q) * dx
        a = a00 + a01 + a10

        p00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
        p11 = ufl.inner(p, q) * dx
        p_form = p00 + p11

        f = Function(W.sub(0).collapse()[0])
        p_zero = Function(W.sub(1).collapse()[0])
        L0 = inner(f, v) * dx
        L1 = inner(p_zero, q) * dx
        L = L0 + L1

        a, p_form, L = form(a), form(p_form), form(L)

        bdofsW0_P2_0 = locate_dofs_topological(W.sub(0), facetdim,
                                               bndry_facets0)
        bdofsW0_P2_1 = locate_dofs_topological(W.sub(0), facetdim,
                                               bndry_facets1)

        bc0 = dirichletbc(bc_value, bdofsW0_P2_0, W.sub(0))
        bc1 = dirichletbc(bc_value, bdofsW0_P2_1, W.sub(0))

        A = assemble_matrix(a, bcs=[bc0, bc1])
        A.assemble()
        P = assemble_matrix(p_form, bcs=[bc0, bc1])
        P.assemble()

        b = assemble_vector(L)
        apply_lifting(b, [a], bcs=[[bc0, bc1]])
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        set_bc(b, [bc0, bc1])

        ksp = PETSc.KSP()
        ksp.create(mesh.comm)
        ksp.setOperators(A, P)
        ksp.setType("minres")
        pc = ksp.getPC()
        pc.setType('lu')

        def monitor(ksp, its, rnorm):
            # print("Num it, rnorm:", its, rnorm)
            pass

        ksp.setTolerances(rtol=1.0e-8, max_it=50)
        ksp.setMonitor(monitor)
        ksp.setFromOptions()
        x = A.createVecRight()
        ksp.solve(b, x)
        assert ksp.getConvergedReason() > 0
        return b.norm(), x.norm(), A.norm(), P.norm()