コード例 #1
0
ファイル: spop_misc_meat.hpp プロジェクト: JD26/ICE
inline
void
spop_resize::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1, spop_resize>& in)
  {
  arma_extra_debug_sigprint();
  
  out = in.m;
  
  out.resize(in.aux_uword_a, in.aux_uword_b);
  }
コード例 #2
0
void Assembler::operKernel(EOExpr<A> oper,const MeshHandler<ORDER>& mesh,
	                     FiniteElement<Integrator, ORDER>& fe, SpMat& OpMat)
{
	std::vector<coeff> triplets;


  	for(auto t=0; t<mesh.num_triangles(); t++)
  	{
		fe.updateElement(mesh.getTriangle(t));

		// Vector of vertices indices (link local to global indexing system)
		std::vector<UInt> identifiers;
		identifiers.resize(ORDER*3);
		for( auto q=0; q<ORDER*3; q++)
			identifiers[q]=mesh.getTriangle(t)[q].id();


		//localM=localMassMatrix(currentelem);
		for(int i = 0; i < 3*ORDER; i++)
		{
			for(int j = 0; j < 3*ORDER; j++)
			{
				Real s=0;

				for(int l = 0;l < Integrator::NNODES; l++)
				{
					s += oper(fe,i,j,l) * fe.getDet() * fe.getAreaReference()* Integrator::WEIGHTS[l];//(*)
				}
			  triplets.push_back(coeff(identifiers[i],identifiers[j],s));
			}
		}

	}

  	UInt nnodes = mesh.num_nodes();
  	OpMat.resize(nnodes, nnodes);
	OpMat.setFromTriplets(triplets.begin(),triplets.end());
	//cout<<"done!"<<endl;;
}
コード例 #3
0
// The Real Core Function doing the actual mesh processing.
bool FilterHarmonicPlugin::applyFilter(QAction * action, MeshDocument & md, RichParameterSet & par, vcg::CallBackPos * cb)
{
	switch(ID(action))
	{
	case FP_SCALAR_HARMONIC_FIELD :
	{
		typedef vcg::GridStaticPtr<CMeshO::VertexType, CMeshO::ScalarType> VertexGrid;

		typedef double                           CoeffScalar; // TODO, when moving the code to a class make it a template (CoeffScalar = double)

		typedef CMeshO::ScalarType               ScalarType;
		typedef CMeshO::CoordType                CoordType;
		typedef CMeshO::VertexType               VertexType;
		typedef CMeshO::FaceType                 FaceType;

		typedef Eigen::Triplet<CoeffScalar>      T;
		typedef Eigen::SparseMatrix<CoeffScalar> SpMat; //sparse matrix type of double


		CMeshO & m = md.mm()->cm;

		vcg::tri::Allocator<CMeshO>::CompactFaceVector(m);
		vcg::tri::Allocator<CMeshO>::CompactVertexVector(m);

		md.mm()->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTMARK);
		vcg::tri::UpdateBounding<CMeshO>::Box(m);
		vcg::tri::UpdateTopology<CMeshO>::FaceFace(m);

		int n  = m.VN();
		int fn = m.FN();

		std::vector<T>             coeffs; // coefficients of the system
		std::map<size_t,CoeffScalar> sums; // row sum of the coefficient

		SpMat laplaceMat; // the system to be solved
		laplaceMat.resize(n, n);

		Log("Generating coefficients.`");
		cb(0, "Generating coefficients...");
		vcg::tri::UpdateFlags<CMeshO>::FaceClearV(m);
		// Iterate over the faces
		for (size_t i = 0; i < m.face.size(); ++i)
		{
			CMeshO::FaceType & f = m.face[i];

			if (f.IsD())
			{
				assert(int(i) == fn);
				break; // TODO FIX the indexing of vertices
			}

			assert(!f.IsV());
			f.SetV();

			// Generate coefficients for each edge
			for (int idx = 0; idx < 3; ++idx)
			{
				CoeffScalar weight;
				WeightInfo res = ComputeWeight<FaceType, CoeffScalar>(f, idx, weight);

				switch (res)
				{
				case EdgeAlreadyVisited : continue;
				case Success            : break;
				case BorderEdge         :
					this->errorMessage = "Mesh not closed, cannot compute harmonic field on mesh containing holes or borders";
					return false;
				default: assert(0);
				}

//				if (weight < 0) weight = 0; // TODO check if negative weight may be an issue

				// Add the weight to the coefficients vector for both the vertices of the considered edge
				size_t v0_idx = vcg::tri::Index(m, f.V0(idx));
				size_t v1_idx = vcg::tri::Index(m, f.V1(idx));

				coeffs.push_back(T(v0_idx, v1_idx, -weight));
				coeffs.push_back(T(v1_idx, v0_idx, -weight));

				// Add the weight to the row sum
				sums[v0_idx] += weight;
				sums[v1_idx] += weight;
			}

			f.SetV();
		}

		// Fill the system matrix
		Log("Fill the system matrix");
		cb(10, "Filling the system matrix...");
		laplaceMat.reserve(coeffs.size());
		for (std::map<size_t,CoeffScalar>::const_iterator it = sums.begin(); it != sums.end(); ++it)
		{
			coeffs.push_back(T(it->first, it->first, it->second));
		}
		laplaceMat.setFromTriplets(coeffs.begin(), coeffs.end());

		// Get the two vertices with value set
		VertexGrid vg;
		vg.Set(m.vert.begin(), m.vert.end());

		vcg::vertex::PointDistanceFunctor<ScalarType> pd;
		vcg::tri::Tmark<CMeshO, VertexType> mv;
		mv.SetMesh(&m);
		mv.UnMarkAll();
		CoordType  closestP;
		ScalarType minDist = 0;
		VertexType * vp0 = vcg::GridClosest(vg, pd, mv, par.getPoint3f("point1"), m.bbox.Diag(), minDist, closestP);
		VertexType * vp1 = vcg::GridClosest(vg, pd, mv, par.getPoint3f("point2"), m.bbox.Diag(), minDist, closestP);
		if (vp0 == NULL || vp1 == NULL || vp0 == vp1)
		{
			this->errorMessage = "Error occurred for selected points.";
			return false;
		}

		size_t v0_idx = vcg::tri::Index(m, vp0);
		size_t v1_idx = vcg::tri::Index(m, vp1);

		// Add penalty factor alpha
		Log("Setting up the system matrix");
		const CoeffScalar alpha = pow(10, 8);

		Eigen::Matrix<CoeffScalar, Eigen::Dynamic, 1> b, x; // Unknown and known terms vectors
		b.setZero(n);
		b(v0_idx) = alpha * par.getFloat("value1");
		b(v1_idx) = alpha * par.getFloat("value2");

		laplaceMat.coeffRef(v0_idx, v0_idx) += alpha;
		laplaceMat.coeffRef(v1_idx, v1_idx) += alpha;

		// Solve system laplacianMat x = b
		Log("System matrix decomposition...");
		cb(20, "System matrix decomposition...");
		Eigen::SimplicialLDLT<Eigen::SparseMatrix<CoeffScalar> > solver; // TODO eventually use another solver
		solver.compute(laplaceMat);
		if(solver.info() != Eigen::Success)
		{
			// decomposition failed
			this->errorMessage = "System matrix decomposition failed: ";
			if (solver.info() == Eigen::NumericalIssue)
				this->errorMessage += "numerical issue.";
			else if (solver.info() == Eigen::NoConvergence)
				this->errorMessage += "no convergence.";
			else if (solver.info() == Eigen::InvalidInput)
				this->errorMessage += "invalid input.";

			return false;
		}

		Log("Solving the system...");
		cb(85, "Solving the system...");
		x = solver.solve(b);
		if(solver.info() != Eigen::Success)
		{
			// solving failed
			this->errorMessage = "System solving failed.";
			return false;
		}

		// Colorize bands for the 0-1 interval
		if (par.getBool("colorize"))
		{
			float steps = 20.0f;
			for (size_t i = 0; int(i) < n; ++i)
			{
				bool on = (int)(x[i]*steps)%2 == 1;
				if (on)
				{
					m.vert[i].C() = vcg::Color4b::ColorRamp(0,2,x[i]);
				}
				else
				{
					m.vert[i].C() = vcg::Color4b::White;
				}
			}
		}

		// Set field value into vertex quality attribute
		for (size_t i = 0; int(i) < n; ++i)
		{
			m.vert[i].Q() = x[i];
		}

		cb(100, "Done.");

		return true;
	}
	default : assert(0);
	}
	return false;
}
コード例 #4
0
ファイル: ADMMCut.cpp プロジェクト: lock794779857/FrameFab
void ADMMCut::CalculateQ(const VX _D, SpMat &Q)
{
	// Construct Hessian Matrix for D-Qp problem
	Q.resize(6 * Ns_, Nd_);
	vector<Eigen::Triplet<double>> Q_list;

	for (int i = 0; i < Ns_; i++)
	{
		int u = ptr_dualgraph_->v_orig_id(i);
		WF_edge *edge = ptr_frame_->GetNeighborEdge(u);

		while (edge != NULL)
		{
			int e_id = ptr_dualgraph_->e_dual_id(edge->ID());
			if (e_id != -1)
			{
				int v = edge->pvert_->ID();
				int j = ptr_dualgraph_->v_dual_id(v);

				MX eKuu = ptr_stiff_->eKv(edge->ID());
				MX eKeu = ptr_stiff_->eKe(edge->ID());
				VX Fe = ptr_stiff_->Fe(edge->ID());
				VX Di(6);
				VX Dj(6);

				if (i < Ns_ && j < Ns_)
				{
					for (int k = 0; k < 6; k++)
					{
						Di[k] = _D[6 * i + k];
						Dj[k] = _D[6 * j + k];
					}
				}
				else
				{
					if (i < Ns_)
					{
						for (int k = 0; k < 6; k++)
						{
							Di[k] = _D[6 * i + k];
							Dj[k] = 0;
						}
					}

					if (j < Ns_)
					{
						for (int k = 0; k < 6; k++)
						{
							Di[k] = 0;
							Dj[k] = _D[6 * j + k];
						}
					}
				}
				VX Gamma = eKuu * Di + eKeu * Dj - Fe;

				for (int k = 0; k < 6; k++)
				{
					Q_list.push_back(Triplet<double>(6 * i + k, e_id, Gamma[k]));
				}
			}

			edge = edge->pnext_;
		}
	}

	Q.setFromTriplets(Q_list.begin(), Q_list.end());
}
コード例 #5
0
ファイル: LAMGLSSolver.cpp プロジェクト: nomadster/lamg_cpp
LevelElimination * LAMGLSSolver::coarsenElimination(const Matrix & finerMatrix) {
cout << "coarsenElimination()" << endl;
    //Per salvare i P ed i q
    std::vector<qPStage*> cStages;
    /* Prealloco spazio per al più SETUP_ELIMINATION_MAX_STAGES così evito
     * possibili riallocazioni */
    cStages.reserve(SETUP_ELIMINATION_MAX_STAGES);

    //Copio la matrice così posso modificarla senza modificare quella del finerLevel
    Matrix A(finerMatrix);
    Matrix Acc; //Per lo Schur Complement System
    Matrix Acf; //Per lo Schur Complement System
    // Il numero di stage di eliminazione eseguiti sulla matrice A
    size_t stageNum = 0;

    /* Vector che vengono riusati*/
    DynamicVector<size_t> Cset; //Insieme dei nodi da non eliminare
    DynamicVector<size_t> Fset; //Insieme dei nodi da eliminare
    DynamicVector<size_t> degree; //Grado di ciascun nodo
    DynamicVector<size_t> candidate; //Nodi candidati all'eliminazione
    DynamicVector<NodeEliminationStatus> status; //Stato dei nodi
    /* P è sempre sparsa anche quando A è densa */
    SpMat P;
    DynamicVector<double> q;

    while (stageNum < SETUP_ELIMINATION_MAX_STAGES) {

        size_t A_rows = A.rows();
        if (A_rows <= MAX_DIRECT_SOLVE_SIZE)
            break;
        /* (1) Calcola il vettore degree della matrice. */
        degree.resize(A_rows);

        for (size_t i = 0; i < A_rows; ++i) {
            degree[i] = A.nonZeros(i);
            if (A(i, i) != 0)//Tolgo l'elemento sulla diagonale
                degree[i]--;
            else
                cerr << "La diagionale i-esima c'ha lelemento a zero!!! ERRORE MORTALE!!!" << endl;
        }

        /* (2) [f c ] = lowDegreeNodes(A,degree,MaxDegree)  */
        candidate.resize(A_rows);
        candidate = 0;
        /* Individuo i nodi candidati (degree[i] <= MAX_DEGREE) */
        size_t cnnZ = 0; //Devo usare questa variabili perché i valori "settati" di candidate comprendono il valore "0" cioè il nodo 0
        for (size_t i = 0; i < A_rows; ++i) {
            if (degree[i] <= SETUP_ELIMINATION_MAX_DEGREE) {
                candidate[cnnZ++] = i;
            }
        }
        /* I primi cnnZ elementi sono stati inizializzati */
        candidate.resize(cnnZ, true);

        status.resize(A_rows);
        status = HIGH_DEGREE; //Tutti gli elementi prendono HIGH_DEGREE
        //    status(candidate)  = 0; % Reset all relevant nodes to "not visited"
        for (size_t i = 0; i < candidate.size(); ++i) {
            status[candidate[i]] = NOT_DECIDED;
        }

        for (size_t k = 0; k < candidate.size(); ++k) {
            lowdegreesweep(A, candidate[k], status); //Template call
        }

        /* Adesso devo creare i vettori F e C, inserendovi i nodi che verranno
         * o meno eliminati */
        size_t nf = 0; //|Fset|
        size_t nc = 0; //|Cset|
        Cset.resize(A_rows, false);
        Fset.resize(A_rows, false);
        for (size_t i = 0; i < A_rows; ++i) {
            if (status[i] == LOW_DEGREE)
                Fset[nf++] = i; //Inserisco il nodo i nell'insieme F
            else
                Cset[nc++] = i; //Lo inserisco invece in C
        }

        /* L'insieme C non può mai essere vuoto, dobbiamo lasciargli almeno
         * un elemento
         */
        if (nc == 0) {
            Cset[nc++] = Fset[--nf];
            Fset[nf] = 0;

        }
        Cset.resize(nc, true); //nc non è mai 0
        Fset.resize(nf, true);

        /* FINE di (2) [f c ] = lowDegreeNodes(A,degree,MaxDegree) */


        if ((nf <= SETUP_ELIMINATION_MIN_ELIM_FRACTION * A_rows)) {
            /* Il coarsening non è abbastanza efficace perché andiamo ad eliminare
             * un numero, nf, di nodi che è inferiore alla minima soglia accettabile
             * di eliminazione. Ci fermiamo senza eliminare.*/
            break;
        }


        /* (3) Una volta individuati i nodi da eliminare devo calcolare gli
         * operatori P e q che mi consentono di eliminare tutti questi nodi
         *      [R, q] = eliminationOperators(A, f, index);
         */


        /* In MEX si crea una matrice columnMajor che poi verrà trasposta perché
         * le matrici di Matlab sono columnMajor e se uno vuole sfruttare la
         * rappresentazione interna deve usarle così.
         * Noi invece possiamo già generare la matrice trasposta costruendo
         * direttamente la matrice rowMajor e "sostituendo" ai termini riga
         * quelli colonna.
         */
        /* P è sempre una matrice sparsa perché il numero dei suoi nonzero
         * e basso anche quando A è densa */
        P.resize(nf, nc, false);
        q.resize(nf, false);

        /* Quanti elemenenti abbiamo salvato in Q (e quante righe di R
         * abbiamo costruito)
         */
        size_t P_row = 0;
        size_t P_col = 0;
        /* Per ogni f-riga di A prendi ciascun c-elemento di questa riga e formaci
         * la i-esima riga di R. L'inverso dell'f-esimo elemento di ciascuna f-riga
         * va messo in q. Inoltre ciascuna riga i di R va scalata di un fattore -q[i]
         */
        for (DynamicVector<size_t>::Iterator dvit = Fset.begin(); dvit != Fset.end(); dvit++) {
            eliminationOperators(A, Cset, (*dvit), q, P, P_col, P_row);
            P_row++; //Passiamo alla prosssima riga
        }
        //Salvo i dati così creati nel cStages
        cStages.push_back(new qPStage(new SpMat(P), new DynamicVector<double>(q),
                new DynamicVector<size_t>(Fset), new DynamicVector<size_t>(Cset), (nf + nc)));
        /* FINE (03) [R, q] = eliminationOperators(A, f, index);*/




        /* (4) Adesso devo calcolare il sistema complementare di Schur dato da
         *  A = Ac,c + Ac,f*R^t         */

        /* Acc è la sottomatrice di A che ha come elementi tutti gli a_ij tali
         * che (ij) appartiene a Cset x Cset. Quindi per ogni riga crow devo
         * prenderci tutti gli elementi che hanno indice pari a ccol */
        MtxOps::submatrix(A, Cset, Cset, Acc);

        /* Acf invece ha nc righe e nf colonne*/
        MtxOps::submatrix(A, Cset, Fset, Acf);
        /* Finalmente posso aggiornare A*/
        A = Acc + Acf * P;
        /* Acc_[nc x nc] + (Acf * P)_[nc x nc].
         * Dunque La matrice A risultante diventa una nc x nc e perdiamo esattamente nf nodi.*/
    }//Fine while(stageNum...)

    /* Usciti dal while dobbiamo creare il livello, se è possibile farlo */
    LevelElimination* ret = NULL;
    if (stageNum != 0) {

        if (useSparse) {
            if (isSparseOK(A)) {
                ret = new LevelElimination(new SpMat(A), cStages, multiGrid.back());
            } else {
                useSparse = false;
                ret = new LevelElimination(new DMat(A), cStages, multiGrid.back());
            }
        } else {

            ret = new LevelElimination(new DMat(A), cStages, multiGrid.back());
        }
    }
cout << "coarsenElimination() finito" << endl;
    return ret;
}