petsc4pylsys.py 2.95 KB
Newer Older
1
2
3
4
5
6
7
8
import petsc4py
import sys
petsc4py.init(sys.argv)
from petsc4py import PETSc
import numpy as np
from ._tools import timeit
from .csr import CSR

9
class LinearSystem:
10
11
12

    def __init__(self, elements, n_fields, options, constraints) :
        PETSc.Options().prefixPush("fluid_")
Jonathan Lambrechts's avatar
clean    
Jonathan Lambrechts committed
13
        PETSc.Options().insertString("-pc_type ilu -pc_factor_levels 5 -pc_factor_shift_type INBLOCKS -pc_factor_shift_amount 1e-16")
14
15
        PETSc.Options().insertString(options)
        PETSc.Options().prefixPop()
16
        self.block = PETSc.Options().getBool("fluid_block_matrix",False)
17
18
19
20
        self.ksp = PETSc.KSP().create()
        self.ksp.setOptionsPrefix(b"fluid_")
        self.ksp.setFromOptions()
        self.localsize = elements.shape[1]*n_fields
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
        if self.block:
            if len(constraints) != 0 :
                raise ValueError("petsc block matrices not implemented with constraints")
            nn = elements.shape[1]
            self.csr = CSR(elements,elements,[])
            self.mat = PETSc.Mat().createBAIJ(self.csr.size*n_fields, n_fields, csr=(self.csr.row, self.csr.col))
            self.idx = (elements[:,None,:]*n_fields+np.arange(n_fields)[None,:,None]).reshape([-1])
            self.n_fields = n_fields
            csrmapl = np.arange(n_fields*n_fields)[None,:].reshape(n_fields,n_fields)
            csrmap = (self.csr.map[0]*n_fields*n_fields)[:,None,None]+csrmapl[None,:,:]
            self.csrmap = np.swapaxes(csrmap.reshape([elements.shape[0],nn,n_fields,nn,n_fields]),2,3).reshape([-1])
        else:
            idx = ((elements*n_fields)[:,:,None]+np.arange(n_fields)[None,None,:]).reshape([elements.shape[0],-1])
            self.constraints = list(c[:,0]*n_fields + c[:,1] for c in constraints)
            idx2 = (elements[:,None,:]*n_fields+np.arange(n_fields)[None,:,None]).reshape([-1])
            self.csr = CSR(idx, idx2, self.constraints)
            self.val = np.zeros(self.csr.col.size)
            self.mat = PETSc.Mat().createAIJWithArrays(self.csr.size,(self.csr.row,self.csr.col,self.val))
39
40

    @timeit
41
42
43
44
45
46
47
48
49
50
51
52
    def local_to_global(self, localv, localm, u, constraints_value):
        if self.block:
            rhs = np.bincount(self.idx,localv,self.csr.size*self.n_fields)
            val = np.bincount(self.csrmap,localm,self.csr.col.size*self.n_fields**2)
            self.mat.zeroEntries()
            self.mat.setValuesBlockedCSR(self.csr.row, self.csr.col, val)
            self.mat.assemble()
            return rhs
        else:
            self.csr.assemble_mat(localm, constraints_value, self.val)
            self.mat.assemble()
            return self.csr.assemble_rhs(localv, u, constraints_value)
53
54
55
56
57
58
59
60

    @timeit
    def solve(self,rhs) :
        x = np.ndarray(rhs.shape)
        prhs = PETSc.Vec().createWithArray(rhs.reshape([-1]))
        px = PETSc.Vec().createWithArray(x.reshape([-1]))
        self.ksp.setOperators(self.mat)
        self.ksp.solve(prhs,px)
61
62
63
64
        if self.block:
            return x
        else:
            return x[:self.csr.ndof]