|
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().
1.7.6.1