bool cloth::processSimplex(std::vector<Simplex> &simplex, glm::vec3 &direction) { Simplex A,B,C,D; glm::vec3 AB,AC,AD,AO; switch(simplex.size()) { case 2: A = simplex.at(1); B = simplex.at(0); AB = B.minkowskiDifference - A.minkowskiDifference; AO = -A.minkowskiDifference; if(isSameDirection(AO,AB)) { direction = glm::cross(glm::cross(AB, AO), AB); } else { direction = AO; } return false; case 3: return checkTriangle(simplex, direction); } }
void EarClipper::CheckForEarAndUpdateVertexType(VertexList::iterator vertexIterator) { if (vertexIterator->type != VertexType::Reflex) { const FVector2 *firstPoint, *secondPoint, *thirdPoint; GetPointsStraddlingVertex(vertexIterator, firstPoint, secondPoint, thirdPoint); Triangle2D_t checkTriangle(*firstPoint, *secondPoint, *thirdPoint); for (VertexList::iterator checkVertexIterator = vertices.begin(), end = vertices.end(); checkVertexIterator != end; ++checkVertexIterator) { if ( (checkVertexIterator->point != firstPoint) && (checkVertexIterator->point != secondPoint) && (checkVertexIterator->point != thirdPoint) ) { if (checkVertexIterator->type == VertexType::Reflex) { if (checkTriangle.PointIsOnPolygon(*(checkVertexIterator->point), EXPERIMENTAL_TOLERANCE)) { vertexIterator->type = VertexType::Convex; return; } } } } vertexIterator->type = VertexType::Ear; } }
/// 最近接交点の探索. /// /// @param[in] center 計算基準点座標 /// @param[in] range 6方向毎の計算基準線分の長さ /// @param[out] pos6 交点座標値配列 /// @param[out] bid6 境界ID配列 /// @param[out] tri6 交点ポリゴンポインタ配列 /// /// @note pos6には計算基準線分長で規格化する前の値を格納 /// void CutSearch::search(const double center[], const double range[], double pos6[], BidType bid6[], Triangle* tri6[]) const { Vec3r min(center[X]-range[X_M], center[Y]-range[Y_M], center[Z]-range[Z_M]); Vec3r max(center[X]+range[X_P], center[Y]+range[Y_P], center[Z]+range[Z_P]); clearCutInfo(range, pos6, bid6, tri6); std::vector<std::string>::const_iterator pg; for (pg = pgList->begin(); pg != pgList->end(); ++pg) { #ifdef CUTLIB_TIMING Timer::Start(SEARCH_POLYGON); #endif std::vector<Triangle*>* tList = pl->search_polygons(*pg, min, max, false); #ifdef CUTLIB_TIMING Timer::Stop(SEARCH_POLYGON); #endif std::vector<Triangle*>::const_iterator t; for (t = tList->begin(); t != tList->end(); ++t) { int exid = (*t)->get_exid(); if (0 < exid && exid < 256) { BidType bid = exid; checkTriangle(*t, bid, center, range, pos6, bid6, tri6); } } delete tList; } }
void AngleSkewMetric::calculateQuality () { const std::vector<MeshLib::Element*>& elements(_mesh.getElements()); const std::size_t nElements (_mesh.getNElements()); for (std::size_t k(0); k < nElements; k++) { Element const& elem (*elements[k]); switch (elem.getGeomType()) { case MeshElemType::LINE: _element_quality_metric[k] = -1.0; break; case MeshElemType::TRIANGLE: _element_quality_metric[k] = checkTriangle (elem); break; case MeshElemType::QUAD: _element_quality_metric[k] = checkQuad (elem); break; case MeshElemType::TETRAHEDRON: _element_quality_metric[k] = checkTetrahedron (elem); break; case MeshElemType::HEXAHEDRON: _element_quality_metric[k] = checkHexahedron (elem); break; case MeshElemType::PRISM: _element_quality_metric[k] = checkPrism (elem); break; default: break; } } }
void triangulate(){ bool pit; pit = true;//points in triangle, assume there are points in the given tri unsigned int i = 0; vector<V3> vec; vector<V3> temp(Points); vector<double> temp1(pointsType); if(Points.size()>0){ while(Points.size() > 2 && i < Points.size()){ pit = true; if(Points.size() == 3){ vec.push_back(Points.at(0)); vec.push_back(Points.at(1)); vec.push_back(Points.at(2)); Tris.push_back(vec); vec.clear(); break; } if(getPointType(i) == CONVEX){ cout<<"CONVEX\n"; if(i == 0) pit = checkTriangle(i, i + 1, Points.size() - 1, Points); else pit = checkTriangle(i, i + 1, i - 1, Points); if(pit){ if(i == 0){ vec.push_back(Points.at(i)); vec.push_back(Points.at(i + 1)); vec.push_back(Points.at(Points.size() - 1)); Tris.push_back(vec); vec.clear(); }else{ vec.push_back(Points.at(i)); vec.push_back(Points.at(i + 1));vec.push_back(Points.at(i - 1)); Tris.push_back(vec); vec.clear(); } Points.erase (Points.begin() + i); pointsType.erase (pointsType.begin() + i); }else{ i++; } }else{ i++; } } } pointsType = temp1; Points = temp; }
void EdgeRatioMetric::calculateQuality() { // get all elements of mesh const std::vector<MeshLib::Element*>& elements(_mesh.getElements()); const std::size_t nElements (_mesh.getNumberOfElements()); for (std::size_t k(0); k < nElements; k++) { Element const& elem (*elements[k]); switch (elem.getGeomType()) { case MeshElemType::LINE: _element_quality_metric[k] = 1.0; break; case MeshElemType::TRIANGLE: { _element_quality_metric[k] = checkTriangle(*elem.getNode(0), *elem.getNode(1), *elem.getNode(2)); break; } case MeshElemType::QUAD: { _element_quality_metric[k] = checkQuad(*elem.getNode(0), *elem.getNode(1), *elem.getNode(2), *elem.getNode(3)); break; } case MeshElemType::TETRAHEDRON: { _element_quality_metric[k] = checkTetrahedron(*elem.getNode(0), *elem.getNode(1), *elem.getNode(2), *elem.getNode(3)); break; } case MeshElemType::PRISM: { std::vector<const MathLib::Point3d*> pnts; for (std::size_t j(0); j < 6; j++) pnts.push_back(elem.getNode(j)); _element_quality_metric[k] = checkPrism(pnts); break; } case MeshElemType::PYRAMID: { std::vector<const MathLib::Point3d*> pnts; for (std::size_t j(0); j < 5; j++) pnts.push_back(elem.getNode(j)); _element_quality_metric[k] = checkPyramid(pnts); break; } case MeshElemType::HEXAHEDRON: { std::vector<const MathLib::Point3d*> pnts; for (std::size_t j(0); j < 8; j++) pnts.push_back(elem.getNode(j)); _element_quality_metric[k] = checkHexahedron(pnts); break; } default: ERR ("MeshQualityShortestLongestRatio::check () check for element type %s not implemented.", MeshElemType2String(elem.getGeomType()).c_str()); } } }
int checkTriangleInequality(struct edge *sortedEdgeList,struct edgeHashTable *edgeHash) { int i,v1,v2,wt,j; int a,b,c; struct edge *temp=(struct edge*)malloc(sizeof(struct edge)); struct edge *found; if(numEdges==0) { return 2; } for(i=numEdges-1;i>=0;i--) { v1=sortedEdgeList[i].vertexId1; v2=sortedEdgeList[i].vertexId2; wt=sortedEdgeList[i].weight; for(j=1;j<=numVertices;j++) { if(j!=v1&&j!=v2) { temp->vertexId1=j; temp->vertexId2=v1; temp->weight=0; if((found=edgeHashSearch(edgeHash,temp))==NULL) { a=typeBWeight; } else a=found->weight; temp->vertexId1=v2; temp->vertexId2=j; temp->weight=0; if((found=edgeHashSearch(edgeHash,temp))==NULL) { b=typeBWeight; } else b=found->weight; c=wt; if(checkTriangle(a,b,c)==1) { printf("\n%s %s %s does not form a triangle",vertices[v1],vertices[v2],vertices[j]); return 1; } } } } return 0; }
void MeshQualityShortestLongestRatio::check() { // get all elements of mesh const std::vector<MeshLib::Element*>& elements(_mesh->getElements()); const size_t nElements (_mesh->getNElements()); for (size_t k(0); k < nElements; k++) { const Element* elem (elements[k]); switch (elem->getType()) { case MshElemType::EDGE: _mesh_quality_measure[k] = 1.0; break; case MshElemType::TRIANGLE: { _mesh_quality_measure[k] = checkTriangle(elem->getNode(0), elem->getNode(1), elem->getNode(2)); break; } case MshElemType::QUAD: { _mesh_quality_measure[k] = checkQuad(elem->getNode(0), elem->getNode(1), elem->getNode(2), elem->getNode(3)); break; } case MshElemType::TETRAHEDRON: { _mesh_quality_measure[k] = checkTetrahedron(elem->getNode(0), elem->getNode(1), elem->getNode(2), elem->getNode(3)); break; } case MshElemType::PRISM: { std::vector<const GeoLib::Point*> pnts; for (size_t j(0); j < 6; j++) pnts.push_back(elem->getNode(j)); _mesh_quality_measure[k] = checkPrism(pnts); break; } case MshElemType::HEXAHEDRON: { std::vector<const GeoLib::Point*> pnts; for (size_t j(0); j < 8; j++) pnts.push_back(elem->getNode(j)); _mesh_quality_measure[k] = checkHexahedron(pnts); break; } default: std::cout << "MeshQualityShortestLongestRatio::check () check for element type " << MshElemType2String(elem->getType()) << " not implemented" << std::endl; } } }
extern "C" void driver(void) { int ignored; int i, count; int myChunk=FEM_My_partition(); /*Add a refinement object to FEM array*/ CkPrintf("[%d] begin init\n",myChunk); FEM_REFINE2D_Init(); CkPrintf("[%d] end init\n",myChunk); myGlobals g; FEM_Register(&g,(FEM_PupFn)pup_myGlobals); init_myGlobal(&g); g.nnodes = FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_NODE); int maxNodes = g.nnodes; g.maxnodes=2*maxNodes; g.m_i_fid=FEM_Create_field(FEM_DOUBLE,1,0,sizeof(double)); resize_nodes((void *)&g,&g.nnodes,&maxNodes); int nghost=0; g.nelems=FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_ELEM); g.maxelems=g.nelems; resize_elems((void *)&g,&g.nelems,&g.maxelems); FEM_REFINE2D_Newmesh(FEM_Mesh_default_read(),FEM_NODE,FEM_ELEM); //Initialize associated data for (i=0;i<g.maxnodes;i++) { g.R_net[i]=g.d[i]=g.v[i]=g.a[i]=vector2d(0.0); } //Apply a small initial perturbation to positions for (i=0;i<g.nnodes;i++) { const double max=1.0e-15/15.0; //Tiny perturbation g.d[i].x+=max*(i&15); g.d[i].y+=max*((i+5)&15); } int fid=FEM_Create_field(FEM_DOUBLE,2,0,sizeof(vector2d)); for (i=0;i<g.nelems;i++){ checkTriangle(g,i); } sleep(5); //Timeloop if (CkMyPe()==0){ CkPrintf("Entering timeloop\n"); } // int tSteps=0x70FF00FF; int tSteps=4; int z=13; calcMasses(g); double startTime=CkWallTimer(); double curArea=2.5e-5/1024; int t = 0; // THIS IS THE INITIAL MESH SENT TO NetFEM if (1) { //Publish data to the net publishMeshToNetFEM(g,myChunk,t); } double desiredArea; /* //should not be necessary as it would have been set in the init for (i=0; i<g.nnodes; i++) { g.validNode[i] = 1; } for (i=0; i<g.nelems; i++) { g.validElem[i] = 1; }*/ double avgArea = 0.0; for (i=0;i<g.nelems;i++) { avgArea += calcArea(g, i); } avgArea /= g.nelems; for (t=1;t<=tSteps;t++) { /* if (1) { //Structural mechanics //Compute forces on nodes exerted by elements CST_NL(g.coord,g.conn,g.R_net,g.d,matConst,g.nnodes,g.nelems,g.S11,g.S22,g.S12); //Communicate net force on shared nodes FEM_Update_field(fid,g.R_net); //Advance node positions advanceNodes(dt,g.nnodes,g.coord,g.R_net,g.a,g.v,g.d,g.m_i,(t%4)==0); }*/ //Debugging/perf. output double curTime=CkWallTimer(); double total=curTime-startTime; startTime=curTime; vector2d *loc; double *areas; // prepare to coarsen loc=new vector2d[2*g.nnodes]; for (i=0;i<g.nnodes;i++) { loc[i]=g.coord[i];//+g.d[i]; } areas=new double[g.nelems]; for (i=0;i<g.nelems;i++) { areas[i] = avgArea; } //coarsen one element at a time //int coarseIdx = (23 + 4*t)%g.nnodes; //areas[coarseIdx] = calcArea(g,coarseIdx)*2.5; CkPrintf("[%d] Starting coarsening step: %d nodes, %d elements\n", myChunk,countValidEntities(g.validNode,g.nnodes),countValidEntities(g.validElem,g.nelems)); FEM_REFINE2D_Coarsen(FEM_Mesh_default_read(),FEM_NODE,(double *)g.coord,FEM_ELEM,areas,FEM_SPARSE); repeat_after_split((void *)&g); g.nelems = FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_ELEM); g.nnodes = FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_NODE); CkPrintf("[%d] Done with coarsening step: %d nodes, %d elements\n", myChunk,countValidEntities(g.validNode,g.nnodes),countValidEntities(g.validElem,g.nelems)); delete [] loc; delete[] areas; // THIS IS THE COARSENED MESH SENT TO NetFEM if (1) { //Publish data to the net publishMeshToNetFEM(g,myChunk,2*t-1); } //prepare to refine loc=new vector2d[2*g.nnodes]; for (i=0;i<g.nnodes;i++) { loc[i]=g.coord[i];//+g.d[i]; } areas=new double[g.nelems]; for (i=0;i<g.nelems;i++) { areas[i] = avgArea; } //refine one element at a time //int refIdx = (13 + 3*t)%g.nnodes; //areas[refIdx] = calcArea(g,refIdx)/1.5; CkPrintf("[%d] Starting refinement step: %d nodes, %d elements\n", myChunk,countValidEntities(g.validNode,g.nnodes),countValidEntities(g.validElem,g.nelems)); FEM_REFINE2D_Split(FEM_Mesh_default_read(),FEM_NODE,(double *)loc,FEM_ELEM,areas,FEM_SPARSE); repeat_after_split((void *)&g); g.nelems = FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_ELEM); g.nnodes = FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_NODE); CkPrintf("[%d] Done with refinement step: %d nodes, %d elements\n", myChunk,countValidEntities(g.validNode,g.nnodes),countValidEntities(g.validElem,g.nelems)); delete [] loc; delete[] areas; // THIS IS THE REFINED MESH SENT TO NetFEM if (1) { //Publish data to the net publishMeshToNetFEM(g,myChunk,2*t); } } if (CkMyPe()==0) CkPrintf("Driver finished\n"); }
EarClipper::VertexList::iterator EarClipper::DetermineMutuallyVisibleVertexFromRayCastResult(const FVector2& maxInteriorPoint, const FVector2& intersectionPointOnEdge, VertexList::iterator pointOnEdgeWithMaximumXIter) { VertexList::iterator verticesEnd = vertices.end(); VertexList::iterator mutuallyVisibleVertexIter = verticesEnd; // Form a triangle with P (see explanation of a) above) (P1), the intersection point on // the edge (P2) and the point on the edge with maximum X (P3). // // If no points on the outer polygon fall on this triangle, then P3 is the visible vertex. // // Otherwise, the reflex vertex of the outer polygon that falls into this triangle and // minimizes the angle to the ray (i.e. x axis) is the mutually visible vertex Triangle2D_t checkTriangle(maxInteriorPoint, intersectionPointOnEdge, *(pointOnEdgeWithMaximumXIter->point)); VertexListIteratorList reflexVerticesOnTriangle; bool hasAnyReflexVerticesOnTriangle = false; for (VertexList::iterator vertexIterator = vertices.begin(); vertexIterator != verticesEnd; ++vertexIterator) { if (checkTriangle.PointIsOnPolygon(*(vertexIterator->point), EXPERIMENTAL_TOLERANCE)) { if (GetConvexOrReflexVertexType(vertexIterator) == VertexType::Reflex) { reflexVerticesOnTriangle.push_front(vertexIterator); hasAnyReflexVerticesOnTriangle = true; } } } if (hasAnyReflexVerticesOnTriangle) { mutuallyVisibleVertexIter = reflexVerticesOnTriangle.front(); reflexVerticesOnTriangle.pop_front(); float minDistance = DistanceBetween(*(mutuallyVisibleVertexIter->point), maxInteriorPoint); float minAngle = AngleBetweenRadians(*(mutuallyVisibleVertexIter->point) - maxInteriorPoint, Vec2D::XAxis() ); for (const VertexList::iterator& reflexVertexIter : reflexVerticesOnTriangle) { float angle = AngleBetweenRadians(*(reflexVertexIter->point) - maxInteriorPoint, Vec2D::XAxis() ); float distance = DistanceBetween(*(reflexVertexIter->point), maxInteriorPoint); if (angle < minAngle) { minAngle = angle; mutuallyVisibleVertexIter = reflexVertexIter; minDistance = distance; } else if (angle == minAngle) { if (distance < minDistance) { minAngle = angle; mutuallyVisibleVertexIter = reflexVertexIter; minDistance = distance; } } } } else { mutuallyVisibleVertexIter = pointOnEdgeWithMaximumXIter; } return mutuallyVisibleVertexIter; }
// uses ear-clipping method, so won't work on polygons with holes, and is relatively slow at O(n^2) // assumes size of _shape is at least 3 std::vector<std::vector<Util::Vector>> SteerLib::GJK_EPA::decompose(std::vector<Util::Vector> _shape) { // list of triangles that _shape decomposed into std::vector<std::vector<Util::Vector>> triangleList; // temporary shape that can be modified std::vector<Util::Vector> tempShape = _shape; int count = crossProductCount(_shape); // if absolute value of count is same as size of shape, then shape is convex if (std::abs(count) == _shape.size()) { triangleList.push_back(_shape); return triangleList; } bool isCCW; // if count > 0, shape is ordered ccw if (count > 0) { isCCW = true; } // if count < 0, shape is ordered cw else if (count < 0) { isCCW = false; } // start the search at any point int shapePos = 0; // loop until there are only 3 points left in tempShape // the loop will find ears in tempShape, and remove the ear, so the number of points in tempShape slowly decreases while (tempShape.size() > 0) { // if shapePos reaches the end, loop back to the beginning if (shapePos == tempShape.size()) { shapePos = 0; } // get the first point, and the two points adjacent to it Util::Vector point = tempShape.at(shapePos); // get the predecessor, if shapePos is 0, get the back of tempShape Util::Vector predecessor; if (shapePos == 0) { predecessor = tempShape.back(); } else { predecessor = tempShape.at(shapePos - 1); } // get the predecessor, if shapePos is the end, get the front of tempShape Util::Vector successor; if (shapePos == tempShape.size()-1) { successor = tempShape.front(); } else { successor = tempShape.at(shapePos + 1); } // find the angle of the first point Util::Vector line1 = predecessor - point; Util::Vector line2 = successor - point; float angle = findAngle(line1, line2); bool angleBool; // if shape is ccw, angles less than pi are positive if (isCCW) { angleBool = angle < M_PI && angle > 0; } // if shape is cw, angles less than pi are negative else { angleBool = angle > -M_PI && angle < 0; } // if the angle is less than pi, it is possible for an ear to exist if (angleBool) { // make another temporary shape that does not include the point and it's adjacent points std::vector<Util::Vector> triangleShape = tempShape; int remove = indexOf(triangleShape, predecessor); triangleShape.erase(triangleShape.begin() + remove); remove = indexOf(triangleShape, point); triangleShape.erase(triangleShape.begin() + remove); remove = indexOf(triangleShape, successor); triangleShape.erase(triangleShape.begin() + remove); // check if any points in tempShape are in the triangle formed by the point and it's adjacent points // if no points are in the triangle, then the point and it's adjacent points form an ear if (!checkTriangle(triangleShape, predecessor, point, successor)) { // construct the ear std::vector<Util::Vector> ear; ear.push_back(predecessor); ear.push_back(point); ear.push_back(successor); // add the ear to the list of decomposed triangles triangleList.push_back(ear); // remove the point from tempShape since no other triangles in the decomposition can use it remove = indexOf(tempShape, point); tempShape.erase(tempShape.begin() + remove); } // there is another point inside the triangle, so it's not an ear // move on to the next position else { shapePos++; } } // if the angle is pi, then the point and it's adjacent points forms a line // the point can be removed from tempShape else if (angle == M_PI || angle == -M_PI) { int remove = indexOf(tempShape, point); tempShape.erase(tempShape.begin() + remove); } // if the angle is greater than pi, it can't be an ear // move on to the next position else { shapePos++; } if (tempShape.size() == 3) { // since there are only 3 points left in tempShape, it must form a triangle in the decomposition triangleList.push_back(tempShape); tempShape.clear(); } } for (int i = 0; i < triangleList.size(); i++) { std::cout << "triangle " << i << "\n"; for (int j = 0; j < triangleList.at(i).size(); j++) { std::cout << "point " << triangleList.at(i).at(j) << "\n"; } } return triangleList; }
extern "C" void driver(void) { int ignored; int i; int myChunk=FEM_My_partition(); /*Add a refinement object to FEM array*/ CkPrintf("[%d] begin init\n",myChunk); FEM_REFINE2D_Init(); CkPrintf("[%d] end init\n",myChunk); myGlobals g; FEM_Register(&g,(FEM_PupFn)pup_myGlobals); init_myGlobal(&g); g.nnodes = FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_NODE); int maxNodes = g.nnodes; g.maxnodes=2*maxNodes; g.m_i_fid=FEM_Create_field(FEM_DOUBLE,1,0,sizeof(double)); resize_nodes((void *)&g,&g.nnodes,&maxNodes); int nghost=0; g.nelems=FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_ELEM); g.maxelems=g.nelems; resize_elems((void *)&g,&g.nelems,&g.maxelems); g.nedges = FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_SPARSE); g.maxedges = g.nedges; resize_edges((void *)&g,&g.nedges,&g.maxedges); FEM_REFINE2D_Newmesh(FEM_Mesh_default_read(),FEM_NODE,FEM_ELEM); //Initialize associated data for (i=0;i<g.maxnodes;i++){ g.R_net[i]=g.d[i]=g.v[i]=g.a[i]=vector2d(0.0); } //Apply a small initial perturbation to positions for (i=0;i<g.nnodes;i++) { const double max=1.0e-15/15.0; //Tiny perturbation g.d[i].x+=max*(i&15); g.d[i].y+=max*((i+5)&15); } int fid=FEM_Create_field(FEM_DOUBLE,2,0,sizeof(vector2d)); for (i=0;i<g.nelems;i++){ checkTriangle(g,i); } //Timeloop if (CkMyPe()==0){ CkPrintf("Entering timeloop\n"); } int tSteps=0x70FF00FF; calcMasses(g); double startTime=CkWallTimer(); double curArea=2.0e-5; for (int t=0;t<tSteps;t++) { if (1) { //Structural mechanics //Compute forces on nodes exerted by elements CST_NL(g.coord,g.conn,g.R_net,g.d,matConst,g.nnodes,g.nelems,g.S11,g.S22,g.S12); //Communicate net force on shared nodes FEM_Update_field(fid,g.R_net); //Advance node positions advanceNodes(dt,g.nnodes,g.coord,g.R_net,g.a,g.v,g.d,g.m_i,(t%4)==0); } //Debugging/perf. output double curTime=CkWallTimer(); double total=curTime-startTime; startTime=curTime; if (CkMyPe()==0 && (t%64==0)) CkPrintf("%d %.6f sec for loop %d \n",CkNumPes(),total,t); /* if (0 && t%16==0) { CkPrintf(" Triangle 0:\n"); for (int j=0;j<3;j++) { int n=g.conn[0][j]; CkPrintf(" Node %d: coord=(%.4f,%.4f) d=(%.4g,%.4g)\n", n,g.coord[n].x,g.coord[n].y,g.d[n].x,g.d[n].y); } }*/ // if (t%512==0) // FEM_Migrate(); if (t%128==0) { //Refinement: vector2d *loc=new vector2d[2*g.nnodes]; for (i=0;i<g.nnodes;i++) { loc[i]=g.coord[i];//+g.d[i]; } double *areas=new double[g.nelems]; curArea=curArea*0.98; for (i=0;i<g.nelems;i++) { #if 0 double origArea=8e-8; //Typical triangle size if (fabs(g.S12[i])>1.0e8) areas[i]=origArea*0.9; //Refine stuff that's stressed else areas[i]=origArea; //Leave everything else big #endif areas[i]=curArea; } CkPrintf("[%d] Starting refinement step: %d nodes, %d elements to %.3g\n", myChunk,g.nnodes,g.nelems,curArea); FEM_REFINE2D_Split(FEM_Mesh_default_read(),FEM_NODE,(double *)loc,FEM_ELEM,areas,FEM_SPARSE); repeat_after_split((void *)&g); g.nelems = FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_ELEM); g.nnodes = FEM_Mesh_get_length(FEM_Mesh_default_read(),FEM_NODE); CkPrintf("[%d] Done with refinement step: %d nodes, %d elements\n", myChunk,g.nnodes,g.nelems); } if (1) { //Publish data to the net NetFEM n=NetFEM_Begin(myChunk,t,2,NetFEM_POINTAT); NetFEM_Nodes(n,g.nnodes,(double *)g.coord,"Position (m)"); NetFEM_Vector(n,(double *)g.d,"Displacement (m)"); NetFEM_Vector(n,(double *)g.v,"Velocity (m/s)"); NetFEM_Elements(n,g.nelems,3,(int *)g.conn,"Triangles"); NetFEM_Scalar(n,g.S11,1,"X Stress (pure)"); NetFEM_Scalar(n,g.S22,1,"Y Stress (pure)"); NetFEM_Scalar(n,g.S12,1,"Shear Stress (pure)"); NetFEM_End(n); } } if (CkMyPe()==0) CkPrintf("Driver finished\n"); }