コード例 #1
0
/*----------------------------------------------------------------------*
 |  build averaged normals                                              |
 *----------------------------------------------------------------------*/
bool MOERTEL::Interface::BuildNormals()
{ 
  //-------------------------------------------------------------------
  // interface needs to be complete
  if (!IsComplete())
  {
    if (gcomm_.MyPID()==0)
      cout << "***ERR*** MOERTEL::Interface::Project:\n"
           << "***ERR*** Complete() not called on interface " << Id_ << "\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
    return false;
  }
  
  //-------------------------------------------------------------------
  // send all procs not member of this interface's intra-comm out of here
  if (!lComm()) return true;

  //-------------------------------------------------------------------
  // interface segments need to have at least one function on each side
  std::map<int,Teuchos::RCP<MOERTEL::Segment> >::iterator curr;
  for (int side=0; side<2; ++side)
    for (curr=rseg_[side].begin(); curr!=rseg_[side].end(); ++curr){
      if (curr->second->Nfunctions() < 1)
      {
        cout << "***ERR*** MOERTEL::Interface::Project:\n"
             << "***ERR*** interface " << Id_ << ", mortar side\n"
             << "***ERR*** segment " << curr->second->Id() << " needs at least 1 function set\n"
             << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
        return false;
      }
	}
    
  //-------------------------------------------------------------------
  // build nodal normals on both sides
  std::map<int,Teuchos::RCP<MOERTEL::Node> >::iterator ncurr;

  for (int side=0; side<2; ++side)

    for (ncurr=rnode_[side].begin(); ncurr!=rnode_[side].end(); ++ncurr) {

#if 0
      cout << "side " << side << ": " << *(ncurr->second);
#endif
      ncurr->second->BuildAveragedNormal();
#if 0
      cout << "side " << side << ": " << *(ncurr->second);
#endif

    } // for(ncurr ...)

  return true;
}
コード例 #2
0
/*----------------------------------------------------------------------*
 | do projection of nodes on master and slave side                      |
 *----------------------------------------------------------------------*/
bool MOERTEL::Interface::ProjectNodes_Orthogonal()
{ 
  if (!IsComplete())
  {
	std::stringstream oss;
    oss << "***ERR*** MOERTEL::Interface::ProjectNodes_Orthogonal:\n"
         << "***ERR*** Complete() not called on interface " << Id() << "\n"
         << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
	throw ReportError(oss);
  }
  if (!lComm()) return true;

  // project the master nodes onto the slave surface orthogonaly
  ProjectNodes_MastertoSlave_Orthogonal();

  // project the slave nodes onto the master surface orthogonal to adjacent slave segment
  ProjectNodes_SlavetoMaster_Orthogonal();  
  
  return true;
}
コード例 #3
0
/*----------------------------------------------------------------------*
 | do projection of nodes on master and slave side                      |
 *----------------------------------------------------------------------*/
bool MOERTEL::Interface::ProjectNodes_NormalField()
{ 
  if (!IsComplete())
  {
	  std::stringstream oss;
    oss << "***ERR*** MOERTEL::Interface::ProjectNodes_NormalField:\n"
         << "***ERR*** Complete() not called on interface " << Id() << "\n"
         << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
	throw ReportError(oss);

  }
  if (!lComm()) return true;

  // project the slave nodes onto the master surface along the slave normal field
  ProjectNodes_SlavetoMaster_NormalField();  
  
  // project the master nodes ontp the slave surface along slave's normal field
  ProjectNodes_MastertoSlave_NormalField();

  return true;
}
コード例 #4
0
/*----------------------------------------------------------------------*
 |  finalize construction of this interface                             |
 *----------------------------------------------------------------------*/
bool MOERTEL::Interface::Complete()
{ 
  if (IsComplete())
  {
    if (OutLevel()>0)
      std::cout << "MOERTEL: ***WRN*** MOERTEL::Interface::InterfaceComplete:\n"
           << "MOERTEL: ***WRN*** InterfaceComplete() was called before, do nothing\n"
           << "MOERTEL: ***WRN*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
    return true;
  }
  
  //-------------------------------------------------------------------
  // check for NULL entries in maps
  bool ok = true;
  for (int i=0; i<2; ++i)
  {
	std::map<int,Teuchos::RCP<MOERTEL::Node> >::const_iterator curr;
    for (curr=node_[i].begin(); curr!=node_[i].end(); ++curr)
    {
      if (curr->second == Teuchos::null)
      {
        std::cout << "***ERR*** MOERTEL::Interface::Complete:\n"
             << "***ERR*** Interface # " << Id_ << ":\n"
             << "***ERR*** found NULL entry in map of nodes\n"
             << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
        ok = false;
      }
    }
  }
  for (int i=0; i<2; ++i)
  {
	std::map<int,Teuchos::RCP<MOERTEL::Segment> >::const_iterator curr;
    for (curr=seg_[i].begin(); curr!=seg_[i].end(); ++curr)
    {
      if (curr->second == Teuchos::null)
      {
        std::cout << "***ERR*** MOERTEL::Interface::Complete:\n"
             << "***ERR*** Interface # " << Id_ << ":\n"
             << "***ERR*** found NULL entry in map of segments\n"
             << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
        ok = false;
      }
    }
  }
  int lok = ok;
  int gok = 1;
  gcomm_.MinAll(&lok,&gok,1);  
  if (!gok) return false;
  
  //-------------------------------------------------------------------
  // check whether all nodes for segments are present
  // (take in account that node might be on different processor)
  // this test is expensive and does not scale. It is therefore only performed
  // when user requests a high output level
#if 1
  if (OutLevel()>9)
  {
    for (int proc=0; proc<gcomm_.NumProc(); ++proc)
    {
      for (int side=0; side<2; ++side)
      {
        // create length of list of all nodes adjacent to segments on proc
        int sendsize =  0;
        if (proc==gcomm_.MyPID())
        {
		  std::map<int,Teuchos::RCP<MOERTEL::Segment> >::const_iterator curr;
          for (curr=seg_[side].begin(); curr!=seg_[side].end(); ++curr)
            sendsize += curr->second->Nnode();
        }
        gcomm_.Broadcast(&sendsize,1,proc);
        
        // create list of all nodes adjacent to segments on proc
		std::vector<int> ids(sendsize);
        if (proc==gcomm_.MyPID())
        {
		  std::map<int,Teuchos::RCP<MOERTEL::Segment> >::const_iterator curr;
          int counter=0;
          for (curr=seg_[side].begin(); curr!=seg_[side].end(); ++curr)
          {
            const int* segids = curr->second->NodeIds();
            for (int i=0; i<curr->second->Nnode(); ++i)
              ids[counter++] = segids[i];
          }
        }
        gcomm_.Broadcast(&ids[0],sendsize,proc);
        
        // check on all processors for nodes in ids
		std::vector<int> foundit(sendsize);
		std::vector<int> gfoundit(sendsize);
        for (int i=0; i<sendsize; ++i) 
        {
          foundit[i] = 0;
          if (node_[side].find(ids[i]) != node_[side].end()) 
            foundit[i] = 1;
        }
        gcomm_.MaxAll(&foundit[0],&gfoundit[0],sendsize);
        for (int i=0; i<sendsize; ++i)
        {
          if (gfoundit[i]!=1)
          {
            if (gcomm_.MyPID()==proc)
            std::cout << "***ERR*** MOERTEL::Interface::Complete:\n"
                 << "***ERR*** cannot find segment's node # " << ids[i] << "\n"
                 << "***ERR*** in map of all nodes on all procs\n"
                 << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
            ids.clear();
            foundit.clear();
            gfoundit.clear();
            gcomm_.Barrier();
            return false;
          }
        }
        
        // tidy up
        ids.clear();
        foundit.clear();
        gfoundit.clear();
      } // for (int size=0; side<2; ++side)
    } // for (int proc=0; proc<gcomm_.NumProc(); ++proc)
  }
#endif  
  //-------------------------------------------------------------------
  // find all procs that have business on this interface (own nodes/segments)
  // build a Epetra_comm that contains only those procs
  // this intra-communicator will be used to handle most stuff on this 
  // interface so the interface will not block all other procs
  {
#ifdef EPETRA_MPI
	std::vector<int> lin(gcomm_.NumProc());
	std::vector<int> gin(gcomm_.NumProc());
    for (int i=0; i<gcomm_.NumProc(); ++i) lin[i] = 0;
    
    // check ownership of any segments
    for (int i=0; i<2; ++i)
      if (seg_[i].size() != 0)
      {
        lin[gcomm_.MyPID()] = 1;
        break;
      }
    // check ownership of any nodes
    for (int i=0; i<2; ++i)
      if (node_[i].size() != 0)
      {
        lin[gcomm_.MyPID()] = 1;
        break;
      }
    gcomm_.MaxAll(&lin[0],&gin[0],gcomm_.NumProc());
    lin.clear();
    
    // typecast the Epetra_Comm to Epetra_MpiComm
    Epetra_MpiComm* epetrampicomm = dynamic_cast<Epetra_MpiComm*>(&gcomm_);
    if (!epetrampicomm)
    {
	  std::stringstream oss;
			oss << "***ERR*** MOERTEL::Interface::Complete:\n"
           << "***ERR*** Interface " << Id() << ": Epetra_Comm is not an Epetra_MpiComm\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
      throw ReportError(oss);
    }

    // split the communicator into participating and none-participating procs
    int color;
    int key = gcomm_.MyPID();
    // I am taking part in the new comm if I have any ownership 
    if (gin[gcomm_.MyPID()]) 
      color = 0; 
    // I am not taking part in the new comm
    else                    
      color = MPI_UNDEFINED;
      
    // tidy up
    gin.clear();

    // create the local communicator   
    MPI_Comm  mpi_global_comm = epetrampicomm->GetMpiComm();
    MPI_Comm* mpi_local_comm  = new MPI_Comm();
    MPI_Comm_split(mpi_global_comm,color,key,mpi_local_comm);

    // create the new Epetra_MpiComm
    if (*mpi_local_comm == MPI_COMM_NULL)
      lcomm_ = Teuchos::null;
    else
      lcomm_ = Teuchos::rcp(new Epetra_MpiComm(*mpi_local_comm)); // FIXME: who destroys the MPI_Comm inside?

#if 0
    // test this stuff on the mpi level
    int grank,lrank;
    MPI_Comm_rank(mpi_global_comm,&grank);
    if (*mpi_local_comm != MPI_COMM_NULL)
      MPI_Comm_rank(*mpi_local_comm,&lrank);
    else
      lrank = -1;
    for (int proc=0; proc<gcomm_.NumProc(); ++proc)
    {
      if (proc==gcomm_.MyPID())
      std::cout << "using mpi    comms: I am global rank " << grank << " and local rank " << lrank << std::endl;
      gcomm_.Barrier();
    }
    // test this stuff on the epetra level
    if (lComm())
      for (int proc=0; proc<lcomm_->NumProc(); ++proc)
      {
        if (proc==lcomm_->MyPID())
        std::cout << "using epetra comms: I am global rank " << gcomm_.MyPID() << " and local rank " << lcomm_->MyPID() << std::endl;
        lcomm_->Barrier();
      }
    gcomm_.Barrier();
#endif


    
#else  // the easy serial case
    Epetra_SerialComm* serialcomm = dynamic_cast<Epetra_SerialComm*>(&gcomm_);
    if (!serialcomm)
    {
	  std::stringstream oss;
			oss << "***ERR*** MOERTEL::Interface::Complete:\n"
           << "***ERR*** Interface " << Id() << ": Epetra_Comm is not an Epetra_SerialComm\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
      throw ReportError(oss);
    }
    lcomm_ = Teuchos::rcp(new Epetra_SerialComm(*serialcomm));
#endif // end of #ifdef PARALLEL    
  }
  
  //-------------------------------------------------------------------
  // create a map of all nodes to there PID (process id)
  if (lComm())
    for (int proc=0; proc<lcomm_->NumProc(); ++proc)
    {
      int lnnodes = 0;
      if (proc==lcomm_->MyPID())
        lnnodes = node_[0].size() + node_[1].size();
      lcomm_->Broadcast(&lnnodes,1,proc);
	  std::vector<int> ids(lnnodes);
      if (proc==lcomm_->MyPID())
      {
		std::map<int,Teuchos::RCP<MOERTEL::Node> >::const_iterator curr;
        int counter=0;
        for (int side=0; side<2; ++side)
          for (curr=node_[side].begin(); curr!=node_[side].end(); ++curr)
            ids[counter++] = curr->first;
      }
      lcomm_->Broadcast(&ids[0],lnnodes,proc);
      for (int i=0; i<lnnodes; ++i)
        nodePID_.insert(std::pair<int,int>(ids[i],proc));
      ids.clear();
    }
  
  //-------------------------------------------------------------------
  // create a map of all segments to there PID (process id)
  if (lComm())
    for (int proc=0; proc<lcomm_->NumProc(); ++proc)
    {
      int lnsegs = 0;
      if (proc==lcomm_->MyPID())
        lnsegs = seg_[0].size() + seg_[1].size();
      lcomm_->Broadcast(&lnsegs,1,proc);
	  std::vector<int> ids(lnsegs);
      if (proc==lcomm_->MyPID())
      {
		std::map<int,Teuchos::RCP<MOERTEL::Segment> >::const_iterator curr;
        int counter=0;
        for (int side=0; side<2; ++side)
          for (curr=seg_[side].begin(); curr!=seg_[side].end(); ++curr)
            ids[counter++] = curr->first;
      }
      lcomm_->Broadcast(&ids[0],lnsegs,proc);
      for (int i=0; i<lnsegs; ++i)
        segPID_.insert(std::pair<int,int>(ids[i],proc));
      ids.clear();
    }
  
  //-------------------------------------------------------------------
  // set isComplete_ flag
  // we set it here already as we will be using some methods that require it
  // from now on
  isComplete_ = true;
  
  //-------------------------------------------------------------------
  // make the nodes know there adjacent segments
  // find max number of nodes to a segment
  if (lComm())
  {
    int lmaxnnode = 0;
    int gmaxnnode = 0;
    for (int side=0; side<2; ++side)
    {
	  std::map<int,Teuchos::RCP<MOERTEL::Segment> >::const_iterator scurr;
      for (scurr=seg_[side].begin(); scurr!=seg_[side].end(); ++scurr)
        if (lmaxnnode < scurr->second->Nnode())
          lmaxnnode = scurr->second->Nnode();
    }
    lcomm_->MaxAll(&lmaxnnode,&gmaxnnode,1);
    
    // loop all procs and broadcast their adjacency
    for (int proc=0; proc<lcomm_->NumProc(); ++proc)
    {
      // local number of segments
      int lnseg = 0;
      if (proc==lcomm_->MyPID())
        lnseg = seg_[0].size() + seg_[1].size();
      lcomm_->Broadcast(&lnseg,1,proc);
      
      // allocate vector to hold adjacency
      int offset = gmaxnnode+2;
      int size   = lnseg*offset;
	  std::vector<int> adj(size);
      
      // proc fills adjacency vector adj and broadcasts
      if (proc==lcomm_->MyPID())
      {
        int count = 0;
        for (int side=0; side<2; ++side)
        {
		  std::map<int,Teuchos::RCP<MOERTEL::Segment> >::const_iterator scurr;
          for (scurr=seg_[side].begin(); scurr!=seg_[side].end(); ++scurr)
          {
			Teuchos::RCP<MOERTEL::Segment> seg = scurr->second;
            adj[count]   = seg->Id();
            adj[count+1] = seg->Nnode();
            const int* ids = seg->NodeIds();
            for (int i=0; i<seg->Nnode(); ++i)
              adj[count+2+i] = ids[i];
            count += offset;
          }
        }
      }
      lcomm_->Broadcast(&adj[0],size,proc);
      
      // all procs read adj and add segment to the nodes they own
      int count = 0;
      for (int i=0; i<lnseg; ++i)
      {
        int segid = adj[count];
        int nnode = adj[count+1];
        for (int j=0; j<nnode; ++j)
        {
          int nid = adj[count+2+j];
          if (lcomm_->MyPID() == NodePID(nid))
          {
            // I own this node, so set the segment segid in it
			Teuchos::RCP<MOERTEL::Node> node = GetNodeViewLocal(nid);
            if (node == Teuchos::null)
            {
				std::stringstream oss;
					oss << "***ERR*** MOERTEL::Interface::Complete:\n"
						<< "***ERR*** cannot find node " << nid << "\n"
                   << "***ERR*** in map of all nodes on this proc\n"
                   << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
				throw ReportError(oss);
            }
            node->AddSegment(segid);
          }
          else
            continue;
        }
        count += offset;
      }
      adj.clear();
    } // for (int proc=0; proc<lcomm_->NumProc(); ++proc)
  } // if (lComm())
  
  //-------------------------------------------------------------------
  // build redundant segments and nodes
  if (lComm())
  {
    int ok = 0;
    ok += RedundantSegments(0);  
    ok += RedundantSegments(1);  
    ok += RedundantNodes(0);
    ok += RedundantNodes(1);
    if (ok != 4)
    {
		std::stringstream oss;
			oss << "***ERR*** MOERTEL::Interface::Complete:\n"
           << "***ERR*** building of redundant information failed\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
		throw ReportError(oss);
    }
  }

  //-------------------------------------------------------------------
  // make topology segments <-> nodes for each side
  if (lComm())
    BuildNodeSegmentTopology(); 

  //-------------------------------------------------------------------
  // delete distributed nodes and segments
  for (int i=0; i<2; ++i)
  {
    seg_[i].clear();
    node_[i].clear();
  }


  //-------------------------------------------------------------------
  // we are done
  // note that there might not be any functions on the interface yet
  // they still have to be set
  
  return ok;
}
コード例 #5
0
/*----------------------------------------------------------------------*
 |  build averaged normals and make projection of nodes                 |
 *----------------------------------------------------------------------*/
bool MOERTEL::Interface::Project()
{ 
  bool ok = false;
  
  //-------------------------------------------------------------------
  // interface needs to be complete
  if (!IsComplete())
  {
    if (gcomm_.MyPID()==0)
      cout << "***ERR*** MOERTEL::Interface::Project:\n"
           << "***ERR*** Complete() not called on interface " << Id_ << "\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
    return false;
  }
  
  //-------------------------------------------------------------------
  // send all procs not member of this interface's intra-comm out of here
  if (!lComm()) return true;

  //-------------------------------------------------------------------
  // interface segments need to have at least one function on each side
  std::map<int,Teuchos::RCP<MOERTEL::Segment> >::iterator curr;
  for (int side=0; side<2; ++side)
    for (curr=rseg_[side].begin(); curr!=rseg_[side].end(); ++curr)
      if (curr->second->Nfunctions() < 1)
      {
        cout << "***ERR*** MOERTEL::Interface::Project:\n"
             << "***ERR*** interface " << Id_ << ", mortar side\n"
             << "***ERR*** segment " << curr->second->Id() << " needs at least 1 function set\n"
             << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
        return false;
      }
    
  //-------------------------------------------------------------------
  // build nodal normals on both sides
  std::map<int,Teuchos::RCP<MOERTEL::Node> >::iterator ncurr;
  for (int side=0; side<2; ++side)
    for (ncurr=rnode_[side].begin(); ncurr!=rnode_[side].end(); ++ncurr)
    {
#if 0
      cout << "side " << side << ": " << *(ncurr->second);
#endif
      ncurr->second->BuildAveragedNormal();
#if 0
      cout << "side " << side << ": " << *(ncurr->second);
#endif
    }

  //-------------------------------------------------------------------
  // check the type of projection to be used and project nodes
  // projection along the normal field:
  // uses the slave side's interpolated normal field to
  // project slave nodes onto the master surfaces.
  // Then projects master nodes along the same normal field on slave
  // surfaces. Overrides the normals in the master nodes by the negative
  // of the normal field of their projection point
  if (GetProjectionType() == MOERTEL::Interface::proj_continousnormalfield)
  {
    ok = ProjectNodes_NormalField();
    if (!ok) return false;
  }
  else if (GetProjectionType() == MOERTEL::Interface::proj_orthogonal)
  {
    ok = ProjectNodes_Orthogonal();
    if (!ok) return false;
  }
  else
  {
    cout << "***ERR*** MOERTEL::Interface::Project:\n"
         << "***ERR*** interface " << Id() << "\n"
         << "***ERR*** unknown type of nodal projection\n"
         << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
    return false;
  }
  return true;
}
コード例 #6
0
/*----------------------------------------------------------------------*
 | project the slave nodes onto master segments orthogonal              |
 *----------------------------------------------------------------------*/
bool MOERTEL::Interface::ProjectNodes_SlavetoMaster_Orthogonal()
{
  if (!IsComplete())
  {
	std::stringstream oss;
    oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_Orthogonal:\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 slave side and project those belonging 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;

#if 0
    cout << "now projecting\n " << *snode;
#endif    
    
    if (NodePID(snode->Id()) != lComm()->MyPID())
      continue;
    
    const double* sx = snode->X();
    double mindist = 1.0e+20;
	Teuchos::RCP<MOERTEL::Node> closenode = Teuchos::null;
    
    // find a node on the master side, that is closest 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;
      const double* mx = mnode->X();
      
      // build distance | mnode->X() - snode->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 = mnode;
      }
      //cout << "snode " << snode->Id() << " mnode " << mnode->Id() << " mindist " << mindist  << " dist " << dist << endl;
    }
    if (closenode == Teuchos::null)
    {
	  std::stringstream oss;
      oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_Orthogonal:\n"
           << "***ERR*** Weired: for slave node " << snode->Id() << " no closest master node found\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
		throw ReportError(oss);
    }

    // get segments attached to closest node cnode
    int  nmseg = closenode->Nseg();
    MOERTEL::Segment** msegs = closenode->Segments(); 
    
    // create a projection-iterator
    MOERTEL::Projector projector(IsOneDimensional(),OutLevel());

    // loop segments and find all projections onto them
    int nsseg = snode->Nseg();
    MOERTEL::Segment** ssegs = snode->Segments(); 
    for (int i=0; i<nmseg; ++i)
    {
      // loop all segments that are adjacent to the slave node
      for (int j=0; j<nsseg; ++j)
      {
        // project the slave node onto that master segment
        double xi[2]; xi[0] = xi[1] = 0.0;
		double gap;
        projector.ProjectNodetoSegment_Orthogonal_to_Slave(*snode,*(msegs[i]),xi,gap,*(ssegs[j]));
        
        // check whether this projection is good
        bool ok = false;
        if (IsOneDimensional())
        {
          if (abs(xi[0])<1.01)
            ok = true;
        }
        else
        {
		  std::stringstream oss;
          oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_Orthogonal:\n"
               << "***ERR*** not impl. for 3D\n"
               << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
			throw ReportError(oss);
        }
        
        if (ok) // the projection is good
        {
          // create a projected node and store it in snode
          MOERTEL::ProjectedNode* pnode = 
            new MOERTEL::ProjectedNode(*snode,xi,msegs[i],ssegs[j]->Id());
          snode->SetProjectedNode(pnode);
		  snode->SetGap(gap);
#if 0
          cout << " snode id: " << pnode->Id()
               << " projects on mseg: " << msegs[i]->Id()
               << " orth to sseg " << ssegs[j]->Id() << endl;
#endif          
        }
      } // for (int j=0; j<nsseg; ++j)
    } // for (int i=0; i<nmseg; ++i)
  } // for (scurr=rnode_[sside].begin(); scurr!=rnode_[sside].end(); ++scurr)  



  // loop all slave nodes again and make projections redundant
  if (lComm()->NumProc()>1)
  {
	std::vector<double> bcast(10*rnode_[sside].size());
    for (int proc=0; proc<lComm()->NumProc(); ++proc)
    {
      int blength=0;
      if (proc==lComm()->MyPID())
      {
        for (scurr=rnode_[sside].begin(); scurr!=rnode_[sside].end(); ++scurr)
        {
		  Teuchos::RCP<MOERTEL::Node> snode = scurr->second;
          if (proc != NodePID(snode->Id())) continue; // cannot have a projection on a node i don't own
          int npnode=0;
		  Teuchos::RCP<MOERTEL::ProjectedNode>* pnode = snode->GetProjectedNode(npnode);        
          if (!pnode) continue; // no projection on this one
          bcast[blength] = (double)snode->Id();
          ++blength;
          bcast[blength] = (double)npnode;
          ++blength;
          for (int j=0; j<npnode; ++j)
          {
            bcast[blength] = (double)pnode[j]->Segment()->Id();
            ++blength;
            const double* xi = pnode[j]->Xi();
            bcast[blength] = xi[0];
            ++blength;
            bcast[blength] = xi[1];
            ++blength;
            bcast[blength] = pnode[j]->OrthoSegment();
            ++blength;
            bcast[blength] = pnode[j]->Gap();
            ++blength;
          }
          if ((int)bcast.size() < blength+20) 
            bcast.resize(bcast.size()+40);
        } // for (mcurr=rnode_[mside].begin(); mcurr!=rnode_[mside].end(); ++mcurr)
        if (blength>=(int)bcast.size())
        {
		  std::stringstream oss;
          oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_Orthogonal:\n"
               << "***ERR*** Overflow in communication buffer occured\n"
               << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
			throw ReportError(oss);
        }
      } // if (proc==lComm()->MyPID())
      
      lComm()->Broadcast(&blength,1,proc);
      if (proc!=lComm()->MyPID()) bcast.resize(blength);
      lComm()->Broadcast(&bcast[0],blength,proc);
      
      if (proc!=lComm()->MyPID())
      {
        int i;
        for (i=0; i<blength;)
        {
          int nid    = (int)bcast[i] ; ++i;
		  Teuchos::RCP<MOERTEL::Node> snode = GetNodeView(nid);
          int npnode = (int) bcast[i]; ++i;
          for (int j=0; j<npnode; ++j)
          {
            int sid     = (int)bcast[i]; ++i;
            double* xi  = &bcast[i];     ++i; ++i;
            int orthseg = (int)bcast[i]; ++i;
			double gap  = bcast[i];      ++i;
			Teuchos::RCP<MOERTEL::Segment> seg   = GetSegmentView(sid);
            MOERTEL::ProjectedNode* pnode = new MOERTEL::ProjectedNode(*snode,xi,seg.get(),orthseg);
            snode->SetProjectedNode(pnode);
			snode->SetGap(gap);
          }
        }
        if (i != blength)
        {
		  std::stringstream oss;
          oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_Orthogonal:\n"
               << "***ERR*** Mismatch in dimension of recv buffer: " << i << " != " << blength << "\n"
               << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
			throw ReportError(oss);
        }
      } // if (proc!=lComm()->MyPID())
    } // for (int proc=0; proc<lComm()->NumProc(); ++proc)
    bcast.clear();
  } // if (lComm()->NumProc()>1)

#if 1
  // Postprocess the projections
  // The slave side of the interface might be larger then the master side
  // of the interface so not all slave nodes have a projection.
  // For those slave nodes without a projection attached to a slave segment
  // which overlaps with the master side, Lagrange multipliers have to be
  // introduced. This is done by checking all nodes without a projection 
  // whether they are attached to some slave segment on which another node
  // HAS a projection. If this case is found, a pseudo ProjectedNode is 
  // introduced for that node.
  for (scurr=rnode_[sside].begin(); scurr!=rnode_[sside].end(); ++scurr)
  {
	Teuchos::RCP<MOERTEL::Node> snode = scurr->second;
    // do only my own nodes

    // don't do anything on nodes that already have a projection
    if (snode->GetProjectedNode() != Teuchos::null)
      continue;

    // get segments adjacent to this node  
    int nseg             = snode->Nseg();
    MOERTEL::Segment** segs = snode->Segments();
    // loop segments and check for other nodes with projection
    bool foundit = false;
    for (int i=0; i<nseg; ++i)
    {
      int nnode = segs[i]->Nnode();
      MOERTEL::Node** nodes = segs[i]->Nodes();
      for (int j=0; j<nnode; ++j)
        if (nodes[j]->GetProjectedNode() != Teuchos::null)
          if (nodes[j]->GetProjectedNode()->Segment())
          {
            foundit = true;
            break;
          }
      if (foundit) break;
    }
    if (foundit)
    {
#if 0
      cout << "Node without projection:\n" << *snode;        
      cout << "...get's lagrange multipliers\n\n";
#endif
      MOERTEL::ProjectedNode* pnode = new MOERTEL::ProjectedNode(*snode,NULL,NULL);
      snode->SetProjectedNode(pnode);
	  snode->SetGap(0.);
    }
  }
#endif


  return true; 
}
コード例 #7
0
/*----------------------------------------------------------------------*
 | project nodes master to slave along slave orthogonal         |
 *----------------------------------------------------------------------*/
bool MOERTEL::Interface::ProjectNodes_MastertoSlave_Orthogonal()
{ 
  if (!IsComplete())
  {
	std::stringstream oss;
    oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_Orthogonal:\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 master nodes 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_Orthogonal:\n"
           << "***ERR*** Weired: for master node " << mnode->Id() << " no closest master node found\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
		throw ReportError(oss);
    }


    // 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];
	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 orthogonally on the slave segment
      double xi[2]; xi[0] = xi[1] = 0.0;
      projector.ProjectNodetoSegment_SegmentOrthogonal(*mnode,*(segs[i]),xi,gap);
      
      // check whether xi is better than previous projection
      if (IsOneDimensional())
      {
        if (abs(xi[0]) < abs(bestdist[0])) 
        {
            bestdist[0] = xi[0];
            bestdist[1] = xi[1];
            bestseg = segs[i];
            bestgap = gap;
        }
      }
      else
      {
		std::stringstream oss;
        oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_Orthogonal:\n"
             << "***ERR*** not impl. for 3D\n"
             << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
		throw ReportError(oss);
      }
      
    } // for (int i=0; i<nseg; ++i)
      
    // check whether this best projection is good
    bool ok = false;
    if (IsOneDimensional())
    {
      if (abs(bestdist[0]) < 1.01) 
        ok = true;
    }
    else
    {
	  std::stringstream oss;
      oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_Orthogonal:\n"
           << "***ERR*** not impl. for 3D\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
		throw ReportError(oss);
    }
    
    if (ok) // the projection is good
    {
      // create a 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***: Node " << mnode->Id() << " does not have projection\n\n";
      //mnode->SetProjectedNode(NULL);
    }
  } // for (mcurr=rnode_[mside].begin(); mcurr!=rnode_[mside].end(); ++mcurr)

  // loop all master nodes again and make projection redundant
  int bsize = 4*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();
        bcast[blength] = (double)pnode->Id();
        ++blength;
        bcast[blength] = (double)pnode->Segment()->Id();
        ++blength;
        bcast[blength] = xi[0];
        ++blength;
        bcast[blength] = xi[1];
        ++blength;
        bcast[blength] = pnode->Gap();
        ++blength;
      } // for (mcurr=rnode_[mside].begin(); mcurr!=rnode_[mside].end(); ++mcurr)
      if (blength>bsize)
      {
		  std::stringstream oss;
        oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_Orthogonal:\n"
             << "***ERR*** Overflow in communication buffer occured\n"
             << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
		throw ReportError(oss);
      }
    } // if (proc==lComm()->MyPID())
    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;
        int     sid = (int)bcast[i];  ++i;
        double* xi  =      &bcast[i]; ++i; ++i; 
		double  gap =      bcast[i];  ++i;
		Teuchos::RCP<MOERTEL::Node> mnode = GetNodeView(nid);
		Teuchos::RCP<MOERTEL::Segment> seg = GetSegmentView(sid);
        if (mnode == Teuchos::null || seg == Teuchos::null)
        {
		  std::stringstream oss;
          oss << "***ERR*** MOERTEL::Interface::ProjectNodes_MastertoSlave_Orthogonal:\n"
               << "***ERR*** Cannot get view of node or segment\n"
               << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
			throw ReportError(oss);
        }
        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_Orthogonal:\n"
             << "***ERR*** Mismatch in dimension of recv buffer: " << i << " != " << blength << "\n"
             << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
			throw ReportError(oss);
      }
    } // if (proc!=lComm()->MyPID())
  }  // for (int proc=0; proc<lComm()->NumProc(); ++proc)
  bcast.clear();

  return true;
}
コード例 #8
0
/*----------------------------------------------------------------------*
 | 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;
}
コード例 #9
0
/*----------------------------------------------------------------------*
 | project the slave nodes onto master segments along slave normal field|
 *----------------------------------------------------------------------*/
bool MOERTEL::Interface::ProjectNodes_SlavetoMaster_NormalField()
{ 
  if (!IsComplete())
  {
	  std::stringstream oss;
    oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_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 slave side and project those belonging 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;
    if (NodePID(snode->Id()) != lComm()->MyPID())
      continue;
    
    const double* sx = snode->X();
    double mindist = 1.0e+20;
	Teuchos::RCP<MOERTEL::Node> closenode = Teuchos::null;
    
    // find a node on the master side, that is closest 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;
      const double* mx = mnode->X();
      
      // build distance | mnode->X() - snode->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 = mnode;
      }
      cout << "snode " << snode->Id() << " mnode " << mnode->Id() << " mindist " << mindist  << " dist " << dist << endl;
    }
    if (closenode == Teuchos::null)
    {
	  std::stringstream oss;
      oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_NormalField:\n"
           << "***ERR*** Weired: for slave node " << snode->Id() << " no closest master node found\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
		throw ReportError(oss);
    }

#if 0
    cout << "snode     " << *snode;
    cout << "closenode " << *closenode;
#endif    

    // get segments attached to closest node cnode
    int  nseg = closenode->Nseg();
    MOERTEL::Segment** segs = closenode->Segments(); 
    
    // create a projection-iterator
    MOERTEL::Projector projector(IsOneDimensional(),OutLevel());

    // finding a good geometric projection is somehow 
    // critical. We work with some tolerance here and pick the 'best'
    // out of all acceptable projections made    
    // loop these segments and project onto them along snode's normal vector
    double bestdist[2];
	double gap, bestgap = 0.0;
    const double tol = 0.2;
    bestdist[0] = bestdist[1] = 1.0e+20;
    MOERTEL::Segment* bestseg = NULL;
    for (int i=0; i<nseg; ++i)
    {
      // project the slave node onto that master segment
      double xi[2]; xi[0] = xi[1] = 0.0;
      projector.ProjectNodetoSegment_NodalNormal(*snode, *(segs[i]), xi, gap);
      
      // check whether xi is better then previous projections
      if (IsOneDimensional()) // 2D case
      {
        if (abs(xi[0]) < abs(bestdist[0])) 
        { 
            bestdist[0] = xi[0];
            bestdist[1] = xi[1];
            bestseg = segs[i];
			bestgap = gap;
        }
      }
      else // 3D case
      {
        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 and bestdist are inside the segment
    // (with some tolerance of 20%)
    bool ok = false;
    if (IsOneDimensional())
    {
      if (abs(bestdist[0]) < 1.2) 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
    {
      // create a projected node and store it in snode
      MOERTEL::ProjectedNode* pnode 
        = new MOERTEL::ProjectedNode(*snode,bestdist,bestseg);
      snode->SetProjectedNode(pnode);
	  snode->SetGap(bestgap);
    }
    else
    {
      if (OutLevel()>6)
        cout << "MOERTEL: ***WRN***: Projection s->m: Node " << snode->Id() << " does not have projection\n";
      snode->SetProjectedNode(NULL);
    }
  } // for (scurr=rnode_[sside].begin(); scurr!=rnode_[sside].end(); ++scurr)
  lComm()->Barrier();
  
  // loop all slave nodes again and make the projections redundant
  std::vector<double> bcast(4*rnode_[sside].size());
  for (int proc=0; proc<lComm()->NumProc(); ++proc)
  {
    int blength = 0;
    if (proc==lComm()->MyPID())
    {
      for (scurr=rnode_[sside].begin(); scurr!=rnode_[sside].end(); ++scurr)
      {
		Teuchos::RCP<MOERTEL::Node> snode = scurr->second;
        if (proc != NodePID(snode->Id())) continue; // I cannot have a projection on a node not owned by me
		Teuchos::RCP<MOERTEL::ProjectedNode> pnode = snode->GetProjectedNode();
        if (pnode==Teuchos::null) continue; // this node does not have a projection
        const double* xi = pnode->Xi();
        bcast[blength] = (double)pnode->Id();            
        ++blength;
        if (pnode->Segment())
          bcast[blength] = (double)pnode->Segment()->Id(); 
        else
          bcast[blength] = -0.1; // indicating this node does not have projection but lagrange multipliers
        ++blength;
        bcast[blength] = xi[0];
        ++blength;
        bcast[blength] = xi[1];
        ++blength;
        bcast[blength] = pnode->Gap();
        ++blength;
      } 
      if (blength > (int)(4*rnode_[sside].size()))
      {
		std::stringstream oss;
        oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_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  gap =      bcast[i]; ++i;
		Teuchos::RCP<MOERTEL::Node> snode = GetNodeView(nid);
		Teuchos::RCP<MOERTEL::Segment> seg = Teuchos::null;
        if (sid!=-0.1)
          seg = GetSegmentView((int)sid);
        if (snode == Teuchos::null)
        {
		  std::stringstream oss;
          oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_NormalField:\n"
               << "***ERR*** Cannot get view of node\n"
               << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
			throw ReportError(oss);
        }
        MOERTEL::ProjectedNode* pnode = new MOERTEL::ProjectedNode(*snode,xi,seg.get());
        snode->SetProjectedNode(pnode);
        snode->SetGap(gap);
      }
      if (i != blength)
      {
		  std::stringstream oss;
        oss << "***ERR*** MOERTEL::Interface::ProjectNodes_SlavetoMaster_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();
  lComm()->Barrier();

#if 1
  // Postprocess the projections
  // The slave side of the interface might be larger then the master side
  // of the interface so not all slave nodes have a projection.
  // For those slave nodes without a projection attached to a slave segment
  // which overlaps with the master side, Lagrange multipliers have to be
  // introduced. This is done by checking all nodes without a projection 
  // whether they are attached to some slave segment on which another node
  // HAS a projection. If this case is found, a pseudo ProjectedNode is 
  // introduced for that node.
  for (scurr=rnode_[sside].begin(); scurr!=rnode_[sside].end(); ++scurr)
  {
	Teuchos::RCP<MOERTEL::Node> snode = scurr->second;
    
    // don't do anything on nodes that already have a projection
    if (snode->GetProjectedNode() != Teuchos::null)
      continue;

    // get segments adjacent to this node  
    int nseg             = snode->Nseg();
    MOERTEL::Segment** segs = snode->Segments();
    
    // loop segments and check for other nodes with projection
    bool foundit = false;
    for (int i=0; i<nseg; ++i)
    {
      int nnode = segs[i]->Nnode();
      MOERTEL::Node** nodes = segs[i]->Nodes();
      for (int j=0; j<nnode; ++j)
        if (nodes[j]->GetProjectedNode() != Teuchos::null)
          if (nodes[j]->GetProjectedNode()->Segment())
          {
            foundit = true;
            break;
          }
      if (foundit) break;
    }
    
    if (foundit)
    {
#if 1
      cout << "Node without projection:\n" << *snode;        
      cout << "...get's lagrange multipliers\n\n";
#endif
      MOERTEL::ProjectedNode* pnode = new MOERTEL::ProjectedNode(*snode,NULL,NULL);
      snode->SetProjectedNode(pnode);
	  snode->SetGap(0.);
    }
  } // for (scurr=rnode_[sside].begin(); scurr!=rnode_[sside].end(); ++scurr)
#endif  

  return true;
}