/*----------------------------------------------------------------------* | mwgee 08/05| | 2D case: | | this method evaluates the function | | F(eta) = ( Ni * xis - xm ) dot g(xi) | | with Ni shape functions of slave segment | | xm nodal coords of master node | | xs nodal coords of slave nodes on segment | | njs nodal outward normal of nodes xs (slave side) | *----------------------------------------------------------------------*/ double MOERTEL::Projector::evaluate_F_2D_SegmentOrthogonal(MOERTEL::Node& node, MOERTEL::Segment& seg, double eta, double &gap) { // check the type of function on the segment // Here, we need 1D functions set as function id 0 MOERTEL::Function::FunctionType type = seg.FunctionType(0); if (type != MOERTEL::Function::func_Linear1D) { std::stringstream oss; oss << "***ERR*** MOERTEL::Projector::evaluate_F_2D_SegmentOrthogonal:\n" << "***ERR*** function is of wrong type\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } // evaluate the first function set on segment at eta int nsnode = seg.Nnode(); double val[100]; seg.EvaluateFunction(0,&eta,val,nsnode,NULL); // get nodal coords and normals of slave nodes and interpolate them double Nx[2]; Nx[0] = Nx[1] = 0.0; MOERTEL::Node** snodes = seg.Nodes(); if (!snodes) { std::stringstream oss; oss << "***ERR*** MOERTEL::Projector::evaluate_F_2D_SegmentOrthogonal:\n" << "***ERR*** segment " << seg.Id() << " ptr to it's nodes is zero\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } for (int i=0; i<nsnode; ++i) { const double* X = snodes[i]->X(); Nx[0] += val[i]*X[0]; Nx[1] += val[i]*X[1]; } // subtract xm from interpolated coords Nx const double* X = node.X(); Nx[0] -= X[0]; Nx[1] -= X[1]; // evaluate the metric of the segment in point xi double g[2]; seg.Metric(&eta,g,NULL); // calculate F double F = Nx[0]*g[0] + Nx[1]*g[1]; gap = (Nx[0] * g[0] + Nx[1] * g[1]); // gap = ((Nx[0] - X[0]) * g[0] + (Nx[1] - X[1]) * g[1]) // / sqrt(g[0] * g[0] + g[1] * g[1]); // ||gap|| cos theta return F; }
/*----------------------------------------------------------------------* | mwgee 08/05| *----------------------------------------------------------------------*/ bool MOERTEL::Projector::ProjectNodetoSegment_Orthogonal_to_Slave( MOERTEL::Node& snode, MOERTEL::Segment& seg, double xi[], double &gap, MOERTEL::Segment& sseg) { #if 0 std::cout << "----- Projector: Node " << snode.Id() << " Segment " << seg.Id() << std::endl; std::cout << " orthogonal to Slave Segment " << sseg.Id() << std::endl; #endif if (IsTwoDimensional()) { // get the local node id of snode on sseg int lid = sseg.GetLocalNodeId(snode.Id()); if (lid<0) { std::stringstream oss; oss << "***ERR*** MOERTEL::Projector::ProjectNodetoSegment_Orthogonal_to_Slave:\n" << "***ERR*** local node id could not be found\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } // get coordinate of local node lid double lidxi; sseg.LocalCoordinatesOfNode(lid,&lidxi); // build tangent vector in xi double g[2]; sseg.Metric(&lidxi,g,NULL); // we do a newton iteration for the projection coordinates xi // set starting value to the middle of the segment double eta = 0.0; int i = 0; double F=0.0,dF=0.0,deta=0.0; for (i=0; i<10; ++i) { F = evaluate_F_2D_SegmentOrthogonal_to_g(snode,seg,eta,gap,g); if (abs(F) < 1.0e-10) break; dF = evaluate_gradF_2D_SegmentOrthogonal_to_g(snode,seg,eta,g); deta = (-F)/dF; eta += deta; } if (abs(F)>1.0e-10) { if (OutLevel()>3) std::cout << "MOERTEL: ***WRN*** MOERTEL::Projector::ProjectNodetoSegment_Orthogonal_to_Slave:\n" << "MOERTEL: ***WRN*** Newton iteration failed to converge\n" << "MOERTEL: ***WRN*** #iterations = " << i << std::endl << "MOERTEL: ***WRN*** F(eta) = " << F << " gradF(eta) = " << dF << " eta = " << eta << " delta(eta) = " << deta << "\n" << "MOERTEL: ***WRN*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; } #if 0 std::cout << "#iterations = " << i << " F = " << F << " eta = " << eta << std::endl; #endif xi[0] = eta; return true; } else { std::stringstream oss; oss << "***ERR*** MOERTEL::Projector::ProjectNodetoSegment_Orthogonal_to_Slave:\n" << "***ERR*** 3D projection not impl.\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } return true; }