HG-MD  1
ChuteWithHopper.h
Go to the documentation of this file.
00001 #include "Chute.h"
00002 #include "Statistics.h"
00003 
00010 class ChuteWithHopper : public Chute {
00011 protected: 
00013         Mdouble HopperLength;
00015         Mdouble HopperHeight;
00017         Mdouble HopperAngle;
00019         Mdouble HopperExitLength;
00021         Mdouble HopperExitHeight;
00023         Mdouble shift;
00025         Mdouble lowerFillHeight;
00027         bool centerHopper;
00028 private:
00030         Mdouble lift;
00031         
00033         unsigned int hopper_dim;
00034         
00036         bool align_base;
00037         
00039         Mdouble fill_percent;
00040 
00041 
00042 public:
00043         
00045         ChuteWithHopper(Chute& other) :                 MD(other), Chute(other) {constructor();}
00046         ChuteWithHopper(HGRID_3D& other) :              MD(other), Chute(other) {constructor();}
00047         ChuteWithHopper(HGRID_base& other) :    MD(other), Chute(other) {constructor();}
00048         ChuteWithHopper(MD& other) :                    MD(other), Chute(other) {constructor();}
00049         
00051         ChuteWithHopper() {constructor();}
00052         
00054         void constructor()
00055                 {
00056                 lowerFillHeight=0.5;
00057                 lift=0.0;
00058                 set_Hopper(0.01, 0.01, 60.0, 0.08);
00059                 shift = 0.0;    
00060                 hopper_dim=1;
00061                 align_base=true;
00062 
00063                 fill_percent=50.0;
00064                 centerHopper=false;
00065 
00066                 }
00067                 
00068         void set_HopperFillPercentage(Mdouble new_fill){fill_percent=new_fill;}
00069         
00070         virtual void setup_particles_initial_conditions()
00071         {
00072                 Chute::setup_particles_initial_conditions();
00073                 //cout << shift << " " << get_xmax() << " " << get_ParticleHandler().get_NumberOfParticles() << endl;
00074                 add_hopper();   
00075         }       
00076         
00078         void add_hopper() {
00079                 //hopper walls
00080                 int n = get_NWall();
00081                 set_NWall(n+2);
00082                 
00083                 //to create the finite hopper walls, we take vector between two wall points in xz-plane, then rotate clockwise and make unit length
00084                 // A\       /A  
00085                 //   \     /       A,B,C denote three points on the left and right hopper walls which are used to construct the hopper
00086                 //    \   /        shift denotes the space by which the chute has to be shifted to the right such that the hopper is in the domain
00087                 //   B|   |B
00088                 //    |   |
00089                 //    |   |
00090                 //   C|   |C
00091                 
00092                 Vec3D A, B, C, temp, normal;
00093                 Mdouble s = sin(get_ChuteAngle());
00094                 Mdouble c = cos(get_ChuteAngle());
00095                 Mdouble HopperLowestPoint = HopperExitHeight - HopperExitLength * tan(ChuteAngle);
00096                 HopperHeight = HopperLowestPoint + 1.1 * 0.5*(HopperLength+HopperExitLength) / tan(HopperAngle);
00097                 Mdouble HopperCornerHeight = HopperHeight - 0.5*(HopperLength-HopperExitLength) / tan(HopperAngle);
00098                 if (HopperCornerHeight<=0.0) { HopperHeight += -HopperCornerHeight + P0.get_Radius(); HopperCornerHeight = P0.get_Radius(); }
00099                 
00100                 //first we create the left hopper wall
00101                 
00102                 //coordinates of A,B,C in (vertical parallel to flow,vertical normal to flow, horizontal) direction
00103                 A = Vec3D(-0.5*(HopperLength-HopperExitLength), 0.0, HopperHeight);
00104                 B = Vec3D(0.0, 0.0, HopperCornerHeight);
00105                 C = Vec3D(0.0, 0.0, 0.0);
00106                 
00107                 
00108                 
00109                 //now rotate the coordinates of A,B,C to be in (x,y,z) direction                
00110                 A = Vec3D(c*A.X-s*A.Z, 0.0, s*A.X+c*A.Z);
00111                 B = Vec3D(c*B.X-s*B.Z, 0.0, s*B.X+c*B.Z);
00112                 C = Vec3D(c*C.X-s*C.Z, 0.0, s*C.X+c*C.Z);
00113                 // the position of A determines shift and zmax
00114                 if (centerHopper) set_shift(-A.X+40);
00115                 else set_shift(-A.X);
00116                 set_zmax(A.Z);
00117                 A.X +=shift;
00118                 B.X +=shift;
00119                 C.X +=shift;
00120                 
00121                 //This lifts the hopper a distance above the chute
00122                 A.Z+=lift;
00123                 B.Z+=lift;
00124                 C.Z+=lift;
00125                 
00126                 //create a finite wall from B to A and from C to B
00127                 temp = B-A;
00128                 normal  = Vec3D(temp.Z,0.0,-temp.X) / sqrt(temp.GetLength2());
00129                 Walls[n].add_finite_wall(normal, Dot(normal,A));
00130                 temp = C-B;
00131                 normal  = Vec3D(temp.Z,0.0,-temp.X) / sqrt(temp.GetLength2());
00132                 Walls[n].add_finite_wall(normal, Dot(normal,B));
00133                 temp = A-C;
00134                 normal = Vec3D(temp.Z,0.0,-temp.X)/sqrt(temp.GetLength2());
00135                 Walls[n].add_finite_wall(normal,Dot(normal,C));
00136                 
00137                 
00138                 
00139                 //next, do the same for the right wall
00140                 A = Vec3D(HopperLength-0.5*(HopperLength-HopperExitLength), 0.0, HopperHeight);
00141                 B = Vec3D(0.5*(HopperLength+HopperExitLength)-0.5*(HopperLength-HopperExitLength), 0.0, HopperCornerHeight);
00142                 C = Vec3D(0.5*(HopperLength+HopperExitLength)-0.5*(HopperLength-HopperExitLength), 0.0, HopperLowestPoint);
00143                 
00144                 
00145                 
00146                 
00147                 //This rotates the right points
00148                 A = Vec3D(c*A.X-s*A.Z+shift, 0.0, s*A.X+c*A.Z);
00149                 B = Vec3D(c*B.X-s*B.Z+shift, 0.0, s*B.X+c*B.Z);
00150                 C = Vec3D(c*C.X-s*C.Z+shift, 0.0, s*C.X+c*C.Z);
00151                 
00152                 //This lifts the hopper a distance above the chute
00153                 A.Z+=lift;
00154                 B.Z+=lift;
00155                 C.Z+=lift;
00156                 
00157                 temp = A-B;
00158                 normal  = Vec3D(temp.Z,0.0,-temp.X) / sqrt(temp.GetLength2());
00159                 Walls[n+1].add_finite_wall(normal, Dot(normal,A));
00160                 temp = B-C;
00161                 normal  = Vec3D(temp.Z,0.0,-temp.X) / sqrt(temp.GetLength2());
00162                 Walls[n+1].add_finite_wall(normal, Dot(normal,B));
00163                 temp = C-A;
00164                 normal  = Vec3D(temp.Z,0.0,-temp.X) / sqrt(temp.GetLength2());
00165                 Walls[n+1].add_finite_wall(normal, Dot(normal,C));
00166                 
00167                 set_zmax(A.Z);
00168                 
00169                 if (hopper_dim == 2)
00170                         {
00171                                 
00172                                 set_NWall(n+4);
00173                                 
00174                                 
00175                                 //coordinates of A,B,C in (vertical parallel to flow,vertical normal to flow, horizontal) direction
00176                                 A = Vec3D(0.0, (get_ymax()-get_ymin()-HopperLength)/2.0, HopperHeight);
00177                                 B = Vec3D(0.0, (get_ymax()-get_ymin()-HopperExitLength)/2.0, HopperCornerHeight);
00178                                 C = Vec3D(0.0, (get_ymax()-get_ymin()-HopperExitLength)/2.0, 0.0);
00179                 
00180                 
00181                 
00182                                 //now rotate the coordinates of A,B,C to be in (x,y,z) direction                
00183                                 A = Vec3D(c*A.X-s*A.Z, A.Y, s*A.X+c*A.Z);
00184                                 B = Vec3D(c*B.X-s*B.Z, B.Y, s*B.X+c*B.Z);
00185                                 C = Vec3D(c*C.X-s*C.Z, C.Y, s*C.X+c*C.Z);
00186                                 // the position of A determines shift and zmax
00187                                 A.X +=shift;
00188                                 B.X +=shift;
00189                                 C.X +=shift;
00190                 
00191                                 //This lifts the hopper a distance above the chute
00192                                 A.Z+=lift;
00193                                 B.Z+=lift;
00194                                 C.Z+=lift;
00195                                 
00196                                 
00197                                 
00198                                 //create a finite wall from B to A and from C to B
00199                                 temp = B-A;
00200                                 normal=Cross(Vec3D(-c,0,-s),temp)/sqrt(temp.GetLength2());
00201                                 //normal  = Vec3D(0.0,temp.Z,-temp.Y) / sqrt(temp.GetLength2());
00202                                 Walls[n+2].add_finite_wall(normal, Dot(normal,A));
00203                                 temp = C-B;
00204                                 //normal  = Vec3D(0.0,temp.Z,-temp.Y) / sqrt(temp.GetLength2());
00205                                 normal=Cross(Vec3D(-c,0,-s),temp)/sqrt(temp.GetLength2());
00206                                 Walls[n+2].add_finite_wall(normal, Dot(normal,B));
00207                                 temp = A-C;
00208                                 //normal = Vec3D(0.0,temp.Z,-temp.Y)/sqrt(temp.GetLength2());
00209                                 normal=Cross(Vec3D(-c,0,-s),temp)/sqrt(temp.GetLength2());
00210                                 Walls[n+2].add_finite_wall(normal,Dot(normal,C));
00211                                 
00212                                 
00213                                 //Now for the right y-wall
00214                                 A = Vec3D(0.0, (get_ymax()-get_ymin()+HopperLength)/2.0,HopperHeight);
00215                                 B = Vec3D(0.0, (get_ymax()-get_ymin()+HopperExitLength)/2.0,HopperCornerHeight);
00216                                 C = Vec3D(0.0, (get_ymax()-get_ymin()+HopperExitLength)/2.0,0.0);
00217                                 
00218                                 //now rotate the coordinates of A,B,C to be in (x,y,z) direction                
00219                                 A = Vec3D(c*A.X-s*A.Z, A.Y, s*A.X+c*A.Z);
00220                                 B = Vec3D(c*B.X-s*B.Z, B.Y, s*B.X+c*B.Z);
00221                                 C = Vec3D(c*C.X-s*C.Z, C.Y, s*C.X+c*C.Z);
00222                                 // the position of A determines shift and zmax
00223                                 A.X +=shift;
00224                                 B.X +=shift;
00225                                 C.X +=shift;
00226                 
00227                                 //This lifts the hopper a distance above the chute
00228                                 A.Z+=lift;
00229                                 B.Z+=lift;
00230                                 C.Z+=lift;
00231                                 
00232                                 //create a finite wall from B to A and from C to B
00233                                 temp = A-B;
00234                                 normal=Cross(Vec3D(-c,0,-s),temp)/sqrt(temp.GetLength2());
00235                                 //normal  = Vec3D(0.0,-temp.Z,temp.Y) / sqrt(temp.GetLength2());
00236                                 Walls[n+3].add_finite_wall(normal, Dot(normal,A));
00237                                 temp = B-C;
00238                                 //normal  = Vec3D(0.0,-temp.Z,temp.Y) / sqrt(temp.GetLength2());
00239                                 normal=Cross(Vec3D(-c,0,-s),temp)/sqrt(temp.GetLength2());
00240                                 Walls[n+3].add_finite_wall(normal, Dot(normal,B));
00241                                 temp = C-A;
00242                                 //normal = Vec3D(0.0,-temp.Z,temp.Y)/sqrt(temp.GetLength2());
00243                                 normal=Cross(Vec3D(-c,0,-s),temp)/sqrt(temp.GetLength2());
00244                                 Walls[n+3].add_finite_wall(normal,Dot(normal,C));
00245                                 
00246                                 
00247                                 
00248                                 
00249                                 
00250                                 
00251                         
00252                                 
00253                         }
00254                 
00255                 
00256                 
00257                 
00258                 
00259                 
00260                 
00261                 //now shift the fixed particles at the bottom so that they begin where the chute begins
00262                 for (vector<Particle*>::iterator it= get_ParticleHandler().begin(); it!=get_ParticleHandler().end(); ++it) { 
00263                         (*it)->get_Position().X+=shift;
00264                         #ifdef USE_SIMPLE_VERLET_INTEGRATION
00265                                 (*it)->PrevPosition.X +=shift;
00266                         #endif
00267                 }
00268         }
00269         
00270         
00276         virtual void create_inflow_particle()
00277         {
00278                 
00279                 
00280                 //use this formula to obtain bidispersed particles
00281                 //P0.Radius = random(0.0,1.0)<0.1?MinInflowParticleRadius:MaxInflowParticleRadius;
00282                 
00283                 //the following formula yields polydispersed particle radii:
00284 
00285                 P0.set_Radius(random.get_RN(MinInflowParticleRadius,MaxInflowParticleRadius));
00286                 P0.compute_particle_mass(Species);
00287                 
00288                 //Define a orthogonal coordinate system this is usful in the hopper, see diagram in html documentation for details.
00289                 static Mdouble s = sin(get_ChuteAngle());
00290                 static Mdouble c = cos(get_ChuteAngle());
00291                 static Mdouble Ht = tan(HopperAngle);
00292                 static Mdouble Hc = cos(HopperAngle);
00293                 static Vec3D AB = Vec3D(c,0.0,s);
00294                 static Vec3D AC = Vec3D(-s,0.0,c);
00295                 static Vec3D AD = Vec3D(0.0,1.0,0.0);
00296                 
00297                 //Point A is located in the centre of the hopper.
00298                 static Vec3D A = Vec3D
00299                         (
00300                         centerHopper?40:0.0, 
00301                         (get_ymax()-get_ymin())/2.0, 
00302                         s*(-0.5*(HopperLength-HopperExitLength)) + c*HopperHeight
00303                         ) 
00304                         + AB*0.5*HopperLength 
00305                         + AC*(-0.5*HopperLength/Ht);
00306 
00307                 Mdouble gamma = random.get_RN((100.0-fill_percent)/100.0,1.0);
00308 
00309                 
00310                 //              Mdouble gamma = random(lowerFillHeight,1.0);
00311 
00312                 Mdouble delta;
00313                 
00314                 if (hopper_dim==1)
00315                         {
00316                         
00317                                 
00318                                 //For the one dimensional delta is a random distance between the two walls the -minus 2 particle radii is to stop 
00322                                 //delta = random(ymin+P0.Radius,ymax-P0.Radius);
00323 
00324                                 delta = random.get_RN(-0.5,0.5)*(get_ymax()-get_ymin()-2.0*P0.get_Radius());
00325 
00326 
00327                         }
00328                 else
00329                         {
00330                                 
00331                                 delta= (random.get_RN(-1.0,1.0)*(0.5*gamma*HopperLength -P0.get_Radius()/Hc));
00332 
00333                         }
00334                 P0.set_Position( A 
00335                         + AC * (gamma*0.5*HopperLength/Ht)
00336 
00337                         + AB * (random.get_RN(-1.0,1.0)*(0.5*gamma*HopperLength - P0.get_Radius()/Hc)) 
00338                         + AD*delta);
00339                         
00340                 
00341                 P0.get_Position().Z+=lift;
00342                 
00343                 //P0.Position.Y = random(ymin+P0.Radius, ymax-P0.Radius);
00344                 //P0.Position.Y=delta;
00345 
00346                 
00347                 
00348         }
00349         
00350         void set_Hopper(Mdouble ExitLength, Mdouble ExitHeight, Mdouble Angle, Mdouble Length){
00351                 if (ExitLength>=0.0) {HopperExitLength = ExitLength;} else cerr << "WARNING : Hopper exit length must be greater than or equal to zero" << endl;
00352                 if (ExitHeight>=0.0) {HopperExitHeight = ExitHeight;} else cerr << "WARNING : Hopper exit height must be greater than or equal to zero" << endl;
00353                 if (Angle>0.0&&Angle<90.0) {HopperAngle = Angle*constants::pi/180.0;} else cerr << "WARNING : Hopper angle must in (0,90)" << endl;
00354                 if (Length>ExitLength) {HopperLength = Length;} else cerr << "WARNING : Hopper length must be greater than exit length" << endl;
00355         }
00356         
00358 
00359         Mdouble get_MaximumVelocityInducedByGravity(){
00360           Mdouble height = HopperHeight+(get_xmax()-shift)*sin(ChuteAngle); 
00361 
00362           return sqrt(2.0*9.8*height);
00363         }
00364         
00366 
00367         Mdouble get_ChuteLength(){return get_xmax()-shift;}
00368 
00370         void set_ChuteLength(Mdouble new_){if (new_>=0.0) {set_xmax(new_+shift); set_xmin(0.0);} else cerr << "WARNING : Chute length unchanged, value must be greater than or equal to zero" << endl;}
00371 
00372         void set_centerHopper(bool new_){centerHopper=new_; }
00373 
00374         void set_lowerFillHeight(Mdouble new_){lowerFillHeight=new_; }
00375         
00376         void set_shift(Mdouble new_){if (new_>=0.0) {set_xmax(get_xmax()+new_-shift); shift = new_;} else cerr << "WARNING : Shift length unchanged, value must be greater than or equal to zero" << endl;}
00377 
00379         virtual void read(std::istream& is)  { 
00380                 Chute::read(is); 
00381                 is >> HopperExitLength >> HopperExitHeight >> HopperLength 
00382                         >> HopperAngle >> HopperHeight >> shift;
00383         }
00384         
00386         virtual void write(std::ostream& os)  { 
00387                 Chute::write(os); 
00388                 os << HopperExitLength << " " << HopperExitHeight << " " << HopperLength 
00389                         << " " << HopperAngle << " " << HopperHeight << " " << shift << " " << endl;
00390         }
00391         
00392         virtual void print(std::ostream& os) {
00393                 Chute::print(os); 
00394                 os 
00395                   << ", HopperExitLength:" << HopperExitLength 
00396                         << ", HopperExitHeight:" << HopperExitHeight 
00397                         << ", HopperLength:" << HopperLength 
00398                         << ", HopperAngle:" << HopperAngle 
00399                         << ", HopperHeight:" << HopperHeight 
00400                         << endl;
00401         }
00402         
00404         void lift_hopper(Mdouble distance){lift=distance;}
00405         Mdouble get_lift_hopper(){return lift;}
00406         
00407         void set_hopper_dim(Mdouble new_hopper_dim){hopper_dim=new_hopper_dim;}
00408         
00409         void set_align_base(bool new_align){align_base=new_align;}
00410 
00411         int readNextArgument(unsigned int& i, unsigned int argc, char *argv[]) {
00412                 if (!strcmp(argv[i],"-hopperLength")) {
00413                         HopperLength=(atof(argv[i+1]));
00414                 } else if (!strcmp(argv[i],"-hopperHeight")) {
00415                         HopperHeight=(atof(argv[i+1]));
00416                 } else if (!strcmp(argv[i],"-hopperAngle")) {
00417                         HopperAngle=(atof(argv[i+1]));
00418                 } else if (!strcmp(argv[i],"-hopperExitLength")) {
00419                         HopperExitLength=(atof(argv[i+1]));
00420                 } else if (!strcmp(argv[i],"-hopperExitHeight")) {
00421                         HopperExitHeight=(atof(argv[i+1]));
00422                 } else if (!strcmp(argv[i],"-lowerFillHeight")) {
00423                         lowerFillHeight=(atof(argv[i+1]));
00424                 } else if (!strcmp(argv[i],"-centerHopper")) {
00425                         centerHopper=(atoi(argv[i+1]));
00426                 } else if (!strcmp(argv[i],"-alignBase")) {
00427                         align_base=(atoi(argv[i+1]));
00428                 } else if (!strcmp(argv[i],"-shift")) {
00429                         shift=(atof(argv[i+1]));
00430                 } else if (!strcmp(argv[i],"-lift")) {
00431                         lift=(atof(argv[i+1]));
00432                 } else return Chute::readNextArgument(i, argc, argv); //if argv[i] is not found, check the commands in Chute
00433                 return true; //returns true if argv[i] is found
00434         }
00435         
00436 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines