コード例 #1
0
ファイル: numerics.c プロジェクト: will-bainbridge/AUPLAS
int least_squares(int m, int n, double **matrix)
{
	if(m < 1 || n < 1 || n > m) return LS_DIMENSION_ERROR;

	int i, j;

	int info, lwork = m*m;
	double *work; if(!allocate_double_vector(&work, lwork)) { return LS_MEMORY_ERROR; }
	char transa = 'N';

	double **a_matrix; if(!allocate_double_matrix(&a_matrix, n, m)) { return LS_MEMORY_ERROR; }
	for(i = 0; i < m; i ++) for(j = 0; j < n; j ++) a_matrix[j][i] = matrix[j][i];

	double **b_matrix; if(!allocate_double_matrix(&b_matrix, m, m)) { return LS_MEMORY_ERROR; }
	for(i = 0; i < m; i ++) for(j = 0; j < m; j ++) b_matrix[i][j] = (i == j);

	dgels_(&transa, &m, &n, &m, a_matrix[0], &m, b_matrix[0], &m, work, &lwork, &info);

	for(i = 0; i < n; i ++) for(j = 0; j < m; j ++) matrix[i][j] = b_matrix[j][i];

	free_matrix((void**)a_matrix);
	free_matrix((void**)b_matrix);
	free_vector(work);
	return LS_SUCCESS;
}
コード例 #2
0
ファイル: banker.c プロジェクト: mollerhoj/bosc_oo2new
int main(int argc, char* argv[])
{
  //Init lock
  pthread_mutex_init(&lock,NULL);

  /* Get size of current state as input */
  int i, j;
  printf("Number of processes: ");
  scanf("%d", &m);
  printf("Number of resources: ");
  scanf("%d", &n);

  s = (State *) malloc(sizeof(State));
  s->resource = (int *) malloc(n * sizeof(int));
  s->available = (int *) malloc(n * sizeof(int));
  s->max = allocate_double_matrix(m,n);
  s->allocation = allocate_double_matrix(m,n);
  s->need = allocate_double_matrix(m,n);

  if (s == NULL) { printf("\nYou need to allocate memory for the state!\n"); exit(0); };

  /* Get current state as input */
    printf("Resource vector: ");
  for(i = 0; i < n; i++)
    scanf("%d", &s->resource[i]);
  printf("Enter max matrix: ");
  for(i = 0;i < m; i++)
    for(j = 0;j < n; j++)
      scanf("%d", &s->max[i][j]);
  printf("Enter allocation matrix: ");
  for(i = 0; i < m; i++)
    for(j = 0; j < n; j++) {
      scanf("%d", &s->allocation[i][j]);
    }
  printf("\n");

  /* Calcuate the need matrix */
  for(i = 0; i < m; i++)
    for(j = 0; j < n; j++)
      s->need[i][j] = s->max[i][j]-s->allocation[i][j];

  /* Calcuate the availability vector */
  for(j = 0; j < n; j++) {
    int sum = 0;
    for(i = 0; i < m; i++)
      sum += s->allocation[i][j];
    s->available[j] = s->resource[j] - sum;
  }

  /* Output need matrix and availability vector */
  printf("Need matrix:\n");
  for(i = 0; i < n; i++)
    printf("R%d ", i+1);
  printf("\n");
  for(i = 0; i < m; i++) {
    for(j = 0; j < n; j++)
      printf("%d  ",s->need[i][j]);
    printf("\n");
  }
  printf("Availability vector:\n");
  for(i = 0; i < n; i++)
    printf("R%d ", i+1);
  printf("\n");
  for(j = 0; j < n; j++)
    printf("%d  ",s->available[j]);
  printf("\n");

  /* If initial state is unsafe then terminate with error */
  if (safe() == 0) {
    printf("An error occurred. The state is not safe\n");
    exit(0);
  }

  /* Seed the random number generator */
  struct timeval tv;
  gettimeofday(&tv, NULL);
  srand(tv.tv_usec);

  /* Create m threads */
  pthread_t *tid = malloc(m*sizeof(pthread_t));
  for (i = 0; i < m; i++)
    pthread_create(&tid[i], NULL, process_thread, (void *) (long) i);

  /* Wait for threads to finish */
  pthread_exit(0);
  free(tid);

  free(s->available);
  free(s->resource);
  free_double_matrix(s->max);
  free_double_matrix(s->allocation);
  free_double_matrix(s->need);
  free(s);

  printf("done");
}
コード例 #3
0
ファイル: numerics.c プロジェクト: Leixushu/ISITEK
int update_face_numerics(int n_variables_old, int n_variables, int *variable_order_old, int *variable_order, int n_faces, struct FACE *face, int n_boundaries_old, struct BOUNDARY *boundary_old)
{
	int a, b, f, g, h, i, j, v;

	// lists of old face boundaries
	int **face_n_boundaries_old = allocate_integer_matrix(NULL,n_faces,n_variables);
	exit_if_false(face_n_boundaries_old != NULL,"allocating face_n_boundaries_old");
	for(i = 0; i < n_faces; i ++) for(j = 0; j < n_variables; j ++) face_n_boundaries_old[i][j] = 0;

	int ***face_boundary_old = allocate_integer_tensor(NULL,n_faces,n_variables,MAX_FACE_N_BOUNDARIES);
	exit_if_false(face_boundary_old != NULL,"allocating face_boundary_old");

	for(b = 0; b < n_boundaries_old; b ++)
	{
		for(i = 0; i < boundary_old[b].n_faces; i ++)
		{
			v = boundary_old[b].variable;
			f = boundary_old[b].face[i] - &face[0];
			face_boundary_old[f][v][face_n_boundaries_old[f][v]++] = b;
		}
	}

	// order and numbers of integration points and bases
	int max_variable_order = 0, max_variable_order_old = 0;
	for(v = 0; v < n_variables; v ++) max_variable_order = MAX(max_variable_order,variable_order[v]);
	for(v = 0; v < n_variables_old; v ++) max_variable_order_old = MAX(max_variable_order_old,variable_order_old[v]);

	int n_gauss = ORDER_TO_N_GAUSS(max_variable_order), n_hammer = ORDER_TO_N_HAMMER(max_variable_order);
	int n_points[MAX_FACE_N_BORDERS], sum_n_points[MAX_FACE_N_BORDERS+1];

	int *n_basis = (int *)malloc(n_variables * sizeof(int)), max_n_basis = ORDER_TO_N_BASIS(max_variable_order);
	exit_if_false(n_basis != NULL,"allocating n_basis");
	for(v = 0; v < n_variables; v ++) n_basis[v] = ORDER_TO_N_BASIS(variable_order[v]);

	// truth values for updating the interpolation on a face
	int *update = (int *)malloc(n_variables * sizeof(int)), max_update = max_variable_order != max_variable_order_old, any_update;
	exit_if_false(update != NULL,"allocating update");

	// transformation
	double **R = allocate_double_matrix(NULL,2,2), det_R, **inv_R = allocate_double_matrix(NULL,2,2);
	exit_if_false(R != NULL,"allocating R");
	exit_if_false(inv_R != NULL,"allocating inv_R");
	double **T = allocate_double_matrix(NULL,max_n_basis,max_n_basis);
	exit_if_false(T != NULL,"allocating T");

	// centre
	double **centre = allocate_double_matrix(NULL,2,1);
	exit_if_false(centre != NULL,"allocating centre");

	// differentials
	int condition[2], none[2] = {0,0};

	// integration locations in cartesian (x) and tranformed (y) coordinates
	double **x, **y;
	double **x_adj[MAX_FACE_N_BORDERS], ***y_adj;
	exit_if_false(y = allocate_double_matrix(NULL,2,n_gauss),"allocating y");
	exit_if_false(y_adj = allocate_double_tensor(NULL,MAX_FACE_N_BORDERS,2,n_hammer*(MAX_ELEMENT_N_FACES-2)),"allocating y_adj");

	// adjacent elements and boundaries to the face
	int n_adj, n_bnd;
	struct ELEMENT **adj;
	struct BOUNDARY **bnd;

	// interpolation problem sizes
	int n_adj_bases = MAX_FACE_N_BORDERS*max_n_basis; // number of adjacent bases
	int n_int_terms = MAX_FACE_N_BORDERS*max_n_basis + MAX_FACE_N_BOUNDARIES; // number of terms from which to interpolate
	int n_int_bases = MAX_FACE_N_BORDERS*max_n_basis + MAX_FACE_N_BOUNDARIES*max_variable_order; // number of interpolant bases

	// face basis taylor indices
	int *face_taylor = (int *)malloc(n_int_bases * sizeof(int));
	exit_if_false(face_taylor != NULL,"allocating face_taylor");

	// temporary matrices
	int ldp, lds, ldq;
	ldp = lds = ldq = MAX_FACE_N_BORDERS*(MAX_ELEMENT_N_FACES-2)*n_hammer;
	int sizep = n_adj_bases*ldp;
	double **P = allocate_double_matrix(NULL,n_adj_bases,ldp);
	double **S = allocate_double_matrix(NULL,n_adj_bases,lds);
	double **Q = allocate_double_matrix(NULL,n_int_bases,ldp);

	int lda, ldb;
	lda = ldb = n_int_bases;
	double **A = allocate_double_matrix(NULL,n_int_bases,n_int_bases);
	double **B = allocate_double_matrix(NULL,n_int_bases,n_int_bases);

	int ldf, ldd;
	ldf = ldd = n_gauss;
	double **F = allocate_double_matrix(NULL,n_int_bases,n_gauss);
	double ***D = allocate_double_tensor(NULL,max_n_basis,n_int_terms,n_gauss);

	int incd = n_int_terms*n_gauss, incq;

	exit_if_false(P != NULL && S != NULL && Q != NULL && A != NULL && B != NULL && F != NULL && D != NULL,"allocating working matrices");

	// blas 
	char trans[2] = "NT";
	int i_one = 1;
	double d_one = 1.0, d_zero = 0.0;

	// lapack
	int info, *pivot = (int *)malloc(n_int_bases * sizeof(int));
	exit_if_false(pivot != NULL,"allocating pivot");

	int updated = 0;

	for(f = 0; f < n_faces; f ++)
	{
		// see if face interpolation needs updating
		any_update = 0;
		for(v = 0; v < n_variables; v ++)
		{
			update[v] = 0;
			if(v >= n_variables_old) update[v] = 1;
			else if(variable_order[v] != variable_order_old[v]) update[v] = 1;
			else if(face[f].n_boundaries[v] != face_n_boundaries_old[f][v]) update[v] = 1;
			else for(i = 0; i < face[f].n_boundaries[v]; i ++)
				for(j = 0; j < 2; j ++)
					if(face[f].boundary[v][i]->condition[j] != boundary_old[face_boundary_old[f][v][i]].condition[j])
						update[v] = 1;
			any_update += update[v];
		}
		if(!any_update) continue;

		// allocate matrices
		exit_if_false(face[f].Q = allocate_face_q(&face[f],n_variables,n_basis,n_gauss),"allocating face Q");

		// rotation to face coordinates
		R[0][0] = + face[f].normal[0]; R[0][1] = + face[f].normal[1];
		R[1][0] = - face[f].normal[1]; R[1][1] = + face[f].normal[0];
		det_R = R[0][0]*R[1][1] - R[0][1]*R[1][0];
		inv_R[0][0] = + R[1][1]/det_R; inv_R[0][1] = - R[0][1]/det_R;
		inv_R[1][0] = - R[1][0]/det_R; inv_R[1][1] = + R[0][0]/det_R;
		transformation_matrix(max_variable_order,T,inv_R);

		// face integration locations
		x = face[f].X;
		for(g = 0; g < n_gauss; g ++)
		{
			for(i = 0; i < 2; i ++)
			{
				y[i][g] = face[f].centre[i];
				for(j = 0; j < 2; j ++) y[i][g] += R[i][j]*(x[j][g] - face[f].centre[j]);
			}
		}

		// numbers of element integration locations
		for(a = 0; a < face[f].n_borders; a ++) n_points[a] = n_hammer*(face[f].border[a]->n_faces-2);
		sum_n_points[0] = 0;
		for(a = 0; a < face[f].n_borders; a ++) sum_n_points[a+1] = sum_n_points[a] + n_points[a];

		// adjacent element integration locations
		for(a = 0; a < face[f].n_borders; a ++)
		{
			x_adj[a] = face[f].border[a]->X;
			for(h = 0; h < n_points[a]; h ++)
			{
				for(i = 0; i < 2; i ++)
				{
					y_adj[a][i][h] = face[f].centre[i];
					for(j = 0; j < 2; j ++) y_adj[a][i][h] += R[i][j]*(x_adj[a][j][h] - face[f].centre[j]);
				}
			}
		}

		// for all variables
		for(v = 0; v < n_variables; v ++)
		{
			if(!max_update && !update[v]) continue;

			n_adj = face[f].n_borders;
			adj = face[f].border;
			n_bnd = face[f].n_boundaries[v];
			bnd = face[f].boundary[v];

			n_adj_bases = n_adj*n_basis[v];
			n_int_terms = n_adj_bases + n_bnd;

			// face basis indices
			n_int_bases = 0;
			for(i = 0; i < n_adj*variable_order[v] + n_bnd; i ++)
				for(j = 0; j < n_adj*variable_order[v] + n_bnd; j ++)
					if(i + n_adj*j < n_adj*variable_order[v] + n_bnd && j < variable_order[v])
						face_taylor[n_int_bases ++] = powers_taylor[i][j];
			exit_if_false(n_int_bases == n_adj_bases + n_bnd*variable_order[v],"mismatched number of interpolation unknowns");

			// element bases at the integration locations
			for(i = 0; i < n_adj*n_basis[v]; i ++) for(j = 0; j < sum_n_points[n_adj]; j ++) P[i][j] = 0.0;
			for(a = 0; a < n_adj; a ++)
				for(i = 0; i < n_basis[v]; i ++)
					basis(n_points[a],&P[i+a*n_basis[v]][sum_n_points[a]],x_adj[a],adj[a]->centre,adj[a]->size,i,none);

			// face bases at the integration locations
			for(a = 0; a < n_adj; a ++)
				for(i = 0; i < n_int_bases; i ++)
					basis(n_points[a],&Q[i][sum_n_points[a]],y_adj[a],face[f].centre,face[f].size,face_taylor[i],none);

			// centre of face in form which can be passed to basis
			for(i = 0; i < 2; i ++) centre[i][0] = face[f].centre[i];

			// integration matrix
			dcopy_(&sizep,P[0],&i_one,S[0],&i_one);
			for(a = 0; a < n_adj; a ++)
				for(i = 0; i < n_points[a]; i ++)
					dscal_(&n_basis[v],&adj[a]->W[i],&S[a*n_basis[v]][i+sum_n_points[a]],&lds);

			// weak interpolation system
			dgemm_(&trans[1],&trans[0],&n_adj_bases,&n_int_bases,&sum_n_points[n_adj],&d_one,S[0],&lds,Q[0],&ldq,&d_zero,A[0],&lda);

			// weak interpolation rhs
			dgemm_(&trans[1],&trans[0],&n_adj_bases,&n_adj_bases,&sum_n_points[n_adj],&d_one,S[0],&lds,P[0],&ldp,&d_zero,B[0],&ldb);

			// boundary conditions
			for(b = 0; b < n_bnd; b ++)
			{
				condition[0] = bnd[b]->condition[0];
				for(i = 0; i < variable_order[v]; i ++)
				{
					condition[1] = bnd[b]->condition[1] + i;
					for(j = 0; j < n_int_bases; j ++)
						basis(1,&A[j][i+n_adj_bases],centre,face[f].centre,face[f].size,face_taylor[j],condition);
				}

				for(i = 0; i < variable_order[v]; i ++) for(j = 0; j < n_int_terms; j ++) B[j][i+n_adj_bases] = 0.0;
				for(i = 0; i < n_adj_bases; i ++) B[n_adj_bases+b][i] = 0.0;
				B[b+n_adj_bases][b*variable_order[v]+n_adj_bases] = 1.0;
			}

			// solve interpolation problem
			dgesv_(&n_int_bases,&n_int_terms,A[0],&lda,pivot,B[0],&ldb,&info);

			// interpolate values to the face integration locations
			for(i = 0; i < n_basis[v]; i ++)
			{
				for(j = 0; j < n_int_bases; j ++) basis(n_gauss,F[j],y,face[f].centre,face[f].size,face_taylor[j],taylor_powers[i]);
				dgemm_(&trans[0],&trans[0],&n_gauss,&n_int_terms,&n_int_bases,&d_one,F[0],&ldf,B[0],&ldb,&d_zero,D[i][0],&ldd);
			}

			// transform from face to cartesian coordinates
			incq = n_int_terms*n_gauss;
			for(i = 0; i < n_int_terms; i ++)
				for(j = 0; j < n_gauss; j ++)
					dgemv_(&trans[1],&n_basis[v],&n_basis[v],&d_one,T[0],&max_n_basis,&D[0][i][j],&incd,&d_zero,&face[f].Q[v][0][i][j],&incq);

			updated ++;
		}
	}

	// clean up
	destroy_matrix((void *)face_n_boundaries_old);
	destroy_tensor((void *)face_boundary_old);

	free(n_basis);
	free(update);

	destroy_matrix((void *)R);
	destroy_matrix((void *)inv_R);
	destroy_matrix((void *)T);

	destroy_matrix((void *)centre);
	destroy_matrix((void *)y);
	destroy_tensor((void *)y_adj);

	free(face_taylor);

	destroy_matrix((void *)P);
	destroy_matrix((void *)Q);
	destroy_matrix((void *)S);
	destroy_matrix((void *)A);
	destroy_matrix((void *)B);
	destroy_matrix((void *)F);
	destroy_tensor((void *)D);

	free(pivot);

	return updated;
}
コード例 #4
0
ファイル: numerics.c プロジェクト: Leixushu/ISITEK
int update_element_numerics(int n_variables_old, int n_variables, int *variable_order_old, int *variable_order, int n_elements, struct ELEMENT *element)
{
	int e, i, j, v;

	// old and new maximum variable orders
	int max_variable_order = 0, max_variable_order_old = 0;
	for(v = 0; v < n_variables; v ++) max_variable_order = MAX(max_variable_order,variable_order[v]);
	for(v = 0; v < n_variables_old; v ++) max_variable_order_old = MAX(max_variable_order_old,variable_order_old[v]);

	// what needs updating
	int max_update = max_variable_order != max_variable_order_old, any_update = n_variables_old < n_variables;
	for(v = 0; v < MIN(n_variables_old,n_variables); v ++) any_update = any_update || (variable_order_old[v] != variable_order[v]);
	if(!any_update) return 0;

	// numbers of basis functions
	int *n_basis, max_n_basis = ORDER_TO_N_BASIS(max_variable_order);
	exit_if_false(n_basis = (int *)malloc(n_variables * sizeof(int)),"allocating n_basis");
        for(v = 0; v < n_variables; v ++) n_basis[v] = ORDER_TO_N_BASIS(variable_order[v]);

	// numbers of points
	int n_gauss = ORDER_TO_N_GAUSS(max_variable_order), n_hammer = ORDER_TO_N_HAMMER(max_variable_order), n_points;

	// no differential
	int no_differential[2] = {0,0};

	// working matrices
	int lds = max_n_basis, ldm = max_n_basis, ldd = max_n_basis, lda = max_n_basis;
        int sizem = max_n_basis*max_n_basis;
	double **S = allocate_double_matrix(NULL,(MAX_ELEMENT_N_FACES-2)*n_hammer,lds);
	double **M = allocate_double_matrix(NULL,max_n_basis,ldm);
        double **D = allocate_double_matrix(NULL,max_n_basis,ldd);
	double **A = allocate_double_matrix(NULL,max_n_basis,lda);
	double **X = allocate_double_matrix(NULL,2,MAX_ELEMENT_N_FACES);
	exit_if_false(S != NULL && M != NULL && A != NULL && X != NULL,"allocating working matrices");

	// lapack and blas
	int info, *pivot = (int *)malloc((max_n_basis + 2) * sizeof(int));
        exit_if_false(pivot != NULL,"allocating pivot");
        char trans[2] = "NT";
        int int_1 = 1;
        double dbl_0 = 0.0, dbl_1 = 1.0;

	for(e = 0; e < n_elements; e ++)
	{
		n_points = n_hammer*(element[e].n_faces - 2);

		if(max_update)
		{
			// interior matrices
			exit_if_false(element[e].P = allocate_element_p(&element[e],max_n_basis,n_points),"allocating element P");
			for(i = 0; i < max_n_basis; i ++)
				for(j = 0; j < max_n_basis; j ++)
					basis(n_points,element[e].P[i][j],element[e].X,element[e].centre,element[e].size,j,taylor_powers[i]);

			// face matrices
			exit_if_false(element[e].Q = allocate_element_q(&element[e],max_n_basis,n_gauss),"allocating element Q");
			for(i = 0; i < element[e].n_faces; i ++)
				for(j = 0; j < max_n_basis; j ++)
					basis(n_gauss,element[e].Q[i][j],element[e].face[i]->X,element[e].centre,element[e].size,j,no_differential);

			// corner matrix
			exit_if_false(element[e].V = allocate_element_v(&element[e],max_n_basis),"allocating element V");
			for(i = 0; i < element[e].n_faces; i ++)
				for(j = 0; j < 2; j ++)
					X[j][i] = element[e].face[i]->node[element[e].face[i]->border[0] != &element[e]]->x[j];
			for(i = 0; i < max_n_basis; i ++)
				basis(element[e].n_faces,element[e].V[i],X,element[e].centre,element[e].size,i,no_differential);
		}

		// mass matrix
                for(i = 0; i < max_n_basis; i ++) dcopy_(&n_points,element[e].P[powers_taylor[0][0]][i],&int_1,&S[0][i],&lds);
                for(i = 0; i < n_points; i ++) dscal_(&max_n_basis,&element[e].W[i],S[i],&int_1);
                dgemm_(&trans[0],&trans[0],&max_n_basis,&max_n_basis,&n_points,&dbl_1,S[0],&lds,element[e].P[powers_taylor[0][0]][0],&n_points,&dbl_0,M[0],&ldm);

		// initialise matrices
		exit_if_false(element[e].I = allocate_element_i(&element[e],n_variables,n_basis,n_points),"allocating element I");
                for(v = 0; v < n_variables; v ++)
                {
			if(!max_update && n_variables_old > v) if(variable_order_old[v] == variable_order[v]) continue;
			for(i = 0; i < n_basis[v]; i ++) dcopy_(&n_points,&S[0][i],&lds,&element[e].I[v][0][i],&n_basis[v]);
			dcopy_(&sizem,M[0],&int_1,A[0],&int_1);
			dgesv_(&n_basis[v],&n_points,A[0],&lda,pivot,element[e].I[v][0],&n_basis[v],&info);
		}

		// limiting matrices
		if(max_n_basis > 1)
		{
			// diffusion matrix
			for(i = 0; i < max_n_basis; i ++) dcopy_(&n_points,element[e].P[powers_taylor[1][0]][i],&int_1,&S[0][i],&lds);
			for(i = 0; i < n_points; i ++) dscal_(&max_n_basis,&element[e].W[i],S[i],&int_1);
			dgemm_(&trans[0],&trans[0],&max_n_basis,&max_n_basis,&n_points,&dbl_1,S[0],&lds,element[e].P[powers_taylor[1][0]][0],&n_points,&dbl_0,D[0],&ldd);
			for(i = 0; i < max_n_basis; i ++) dcopy_(&n_points,element[e].P[powers_taylor[0][1]][i],&int_1,&S[0][i],&lds);
			for(i = 0; i < n_points; i ++) dscal_(&max_n_basis,&element[e].W[i],S[i],&int_1);
			dgemm_(&trans[0],&trans[0],&max_n_basis,&max_n_basis,&n_points,&dbl_1,S[0],&lds,element[e].P[powers_taylor[0][1]][0],&n_points,&dbl_1,D[0],&ldd);
		}

		// limiting matrices
		exit_if_false(element[e].L = allocate_element_l(&element[e],n_variables,n_basis),"allocating element L");
		for(v = 0; v < n_variables; v ++)
		{
			if(n_variables_old > v) if(variable_order_old[v] == variable_order[v]) continue;
			if(variable_order[v] == 1) continue;
			dcopy_(&sizem,M[0],&int_1,A[0],&int_1);
			for(i = 0; i < n_basis[v]; i ++) dcopy_(&n_basis[v],D[i],&int_1,element[e].L[v][i],&int_1);
			dgesv_(&n_basis[v],&n_basis[v],A[0],&lda,pivot,element[e].L[v][0],&n_basis[v],&info);
		}
	}

	free(n_basis);
	destroy_matrix((void *)S);
	destroy_matrix((void *)M);
	destroy_matrix((void *)D);
	destroy_matrix((void *)A);
	destroy_matrix((void *)X);
	free(pivot);

	return n_elements;
}
コード例 #5
0
ファイル: numerics.c プロジェクト: will-bainbridge/AUPLAS
int constrained_least_squares(int m, int n, double **matrix, int c, int *constrained)
{
	//check problem dimensions
	if(m < 1 || n < 1 || n > m || c > n) return LS_DIMENSION_ERROR;

	//counters
	int i, j;

	//extra problem dimensions
	int f = m - c, u = n - c;

	//lapack and blas inputs
	char transa, transb;
	double alpha, beta;

	//lapack output
	int info;

	//lapack workspace
	int lwork = m*m;
	double *work; if(!allocate_double_vector(&work, lwork)) { return LS_MEMORY_ERROR; }

	//lapack LU pivot indices
	int *ipiv; if(!allocate_integer_vector(&ipiv,c)) { return LS_MEMORY_ERROR; }

	//lapack coefficients of QR elementary reflectors
	double *tau; if(!allocate_double_vector(&tau,c)) { return LS_MEMORY_ERROR; }

	//matrices used
	double **t_matrix; if(!allocate_double_matrix(&t_matrix, m, m)) { return LS_MEMORY_ERROR; }
	double **c_matrix; if(!allocate_double_matrix(&c_matrix, n, n)) { return LS_MEMORY_ERROR; }
	double **r_matrix; if(!allocate_double_matrix(&r_matrix, c, c)) { return LS_MEMORY_ERROR; }
	double **a_matrix; if(!allocate_double_matrix(&a_matrix, n, f)) { return LS_MEMORY_ERROR; }
	double **d_matrix; if(!allocate_double_matrix(&d_matrix, f, f)) { return LS_MEMORY_ERROR; }

	//indices of unconstrained equations
	int *temp, *unconstrained;
	if(!allocate_integer_vector(&temp,m)) { return LS_MEMORY_ERROR; }
	if(!allocate_integer_vector(&unconstrained,f)) { return LS_MEMORY_ERROR; }

	//create vector of unconstrained indices
	for(i = 0; i < m; i ++) temp[i] = 0;
	for(i = 0; i < c; i ++) temp[constrained[i]] = 1;
	j = 0;
	for(i = 0; i < m; i ++) if(!temp[i]) unconstrained[j++] = i;

	//copy unconstrained equations from input matrix -> t_matrix
	for(i = 0; i < f; i ++) for(j = 0; j < n; j ++) t_matrix[i][j] = matrix[j][unconstrained[i]];

	//copy constrained equations from input matrix -> c_matrix
	for(i = 0; i < c; i ++) for(j = 0; j < n; j ++) c_matrix[i][j] = matrix[j][constrained[i]];

	//QR decomposition of the transposed constrained equations -> c_matrix
	dgeqrf_(&n, &c, c_matrix[0], &n, tau, work, &lwork, &info);

	//copy R out of the above QR decomposition -> r_matrix
	for(i = 0; i < c; i ++) for(j = 0; j < c; j ++) r_matrix[i][j] = ((j >= i) ? c_matrix[j][i] : 0);

	//form the square matrix Q from the above QR decomposition -> c_matrix'
	dorgqr_(&n, &n, &c, c_matrix[0], &n, tau, work, &lwork, &info);

	//multiply unconstrained eqations by Q -> a_matrix'
	transa = 'T'; transb = 'N'; alpha = 1.0; beta = 0.0;
	dgemm_(&transa, &transb, &f, &n, &n, &alpha, t_matrix[0], &m, c_matrix[0], &n, &beta, a_matrix[0], &f);

	//invert R' of the above QR decomposition -> r_matrix
	dgetrf_(&c, &c, r_matrix[0], &c, ipiv, &info);
	dgetri_(&c, r_matrix[0], &c, ipiv, work, &lwork, &info);

	//LS inversion of the non-square parts from unconstrained * Q -> d_matrix'
	for(i = 0; i < f; i ++) for(j = 0; j < u; j ++) t_matrix[j][i] = a_matrix[j+c][i];
	for(i = 0; i < f; i ++) for(j = 0; j < f; j ++) d_matrix[i][j] = (i == j);
	transa = 'N';
	dgels_(&transa, &f, &u, &f, t_matrix[0], &m, d_matrix[0], &f, work, &lwork, &info);

	//multiply matrices together to form the CLS solution -> t_matrix'
	transa = transb = 'N'; alpha = 1.0; beta = 0.0;
	dgemm_(&transa, &transb, &n, &f, &u, &alpha, c_matrix[c], &n, d_matrix[0], &f, &beta, t_matrix[0], &m);

	alpha = -1.0; beta = 1.0;
	dgemm_(&transa, &transb, &n, &c, &f, &alpha, t_matrix[0], &m, a_matrix[0], &f, &beta, c_matrix[0], &n);

	alpha = 1.0; beta = 0.0;
	dgemm_(&transa, &transb, &n, &c, &c, &alpha, c_matrix[0], &n, r_matrix[0], &c, &beta, t_matrix[f], &m);

	//copy the result out of the temporary matrix -> matrix
	for(i = 0; i < n; i ++) for(j = 0; j < f; j ++) matrix[i][unconstrained[j]] = t_matrix[j][i];
	for(i = 0; i < n; i ++) for(j = 0; j < c; j ++) matrix[i][constrained[j]] = t_matrix[j+f][i];

	//clean up and return successful
	free_vector(work);
	free_vector(ipiv);
	free_vector(tau);
	free_vector(temp);
	free_vector(unconstrained);
	free_matrix((void **)t_matrix);
	free_matrix((void **)c_matrix);
	free_matrix((void **)r_matrix);
	free_matrix((void **)a_matrix);
	free_matrix((void **)d_matrix);
	return LS_SUCCESS;
}
コード例 #6
0
ファイル: numerics.c プロジェクト: will-bainbridge/AUPLAS
void calculate_cell_reconstruction_matrices(int n_variables, double *weight_exponent, int *maximum_order, struct FACE *face, int n_cells, struct CELL *cell, struct ZONE *zone)
{
	int c, u, i, j, k, l;

	int order, n_powers, n_stencil;

	//find the overall maximum order
	int maximum_maximum_order = 0;
	for(u = 0; u < n_variables; u ++) if(maximum_order[u] > maximum_maximum_order) maximum_maximum_order = maximum_order[u];

	//cell structure allocation
	for(c = 0; c < n_cells; c ++) exit_if_false(cell_matrix_new(n_variables, &cell[c]),"allocating cell matrices");

	//numerics values
	double **matrix, *weight;
	int n_constraints, *constraint;
	exit_if_false(allocate_double_matrix(&matrix,ORDER_TO_POWERS(maximum_maximum_order),MAX_STENCIL),"allocating matrix");
	exit_if_false(allocate_integer_vector(&constraint,MAX_STENCIL),"allocating constraints");
	exit_if_false(allocate_double_vector(&weight,MAX_STENCIL),"allocating weights");

	//stencil element properties
	int s_id, s_index;
	struct ZONE *s_zone;
	char s_location, *s_condition;
	double s_area, *s_centroid, s_weight;

	//integration
	double x[2];
	int differential[2], d;

	//CV polygon
	int n_polygon;
	double ***polygon;
	exit_if_false(allocate_double_pointer_matrix(&polygon,MAX(MAX_CELL_FACES,4),2),"allocating polygon memory");

	for(c = 0; c < n_cells; c ++)
	{
		for(u = 0; u < n_variables; u ++)
		{
			//problem size
			order = cell[c].order[u];
			n_powers = ORDER_TO_POWERS(order);
			n_stencil = cell[c].n_stencil[u];
			n_constraints = 0;

			for(i = 0; i < n_stencil; i ++)
			{
				//stencil element properties
				s_id = cell[c].stencil[u][i];
				s_index = ID_TO_INDEX(s_id);
				s_zone = &zone[ID_TO_ZONE(s_id)];
				s_location = s_zone->location;
				s_condition = s_zone->condition;

				if(s_location == 'f') {
					s_centroid = face[s_index].centroid;
					s_area = face[s_index].area;
				} else if(s_location == 'c') {
					s_centroid = cell[s_index].centroid;
					s_area = cell[s_index].area;
				} else exit_if_false(0,"recognising zone location");

				s_weight  = (s_centroid[0] - cell[c].centroid[0])*(s_centroid[0] - cell[c].centroid[0]);
				s_weight += (s_centroid[1] - cell[c].centroid[1])*(s_centroid[1] - cell[c].centroid[1]);
				s_weight  = 1.0/pow(s_weight,0.5*weight_exponent[u]);
				if(s_location == 'c' && s_index == c) s_weight = 1.0;

				weight[i] = s_weight;

				//unknown and dirichlet conditions have zero differentiation
				differential[0] = differential[1] = 0;
				//other conditions have differential determined from numbers of x and y-s in the condition string
				if(s_condition[0] != 'u' && s_condition[0] != 'd')
				{
					j = 0;
					while(s_condition[j] != '\0')
					{
						differential[0] += (s_condition[j] == 'x');
						differential[1] += (s_condition[j] == 'y');
						j ++;
					}
				}

				//index for the determined differential
				d = differential_index[differential[0]][differential[1]];

				//unknowns
				if(s_condition[0] == 'u')
				{
					/*//fit unknowns to centroid points
					x[0] = s_centroid[0] - cell[c].centroid[0];
					x[1] = s_centroid[1] - cell[c].centroid[1];

					for(j = 0; j < n_powers; j ++)
					{
						matrix[j][i] = polynomial_coefficient[d][j]*
							integer_power(x[0],polynomial_power_x[d][j])*
							integer_power(x[1],polynomial_power_y[d][j])*
							s_weight;
					}*/

					//fit unknowns to CV average
					n_polygon = generate_control_volume_polygon(polygon, s_index, s_location, face, cell);

					for(j = 0; j < n_powers; j ++) matrix[j][i] = 0.0;

					for(j = 0; j <= order; j ++) 
					{
						for(k = 0; k < n_polygon; k ++)
						{
							x[0] =  0.5*polygon[k][0][0]*(1.0 - gauss_x[order][j]) +
								0.5*polygon[k][1][0]*(1.0 + gauss_x[order][j]) -
								cell[c].centroid[0];
							x[1] =  0.5*polygon[k][0][1]*(1.0 - gauss_x[order][j]) +
								0.5*polygon[k][1][1]*(1.0 + gauss_x[order][j]) -
								cell[c].centroid[1];

							for(l = 0; l < n_powers; l ++)
							{
								//[face integral of polynomial integrated wrt x] * [x normal] / [CV area]
								
								matrix[l][i] += polynomial_coefficient[d][l] *
									(1.0 / (polynomial_power_x[d][l] + 1.0)) *
									integer_power(x[0],polynomial_power_x[d][l]+1) *
									integer_power(x[1],polynomial_power_y[d][l]) *
									s_weight * gauss_w[order][j] * 0.5 *
									(polygon[k][1][1] - polygon[k][0][1]) / s_area;
							}
						}
					}
				}

				//knowns
				else
				{
					//known faces fit to face average
					if(s_location == 'f')
					{
						for(j = 0; j < n_powers; j ++) matrix[j][i] = 0.0;

						for(j = 0; j < order; j ++)
						{
							x[0] =  0.5*face[s_index].node[0]->x[0]*(1.0 - gauss_x[order-1][j]) +
								0.5*face[s_index].node[1]->x[0]*(1.0 + gauss_x[order-1][j]) - 
								cell[c].centroid[0];
							x[1] =  0.5*face[s_index].node[0]->x[1]*(1.0 - gauss_x[order-1][j]) +
								0.5*face[s_index].node[1]->x[1]*(1.0 + gauss_x[order-1][j]) -
								cell[c].centroid[1];

							for(k = 0; k < n_powers; k ++)
							{
								matrix[k][i] += polynomial_coefficient[d][k] *
									integer_power(x[0],polynomial_power_x[d][k]) *
									integer_power(x[1],polynomial_power_y[d][k]) *
									s_weight*gauss_w[order-1][j]*0.5;
							}
						}
					}

					//cells need implementing
					//if(s_location == 'c')
					//{
					//}
				}

				//constraints are the centre cell and any dirichlet boundaries
				if((s_location == 'c' && s_index == c) || s_condition[0] == 'd') constraint[n_constraints++] = i;
			}

			//solve
			if(n_constraints > 0)
				exit_if_false(constrained_least_squares(n_stencil,n_powers,matrix,n_constraints,constraint) == LS_SUCCESS, "doing CLS calculation");
			else
				exit_if_false(least_squares(n_stencil,n_powers,matrix) == LS_SUCCESS,"doing LS calculation");

			//multiply by the weights
			for(i = 0; i < n_powers; i ++) for(j = 0; j < n_stencil; j ++) matrix[i][j] *= weight[j];

			//store in the cell structure
			for(i = 0; i < n_powers; i ++) for(j = 0; j < n_stencil; j ++) cell[c].matrix[u][i][j] = matrix[i][j];
		}
	}

	//clean up
	free_matrix((void**)matrix);
	free_vector(constraint);
	free_vector(weight);
	free_matrix((void**)polygon);
}