MOAB: Mesh Oriented datABase  (version 5.2.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) kraftche@cae.wisc.edu
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&, CachedTargetData& data, PatchData& subpatch, const size_t*,
00055                                                 const size_t* element_map, MsqError& /*err*/ )
00056 {
00057     // If no cached data for this patch, just return
00058     if( data.has_data() ) return;
00059 
00060     // Create a new cached data object on the subpatch
00061     CachedTargetData& sub_data = get_data( subpatch );
00062     sub_data.clear();
00063 
00064     // populate the element offset list, and count the total
00065     // number of cached target matrices.
00066     sub_data.elementOffsets.resize( subpatch.num_elements() );
00067     size_t count_2D = 0, count_3D = 0;
00068     for( size_t i = 0; i < subpatch.num_elements(); ++i )
00069     {
00070         EntityTopology type        = subpatch.element_by_index( i ).get_element_type();
00071         size_t& count              = ( TopologyInfo::dimension( type ) == 2 ) ? count_2D : count_3D;
00072         sub_data.elementOffsets[i] = count;
00073         NodeSet samples            = subpatch.get_samples( i );
00074         count += samples.num_nodes();
00075     }
00076 
00077     const bool orient = have_surface_orient();
00078     sub_data.targets3D.resize( count_3D );
00079     if( orient )
00080         sub_data.targetsSurface.resize( count_2D );
00081     else
00082         sub_data.targets2D.resize( count_2D );
00083 
00084     for( size_t i = 0; i < subpatch.num_elements(); ++i )
00085     {
00086         EntityTopology type = subpatch.element_by_index( i ).get_element_type();
00087         size_t off          = sub_data.elementOffsets[i];
00088         size_t old_off      = data.elementOffsets[element_map[i]];
00089         NodeSet samples     = subpatch.get_samples( i );
00090         size_t count        = samples.num_nodes();
00091 
00092         if( TopologyInfo::dimension( type ) == 3 )
00093             memcpy( &sub_data.targets3D[off], &data.targets3D[old_off], count * sizeof( MsqMatrix< 3, 3 > ) );
00094         else if( orient )
00095             memcpy( &sub_data.targetsSurface[off], &data.targetsSurface[old_off], count * sizeof( MsqMatrix< 3, 2 > ) );
00096         else
00097             memcpy( &sub_data.targets2D[off], &data.targets2D[old_off], count * sizeof( MsqMatrix< 2, 2 > ) );
00098     }
00099 }
00100 
00101 static void populate_data( PatchData& pd, CachedTargetData* data, TargetCalculator* calc, MsqError& err )
00102 {
00103     size_t i, j;
00104 
00105     const bool orient = calc->have_surface_orient();
00106     if( data->elementOffsets.empty() )
00107     {
00108         size_t count_3d = 0, count_2d = 0;
00109         data->elementOffsets.resize( pd.num_elements() );
00110         for( i = 0; i < pd.num_elements(); ++i )
00111         {
00112             EntityTopology type     = pd.element_by_index( i ).get_element_type();
00113             NodeSet sample_pts      = pd.get_samples( i );
00114             size_t& count           = ( TopologyInfo::dimension( type ) == 3 ) ? count_3d : count_2d;
00115             data->elementOffsets[i] = count;
00116             count += sample_pts.num_nodes();
00117         }
00118         data->targets3D.resize( count_3d );
00119         if( orient )
00120             data->targetsSurface.resize( count_2d );
00121         else
00122             data->targets2D.resize( count_2d );
00123     }
00124 
00125     size_t off2 = 0, off3 = 0;
00126     for( i = 0; i < pd.num_elements(); ++i )
00127     {
00128         EntityTopology type = pd.element_by_index( i ).get_element_type();
00129         NodeSet sample_pts  = pd.get_samples( i );
00130         if( TopologyInfo::dimension( type ) == 3 )
00131         {
00132             assert( off3 == data->elementOffsets[i] );
00133             for( j = 0; j < TopologyInfo::corners( type ); ++j )
00134             {
00135                 if( sample_pts.corner_node( j ) )
00136                 {
00137                     assert( off3 < data->targets3D.size() );
00138                     calc->get_3D_target( pd, i, Sample( 0, j ), data->targets3D[off3++], err );MSQ_ERRRTN( err );
00139                 }
00140             }
00141             for( j = 0; j < TopologyInfo::edges( type ); ++j )
00142             {
00143                 if( sample_pts.mid_edge_node( j ) )
00144                 {
00145                     assert( off3 < data->targets3D.size() );
00146                     calc->get_3D_target( pd, i, Sample( 1, j ), data->targets3D[off3++], err );MSQ_ERRRTN( err );
00147                 }
00148             }
00149             for( j = 0; j < TopologyInfo::faces( type ); ++j )
00150             {
00151                 if( sample_pts.mid_face_node( j ) )
00152                 {
00153                     assert( off3 < data->targets3D.size() );
00154                     calc->get_3D_target( pd, i, Sample( 2, j ), data->targets3D[off3++], err );MSQ_ERRRTN( err );
00155                 }
00156             }
00157             if( sample_pts.mid_region_node() )
00158             {
00159                 assert( off3 < data->targets3D.size() );
00160                 calc->get_3D_target( pd, i, Sample( 3, 0 ), data->targets3D[off3++], err );MSQ_ERRRTN( err );
00161             }
00162         }
00163         else if( orient )
00164         {
00165             assert( off2 == data->elementOffsets[i] );
00166             for( j = 0; j < TopologyInfo::corners( type ); ++j )
00167             {
00168                 if( sample_pts.corner_node( j ) )
00169                 {
00170                     assert( off2 < data->targetsSurface.size() );
00171                     calc->get_surface_target( pd, i, Sample( 0, j ), data->targetsSurface[off2++], err );MSQ_ERRRTN( err );
00172                 }
00173             }
00174             for( j = 0; j < TopologyInfo::edges( type ); ++j )
00175             {
00176                 if( sample_pts.mid_edge_node( j ) )
00177                 {
00178                     assert( off2 < data->targetsSurface.size() );
00179                     calc->get_surface_target( pd, i, Sample( 1, j ), data->targetsSurface[off2++], err );MSQ_ERRRTN( err );
00180                 }
00181             }
00182             if( sample_pts.mid_face_node( 0 ) )
00183             {
00184                 assert( off2 < data->targetsSurface.size() );
00185                 calc->get_surface_target( pd, i, Sample( 2, 0 ), data->targetsSurface[off2++], err );MSQ_ERRRTN( err );
00186             }
00187         }
00188         else
00189         {
00190             assert( off2 == data->elementOffsets[i] );
00191             for( j = 0; j < TopologyInfo::corners( type ); ++j )
00192             {
00193                 if( sample_pts.corner_node( j ) )
00194                 {
00195                     assert( off2 < data->targets2D.size() );
00196                     calc->get_2D_target( pd, i, Sample( 0, j ), data->targets2D[off2++], err );MSQ_ERRRTN( err );
00197                 }
00198             }
00199             for( j = 0; j < TopologyInfo::edges( type ); ++j )
00200             {
00201                 if( sample_pts.mid_edge_node( j ) )
00202                 {
00203                     assert( off2 < data->targets2D.size() );
00204                     calc->get_2D_target( pd, i, Sample( 1, j ), data->targets2D[off2++], err );MSQ_ERRRTN( err );
00205                 }
00206             }
00207             if( sample_pts.mid_face_node( 0 ) )
00208             {
00209                 assert( off2 < data->targets2D.size() );
00210                 calc->get_2D_target( pd, i, Sample( 2, 0 ), data->targets2D[off2++], err );MSQ_ERRRTN( err );
00211             }
00212         }
00213     }
00214 }
00215 
00216 bool CachingTargetCalculator::get_3D_target( PatchData& pd, size_t element, Sample sample, MsqMatrix< 3, 3 >& W_out,
00217                                              MsqError& err )
00218 {
00219     CachedTargetData& data = get_data( pd );
00220     if( data.targets3D.empty() )
00221     {
00222         populate_data( pd, &data, cachedCalculator, err );
00223         MSQ_ERRZERO( err );
00224     }
00225 
00226     // calculate index of sample in array
00227     NodeSet all_samples = pd.get_samples( element );
00228     unsigned offset     = all_samples.num_before( sample );
00229 
00230     W_out = data.targets3D[data.elementOffsets[element] + offset];
00231     return true;
00232 }
00233 
00234 bool CachingTargetCalculator::get_2D_target( PatchData& pd, size_t element, Sample sample, MsqMatrix< 2, 2 >& W_out,
00235                                              MsqError& err )
00236 {
00237     CachedTargetData& data = get_data( pd );
00238     if( data.targets2D.empty() )
00239     {
00240         if( have_surface_orient() )
00241         {
00242             MSQ_SETERR( err )( "Incorrect surface mesh target type", MsqError::INTERNAL_ERROR );
00243             return false;
00244         }
00245 
00246         populate_data( pd, &data, cachedCalculator, err );
00247         MSQ_ERRZERO( err );
00248         if( data.targets2D.empty() )
00249         {
00250             MSQ_SETERR( err )
00251             ( "Attempt to get 2D target for 3D element type", MsqError::INVALID_STATE );
00252             return false;
00253         }
00254     }
00255 
00256     // calculate index of sample in array
00257     NodeSet all_samples = pd.get_samples( element );
00258     unsigned offset     = all_samples.num_before( sample );
00259 
00260     W_out = data.targets2D[data.elementOffsets[element] + offset];
00261     return true;
00262 }
00263 
00264 bool CachingTargetCalculator::get_surface_target( PatchData& pd, size_t element, Sample sample,
00265                                                   MsqMatrix< 3, 2 >& W_out, MsqError& err )
00266 {
00267     CachedTargetData& data = get_data( pd );
00268     if( data.targetsSurface.empty() )
00269     {
00270         if( !have_surface_orient() )
00271         {
00272             MSQ_SETERR( err )( "Incorrect surface mesh target type", MsqError::INTERNAL_ERROR );
00273             return false;
00274         }
00275 
00276         populate_data( pd, &data, cachedCalculator, err );
00277         MSQ_ERRZERO( err );
00278         if( data.targetsSurface.empty() )
00279         {
00280             MSQ_SETERR( err )
00281             ( "Attempt to get 2D target for 3D element type", MsqError::INVALID_STATE );
00282             return false;
00283         }
00284     }
00285 
00286     // calculate index of sample in array
00287     NodeSet all_samples = pd.get_samples( element );
00288     unsigned offset     = all_samples.num_before( sample );
00289 
00290     W_out = data.targetsSurface[data.elementOffsets[element] + offset];
00291     return true;
00292 }
00293 
00294 }  // namespace MBMesquite
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines