Exemple #1
0
int main( int argc, char* argv[] )
{
  parse_options( argv, argc );
  
  MeshImpl mesh;
  XYRectangle domain( max_x - min_x, max_y - min_y, min_x, min_y );
  MsqError err;
  
  create_input_mesh( input_x, mesh, err );
  if (MSQ_CHKERR(err)) { std::cerr << err << std::endl; return 2; }
  
  domain.setup( &mesh, err );
  if (MSQ_CHKERR(err)) { std::cerr << err << std::endl; return 2; }
  
  QualityMetric* metric = 0;
  if (mMetric == 'c')
    metric = new ConditionNumberQualityMetric;
  else
    metric = new IdealWeightInverseMeanRatio;
  
  LPtoPTemplate function( 1, metric );
  
  VertexMover* solver = 0;
  if (mSolver == 'j')
    solver = new ConjugateGradient( &function );
  else
    solver = new FeasibleNewton( &function );
    
  if (PatchSetUser* psu = dynamic_cast<PatchSetUser*>(solver)) 
    psu->use_global_patch();
  
  TerminationCriterion inner;
  inner.add_absolute_vertex_movement( 1e-4 );
  inner.write_mesh_steps( "synchronous", TerminationCriterion::GNUPLOT );
  solver->set_inner_termination_criterion( &inner );  
  
  InstructionQueue q;
  QualityAssessor qa( metric, 10 );
  q.add_quality_assessor( &qa, err );
  q.set_master_quality_improver( solver, err );
  q.add_quality_assessor( &qa, err );
  MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &domain);
  q.run_instructions( &mesh_and_domain, err );
  delete solver;
  delete metric;
  
  if (MSQ_CHKERR(err)) 
    { std::cerr << err << std::endl; return 3; }
    
  mesh.write_vtk( outputFile, err );
  if (MSQ_CHKERR(err)) 
    { std::cerr << err << std::endl; return 2; }
  
  return 0;
}
//VERTEX BOUND
void TerminationCriterionTest::test_vertex_bound()
{
  MsqPrintError err(std::cout);
  PatchData pd;
  create_twelve_hex_patch( pd, err );
  ASSERT_NO_ERROR(err);
  
    // get bounding dimension for patch
  double maxcoord = 0.0;
  for (size_t i = 0; i < pd.num_nodes(); ++i) 
    for (int d = 0; d < 3; ++d)
      if (fabs(pd.vertex_by_index(i)[d]) > maxcoord)
        maxcoord = fabs(pd.vertex_by_index(i)[d]);
    // add a little bit for rounding error
  maxcoord += 1e-5;
  
  TerminationCriterion tc;
  tc.add_bounded_vertex_movement( maxcoord );
  tc.reset_inner( pd, ofEval, err );
  ASSERT_NO_ERROR(err);
  tc.reset_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(!tc.terminate());
  
  int idx = pd.num_free_vertices() - 1;
  Vector3D pos = pd.vertex_by_index(idx);
  pos[0] = 2*maxcoord;
  pd.set_vertex_coordinates( pos, idx, err );
  ASSERT_NO_ERROR(err);
  tc.accumulate_inner( pd, 0.0, 0, err );
  ASSERT_NO_ERROR(err);
  tc.accumulate_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(tc.terminate());
}
void TerminationCriterionTest::test_number_of_iterates_outer()
{
  MsqPrintError err(std::cout);
  PatchData pd;
  const int LIMIT = 2;

  TerminationCriterion tc;
  tc.add_iteration_limit(LIMIT);
  tc.reset_outer( 0, 0, ofEval, 0, err );
  ASSERT_NO_ERROR(err);
  tc.reset_patch( pd, err );
  ASSERT_NO_ERROR(err);
  for (int i = 0; i < LIMIT; ++i) {
    CPPUNIT_ASSERT(!tc.terminate());
    CPPUNIT_ASSERT_EQUAL( i, tc.get_iteration_count() );
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR(err);
    tc.accumulate_outer( 0, 0, ofEval, 0, err );
    ASSERT_NO_ERROR(err);
  }
  CPPUNIT_ASSERT_EQUAL( 2, tc.get_iteration_count() );
  CPPUNIT_ASSERT(tc.terminate());
}
//UNTANGLED
void TerminationCriterionTest::test_untangled_mesh()
{
  MsqPrintError err(std::cout);
  PatchData pd;
  create_twelve_hex_patch( pd, err );
  ASSERT_NO_ERROR(err);
  
    // get two opposite vertices in first hexahedral element
  int vtx1 = pd.element_by_index(0).get_vertex_index_array()[0];
  int vtx2 = pd.element_by_index(0).get_vertex_index_array()[7];
  Vector3D saved_coords = pd.vertex_by_index(vtx2);
  Vector3D opposite_coords = pd.vertex_by_index(vtx1);

    // invert the element
  pd.move_vertex( 2*(opposite_coords-saved_coords), vtx2, err );
  ASSERT_NO_ERROR(err);
  int inverted, samples;
  pd.element_by_index(0).check_element_orientation( pd, inverted, samples, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(inverted > 0);
  
    // check initial termination criterion
  TerminationCriterion tc;
  tc.add_untangled_mesh();
  tc.reset_inner( pd, ofEval, err );
  ASSERT_NO_ERROR(err);
  tc.reset_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(!tc.terminate());
  
    // fix the element
  pd.set_vertex_coordinates( saved_coords, vtx2, err );
  ASSERT_NO_ERROR(err);
  pd.element_by_index(0).check_element_orientation( pd, inverted, samples, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT_EQUAL(0,inverted);
  
    // check that TC recognized untangled mesh
  tc.accumulate_inner( pd, 0.0, 0, err );
  ASSERT_NO_ERROR(err);
  tc.accumulate_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(tc.terminate());
}
      //! Constructor sets the instructions in the queue.  
      LaplacianIQ() {
         MsqError err;
         // creates a mean ratio quality metric ...
         inverseMeanRatio = new IdealWeightInverseMeanRatio(err);
     
         // creates the laplacian smoother  procedures
         lapl1 = new LaplacianSmoother(err);
         mQA = new QualityAssessor(inverseMeanRatio,QualityAssessor::MAXIMUM, err);
     
         //**************Set stopping criterion****************
         mTerm = new TerminationCriterion();
         mTerm->add_criterion_type_with_int(TerminationCriterion::NUMBER_OF_ITERATES,10,err);
 
            lapl1->set_outer_termination_criterion(mTerm);
            // sets a culling method on the first QualityImprover
            lapl1->add_culling_method(PatchData::NO_BOUNDARY_VTX);
      
            // adds 1 pass of pass1 
            this->add_quality_assessor(mQA,err); MSQ_CHKERR(err);
            this->set_master_quality_improver(lapl1, err); MSQ_CHKERR(err);
            this->add_quality_assessor(mQA,err); MSQ_CHKERR(err);
      }
Exemple #6
0
int main( int argc, char* argv[] )
{
  const char* input_file = DEFAULT_INPUT_FILE;
  const char* output_file_base = 0;
  bool expect_output_base = false;
  for (int i = 1; i < argc; ++i) {
    if (expect_output_base) {
      output_file_base = argv[i];
      expect_output_base = false;
    }
    else if (!strcmp(argv[i],"-o"))
      expect_output_base = true;
    else if (input_file != DEFAULT_INPUT_FILE)
      usage(argv[0]);
    else
      input_file = argv[i];
  }
  if (expect_output_base)
    usage(argv[0]);
  
  MsqPrintError err(std::cerr);
  SlaveBoundaryVertices slaver(1);
  TShapeNB1 tmetric;
  IdealShapeTarget target;
  TQualityMetric metric( &target, &tmetric );
  PMeanPTemplate of( 1.0, &metric );
  SteepestDescent improver( &of );
  TerminationCriterion inner;
  inner.add_absolute_vertex_movement( 1e-3 );
  improver.set_inner_termination_criterion( &inner );
  QualityAssessor assess( &metric );
  InstructionQueue q;
  q.set_master_quality_improver( &improver, err );
  q.add_quality_assessor( &assess, err );
  
  TriLagrangeShape trishape;
  QuadLagrangeShape quadshape;
  q.set_mapping_function( &trishape );
  q.set_mapping_function( &quadshape );
  
  const int NUM_MODES = 4;
  
  Settings::HigherOrderSlaveMode modes[NUM_MODES] = 
    { Settings::SLAVE_NONE, 
      Settings::SLAVE_ALL,
      Settings::SLAVE_CALCULATED,
      Settings::SLAVE_FLAG
    };
  
  std::string names[NUM_MODES] = 
    { "NONE",
      "ALL",
      "CALCULATED",
      "FLAG" };
  
  MeshImpl meshes[NUM_MODES];
  std::vector<MeshDomainAssoc> meshes_and_domains;

  bool have_slaved_flag = true;
  std::vector<bool> flag(1);
  for (int i = 0; i < NUM_MODES; ++i) {
    std::cout << std::endl
              << "-----------------------------------------------" << std::endl
              << "     Mode: " << names[i] << std::endl
              << "-----------------------------------------------" << std::endl;
    
    meshes[i].read_vtk( input_file, err );
    if (err) return 1;
  
    if (modes[i] == Settings::SLAVE_CALCULATED) {
        q.add_vertex_slaver( &slaver, err );
    }
    else if (modes[i] == Settings::SLAVE_FLAG) {
      std::vector<Mesh::VertexHandle> verts;
      meshes[i].get_all_vertices( verts, err );
      if (err) return 1;
      meshes[i].vertices_get_slaved_flag( arrptr(verts), flag, 1, err );
      if (err) {
        have_slaved_flag = false;
        std::cout << "Skipped because input file does not contain slaved attribute" << std::endl;
        err.clear();
        continue;
      }
    }

  
    if (have_slaved_flag && modes[i] == Settings::SLAVE_FLAG) {
      if (!check_no_slaved_corners( meshes[i], err ) || err)
        return 1;
      if (!check_global_patch_slaved( meshes[i], err ) || err)
        return 1;
    }

  
    PlanarDomain plane;
    plane.fit_vertices( &meshes[i], err );
    if (err) return 1;

    q.set_slaved_ho_node_mode( modes[i] );
    meshes_and_domains.push_back(MeshDomainAssoc(&meshes[i], &plane));
    q.run_instructions( &meshes_and_domains[i], err );
    if (err) return 1;

    if (modes[i] == Settings::SLAVE_CALCULATED) {
        q.remove_vertex_slaver( &slaver, err );
    }
    
    if (output_file_base) {
      tag_patch_slaved( meshes[i], modes[i], err );
      std::string name(output_file_base);
      name += "-";
      name += names[i];
      name += ".vtk";
      meshes[i].write_vtk( name.c_str(), err );
      if (err) return 1;
    }
  }
  
  int exit_code = 0;
  if (input_file == DEFAULT_INPUT_FILE) {
    for (int i = 0; i < NUM_MODES; ++i) {
      std::cout << std::endl
                << "-----------------------------------------------" << std::endl
                << "     Mode: " << names[i] << std::endl
                << "-----------------------------------------------" << std::endl;
    
      exit_code += check_slaved_coords( meshes[i], modes[i], names[i], have_slaved_flag, err );
      if (err) return 1;
    }
    
      // flags should correspond to same slaved nodes as calculated,
      // so resulting meshes should be identical.
    if (have_slaved_flag) {
      int flag_idx = std::find( modes, modes+NUM_MODES, Settings::SLAVE_FLAG ) - modes;
      int calc_idx = std::find( modes, modes+NUM_MODES, Settings::SLAVE_CALCULATED ) - modes;
      exit_code += compare_node_coords( meshes[flag_idx], meshes[calc_idx], err );
      if (err) return 1;    
    }
  }
  
  return exit_code;
}
void TerminationCriterionTest::test_quality_common( bool absolute, bool successive )
{
  MsqPrintError err(std::cout);
  PatchData pd;
  ASSERT_NO_ERROR(err);
  
  const double LIMIT = 1e-4;
  TerminationCriterion tc;
  bool (*func_ptr)(double, double, double, double);
  if (absolute) {
    if (successive) {
      tc.add_absolute_successive_improvement( LIMIT );
      func_ptr = &limit_absolute_sucessive;
    }
    else {
      tc.add_absolute_quality_improvement( LIMIT );
      func_ptr = &limit_absolute_quality;
    }
  }
  else {
    if (successive) {
      tc.add_relative_successive_improvement( LIMIT );
      func_ptr = &limit_relative_sucessive;
    }
    else {
      tc.add_relative_quality_improvement( LIMIT );
      func_ptr = &limit_relative_quality;
    }
  }

  const double INIT_VALUE = 10.0;
  objFunc.mValue = INIT_VALUE;
  tc.reset_inner( pd, ofEval, err );
  ASSERT_NO_ERROR(err);
  tc.reset_patch( pd, err );
  ASSERT_NO_ERROR(err);
  double prev = HUGE_VAL;

  while (!func_ptr(INIT_VALUE,prev,objFunc.mValue,LIMIT)) {
    CPPUNIT_ASSERT(!tc.terminate());

    prev = objFunc.mValue;
    objFunc.mValue *= 0.1;
    tc.accumulate_inner( pd, objFunc.mValue, 0, err );
    ASSERT_NO_ERROR(err);
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR(err);
  }
  
  CPPUNIT_ASSERT(tc.terminate());
}
void TerminationCriterionTest::test_gradient_common( bool absolute, bool L2 )
{
  MsqPrintError err(std::cout);
  PatchData pd;
  create_twelve_hex_patch( pd, err );
  ASSERT_NO_ERROR(err);
  
  const double LIMIT = 1e-4;
  TerminationCriterion tc;
  if (absolute) {
    if (L2)
      tc.add_absolute_gradient_L2_norm( LIMIT );
    else
      tc.add_absolute_gradient_inf_norm( LIMIT );
  }
  else {
    if (L2)
      tc.add_relative_gradient_L2_norm( LIMIT );
    else
      tc.add_relative_gradient_inf_norm( LIMIT );
  }
  
  double (*func_ptr)(const Vector3D*, int) = L2 ? &lenfunc : &maxfunc;

  double junk, value = 1; 
  objFunc.mGrad = Vector3D(value,value,value);
  tc.reset_inner( pd, ofEval, err );
  ASSERT_NO_ERROR(err);
  tc.reset_patch( pd, err );
  ASSERT_NO_ERROR(err);
  
  std::vector<Vector3D> grad;
  ofEval.evaluate( pd, junk, grad, err );
  ASSERT_NO_ERROR(err);
  
  double limit = LIMIT;
  if (!absolute) 
    limit *= func_ptr(arrptr(grad),pd.num_free_vertices());

  while (func_ptr(arrptr(grad),pd.num_free_vertices()) > limit) {
    CPPUNIT_ASSERT(!tc.terminate());

    value *= 0.1;
    objFunc.mGrad = Vector3D(value,value,value);
    ofEval.evaluate( pd, junk, grad, err );
    ASSERT_NO_ERROR(err);
 
    tc.accumulate_inner( pd, 0.0, arrptr(grad), err );
    ASSERT_NO_ERROR(err);
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR(err);
  }
  
  CPPUNIT_ASSERT(tc.terminate());
}
void TerminationCriterionTest::test_absolute_vertex_movement_edge_length()
{
  MsqPrintError err(std::cout);
  
  // define two-tet mesh where tets share a face
  double coords[] = {  0, -5, 0,
                       0,  5, 0,
                       1,  0, 0,
                       0,  0, 0,
                       0,  0, 1 };
  const unsigned long conn[] = { 4, 3, 2, 0,
                                 2, 3, 4, 1 };
  int fixed[5] = {0};
  ArrayMesh mesh( 3, 5, coords, fixed, 2, TETRAHEDRON, conn );
  
    // calculate beta 
  const double LIMIT = 1e-4; // desired absolute limit
  MeshUtil tool(&mesh);
  SimpleStats len;
  tool.edge_length_distribution( len, err );
  ASSERT_NO_ERROR(err);
  const double beta = LIMIT / (len.average() - len.standard_deviation());
  
    // initialize termination criterion
  TerminationCriterion tc;
  tc.add_absolute_vertex_movement_edge_length( beta );
  MeshDomainAssoc mesh_and_domain2 = MeshDomainAssoc(&mesh, 0);
  tc.initialize_queue( &mesh_and_domain2, 0, err ); ASSERT_NO_ERROR(err);
  
    // get a patch data
  PatchData pd;
  pd.set_mesh( &mesh );
  pd.fill_global_patch( err ); ASSERT_NO_ERROR(err);

    // test termination criteiorn
  tc.reset_inner( pd, ofEval, err );
  ASSERT_NO_ERROR(err);
  tc.reset_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(!tc.terminate());

  const double FIRST_STEP=10.0;
    // move a vertex by 10 units and check that it did not meet criterion
  pd.move_vertex( Vector3D(FIRST_STEP,0,0), 0, err );
  ASSERT_NO_ERROR(err);
  tc.accumulate_inner( pd, 0.0, 0, err );
  ASSERT_NO_ERROR(err);
  tc.accumulate_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(!tc.terminate());
  
  double test_limit = LIMIT;
    
  int idx = 0;
  for (double step = FIRST_STEP; step > test_limit; step *= 0.09) {
    idx = (idx + 1) % pd.num_free_vertices();
    pd.move_vertex( Vector3D(step,0,0), idx, err );
    ASSERT_NO_ERROR(err);
    
    tc.accumulate_inner( pd, 0.0, 0, err );
    ASSERT_NO_ERROR(err);
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR(err);
    CPPUNIT_ASSERT(!tc.terminate());
  }
  
  idx = (idx + 1) % pd.num_free_vertices();
  pd.move_vertex( Vector3D(0.5*test_limit,0,0), idx, err );
  ASSERT_NO_ERROR(err);

  tc.accumulate_inner( pd, 0.0, 0, err );
  ASSERT_NO_ERROR(err);
  tc.accumulate_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(tc.terminate());
}
void TerminationCriterionTest::test_vertex_movement_common( bool absolute )
{
  MsqPrintError err(std::cout);
  PatchData pd;
  create_twelve_hex_patch( pd, err );
  ASSERT_NO_ERROR(err);
 
  const double LIMIT = 1e-4;
  TerminationCriterion tc;
  if (absolute)
    tc.add_absolute_vertex_movement( LIMIT );
  else
    tc.add_relative_vertex_movement( LIMIT );

  tc.reset_inner( pd, ofEval, err );
  ASSERT_NO_ERROR(err);
  tc.reset_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(!tc.terminate());

  const double FIRST_STEP=10.0;
    // move a vertex by 10 units and check that it did not meet criterion
  pd.move_vertex( Vector3D(FIRST_STEP,0,0), 0, err );
  ASSERT_NO_ERROR(err);
  tc.accumulate_inner( pd, 0.0, 0, err );
  ASSERT_NO_ERROR(err);
  tc.accumulate_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(!tc.terminate());
  
  double test_limit = LIMIT;
  if (!absolute)
    test_limit *= FIRST_STEP;
    
  int idx = 0;
  for (double step = FIRST_STEP; step > test_limit; step *= 0.09) {
    idx = (idx + 1) % pd.num_free_vertices();
    pd.move_vertex( Vector3D(step,0,0), idx, err );
    ASSERT_NO_ERROR(err);
    
    tc.accumulate_inner( pd, 0.0, 0, err );
    ASSERT_NO_ERROR(err);
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR(err);
    CPPUNIT_ASSERT(!tc.terminate());
  }
  
  idx = (idx + 1) % pd.num_free_vertices();
  pd.move_vertex( Vector3D(0.5*test_limit,0,0), idx, err );
  ASSERT_NO_ERROR(err);

  tc.accumulate_inner( pd, 0.0, 0, err );
  ASSERT_NO_ERROR(err);
  tc.accumulate_patch( pd, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(tc.terminate());
}
    //CPU TIME
void TerminationCriterionTest::test_cpu_time_common( bool inner )
{
  MsqPrintError err(std::cout);
  PatchData pd;
  double LIMIT = 0.5;

  TerminationCriterion tc;
  tc.add_cpu_time(LIMIT);
  if (inner)
    tc.reset_inner( pd, ofEval, err );
  else
    tc.reset_outer( 0, 0, ofEval, 0, err );
  ASSERT_NO_ERROR(err);
  tc.reset_patch( pd, err );
  ASSERT_NO_ERROR(err);
  
  Timer timer;
  while (timer.since_birth() < 0.5*LIMIT) {
    CPPUNIT_ASSERT(!tc.terminate());
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR(err);
    if (inner)
      tc.accumulate_inner( pd, 0, 0, err );
    else
      tc.accumulate_outer( 0, 0, ofEval, 0, err );
    ASSERT_NO_ERROR(err);
  }
  
  while (timer.since_birth() < 1.1*LIMIT);

  tc.accumulate_patch( pd, err );
  ASSERT_NO_ERROR(err);
  if (inner)
    tc.accumulate_inner( pd, 0, 0, err );
  else
    tc.accumulate_outer( 0, 0, ofEval, 0, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(tc.terminate());
}
Exemple #12
0
void run_test( Grouping grouping, int of_power, Weight w, const string filename )
{
    MsqError err;

    IdentityTarget target;
    TSquared target_metric;
    AffineMapMetric qual_metric( &target, &target_metric );
    ElementPMeanP elem_metric( of_power, &qual_metric );
    QualityMetric* qm_ptr = (grouping == ELEMENT) ? (QualityMetric*)&elem_metric : (QualityMetric*)&qual_metric;

    PMeanPTemplate OF( of_power, qm_ptr );
    ConjugateGradient solver( &OF );
    TerminationCriterion tc;
    TerminationCriterion itc;
    tc.add_absolute_vertex_movement( 1e-4 );
    itc.add_iteration_limit( 2 );
#ifdef USE_GLOBAL_PATCH
    solver.use_global_patch();
    solver.set_inner_termination_criterion( &tc );
#else
    solver.use_element_on_vertex_patch();
    solver.set_inner_termination_criterion( &itc );
    solver.set_outer_termination_criterion( &tc );
#endif

    MeshImpl mesh, expected_mesh;
    mesh.read_vtk( SRCDIR "/initial.vtk", err );
    CHKERR(err)
//  expected_mesh.read_vtk( (filename + ".vtk").c_str(), err ); CHKERR(err)

    PlanarDomain plane( PlanarDomain::XY );

    MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &plane);

    MetricWeight mw( &qual_metric );
    InverseMetricWeight imw( &qual_metric );
    WeightReader reader;
    if (w == METRIC) {
        TargetWriter writer( 0, &mw );
        InstructionQueue tq;
        tq.add_target_calculator( &writer, err );
        tq.run_instructions( &mesh_and_domain, err );
        CHKERR(err);
        qual_metric.set_weight_calculator( &reader );
    }
    else if (w == INV_METRIC) {
        TargetWriter writer( 0, &imw );
        InstructionQueue tq;
        tq.add_target_calculator( &writer, err );
        tq.run_instructions( &mesh_and_domain, err );
        CHKERR(err);
        qual_metric.set_weight_calculator( &reader );
    }

    InstructionQueue q;
    q.set_master_quality_improver( &solver, err );
    q.run_instructions( &mesh_and_domain, err );
    CHKERR(err)
    /*
      vector<Mesh::VertexHandle> vemain.cpprts;
      vector<MsqVertex> mesh_coords, expected_coords;
      mesh.get_all_vertices( verts, err ); CHKERR(err)
      mesh_coords.resize(verts.size());
      mesh.vertices_get_coordinates( arrptr(verts), arrptr(mesh_coords), verts.size(), err ); CHKERR(err)
      expected_mesh.get_all_vertices( verts, err ); CHKERR(err)
      expected_coords.resize(verts.size());
      expected_mesh.vertices_get_coordinates( arrptr(verts), arrptr(expected_coords), verts.size(), err ); CHKERR(err)
      if (expected_coords.size() != mesh_coords.size()) {
        cerr << "Invlid expected mesh.  Vertex count doesn't match" << endl;
        exit(1);
      }

      unsigned error_count = 0;
      for (size_t i = 0; i < mesh_coords.size(); ++i)
        if ((expected_coords[i] - mesh_coords[i]).length_squared() > epsilon*epsilon)
          ++error_count;

      if (!error_count)
        cout << filename << " : SUCCESS" << endl;
      else
        cout << filename << " : FAILURE (" << error_count
             << " vertices differ by more than " << epsilon << ")" << endl;
    */
    if (write_results)
        mesh.write_vtk( (filename + ".results.vtk").c_str(), err );
    CHKERR(err)
}
Exemple #13
0
int main( int argc, char* argv[] )
{
  const double default_fraction = 0.05;
  const double zero = 0.0;
  int one = 1;
  CLArgs::ToggleArg allow_invalid( false );
  CLArgs::DoubleRangeArg rand_percent( default_fraction, &zero, 0 );
  CLArgs::IntRangeArg unoptimize( 0, &one, 0 );
  
  CLArgs args( "vtkrandom",
               "Randomize mesh vertex locations.",
               "Read VTK file, randomize locations of containded vertices, and re-write file." );
  args.toggle_flag( INVALID_FLAG, "Allow inverted elements in output", &allow_invalid );
  args.double_flag( PERCENT_FLAG, "fract", "Randomize fraction", &rand_percent );
  args.int_flag( UNOPTIMIZE_FLAG, "N", "Use UnOptimizer with N passes rather than Randomize", &unoptimize );
  add_domain_args( args );
  args.add_required_arg( "input_file" );
  args.add_required_arg( "output_file" );

  std::vector<std::string> files;
  if (!args.parse_options( argc, argv, files, std::cerr )) {
    args.print_usage( std::cerr );
    exit(1);
  }
  std::string input_file = files[0];
  std::string output_file = files[1];
  
  MsqError err;
  MeshImpl mesh;
  mesh.read_vtk( input_file.c_str(), err );
  if (err) {
    std::cerr << "ERROR READING FILE: " << input_file << std::endl
                    << err << std::endl;
    return 2;
  }
  MeshDomain* domain = process_domain_args( &mesh );

  TerminationCriterion tc;
  QualityAssessor qa( false );
  InstructionQueue q;
  Randomize op( rand_percent.value() );
  IdealWeightInverseMeanRatio metric;
  PMeanPTemplate of( 1, &metric );
  UnOptimizer op2( &of );
  if (unoptimize.seen()) {
    tc.add_iteration_limit( unoptimize.value() );
    op2.set_outer_termination_criterion( &tc );
    q.add_preconditioner( &op, err );
    q.set_master_quality_improver( &op2, err );
  }
  else {
    q.set_master_quality_improver( &op, err );
  }
  q.add_quality_assessor( &qa, err );
  q.run_instructions( &mesh, domain, err );
  if (err) {
    std::cerr << err << std::endl;
    return 3;
  }

  int inverted, junk;
  if (qa.get_inverted_element_count( inverted, junk, err ) && inverted ) {
    if (allow_invalid.value())
      std::cerr << "Warning: output mesh contains " << inverted << " inverted elements" << std::endl;
    else {
      std::cerr << "Error: output mesh contains " << inverted << " inverted elements" << std::endl;
      return 4;
    }
  }
  
  mesh.write_vtk( output_file.c_str(), err );
  if (err) {
    std::cerr << "ERROR WRITING FILE: " << output_file << std::endl
                    << err << std::endl;
    return 2;
  }
  
  return 0;
}