示例#1
0
double hyperbolic_step(MESH& m, FLUX& f, double t, double dt, Point ball_loc, int water_tris) {
  for (auto tri_it = m.triangle_begin(); (*tri_it).index() != water_tris; ++tri_it) {
    QVar sum = QVar(0,0,0);

    /* Defines the force of the floating objects by checking its submerged 
    *  cross section of the ball intersects with the centers of adjacent triangles 
    */
    floatObj obj = floatObj();
    if (norm((*tri_it).center()-Point(ball_loc.x, ball_loc.y, 0)) < ball_loc.z)
      obj = floatObj(total_mass*grav, M_PI*ball_loc.z*ball_loc.z, density);

    Point norm_vec = (*tri_it).normal((*tri_it).node1(), (*tri_it).node2());
    // Calcuate flux using adjacent triangle's Q
    if ((*tri_it).adj_triangle((*tri_it).node1(), (*tri_it).node2()).is_valid())
      sum += f(norm_vec.x, norm_vec.y, dt, (*tri_it).value().q_bar, 
      		(*tri_it).adj_triangle((*tri_it).node1(), (*tri_it).node2()).value().q_bar, obj);
    // Boundary conditions
    else
      sum += f(norm_vec.x, norm_vec.y, dt, (*tri_it).value().q_bar, 
      		QVar((*tri_it).value().q_bar.h, 0, 0), obj);

    norm_vec = (*tri_it).normal((*tri_it).node2(), (*tri_it).node3());
    // Calcuate flux using adjacent triangle's Q
    if ((*tri_it).adj_triangle((*tri_it).node2(), (*tri_it).node3()).is_valid()) 
      sum += f(norm_vec.x, norm_vec.y, dt, (*tri_it).value().q_bar, 
      		(*tri_it).adj_triangle((*tri_it).node2(), (*tri_it).node3()).value().q_bar, obj); 
    // Boundary conditions
    else 
      sum += f(norm_vec.x, norm_vec.y, dt, (*tri_it).value().q_bar, 
      		QVar((*tri_it).value().q_bar.h, 0, 0), obj);

    norm_vec = (*tri_it).normal((*tri_it).node3(), (*tri_it).node1());
    // Calcuate flux using adjacent triangle's Q
    if ((*tri_it).adj_triangle((*tri_it).node3(), (*tri_it).node1()).is_valid())
      sum += f(norm_vec.x, norm_vec.y, dt, (*tri_it).value().q_bar, 
      		(*tri_it).adj_triangle((*tri_it).node3(), (*tri_it).node1()).value().q_bar, obj); 
    // Boundary conditions
    else
      sum += f(norm_vec.x, norm_vec.y, dt, (*tri_it).value().q_bar, 
      		QVar((*tri_it).value().q_bar.h, 0, 0), obj);

    (*tri_it).value().q_bar2 = ((*tri_it).value().S * dt/(*tri_it).area()) + (*tri_it).value().q_bar - 
                               (sum * dt/(*tri_it).area());
	}

  /* In order to use original (as opposed to update) q_bar values in the equation above, we have to update
   * q_bar values for all triangles after the q_bar values have been calculated.
   * Updates the Source term
   */
  for (auto tri_it = m.triangle_begin(); (*tri_it).index() != water_tris; ++tri_it){
    (*tri_it).value().S = (*tri_it).value().S/(*tri_it).value().q_bar.h*(*tri_it).value().q_bar2.h;
    (*tri_it).value().q_bar = (*tri_it).value().q_bar2;
  }

  return t + dt;
}
示例#2
0
 double initialize_node_values(MeshType& mesh) const {
     double max_height = 0;
     for (auto nit = mesh.node_begin(); nit != mesh.node_end(); ++nit) {
         if ((*nit).position().x < 0) {
             (*nit).value() = QVar(1.75, 0, 0);
         }
         else {
             (*nit).value() = QVar(1, 0, 0);
         }
         max_height = std::max(max_height, (*nit).value().h);
     }
     
     return max_height;
 }
示例#3
0
/*
 * implementation of euler approximation of the shallow water PDE
 * @pre: a valid Mesh class instance @mesh
 * @post: all triangle in the mesh class have new value() = old value - dt/area() * total flux, 
		  where total flux is calculated by all three edges of the triangle
   @return: return total time t+dt
*/
double hyperbolic_step(MESH& mesh, FLUX& f, double t, double dt) {
  // Step the finite volume model in time by dt.
  // Implement Equation 7 from your pseudocode here.

  for (auto it = mesh.tri_begin(); it!=mesh.tri_end() ; ++it)
  {
	// value function will return the flux
	QVar total_flux=QVar(0,0,0);
	QVar qm = QVar(0,0,0);
	// iterate through 3 edges of a triangle
	auto edgetemp = (*it).edge1();
	for (int num = 0; num < 3; num++)
	{	
		if (num ==0)
			edgetemp= (*it).edge1();
		else if (num==1)
			edgetemp = (*it).edge2();
		else	
			edgetemp = (*it).edge3();
			
		if (  mesh.has_neighbor(edgetemp.index()) ) // it has a common triangle
		{
			auto nx =  ((*it).norm_vector(edgetemp)).x;
			auto ny =  ((*it).norm_vector(edgetemp)).y;
			
			// find the neighbour of a common edge
			for (auto i = mesh.tri_edge_begin(edgetemp.index()); i != mesh.tri_edge_end(edgetemp.index()); ++i){	
				if (!(*i==*it))
					qm = (*i).value();
			}
			// calculat the total flux
			total_flux += f(nx, ny, dt, (*it).value(), qm);
		}
		else{
			// when it doesnt have a neighbour shared with this edge
			auto nx =  ((*it).norm_vector(edgetemp)).x;
			auto ny =  ((*it).norm_vector(edgetemp)).y;
			qm = QVar((*it).value().h, 0, 0 ); // approximation

			total_flux += f(nx, ny, dt, (*it).value(), qm);
		}
	}
	
	(*it).value() +=  total_flux * (- dt / (*it).area());
  }
  
  
  return t + dt;
}
示例#4
0
  QVar operator+(const QVar& q){
	double hnew = h+q.h;
	double hunew = hu+q.hu;
	double hvnew = hv+q.hv;
	//return QVar(h+q.h, hu + q.hu, hv + q.hv);
	return QVar(hnew, hunew, hvnew);
  }
示例#5
0
  QVar operator()(double nx, double ny, double dt,
                  const QVar& qk, const QVar& qm) {
    // Normalize the (nx,ny) vector
    double n_length = std::sqrt(nx*nx + ny*ny);
    nx /= n_length;
    ny /= n_length;

    // The velocities normal to the edge
    double wm = (qm.hx*nx + qm.hy*ny) / qm.h;
    double wk = (qk.hx*nx + qk.hy*ny) / qk.h;

    // Lax-Wendroff local dissipation coefficient
    double vm = sqrt(grav*qm.h) + sqrt(qm.hx*qm.hx + qm.hy*qm.hy) / qm.h;
    double vk = sqrt(grav*qk.h) + sqrt(qk.hx*qk.hx + qk.hy*qk.hy) / qk.h;
    double a  = dt * std::max(vm*vm, vk*vk);

    // Helper values
    double scale = 0.5 * n_length;
    double gh2   = 0.5 * grav * (qm.h*qm.h + qk.h*qk.h);

    // Simple flux with dissipation for stability
    return QVar(scale * (wm*qm.h  + wk*qk.h)           - a * (qm.h  - qk.h),
                scale * (wm*qm.hx + wk*qk.hx + gh2*nx) - a * (qm.hx - qk.hx),
                scale * (wm*qm.hy + wk*qk.hy + gh2*ny) - a * (qm.hy - qk.hy));
  }
示例#6
0
double hyperbolic_step(MESH& m, FLUX& f, double t, double dt) {
  // HW4B: YOUR CODE HERE
  // Step the finite volume model in time by dt.

  // Pseudocode:
  // Compute all fluxes. (before updating any triangle Q_bars)
  // For each triangle, update Q_bar using the fluxes as in Equation 8.
  //  NOTE: Much like symp_euler_step, this may require TWO for-loops

  /* 1. Initialize a vector temp_Q of size @a m.num_triangles() for storing all temp Q_bar values
   * 2. Use a TriangleIterator to iterate through all the triangles, for each tri_it:
   *      a. Compute the sum of fluxes sum_fluxes
   *      b. temp_Q[(*it).index()] = sum_fluxes
   * 3. Use indices of triangles to do another for loop, for each triangle(i):
   *      a. triangle_i.value().Q_bar = temp_Q[i]
   */
  std::vector<QVar> temp_fluxes(m.num_triangles(), QVar());
  for (auto tri_it = m.triangle_begin(); tri_it != m.triangle_end(); ++tri_it) {
    auto qk = (*tri_it).value();
    
    QVar F_k(0, 0, 0);
    for (size_type i = 0; i < 3; ++i) {
      auto edge = (*tri_it).edge(i);
      QVar qm(0, 0, 0);
      if (m.adj_triangle1_index(edge) == -1 || m.adj_triangle2_index(edge) == -1) {
          //set_boundary_conditions
        qm = QVar(qk.h, 0, 0);
      } else {
        size_type adj_tri_idx = m.adj_triangle1_index(edge) == (*tri_it).index() ?
            m.adj_triangle2_index(edge) : m.adj_triangle1_index(edge);

        auto adj_triangle = m.triangle(adj_tri_idx);
        qm = adj_triangle.value(); 
      }
      auto norm_ke = m.out_norm((*tri_it), edge); 
      F_k = F_k + f(norm_ke.x, norm_ke.y, dt, qk, qm);
    } 
    // print_triangle(m, (*tri_it), f, t, dt);
    temp_fluxes[(*tri_it).index()] = qk - F_k * (dt / (*tri_it).area());
  }
  
  for (auto tri_it = m.triangle_begin(); tri_it != m.triangle_end(); ++tri_it) {
    (*tri_it).value() = temp_fluxes[(*tri_it).index()];
  }
  
  return t + dt;
}
示例#7
0
 double initialize_node_values(MeshType& mesh) const {
     double max_height = 0;
     for (auto nit = mesh.node_begin(); nit != mesh.node_end(); ++nit) {
         unsigned H = 0;
         if ((*nit).position().x < 0) H = 1;
         (*nit).value() = QVar(1 + 0.75 * H * (pow(((*nit).position().x - 0.75), 2) + 
                   pow((*nit).position().y, 2) - 0.15 * 0.15), 0, 0);
         max_height = std::max(max_height, (*nit).value().h);
     }
     
     return max_height;
 }
示例#8
0
double hyperbolic_step(MESH& m, FLUX& f, double t, double dt) {
  // HW4B: YOUR CODE HERE
  // Step the finite volume model in time by dt.

  // Pseudocode:
  // Compute all fluxes. (before updating any triangle Q_bars)
  // For each triangle, update Q_bar using the fluxes as in Equation 8.
  //  NOTE: Much like symp_euler_step, this may require TWO for-loops
  
  // Implement Equation 7 from your pseudocode here.

  for(auto i = m.edge_begin(); i != m.edge_end(); ++i){
    if ((*i).triangle1().index() != (unsigned) -1 && (*i).triangle2().index() != (unsigned) -1 ){
      MeshType::Triangle trik = (*i).triangle1();
      MeshType::Triangle trim = (*i).triangle2();
      unsigned int edge_k = 0;
      unsigned int edge_m = 0;
      //which edge (*i) is in trik and trim
      while(trik.node(edge_k).index()== (*i).node1().index() 
        || trik.node(edge_k).index()== (*i).node2().index() )
        ++edge_k;
      while(trim.node(edge_m).index()== (*i).node1().index() 
        || trim.node(edge_m).index()== (*i).node2().index() )
        ++edge_m;
      QVar flux = f(trik.normal(edge_k).x, trik.normal(edge_k).y, dt, trik.value().Q, trim.value().Q);
      trik.value().F[edge_k] = flux;
      trim.value().F[edge_m] = -flux;
    }
    else{
      MeshType::Triangle trik;
      if ((*i).triangle1().index() != (unsigned) -1)
        trik = (*i).triangle1();
      else
        trik = (*i).triangle2();
      unsigned int edge_k = 0;
      while(trik.node(edge_k).index()== (*i).node1().index() 
        || trik.node(edge_k).index()== (*i).node2().index() )
        ++edge_k;
      QVar flux = f(trik.normal(edge_k).x, trik.normal(edge_k).y, dt, trik.value().Q, QVar(trik.value().Q.h, 0, 0));
      trik.value().F[edge_k] = flux;
    }
  }

  for(auto i = m.triangle_begin(); i != m.triangle_end(); ++i){
    QVar sum = QVar(0, 0, 0);
    for (int j = 0; j < 3; ++j){
      sum += (*i).value().F[j];
    }
    (*i).value().Q = (*i).value().Q-dt/(*i).area()*sum;
  }
  
  return t + dt;
};
示例#9
0
    double initialize_node_values(MeshType& mesh) const {
        double max_height = 0;
        for (auto nit = mesh.node_begin(); nit != mesh.node_end(); ++nit) {
            (*nit).value() = QVar(1 - 0.75 * exp(
              -80*(pow((*nit).position().x - 0.75, 2) + pow((*nit).position().y, 2))
              ), 0, 0);

            max_height = std::max(max_height, (*nit).value().h);
        }

        return max_height;
    }
示例#10
0
void post_process(MESH& m) {
  // HW4B: Post-processing step
  // Translate the triangle-averaged values to node-averaged values
  // Implement Equation 9 from your pseudocode here
  for (auto it = m.node_begin(); it != m.node_end(); ++it){
    double sumarea=0;
    QVar sumQ = QVar(0, 0, 0);
    for(auto j = m.triangle_begin(*it); j != m.triangle_end(*it); ++j){
      sumarea += (*j).area();
      sumQ += (*j).value().Q * (*j).area();
    }
    (*it).value().Q = sumQ/sumarea;
  }
}
示例#11
0
Point post_process(MESH& m, FORCE force, CONSTRAINT& c, double t, double dt, uint water_nodes) {
  static double ball_bottom = std::numeric_limits<double>::max();
  double water_dis = std::numeric_limits<double>::max();
  double dh = 0;
  static double submerged_height = 0;
  Point bottom_loc;
  Point water_loc;

  for (auto n_it = m.node_begin(); n_it != m.node_end(); ++n_it) {
    // handles the shallow water
  	if ((*n_it).index() < water_nodes) {
	    double sum_area = 0;
	    QVar value = QVar(0,0,0);

	    for (auto tri_it = m.adj_triangle_begin((*n_it).uid()); tri_it != m.adj_triangle_end((*n_it).uid()); ++tri_it) {
	      value += (*tri_it).value().q_bar * (*tri_it).area();
	      sum_area += (*tri_it).area();
	    }

	    (*n_it).value().q = value * 1.0/(sum_area);
	  }
    // handles the ball
    else {
      (*n_it).set_position((*n_it).position() + (*n_it).value().velocity*dt);
      dh = (*n_it).value().q.h - (*n_it).position().z;
      (*n_it).value().q.h = (*n_it).position().z;
      (*n_it).value().velocity += force(m,(*n_it),t)*dt/(*n_it).value().mass;
      if ((*n_it).value().q.h < ball_bottom) {
        ball_bottom = (*n_it).position().z;
        bottom_loc = (*n_it).position();
      }
    }
  }
  // find the water node closest to the bottom of the ball
  for (auto n_it = m.node_begin(); (*n_it).index() != water_nodes; ++n_it) {
    if (norm(Point((*n_it).position().x,(*n_it).position().y,0)-Point(bottom_loc.x,bottom_loc.y,0)) < water_dis){
      water_dis = norm(Point((*n_it).position().x,(*n_it).position().y,0)-Point(bottom_loc.x,bottom_loc.y,0));
      water_loc = Point((*n_it).position().x,(*n_it).position().y,(*n_it).value().q.h);
    }
  }

  // apply contraints of neccessary
  c(m,ball_bottom);

  // determines if the ball fell below shallow water and updates height submerged
  if (bottom_loc.z < water_loc.z)
    submerged_height += dh;
  return Point(bottom_loc.x, bottom_loc.y, submerged_height);
}
示例#12
0
/*	
 * post process of a mesh instance to update the values of all the nodes values
 * @pre: a valid mesh instance
 * @post: update the nodes values based on approximation of the average of neighbours values
		  refer to equation 9 on the notes
*/
void post_process(MESH& m) {
  // Translate the triangle-averaged values to node-averaged values
  // Implement Equation 8 from your pseudocode here
  	// iterate through all the nodes
  for ( auto it = m.node_begin(); it!= m.node_end(); ++it)
  {
	
	QVar sum = QVar(0,0,0);
	double sumTriArea = 0;
	// for each node, iterate through its adjacent triangles
	
	for (auto adji = m.vertex_begin((*it).index()); adji !=  m.vertex_end((*it).index()); ++ adji)
	{
		auto tri = (*adji);
		sum += tri.area() * tri.value();
		sumTriArea += tri.area();  
	}

	(*it).value() = sum/sumTriArea; // update nodes value
  }
}
示例#13
0
  QVar operator()(double nx, double ny, double dt,
                  const QVar& qk, const QVar& qm) {
    double e_length = sqrt(nx*nx + ny*ny);
    nx /= e_length;
    ny /= e_length;

    // The velocities normal to the edge
    double wm = (qm.hu*nx + qm.hv*ny) / qm.h;
    double wk = (qk.hu*nx + qk.hv*ny) / qk.h;

    // Lax-Wendroff local dissipation coefficient
    double vm = sqrt(grav*qm.h) + sqrt(qm.hu*qm.hu + qm.hv*qm.hv) / qm.h;
    double vk = sqrt(grav*qk.h) + sqrt(qk.hu*qk.hu + qk.hv*qk.hv) / qk.h;
    double a  = dt * std::max(vm*vm, vk*vk);

    // Helper values
    double scale = 0.5 * e_length;
    double gh2   = 0.5 * grav * (qm.h*qm.h + qk.h*qk.h);

    // Simple flux with dissipation for stability
    return QVar(scale * (wm*qm.h  + wk*qk.h)           - a * (qm.h  - qk.h),
                scale * (wm*qm.hu + wk*qk.hu + gh2*nx) - a * (qm.hu - qk.hu),
                scale * (wm*qm.hv + wk*qk.hv + gh2*ny) - a * (qm.hv - qk.hv));
  }
示例#14
0
  QVar operator()(double nx, double ny, double dt,
                  const QVar& qk, const QVar& qm, floatObj obj = floatObj()) {
    double e_length = sqrt(nx*nx + ny*ny);
    nx /= e_length;
    ny /= e_length;

    // The velocities normal to the edge
    double wm = (qm.hu*nx + qm.hv*ny) / qm.h;
    double wk = (qk.hu*nx + qk.hv*ny) / qk.h;

    // Lax-Wendroff local dissipation coefficient
    double vm = sqrt(grav*qm.h) + sqrt(qm.hu*qm.hu + qm.hv*qm.hv) / qm.h;
    double vk = sqrt(grav*qk.h) + sqrt(qk.hu*qk.hu + qk.hv*qk.hv) / qk.h;
    double a  = dt * std::max(vm*vm, vk*vk);

    // Helper values which accounts for floating objects (MODIFIED EQN HERE)
    double scale = 0.5 * e_length;
    double gh2   = (0.5 * grav) * (qm.h*qm.h + qk.h*qk.h) + (obj.F/(obj.A * obj.ro)*(qm.h+qk.h));

    // Simple flux with dissipation for stability
    return QVar(scale * (wm*qm.h  + wk*qk.h)           - a * (qm.h  - qk.h),
                scale * (wm*qm.hu + wk*qk.hu + gh2*nx) - a * (qm.hu - qk.hu),
                scale * (wm*qm.hv + wk*qk.hv + gh2*ny) - a * (qm.hv - qk.hv));
  }
示例#15
0
 TriData():Q(QVar()), F(3, QVar()){}
示例#16
0
int main(int argc, char* argv[])
{
  // Check arguments
  if (argc < 3) {
    std::cerr << "Usage: shallow_water NODES_FILE TRIS_FILE\n";
    exit(1);
  }

  MeshType mesh;
  // HW4B: Need node_type before this can be used!
#if 1
  std::vector<typename MeshType::node_type> mesh_node;
#endif

  // Read all Points and add them to the Mesh
  std::ifstream nodes_file(argv[1]);
  Point p;
  while (CS207::getline_parsed(nodes_file, p)) {
    // HW4B: Need to implement add_node before this can be used!
#if 1
    mesh_node.push_back(mesh.add_node(p));
#endif
  }

  // Read all mesh triangles and add them to the Mesh
  std::ifstream tris_file(argv[2]);
  std::array<int,3> t;
  while (CS207::getline_parsed(tris_file, t)) {
    // HW4B: Need to implement add_triangle before this can be used!
#if 1
    mesh.add_triangle(mesh_node[t[0]], mesh_node[t[1]], mesh_node[t[2]]);
#endif
  }

  // Print out the stats
  std::cout << mesh.num_nodes() << " "
            << mesh.num_edges() << " "
            << mesh.num_triangles() << std::endl;

  // HW4B Initialization
  // Set the initial conditions according the type of input pattern
  if(argv[2][5]=='d'){
    Dam<MeshType> init;
    for(auto it= mesh.node_begin(); it != mesh.node_end(); ++it)
      init(*it);
    }
  else if((argv[2][5]=='p')){
    Pebble<MeshType> init;
    for(auto it= mesh.node_begin(); it != mesh.node_end(); ++it)
      init(*it);
    }
  else{
    Wave<MeshType> init;
    for(auto it= mesh.node_begin(); it != mesh.node_end(); ++it)
      init(*it);
    }

  // Set triangle values
  for (auto it=mesh.triangle_begin(); it!=mesh.triangle_end(); ++it) {
    (*it).value().Q = QVar(0.0,0.0,0.0);
    (*it).value().Q += (*it).node(0).value().Q;
    (*it).value().Q += (*it).node(1).value().Q;
    (*it).value().Q += (*it).node(2).value().Q;
    (*it).value().Q /= 3.0;
  }
 

  // Launch the SDLViewer
  CS207::SDLViewer viewer;
  viewer.launch();


  // HW4B: Need to define Mesh::node_type and node/edge iterator
  // before these can be used!
#if 1
  auto node_map = viewer.empty_node_map(mesh);
  viewer.add_nodes(mesh.node_begin(), mesh.node_end(),
                   CS207::DefaultColor(), NodePosition(), node_map);
  viewer.add_edges(mesh.edge_begin(), mesh.edge_end(), node_map);
#endif
  viewer.center_view();


  // HW4B: Timestep
  // CFL stability condition requires dt <= dx / max|velocity|
  // For the shallow water equations with u = v = 0 initial conditions
  //   we can compute the minimum edge length and maximum original water height
  //   to set the time-step
  // Compute the minimum edge length and maximum water height for computing dt
  double min_edge_length =( *mesh.edge_begin()).length();
  for (auto it=mesh.edge_begin(); it!=mesh.edge_end(); ++it) {
    if ((*it).length() < min_edge_length) {
      min_edge_length = (*it).length();
    }
  }
  double max_height = 0.0;
  for (auto it=mesh.node_begin(); it!=mesh.node_end(); ++it) {
    if ((*it).value().Q.h > max_height) {
      max_height = (*it).value().Q.h;
    }
  }
  
#if 1

  double dt = 0.25 * min_edge_length / (sqrt(grav * max_height));
#else
  // Placeholder!! Delete me when min_edge_length and max_height can be computed!
  double dt = 0.1;
#endif
  double t_start = 0;
  double t_end = 10;

  // Preconstruct a Flux functor
  EdgeFluxCalculator f;

  // Begin the time stepping
  for (double t = t_start; t < t_end; t += dt) {
    //print(mesh, t);
    // Step forward in time with forward Euler
    hyperbolic_step(mesh, f, t, dt);

    // Update node values with triangle-averaged values
    post_process(mesh);

    // Update the viewer with new node positions
    // HW4B: Need to define node_iterators before these can be used!
#if 1
    viewer.add_nodes(mesh.node_begin(), mesh.node_end(),
                     CS207::DefaultColor(), NodePosition(), node_map);
#endif
    viewer.set_label(t);

    // These lines slow down the animation for small meshes.
    // Feel free to remove them or tweak the constants.
    if (mesh.num_nodes() < 100)
      CS207::sleep(0.05);
  }

  return 0;
}
示例#17
0
int main(int argc, char* argv[]) {
  // Check arguments
  if (argc < 5) {
    std::cerr << "Usage: final_project NODES_FILE TRIS_FILE ball.nodes ball.tris \n";
    exit(1);
  }

  MeshType mesh;
  std::vector<typename MeshType::node_type> mesh_node;

  // Read all water Points and add them to the Mesh
  std::ifstream nodes_file(argv[1]);
  Point p;
  uint water_nodes = 0;
  while (CS207::getline_parsed(nodes_file, p)) {
    mesh_node.push_back(mesh.add_node(p));
    water_nodes++;
  }

  // Read all water mesh triangles and add them to the Mesh
  std::ifstream tris_file(argv[2]);
  std::array<int,3> t;
  int water_tris = 0;
  while (CS207::getline_parsed(tris_file, t)) {
    mesh.add_triangle(mesh_node[t[0]], mesh_node[t[1]], mesh_node[t[2]]);
    water_tris++;
  }
  uint water_edges = mesh.num_edges();

  std::ifstream nodes_file2(argv[3]);
  double radius = 1 * scale;
  while (CS207::getline_parsed(nodes_file2, p)) {
    p *= scale;
    p.z += + start_height;
    mesh_node.push_back(mesh.add_node(p));
  }

  // Read all ball mesh triangles and add them to the mesh
  std::ifstream tris_file2(argv[4]);
  while (CS207::getline_parsed(tris_file2, t)) {
    mesh.add_triangle(mesh_node[t[0]+water_nodes], mesh_node[t[1]+water_nodes], mesh_node[t[2]+water_nodes]);
  }

  // Print out the stats
  std::cout << mesh.num_nodes() << " "
            << mesh.num_edges() << " "
            << mesh.num_triangles() << std::endl;

  /* Set the initial conditions */ 
  // Set the initial values of the nodes and get the maximum height double
  double max_h = 0;
  double dx = 0;
  double dy = 0;
  auto init_cond = Still();
  auto b_init_cond = Cone(); 

  // Find the maximum height and apply initial conditions to nodes
  for (auto it = mesh.node_begin(); it != mesh.node_end(); ++it) { 
    auto n = *it;
    if (n.index() < water_nodes){
	    n.value().q = init_cond(n.position());
	    n.value().b = b_init_cond(n.position());
	    max_h = std::max(max_h, n.value().q.h);
  	}
  	else {
  		n.value().q = QVar(n.position().z, 0, 0);
      n.value().mass = total_mass/(mesh.num_nodes() - water_nodes);
      n.value().velocity = Point(0.0,0.0,0.0);
  	}
  } 

  // Set the initial values of the triangles to the average of their nodes and finds S
  // Set the triangle direction values so that we can determine which 
  // way to point normal vectors. This part assumes a convex shape
  Point center = get_center(mesh); 
  for (auto it = mesh.triangle_begin(); it != mesh.triangle_end(); ++it) {
    auto t = *it; 
    if (t.index() < water_tris){
	    t.value().q_bar = (t.node1().value().q + 
	                       t.node2().value().q + 
	                       t.node3().value().q) / 3.0;
	    t.value().q_bar2 = t.value().q_bar;

	    double b_avg = (t.node1().value().b + 
	                    t.node2().value().b + 
	                    t.node3().value().b) / 3.0;
	    // finds the max dx and dy to calculate Source
	    dx = std::max(dx, fabs(t.node1().position().x - t.node2().position().x));
	    dx = std::max(dx, fabs(t.node2().position().x - t.node3().position().x));
	    dx = std::max(dx, fabs(t.node3().position().x - t.node1().position().x));
	    dy = std::max(dy, fabs(t.node1().position().y - t.node2().position().y));
	    dy = std::max(dy, fabs(t.node2().position().y - t.node3().position().y));
	    dy = std::max(dy, fabs(t.node3().position().y - t.node1().position().y));
	    t.value().S = QVar(0, -grav * t.value().q_bar.h * b_avg / dx, -grav * t.value().q_bar.h * b_avg / dy);
	  } 
    else
      set_normal_direction((*it),center);
  }

  // Calculate the minimum edge length and set edge inital condititons
  double min_edge_length = std::numeric_limits<double>::max();
  uint count = 0;
  for (auto it = mesh.edge_begin(); it != mesh.edge_end(); ++it, count++){
    if (count < water_edges)
      min_edge_length = std::min(min_edge_length, (*it).length());
    else {
      (*it).value().spring_constant = spring_const;
      (*it).value().initial_length = (*it).length();
    }
  }
	
  // Launch the SDLViewer
  CS207::SDLViewer viewer;
  viewer.launch();

  auto node_map = viewer.empty_node_map(mesh);
  viewer.add_nodes(mesh.node_begin(), mesh.node_end(),
                   Color(water_nodes), NodePosition(), node_map);
  viewer.add_edges(mesh.edge_begin(), mesh.edge_end(), node_map);
  // adds solid color-slows down program significantly
  //viewer.add_triangles(mesh.triangle_begin(), mesh.triangle_end(), node_map);
  viewer.center_view();


  // CFL stability condition requires dt <= dx / max|velocity|
  // For the shallow water equations with u = v = 0 initial conditions
  //   we can compute the minimum edge length and maximum original water height
  //   to set the time-step
  // Compute the minimum edge length and maximum water height for computing dt
  double dt = 0.25 * min_edge_length / (sqrt(grav * max_h));
  double t_start = 0;
  double t_end = 10;
  Point ball_loc = Point(0,0,0);
  double dh = 0;
  // double pressure = gas_const/(4/3*M_PI*radius*radius*radius);

  // add listener
  my_listener* l = new my_listener(viewer,mesh,dt); 
  viewer.add_listener(l);

  // Preconstruct a Flux functor
  EdgeFluxCalculator f;
  // defines the constraint
  PlaneConstraint c = PlaneConstraint(plane_const);

  // Begin the time stepping
  for (double t = t_start; t < t_end; t += dt) {
    // define forces on ball
    GravityForce g_force;
    BuoyantForce b_force = BuoyantForce(dh, ball_loc.z);
    WindForce w_force;
    MassSpringForce ms_force;
    // PressureForce p_force = PressureForce(pressure);
    // DampingForce d_force = DampingForce(mesh.num_nodes());
    auto combined_forces = make_combined_force(g_force, b_force, w_force, ms_force);
    
    // Step forward in time with forward Euler
    hyperbolic_step(mesh, f, t, dt, ball_loc, water_tris);

    // Update node values with triangle-averaged values
    ball_loc = post_process(mesh, combined_forces, c, t, dt, water_nodes);

    // Update the viewer with new node positions
    viewer.add_nodes(mesh.node_begin(), mesh.node_end(), 
                     Color(water_nodes), NodePosition(), node_map);
    // viewer.add_triangles(mesh.triangle_begin(), mesh.triangle_end(), node_map);
    viewer.set_label(t);

    // find radius of cross sectional radius of ball submerged
    dh = ball_loc.z;
    if (dh > 2*radius)
      dh = 2 * radius;
    ball_loc.z = cross_radius(radius, dh);

    // These lines slow down the animation for small meshes.
    if (mesh.num_nodes() < 100)
      CS207::sleep(0.05);
  }
  return 0;
}
示例#18
0
  QVar operator/ (double n){
	return QVar(h/n, hu/n, hv/n);
  
  }
示例#19
0
 QVar operator()(Point p) {
   if (pow(p.x-0.75,2) + pow(p.y,2) - pow(0.15,2) < 0)
     return QVar(1.75,0,0);
   else
     return QVar(1.0,0,0);
 }
示例#20
0
 QVar operator()(Point p) {
   return QVar(1.0 - 0.75*exp(-80*(pow((p.x-0.75),2) + pow(p.y,2))), 0, 0);
 }
示例#21
0
int main(int argc, char* argv[])
{
  // Check arguments
  if (argc < 3) {
    std::cerr << "Usage: shallow_water NODES_FILE TRIS_FILE\n";
    exit(1);
  }

auto start = std::chrono::high_resolution_clock::now();

  MeshType mesh;
  // HW4B: Need node_type before this can be used!

  std::vector<typename MeshType::node_type> mesh_node;

  // Read all Points and add them to the Mesh
  std::ifstream nodes_file(argv[1]);
  Point p;
  while (CS207::getline_parsed(nodes_file, p)) {
    mesh_node.push_back(mesh.add_node(p));
  }

  // Read all mesh triangles and add them to the Mesh
  std::ifstream tris_file(argv[2]);
  std::array<int,3> t;
  while (CS207::getline_parsed(tris_file, t)) {
    // HW4B: Need to implement add_triangle before this can be used!
    mesh.add_triangle(mesh_node[t[0]], mesh_node[t[1]], mesh_node[t[2]]);
  }

  // Print out the stats
  std::cout << mesh.num_nodes() << " "
            << mesh.num_edges() << " "
            << mesh.num_triangles() << std::endl;

 
 //Start of nearest neighor.  Put all positions that you want inspected in a vector of type double
 std::vector<double> pos; 
 for (auto it = mesh.node_begin(); it != mesh.node_end(); ++it ) 	
	pos.push_back((*it).position().z);

  unsigned num_neighbors = 10; //num of neighors to return
  unsigned object_idx = 5; // do this if you want to examine the neighbors of a specific idx

  MeshType::NearestNeighbor a = mesh.calculateNearestNeighbors(num_neighbors ,pos);
  auto idx = mesh.getNeighbors(a,object_idx);
  auto dist = mesh.getNeighborDistances(a,object_idx);
  /*auto all_n = mesh.getAllNeighbors(a);
  auto all_d = mesh.getAllNeighborDistances(a);*/

  for (unsigned i = 0; i < idx.size(); ++i)
	std::cout << "Node " << object_idx << "'s " << i << " neighbor is: node " << idx[i] << " with distance of " << dist[i] << endl;

  /*//Uncomment to view results for all nodes
  for (unsigned j = 0; j < pos.size(); ++j){
     std::cout << endl;
     for (unsigned i = 0; i < num_neighbors; ++i)
	std::cout << "For node " << j << " neighbor " << i << " is index " << all_n[i+j*num_neighbors] << " and distance is " << all_d[i+j*num_neighbors] << endl;
  }*/


  // HW4B Initialization
  // Set the initial conditions
  int wave = 0, peddle=0, dam=1;
  if (wave){
	for ( auto it = mesh.node_begin(); it!= mesh.node_end(); ++it){
		auto x = (*it).position().x;
		auto y = (*it).position().y;
		double h = 1-0.75 * exp(-80 * ( (x-0.75)*(x-0.75) + y*y ));
		mesh.value((*it),QVar( h,0,0));
	}
  }
  else if (peddle){
	for ( auto it = mesh.node_begin(); it!= mesh.node_end(); ++it){
		auto x = (*it).position().x;
		auto y = (*it).position().y;
		double h = (x-0.75)*(x-0.75) + y*y -0.15*0.15 ;
		int H =0;
		if (h < 0)
			H = 1;
		mesh.value((*it), QVar(1+0.75*H,0,0));
	}
  }
  else if (dam){
	for ( auto it = mesh.node_begin(); it!= mesh.node_end(); ++it){
		auto x = (*it).position().x;
		int H =0;
		if (x < 0)
			H = 1;
		mesh.value((*it), QVar(1+0.75*H,0,0));
	}
  }
  
  
  // Perform any needed precomputation
// initialize triangle
  for (auto it = mesh.tri_begin(); it != mesh.tri_end(); ++it ) {
	(*it).value() = ((*it).node1().value() + (*it).node2().value() + (*it).node3().value())/3.0;
  }


  // Launch the SDLViewer
  CS207::SDLViewer viewer;
  viewer.launch();

  // HW4B: Need to define Mesh::node_type and node/edge iterator
  // before these can be used!
  
  auto node_map = viewer.empty_node_map(mesh);
  viewer.add_nodes(mesh.node_begin(), mesh.node_end(),
                   CS207::DefaultColor(), NodePosition(), node_map);
  viewer.add_edges(mesh.edge_begin(), mesh.edge_end(), node_map);

  viewer.center_view();
  
  // HW4B: Timestep
  // CFL stability condition requires dt <= dx / max|velocity|
  // For the shallow water equations with u = v = 0 initial conditions
  //   we can compute the minimum edge length and maximum original water height
  //   to set the time-step
  // Compute the minimum edge length and maximum water height for computing dt
  auto min_length = *std::min_element(mesh.edge_begin(), mesh.edge_end(), EdgeComparator);
  
  auto max_h = *std::max_element(mesh.node_begin(), mesh.node_end(), HeightComparator);
  
  double dt = 0.25 * min_length.length() / (sqrt(grav * max_h.value().h));
  double t_start = 0;
  double t_end = 0.1;

  // Preconstruct a Flux functor
  EdgeFluxCalculator f;

  // Begin the time stepping
  for (double t = t_start; t < t_end; t += dt) {
    // Step forward in time with forward Euler
    hyperbolic_step(mesh, f, t, dt);

    // Update node values with triangle-averaged values
    post_process(mesh);

    // Update the viewer with new node positions
    // HW4B: Need to define node_iterators before these can be used!
    viewer.add_nodes(mesh.node_begin(), mesh.node_end(),
                     CS207::DefaultColor(), NodePosition(), node_map);
    viewer.set_label(t);
	
    // These lines slow down the animation for small meshes.
    // Feel free to remove them or tweak the constants.
    if (mesh.num_nodes() < 100)
      CS207::sleep(0.05);
  }
auto elapsed = std::chrono::high_resolution_clock::now() - start;
long long microseconds = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();

cout << microseconds << endl;
  
return 0;
}
示例#22
0
  QVar operator-(const QVar& q){
	return QVar(h-q.h, hu - q.hu, hv - q.hv);
  }  
示例#23
0
QVar operator*(double n, QVar& q){
	return QVar(n*q.h,n*q.hu,n*q.hv);  
}
示例#24
0
 QVar operator()(Point p) {
   if (p.x < 0)
     return QVar(1.75,0,0);
   else
     return QVar(1.0,0,0);
 }
示例#25
0
  QVar operator* (double n){
	return QVar(h*n, hu*n, hv*n);
  }
示例#26
0
 QVar operator()(Point p) {
   (void) p;
   return QVar(1.0,0,0);
 }
示例#27
0
QVar operator/(double n,QVar& q) {
	return QVar(n/q.h, n/q.hu, n/q.hv);
}