int NonGradient::getPatchDimension(const PatchData &pd, MsqError &err)
{
  const size_t numElt = pd.num_elements();
  unsigned edimMax = 0;  // in case numElt == 0
  for( size_t elementId = 0; elementId < numElt; elementId++)
  {
    const MsqMeshEntity& element = pd.element_by_index( elementId );
    EntityTopology type = element.get_element_type();
    unsigned edim = TopologyInfo::dimension( type );
    if( elementId == 0 ) 
    {
      edimMax = edim;
    } 
    else
    { 
      if(edimMax != edim)
      {
        MSQ_SETERR(err)("A patch has elements of different dimensions", MsqError::INVALID_MESH);
        std::cout << "A patch has elements of different dimensions" << edimMax << "  "  << edim << std::endl;
        if(edimMax < edim)
        {
          edimMax = edim;
        }
      }
    }
  }
  return( edimMax );
}
void NonGradient::printPatch(const PatchData &pd, MsqError &err)
{
  if( mNonGradDebug==0 )
  {
    return;
  }
  const size_t numNode = pd.num_nodes();   //27,  27 what?
  MSQ_PRINT(3)("Number of Vertices: %d\n",(int)pd.num_nodes());
  const size_t numVert = pd.num_free_vertices(); // 1
  MSQ_PRINT(3)("Num Free = %d\n",(int)pd.num_free_vertices());
  const size_t numSlaveVert = pd.num_slave_vertices(); //0
  const size_t numCoin = pd.num_corners(); // 64
  const MsqVertex* coord = pd.get_vertex_array(err);
  MSQ_PRINT(3)("Number of Vertices: %d\n",(int)pd.num_nodes());

  std::cout << "Patch " << numNode << "  " << numVert << "  " << numSlaveVert << "  " << numCoin << std::endl;
  MSQ_PRINT(3)("");
  std::cout << "Coordinate ";
  std::cout << "         " << std::endl;
  for( size_t index = 0; index < numVert; index++ )
  {
    std::cout << coord[index][0] << "  " << coord[index][1] << "  " << coord[index][2] << std::endl;
  }
  //const size_t numElt = pd.num_elements();
  if( mNonGradDebug >= 3 ) 
  {      
         std::cout << "Number of Elements: " << pd.num_elements() << std::endl;
  }      
  MSQ_PRINT(3)("Number of Elements: %d\n",(int)pd.num_elements());
}
/*!Returns an appropiate value (eps) to use as a delta step for
  MsqVertex vertex in dimension k (i.e. k=0 -> x, k=1 -> y, k=2 -> z).
  The objective function value at the perturbed vertex position is given
  in local_val.
*/
double ObjectiveFunction::get_eps( PatchData &pd, 
                                   EvalType type,
                                   double &local_val,
                                   int dim,
                                   size_t vertex_index, 
                                   MsqError& err)
{
  double eps = 1.e-07;
  const double rho = 0.5;
  const int imax = 20;
  bool feasible = false;
  double tmp_var = 0.0;
  Vector3D delta(0,0,0);
  for (int i = 0; i < imax; ++i)
  {
    //perturb kth coord val and check feas if needed
    tmp_var = pd.vertex_by_index(vertex_index)[dim];
    delta[dim] = eps;
    pd.move_vertex( delta, vertex_index, err );
    feasible = evaluate( type, pd, local_val, OF_FREE_EVALS_ONLY, err ); MSQ_ERRZERO(err);
    //revert kth coord val
    delta = pd.vertex_by_index(vertex_index);
    delta[dim] = tmp_var;
    pd.set_vertex_coordinates( delta, vertex_index, err );
    //if step was too big, shorten it and go again
    if (feasible)
      return eps;
    else
      eps *= rho;
  }//end while looking for feasible eps
  return 0.0;
}//end function get_eps
void MsqMeshEntityTest::test_all_nodes( EntityTopology type, unsigned num_nodes )
{
  const unsigned num_vtx = 27;
  double coords[3*num_vtx] = {0.0};
  size_t conn[num_vtx];
  for (size_t i = 0; i < num_vtx; ++i)
    conn[i] = i;
  bool fixed[num_vtx] = {false};
  CPPUNIT_ASSERT(num_nodes <= num_vtx);
  
  MsqError err;
  PatchData pd;
  size_t n = num_nodes;
  pd.fill( num_nodes, coords, 1, &type, &n, conn, fixed, err );
  ASSERT_NO_ERROR(err);
  
  MsqMeshEntity& elem = pd.element_by_index(0);
  NodeSet all = elem.all_nodes(err);
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT_EQUAL( num_nodes, all.num_nodes() );
  CPPUNIT_ASSERT( all.have_any_corner_node() );
  bool mid_edge, mid_face, mid_reg;
  TopologyInfo::higher_order( type, num_nodes, mid_edge, mid_face, mid_reg, err );
  ASSERT_NO_ERROR(err);
  CPPUNIT_ASSERT_EQUAL( mid_edge, !!all.have_any_mid_edge_node() );
  CPPUNIT_ASSERT_EQUAL( mid_face, !!all.have_any_mid_face_node() );
  CPPUNIT_ASSERT_EQUAL( mid_reg,  !!all.have_any_mid_region_node() );
  
}
void ObjectiveFunctionTests::compare_numerical_gradient( ObjectiveFunction* of )
{
  MsqPrintError err(std::cout);
  PatchData pd;
  create_twelve_hex_patch( pd, err ); 
  ASSERT_NO_ERROR( err );
  
  std::vector<Vector3D> num_grad, ana_grad;
  double num_val, ana_val;
  bool valid;
  
  valid = of->evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, ana_val, ana_grad, err );
  ASSERT_NO_ERROR( err );
  CPPUNIT_ASSERT(valid);
  CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), ana_grad.size() );
  
  valid = of->ObjectiveFunction::evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, num_val, num_grad, err );
  ASSERT_NO_ERROR( err );
  CPPUNIT_ASSERT(valid);
  CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), num_grad.size() );
  
  CPPUNIT_ASSERT_DOUBLES_EQUAL( ana_val, num_val, 1e-6 );
  for (size_t i = 0; i < pd.num_free_vertices(); ++i) {
    CPPUNIT_ASSERT_VECTORS_EQUAL( num_grad[i], ana_grad[i], 1e-3 );
  }
}
double 
NonGradient::evaluate( double *point,  PatchData &pd, MsqError &err )
{
  if( pd.num_free_vertices() > 1 )
  {
    MSQ_SETERR(err)("Only one free vertex per patch implemented", MsqError::NOT_IMPLEMENTED);
  }
  const size_t vertexIndex = 0; 
  Vector3D originalVec = pd.vertex_by_index(vertexIndex);
  Vector3D pointVec;
  for( int index = 0; index<3; index++)
  {
    pointVec[index] = point[index];
  }
  pd.set_vertex_coordinates( pointVec, vertexIndex, err ); 
  pd.snap_vertex_to_domain( vertexIndex, err );  

  OFEvaluator& obj_func = get_objective_function_evaluator();
  TerminationCriterion* term_crit=get_inner_termination_criterion();

  double value;
  bool feasible = obj_func.evaluate( pd, value, err ); // MSQ_ERRZERO(err);
  term_crit->accumulate_inner( pd, value, 0, err );  //MSQ_CHKERR(err);
  if (err.error_code() == err.BARRIER_VIOLATED)
    err.clear();   // barrier violation not an error here
  MSQ_ERRZERO(err);
  pd.set_vertex_coordinates( originalVec, vertexIndex, err ); 
  if( !feasible && mUseExactPenaltyFunction )  
  { // "value" undefined btw
    double ensureFiniteRtol= .25;
    value = DBL_MAX * ensureFiniteRtol;
    //std::cout << " Infeasible patch: " << value << std::endl; printPatch( pd, err );
  }
  return value;
}
Example #7
0
bool PatchPowerMeanP::initialize_block_coordinate_descent( Mesh* mesh, 
                                                      MeshDomain* domain, 
                                                      const Settings* settings,
                                                      PatchSet* patch_set,
                                                      MsqError& err )
{
  clear();
  PatchIterator patches( patch_set );
  
  PatchData pd;
  pd.set_mesh( mesh );
  pd.set_domain( domain );
  if (settings)
    pd.attach_settings(settings);
  
  bool result = true;
  while (patches.get_next_patch( pd, err ) && !MSQ_CHKERR(err))
  {
    double value;
    bool b = evaluate( ObjectiveFunction::ACCUMULATE, pd, value, false, err ); 
    MSQ_ERRZERO(err);
    result = result && b;
  }
  return result;
}
void MappingFunction3D::jacobian( const PatchData& pd,
                                  size_t element_number,
                                  NodeSet nodeset,
                                  Sample location,
                                  size_t* vertex_patch_indices_out,
                                  MsqVector<3>* d_coeff_d_xi_out,
                                  size_t& num_vtx_out,
                                  MsqMatrix<3,3>& jacobian_out,
                                  MsqError& err ) const
{
  const MsqMeshEntity& elem = pd.element_by_index( element_number );
  const size_t* conn = elem.get_vertex_index_array();
  
  derivatives( location, nodeset, vertex_patch_indices_out,
               d_coeff_d_xi_out, num_vtx_out, err ); MSQ_ERRRTN(err);
 
  convert_connectivity_indices( elem.node_count(), vertex_patch_indices_out, 
                                num_vtx_out, err );  MSQ_ERRRTN(err);
 
  jacobian_out.zero();
  size_t w = 0;
  for (size_t r = 0; r < num_vtx_out; ++r) {
    size_t i = conn[vertex_patch_indices_out[r]];
    MsqMatrix<3,1> coords( pd.vertex_by_index( i ).to_array() );
    jacobian_out += coords * transpose(d_coeff_d_xi_out[r]);
    if (i < pd.num_free_vertices()) {
      vertex_patch_indices_out[w] = i;
      d_coeff_d_xi_out[w] = d_coeff_d_xi_out[r];
      ++w;
    }
  }
  num_vtx_out = w;
}
void ObjectiveFunctionTests::compare_hessian_diagonal( ObjectiveFunction* of )
{
  MsqPrintError err(std::cout);
  PatchData pd;
  create_twelve_hex_patch( pd, err ); 
  ASSERT_NO_ERROR( err );
  
  std::vector<Vector3D> diag_grad, hess_grad;
  std::vector<SymMatrix3D> diag;
  MsqHessian hess;
  double diag_val, hess_val;
  bool valid;
  
  valid = of->evaluate_with_Hessian_diagonal( ObjectiveFunction::CALCULATE, pd, diag_val, diag_grad, diag, err );
  ASSERT_NO_ERROR( err );
  CPPUNIT_ASSERT(valid);
  CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), diag_grad.size() );
  CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), diag.size() );
  
  hess.initialize( pd, err );
  ASSERT_NO_ERROR( err );
  valid = of->evaluate_with_Hessian( ObjectiveFunction::CALCULATE, pd, hess_val, hess_grad, hess, err );
  ASSERT_NO_ERROR( err );
  CPPUNIT_ASSERT(valid);
  CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess_grad.size() );
  CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess.size() );
  
  CPPUNIT_ASSERT_DOUBLES_EQUAL( hess_val, diag_val, 1e-6 );
  for (size_t i = 0; i < pd.num_free_vertices(); ++i) {
    CPPUNIT_ASSERT_VECTORS_EQUAL( hess_grad[i], diag_grad[i], 1e-6 );
    CPPUNIT_ASSERT_MATRICES_EQUAL( *hess.get_block(i,i), diag[i], 1e-6 );
  }
}
Example #10
0
bool AffineMapMetric::evaluate_with_indices( PatchData& pd,
                                             size_t handle,
                                             double& value,
                                             std::vector<size_t>& indices,
                                             MsqError& err )
{
  Sample   s = ElemSampleQM::sample( handle );
  size_t   e = ElemSampleQM::  elem( handle );
  MsqMeshEntity& elem = pd.element_by_index( e );
  EntityTopology type = elem.get_element_type();
  const size_t* conn = elem.get_vertex_index_array();
  
    // this metric only supports sampling at corners
  if (s.dimension != 0) {
    if (type != TRIANGLE && type != TETRAHEDRON) {
      MSQ_SETERR(err)("Invalid sample point for AffineMapMetric", MsqError::UNSUPPORTED_ELEMENT );
      return false;
    }
    s.dimension = 0;
    s.number = 0;
  }

  unsigned n;
  const unsigned* adj = TopologyInfo::adjacent_vertices( type, s.number, n );
  indices.clear();
  if (conn[s.number] < pd.num_free_vertices())
    indices.push_back(conn[s.number]);
  for (unsigned i = 0; i < n; ++i)
    if (conn[adj[i]] < pd.num_free_vertices())
      indices.push_back(conn[adj[i]]);
  
  return evaluate( pd, handle, value, err );
}
Example #11
0
bool CompositeOFAdd::evaluate_with_Hessian( EvalType type, 
                                            PatchData& pd,
                                            double& value_out,
                                            std::vector<Vector3D>& grad_out,
                                            MsqHessian& Hessian_out,
                                            MsqError& err )
{
  double value_2;
  bool ok;
  
  mHessian.initialize( Hessian_out );
  
  ok = objFunc1->evaluate_with_Hessian( type, pd, value_out, grad_out, Hessian_out, err );
  if (MSQ_CHKERR(err) || !ok) return false;
  ok = objFunc2->evaluate_with_Hessian( type, pd, value_2, mGradient, mHessian, err );
  if (MSQ_CHKERR(err) || !ok) return false;
  
  value_out += value_2;
  
  assert( grad_out.size() == pd.num_free_vertices() );
  assert( mGradient.size() == pd.num_free_vertices() );
  
  for (size_t i = 0; i < pd.num_free_vertices(); ++i) 
    grad_out[i] += mGradient[i];
  Hessian_out.add( mHessian );
  return true;
}
Example #12
0
bool CompositeOFAdd::evaluate_with_gradient( EvalType type, 
                                             PatchData& pd,
                                             double& value_out,
                                             std::vector<Vector3D>& grad_out,
                                             MsqError& err )
{
  double value_2;
  bool ok;
  
  ok = objFunc1->evaluate_with_gradient( type, pd, value_out, grad_out, err );
  if (MSQ_CHKERR(err) || !ok) return false;
  ok = objFunc2->evaluate_with_gradient( type, pd, value_2, mGradient, err );
  if (MSQ_CHKERR(err) || !ok) return false;
  
  assert( grad_out.size() == pd.num_free_vertices() );
  assert( mGradient.size() == pd.num_free_vertices() );
  
  std::vector<Vector3D>::iterator i = grad_out.begin(), j = mGradient.begin();
  while (i != grad_out.end()) {
    *i += *j;
    ++i;
    ++j;
  }
  value_out += value_2;
  return true;
}
Example #13
0
   /*! \fn create_six_quads_patch(PatchData &four_quads, MsqError &err)
     our 2D set up: 6 quads, 1 center vertex outcentered by (0,-0.5), the other centered
      7____6____5___11
      |    |    |    |
      | 2  |  3 | 5  |
      8-_  |  _-4---10       vertex 1 is at (0,0)
      |  -_0_-  |    |       vertex 11 is at (3,2)
      | 0  |  1 | 4  |
      1----2----3----9

      use destroy_patch_with_domain() in sync.
   */
   inline void create_six_quads_patch_with_domain(PatchData &pd, MsqError &err) 
   {
     // associates domain
     Vector3D pnt(0,0,0);
     Vector3D s_norm(0,0,3);
     pd.set_domain( new PlanarDomain(s_norm, pnt) );

     double coords[] = { 1,.5, 0,
                         0, 0, 0,
                         1, 0, 0,
                         2, 0, 0,
                         2, 1, 0,
                         2, 2, 0,
                         1, 2, 0,
                         0, 2, 0,
                         0, 1, 0,
                         3, 0, 0,
                         3, 1, 0,
                         3, 2, 0 };

     size_t indices[] = { 1,  2,  0, 8,
                          2,  3,  4, 0,
                          8,  0,  6, 7,
                          0,  4,  5, 6,
                          3,  9, 10, 4,
                          4, 10, 11, 5 };
     
     bool fixed[] = { false, true, true, true, 
                      false, true, true, true, 
                      true, true, true, true };
     
     pd.fill( 12, coords, 6, QUADRILATERAL, indices, fixed, err );
   }
void ObjectiveFunctionTests::compare_diagonal_gradient( ObjectiveFunction* of )
{
  MsqPrintError err(std::cout);
  PatchData pd;
  create_twelve_hex_patch( pd, err ); 
  ASSERT_NO_ERROR( err );
  
  std::vector<Vector3D> grad, hess_grad;
  std::vector<SymMatrix3D> hess;
  double grad_val, hess_val;
  bool valid;
  
  valid = of->evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, grad_val, grad, err );
  ASSERT_NO_ERROR( err );
  CPPUNIT_ASSERT(valid);
  CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), grad.size() );
  
  valid = of->evaluate_with_Hessian_diagonal( ObjectiveFunction::CALCULATE, pd, hess_val, hess_grad, hess, err );
  ASSERT_NO_ERROR( err );
  CPPUNIT_ASSERT(valid);
  CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess_grad.size() );
  
  CPPUNIT_ASSERT_DOUBLES_EQUAL( grad_val, hess_val, 1e-6 );
  for (size_t i = 0; i < pd.num_free_vertices(); ++i) {
    CPPUNIT_ASSERT_VECTORS_EQUAL( grad[i], hess_grad[i], 1e-6 );
  }
}
bool EdgeLengthQualityMetric::evaluate_vertex(PatchData &pd, MsqVertex* vert,
                                             double &fval, MsqError &err)
{
  fval=0.0;
  size_t this_vert = pd.get_vertex_index(vert);
  size_t other_vert;
  vector<size_t> adj_verts;
  Vector3D edg;
  pd.get_adjacent_vertex_indices(this_vert,adj_verts,err);  MSQ_ERRZERO(err);
  int num_sample_points=adj_verts.size();
  double *metric_values=new double[num_sample_points];
  MsqVertex* verts = pd.get_vertex_array(err);  MSQ_ERRZERO(err);
  int point_counter=0;
  while(!adj_verts.empty()){
    other_vert=adj_verts.back();
    adj_verts.pop_back();
    edg[0]=verts[this_vert][0]-verts[other_vert][0];
    edg[1]=verts[this_vert][1]-verts[other_vert][1];
    edg[2]=verts[this_vert][2]-verts[other_vert][2];    
    metric_values[point_counter]=edg.length();
    ++point_counter;
  }
  fval=average_metrics(metric_values,num_sample_points,err);  MSQ_ERRZERO(err);
  delete[] metric_values;
  
  return true;
  
}
Example #16
0
void write_gnuplot( Mesh* mesh, const char* out_filebase, MsqError &err)
{
    // loads a global patch
  PatchData pd;
  pd.set_mesh( mesh );
  pd.fill_global_patch( err ); MSQ_ERRRTN(err);
  write_gnuplot( pd, out_filebase, err );
}
Example #17
0
/*! 
  Numerically Calculates the gradient of the ObjectiveFunction for the
  free vertices in the patch.  Returns 'false' if the patch is outside
  of a required feasible region, returns 'ture' otherwise.
  The behavior of the function depends on the value of the boolean
  useLocalGradient.  If useLocalGradient is set to
  'true', compute_numerical_gradient creates a sub-patch around a free
  vertex, and then perturbs that vertex in one of the coordinate directions.
  Only the ObjectiveFunction value on the local sub-patch is used in the
  computation of the gradient.  Therefore, useLocalGradient should only
  be set to 'true' for ObjectiveFunctions which can use this method.  Unless
  the concrete ObjectiveFunction sets useLocalGradient to 'true' in its
  constructor, the value will be 'false'.  In this case, the objective
  function value for the entire patch is used in the calculation of the
  gradient.  This is computationally expensive, but it is numerically
  correct for all (C_1) functions.
  \param pd  PatchData on which the gradient is taken.
  \param grad  Array of Vector3D of length the number of vertices used to store gradient.
  \param OF_val will be set to the objective function value.
 */
bool ObjectiveFunction::evaluate_with_gradient( EvalType eval_type,
                                                PatchData &pd,
                                                double& OF_val,
                                                std::vector<Vector3D>& grad,
                                                MsqError &err )
{
  bool b;
  grad.resize( pd.num_free_vertices() );
  
    // Fast path for single-free-vertex patch
  if (pd.num_free_vertices() == 1) {
    const EvalType sub_type = (eval_type == CALCULATE) ? CALCULATE : TEMPORARY;
    b = compute_subpatch_numerical_gradient( eval_type, sub_type, pd, OF_val, grad[0], err );
    return !MSQ_CHKERR(err) && b;
  }
  
  ObjectiveFunction* of = this;
  std::auto_ptr<ObjectiveFunction> deleter;
  if (eval_type == CALCULATE) {
    of->clear();
    b = of->evaluate( ACCUMULATE, pd, OF_val, OF_FREE_EVALS_ONLY, err );
    if (err) { // OF doesn't support BCD type evals, try slow method
      err.clear();
      of->clear();
      b = compute_patch_numerical_gradient( CALCULATE, CALCULATE, pd, OF_val, grad, err );
      return !MSQ_CHKERR(err) && b;
    }
    else if (!b)
      return b;
  } 
  else {
    b = this->evaluate( eval_type, pd, OF_val, OF_FREE_EVALS_ONLY, err );
    if (MSQ_CHKERR(err) || !b)
      return false;
    of = this->clone();
    deleter = std::auto_ptr<ObjectiveFunction>(of);
  }

    // Determine number of layers of adjacent elements based on metric type.
  unsigned layers = min_patch_layers();
  
    // Create a subpatch for each free vertex and use it to evaluate the
    // gradient for that vertex.
  double flocal;
  PatchData subpatch;
  for (size_t i = 0; i < pd.num_free_vertices(); ++i)
  {
    pd.get_subpatch( i, layers, subpatch, err ); MSQ_ERRZERO(err);
    b = of->compute_subpatch_numerical_gradient( SAVE, TEMPORARY, subpatch, flocal, grad[i], err );
    if (MSQ_CHKERR(err) || !b) {
      of->clear();
      return false;
    }
  }
  
  of->clear();
  return true;
}
Example #18
0
   void test_elements()
   {
      MsqPrintError err(cout);
     /* Adds TSTT mesh to a MeshSet. */
      MeshSet mesh_set;
      TSTTMesh tstt_mesh;
      tstt_mesh.set_mesh(tri10);
      mesh_set.add_mesh(&tstt_mesh, err); CPPUNIT_ASSERT(!err);

      /* Retrieves a global patch */
      PatchData pd;
      PatchDataParameters pd_params;
      pd_params.set_patch_type(PatchData::ELEMENTS_ON_VERTEX_PATCH, err, 1, 0);
      
      mesh_set.get_next_patch(pd, pd_params, err); CPPUNIT_ASSERT(!err);

      int free_vtx = pd.num_free_vertices(err); CPPUNIT_ASSERT(!err);
      std::cout << "nb of free vertices: " << free_vtx << std::endl;
      CPPUNIT_ASSERT( free_vtx == 1 );
      
      element_array =  pd.get_element_array(err); CPPUNIT_ASSERT(!err);
      num_elements = pd.num_elements();
      CPPUNIT_ASSERT( num_elements == 6 );

      //      for (int i=0; i<num_elements; ++i) {
      //         std::cout << element_array[i];
      //      }
      
      vtx_array = pd.get_vertex_array(err); CPPUNIT_ASSERT(!err);
      num_vertices = pd.num_vertices();
      CPPUNIT_ASSERT( num_vertices == 7 );

      //      for (int i=0; i<num_vertices; ++i) {
      //         std::cout << vtx_array[i];
      //      }

      CPPUNIT_ASSERT( tri_check_validity() == 1 );
      
      mesh_set.get_next_patch(pd, pd_params, err); CPPUNIT_ASSERT(!err);

      element_array =  pd.get_element_array(err); CPPUNIT_ASSERT(!err);
      num_elements = pd.num_elements();
      CPPUNIT_ASSERT( num_elements == 6 );

      //      for (int i=0; i<num_elements; ++i) {
      //         std::cout << element_array[i];
      //      }
      
      vtx_array = pd.get_vertex_array(err); CPPUNIT_ASSERT(!err);
      num_vertices = pd.num_vertices();
      CPPUNIT_ASSERT( num_vertices == 7 );

      //      for (int i=0; i<num_vertices; ++i) {
      //         std::cout << vtx_array[i];
      //      }

      CPPUNIT_ASSERT( tri_check_validity() == 1 );
   }
void NonGradient::initialize_mesh_iteration(PatchData &pd, MsqError &err)
{
  int elementDimension = getPatchDimension( pd, err );  // to do: react to error
  int dimension = elementDimension * pd.num_free_vertices();
  //printPatch( pd, err );
  setDimension(dimension);
  int maxNumEval = 100*dimension;  // 1. Make this a user parameter
  setMaxNumEval(maxNumEval);
  double threshold = 1.e-10; // avoid division by zero
  setThreshold(threshold);
  double minEdgeLen = 0.0;
  double maxEdgeLen = 0.0;
//  double ftol = 0.;
  if( dimension > 0 )
  {
    pd.get_minmax_edge_length( minEdgeLen, maxEdgeLen );
    //ftol = minEdgeLen * 1.e-4; // Turn off Amoeba convergence criterion
    if( mNonGradDebug >= 1 ) 
    {      
         std::cout << "minimum edge length " << minEdgeLen << " maximum edge length " << maxEdgeLen << std::endl;
    }      
    MSQ_PRINT(3)("minimum edge length %e    maximum edge length %e\n", minEdgeLen,  maxEdgeLen);
  }
//  setTolerance(ftol);
  int numRow = dimension;
  int numCol = numRow+1;  
  if( numRow*numCol <= simplex.max_size() )
  { 
    simplex.assign(numRow*numCol, 0.);  // guard against previous simplex value
    double scale = minEdgeLen * mScaleDiameter;; 
    const MsqVertex* coord = pd.get_vertex_array(err);
    if( pd.num_free_vertices() > 1 )
    {
      MSQ_SETERR(err)("Only one free vertex per patch implemented", MsqError::NOT_IMPLEMENTED);
    }
    size_t index = 0;
    for( int col = 0; col < numCol; col++ )
    {
      for (int row=0;row<numRow;row++)
      {
        simplex[ row + col*numRow ] = coord[index][row];
        if( row == col-1 )
        {
          simplex[ row + col*numRow ] += scale/ static_cast<double>(numCol);
        }
      }
    }
  }
  else
  {
    MSQ_SETERR(err)("Use patch with fewer free vertices", MsqError::OUT_OF_MEMORY);
    if( mNonGradDebug >= 1 ) 
    {      
      std::cout << "ERROR: Too many free vertices in patch" << std::endl;
    }      
    //MSQ_PRINT(1)("ERROR: Too many free vertices in patch\n");
  }
}
Example #20
0
  // Create patch containing one ideal element, optionally higher-order.
  // For 2D elements, will attach appropriate planar domain.
  inline void create_ideal_element_patch( PatchData& pd,
                                          EntityTopology type, 
                                          size_t num_nodes,
                                          MsqError& err )
  {
     static PlanarDomain zplane(PlanarDomain::XY);
     static Settings settings;
     settings.set_slaved_ho_node_mode( Settings::SLAVE_NONE );
     pd.attach_settings( &settings );
     
  
       // build list of vertex coordinates
     const Vector3D* corners = unit_edge_element( type );
     std::vector<Vector3D> coords( corners, corners+TopologyInfo::corners(type) );
     bool mids[4] = {false};
     TopologyInfo::higher_order( type, num_nodes, mids[1], mids[2], mids[3], err );
     MSQ_ERRRTN(err);
     std::vector<size_t> conn(coords.size());
     for (unsigned i = 0; i < coords.size(); ++i)
       conn[i] = i;
 
     for (unsigned dim = 1; dim <= TopologyInfo::dimension(type); ++dim) {
       if (!mids[dim])
         continue;
       
       int num_side;
       if (dim == TopologyInfo::dimension(type))
         num_side = 1;
       else
         num_side = TopologyInfo::adjacent( type, dim );
       
       for (int s = 0; s < num_side; ++s) {
         unsigned idx = TopologyInfo::higher_order_from_side( type, num_nodes, dim, s, err );
         MSQ_ERRRTN(err);
         conn.push_back(idx);
       
         unsigned n;
         const unsigned* side = TopologyInfo::side_vertices( type, dim, s, n, err );
         MSQ_ERRRTN(err);
         Vector3D avg = coords[side[0]];
         for (unsigned v = 1; v < n; ++v)
           avg += coords[side[v]];
         avg *= 1.0/n;
         coords.push_back(avg);
       }
     }
     
     bool* fixed = new bool[coords.size()];
     std::fill( fixed, fixed+coords.size(), false );
     pd.fill( coords.size(), coords[0].to_array(), 1, &type, 
              &num_nodes, &conn[0], fixed, err );
     delete [] fixed;
     MSQ_ERRRTN(err);
     
     if (TopologyInfo::dimension(type) == 2)
       pd.set_domain( &zplane );
  }
bool TQualityMetric::evaluate_internal( PatchData& pd,
                                        size_t handle,
                                        double& value,
                                        size_t* indices,
                                        size_t& num_indices,
                                        MsqError& err )
{
  const Sample s = ElemSampleQM::sample( handle );
  const size_t e = ElemSampleQM::  elem( handle );
  MsqMeshEntity& elem = pd.element_by_index( e );
  EntityTopology type = elem.get_element_type();
  unsigned edim = TopologyInfo::dimension( type );
  const NodeSet bits = pd.non_slave_node_set( e );
  
  bool rval;
  if (edim == 3) { // 3x3 or 3x2 targets ?
    const MappingFunction3D* mf = pd.get_mapping_function_3D( type );
    if (!mf) {
      MSQ_SETERR(err)( "No mapping function for element type", MsqError::UNSUPPORTED_ELEMENT );
      return false;
    }

    MsqMatrix<3,3> A, W;
    mf->jacobian( pd, e, bits, s, indices, mDerivs3D, num_indices, A, err );
    MSQ_ERRZERO(err);
    targetCalc->get_3D_target( pd, e, s, W, err ); MSQ_ERRZERO(err);
    const MsqMatrix<3,3> Winv = inverse(W);
    const MsqMatrix<3,3> T = A*Winv;
    rval = targetMetric->evaluate( T, value, err ); MSQ_ERRZERO(err);
#ifdef PRINT_INFO
    print_info<3>( e, s, A, W, A * inverse(W) );
#endif
  }
  else if (edim == 2) {
    MsqMatrix<2,2> W, A;
    MsqMatrix<3,2> S_a_transpose_Theta;
    rval = evaluate_surface_common( pd, s, e, bits, indices, num_indices,
                                 mDerivs2D, W, A, S_a_transpose_Theta, err ); 
    if (MSQ_CHKERR(err) || !rval)
      return false;
    const MsqMatrix<2,2> Winv = inverse(W);
    const MsqMatrix<2,2> T = A * Winv;
    rval = targetMetric->evaluate( T, value, err );
    MSQ_ERRZERO(err);

#ifdef PRINT_INFO
    print_info<2>( e, s, J, Wp, A * inverse(W) );
#endif
  }
  else {
    assert(false);
    return false;
  }
  
  return rval;
}
Example #22
0
void write_gnuplot( Mesh* mesh, std::vector<Mesh::ElementHandle>& elems,
                    const char* out_filebase, MsqError &err)
{
    // loads a global patch
  PatchData pd;
  pd.set_mesh( mesh );
  std::vector<Mesh::VertexHandle> verts;
  pd.set_mesh_entities( elems, verts, err ); MSQ_ERRRTN(err);
  write_gnuplot( pd, out_filebase, err );
}
Example #23
0
 //! must be called in sync with create_...._patch_with_domain
 inline void destroy_patch_with_domain(PatchData &pd)
 {
   MeshDomain* domain = pd.get_domain();
   pd.set_domain( 0 );
   delete domain;
   
   //Mesh* mesh = pd.get_mesh();
   //pd.set_mesh( 0 );
   //delete mesh;
 }
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());
}
Example #25
0
 void get_nonideal_element( EntityTopology type, PatchData& pd )
   {
     tester.get_nonideal_element( type, pd, true );
       // Callers assume surface elements are in XY plane.
       // Verify this assumption.
     if (TopologyInfo::dimension(type) == 2) {
       for (size_t i = 0; i < pd.num_nodes(); ++i) {
         CPPUNIT_ASSERT_DOUBLES_EQUAL( pd.vertex_by_index(i)[2], 0.0, 1e-6 );
       }
     }
   }
void TerminationCriterion::accumulate_inner( PatchData& pd, 
                                             double of_value,
                                             Vector3D* grad_array,
                                             MsqError& err )
{
  //if terminating on the norm of the gradient
  //currentGradL2NormSquared = HUGE_VAL;
  if (terminationCriterionFlag & (GRADIENT_L2_NORM_ABSOLUTE | GRADIENT_L2_NORM_RELATIVE)) 
  {
    currentGradL2NormSquared = length_squared(grad_array, pd.num_free_vertices()); // get the L2 norm
    MSQ_DBGOUT_P0_ONLY(debugLevel) << par_string() << "  o Info -- gradient L2 norm: " << " "
                                   << RPM(std::sqrt(currentGradL2NormSquared)) << std::endl;
  }
  //currentGradInfNorm = 10e6;
  if (terminationCriterionFlag & (GRADIENT_INF_NORM_ABSOLUTE | GRADIENT_INF_NORM_RELATIVE)) 
  {
    currentGradInfNorm = Linf(grad_array, pd.num_free_vertices()); // get the Linf norm
    MSQ_DBGOUT_P0_ONLY(debugLevel) << par_string() << "  o Info -- gradient Inf norm: " << " "
                                   << RPM(currentGradInfNorm) << std::endl;
  } 
  
  if (terminationCriterionFlag & VERTEX_MOVEMENT_RELATIVE)
  {
    maxSquaredInitialMovement = pd.get_max_vertex_movement_squared(
                               initialVerticesMemento, err );  MSQ_ERRRTN(err);
    MSQ_DBGOUT_P0_ONLY(debugLevel) << par_string() << "  o Info -- max initial vertex movement: " << " "
                                   << RPM(maxSquaredInitialMovement) << std::endl;
  }
  
  previousOFValue = currentOFValue;
  currentOFValue = of_value;
  if (terminationCriterionFlag & OF_FLAGS) {
    MSQ_DBGOUT_P0_ONLY(debugLevel) << par_string() << "  o Info -- OF Value: " << " " << RPM(of_value) << " iterationCounter= " << iterationCounter << std::endl;
  }
  else if (grad_array) {
    MSQ_DBGOUT_P0_ONLY(debugLevel) << par_string() << "  o OF Value: " << " " << RPM(of_value) << " iterationCounter= " << iterationCounter 
      //<< " terminationCriterionFlag= " << terminationCriterionFlag << " OF_FLAGS = " << OF_FLAGS
                                   << std::endl;
  }
  
  ++iterationCounter;
  if (timeStepFileType)
    write_timestep( pd, grad_array, err);
    
  if (plotFile.is_open()) 
    plotFile << iterationCounter 
     << '\t' << mTimer.since_birth() 
     << '\t' << of_value 
     << '\t' << std::sqrt( currentGradL2NormSquared ) 
     << '\t' << currentGradInfNorm 
     << '\t' << (maxSquaredMovement > 0.0 ? std::sqrt( maxSquaredMovement ) : 0.0)
     << '\t' << globalInvertedCount
     << std::endl;
}
size_t SmartLaplacianSmoother::num_inverted( PatchData& pd, MsqError& err )
{
  size_t result = 0;
  int inverted, junk;
  for (size_t i = 0; i < pd.num_elements(); ++i) {
    pd.element_by_index(i).check_element_orientation( pd, inverted, junk, err ); 
    MSQ_ERRZERO(err);
    if (inverted)
      ++result;
  }
  return result;
}
size_t TerminationCriterion::count_inverted( PatchData& pd, MsqError& err )
{
  size_t num_elem = pd.num_elements();
  size_t count=0;
  int inverted, samples;
  for (size_t i = 0; i < num_elem; i++) {
    pd.element_by_index(i).check_element_orientation(pd, inverted, samples, err);
    if (inverted)
      ++count;
  }
  return count;
}
 void test_unsigned_area()
    {
      MsqPrintError err(cout);
      MsqMeshEntity* tri = oneTriPatch.get_element_array(err);
      CPPUNIT_ASSERT(!err);
      CPPUNIT_ASSERT(fabs(tri->compute_unsigned_area(oneTriPatch,err)
                          -(sqrt(3.0)/4.0)) < tolEps);
      MsqMeshEntity* quad = oneQuadPatch.get_element_array(err);
      CPPUNIT_ASSERT(!err);
      CPPUNIT_ASSERT(fabs(quad->compute_unsigned_area(oneQuadPatch,err)
                          -1.0) < tolEps);
    }
Example #30
0
void NonSmoothDescent::optimize_vertex_positions(PatchData &pd, 
                                                MsqError &err)
{
  MSQ_FUNCTION_TIMER( "NonSmoothDescent" );

  //  cout << "- Executing NonSmoothDescent::optimize_node_positions()\n";
  /* perform the min max smoothing algorithm */
  MSQ_PRINT(2)("\nInitializing the patch iteration\n");

  MSQ_PRINT(3)("Number of Vertices: %d\n",(int)pd.num_nodes());
  MSQ_PRINT(3)("Number of Elements: %d\n",(int)pd.num_elements());
    //Michael: Note: is this a reliable way to get the dimension?
  mDimension = pd.get_mesh()->get_geometric_dimension(err); MSQ_ERRRTN(err);
  MSQ_PRINT(3)("Spatial Dimension: %d\n",mDimension);

  MSQ_PRINT(3)("Num Free = %d\n",(int)pd.num_free_vertices());

  MsqFreeVertexIndexIterator free_iter(pd, err); MSQ_ERRRTN(err);
  free_iter.reset();
  free_iter.next(); 
  freeVertexIndex = free_iter.value();
  MSQ_PRINT(3)("Free Vertex Index = %d\n",freeVertexIndex);

  // TODO - need to switch to validity via metric evaluations should
  // be associated with the compute_function somehow
  /* check for an invalid mesh; if it's invalid return and ask the user 
     to use untangle */
  if (this->validity_check(pd,err)!=1) {
      MSQ_PRINT(1)("ERROR: Invalid mesh\n");
      MSQ_SETERR(err)("Invalid Mesh: Use untangle to create a valid "
                      "triangulation", MsqError::INVALID_MESH);
      return;
  }

  /* assumes one function value per element */
  // TODO - need to include vertex metrics 
  numFunctionValues = pd.num_elements();

  /* initialize the optimization data up to numFunctionValues */
  this->init_opt(err); MSQ_ERRRTN(err);
  this->init_max_step_length(pd,err);  MSQ_ERRRTN(err);
  MSQ_PRINT(3)("Done initializing optimization\n");

  /* compute the initial function values */
  //TODO this should return a bool with the validity
  this->compute_function(&pd, originalFunction, err);  MSQ_ERRRTN(err);
 
  // find the initial active set
  this->find_active_set(originalFunction, mActive, err);   MSQ_ERRRTN(err);

  this->minmax_opt(pd,err);  MSQ_ERRRTN(err);
}