void MeshPara::LSCM() { is_Parameterized = true; int nb_vertices = mesh_.n_vertices(); nlNewContext(); nlSolverParameteri(NL_SOLVER, NL_CG); nlSolverParameteri(NL_PRECONDITIONER, NL_PRECOND_JACOBI); nlSolverParameteri(NL_NB_VARIABLES, 2 * nb_vertices); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); nlSolverParameteri(NL_MAX_ITERATIONS, 5 * nb_vertices); nlSolverParameterd(NL_THRESHOLD, 1e-10); nlBegin(NL_SYSTEM); init_slover(); nlBegin(NL_MATRIX); setup_LSCM(); nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); std::cout << "Solving ..." << std::endl; nlSolve(); // Get results get_result(); // Display time and iter_num double time; NLint iterations; nlGetDoublev(NL_ELAPSED_TIME, &time); nlGetIntergerv(NL_USED_ITERATIONS, &iterations); std::cout << "Solver time: " << time << std::endl; std::cout << "Used iterations: " << iterations << std::endl; nlDeleteContext(nlGetCurrent()); }
static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq) { LaplacianSystem *sys; sys= MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem"); sys->verts= MEM_callocN(sizeof(float*)*totvert, "LaplacianSystemVerts"); sys->vpinned= MEM_callocN(sizeof(char)*totvert, "LaplacianSystemVpinned"); sys->faces= MEM_callocN(sizeof(int)*3*totface, "LaplacianSystemFaces"); sys->totvert= 0; sys->totface= 0; sys->areaweights= 1; sys->storeweights= 0; /* create opennl context */ nlNewContext(); nlSolverParameteri(NL_NB_VARIABLES, totvert); if(lsq) nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); sys->context= nlGetCurrent(); return sys; }
void leastSquaresSystem::solve(double *vs) { int i; Node *n; coeffIndexPair *f; nlNewContext(); nlSolverParameteri(NL_SOLVER, NL_PERM_SUPERLU_EXT); nlSolverParameteri(NL_NB_VARIABLES, num_variables); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE) ; nlSolverParameteri(NL_MAX_ITERATIONS, 1000) ; nlSolverParameterd(NL_THRESHOLD, 1e-10) ; nlBegin(NL_SYSTEM); for (i=0; i<num_variables; i++) { nlSetVariable(i, vs[i]); if (locks[i]) nlLockVariable(i); } nlBegin(NL_MATRIX); for (i=0; i<num_equations; i++) { nlRowParameterd(NL_RIGHT_HAND_SIDE, known_term[0][i]); nlBegin(NL_ROW); for (n=rows[i].cips.head(); n!=NULL; n=n->next()) { f = (coeffIndexPair *)n->data; nlCoefficient(f->index, f->coeff); } nlEnd(NL_ROW); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); nlSolve(); for (i=0; i<num_variables; i++) vs[i] = nlGetVariable(i); nlDeleteContext(nlGetCurrent()); }
void sparse3System::solve(double *vs) { int i, j; Node *n; coeffIndexPair *f; for (j=0; j<3; j++) { nlNewContext(); nlSolverParameteri(NL_SOLVER, NL_PERM_SUPERLU_EXT); nlSolverParameteri(NL_NB_VARIABLES, num_variables); nlBegin(NL_SYSTEM); for (i=0; i<num_variables; i++) { nlSetVariable(i, vs[i*3 + j]); if (locks[i]) nlLockVariable(i); } nlBegin(NL_MATRIX); for (i=0; i<num_equations; i++) { nlRowParameterd(NL_RIGHT_HAND_SIDE, known_term[j][i]); nlBegin(NL_ROW); for (n=rows[i].cips.head(); n!=NULL; n=n->next()) { f = (coeffIndexPair *)n->data; nlCoefficient(f->index, f->coeff); } nlEnd(NL_ROW); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); nlSolve(); for (i=0; i<num_variables; i++) vs[i*3 + j] = nlGetVariable(i); nlDeleteContext(nlGetCurrent()); } }
// Solves the system for j'th component of B bool sparseSystem::solve(double *x, int j) { int i; Node *n; coeffIndexPair *f; nlNewContext(); nlSolverParameteri(NL_SOLVER, NL_PERM_SUPERLU_EXT); nlSolverParameteri(NL_NB_VARIABLES, num_variables); nlBegin(NL_SYSTEM); for (i=0; i<num_variables; i++) nlSetVariable(i, x[i]); nlBegin(NL_MATRIX); for (i=0; i<num_equations; i++) { nlRowParameterd(NL_RIGHT_HAND_SIDE, known_term[j][i]); nlBegin(NL_ROW); for (n=rows[i].cips.head(); n!=NULL; n=n->next()) { f = (coeffIndexPair *)n->data; nlCoefficient(f->index, f->coeff); } nlEnd(NL_ROW); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); bool success = (bool)nlSolve(); if (success) for (i=0; i<num_variables; i++) x[i] = nlGetVariable(i); nlDeleteContext(nlGetCurrent()); return success; }
static void laplaciansmoothModifier_do( LaplacianSmoothModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { LaplacianSystem *sys; MDeformVert *dvert = NULL; MDeformVert *dv = NULL; float w, wpaint; int i, iter; int defgrp_index; DM_ensure_tessface(dm); sys = init_laplacian_system(dm->getNumEdges(dm), dm->getNumTessFaces(dm), numVerts); if (!sys) { return; } sys->mfaces = dm->getTessFaceArray(dm); sys->medges = dm->getEdgeArray(dm); sys->vertexCos = vertexCos; sys->min_area = 0.00001f; modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index); sys->vert_centroid[0] = 0.0f; sys->vert_centroid[1] = 0.0f; sys->vert_centroid[2] = 0.0f; memset_laplacian_system(sys, 0); #ifdef OPENNL_THREADING_HACK modifier_opennl_lock(); #endif nlNewContext(); sys->context = nlGetCurrent(); nlSolverParameteri(NL_NB_VARIABLES, numVerts); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); nlSolverParameteri(NL_NB_ROWS, numVerts); nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); init_laplacian_matrix(sys); for (iter = 0; iter < smd->repeat; iter++) { nlBegin(NL_SYSTEM); for (i = 0; i < numVerts; i++) { nlSetVariable(0, i, vertexCos[i][0]); nlSetVariable(1, i, vertexCos[i][1]); nlSetVariable(2, i, vertexCos[i][2]); if (iter == 0) { add_v3_v3(sys->vert_centroid, vertexCos[i]); } } if (iter == 0 && numVerts > 0) { mul_v3_fl(sys->vert_centroid, 1.0f / (float)numVerts); } nlBegin(NL_MATRIX); dv = dvert; for (i = 0; i < numVerts; i++) { nlRightHandSideSet(0, i, vertexCos[i][0]); nlRightHandSideSet(1, i, vertexCos[i][1]); nlRightHandSideSet(2, i, vertexCos[i][2]); if (iter == 0) { if (dv) { wpaint = defvert_find_weight(dv, defgrp_index); dv++; } else { wpaint = 1.0f; } if (sys->zerola[i] == 0) { if (smd->flag & MOD_LAPLACIANSMOOTH_NORMALIZED) { w = sys->vweights[i]; sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w; w = sys->vlengths[i]; sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w; if (sys->numNeEd[i] == sys->numNeFa[i]) { nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda) * wpaint); } else { nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f); } } else { w = sys->vweights[i] * sys->ring_areas[i]; sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / (4.0f * w); w = sys->vlengths[i]; sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w; if (sys->numNeEd[i] == sys->numNeFa[i]) { nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda) * wpaint / (4.0f * sys->ring_areas[i])); } else { nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f); } } } else { nlMatrixAdd(i, i, 1.0f); } } } if (iter == 0) { fill_laplacian_matrix(sys); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE)) { validate_solution(sys, smd->flag, smd->lambda, smd->lambda_border); } } nlDeleteContext(sys->context); sys->context = NULL; #ifdef OPENNL_THREADING_HACK modifier_opennl_unlock(); #endif delete_laplacian_system(sys); }
static void meshdeform_matrix_solve(MeshDeformBind *mdb) { NLContext *context; float vec[3], gridvec[3]; int a, b, x, y, z, totvar; char message[1024]; /* setup variable indices */ mdb->varidx= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformDSvaridx"); for(a=0, totvar=0; a<mdb->size3; a++) mdb->varidx[a]= (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)? -1: totvar++; if(totvar == 0) { MEM_freeN(mdb->varidx); return; } progress_bar(0, "Starting mesh deform solve"); /* setup opennl solver */ nlNewContext(); context= nlGetCurrent(); nlSolverParameteri(NL_NB_VARIABLES, totvar); nlSolverParameteri(NL_NB_ROWS, totvar); nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 1); nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); /* build matrix */ for(z=0; z<mdb->size; z++) for(y=0; y<mdb->size; y++) for(x=0; x<mdb->size; x++) meshdeform_matrix_add_cell(mdb, x, y, z); /* solve for each cage vert */ for(a=0; a<mdb->totcagevert; a++) { if(a != 0) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); } /* fill in right hand side and solve */ for(z=0; z<mdb->size; z++) for(y=0; y<mdb->size; y++) for(x=0; x<mdb->size; x++) meshdeform_matrix_add_rhs(mdb, x, y, z, a); nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); #if 0 nlPrintMatrix(); #endif if(nlSolveAdvanced(NULL, NL_TRUE)) { for(z=0; z<mdb->size; z++) for(y=0; y<mdb->size; y++) for(x=0; x<mdb->size; x++) meshdeform_matrix_add_semibound_phi(mdb, x, y, z, a); for(z=0; z<mdb->size; z++) for(y=0; y<mdb->size; y++) for(x=0; x<mdb->size; x++) meshdeform_matrix_add_exterior_phi(mdb, x, y, z, a); for(b=0; b<mdb->size3; b++) { if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR) mdb->phi[b]= nlGetVariable(0, mdb->varidx[b]); mdb->totalphi[b] += mdb->phi[b]; } if(mdb->weights) { /* static bind : compute weights for each vertex */ for(b=0; b<mdb->totvert; b++) { if(mdb->inside[b]) { copy_v3_v3(vec, mdb->vertexcos[b]); gridvec[0]= (vec[0] - mdb->min[0] - mdb->halfwidth[0])/mdb->width[0]; gridvec[1]= (vec[1] - mdb->min[1] - mdb->halfwidth[1])/mdb->width[1]; gridvec[2]= (vec[2] - mdb->min[2] - mdb->halfwidth[2])/mdb->width[2]; mdb->weights[b*mdb->totcagevert + a]= meshdeform_interp_w(mdb, gridvec, vec, a); } } } else { MDefBindInfluence *inf; /* dynamic bind */ for(b=0; b<mdb->size3; b++) { if(mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) { inf= BLI_memarena_alloc(mdb->memarena, sizeof(*inf)); inf->vertex= a; inf->weight= mdb->phi[b]; inf->next= mdb->dyngrid[b]; mdb->dyngrid[b]= inf; } } } } else { error("Mesh Deform: failed to find solution."); break; } sprintf(message, "Mesh deform solve %d / %d |||", a+1, mdb->totcagevert); progress_bar((float)(a+1)/(float)(mdb->totcagevert), message); } #if 0 /* sanity check */ for(b=0; b<mdb->size3; b++) if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR) if(fabs(mdb->totalphi[b] - 1.0f) > 1e-4) printf("totalphi deficiency [%s|%d] %d: %.10f\n", (mdb->tag[b] == MESHDEFORM_TAG_INTERIOR)? "interior": "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]); #endif /* free */ MEM_freeN(mdb->varidx); nlDeleteContext(context); }
static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3]) { int vid, i, j, n, na; n = sys->total_verts; na = sys->total_anchors; #ifdef OPENNL_THREADING_HACK modifier_opennl_lock(); #endif if (!sys->is_matrix_computed) { nlNewContext(); sys->context = nlGetCurrent(); nlSolverParameteri(NL_NB_VARIABLES, n); nlSolverParameteri(NL_SYMMETRIC, NL_FALSE); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); nlSolverParameteri(NL_NB_ROWS, n + na); nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); nlBegin(NL_SYSTEM); for (i = 0; i < n; i++) { nlSetVariable(0, i, sys->co[i][0]); nlSetVariable(1, i, sys->co[i][1]); nlSetVariable(2, i, sys->co[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlSetVariable(0, vid, vertexCos[vid][0]); nlSetVariable(1, vid, vertexCos[vid][1]); nlSetVariable(2, vid, vertexCos[vid][2]); } nlBegin(NL_MATRIX); initLaplacianMatrix(sys); computeImplictRotations(sys); for (i = 0; i < n; i++) { nlRightHandSideSet(0, i, sys->delta[i][0]); nlRightHandSideSet(1, i, sys->delta[i][1]); nlRightHandSideSet(2, i, sys->delta[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); nlMatrixAdd(n + i, vid, 1.0f); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE)) { sys->has_solution = true; for (j = 1; j <= sys->repeat; j++) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); rotateDifferentialCoordinates(sys); for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (!nlSolveAdvanced(NULL, NL_FALSE)) { sys->has_solution = false; break; } } if (sys->has_solution) { for (vid = 0; vid < sys->total_verts; vid++) { vertexCos[vid][0] = nlGetVariable(0, vid); vertexCos[vid][1] = nlGetVariable(1, vid); vertexCos[vid][2] = nlGetVariable(2, vid); } } else { sys->has_solution = false; } } else { sys->has_solution = false; } sys->is_matrix_computed = true; } else if (sys->has_solution) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); for (i = 0; i < n; i++) { nlRightHandSideSet(0, i, sys->delta[i][0]); nlRightHandSideSet(1, i, sys->delta[i][1]); nlRightHandSideSet(2, i, sys->delta[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); nlMatrixAdd(n + i, vid, 1.0f); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_FALSE)) { sys->has_solution = true; for (j = 1; j <= sys->repeat; j++) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); rotateDifferentialCoordinates(sys); for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (!nlSolveAdvanced(NULL, NL_FALSE)) { sys->has_solution = false; break; } } if (sys->has_solution) { for (vid = 0; vid < sys->total_verts; vid++) { vertexCos[vid][0] = nlGetVariable(0, vid); vertexCos[vid][1] = nlGetVariable(1, vid); vertexCos[vid][2] = nlGetVariable(2, vid); } } else { sys->has_solution = false; } } else { sys->has_solution = false; } } #ifdef OPENNL_THREADING_HACK modifier_opennl_unlock(); #endif }