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:
Abhishek Yenpure 2022-08-14 18:58:51 -07:00 committed by Abhishek Yenpure
parent 2dc485ac22
commit 606223edd2
8 changed files with 217 additions and 38 deletions

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7a569aff0c6872611ef75a4dcb597e1320cb966b80f840a0dbd76a29b2760dbb
size 50335052

@ -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

@ -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);
}