Beispiel #1
0
void TagVertexMeshTest::test_alternate_name()
{
  MsqPrintError err( std::cerr );
  Vector3D new_coords(5, 5, 5);
  MsqVertex get_coords;
  
  std::vector<Mesh::VertexHandle> vertices;
  realMesh->get_all_vertices( vertices, err );
  ASSERT_NO_ERROR(err);
  Mesh::VertexHandle vertex = vertices[0];

  realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  Vector3D orig_coords = get_coords;

    // modify a vertex in the tag interface and save it
  {
    TagVertexMesh tag_mesh( err, realMesh, false, "foobar" );
    ASSERT_NO_ERROR(err);
    tag_mesh.vertex_set_coordinates( vertex, new_coords, err );
    ASSERT_NO_ERROR(err);
  }
  
    // verify that it is modified in the new interface
  {
    TagVertexMesh tag_mesh( err, realMesh, false, "foobar" );
    ASSERT_NO_ERROR(err);
    tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err );
    ASSERT_NO_ERROR(err);
    CPPUNIT_ASSERT_VECTORS_EQUAL( new_coords, get_coords, DBL_EPSILON );
  }
}
Beispiel #2
0
void TagVertexMeshTest::test_cleanup()
{
  MsqPrintError err( std::cerr );
  Vector3D new_coords(5, 5, 5);
  MsqVertex get_coords;
  
  std::vector<Mesh::VertexHandle> vertices;
  realMesh->get_all_vertices( vertices, err );
  ASSERT_NO_ERROR(err);
  Mesh::VertexHandle vertex = vertices[0];

  realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  Vector3D orig_coords = get_coords;

    // modify a vertex in the tag interface
  {
    TagVertexMesh tag_mesh( err, realMesh, true );
    ASSERT_NO_ERROR(err);
    tag_mesh.vertex_set_coordinates( vertex, new_coords, err );
    ASSERT_NO_ERROR(err);
  }

    // check that values were cleaned up when previous instance was destroyed
  {
    TagVertexMesh tag_mesh( err, realMesh, false );
    ASSERT_NO_ERROR(err);
    tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err );
    ASSERT_NO_ERROR(err);
    CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, get_coords, DBL_EPSILON );
  }
}
void DomainClassifierTest::check_domain( DomainClassifier& domain )
{
  std::vector<Mesh::VertexHandle> vertices, cverts;
  std::vector<Mesh::ElementHandle> elements, celems;
  
    // Check that, for each entity with a domain, the 
    // DomainClassifier instance returns that domain.
    // Also, put all entities with domains into cverts and
    // celems for later.
  for (unsigned i = 0; i < myDomains.size(); ++i) {
    for (unsigned j = 0; j < myDomains[i].vertices.size(); ++j) {
      Mesh::VertexHandle v = myDomains[i].vertices[j];
      const MeshDomain* ptr = domain.find_vertex_domain( v );
      CPPUNIT_ASSERT( myDomains[i].domain == ptr );
      cverts.push_back( v );
    }
    for (unsigned k = 0; k < myDomains[i].elements.size(); ++k) {
      Mesh::ElementHandle e = myDomains[i].elements[k];
      const MeshDomain* ptr = domain.find_element_domain( e );
      CPPUNIT_ASSERT( myDomains[i].domain == ptr );
      celems.push_back( e );
    }
  }
  
    // sort cverts and celems so we can do binary_search later
  std::sort( cverts.begin(), cverts.end() );
  std::sort( celems.begin(), celems.end() );
    // get all vertices and elements in mesh
  MsqPrintError err(std::cerr);
  myMesh.get_all_vertices( vertices, err );
  CPPUNIT_ASSERT(!err);
  myMesh.get_all_elements( elements, err );
  CPPUNIT_ASSERT(!err);
  
    // For each vertex not in a domain (not in cverts), make sure
    // that the domain is NULL.
  for (size_t i = 0; i < vertices.size(); ++i) {
    if (std::binary_search( cverts.begin(), cverts.end(), vertices[i] ))
      continue;
    
    const MeshDomain* ptr = domain.find_vertex_domain( vertices[i] );
    CPPUNIT_ASSERT( NULL == ptr );
  }
    // For each element not in a domain (not in celems), make sure
    // that the domain is NULL.
  for (size_t i = 0; i < elements.size(); ++i) {
    if (std::binary_search( celems.begin(), celems.end(), elements[i] ))
      continue;
    
    const MeshDomain* ptr = domain.find_element_domain( elements[i] );
    CPPUNIT_ASSERT( NULL == ptr );
  }
}
Beispiel #4
0
void get_planar_example( const char* filename,
                         DomainClassifier& geom,
                         MeshImpl& mesh,
                         MsqError& err )
{
  static PlanarDomain z(PlanarDomain::XY);
  mesh.read_vtk(filename, err); MSQ_ERRRTN(err);
  mesh.mark_skin_fixed(err); MSQ_ERRRTN(err);
  DomainClassifier::DomainSet set(&z);
  mesh.get_all_vertices( set.vertices, err ); MSQ_ERRRTN(err);
  mesh.get_all_elements( set.elements, err ); MSQ_ERRRTN(err);
  DomainClassifier::classify_by_handle( geom, &mesh, &set, 1, err ); MSQ_ERRRTN(err);
}
Beispiel #5
0
void TagVertexMeshTest::test_reference_mesh()
{
  MsqPrintError err( std::cerr );
  TagVertexMesh tag_mesh( err, realMesh, true );
  ASSERT_NO_ERROR(err);
  
  std::vector<Mesh::VertexHandle> vertices;
  realMesh->get_all_vertices( vertices, err );
  ASSERT_NO_ERROR(err);
  
    // copy real mesh coordinates into tag data in TagVertexMesh
  InstructionQueue q;
  q.add_tag_vertex_mesh( &tag_mesh, err );
  ASSERT_NO_ERROR(err);
  q.run_instructions( realMesh, err );
  ASSERT_NO_ERROR(err);
  
    // Check that initial position for vertex matches that of real mesh
  Mesh::VertexHandle vertex = vertices[0];
  MsqVertex get_coords;
  Vector3D orig_coords, real_coords, tag_coords;
  realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  orig_coords = get_coords;
  tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  tag_coords = get_coords;
  CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, tag_coords, DBL_EPSILON );
  
    // Check that modified vertex coords show up in real mesh but not
    // tag mesh.
  realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  orig_coords = get_coords;
  Vector3D new_coords(5,5,5);
  realMesh->vertex_set_coordinates( vertex, new_coords, err );
  ASSERT_NO_ERROR(err);
  tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  tag_coords = get_coords;
  CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, tag_coords, DBL_EPSILON );
    // restore realMesh to initial state
  realMesh->vertex_set_coordinates( vertex, orig_coords, err );
  ASSERT_NO_ERROR(err);
}
Beispiel #6
0
void TagVertexMeshTest::test_vertex_coordinates()
{
  MsqPrintError err( std::cerr );
  TagVertexMesh tag_mesh( err, realMesh, true );
  ASSERT_NO_ERROR(err);
  
  std::vector<Mesh::VertexHandle> vertices;
  realMesh->get_all_vertices( vertices, err );
  ASSERT_NO_ERROR(err);
  
    // Check that initial position for vertex matches that of real mesh
  Mesh::VertexHandle vertex = vertices[0];
  MsqVertex get_coords;
  Vector3D orig_coords, real_coords, tag_coords;
  realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  orig_coords = get_coords;
  tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  tag_coords = get_coords;
  CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, tag_coords, DBL_EPSILON );
  
    // Check that modified vertex coords show up in tag mesh but not
    // real mesh.
  Vector3D new_coords(5,5,5);
  tag_mesh.vertex_set_coordinates( vertex, new_coords, err );
  ASSERT_NO_ERROR(err);
  tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  tag_coords = get_coords;
  CPPUNIT_ASSERT_VECTORS_EQUAL( new_coords, tag_coords, DBL_EPSILON );
  realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err );
  ASSERT_NO_ERROR(err);
  real_coords = get_coords;
  CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, real_coords, DBL_EPSILON );
}
Beispiel #7
0
// Routine to create initial mesh for test.
// o Marks vertices at a greater topological depth than the specified
//   value as slaved.  
// o Perturbs higher-order vertices on skin towards element center
// o Marks skin vertices as fixed
int main( int argc, char* argv[] )
{
  if (argc != 4)
    usage(argv[0]);
  
  char* endptr = 0;
  const long n = strtol( argv[1], &endptr, 0 );
  if (*endptr || n < 0) 
    usage(argv[0]);
  
    // read input mesh
  MeshImpl mesh;
  MsqPrintError err(std::cerr);
  mesh.read_vtk( argv[2], err );
  if (err) return 1;
  
    // get skin vertices
  mesh.mark_skin_fixed( err, true );
  if (err) return 1;
  std::vector<Mesh::VertexHandle> verts;
  mesh.get_all_vertices( verts, err );
  if (err) return 1;
  std::vector<bool> fixed;
  mesh.vertices_get_fixed_flag( arrptr(verts), fixed, verts.size(), err );
  if (err) return 1;
  std::vector<Mesh::VertexHandle> skin;
  for (size_t i = 0; i < verts.size(); ++i)
    if (fixed[i])
      skin.push_back( verts[i] );
  
    // create map for vertex depth, and initialize to 0 for skin vertices
  std::map<Mesh::VertexHandle,int> depth;
  std::map<Mesh::VertexHandle,int>::iterator d_iter;
  for (size_t i = 0; i < skin.size(); ++i)
    depth[skin[i]] = 0;
  
    // get all elements
  std::vector<Mesh::ElementHandle> curr, next;
  std::vector<Mesh::ElementHandle> conn;
  std::vector<size_t> off;
  mesh.get_all_elements( next, err );

    // build sorted list of higher-order vertices
  std::vector<Mesh::VertexHandle> higher_order;
  for (size_t i = 0; i < next.size(); ++i) {
    Mesh::ElementHandle elem = next[i];
    conn.clear();
    mesh.elements_get_attached_vertices( &elem, 1, conn, off, err );
    if (err) return 1;
    EntityTopology type;
    mesh.elements_get_topologies( &elem, &type, 1, err );
    std::copy( conn.begin() + TopologyInfo::corners(type), conn.end(), 
               std::back_inserter( higher_order ) );
  }
  std::sort( higher_order.begin(), higher_order.end() );
  higher_order.erase( std::unique( higher_order.begin(), higher_order.end() ), 
                      higher_order.end() );

    // build depth map for all vertices
  while (!next.empty()) {
    curr.swap( next );
    next.clear();
    while (!curr.empty()) {
      Mesh::ElementHandle elem = curr.back();
      curr.pop_back();
      
      conn.clear();
      mesh.elements_get_attached_vertices( &elem, 1, conn, off, err );
      if (err) return 1;
      
      int min = std::numeric_limits<int>::max();
      for (size_t i = 0; i < conn.size(); ++i) {
        d_iter = depth.find( conn[i] );
        if (d_iter != depth.end() && d_iter->second < min)
          min = d_iter->second;
      }
      
      if (min == std::numeric_limits<int>::max()) {
        next.push_back( elem );
        continue;
      }
      
      for (size_t i = 0; i < conn.size(); ++i) {
        d_iter = depth.find( conn[i] );
      
        if (d_iter == depth.end() || d_iter->second > min+1)
          depth[conn[i]] = min+1;
      }
    }
  }
  
    // write depth map to tag for debugging purposes
  std::vector<int> depth_vals(verts.size());
  for (size_t i = 0; i < verts.size(); ++i)
    depth_vals[i] = depth[verts[i]];
  TagHandle tag = mesh.tag_create( "depth", Mesh::INT, 1, 0, err );
  if (err) return 1;
  mesh.tag_set_vertex_data( tag, verts.size(), arrptr(verts), arrptr(depth_vals), err );
  if (err) return 1;
  
  
    // set tag specifying slaved vertices
  for (size_t i = 0; i < verts.size(); ++i)
    if (std::binary_search( higher_order.begin(), higher_order.end(), verts[i] ))
      depth_vals[i] = depth[verts[i]] > n;
    else
      depth_vals[i] = 0;
  tag = mesh.tag_create( "slaved", Mesh::INT, 1, 0, err );
  if (err) return 1;
  mesh.tag_set_vertex_data( tag, verts.size(), arrptr(verts), arrptr(depth_vals), err );
  if (err) return 1;
  
    // perturb mid-edge nodes along boundary
  std::vector<MsqVertex> coords;
  for (size_t i = 0; i < skin.size(); ++i) {
    if (!std::binary_search( higher_order.begin(), higher_order.end(), skin[i]))
      continue;
  
    curr.clear();
    mesh.vertices_get_attached_elements( &skin[i], 1, curr, off, err );
    if (err) return 1;
    assert(curr.size() == 1);
    conn.clear();
    mesh.elements_get_attached_vertices( arrptr(curr), 1, conn, off, err );
    if (err) return 1;
    
    // estimate element center
    coords.resize( conn.size() );
    mesh.vertices_get_coordinates( arrptr(conn), arrptr(coords), conn.size(), err );
    if (err) return 1;
    
    Vector3D mean(0.0);
    for (size_t j = 0; j < coords.size(); ++j)
      mean += coords[j];
    mean /= coords.size();
    
    size_t idx = std::find( conn.begin(), conn.end(), skin[i] ) - conn.begin();
    assert(idx < conn.size());
    Vector3D init = coords[idx];
    Vector3D pos = (1 - PERTURB_FRACT) * init + PERTURB_FRACT * mean;
    mesh.vertex_set_coordinates( skin[i], pos, err );
    if (err) return 1;
  }
  
  mesh.write_vtk( argv[3], err );
  if (err) return 1;
  
  return 0;
}
Beispiel #8
0
int uwt( bool skip,
         UntangleWrapper::UntangleMetric metric,
         const char* input_file_base,
         int expected,
         bool flip_domain )
{
  if (skip)
    return 0;

  if (!brief_output)
    std::cout << std::endl << "**********************************************" << std::endl;
  std::cout << "Running \"" << input_file_base << "\" for " << tostr(metric) << std::endl;
  if (!brief_output)
    std::cout << "**********************************************" << std::endl << std::endl;

    // get mesh
  MsqError err;
  MeshImpl mesh;
  std::string input_file( VTK_2D_DIR );
  input_file += input_file_base;
  mesh.read_vtk( input_file.c_str(), err );
  if (err) {
    std::cerr << err << std::endl;
    std::cerr << "ERROR: " << input_file << " : failed to read file" << std::endl;
    return 1;
  }
    // get domain
  std::vector<Mesh::VertexHandle> verts;
  mesh.get_all_vertices( verts, err );
  if (err || verts.empty()) abort();
  MsqVertex coords;
  mesh.vertices_get_coordinates( arrptr(verts), &coords, 1, err );
  if (err) abort();
  Vector3D norm(0,0,flip_domain ? -1 : 1);
  PlanarDomain domain( norm, coords );
    // run wrapper
  UntangleWrapper wrapper( metric );
  wrapper.set_vertex_movement_limit_factor( 0.005 );
  double constant = (metric == UntangleWrapper::BETA) ? beta : mu_sigma;
  if (constant > 0)
    wrapper.set_metric_constant( constant );
  if (brief_output)
    wrapper.quality_assessor().disable_printing_results();
  MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &domain);
  wrapper.run_instructions( &mesh_and_domain, err );
  if (err) {
    std::cerr << err << std::endl;
    std::cerr << "ERROR: optimization failed" << std::endl;
    return 1;
  }
    // write output file
  if (write_output) {
    std::string result_file(tostr(metric));
    result_file += "-";
    result_file += input_file_base;
    mesh.write_vtk( result_file.c_str(), err );
    if (err) {
      std::cerr << err << std::endl;
      std::cerr << "ERROR: " << result_file << " : failed to write file" << std::endl;
      err.clear();
    }
    else {
      std::cerr << "Wrote file: " << result_file << std::endl;
    }
  }
  
    // test number of inverted elements
  int count, junk;
  wrapper.quality_assessor().get_inverted_element_count( count, junk, err );
  if (err) abort();
  if (count < expected) {
    std::cout << "WARNING: expected " << expected 
              << " inverted elements but finished with only " 
              << count << std::endl
              << "Test needs to be updated?" << std::endl << std::endl;
    return 0;
  }
  else if (count == expected) {
    std::cout << "Completed with " << count << " inverted elements remaining" 
              << std::endl << std::endl;
    return 0;
  }
  else {
    std::cerr << "ERROR: expected " << expected 
              << " inverted elements but finished with " 
              << count << std::endl << std::endl;
    return 1;
  }
}
Beispiel #9
0
double run( QualityMetric* metric, 
            Solver solver_type,
            const char* input_file,
            double& seconds_out,
            int& iterations_out )
{
  MsqPrintError err(cerr);
  IdealWeightInverseMeanRatio qa_metric;
  TerminationCriterion inner, outer;
  outer.add_iteration_limit( 1 );
  inner.add_absolute_vertex_movement( 1e-4 );
  inner.add_iteration_limit( 100 );
  PMeanPTemplate of( 1.0, metric );
  QualityAssessor qa( &qa_metric );
  qa.add_quality_assessment( metric );
  InstructionQueue q;
  SteepestDescent steep(&of);
  QuasiNewton quasi(&of);
  ConjugateGradient conj(&of);
  VertexMover* solver = 0;
  switch (solver_type) {
    case STEEP_DESCENT: solver = &steep; break;
    case QUASI_NEWT:solver = &quasi;break;
    case CONJ_GRAD: solver = &conj; break;
  }
  q.set_master_quality_improver( solver, err );
  q.add_quality_assessor( &qa, err );
  solver->set_inner_termination_criterion(&inner);
  solver->set_outer_termination_criterion(&outer);
  
  
  if (plot_file)
    inner.write_iterations( plot_file, err );
  
  MeshImpl mesh;
  mesh.read_vtk( input_file, err );
  if (err) {
    cerr << "Failed to read input file: \"" << input_file << '"' << endl;
    exit(1);
  }
  
  std::vector<Mesh::VertexHandle> handles;
  mesh.get_all_vertices( handles, err );
  if (handles.empty()) {
    cerr << "no veritces in mesh" << endl;
    exit(1);
  }
  std::vector<MsqVertex> coords(handles.size());
  mesh.vertices_get_coordinates( arrptr(handles), arrptr(coords), handles.size(), err );
  Vector3D min(HUGE_VAL), max(-HUGE_VAL);
  for (size_t i = 0; i < coords.size(); ++i) {
    for (int j = 0; j < 3; ++j) {
      if (coords[i][j] < min[j])
        min[j] = coords[i][j];
      if (coords[i][j] > max[j])
        max[j] = coords[i][j];
    }
  }
  
  Vector3D size = max - min;
  PlanarDomain* domain = 0;
  if (size[0] < 1e-4) 
    domain = new PlanarDomain( PlanarDomain::YZ, min[0] );
  else if (size[1] < 1e-4)
    domain = new PlanarDomain( PlanarDomain::XZ, min[1] );
  else if (size[2] < 1e-4)
    domain = new PlanarDomain( PlanarDomain::XY, min[2] );
  
  Timer timer;
  q.run_instructions( &mesh, domain, err );
  seconds_out = timer.since_birth();
  if (err) {
    cerr << "Optimization failed." << endl << err << endl;
    abort();
  }

  if (vtk_file) {
    MeshWriter::write_vtk( &mesh, vtk_file, err );
    if (err) 
      cerr << vtk_file << ": failed to write file." << endl;
  }
  if (gpt_file) {
    MeshWriter::write_gnuplot( &mesh, gpt_file, err );
    if (err) 
      cerr << gpt_file << ": failed to write file." << endl;
  }
  if (eps_file) {
    PlanarDomain xy(PlanarDomain::XY);
    MeshWriter::Projection proj( domain ? domain : &xy );
    MeshWriter::write_eps( &mesh, eps_file, proj, err );
    if (err) 
      cerr << eps_file << ": failed to write file." << endl;
  }
  delete domain;
  
  iterations_out = inner.get_iteration_count();
  
  const QualityAssessor::Assessor* a = qa.get_results( &qa_metric );
  return a->get_average();
}
void DomainClassifierTest::setUp()
{
  myMesh.clear();
  myDomains.clear();
  domainDims.clear();
    // vertex coodinates
  const char vertex_data[] =
  "POINTS 64 float\n"
  "0 0 0  1 0 0  2 0 0  3 0 0\n"
  "0 1 0  1 1 0  2 1 0  3 1 0\n"
  "0 2 0  1 2 0  2 2 0  3 2 0\n"
  "0 3 0  1 3 0  2 3 0  3 3 0\n"
  "\n"
  "0 0 1  1 0 1  2 0 1  3 0 1\n"
  "0 1 1  1 1 1  2 1 1  3 1 1\n"
  "0 2 1  1 2 1  2 2 1  3 2 1\n"
  "0 3 1  1 3 1  2 3 1  3 3 1\n"
  "\n"
  "0 0 2  1 0 2  2 0 2  3 0 2\n"
  "0 1 2  1 1 2  2 1 2  3 1 2\n"
  "0 2 2  1 2 2  2 2 2  3 2 2\n"
  "0 3 2  1 3 2  2 3 2  3 3 2\n"
  "\n"
  "0 0 3  1 0 3  2 0 3  3 0 3\n"
  "0 1 3  1 1 3  2 1 3  3 1 3\n"
  "0 2 3  1 2 3  2 2 3  3 2 3\n"
  "0 3 3  1 3 3  2 3 3  3 3 3\n"
  "\n";
    // quad connectivity for quads on mesh skin
  const int num_quads = 9*6; // nine per side
  const char quad_data[] = 
  "4  1  0  4  5\n" // -z face (z == 0)
  "4  2  1  5  6\n"
  "4  3  2  6  7\n"
  "4  5  4  8  9\n"
  "4  6  5  9 10\n"
  "4  7  6 10 11\n"
  "4  9  8 12 13\n"
  "4 10  9 13 14\n"
  "4 11 10 14 15\n" 
  "\n"
  "4 48 49 53 52\n" // +z face (z == 3)
  "4 49 50 54 53\n"
  "4 50 51 55 54\n"
  "4 52 53 57 56\n"
  "4 53 54 58 57\n"
  "4 54 55 59 58\n"
  "4 56 57 61 60\n"
  "4 57 58 62 61\n"
  "4 58 59 63 62\n" 
  "\n"
  "4  0  1 17 16\n" // -y face (y == 0)
  "4  1  2 18 17\n"
  "4  2  3 19 18\n"
  "4 16 17 33 32\n"
  "4 17 18 34 33\n"
  "4 18 19 35 34\n"
  "4 32 33 49 48\n"
  "4 33 34 50 49\n"
  "4 34 35 51 50\n"
  "\n"
  "4 13 12 28 29\n" // +y face (y == 3)
  "4 14 13 29 30\n"
  "4 15 14 30 31\n"
  "4 29 28 44 45\n"
  "4 30 29 45 46\n"
  "4 31 30 46 47\n"
  "4 45 44 60 61\n"
  "4 46 45 61 62\n"
  "4 47 46 62 63\n"
  "\n"
  "4  4  0 16 20\n" // -x face (x == 0)
  "4  8  4 20 24\n"
  "4 12  8 24 28\n"
  "4 20 16 32 36\n"
  "4 24 20 36 40\n"
  "4 28 24 40 44\n"
  "4 36 32 48 52\n"
  "4 40 36 52 56\n"
  "4 44 40 56 60\n"
  "\n"
  "4  3  7 23 19\n" // +x face (x == 3)
  "4  7 11 27 23\n"
  "4 11 15 31 27\n"
  "4 19 23 39 35\n"
  "4 23 27 43 39\n"
  "4 27 31 47 43\n"
  "4 35 39 55 51\n"
  "4 39 43 59 55\n"
  "4 43 47 63 59\n"
  "\n";
    // hexahedron connectivity
  const int num_hexes = 3*3*3;
  const char hex_data[] =
  "8  0  1  5  4 16 17 21 20\n"
  "8  1  2  6  5 17 18 22 21\n"
  "8  2  3  7  6 18 19 23 22\n"
  "8  4  5  9  8 20 21 25 24\n"
  "8  5  6 10  9 21 22 26 25\n"
  "8  6  7 11 10 22 23 27 26\n"
  "8  8  9 13 12 24 25 29 28\n"
  "8  9 10 14 13 25 26 30 29\n"
  "8 10 11 15 14 26 27 31 30\n"
  "\n"
  "8 16 17 21 20 32 33 37 36\n"
  "8 17 18 22 21 33 34 38 37\n"
  "8 18 19 23 22 34 35 39 38\n"
  "8 20 21 25 24 36 37 41 40\n"
  "8 21 22 26 25 37 38 42 41\n"
  "8 22 23 27 26 38 39 43 42\n"
  "8 24 25 29 28 40 41 45 44\n"
  "8 25 26 30 29 41 42 46 45\n"
  "8 26 27 31 30 42 43 47 46\n"
  "\n"
  "8 32 33 37 36 48 49 53 52\n"
  "8 33 34 38 37 49 50 54 53\n"
  "8 34 35 39 38 50 51 55 54\n"
  "8 36 37 41 40 52 53 57 56\n"
  "8 37 38 42 41 53 54 58 57\n"
  "8 38 39 43 42 54 55 59 58\n"
  "8 40 41 45 44 56 57 61 60\n"
  "8 41 42 46 45 57 58 62 61\n"
  "8 42 43 47 46 58 59 63 62\n"
  "\n";
    // a few interior quads
  const int num_interior_quads = 3;
  const char interior_quad_data[] = 
  "4  1  5 25 17\n"
  "4  4  5 25 24\n"
  "4 16 17 25 24\n"
  "\n";
  
  
  const char filename[] = "dctest.vtk";
  FILE* file = fopen( filename, "w" );
  fputs( "# vtk DataFile Version 2.0\n", file );
  fputs( "Mesquite Mesh\n", file );
  fputs( "ASCII\n", file );
  fputs( "DATASET UNSTRUCTURED_GRID\n", file );
  fputs( vertex_data, file );
  
  int num_elem = num_quads + num_hexes + num_interior_quads;
  int num_elem_data = 5*num_quads + 9*num_hexes * 5*num_interior_quads;
  fprintf( file, "CELLS %d %d\n", num_elem, num_elem_data );
  fputs( quad_data, file );
  fputs( hex_data, file );
  fputs( interior_quad_data, file );
  fprintf( file, "CELL_TYPES %d\n", num_elem );
  for (int i = 0; i < num_quads; ++i)
    fputs( "9\n", file );
  for (int i = 0; i < num_hexes; ++i)
    fputs( "12\n", file );
  for (int i = 0; i < num_interior_quads; ++i)
    fputs( "9\n", file );
  
  fclose( file );
  MsqPrintError err(std::cerr);
  myMesh.read_vtk( filename, err );
  remove( filename );
  CPPUNIT_ASSERT(!err);

  std::vector<Mesh::VertexHandle> verts;
  std::vector<Mesh::ElementHandle> elems;
  myMesh.get_all_vertices(verts, err);
  CPPUNIT_ASSERT(!err);
  CPPUNIT_ASSERT_EQUAL( (size_t)64, verts.size() );
  myMesh.get_all_elements(elems, err);
  CPPUNIT_ASSERT(!err);
  CPPUNIT_ASSERT_EQUAL( (size_t)num_elem, elems.size() );
  
    // define point domains
  PointDomain* pdom[8];
  pdom[0] = new PointDomain( Vector3D(0,0,0) );
  pdom[1] = new PointDomain( Vector3D(3,0,0) );
  pdom[2] = new PointDomain( Vector3D(0,3,0) );
  pdom[3] = new PointDomain( Vector3D(3,3,0) );
  pdom[4] = new PointDomain( Vector3D(0,0,3) );
  pdom[5] = new PointDomain( Vector3D(3,0,3) );
  pdom[6] = new PointDomain( Vector3D(0,3,3) );
  pdom[7] = new PointDomain( Vector3D(3,3,3) );
  size_t pdidx[8] = { 0, 3, 12, 15, 48, 51, 60, 63 };
  for (unsigned i = 0; i < 8; ++i) {
    MsqVertex coords;
    Mesh::VertexHandle h = verts[pdidx[i]];
    myMesh.vertices_get_coordinates( &h, &coords, 1, err );
    CPPUNIT_ASSERT(!err);
    CPPUNIT_ASSERT_VECTORS_EQUAL( pdom[i]->geom(), coords, 1e-6 );
    DomSet set;
    set.domain = pdom[i];
    set.vertices.push_back( h );
    myDomains.push_back( set );
    domainDims.push_back( 0 );
  }
  
    // define line domains
  LineDomain* ldom[12];
  ldom[0] = new LineDomain( Vector3D(0,0,0), Vector3D(1,0,0) ); // y=0,z=0
  ldom[1] = new LineDomain( Vector3D(0,3,0), Vector3D(1,0,0) ); // y=3,z=0
  ldom[2] = new LineDomain( Vector3D(0,0,3), Vector3D(1,0,0) ); // y=0,z=3
  ldom[3] = new LineDomain( Vector3D(0,3,3), Vector3D(1,0,0) ); // y=3,z=3
  ldom[4] = new LineDomain( Vector3D(0,0,0), Vector3D(0,1,0) ); // x=0,z=0
  ldom[5] = new LineDomain( Vector3D(3,0,0), Vector3D(0,1,0) ); // x=3,z=0
  ldom[6] = new LineDomain( Vector3D(0,0,3), Vector3D(0,1,0) ); // x=0,z=3
  ldom[7] = new LineDomain( Vector3D(3,0,3), Vector3D(0,1,0) ); // x=3,z=3
  ldom[8] = new LineDomain( Vector3D(0,0,0), Vector3D(0,0,1) ); // x=0,y=0
  ldom[9] = new LineDomain( Vector3D(3,0,0), Vector3D(0,0,1) ); // x=3,y=0
  ldom[10]= new LineDomain( Vector3D(0,3,0), Vector3D(0,0,1) ); // x=0,y=3
  ldom[11]= new LineDomain( Vector3D(3,3,0), Vector3D(0,0,1) ); // x=3,y=3
  size_t ldidx[12][2] = { {  1,  2 }, { 13, 14 }, { 49, 50 }, { 61, 62 },
                          {  4,  8 }, {  7, 11 }, { 52, 56 }, { 55, 59 },
                          { 16, 32 }, { 19, 35 }, { 28, 44 }, { 31, 47 } };
  for (unsigned i = 0; i < 12; ++i) {
    Mesh::VertexHandle v[2];
    v[0] = verts[ldidx[i][0]];
    v[1] = verts[ldidx[i][1]];
    MsqVertex coords[2];
    myMesh.vertices_get_coordinates( v, coords, 2, err );
    CPPUNIT_ASSERT(!err);
    CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, ldom[i]->geom().distance( coords[0] ), 1e-6 );
    CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, ldom[i]->geom().distance( coords[1] ), 1e-6 );
    DomSet set;
    set.domain = ldom[i];
    set.vertices.push_back(v[0]);
    set.vertices.push_back(v[1]);
    myDomains.push_back( set );
    domainDims.push_back( 1 );
  }
  
    // define planar domains
  PlanarDomain* sdom[6];
  sdom[0] = new PlanarDomain( Vector3D( 0, 0,-1), Vector3D(0,0,0) );
  sdom[1] = new PlanarDomain( Vector3D( 0, 0, 1), Vector3D(0,0,3) );
  sdom[2] = new PlanarDomain( Vector3D( 0,-1, 0), Vector3D(0,0,0) );
  sdom[3] = new PlanarDomain( Vector3D( 0, 1, 0), Vector3D(0,3,0) );
  sdom[4] = new PlanarDomain( Vector3D(-1, 0, 0), Vector3D(0,0,0) );
  sdom[5] = new PlanarDomain( Vector3D( 1, 0, 0), Vector3D(3,0,0) );
  size_t sdidx[6][4] = { {  5,  6,  9, 10 }, { 53, 54, 57, 58 },
                         { 17, 18, 33, 34 }, { 29, 30, 45, 46 },
                         { 20, 24, 36, 40 }, { 23, 27, 39, 43 } };
  for (unsigned i = 0; i < 6; ++i) {
    DomSet set;
    set.domain = sdom[i];
    for (unsigned j = 0; j < 4; ++j)
      set.vertices.push_back( verts[sdidx[i][j]] );
    for (unsigned j = 0; j < 9; ++j)
      set.elements.push_back( elems[9*i+j] );
    myDomains.push_back( set );
    domainDims.push_back( 2 );
  }
  
  
//  for (unsigned i = 0; i < myDomains.size(); ++i) 
//    print_domain( i, myDomains[i] );
}
Beispiel #11
0
void SlaveBoundaryVerticesTest::test_slaved_common( unsigned depth, unsigned boundary )
{
  MeshImpl mesh;
  DomainClassifier domain;
  make_mesh( mesh, domain, 2*depth+2 );

  MsqPrintError err(std::cerr);
  std::vector< std::vector<Mesh::VertexHandle> > depths(depth+1);
  std::set<Mesh::VertexHandle> non_slave;
  std::set<Mesh::VertexHandle>::iterator p;

    // find boundary vertices
  std::vector<Mesh::VertexHandle> verts;
  mesh.get_all_vertices( verts, err ); ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(!verts.empty());
  if (boundary >= 4) {
    std::vector<bool> flags;
    mesh.vertices_get_fixed_flag( arrptr(verts), flags, verts.size(), err );
    ASSERT_NO_ERROR(err);
    for (size_t i = 0; i < verts.size(); ++i)
      if (flags[i]) {
        depths[0].push_back( verts[i] );
        non_slave.insert( verts[i] );
      }
  }
  else {
    std::vector<unsigned short> dim(verts.size());
    domain.domain_DoF( arrptr(verts), arrptr(dim), verts.size(), err );
    ASSERT_NO_ERROR(err);
    for (size_t i = 0; i < verts.size(); ++i)
      if (dim[i] <= boundary) {
        depths[0].push_back( verts[i] );
        non_slave.insert( verts[i] );
      }
  }
  
    // check that our input is usable for this test
  CPPUNIT_ASSERT( !verts.empty() );
  
    // find all vertices up to specified depth
  for (unsigned d = 0; d < depth; ++d) {
    for (size_t i = 0; i < depths[d].size(); ++i) {
      std::vector<Mesh::ElementHandle> adj;
      std::vector<size_t> junk;
      mesh.vertices_get_attached_elements( &depths[d][i], 1, adj, junk, err );
      ASSERT_NO_ERROR(err);
      for(size_t j = 0; j < adj.size(); ++j) {
        junk.clear();
        std::vector<Mesh::VertexHandle> conn;
        mesh.elements_get_attached_vertices( &adj[j], 1, conn, junk, err );
        ASSERT_NO_ERROR(err);
        for (size_t k = 0; k < conn.size(); ++k) {
          p = non_slave.find(conn[k]);
          if (p == non_slave.end()) {
            non_slave.insert( p, conn[k] );
            depths[d+1].push_back( conn[k] );
          }
        }
      }
    }
  }
  
    // Check that our input is usable for this test:
    // Should have some vertices that are not within the specified depth of 
    // the boundary.
  CPPUNIT_ASSERT( non_slave.size() < verts.size() );
  
    // Now build a map of all higher-order nodes in the mesh
  std::set<Mesh::VertexHandle> higher_order;
  std::vector<Mesh::ElementHandle> elems;
  mesh.get_all_elements( elems, err ); 
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(!elems.empty());
  std::vector<EntityTopology> types(elems.size());
  mesh.elements_get_topologies( arrptr(elems), arrptr(types), elems.size(), err );
  ASSERT_NO_ERROR(err);
  for (size_t i = 0; i < elems.size(); ++i) {
    std::vector<Mesh::VertexHandle> conn;
    std::vector<size_t> junk;
    mesh.elements_get_attached_vertices( &elems[i], 1, conn, junk, err );
    ASSERT_NO_ERROR(err);
    for (size_t j = TopologyInfo::corners( types[i] ); j < conn.size(); ++j)
      higher_order.insert( conn[j] );
  }
  
    // Check that our input is usable for this test:
    // Should have some higher-order vertices
  CPPUNIT_ASSERT( !higher_order.empty() );
  
    // Now build a map of all fixed vertices
  std::set<Mesh::VertexHandle> fixed_vertices;
  std::vector<bool> fixed;
  mesh.vertices_get_fixed_flag( arrptr(verts), fixed, verts.size(), err );
  ASSERT_NO_ERROR(err);
  for (size_t i = 0; i < verts.size(); ++i)
    if (fixed[i])
      fixed_vertices.insert( verts[i] );

    // Now actually run the tool
  Settings settings;
  settings.set_slaved_ho_node_mode( Settings::SLAVE_CALCULATED );
  SlaveBoundaryVertices tool( depth, boundary );
  tool.loop_over_mesh( &mesh, &domain, &settings, err );
  ASSERT_NO_ERROR(err);
  
    // Now verify the results
  std::vector<unsigned char> bytes( verts.size() );
  mesh.vertices_get_byte( arrptr(verts), arrptr(bytes), verts.size(), err );
  ASSERT_NO_ERROR(err);
  for (size_t i = 0; i < verts.size(); ++i) {
    bool in_non_slave = (non_slave.find( verts[i] ) != non_slave.end());
    bool in_fixed = (fixed_vertices.find( verts[i] ) != fixed_vertices.end());
    bool in_higher_order = (higher_order.find( verts[i] ) != higher_order.end());
    if (bytes[i] & MsqVertex::MSQ_DEPENDENT) { // if slave node
        // must not be within 'depth' of boundary
      CPPUNIT_ASSERT( !in_non_slave );
        // must be a higher-order vertex
      CPPUNIT_ASSERT( in_higher_order );
        // must not be fixed
      CPPUNIT_ASSERT( !in_fixed );
    }
    else {
        // there are three reasons that a vertex isn't slaved
      bool in_non_slave = (non_slave.find( verts[i] ) != non_slave.end());
      bool in_fixed = (fixed_vertices.find( verts[i] ) != fixed_vertices.end());
      bool in_higher_order = (higher_order.find( verts[i] ) != higher_order.end());
      CPPUNIT_ASSERT( in_fixed || !in_higher_order || in_non_slave );
    }
  }
}
Beispiel #12
0
void BCDTest::compare_bcd( ObjectiveFunction* OF, string name, const char* mesh_file )
{
  MsqPrintError err(cout);
  size_t i;
  vector<MsqVertex> initial_coords, global_coords, bcd_coords;
  vector<Mesh::VertexHandle> vertex_list;
  
    // set up a smoother
  TerminationCriterion iterations, vertex_movement;
  iterations.add_iteration_limit( 2 );
  vertex_movement.add_absolute_vertex_movement( 1e-3 );

  SolverType global_solver( OF );
  SolverType bcd_solver( OF );
  global_solver.use_global_patch();
  bcd_solver.use_element_on_vertex_patch();
  bcd_solver.do_block_coordinate_descent_optimization();
  global_solver.set_inner_termination_criterion( &vertex_movement );
  bcd_solver.set_inner_termination_criterion( &iterations );
  bcd_solver.set_outer_termination_criterion( &vertex_movement );

  QualityAssessor qa;
  qa.add_quality_assessment( &mMetric );

  InstructionQueue global_q, bcd_q;
  global_q.add_quality_assessor( &qa, err );
  global_q.set_master_quality_improver( &global_solver, err );
  global_q.add_quality_assessor( &qa, err );
  bcd_q.set_master_quality_improver( &bcd_solver, err );
  bcd_q.add_quality_assessor( &qa, err );
  
    // read mesh
  MeshImpl mesh;
  mesh.read_vtk( mesh_file, err ); ASSERT_NO_ERROR(err);
  mesh.get_all_vertices( vertex_list, err ); ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT(!vertex_list.empty());
  initial_coords.resize( vertex_list.size() );
  mesh.vertices_get_coordinates( arrptr(vertex_list), arrptr(initial_coords), vertex_list.size(), err );
  ASSERT_NO_ERROR(err);
  
    // run global smoother
  global_q.run_instructions( &mesh, err ); 
  ASSERT_NO_ERROR(err);
  mesh.write_vtk( (name + "-gbl.vtk").c_str(), err );
  global_coords.resize( vertex_list.size() );
  mesh.vertices_get_coordinates( arrptr(vertex_list), arrptr(global_coords), vertex_list.size(), err );
  ASSERT_NO_ERROR(err);
  
    // restore initial vertex positions
  for (i = 0; i < vertex_list.size(); ++i) {
    mesh.vertex_set_coordinates( vertex_list[i], initial_coords[i], err );
    ASSERT_NO_ERROR(err);
  }
  
    // run local smoother
  bcd_q.run_instructions( &mesh, err );
  ASSERT_NO_ERROR(err);
  mesh.write_vtk( (name + "-bcd.vtk").c_str(), err );
  bcd_coords.resize( vertex_list.size() );
  mesh.vertices_get_coordinates( arrptr(vertex_list), arrptr(bcd_coords), vertex_list.size(), err );
  ASSERT_NO_ERROR(err);
  
    // compare results
  for (i = 0; i < bcd_coords.size(); ++i)
    CPPUNIT_ASSERT_VECTORS_EQUAL( global_coords[i], bcd_coords[i], 1e-2 );
}