FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
gate_asm.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
9#include <kernel/lafem/dense_vector.hpp>
10#include <kernel/lafem/dense_vector_blocked.hpp>
11#include <kernel/lafem/vector_mirror.hpp>
12#include <kernel/global/gate.hpp>
13#include <kernel/assembly/mirror_assembler.hpp>
14
15#include <control/domain/domain_control.hpp>
16
17namespace FEAT
18{
19 namespace Control
20 {
21 namespace Asm
22 {
43 template<typename DomainLevel_, typename Space_, typename Gate_>
44 void asm_gate(const Domain::VirtualLevel<DomainLevel_>& virt_lvl,
45 const Space_& space, Gate_& gate, bool skip_empty_halos)
46 {
47 typedef typename Gate_::LocalVectorType VectorType;
48 typedef typename Gate_::MirrorType MirrorType;
49
50 const auto& dom_level = virt_lvl.level();
51 const auto& dom_layer = virt_lvl.layer();
52
53 // set the gate comm
54 gate.set_comm(dom_layer.comm_ptr());
55
56 // loop over all ranks
57 for(Index i(0); i < dom_layer.neighbor_count(); ++i)
58 {
59 int rank = dom_layer.neighbor_rank(i);
60
61 // try to find our halo
62 auto* halo = dom_level.find_halo_part(rank);
63 if(halo == nullptr)
64 {
65 if(skip_empty_halos)
66 continue;
67 XABORTM("empty halo for neighbor rank " + stringify(rank) + " detected");
68 }
69
70 // assemble the mirror
71 MirrorType mirror;
73
74 // push mirror into gate
75 if(!mirror.empty())
76 gate.push(rank, std::move(mirror));
77 }
78
79 // create local template vector
80 VectorType tmpl_s(space.get_num_dofs());
81
82 // compile gate
83 gate.compile(std::move(tmpl_s));
84 }
85
102 template<typename SysGate_, typename Gate0_, typename Gate1_>
103 void build_gate_tuple(SysGate_& gate_sys, const Gate0_& gate_0, const Gate1_& gate_1)
104 {
105 typedef typename SysGate_::LocalVectorType LocalSystemVectorType;
106 typedef typename SysGate_::MirrorType SystemMirrorType;
107
108 // set the communicator; this one must be identical for all gates
109 XASSERTM(gate_0.get_comm() == gate_1.get_comm(), "gates have incompatible communicators");
110 gate_sys.set_comm(gate_0.get_comm());
111
112 // collect all neighbor ranks; these may differ for each gate
113 std::set<int> neighbors;
114 const std::vector<int>& ranks_0 = gate_0.get_ranks();
115 const std::vector<int>& ranks_1 = gate_1.get_ranks();
116 for(auto r : ranks_0)
117 neighbors.insert(r);
118 for(auto r : ranks_1)
119 neighbors.insert(r);
120
121 // get the mirrors
122 const auto& mirrors_0 = gate_0.get_mirrors();
123 const auto& mirrors_1 = gate_1.get_mirrors();
124
125 // build a temporary vector from the gate frequency vectors
126 LocalSystemVectorType sys_loc;
127 sys_loc.template at<0>().clone(gate_0.get_freqs(), LAFEM::CloneMode::Layout);
128 sys_loc.template at<1>().clone(gate_1.get_freqs(), LAFEM::CloneMode::Layout);
129
130 // loop over all neighbor ranks
131 for(auto rank : neighbors)
132 {
133 // create a mirror with empty sub-mirrors of correct size first
134 SystemMirrorType sys_mir = SystemMirrorType::make_empty(sys_loc);
135 for(std::size_t i(0); i < ranks_0.size(); ++i)
136 {
137 if(ranks_0[i] == rank)
138 {
139 sys_mir.template at<0>().clone(mirrors_0[i], LAFEM::CloneMode::Shallow);
140 break;
141 }
142 }
143 for(std::size_t i(0); i < ranks_1.size(); ++i)
144 {
145 if(ranks_1[i] == rank)
146 {
147 sys_mir.template at<1>().clone(mirrors_1[i], LAFEM::CloneMode::Shallow);
148 break;
149 }
150 }
151 // sys_mir cannot be empty, since at least one of the above gates must have a mirror for this neighbor
152 XASSERTM(!sys_mir.empty(), "invalid empty mirror");
153 gate_sys.push(rank, std::move(sys_mir));
154 }
155
156 // compile the system gate
157 gate_sys.compile(std::move(sys_loc));
158 }
159
179 template<typename SysGate_, typename Gate0_, typename Gate1_, typename Gate2_>
180 void build_gate_tuple(SysGate_& gate_sys, const Gate0_& gate_0, const Gate1_& gate_1, const Gate2_& gate_2)
181 {
182 typedef typename SysGate_::LocalVectorType LocalSystemVectorType;
183 typedef typename SysGate_::MirrorType SystemMirrorType;
184
185 // set the communicator; this one must be identical for all gates
186 XASSERTM(gate_0.get_comm() == gate_1.get_comm(), "gates have incompatible communicators");
187 XASSERTM(gate_0.get_comm() == gate_2.get_comm(), "gates have incompatible communicators");
188 gate_sys.set_comm(gate_0.get_comm());
189
190 // collect all neighbor ranks; these may differ for each gate
191 std::set<int> neighbors;
192 const std::vector<int>& ranks_0 = gate_0.get_ranks();
193 const std::vector<int>& ranks_1 = gate_1.get_ranks();
194 const std::vector<int>& ranks_2 = gate_2.get_ranks();
195 for(auto r : ranks_0)
196 neighbors.insert(r);
197 for(auto r : ranks_1)
198 neighbors.insert(r);
199 for(auto r : ranks_2)
200 neighbors.insert(r);
201
202 // get the mirrors
203 const auto& mirrors_0 = gate_0.get_mirrors();
204 const auto& mirrors_1 = gate_1.get_mirrors();
205 const auto& mirrors_2 = gate_2.get_mirrors();
206
207 // build a temporary vector from the gate frequency vectors
208 LocalSystemVectorType sys_loc;
209 sys_loc.template at<0>().clone(gate_0.get_freqs(), LAFEM::CloneMode::Layout);
210 sys_loc.template at<1>().clone(gate_1.get_freqs(), LAFEM::CloneMode::Layout);
211 sys_loc.template at<2>().clone(gate_2.get_freqs(), LAFEM::CloneMode::Layout);
212
213 // loop over all neighbor ranks
214 for(auto rank : neighbors)
215 {
216 // create a mirror with empty sub-mirrors of correct size first
217 SystemMirrorType sys_mir = SystemMirrorType::make_empty(sys_loc);
218 for(std::size_t i(0); i < ranks_0.size(); ++i)
219 {
220 if(ranks_0[i] == rank)
221 {
222 sys_mir.template at<0>().clone(mirrors_0[i], LAFEM::CloneMode::Shallow);
223 break;
224 }
225 }
226 for(std::size_t i(0); i < ranks_1.size(); ++i)
227 {
228 if(ranks_1[i] == rank)
229 {
230 sys_mir.template at<1>().clone(mirrors_1[i], LAFEM::CloneMode::Shallow);
231 break;
232 }
233 }
234 for(std::size_t i(0); i < ranks_2.size(); ++i)
235 {
236 if(ranks_2[i] == rank)
237 {
238 sys_mir.template at<2>().clone(mirrors_2[i], LAFEM::CloneMode::Shallow);
239 break;
240 }
241 }
242 // sys_mir cannot be empty, since at least one of the above gates must have a mirror for this neighbor
243 XASSERTM(!sys_mir.empty(), "invalid empty mirror");
244 gate_sys.push(rank, std::move(sys_mir));
245 }
246
247 // compile the system gate
248 gate_sys.compile(std::move(sys_loc));
249 }
250 } // namespace Asm
251 } // namespace Control
252} // namespace FEAT
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
FEAT Kernel base header.
static void assemble_mirror(LAFEM::VectorMirror< DataType_, IndexType_ > &vec_mirror, const Space_ &space, const MeshPart_ &mesh_part)
Assembles a VectorMirror from a space and a mesh-part.
Virtual Domain Level class template.
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
std::uint64_t Index
Index data type.