HG-MD
1
|
Definition of a wall (planar or finite). More...
#include <CWall.h>
Public Member Functions | |
CWall () | |
void | set_is_hopper () |
void | set (Vec3D normal_, Mdouble position_) |
Defines a standard wall, given an outward normal vector s. t. normal*x=position. | |
void | is_finite () |
void | add_finite_wall (Vec3D normal, Vec3D point) |
Adds a wall to the set of finite walls, given an outward normal vector s.t. normal*x=normal*point. | |
void | add_finite_wall (Vec3D normal_, Mdouble position_) |
Adds a wall to the set of finite walls, given an outward normal vector s.t. normal*x=position. | |
void | move (Mdouble position_) |
Allows the wall to be moved to a new position. | |
void | move (Vec3D velocity_, Mdouble dt) |
Allows the wall to be moved to a new position (also orthogonal to the normal), and setting the velocity. | |
Mdouble | get_distance (Vec3D &Position) |
Returns the distance of the wall to the particle. | |
bool | get_distance_and_normal (Particle &P, Mdouble &distance, Vec3D &normal_return) |
Since this function should be called before calculating any Particle-Wall interactions, it can also be used to set the normal vector in case of curved walls. | |
void | read (std::istream &is) |
reads wall | |
void | print (std::ostream &os) |
outputs wall | |
Vec3D | get_normal () |
access function for normal | |
void | set_normal (Vec3D new_) |
Mdouble | get_position () |
access function for position | |
Vec3D | get_velocity () |
access function for velocity | |
void | set_velocity (Vec3D new_) |
access function for velocity | |
bool | get_distance_and_normal_for_axissymmetric_wall (Particle &P, Mdouble &distance, Vec3D &normal_return) |
transforms to axisymmetric coordinates before calculating the distance to the wall, then transforms back | |
void | setSymmetryAxis (Vec3D new_axisOrigin, Vec3D new_axisOrientation) |
defines an axisymmetric wall | |
void | removeSymmetryAxis () |
removes the axysymmetric property of the wall | |
Public Attributes | |
Vec3D | velocity |
velocity of the wall (used to calculate the relative velocity in the force calculation) | |
int | indSpecies |
bool | is_hopper |
bool | isAxisymmetric |
Vec3D | axisOrigin |
Vec3D | axisOrientation |
Private Attributes | |
vector< CWall > | finite_walls |
vector< Vec3D > | A |
vector< Vec3D > | AB |
vector< Vec3D > | C |
Vec3D | normal |
Mdouble | position |
Mdouble | factor |
Friends | |
std::ostream & | operator<< (std::ostream &os, CWall &w) |
writes wall | |
std::istream & | operator>> (std::istream &is, CWall &w) |
reads wall |
Definition of a wall (planar or finite).
A standard wall is a plane defined as {x: normal*x=position}, with normal being the outward unit normal vector of the wall. A particle touches a standard wall if position-normal*x<=radius. A finite wall is convex polygon defined by a set of normals normal_i and positions position_i. A particle touches a finite wall if position_i-normal_i*x<=radius for all i.
CWall::CWall | ( | ) | [inline] |
References indSpecies, is_hopper, isAxisymmetric, Vec3D::set_zero(), and velocity.
{ indSpecies = 0; is_hopper = false; isAxisymmetric = false; velocity.set_zero(); }
void CWall::add_finite_wall | ( | Vec3D | normal, |
Vec3D | point | ||
) | [inline] |
Adds a wall to the set of finite walls, given an outward normal vector s.t. normal*x=normal*point.
Referenced by read().
{ add_finite_wall(normal,Dot(normal,point)); }
void CWall::add_finite_wall | ( | Vec3D | normal_, |
Mdouble | position_ | ||
) | [inline] |
Adds a wall to the set of finite walls, given an outward normal vector s.t. normal*x=position.
References A, AB, C, finite_walls, normal, and Vec3D::Y.
{ //n is the index of the new wall int n = finite_walls.size(); finite_walls.resize(n+1); finite_walls[n].set(normal_,position_); // AB[n*(n-1)/2+m] is the direction of the intersecting line between walls m and n, m<n // A[n*(n-1)/2+m] is a point on the intersecting line between walls m and n, m<n // See http://www.netcomuk.co.uk/~jenolive/vect18d.html for finding the line where two planes meet AB.resize(n*(n+1)/2); A.resize (n*(n+1)/2); for(int m=0; m<n; m++) { int id = (n-1)*n/2+m; //first we cross the wall normals and normalize to obtain AB AB[id] = Cross(finite_walls[m].normal, finite_walls[n].normal); AB[id] /= sqrt(AB[id].GetLength2()); //then we find a point A (using AB*x=0 as a third plane) Mdouble invdet = 1.0/(+finite_walls[n].normal.X*(finite_walls[m].normal.Y*AB[id].Z-AB[id].Y*finite_walls[m].normal.Z) -finite_walls[n].normal.Y*(finite_walls[m].normal.X*AB[id].Z-finite_walls[m].normal.Z*AB[id].X) +finite_walls[n].normal.Z*(finite_walls[m].normal.X*AB[id].Y-finite_walls[m].normal.Y*AB[id].X)); A[id] = Vec3D(+(finite_walls[m].normal.Y*AB[id].Z-AB[id].Y*finite_walls[m].normal.Z)*finite_walls[n].position -(finite_walls[n].normal.Y*AB[id].Z-finite_walls[n].normal.Z*AB[id].Y)*finite_walls[m].position +(finite_walls[n].normal.Y*finite_walls[m].normal.Z-finite_walls[n].normal.Z*finite_walls[m].normal.Y)*0.0, -(finite_walls[m].normal.X*AB[id].Z-finite_walls[m].normal.Z*AB[id].X)*finite_walls[n].position +(finite_walls[n].normal.X*AB[id].Z-finite_walls[n].normal.Z*AB[id].X)*finite_walls[m].position -(finite_walls[n].normal.X*finite_walls[m].normal.Z-finite_walls[m].normal.X*finite_walls[n].normal.Z)*0.0, +(finite_walls[m].normal.X*AB[id].Y-AB[id].X*finite_walls[m].normal.Y)*finite_walls[n].position -(finite_walls[n].normal.X*AB[id].Y-AB[id].X*finite_walls[n].normal.Y)*finite_walls[m].position +(finite_walls[n].normal.X*finite_walls[m].normal.Y-finite_walls[m].normal.X*finite_walls[n].normal.Y)*0.0 ) * invdet; } // C[(n-2)*(n-1)*n/6+(m-1)*m/2+l] is a point intersecting walls l, m and n, l<m<n C.resize((n-1)*n*(n+1)/6); for(int m=0; m<n; m++) { for(int l=0; l<m; l++) { int id = (n-2)*(n-1)*n/6+(m-1)*m/2+l; Mdouble invdet = 1.0/(+finite_walls[n].normal.X*(finite_walls[m].normal.Y*finite_walls[l].normal.Z-finite_walls[l].normal.Y*finite_walls[m].normal.Z) -finite_walls[n].normal.Y*(finite_walls[m].normal.X*finite_walls[l].normal.Z-finite_walls[m].normal.Z*finite_walls[l].normal.X) +finite_walls[n].normal.Z*(finite_walls[m].normal.X*finite_walls[l].normal.Y-finite_walls[m].normal.Y*finite_walls[l].normal.X)); C[id] = Vec3D(+(finite_walls[m].normal.Y*finite_walls[l].normal.Z-finite_walls[l].normal.Y*finite_walls[m].normal.Z)*finite_walls[n].position -(finite_walls[n].normal.Y*finite_walls[l].normal.Z-finite_walls[n].normal.Z*finite_walls[l].normal.Y)*finite_walls[m].position +(finite_walls[n].normal.Y*finite_walls[m].normal.Z-finite_walls[n].normal.Z*finite_walls[m].normal.Y)*finite_walls[l].position, -(finite_walls[m].normal.X*finite_walls[l].normal.Z-finite_walls[m].normal.Z*finite_walls[l].normal.X)*finite_walls[n].position +(finite_walls[n].normal.X*finite_walls[l].normal.Z-finite_walls[n].normal.Z*finite_walls[l].normal.X)*finite_walls[m].position -(finite_walls[n].normal.X*finite_walls[m].normal.Z-finite_walls[m].normal.X*finite_walls[n].normal.Z)*finite_walls[l].position, +(finite_walls[m].normal.X*finite_walls[l].normal.Y-finite_walls[l].normal.X*finite_walls[m].normal.Y)*finite_walls[n].position -(finite_walls[n].normal.X*finite_walls[l].normal.Y-finite_walls[l].normal.X*finite_walls[n].normal.Y)*finite_walls[m].position +(finite_walls[n].normal.X*finite_walls[m].normal.Y-finite_walls[m].normal.X*finite_walls[n].normal.Y)*finite_walls[l].position ) * invdet; } } }
Mdouble CWall::get_distance | ( | Vec3D & | Position | ) | [inline] |
bool CWall::get_distance_and_normal | ( | Particle & | P, |
Mdouble & | distance, | ||
Vec3D & | normal_return | ||
) | [inline] |
Since this function should be called before calculating any Particle-Wall interactions, it can also be used to set the normal vector in case of curved walls.
References A, AB, C, finite_walls, get_distance(), get_distance_and_normal_for_axissymmetric_wall(), Particle::get_Position(), Particle::get_Radius(), Vec3D::GetLength(), Vec3D::GetLength2, is_hopper, isAxisymmetric, normal, SIGN, sqr, Vec3D::X, Vec3D::Y, and Vec3D::Z.
Referenced by get_distance_and_normal_for_axissymmetric_wall().
{ if (isAxisymmetric) return get_distance_and_normal_for_axissymmetric_wall(P, distance, normal_return); static Mdouble distance_new; static Mdouble distance2; static Mdouble distance3; static int id; static int id2; static int id3; if(is_hopper){//this is first becuase i dont know what it does if not // Three posible normals for the hopper, they are averaged // when a particle touch 2 walls Vec3D normalOuterCylinder = Vec3D(0,0,0); Vec3D normalInnerCylinder = Vec3D(0,0,0); Vec3D normalBase = Vec3D(0,0,0); //Radial coordinate of the particle Mdouble particleRadius = sqrt(sqr(P.get_Position().X) + sqr(P.get_Position().Y)); Mdouble innerRadius = 20*P.get_Radius();// hardcoded geometry for the moment Mdouble outerRadius = 50*P.get_Radius(); Mdouble distanceOuterCylinder = 0.0; Mdouble distanceInnerCylinder = 0.0; Mdouble distanceBase = 0.0; //cout << "Mass of particles: " << P.get_restitution_coefficient() << endl; //set normal outer cilinder if(particleRadius + P.get_Radius() > outerRadius){ normalOuterCylinder = Vec3D(P.get_Position().X, P.get_Position().Y, 0.0)/particleRadius; distanceOuterCylinder = outerRadius - particleRadius; //cout << "Outer Cylinder "<< endl; } //\todo set a real hopper with two more walls /* if (P.get_Position().Z - P.Radius < 0.0 && particleRadius + P.Radius >= innerRadius */ /* && P.get_Position().Z > 0){// the particle feels the ground */ /* normalBase = Vec3D(0.0,0.0,-1.0);//normalized normal outer to the geometry */ /* distanceBase = P.get_Position().Z;//the distance to the wall from the center of the particle */ /* //cout << "Base "<< endl; */ /* } */ //\todo set a real hopper with two more walls if (abs(P.get_Position().Z) - P.get_Radius() < 0.0 && particleRadius > innerRadius){// the particle feels the ground normalBase = Vec3D(0.0,0.0,-1.0)*SIGN(P.get_Position().Z); distanceBase = P.get_Position().Z; } Vec3D dr = Vec3D(P.get_Position().X, P.get_Position().Y, 0.0)*innerRadius/particleRadius - P.get_Position(); if(dr.GetLength() < P.get_Radius() ){ cout << " toy en el borde" << endl; distanceBase = dr.GetLength(); normalBase = dr/distanceBase; } /* if(particleRadius + P.Radius > innerRadius */ /* && P.get_Position().Z > -40*P.Radius */ /* && P.get_Position().Z + P.Radius < 0.0 ){//inside wall */ /* normalInnerCylinder = Vec3D(-P.get_Position().X, -P.get_Position().Y, 0.0)/particleRadius; */ /* distanceInnerCylinder = innerRadius - particleRadius; */ /* //cout << "Inner Cylinder "<< endl; */ /* } */ /* if(P.get_Position().Z > 0.0 && P.get_Position().Z - P.Radius < 0.0 && particleRadius < innerRadius ){// Colliding with line */ /* normal_return = Vec3D(P.get_Position().X,P.get_Position().Y,0)*(innerRadius/particleRadius - 1.0)+ */ /* Vec3D(0.0,0.0,-P.get_Position().Z); */ /* distance = normal_return.GetLength(); */ /* normal_return /= normal_return.GetLength(); */ /* if(distance < P.Radius){ */ /* cout << "Border normal " << normal_return << " distance " << distance<< endl; */ /* return true; */ /* } */ /* } */ if(distanceOuterCylinder != 0.0 || distanceBase != 0.0){ //average normals normal_return = distanceOuterCylinder*normalOuterCylinder + distanceInnerCylinder*normalInnerCylinder + distanceBase*normalBase; normal_return /= normal_return.GetLength(); // distance = sqrt(SQR(distanceBase) + SQR(distanceOuterCylinder) // + SQR(distanceInnerCylinder)); distance = 0.5*(distanceBase + distanceOuterCylinder); //cout << "normal " << normal_return << " distance " << distance<< endl; return true; } /* if(distanceBase != 0 || distanceInnerCylinder != 0.0){ //collision with inner walls */ /* //average normals */ /* normal_return = distanceInnerCylinder*normalInnerCylinder */ /* + distanceBase*normalBase; */ /* normal_return /= normal_return.GetLength(); */ /* // distance = sqrt(SQR(distanceBase) + SQR(distanceOuterCylinder) */ /* // + SQR(distanceInnerCylinder)); */ /* distance = 0.5*(distanceBase + distanceInnerCylinder); */ /* //cout << "normal " << normal_return << " distance " << distance<< endl; */ /* return true; */ /* } */ //cout << "False " << endl; //getchar(); // no collision, so return false return false; } if (!finite_walls.size()) { //for standard walls this function sets normal_return and distance and returns true if the particle is in contact distance = get_distance(P.get_Position()); if (distance>=P.get_Radius()) return false; normal_return = normal; return true; } //if we are here, this is a finite wall distance = -1e20; distance2 = -1e20; distance3 = -1e20; //for all finite walls for (unsigned int i=0; i<finite_walls.size(); i++) { //calculate the distance to the particle distance_new = finite_walls[i].get_distance(P.get_Position()); //return false if the distance to any one wall is too large (i.e. no contact) if (distance_new>=P.get_Radius()) return false; //store the minimum distance and the respective wall in "distance" and "id" //and store up to two walls (id2, id3) and their distances (distance2, distance3), if the possible contact point is near the intersection between id and id2 (and id3) if (distance_new>distance) { if (distance>-P.get_Radius()) { if (distance2>-P.get_Radius()) {distance3 = distance; id3 = id;} else {distance2 = distance; id2 = id;} } distance = distance_new; id = i; } else if (distance_new>-P.get_Radius()) { if (distance2>-P.get_Radius()) {distance3 = distance_new; id3 = i;} else {distance2 = distance_new; id2 = i;} } } //if we are here, the closest wall is id; //if distance2>-P.Radius (and distance3>-P.Radius), the possible contact point is near the intersection between id and id2 (and id3) if (distance2>-P.get_Radius()) { //D is the point on wall id closest to P Vec3D D = P.get_Position() + finite_walls[id].normal * distance; //If the distance of D to id2 is positive, the contact is with the intersection bool intersection_with_id2 = (finite_walls[id2].get_distance(D)>0.0); if (distance3>-P.get_Radius()&&(finite_walls[id3].get_distance(D)>0.0)) { if (intersection_with_id2) { //possible contact is with intersection of id,id2,id3 //we know id2<id3 int index = (id<id2)?( (id3-2)*(id3-1)*id3/6+(id2-1)*id2/2+id ): (id<id3)?( (id3-2)*(id3-1)*id3/6+(id -1)*id /2+id2 ): ( (id -2)*(id -1)*id /6+(id3-1)*id3/2+id2 ); normal_return = P.get_Position() - C[index]; distance = sqrt(normal_return.GetLength2()); if (distance>=P.get_Radius()) return false; //no contact normal_return /= -distance; return true; //contact with id,id2,id3 } else { intersection_with_id2 = true; distance2 = distance3; id2 = id3; } } if (intersection_with_id2) { //possible contact is with intersection of id,id2 int index = (id>id2)?((id-1)*id/2+id2):((id2-1)*id2/2+id); Vec3D AC = P.get_Position() - A[index]; normal_return = AC - AB[index] * Dot(AC,AB[index]); distance = sqrt(normal_return.GetLength2()); if (distance>=P.get_Radius()) return false; //no contact normal_return /= -distance; return true; //contact with two walls } } //contact is with id normal_return = finite_walls[id].normal; return true; }
bool CWall::get_distance_and_normal_for_axissymmetric_wall | ( | Particle & | P, |
Mdouble & | distance, | ||
Vec3D & | normal_return | ||
) | [inline] |
transforms to axisymmetric coordinates before calculating the distance to the wall, then transforms back
References axisOrientation, axisOrigin, get_distance_and_normal(), Particle::get_Position(), Vec3D::GetLength(), isAxisymmetric, Particle::set_Position(), Vec3D::X, Vec3D::Y, and Vec3D::Z.
Referenced by get_distance_and_normal().
{ //transform to axisymmetric coordinates Vec3D PO = P.get_Position() - axisOrigin; P.get_Position().Z = Dot(axisOrientation,PO); P.get_Position().Y = 0.0; Vec3D tangential = PO-P.get_Position().Z*axisOrientation; P.get_Position().X = tangential.GetLength(); tangential /= P.get_Position().X; Vec3D normal_axisymmetric_coordinates; //determine wall distance, normal and contact in axosymmetric coordinates isAxisymmetric = false; bool retval = get_distance_and_normal(P, distance, normal_axisymmetric_coordinates); isAxisymmetric = true; //transform from axisymmetric coordinates normal_return = normal_axisymmetric_coordinates.Z * axisOrientation + tangential*normal_axisymmetric_coordinates.X; P.set_Position(PO + axisOrigin); return retval; }
Vec3D CWall::get_normal | ( | ) | [inline] |
Mdouble CWall::get_position | ( | ) | [inline] |
Vec3D CWall::get_velocity | ( | ) | [inline] |
void CWall::is_finite | ( | ) | [inline] |
References finite_walls.
{finite_walls.resize(0);}
void CWall::move | ( | Mdouble | position_ | ) | [inline] |
void CWall::move | ( | Vec3D | velocity_, |
Mdouble | dt | ||
) | [inline] |
void CWall::print | ( | std::ostream & | os | ) | [inline] |
outputs wall
References finite_walls, normal, and position.
{ if (finite_walls.size()) { os << "finite_wall( "; for (vector<CWall>::iterator it = finite_walls.begin(); it!=finite_walls.end(); ++it) os << "normal:" << it->get_normal() << ", position:" << it->get_position() << " "; os << " )"; } else os << "wall( normal:" << normal << ", position:" << position << ")"; }
void CWall::read | ( | std::istream & | is | ) | [inline] |
reads wall
References add_finite_wall(), normal, position, and velocity.
{ string dummy; int n; is >> dummy >> n; if (n!=0) { Vec3D normal; Mdouble position; for (int i=0; i<n; i++) { is >> dummy >> normal >> dummy >> position; add_finite_wall(normal,position); } } else { //use stringstream to ensure that old restart files w/o velocity don't break the code stringstream ss(""); string s; getline(is,s); ss << s; ss >> dummy >> normal >> dummy >> position >> dummy >> velocity; } }
void CWall::removeSymmetryAxis | ( | ) | [inline] |
removes the axysymmetric property of the wall
References isAxisymmetric.
{ isAxisymmetric = false; }
void CWall::set | ( | Vec3D | normal_, |
Mdouble | position_ | ||
) | [inline] |
Defines a standard wall, given an outward normal vector s. t. normal*x=position.
References factor, finite_walls, normal, and position.
void CWall::set_is_hopper | ( | ) | [inline] |
void CWall::set_normal | ( | Vec3D | new_ | ) | [inline] |
void CWall::set_velocity | ( | Vec3D | new_ | ) | [inline] |
void CWall::setSymmetryAxis | ( | Vec3D | new_axisOrigin, |
Vec3D | new_axisOrientation | ||
) | [inline] |
defines an axisymmetric wall
References axisOrientation, axisOrigin, isAxisymmetric, and Vec3D::normalize().
{ axisOrigin = new_axisOrigin; axisOrientation = new_axisOrientation; axisOrientation.normalize(); isAxisymmetric = true; cout << "axisOrigin" << axisOrigin << "axisOrientation" << axisOrientation << "isAxisymmetric" << isAxisymmetric << endl; }
std::ostream& operator<< | ( | std::ostream & | os, |
CWall & | w | ||
) | [friend] |
writes wall
{ os << "numFiniteWalls " << w.finite_walls.size(); if (w.finite_walls.size()) { for (vector<CWall>::iterator it = w.finite_walls.begin(); it!=w.finite_walls.end(); ++it) { os << " normal " << it->normal << " position " << it->position; } } else { os << " normal " << w.normal << " position " << w.position; //optional output if (w.velocity.GetLength2()) os << " velocity " << w.velocity; } return os; }
std::istream& operator>> | ( | std::istream & | is, |
CWall & | w | ||
) | [friend] |
Referenced by add_finite_wall(), and get_distance_and_normal().
Referenced by add_finite_wall(), and get_distance_and_normal().
Referenced by get_distance_and_normal_for_axissymmetric_wall(), and setSymmetryAxis().
Referenced by get_distance_and_normal_for_axissymmetric_wall(), and setSymmetryAxis().
Referenced by add_finite_wall(), and get_distance_and_normal().
Mdouble CWall::factor [private] |
vector<CWall> CWall::finite_walls [private] |
Referenced by add_finite_wall(), get_distance_and_normal(), is_finite(), print(), and set().
Referenced by CWall().
bool CWall::is_hopper |
Referenced by CWall(), get_distance_and_normal(), and set_is_hopper().
Vec3D CWall::normal [private] |
Referenced by add_finite_wall(), get_distance(), get_distance_and_normal(), get_normal(), move(), print(), read(), set(), and set_normal().
Mdouble CWall::position [private] |
Referenced by get_distance(), get_position(), move(), print(), read(), and set().
velocity of the wall (used to calculate the relative velocity in the force calculation)
Referenced by CWall(), get_velocity(), move(), read(), and set_velocity().