187 libmesh_assert( node != NULL );
190 libMesh::Real distance = std::numeric_limits<libMesh::Real>::infinity();
194 libmesh_assert( (dim==2) || (dim==3) );
197 std::vector<libMesh::Real> xnode(dim);
198 for(
unsigned int ii=0; ii<dim; ii++ ) xnode[ii] = (*node)(ii);
208 libMesh::MeshBase::const_element_iterator el =
_boundary_mesh.active_elements_begin();
209 const libMesh::MeshBase::const_element_iterator end_el =
_boundary_mesh.active_elements_end();
213 std::cout <<
"There are no elements to iterate through!!! Returning..." << std::endl;
217 const libMesh::Elem* elem_containing_min = NULL;
218 libMesh::Real dmin = std::numeric_limits<Real>::infinity();
220 for ( ; el != end_el; ++el) {
222 const libMesh::Elem* belem = *el;
224 for (
unsigned int bnode=0; bnode<belem->n_nodes(); ++bnode)
226 const libMesh::Point& pbndry = belem->point(bnode);
228 libMesh::Real dnode = 0.0;
229 for (
unsigned int idim=0; idim<dim; ++idim)
230 dnode += (xnode[idim] - pbndry(idim))*(xnode[idim] - pbndry(idim));
232 dnode = std::sqrt(dnode);
237 elem_containing_min = belem;
244 std::set<const libMesh::Elem*> near_min_elems;
245 elem_containing_min->find_point_neighbors (near_min_elems);
248 near_min_elems.insert(elem_containing_min);
250 std::set<const libMesh::Elem*>::iterator nm_el;
253 for (nm_el=near_min_elems.begin(); nm_el!=near_min_elems.end(); ++nm_el)
256 const libMesh::Elem* belem = *nm_el;
259 libmesh_assert( belem->default_order() == FIRST );
264 libMesh::Real dedge = std::numeric_limits<libMesh::Real>::infinity();
274 if (belem->dim()!=1)
continue;
278 libmesh_assert( belem->n_nodes() == 2 );
279 libmesh_assert( belem->type() == EDGE2 );
282 const libMesh::Point& p0 = belem->point(0);
283 const libMesh::Point& p1 = belem->point(1);
289 DistanceToSegment<2>(*node, line, dedge);
291 if ( dedge < distance ) distance = dedge;
302 if (belem->dim()!=2)
continue;
304 libmesh_assert( (belem->type() == TRI3) || (belem->type() == QUAD4) );
306 if ( belem->type() == TRI3 )
314 const libMesh::Point& p0 = belem->point(0);
315 const libMesh::Point& p1 = belem->point(1);
316 const libMesh::Point& p2 = belem->point(2);
318 const libMesh::Real x_xi = (p1(0) - p0(0)), x_et = (p2(0) - p0(0));
319 const libMesh::Real y_xi = (p1(1) - p0(1)), y_et = (p2(1) - p0(1));
320 const libMesh::Real z_xi = (p1(2) - p0(2)), z_et = (p2(2) - p0(2));
322 libMesh::Real A[2][2], b[2];
324 A[0][0] = x_xi*x_xi + y_xi*y_xi + z_xi*z_xi;
325 A[0][1] = x_xi*x_et + y_xi*y_et + z_xi*z_et;
326 A[1][0] = x_xi*x_et + y_xi*y_et + z_xi*z_et;
327 A[1][1] = x_et*x_et + y_et*y_et + z_et*z_et;
329 b[0] = (xnode[0] - p0(0))*x_xi + (xnode[1] - p0(1))*y_xi + (xnode[2] - p0(2))*z_xi;
330 b[1] = (xnode[0] - p0(0))*x_et + (xnode[1] - p0(1))*y_et + (xnode[2] - p0(2))*z_et;
332 const libMesh::Real detA = A[0][0]*A[1][1] - A[1][0]*A[0][1];
333 libmesh_assert( fabs(detA) > 0.0 );
335 const libMesh::Real xi = ( A[1][1]*b[0] - A[0][1]*b[1])/detA;
336 const libMesh::Real et = (-A[1][0]*b[0] + A[0][0]*b[1])/detA;
344 if ( (xi<0.0) || (et<0.0) || (et>1.0-xi) ) {
346 libMesh::Real dtmp = std::numeric_limits<libMesh::Real>::infinity();
354 for (
unsigned int iedge=0; iedge<3; iedge++ ){
359 if (iedge==0) { line.p0 = p1; line.p1 = p2; }
360 else if (iedge==1) { line.p0 = p0; line.p1 = p2; }
361 else { line.p0 = p0; line.p1 = p1; }
363 DistanceToSegment<3>(*node, line, dtmp);
365 if( dtmp < dedge ) dedge = dtmp;
372 libMesh::Real xint[3];
373 for (
unsigned int ii=0; ii<3; ii++ ) {
374 xint[ii] = p0(ii)*(1.0 - xi - et) + p1(ii)*xi + p2(ii)*et;
379 for (
unsigned int ii=0; ii<3; ii++ ) {
380 dedge += (xnode[ii] - xint[ii])*(xnode[ii] - xint[ii]);
387 else if ( belem->type() == QUAD4 )
391 libMesh::Real RTOL = 1e-10;
392 libMesh::Real ATOL = 1e-20;
393 const unsigned int ITER_MAX=1000;
396 ComputeDistanceResidual res(belem, node);
398 ComputeDistanceJacobian jac;
400 libMesh::DenseVector<libMesh::Real> X(2); X(0) = X(1) = 0.0;
401 libMesh::DenseVector<libMesh::Real> dX(2);
404 libMesh::DenseVector<libMesh::Real> R(2);
405 libMesh::DenseMatrix<libMesh::Real> dRdX(2,2);
406 libMesh::DenseMatrix<libMesh::Real> dRdXinv(2,2);
411 libMesh::Real R0 = R.l2_norm();
414 while ( (R.l2_norm() > ATOL) && (R.l2_norm()/R0 > RTOL) && (iter<ITER_MAX) )
417 jac(X, R, res, dRdX);
420 det = dRdX(0,0)*dRdX(1,1) - dRdX(0,1)*dRdX(1,0);
423 if(std::abs(det)<=1e-20)
425 std::cout <<
"WARNING: about to divide by zero." << std::endl;
428 dRdXinv(0,0) = dRdX(1,1)/det;
429 dRdXinv(0,1) = -dRdX(0,1)/det;
430 dRdXinv(1,0) = -dRdX(1,0)/det;
431 dRdXinv(1,1) = dRdX(0,0)/det;
434 dX(0) = -( dRdXinv(0,0)*R(0) + dRdXinv(0,1)*R(1) );
435 dX(1) = -( dRdXinv(1,0)*R(0) + dRdXinv(1,1)*R(1) );
461 std::cout <<
"WARNING: Failed to converge distance function iteration. Assuming that min is outside this face. Use closest distance to edges to proceed." << std::endl;
469 if ( std::abs(X(0)) > 1.0 || std::abs(X(1)) > 1.0 )
474 libMesh::Real dtmp = std::numeric_limits<libMesh::Real>::infinity();
482 for (
unsigned int iedge=0; iedge<4; iedge++ ){
487 if (iedge==0) { line.p0 = belem->point(0); line.p1 = belem->point(1); }
488 else if (iedge==1) { line.p0 = belem->point(1); line.p1 = belem->point(2); }
489 else if (iedge==2) { line.p0 = belem->point(2); line.p1 = belem->point(3); }
490 else { line.p0 = belem->point(3); line.p1 = belem->point(0); }
492 DistanceToSegment<3>(*node, line, dtmp);
494 if( dtmp < dedge ) dedge = dtmp;
503 libMesh::UniquePtr<libMesh::FEBase> fe( libMesh::FEBase::build(2, libMesh::FEType(libMesh::FIRST, libMesh::LAGRANGE)) );
505 std::vector<libMesh::Point> xi(1);
510 const std::vector<std::vector<libMesh::Real> > &basis = fe->get_phi();
513 fe->reinit(belem, &xi);
516 libMesh::DenseVector<libMesh::Real> xx(3);
519 for (
unsigned int inode=0; inode<belem->n_nodes(); ++inode)
520 for (
unsigned int idim=0; idim<3; ++idim)
521 xx(idim) += belem->point(inode)(idim) * basis[inode][0];
525 for (
unsigned int ii=0; ii<3; ii++ ) {
526 dedge += (xnode[ii] - xx(ii))*(xnode[ii] - xx(ii));
535 std::cout <<
"My type is " << belem->type() << std::endl;
536 libmesh_not_implemented();
539 if ( dedge < distance ) distance = dedge;
libMesh::EquationSystems & _equation_systems
const libMesh::UnstructuredMesh & _boundary_mesh