File: fn_mesh.hpp

package info (click to toggle)
gridtools 2.3.9-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 29,480 kB
  • sloc: cpp: 228,792; python: 17,561; javascript: 9,164; ansic: 4,101; sh: 850; makefile: 231; f90: 201
file content (131 lines) | stat: -rw-r--r-- 5,227 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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * GridTools
 *
 * Copyright (c) 2014-2023, ETH Zurich
 * All rights reserved.
 *
 * Please, refer to the LICENSE file in the root directory.
 * SPDX-License-Identifier: BSD-3-Clause
 */
#pragma once

#include <cassert>

#include <gridtools/storage/builder.hpp>
#include <type_traits>

namespace gridtools {

    struct v2e {};
    struct e2v {};

    template <class StorageTraits, class FloatType>
    class structured_unstructured_mesh {
        int m_nx, m_ny, m_nz;

        constexpr auto v2e_initializer() const {
            return [nx = m_nx, ny = m_ny](int const vertex, int const neighbor) {
                assert(vertex >= 0 && vertex < nx * ny);
                int const nxedges = (nx - 1) * ny;
                int const nyedges = nx * (ny - 1);
                int const i = vertex % nx;
                int const j = vertex / nx;
                int n = 0;
                if (i > 0 && neighbor == n++)
                    return (i - 1) + (nx - 1) * j;
                if (i < nx - 1 && neighbor == n++)
                    return i + (nx - 1) * j;
                if (j > 0 && neighbor == n++)
                    return nxedges + i + nx * (j - 1);
                if (j < ny - 1 && neighbor == n++)
                    return nxedges + i + nx * j;
                if (i < nx - 1 && j > 0 && neighbor == n++)
                    return nxedges + nyedges + i + (nx - 1) * (j - 1);
                if (i > 0 && j < ny - 1 && neighbor == n++)
                    return nxedges + nyedges + (i - 1) + (nx - 1) * j;
                return -1;
            };
        }

        constexpr auto e2v_initializer() const {
            return [nx = m_nx, ny = m_ny](int edge, int const neighbor) {
                int const nxedges = (nx - 1) * ny;
                int const nyedges = nx * (ny - 1);
                [[maybe_unused]] int const nxyedges = (nx - 1) * (ny - 1);
                assert(edge >= 0 && edge < nxedges + nyedges + nxyedges);
                if (edge < nxedges) {
                    int i = edge % (nx - 1);
                    int j = edge / (nx - 1);
                    return neighbor == 0 ? i + nx * j : i + 1 + nx * j;
                }
                edge -= nxedges;
                if (edge < nyedges) {
                    int i = edge % nx;
                    int j = edge / nx;
                    return neighbor == 0 ? i + nx * j : i + nx * (j + 1);
                }
                edge -= nyedges;
                assert(edge < nxyedges);
                int i = edge % (nx - 1);
                int j = edge / (nx - 1);
                return neighbor == 0 ? i + 1 + nx * j : i + nx * (j + 1);
            };
        }

      public:
        using max_v2e_neighbors_t = std::integral_constant<int, 6>;
        using max_e2v_neighbors_t = std::integral_constant<int, 2>;
        using float_t = FloatType;

        constexpr structured_unstructured_mesh(int nx, int ny, int nz) : m_nx(nx), m_ny(ny), m_nz(nz) {}

        constexpr int nvertices() const { return m_nx * m_ny; }
        constexpr int nedges() const {
            int nxedges = (m_nx - 1) * m_ny;
            int nyedges = m_nx * (m_ny - 1);
            int nxyedges = (m_nx - 1) * (m_ny - 1);
            return nxedges + nyedges + nxyedges;
        }
        constexpr int nlevels() const { return m_nz; }

        template <class T = FloatType,
            int Id = -1,
            class Init,
            class... Dims,
            std::enable_if_t<!(std::is_integral_v<Init> || is_integral_constant<Init>::value), int> = 0>
        auto make_storage(Init const &init, Dims... dims) const {
            auto builder = storage::builder<StorageTraits>.dimensions(dims...).template type<T>().initializer(init);
            if constexpr (Id == -1)
                return builder.unknown_id().build();
            else
                return builder.template id<Id>().build();
            // disable incorrect warning "missing return statement at end of non-void function"
            GT_NVCC_DIAG_PUSH_SUPPRESS(940)
        }
        GT_NVCC_DIAG_POP_SUPPRESS(940)

        template <class T = FloatType,
            int Id = -1,
            class... Dims,
            std::enable_if_t<std::conjunction_v<std::bool_constant<std::is_integral<Dims>::value ||
                                                                   is_integral_constant<Dims>::value>...>,
                int> = 0>
        auto make_storage(Dims... dims) const {
            return make_storage<T, Id>([](int...) { return T(); }, dims...);
        }

        template <class T = FloatType, int Id = -1, class... Args>
        auto make_const_storage(Args &&...args) const {
            return make_storage<T const, Id>(std::forward<Args>(args)...);
        }

        auto v2e_table() const {
            return storage::builder<StorageTraits>.dimensions(nvertices(), max_v2e_neighbors_t()).template type<int const>().initializer(v2e_initializer()).unknown_id().build();
        }

        auto e2v_table() const {
            return storage::builder<StorageTraits>.dimensions(nedges(), max_e2v_neighbors_t()).template type<int const>().initializer(e2v_initializer()).unknown_id().build();
        }
    };

} // namespace gridtools