MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
filter.h
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#ifndef FILTER_H_
8#define FILTER_H_
9
10#include <cmath>
12#include "INCLUDE/maiatypes.h"
13#include "IO/context.h"
14#include "UTIL/debug.h"
15
17
18namespace maia {
19namespace filter {
20
21namespace slope {
22
23namespace detail_ {
24
26template <typename T, typename F>
27T f2way(const T a, const T b, const T c, const T d, const T x, F&& f) {
28 if(x < c) {
29 return f(a, b, x);
30 } else {
31 return 1.0 - f(c, d, x);
32 }
33}
34
36template <MInt nDim, typename T, typename F>
37T fbox(const T* const boxmin, const T* const boxmax, const T width, const T* const x, F&& f) {
38 T r = 0.0;
39 for(MInt i = 0; i < nDim; i++) {
40 if(boxmin[i] - x[i] > 0.0) {
41 r += (boxmin[i] - x[i]) * (boxmin[i] - x[i]);
42 } else if(x[i] - boxmax[i] > 0.0) {
43 r += (x[i] - boxmax[i]) * (x[i] - boxmax[i]);
44 }
45 }
46 return 1.0 - f(0.0, width, std::sqrt(r));
47}
48
50template <MInt nDim, typename T, typename F>
51T fmultibox(const T* const boxmin, const T* const boxmax, const T* const width, const T* const x, F&& f) {
52 T filter = 1.0;
53 for(MInt i = 0; i < nDim; i++) {
54 filter *= f2way(boxmin[i] - width[2 * i], boxmin[i], boxmax[i], boxmax[i] + width[2 * i + 1], x[i], f);
55 }
56 return filter;
57}
58
60template <MInt nDim, typename T, typename F>
61T fsphere(const T* const center, const T radius, const T width, const T* const x, F&& f) {
62 T r = 0.0;
63 for(MInt i = 0; i < nDim; i++) {
64 r += (x[i] - center[i]) * (x[i] - center[i]);
65 }
66 return 1.0 - f(0.0, width, std::sqrt(r) - radius);
67}
68
69} // namespace detail_
70
82template <typename T>
83T linear(const T a, const T b, const T x) {
84 if(x < a) {
85 return 0.0;
86 } else if(x > b) {
87 return 1.0;
88 } else {
89 return (x - a) / (b - a);
90 }
91}
92
93template <typename T>
94T linear2way(const T a, const T b, const T c, const T d, const T x) {
95 return detail_::f2way(a, b, c, d, x, &linear<T>);
96}
97
98template <MInt nDim, typename T>
99T linearbox(const T* const boxmin, const T* const boxmax, const T width, const T* const x) {
100 return detail_::fbox<nDim>(boxmin, boxmax, width, x, &linear<T>);
101}
102
103template <MInt nDim, typename T>
104T linearmultibox(const T* const boxmin, const T* const boxmax, const T* const width, const T* const x) {
105 return detail_::fmultibox<nDim>(boxmin, boxmax, width, x, &linear<T>);
106}
107
108template <MInt nDim, typename T>
109T linearsphere(const T* const center, const T radius, const T width, const T* const x) {
110 return detail_::fsphere<nDim>(center, radius, width, x, &linear<T>);
111}
112
124template <typename T>
125T cos(const T a, const T b, const T x) {
126 if(x < a) {
127 return 0.0;
128 } else if(x > b) {
129 return 1.0;
130 } else {
131 return 0.5 * std::cos(PI / (b - a) * (x - b)) + 0.5;
132 }
133}
134
135template <typename T>
136T cos2way(const T a, const T b, const T c, const T d, const T x) {
137 return detail_::f2way(a, b, c, d, x, &cos<T>);
138}
139
140template <MInt nDim, typename T>
141T cosbox(const T* const boxmin, const T* const boxmax, const T width, const T* const x) {
142 return detail_::fbox<nDim>(boxmin, boxmax, width, x, &cos<T>);
143}
144
145template <MInt nDim, typename T>
146T cosmultibox(const T* const boxmin, const T* const boxmax, const T* const width, const T* const x) {
147 return detail_::fmultibox<nDim>(boxmin, boxmax, width, x, &cos<T>);
148}
149
150template <MInt nDim, typename T>
151T cossphere(const T* const center, const T radius, const T width, const T* const x) {
152 return detail_::fsphere<nDim>(center, radius, width, x, &cos<T>);
153}
154
155template <MInt nDim, typename T>
156T coscylinderzaxis(const T* const center, const T radius, const T width, const T* const x) {
157 return detail_::fsphere<nDim>(center, radius, width, x, &cos<T>);
158}
159
160} // namespace slope
161
162} // namespace filter
163} // namespace maia
164
165
170template <MInt nDim>
171class Filter {
172 public:
173 Filter(const MInt solverId) : m_solverId(solverId) {}
174 void init();
175
176 MFloat filter(const MFloat* const point) const;
177 void filter(const MFloat* const points, const MInt count, MFloat* const values);
178 MString name() const;
179
180 private:
181 // Solver id for property calls
182 const MInt m_solverId = -1;
183
184 // Enumaration of possible filter and slope combinations
186
187 // Filter identificication
189 // Minimum coordinates for box-shaped filter
190 std::array<MFloat, nDim> m_filterRegionMin{};
191 // Maximum coordinates for box-shaped filter
192 std::array<MFloat, nDim> m_filterRegionMax{};
193 // Center point for sphere-shaped filter
194 std::array<MFloat, nDim> m_filterCenter{};
195 // Radius for sphere-shaped filter
197 // Width of slope at the edge of the source term
199 // Width of slope at the edge of the source term (multibox version)
200 std::array<MFloat, 2 * nDim> m_filterSlopeWidthMultiBox{};
201 // Check for Initialization by init() method
203};
204
205
212template <MInt nDim>
213void Filter<nDim>::init() {
214 // sets the shape of the filter
215 MString filterShape;
216 // sets the calculating function of the slope
217 MString filterSlopeType;
218
219 // Map to compare input filtertype with implemented filters
220 std::map<MString, FilterType> filterMap;
221
222 // Define filterlist
223 // Note: if you add a new filter, do not forget to also adapt the switch
224 // statements in filter() and name()
225 filterMap["cossphere"] = FilterType::cossphere;
226 filterMap["linearsphere"] = FilterType::linearsphere;
227 filterMap["coscylinderzaxis"] = FilterType::coscylinderzaxis;
228 filterMap["cosbox"] = FilterType::cosbox;
229 filterMap["linearbox"] = FilterType::linearbox;
230 filterMap["cosmultibox"] = FilterType::cosmultibox;
231 filterMap["linearmultibox"] = FilterType::linearmultibox;
232
247 filterShape = Context::getSolverProperty<MString>("filterShape", m_solverId, AT_);
248
261 filterSlopeType = Context::getSolverProperty<MString>("filterSlopeType", m_solverId, AT_);
262
263 // Check if filter type exists and sets the filter id. If the filter type
264 // does not exists it throws an error
265 auto search = filterMap.find(filterSlopeType + filterShape);
266 if(search != filterMap.end()) {
267 m_filterId = filterMap[filterSlopeType + filterShape];
268 } else {
269 TERMM(1, "Unknown filter type! Please check your property file.");
270 }
271
272 // Width of filter slope
273 if(filterShape == "multibox") {
274 for(MInt i = 0; i < 2 * nDim; i++) {
275 m_filterSlopeWidthMultiBox[i] = Context::getSolverProperty<MFloat>("filterSlopeWidth", m_solverId, AT_, i);
276 }
277 } else {
278 m_filterSlopeWidth = Context::getSolverProperty<MFloat>("filterSlopeWidth", m_solverId, AT_);
279 }
280
281 // read filter specific properties
282 if(filterShape == "sphere" || filterShape == "cylinderzaxis") {
283 // read properties of sphere filter
284 for(MInt i = 0; i < nDim; i++) {
285 // /*! \page propertyPage1
286 // \section filterCenter
287 // <code>MFloat DgCcApeSourceFiles::m_filterCenter </code>\n
288 // default = <code>none</code>\n \n
289 // The centor of the sphere that specifies the source term
290 // region.\n
291 // Keywords: <i>COUPLING, SOURCE_TERM, FILTER</i>
292 // */
293 m_filterCenter[i] = Context::getSolverProperty<MFloat>("filterCenter", m_solverId, AT_, i);
294 }
295 // /*! \page propertyPage1
296 // \section filterRadius
297 // <code>MFloat DgCcApeSourceFiles::m_filterRadius </code>\n
298 // default = <code>none</code>\n \n
299 // The radius of the sphere that specifies the source term
300 // region.\n
301 // Keywords: <i>COUPLING, SOURCE_TERM, FILTER</i>
302 // */
303 m_filterRadius = Context::getSolverProperty<MFloat>("filterRadius", m_solverId, AT_);
304 } else {
305 // read properties of box filter
306 for(MInt i = 0; i < nDim; i++) {
307 // /*! \page propertyPage1
308 // \section filterRegionMin
309 // <code>MFloat DgCcApeSourceFiles::m_filterRegionMin </code>\n
310 // default = <code>none</code>\n \n
311 // The coordinates of the lower left corner of the source term
312 // region.\n
313 // Keywords: <i>COUPLING, SOURCE_TERM, FILTER</i>
314 // */
315 m_filterRegionMin[i] = Context::getSolverProperty<MFloat>("filterRegionMin", m_solverId, AT_, i);
316
317 // /*! \page propertyPage1
318 // \section filterRegionMax
319 // <code>MFloat DgCcApeSourceFiles::m_filterRegionMax</code>\n
320 // default = <code>none</code>\n \n
321 // The coordinates of the upper right corner of the source term
322 // region.\n
323 // Keywords: <i>COUPLING, SOURCE_TERM, FILTER</i>
324 // */
325 m_filterRegionMax[i] = Context::getSolverProperty<MFloat>("filterRegionMax", m_solverId, AT_, i);
326 }
327 }
328
329 // Initialization is done!
330 m_isInitialized = true;
331}
332
333
338template <MInt nDim>
339MFloat Filter<nDim>::filter(const MFloat* const coordinates) const {
340 // Check for correkt initialization of the filter object
341 if(!m_isInitialized) {
342 TERMM(1, "Filter Object was not initialized correctly!");
343 }
344
345 // selection of the type of filter
346 switch(m_filterId) {
347 // cosphere
348 case FilterType::cossphere:
349 // calculate filter value and return it
350 return maia::filter::slope::cossphere<nDim>(&m_filterCenter[0], m_filterRadius, m_filterSlopeWidth, coordinates);
351
352 // linearsphere
353 case FilterType::linearsphere:
354 TERMM(1, "linearsphere type of filter has not been tested yet!");
355
356 // calculate filter value and return it
357 return maia::filter::slope::linearsphere<nDim>(&m_filterCenter[0], m_filterRadius, m_filterSlopeWidth,
358 coordinates);
359 // coscylinderzaxis
360 case FilterType::coscylinderzaxis:
361 // calculate filter value and return it
362 // Simply uses sphere filter
363 return maia::filter::slope::cossphere<2>(&m_filterCenter[0], m_filterRadius, m_filterSlopeWidth, coordinates);
364
365 // cosbox
366 case FilterType::cosbox:
367 TERMM(1, "Cosbox type of filter has not been tested yet!");
368
369 // calculate filter value and return it
370 return maia::filter::slope::cosbox<nDim>(&m_filterRegionMin[0], &m_filterRegionMax[0], m_filterSlopeWidth,
371 coordinates);
372
373 // linearbox
374 case FilterType::linearbox:
375 TERMM(1, "linearbox type of filter has not been tested yet!");
376
377 // calculate filter value and return it
378 return maia::filter::slope::linearbox<nDim>(&m_filterRegionMin[0], &m_filterRegionMax[0], m_filterSlopeWidth,
379 coordinates);
380
381 // cosmultibox
382 case FilterType::cosmultibox:
383 // calculate filter value and return it
384 return maia::filter::slope::cosmultibox<nDim>(&m_filterRegionMin[0], &m_filterRegionMax[0],
385 &m_filterSlopeWidthMultiBox[0], coordinates);
386
387 // linearmultibox
388 case FilterType::linearmultibox:
389
390 // calculate filter value and return it
391 return maia::filter::slope::linearmultibox<nDim>(&m_filterRegionMin[0], &m_filterRegionMax[0],
392 &m_filterSlopeWidthMultiBox[0], coordinates);
393
394 default:
395 TERMM(1, "Unknown filter type! Please check your property file.");
396 break;
397 }
398}
399
400
406template <MInt nDim>
407void Filter<nDim>::filter(const MFloat* const coordinates, const MInt count, MFloat* const values) {
408 // Check for correct initialization of the filter object
409 if(!m_isInitialized) {
410 TERMM(1, "Filter Object was not initialized correctly!");
411 }
412
413 // selection of the type of filter
414 switch(m_filterId) {
415 // cosphere
416 case FilterType::cossphere:
417 // calculate all filter values for each point
418 for(MInt j = 0; j < count; j++) {
419 values[j] = maia::filter::slope::cossphere<nDim>(&m_filterCenter[0], m_filterRadius, m_filterSlopeWidth,
420 coordinates + j * nDim);
421 }
422 break;
423
424 // linearsphere
425 case FilterType::linearsphere:
426 TERMM(1, "linearsphere type of filter has not been tested yet!");
427
428 // calculate all filter values for each point
429 for(MInt j = 0; j < count; j++) {
430 values[j] = maia::filter::slope::linearsphere<nDim>(&m_filterCenter[0], m_filterRadius, m_filterSlopeWidth,
431 coordinates + j * nDim);
432 }
433 break;
434
435 case FilterType::coscylinderzaxis:
436 // calculate all filter values for each point
437 for(MInt j = 0; j < count; j++) {
438 values[j] = maia::filter::slope::cossphere<2>(&m_filterCenter[0], m_filterRadius, m_filterSlopeWidth,
439 coordinates + j * nDim);
440 }
441 break;
442
443 // cosbox
444 case FilterType::cosbox:
445 TERMM(1, "Cosbox type of filter has not been tested yet!");
446
447 // calculate all filter values for each point
448 for(MInt j = 0; j < count; j++) {
449 values[j] = maia::filter::slope::cosbox<nDim>(&m_filterRegionMin[0], &m_filterRegionMax[0], m_filterSlopeWidth,
450 coordinates + j * nDim);
451 }
452 break;
453 // linearbox
454 case FilterType::linearbox:
455 TERMM(1, "linearbox type of filter has not been tested yet!");
456
457 // calculate all filter values for each point
458 for(MInt j = 0; j < count; j++) {
459 values[j] = maia::filter::slope::linearbox<nDim>(&m_filterRegionMin[0], &m_filterRegionMax[0],
460 m_filterSlopeWidth, coordinates + j * nDim);
461 }
462 break;
463
464 // cosmultibox
465 case FilterType::cosmultibox:
466 // calculate all filter values for each point
467 for(MInt j = 0; j < count; j++) {
468 values[j] = maia::filter::slope::cosmultibox<nDim>(&m_filterRegionMin[0], &m_filterRegionMax[0],
469 &m_filterSlopeWidthMultiBox[0], coordinates + j * nDim);
470 }
471 break;
472 // linearmultibox
473 case FilterType::linearmultibox:
474
475 // calculate all filter values for each point
476 for(MInt j = 0; j < count; j++) {
477 values[j] = maia::filter::slope::linearmultibox<nDim>(&m_filterRegionMin[0], &m_filterRegionMax[0],
478 &m_filterSlopeWidthMultiBox[0], coordinates + j * nDim);
479 }
480 break;
481
482 default:
483 TERMM(1, "Unknown filter type! Please check your property file.");
484 break;
485 }
486}
487
488
495template <MInt nDim>
497 TRACE();
498
499 MString filterName;
500 switch(m_filterId) {
501 case FilterType::cossphere:
502 filterName = "cossphere";
503 break;
504 case FilterType::linearsphere:
505 filterName = "linearsphere";
506 break;
507 case FilterType::coscylinderzaxis:
508 filterName = "coscylinderzaxis";
509 break;
510 case FilterType::cosbox:
511 filterName = "cosbox";
512 break;
513 case FilterType::linearbox:
514 filterName = "linearbox";
515 break;
516 case FilterType::cosmultibox:
517 filterName = "cosmultibox";
518 break;
519 case FilterType::linearmultibox:
520 filterName = "linearmultibox";
521 break;
522 default:
523 TERMM(1, "Unknown filter type! Please check your property file.");
524 break;
525 }
526
527 return filterName;
528}
529
530#endif // FILTER_H_
Filter object for source terms.
Definition: filter.h:171
void init()
Initializes the filter. Read all properties and set the filter function.
std::array< MFloat, nDim > m_filterCenter
Definition: filter.h:194
FilterType
Definition: filter.h:185
MBool m_isInitialized
Definition: filter.h:202
std::array< MFloat, 2 *nDim > m_filterSlopeWidthMultiBox
Definition: filter.h:200
const MInt m_solverId
Definition: filter.h:182
MFloat m_filterSlopeWidth
Definition: filter.h:198
FilterType m_filterId
Definition: filter.h:188
std::array< MFloat, nDim > m_filterRegionMax
Definition: filter.h:192
void filter(const MFloat *const points, const MInt count, MFloat *const values)
MFloat filter(const MFloat *const point) const
MFloat m_filterRadius
Definition: filter.h:196
Filter(const MInt solverId)
Definition: filter.h:173
MString name() const
std::array< MFloat, nDim > m_filterRegionMin
Definition: filter.h:190
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
T fsphere(const T *const center, const T radius, const T width, const T *const x, F &&f)
Auxiliary function to create a sphere slope filter.
Definition: filter.h:61
T fbox(const T *const boxmin, const T *const boxmax, const T width, const T *const x, F &&f)
Auxiliary function to create a box slope filter (constant slope width)
Definition: filter.h:37
T fmultibox(const T *const boxmin, const T *const boxmax, const T *const width, const T *const x, F &&f)
Auxiliary function to create a box slope filter (variable slope width)
Definition: filter.h:51
T f2way(const T a, const T b, const T c, const T d, const T x, F &&f)
Auxiliary function to create two-way slope filters.
Definition: filter.h:27
T cosmultibox(const T *const boxmin, const T *const boxmax, const T *const width, const T *const x)
Definition: filter.h:146
T cos2way(const T a, const T b, const T c, const T d, const T x)
Definition: filter.h:136
T linear(const T a, const T b, const T x)
Linear slope filter.
Definition: filter.h:83
T coscylinderzaxis(const T *const center, const T radius, const T width, const T *const x)
Definition: filter.h:156
T linearsphere(const T *const center, const T radius, const T width, const T *const x)
Definition: filter.h:109
T linearbox(const T *const boxmin, const T *const boxmax, const T width, const T *const x)
Definition: filter.h:99
T cosbox(const T *const boxmin, const T *const boxmax, const T width, const T *const x)
Definition: filter.h:141
T cossphere(const T *const center, const T radius, const T width, const T *const x)
Definition: filter.h:151
T cos(const T a, const T b, const T x)
Cosine slope filter.
Definition: filter.h:125
T linear2way(const T a, const T b, const T c, const T d, const T x)
Definition: filter.h:94
T linearmultibox(const T *const boxmin, const T *const boxmax, const T *const width, const T *const x)
Definition: filter.h:104
Namespace for auxiliary functions/classes.
Definition: contexttypes.h:19