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; }
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"); }
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; }
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; }
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; }
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); }