1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2020 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 
18 #ifndef LIBMESH_MULTI_PREDICATES_H
19 #define LIBMESH_MULTI_PREDICATES_H
20 
21 // Local includes
22 #include "libmesh/libmesh.h" // libMesh::invalid_uint
23 #include "libmesh/single_predicates.h"
24 
25 // C++ includes
26 #include <vector>
27 
28 namespace libMesh {
29 class Elem;
30 }
31 
32 namespace libMesh
33 {
34 
35 // Forward declarations
36 class BoundaryInfo;
37 
38 /**
39  * This namespace defines several multi_predicates which are used by
40  * the element and node iterators.  These classes are not in general
41  * used by the user, although they could be.
42  *
43  * \author John W. Peterson
44  * \date 2004
45  */
46 namespace Predicates
47 {
48 
49 // Empty place-holder base class for multi_predicates
50 struct multi_predicate {};
51 
52 
53 // This class represents a generic combination of more than one predicate.
54 // It is meant to be derived from to actually be used.
55 template <typename T>
56 struct abstract_multi_predicate : multi_predicate
57 {
58   // virtual destructor.
~abstract_multi_predicateabstract_multi_predicate59   virtual ~abstract_multi_predicate()
60   {
61     // Clean-up vector
62     for (auto p : _predicates)
63       delete p;
64   }
65 
66   // operator= (perform deep copy of entries in _predicates vector
67   abstract_multi_predicate & operator=(const abstract_multi_predicate & rhs)
68   {
69     // First clear out the predicates vector
70     for (auto p : _predicates)
71       delete p;
72 
73     // Now copy over the information from the rhs.
74     this->deep_copy(rhs);
75 
76     return *this;
77   }
78 
79   // operator() checks all the predicates in the vector.
operatorabstract_multi_predicate80   virtual bool operator()(const T & it) const
81   {
82     for (const auto pred : _predicates)
83       {
84         libmesh_assert (pred);
85 
86         if (!(*pred)(it))
87           return false;
88       }
89 
90     return true;
91   }
92 
93 protected:
94   // Do not instantiate the base class.
abstract_multi_predicateabstract_multi_predicate95   abstract_multi_predicate() {}
96 
97   // Copy constructor.
abstract_multi_predicateabstract_multi_predicate98   abstract_multi_predicate(const abstract_multi_predicate & rhs)
99   {
100     this->deep_copy(rhs);
101   }
102 
103   // The deep_copy function is used by both the op= and
104   // copy constructors.  This function uses the default (empty)
105   // copy constructor for the predicate class.
deep_copyabstract_multi_predicate106   void deep_copy(const abstract_multi_predicate & rhs)
107   {
108     for (auto p : rhs._predicates)
109       _predicates.push_back(p->clone());
110   }
111 
112   // Predicates to be evaluated.
113   std::vector<predicate<T> *> _predicates;
114 };
115 
116 
117 
118 /**
119  * Used to iterate over nullptr entries in a container.
120  */
121 template <typename T>
122 struct IsNull : abstract_multi_predicate<T>
123 {
124   // Constructor, pushes back a single predicate
IsNullIsNull125   IsNull()
126   {
127     this->_predicates.push_back(new is_null<T>);
128   }
129 };
130 
131 
132 
133 /**
134  * Used to iterate over non-nullptr entries in a container.
135  */
136 template <typename T>
137 struct NotNull : abstract_multi_predicate<T>
138 {
139   // Constructor, pushes back a single predicate
NotNullNotNull140   NotNull()
141   {
142     this->_predicates.push_back(new not_null<T>);
143   }
144 };
145 
146 
147 
148 /**
149  * Used to iterate over non-nullptr, active entries in a container.
150  */
151 template <typename T>
152 struct Active : abstract_multi_predicate<T>
153 {
154   // Constructor, pushes back two single predicates
ActiveActive155   Active()
156   {
157     this->_predicates.push_back(new not_null<T>);
158     this->_predicates.push_back(new active<T>);
159   }
160 };
161 
162 
163 
164 /**
165  * Used to iterate over non-nullptr, inactive entries in a container.
166  */
167 template <typename T>
168 struct NotActive : abstract_multi_predicate<T>
169 {
170   // Constructor, pushes back two single predicates
NotActiveNotActive171   NotActive()
172   {
173     this->_predicates.push_back(new not_null<T>);
174     this->_predicates.push_back(new not_active<T>);
175   }
176 };
177 
178 
179 
180 
181 /**
182  * Used to iterate over non-nullptr, entries that have children (i.e. are
183  * ancestors) in a container.
184  */
185 template <typename T>
186 struct Ancestor : abstract_multi_predicate<T>
187 {
188   // Constructor, pushes back two single predicates
AncestorAncestor189   Ancestor()
190   {
191     this->_predicates.push_back(new not_null<T>);
192     this->_predicates.push_back(new ancestor<T>);
193   }
194 };
195 
196 
197 
198 
199 /**
200  * Used to iterate over non-nullptr, entries that have no children (i.e. are not
201  * ancestors) in a container.
202  */
203 template <typename T>
204 struct NotAncestor : abstract_multi_predicate<T>
205 {
206   // Constructor, pushes back two single predicates
NotAncestorNotAncestor207   NotAncestor()
208   {
209     this->_predicates.push_back(new not_null<T>);
210     this->_predicates.push_back(new not_ancestor<T>);
211   }
212 };
213 
214 
215 
216 
217 /**
218  * Used to iterate over non-nullptr, subactive entries (i.e. has no
219  * active children) in a container.
220  */
221 template <typename T>
222 struct SubActive : abstract_multi_predicate<T>
223 {
224   // Constructor, pushes back two single predicates
SubActiveSubActive225   SubActive()
226   {
227     this->_predicates.push_back(new not_null<T>);
228     this->_predicates.push_back(new subactive<T>);
229   }
230 };
231 
232 
233 
234 
235 /**
236  * Used to iterate over non-nullptr, non-subactive entries (i.e. has one
237  * or more active children) in a container.
238  */
239 template <typename T>
240 struct NotSubActive : abstract_multi_predicate<T>
241 {
242   // Constructor, pushes back two single predicates
NotSubActiveNotSubActive243   NotSubActive()
244   {
245     this->_predicates.push_back(new not_null<T>);
246     this->_predicates.push_back(new not_subactive<T>);
247   }
248 };
249 
250 
251 
252 /**
253  * Used to iterate over non-nullptr, local entries (i.e. owned by the
254  * current processor) in a container.
255  */
256 template <typename T>
257 struct Local : abstract_multi_predicate<T>
258 {
259   // Constructor, pushes back two single predicates
LocalLocal260   Local(processor_id_type my_pid)
261   {
262     this->_predicates.push_back(new not_null<T>);
263     this->_predicates.push_back(new pid<T>(my_pid));
264   }
265 };
266 
267 
268 /**
269  * Used to iterate over non-nullptr, semi-local entries (i.e. are not
270  * subactive and have are owned by an attached processor) in a
271  * container.
272  *
273  * FIXME: This is not currently safe to use on adaptively-refined
274  * grids, it should be added back when Elem::is_semilocal() has been
275  * patched to not require the Elem to be active.
276  */
277 // template <typename T>
278 // struct SemiLocal : abstract_multi_predicate<T>
279 // {
280 //   // Constructor, pushes back two single predicates
281 //   SemiLocal(processor_id_type my_pid)
282 //   {
283 //     this->_predicates.push_back(new not_null<T>);
284 //     this->_predicates.push_back(new not_subactive<T>);
285 //     this->_predicates.push_back(new semilocal_pid<T>(my_pid));
286 //   }
287 // };
288 
289 
290 /**
291  * Used to iterate over non-nullptr, active, non sub-active, semi-local
292  * elements in a container.
293  */
294 template <typename T>
295 struct ActiveSemiLocal : abstract_multi_predicate<T>
296 {
297   // Constructor, pushes back two single predicates
ActiveSemiLocalActiveSemiLocal298   ActiveSemiLocal(processor_id_type my_pid)
299   {
300     this->_predicates.push_back(new not_null<T>);
301     this->_predicates.push_back(new active<T>);
302     this->_predicates.push_back(new not_subactive<T>);
303     this->_predicates.push_back(new semilocal_pid<T>(my_pid));
304   }
305 };
306 
307 
308 /**
309  * Used to iterate over non-nullptr, face-local entries (i.e. are not
310  * subactive and are on or have a neighbor on processor my_pid) in a
311  * container.
312  */
313 template <typename T>
314 struct FaceLocal : abstract_multi_predicate<T>
315 {
316   // Constructor, pushes back two single predicates
FaceLocalFaceLocal317   FaceLocal(processor_id_type my_pid)
318   {
319     this->_predicates.push_back(new not_null<T>);
320     this->_predicates.push_back(new not_subactive<T>);
321     this->_predicates.push_back(new facelocal_pid<T>(my_pid));
322   }
323 };
324 
325 
326 
327 /**
328  * Used to iterate over non-nullptr, non-local entries in a
329  * container.
330  */
331 template <typename T>
332 struct NotLocal : abstract_multi_predicate<T>
333 {
334   // Constructor, pushes back two single predicates
NotLocalNotLocal335   NotLocal(processor_id_type my_pid)
336   {
337     this->_predicates.push_back(new not_null<T>);
338     this->_predicates.push_back(new not_pid<T>(my_pid));
339   }
340 };
341 
342 
343 /**
344  * Used to iterate over non-nullptr, active, non-local entries in a
345  * container.
346  */
347 template <typename T>
348 struct ActiveNotLocal : abstract_multi_predicate<T>
349 {
350   // Constructor, pushes back two single predicates
ActiveNotLocalActiveNotLocal351   ActiveNotLocal(processor_id_type my_pid)
352   {
353     this->_predicates.push_back(new not_null<T>);
354     this->_predicates.push_back(new active<T>);
355     this->_predicates.push_back(new not_pid<T>(my_pid));
356   }
357 };
358 
359 
360 /**
361  * Used to iterate over non-nullptr, elements of a given geometric type.
362  */
363 template <typename T>
364 struct Type : abstract_multi_predicate<T>
365 {
TypeType366   Type(ElemType type)
367   {
368     this->_predicates.push_back(new not_null<T>);
369     this->_predicates.push_back(new elem_type<T>(type));
370   }
371 };
372 
373 
374 
375 /**
376  * Used to iterate over non-nullptr, active elements of a given geometric type.
377  */
378 template <typename T>
379 struct ActiveType : abstract_multi_predicate<T>
380 {
ActiveTypeActiveType381   ActiveType(ElemType type)
382   {
383     this->_predicates.push_back(new not_null<T>);
384     this->_predicates.push_back(new active<T>);
385     this->_predicates.push_back(new elem_type<T>(type));
386   }
387 };
388 
389 
390 
391 #ifdef LIBMESH_ENABLE_AMR
392 /**
393  * Used to iterate over non-nullptr, elements with a given refinement
394  * flag.
395  */
396 template <typename T>
397 struct Flagged : abstract_multi_predicate<T>
398 {
FlaggedFlagged399   Flagged(unsigned char rflag)
400   {
401     this->_predicates.push_back(new not_null<T>);
402     this->_predicates.push_back(new flagged<T>(rflag));
403   }
404 };
405 
406 
407 
408 /**
409  * Used to iterate over non-nullptr, elements with a given refinement
410  * flag belonging to a given processor.
411  */
412 template <typename T>
413 struct FlaggedPID : abstract_multi_predicate<T>
414 {
FlaggedPIDFlaggedPID415   FlaggedPID(unsigned char rflag, processor_id_type proc_id)
416   {
417     this->_predicates.push_back(new not_null<T>);
418     this->_predicates.push_back(new flagged<T>(rflag));
419     this->_predicates.push_back(new pid<T>(proc_id));
420   }
421 };
422 
423 #endif // LIBMESH_ENABLE_AMR
424 
425 
426 
427 
428 /**
429  * Used to iterate over non-nullptr, active elements owned by a given
430  * processor.
431  */
432 template <typename T>
433 struct ActivePID : abstract_multi_predicate<T>
434 {
ActivePIDActivePID435   ActivePID(processor_id_type proc_id)
436   {
437     this->_predicates.push_back(new not_null<T>);
438     this->_predicates.push_back(new active<T>);
439     this->_predicates.push_back(new pid<T>(proc_id));
440   }
441 };
442 
443 
444 
445 
446 
447 /**
448  * Used to iterate over non-nullptr, active, local elements owned by a
449  * given processor.
450  */
451 template <typename T>
452 struct ActiveLocal : abstract_multi_predicate<T>
453 {
ActiveLocalActiveLocal454   ActiveLocal(processor_id_type my_pid)
455   {
456     this->_predicates.push_back(new not_null<T>);
457     this->_predicates.push_back(new active<T>);
458     this->_predicates.push_back(new pid<T>(my_pid));
459   }
460 };
461 
462 
463 
464 
465 
466 /**
467  * Used to iterate over non-nullptr elements owned by a given processor.
468  */
469 template <typename T>
470 struct PID : abstract_multi_predicate<T>
471 {
PIDPID472   PID(processor_id_type proc_id)
473   {
474     this->_predicates.push_back(new not_null<T>);
475     this->_predicates.push_back(new pid<T>(proc_id));
476   }
477 };
478 
479 
480 
481 /**
482  * Used to iterate over non-nullptr elements on the boundary with a given
483  * ID.
484  */
485 template <typename T>
486 struct BID : abstract_multi_predicate<T>
487 {
BIDBID488   BID(boundary_id_type bndry_id, const BoundaryInfo & bndry_info)
489   {
490     this->_predicates.push_back(new not_null<T>);
491     this->_predicates.push_back(new bid<T>(bndry_id, bndry_info));
492   }
493 };
494 
495 
496 
497 /**
498  * Used to iterate over non-nullptr elements on the boundary.
499  */
500 template <typename T>
501 struct BND : abstract_multi_predicate<T>
502 {
BNDBND503   BND(const BoundaryInfo & bndry_info)
504   {
505     this->_predicates.push_back(new not_null<T>);
506     this->_predicates.push_back(new bnd<T>(bndry_info));
507   }
508 };
509 
510 
511 
512 /**
513  * Used to iterate over non-nullptr elements *not* owned by a given
514  * processor.
515  */
516 template <typename T>
517 struct NotPID : abstract_multi_predicate<T>
518 {
NotPIDNotPID519   NotPID(processor_id_type proc_id)
520   {
521     this->_predicates.push_back(new not_null<T>);
522     this->_predicates.push_back(new not_pid<T>(proc_id));
523   }
524 };
525 
526 
527 
528 /**
529  * Used to iterate over non-nullptr elements of a specified (refinement) level.
530  */
531 template <typename T>
532 struct Level : abstract_multi_predicate<T>
533 {
LevelLevel534   Level(unsigned int l)
535   {
536     this->_predicates.push_back(new not_null<T>);
537     this->_predicates.push_back(new level<T>(l));
538   }
539 };
540 
541 
542 
543 /**
544  * Used to iterate over non-nullptr elements *not* of a specified
545  * (refinement) level.
546  */
547 template <typename T>
548 struct NotLevel : abstract_multi_predicate<T>
549 {
NotLevelNotLevel550   NotLevel(unsigned int l)
551   {
552     this->_predicates.push_back(new not_null<T>);
553     this->_predicates.push_back(new not_level<T>(l));
554   }
555 };
556 
557 
558 
559 /**
560  * Used to iterate over non-nullptr local elements with a specified
561  * (refinement) level.
562  */
563 template <typename T>
564 struct LocalLevel : abstract_multi_predicate<T>
565 {
LocalLevelLocalLevel566   LocalLevel(processor_id_type my_pid,
567              unsigned int l)
568   {
569     this->_predicates.push_back(new not_null<T>);
570     this->_predicates.push_back(new pid<T>(my_pid));
571     this->_predicates.push_back(new level<T>(l));
572   }
573 };
574 
575 
576 
577 /**
578  * Used to iterate over non-nullptr local elements *not* of a specified
579  * (refinement) level.
580  */
581 template <typename T>
582 struct LocalNotLevel : abstract_multi_predicate<T>
583 {
LocalNotLevelLocalNotLevel584   LocalNotLevel(processor_id_type my_pid,
585                 unsigned int l)
586   {
587     this->_predicates.push_back(new not_null<T>);
588     this->_predicates.push_back(new pid<T>(my_pid));
589     this->_predicates.push_back(new not_level<T>(l));
590   }
591 };
592 
593 
594 
595 /**
596  * Used to iterate over non-nullptr, active elements which are on the
597  * boundary.
598  */
599 template <typename T>
600 struct ActiveOnBoundary : abstract_multi_predicate<T>
601 {
ActiveOnBoundaryActiveOnBoundary602   ActiveOnBoundary()
603   {
604     this->_predicates.push_back(new not_null<T>);
605     this->_predicates.push_back(new active<T>);
606     this->_predicates.push_back(new null_neighbor<T>);
607   }
608 };
609 
610 
611 
612 /**
613  * Used to iterate over the sides of an element which are on the
614  * boundary of the Mesh.
615  */
616 template <typename T>
617 struct BoundarySide : abstract_multi_predicate<T>
618 {
BoundarySideBoundarySide619   BoundarySide()
620   {
621     this->_predicates.push_back(new boundary_side<T>);
622   }
623 };
624 
625 
626 
627 /**
628  * Used to iterate over non-nullptr, active elements with a given PID on
629  * a given subdomain.
630  */
631 template <typename T>
632 struct ActiveLocalSubdomain : abstract_multi_predicate<T>
633 {
ActiveLocalSubdomainActiveLocalSubdomain634   ActiveLocalSubdomain(processor_id_type my_pid,
635                        subdomain_id_type subdomain_id)
636   {
637     this->_predicates.push_back(new not_null<T>);
638     this->_predicates.push_back(new active<T>);
639     this->_predicates.push_back(new pid<T>(my_pid));
640     this->_predicates.push_back(new subdomain<T>(subdomain_id));
641   }
642 };
643 
644 
645 
646 /**
647  * Used to iterate over non-nullptr, active elements on a given
648  * subdomain.
649  */
650 template <typename T>
651 struct ActiveSubdomain : abstract_multi_predicate<T>
652 {
ActiveSubdomainActiveSubdomain653   ActiveSubdomain(subdomain_id_type subdomain_id)
654   {
655     this->_predicates.push_back(new not_null<T>);
656     this->_predicates.push_back(new active<T>);
657     this->_predicates.push_back(new subdomain<T>(subdomain_id));
658   }
659 };
660 
661 
662 
663 /**
664  * Used to iterate over non-nullptr, active elements whose
665  * subdomains are in a user-specified set.
666  */
667 template <typename T>
668 struct ActiveSubdomainSet : abstract_multi_predicate<T>
669 {
ActiveSubdomainSetActiveSubdomainSet670   ActiveSubdomainSet(std::set<subdomain_id_type> sset)
671   {
672     this->_predicates.push_back(new not_null<T>);
673     this->_predicates.push_back(new active<T>);
674     this->_predicates.push_back(new subdomain_set<T>(sset));
675   }
676 };
677 
678 
679 
680 /**
681  * Used to iterate over non-nullptr elements not owned by a given
682  * processor but semi-local to that processor, i.e. ghost elements.
683  */
684 template <typename T>
685 struct Ghost : abstract_multi_predicate<T>
686 {
GhostGhost687   Ghost(processor_id_type my_pid)
688   {
689     this->_predicates.push_back(new not_null<T>);
690     this->_predicates.push_back(new active<T>);
691     this->_predicates.push_back(new not_pid<T>(my_pid));
692     this->_predicates.push_back(new semilocal_pid<T>(my_pid));
693   }
694 };
695 
696 
697 
698 /**
699  * Used to iterate over elements where solutions indexed by a given
700  * DofMap are evaluable for a given variable var_num.
701  */
702 template <typename T>
703 struct Evaluable: abstract_multi_predicate<T>
704 {
705   Evaluable(const DofMap & dof_map,
706             unsigned int var_num = libMesh::invalid_uint)
707   {
708     this->_predicates.push_back(new not_null<T>);
709     this->_predicates.push_back(new active<T>);
710     this->_predicates.push_back(new evaluable<T>(dof_map, var_num));
711   }
712 };
713 
714 }
715 
716 
717 } // namespace libMesh
718 
719 #endif // LIBMESH_MULTI_PREDICATES_H
720