Example #1
0
TEST(Arith, SparseDenseMult)
{
    i64 arrayDims[] = {2200L, 2100L};
    i64 blockDims[] = {1200L, 1100L};
    u8  orders[] = {0,1};
    i64 rows = arrayDims[0];
    i64 cols = arrayDims[1];

    i64 total = rows*cols/100; // sparsity=1/100
    SparseMatrix::Element *elements = new SparseMatrix::Element[total];
    for (int i=0; i<total; ++i) {
        elements[i].coord = Matrix::Coord(rand() % rows, rand() % cols);
        elements[i].datum = i+1;
    }

    BlockBased<2> *block = new BlockBased<2>(arrayDims, blockDims, orders, orders);
    StorageParam sp;
    sp.type = BTREE;
    sp.fileName = "a.bin";
    sp.intSp = 'M';
    sp.leafSp = 'B';
    sp.useDenseLeaf = config->useDenseLeaf;
    Matrix a(&sp, MDCoord<2>(arrayDims), block);
    MDCoord<2> begin(0, 0), end(rows-1, cols-1);
    SparseMatrix asp(elements, total, begin, end, false);
    a.batchPut(begin, asp);

    // // check a block in a
    // for (int ii=0; ii<3;++ii)
    //     for (int jj=0; jj<3;++jj)
    // 	    {
    // 		SparseMatrix sm = a.batchGet(MDCoord<2>(ii*1000,jj*1000),
    // 					     MDCoord<2>((ii+1)*1000-1,(jj+1)*1000-1));
    // 		cholmod_sparse *sp = sm.storage();
    // 		int *p = (int*) sp->p;
    // 		int *r = (int*) sp->i;
    // 		int *p1 = (int*) asp.storage()->p;
    // 		int *r1 = (int*) asp.storage()->i;
    // 		double *x1 = (double*) asp.storage()->x;
    // 		double *x = (double*) sp->x;
    // 		for (int j=0; j<sp->ncol; ++j) {
    // 		    int l = p1[j+jj*1000];
    // 		    int colend = std::min(int(asp.storage()->ncol), j+1+jj*1000);
    // 		    for (int i=p[j]; i<p[j+1]; i++) {
    // 			// find element [k,j] in asp and check data
    // 			for (; l<p1[colend]; l++)
    // 			    if (r1[l] == r[i]+ii*1000) {
    // 				ASSERT_DOUBLE_EQ(x1[l], x[i]);
    // 				break;
    // 			    }
    // 			if (l==p1[colend])
    // 			    ASSERT_TRUE(false);
    // 		    }
    // 		}
    // 	    }
    Linearization<2> *block1 = block->transpose();
    sp.fileName = "b.bin";
    Matrix b(&sp, MDCoord<2>(cols, rows), block1);
    total = rows * cols;
    Datum_t *data = new Datum_t[total];
    for (int i=0; i<total; ++i) {
        data[i] = i;
    }
    b.batchPut(begin, MDCoord<2>(cols-1, rows-1), data);

    // // check block in b
    // for (int ii=0; ii<3; ++ii)
    //     for (int jj=0; jj<3; ++jj)
    // 	    {
    // 		Datum_t *x = new Datum_t[1000*1000];
    // 		b.batchGet(MDCoord<2>(ii*1000,jj*1000), MDCoord<2>(ii*1000+999,jj*1000+999), x);
    // 		int rowend = std::min(1000, int(cols-ii*1000));
    // 		int colend = std::min(1000, int(rows-jj*1000));
    // 		for (int i=0; i<rowend; ++i)
    // 		    for (int j=0; j<colend; ++j) {
    // 			ASSERT_DOUBLE_EQ(data[i+ii*1000+(j+jj*1000)*cols], x[i+j*1000]);
    // 		    }
    // 		delete[] x;
    // 	    }

    Matrix c = a*b;

    // // compute c[2,0] manually
    // double c20 = 0;
    // int *p = (int*) asp.storage()->p;
    // int *i = (int*) asp.storage()->i;
    // double *x = (double*) asp.storage()->x;
    // for (int j=0; j<cols; j++) {
    //     for (int k=p[j]; k<p[j+1]; k++) {
    //         if (i[k] == 2)
    //             c20 += x[k] * data[j+rows*0]; // a[2,j] * b[j,0]
    //     }
    // }
    // cout<<"c[2,0]="<<c20<<endl;

    // check correctness against in-memory cholmod_sdmult
    cholmod_dense *resultd = cholmod_allocate_dense(rows, rows, rows, CHOLMOD_REAL,
						    SparseMatrix::chmCommon);
    cholmod_dense rightd;
    rightd.nrow = cols;
    rightd.ncol = rows;
    rightd.nzmax = total;
    rightd.d = rightd.nrow;
    rightd.x = data;
    rightd.xtype = CHOLMOD_REAL;
    rightd.dtype = CHOLMOD_DOUBLE;
    double alpha[] = {1, 0};
    double beta[]  = {0, 0};
    cholmod_sdmult(
		   asp.storage(), // cholmod_sparse
		   0, // no transpose
		   alpha, // scaling factor for sparse matrix
		   beta, // scaling factor for result
		   &rightd,
		   resultd,
		   SparseMatrix::chmCommon);
    double * result = (double*) resultd->x;
    for (int i=0; i<rows; ++i) // col
        for (int j=0; j<rows; ++j) { // row
            Datum_t d;
            c.get(MDCoord<2>(j,i), d);
            ASSERT_DOUBLE_EQ(result[j+i*rows],
			     d)<<j<<"\t"<<i<<"\t"<<result[j*rows+i];
        }
    cholmod_free_dense(&resultd, SparseMatrix::chmCommon);
    delete[] elements;
    delete[] data;
    delete block;
    delete block1;
}
Example #2
0
TEST(Arith, SparseSparseMult)
{
    i64 arrayDims[] = {2200L, 2100L};
    i64 blockDims[] = {1200L, 1100L};
    //i64 arrayDims[] = {8L, 7L};
    //i64 blockDims[] = {3L, 2L};
    u8  orders[] = {0,1};
    i64 rows = arrayDims[0];
    i64 cols = arrayDims[1];

    i64 total = rows*cols/100; // sparsity=1/100
    SparseMatrix::Element *elements = new SparseMatrix::Element[total];
    for (int i=0; i<total; ++i) {
        elements[i].coord = Matrix::Coord(rand() % rows, rand() % cols);
        elements[i].datum = i+1;
	//cout<<elements[i].coord<<'\t'<<elements[i].datum<<endl;
    }

    double *temp = new double[rows*cols];

    BlockBased<2> *block = new BlockBased<2>(arrayDims, blockDims, orders, orders);
    StorageParam sp;
    sp.type = BTREE;
    sp.fileName = "a.bin";
    sp.intSp = 'M';
    sp.leafSp = 'B';
    sp.useDenseLeaf = config->useDenseLeaf;
    Matrix a(&sp, MDCoord<2>(arrayDims), block);
    MDCoord<2> begin(0, 0);
    SparseMatrix asp(elements, total, begin, MDCoord<2>(rows-1, cols-1), false);
    a.batchPut(begin, asp);

    a.batchGet(begin, MDCoord<2>(rows-1, cols-1), temp);
    for (SparseMatrix::Iterator it = asp.begin();
            it != asp.end();
            ++it) {
        ASSERT_DOUBLE_EQ(it->datum, temp[it->coord[0]+it->coord[1]*rows]);
    }

    Linearization<2> *block1 = block->transpose();
    sp.fileName = "b.bin";
    Matrix b(&sp, MDCoord<2>(cols, rows), block1);
    for (int i=0; i<total; ++i) {
        i64 temp = elements[i].coord[0];
        elements[i].coord[0] = elements[i].coord[1];
        elements[i].coord[1] = temp;
    }
    SparseMatrix bsp(elements, total, begin, MDCoord<2>(cols-1, rows-1), false);
    b.batchPut(begin, bsp);

    b.batchGet(begin, MDCoord<2>(cols-1, rows-1), temp);
    for (SparseMatrix::Iterator it = bsp.begin();
            it != bsp.end();
            ++it) {
        ASSERT_DOUBLE_EQ(it->datum, temp[it->coord[0]+it->coord[1]*cols])
            <<it->coord;
    }
    delete[] temp;
    
    Matrix c = a*b;

    // check correctness against in-memory cholmod_ssmult
    SparseMatrix csp = asp * bsp;
    for (SparseMatrix::Iterator it = csp.begin();
            it != csp.end();
            ++it) {
        Datum_t d;
        c.get(it->coord, d);
        ASSERT_DOUBLE_EQ(it->datum, d)<<it->coord;
    }
    delete[] elements;
    delete block;
    delete block1;
}
Example #3
0
bool PassPointList::estimateSimilarityTransformation(not_null<QTransform*> out)
{
	auto num_pass_points = int(size());
	if (num_pass_points == 1)
	{
		PassPoint* point = &at(0);
		MapCoordF offset = point->dest_coords - point->src_coords;
		
		*out = QTransform::fromTranslate(offset.x(), offset.y());
		point->calculated_coords = point->dest_coords;
		point->error = 0;
	}
	else if (num_pass_points >= 2)
	{
		// Create linear equation system and solve using the pseuo inverse
		
		// Derivation:
		// (Attention: not by a mathematician. Please correct any errors.)
		//
		// Start by stating that the original coordinates (x, y) multiplied
		// with the transformation matrix should give the desired coordinates (X, Y):
		//
		// | a  b  c|   |x|   |X|
		// | d  e  f| * |y| = |Y|
		//              |1|
		//
		// The parametrization of the transformation matrix should be simplified because
		// we want to have isotropic scaling.
		// With s = scaling, r = rotation and (x, y) = offset, it looks like this:
		//
		// | s*cos(r) s*sin(r) x|    | a  b  c|
		// |-s*sin(r) s*cos(r) y| =: |-b  a  d|
		// 
		// With this, reordering the matrices to have the unknowns
		// in the second matrix results in:
		// 
		// | x  y  1  0|   |a|   |X|
		// | y -x  0  1| * |b| = |Y|
		//                 |c|
		//                 |d|
		//
		// For every pass point, two rows like this result. The complete, stacked
		// equation system is then "solved" as good as possible using the
		// pseudo inverse. Finally, s, r, x and y are recovered from a, b, c and d.
		
		Matrix mat(2*num_pass_points, 4);
		Matrix values(2*num_pass_points, 1);
		for (int i = 0; i < num_pass_points; ++i)
		{
			PassPoint* point = &at(i);
			mat.set(2*i, 0, point->src_coords.x());
			mat.set(2*i, 1, point->src_coords.y());
			mat.set(2*i, 2, 1);
			mat.set(2*i, 3, 0);
			mat.set(2*i+1, 0, point->src_coords.y());
			mat.set(2*i+1, 1, -point->src_coords.x());
			mat.set(2*i+1, 2, 0);
			mat.set(2*i+1, 3, 1);
			
			values.set(2*i, 0, point->dest_coords.x());
			values.set(2*i+1, 0, point->dest_coords.y());
		}
		
		Matrix transposed;
		mat.transpose(transposed);
		
		Matrix mat_temp, mat_temp2, pseudo_inverse;
		transposed.multiply(mat, mat_temp);
		if (!mat_temp.invert(mat_temp2))
			return false;
		mat_temp2.multiply(transposed, pseudo_inverse);
		
		// Calculate transformation parameters
		Matrix output;
		pseudo_inverse.multiply(values, output);
		
		double move_x = output.get(2, 0);
		double move_y = output.get(3, 0);
		double rotation = qAtan2((-1) * output.get(1, 0), output.get(0, 0));
		// Avoid division by (values close to) zero
		bool use_cos = (qAbs(rotation) < 0.34 * M_PI || qAbs(rotation) > 0.66 * M_PI);
		double scale = use_cos ? (output.get(0, 0) / qCos(rotation)) : (output.get(1, 0) / -qSin(rotation));
		
		// Calculate transformation matrix
		double cosr = cos(rotation);
		double sinr = sin(rotation);
		
		out->setMatrix(
			scale * cosr,    scale * sinr, 0,
			scale * (-sinr), scale * cosr, 0,
			move_x,          move_y,       1);
		
		// Transform the pass points and calculate error
		for (auto& point : *this)
		{
			point.calculated_coords = MapCoordF(out->map(point.src_coords));
			point.error = point.calculated_coords.distanceTo(point.dest_coords);
		}
	}
	
	return true;
}
Example #4
0
int main(int argc, char* argv[])
{
	if(argc < 2)
	{
		cout << "Please provide a control file name.\n";
		return -1;
	}
	
	string confile = argv[1];
	string inp, outp, outdg, jacs, dum, anglestr, solver;
	double suprad, tol;
	int nmarks;		// number of boundary markers to read
	int nrbfsteps, maxiter;
	vector<double> centre(2);
	Matrix<int> n_rot;

	ifstream conf(confile);
	conf >> dum; conf >> inp;
	conf >> dum; conf >> outp;
	conf >> dum; conf >> jacs;
	conf >> dum; conf >> anglestr;
	conf >> dum; conf >> centre[0] >> centre[1];
	conf >> dum; conf >> nmarks;

	conf >> dum;
	n_rot.setup(nmarks,1);
	for(int i = 0; i < nmarks; i++)
		conf >> n_rot(i);
	
	conf >> dum; conf >> suprad;
	conf >> dum; conf >> nrbfsteps;
	conf >> dum; conf >> solver;
	conf >> dum; conf >> tol;
	conf >> dum; conf >> maxiter;
	conf.close();

	double angle = stod(anglestr)*PI/180.0;			// convert to radians
	cout << "support radius is " << suprad << endl;
	cout << "Centre is " << centre[0] << " " << centre[1] << endl;

	// read mesh
	UMesh2d m;
	m.readGmsh2(inp,2);

	// create a vector do distinguish boundary points from interior points
	Matrix<int> flags(m.gnpoin(),1);
	flags.zeros();
	for(int i = 0; i < m.gnface(); i++)
		for(int j = 0; j < m.gnnofa(); j++)
			flags(m.gbface(i,j)) = 1;

	//calculate boundary displacement
	MRotation2d rot(&m, angle, centre[0], centre[1], n_rot);
	Matrix<double> bc = rot.rhsvect_rotate();

	// get number of interior points and boundary points
	int n_bpoin=0, n_inpoin=0;
	for(int i = 0; i < m.gnpoin(); i++)
		n_bpoin += flags(i);
	n_inpoin = m.gnpoin() - n_bpoin;

	// Split interior data and boundary data
	Matrix<double> inpoints(n_inpoin, m.gndim());
	Matrix<double> bpoints(n_bpoin, m.gndim());
	Matrix<double> bcb(n_bpoin, m.gndim());
	int k = 0;
	for(int i = 0; i < flags.rows(); i++)
		if(flags(i) == 0)
		{
			for(int j = 0; j < m.gndim(); j++)
				inpoints(k,j) = m.gcoords(i,j);
			k++;
		}
	
	k = 0;
	for(int i = 0; i < flags.rows(); i++)
		if(flags(i) == 1)
		{
			for(int j = 0; j < m.gndim(); j++){
				bpoints(k,j) = m.gcoords(i,j);
				bcb(k,j) = bc.get(i,j);
			}
			k++;
		}

	// carry out DG mapping procedure
	RBFmove d;
	d.setup(&inpoints, &bpoints, &bcb, 2, suprad, nrbfsteps, tol, maxiter,solver);
	d.move();
	inpoints = d.getInteriorPoints();
	bpoints = d.getBoundaryPoints();

	// create a coords matrix with same point numbering as initial matrix and return it
	Matrix<double> newcoords(m.gnpoin(),m.gndim());
	int a = 0, b = 0; k = 0;
	for(int i = 0; i < flags.rows(); i++)
	{
		if(flags(i) == 0)
		{
			for(int dim = 0; dim < m.gndim(); dim++)
				newcoords(k,dim) = inpoints(a,dim);
			k++;
			a++;
		}
		else
		{
			for(int dim = 0; dim < m.gndim(); dim++)
				newcoords(k,dim) = bpoints.get(b,dim);
			k++;
			b++;
		}
	}

	m.setcoords(&newcoords);
	m.writeGmsh2(outp);

	m.compute_jacobians();
	cout << "Checking jacobians\n";
	ofstream ojac(jacs);
	m.detect_negative_jacobians(ojac);
	ojac.close();

	cout << "Done.\n" << endl;
	return 0;
}
template <class T> void Matrix<T>::setBlock(int start_row, int start_column, Matrix referncedMatrix) //sets a block in a given position of row and column to the passed matrix
{
	for (int i = 0; i < referncedMatrix._M; i++) //loops through the entire passed matrix
		for (int j = 0; j < referncedMatrix._N; j++)
			_data[(start_row + i) * _N + (start_column + j)] = referncedMatrix.get(i, j); //sets the new block with the refrencedMatrix passed to the appropraite location in the matrix object calling the function
}