Repository navigation
Expand file tree
/
Copy pathbem_fma.h
More file actions
461 lines (348 loc) · 14.8 KB
/
Copy pathbem_fma.h
File metadata and controls
461 lines (348 loc) · 14.8 KB
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
// ---------------------------------------------------------------------
//
// Copyright (C) 2014 - 2019 by the pi-BEM authors.
//
// This file is part of the pi-BEM library.
//
// The BEMStokes is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License version 2.1 as published by the Free Software Foundation.
// The full text of the license can be found in the file LICENSE at
// the top level of the BEMStokes distribution.
//
// Authors: Nicola Giuliani, Andrea Mola, Luca Heltai
//
// ---------------------------------------------------------------------
/// This class contains all the methods
/// of the Fast Multipole Algorithm
/// applied to the Boundary Element
/// Method
#ifndef bem_fma_h
#define bem_fma_h
#include <deal.II/base/std_cxx11/bind.h>
#include <deal.II/base/types.h>
#include <deal.II/base/work_stream.h>
#include <deal.II/lac/trilinos_block_sparse_matrix.h>
#include <deal.II/lac/trilinos_precondition.h>
#include <deal.II/lac/trilinos_sparse_matrix.h>
#include <deal.II/lac/trilinos_vector.h>
#include <deal2lkit/parameter_acceptor.h>
#include <deal2lkit/utilities.h>
#include <mpi.h>
#include <cmath>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include "../include/ass_leg_function.h"
#include "../include/computational_domain.h"
#include "../include/local_expansion.h"
#include "../include/multipole_expansion.h"
#include "../include/octree_block.h"
namespace Operator
{
template <int dim>
class MinBEMOperator;
}
using namespace dealii;
using namespace deal2lkit;
/**
* A class for the handling of the Fast Multiple Method coupled with the Bundary
Element Method.
* It is derived from ParameterAcceptor to have a common interface with parameter
files. In
* particular this class performs the matrix vector products approximating long
range interactions
* via Multipole and Local Expansions that are contained in dedicated classes.
*/
template <int dim> //, Type V>
class BEMFMA : public deal2lkit::ParameterAcceptor
{
public:
/// Function to be used in the tests, it can access everything inside bemfma
// template<int fdim>
// friend void test(Operator::MinBEMOperator<fdim> &);
/// Class that implements a minimal operator
friend class Operator::MinBEMOperator<dim>;
template <int gdim>
friend void
test(BEMFMA<gdim> &);
/// Just renaming the cell iterator type
typedef typename DoFHandler<dim - 1, dim>::active_cell_iterator cell_it;
/// Contructor: needs only a MPI communicator
/// to be consistent with the other classes of
/// the problem.
BEMFMA(MPI_Comm mpi_commy = MPI_COMM_WORLD);
/// Destructor: does not need anything. It frees all
/// the block pointer in the octree lists.
~BEMFMA();
/// Initialization function. It sets up the DoFHandler, FiniteElement,
/// Mapping in the BEMFMA class. It also sets up some useful vector for,
/// mixed boundary conditions and double nodes handling.
void
init_fma(const DoFHandler<dim - 1, dim> & input_dh,
const std::vector<std::set<types::global_dof_index>> &db_in,
const TrilinosWrappers::MPI::Vector & input_sn,
const Mapping<dim - 1, dim> & input_mapping =
StaticMappingQ1<dim - 1, dim>::mapping,
unsigned int quad_order = 4,
unsigned int sing_quad_order = 5);
/// Parameters declaration: we take the number of octree level and
/// the level of approximation of the Kernels
virtual void
declare_parameters(ParameterHandler &prm);
/// Parameter parsing from input file
virtual void
parse_parameters(ParameterHandler &prm);
/// Method computing the parts of the
/// BEM system matrices in which the
/// integrals have to be performed
/// directly. It also sets up the preconditioner. We
/// don't consider any constraints in this function.
/// We have set up the function to work with two levels
/// of parallelism, TBB and MPI. We build up the direct
/// contribution for all those block that doesn't satisfy
/// the accuracy bounds for multipole (and consequently)
/// local expansions.
void
direct_integrals();
/// Method computing the multipole
/// expansion containing the integrals
/// values for each bottom level block.
/// It is called once for each
/// GMRES solved. This function set up
/// the structure to build the actual
/// multipoles associated with quadrature
/// points. For this reason it has to be called just once.
void
multipole_integrals();
/// [TODO] TO BE MOVED INSIDE multipole_matr_vect_products and made private
/// Ascending phase of the FMA method.
/// Multipole expansions are genarated
/// at the bottom level blocks, and then
/// translated to their parent blocks up
/// to the highest level. It is
/// called once per matrix-vector multiplication. We need to
/// ensure that the proper structure as been set through the
/// function multipole_integral(). We have chosen to use only
/// one level of parallelism inside this function: multithreading with TBB.
void
generate_multipole_expansions(
const TrilinosWrappers::MPI::Vector &phi_values,
const TrilinosWrappers::MPI::Vector &dphi_dn_values) const;
/// Descending phase of the FMA method. Local
/// Expansions are obtained for each block
/// starting from the top level and down
/// to the bottom ones, where they are used
/// to approximete the values of the
/// integrals, i.e. the BEM matrix-vector
/// product values.
/// This function is called once per every matrix-vector product.
/// We need to call this function after having generating the multipole
/// expansions. Since this function takes a considerable amount of time we
/// have chosen to parallelise it using multithreaded TBB on a single node and
/// MPI to allow even a greater level of parallelism. In this case we don't
/// need any communication because we have made sure that the multipole
/// expansions are replicated on each node. Thus we can safely split the
/// descending phase.
void
multipole_matr_vect_products(
const TrilinosWrappers::MPI::Vector &phi_values,
const TrilinosWrappers::MPI::Vector &dphi_dn_values,
TrilinosWrappers::MPI::Vector & matrVectProdN,
TrilinosWrappers::MPI::Vector & matrVectProdD) const;
// void compute_m2l_flags();
/// this methods creates the adaptive
/// octree partitioning of the domain,
/// needed by the FMA algorithm.
/// Since it takes a very small relative amount of time, and it is
/// called just once in our program we have chosen not to parallelise it.
void
generate_octree_blocking();
// In this function we have grouped some geometrical computation that
// are useful for setting up the octree blocking. For example the maps
// containing the surrounding elements for each element, or the component
// associated with each vectorial degree of freedom.
void
compute_geometry_cache();
/// Method for the assembling of the
/// sparse preconitioning matrix for FMA.
/// In this function we actually build up the final preconditioner taking
/// great care of all the constraints, through a constraint matrix, we need to
/// impose on our system. We need the vector alpha to properly build up the
/// band of the BEM system we are going to invert (with ILU in this case).
/// This function takes a lot of time to properly compute the preconditioner
/// sparsity pattern and fill it. For this very reason we have taken great
/// care in providing a double parallelisation strategy. Firstly we split
/// among different nodes the computations with MPI and then we use TBB to
/// ensure a parallelisation between different threads on multicore
/// architectures.
TrilinosWrappers::PreconditionILU &
FMA_preconditioner(const TrilinosWrappers::MPI::Vector &alpha,
AffineConstraints<double> & c);
protected:
/// Three pointers to the problem parameters to be set equal to
/// the ones in the calling problem through the init function
SmartPointer<const DoFHandler<dim - 1, dim>> fma_dh;
SmartPointer<const Mapping<dim - 1, dim>> fma_mapping;
/// Truncation order for the multipole
/// and local expansion series: it is
/// read from the parameters input file.
unsigned int trunc_order;
/// Sparsity pattern for the
/// initial preconditioning matrix
/// (no constraints applied)
TrilinosWrappers::SparsityPattern init_prec_sparsity_pattern;
/// Sparsity pattern for the
/// final preconditioning matrix
/// (constraints applied)
TrilinosWrappers::SparsityPattern final_prec_sparsity_pattern;
/// Sparse Neumann matrix containing
/// only direct integrals contributions
TrilinosWrappers::SparseMatrix prec_neumann_matrix;
// SparseMatrix<double> prec_neumann_matrix;
/// Sparse Dirichlet matrix containing
/// only direct integrals contributions
TrilinosWrappers::SparseMatrix prec_dirichlet_matrix;
// SparseMatrix<double> prec_dirichlet_matrix;
/// Initial sparse preconditioning matrix (without constraints)
TrilinosWrappers::SparseMatrix init_preconditioner;
/// Final sparse preconditioning matrix (with constraints)
TrilinosWrappers::SparseMatrix final_preconditioner;
/// Structures where the Dirichlet
/// matrix multipole
/// integrals are stored: for each cell
/// there are as many multipole
/// expansions as the lowest level
/// blocks in which element's quad
/// points lie.
mutable std::map<types::global_dof_index,
std::map<cell_it, std::vector<MultipoleExpansion>>>
elemMultipoleExpansionsKer1;
/// Structures where the Neumann
/// matrix multipole
/// integrals are stored: for each cell
/// there are as many multipole
/// expansions as the lowest level
/// blocks in which element's quad
/// points lie.
mutable std::map<types::global_dof_index,
std::map<cell_it, std::vector<MultipoleExpansion>>>
elemMultipoleExpansionsKer2;
/// Vector storing the Dirichlet
/// integrals multipole expansions
/// for each block
mutable std::vector<MultipoleExpansion> blockMultipoleExpansionsKer1;
/// Vector storing the Neumann
/// integrals multipole expansions
/// for each block
mutable std::vector<MultipoleExpansion> blockMultipoleExpansionsKer2;
/// Vector storing the Dirichlet
/// integrals local expansions
/// for each block
mutable std::vector<LocalExpansion> blockLocalExpansionsKer1;
/// Vector storing the Neumann
/// integrals local expansions
/// for each block
mutable std::vector<LocalExpansion> blockLocalExpansionsKer2;
/// Associated Legendre functions class
AssLegFunction assLegFunction;
/// the preconditioner to be passed to bem_problem
/// contributi diretti del multipolo, assembla la parte
/// diretta in una vera matrice.
TrilinosWrappers::PreconditionILU preconditioner;
unsigned int quadrature_order;
unsigned int singular_quadrature_order;
/// mpi related variables
MPI_Comm mpi_communicator;
unsigned int n_mpi_processes;
unsigned int this_mpi_process;
/// maximum number of collocation points
/// that can be contained by a childless block:
/// if a block contains less nodes than this number
/// it is not further refined
unsigned int max_num_nodes_per_block;
/// number of levels of the octree
/// partitioning
unsigned int num_octree_levels;
/// Granularity for TBB cycles. Simple parallel_for at the moment.
unsigned int tbb_granularity;
/// here are declared dome structures which
/// will be created in the framework of the
/// octree partitioning of the mesh, and
/// will be used in the FMA
/// a map associating each DoF with the cells
/// it belongs to
std::map<types::global_dof_index, std::vector<cell_it>> dof_to_elems;
/// a map associating each gradient DoF
/// with the cells it belongs to
std::map<types::global_dof_index, std::vector<cell_it>> gradient_dof_to_elems;
/// a vector associating each gradient DoF
/// with the component it represents
std::vector<unsigned int> gradient_dof_components;
/// a map associating each DoF to the
/// block it belongs to
/// for each level
std::map<types::global_dof_index, std::vector<types::global_dof_index>>
dof_to_block;
/// a map associating each quad point to the
/// block it belongs to for
/// each level
std::map<cell_it, std::vector<std::vector<types::global_dof_index>>>
quad_point_to_block;
/// a map associating each cell with a std::set
/// containing the surrounding
/// cells
std::map<cell_it, std::set<cell_it>> elem_to_surr_elems;
/// a vector to store all OctreeBlocks
/// in which the geometry is divided
mutable std::vector<OctreeBlock<dim> *> blocks;
/// the total blocks number
types::global_dof_index num_blocks;
/// the indices in the blocks vector, at which
/// each of the levels start or end
std::vector<types::global_dof_index> endLevel;
std::vector<types::global_dof_index> startLevel;
/// a list of the indices of all the childless
/// blocks
std::vector<types::global_dof_index> childlessList;
/// a list of the number of parent blocks
/// for each level
std::vector<types::global_dof_index> numParent;
/// a std::vector containing the list of
/// parent blocks for each level
std::vector<std::vector<types::global_dof_index>> parentList;
/// a std::map of std::vectors containing the
/// list of quadrature points
std::map<cell_it, std::vector<Point<dim>>> quadPoints;
/// a std::map of std::vectors containing the
/// list of normals at quadrature points
// std::map <cell_it, std::vector <Point <dim> > > quadNormals;
std::map<cell_it, std::vector<Tensor<1, dim>>> quadNormals;
/// a std::map of std::vectors containing the
/// list of shape function values at
/// quadrature points
std::map<cell_it, std::vector<std::vector<double>>> quadShapeFunValues;
/// a std::map of std::vectors containing the
/// list of JxW values at
/// quadrature points
std::map<cell_it, std::vector<double>> quadJxW;
/// a std::vector containing std::vectors with
/// the IDs of blocks with at least one dof,
/// for each level
std::vector<std::vector<types::global_dof_index>> dofs_filled_blocks;
/// a std::vector containing std::vectors with
/// the IDs of blocks with at least one
/// quad point, for each level
std::vector<std::vector<types::global_dof_index>> quad_points_filled_blocks;
ConditionalOStream pcout;
/// TODO parsed quadrature?
shared_ptr<Quadrature<dim - 1>> quadrature;
SmartPointer<const Vector<double>> dirichlet_nodes;
/// This should be erased by the usage of the constraint matrix.
const std::vector<std::set<types::global_dof_index>> *double_nodes_set;
std::vector<std::vector<types::global_dof_index>> m2l_flags;
IndexSet this_cpu_set;
};
#endif