class Mass(MuCallable): _ident_ = 'Mass' def __init__(self, n, basisname, *deps, scale=1): super().__init__((n, n), deps, scale=scale) self.basisname = basisname def write(self, group): super().write(group) util.to_dataset(self.basisname, group, 'basisname') def _read(self, group): super()._read(group) self.basisname = util.from_dataset(group['basisname']) def evaluate(self, case, mu, cont): geom = case['geometry'](mu) basis = case.basis(self.basisname, mu) itg = fn.outer(basis) if basis.ndim > 1: itg = itg.sum([-1]) itg = util.contract(itg, cont) with matrix.Scipy(): return unwrap(case.domain.integrate(itg * fn.J(geom), ischeme='gauss9'))
class NSDivergence(MuCallable): _ident_ = 'NSDivergence' def __init__(self, n, *deps, scale=1): super().__init__((n, n), deps, scale=scale) def evaluate(self, case, mu, cont): geom = case['geometry'](mu) vbasis = case.basis('v', mu) pbasis = case.basis('p', mu) itg = -fn.outer(vbasis.div(geom), pbasis) itg = util.contract(itg, cont) with matrix.Scipy(): return unwrap(case.domain.integrate(itg * fn.J(geom), ischeme='gauss9'))
def constrain(self, basisname, *boundaries, component=None): if isinstance(basisname, np.ndarray): return super().constrain(basisname) if all(isinstance(bnd, str) for bnd in boundaries): boundary = self.domain.boundary[','.join(boundaries)] else: boundary = boundaries[0] basis = self.bases[basisname].obj zero = np.zeros(self.shape(basisname)) if component is not None: basis = basis[...,component] zero = zero[...,component] with matrix.Scipy(): projected = boundary.project(zero, onto=basis, geometry=self.refgeom, ischeme='gauss2') super().constrain(projected)
def test_matrix_scipy(self): self._test_matrix(matrix.Scipy())
velocity = velocity[:npts] pressure = pressure[:npts] linbasis = case.domain.basis('spline', degree=1) vsol = linbasis.dot(velocity[:,0])[_] * (1,0) + linbasis.dot(velocity[:,1])[_] * (0,1) psol = linbasis.dot(pressure) geom = case.physical_geometry(param) vbasis = case.basis('v', param) vgrad = vbasis.grad(geom) pbasis = case.basis('p', param) lhs = case.domain.project(psol, onto=pbasis, geometry=geom, ischeme='gauss9') vind = case.basis_indices('v') itg = fn.outer(vbasis).sum([-1]) + fn.outer(vgrad).sum([-1,-2]) with matrix.Scipy(): mx = case.domain.integrate(itg * fn.J(geom), ischeme='gauss9').core[np.ix_(vind,vind)] itg = (vbasis * vsol[_,:]).sum([-1]) + (vgrad * vsol.grad(geom)[_,:,:]).sum([-1,-2]) rhs = case.domain.integrate(itg * fn.J(geom), ischeme='gauss9')[vind] lhs[vind] = matrix.ScipyMatrix(mx).solve(rhs) lift = case._lift(param) solutions.append((lhs - lift) * weight) solutions = np.array(solutions) supremizers = ens.make_ensemble( case, solvers.supremizer, scheme, weights=False, parallel=False, args=[solutions], ) return scheme, solutions, supremizers
def test_deprecated_context(self): with self.assertWarns(warnings.NutilsDeprecationWarning): with matrix.Scipy(): pass
s = pickle.dumps(self.matrix) mat = pickle.loads(s) self.assertIsInstance(mat, type(self.matrix)) numpy.testing.assert_equal(mat.export('dense'), self.exact) with self.subTest('cross-pickle'), matrix.Numpy(): mat = pickle.loads(s) self.assertIsInstance(mat, matrix.NumpyMatrix) numpy.testing.assert_equal(mat.export('dense'), self.exact) @ifsupported def test_diagonal(self): self.assertAllEqual(self.matrix.diagonal(), numpy.diag(self.exact)) solver('numpy', backend=matrix.Numpy(), args=[{}]) solver('scipy', backend=matrix.Scipy(), args=[{}, dict(solver='gmres', atol=1e-5, restart=100, precon='spilu'), dict(solver='gmres', atol=1e-5, precon='splu'), dict(solver='cg', atol=1e-5, precon='diag')] + [ dict(solver=s, atol=1e-5) for s in ('bicg', 'bicgstab', 'cg', 'cgs', 'lgmres', 'minres') ]) for threading in matrix.MKL.Threading.SEQUENTIAL, matrix.MKL.Threading.TBB: solver('mkl:{}'.format(threading.name.lower()), backend=matrix.MKL(threading=threading), args=[{}, dict(solver='fgmres', atol=1e-8), dict(solver='fgmres', atol=1e-8, precon='diag')])
def get_case(refine: int, degree: int): nel_up = int(10 * refine) nel_length = int(100 * refine) up_edges = [(0, 1), (3, 4), (6, 7), (0, 3), (1, 4), (2, 3), (5, 6)] length_edges = [(2, 5), (3, 6), (4, 7)] all_edges = [*up_edges, *length_edges] domain, refgeom = mesh.multipatch( patches=[[(0, 1), (3, 4)], [(3, 4), (6, 7)], [(2, 3), (5, 6)]], nelems={ **{e: nel_up for e in up_edges}, **{e: nel_length for e in length_edges} }, patchverts=[(-1, 0), (-1, 1), (0, -1), (0, 0), (0, 1), (1, -1), (1, 0), (1, 1)]) case = NutilsCase('Backward-facing step channel', domain, refgeom, refgeom) NU = 1 / case.parameters.add('viscosity', 20, 50) L = case.parameters.add('length', 9, 12, 10) H = case.parameters.add('height', 0.3, 2, 1) V = case.parameters.add('velocity', 0.5, 1.2, 1) vxbasis = domain.basis('spline', degree=degree) vybasis = domain.basis('spline', degree=degree) pbasis = domain.basis('spline', degree=degree - 1) vdofs = len(vxbasis) + len(vybasis) pdofs = len(pbasis) ndofs = vdofs + pdofs vxbasis, vybasis, pbasis = fn.chain([vxbasis, vybasis, pbasis]) vbasis = vxbasis[:, _] * (1, 0) + vybasis[:, _] * (0, 1) case.bases.add('v', vbasis, length=vdofs) case.bases.add('p', pbasis, length=pdofs) case['geometry'] = MuLambda( partial(geometry, L=L, H=H, refgeom=refgeom), (2, ), ('length', 'height'), ) case.constrain( 'v', 'patch0-bottom', 'patch0-top', 'patch0-left', 'patch1-top', 'patch2-bottom', 'patch2-left', ) case['divergence'] = ntl.NSDivergence(ndofs, 'length', 'height') case['convection'] = ntl.NSConvection(ndofs, 'length', 'height') case['laplacian'] = ntl.Laplacian(ndofs, 'v', 'length', 'height', scale=NU) case['v-h1s'] = ntl.Laplacian(ndofs, 'v', 'length', 'height') case['p-l2'] = ntl.Mass(ndofs, 'p', 'length', 'height') with matrix.Scipy(): __, y = refgeom profile = fn.max(0, y * (1 - y))[_] * (1, 0) case['lift'] = MuConstant(case.project_lift(profile, 'v'), scale=V) mu = case.parameter() lhs = solvers.stokes(case, mu) case['lift'] = MuConstant(case.solution_vector(lhs, mu, lift=True), scale=V) return case