vtk-m2/vtkm/worklet/particleadvection/ParticlesAOS.h

304 lines
9.1 KiB
C++

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_worklet_particleadvection_Particles_AOS_h
#define vtk_m_worklet_particleadvection_Particles_AOS_h
class ParticleExecutionObjectType;
#include <vtkm/Types.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/ExecutionObjectBase.h>
namespace vtkm
{
namespace worklet
{
namespace particleadvection
{
template <typename Device>
class ParticleExecutionObjectAOS
{
public:
VTKM_EXEC_CONT
ParticleExecutionObjectAOS()
: Particle()
, MaxSteps(0)
{
}
ParticleExecutionObjectAOS(vtkm::cont::ArrayHandle<vtkm::Particle> pArray, vtkm::Id maxSteps)
{
Particle = pArray.PrepareForInPlace(Device());
MaxSteps = maxSteps;
}
VTKM_EXEC
void TakeStep(const vtkm::Id& idx, const vtkm::Vec3f& pt, const vtkm::FloatDefault& t)
{
vtkm::Particle p = this->Particle.Get(idx);
p.Pos = pt;
p.NumSteps++;
p.Time += t;
//std::cout<<idx<<" take step: "<<pt<<" "<<p.NumSteps<<" max= "<<this->MaxSteps<<std::endl;
if (p.NumSteps == this->MaxSteps)
{
p.Status &= ~static_cast<vtkm::Id>(ParticleStatus::SUCCESS);
p.Status |= static_cast<vtkm::Id>(ParticleStatus::TERMINATED);
}
this->Particle.Set(idx, p);
}
/* Set/Change Status */
VTKM_EXEC
void SetOK(const vtkm::Id& idx)
{
Clear(idx);
SetBit(idx, ParticleStatus::SUCCESS);
}
VTKM_EXEC
void SetTerminated(const vtkm::Id& idx)
{
ClearBit(idx, ParticleStatus::SUCCESS);
SetBit(idx, ParticleStatus::TERMINATED);
}
VTKM_EXEC
void SetTookAnySteps(const vtkm::Id& idx, const bool& val)
{
if (val)
SetBit(idx, ParticleStatus::TOOK_ANY_STEPS);
else
ClearBit(idx, ParticleStatus::TOOK_ANY_STEPS);
}
VTKM_EXEC
void SetExitSpatialBoundary(const vtkm::Id& idx)
{
ClearBit(idx, ParticleStatus::SUCCESS);
SetBit(idx, ParticleStatus::EXIT_SPATIAL_BOUNDARY);
}
VTKM_EXEC
void SetExitTemporalBoundary(const vtkm::Id& idx)
{
ClearBit(idx, ParticleStatus::SUCCESS);
SetBit(idx, ParticleStatus::EXIT_TEMPORAL_BOUNDARY);
}
VTKM_EXEC
void SetError(const vtkm::Id& idx)
{
ClearBit(idx, ParticleStatus::SUCCESS);
SetBit(idx, ParticleStatus::FAIL);
}
/* Check Status */
VTKM_EXEC
bool OK(const vtkm::Id& idx) { return CheckBit(idx, ParticleStatus::SUCCESS); }
VTKM_EXEC
bool Terminated(const vtkm::Id& idx) { return CheckBit(idx, ParticleStatus::TERMINATED); }
VTKM_EXEC
bool ExitSpatialBoundary(const vtkm::Id& idx)
{
return CheckBit(idx, ParticleStatus::EXIT_SPATIAL_BOUNDARY);
}
VTKM_EXEC
bool ExitTemporalBoundary(const vtkm::Id& idx)
{
return CheckBit(idx, ParticleStatus::EXIT_TEMPORAL_BOUNDARY);
}
VTKM_EXEC
bool Error(const vtkm::Id& idx) { return CheckBit(idx, ParticleStatus::FAIL); }
VTKM_EXEC
bool Done(const vtkm::Id& idx) { return !Integrateable(idx); }
VTKM_EXEC
bool Integrateable(const vtkm::Id& idx)
{
return OK(idx) && !(Terminated(idx) || ExitSpatialBoundary(idx) || ExitTemporalBoundary(idx));
}
/* Bit Operations */
VTKM_EXEC
void Clear(const vtkm::Id& idx)
{
vtkm::Particle p = Particle.Get(idx);
p.Status = 0;
Particle.Set(idx, p);
}
VTKM_EXEC
void SetBit(const vtkm::Id& idx, const ParticleStatus& b)
{
vtkm::Particle p = Particle.Get(idx);
p.Status |= static_cast<vtkm::Id>(b);
Particle.Set(idx, p);
}
VTKM_EXEC
void ClearBit(const vtkm::Id& idx, const ParticleStatus& b)
{
vtkm::Particle p = Particle.Get(idx);
p.Status &= ~static_cast<vtkm::Id>(b);
Particle.Set(idx, p);
}
VTKM_EXEC
bool CheckBit(const vtkm::Id& idx, const ParticleStatus& b) const
{
return (Particle.Get(idx).Status & static_cast<vtkm::Id>(b)) != 0;
}
VTKM_EXEC
vtkm::Vec3f GetPos(const vtkm::Id& idx) const { return Particle.Get(idx).Pos; }
VTKM_EXEC
vtkm::Id GetStep(const vtkm::Id& idx) const { return Particle.Get(idx).NumSteps; }
VTKM_EXEC
vtkm::Id GetStatus(const vtkm::Id& idx) const { return Particle.Get(idx).Status; }
VTKM_EXEC
vtkm::FloatDefault GetTime(const vtkm::Id& idx) const { return Particle.Get(idx).Time; }
// VTKM_EXEC
// void SetTime(const vtkm::Id& idx, vtkm::FloatDefault time) const { Time.Set(idx, time); }
protected:
using ParticlePortal =
typename vtkm::cont::ArrayHandle<vtkm::Particle>::template ExecutionTypes<Device>::Portal;
ParticlePortal Particle;
vtkm::Id MaxSteps;
};
class ParticlesAOS : public vtkm::cont::ExecutionObjectBase
{
public:
template <typename Device>
VTKM_CONT vtkm::worklet::particleadvection::ParticleExecutionObjectAOS<Device>
PrepareForExecution(Device) const
{
return vtkm::worklet::particleadvection::ParticleExecutionObjectAOS<Device>(this->ParticleArray,
this->MaxSteps);
}
VTKM_CONT
ParticlesAOS(vtkm::cont::ArrayHandle<vtkm::Particle>& pArray, const vtkm::Id& maxSteps)
: ParticleArray(pArray)
, MaxSteps(maxSteps)
{
}
ParticlesAOS() {}
protected:
vtkm::cont::ArrayHandle<vtkm::Particle> ParticleArray;
vtkm::Id MaxSteps;
};
#if 0
template <typename Device>
class StateRecordingParticleExecutionObject : public ParticleExecutionObject<Device>
{
public:
VTKM_EXEC_CONT
StateRecordingParticleExecutionObject()
: ParticleExecutionObject<Device>()
, History()
, Length(0)
, ValidPoint()
{
}
StateRecordingParticleExecutionObject(vtkm::cont::ArrayHandle<vtkm::Vec3f> posArray,
vtkm::cont::ArrayHandle<vtkm::Vec3f> historyArray,
vtkm::cont::ArrayHandle<vtkm::Id> stepsArray,
vtkm::cont::ArrayHandle<vtkm::Id> statusArray,
vtkm::cont::ArrayHandle<vtkm::FloatDefault> timeArray,
vtkm::cont::ArrayHandle<vtkm::Id> validPointArray,
vtkm::Id maxSteps)
: ParticleExecutionObject<Device>(posArray, stepsArray, statusArray, timeArray, maxSteps)
{
Length = maxSteps;
vtkm::Id numPos = posArray.GetNumberOfValues();
History = historyArray.PrepareForOutput(numPos * Length, Device());
ValidPoint = validPointArray.PrepareForInPlace(Device());
}
VTKM_EXEC_CONT
void TakeStep(const vtkm::Id& idx, const vtkm::Vec3f& pt)
{
this->ParticleExecutionObject<Device>::TakeStep(idx, pt);
//TakeStep incremented the step, so we want the PREV step value.
vtkm::Id nSteps = this->Steps.Get(idx) - 1;
// Update the step for streamline storing portals.
// This includes updating the history and the valid points.
vtkm::Id loc = idx * Length + nSteps;
this->History.Set(loc, pt);
this->ValidPoint.Set(loc, 1);
}
vtkm::Vec3f GetHistory(const vtkm::Id& idx, const vtkm::Id& step) const
{
return this->History.Get(idx * this->Length + step);
}
protected:
using IdPortal =
typename vtkm::cont::ArrayHandle<vtkm::Id>::template ExecutionTypes<Device>::Portal;
using PositionPortal =
typename vtkm::cont::ArrayHandle<vtkm::Vec3f>::template ExecutionTypes<Device>::Portal;
PositionPortal History;
vtkm::Id Length;
IdPortal ValidPoint;
};
class StateRecordingParticles : vtkm::cont::ExecutionObjectBase
{
public:
template <typename Device>
VTKM_CONT vtkm::worklet::particleadvection::StateRecordingParticleExecutionObject<Device>
PrepareForExecution(Device) const
{
return vtkm::worklet::particleadvection::StateRecordingParticleExecutionObject<Device>(
PosArray, HistoryArray, StepsArray, StatusArray, TimeArray, ValidPointArray, MaxSteps);
}
VTKM_CONT
StateRecordingParticles(vtkm::cont::ArrayHandle<vtkm::Vec3f>& posArray,
vtkm::cont::ArrayHandle<vtkm::Vec3f>& historyArray,
vtkm::cont::ArrayHandle<vtkm::Id>& stepsArray,
vtkm::cont::ArrayHandle<vtkm::Id>& statusArray,
vtkm::cont::ArrayHandle<vtkm::FloatDefault>& timeArray,
vtkm::cont::ArrayHandle<vtkm::Id>& validPointArray,
const vtkm::Id& maxSteps)
{
PosArray = posArray;
HistoryArray = historyArray;
StepsArray = stepsArray;
StatusArray = statusArray;
TimeArray = timeArray;
ValidPointArray = validPointArray;
MaxSteps = maxSteps;
}
protected:
vtkm::cont::ArrayHandle<vtkm::Id> StepsArray;
vtkm::cont::ArrayHandle<vtkm::Id> StatusArray;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> TimeArray;
vtkm::cont::ArrayHandle<vtkm::Id> ValidPointArray;
vtkm::cont::ArrayHandle<vtkm::Vec3f> HistoryArray;
vtkm::cont::ArrayHandle<vtkm::Vec3f> PosArray;
vtkm::Id MaxSteps;
};
#endif
} //namespace particleadvection
} //namespace worklet
} //namespace vtkm
#endif // vtk_m_worklet_particleadvection_Particles_AOS_h