mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
Fixing choice of dataset integrator
Adding updates Adding WarpX data and unit test Fixing code from feedback Fixing code from Ollie and Dave's feedback Reducing WarpX dataset size Fixing high precision requirement to store properties Fixing Particle Sizeof Fixing high precision requirement to store properties fixing code from Ollie and Dave's feedback Trying test Fixing ChargedParticle serailization for MPI
This commit is contained in:
parent
2dc485ac22
commit
606223edd2
3
data/data/misc/warpXfields.vtk
Normal file
3
data/data/misc/warpXfields.vtk
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7a569aff0c6872611ef75a4dcb597e1320cb966b80f840a0dbd76a29b2760dbb
|
||||
size 50335052
|
3
data/data/misc/warpXparticles.vtk
Normal file
3
data/data/misc/warpXparticles.vtk
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:671345bdb045aeadc8e9fa1060de51e53286c74929c6c8c60a529b318f02bbfc
|
||||
size 3795
|
@ -164,9 +164,9 @@ public:
|
||||
VTKM_EXEC_CONT
|
||||
ChargedParticle(const vtkm::Vec3f& position,
|
||||
const vtkm::Id& id,
|
||||
const vtkm::FloatDefault& mass,
|
||||
const vtkm::FloatDefault& charge,
|
||||
const vtkm::FloatDefault& weighting,
|
||||
const vtkm::Float64& mass,
|
||||
const vtkm::Float64& charge,
|
||||
const vtkm::Float64& weighting,
|
||||
const vtkm::Vec3f& momentum,
|
||||
const vtkm::Id& numSteps = 0,
|
||||
const vtkm::ParticleStatus& status = vtkm::ParticleStatus(),
|
||||
@ -184,16 +184,16 @@ public:
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::FloatDefault Gamma(vtkm::Vec3f momentum, bool reciprocal = false) const
|
||||
vtkm::Float64 Gamma(vtkm::Vec3f momentum, bool reciprocal = false) const
|
||||
{
|
||||
constexpr vtkm::FloatDefault c2 = SPEED_OF_LIGHT * SPEED_OF_LIGHT;
|
||||
const auto fMom2 = vtkm::MagnitudeSquared(momentum);
|
||||
const auto m2 = this->Mass * this->Mass;
|
||||
const auto m2_c2_reci = 1.0 / (m2 * c2);
|
||||
const vtkm::Float64 fMom2 = vtkm::MagnitudeSquared(momentum);
|
||||
const vtkm::Float64 m2 = this->Mass * this->Mass;
|
||||
const vtkm::Float64 m2_c2_reci = 1.0 / (m2 * c2);
|
||||
if (reciprocal)
|
||||
return static_cast<vtkm::FloatDefault>(vtkm::RSqrt(1.0 + fMom2 * m2_c2_reci));
|
||||
return vtkm::RSqrt(1.0 + fMom2 * m2_c2_reci);
|
||||
else
|
||||
return static_cast<vtkm::FloatDefault>(vtkm::Sqrt(1.0 + fMom2 * m2_c2_reci));
|
||||
return vtkm::Sqrt(1.0 + fMom2 * m2_c2_reci);
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
@ -208,11 +208,11 @@ public:
|
||||
vtkm::Vec3f eField = vectors[0];
|
||||
vtkm::Vec3f bField = vectors[1];
|
||||
|
||||
const vtkm::FloatDefault QoM = this->Charge / this->Mass;
|
||||
const vtkm::Float64 QoM = this->Charge / this->Mass;
|
||||
const vtkm::Vec3f mom_minus = this->Momentum + (0.5 * this->Charge * eField * length);
|
||||
|
||||
// Get reciprocal of Gamma
|
||||
vtkm::Vec3f gamma_reci = this->Gamma(mom_minus, true);
|
||||
vtkm::Vec3f gamma_reci = static_cast<vtkm::FloatDefault>(this->Gamma(mom_minus, true));
|
||||
const vtkm::Vec3f t = 0.5 * QoM * length * bField * gamma_reci;
|
||||
const vtkm::Vec3f s = 2.0f * t * (1.0 / (1.0 + vtkm::Magnitude(t)));
|
||||
const vtkm::Vec3f mom_prime = mom_minus + vtkm::Cross(mom_minus, t);
|
||||
@ -254,9 +254,9 @@ public:
|
||||
vtkm::FloatDefault Time = 0;
|
||||
|
||||
private:
|
||||
vtkm::FloatDefault Mass;
|
||||
vtkm::FloatDefault Charge;
|
||||
vtkm::FloatDefault Weighting;
|
||||
vtkm::Float64 Mass;
|
||||
vtkm::Float64 Charge;
|
||||
vtkm::Float64 Weighting;
|
||||
vtkm::Vec3f Momentum;
|
||||
constexpr static vtkm::FloatDefault SPEED_OF_LIGHT =
|
||||
static_cast<vtkm::FloatDefault>(2.99792458e8);
|
||||
@ -271,11 +271,10 @@ public:
|
||||
+ sizeof(vtkm::Id) // NumSteps
|
||||
+ sizeof(vtkm::UInt8) // Status
|
||||
+ sizeof(vtkm::FloatDefault) // Time
|
||||
+ sizeof(vtkm::FloatDefault) //Mass
|
||||
+ sizeof(vtkm::FloatDefault) //Charge
|
||||
+ sizeof(vtkm::FloatDefault) //Weighting
|
||||
+ sizeof(vtkm::Vec3f) //Momentum
|
||||
+ sizeof(vtkm::FloatDefault); //Speed_of_light
|
||||
+ sizeof(vtkm::Float64) //Mass
|
||||
+ sizeof(vtkm::Float64) //Charge
|
||||
+ sizeof(vtkm::Float64) //Weighting
|
||||
+ sizeof(vtkm::Vec3f); //Momentum
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
@ -64,6 +64,17 @@ public:
|
||||
this->VecFieldType = vecFieldType;
|
||||
}
|
||||
|
||||
//@{
|
||||
/// Choose the field to operate on. Note, if
|
||||
/// `this->UseCoordinateSystemAsField` is true, then the active field is not used.
|
||||
VTKM_CONT void SetEField(const std::string& name) { this->SetActiveField(0, name); }
|
||||
|
||||
VTKM_CONT void SetBField(const std::string& name) { this->SetActiveField(1, name); }
|
||||
|
||||
VTKM_CONT std::string GetEField() const { return this->GetActiveFieldName(0); }
|
||||
|
||||
VTKM_CONT std::string GetBField() const { return this->GetActiveFieldName(1); }
|
||||
|
||||
VTKM_CONT
|
||||
bool GetUseThreadedAlgorithm() { return this->UseThreadedAlgorithm; }
|
||||
|
||||
|
@ -24,12 +24,14 @@ namespace flow
|
||||
namespace
|
||||
{
|
||||
VTKM_CONT std::vector<vtkm::filter::flow::internal::DataSetIntegratorSteadyState>
|
||||
CreateDataSetIntegrators(const vtkm::cont::PartitionedDataSet& input,
|
||||
const std::pair<std::string, std::string>& activeField,
|
||||
const vtkm::filter::flow::internal::BoundsMap& boundsMap,
|
||||
const vtkm::filter::flow::IntegrationSolverType solverType,
|
||||
const vtkm::filter::flow::VectorFieldType vecFieldType,
|
||||
const vtkm::filter::flow::FlowResultType resultType)
|
||||
CreateDataSetIntegrators(
|
||||
const vtkm::cont::PartitionedDataSet& input,
|
||||
const vtkm::cont::internal::Variant<std::string, std::pair<std::string, std::string>>&
|
||||
activeField,
|
||||
const vtkm::filter::flow::internal::BoundsMap& boundsMap,
|
||||
const vtkm::filter::flow::IntegrationSolverType solverType,
|
||||
const vtkm::filter::flow::VectorFieldType vecFieldType,
|
||||
const vtkm::filter::flow::FlowResultType resultType)
|
||||
{
|
||||
using DSIType = vtkm::filter::flow::internal::DataSetIntegratorSteadyState;
|
||||
|
||||
@ -38,14 +40,24 @@ CreateDataSetIntegrators(const vtkm::cont::PartitionedDataSet& input,
|
||||
{
|
||||
vtkm::Id blockId = boundsMap.GetLocalBlockId(i);
|
||||
auto ds = input.GetPartition(i);
|
||||
if (!ds.HasPointField(activeField.first) && !ds.HasCellField(activeField.first))
|
||||
throw vtkm::cont::ErrorFilterExecution("Unsupported field assocation");
|
||||
if (!ds.HasPointField(activeField.second) && !ds.HasCellField(activeField.second))
|
||||
throw vtkm::cont::ErrorFilterExecution("Unsupported field assocation");
|
||||
|
||||
if (activeField.IsType<DSIType::VelocityFieldNameType>())
|
||||
{
|
||||
const auto& fieldNm = activeField.Get<DSIType::VelocityFieldNameType>();
|
||||
if (!ds.HasPointField(fieldNm) && !ds.HasCellField(fieldNm))
|
||||
throw vtkm::cont::ErrorFilterExecution("Unsupported field assocation");
|
||||
}
|
||||
else if (activeField.IsType<DSIType::ElectroMagneticFieldNameType>())
|
||||
{
|
||||
const auto& fieldNm = activeField.Get<DSIType::ElectroMagneticFieldNameType>();
|
||||
const auto& electric = fieldNm.first;
|
||||
const auto& magnetic = fieldNm.second;
|
||||
if (!ds.HasPointField(electric) && !ds.HasCellField(electric))
|
||||
throw vtkm::cont::ErrorFilterExecution("Unsupported field assocation");
|
||||
if (!ds.HasPointField(magnetic) && !ds.HasCellField(magnetic))
|
||||
throw vtkm::cont::ErrorFilterExecution("Unsupported field assocation");
|
||||
}
|
||||
dsi.emplace_back(ds, blockId, activeField, solverType, vecFieldType, resultType);
|
||||
}
|
||||
|
||||
return dsi;
|
||||
}
|
||||
|
||||
@ -57,11 +69,25 @@ VTKM_CONT vtkm::cont::PartitionedDataSet NewFilterParticleAdvectionSteadyState::
|
||||
using DSIType = vtkm::filter::flow::internal::DataSetIntegratorSteadyState;
|
||||
this->ValidateOptions();
|
||||
|
||||
std::pair<std::string, std::string> field("E", "B");
|
||||
using VariantType =
|
||||
vtkm::cont::internal::Variant<std::string, std::pair<std::string, std::string>>;
|
||||
VariantType variant;
|
||||
|
||||
if (this->VecFieldType == vtkm::filter::flow::VectorFieldType::VELOCITY_FIELD_TYPE)
|
||||
{
|
||||
const auto& field = this->GetActiveFieldName();
|
||||
variant.Emplace<DSIType::VelocityFieldNameType>(field);
|
||||
}
|
||||
else if (this->VecFieldType == vtkm::filter::flow::VectorFieldType::ELECTRO_MAGNETIC_FIELD_TYPE)
|
||||
{
|
||||
const auto& electric = this->GetEField();
|
||||
const auto& magnetic = this->GetBField();
|
||||
variant.Emplace<DSIType::ElectroMagneticFieldNameType>(electric, magnetic);
|
||||
}
|
||||
|
||||
vtkm::filter::flow::internal::BoundsMap boundsMap(input);
|
||||
auto dsi = CreateDataSetIntegrators(
|
||||
input, field, boundsMap, this->SolverType, this->VecFieldType, this->GetResultType());
|
||||
input, variant, boundsMap, this->SolverType, this->VecFieldType, this->GetResultType());
|
||||
|
||||
vtkm::filter::flow::internal::ParticleAdvector<DSIType> pav(
|
||||
boundsMap, dsi, this->UseThreadedAlgorithm, this->GetResultType());
|
||||
|
@ -55,7 +55,7 @@ protected:
|
||||
VTKM_CONT void GetVelocityField(
|
||||
vtkm::worklet::flow::VelocityField<ArrayType>& velocityField) const
|
||||
{
|
||||
if (this->FieldName.GetIndex() == this->FieldName.GetIndexOf<VelocityFieldNameType>())
|
||||
if (this->FieldName.IsType<VelocityFieldNameType>())
|
||||
{
|
||||
const auto& fieldNm = this->FieldName.Get<VelocityFieldNameType>();
|
||||
auto assoc = this->DataSet.GetField(fieldNm).GetAssociation();
|
||||
@ -72,20 +72,25 @@ protected:
|
||||
VTKM_CONT void GetElectroMagneticField(
|
||||
vtkm::worklet::flow::ElectroMagneticField<ArrayType>& ebField) const
|
||||
{
|
||||
if (this->FieldName.GetIndex() == this->FieldName.GetIndexOf<ElectroMagneticFieldNameType>())
|
||||
if (this->FieldName.IsType<ElectroMagneticFieldNameType>())
|
||||
{
|
||||
const auto& fieldNm = this->FieldName.Get<ElectroMagneticFieldNameType>();
|
||||
const auto& electric = fieldNm.first;
|
||||
const auto& magnetic = fieldNm.second;
|
||||
auto assoc = this->DataSet.GetField(electric).GetAssociation();
|
||||
auto eAssoc = this->DataSet.GetField(electric).GetAssociation();
|
||||
auto bAssoc = this->DataSet.GetField(magnetic).GetAssociation();
|
||||
|
||||
if (eAssoc != bAssoc)
|
||||
{
|
||||
throw vtkm::cont::ErrorFilterExecution("E and B field need to have same association");
|
||||
}
|
||||
ArrayType eField, bField;
|
||||
vtkm::cont::ArrayCopyShallowIfPossible(this->DataSet.GetField(electric).GetData(), eField);
|
||||
vtkm::cont::ArrayCopyShallowIfPossible(this->DataSet.GetField(magnetic).GetData(), bField);
|
||||
ebField = vtkm::worklet::flow::ElectroMagneticField<ArrayType>(eField, bField, assoc);
|
||||
ebField = vtkm::worklet::flow::ElectroMagneticField<ArrayType>(eField, bField, eAssoc);
|
||||
}
|
||||
else
|
||||
throw vtkm::cont::ErrorFilterExecution("Velocity field vector type not available");
|
||||
throw vtkm::cont::ErrorFilterExecution("Electromagnetic field vector type not available");
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
set(filter_unit_tests
|
||||
UnitTestStreamlineFilter.cxx
|
||||
UnitTestStreamlineFilterWarpX.cxx
|
||||
UnitTestStreamSurfaceFilter.cxx
|
||||
)
|
||||
set(worklet_unit_tests
|
||||
|
131
vtkm/filter/flow/testing/UnitTestStreamlineFilterWarpX.cxx
Normal file
131
vtkm/filter/flow/testing/UnitTestStreamlineFilterWarpX.cxx
Normal file
@ -0,0 +1,131 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/Particle.h>
|
||||
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/filter/flow/Streamline.h>
|
||||
#include <vtkm/io/VTKDataSetReader.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class GetChargedParticles : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
GetChargedParticles() {}
|
||||
|
||||
using ControlSignature = void(FieldIn pos,
|
||||
FieldIn mom,
|
||||
FieldIn mass,
|
||||
FieldIn charge,
|
||||
FieldIn weighting,
|
||||
FieldOut electrons);
|
||||
|
||||
using ExecutionSignature = void(WorkIndex, _1, _2, _3, _4, _5, _6);
|
||||
|
||||
void operator()(const vtkm::Id index,
|
||||
const vtkm::Vec3f& pos,
|
||||
const vtkm::Vec3f& mom,
|
||||
const vtkm::Float64& mass,
|
||||
const vtkm::Float64& charge,
|
||||
const vtkm::Float64& w,
|
||||
vtkm::ChargedParticle& electron) const
|
||||
{
|
||||
electron = vtkm::ChargedParticle(pos, index, mass, charge, w, mom);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void GenerateChargedParticles(const vtkm::cont::ArrayHandle<vtkm::Vec3f>& pos,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec3f>& mom,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float64>& mass,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float64>& charge,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float64>& weight,
|
||||
vtkm::cont::ArrayHandle<vtkm::ChargedParticle>& seeds)
|
||||
{
|
||||
vtkm::cont::Invoker invoker;
|
||||
invoker(GetChargedParticles{}, pos, mom, mass, charge, weight, seeds);
|
||||
}
|
||||
|
||||
|
||||
void TestStreamlineFilters()
|
||||
{
|
||||
std::string particleFile = vtkm::cont::testing::Testing::DataPath("misc/warpXparticles.vtk");
|
||||
std::string fieldFile = vtkm::cont::testing::Testing::DataPath("misc/warpXfields.vtk");
|
||||
|
||||
using SeedsType = vtkm::cont::ArrayHandle<vtkm::ChargedParticle>;
|
||||
|
||||
SeedsType seeds;
|
||||
vtkm::io::VTKDataSetReader seedsReader(particleFile);
|
||||
vtkm::cont::DataSet seedsData = seedsReader.ReadDataSet();
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> pos, mom;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64> mass, charge, w;
|
||||
|
||||
seedsData.GetCoordinateSystem().GetDataAsDefaultFloat().AsArrayHandle(pos);
|
||||
seedsData.GetField("Momentum").GetDataAsDefaultFloat().AsArrayHandle(mom);
|
||||
seedsData.GetField("Mass").GetData().AsArrayHandle(mass);
|
||||
seedsData.GetField("Charge").GetData().AsArrayHandle(charge);
|
||||
seedsData.GetField("Weighting").GetData().AsArrayHandle(w);
|
||||
|
||||
GenerateChargedParticles(pos, mom, mass, charge, w, seeds);
|
||||
|
||||
vtkm::io::VTKDataSetReader dataReader(fieldFile);
|
||||
vtkm::cont::DataSet dataset = dataReader.ReadDataSet();
|
||||
vtkm::cont::UnknownCellSet cells = dataset.GetCellSet();
|
||||
vtkm::cont::CoordinateSystem coords = dataset.GetCoordinateSystem();
|
||||
|
||||
auto bounds = coords.GetBounds();
|
||||
std::cout << "Bounds : " << bounds << std::endl;
|
||||
using Structured3DType = vtkm::cont::CellSetStructured<3>;
|
||||
Structured3DType castedCells;
|
||||
cells.AsCellSet(castedCells);
|
||||
auto dims = castedCells.GetSchedulingRange(vtkm::TopologyElementTagPoint());
|
||||
vtkm::Vec3f spacing = { static_cast<vtkm::FloatDefault>(bounds.X.Length()) / (dims[0] - 1),
|
||||
static_cast<vtkm::FloatDefault>(bounds.Y.Length()) / (dims[1] - 1),
|
||||
static_cast<vtkm::FloatDefault>(bounds.Z.Length()) / (dims[2] - 1) };
|
||||
std::cout << spacing << std::endl;
|
||||
constexpr static vtkm::FloatDefault SPEED_OF_LIGHT =
|
||||
static_cast<vtkm::FloatDefault>(2.99792458e8);
|
||||
spacing = spacing * spacing;
|
||||
|
||||
|
||||
vtkm::Id steps = 50;
|
||||
vtkm::FloatDefault length = static_cast<vtkm::FloatDefault>(
|
||||
1.0 / (SPEED_OF_LIGHT * vtkm::Sqrt(1. / spacing[0] + 1. / spacing[1] + 1. / spacing[2])));
|
||||
std::cout << "CFL length : " << length << std::endl;
|
||||
|
||||
vtkm::filter::flow::Streamline streamline;
|
||||
|
||||
streamline.SetStepSize(length);
|
||||
streamline.SetNumberOfSteps(steps);
|
||||
streamline.SetSeeds(seeds);
|
||||
streamline.SetVectorFieldType(vtkm::filter::flow::VectorFieldType::ELECTRO_MAGNETIC_FIELD_TYPE);
|
||||
streamline.SetEField("E");
|
||||
streamline.SetBField("B");
|
||||
std::cout << "[pre] Executing test" << std::endl;
|
||||
auto output = streamline.Execute(dataset);
|
||||
std::cout << "[post] Executing test" << std::endl;
|
||||
std::cout << "[pre] Executing asserts" << std::endl;
|
||||
VTKM_TEST_ASSERT(output.GetNumberOfCoordinateSystems() == 1,
|
||||
"Wrong number of coordinate systems in the output dataset");
|
||||
VTKM_TEST_ASSERT(output.GetCoordinateSystem().GetNumberOfPoints() == 2550,
|
||||
"Wrong number of coordinates");
|
||||
VTKM_TEST_ASSERT(output.GetCellSet().GetNumberOfCells() == 50, "Wrong number of cells");
|
||||
std::cout << "[post] Executing asserts" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int UnitTestStreamlineFilterWarpX(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestStreamlineFilters, argc, argv);
|
||||
}
|
Loading…
Reference in New Issue
Block a user