parcelSelectionDetail.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2018-2019 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "cloud.H"
30#include "scalarPredicates.H"
31#include "labelField.H"
32#include "scalarField.H"
33#include "pointField.H"
34#include "ListListOps.H"
35
36// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37
38const Foam::Enum
39<
41>
43({
44 { actionType::ALL, "all" },
45 { actionType::CLEAR, "clear" },
46 { actionType::INVERT, "invert" },
47 { actionType::USE, "use" },
48 { actionType::ADD, "add" },
49 { actionType::SUBTRACT, "subtract" },
50 { actionType::SUBSET, "subset" },
51 { actionType::IGNORE, "ignore" },
52});
53
54
55const Foam::Enum
56<
58>
60({
61 { sourceType::FIELD, "field" },
62 { sourceType::STRIDE, "stride" },
63});
64
65
66const Foam::Enum
67<
70({
71 { logicType::AND, "and" },
72 { logicType::OR, "or" },
73});
74
75
76// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
77
78namespace Foam
79{
80 template<class Type, class Predicate, class AccessOp>
81 static void apply
82 (
83 bitSet& selection,
85 const Predicate& accept,
86 const UList<Type>& list,
87 const AccessOp& aop
88 )
89 {
90 using actionType = Detail::parcelSelection::actionType;
91
92 const label len = selection.size();
93
94 switch (action)
95 {
96 case actionType::ADD:
97 case actionType::USE:
98 {
99 if (actionType::USE == action)
100 {
101 // USE = CLEAR + ADD (ie, only use this selection)
102 selection = false;
103 }
104
105 for (label parceli = 0; parceli < len; ++parceli)
106 {
107 if (accept(aop(list[parceli])))
108 {
109 selection.set(parceli);
110 }
111 }
112 }
113 break;
114
115 case actionType::SUBTRACT:
116 {
117 for (label parceli = 0; parceli < len; ++parceli)
118 {
119 if (accept(aop(list[parceli])))
120 {
121 selection.unset(parceli);
122 }
123 }
124 }
125 break;
126
127 case actionType::SUBSET:
128 {
129 for (const label parceli : selection)
130 {
131 if (!accept(aop(list[parceli])))
132 {
133 selection.unset(parceli);
134 }
135 }
136 }
137 break;
138
139 default:
140 break;
141 }
142 }
143
144} // End namespace Foam
145
146
147// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
148
150(
151 const objectRegistry& obrTmp,
152 const bool log
153)
154{
155 if (parcelSelect_.empty())
156 {
158 return false;
159 }
160
161 // Start with all parcels unselected
162
163 // Number of parcels (locally)
164 const auto* pointsPtr = cloud::findIOPosition(obrTmp);
165 label nParcels = pointsPtr->size();
166
168 parcelAddr_.resize(nParcels);
169
170 reduce(nParcels, sumOp<label>());
171
172 Log << "Applying parcel filtering to " << nParcels << " parcels" << nl;
173
174 if (!nParcels)
175 {
177 return false;
178 }
179
180 // The unary function type(s) for testing a scalar.
181 // Allocate 3 slots.
182 // 0 is the test
183 // 1,2 are for storage of composite tests (eg, and/or logic)
184 predicates::scalars tests(3);
185
186 for (const entry& dEntry : parcelSelect_)
187 {
188 if (!dEntry.isDict())
189 {
191 << "Ignoring non-dictionary entry "
192 << dEntry << endl;
193 continue;
194 }
195
196 const dictionary& dict = dEntry.dict();
197
198 // A very limited number of sources (stride, field)
199 // and actions (all add subtract subset) so handle manually
200
201 auto action = actionNames.get("action", dict);
202
203 // These ones we do directly
204 switch (action)
205 {
206 case actionType::ALL:
207 Log << "- select all" << nl;
208 parcelAddr_ = true;
209 continue;
210 break;
211
213 Log << "- clear" << nl;
214 parcelAddr_ = false;
215 continue;
216 break;
217
219 Log << "- invert" << nl;
221 continue;
222 break;
223
225 continue;
226 break;
227
228 default:
229 break;
230 }
231
232 // The others need a source
233 // Need a source
234 const auto source = sourceNames.get("source", dict);
235
236 switch (source)
237 {
239 {
240 const label stride = dict.get<label>("stride");
241
242 const labelField& ids =
243 obrTmp.lookupObject<labelField>("origId");
244
245 Log << "- " << actionNames[action]
246 << " stride " << stride << nl;
247
248 if (stride <= 0)
249 {
251 << nl
252 << "Ignoring bad value for stride=" << stride << nl
253 << endl;
254 }
255 else if (stride == 1)
256 {
257 // More efficient handling of stride 1, but should
258 // not really be using stride == 1.
259 switch (action)
260 {
261 case actionType::ADD:
262 parcelAddr_ = true;
263 break;
264
266 parcelAddr_ = false;
267 break;
268
269 default:
270 break;
271 }
272 }
273 else
274 {
275 // Using stride > 1
276 apply
277 (
279 action,
280 [=](const label id) -> bool { return !(id % stride); },
281 ids,
282 accessOp<label>() // pass-through
283 );
284 }
285 }
286 break;
287
289 {
290 const word fieldName(dict.get<word>("field"));
291
292 const auto* labelFld =
293 obrTmp.findObject<labelField>(fieldName);
294
295 const auto* scalarFld =
296 obrTmp.findObject<scalarField>(fieldName);
297
298 const auto* vectorFld =
299 obrTmp.findObject<vectorField>(fieldName);
300
301
302 Log << "- " << actionNames[action] << " field " << fieldName;
303
304 if (!labelFld && !scalarFld && !vectorFld)
305 {
307 << nl
308 << "No scalar/vector parcel field: " << fieldName
309 << " ignoring selection" << nl
310 << endl;
311 continue;
312 }
313
314 const entry& e = dict.lookupEntry("accept", keyType::LITERAL);
315
316 ITstream& is = e.stream();
317
318 if (4 == is.size())
319 {
320 // 4 tokens:
321 // -> (op val)
322
323 Tuple2<word,scalar> expr1(is);
324 e.checkITstream(is);
325
326 tests.first() = predicates::scalars::operation(expr1);
327
328 Log << " : " << expr1;
329 }
330 else if (9 == is.size())
331 {
332 // 9 tokens:
333 // -> (op val) and (op val)
334 // -> (op val) or (op val)
335
336 Tuple2<word,scalar> expr1(is);
337 word logicName(is);
338 Tuple2<word,scalar> expr2(is);
339 e.checkITstream(is);
340
341 logicType logic = logicNames[logicName];
342 tests[1] = predicates::scalars::operation(expr1);
343 tests[2] = predicates::scalars::operation(expr2);
344
345 switch (logic)
346 {
347 case logicType::AND:
348 tests.first() =
349 predicates::scalars::andOp(tests[1], tests[2]);
350 break;
351
352 case logicType::OR:
353 tests.first() =
354 predicates::scalars::orOp(tests[1], tests[2]);
355 break;
356 }
357
358 Log << " : " << expr1 << ' ' << logicName << ' ' << expr2;
359 }
360 else
361 {
362 action = actionType::IGNORE;
363
364 // Use the following to always provoke an error.
365 e.checkITstream(is);
366 }
367
368 if (labelFld)
369 {
370 apply
371 (
373 action,
374 tests.first(),
375 *labelFld,
376 accessOp<label>() // pass-through
377 );
378 }
379 else if (scalarFld)
380 {
381 apply
382 (
384 action,
385 tests.first(),
386 *scalarFld,
387 accessOp<scalar>() // pass-through
388 );
389 }
390 else if (vectorFld)
391 {
392 apply
393 (
395 action,
396 tests.first(),
397 *vectorFld,
398 [](const vector& val) -> scalar
399 {
400 return Foam::mag(val);
401 }
402 );
403 }
404
405 Log << endl;
406 }
407 break;
408
409 default:
410 break;
411 }
412 }
413
414 return true;
415}
416
417
418// ************************************************************************* //
#define Log
Definition: PDRblock.C:35
static const Enum< actionType > actionNames
Names for the actionType.
sourceType
Enumeration defining the valid sources.
@ STRIDE
"stride" - select based on stride (parcel id)
@ FIELD
"field" - select based on field value
bitSet parcelAddr_
The filtered parcel addressing. Eg, for the current cloud.
bool calculateFilter(const objectRegistry &obrTmp, const bool log=true)
Calculate parcel selection filter.
static const Enum< logicType > logicNames
Names for the logicType.
actionType
Enumeration defining the valid selection actions.
@ CLEAR
"clear" - clear the selection
@ SUBTRACT
"subtract" - remove parcel selection
@ ALL
"all" - select all parcels
@ INVERT
"invert" - invert the selection
@ ADD
"add" - parcel selection
dictionary parcelSelect_
The filtered parcel addressing. Eg, for the current cloud.
logicType
Enumeration defining and/or logic.
static const Enum< sourceType > sourceNames
Names for the sourceType.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: Enum.H:61
EnumType get(const word &enumName) const
The enumeration corresponding to the given name.
Definition: Enum.C:75
An input stream of tokens.
Definition: ITstream.H:56
void resize(const label numElem, const unsigned int val=0u)
Reset addressable list size, does not shrink the allocated size.
Definition: PackedListI.H:409
label size() const noexcept
Number of entries.
Definition: PackedListI.H:377
void clear()
Clear the list, i.e. set addressable size to zero.
Definition: PackedListI.H:512
void reset()
Clear all bits but do not adjust the addressable size.
Definition: PackedListI.H:505
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: Tuple2.H:58
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:94
T & first()
Return the first element of the list.
Definition: UListI.H:202
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
void flip()
Invert all bits in the addressable region.
Definition: bitSetI.H:634
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:590
bitSet & unset(const bitSet &other)
Definition: bitSetI.H:628
static const IOField< point > * findIOPosition(const objectRegistry &obr)
Locate the "position" IOField within object registry.
Definition: cloud.H:153
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
const entry & lookupEntry(const word &keyword, enum keyType::option matchOpt) const
Search for an entry (const access) with the given keyword.
Definition: dictionary.C:366
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
@ LITERAL
String literal.
Definition: keyType.H:81
Registry of regIOobjects.
const Type * findObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
const Type & lookupObject(const word &name, const bool recursive=false) const
A list of unary predicates (tests) on scalars. Includes a number of standard comparison predicates (e...
static unary operation(const opType op, const scalar opVal, const scalar tol=VSMALL)
Standard comparison method by type.
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
static void apply(bitSet &selection, const Detail::parcelSelection::actionType action, const Predicate &accept, const UList< Type > &list, const AccessOp &aop)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
dictionary dict
volScalarField & e
Definition: createFields.H:11