void Jacobian_2(Teuchos::RCP<Intrepid::FieldContainer<Real> > & jac, const Teuchos::RCP<const Intrepid::FieldContainer<Real> > & u_coeff, const Teuchos::RCP<const Intrepid::FieldContainer<Real> > & z_coeff = Teuchos::null, const Teuchos::RCP<const std::vector<Real> > & z_param = Teuchos::null) { if ( z_coeff != Teuchos::null ) { // GET DIMENSIONS int c = u_coeff->dimension(0); int f = basisPtr_->getCardinality(); // INITIALIZE JACOBIAN jac = Teuchos::rcp(new Intrepid::FieldContainer<Real>(c, f, f)); // ADD CONTROL TERM Intrepid::FunctionSpaceTools::integrate<Real>(*jac, *(fe_vol_->N()), *(fe_vol_->NdetJ()), Intrepid::COMP_CPP, false); // APPLY DIRICHLET CONDITIONS int numSideSets = bdryCellLocIds_.size(); if (numSideSets > 0) { for (int i = 0; i < numSideSets; ++i) { int numLocalSideIds = bdryCellLocIds_[i].size(); for (int j = 0; j < numLocalSideIds; ++j) { int numCellsSide = bdryCellLocIds_[i][j].size(); int numBdryDofs = fidx_[j].size(); for (int k = 0; k < numCellsSide; ++k) { int cidx = bdryCellLocIds_[i][j][k]; for (int l = 0; l < numBdryDofs; ++l) { //std::cout << "\n j=" << j << " l=" << l << " " << fidx[j][l]; for (int m = 0; m < f; ++m) { (*jac)(cidx,fidx_[j][l],m) = static_cast<Real>(0); } } } } } } } else { throw Exception::Zero(">>> (PDE_Poisson::Jacobian_2): Jacobian is zero."); } }
/*----------------------------------------------------------------------* | project nodes master to slave along slave cont. normal field | *----------------------------------------------------------------------*/ bool MOERTEL::Interface::ProjectNodes_MastertoSlave_NormalField() { if (!IsComplete()) { std::stringstream oss; oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_NormalField:\n" << "***ERR*** Complete() not called on interface " << Id() << "\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } if (!lComm()) return true; int mside = MortarSide(); int sside = OtherSide(mside); // iterate over all nodes of the master side and project those belonging to me std::map<int,Teuchos::RCP<MOERTEL::Node> >::iterator mcurr; for (mcurr=rnode_[mside].begin(); mcurr!=rnode_[mside].end(); ++mcurr) { Teuchos::RCP<MOERTEL::Node> mnode = mcurr->second; if (NodePID(mnode->Id()) != lComm()->MyPID()) continue; const double* mx = mnode->X(); double mindist = 1.0e+20; Teuchos::RCP<MOERTEL::Node> closenode = Teuchos::null; // find a node on the slave side that is closest to me std::map<int,Teuchos::RCP<MOERTEL::Node> >::iterator scurr; for (scurr=rnode_[sside].begin(); scurr!=rnode_[sside].end(); ++scurr) { Teuchos::RCP<MOERTEL::Node> snode = scurr->second; const double* sx = snode->X(); // build distance | snode->X() - mnode->X() | double dist = 0.0; for (int i=0; i<3; ++i) dist += (mx[i]-sx[i])*(mx[i]-sx[i]); dist = sqrt(dist); if (dist < mindist) { mindist = dist; closenode = snode; } } if (closenode == Teuchos::null) { std::stringstream oss; oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_NormalField:\n" << "***ERR*** Weired: for master node " << mnode->Id() << " no closest master node found\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } #if 0 cout << "snode " << *mnode; cout << "closenode " << *closenode; #endif // get segments attached to closest node closenode int nseg = closenode->Nseg(); MOERTEL::Segment** segs = closenode->Segments(); // create a projection operator MOERTEL::Projector projector(IsOneDimensional(),OutLevel()); // loop these segments and find best projection double bestdist[2]; const double tol = 0.2; double bestgap = 0.0, gap; bestdist[0] = bestdist[1] = 1.0e+20; MOERTEL::Segment* bestseg = NULL; for (int i=0; i<nseg; ++i) { // project the master node on the slave segment along the segments interpolated normal field double xi[2]; xi[0] = xi[1] = 0.0; projector.ProjectNodetoSegment_SegmentNormal(*mnode,*(segs[i]),xi,gap); // check whether xi is better then previous projections if (IsOneDimensional()) { if (abs(xi[0]) < abs(bestdist[0])) { bestdist[0] = xi[0]; bestdist[1] = xi[1]; bestseg = segs[i]; bestgap = gap; } } else { double third = 1./3.; // it's 'inside' with some tolerance if ( xi[0]<=1.+tol && xi[1]<=abs(1.-xi[0])+tol && xi[0]>=0.-tol && xi[1]>=0.-tol ) { // it's better in both directions if ( sqrt((xi[0]-third)*(xi[0]-third)) < sqrt((bestdist[0]-third)*(bestdist[0]-third)) && sqrt((xi[1]-third)*(xi[1]-third)) < sqrt((bestdist[1]-third)*(bestdist[1]-third)) ) { bestdist[0] = xi[0]; bestdist[1] = xi[1]; bestseg = segs[i]; bestgap = gap; } //it's better in one direction and 'in' in the other else if ( (sqrt((xi[0]-third)*(xi[0]-third))<sqrt((bestdist[0]-third)*(bestdist[0]-third)) && xi[1]<=abs(1.-xi[0])+tol && xi[1]>=0.-tol ) || (sqrt((xi[1]-third)*(xi[1]-third))<sqrt((bestdist[1]-third)*(bestdist[1]-third)) && xi[0]<=1.+tol && xi[0]>=0.-tol ) ) { bestdist[0] = xi[0]; bestdist[1] = xi[1]; bestseg = segs[i]; bestgap = gap; } } } } // for (int i=0; i<nseg; ++i) // check whether the bestseg/bestdist are inside that segment // (with some tolerance of 20%) bool ok = false; if (IsOneDimensional()) { if (abs(bestdist[0]) < 1.1) ok = true; } else { if (bestdist[0]<=1.+tol && bestdist[1]<=abs(1.-bestdist[0])+tol && bestdist[0]>=0.-tol && bestdist[1]>=0.-tol) ok = true; } if (ok) // the projection is good { // build the interpolated normal and overwrite the mnode normal with -n int nsnode = bestseg->Nnode(); MOERTEL::Node** snodes = bestseg->Nodes(); std::vector<double> val(nsnode); bestseg->EvaluateFunction(0,bestdist,&val[0],nsnode,NULL); double NN[3]; NN[0] = NN[1] = NN[2] = 0.0; for (int i=0; i<nsnode; ++i) { const double* N = snodes[i]->N(); for (int j=0; j<3; ++j) NN[j] -= val[i]*N[j]; } val.clear(); mnode->SetN(NN); // create projected node and store it in mnode MOERTEL::ProjectedNode* pnode = new MOERTEL::ProjectedNode(*mnode,bestdist,bestseg); mnode->SetProjectedNode(pnode); mnode->SetGap(bestgap); } else // this mnode does not have a valid projection { if (OutLevel()>6) cout << "MOERTEL: ***WRN***: Projection m->s: Node " << mnode->Id() << " does not have projection\n"; mnode->SetProjectedNode(NULL); } } // for (scurr=rnode_[mside].begin(); scurr!=rnode_[mside].end(); ++scurr) // loop all master nodes again and make the projection and the new normal redundant int bsize = 7*rnode_[mside].size(); std::vector<double> bcast(bsize); for (int proc=0; proc<lComm()->NumProc(); ++proc) { int blength = 0; if (proc==lComm()->MyPID()) { for (mcurr=rnode_[mside].begin(); mcurr!=rnode_[mside].end(); ++mcurr) { Teuchos::RCP<MOERTEL::Node> mnode = mcurr->second; if (proc != NodePID(mnode->Id())) continue; // cannot have a projection on a node i don't own Teuchos::RCP<MOERTEL::ProjectedNode> pnode = mnode->GetProjectedNode(); if (pnode == Teuchos::null) continue; // this node does not have a projection const double* xi = pnode->Xi(); const double* N = mnode->N(); bcast[blength] = (double)pnode->Id(); ++blength; if (pnode->Segment()) bcast[blength] = (double)pnode->Segment()->Id(); else bcast[blength] = -0.1; ++blength; bcast[blength] = xi[0]; ++blength; bcast[blength] = xi[1]; ++blength; bcast[blength] = N[0]; ++blength; bcast[blength] = N[1]; ++blength; bcast[blength] = N[2]; ++blength; bcast[blength] = pnode->Gap(); ++blength; } if (blength > bsize) { std::stringstream oss; oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_NormalField:\n" << "***ERR*** Overflow in communication buffer occured\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } } lComm()->Broadcast(&blength,1,proc); lComm()->Broadcast(&bcast[0],blength,proc); if (proc!=lComm()->MyPID()) { int i; for (i=0; i<blength;) { int nid = (int)bcast[i]; ++i; double sid = bcast[i]; ++i; double* xi = &bcast[i]; ++i; ++i; double* n = &bcast[i]; ++i; ++i; ++i; double gap = bcast[i]; ++i; Teuchos::RCP<MOERTEL::Node> mnode = GetNodeView(nid); Teuchos::RCP<MOERTEL::Segment> seg = Teuchos::null; if (sid != -0.1) seg = GetSegmentView((int)sid); if (mnode == Teuchos::null) { std::stringstream oss; oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_NormalField:\n" << "***ERR*** Cannot get view of node\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } mnode->SetN(n); MOERTEL::ProjectedNode* pnode = new MOERTEL::ProjectedNode(*mnode,xi,seg.get()); mnode->SetProjectedNode(pnode); mnode->SetGap(gap); } if (i != blength) { std::stringstream oss; oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_NormalField:\n" << "***ERR*** Mismatch in dimension of recv buffer\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } } } // for (int proc=0; proc<lComm()->NumProc(); ++proc) bcast.clear(); return true; }