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
35
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}
108 */
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
135
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>
188LevelSetBooleanOperation LevelSetBooleanBaseObject<SourceLevelSetObject>::getBooleanOperation() const{
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()) ;
287 VolumeKernel::CellConstIterator cellBegin = mesh.cellConstBegin();
288 VolumeKernel::CellConstIterator cellEnd = mesh.cellConstEnd();
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) -> double
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) -> std::array<double, 3>
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) -> double
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) -> std::array<double,3>
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
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
CellConstIterator cellConstBegin() const
CellConstIterator cellConstEnd() const
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.
namespace containing default values
const std::array< double, 3 > GRADIENT