def _solve_(self, L, x, b): diag = L.takeDiagonal() maxdiag = max(numerix.absolute(diag)) L = L * (1 / maxdiag) b = b * (1 / maxdiag) LU = superlu.factorize(L.matrix.to_csr()) if DEBUG: import sys print(L.matrix, file=sys.stderr) error0 = numerix.sqrt(numerix.sum((L * x - b)**2)) for iteration in range(self.iterations): errorVector = L * x - b if (numerix.sqrt(numerix.sum(errorVector**2)) / error0) <= self.tolerance: break xError = numerix.zeros(len(b), 'd') LU.solve(errorVector, xError) x[:] = x - xError if 'FIPY_VERBOSE_SOLVER' in os.environ: from fipy.tools.debug import PRINT PRINT('iterations: %d / %d' % (iteration+1, self.iterations)) PRINT('residual:', numerix.sqrt(numerix.sum(errorVector**2)))
def _solve_(self, L, x, b): diag = L.takeDiagonal() maxdiag = max(numerix.absolute(diag)) L = L * (1 / maxdiag) b = b * (1 / maxdiag) LU = superlu.factorize(L.matrix.to_csr()) if DEBUG: import sys print >> sys.stderr, L.matrix error0 = numerix.sqrt(numerix.sum((L * x - b)**2)) for iteration in range(self.iterations): errorVector = L * x - b if (numerix.sqrt(numerix.sum(errorVector**2)) / error0) <= self.tolerance: break xError = numerix.zeros(len(b),'d') LU.solve(errorVector, xError) x[:] = x - xError if 'FIPY_VERBOSE_SOLVER' in os.environ: from fipy.tools.debug import PRINT PRINT('iterations: %d / %d' % (iteration+1, self.iterations)) PRINT('residual:', numerix.sqrt(numerix.sum(errorVector**2)))
def fea(self): """ Performs a Finite Element Analysis given the updated global stiffness matrix [K] and the load vector {r}, both of which must be in the modified state, i.e., [K] and {r} must represent the unconstrained system of equations. Return the global displacement vector {d} as a NumPy array. EXAMPLES: >>> t.fea() See also: set_top_params """ if not self.topydict: raise Exception('You must first load a TPD file!') if self.itercount >= MAX_ITERS: raise Exception('Maximum internal number of iterations exceeded!') Kfree = self._updateK(self.K.copy()) if self.dofpn < 3 and self.nelz == 0: # Direct solver Kfree = Kfree.to_csr() # Need CSR for SuperLU factorisation lu = superlu.factorize(Kfree) lu.solve(self.rfree, self.dfree) if self.probtype == 'mech': lu.solve(self.rfreeout, self.dfreeout) # mechanism synthesis else: # Iterative solver for 3D problems Kfree = Kfree.to_sss() preK = precon.ssor(Kfree) # Preconditioned Kfree (info, numitr, relerr) = itsolvers.pcg(Kfree, self.rfree, self.dfree, 1e-8, 8000, preK) if info < 0: logger.error('PySparse error: Type: {}, ' 'at {} iterations'.format(info, numitr)) raise Exception('Solution for FEA did not converge.') else: logger.debug('ToPy: Solution for FEA converged after ' '{} iterations'.format(numitr)) if self.probtype == 'mech': # mechanism synthesis (info, numitr, relerr) = itsolvers.pcg(Kfree, self.rfreeout, self.dfreeout, 1e-8, 8000, preK) if info < 0: logger.error('PySparse error: Type: {}, ' 'at {} iterations'.format(info, numitr)) raise Exception('Solution for FEA of adjoint load ' 'case did not converge.') # Update displacement vectors: self.d[self.freedof] = self.dfree if self.probtype == 'mech': # 'adjoint' vectors self.dout[self.freedof] = self.dfreeout # Increment internal iteration counter self.itercount += 1
def fea(self): """ Performs a Finite Element Analysis given the updated global stiffness matrix [K] and the load vector {r}, both of which must be in the modified state, i.e., [K] and {r} must represent the unconstrained system of equations. Return the global displacement vector {d} as a NumPy array. EXAMPLES: >>> t.fea() See also: set_top_params """ if not self.topydict: raise ToPyError('You must first load a TPD file!') if self.itercount >= MAX_ITERS: raise ToPyError('Maximum internal number of iterations exceeded!') Kfree = self._updateK(self.K.copy()) if self.dofpn < 3 and self.nelz == 0: # Direct solver Kfree = Kfree.to_csr() # Need CSR for SuperLU factorisation lu = superlu.factorize(Kfree) lu.solve(self.rfree, self.dfree) if self.probtype == 'mech': lu.solve(self.rfreeout, self.dfreeout) # mechanism synthesis else: # Iterative solver for 3D problems Kfree = Kfree.to_sss() preK = precon.ssor(Kfree) # Preconditioned Kfree (info, numitr, relerr) = \ itsolvers.pcg(Kfree, self.rfree, self.dfree, 1e-8, 8000, preK) if info < 0: print 'PySparse error: Type:', info,', at', numitr, \ 'iterations.' raise ToPyError('Solution for FEA did not converge.') else: print 'ToPy: Solution for FEA converged after', numitr, \ 'iterations.' if self.probtype == 'mech': # mechanism synthesis (info, numitr, relerr) = \ itsolvers.pcg(Kfree, self.rfreeout, self.dfreeout, 1e-8, \ 8000, preK) if info < 0: print 'PySparse error: Type:', info,', at', numitr, \ 'iterations.' raise ToPyError('Solution for FEA of adjoint load case \ did not converge.') # Update displacement vectors: self.d[self.freedof] = self.dfree if self.probtype == 'mech': # 'adjoint' vectors self.dout[self.freedof] = self.dfreeout # Increment internal iteration counter self.itercount += 1
def __init__(self, A, **kwargs): PysparseDirectSolver.__init__(self, A, **kwargs) self.type = numpy.float self.nrow, self.ncol = A.getShape() t = cputime() self.LU = superlu.factorize(A.matrix.to_csr(), **kwargs) self.factorizationTime = cputime() - t self.solutionTime = 0.0 self.sol = None self.L = self.U = None return
def testTrivial(self): luA = superlu.factorize(self.A) luA.solve(self.b, self.x) self.failUnless(residual(self.A, self.x, self.b) == 0.0) luA = superlu.factorize(self.A, diag_pivot_thresh=0.0) luA.solve(self.b, self.x) self.failUnless(residual(self.A, self.x, self.b) == 0.0) luA = superlu.factorize(self.A, relax=20) luA.solve(self.b, self.x) self.failUnless(residual(self.A, self.x, self.b) == 0.0) luA = superlu.factorize(self.A, panel_size=1) luA.solve(self.b, self.x) self.failUnless(residual(self.A, self.x, self.b) == 0.0) for permc_spec in [0, 1, 2, 3]: luA = superlu.factorize(self.A, permc_spec=permc_spec) luA.solve(self.b, self.x) self.failUnless(residual(self.A, self.x, self.b) == 0.0)
def staticSolver(self): self.solution = np.zeros((self.dofcount, ), dtype=float) forces = self.nodalforces if SOLVER == 'default': spooles = solver.Spooles(self.GK) self.solution[:] = forces spooles.solve(self.solution) elif SOLVER == 'pysparse': mat = self.GK.to_csr() LU = superlu.factorize(mat, permc_spec=2, diag_pivot_thresh=0.) LU.solve(forces, self.solution) else: raise FEError('unknown solver')
def staticSolver(self): self.solution = np.zeros((self.dofcount,), dtype=float) forces = self.nodalforces if SOLVER == 'default': spooles = solver.Spooles(self.GK) self.solution[:] = forces spooles.solve(self.solution) elif SOLVER == 'pysparse': mat = self.GK.to_csr() LU = superlu.factorize(mat, permc_spec=2, diag_pivot_thresh=0.) LU.solve(forces, self.solution) else: raise FEError('unknown solver')
def _solve_(self, L, x, b): diag = L.takeDiagonal() maxdiag = max(numerix.absolute(diag)) L = L * (1 / maxdiag) b = b * (1 / maxdiag) LU = superlu.factorize(L._getMatrix().to_csr()) error0 = numerix.sqrt(numerix.sum((L * x - b)**2)) for iteration in range(self.iterations): errorVector = L * x - b if (numerix.sqrt(numerix.sum(errorVector**2)) / error0) <= self.tolerance: break xError = numerix.zeros(len(b),'d') LU.solve(errorVector, xError) x[:] = x - xError
def staticSolver(self, solver_arg): self.solution = np.zeros((self.dofcount,), dtype=float) forces = self.nodalforces if solver_arg == 'default': spooles = solver.Spooles(self.GK) self.solution[:] = forces spooles.solve(self.solution) elif solver_arg == 'pysparse': print 'solver used: ', solver_arg mat = self.GK.to_csr() LU = superlu.factorize(mat, permc_spec=2, diag_pivot_thresh=0.) LU.solve(forces, self.solution) elif solver_arg == 'sparse': print 'solver used: ', solver_arg mat = self.GK LU = linalg.splu(mat, permc_spec='MMD_AT_PLUS_A', diag_pivot_thresh=0) self.solution = LU.solve(forces) else: raise FEError('unknown solver')
def PoissonSolveFem(xmax,nelx,no,bval,dens): bdcon=array([1,1,1,1,1,1]) # these bc's to for non zero Dirichlet tx=linspace(0.0,1.0,nelx+1) # nodes quadratically scaled around origin! t2=tx**2 tm=(-t2).tolist() tm.reverse() t=array(tm[:-1]+t2.tolist()) print t x=y=z=t*xmax print x print y print z box=fem3d(x,y,z,no,bdcon) def v(xx,yy,zz): val=0.0 return val def w(xx,yy,zz): return 1.0 def IsOnBoundary(x,y,z): # this function returns True if (x,y,z) is on the Boundary if (abs(x) == xmax or abs(y) ==xmax or abs(z) == xmax): val= True else: val= False return val def bval1(x,y,z): # returns phi (x,y,z) for (x,y,z) on the boundary # but otherwise zero if IsOnBoundary(x,y,z): return bval(x,y,z) else: return 0.0 box.calc_mat(v,w) nodes=box.gn # K=box.All # Matrix representing negative Laplace operator U=box.Mll # Overlap matrix between basis functions N0=K.shape[0] # Order of matrix including boundary DOF # rho is density at points of FEM grid rho=array([dens(x,y,z) for (x,y,z) in nodes]) # mask is needed for pysparse mask=array([1-IsOnBoundary(x,y,z) for (x,y,z) in nodes]) bcv=array([bval1(x,y,z) for (x,y,z) in nodes]) K0bcv=empty(N0) # convert K to sparse skyline format K0=K.to_sss() # calculate ( K_{01}+K_{11}) c_1 K0.matvec(bcv,K0bcv) # modify matrix K to implement Boundary Condition # all rows and columns corresponding to boundary nodes are deleted from the matrix K.delete_rowcols(mask) N1=K.shape[0] # Order of matrix without boundary dof's print K.shape # create new list of global nodes as newnodes=array([nodes[i] for i in range(N0) if mask[i] ==1 ]) # create indices for new nodes in old nodes ii=zeros(N1,"i") j=0 for i in range(N0): if mask[i] == 1: ii[j]=i j=j+1 # convert K to compressed sparse row format K1=K.to_csr() # convert U to sparse skyline format M=U.to_sss() b=empty(N0) # calculate U rho on whole domain including boundary M.matvec(rho,b) b=b-K0bcv # project on interior space yielding RHS of (8) b1=array([ b[i] for i in range(N0) if mask[i] == 1 ]) pot=empty(N1) t0=time() # calculate LU factorization using the superlu module from pysparse LU=superlu.factorize(K1) t1=time() print "time taken for factorization of K1:", t1-t0 t0=time() LU.solve(b1,pot) t1=time() print "time taken to solve Laplace equation using LU Decomposition :", t1-t0 pot0=empty(N0) # the following code fills the vector pot0 with the boundary values # of the potential at the corresponding positions for i in range(N0): if mask[i] ==0: x,y,z=nodes[i] pot0[i]=bval(x,y,z) pot0[ii]=pot # making use of the interpolation functionality provided by fem3d # define a function that returns the values at of the resulting potential # at the points defined by (xi[k],yi[k],zi[k]) def potf(xi,yi,zi): return box.wave(xi,yi,zi,pot0) # the following lines define xi,yi,zi along a line with constant y and z-values # from -xmax to xmax xi=linspace(-xmax,xmax,1001) yi=zi=zeros(1001,"i") poti=potf(xi,yi,zi) #open file to write potential values to pfile=open("pot_direct_xmax=%f_nel=%d_no=%d.dat" % (xmax,2*nelx,no), "w") print >> pfile, "# N0=",N0, "N1=",N1 for x,p in zip(xi,poti): print >> pfile, x,p,p-exactpot(x,0,0) pfile.close()
def testPoisson1dMMD_AplusA(self): luA = superlu.factorize(self.B, permc_spec=2) luA.solve(self.b, self.x) print error(self.x, self.x_exact), self.tol, luA.nnz self.failUnless(error(self.x, self.x_exact) < self.tol)
def __init__(self, A, n11): n = A.shape[0] self.n11 = n11 self.lu11 = superlu.factorize(A[:n11,:n11].to_csr(), diag_pivot_thresh=0) self.K22 = precon.ssor(A[n11:,n11:].to_sss()) self.shape = (n, n)
def testPoisson2dCOLAMD(self): luA = superlu.factorize(self.B, permc_spec=3) luA.solve(self.b, self.x) print error(self.x, self.x_exact), self.tol, luA.nnz self.failUnless(error(self.x, self.x_exact) < self.tol)
def testPoisson1dDefault(self): luA = superlu.factorize(self.B) luA.solve(self.b, self.x) print error(self.x, self.x_exact), self.tol, luA.nnz self.failUnless(error(self.x, self.x_exact) < self.tol)
def analyze(vxg, loads, boundary, iter): """ main analysis function - vxg: voxel grid (3d list) - loads: each consisting of * points [point set #1, point set #2 ...] * value [value #1, value #2, ...] - boundary * points - iter: whether to use iterative or direct solver (points are element numbers) output: - displacement vector - von Mises stress vector """ global Ke, B, C nz = len(vxg) ny = len(vxg[0]) nx = len(vxg[0][0]) _log('voxelization') print('voxel grid: ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz)) # compute stiffness matrix for individual elements DOF = 3 ksize = DOF * (nx + 1) * (ny + 1) * (nz + 1) kall = spmatrix.ll_mat_sym(ksize, ksize) SOLID = 1.000 VOID = 0.001 for i in range(0, nz): for j in range(0, ny): for k in range(0, nx): xe = SOLID if vxg[i][j][k] == 1 else VOID nodes = _node_nums_3d(nx, ny, nz, k + 1, j + 1, i + 1) ind = [] for n in nodes: ind.extend([(n - 1) * DOF, (n - 1) * DOF + 1, (n - 1) * DOF + 2]) mask = np.ones(len(ind), dtype=int) kall.update_add_mask_sym(Ke * xe, ind, mask) _log('updated stiffness matrix for all elements') # formulate loading scenario rall = [0] * ksize indicesset = loads['points'] values = loads['values'] for i in range(0, len(indicesset)): indices = indicesset[i] value = values[i] for idx in indices: nodes = _node_nums_3d(nx, ny, nz, idx[0] + 1, idx[1] + 1, idx[2] + 1) for j in range(0, DOF): for k in range(0, len(nodes)): rall[DOF * (nodes[k] - 1) + j] = value[j] # formulate boundary condition elemmask = [1] * (nx + 1) * (ny + 1) * (nz + 1) for idx in boundary: nodes = _node_nums_3d(nx, ny, nz, idx[0] + 1, idx[1] + 1, idx[2] + 1) for j in range(0, len(nodes)): elemmask[nodes[j] - 1] = 0 freedofs = [] fixeddofs = [] for i in range(0, len(elemmask)): if elemmask[i] == 1: freedofs.extend((DOF * i, DOF * i + 1, DOF * i + 2)) else: fixeddofs.extend((DOF * i, DOF * i + 1, DOF * i + 2)) _log('formulated loading scenario and boundary condition') # solve KU=F rfree = np.take(rall, freedofs) dfree = np.empty(len(freedofs)) alldofs = np.arange(ksize) rcfixed = np.where(np.in1d(alldofs, fixeddofs), 0, 1) kfree = kall kfree.delete_rowcols(rcfixed) _log('removed constrained elements') if iter: kfree = kfree.to_sss() prek = precon.ssor(kfree) (info, numitr, relerr) = itsolvers.pcg(kfree, rfree, dfree, 1e-8, 8000, prek) if info >= 0: print('converged after ' + str(numitr) + ' iterations with error of ' + str(relerr)) else: print('PySparse error: Type:' + info + ', at' + str(numitr) + 'iterations.') else: kfree = kfree.to_csr() lu = superlu.factorize(kfree) lu.solve(rfree, dfree) _log('solved KU=F') dall = np.zeros_like(rall) for i in range(0, len(freedofs)): dall[freedofs[i]] = dfree[i] # compute stress cb = C * B vonmises = [] for i in range(0, nz): vmplane = [] for j in range(0, ny): vmrow = [] for k in range(0, nx): nodes = _node_nums_3d(nx, ny, nz, k + 1, j + 1, i + 1) disps = [] for n in nodes: disps.extend([ dall[DOF * (n - 1)], dall[DOF * (n - 1) + 1], dall[DOF * (n - 1) + 2] ]) d = np.matrix(disps).transpose() sigma = cb * d s11 = sigma.item(0, 0) s22 = sigma.item(1, 0) s33 = sigma.item(2, 0) s12 = sigma.item(3, 0) * 0.5 # DOUBLE CHECK THIS s23 = sigma.item(4, 0) * 0.5 s31 = sigma.item(5, 0) * 0.5 # von Mises stress, cf. Strava et al.'s Stress Relief paper (SIGGRAPH '12) vmrow.append( sqrt(0.5 * ((s11 - s22)**2 + (s22 - s33)**2 + (s33 - s11)**2 + 6 * (s12**2 + s23**2 + s31**2)))) vmplane.append(vmrow) vonmises.append(vmplane) t1 = _log('computed stress') global t0 print('total time:' + str(t1 - t0) + ' ms') return {'displacements': dall.tolist(), 'stress': vonmises}
def testPoisson1dNoPivot(self): luA = superlu.factorize(self.B, diag_pivot_thresh=0.0) luA.solve(self.b, self.x) print error(self.x, self.x_exact), self.tol, luA.nnz self.failUnless(error(self.x, self.x_exact) < self.tol)
def testPoisson1dOrigOrdering(self): luA = superlu.factorize(self.B, permc_spec=0) luA.solve(self.b, self.x) print error(self.x, self.x_exact), self.tol, luA.nnz self.failUnless(error(self.x, self.x_exact) < self.tol)
def testPoisson1dSmallPanel(self): luA = superlu.factorize(self.B, panel_size=1) luA.solve(self.b, self.x) print error(self.x, self.x_exact), self.tol, luA.nnz self.failUnless(error(self.x, self.x_exact) < self.tol)
def testPoisson1dRelax(self): luA = superlu.factorize(self.B, relax=20) luA.solve(self.b, self.x) print error(self.x, self.x_exact), self.tol, luA.nnz self.failUnless(error(self.x, self.x_exact) < self.tol)