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());	
}
Exemple #2
0
int laplacian_system_solve(LaplacianSystem *sys)
{
	nlEnd(NL_MATRIX);
	nlEnd(NL_SYSTEM);
	sys->nlbegun = 0;

	//nlPrintMatrix();

	return nlSolveAdvanced(NULL, NL_TRUE);
}
// LSCM equation, geometric form :
// (Z1 - Z0)(U2 - U0) = (Z2 - Z0)(U1 - U0)
// Where Uk = uk + i.vk is the complex number 
//                       corresponding to (u,v) coords
//       Zk = xk + i.yk is the complex number 
//                       corresponding to local (x,y) coords
void MeshPara::setup_conformal_map_relations(Mesh::FHandle fh)
{
	int id[3];
	Vec3f p[3];
	auto fv = mesh_.fv_begin(fh);
	for (int i = 0; i < 3; i++, fv++)
	{
		p[i] = mesh_.point(*fv);
		id[i] = (*fv).idx();
	}

	Vec2f z[3];
	project_triangle(p[0], p[1], p[2], z[0], z[1], z[2]);
	Vec2f z01 = z[1] - z[0];
	Vec2f z02 = z[2] - z[0];
	double a = z01[0];
	double b = z01[1];
	double c = z02[0];
	double d = z02[1];
	assert(b == 0.0);

	// Note  : 2*id + 0 --> u
	//         2*id + 1 --> v
	int u0_id = 2 * id[0];
	int v0_id = 2 * id[0] + 1;
	int u1_id = 2 * id[1];
	int v1_id = 2 * id[1] + 1;
	int u2_id = 2 * id[2];
	int v2_id = 2 * id[2] + 1;

	// Note : b = 0

	// Real part
	nlBegin(NL_ROW);
	nlCoefficient(u0_id, -a + c);
	nlCoefficient(v0_id, b - d);
	nlCoefficient(u1_id, -c);
	nlCoefficient(v1_id, d);
	nlCoefficient(u2_id, a);
	nlEnd(NL_ROW);

	// Imaginary part
	nlBegin(NL_ROW);
	nlCoefficient(u0_id, -b + d);
	nlCoefficient(v0_id, -a + c);
	nlCoefficient(u1_id, -d);
	nlCoefficient(v1_id, -c);
	nlCoefficient(v2_id, a);
	nlEnd(NL_ROW);
}
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);
}
Exemple #8
0
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
}