MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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