boost::tuple<mpl::size_t<MESH_EDGES>, typename MeshTraits<MeshType>::location_edge_const_iterator, typename MeshTraits<MeshType>::location_edge_const_iterator> internaledges( MeshType const& mesh, mpl::bool_<false> ) { return boost::make_tuple( mpl::size_t<MESH_EDGES>(), mesh.beginInternalEdge(), mesh.endInternalEdge() ); }
MeshType* load(const xml::Node& desc, gcm::Body* body) { MeshType* mesh = new MeshType(); mesh->setId(desc["id"]); mesh->setCalc(desc.getAttributeByName("calc", "false") == "true"); mesh->setBody(body); loadMesh(desc, mesh); return mesh; }
boost::tuple<mpl::size_t<MESH_FACES>, typename MeshTraits<MeshType>::face_const_iterator, typename MeshTraits<MeshType>::face_const_iterator> idedfaces( MeshType const& mesh, size_type id, mpl::bool_<false> ) { return boost::make_tuple( mpl::size_t<MESH_FACES>(), mesh.beginFaceWithId( id ), mesh.endFaceWithId( id ) ); }
boost::tuple<mpl::size_t<MESH_POINTS>, typename MeshTraits<MeshType>::location_point_const_iterator, typename MeshTraits<MeshType>::location_point_const_iterator> internalpoints( MeshType const& mesh, mpl::bool_<false> ) { return boost::make_tuple( mpl::size_t<MESH_POINTS>(), mesh.beginInternalPoint( ), mesh.endInternalPoint() ); }
boost::tuple<mpl::size_t<MESH_EDGES>, typename MeshTraits<MeshType>::location_edge_const_iterator, typename MeshTraits<MeshType>::location_edge_const_iterator> boundaryedges( MeshType const& mesh, mpl::bool_<false> ) { return boost::make_tuple( mpl::size_t<MESH_EDGES>(), mesh.beginEdgeOnBoundary(), mesh.endEdgeOnBoundary() ); }
boost::tuple<mpl::size_t<MESH_ELEMENTS>, typename MeshTraits<MeshType>::element_const_iterator, typename MeshTraits<MeshType>::element_const_iterator> allelements( MeshType const& mesh, mpl::bool_<false> ) { return boost::make_tuple( mpl::size_t<MESH_ELEMENTS>(), mesh.beginElement(), mesh.endElement() ); }
boost::tuple<mpl::size_t<MESH_POINTS>, typename MeshTraits<MeshType>::marker_point_const_iterator, typename MeshTraits<MeshType>::marker_point_const_iterator> markedpoints( MeshType const& mesh, size_type flag, mpl::bool_<false> ) { return boost::make_tuple( mpl::size_t<MESH_POINTS>(), mesh.beginPointWithMarker( flag ), mesh.endPointWithMarker( flag ) ); }
boost::tuple<mpl::size_t<MESH_ELEMENTS>, typename MeshTraits<MeshType>::element_const_iterator, typename MeshTraits<MeshType>::element_const_iterator> elements( MeshType const& mesh, rank_type pid, mpl::bool_<false> ) { return boost::make_tuple( mpl::size_t<MESH_ELEMENTS>(), mesh.beginElementWithProcessId( pid ), mesh.endElementWithProcessId( pid ) ); }
boost::tuple<mpl::size_t<MESH_FACES>, typename MeshTraits<MeshType>::marker3_face_const_iterator, typename MeshTraits<MeshType>::marker3_face_const_iterator> marked3faces( MeshType const& mesh, rank_type __pid, mpl::bool_<false> ) { typedef typename MeshTraits<MeshType>::marker3_face_const_iterator iterator; auto beg = mesh.beginFaceWithMarker3(); auto end = mesh.endFaceWithMarker3(); return boost::make_tuple( mpl::size_t<MESH_FACES>(), beg, end ); }
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; }
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; }
std::pair<double, double> operator()(MeshType& mesh) const { double max_height = derived().initialize_node_values(mesh); double min_edge_length = (*mesh.edge_begin()).length(); for (auto eit = mesh.edge_begin(); eit != mesh.edge_end(); ++eit) { min_edge_length = std::min(min_edge_length, (*eit).length()); } for (auto tri_it = mesh.triangle_begin(); tri_it != mesh.triangle_end(); ++tri_it) { (*tri_it).value() = ((*tri_it).node(0).value() + (*tri_it).node(1).value() + (*tri_it).node(2).value()) / 3.0; } return std::make_pair(max_height, min_edge_length); }
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; }
void createPointNeighbors ( MeshType const& mesh, neighborList_Type& neighborList ) { neighborList.resize ( mesh.numGlobalPoints() ); // generate point neighbors by watching edges // note: this can be based also on faces or volumes for ( UInt ie = 0; ie < mesh.numEdges(); ie++ ) { ID id0 = mesh.edge ( ie ).point ( 0 ).id(); ID id1 = mesh.edge ( ie ).point ( 1 ).id(); ASSERT ( mesh.point ( id0 ).id() == id0 && mesh.point ( id1 ).id() == id1, "the mesh has been reordered, the point must be found" ); neighborList[ id0 ].insert ( id1 ); neighborList[ id1 ].insert ( id0 ); } }
boost::tuple<mpl::size_t<MESH_ELEMENTS>, typename MeshTraits<MeshType>::location_element_const_iterator, typename MeshTraits<MeshType>::location_element_const_iterator> boundaryelements( MeshType const& mesh, uint16_type entity_min_dim, uint16_type entity_max_dim, rank_type pid, mpl::bool_<false> ) { typedef typename MeshTraits<MeshType>::location_element_const_iterator iterator; std::pair<iterator, iterator> p = mesh.boundaryElements( entity_min_dim, entity_max_dim, pid ); return boost::make_tuple( mpl::size_t<MESH_ELEMENTS>(), p.first, p.second ); }
boost::tuple<mpl::size_t<MESH_ELEMENTS>, typename MeshTraits<MeshType>::location_element_const_iterator, typename MeshTraits<MeshType>::location_element_const_iterator> internalelements( MeshType const& mesh, rank_type pid, mpl::bool_<false> ) { typedef typename MeshTraits<MeshType>::location_element_const_iterator iterator; std::pair<iterator, iterator> p = mesh.internalElements( pid ); return boost::make_tuple( mpl::size_t<MESH_ELEMENTS>(), p.first, p.second ); }
boost::tuple<mpl::size_t<MESH_FACES>, typename MeshTraits<MeshType>::pid_face_const_iterator, typename MeshTraits<MeshType>::pid_face_const_iterator> faces( MeshType const& mesh, rank_type __pid, mpl::bool_<false> ) { typedef typename MeshTraits<MeshType>::pid_face_const_iterator pid_face_const_iterator; pid_face_const_iterator it,en; boost::tie( it, en ) = mesh.facesWithProcessId( __pid ); return boost::make_tuple( mpl::size_t<MESH_FACES>(), it, en ); }
boost::tuple<mpl::size_t<MESH_FACES>, typename MeshTraits<MeshType>::location_face_const_iterator, typename MeshTraits<MeshType>::location_face_const_iterator> boundaryfaces( MeshType const& mesh, rank_type __pid, mpl::bool_<false> ) { typedef typename MeshTraits<MeshType>::location_face_const_iterator iterator; std::pair<iterator, iterator> p = mesh.facesOnBoundary( __pid ); return boost::make_tuple( mpl::size_t<MESH_FACES>(), p.first, p.second ); }
boost::tuple<mpl::size_t<MESH_ELEMENTS>, typename MeshTraits<MeshType>::marker3_element_const_iterator, typename MeshTraits<MeshType>::marker3_element_const_iterator> marked3elements( MeshType const& mesh, flag_type flag, rank_type pid, mpl::bool_<false> ) { typedef typename MeshTraits<MeshType>::marker3_element_const_iterator iterator; std::pair<iterator, iterator> p = mesh.elementsWithMarker3( flag, pid ); return boost::make_tuple( mpl::size_t<MESH_ELEMENTS>(), p.first, p.second ); }
boost::tuple<mpl::size_t<MESH_EDGES>, typename MeshTraits<MeshType>::marker_edge_const_iterator, typename MeshTraits<MeshType>::marker_edge_const_iterator> markededges( MeshType const& mesh, flag_type __marker, rank_type __pid, mpl::bool_<false> ) { typedef typename MeshTraits<MeshType>::marker_edge_const_iterator iterator; std::pair<iterator, iterator> p = mesh.edgesWithMarker( __marker, __pid ); return boost::make_tuple( mpl::size_t<MESH_EDGES>(), p.first, p.second ); }
void createPointNeighbors ( MeshType& mesh ) { // TODO: ASSERT_COMPILE_TIME that MeshType::pointMarker == NeighborMarker // this guarantees that the pointNeighbors structure is available. // generate point neighbors by watching edges // note: this can be based also on faces or volumes for ( UInt ie = 0; ie < mesh.numEdges(); ie++ ) { ID id0 = mesh.edge ( ie ).point ( 0 ).id(); ID id1 = mesh.edge ( ie ).point ( 1 ).id(); ASSERT ( mesh.point ( id0 ).id() == id0 , "the mesh has been reordered, the point must be found" ); ASSERT ( mesh.point ( id1 ).id() == id1 , "the mesh has been reordered, the point must be found" ); mesh.point ( id0 ).pointNeighbors().insert ( id1 ); mesh.point ( id1 ).pointNeighbors().insert ( id0 ); } }
void test(const shared_ptr< DistanceOctree< MeshType > > & distanceOctree, const MeshType & mesh, const AABB & domainAABB, Vector3<uint_t> numBlocks) { Vector3<real_t> blockSize(domainAABB.xSize() / real_c(numBlocks[0]), domainAABB.ySize() / real_c(numBlocks[1]), domainAABB.zSize() / real_c(numBlocks[2])); real_t maxError = blockSize.min() / real_t(10); SetupBlockForest setupBlockforest; setupBlockforest.addRootBlockExclusionFunction(F(distanceOctree, maxError)); setupBlockforest.addWorkloadMemorySUIDAssignmentFunction(blockforest::uniformWorkloadAndMemoryAssignment); setupBlockforest.init(domainAABB, numBlocks[0], numBlocks[1], numBlocks[2], false, false, false); WALBERLA_LOG_DEVEL(setupBlockforest.toString()); std::vector< Vector3<real_t> > vertexPositions; vertexPositions.reserve(mesh.n_vertices()); for (auto vIt = mesh.vertices_begin(); vIt != mesh.vertices_end(); ++vIt) { vertexPositions.push_back(toWalberla(mesh.point(*vIt))); } std::vector< const blockforest::SetupBlock* > setupBlocks; setupBlockforest.getBlocks(setupBlocks); // Check wether all vertices are located in allocated blocks std::vector< Vector3<real_t> > uncoveredVertices(vertexPositions); for (auto bIt = setupBlocks.begin(); bIt != setupBlocks.end(); ++bIt) { const AABB & aabb = (*bIt)->getAABB(); uncoveredVertices.erase(std::remove_if(uncoveredVertices.begin(), uncoveredVertices.end(), PointInAABB(aabb)), uncoveredVertices.end()); } WALBERLA_CHECK(uncoveredVertices.empty(), "Not all vertices of the mesh are located in allocated blocks!"); //setupBlockforest.assignAllBlocksToRootProcess(); //setupBlockforest.writeVTKOutput( "setupblockforest" ); }
boost::tuple<mpl::size_t<MESH_FACES>, typename MeshTraits<MeshType>::interprocess_face_const_iterator, typename MeshTraits<MeshType>::interprocess_face_const_iterator> interprocessfaces( MeshType const& mesh, rank_type neighbor_pid, mpl::bool_<false> ) { typedef typename MeshTraits<MeshType>::interprocess_face_const_iterator iterator; std::pair<iterator, iterator> p = mesh.interProcessFaces( neighbor_pid ); return boost::make_tuple( mpl::size_t<MESH_FACES>(), p.first, p.second ); }
coupledInfo<MeshType>::coupledInfo ( const MeshType& mesh, const bool isTwoDMesh, const bool isLocal, const bool isSend, const label patchIndex, const label mPatch, const label sPatch, const label mfzIndex, const label sfzIndex ) : mesh_(mesh), builtMaps_(false), map_ ( IOobject ( "coupleMap_" + Foam::name(mPatch) + "_To_" + Foam::name(sPatch) + word(isLocal ? "_Local" : "_Proc") + word(isSend ? "_Send" : "_Recv"), mesh.time().timeName(), mesh, IOobject::NO_READ, IOobject::NO_WRITE, true ), isTwoDMesh, isLocal, isSend, patchIndex, mPatch, sPatch ), masterFaceZone_(mfzIndex), slaveFaceZone_(sfzIndex) {}
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 based off third argument // Perform any needed precomputation std::pair<double, double> value_pair; if ((*argv[3]) == '0') { std::cout << "Pebble Ripple" << std::endl; value_pair = PebbleRipple()(mesh); } else if ((*argv[3]) == '1') { std::cout << "Sharp Wave" << std::endl; value_pair = SharpWave()(mesh); } else { std::cout << "Dam Break" << std::endl; value_pair = DamBreak()(mesh); } double max_height = value_pair.first; double min_edge_length = value_pair.second; // 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(); // 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 #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 = 5; // 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 #if 1 // Update viewer with nodes' new positions viewer.add_nodes(mesh.node_begin(), mesh.node_end(), CoolColor(), 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; }
/** Returns a grid of the interval separated by the number of points. * @param[in] x [low, high] domain of x * @param[in] y [low, high] domain of y * @param[in] n_x number of linearly spaced points in interval x * @param[in] n_y number of linearly space points in interval y * @return Mesh which connects all the points in the grid. * * Complexity: O(n_x*n_y). */ MeshType operator()(interval x, interval y, size_type n_x, size_type n_y) { MeshType mesh; value_type x_step = (x.second - x.first) / (n_x - 1); value_type y_step = (y.second - y.first) / (n_y - 1); for (size_type j = n_y; j > 0; --j) { for (size_type i = 1; i <= n_x; ++i) { mesh.add_node(Point((i-1)*x_step, (j-1)*y_step, 0)); MeshType::size_type idx = mesh.num_nodes() - 1; if (j != n_y) { if (i == 1) { mesh.add_triangle(mesh.node(idx), mesh.node(idx - n_x), mesh.node(idx - n_x + 1)); } else if (i == n_x) { mesh.add_triangle(mesh.node(idx), mesh.node(idx - 1), mesh.node(idx - n_x)); } else { mesh.add_triangle(mesh.node(idx), mesh.node(idx - 1), mesh.node(idx - n_x)); mesh.add_triangle(mesh.node(idx), mesh.node(idx - n_x), mesh.node(idx - n_x + 1)); } } } } return mesh; }
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; }
int main(int argc, char* argv[]) { // Check arguments if (argc < 2) { std::cerr << "Usage: " << argv[0] << " NODES_FILE TETS_FILE\n"; exit(1); } MeshType mesh; std::vector<typename MeshType::node_type> nodes; // Create a nodes_file from the first input argument std::ifstream nodes_file(argv[1]); // Interpret each line of the nodes_file as a 3D Point and add to the Mesh Point p; while (CS207::getline_parsed(nodes_file, p)) nodes.push_back(mesh.add_node(p)); // Create a trianges_file from the second input argument std::ifstream triangles_file(argv[2]); // Interpret each line of the tets_file as three ints which refer to nodes std::array<int,3> t; // add in the triangles while (CS207::getline_parsed(triangles_file, t)) for (unsigned i = 1; i < t.size(); ++i) for (unsigned j = 0; j < i; ++j) for (unsigned k = 0; k < j; ++k) { mesh.add_triangle(nodes[t[i]], nodes[t[j]], nodes[t[k]]); } // Set masses of nodes equal to 1/N where N is the number of nodes // and the initial velocities to 0. Also, get the indexes of // the nodes at positions (1,0,0) and (0,0,0) for(auto it=mesh.node_begin(); it != mesh.node_end(); ++ it) { (*it).value().mass = total_mass/mesh.num_nodes(); (*it).value().velocity = Point(0.0,0.0,0.0); } // Set spring constants for each node equal to spring_const variable // and set initial length values equal to lengths of edges prior to // running the symplectic Euler steps for(auto it=mesh.edge_begin(); it != mesh.edge_end(); ++ it) { (*it).value().spring_constant = spring_const; (*it).value().initial_length = (*it).length(); } // 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) { //std::cout << (*it).index() << std::endl; set_normal_direction((*it),center); } // Print out the stats std::cout << mesh.num_nodes() << " " << mesh.num_edges() << std::endl; std::cout << "Center: " << get_center(mesh) << std::endl; // Launch the SDLViewer CS207::SDLViewer viewer; auto node_map = viewer.empty_node_map(mesh); viewer.launch(); viewer.add_nodes(mesh.node_begin(), mesh.node_end(), node_map); viewer.add_edges(mesh.edge_begin(), mesh.edge_end(), node_map); viewer.center_view(); // Begin the mass-spring simulation double dt = 0.0001; double t_start = 0; double t_end = 20.0; // Initialize constraints PlaneConstraint c1; //SelfCollisionConstraint c2; //auto combined_constraints = make_combined_constraints(c1,c2); for (double t = t_start; t < t_end; t += dt) { MassSpringForce ms_force; PressureForce p_force = PressureForce(0.0); DampingForce d_force = DampingForce(mesh.num_nodes()); GravityForce g_force; WindForce w_force; (void) d_force; // prevents compiler from throwing error for unused variable if (t >= t_addgas - dt) { p_force.set_pressure(gas_const/get_volume(mesh)); if (t < t_addgas) std::cout << "Adding gas to the ball now..." << std::endl; } auto combined_forces = make_combined_force(ms_force, p_force, w_force, g_force); symp_euler_step(mesh, t, dt, combined_forces, c1); // Update viewer with nodes' new positions viewer.add_nodes(mesh.node_begin(), mesh.node_end(), node_map); // update the viewer's label with the ball center's position on the z axis viewer.set_label(get_center(mesh).z); } return 0; }
Array<Mesh> SerialPartitionerBase::makeMeshParts(const Mesh& mesh, int np, Array<Sundance::Map<int, int> >& oldElemLIDToNewLIDMaps, Array<Sundance::Map<int, int> >& oldVertLIDToNewLIDMaps) const { int dim = mesh.spatialDim(); Array<int> elemAssignments; Array<int> nodeAssignments; Array<int> nodeOwnerElems; Array<int> nodesPerProc; getAssignments(mesh, np, elemAssignments); getNodeAssignments(np, elemAssignments, nodeAssignments, nodeOwnerElems, nodesPerProc); Array<Array<int> > offProcNodes(np); Array<Array<int> > offProcElems(np); Array<Set<int> > offProcNodeSet(np); Array<Set<int> > offProcElemSet(np); Array<Array<int> > procNodes(np); Array<Array<int> > procElems(np); for (int p=0; p<np; p++) { getOffProcData(p, elemAssignments, nodeAssignments, offProcNodeSet[p], offProcElemSet[p]); offProcNodes[p] = offProcNodeSet[p].elements(); offProcElems[p] = offProcElemSet[p].elements(); procElems[p].reserve(elemAssignments.size()/np); procNodes[p].reserve(nodeAssignments.size()/np); } Array<int> remappedElems; Array<int> remappedNodes; remapEntities(elemAssignments, np, remappedElems); remapEntities(nodeAssignments, np, remappedNodes); for (int e=0; e<elemAssignments.size(); e++) { procElems[elemAssignments[e]].append(e); } for (int n=0; n<nodeAssignments.size(); n++) { procNodes[nodeAssignments[n]].append(n); } /* Now we make NP submeshes */ Array<Mesh> rtn(np); oldVertLIDToNewLIDMaps.resize(np); oldElemLIDToNewLIDMaps.resize(np); for (int p=0; p<np; p++) { Sundance::Map<int, int>& oldVertLIDToNewLIDMap = oldVertLIDToNewLIDMaps[p]; Sundance::Map<int, int>& oldElemLIDToNewLIDMap = oldElemLIDToNewLIDMaps[p]; MeshType type = new BasicSimplicialMeshType(); rtn[p] = type.createEmptyMesh(mesh.spatialDim(), MPIComm::world()); Set<int> unusedVertGID; /* add the on-processor nodes */ for (int n=0; n<procNodes[p].size(); n++) { int oldLID = procNodes[p][n]; int newGID = remappedNodes[oldLID]; unusedVertGID.put(newGID); int newLID = rtn[p].addVertex(newGID, mesh.nodePosition(oldLID), p, 0); oldVertLIDToNewLIDMap.put(oldLID, newLID); } /* add the off-processor nodes */ for (int n=0; n<offProcNodes[p].size(); n++) { int oldLID = offProcNodes[p][n]; int nodeOwnerProc = nodeAssignments[oldLID]; int newGID = remappedNodes[oldLID]; unusedVertGID.put(newGID); int newLID = rtn[p].addVertex(newGID, mesh.nodePosition(oldLID), nodeOwnerProc, 0); oldVertLIDToNewLIDMap.put(oldLID, newLID); } /* add the on-processor elements */ for (int e=0; e<procElems[p].size(); e++) { int oldLID = procElems[p][e]; int newGID = remappedElems[oldLID]; Array<int> vertGIDs; Array<int> orientations; mesh.getFacetArray(dim, oldLID, 0, vertGIDs, orientations); for (int v=0; v<vertGIDs.size(); v++) { vertGIDs[v] = remappedNodes[vertGIDs[v]]; if (unusedVertGID.contains(vertGIDs[v])) unusedVertGID.erase(newGID); } int newLID = rtn[p].addElement(newGID, vertGIDs, p, 1); oldElemLIDToNewLIDMap.put(oldLID, newLID); } /* add the off-processor elements */ for (int e=0; e<offProcElems[p].size(); e++) { int oldLID = offProcElems[p][e]; int newGID = remappedElems[oldLID]; int elemOwnerProc = elemAssignments[oldLID]; Array<int> vertGIDs; Array<int> orientations; mesh.getFacetArray(dim, oldLID, 0, vertGIDs, orientations); for (int v=0; v<vertGIDs.size(); v++) { vertGIDs[v] = remappedNodes[vertGIDs[v]]; if (unusedVertGID.contains(vertGIDs[v])) unusedVertGID.erase(newGID); } int newLID = rtn[p].addElement(newGID, vertGIDs, elemOwnerProc, 1); oldElemLIDToNewLIDMap.put(oldLID, newLID); // TEST_FOR_EXCEPTION(unusedVertGID.size() != 0, InternalError, // "unused vertices=" << unusedVertGID); } /* Now, propagate the labels of any intermediate-dimension cells * to the submesh */ for (int d=1; d<dim; d++) { Set<int> labels = mesh.getAllLabelsForDimension(d); for (Set<int>::const_iterator i=labels.begin(); i!=labels.end(); i++) { Array<int> labeledCells; int label = *i; if (label == 0) continue; mesh.getLIDsForLabel(d, label, labeledCells); for (int c=0; c<labeledCells.size(); c++) { int lid = labeledCells[c]; Array<int> cofacets; mesh.getCofacets(d, lid, dim, cofacets); for (int n=0; n<cofacets.size(); n++) { int cofLID = cofacets[n]; if (elemAssignments[cofLID]==p || offProcElemSet[p].contains(cofLID)) { /* at this point we need to find the facet index of the side * relative to the new element. */ /* find vertices of old cell */ Array<int> oldVerts; Array<int> newVerts; Array<int> orientation; mesh.getFacetArray(d, lid, 0, oldVerts, orientation); for (int v=0; v<oldVerts.size(); v++) { newVerts.append(remappedNodes[oldVerts[v]]); } /* Put the vertices in a set. This will let us compare to the * vertex sets in the new submesh. */ Set<int> newVertSet = arrayToSet(newVerts); /* Find the cofacet in the new submesh */ int newElemLID = oldElemLIDToNewLIDMap.get(cofLID); /* Get the d-facets of the element in the new submesh */ Array<int> submeshFacets; rtn[p].getFacetArray(dim, newElemLID, d, submeshFacets, orientation); int facetIndex = -1; for (int df=0; df<submeshFacets.size(); df++) { /* Get the vertices of this d-facet */ int facetLID = submeshFacets[df]; Array<int> verts; rtn[p].getFacetArray(d, facetLID, 0, verts, orientation); Array<int> vertGID(verts.size()); for (int v=0; v<verts.size(); v++) { vertGID[v] = rtn[p].mapLIDToGID(0, verts[v]); } Set<int> subVertSet = arrayToSet(vertGID); if (subVertSet==newVertSet) { facetIndex = df; break; } } TEST_FOR_EXCEPTION(facetIndex==-1, InternalError, "couldn't match new " << d << "-cell in submesh to old " << d << "cell. This should never happen"); /* OK, now we have the d-cell's facet index relative to one * of its cofacets existing on the new submesh. We now * find the LID of the d-cell so we can set its label */ int o; // dummy orientation variable; not needed here int newFacetLID = rtn[p].facetLID(dim, newElemLID, d, facetIndex, o); /* Set the label, finally! */ rtn[p].setLabel(d, newFacetLID, label); break; /* no need to continue the loop over cofacets once * we've set the label */ } else { } } } } } } return rtn; }
int main(int argc, char** argv) { // Check arguments if (argc < 5) { std::cerr << "Usage: " << argv[0] << " NODES_FILE TETS_FILE\n"; exit(1); } // Construct the first mesh MeshType mesh; //construct the second mesh MeshType mesh2; 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)) { mesh.add_triangle(mesh_node[t[0]], mesh_node[t[1]], mesh_node[t[2]]); } std::vector<typename MeshType::node_type> mesh_node2; // Read all Points and add them to the Mesh std::ifstream nodes_file2(argv[3]); while (CS207::getline_parsed(nodes_file2, p)) { mesh_node2.push_back(mesh2.add_node(p)); } // Read all mesh triangles and add them to the Mesh std::ifstream tris_file2(argv[4]); while (CS207::getline_parsed(tris_file2, t)) { mesh2.add_triangle(mesh_node2[t[0]], mesh_node2[t[1]], mesh_node2[t[2]]); } //move the second mesh to the specified position for(auto it = mesh2.node_begin();it!=mesh2.node_end();++it){ (*it).position().elem[1] +=4 ; (*it).position().elem[2] +=4 ; } // Print out the stats std::cout << mesh.num_nodes() << " " << mesh.num_edges() << " " << mesh.num_triangles() << std::endl; std::cout << mesh2.num_nodes() << " " << mesh2.num_edges() << " " << mesh2.num_triangles() << std::endl; //set the mass and velocity of each Node for the first mesh for (auto it = mesh.node_begin(); it != mesh.node_end(); ++it){ (*it).value().mass = float(1)/mesh.num_nodes(); (*it).value().velocity = Point(0, 10, 10); } //set the mass and velocity of each Node for the second mesh for (auto it = mesh2.node_begin(); it != mesh2.node_end(); ++it){ (*it).value().mass = float(1)/mesh.num_nodes(); (*it).value().velocity = Point(0, -10, -10); } //set K and L for each edge for (auto it = mesh.node_begin(); it != mesh.node_end(); ++it) { for (auto j = (*it).edge_begin(); j != (*it).edge_end(); ++j){ (*j).value().L = (*j).length(); (*j).value().K = 16000; } } for (auto it = mesh2.node_begin(); it != mesh2.node_end(); ++it) { for (auto j = (*it).edge_begin(); j != (*it).edge_end(); ++j){ (*j).value().L = (*j).length(); (*j).value().K = 16000; } } // Launch the SDLViewer CS207::SDLViewer viewer; auto node_map = viewer.empty_node_map(mesh); viewer.launch(); viewer.add_nodes(mesh.node_begin(), mesh.node_end(), node_map); viewer.add_edges(mesh.edge_begin(), mesh.edge_end(), node_map); viewer.add_nodes(mesh2.node_begin(), mesh2.node_end(), node_map); viewer.add_edges(mesh2.edge_begin(), mesh2.edge_end(), node_map); viewer.center_view(); //Begin the mass-spring simulation double dt = 0.0002; double t_start = 0.0; double t_end = 10.0; //three color parameter int color1 = 1; int color2 = 1; int color3 = 1; //Create listener Pause_listener* pause = new Pause_listener(dt); Speed_listener* speed = new Speed_listener(dt, dt); XYZ_listener<MeshType>* xyz = new XYZ_listener<MeshType>(&mesh); Color_listener* col = new Color_listener(&color1, &color2, &color3); //add listener viewer.add_listener(pause); viewer.add_listener(speed); viewer.add_listener(xyz); viewer.add_listener(col); //Initialize forces WindForce wind_force(Point(0,100,200)); PressureForce<typename MeshType::node_type, MeshType> pressure_force(1, 2500, &mesh); DampingForce damp_force(float(1)/mesh.num_nodes()); //auto force = make_combined_force(MassSpringForce(), GravityForce(), make_combined_force(pressure_force, damp_force, wind_force)); auto force = make_combined_force(MassSpringForce(), make_combined_force(pressure_force, damp_force, wind_force)); //Initialize constriants auto constraint = PlaneConstraint<MeshType>(-4); //simulation processing for (double t = t_start; t < t_end; t += dt) { constraint(mesh, 0); constraint(mesh2, 0); //define a collision constrain auto collision_constrain = CollisionConstraint<MeshType>(); //add the forces to the meshs at each dt symp_euler_step(mesh, t, dt, force); symp_euler_step(mesh2, t, dt, force); //detec the collision betweent the two meshes CollisionDetector<MeshType> c; c.add_object(mesh); c.add_object(mesh2); c.check_collisions(); std::vector<unsigned> collision; std::vector<unsigned> collision2; //find the corresponding mesh for each node for (auto it=c.begin(); it!= c.end(); ++it){ auto boom = *it; Node n = boom.n1; if (boom.mesh1 == &mesh) collision.push_back(n.index()); if (boom.mesh1 == &mesh2) collision2.push_back(n.index()); } //add the collision constrain to the meshes collision_constrain(mesh,mesh2,collision,collision2); viewer.set_label(t); //update with removed nodes //clear teh viewer's node viewer.clear(); node_map.clear(); //update viewer with new positions and new edges viewer.add_nodes(mesh.node_begin(), mesh.node_end(), color(color1, color2, color3), node_map); viewer.add_edges(mesh.edge_begin(), mesh.edge_end(), node_map); viewer.add_nodes(mesh2.node_begin(), mesh2.node_end(), color(color1, color2, color3), node_map); viewer.add_edges(mesh2.edge_begin(), mesh2.edge_end(), node_map); // These lines slow down the animation for small graphs if (mesh.num_nodes() < 100) CS207::sleep(0.001); } return 0; }