private void GetNeighbors_3OtherPrimaryParticlesAre2DClose_1isTooFarAway() { var r = 5; var pos = new Vector3(0, 0, 100); var primaryParticle = new PrimaryParticle(0, pos, r); var handler = new BallisticSingleParticleDepositionHandler(); var pos2 = new Vector3(0, 3, 10); var pos3 = new Vector3(3, -3, 10); var pos4 = new Vector3(-3, -3, 10); var pos5 = new Vector3(-30, -30, 10); var pp2 = new PrimaryParticle(1, pos2, r); var pp3 = new PrimaryParticle(2, pos3, r); var pp4 = new PrimaryParticle(3, pos4, r); var pp5 = new PrimaryParticle(4, pos5, r); var particles = new List <PrimaryParticle>() { pp2, pp3, pp4, pp5 }; var neighborsList = _neighborslistFactory.Build2DNeighborslist(particles); var maxRadius = particles.GetMaxRadius(); var searchRadius = (primaryParticle.Radius + maxRadius) * _config.Delta; var neighbors = neighborsList.GetPrimaryParticlesWithinRadius(primaryParticle.Position, searchRadius); //var neighbors = handler.GetNeighbors(primaryParticle, neighborsList, maxRadius); Assert.Equal(3, neighbors.Count()); foreach (var neighbor in neighbors) { Assert.NotEqual(pos5, neighbor.Position); } }
private void ComputeCorrectMinDepositionDistance_CollisionWithPrimaryParticleTwoNeighbors() { var r = 1.0; var pos = new Vector3(0, 0, 100); var primaryParticle = new PrimaryParticle(0, pos, r); var handler = new BallisticSingleParticleDepositionHandler(); var pos2 = new Vector3(1, 0, 10); var pp2 = new PrimaryParticle(1, pos2, r); var pos3 = new Vector3(1, 0, 5); var pp3 = new PrimaryParticle(1, pos3, r); var otherParticles = new List <PrimaryParticle>() { pp2, pp3 }; var neighborsList = _neighborslistFactory.Build2DNeighborslist(otherParticles); var dist = handler.GetDepositionDistance(primaryParticle, otherParticles, neighborsList, otherParticles.GetMaxRadius(), _config.Delta); var shouldBeDistance = 90 - Math.Sqrt(3); Assert.Equal(shouldBeDistance, dist); }
private static Aggregate GetExampleAggregate() { var radius = 1.0; var p11 = new PrimaryParticle(0, new Vector3(0, 0, 100), radius); var p12 = new PrimaryParticle(1, new Vector3(2 * radius, 0, 100), radius); var p13 = new PrimaryParticle(2, new Vector3(0, 2 * radius, 100), radius); var p14 = new PrimaryParticle(3, new Vector3(2 * radius, 2 * radius, 100), radius); var cluster1 = new Cluster(0, new List <PrimaryParticle>() { p11, p12, p13, p14 }); var p21 = new PrimaryParticle(0, new Vector3(0, 0, 100 - 2 * radius), radius); var p22 = new PrimaryParticle(1, new Vector3(2 * radius, 0, 100 - 2 * radius), radius); var p23 = new PrimaryParticle(2, new Vector3(0, 2 * radius, 100 - 2 * radius), radius); var p24 = new PrimaryParticle(3, new Vector3(2 * radius, 2 * radius, 100 - 2 * radius), radius); var cluster2 = new Cluster(0, new List <PrimaryParticle>() { p21, p22, p23, p24 }); var aggregate = new Aggregate(new List <Cluster>() { cluster1, cluster2 }); return(aggregate); }
public void TrySetClusterTest() { var pp1 = new PrimaryParticle(1, new Vector3(0, 0, 0), 5); var pp2 = new PrimaryParticle(2, new Vector3(0, 0, 10), 5); var cca = new ClusterClusterAggregationFactory(_monoPSD, _config, _logger, _neighborslistFactory, _seed); var cluster1 = new Cluster(1, new List <PrimaryParticle>() { pp1, pp2 }); var depositedCluster = new List <Cluster> { cluster1 }; var neighborslist = _neighborslistFactory.Build3DNeighborslist(cluster1.PrimaryParticles); var pp3 = new PrimaryParticle(3, new Vector3(0, 0, 30), 5); var pp4 = new PrimaryParticle(4, new Vector3(0, 0, 20), 5); var cluster2 = new Cluster(1, new List <PrimaryParticle>() { pp3, pp4 }); var position = new Vector3(0, 0, 25.02); cluster2.MoveTo(position); var set = cca.IsClusterPositionValid(cluster2, neighborslist, depositedCluster); Assert.True(set); var position2 = new Vector3(0, 0, 24); cluster2.MoveTo(position2); var set2 = cca.IsClusterPositionValid(cluster2, neighborslist, depositedCluster); Assert.False(set2); }
/// <summary> /// Since there is a nearby primary particle, check if the position is valid: /// (1) there is at least 1 contact with other primary particles /// (2) there are no overlaps. /// </summary> /// <param name="particle"></param> /// <param name="primaryParticles"></param> /// <param name="config"></param> /// <param name="neighbors"></param> /// <returns></returns> private static bool IsAnyNeighborPositionValid( PrimaryParticle particle, Vector3 setToPosition, IAggregateFormationConfig config, IEnumerable <Tuple <PrimaryParticle, double> > neighborsWithDistance) { var(isInContact, hasNoOverlap) = ParticleFormationUtil.IsAnyNeighborInContactOrOverlapping(particle, setToPosition, config, neighborsWithDistance); return(isInContact && hasNoOverlap); }
private void CheckXDimension(PrimaryParticle primaryParticle, ISimulationBox simulationBox) { if (primaryParticle.Position.X > simulationBox.XDim.Upper) { primaryParticle.MoveBy(new Vector3(-1 * simulationBox.XDim.Width, 0, 0)); } if (primaryParticle.Position.X < simulationBox.XDim.Lower) { primaryParticle.MoveBy(new Vector3(simulationBox.XDim.Width, 0, 0)); } }
private static IEnumerable <PrimaryParticle> GetDepositedParticlesFarAway() { var radius = 1.0; var pos2 = new Vector3(30, 30, 1); var pp2 = new PrimaryParticle(1, pos2, radius); return(new List <PrimaryParticle>() { pp2 }); }
private void CheckYDimension(PrimaryParticle primaryParticle, ISimulationBox simulationBox) { if (primaryParticle.Position.Y > simulationBox.YDim.Upper) { primaryParticle.MoveBy(new Vector3(0, -1 * simulationBox.YDim.Width, 0)); } if (primaryParticle.Position.Y < simulationBox.YDim.Lower) { primaryParticle.MoveBy(new Vector3(0, simulationBox.YDim.Width, 0)); } }
private void DistanceToCenterLine_CorrectDistanceComputed() { var r = 5; var pos = new Vector3(0, 0, 100); var primaryParticle = new PrimaryParticle(0, pos, r); var neighborPosposition = new[] { 1.0, 1.0 }; var dist = primaryParticle.GetDistanceToVerticalAxis(neighborPosposition); Assert.Equal(Math.Sqrt(2), dist); }
/// <summary> /// Search in a defined radius around the primary particles if there are any more primary particles. /// </summary> /// <param name="primaryParticle">Primary particle that will be positioned</param> /// <param name="randomPosition">The random position where the primary particle might be positioned</param> /// <param name="otherPrimaryParticles">All primary particles that are already deposited (and remain fixed)</param> /// <param name="config"></param> /// <returns></returns> public static List <NodeDistance <KDTreeNode <double> > > GetPossibleNeighbors( PrimaryParticle primaryParticle, Vector3 randomPosition, KDTree <double> tree, IEnumerable <PrimaryParticle> otherPrimaryParticles, IAggregateFormationConfig config) { var searchRadius = (primaryParticle.Radius + otherPrimaryParticles.GetMaxRadius()) * config.Delta; var neighbors = tree.Nearest(randomPosition.ToArray(), radius: searchRadius); return(neighbors); }
private static void AddParticleToAggregates(List <Aggregate> aggregates, string line, Dictionary <string, int> map) { var primaryParticleId = Convert.ToInt32(line[map["id"]]); var aggregateId = Convert.ToInt32(line[map["aggregate"]]); var clusterId = Convert.ToInt32(line[map["cluster"]]); var x = Convert.ToDouble(line[map["x"]], CultureInfo.InvariantCulture); var y = Convert.ToDouble(line[map["y"]], CultureInfo.InvariantCulture); var z = Convert.ToDouble(line[map["z"]], CultureInfo.InvariantCulture); var radius = Convert.ToDouble(line[map["Radius"]], CultureInfo.InvariantCulture); var position = new Vector3(x, y, z); var pp = new PrimaryParticle(primaryParticleId, position, radius); var clus = GetCluster(aggregates, aggregateId, clusterId); clus.PrimaryParticles.Add(pp); }
private void ComputeCorrectDepositionDistance_CollisionWithParticle() { var r = 1.0; var pos = new Vector3(0, 0, 100); var primaryParticle = new PrimaryParticle(0, pos, r); var neighbor = new PrimaryParticle(1, new Vector3(1, 0, 10), 1.0); var dist = BallisticSingleParticleDepositionHandler.Get1DDistanceToNeighbor(primaryParticle, neighbor); // Math.Sqrt(3) results from the square of the combined radius (4) - the distance to centerline. // This origins from the triangle: final position pp1. position neigbor, center projection neighbor. var shouldBeDistance = 90 - Math.Sqrt(3); Assert.Equal(shouldBeDistance, dist); }
/// <summary> /// (1) Check for the specific primary particles if the position is valid: no overlap /// (2) Check if any other primary particle is in contact /// </summary> /// <param name="tree">neighborListTree</param> /// <param name="primaryParticle">primary particle of interest</param> /// <param name="otherPrimaryParticles">all other fixed primary particles</param> /// <param name="config"></param> /// <returns></returns> public (bool isInContact, bool hasNoOverlap) IsPrimaryParticlePositionValid( INeighborslist neighborslist, PrimaryParticle primaryParticle, IEnumerable <PrimaryParticle> otherPrimaryParticles) { //var neighbors = ParticleFormationUtil.GetPossibleNeighbors(primaryParticle, primaryParticle.Position, tree, otherPrimaryParticles, config); var searchRadius = (primaryParticle.Radius + otherPrimaryParticles.GetMaxRadius()) * _config.Delta; var neighborsWithDistance = neighborslist.GetPrimaryParticlesAndDistanceWithinRadius(primaryParticle.Position, searchRadius); if (!neighborsWithDistance.Any()) { return(isInContact : false, hasNoOverlap : true); } return(ParticleFormationUtil.IsAnyNeighborInContactOrOverlapping(primaryParticle, primaryParticle.Position, _config, neighborsWithDistance)); }
internal static double Get1DDistanceToNeighbor(PrimaryParticle primaryParticle, PrimaryParticle neighbor) { var distanceToCenterline = primaryParticle.GetDistanceToVerticalAxis(neighbor); var combinedRadius = neighbor.Radius + primaryParticle.Radius; // If the neighbor is close but it won't be hit during deposition return max deposition distance if (distanceToCenterline > combinedRadius) { return(primaryParticle.Position.Z - primaryParticle.Radius); } var extraHeight = Math.Sqrt(Math.Pow(combinedRadius, 2) - Math.Pow(distanceToCenterline, 2)); var distance = primaryParticle.Position.Z - neighbor.Position.Z - extraHeight; return(distance); }
/// <summary> /// The second primary particle position is determined by its and the radius of the initial primary particle /// </summary> /// <param name="primaryParticles"></param> public void SetSecondPrimaryParticle(List <PrimaryParticle> primaryParticles) { var radius = _psd.GetRandomSize(); // Distance of the CenterOfMass (com) of the second pp from the com // of the first pp var particle = new PrimaryParticle(0, radius); // Position the second primary particle directly in contact with the first var ppDistance = _config.Epsilon * (primaryParticles[0].Radius + particle.Radius); // Get any random position withon that distance var rndPosition = ParticleFormationUtil.GetRandomPosition(_rndGen, ppDistance); particle.MoveTo(rndPosition); primaryParticles.Add(particle); }
public static (bool isInContact, bool hasNoOverlap) IsAnyNeighborInContactOrOverlapping( PrimaryParticle particle, Vector3 setToPosition, IAggregateFormationConfig config, IEnumerable <Tuple <PrimaryParticle, double> > neighborsWithDistance) { var isInContact = false; var hasNoOverlap = true; foreach (var neigh in neighborsWithDistance) { var radiusParticle2 = neigh.Item1.Radius; var distance = neigh.Item2; isInContact = isInContact || IsInContact(distance, particle.Radius, radiusParticle2, config.Delta); hasNoOverlap = hasNoOverlap && HasNoOverlap(distance, particle.Radius, radiusParticle2, config.Epsilon); } return(isInContact, hasNoOverlap); }
/// <summary> /// A primary particle positon is valid if: /// (1) there is at least 1 contact with other primary particles /// (2) there are no overlaps. /// </summary> /// <param name="particle"></param> /// <param name="rndPosition"></param> /// <param name="tree"></param> /// <param name="primaryParticles"></param> /// <param name="config"></param> /// <returns></returns> public bool IsPrimaryParticlePositionValid( PrimaryParticle particle, Vector3 rndPosition, INeighborslist neighborslist, IEnumerable <PrimaryParticle> primaryParticles, IAggregateFormationConfig config) { // Get all neighbors within potential reach of the primary particle var searchRadius = (particle.Radius + primaryParticles.GetMaxRadius()) * config.Delta; var neighborsWithDistance = neighborslist.GetPrimaryParticlesAndDistanceWithinRadius(rndPosition, searchRadius); // no neighbor: invalid position if (!neighborsWithDistance.Any()) { return(false); } return(IsAnyNeighborPositionValid(particle, rndPosition, config, neighborsWithDistance)); }
public void IsPrimaryParticlePositionValid_CorrectDetectionTest() { var pp1 = new PrimaryParticle(1, new Vector3(), 4.5); var pp2 = new PrimaryParticle(2, new Vector3(4.035344, 0.969021, 7.427756), 4.0); var primaryParticles = new List <PrimaryParticle>() { pp1, pp2 }; var pp3 = new PrimaryParticle(3, 5.5); var com = primaryParticles.GetCenterOfMass(); var setPosition = new Vector3(-11.098618, 1.316368, -6.026161) + com; var psd = new MonodispersePrimaryParticleSizeDistribution(5); var pca = new ParticleClusterAggregationFactory(psd, _rndGen, _config, _neighborslistFactory, _logger); var neighborslist = _neighborslistFactory.Build3DNeighborslist(primaryParticles); var check = pca.IsPrimaryParticlePositionValid(pp3, setPosition, neighborslist, primaryParticles, _config); Assert.True(check); }
public void FeasiblePositionTest() { var logger = new Mock <ILogger>().Object; var rndGen = new Random(_seed); var cca = new ClusterClusterAggregationFactory(_monoPSD, _config, _logger, _neighborslistFactory, _seed); var pp1 = new PrimaryParticle(1, new Vector3(0, 0, 0), 5); var pp2 = new PrimaryParticle(2, new Vector3(0, 0, 10), 5); var cluster1 = new Cluster(1, new List <PrimaryParticle>() { pp1, pp2 }); var depositedCluster = new List <Cluster> { cluster1 }; var neighborslist = _neighborslistFactory.Build3DNeighborslist(cluster1.PrimaryParticles); var pp3 = new PrimaryParticle(3, new Vector3(0, 0, 25), 5); var pp4 = new PrimaryParticle(4, new Vector3(0, 0, 19), 5); var pp5 = new PrimaryParticle(4, new Vector3(0, 0, 20.02), 5); var(anyNearby1, allFeasible1) = cca.IsPrimaryParticlePositionValid(neighborslist, pp3, depositedCluster.GetPrimaryParticles()); Assert.False(anyNearby1); Assert.True(allFeasible1); var(anyNearby2, allFeasible2) = cca.IsPrimaryParticlePositionValid(neighborslist, pp4, depositedCluster.GetPrimaryParticles()); Assert.True(anyNearby2); Assert.False(allFeasible2); var(anyNearby3, allFeasible3) = cca.IsPrimaryParticlePositionValid(neighborslist, pp5, depositedCluster.GetPrimaryParticles()); Assert.True(anyNearby3); Assert.True(allFeasible3); }
private static int GetPrimaryParticleOverlaps(PrimaryParticle primaryParticle, IParticleFilm <Aggregate> particleFilm, INeighborslist neighborslist, bool highlightPrimaryParticle) { var neighbors = neighborslist.GetPrimaryParticlesAndDistanceWithinRadius(primaryParticle.Position, primaryParticle.Radius + particleFilm.PrimaryParticles.GetMaxRadius()); var count = 0; foreach (var neigh in neighbors) { if (primaryParticle == neigh.Item1) { continue; } if (primaryParticle.Radius + neigh.Item1.Radius - neigh.Item2 > 1e-6) { count++; if (highlightPrimaryParticle) { primaryParticle.Type = 2; } } } return(count); }
private void ComputeCorrectMinDepositionDistance_NoCollision() { var r = 1.0; var pos = new Vector3(0, 0, 100); var primaryParticle = new PrimaryParticle(0, pos, r); var handler = new BallisticSingleParticleDepositionHandler(); var pos2 = new Vector3(5, 0, 10); var pp2 = new PrimaryParticle(1, pos2, r); var otherParticles = new List <PrimaryParticle>() { pp2 }; var neighborsList = _neighborslistFactory.Build2DNeighborslist(otherParticles); var dist = handler.GetDepositionDistance(primaryParticle, otherParticles, neighborsList, otherParticles.GetMaxRadius(), _config.Delta); var shouldBeDistance = primaryParticle.Position.Z - primaryParticle.Radius; Assert.Equal(shouldBeDistance, dist); }
public double GetDepositionDistance( PrimaryParticle primaryParticle, IEnumerable <PrimaryParticle> depositedPrimaryParticles, INeighborslist neighborsList2D, double maxRadius, double delta) { var distance = primaryParticle.Position.Z - primaryParticle.Radius; if (!depositedPrimaryParticles.Any()) { return(distance); } var searchRadius = (primaryParticle.Radius + maxRadius) * delta; var neighbors = neighborsList2D.GetPrimaryParticlesWithinRadius(primaryParticle.Position, searchRadius); foreach (var neighbor in neighbors) { distance = Math.Min(distance, Get1DDistanceToNeighbor(primaryParticle, neighbor)); } return(distance); }
private void ComputeCorrectMinDepositionDistance_CollisionWithPrimaryParticleOnlyOneNeighbor() { var r = 1.0; var pos = new Vector3(0, 0, 100); var primaryParticle = new PrimaryParticle(0, pos, r); var handler = new BallisticSingleParticleDepositionHandler(); var pos2 = new Vector3(1, 0, 10); var pp2 = new PrimaryParticle(1, pos2, r); var otherParticles = new List <PrimaryParticle>() { pp2 }; var neighborsList = _neighborslistFactory.Build2DNeighborslist(otherParticles); var dist = handler.GetDepositionDistance(primaryParticle, otherParticles, neighborsList, otherParticles.GetMaxRadius(), _config.Delta); // Math.Sqrt(3) results from the square of the combined radius (4) - the distance to centerline. // This origins from the triangle: final position pp1. position neigbor, center projection neighbor. var shouldBeDistance = 90 - Math.Sqrt(3); Assert.Equal(shouldBeDistance, dist); }
/// <summary> /// Check if the primary particle is in contact with any other primary particle (isInContact) and if it is overlapping with any other primary particle (hasNoOverlap) /// </summary> /// <param name="particle"></param> /// <param name="primaryParticles"></param> /// <param name="config"></param> /// <param name="neighbors"></param> /// <returns></returns> public static (bool isInContact, bool hasNoOverlap) IsAnyNeighborInContactOrOverlapping(PrimaryParticle particle, IEnumerable <PrimaryParticle> primaryParticles, IAggregateFormationConfig config, List <NodeDistance <KDTreeNode <double> > > neighbors) { var isInContact = false; var hasNoOverlap = true; foreach (var neigh in neighbors) { var radiusParticle2 = GetRadiusOfNodePrimaryParticle(neigh.Node.Position, primaryParticles); isInContact = isInContact || IsInContact(neigh.Distance, particle.Radius, radiusParticle2, config.Delta); hasNoOverlap = hasNoOverlap && HasNoOverlap(neigh.Distance, particle.Radius, radiusParticle2, config.Epsilon); } return(isInContact, hasNoOverlap); }
private static string GetPrimaryParticleString(PrimaryParticle particle, Cluster cluster, Aggregate agg) { return($"{particle.Id} {particle.Type} {agg.Id} {cluster.Id} {DoubleToString(particle.Position.X)} {DoubleToString(particle.Position.Y)} {DoubleToString(particle.Position.Z)} {DoubleToString(particle.Radius)}{Environment.NewLine}"); }
/// <summary> /// Nothing to do here, since particles can penetrate the wall and have no lateral movement. /// </summary> /// <param name="primaryParticle"></param> /// <param name="simulationBox"></param> public void CheckPrimaryParticle(PrimaryParticle primaryParticle, ISimulationBox simulationBox) { return; }
public void CheckPrimaryParticle(PrimaryParticle primaryParticle, ISimulationBox simulationBox) { CheckXDimension(primaryParticle, simulationBox); CheckYDimension(primaryParticle, simulationBox); }