File: mat.py

package info (click to toggle)
ngspetsc 0.1.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 27,120 kB
  • sloc: python: 3,391; makefile: 42; sh: 29
file content (146 lines) | stat: -rw-r--r-- 6,477 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
'''
This module contains all the functions related to wrapping NGSolve matrices to
PETSc matrices using the petsc4py interface.
'''
import numpy as np

from ngsolve import FESpace
from petsc4py import PETSc

class Matrix(object):
    '''
    This class creates a PETSc Matrix

    :arg ngsMat: the NGSolve matrix

    :arg freeDofs: free DOFs of the FE spaces used to construct the matrix

    :arg matType: type of PETSc matrix, i.e. PETSc sparse: aij,
    MKL sparse: aijmkl or CUDA: aijcusparse

    '''
    def __init__(self, ngsMat, parDescr, matType="aij", petscMat=None):
        if not isinstance(parDescr, (tuple, list)):
            samerc = True
            if isinstance(parDescr, FESpace):
                dofs = parDescr.ParallelDofs()
                self.freeDofs = (parDescr.FreeDofs(),parDescr.FreeDofs())
                comm = dofs.comm.mpi4py
            else:
                dofs, freeDofs, dofsInfo = parDescr
                self.freeDofs = (freeDofs,freeDofs)
                if dofs is not None:
                    comm = dofs.comm.mpi4py
                else:
                    ### create suitable dofs
                    comm = PETSc.COMM_SELF
                    dofs = type('', (object,), {'entrysize':dofsInfo["bsize"][0]})()
        else:
            samerc = False
            if isinstance(parDescr[0], FESpace) and isinstance(parDescr[1], FESpace):
                dofs = parDescr[0].ParallelDofs()
                self.freeDofs = (parDescr[0].FreeDofs(),parDescr[1].FreeDofs())
                comm = dofs.comm.mpi4py
            elif isinstance(parDescr[0], (tuple, list)):
                dofs = parDescr[0][0]
                self.freeDofs = (parDescr[0][1], parDescr[1][1])
                if dofs is not None:
                    comm = dofs.comm.mpi4py
                else:
                    ### create suitable dofs
                    comm = PETSc.COMM_SELF
            else:
                samerc = True
                dofs = parDescr[0]
                self.freeDofs = (parDescr[1], parDescr[1])
                if dofs is not None:
                    comm = dofs.comm.mpi4py
                else:
                    ### create suitable dofs
                    comm = PETSc.COMM_SELF

        localMat = ngsMat.local_mat
        entryHeight, entryWidth = localMat.entrysizes
        if entryHeight != entryWidth: raise RuntimeError ("Only square entries are allowed.")

        valMat, colMat, indMat = localMat.CSR()
        indMat = np.array(indMat).astype(PETSc.IntType)
        colMat = np.array(colMat).astype(PETSc.IntType)
        if entryHeight > 1:
            petscLocalMat = PETSc.Mat().createBAIJ(size=(entryHeight*localMat.height,
                                                         entryWidth*localMat.width),
                                                   bsize=entryHeight,
                                                   csr=(indMat,colMat,valMat),
                                                   comm=PETSc.COMM_SELF)
        else:
            petscLocalMat = PETSc.Mat().createAIJ(size=(localMat.height,
                                                        localMat.width),
                                                  csr=(indMat,colMat,valMat),
                                                  comm=PETSc.COMM_SELF)
        if self.freeDofs[0] is not None or self.freeDofs[1] is not None:
            rowIsFreeLocal = None
            if self.freeDofs[0] is not None:
                rowLocalMatFree = np.flatnonzero(self.freeDofs[0]).astype(PETSc.IntType)
                rowIsFreeLocal = PETSc.IS().createBlock(indices=rowLocalMatFree,
                                                        bsize=entryHeight,comm=PETSc.COMM_SELF)
            colIsFreeLocal = rowIsFreeLocal
            if self.freeDofs[1] is not None and not samerc:
                colLocalMatFree = np.flatnonzero(self.freeDofs[1]).astype(PETSc.IntType)
                colIsFreeLocal = PETSc.IS().createBlock(indices=colLocalMatFree,
                                                        bsize=entryHeight,comm=PETSc.COMM_SELF)
            petscLocalMat = petscLocalMat.createSubMatrices(rowIsFreeLocal, colIsFreeLocal)[0]

        if comm.Get_size() > 1:
            # is this a BUG in the bindings?
            #rparallelDofs = ngsMat.row_pardofs
            rparallelDofs = ngsMat.col_pardofs
            rglobalNums, rnumberGlobal = rparallelDofs.EnumerateGlobally(self.freeDofs[0])
            if self.freeDofs[0] is not None:
                rglobalNums = np.array(rglobalNums, dtype=PETSc.IntType)[self.freeDofs[0]]
            rlocalGlobalMap = PETSc.LGMap().create(indices=rglobalNums,
                                                   bsize=entryHeight,
                                                   comm=comm)
            if not samerc:
                # is this a BUG in the bindings?
                #cparallelDofs = ngsMat.col_pardofs
                cparallelDofs = ngsMat.row_pardofs
                cglobalNums, cnumberGlobal = cparallelDofs.EnumerateGlobally(self.freeDofs[1])
                if self.freeDofs[1] is not None:
                    cglobalNums = np.array(cglobalNums, dtype=PETSc.IntType)[self.freeDofs[1]]
                clocalGlobalMap = PETSc.LGMap().create(indices=cglobalNums,
                                                       bsize=entryWidth,
                                                       comm=comm)
            else:
                clocalGlobalMap = rlocalGlobalMap
                cnumberGlobal = rnumberGlobal

            mat = PETSc.Mat().create(comm=comm)
            mat.setSizes(size=(rnumberGlobal*entryHeight,
                            cnumberGlobal*entryHeight), bsize=entryHeight)
            mat.setType(PETSc.Mat.Type.IS)
            mat.setLGMap(rlocalGlobalMap, clocalGlobalMap)
            mat.setISLocalMat(petscLocalMat)
            mat.assemble()
            if matType != 'is':
                mat.convert(matType)
            if petscMat is None:
                self.mat = mat
            else:
                mat.copy(petscMat)
        else:
            mat = petscLocalMat
            mat.convert(matType)
            if matType != 'is':
                mat.convert(matType)

            if petscMat is None:
                self.mat = mat
            else:
                mat.copy(petscMat)

    def view(self):
        '''
        This function display PETSc Mat info

        '''
        self.mat.view()