bool LInfTemplate::evaluate( EvalType type, PatchData& pd, double& value_out, bool free, MsqError& err ) { if (type != ObjectiveFunction::CALCULATE) { MSQ_SETERR(err)( "LInfTemplate does not support block coodinate descent algoritms", MsqError::INVALID_STATE ); return false; } QualityMetric* qm = get_quality_metric(); qm->get_evaluations( pd, qmHandles, free, err ); MSQ_ERRFALSE(err); const double negate = qm->get_negate_flag(); // calculate OF value for just the patch std::vector<size_t>::const_iterator i; double value; value_out = -HUGE_VAL; for (i = qmHandles.begin(); i != qmHandles.end(); ++i) { bool result = qm->evaluate( pd, *i, value, err ); if (MSQ_CHKERR(err) || !result) return false; value = negate * fabs(value); if (value > value_out) value_out = value; } return true; }
bool PMeanPTemplate::evaluate( EvalType type, PatchData& pd, double& value_out, bool free, MsqError& err ) { QualityMetric* qm = get_quality_metric(); if (type == ObjectiveFunction::ACCUMULATE) qm->get_single_pass( pd, qmHandles, free, err ); else qm->get_evaluations( pd, qmHandles, free, err ); MSQ_ERRFALSE(err); // calculate OF value for just the patch std::vector<size_t>::const_iterator i; double value, working_sum = 0.0; for (i = qmHandles.begin(); i != qmHandles.end(); ++i) { bool result = qm->evaluate( pd, *i, value, err ); if (MSQ_CHKERR(err) || !result) return false; working_sum += mPower.raise( value ); } // get overall OF value, update member data, etc. size_t global_count; value_out = qm->get_negate_flag() * get_value( working_sum, qmHandles.size(), type, global_count ); return true; }
bool ElementMaxQM::evaluate( PatchData& pd, size_t handle, double& value, MsqError& err ) { ElemSampleQM* qm = get_quality_metric(); mHandles.clear(); qm->get_element_evaluations( pd, handle, mHandles, err ); MSQ_ERRFALSE(err); bool valid = true; double tmpval; bool tmpvalid; value = -1.e+100; // initialize max computation for (std::vector<size_t>::iterator h = mHandles.begin(); h != mHandles.end(); ++h) { tmpvalid = qm->evaluate( pd, *h, tmpval, err ); // MSQ_ERRZERO(err); if (!tmpvalid) { value = +1.e+100; return false; // if any handle within the element makes tmpvalid false, then valid is false, no matter what the other handles say } else if (tmpval > value) value = tmpval; } return valid; }
bool ElementAvgQM::evaluate( PatchData& pd, size_t handle, double& value, MsqError& err ) { ElemSampleQM* qm = get_quality_metric(); mHandles.clear(); qm->get_element_evaluations( pd, handle, mHandles, err ); MSQ_ERRFALSE(err); bool valid = true; double tmpval; double accumulate = 0.0; int num_values = 0; bool tmpvalid; value = -std::numeric_limits<double>::infinity(); for (std::vector<size_t>::iterator h = mHandles.begin(); h != mHandles.end(); ++h) { tmpvalid = qm->evaluate( pd, *h, tmpval, err ); MSQ_ERRZERO(err); if (!tmpvalid) { valid = false; break; } else { accumulate += tmpval; num_values++; } } if (valid) value = accumulate/num_values; return valid; }
bool ElementPMeanP::evaluate( PatchData& pd, size_t handle, double& value, MsqError& err ) { ElemSampleQM* qm = get_quality_metric(); mHandles.clear(); qm->get_element_evaluations( pd, handle, mHandles, err ); MSQ_ERRFALSE(err); bool result = average( pd, qm, mHandles, value, err ); return !MSQ_CHKERR(err) && result; }
bool ElementPMeanP::evaluate_with_gradient( PatchData& pd, size_t handle, double& value, std::vector<size_t>& indices, std::vector<Vector3D>& gradient, MsqError& err ) { ElemSampleQM* qm = get_quality_metric(); mHandles.clear(); qm->get_element_evaluations( pd, handle, mHandles, err ); MSQ_ERRFALSE(err); bool result = average_with_gradient( pd, qm, mHandles, value, indices, gradient, err ); return !MSQ_CHKERR(err) && result; }
bool PMeanPTemplate::evaluate_with_gradient( EvalType type, PatchData& pd, double& value_out, std::vector<Vector3D>& grad_out, MsqError& err ) { QualityMetric* qm = get_quality_metric(); qm->get_evaluations( pd, qmHandles, OF_FREE_EVALS_ONLY, err ); MSQ_ERRFALSE(err); // zero gradient grad_out.clear(); grad_out.resize( pd.num_free_vertices(), Vector3D(0.0,0.0,0.0) ); // calculate OF value and gradient for just the patch std::vector<size_t>::const_iterator i; double value, working_sum = 0.0; const double f = qm->get_negate_flag() * mPower.value(); for (i = qmHandles.begin(); i != qmHandles.end(); ++i) { bool result = qm->evaluate_with_gradient( pd, *i, value, mIndices, mGradient, err ); if (MSQ_CHKERR(err) || !result) return false; if (fabs(value) < DBL_EPSILON) continue; const double r1 = mPowerMinus1.raise( value ); const double qmp = r1 * value; working_sum += qmp; value = f * r1; for (size_t j = 0; j < mIndices.size(); ++j) { mGradient[j] *= value; grad_out[mIndices[j]] += mGradient[j]; } } // get overall OF value, update member data, etc. size_t global_count; value_out = qm->get_negate_flag() * get_value( working_sum, qmHandles.size(), type, global_count ); const double inv_n = 1.0 / global_count; std::vector<Vector3D>::iterator g; for (g = grad_out.begin(); g != grad_out.end(); ++g) *g *= inv_n; return true; }
bool PMeanPTemplate::evaluate_with_Hessian( EvalType type, PatchData& pd, double& value_out, std::vector<Vector3D>& grad_out, MsqHessian& Hessian_out, MsqError& err ) { QualityMetric* qm = get_quality_metric(); qm->get_evaluations( pd, qmHandles, OF_FREE_EVALS_ONLY, err ); MSQ_ERRFALSE(err); // zero gradient and hessian grad_out.clear(); grad_out.resize( pd.num_free_vertices(), 0.0 ); Hessian_out.zero_out(); // calculate OF value and gradient for just the patch std::vector<size_t>::const_iterator i; size_t j, k, n; double value, working_sum = 0.0; const double f1 = qm->get_negate_flag() * mPower.value(); const double f2 = f1 * (mPower.value() - 1); Matrix3D m; for (i = qmHandles.begin(); i != qmHandles.end(); ++i) { bool result = qm->evaluate_with_Hessian( pd, *i, value, mIndices, mGradient, mHessian, err ); if (MSQ_CHKERR(err) || !result) return false; if (fabs(value) < DBL_EPSILON) continue; const size_t nfree = mIndices.size(); n = 0; if (mPower.value() == 1.0) { working_sum += mPower.raise( value ); for (j = 0; j < nfree; ++j) { mGradient[j] *= f1; grad_out[mIndices[j]] += mGradient[j]; for (k = j; k < nfree; ++k) { mHessian[n] *= f1; Hessian_out.add( mIndices[j], mIndices[k], mHessian[n], err ); MSQ_ERRFALSE(err); ++n; } } } else { const double r2 = mPowerMinus2.raise( value ); const double r1 = r2 * value; working_sum += r1 * value; const double hf = f2 * r2; const double gf = f1 * r1; for (j = 0; j < nfree; ++j) { for (k = j; k < nfree; ++k) { m.outer_product( mGradient[j], mGradient[k] ); m *= hf; mHessian[n] *= gf; m += mHessian[n]; Hessian_out.add( mIndices[j], mIndices[k], m, err ); MSQ_ERRFALSE(err); ++n; } } for (j = 0; j < nfree; ++j) { mGradient[j] *= gf; grad_out[mIndices[j]] += mGradient[j]; } } } // get overall OF value, update member data, etc. size_t global_count; value_out = qm->get_negate_flag() * get_value( working_sum, qmHandles.size(), type, global_count ); const double inv_n = 1.0 / global_count; std::vector<Vector3D>::iterator g; for (g = grad_out.begin(); g != grad_out.end(); ++g) *g *= inv_n; Hessian_out.scale( inv_n ); return true; }
bool PMeanPTemplate::evaluate_with_Hessian_diagonal( EvalType type, PatchData& pd, double& value_out, std::vector<Vector3D>& grad_out, std::vector<SymMatrix3D>& hess_diag_out, MsqError& err ) { QualityMetric* qm = get_quality_metric(); qm->get_evaluations( pd, qmHandles, OF_FREE_EVALS_ONLY, err ); MSQ_ERRFALSE(err); // zero gradient and hessian const size_t s = pd.num_free_vertices(); grad_out.clear(); grad_out.resize( s, 0.0 ); hess_diag_out.clear(); hess_diag_out.resize( s, 0.0 ); // calculate OF value and gradient for just the patch std::vector<size_t>::const_iterator i; size_t j; double value, working_sum = 0.0; const double f1 = qm->get_negate_flag() * mPower.value(); const double f2 = f1 * (mPower.value() - 1); for (i = qmHandles.begin(); i != qmHandles.end(); ++i) { bool result = qm->evaluate_with_Hessian_diagonal( pd, *i, value, mIndices, mGradient, mDiag, err ); if (MSQ_CHKERR(err) || !result) return false; if (fabs(value) < DBL_EPSILON) continue; const size_t nfree = mIndices.size(); if (mPower.value() == 1.0) { working_sum += mPower.raise( value ); for (j = 0; j < nfree; ++j) { const size_t idx = mIndices[j]; hess_diag_out[idx] += f1 * mDiag[j]; mGradient[j] *= f1; grad_out[idx] += mGradient[j]; } } else { const double r2 = mPowerMinus2.raise( value ); const double r1 = r2 * value; working_sum += r1 * value; const double hf = f2 * r2; const double gf = f1 * r1; for (j = 0; j < nfree; ++j) { const size_t idx = mIndices[j]; hess_diag_out[idx] += hf * outer( mGradient[j] ); hess_diag_out[idx] += gf * mDiag[j]; mGradient[j] *= gf; grad_out[idx] += mGradient[j]; } } } // get overall OF value, update member data, etc. size_t global_count; value_out = qm->get_negate_flag() * get_value( working_sum, qmHandles.size(), type, global_count ); const double inv_n = 1.0 / global_count; for (j = 0; j < s; ++j) { grad_out[j] *= inv_n; hess_diag_out[j] *= inv_n; } return true; }
bool I_DFT_NoBarrierSmoother::i_dft_no_barrier_smooth_mesh( PatchData &pd, size_t free_index, MsqError &err) { //get vertex and element arrays MsqVertex* verts=pd.get_vertex_array(err); MSQ_ERRFALSE(err); MsqMeshEntity* elems=pd.get_element_array(err);MSQ_ERRFALSE(err); size_t num_elements = pd.num_elements(); //matrix to store a map for the given corner // (element/vertex combination) that maps the //vertex to 0 and the other vertices to 1,2,3 int local_matrix_map[MSQ_MAX_NUM_VERT_PER_ENT]; size_t local_matrix_map_length=MSQ_MAX_NUM_VERT_PER_ENT; size_t local_matrix_map_used=0; Vector3D new_position; //will be used as the denominator double scale_value = 0.0; size_t i, j, k; //Z and Z^(t) Matrix3D z_mat_transpose; Matrix3D z_mat[4]; //array of Y's... one for each vertex in this corner. Matrix3D y_mat[4]; //c_(j,k) for the vertices double c_scalars[4]; //zeta for this corner Vector3D zeta_vector; vector<size_t> elems_verts; //loop over the two or three dimensions for(i=0;i<num_elements;++i) { //actually get the map for this corner... local_matrix_map_used = elems[i].get_local_matrix_map_about_vertex( pd, &verts[free_index],local_matrix_map_length, local_matrix_map,err); MSQ_ERRFALSE(err); //get a vector of the vertex indices for this element elems[i].get_vertex_indices(elems_verts); //get the W array for this elements int elem_idx = pd.get_element_index(&elems[i]); const TargetMatrix* W = pd.targetMatrices.get_element_corner_tags( &pd, elem_idx, err ); MSQ_ERRFALSE(err); //initial c_scalars and zeta_vector to 0.0 and calculate Y for //each vertex in the this corner. zeta_vector.set( 0.0, 0.0, 0.0); for(j=0;j<local_matrix_map_used;++j){ c_scalars[j]=0.0; if(local_matrix_map[j] < 0){ MSQ_SETERR(err)("Invalid index returned from MsqMeshEntity.\n", MsqError::INVALID_STATE); return false; } inv(z_mat[j],W[local_matrix_map[j]]); //inv(z_mat[j], I); z_mat_transpose=transpose(z_mat[j]); matmult( y_mat[j], z_mat[j], z_mat_transpose); //std::cout<<"\n j "<<j<<"\n"; //std::cout<<"\n"<<y_mat[j]<<"\n"; } //0 case (c_scalars[0]) for(j=0;j<3;++j){ for(k=0;k<3;++k){ c_scalars[0] += ((y_mat[0])[j][k]); } c_scalars[0] += ((y_mat[j+1])[j][j]); } //1, 2, and if need 3 for(j=0;j<3;++j){ for(k=0;k<3;++k){ c_scalars[j+1] -= (((y_mat[0])[j][k]) + ((y_mat[j+1])[k][j])); } c_scalars[j+1] += ((y_mat[((j+2)%3)+1])[((j+1)%3)][((j+2)%3)]); c_scalars[j+1] += ((y_mat[((j+1)%3)+1])[((j+2)%3)][((j+1)%3)]); } //now do zeta_vector for(j=0;j<3;++j){ for(k=0;k<3;++k){ zeta_vector[j] += ((z_mat[0])[k][j] - (z_mat[k+1])[k][j]); } } // accumulate this corner's contribution to the numerator // and the denominator... for(j=1;j<local_matrix_map_used;++j){ //std::cout<<"c_k ("<<j<<") ="<<c_scalars[j]<<"\n"; //std::cout<<"x_k ("<<j<<") ="<<verts[elems_verts[ (size_t) local_matrix_map[j]]]<<"\n"; new_position+=verts[elems_verts[ (size_t) local_matrix_map[j]]] *c_scalars[j]; } new_position+=zeta_vector; //std::cout<<"c_k (0) ="<<c_scalars[0]<<"\n"; //std::cout<<"zeta ="<<zeta_vector<<"\n"; scale_value+=c_scalars[0]; } if(scale_value==0.0){ MSQ_SETERR(err)("Invalid accummulation.\n", MsqError::INVALID_STATE); return false; } //divide the new position by the denominator and get the // negative sign into the equation. new_position/=(-1.0*scale_value); //debug //MSQ_DBGOUT(1) << "Original position "<<verts[free_index]<<"\n"; //MSQ_DBGOUT(1) << "New position "<<new_position<<"\n"; //actually set the new position verts[free_index].set(new_position); return true; }