void LUDecompositionTest::testLU()
{
  Matrix<4,4,double> A;
  assignList(A) =
      5.0, 2.0, 3.0, 1.0,
      6.0, 3.0, 6.0, 1.0,
      3.0, 2.0, 5.0, 4.0,
      4.0, 1.0, 2.0, 1.0;
  Matrix<4,4,double> Acopy(A);
  Vector<4,int> pivots;
  lu(A,pivots);
  Matrix<4,4,double> L(A);
  for (int i=0; i < 4; i++){
    L(i,i) = 1.0;
    for (int j=i+1; j < 4; j++){
      L(i,j) = 0.0;
    }
  }
  Matrix<4,4,double> R(A);
  for (int j=0; j < 4; j++){
    for (int i=j+1; i < 4; i++){
      R(i,j) = 0.0;
    }
  }
  assign(A) = 0.0;
  multiply (L, R, A);
  for (int i=0; i < 4; i++){
    for (int j=0; j < 4; j++){
      double temp = Acopy(i,j);
      Acopy(i,j) = Acopy(pivots(i),j);
      Acopy(pivots(i),j) = temp;
    }
  }
  //TODO validateWithParams1 (equals(A, Acopy), A);
}
//---------------------------------------------------------------------------
Matrix invert(const Matrix& A)
{
  Matrix y(A.numRows(), A.numRows(), false);

  // Make sure A is square!
  if (A.numRows() != A.numCols())
  {
    std::cerr << "ERROR!  A must be square matrix!\n";
    return y;
  }

  const int N = A.numRows();

  // Make a copy of A since it gets modified
  Matrix Acopy(A);

 // y.setSize(N,N);
  Matrix col(N,1);
  Matrix indx(N,1);
  double d;
  int i,j;

  ludcmp(Acopy,indx,d);
  for (j = 0; j < N; j++)
  {
    for (i = 0; i < N; i++) col(i,0) = 0.0;
    col(j,0) = 1.0;
    lubksb(Acopy,indx,col);
    for (i = 0; i < N; i++) y(i,j) = col(i,0);
  }

  std::cout.flush();
  // Return result
  return y;
}
//---------------------------------------------------------------------------
Matrix solveLinearSystem(const Matrix& A, const Matrix& b)
{
  Matrix x;

  // Make sure A is square!
  if (A.numRows() != A.numCols())
  {
    std::cerr << "ERROR!  A must be square matrix!\n";
    return x;
  }

  // Make sure b is a column vector with the same dimensions
  // as A
  if (b.numRows() != A.numRows())
  {
    std::cerr << "ERROR!  b must be a column vector with the same dimensions as square matrix A!\n";
    return x;
  }

  // Make a copy of A since it gets modified
  Matrix Acopy(A);

  const int N = Acopy.numRows();
  Matrix indx(N,1);
  double d;
  ludcmp(Acopy,indx,d);
  x = b;  // x will contain solution
  lubksb(Acopy,indx,x);

  // Return solution column vector
  return x;
}
int four_quads(const Epetra_Comm& Comm, bool preconstruct_graph, bool verbose)
{
  if (verbose) {
    std::cout << "******************* four_quads ***********************"<<std::endl;
  }

  //This function assembles a matrix representing a finite-element
  //mesh of four 2-D quad elements. There are 9 nodes in the problem. The
  //same problem is assembled no matter how many processors are being used
  //(within reason). It may not work if more than 9 processors are used.
  //
  //  *------*------*
  // 6|     7|     8|
  //  | E2   | E3   |
  //  *------*------*
  // 3|     4|     5|
  //  | E0   | E1   |
  //  *------*------*
  // 0      1      2
  //
  //Nodes are denoted by * with node-numbers below and left of each node.
  //E0, E1 and so on are element-numbers.
  //
  //Each processor will contribute a sub-matrix of size 4x4, filled with 1's,
  //for each element. Thus, the coefficient value at position 0,0 should end up
  //being 1.0*numProcs, the value at position 4,4 should be 1.0*4*numProcs, etc.
  //
  //Depending on the number of processors being used, the locations of the
  //specific matrix positions (in terms of which processor owns them) will vary.
  //

  int numProcs = Comm.NumProc();

  long long numNodes = 9;
  int numElems = 4;
  int numNodesPerElem = 4;

  int indexBase = 0;

  //Create a map using epetra-defined linear distribution.
  Epetra_Map map(numNodes, indexBase, Comm);

  Epetra_FECrsGraph* graph = NULL;

  long long* nodes = new long long[numNodesPerElem];
  int i, err = 0;

  if (preconstruct_graph) {
    graph = new Epetra_FECrsGraph(Copy, map, 1);

    //we're going to fill the graph with indices, by passing our
    //connectivity lists.
    //FECrsGraph should accept indices in all rows, regardless of
    //whether map.MyGID(row) is true.

    for(i=0; i<numElems; ++i) {
      switch(i) {
      case 0:
	nodes[0] = 0; nodes[1] = 1; nodes[2] = 4; nodes[3] = 3;
	break;
      case 1:
	nodes[0] = 1; nodes[1] = 2; nodes[2] = 5; nodes[3] = 4;
	break;
      case 2:
	nodes[0] = 3; nodes[1] = 4; nodes[2] = 7; nodes[3] = 6;
	break;
      case 3:
	nodes[0] = 4; nodes[1] = 5; nodes[2] = 8; nodes[3] = 7;
	break;
      }

      err = graph->InsertGlobalIndices(numNodesPerElem, nodes,
                                       numNodesPerElem, nodes);
      if (err < 0) {
        std::cerr << "ERROR, FECrsGraph error in InsertGlobalIndices, err="
          << err << std::endl;
        return(-1);
      }
    }

    EPETRA_CHK_ERR( graph->GlobalAssemble() );
  }

  Epetra_FECrsMatrix* A = NULL;

  if (preconstruct_graph) {
    A = new Epetra_FECrsMatrix(Copy, *graph);
  }
  else {
    A = new Epetra_FECrsMatrix(Copy, map, 1);
  }

  EPETRA_CHK_ERR( A->PutScalar(0.0) );

  double* values_1d = new double[numNodesPerElem*numNodesPerElem];
  double** values_2d = new double*[numNodesPerElem];

  for(i=0; i<numNodesPerElem*numNodesPerElem; ++i) values_1d[i] = 1.0;

  int offset = 0;
  for(i=0; i<numNodesPerElem; ++i) {
    values_2d[i] = &(values_1d[offset]);
    offset += numNodesPerElem;
  }

  int format = Epetra_FECrsMatrix::ROW_MAJOR;
  Epetra_LongLongSerialDenseVector epetra_nodes(View, nodes, numNodesPerElem);
  Epetra_SerialDenseMatrix epetra_values(View, values_1d, numNodesPerElem,
					 numNodesPerElem, numNodesPerElem);

  for(i=0; i<numElems; ++i) {
    switch(i) {
    case 0:
      nodes[0] = 0; nodes[1] = 1; nodes[2] = 4; nodes[3] = 3;
      if (preconstruct_graph) {
	err = A->SumIntoGlobalValues(epetra_nodes,
				     epetra_values, format);
	if (err<0) return(err);
      }
      else {
	err = A->InsertGlobalValues(epetra_nodes,
				    epetra_values, format);
	if (err<0) return(err);
      }
      break;

    case 1:
      nodes[0] = 1; nodes[1] = 2; nodes[2] = 5; nodes[3] = 4;
      if (preconstruct_graph) {
	err = A->SumIntoGlobalValues(numNodesPerElem, nodes,
				     values_2d, format);
	if (err<0) return(err);
      }
      else {
	err = A->InsertGlobalValues(numNodesPerElem, nodes,
				    values_2d, format);
	if (err<0) return(err);
      }
      break;

    case 2:
      nodes[0] = 3; nodes[1] = 4; nodes[2] = 7; nodes[3] = 6;
      if (preconstruct_graph) {
	err = A->SumIntoGlobalValues(numNodesPerElem, nodes,
				     numNodesPerElem, nodes,
				     values_1d, format);
	if (err<0) return(err);
      }
      else {
	err = A->InsertGlobalValues(numNodesPerElem, nodes,
				    numNodesPerElem, nodes,
				    values_1d, format);
	if (err<0) return(err);
      }
      break;

     case 3:
      nodes[0] = 4; nodes[1] = 5; nodes[2] = 8; nodes[3] = 7;
      if (preconstruct_graph) {
	err = A->SumIntoGlobalValues(numNodesPerElem, nodes,
				     numNodesPerElem, nodes,
				     values_2d, format);
	if (err<0) return(err);
      }
      else {
	err = A->InsertGlobalValues(numNodesPerElem, nodes,
				    numNodesPerElem, nodes,
				    values_2d, format);
	if (err<0) return(err);
      }
      break;
    }
  }

  err = A->GlobalAssemble();
  if (err < 0) {
    return(err);
  }

  Epetra_Vector x(A->RowMap()), y(A->RowMap());

  x.PutScalar(1.0); y.PutScalar(0.0);

  Epetra_FECrsMatrix Acopy(*A);

  Epetra_Vector x2(Acopy.RowMap()), y2(Acopy.RowMap());

  x2.PutScalar(1.0); y2.PutScalar(0.0);

  A->Multiply(false, x, y);

  Acopy.Multiply(false, x2, y2);

  double ynorm2, y2norm2;

  y.Norm2(&ynorm2);
  y2.Norm2(&y2norm2);
  if (ynorm2 != y2norm2) {
    std::cerr << "norm2(A*ones) != norm2(Acopy*ones)"<<std::endl;
    return(-99);
  }

  err = Acopy.GlobalAssemble();
  if (err < 0) {
    return(err);
  }

  if (verbose) {
    std::cout << "A:"<<std::endl<<*A << std::endl;
    std::cout << "Acopy:"<<std::endl<<Acopy << std::endl;
  }

  Epetra_FECrsMatrix Acopy2(Copy, A->RowMap(), A->ColMap(), 1);

  Acopy2 = Acopy;

  Epetra_Vector x3(Acopy.RowMap()), y3(Acopy.RowMap());

  x3.PutScalar(1.0); y3.PutScalar(0.0);

  Acopy2.Multiply(false, x3, y3);

  double y3norm2;
  y3.Norm2(&y3norm2);

  if (y3norm2 != y2norm2) {
    std::cerr << "norm2(Acopy*ones) != norm2(Acopy2*ones)"<<std::endl;
    return(-999);
  }

  int len = 20;
  long long* indices = new long long[len];
  double* values = new double[len];
  int numIndices;

  if (map.MyGID(0)) {
    EPETRA_CHK_ERR( A->ExtractGlobalRowCopy(0, len, numIndices,
					    values, indices) );
    if (numIndices != 4) {
      return(-1);
    }
    if (indices[0] != 0) {
      return(-2);
    }

    if (values[0] != 1.0*numProcs) {
      std::cout << "ERROR: values[0] ("<<values[0]<<") should be "<<numProcs<<std::endl;
      return(-3);
    }
  }

  if (map.MyGID(4)) {
    EPETRA_CHK_ERR( A->ExtractGlobalRowCopy(4, len, numIndices,
					    values, indices) );

    if (numIndices != 9) {
      return(-4);
    }
    int lcid = A->LCID(4);
    if (lcid<0) {
      return(-5);
    }
    if (values[lcid] != 4.0*numProcs) {
      std::cout << "ERROR: values["<<lcid<<"] ("<<values[lcid]<<") should be "
	   <<4*numProcs<<std::endl;
      return(-6);
    }
  }

// now let's do the checks for Acopy...

  if (map.MyGID(0)) {
    EPETRA_CHK_ERR( Acopy.ExtractGlobalRowCopy(0, len, numIndices,
                                            values, indices) );
    if (numIndices != 4) {
      return(-1);
    }
    if (indices[0] != 0) {
      return(-2);
    }

    if (values[0] != 1.0*numProcs) {
      std::cout << "ERROR: Acopy.values[0] ("<<values[0]<<") should be "<<numProcs<<std::endl;
      return(-3);
    }
  }

  if (map.MyGID(4)) {
    EPETRA_CHK_ERR( Acopy.ExtractGlobalRowCopy(4, len, numIndices,
                                            values, indices) );

    if (numIndices != 9) {
      return(-4);
    }
    int lcid = A->LCID(4);
    if (lcid<0) {
      return(-5);
    }
    if (values[lcid] != 4.0*numProcs) {
      std::cout << "ERROR: Acopy.values["<<lcid<<"] ("<<values[lcid]<<") should be "
           <<4*numProcs<<std::endl;
      return(-6);
    }
  }

// now let's do the checks for Acopy2...

  if (map.MyGID(0)) {
    EPETRA_CHK_ERR( Acopy2.ExtractGlobalRowCopy(0, len, numIndices,
                                            values, indices) );
    if (numIndices != 4) {
      return(-1);
    }
    if (indices[0] != 0) {
      return(-2);
    }

    if (values[0] != 1.0*numProcs) {
      std::cout << "ERROR: Acopy2.values[0] ("<<values[0]<<") should be "<<numProcs<<std::endl;
      return(-3);
    }
  }

  if (map.MyGID(4)) {
    EPETRA_CHK_ERR( Acopy2.ExtractGlobalRowCopy(4, len, numIndices,
                                            values, indices) );

    if (numIndices != 9) {
      return(-4);
    }
    int lcid = A->LCID(4);
    if (lcid<0) {
      return(-5);
    }
    if (values[lcid] != 4.0*numProcs) {
      std::cout << "ERROR: Acopy2.values["<<lcid<<"] ("<<values[lcid]<<") should be "
           <<4*numProcs<<std::endl;
      return(-6);
    }
  }

  delete [] values_2d;
  delete [] values_1d;
  delete [] nodes;
  delete [] indices;
  delete [] values;

  delete A;
  delete graph;

  return(0);
}
int four_quads(const Epetra_Comm& Comm, bool preconstruct_graph, bool verbose)
{
  if (verbose) {
    cout << "******************* four_quads ***********************"<<endl;
  }

  //This function assembles a matrix representing a finite-element mesh
  //of four 2-D quad elements. There are 9 nodes in the problem. The
  //same problem is assembled no matter how many processors are being used
  //(within reason). It may not work if more than 9 processors are used.
  //
  //  *------*------*
  // 6|     7|     8|
  //  | E2   | E3   |
  //  *------*------*
  // 3|     4|     5|
  //  | E0   | E1   |
  //  *------*------*
  // 0      1      2
  //
  //Nodes are denoted by * with node-numbers below and left of each node.
  //E0, E1 and so on are element-numbers.
  //
  //Each processor will contribute a sub-matrix of size 4x4, filled with 1's,
  //for each element. Thus, the coefficient value at position 0,0 should end up
  //being 1.0*numProcs, the value at position 4,4 should be 1.0*4*numProcs, etc.
  //
  //Depending on the number of processors being used, the locations of the
  //specific matrix positions (in terms of which processor owns them) will vary.
  //

  int numProcs = Comm.NumProc();

  int numNodes = 9;
  int numElems = 4;
  int numNodesPerElem = 4;

  int indexBase = 0;

  //Create a map using epetra-defined linear distribution.
  Epetra_Map map(numNodes, indexBase, Comm);

  Epetra_CrsGraph* graph = NULL;

  int* nodes = new int[numNodesPerElem];
  int i, j, err = 0;

  if (preconstruct_graph) {
    graph = new Epetra_CrsGraph(Copy, map, 1);

    //we're going to fill the graph with indices, but remember it will only
    //accept indices in rows for which map.MyGID(row) is true.

    for(i=0; i<numElems; ++i) {
      switch(i) {
      case 0:
	nodes[0] = 0; nodes[1] = 1; nodes[2] = 4; nodes[3] = 3;
	break;
      case 1:
	nodes[0] = 1; nodes[1] = 2; nodes[2] = 5; nodes[3] = 4;
	break;
      case 2:
	nodes[0] = 3; nodes[1] = 4; nodes[2] = 7; nodes[3] = 6;
	break;
      case 3:
	nodes[0] = 4; nodes[1] = 5; nodes[2] = 8; nodes[3] = 7;
	break;
      }

      for(j=0; j<numNodesPerElem; ++j) {
	if (map.MyGID(nodes[j])) {
	  err = graph->InsertGlobalIndices(nodes[j], numNodesPerElem,
					   nodes);
	  if (err<0) return(err);
	}
      }
    }

    EPETRA_CHK_ERR( graph->FillComplete() );
  }

  Epetra_FECrsMatrix* A = NULL;

  if (preconstruct_graph) {
    A = new Epetra_FECrsMatrix(Copy, *graph);
  }
  else {
    A = new Epetra_FECrsMatrix(Copy, map, 1);
  }

  EPETRA_CHK_ERR( A->PutScalar(0.0) );

  double* values_1d = new double[numNodesPerElem*numNodesPerElem];
  double** values_2d = new double*[numNodesPerElem];

  for(i=0; i<numNodesPerElem*numNodesPerElem; ++i) values_1d[i] = 1.0;

  int offset = 0;
  for(i=0; i<numNodesPerElem; ++i) {
    values_2d[i] = &(values_1d[offset]);
    offset += numNodesPerElem;
  }

  int format = Epetra_FECrsMatrix::ROW_MAJOR;
  Epetra_IntSerialDenseVector epetra_nodes(View, nodes, numNodesPerElem);
  Epetra_SerialDenseMatrix epetra_values(View, values_1d, numNodesPerElem,
					 numNodesPerElem, numNodesPerElem);

  for(i=0; i<numElems; ++i) {
    switch(i) {
    case 0:
      nodes[0] = 0; nodes[1] = 1; nodes[2] = 4; nodes[3] = 3;
      if (preconstruct_graph) {
	err = A->SumIntoGlobalValues(epetra_nodes,
				     epetra_values, format);
	if (err<0) return(err);
      }
      else {
	err = A->InsertGlobalValues(epetra_nodes,
				    epetra_values, format);
	if (err<0) return(err);
      }
      break;

    case 1:
      nodes[0] = 1; nodes[1] = 2; nodes[2] = 5; nodes[3] = 4;
      if (preconstruct_graph) {
	err = A->SumIntoGlobalValues(nodes[0], numNodesPerElem, values_2d[0],
                                     nodes);
	err += A->SumIntoGlobalValues(nodes[1], numNodesPerElem, values_2d[1],
                                     nodes);
	err += A->SumIntoGlobalValues(nodes[2], numNodesPerElem, values_2d[2],
                                     nodes);
	err += A->SumIntoGlobalValues(nodes[3], numNodesPerElem, values_2d[3],
                                     nodes);
	if (err<0) return(err);
      }
      else {
	err = A->InsertGlobalValues(numNodesPerElem, nodes,
				    values_2d, format);
	if (err<0) return(err);
      }
      break;

    case 2:
      nodes[0] = 3; nodes[1] = 4; nodes[2] = 7; nodes[3] = 6;
      if (preconstruct_graph) {
	err = A->SumIntoGlobalValues(numNodesPerElem, nodes,
				     numNodesPerElem, nodes,
				     values_1d, format);
	if (err<0) return(err);
      }
      else {
	err = A->InsertGlobalValues(numNodesPerElem, nodes,
				    numNodesPerElem, nodes,
				    values_1d, format);
	if (err<0) return(err);
      }
      break;

     case 3:
      nodes[0] = 4; nodes[1] = 5; nodes[2] = 8; nodes[3] = 7;
      if (preconstruct_graph) {
	err = A->SumIntoGlobalValues(numNodesPerElem, nodes,
				     numNodesPerElem, nodes,
				     values_2d, format);
	if (err<0) return(err);
      }
      else {
	err = A->InsertGlobalValues(numNodesPerElem, nodes,
				    numNodesPerElem, nodes,
				    values_2d, format);
	if (err<0) return(err);
      }
      break;
    }
  }

  err = A->GlobalAssemble();
  if (err < 0) {
    return(err);
  }

  Epetra_Vector x(A->RowMap()), y(A->RowMap());

  x.PutScalar(1.0); y.PutScalar(0.0);

  Epetra_FECrsMatrix Acopy(*A);

  err = Acopy.GlobalAssemble();
  if (err < 0) {
    return(err);
  }

  bool the_same = epetra_test::compare_matrices(*A, Acopy);
  if (!the_same) {
    return(-1);
  }

  Epetra_FECrsMatrix Acopy2(Copy, A->RowMap(), A->ColMap(), 1);

  Acopy2 = Acopy;

  the_same = epetra_test::compare_matrices(*A, Acopy);
  if (!the_same) {
    return(-1);
  }

  int len = 20;
  int* indices = new int[len];
  double* values = new double[len];
  int numIndices;

  if (map.MyGID(0)) {
    EPETRA_CHK_ERR( A->ExtractGlobalRowCopy(0, len, numIndices,
					    values, indices) );
    if (numIndices != 4) {
      return(-1);
    }
    if (indices[0] != 0) {
      return(-2);
    }

    if (values[0] != 1.0*numProcs) {
      cout << "ERROR: values[0] ("<<values[0]<<") should be "<<numProcs<<endl;
      return(-3);
    }
  }

  if (map.MyGID(4)) {
    EPETRA_CHK_ERR( A->ExtractGlobalRowCopy(4, len, numIndices,
					    values, indices) );

    if (numIndices != 9) {
      return(-4);
    }
    int lcid = A->LCID(4);
    if (lcid<0) {
      return(-5);
    }
    if (values[lcid] != 4.0*numProcs) {
      cout << "ERROR: values["<<lcid<<"] ("<<values[lcid]<<") should be "
	   <<4*numProcs<<endl;
      return(-6);
    }
  }

  delete [] values_2d;
  delete [] values_1d;
  delete [] nodes;
  delete [] indices;
  delete [] values;

  delete A;
  delete graph;

  return(0);
}
Beispiel #6
0
int Pseudoinverse(
	size_t m, size_t n,
	const doublecomplex *A, size_t lda,
	doublecomplex *P, size_t ldp
){
	integer info;
	CMat Acopy(Eigen::Map<const CMat,Eigen::Unaligned,Eigen::OuterStride<> >(A, m, n, Eigen::OuterStride<>(lda)));
	Eigen::Map<CMat,Eigen::Unaligned,Eigen::OuterStride<> > mP(P, n, m, Eigen::OuterStride<>(ldp));
	if(m >= n){ // tall case
		RVec S(n);
		CMat VH(n,n);
		doublecomplex dum;
		integer lwork = -1;
		RVec rwork(5*n);
		zgesvd_(
			"O","A", m,n, Acopy.data(), Acopy.outerStride(),
			S.data(), NULL, m, VH.data(), VH.outerStride(),
			&dum, lwork, rwork.data(), &info
		);
		lwork = (integer)dum.real();
		CVec work(lwork);
		zgesvd_(
			"O","A", m,n, Acopy.data(), Acopy.outerStride(),
			S.data(), NULL, m, VH.data(), VH.outerStride(),
			work.data(), lwork, rwork.data(), &info
		);
		mP = Acopy.adjoint();
		
		{
			double threshold = 2 * std::numeric_limits<double>::epsilon() * S[0];
			for(size_t i = 0; i < n; ++i){
				if(S[i] < threshold){
					break;
				}
				S[i] = 1./S[i];
			}
		}
		mP = VH.adjoint() * S.asDiagonal() * mP;
	}else{ // wide case
		RVec S(m);
		CMat U(m,m);
		doublecomplex dum;
		integer lwork = -1;
		RVec rwork(5*m);
		zgesvd_(
			"A","O", m,n, Acopy.data(), Acopy.outerStride(),
			S.data(), U.data(), U.outerStride(), NULL, m,
			&dum, lwork, rwork.data(), &info
		);
		lwork = (integer)dum.real();
		CVec work(lwork);
		zgesvd_(
			"A","O", m,n, Acopy.data(), Acopy.outerStride(),
			S.data(), U.data(), U.outerStride(), NULL, m,
			work.data(), lwork, rwork.data(), &info
		);
		mP = Acopy.adjoint();
		
		{
			double threshold = 2 * std::numeric_limits<double>::epsilon() * S[0];
			for(size_t i = 0; i < m; ++i){
				if(S[i] < threshold){
					break;
				}
				S[i] = 1./S[i];
			}
		}
		mP = mP * S.asDiagonal() * U.adjoint();
	}
	return info;
}