MOAB: Mesh Oriented datABase  (version 5.2.1)
untangle.cpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2010 Sandia National Laboratories.  Developed at the
00005     University of Wisconsin--Madison under SNL contract number
00006     624796.  The U.S. Government and the University of Wisconsin
00007     retain certain rights to 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     (2010) kraftche@cae.wisc.edu
00024 
00025   ***************************************************************** */
00026 
00027 /** \file untangle.cpp
00028  *  \brief tast untangle wrapper
00029  *  \author Jason Kraftcheck
00030  */
00031 #include "TestUtil.hpp"
00032 
00033 #include "MeshImpl.hpp"
00034 #include "MsqError.hpp"
00035 #include "MsqVertex.hpp"
00036 #include "PlanarDomain.hpp"
00037 #include "UntangleWrapper.hpp"
00038 #include "QualityAssessor.hpp"
00039 
00040 #include <iostream>
00041 using std::cout;
00042 using std::endl;
00043 #include <cstdlib>
00044 
00045 using namespace MBMesquite;
00046 
00047 std::string VTK_2D_DIR = TestDir + "/2D/vtk/";
00048 
00049 // Test untangle wrapper
00050 // Assumes all meshes lie in a plane for which the normal is [0,0,1].
00051 int uwt( bool skip, UntangleWrapper::UntangleMetric metric, const char* input_file,
00052          int expected_number_of_remaining_inverted_elems, bool flip_domain = false );
00053 
00054 bool brief_output = false;
00055 bool write_output = false;
00056 double mu_sigma   = -1;
00057 double beta       = -1;
00058 
00059 void usage( const char* argv0 )
00060 {
00061     std::cerr << "Usage: " << argv0 << " [-<flags>] [-c <sigma>] [-b <beta>]" << std::endl
00062               << "       " << argv0 << " -h" << std::endl;
00063 }
00064 void help( const char* argv0 )
00065 {
00066     std::cout << "Usage: " << argv0 << " [-<flags>] [-c <sigma>] [-b <beta>]" << std::endl
00067               << "Flags: -q : brief output" << std::endl
00068               << "       -w : write result meshes" << std::endl
00069               << "       -B : skip tests using untangle beta target metric" << std::endl
00070               << "       -Z : skip tests using size untangle target metric" << std::endl
00071               << "       -P : skip tests using shapesize untangle target metric" << std::endl
00072               << "       -H : skip tests using 'tangled_horse1.vtk' as input" << std::endl
00073               << "       -Q : skip tests using 'hole_in_square_tanglap.vtk' as input" << std::endl
00074               << "       -I : skip tests using 'inverted-hole-2.vtk' as input" << std::endl
00075               << "       -S : skip tests using 'shest_grid32.vtk' as input" << std::endl
00076               << "       -c : specify sigma value for untangle metrics" << std::endl
00077               << "       -b : specify beta value for untangle beta metric" << std::endl
00078               << std::endl;
00079 }
00080 
00081 int main( int argc, char* argv[] )
00082 {
00083     bool skip_beta  = false;
00084     bool skip_size  = false;
00085     bool skip_shape = false;
00086     bool skip_horse = false;
00087     bool skip_hole  = false;
00088     bool skip_invrt = false;
00089     bool skip_shest = false;
00090     std::list< double* > expected;
00091 
00092     for( int i = 1; i < argc; ++i )
00093     {
00094         if( !expected.empty() )
00095         {
00096             char* endptr;
00097             *expected.front() = strtod( argv[i], &endptr );
00098             if( *endptr || *expected.front() <= 0 )
00099             {
00100                 std::cerr << "Expected positive number, found \"" << argv[i] << '"' << std::endl;
00101                 usage( argv[0] );
00102                 return 1;
00103             }
00104             expected.pop_front();
00105         }
00106         else if( argv[i][0] == '-' && argv[i][1] )
00107         {
00108             for( int j = 1; argv[i][j]; ++j )
00109             {
00110                 switch( argv[i][j] )
00111                 {
00112                     case 'q':
00113                         brief_output = true;
00114                         break;
00115                     case 'w':
00116                         write_output = true;
00117                         break;
00118                     case 'B':
00119                         skip_beta = true;
00120                         break;
00121                     case 'Z':
00122                         skip_size = true;
00123                         break;
00124                     case 'P':
00125                         skip_shape = true;
00126                         break;
00127                     case 'H':
00128                         skip_horse = true;
00129                         break;
00130                     case 'Q':
00131                         skip_hole = true;
00132                         break;
00133                     case 'I':
00134                         skip_invrt = true;
00135                         break;
00136                     case 'S':
00137                         skip_shest = true;
00138                         break;
00139                     case 'c':
00140                         expected.push_back( &mu_sigma );
00141                         break;
00142                     case 'b':
00143                         expected.push_back( &beta );
00144                         break;
00145                     case 'h':
00146                         help( argv[0] );
00147                         return 0;
00148                     default:
00149                         std::cerr << "Invalid flag: -" << argv[i][j] << std::endl;
00150                         usage( argv[0] );
00151                         return 1;
00152                 }
00153             }
00154         }
00155         else
00156         {
00157             std::cerr << "Unexpected argument: \"" << argv[i] << '"' << std::endl;
00158             usage( argv[0] );
00159             return 1;
00160         }
00161     }
00162 
00163     int result = 0;
00164 
00165     result += uwt( skip_beta || skip_horse, UntangleWrapper::BETA, "quads/tangled/tangled_horse1.vtk", 0 );
00166     result += uwt( skip_beta || skip_hole, UntangleWrapper::BETA, "quads/tangled/hole_in_square_tanglap.vtk", 0, true );
00167     result += uwt( skip_beta || skip_invrt, UntangleWrapper::BETA, "quads/tangled/inverted-hole-2.vtk", 0 );
00168     result += uwt( skip_beta || skip_shest, UntangleWrapper::BETA, "quads/untangled/shest_grid32.vtk", 0 );
00169 
00170     result += uwt( skip_size || skip_horse, UntangleWrapper::SIZE, "quads/tangled/tangled_horse1.vtk", 0 );
00171     result += uwt( skip_size || skip_hole, UntangleWrapper::SIZE, "quads/tangled/hole_in_square_tanglap.vtk", 6, true );
00172     result += uwt( skip_size || skip_invrt, UntangleWrapper::SIZE, "quads/tangled/inverted-hole-2.vtk", 0 );
00173     result += uwt( skip_size || skip_shest, UntangleWrapper::SIZE, "quads/untangled/shest_grid32.vtk", 0 );
00174 
00175     result += uwt( skip_shape || skip_horse, UntangleWrapper::SHAPESIZE, "quads/tangled/tangled_horse1.vtk", 0 );
00176     result +=
00177         uwt( skip_shape || skip_hole, UntangleWrapper::SHAPESIZE, "quads/tangled/hole_in_square_tanglap.vtk", 0, true );
00178     result += uwt( skip_shape || skip_invrt, UntangleWrapper::SHAPESIZE, "quads/tangled/inverted-hole-2.vtk", 8 );
00179     result += uwt( skip_shape || skip_shest, UntangleWrapper::SHAPESIZE, "quads/untangled/shest_grid32.vtk", 0 );
00180 
00181     return result;
00182 }
00183 
00184 const char* tostr( UntangleWrapper::UntangleMetric m )
00185 {
00186     static const char BETA[]      = "BETA";
00187     static const char SIZE[]      = "SIZE";
00188     static const char SHAPESIZE[] = "SHAPESIZE";
00189     switch( m )
00190     {
00191         case UntangleWrapper::BETA:
00192             return BETA;
00193         case UntangleWrapper::SIZE:
00194             return SIZE;
00195         case UntangleWrapper::SHAPESIZE:
00196             return SHAPESIZE;
00197     }
00198     return 0;
00199 }
00200 
00201 int uwt( bool skip, UntangleWrapper::UntangleMetric metric, const char* input_file_base, int expected,
00202          bool flip_domain )
00203 {
00204     if( skip ) return 0;
00205 
00206     if( !brief_output ) std::cout << std::endl << "**********************************************" << std::endl;
00207     std::cout << "Running \"" << input_file_base << "\" for " << tostr( metric ) << std::endl;
00208     if( !brief_output ) std::cout << "**********************************************" << std::endl << std::endl;
00209 
00210     // get mesh
00211     MsqError err;
00212     MeshImpl mesh;
00213     std::string input_file( VTK_2D_DIR );
00214     input_file += input_file_base;
00215     mesh.read_vtk( input_file.c_str(), err );
00216     if( err )
00217     {
00218         std::cerr << err << std::endl;
00219         std::cerr << "ERROR: " << input_file << " : failed to read file" << std::endl;
00220         return 1;
00221     }
00222     // get domain
00223     std::vector< Mesh::VertexHandle > verts;
00224     mesh.get_all_vertices( verts, err );
00225     if( err || verts.empty() ) abort();
00226     MsqVertex coords;
00227     mesh.vertices_get_coordinates( arrptr( verts ), &coords, 1, err );
00228     if( err ) abort();
00229     Vector3D norm( 0, 0, flip_domain ? -1 : 1 );
00230     PlanarDomain domain( norm, coords );
00231     // run wrapper
00232     UntangleWrapper wrapper( metric );
00233     wrapper.set_vertex_movement_limit_factor( 0.005 );
00234     double constant = ( metric == UntangleWrapper::BETA ) ? beta : mu_sigma;
00235     if( constant > 0 ) wrapper.set_metric_constant( constant );
00236     if( brief_output ) wrapper.quality_assessor().disable_printing_results();
00237     MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( &mesh, &domain );
00238     wrapper.run_instructions( &mesh_and_domain, err );
00239     if( err )
00240     {
00241         std::cerr << err << std::endl;
00242         std::cerr << "ERROR: optimization failed" << std::endl;
00243         return 1;
00244     }
00245     // write output file
00246     if( write_output )
00247     {
00248         std::string result_file( tostr( metric ) );
00249         result_file += "-";
00250         result_file += input_file_base;
00251         mesh.write_vtk( result_file.c_str(), err );
00252         if( err )
00253         {
00254             std::cerr << err << std::endl;
00255             std::cerr << "ERROR: " << result_file << " : failed to write file" << std::endl;
00256             err.clear();
00257         }
00258         else
00259         {
00260             std::cerr << "Wrote file: " << result_file << std::endl;
00261         }
00262     }
00263 
00264     // test number of inverted elements
00265     int count, junk;
00266     wrapper.quality_assessor().get_inverted_element_count( count, junk, err );
00267     if( err ) abort();
00268     if( count < expected )
00269     {
00270         std::cout << "WARNING: expected " << expected << " inverted elements but finished with only " << count
00271                   << std::endl
00272                   << "Test needs to be updated?" << std::endl
00273                   << std::endl;
00274         return 0;
00275     }
00276     else if( count == expected )
00277     {
00278         std::cout << "Completed with " << count << " inverted elements remaining" << std::endl << std::endl;
00279         return 0;
00280     }
00281     else
00282     {
00283         std::cerr << "ERROR: expected " << expected << " inverted elements but finished with " << count << std::endl
00284                   << std::endl;
00285         return 1;
00286     }
00287 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines