Loading...
Searching...
No Matches
levelSetBooleanObject.tpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
25# ifndef __BITPIT_LEVELSET_BOOLEAN_OBJECT_TPP__
26# define __BITPIT_LEVELSET_BOOLEAN_OBJECT_TPP__
27
28namespace bitpit {
29
41template<typename SourceLevelSetObject>
43 : m_operation(operation), m_object(nullptr), m_objectSign(0), m_value(levelSetDefaults::VALUE)
44{
45}
46
54template<typename SourceLevelSetObject>
55LevelSetBooleanResult<SourceLevelSetObject>::LevelSetBooleanResult(LevelSetBooleanOperation operation, const SourceLevelSetObject *object, double value)
56 : m_operation(operation), m_object(object), m_objectSign(1), m_value(value)
57{
58}
59
66template<typename SourceLevelSetObject>
67void LevelSetBooleanResult<SourceLevelSetObject>::update(const SourceLevelSetObject *object, double value)
68{
69 // Early return if the result was not initialized
70 if (!m_object) {
71 m_object = object;
72 m_objectSign = 1;
73
74 m_value = value;
75
76 return;
77 }
78
79 // Update the result
81 if(m_value > value) {
82 m_object = object;
83 m_objectSign = 1;
84
85 m_value = m_objectSign * value;
86 }
88 } else if ( m_operation == LevelSetBooleanOperation::INTERSECTION){
89 if(m_value < value) {
90 m_object = object;
91 m_objectSign = 1;
93 m_value = m_objectSign * value;
94 }
96 } else if ( m_operation == LevelSetBooleanOperation::SUBTRACTION){
97 if(m_value < - value) {
98 m_object = object;
99 m_objectSign = -1;
100
101 m_value = m_objectSign * value;
102 }
103 }
104}
109template<typename SourceLevelSetObject>
110const SourceLevelSetObject * LevelSetBooleanResult<SourceLevelSetObject>::getObject() const {
111 return m_object;
112}
113
117template<typename SourceLevelSetObject>
119 return m_objectSign;
120}
121
125template<typename SourceLevelSetObject>
127 return m_value;
128}
129
143template<typename SourceLevelSetObject>
144LevelSetBooleanBaseObject<SourceLevelSetObject>::LevelSetBooleanBaseObject( int id, LevelSetBooleanOperation op, const SourceLevelSetObject *source1, const SourceLevelSetObject *source2 )
145 : LevelSetProxyObject<SourceLevelSetObject, SourceLevelSetObject>(id) {
146
147 m_operation = op;
148 m_sourceObjects.push_back(source1);
149 m_sourceObjects.push_back(source2);
150}
151
159template<typename SourceLevelSetObject>
160LevelSetBooleanBaseObject<SourceLevelSetObject>::LevelSetBooleanBaseObject( int id, LevelSetBooleanOperation op, const std::vector<const SourceLevelSetObject *> &sourceObjects )
161 : LevelSetProxyObject<SourceLevelSetObject, SourceLevelSetObject>(id),
162 m_operation(op), m_sourceObjects(sourceObjects) {
163
164}
165
171template<typename SourceLevelSetObject>
173
174 for (const SourceLevelSetObject *sourceObject : m_sourceObjects) {
175 if (!sourceObject->empty()) {
176 return false;
177 }
178 }
179
180 return true;
181}
182
183/*
184 * Returns the boolean operation
185 * @return boolean operation
186 */
187template<typename SourceLevelSetObject>
189 return m_operation;
190}
191
198template<typename SourceLevelSetObject>
199LevelSetBooleanResult<SourceLevelSetObject> LevelSetBooleanBaseObject<SourceLevelSetObject>::computeBooleanResult( long id, bool signedLevelSet ) const{
200
201 if (m_sourceObjects.empty()) {
202 return LevelSetBooleanResult<SourceLevelSetObject>(getBooleanOperation());
203 }
204
205 LevelSetBooleanResult<SourceLevelSetObject> result( getBooleanOperation(), m_sourceObjects[0], m_sourceObjects[0]->evalCellValue(id, signedLevelSet) );
206 for( size_t n=1; n<m_sourceObjects.size(); ++n){
207 result.update(m_sourceObjects[n], m_sourceObjects[n]->evalCellValue(id, signedLevelSet));
208 }
209
210 return result;
211}
212
219template<typename SourceLevelSetObject>
220LevelSetBooleanResult<SourceLevelSetObject> LevelSetBooleanBaseObject<SourceLevelSetObject>::computeBooleanResult( const std::array<double,3> &coords, bool signedLevelSet ) const{
221
222 if (m_sourceObjects.empty()) {
223 return LevelSetBooleanResult<SourceLevelSetObject>(getBooleanOperation());
224 }
225
226 LevelSetBooleanResult<SourceLevelSetObject> result( getBooleanOperation(), m_sourceObjects[0], m_sourceObjects[0]->evalValue(coords, signedLevelSet) );
227 for( size_t n=1; n<m_sourceObjects.size(); ++n){
228 result.update(m_sourceObjects[n], m_sourceObjects[n]->evalValue(coords, signedLevelSet));
229 }
230
231 return result;
232}
233
239template<typename SourceLevelSetObject>
240void LevelSetBooleanBaseObject<SourceLevelSetObject>::replaceSourceObject(const SourceLevelSetObject *current, const SourceLevelSetObject *updated){
241
242 std::size_t nSources = m_sourceObjects.size();
243 for (std::size_t i = 0; i < nSources; ++i) {
244 const SourceLevelSetObject *source = m_sourceObjects[i];
245 if (source == current) {
246 m_sourceObjects[i] = updated;
247 return;
248 }
249 }
250
251 throw std::runtime_error("Unable to find the source that should be replaced.");
252}
253
257template<typename SourceLevelSetObject>
259{
260 // Early return if propagated sign cannot be copied from the source object
261 for (const SourceLevelSetObject *sourceObject : m_sourceObjects) {
262 LevelSetBulkEvaluationMode sourceBulkEvaluationMode = sourceObject->getCellBulkEvaluationMode();
263
264 bool useSourceSign = false;
265 if (sourceBulkEvaluationMode == LevelSetBulkEvaluationMode::SIGN_PROPAGATION) {
266 useSourceSign = true;
267 } else if (sourceBulkEvaluationMode == LevelSetBulkEvaluationMode::EXACT) {
268 LevelSetCacheMode sourceSignCacheMode = sourceObject->getFieldCellCacheMode(LevelSetField::SIGN);
269 if (sourceSignCacheMode == LevelSetCacheMode::FULL) {
270 useSourceSign = true;
271 } else {
272 LevelSetCacheMode sourceValueCacheMode = sourceObject->getFieldCellCacheMode(LevelSetField::VALUE);
273 if (sourceValueCacheMode == LevelSetCacheMode::FULL) {
274 useSourceSign = true;
275 }
276 }
277 }
278
279 if (!useSourceSign) {
280 SourceLevelSetObject::fillCellPropagatedSignCache();
281 return;
282 }
283 }
284
285 // Mesh information
286 const VolumeKernel &mesh = *(this->getKernel()->getMesh()) ;
289
290 // Get cache for sign propagation
291 typedef typename SourceLevelSetObject::CellCacheCollection::template ValueCache<char> ZoneCache;
292 ZoneCache *propagatedSignCache = this->template getCellCache<char>(this->m_cellPropagatedSignCacheId);
293
294 // Get propagated sign from source objects
295 for (VolumeKernel::CellConstIterator cellItr = cellBegin; cellItr != cellEnd; ++cellItr) {
296 long cellId = cellItr.getId();
297 const LevelSetBooleanResult<SourceLevelSetObject> cellResult = computeBooleanResult(cellId, true);
298 short cellSign = this->evalValueSign(cellResult.getValue());
299
300 propagatedSignCache->insertEntry(cellId, static_cast<char>(cellSign));
301 }
302}
303
310template<typename SourceLevelSetObject>
312 return this->evalValueSign(_evalCellValue(id, true));
313}
314
322template<typename SourceLevelSetObject>
323double LevelSetBooleanBaseObject<SourceLevelSetObject>::_evalCellValue(long id, bool signedLevelSet) const {
324 return _evalCellFunction<double>(id, signedLevelSet, [] (const LevelSetBooleanResult<SourceLevelSetObject> &result)
325 {
326 const LevelSetObject *resultObject = result.getObject();
327 if ( !resultObject ) {
329 }
330
331 return result.getValue();
332 });
333}
334
341template<typename SourceLevelSetObject>
342std::array<double,3> LevelSetBooleanBaseObject<SourceLevelSetObject>::_evalCellGradient(long id, bool signedLevelSet) const {
343 return _evalCellFunction<std::array<double,3>>(id, signedLevelSet, [id, signedLevelSet] (const LevelSetBooleanResult<SourceLevelSetObject> &result)
344 {
345 const LevelSetObject *resultObject = result.getObject();
346 if ( !resultObject ) {
348 }
349
350 std::array<double,3> gradient = resultObject->evalCellGradient(id, signedLevelSet);
351 if (signedLevelSet) {
352 return gradient;
353 }
354
355 return static_cast<double>(result.getObjectSign()) * gradient;
356 });
357}
358
366template<typename SourceLevelSetObject>
367double LevelSetBooleanBaseObject<SourceLevelSetObject>::_evalValue(const std::array<double,3> &point, bool signedLevelSet) const {
368 return _evalFunction<double>(point, signedLevelSet, [] (const LevelSetBooleanResult<SourceLevelSetObject> &result)
369 {
370 const SourceLevelSetObject *resultObject = result.getObject();
371 if ( !resultObject ) {
373 }
374
375 return result.getValue();
376 });
377}
378
386template<typename SourceLevelSetObject>
387std::array<double,3> LevelSetBooleanBaseObject<SourceLevelSetObject>::_evalGradient(const std::array<double,3> &point, bool signedLevelSet) const {
388 return _evalFunction<std::array<double,3>>(point, signedLevelSet, [&point, signedLevelSet] (const LevelSetBooleanResult<SourceLevelSetObject> &result)
389 {
390 const LevelSetObject *resultObject = result.getObject();
391 if ( !resultObject ) {
393 }
394
395 std::array<double,3> gradient = resultObject->evalGradient(point, signedLevelSet);
396 if (signedLevelSet) {
397 return gradient;
398 }
399
400 return static_cast<double>(result.getObjectSign()) * gradient;
401 });
402}
403
410template<typename SourceLevelSetObject>
411template<typename data_t, typename function_t>
413 const function_t &function) const
414{
415 const LevelSetBooleanResult<SourceLevelSetObject> result = computeBooleanResult( id, signedLevelSet ) ;
416
417 return function(result) ;
418}
419
426template<typename SourceLevelSetObject>
427template<typename data_t, typename function_t>
428data_t LevelSetBooleanBaseObject<SourceLevelSetObject>::_evalFunction(const std::array<double,3> &point, bool signedLevelSet,
429 const function_t &function) const
430{
431 const LevelSetBooleanResult<SourceLevelSetObject> result = computeBooleanResult( point, signedLevelSet ) ;
432
433 return function(result) ;
434}
435
442template<typename SourceLevelSetObject>
444
445 // Early return if the object has no sources
446 if (m_sourceObjects.empty()) {
447 return nullptr;
448 }
449
450 // Early return if the object has only one source
451 if (m_sourceObjects.size() == 1) {
452 return m_sourceObjects.front();
453 }
454
455 // Evaluate reference object from boolean result
456 const LevelSetBooleanResult<SourceLevelSetObject> result = computeBooleanResult(id, true) ;
457
458 return result.getObject();
459
460}
461
468template<typename SourceLevelSetObject>
469const SourceLevelSetObject * LevelSetBooleanBaseObject<SourceLevelSetObject>::getReferenceObject(const std::array<double, 3> &point) const{
470
471 // Early return if the object has no sources
472 if (m_sourceObjects.empty()) {
473 return nullptr;
474 }
475
476 // Early return if the object has only one source
477 if (m_sourceObjects.size() == 1) {
478 return m_sourceObjects.front();
479 }
480
481 // Evaluate reference object from boolean result
482 const LevelSetBooleanResult<SourceLevelSetObject> result = computeBooleanResult(point, true) ;
483
484 return result.getObject();
485
486}
487
493template<typename SourceLevelSetObject>
494std::vector<const SourceLevelSetObject *> LevelSetBooleanBaseObject<SourceLevelSetObject>::getSourceObjects() const{
495
496 return m_sourceObjects;
497
498}
499
500}
501
502#endif
Base class which deals with boolean operation between two LevelSetObjects.
std::vector< const SourceLevelSetObject * > getSourceObjects() const override
std::array< double, 3 > _evalGradient(const std::array< double, 3 > &point, bool signedLevelSet) const override
const SourceLevelSetObject * getCellReferenceObject(long id) const override
double _evalValue(const std::array< double, 3 > &point, bool signedLevelSet) const override
std::array< double, 3 > _evalCellGradient(long id, bool signedLevelSet) const override
LevelSetBooleanBaseObject(int, LevelSetBooleanOperation, const SourceLevelSetObject *, const SourceLevelSetObject *)
const SourceLevelSetObject * getReferenceObject(const std::array< double, 3 > &point) const override
data_t _evalCellFunction(long id, bool signedLevelSet, const function_t &function) const
short _evalCellSign(long id) const override
double _evalCellValue(long id, bool signedLevelSet) const override
data_t _evalFunction(const std::array< double, 3 > &point, bool signedLevelSet, const function_t &function) const
void replaceSourceObject(const SourceLevelSetObject *current, const SourceLevelSetObject *updated) override
Allow to evaluate the result of a boolean operation between two LevelSetObjects.
void update(const SourceLevelSetObject *object, double value)
LevelSetBooleanResult(LevelSetBooleanOperation operation)
const SourceLevelSetObject * getObject() const
Interface class for all objects with respect to whom the levelset function may be computed.
virtual std::array< double, 3 > evalCellGradient(long id, bool signedLevelSet) const
virtual std::array< double, 3 > evalGradient(const std::array< double, 3 > &point, bool signedLevelSet) const
Interface class for all objects, which depend on other LevelSetObjects.
CellConstIterator cellConstBegin() const
CellConstIterator cellConstEnd() const
Iterator for the class PiercedStorage.
The VolumeKernel class provides an interface for defining volume patches.
@ FULL
Data are cached in the whole domain.
@ SIGN_PROPAGATION
Sign is propagated from the narrow band, no other data will be evaluated.
@ EXACT
Exact data is evaluated.
const std::array< double, 3 > GRADIENT
--- layout: doxygen_footer ---