MOAB: Mesh Oriented datABase  (version 5.4.1)
MBMesquite::SlaveBoundaryVertices Class Reference

Utility to set slaved vs. non-slaved vertices. More...

#include <SlaveBoundaryVertices.hpp>

+ Inheritance diagram for MBMesquite::SlaveBoundaryVertices:
+ Collaboration diagram for MBMesquite::SlaveBoundaryVertices:

Public Member Functions

 SlaveBoundaryVertices (unsigned depth, unsigned max_boundary_domain_dimension=4)
 Define defintion of boundary as either the distance from a fixed vertex or the distance from the domain of the boundary vertices.
virtual double loop_over_mesh (MeshDomainAssoc *mesh_and_domain, const Settings *settings, MsqError &err)
virtual std::string get_name () const
 Get string name for use in diagnostic and status output.
virtual void initialize_queue (MeshDomainAssoc *mesh_and_domain, const Settings *settings, MsqError &err)
unsigned get_num_boundary_layers () const
bool boundary_is_fixed_vertices () const
bool boundary_is_mesh_domain () const
unsigned boundary_mesh_domain_dimension () const

Private Attributes

unsigned elemDepth
unsigned domainDoF

Detailed Description

Utility to set slaved vs. non-slaved vertices.

This class can be inserted in the instruction queue before any optimization to determine which higher-order nodes are slaved as a function of their distance from the bounary of the mesh.

This implementation assumes that the boundary of the mesh can be identified either by dimension of the associated geometric domain or by fixed vertices.

Definition at line 51 of file SlaveBoundaryVertices.hpp.


Constructor & Destructor Documentation

MBMesquite::SlaveBoundaryVertices::SlaveBoundaryVertices ( unsigned  depth,
unsigned  max_boundary_domain_dimension = 4 
)

Define defintion of boundary as either the distance from a fixed vertex or the distance from the domain of the boundary vertices.

If the second parameter is not specified, the boundary will be assumed to be indicated by fixed vertices. If it is specified, the boundary will be assumed to be those vertices constrained to a domain less than or equal to the specified dimension (I.e. vertices constrained such that the number of degrees of freedom in their motion is less than or equal to the specified number.)

Parameters:
depthThe number of elements inwards from the boundary for which all contained higher-order nodes will be free variables in the optimization. Any vertex for further from the boundary will be slaved. Specifying zero will result in all higher-order nodes being slaved except free nodes on the boundary.
max_boundary_domain_dimensionSpecify the definition of "boundary". If greater than or equal to 4, then the the set of all fixed vertices is assumed to be the boundary. If less than four, then all vertices constrained to a domain with the specified number of fewer degrees of freedom (constrained to a geometric entity with an equal or smaller topological dimension) will be considered to be the boundary.

Definition at line 44 of file SlaveBoundaryVertices.cpp.

: elemDepth( depth ), domainDoF( dim ) {}

Member Function Documentation

Definition at line 92 of file SlaveBoundaryVertices.hpp.

    {
        return domainDoF >= 4;
    }

Definition at line 96 of file SlaveBoundaryVertices.hpp.

    {
        return domainDoF < 4;
    }

Definition at line 100 of file SlaveBoundaryVertices.hpp.

    {
        return domainDoF;
    }
std::string MBMesquite::SlaveBoundaryVertices::get_name ( ) const [virtual]

Get string name for use in diagnostic and status output.

Implements MBMesquite::Instruction.

Definition at line 46 of file SlaveBoundaryVertices.cpp.

{
    return "SlaveBoundaryVertices";
}

Definition at line 88 of file SlaveBoundaryVertices.hpp.

    {
        return elemDepth;
    }
void MBMesquite::SlaveBoundaryVertices::initialize_queue ( MeshDomainAssoc mesh_and_domain,
const Settings settings,
MsqError err 
) [virtual]

Called for all instructions in queue before loop_over_mesh is called for any insetruction in queue. Default behavior is to do nothing.

Implements MBMesquite::Instruction.

Definition at line 196 of file SlaveBoundaryVertices.cpp.

{}
double MBMesquite::SlaveBoundaryVertices::loop_over_mesh ( MeshDomainAssoc mesh_and_domain,
const Settings settings,
MsqError err 
) [virtual]

Virtual fuction implementing primary functionaliy of instruction instance.

Implements MBMesquite::Instruction.

Definition at line 51 of file SlaveBoundaryVertices.cpp.

References MBMesquite::arrptr(), conn, corners, dim, dof(), MBMesquite::MeshDomain::domain_DoF(), domainDoF, elemDepth, MBMesquite::Mesh::elements_get_attached_vertices(), MBMesquite::Mesh::elements_get_topologies(), fixed, MBMesquite::Settings::FIXED_FLAG, MBMesquite::Mesh::get_all_elements(), MBMesquite::Mesh::get_all_vertices(), MBMesquite::MeshDomainAssoc::get_domain(), MBMesquite::Settings::get_fixed_vertex_mode(), MBMesquite::MeshDomainAssoc::get_mesh(), MBMesquite::Settings::get_slaved_ho_node_mode(), MBMesquite::MsqError::INVALID_MESH, MBMesquite::MsqError::INVALID_STATE, mesh, MBMesquite::MsqVertex::MSQ_DEPENDENT, MSQ_ERRZERO, MSQ_SETERR, MBMesquite::Settings::SLAVE_CALCULATED, MBMesquite::Mesh::vertices_get_byte(), MBMesquite::Mesh::vertices_get_fixed_flag(), and MBMesquite::Mesh::vertices_set_byte().

Referenced by SlaveBoundaryVerticesTest::test_fail_if_slaves_not_calculated(), and SlaveBoundaryVerticesTest::test_slaved_common().

{
    Mesh* mesh         = mesh_and_domain->get_mesh();
    MeshDomain* domain = mesh_and_domain->get_domain();

    if( settings->get_slaved_ho_node_mode() != Settings::SLAVE_CALCULATED )
    {
        MSQ_SETERR( err )
        ( "Request to calculate higher-order node slaved status "
          "when Settings::get_get_slaved_ho_node_mode() "
          "!= SLAVE_CALCUALTED",
          MsqError::INVALID_STATE );
        return 0.0;
    }

    // If user said that we should treat fixed vertices as the
    // boundary, but specified that fixed vertices are defined
    // by the dimension of their geometric domain, then just
    // do distance from the geometric domain.
    int dim = this->domainDoF;
    if( dim >= 4 && settings->get_fixed_vertex_mode() != Settings::FIXED_FLAG ) dim = settings->get_fixed_vertex_mode();

    // Create a map to contain vertex depth.  Intiliaze all to
    // elemDepth+1.
    std::vector< Mesh::VertexHandle > vertices;
    mesh->get_all_vertices( vertices, err );
    MSQ_ERRZERO( err );
    if( vertices.empty() ) return 0.0;
    std::sort( vertices.begin(), vertices.end() );
    std::vector< unsigned short > depth( vertices.size(), elemDepth + 1 );
    std::vector< bool > fixed;
    mesh->vertices_get_fixed_flag( arrptr( vertices ), fixed, vertices.size(), err );
    MSQ_ERRZERO( err );

    // Initialize map with boundary vertices.
    if( dim >= 4 )
    {
        for( size_t i = 0; i < vertices.size(); ++i )
            if( fixed[i] ) depth[i] = 0;
    }
    else
    {
        if( !domain )
        {
            MSQ_SETERR( err )
            ( "Request to calculate higher-order node slaved status "
              "by distance from bounding domain without a domain.",
              MsqError::INVALID_STATE );
            return 0.0;
        }

        std::vector< unsigned short > dof( vertices.size() );
        domain->domain_DoF( arrptr( vertices ), arrptr( dof ), vertices.size(), err );
        MSQ_ERRZERO( err );
        for( size_t i = 0; i < vertices.size(); ++i )
            if( dof[i] <= dim ) depth[i] = 0;
    }

    // Now iterate over elements repeatedly until we've found all of the
    // elements near the boundary.  This could be done much more efficiently
    // using vertex-to-element adjacencies, but it is to common for
    // applications not to implement that unless doing relaxation smoothing.
    // This is O(elemDepth * elements.size() * ln(vertices.size()));
    std::vector< Mesh::ElementHandle > elements;
    std::vector< Mesh::ElementHandle >::const_iterator j, k;
    std::vector< Mesh::VertexHandle > conn;
    std::vector< size_t > junk( 2 );
    mesh->get_all_elements( elements, err );
    MSQ_ERRZERO( err );
    if( elements.empty() ) return 0.0;
    bool some_changed;
    do
    {
        some_changed = false;
        for( j = elements.begin(); j != elements.end(); ++j )
        {
            conn.clear();
            junk.clear();
            mesh->elements_get_attached_vertices( &*j, 1, conn, junk, err );
            MSQ_ERRZERO( err );
            unsigned short elem_depth = elemDepth + 1;
            for( k = conn.begin(); k != conn.end(); ++k )
            {
                size_t i = std::lower_bound( vertices.begin(), vertices.end(), *k ) - vertices.begin();
                if( i == vertices.size() )
                {
                    MSQ_SETERR( err )
                    ( "Invalid vertex handle in element connectivity list.", MsqError::INVALID_MESH );
                    return 0.0;
                }
                if( depth[i] < elem_depth ) elem_depth = depth[i];
            }
            if( elem_depth == elemDepth + 1 ) continue;

            ++elem_depth;
            for( k = conn.begin(); k != conn.end(); ++k )
            {
                size_t i = std::lower_bound( vertices.begin(), vertices.end(), *k ) - vertices.begin();
                if( depth[i] > elem_depth )
                {
                    depth[i]     = elem_depth;
                    some_changed = true;
                }
            }
        }  // for(elements)
    } while( some_changed );

    // Now remove any corner vertices from the slaved set
    std::vector< Mesh::VertexHandle >::iterator p;
    std::vector< EntityTopology > types( elements.size() );
    mesh->elements_get_topologies( arrptr( elements ), arrptr( types ), elements.size(), err );
    MSQ_ERRZERO( err );
    for( j = elements.begin(); j != elements.end(); ++j )
    {
        const unsigned corners = TopologyInfo::corners( types[j - elements.begin()] );
        conn.clear();
        junk.clear();
        mesh->elements_get_attached_vertices( &*j, 1, conn, junk, err );
        MSQ_ERRZERO( err );
        for( unsigned i = 0; i < corners; ++i )
        {
            p                           = std::lower_bound( vertices.begin(), vertices.end(), conn[i] );
            depth[p - vertices.begin()] = 0;
        }
    }

    // Now mark all vertices *not* within specified depth as slave vertices.
    std::vector< unsigned char > bytes( vertices.size() );
    mesh->vertices_get_byte( arrptr( vertices ), arrptr( bytes ), vertices.size(), err );
    MSQ_ERRZERO( err );
    for( size_t i = 0; i < vertices.size(); ++i )
    {
        if( depth[i] <= elemDepth || fixed[i] )
            bytes[i] &= ~MsqVertex::MSQ_DEPENDENT;
        else
            bytes[i] |= MsqVertex::MSQ_DEPENDENT;
    }

    mesh->vertices_set_byte( arrptr( vertices ), arrptr( bytes ), vertices.size(), err );
    MSQ_ERRZERO( err );
    return 0.0;
}

Member Data Documentation

Definition at line 107 of file SlaveBoundaryVertices.hpp.

Referenced by loop_over_mesh().

Definition at line 106 of file SlaveBoundaryVertices.hpp.

Referenced by loop_over_mesh().

List of all members.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines