def test_mixed_non_mixed_dat(self, backend, mdat, mmap, iterset): """Increment into a MixedDat from a non-mixed Dat.""" d = op2.Dat(iterset, np.ones(iterset.size)) kernel_inc = """void kernel_inc(double **d, double *x) { d[0][0] += x[0]; d[1][0] += x[0]; }""" op2.par_loop(op2.Kernel(kernel_inc, "kernel_inc"), iterset, mdat(op2.INC, mmap), d(op2.READ)) assert all(mdat[0].data == 1.0) and mdat[1].data == 4096.0
def test_direct_loop(self, backend, iterset): """Test a direct ParLoop on a subset""" indices = np.array([i for i in range(nelems) if not i % 2], dtype=np.int) ss = op2.Subset(iterset, indices) d = op2.Dat(iterset ** 1, data=None, dtype=np.uint32) k = op2.Kernel("void inc(unsigned int* v) { *v += 1; }", "inc") op2.par_loop(k, ss, d(op2.RW)) inds, = np.where(d.data) assert (inds == indices).all()
def test_ro_accessor(self, skip_greedy, iterset): """Read-only access to a Dat should force computation that writes to it.""" base._trace.clear() d = op2.Dat(iterset, numpy.zeros(iterset.total_size), dtype=numpy.float64) k = op2.Kernel('void k(double *x) { *x = 1.0; }', 'k') op2.par_loop(k, iterset, d(op2.WRITE)) assert all(d.data_ro == 1.0) assert len(base._trace._trace) == 0
def test_inner_mixed(self): s = op2.Set(1) n = op2.Dat(s, [3], np.float64) o = op2.Dat(s, [4], np.float64) md = op2.MixedDat([n, o]) n1 = op2.Dat(s, [4], np.float64) o1 = op2.Dat(s, [5], np.float64) md1 = op2.MixedDat([n1, o1]) ret = md.inner(md1) assert abs(ret - 32) < 1e-12 ret = md1.inner(md) assert abs(ret - 32) < 1e-12
def test_indirect_loop_with_direct_dat(self, iterset): """Test a indirect ParLoop on a subset""" indices = np.array([i for i in range(nelems) if not i % 2], dtype=np.int) ss = op2.Subset(iterset, indices) indset = op2.Set(2, "indset") map = op2.Map(iterset, indset, 1, [(1 if i % 2 else 0) for i in range(nelems)]) values = [2976579765] * nelems values[::2] = [i // 2 for i in range(nelems)][::2] dat1 = op2.Dat(iterset**1, data=values, dtype=np.uint32) dat2 = op2.Dat(indset**1, data=None, dtype=np.uint32) k = op2.Kernel("void inc(unsigned* s, unsigned int* d) { *d += *s;}", "inc") op2.par_loop(k, ss, dat1(op2.READ), dat2(op2.INC, map[0])) assert dat2.data[0] == sum(values[::2])
def __init__(self, x): """Build a `Vector` that wraps a :class:`pyop2.Dat` for Dolfin compatibilty. :arg x: an :class:`pyop2.Dat` to wrap or a :class:`Vector` to copy. This copies the underlying data in the :class:`pyop2.Dat`. """ if isinstance(x, Vector): self.dat = op2.Dat(x.dat) elif isinstance(x, op2.base.Dat): # ugh self.dat = x else: raise RuntimeError("Don't know how to build a Vector from a %r" % type(x))
def test_mixed_non_mixed_dat_itspace(self, mdat, mmap, iterset): """Increment into a MixedDat from a Dat using iteration spaces.""" d = op2.Dat(iterset, np.ones(iterset.size)) assembly = Incr(Symbol("d", ("j", )), Symbol("x", (0, ))) assembly = c_for("j", 2, assembly) kernel_code = FunDecl( "void", "kernel_inc", [Decl("double", c_sym("*d")), Decl("double", c_sym("*x"))], Block([assembly], open_scope=False)) op2.par_loop(op2.Kernel(kernel_code, "kernel_inc"), iterset, mdat(op2.INC, mmap[op2.i[0]]), d(op2.READ)) assert all(mdat[0].data == 1.0) and mdat[1].data == 4096.0
def get_boundary_nodes(mesh, key, V): _, sub_domain, method = key indices = dmplex.boundary_nodes(V, sub_domain, method) # We need a halo exchange to determine all bc nodes. # Should be improved by doing this on the DM topology once. d = op2.Dat(V.dof_dset.set, dtype=IntType) d.data_with_halos[indices] = 1 d.global_to_local_begin(op2.READ) d.global_to_local_end(op2.READ) indices, = numpy.where(d.data_ro_with_halos == 1) # cast, because numpy where returns an int64 return indices.astype(IntType)
def test_direct_complementary_subsets_with_indexing(self, backend, iterset): """Test direct par_loop over two complementary subsets""" even = np.arange(0, nelems, 2, dtype=np.int) odd = np.arange(1, nelems, 2, dtype=np.int) sseven = iterset(even) ssodd = iterset(odd) d = op2.Dat(iterset ** 1, data=None, dtype=np.uint32) k = op2.Kernel("void inc(unsigned int* v) { *v += 1; }", "inc") op2.par_loop(k, sseven, d(op2.RW)) op2.par_loop(k, ssodd, d(op2.RW)) assert (d.data == 1).all()
def test_2d_map(self): """Sum nodal values incident to a common edge.""" nedges = nelems - 1 nodes = op2.Set(nelems, "nodes") edges = op2.Set(nedges, "edges") node_vals = op2.Dat(nodes, np.arange(nelems, dtype=np.uint32), np.uint32, "node_vals") edge_vals = op2.Dat(edges, np.zeros(nedges, dtype=np.uint32), np.uint32, "edge_vals") e_map = np.array([(i, i + 1) for i in range(nedges)], dtype=np.uint32) edge2node = op2.Map(edges, nodes, 2, e_map, "edge2node") kernel_sum = """ static void sum(unsigned int *edge, unsigned int *nodes) { *edge = nodes[0] + nodes[1]; }""" op2.par_loop(op2.Kernel(kernel_sum, "sum"), edges, edge_vals(op2.WRITE), node_vals(op2.READ, edge2node)) expected = np.arange(1, nedges * 2 + 1, 2) assert all(expected == edge_vals.data)
def test_direct_complementary_subsets(self, backend, iterset): """Test direct par_loop over two complementary subsets""" even = np.array([i for i in range(nelems) if not i % 2], dtype=np.int) odd = np.array([i for i in range(nelems) if i % 2], dtype=np.int) sseven = op2.Subset(iterset, even) ssodd = op2.Subset(iterset, odd) d = op2.Dat(iterset ** 1, data=None, dtype=np.uint32) k = op2.Kernel("void inc(unsigned int* v) { *v += 1; }", "inc") op2.par_loop(k, sseven, d(op2.RW)) op2.par_loop(k, ssodd, d(op2.RW)) assert (d.data == 1).all()
def test_indirect_loop_empty(self, backend, iterset): """Test a indirect ParLoop on an empty""" ss = op2.Subset(iterset, []) indset = op2.Set(2, "indset") map = op2.Map(iterset, indset, 1, [(1 if i % 2 else 0) for i in range(nelems)]) d = op2.Dat(indset ** 1, data=None, dtype=np.uint32) k = op2.Kernel("void inc(unsigned int* v) { *v += 1;}", "inc") d.data[:] = 0 op2.par_loop(k, ss, d(op2.INC, map[0])) assert (d.data == 0).all()
def test_indirect_loop(self, backend, iterset): """Test a indirect ParLoop on a subset""" indices = np.array([i for i in range(nelems) if not i % 2], dtype=np.int) ss = op2.Subset(iterset, indices) indset = op2.Set(2, "indset") map = op2.Map(iterset, indset, 1, [(1 if i % 2 else 0) for i in range(nelems)]) d = op2.Dat(indset ** 1, data=None, dtype=np.uint32) k = op2.Kernel("void inc(unsigned int* v) { *v += 1;}", "inc") op2.par_loop(k, ss, d(op2.INC, map[0])) assert d.data[0] == nelems / 2
def test_vec_norm_changes(self, backend, skip_cuda, skip_opencl): s = op2.Set(1) d = op2.Dat(s) d.data[:] = 1 with d.vec_ro as v: assert np.allclose(v.norm(), 1.0) d.data[:] = 2 with d.vec_ro as v: assert np.allclose(v.norm(), 2.0)
def test_vec_norm_changes(self): s = op2.Set(1) d = op2.Dat(s) d.data[:] = 1 with d.vec_ro as v: assert np.allclose(v.norm(), 1.0) d.data[:] = 2 with d.vec_ro as v: assert np.allclose(v.norm(), 2.0)
def test_dat_save_and_load(self, tmpdir, d1, s, mdat): """The save method should dump Dat and MixedDat values to the file 'output', and the load method should read back those same values from the 'output' file. """ output = tmpdir.join('output').strpath d1.save(output) d2 = op2.Dat(s) d2.load(output) assert (d1.data_ro == d2.data_ro).all() mdat.save(output) mdat2 = op2.MixedDat([d1, d1]) mdat2.load(output) assert all(all(d.data_ro == d_.data_ro) for d, d_ in zip(mdat, mdat2))
def test_kernel_cplusplus(self, backend, delems): """Test that passing cpp=True to a Kernel works.""" y = op2.Dat(delems, dtype=np.float64) y.data[:] = -10.5 k = op2.Kernel(""" #include <cmath> void kernel(double *y) { *y = std::abs(*y); } """, "kernel", cpp=True) op2.par_loop(k, y.dataset.set, y(op2.RW)) assert (y.data == 10.5).all()
def test_matrix(self, backend): """Test a indirect par_loop with a matrix argument""" iterset = op2.Set(2) idset = op2.Set(2) ss01 = op2.Subset(iterset, [0, 1]) ss10 = op2.Subset(iterset, [1, 0]) indset = op2.Set(4) dat = op2.Dat(idset ** 1, data=[0, 1], dtype=np.float) map = op2.Map(iterset, indset, 4, [0, 1, 2, 3, 0, 1, 2, 3]) idmap = op2.Map(iterset, idset, 1, [0, 1]) sparsity = op2.Sparsity((indset, indset), (map, map)) mat = op2.Mat(sparsity, np.float64) mat01 = op2.Mat(sparsity, np.float64) mat10 = op2.Mat(sparsity, np.float64) assembly = c_for("i", 4, c_for("j", 4, Incr(Symbol("mat", ("i", "j")), FlatBlock("(*dat)*16+i*4+j")))) kernel_code = FunDecl("void", "unique_id", [Decl("double*", c_sym("dat")), Decl("double", Symbol("mat", (4, 4)))], Block([assembly], open_scope=False)) k = op2.Kernel(kernel_code, "unique_id") mat.zero() mat01.zero() mat10.zero() op2.par_loop(k, iterset, dat(op2.READ, idmap[0]), mat(op2.INC, (map[op2.i[0]], map[op2.i[1]]))) mat.assemble() op2.par_loop(k, ss01, dat(op2.READ, idmap[0]), mat01(op2.INC, (map[op2.i[0]], map[op2.i[1]]))) mat01.assemble() op2.par_loop(k, ss10, dat(op2.READ, idmap[0]), mat10(op2.INC, (map[op2.i[0]], map[op2.i[1]]))) mat10.assemble() assert (mat01.values == mat.values).all() assert (mat10.values == mat.values).all()
def read_triangle(f, layers=None): """Read the triangle file with prefix f into OP2 data strctures. Presently only .node and .ele files are read, attributes are ignored, and there may be bugs. The dat structures are returned as: (nodes, coords, elements, elem_node) These items have type: (Set, Dat, Set, Map) The Layers argument allows the reading of data for extruded meshes. It is to be used when dealing with extruded meshes. """ # Read nodes with open(f + '.node') as h: num_nodes = int(h.readline().split(' ')[0]) node_values = np.zeros((num_nodes, 2), dtype=np.float64) for line in h: if line[0] == '#': continue node, x, y = line.split()[:3] node_values[int(node) - 1, :] = [float(x), float(y)] nodes = op2.Set(num_nodes, "nodes") coords = op2.Dat(nodes ** 2, node_values, name="coords") # Read elements with open(f + '.ele') as h: num_tri, nodes_per_tri, num_attrs = [int(col) for col in h.readline().split()] map_values = np.zeros((num_tri, nodes_per_tri), dtype=np.int32) for line in h: if line[0] == '#': continue vals = [int(v) - 1 for v in line.split()] map_values[vals[0], :] = vals[1:nodes_per_tri + 1] if layers is not None: elements = op2.ExtrudedSet(op2.Set(num_tri, "elements"), layers=layers) else: elements = op2.Set(num_tri, "elements") elem_node = op2.Map(elements, nodes, nodes_per_tri, map_values, "elem_node") return nodes, coords, elements, elem_node
def test_change_const_data_doesnt_matter(self, backend, iterset, diterset): d = op2.Dat(diterset, range(nelems), numpy.uint32) self.cache.clear() assert len(self.cache) == 0 k = op2.Kernel("""void k(unsigned int *x) {}""", 'k') c = op2.Const(1, 1, name='c', dtype=numpy.uint32) op2.par_loop(k, iterset, d(op2.WRITE)) op2.base._trace.evaluate(set([d]), set()) assert len(self.cache) == 1 c.data = 2 op2.par_loop(k, iterset, d(op2.WRITE)) op2.base._trace.evaluate(set([d]), set()) assert len(self.cache) == 1 c.remove_from_namespace()
def testKernel(data=None, op2set=None, op2map=None): """ for testing purposes, it just prints out the data Dat array (assuming) it has dimension 3 in its Map (op2map). The kernel iterates over the Set op2set, if no arguments are passed in, this creates dummy values and prints them out """ if not op2set: op2set = op2.Set(5, 'fromset') if not op2map: op2toset = op2.Set(4, 'toset') npmapping = np.array([0, 1, 1, 2, 2, 3, 3, 1, 3, 2], np.uint32) print '-' * 80 print 'mapping: ', npmapping, npmapping.dtype, npmapping.shape op2map = op2.Map(op2set, op2toset, 2, npmapping, 'testmap') if not data: numpydata = np.array([[0, 1, 1], [1, 2, 2], [2, 3, 3], [3, 4, 4]], dtype=np.float64) print '-' * 80 print 'data:' print numpydata data = op2.Dat(op2toset ** 3, numpydata, np.float64, 'testdata') test = op2.Kernel(""" void test_kernel(double *x[3]) { std::cout << " " << x[0][0] << " " << x[0][1] << " " << x[0][2]; std::cout << " : " << x[1][0] << " " << x[1][1] << " " << x[1][2] << std::endl; } """, 'test_kernel') print '-' * 80 print 'PyOP2 output:' op2.par_loop(test, op2set, data(op2map, op2.READ)) print '-' * 80
def coords(dvnodes): coord_vals = np.asarray([(0.0, 0.0), (2.0, 0.0), (1.0, 1.0), (0.0, 1.5)], dtype=valuetype) return op2.Dat(dvnodes, coord_vals, valuetype, "coords")
def exterior_facet_boundary_node_map(self, V, method): """Return the :class:`pyop2.Map` from exterior facets to nodes on the boundary. :arg V: The function space. :arg method: The method for determining boundary nodes. See :class:`~.DirichletBC` for details. """ try: return self.map_caches["boundary_node"][method] except KeyError: pass el = V.finat_element dim = self.mesh.facet_dimension() if method == "topological": boundary_dofs = el.entity_closure_dofs()[dim] elif method == "geometric": # This function is only called on extruded meshes when # asking for the nodes that live on the "vertical" # exterior facets. boundary_dofs = entity_support_dofs(el, dim) nodes_per_facet = \ len(boundary_dofs[0]) # HACK ALERT # The facet set does not have a halo associated with it, since # we only construct halos for DoF sets. Fortunately, this # loop is direct and we already have all the correct # information available locally. So We fake a set of the # correct size and carry out a direct loop facet_set = op2.Set(self.mesh.exterior_facets.set.total_size, comm=self.mesh.comm) fs_dat = op2.Dat( facet_set**el.space_dimension(), data=V.exterior_facet_node_map().values_with_halo.view()) facet_dat = op2.Dat(facet_set**nodes_per_facet, dtype=IntType) # Ensure these come out in sorted order. local_facet_nodes = numpy.array( [boundary_dofs[e] for e in sorted(boundary_dofs.keys())]) # Helper function to turn the inner index of an array into c # array literals. c_array = lambda xs: "{" + ", ".join(map(str, xs)) + "}" # AST for: l_nodes[facet[0]][n] rank_ast = ast.Symbol("l_nodes", rank=(ast.Symbol("facet", rank=(0, )), "n")) body = ast.Block([ ast.Decl("int", ast.Symbol("l_nodes", (len(el.cell.topology[dim]), nodes_per_facet)), init=ast.ArrayInit( c_array(map(c_array, local_facet_nodes))), qualifiers=["const"]), ast.For( ast.Decl("int", "n", 0), ast.Less("n", nodes_per_facet), ast.Incr("n", 1), ast.Assign(ast.Symbol("facet_nodes", ("n", )), ast.Symbol("cell_nodes", (rank_ast, )))) ]) kernel = op2.Kernel( ast.FunDecl("void", "create_bc_node_map", [ ast.Decl("%s*" % as_cstr(fs_dat.dtype), "cell_nodes"), ast.Decl("%s*" % as_cstr(facet_dat.dtype), "facet_nodes"), ast.Decl("unsigned int*", "facet") ], body), "create_bc_node_map") local_facet_dat = op2.Dat( facet_set**self.mesh.exterior_facets._rank, self.mesh.exterior_facets.local_facet_dat.data_ro_with_halos, dtype=numpy.uintc) op2.par_loop(kernel, facet_set, fs_dat(op2.READ), facet_dat(op2.WRITE), local_facet_dat(op2.READ)) if self.extruded: offset = self.offset[boundary_dofs[0]] else: offset = None val = op2.Map(facet_set, self.node_set, nodes_per_facet, facet_dat.data_ro_with_halos, name="exterior_facet_boundary_node", offset=offset) self.map_caches["boundary_node"][method] = val return val
def mdat(mset): return op2.MixedDat(op2.Dat(s, rdata(s.size)) for s in mset)
def mvdat(mset): return op2.MixedDat(op2.Dat(s ** 2, list(zip(rdata(s.size), rdata(s.size)))) for s in mset)
def x_vec(dvnodes): x_vals = np.zeros(NUM_NODES * 2, dtype=valuetype) return op2.Dat(dvnodes, x_vals, valuetype, "x")
def x(dnodes): x_vals = np.zeros(NUM_NODES, dtype=valuetype) return op2.Dat(dnodes, x_vals, valuetype, "x")
def b_vec(dvnodes): b_vals = np.zeros(NUM_NODES * 2, dtype=valuetype) return op2.Dat(dvnodes, b_vals, valuetype, "b")
def b(dnodes): b_vals = np.zeros(NUM_NODES, dtype=valuetype) return op2.Dat(dnodes, b_vals, valuetype, "b")
def f_vec(dvnodes): f_vals = np.asarray([(1.0, 2.0)] * 4, dtype=valuetype) return op2.Dat(dvnodes, f_vals, valuetype, "f")