/*----------------------------------------------------------------------* | 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| | 2D case: | | this method evaluates the function | | gradF(eta) = | | ( Ni,eta * xis ) * ( Ni,eta * xis ) | | with Ni,eta derivative of shape functions of segment | | Ni,Nj shape functions of segment | | xis nodal coords of segment's nodes i (slave side) | *----------------------------------------------------------------------*/ double MOERTEL::Projector::evaluate_gradF_2D_SegmentOrthogonal_to_g( MOERTEL::Node& node, MOERTEL::Segment& seg, double eta, double* g) { // 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_gradF_2D_SegmentOrthogonal_to_g:\n" << "***ERR*** function is of wrong type\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } // evaluate function and derivatives of the first function set on segment at eta int nmnode = seg.Nnode(); double deriv[200]; seg.EvaluateFunction(0,&eta,NULL,nmnode,deriv); // intermediate data: // Nxeta = Ni,eta * xi // get nodal coords and normals of nodes and interpolate them double Nxeta[2]; Nxeta[0] = Nxeta[1] = 0.0; MOERTEL::Node** mnodes = seg.Nodes(); if (!mnodes) { std::stringstream oss; oss << "***ERR*** MOERTEL::Projector::evaluate_gradF_2D_SegmentOrthogonal_to_g:\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<nmnode; ++i) { const double* X = mnodes[i]->X(); Nxeta[0] += deriv[i]*X[0]; Nxeta[1] += deriv[i]*X[1]; } // calculate gradF double gradF = Nxeta[0]*g[0] + Nxeta[1]*g[1]; return gradF; }
/*----------------------------------------------------------------------* | mwgee 07/05| | 2D case: | | this method evaluates the function | | gradF(eta) = | | ( Ni,eta * xis ) * ( Nj nyjs ) | | + ( Ni * xis - xm ) * ( Nj,eta * nyjs) | | - ( Ni,eta * yis ) * ( Nj nxjs ) | | - ( Ni * yis - ym ) * ( Nj,eta * nxjs) | | with Ni,eta derivative of shape functions of segment | | Ni,Nj shape functions of segment | | xis,yis nodal coords of segment's nodes i (slave side) | | xm,ym nodal coords of master node | | nxjs,nyjs outward normals of node j (slave side) | *----------------------------------------------------------------------*/ double MOERTEL::Projector::evaluate_gradF_2D_SegmentNormal(MOERTEL::Node& node, MOERTEL::Segment& seg, double eta) { // 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_gradF_2D_SegmentNormal:\n" << "***ERR*** function is of wrong type\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } // evaluate function and derivatives of the first function set on segment at eta int nsnode = seg.Nnode(); double val[100]; double deriv[200]; seg.EvaluateFunction(0,&eta,val,nsnode,deriv); // several intermediate data: // Nx = Ni * xi // Nxeta = Ni,eta * xi // NN = Nj * nj // NNeta = Nj,eta * nj // get nodal coords and normals of nodes and interpolate them double Nx[2]; Nx[0] = Nx[1] = 0.0; double Nxeta[2]; Nxeta[0] = Nxeta[1] = 0.0; double NN[2]; NN[0] = NN[1] = 0.0; double NNeta[2]; NNeta[0] = NNeta[1] = 0.0; MOERTEL::Node** snodes = seg.Nodes(); if (!snodes) { std::stringstream oss; oss << "***ERR*** MOERTEL::Projector::evaluate_gradF_2D_SegmentNormal:\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]; Nxeta[0] += deriv[i]*X[0]; Nxeta[1] += deriv[i]*X[1]; const double* N = snodes[i]->N(); NN[0] += val[i]*N[0]; NN[1] += val[i]*N[1]; NNeta[0] += deriv[i]*N[0]; NNeta[1] += deriv[i]*N[1]; } // get master node coords const double* xm = node.X(); // calculate gradF double gradF = Nxeta[0]*NN[1] + (Nx[0] - xm[0])*NNeta[1] - Nxeta[1]*NN[0] - (Nx[1] - xm[1])*NNeta[0]; return gradF; }
/*----------------------------------------------------------------------* | mwgee 07/05| | modded gah 07/2010 | | 2D case: | | this function evaluates the function | | F(eta) = ( Ni * xim - xs ) cross ns , | | with Ni shape functions of segment | | xim nodal coords of segment's nodes (master side) | | xs nodal coords of node (slave side) | | ns outward normal of node (slave side) | *----------------------------------------------------------------------*/ double MOERTEL::Projector::evaluate_F_2D_NodalNormal(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_NodalNormal:\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 nmnode = seg.Nnode(); double val[100]; seg.EvaluateFunction(0,&eta,val,nmnode,NULL); // get nodal coords of nodes and interpolate them double Nx[2]; Nx[0] = Nx[1] = 0.0; MOERTEL::Node** mnodes = seg.Nodes(); if (!mnodes) { std::stringstream oss; oss << "***ERR*** MOERTEL::Projector::evaluate_F_2D_NodalNormal:\n" << "***ERR*** segment " << seg.Id() << " ptr to it's nodes is zero\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } // Here, Nx[0] and Nx[1] are the coordinates of the guess at the root for (int i=0; i<nmnode; ++i) { const double* X = mnodes[i]->X(); Nx[0] += val[i]*X[0]; Nx[1] += val[i]*X[1]; } // subtract xs (Coordinates of the slave node) const double* X = node.X(); Nx[0] -= X[0]; Nx[1] -= X[1]; // get the normal of node const double* n = node.N(); // calculate F double F = Nx[0]*n[1] - Nx[1]*n[0]; gap = Nx[0] * n[0] + Nx[1] * n[1]; // Do we need to divide by the length of the normal??? GAH // // gap = (Nx[0] * n[0] + Nx[1] * n[1]) // / sqrt(n[0] * n[0] + n[1] * n[1]); // ||gap|| cos theta #if 0 std::cout << "node " << node.Id() << " seg " << seg.Id() << " n[0] " << n[0] << " n[1] " << n[1] << std::endl; std::cout << "X[0] " << X[0] << " X[1] " << X[1] << std::endl; std::cout << "Nx[0] " << Nx[0] << " Nx[1] " << Nx[1] << " gap " << gap << std::endl; std::cout << "norm " << sqrt(n[0] * n[0] + n[1] * n[1]) << std::endl; #endif return F; }