示例#1
0
文件: expmv.c 项目: cran/expoTree
void expmv(double t, int n, matMat fmv, normFunc nf, traceFunc tf,
    double* b, int ncol, int m_max, int p_max, double* tm, int recalcm,
    char prec, double shift, char bal, int full_term, int prnt, int* info,
    int wrklen, double* wrk, int iwrklen, int* iwrk)
{
  int mv;
  int mvd;
  int unA;

  int i;
  int j;
  int k;

  double tt;
  // double trace;
  double tol;

  /* size of Taylor approximation */
  int tcol;

  int wlen;
  int nalen;

  double* talpha;
  double* teta;
  double* C;
  double* b1;
  double* b2;
  double* nawrk;

  wlen = 2*p_max + 2*n*ncol + m_max*(p_max-1);
  nalen = 3*n + (4*n+1)*ncol;
  if (wrklen < wlen+nalen || iwrklen < 2*n + 4) {
    if (prnt) {
      Rprintf("Not enough workspace supplied!\n");
      Rprintf("  Required 'double': %d\n",wlen+nalen);
      Rprintf("  Supplied         : %d\n",wrklen);
      Rprintf("  Required 'int'   : %d\n",2*n+4);
      Rprintf("  Supplied         : %d\n",iwrklen);
    }
    *info = -2;
    return;
  }

  talpha = wrk;
  teta   = talpha + p_max;
  C      = teta + p_max;
  b1     = C + m_max*(p_max-1);
  b2     = b1 + n*ncol;
  nawrk  = b2 + n*ncol;

  switch (prec) {
    case 's': 
      tol = pow(2.,-24.);
      break;
    case 'h': 
      tol = pow(2.,-10.);
      break;
    case 'd': 
    default:
      tol = pow(2.,-53.);
      break;
  }

  // get required Taylor truncation (if not set)
  if (recalcm) {
    if (prnt > 2) Rprintf("Calculating required Taylor truncation...");
    tt = 1.;
    select_taylor_degree(n,fmv,t,b,ncol,nf,m_max,p_max,
                         prec,talpha,teta,tm,&mvd,&unA,shift,bal,0,
                         wrklen-wlen,nawrk,iwrklen,iwrk);
    if (prnt > 3) {
      for (i = 0; i < m_max; ++i) {
        for (j = 0; j < p_max-1; ++j) {
          Rprintf("%16.8e ",tm[j*m_max+i]);
        }
        Rprintf("\n");
      }
    }
    mv = mvd;
    if (prnt > 2) Rprintf("done.\n");
  } else {
    tt = t; 
    mv = 0; 
    mvd = 0;
  }

  double s = 1.0;     // cost per column
  double cost = 0.0;
  double ccost = 0.0;

  if (t == 0.0) { 
    tcol = 0; 
  } else {
    k = 0;
    for (i = 0; i < m_max; ++i) {
      for (j = 0; j < p_max-1; ++j) {
        C[k] = ceil(fabs(tt)*tm[j*(m_max)+i])*(i+1.);
        if (C[k] == 0.0) C[k] = 1./0.;
        ++k;
      }
    }

    cost = R_PosInf;
    tcol = 0;
    for (i = 0; i < m_max; ++i) {
      ccost = R_PosInf;
      for (j = 0; j < p_max-1; ++j) {
        if (C[i*(p_max-1)+j] < ccost) {
          ccost = C[i*(p_max-1)+j];
        }
      }
      if (ccost < cost) {
        cost = ccost;
        tcol = i+1;
      }
    }

    s = (cost/tcol > 1) ? cost/tcol : 1.0;
  }

  if (tcol == 0) {
    if (prnt) {
      Rprintf("Cannot calculate matrix exponential (under-/overflow?).\n");
      Rprintf("Returned results may be gibberish.\n");
    }
    *info = -1;
    return;
  }

  double eta = 1.0;
  if (shift != 0.0) eta = exp(t*shift/s);

  double* btmp = NULL;

  memcpy(b1,b,n*ncol*sizeof(double));

  if (prnt > 2) Rprintf("m = %2d, s = %g\n", tcol, s);

  double c1, c2;
  double bnorm;
  int ss;
  for (ss = 1; ss <= s; ++ss) {
    c1 = inf_norm(n,ncol,b1);
    if (prnt > 3) Rprintf("s = %d, ",ss);
    if (prnt > 4) Rprintf("\n");
    for (k = 1; k <= tcol; ++k) {
      fmv('n',n,ncol,t/(s*k),b1,b2);
      btmp = b1; b1 = b2; b2 = btmp; btmp = NULL;
      ++mv;
      for (i = 0; i < n; ++i) {
        for (j = 0; j < ncol; ++j) {
          b[j*n+i] += b1[j*n+i];
        }
      }
      c2 = inf_norm(n,ncol,b1);
      if (prnt > 4) Rprintf("k=%3d: %9.2e %9.2e %9.2e",k,bnorm,c1,c2);
      if (!full_term) {
        bnorm = inf_norm(n,ncol,b);
        if (prnt > 4) Rprintf(" %9.2e, \n",(c1+c2)/bnorm);
        if (c1+c2 <= tol*bnorm) {
          if (prnt == 4) {
            Rprintf("k=%3d: %9.2e %9.2e %9.2e",k,bnorm,c1,c2);
            Rprintf(" %9.2e, ",(c1+c2)/bnorm);
          }
          if (prnt > 3) Rprintf("m_actual = %2d\n", k);
          break;
        }
        c1 = c2;
      }
    }
    for (i = 0; i < n*ncol; ++i) b[i] *= eta;

    memcpy(b1,b,n*ncol*sizeof(double));
  }

  iwrk[0] = tcol;
  iwrk[1] = k;
}
示例#2
0
void lin_alg::gauss_seidel_solve(double **a, double *x, double *b, int n, int max_iter, bool &solved, double tol, double &error)
{
	// Solve the system Ax=b by Gauss-Seidel iteration method
	// R. Sheehan 3 - 8 - 2011
	
	bool cgt=false;

	double *oldx = vector(n); 
	double *diffx = vector(n); 
		
	int n_iter = 1;
	double bi, mi, err;
		
	while(n_iter<max_iter){

		// store the initial approximation to the solution
		for(int i=1; i<=n; i++){
			oldx[i] = x[i]; 
		}

		// iteratively compute the solution vector x
		for(int i=1; i<=n; i++){

			bi=b[i]; 
			mi=a[i][i];

			for(int j=1; j<i; j++){

				bi -= a[i][j]*x[j];

			}

			for(int j=i+1; j<=n; j++){

				bi -= a[i][j]*oldx[j];

			}

			x[i] = bi/mi;
		}
			
		// test for convergence
		// compute x - x_{old} difference between the two is the error
		diffx = vector_diff(x, oldx, n, n); 

		// error is measured as the length of the difference vector ||x - x_{old}||_{\infty}
		err = inf_norm(diffx, n); 

		if( n_iter%4 == 0){
			cout<<"iteration "<<n_iter<<" , error = "<<err<<endl;
		}
			
		if(abs(err)<tol){ // solution has converged, stop iterating

			cout<<"\nGauss-Seidel Iteration Complete\nSolution converged in "<<n_iter<<" iterations\n";

			cout<<"Error = "<<abs(err)<<endl<<endl;

			error=abs(err);

			cgt=solved=true;

			break;
		}
			
		n_iter++; // solution has not converged, keep iterating
	}
		
	if(!cgt){ // solution did not converge

		cout<<"\nError: Gauss-Seidel Iteration\n";

		cout<<"Error: Solution did not converge in "<<max_iter<<" iterations\n";

		cout<<"Error = "<<abs(err)<<endl;

		error=abs(err);

		solved=false;
	}

	delete[] oldx; 
	delete[] diffx; 
}
示例#3
0
void expm(Matrix A, Matrix B, double h) {

	static int firsttime = TRUE;
	static Matrix M;
	static Matrix M2;
	static Matrix M3;
	static Matrix D;
	static Matrix N;

	if (firsttime) {
		firsttime = FALSE;
		M = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
		M2 = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
		M3 = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
		D = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
		N = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
	}

	int norm = 0;
	double c = 0.5;
	int q = 6; // uneven p-q order for Pade approx.
	int p = 1;
	int i,j,k;

	// Form the big matrix
	mat_mult_scalar(A, h, A);
	mat_equal_size(A, 2*N_DOFS, 2*N_DOFS, M);
	for (i = 1; i <= 2*N_DOFS; ++i) {
		for (j = 1; j <= N_DOFS; ++j) {
			M[i][2*N_DOFS + j] = h * B[i][j];
	    }
	}
	//print_mat("M is:\n", M);

	// scale M by power of 2 so that its norm < 1/2
	norm = (int)(log2(inf_norm(M))) + 2;
	//printf("Inf norm of M: %f \n", inf_norm(M));
	if (norm < 0)
		norm = 0;

	mat_mult_scalar(M, 1/pow(2,(double)norm), M);
	//printf("Norm of M logged, floored and 2 added is: %d\n", norm);
	//print_mat("M after scaling is:\n", M);

	for (i = 1; i <= 3*N_DOFS; i++) {
		for (j = 1; j <= 3*N_DOFS; j++) {
			N[i][j] = c * M[i][j];
			D[i][j] = -c * M[i][j];
		}
		N[i][i] = N[i][i] + 1.0;
		D[i][i] = D[i][i] + 1.0;
	}

	// set M2 equal to M
	mat_equal(M, M2);

	// start pade approximation

	for (k = 2; k <= q; k++) {
		c = c * (q - k + 1) / (double)(k * (2*q - k + 1));
		mat_mult(M,M2,M2);
		mat_mult_scalar(M2,c,M3);
		mat_add(N,M3,N);
		if (p == 1)
			mat_add(D,M3,D);
		else
			mat_sub(D,M3,D);
		p = -1 * p;
	}

	// multiply denominator with nominator i.e. D\E
	my_inv_ludcmp(D, 3*N_DOFS, D);
	mat_mult(D,N,N);

	// undo scaling by repeated squaring
	for (k = 1; k <= norm; k++)
		mat_mult(N,N,N);

	// get the matrices out
	// read off the entries
	for (i = 1; i <= 2*N_DOFS; i++) {
		for (j = 1; j <= 2*N_DOFS; j++) {
			A[i][j] = N[i][j];
		}
		for (j = 1; j <= N_DOFS; j++) {
			B[i][j] = N[i][2*N_DOFS + j];
		}
	}
}
示例#4
0
void lin_alg::jacobi_solve(double **a, double *x, double *b, int n, int max_iter, bool &solved, double tol, double &error)
{
	// Solve the system Ax=b by Jacobi's iteration method
	// This has the slowest convergence rate of the iterative techniques
	// In practice you never use this algorithm
	// Always use GS or SOR for iterative solution
	// R. Sheehan 3 - 8 - 2011
	
	bool cgt = false;
	
	double *oldx = vector(n); 
	double *diffx = vector(n); 
		
	int n_iter = 1;
	double bi, mi, err;
		
	while(n_iter < max_iter){

		// store the initial approximation to the solution
		for(int i=1; i<=n; i++){
			oldx[i] = x[i]; 
		}
		
		for(int i=1;i<=n;i++){

			bi=b[i]; mi=a[i][i];

			for(int j=1;j<=n;j++){

				if(j!=i){
					bi-=a[i][j]*oldx[j];
				}

			}

			x[i]=bi/mi;
		}
			
		diffx = vector_diff(x, oldx, n, n); 
		
		err = inf_norm(diffx, n);

		if( n_iter%4 == 0){
			cout<<"iteration "<<n_iter<<" , error = "<<err<<endl;
		}
			
		if(abs(err)<tol){

			cout<<"\nJacobi Iteration Complete\nSolution converged in "<<n_iter<<" iterations\n";
			cout<<"Error = "<<abs(err)<<endl<<endl;
			
			error = abs(err);

			cgt = solved = true;
			
			break;
		}
			
		n_iter++;
	}
		
	if(!cgt){
		cout<<"\nError: Jacobi Iteration\n";
		cout<<"Error: Solution did not converge in "<<max_iter<<" iterations\n\n";
	}

	delete[] oldx; 
	delete[] diffx; 
}
示例#5
0
void fem(size_t n, double errors[2], double (*fn_f)(double, double),
         double (*fn_g)(unsigned char, double, double),
         double (*fn_u)(double, double))
{
  mesh m;
  crs_matrix mat;
  double * u, * rhs;
  double local_stiffness[3][3];
  double local_load[3];
  size_t elem;

  /* 1. Allocate and generate mesh */
  get_mesh(&m, n);

#ifdef PRINT_DEBUG
  print_mesh(&m);
#endif

  /* 2. Allocate the linear system */
  init_matrix(&mat, &m);

  u = (double *) malloc(sizeof(double) * m.n_vertices);
  if (u == NULL) err_exit("Allocation of solution vector failed!");
  memset(u, 0, sizeof(double) * m.n_vertices);

  rhs = (double *) malloc(sizeof(double) * m.n_vertices);
  if (rhs == NULL)
    err_exit("Allocation of right hand side failed!");
  memset(rhs, 0, sizeof(double) * m.n_vertices);

  /* 3. Assemble the matrix */
  for (elem = 0; elem <  m.n_triangles; ++elem)
  {
    /* Compute local stiffness and load */
    get_local_stiffness(local_stiffness, &m, elem);
    get_local_load(local_load, &m, elem, fn_f);

#ifdef PRINT_DEBUG
    print_local_stiffness(local_stiffness);
    print_local_load(local_load);
#endif

    /* insert into global matrix and rhs */
    assemble_local2global_stiffness(local_stiffness, &mat, &m, elem);
    assemble_local2global_load(local_load, rhs, &m, elem);
  }

#ifdef PRINT_DEBUG
  printf("Matrix after assembly:\n");
  print_matrix(&mat);
  printf("rhs after assembly:\n");
  for(size_t i = 0; i < m.n_vertices; ++i) {
      printf("%5.2f\n", rhs[i]);
  }
  printf("\n");
#endif

  /* 4. Apply boundary conditions */
  apply_dbc(&mat, rhs, &m, fn_g);

#ifdef PRINT_DEBUG
  printf("Matrix after application of BCs:\n");
  print_matrix(&mat);
  printf("rhs after application of BCs:\n");
  for(size_t i = 0; i < m.n_vertices; ++i) {
      printf("%5.2f\n", rhs[i]);
  }
  printf("\n");
#endif

  /* 5. Solve the linear system */
  solve(&mat, u, rhs);

  /* 6. Evaluate error */
  errors[0] = l2_norm(u, &m, fn_u);
  errors[1] = inf_norm(u, &m, fn_u);

  /* free allocated resources */
  free(u);
  free(rhs);
  rhs = NULL;
  free_matrix(&mat);
  free_mesh(&m);
}