MOAB: Mesh Oriented datABase  (version 5.4.1)
CachingTargetCalculator.cpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2006 Lawrence Livermore National Laboratory.  Under
00005     the terms of Contract B545069 with the University of Wisconsin --
00006     Madison, Lawrence Livermore National Laboratory retains certain
00007     rights in this software.
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Lesser General Public
00011     License as published by the Free Software Foundation; either
00012     version 2.1 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     (lgpl.txt) along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023     (2006) [email protected]
00024 
00025   ***************************************************************** */
00026 
00027 /** \file CachingTargetCalculator.cpp
00028  *  \brief
00029  *  \author Jason Kraftcheck
00030  */
00031 
00032 #include "Mesquite.hpp"
00033 #include "CachingTargetCalculator.hpp"
00034 #include "PatchData.hpp"
00035 #include "MsqMatrix.hpp"
00036 #include "ExtraData.hpp"
00037 #include "ElemSampleQM.hpp"
00038 
00039 namespace MBMesquite
00040 {
00041 
00042 CachingTargetCalculator::~CachingTargetCalculator() {}
00043 
00044 void CachingTargetCalculator::notify_new_patch( PatchData&, CachedTargetData& data )
00045 {
00046     data.clear();
00047 }
00048 
00049 void CachingTargetCalculator::notify_patch_destroyed( CachedTargetData& data )
00050 {
00051     data.clear();
00052 }
00053 
00054 void CachingTargetCalculator::notify_sub_patch( PatchData&,
00055                                                 CachedTargetData& data,
00056                                                 PatchData& subpatch,
00057                                                 const size_t*,
00058                                                 const size_t* element_map,
00059                                                 MsqError& /*err*/ )
00060 {
00061     // If no cached data for this patch, just return
00062     if( data.has_data() ) return;
00063 
00064     // Create a new cached data object on the subpatch
00065     CachedTargetData& sub_data = get_data( subpatch );
00066     sub_data.clear();
00067 
00068     // populate the element offset list, and count the total
00069     // number of cached target matrices.
00070     sub_data.elementOffsets.resize( subpatch.num_elements() );
00071     size_t count_2D = 0, count_3D = 0;
00072     for( size_t i = 0; i < subpatch.num_elements(); ++i )
00073     {
00074         EntityTopology type        = subpatch.element_by_index( i ).get_element_type();
00075         size_t& count              = ( TopologyInfo::dimension( type ) == 2 ) ? count_2D : count_3D;
00076         sub_data.elementOffsets[i] = count;
00077         NodeSet samples            = subpatch.get_samples( i );
00078         count += samples.num_nodes();
00079     }
00080 
00081     const bool orient = have_surface_orient();
00082     sub_data.targets3D.resize( count_3D );
00083     if( orient )
00084         sub_data.targetsSurface.resize( count_2D );
00085     else
00086         sub_data.targets2D.resize( count_2D );
00087 
00088     for( size_t i = 0; i < subpatch.num_elements(); ++i )
00089     {
00090         EntityTopology type = subpatch.element_by_index( i ).get_element_type();
00091         size_t off          = sub_data.elementOffsets[i];
00092         size_t old_off      = data.elementOffsets[element_map[i]];
00093         NodeSet samples     = subpatch.get_samples( i );
00094         size_t count        = samples.num_nodes();
00095 
00096         if( TopologyInfo::dimension( type ) == 3 )
00097             memcpy( &sub_data.targets3D[off], &data.targets3D[old_off], count * sizeof( MsqMatrix< 3, 3 > ) );
00098         else if( orient )
00099             memcpy( &sub_data.targetsSurface[off], &data.targetsSurface[old_off], count * sizeof( MsqMatrix< 3, 2 > ) );
00100         else
00101             memcpy( &sub_data.targets2D[off], &data.targets2D[old_off], count * sizeof( MsqMatrix< 2, 2 > ) );
00102     }
00103 }
00104 
00105 static void populate_data( PatchData& pd, CachedTargetData* data, TargetCalculator* calc, MsqError& err )
00106 {
00107     size_t i, j;
00108 
00109     const bool orient = calc->have_surface_orient();
00110     if( data->elementOffsets.empty() )
00111     {
00112         size_t count_3d = 0, count_2d = 0;
00113         data->elementOffsets.resize( pd.num_elements() );
00114         for( i = 0; i < pd.num_elements(); ++i )
00115         {
00116             EntityTopology type     = pd.element_by_index( i ).get_element_type();
00117             NodeSet sample_pts      = pd.get_samples( i );
00118             size_t& count           = ( TopologyInfo::dimension( type ) == 3 ) ? count_3d : count_2d;
00119             data->elementOffsets[i] = count;
00120             count += sample_pts.num_nodes();
00121         }
00122         data->targets3D.resize( count_3d );
00123         if( orient )
00124             data->targetsSurface.resize( count_2d );
00125         else
00126             data->targets2D.resize( count_2d );
00127     }
00128 
00129     size_t off2 = 0, off3 = 0;
00130     for( i = 0; i < pd.num_elements(); ++i )
00131     {
00132         EntityTopology type = pd.element_by_index( i ).get_element_type();
00133         NodeSet sample_pts  = pd.get_samples( i );
00134         if( TopologyInfo::dimension( type ) == 3 )
00135         {
00136             assert( off3 == data->elementOffsets[i] );
00137             for( j = 0; j < TopologyInfo::corners( type ); ++j )
00138             {
00139                 if( sample_pts.corner_node( j ) )
00140                 {
00141                     assert( off3 < data->targets3D.size() );
00142                     calc->get_3D_target( pd, i, Sample( 0, j ), data->targets3D[off3++], err );MSQ_ERRRTN( err );
00143                 }
00144             }
00145             for( j = 0; j < TopologyInfo::edges( type ); ++j )
00146             {
00147                 if( sample_pts.mid_edge_node( j ) )
00148                 {
00149                     assert( off3 < data->targets3D.size() );
00150                     calc->get_3D_target( pd, i, Sample( 1, j ), data->targets3D[off3++], err );MSQ_ERRRTN( err );
00151                 }
00152             }
00153             for( j = 0; j < TopologyInfo::faces( type ); ++j )
00154             {
00155                 if( sample_pts.mid_face_node( j ) )
00156                 {
00157                     assert( off3 < data->targets3D.size() );
00158                     calc->get_3D_target( pd, i, Sample( 2, j ), data->targets3D[off3++], err );MSQ_ERRRTN( err );
00159                 }
00160             }
00161             if( sample_pts.mid_region_node() )
00162             {
00163                 assert( off3 < data->targets3D.size() );
00164                 calc->get_3D_target( pd, i, Sample( 3, 0 ), data->targets3D[off3++], err );MSQ_ERRRTN( err );
00165             }
00166         }
00167         else if( orient )
00168         {
00169             assert( off2 == data->elementOffsets[i] );
00170             for( j = 0; j < TopologyInfo::corners( type ); ++j )
00171             {
00172                 if( sample_pts.corner_node( j ) )
00173                 {
00174                     assert( off2 < data->targetsSurface.size() );
00175                     calc->get_surface_target( pd, i, Sample( 0, j ), data->targetsSurface[off2++], err );MSQ_ERRRTN( err );
00176                 }
00177             }
00178             for( j = 0; j < TopologyInfo::edges( type ); ++j )
00179             {
00180                 if( sample_pts.mid_edge_node( j ) )
00181                 {
00182                     assert( off2 < data->targetsSurface.size() );
00183                     calc->get_surface_target( pd, i, Sample( 1, j ), data->targetsSurface[off2++], err );MSQ_ERRRTN( err );
00184                 }
00185             }
00186             if( sample_pts.mid_face_node( 0 ) )
00187             {
00188                 assert( off2 < data->targetsSurface.size() );
00189                 calc->get_surface_target( pd, i, Sample( 2, 0 ), data->targetsSurface[off2++], err );MSQ_ERRRTN( err );
00190             }
00191         }
00192         else
00193         {
00194             assert( off2 == data->elementOffsets[i] );
00195             for( j = 0; j < TopologyInfo::corners( type ); ++j )
00196             {
00197                 if( sample_pts.corner_node( j ) )
00198                 {
00199                     assert( off2 < data->targets2D.size() );
00200                     calc->get_2D_target( pd, i, Sample( 0, j ), data->targets2D[off2++], err );MSQ_ERRRTN( err );
00201                 }
00202             }
00203             for( j = 0; j < TopologyInfo::edges( type ); ++j )
00204             {
00205                 if( sample_pts.mid_edge_node( j ) )
00206                 {
00207                     assert( off2 < data->targets2D.size() );
00208                     calc->get_2D_target( pd, i, Sample( 1, j ), data->targets2D[off2++], err );MSQ_ERRRTN( err );
00209                 }
00210             }
00211             if( sample_pts.mid_face_node( 0 ) )
00212             {
00213                 assert( off2 < data->targets2D.size() );
00214                 calc->get_2D_target( pd, i, Sample( 2, 0 ), data->targets2D[off2++], err );MSQ_ERRRTN( err );
00215             }
00216         }
00217     }
00218 }
00219 
00220 bool CachingTargetCalculator::get_3D_target( PatchData& pd,
00221                                              size_t element,
00222                                              Sample sample,
00223                                              MsqMatrix< 3, 3 >& W_out,
00224                                              MsqError& err )
00225 {
00226     CachedTargetData& data = get_data( pd );
00227     if( data.targets3D.empty() )
00228     {
00229         populate_data( pd, &data, cachedCalculator, err );
00230         MSQ_ERRZERO( err );
00231     }
00232 
00233     // calculate index of sample in array
00234     NodeSet all_samples = pd.get_samples( element );
00235     unsigned offset     = all_samples.num_before( sample );
00236 
00237     W_out = data.targets3D[data.elementOffsets[element] + offset];
00238     return true;
00239 }
00240 
00241 bool CachingTargetCalculator::get_2D_target( PatchData& pd,
00242                                              size_t element,
00243                                              Sample sample,
00244                                              MsqMatrix< 2, 2 >& W_out,
00245                                              MsqError& err )
00246 {
00247     CachedTargetData& data = get_data( pd );
00248     if( data.targets2D.empty() )
00249     {
00250         if( have_surface_orient() )
00251         {
00252             MSQ_SETERR( err )( "Incorrect surface mesh target type", MsqError::INTERNAL_ERROR );
00253             return false;
00254         }
00255 
00256         populate_data( pd, &data, cachedCalculator, err );
00257         MSQ_ERRZERO( err );
00258         if( data.targets2D.empty() )
00259         {
00260             MSQ_SETERR( err )
00261             ( "Attempt to get 2D target for 3D element type", MsqError::INVALID_STATE );
00262             return false;
00263         }
00264     }
00265 
00266     // calculate index of sample in array
00267     NodeSet all_samples = pd.get_samples( element );
00268     unsigned offset     = all_samples.num_before( sample );
00269 
00270     W_out = data.targets2D[data.elementOffsets[element] + offset];
00271     return true;
00272 }
00273 
00274 bool CachingTargetCalculator::get_surface_target( PatchData& pd,
00275                                                   size_t element,
00276                                                   Sample sample,
00277                                                   MsqMatrix< 3, 2 >& W_out,
00278                                                   MsqError& err )
00279 {
00280     CachedTargetData& data = get_data( pd );
00281     if( data.targetsSurface.empty() )
00282     {
00283         if( !have_surface_orient() )
00284         {
00285             MSQ_SETERR( err )( "Incorrect surface mesh target type", MsqError::INTERNAL_ERROR );
00286             return false;
00287         }
00288 
00289         populate_data( pd, &data, cachedCalculator, err );
00290         MSQ_ERRZERO( err );
00291         if( data.targetsSurface.empty() )
00292         {
00293             MSQ_SETERR( err )
00294             ( "Attempt to get 2D target for 3D element type", MsqError::INVALID_STATE );
00295             return false;
00296         }
00297     }
00298 
00299     // calculate index of sample in array
00300     NodeSet all_samples = pd.get_samples( element );
00301     unsigned offset     = all_samples.num_before( sample );
00302 
00303     W_out = data.targetsSurface[data.elementOffsets[element] + offset];
00304     return true;
00305 }
00306 
00307 }  // namespace MBMesquite
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines