File: test_vector_scatter.py

package info (click to toggle)
fenics-dolfinx 1%3A0.10.0.post5-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,952 kB
  • sloc: cpp: 36,535; python: 25,391; makefile: 223; sh: 174; xml: 55
file content (114 lines) | stat: -rw-r--r-- 3,454 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
# Copyright (C) 2021 Chris Richardson and Igor Baratta
#
# This file is part of DOLFINx (https://www.fenicsproject.org)
#
# SPDX-License-Identifier:    LGPL-3.0-or-later
"""Unit tests for the KrylovSolver interface"""

from mpi4py import MPI

import numpy as np
import pytest

from basix.ufl import element
from dolfinx import default_real_type, la
from dolfinx.fem import Function, functionspace
from dolfinx.mesh import create_unit_square


@pytest.mark.parametrize(
    "e",
    [
        element("Lagrange", "triangle", 1, dtype=default_real_type),
        element("Lagrange", "triangle", 1, shape=(2,), dtype=default_real_type),
    ],
)
def test_scatter_forward(e):
    mesh = create_unit_square(MPI.COMM_WORLD, 5, 5)
    V = functionspace(mesh, e)
    u = Function(V)
    bs = V.dofmap.bs

    u.interpolate(lambda x: [x[i] for i in range(bs)])

    # Forward scatter should have no effect
    w0 = u.x.array.copy()
    u.x.scatter_forward()
    assert np.allclose(w0, u.x.array)

    # Fill local array with the mpi rank
    u.x.array.fill(MPI.COMM_WORLD.rank)
    w0 = u.x.array.copy()
    u.x.scatter_forward()

    # Now the ghosts should have the value of the rank of the owning
    # process
    ghost_owners = u.function_space.dofmap.index_map.owners
    ghost_owners = np.repeat(ghost_owners, bs)
    local_size = u.function_space.dofmap.index_map.size_local * bs
    assert np.allclose(u.x.array[local_size:], ghost_owners)


@pytest.mark.parametrize(
    "e",
    [
        element("Lagrange", "triangle", 1, dtype=default_real_type),
        element("Lagrange", "triangle", 1, shape=(2,), dtype=default_real_type),
    ],
)
def test_scatter_reverse(e):
    comm = MPI.COMM_WORLD
    mesh = create_unit_square(MPI.COMM_WORLD, 5, 5)
    V = functionspace(mesh, e)
    u = Function(V)
    bs = V.dofmap.bs

    u.interpolate(lambda x: [x[i] for i in range(bs)])

    # Reverse scatter (insert) should have no effect
    w0 = u.x.array.copy()
    u.x.scatter_reverse(la.InsertMode.insert)
    assert np.allclose(w0, u.x.array)

    # Fill with MPI rank, and sum all entries in the vector (including
    # ghosts)
    u.x.array.fill(comm.rank)
    all_count0 = MPI.COMM_WORLD.allreduce(u.x.array.sum(), op=MPI.SUM)

    # Reverse scatter (add)
    u.x.scatter_reverse(la.InsertMode.add)
    num_ghosts = V.dofmap.index_map.num_ghosts
    ghost_count = MPI.COMM_WORLD.allreduce(num_ghosts * comm.rank, op=MPI.SUM)

    # New count should have gone up by the number of ghosts times their
    # rank on all processes
    all_count1 = MPI.COMM_WORLD.allreduce(u.x.array.sum(), op=MPI.SUM)
    assert all_count1 == (all_count0 + bs * ghost_count)


@pytest.mark.parametrize(
    "dtype",
    [
        np.float32,
        np.float64,
        np.complex64,
        np.complex128,
        np.int8,
        np.int32,
        np.int64,
    ],
)
def test_vector_from_index_map_scatter_forward(dtype):
    comm = MPI.COMM_WORLD
    mesh = create_unit_square(comm, 5, 5)

    for d in range(mesh.topology.dim):
        mesh.topology.create_entities(d)
        im = mesh.topology.index_map(d)
        vector = la.vector(im, dtype=dtype)
        vector.array[: im.size_local] = np.arange(*im.local_range, dtype=dtype)
        vector.scatter_forward()
        global_idxs = im.local_to_global(np.arange(im.size_local + im.num_ghosts, dtype=np.int32))
        global_idxs = np.asarray(global_idxs, dtype)

        assert np.all(vector.array == global_idxs)