1 /* *****************************************************************
2 MESQUITE -- The Mesh Quality Improvement Toolkit
3
4 Copyright 2006 Lawrence Livermore National Laboratory. Under
5 the terms of Contract B545069 with the University of Wisconsin --
6 Madison, Lawrence Livermore National Laboratory retains certain
7 rights in this software.
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 (lgpl.txt) along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 (2006) kraftche@cae.wisc.edu
24
25 ***************************************************************** */
26
27
28 /** \file CachingTargetTest.cpp
29 * \brief Unit tests for CachingTargetCalculator class
30 * \author Jason Kraftcheck
31 */
32
33 #include "Mesquite.hpp"
34 #include "CachingTargetCalculator.hpp"
35 #include "PatchData.hpp"
36 #include "UnitUtil.hpp"
37 #include "PatchDataInstances.hpp"
38 #include <cppunit/extensions/HelperMacros.h>
39 #include <algorithm>
40
41 using namespace MBMesquite;
42
43 class CachedTargetCalculator;
44
45 class CachingTargetTest : public CppUnit::TestFixture
46 {
47 private:
48 CPPUNIT_TEST_SUITE(CachingTargetTest);
49 CPPUNIT_TEST (test_surface_orient_flag);
50 CPPUNIT_TEST (test_3d_targets_cached);
51 CPPUNIT_TEST (test_2d_targets_cached);
52 CPPUNIT_TEST (test_surface_targets_cached);
53 CPPUNIT_TEST (test_3d_target_values);
54 CPPUNIT_TEST (test_2d_target_values);
55 CPPUNIT_TEST (test_surface_target_values);
56 CPPUNIT_TEST (test_3d_target_subpatch);
57 CPPUNIT_TEST (test_2d_target_subpatch);
58 CPPUNIT_TEST (test_surface_target_subpatch);
59 CPPUNIT_TEST (test_cache_cleared);
60 CPPUNIT_TEST_SUITE_END();
61
62 PatchData patch_3d, patch_2d;
63 CachedTargetCalculator* cached;
64 CachingTargetCalculator* cacher;
65
66 unsigned request_all_targets_3d();
67 unsigned request_all_targets_2d();
68 unsigned request_all_targets_surf();
69
70 public:
71
72 void setUp();
73 void tearDown();
74
75 void test_surface_orient_flag();
76 void test_3d_targets_cached();
77 void test_2d_targets_cached();
78 void test_surface_targets_cached();
79 void test_3d_target_values();
80 void test_2d_target_values();
81 void test_surface_target_values();
82 void test_3d_target_subpatch();
83 void test_2d_target_subpatch();
84 void test_surface_target_subpatch();
85 void test_cache_cleared();
86
87 };
88
89 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CachingTargetTest, "CachingTargetTest");
90 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CachingTargetTest, "Unit");
91
92 class CachedTargetCalculator : public TargetCalculator
93 {
94 private:
95 unsigned called_3d, called_2d, called_surf;
96 bool surfOrientFlag;
97
98 public:
99
100 static MsqMatrix<3,3> make_3d( size_t elem, Sample sample );
101 static MsqMatrix<2,2> make_2d( size_t elem, Sample sample );
102 static MsqMatrix<3,2> make_surf( size_t elem, Sample sample );
103
CachedTargetCalculator()104 CachedTargetCalculator()
105 : called_3d(0), called_2d(0), called_surf(0), surfOrientFlag(true) {}
106
get_3D_target(PatchData &,size_t elem,Sample sample,MsqMatrix<3,3> & result,MsqError &)107 virtual bool get_3D_target( PatchData&, size_t elem, Sample sample, MsqMatrix<3,3>& result, MsqError& )
108 { ++called_3d; result = make_3d( elem, sample); return true; }
109
get_2D_target(PatchData &,size_t elem,Sample sample,MsqMatrix<2,2> & result,MsqError &)110 virtual bool get_2D_target( PatchData&, size_t elem, Sample sample, MsqMatrix<2,2>& result, MsqError& )
111 { ++called_2d; result = make_2d( elem, sample); return true; }
112
get_surface_target(PatchData &,size_t elem,Sample sample,MsqMatrix<3,2> & result,MsqError &)113 virtual bool get_surface_target( PatchData&, size_t elem, Sample sample, MsqMatrix<3,2>& result, MsqError& )
114 { ++called_surf; result = make_surf( elem, sample); return true; }
115
clear()116 void clear()
117 { called_3d = 0; called_2d = 0; called_surf = 0; }
118
calls_3d() const119 unsigned calls_3d() const
120 { return called_3d; }
121
calls_2d() const122 unsigned calls_2d() const
123 { return called_2d; }
124
calls_surf() const125 unsigned calls_surf() const
126 { return called_surf; }
127
surf_orient(bool value)128 void surf_orient( bool value )
129 { surfOrientFlag = value; }
130
have_surface_orient() const131 virtual bool have_surface_orient() const
132 { return surfOrientFlag; }
133 };
134
make_3d(size_t elem,Sample sample)135 MsqMatrix<3,3> CachedTargetCalculator::make_3d( size_t elem, Sample sample )
136 {
137 double v = 100. * elem + 4 * sample.number + sample.dimension + 1;
138 const double values[] = { v, 0, 0,
139 0, v, 0,
140 0, 0, 1/v };
141 return MsqMatrix<3,3>(values);
142 }
143
make_2d(size_t elem,Sample sample)144 MsqMatrix<2,2> CachedTargetCalculator::make_2d( size_t elem, Sample sample )
145 {
146 double v = 100. * elem + 4 * sample.number + sample.dimension + 1;
147 const double values[] = { v, 0,
148 0, 1/v };
149 return MsqMatrix<2,2>(values);
150 }
151
make_surf(size_t elem,Sample sample)152 MsqMatrix<3,2> CachedTargetCalculator::make_surf( size_t elem, Sample sample )
153 {
154 double v = 100. * elem + 4 * sample.number + sample.dimension + 1;
155 const double values[] = { v, 0,
156 0, v,
157 0.5*v, 0.5*v };
158 return MsqMatrix<3,2>(values);
159 }
160
setUp()161 void CachingTargetTest::setUp()
162 {
163 // make sure these are null so that if we fail within setUp,
164 // tearDown doesn't try to delete stale pointers
165 cached = 0;
166 cacher = 0;
167
168 MsqError err;
169 create_four_quads_patch( patch_2d, err ); CPPUNIT_ASSERT(!err);
170 create_qm_two_hex_patch( patch_3d, err ); CPPUNIT_ASSERT(!err);
171
172 cached = new CachedTargetCalculator( );
173 cacher = new CachingTargetCalculator( cached );
174 }
175
request_all_targets_3d()176 unsigned CachingTargetTest::request_all_targets_3d()
177 {
178 unsigned total = 0;
179 MsqMatrix<3,3> W;
180 MsqPrintError err(std::cout);
181 std::vector<Sample> locations;
182
183 for (size_t i = 0; i < patch_3d.num_elements(); ++i)
184 {
185 patch_3d.get_samples( i, locations, err ); ASSERT_NO_ERROR(err);
186 total += locations.size();
187 for (unsigned j = 0; j < locations.size(); ++j)
188 {
189 bool rval = cacher->get_3D_target( patch_3d, i, locations[j], W, err );
190 CPPUNIT_ASSERT(rval);
191 CPPUNIT_ASSERT(!err);
192 }
193 }
194 return total;
195 }
196
request_all_targets_2d()197 unsigned CachingTargetTest::request_all_targets_2d()
198 {
199 unsigned total = 0;
200 MsqMatrix<2,2> W;
201 MsqPrintError err(std::cout);
202 std::vector<Sample> locations;
203
204 for (size_t i = 0; i < patch_2d.num_elements(); ++i)
205 {
206 patch_2d.get_samples( i, locations, err ); ASSERT_NO_ERROR(err);
207 total += locations.size();
208 for (unsigned j = 0; j < locations.size(); ++j)
209 {
210 bool rval = cacher->get_2D_target( patch_2d, i, locations[j], W, err );
211 CPPUNIT_ASSERT(rval);
212 CPPUNIT_ASSERT(!err);
213 }
214 }
215 return total;
216 }
217
request_all_targets_surf()218 unsigned CachingTargetTest::request_all_targets_surf()
219 {
220 unsigned total = 0;
221 MsqMatrix<3,2> W;
222 MsqPrintError err(std::cout);
223 std::vector<Sample> locations;
224
225 for (size_t i = 0; i < patch_2d.num_elements(); ++i)
226 {
227 patch_2d.get_samples( i, locations, err ); ASSERT_NO_ERROR(err);
228 total += locations.size();
229 for (unsigned j = 0; j < locations.size(); ++j)
230 {
231 bool rval = cacher->get_surface_target( patch_2d, i, locations[j], W, err );
232 CPPUNIT_ASSERT(rval);
233 CPPUNIT_ASSERT(!err);
234 }
235 }
236 return total;
237 }
238
tearDown()239 void CachingTargetTest::tearDown()
240 {
241 delete cacher;
242 delete cached;
243 }
244
test_surface_orient_flag()245 void CachingTargetTest::test_surface_orient_flag()
246 {
247 cached->surf_orient(true);
248 CPPUNIT_ASSERT( cacher->have_surface_orient() );
249 cached->surf_orient(false);
250 CPPUNIT_ASSERT( !cacher->have_surface_orient() );
251 }
252
test_3d_targets_cached()253 void CachingTargetTest::test_3d_targets_cached()
254 {
255 CPPUNIT_ASSERT_EQUAL( cached->calls_3d(), 0u );
256 CPPUNIT_ASSERT_EQUAL( cached->calls_surf(), 0u );
257 CPPUNIT_ASSERT_EQUAL( cached->calls_2d(), 0u );
258 unsigned count = request_all_targets_3d();
259 CPPUNIT_ASSERT_EQUAL( cached->calls_3d(), count );
260 CPPUNIT_ASSERT_EQUAL( cached->calls_surf(), 0u );
261 CPPUNIT_ASSERT_EQUAL( cached->calls_2d(), 0u );
262 cached->clear();
263 request_all_targets_3d();
264 CPPUNIT_ASSERT_EQUAL( cached->calls_3d(), 0u );
265 }
266
test_2d_targets_cached()267 void CachingTargetTest::test_2d_targets_cached()
268 {
269 cached->surf_orient(false);
270 CPPUNIT_ASSERT_EQUAL( cached->calls_2d(), 0u );
271 CPPUNIT_ASSERT_EQUAL( cached->calls_surf(), 0u );
272 CPPUNIT_ASSERT_EQUAL( cached->calls_3d(), 0u );
273 unsigned count = request_all_targets_2d();
274 CPPUNIT_ASSERT_EQUAL( cached->calls_2d(), count );
275 CPPUNIT_ASSERT_EQUAL( cached->calls_surf(), 0u );
276 CPPUNIT_ASSERT_EQUAL( cached->calls_3d(), 0u );
277 cached->clear();
278 request_all_targets_2d();
279 CPPUNIT_ASSERT_EQUAL( cached->calls_2d(), 0u );
280 }
281
test_surface_targets_cached()282 void CachingTargetTest::test_surface_targets_cached()
283 {
284 cached->surf_orient(true);
285 CPPUNIT_ASSERT_EQUAL( cached->calls_2d(), 0u );
286 CPPUNIT_ASSERT_EQUAL( cached->calls_surf(), 0u );
287 CPPUNIT_ASSERT_EQUAL( cached->calls_3d(), 0u );
288 unsigned count = request_all_targets_surf();
289 CPPUNIT_ASSERT_EQUAL( cached->calls_2d(), 0u );
290 CPPUNIT_ASSERT_EQUAL( cached->calls_surf(), count );
291 CPPUNIT_ASSERT_EQUAL( cached->calls_3d(), 0u );
292 cached->clear();
293 request_all_targets_surf();
294 CPPUNIT_ASSERT_EQUAL( cached->calls_surf(), 0u );
295 }
296
test_3d_target_values()297 void CachingTargetTest::test_3d_target_values()
298 {
299 MsqPrintError err(std::cout);
300 std::vector<Sample> locations;
301
302 // evaluate all once to make sure we test the cached values
303 request_all_targets_3d();
304
305 // test each value
306 for (size_t i = 0; i < patch_3d.num_elements(); ++i)
307 {
308 patch_3d.get_samples( i, locations, err ); ASSERT_NO_ERROR(err);
309 for (unsigned j = 0; j < locations.size(); ++j)
310 {
311 MsqMatrix<3,3> W;
312 bool rval = cacher->get_3D_target( patch_3d, i, locations[j], W, err );
313 CPPUNIT_ASSERT(rval && !err);
314
315 MsqMatrix<3,3> M = CachedTargetCalculator::make_3d( i, locations[j] );
316 ASSERT_MATRICES_EQUAL( W, M, DBL_EPSILON );
317 }
318 }
319 }
320
test_2d_target_values()321 void CachingTargetTest::test_2d_target_values()
322 {
323 MsqPrintError err(std::cout);
324 std::vector<Sample> locations;
325
326 // evaluate all once to make sure we test the cached values
327 cached->surf_orient(false);
328 request_all_targets_2d();
329
330 // test each value
331 for (size_t i = 0; i < patch_2d.num_elements(); ++i)
332 {
333 patch_2d.get_samples( i, locations, err ); ASSERT_NO_ERROR(err);
334 for (unsigned j = 0; j < locations.size(); ++j)
335 {
336 MsqMatrix<2,2> W;
337 bool rval = cacher->get_2D_target( patch_2d, i, locations[j], W, err );
338 CPPUNIT_ASSERT(rval && !err);
339
340 MsqMatrix<2,2> M = CachedTargetCalculator::make_2d( i, locations[j] );
341 ASSERT_MATRICES_EQUAL( W, M, DBL_EPSILON );
342 }
343 }
344 }
345
test_surface_target_values()346 void CachingTargetTest::test_surface_target_values()
347 {
348 MsqPrintError err(std::cout);
349 std::vector<Sample> locations;
350
351 // evaluate all once to make sure we test the cached values
352 cached->surf_orient(true);
353 request_all_targets_surf();
354
355 // test each value
356 for (size_t i = 0; i < patch_2d.num_elements(); ++i)
357 {
358 patch_2d.get_samples( i, locations, err ); ASSERT_NO_ERROR(err);
359 for (unsigned j = 0; j < locations.size(); ++j)
360 {
361 MsqMatrix<3,2> W;
362 bool rval = cacher->get_surface_target( patch_2d, i, locations[j], W, err );
363 CPPUNIT_ASSERT(rval && !err);
364
365 MsqMatrix<3,2> M = CachedTargetCalculator::make_surf( i, locations[j] );
366 ASSERT_MATRICES_EQUAL( W, M, DBL_EPSILON );
367 }
368 }
369 }
370
test_3d_target_subpatch()371 void CachingTargetTest::test_3d_target_subpatch()
372 {
373 MsqPrintError err(std::cout);
374 std::vector<Sample> locations;
375
376 // cache some values on the main patch
377 request_all_targets_3d();
378
379 // clear the count so we know if any additional
380 // evalutions of the base target calculator are
381 // done during subpatch creation.
382 cached->clear();
383
384 // create a sub-patch
385 CPPUNIT_ASSERT( patch_3d.num_nodes() > 1 );
386 PatchData subpatch;
387 patch_3d.get_subpatch( 1, 1, subpatch, err );
388 CPPUNIT_ASSERT( !err );
389
390 // make sure we copied the cached values onto the subpatch
391 CPPUNIT_ASSERT_EQUAL( cached->calls_3d(), 0u );
392
393 // Test the values for each cached matrix on the subpatch
394 // NOTE: This test takes advantange of the fact that the
395 // "handles" in the subpatch are indices into the main patch.
396
397 // test each value
398 for (size_t i = 0; i < subpatch.num_elements(); ++i)
399 {
400 subpatch.get_samples( i, locations, err ); ASSERT_NO_ERROR(err);
401 for (unsigned j = 0; j < locations.size(); ++j)
402 {
403 MsqMatrix<3,3> W;
404 bool rval = cacher->get_3D_target( subpatch, i, locations[j], W, err );
405 CPPUNIT_ASSERT(rval && !err);
406
407 Mesh::ElementHandle h = subpatch.get_element_handles_array()[i];
408 Mesh::ElementHandle* old_h = patch_3d.get_element_handles_array();
409 size_t old_idx = std::find( old_h, old_h + patch_3d.num_elements(), h ) - old_h;
410 CPPUNIT_ASSERT(old_idx < patch_3d.num_elements());
411 MsqMatrix<3,3> M = CachedTargetCalculator::make_3d( old_idx, locations[j]);
412 ASSERT_MATRICES_EQUAL( W, M, DBL_EPSILON );
413 }
414 }
415 }
416
test_2d_target_subpatch()417 void CachingTargetTest::test_2d_target_subpatch()
418 {
419 MsqPrintError err(std::cout);
420 std::vector<Sample> locations;
421
422 // cache some values on the main patch
423 cached->surf_orient(false);
424 request_all_targets_2d();
425
426 // clear the count so we know if any additional
427 // evalutions of the base target calculator are
428 // done during subpatch creation.
429 cached->clear();
430
431 // create a sub-patch
432 CPPUNIT_ASSERT( patch_2d.num_nodes() > 1 );
433 PatchData subpatch;
434 patch_2d.get_subpatch( 1, 1, subpatch, err );
435 CPPUNIT_ASSERT( !err );
436
437 // make sure we copied the cached values onto the subpatch
438 CPPUNIT_ASSERT_EQUAL( cached->calls_2d(), 0u );
439
440 // Test the values for each cached matrix on the subpatch
441 // NOTE: This test takes advantange of the fact that the
442 // "handles" in the subpatch are indices into the main patch.
443
444 // test each value
445 for (size_t i = 0; i < subpatch.num_elements(); ++i)
446 {
447 subpatch.get_samples( i, locations, err ); ASSERT_NO_ERROR(err);
448 for (unsigned j = 0; j < locations.size(); ++j)
449 {
450 MsqMatrix<2,2> W;
451 bool rval = cacher->get_2D_target( subpatch, i, locations[j], W, err );
452 CPPUNIT_ASSERT(rval && !err);
453
454 Mesh::ElementHandle h = subpatch.get_element_handles_array()[i];
455 Mesh::ElementHandle* old_h = patch_2d.get_element_handles_array();
456 size_t old_idx = std::find( old_h, old_h + patch_2d.num_elements(), h ) - old_h;
457 CPPUNIT_ASSERT(old_idx < patch_2d.num_elements());
458 MsqMatrix<2,2> M = CachedTargetCalculator::make_2d( old_idx, locations[j] );
459 ASSERT_MATRICES_EQUAL( W, M, DBL_EPSILON );
460 }
461 }
462 }
463
test_surface_target_subpatch()464 void CachingTargetTest::test_surface_target_subpatch()
465 {
466 MsqPrintError err(std::cout);
467 std::vector<Sample> locations;
468
469 // cache some values on the main patch
470 cached->surf_orient(true);
471 request_all_targets_surf();
472
473 // clear the count so we know if any additional
474 // evalutions of the base target calculator are
475 // done during subpatch creation.
476 cached->clear();
477
478 // create a sub-patch
479 CPPUNIT_ASSERT( patch_2d.num_nodes() > 1 );
480 PatchData subpatch;
481 patch_2d.get_subpatch( 1, 1, subpatch, err );
482 CPPUNIT_ASSERT( !err );
483
484 // make sure we copied the cached values onto the subpatch
485 CPPUNIT_ASSERT_EQUAL( cached->calls_2d(), 0u );
486
487 // Test the values for each cached matrix on the subpatch
488 // NOTE: This test takes advantange of the fact that the
489 // "handles" in the subpatch are indices into the main patch.
490
491 // test each value
492 for (size_t i = 0; i < subpatch.num_elements(); ++i)
493 {
494 subpatch.get_samples( i, locations, err ); ASSERT_NO_ERROR(err);
495 for (unsigned j = 0; j < locations.size(); ++j)
496 {
497 MsqMatrix<3,2> W;
498 bool rval = cacher->get_surface_target( subpatch, i, locations[j], W, err );
499 CPPUNIT_ASSERT(rval && !err);
500
501 Mesh::ElementHandle h = subpatch.get_element_handles_array()[i];
502 Mesh::ElementHandle* old_h = patch_2d.get_element_handles_array();
503 size_t old_idx = std::find( old_h, old_h + patch_2d.num_elements(), h ) - old_h;
504 CPPUNIT_ASSERT(old_idx < patch_2d.num_elements());
505 MsqMatrix<3,2> M = CachedTargetCalculator::make_surf( old_idx, locations[j] );
506 ASSERT_MATRICES_EQUAL( W, M, DBL_EPSILON );
507 }
508 }
509 }
510
test_cache_cleared()511 void CachingTargetTest::test_cache_cleared()
512 {
513 MsqPrintError err(std::cout);
514
515 // cache some values on the main patch
516 request_all_targets_3d();
517
518 // clear the count so we know if any additional
519 // evalutions of the base target calculator are
520 // done.
521 cached->clear();
522
523 // now re-create the patch, which should result in the
524 // cached data being notified that the mesh has changed
525 create_twelve_hex_patch( patch_3d, err );
526 CPPUNIT_ASSERT(!err);
527
528 // now get cached values for each element
529 unsigned count = request_all_targets_3d();
530
531 // and check that they were all re-calculated
532 CPPUNIT_ASSERT_EQUAL( cached->calls_3d(), count );
533 }
534
535
536