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 -------------------------------------------------------------------------------
10 License
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"
29 #include "parcelSelectionDetail.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 
38 const 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 
55 const Foam::Enum
56 <
58 >
60 ({
61  { sourceType::FIELD, "field" },
62  { sourceType::STRIDE, "stride" },
63 });
64 
65 
66 const Foam::Enum
67 <
70 ({
71  { logicType::AND, "and" },
72  { logicType::OR, "or" },
73 });
74 
75 
76 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
77 
78 namespace 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 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
148 
150 :
151  parcelSelect_(),
152  parcelAddr_()
153 {}
154 
155 
156 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
157 
159 (
160  const objectRegistry& obrTmp,
161  const bool log
162 )
163 {
164  if (parcelSelect_.empty())
165  {
166  parcelAddr_.clear();
167  return false;
168  }
169 
170  // Start with all parcels unselected
171 
172  // Number of parcels (locally)
173  const auto* pointsPtr = cloud::findIOPosition(obrTmp);
174  label nParcels = pointsPtr->size();
175 
176  parcelAddr_.reset();
177  parcelAddr_.resize(nParcels);
178 
179  reduce(nParcels, sumOp<label>());
180 
181  Log << "Applying parcel filtering to " << nParcels << " parcels" << nl;
182 
183  if (!nParcels)
184  {
185  parcelAddr_.clear();
186  return false;
187  }
188 
189  // The unary function type(s) for testing a scalar.
190  // Allocate 3 slots.
191  // 0 is the test
192  // 1,2 are for storage of composite tests (eg, and/or logic)
193  predicates::scalars tests(3);
194 
195  for (const entry& dEntry : parcelSelect_)
196  {
197  if (!dEntry.isDict())
198  {
200  << "Ignoring non-dictionary entry "
201  << dEntry << endl;
202  continue;
203  }
204 
205  const dictionary& dict = dEntry.dict();
206 
207  // A very limited number of sources (stride, field)
208  // and actions (all add subtract subset) so handle manually
209 
210  auto action = actionNames.get("action", dict);
211 
212  // These ones we do directly
213  switch (action)
214  {
215  case actionType::ALL:
216  Log << "- select all" << nl;
217  parcelAddr_ = true;
218  continue;
219  break;
220 
221  case actionType::CLEAR:
222  Log << "- clear" << nl;
223  parcelAddr_ = false;
224  continue;
225  break;
226 
227  case actionType::INVERT:
228  Log << "- invert" << nl;
229  parcelAddr_.flip();
230  continue;
231  break;
232 
233  case actionType::IGNORE:
234  continue;
235  break;
236 
237  default:
238  break;
239  }
240 
241  // The others need a source
242  // Need a source
243  const auto source = sourceNames.get("source", dict);
244 
245  switch (source)
246  {
247  case sourceType::STRIDE:
248  {
249  const label stride = dict.get<label>("stride");
250 
251  const labelField& ids =
252  obrTmp.lookupObject<labelField>("origId");
253 
254  Log << "- " << actionNames[action]
255  << " stride " << stride << nl;
256 
257  if (stride <= 0)
258  {
260  << nl
261  << "Ignoring bad value for stride=" << stride << nl
262  << endl;
263  }
264  else if (stride == 1)
265  {
266  // More efficient handling of stride 1, but should
267  // not really be using stride == 1.
268  switch (action)
269  {
270  case actionType::ADD:
271  parcelAddr_ = true;
272  break;
273 
274  case actionType::SUBTRACT:
275  parcelAddr_ = false;
276  break;
277 
278  default:
279  break;
280  }
281  }
282  else
283  {
284  // Using stride > 1
285  apply
286  (
287  parcelAddr_,
288  action,
289  [=](const label id) -> bool { return !(id % stride); },
290  ids,
291  accessOp<label>() // pass-through
292  );
293  }
294  }
295  break;
296 
297  case sourceType::FIELD:
298  {
299  const word fieldName(dict.get<word>("field"));
300 
301  const auto* labelFld =
302  obrTmp.findObject<labelField>(fieldName);
303 
304  const auto* scalarFld =
305  obrTmp.findObject<scalarField>(fieldName);
306 
307  const auto* vectorFld =
308  obrTmp.findObject<vectorField>(fieldName);
309 
310 
311  Log << "- " << actionNames[action] << " field " << fieldName;
312 
313  if (!labelFld && !scalarFld && !vectorFld)
314  {
316  << nl
317  << "No scalar/vector parcel field: " << fieldName
318  << " ignoring selection" << nl
319  << endl;
320  continue;
321  }
322 
323  const entry& e = dict.lookupEntry("accept", keyType::LITERAL);
324 
325  ITstream& is = e.stream();
326 
327  if (4 == is.size())
328  {
329  // 4 tokens:
330  // -> (op val)
331 
332  Tuple2<word,scalar> expr1(is);
333  e.checkITstream(is);
334 
335  tests.first() = predicates::scalars::operation(expr1);
336 
337  Log << " : " << expr1;
338  }
339  else if (9 == is.size())
340  {
341  // 9 tokens:
342  // -> (op val) and (op val)
343  // -> (op val) or (op val)
344 
345  Tuple2<word,scalar> expr1(is);
346  word logicName(is);
347  Tuple2<word,scalar> expr2(is);
348  e.checkITstream(is);
349 
350  logicType logic = logicNames[logicName];
351  tests[1] = predicates::scalars::operation(expr1);
352  tests[2] = predicates::scalars::operation(expr2);
353 
354  switch (logic)
355  {
356  case logicType::AND:
357  tests.first() =
358  predicates::scalars::andOp(tests[1], tests[2]);
359  break;
360 
361  case logicType::OR:
362  tests.first() =
363  predicates::scalars::orOp(tests[1], tests[2]);
364  break;
365  }
366 
367  Log << " : " << expr1 << ' ' << logicName << ' ' << expr2;
368  }
369  else
370  {
371  action = actionType::IGNORE;
372 
373  // Use the following to always provoke an error.
374  e.checkITstream(is);
375  }
376 
377  if (labelFld)
378  {
379  apply
380  (
381  parcelAddr_,
382  action,
383  tests.first(),
384  *labelFld,
385  accessOp<label>() // pass-through
386  );
387  }
388  else if (scalarFld)
389  {
390  apply
391  (
392  parcelAddr_,
393  action,
394  tests.first(),
395  *scalarFld,
396  accessOp<scalar>() // pass-through
397  );
398  }
399  else if (vectorFld)
400  {
401  apply
402  (
403  parcelAddr_,
404  action,
405  tests.first(),
406  *vectorFld,
407  [](const vector& val) -> scalar
408  {
409  return Foam::mag(val);
410  }
411  );
412  }
413 
414  Log << endl;
415  }
416  break;
417 
418  default:
419  break;
420  }
421  }
422 
423  return true;
424 }
425 
426 
427 // ************************************************************************* //
Foam::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:57
Log
#define Log
Definition: PDRblock.C:35
Foam::accessOp
Definition: UList.H:668
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
scalarField.H
Foam::predicates::scalars
A list of unary predicates (tests) on scalars. Includes a number of standard comparison predicates (e...
Definition: scalarPredicates.H:66
ListListOps.H
Foam::bitSet::unset
bitSet & unset(const bitSet &other)
Definition: bitSetI.H:612
Foam::Detail::parcelSelection::sourceType
sourceType
Enumeration defining the valid sources.
Definition: parcelSelectionDetail.H:202
Foam::Detail::parcelSelection::actionNames
static const Enum< actionType > actionNames
Names for the actionType.
Definition: parcelSelectionDetail.H:198
parcelSelectionDetail.H
cloud.H
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:574
Foam::Detail::parcelSelection::logicNames
static const Enum< logicType > logicNames
Names for the logicType.
Definition: parcelSelectionDetail.H:216
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::Detail::parcelSelection::actionType
actionType
Enumeration defining the valid selection actions.
Definition: parcelSelectionDetail.H:185
Foam::Detail::parcelSelection::parcelSelection
parcelSelection()
Construct null.
Definition: parcelSelectionDetail.C:149
Foam::sumOp
Definition: ops.H:213
Foam::Detail::parcelSelection::calculateFilter
bool calculateFilter(const objectRegistry &obrTmp, const bool log=true)
Calculate parcel selection filter.
Definition: parcelSelectionDetail.C:159
Foam::objectRegistry
Registry of regIOobjects.
Definition: objectRegistry.H:60
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::Field< label >
Foam::ITstream
An input stream of tokens.
Definition: ITstream.H:52
Foam::objectRegistry::lookupObject
const Type & lookupObject(const word &name, const bool recursive=false) const
Definition: objectRegistryTemplates.C:434
Foam::predicates::scalars::andOp
static unary andOp(const unary &test1, const unary &test2)
Combine unary tests as an AND operation.
Definition: scalarPredicates.H:183
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::Detail::parcelSelection::sourceNames
static const Enum< sourceType > sourceNames
Names for the sourceType.
Definition: parcelSelectionDetail.H:209
Foam::log
dimensionedScalar log(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:262
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::predicates::scalars::operation
static unary operation(const opType op, const scalar opVal, const scalar tol=VSMALL)
Standard comparison method by type.
pointField.H
Foam::Detail::parcelSelection::logicType
logicType
Enumeration defining and/or logic.
Definition: parcelSelectionDetail.H:213
Foam::objectRegistry::findObject
const Type * findObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
Definition: objectRegistryTemplates.C:401
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::Vector< scalar >
Foam::apply
static void apply(bitSet &selection, const Detail::parcelSelection::actionType action, const Predicate &accept, const UList< Type > &list, const AccessOp &aop)
Definition: parcelSelectionDetail.C:82
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::PackedList::size
label size() const noexcept
Number of entries.
Definition: PackedListI.H:377
Foam::UList< Type >
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::cloud::findIOPosition
static const IOField< point > * findIOPosition(const objectRegistry &obr)
Locate the "position" IOField within object registry.
Definition: cloud.H:153
Foam::actionNames
const Enum< topoSetSource::setAction > actionNames({ { topoSetSource::NEW, "use" }, { topoSetSource::ADD, "add" }, { topoSetSource::SUBTRACT, "subtract" }, { topoSetSource::SUBSET, "subset" }, { topoSetSource::INVERT, "invert" }, })
Foam::keyType::LITERAL
String literal.
Definition: keyType.H:81
Foam::predicates::scalars::orOp
static unary orOp(const unary &test1, const unary &test2)
Combine unary tests as an OR operation.
Definition: scalarPredicates.H:192
scalarPredicates.H
Foam::Tuple2
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: stringOps.H:60
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
labelField.H