tutorial
来自「并行解法器,功能强大」· 代码 · 共 1,185 行 · 第 1/4 页
TXT
1,185 行
Replace 68b printf("Enter grid size (n, for n x n grid)\n");by 68b printf("Enter grid size (n, n horizontal lines in grid)\n");Replace 73 AZ_read_update(&N_update,&update,proc_config,nrow,1,AZ_linear);by 73 total = 0; /* total is set to the total number of grid points */ 73a for (i = 0 ; i < n ; i++ ) { total += (right(i) - left(i)+1);} 73b AZ_read_update(&N_update,&update,proc_config,total,1,AZ_linear);Note: total needs to be declared as well.Replace 86 for (i = 0 ; i < N_update ; i++ ) { 87 create_matrix_row(update[i],i,val,bindx); 88 }by 86 yval = 0; yline_head = 0; 87 next = right(0) - left(0) + 1; 88 for (i = 0 ; i < N_update ; i++ ) { 88a while ( next <= update[i] ) { 88b yline_head = next; yval++; 88c next = yline_head + right(yval) - left(yval) + 1; 88d } 88e create_matrix_row(update[i],i,val,bindx,yline_head,yval,n); 88f }and add the subroutine create_matrix_row():void create_matrix_row(int row,int location,double val[],int bindx[], int yline_head, int yval,int n){/* Add one row to an MSR matrix corresponding to a discrete approximation * on an irregular 2D domain. Specifically, the grid contains n horizontal * lines. The x values on line j start at left(j) and end at right(j). * * Parameters: * row == global row number of the new row to be added. * location == local row where diagonal of the new row will be stored. * val,bindx == (see user's guide). On output, val[] and bindx[] * are appended such that the new row has been added. * yline_head == global row number of the first grid point in the * horizontal line containing 'row'. * yval == horizontal line y = yval contains 'row'. * n == total number of horizontal lines in grid. */ int b_neigh = 0, t_neigh = 0, l_neigh = 0, r_neigh = 0; int lval0 = 0, rval1 = 0, lval2 = 0, rval2 = 0, lval3 = 0, rval3 = 0; extern int left(), right(); int normalized, k; normalized = yline_head - left(yval); l_neigh = row-1; lval0 = normalized + left(yval) + 1; r_neigh = row+1; rval1 = normalized + right(yval) - 1; if (yval != 0) { b_neigh = row+left(yval)-right(yval-1)-1; lval2 = normalized + left(yval-1); rval2 = normalized + right(yval-1); } else rval2 = lval2 - 1; if (yval != n-1) { t_neigh = row-left(yval+1)+right(yval)+1; lval3 = normalized + left(yval+1); rval3 = normalized + right(yval+1); } else rval3 = lval3 - 1; /* check neighbors in each direction and add nonzero if neighbor exits */ k = bindx[location]; bindx[k] = l_neigh; if (row >= lval0) val[k++] = -1.; bindx[k] = r_neigh; if (row <= rval1) val[k++] = -1.; bindx[k] = b_neigh; if ((row >= lval2) && (row <= rval2)) val[k++] = -1.; bindx[k] = t_neigh; if ((row >= lval3) && (row <= rval3)) val[k++] = -1.; bindx[location+1] = k; val[location] = 4.; /* matrix diagonal */} Problem 10:==========Change line 68b in Problem 4 program to 68b printf("Enter grid size (n, for n x n x n grid)\n");Change line 72 in Problem 4 program to 72 nrow=n*n*n;Change #define MAX_NZ_ROW 5to #define MAX_NZ_ROW 7so that the proper amount of memory is allocated in lines 80 & 81.Change line 147 to 147 * to the 3D Poisson operator on an n x n x n square.After line 165, add the following lines:165a bindx[k] = row + n*n; if ((row/(n*n))%n != n-1) val[k++] = -1.;165b bindx[k] = row - n*n; if ((row/(n*n))%n != 0) val[k++] = -1.;and finally change the matrix diagonal in line 167 to 117 bindx[location+1] = k; val[location] = 6.; /* matrix diagonal */Problem 11:==========Our new program is as follows:/* This software was developed at Sandia National Labs under US Energy Dept. * contract DE-AC-4-76DP00789 and is copyrighted by Sandia Corporation. */#include <stdio.h>#include <stdlib.h>#ifdef AZ_MPI#include <mpi.h>#endif#include "az_aztec.h"#define perror(str) { fprintf(stderr,"%s\n",str); exit(-1); }int m, n = 6; /* EQUATIONS WILL BE SOLVED ON an n x n x n GRID. */void main(int argc, char *argv[])/* Set up a coupled PDE test problem and solve it with AZTEC. */{ double *b,*x; /* rhs and approximate solution */ int i, j, nrow; extern void create_matrix_row(int row,int location, int rpntr[],int bpntr[], int bindx[], int indx[],double val[]); /* See Aztec User's Guide for the variables that follow: */ int proc_config[AZ_PROC_SIZE];/* Processor information. */ int options[AZ_OPTIONS_SIZE]; /* Array used to select solver options. */ double params[AZ_PARAMS_SIZE]; /* User selected solver paramters. */ int *data_org; /* Array to specify data layout */ double status[AZ_STATUS_SIZE]; /* Information returned from AZ_solve(). */ int *update, /* vector elements updated on this node. */ *external; /* vector elements needed by this node. */ int *update_index; /* ordering of update[] and external[] */ int *extern_index; /* locally on this processor. */ int *bindx; /* Sparse matrix to be solved is stored */ double *val; /* in these MSR arrays. */ int *indx,*cpntr,*bpntr,*rpntr; int N_update; /* # of unknowns updated on this node */#ifdef AZ_MPI MPI_Init(&argc,&argv);#endif /* get number of processors and the name of this processor */ AZ_processor_info(proc_config); if (proc_config[AZ_node] == 0) { printf("Enter grid size (n, for n x n x n grid)\n"); scanf("%d",&n); printf("Enter number of PDEs\n"); scanf("%d",&m); } AZ_broadcast((char *) &n, sizeof(int), proc_config, AZ_PACK); AZ_broadcast((char *) &m, sizeof(int), proc_config, AZ_PACK); AZ_broadcast(NULL , 0, proc_config, AZ_SEND); /* Define partitioning:matrix rows (ascending order) owned by this node */ nrow = n*n*n; AZ_read_update(&N_update,&update,proc_config,nrow,1,AZ_linear); /* create the matrix: each processor creates only rows */ /* appearing in update[] (using global col. numbers). */ rpntr = (int *) calloc(N_update+1,sizeof(int)); bpntr = (int *) calloc(N_update+1,sizeof(int)); bindx = (int *) calloc(N_update*7+1,sizeof(int)); indx = (int *) calloc(N_update*7+1,sizeof(int)); val = (double *) calloc(m*m*N_update*7+1,sizeof(double)); if (val == NULL) perror("Error: Not enough space to create matrix") rpntr[0] = 0; bpntr[0] = 0; indx[0] = 0; for (i = 0 ; i < N_update ; i++ ) { create_matrix_row(update[i],i,rpntr,bpntr,bindx,indx,val); } /* convert matrix to a local distributed matrix */ AZ_transform(proc_config,&external,bindx,val,update,&update_index, &extern_index,&data_org,N_update,indx,bpntr,rpntr,&cpntr,AZ_VBR_MATRIX); /* initialize AZTEC options */ AZ_defaults(options, params); options[AZ_solver] = AZ_tfqmr; params[AZ_tol] = 1.0e-5; /* Set rhs (delta function at lower left corner) and initialize guess */ b = (double *) calloc(m*N_update,sizeof(double)); x = (double *) calloc(m*N_update + data_org[AZ_N_external],sizeof(double)); if ((x == NULL) && (i != 0)) perror("Not enough space in rhs") for (i=0 ; i < N_update; i++ ) { for (j = 0 ; j < m ; j++ ) { x[m*update_index[i]+j] = 0.0; b[m*update_index[i]+j] = 0.0; } if (update[i] == 0 ) b[m*update_index[i]] = 1.0; } /* solve the system of equations using b as the right hand side */ AZ_solve(x,b, options, params, indx,bindx,rpntr,cpntr,bpntr,val, data_org, status, proc_config);#ifdef AZ_MPI MPI_Finalize();#endif}/***************************************************************************//***************************************************************************/void create_matrix_row(int row,int location, int rpntr[],int bpntr[],int bindx[], int indx[],double val[]){/* Add one row to an MSR matrix corresponding to a discrete approximation * to the 3D Poisson operator on an n x n x n square. * * Parameters: * row == global row number of the new row to be added. * location == local row where diagonal of the new row will be stored. * val,bindx == (see user's guide). On output, val[] and bindx[] * are appended such that the new row has been added. */ int k; extern void VBR_block(int indx[],int *k,double val[],double factor); /* check neighbors in each direction and add nonzero if neighbor exits */ rpntr[location+1] = rpntr[location] + m; k = bpntr[location]; bindx[k] = row; VBR_block(indx,&k,val, 6.); bindx[k] = row + 1; if ((row )%n != n-1) VBR_block(indx,&k,val,-1.); bindx[k] = row - 1; if ((row )%n != 0) VBR_block(indx,&k,val,-1.); bindx[k] = row + n; if ((row/n)%n != n-1) VBR_block(indx,&k,val,-1.); bindx[k] = row - n; if ((row/n)%n != 0) VBR_block(indx,&k,val,-1.); bindx[k] = row + n*n; if ((row/(n*n))%n != n-1) VBR_block(indx,&k,val,-1.); bindx[k] = row - n*n; if ((row/(n*n))%n != 0) VBR_block(indx,&k,val,-1.); bpntr[location+1] = k; }void VBR_block(int indx[],int *k,double val[],double factor){ int i,j,indx_ptr; indx_ptr = indx[*k]; indx[*k+1] = indx_ptr + m*m; for (i = 0 ; i < m ; i++ ) { for (j = 0 ; j < m ; j++ ) { if (i == j) val[indx_ptr++] = factor; else val[indx_ptr++] = factor * .1; } } (*k)++;}All the necessary changes include: 1) new declarations (m,j,*indx,*cpntr,*bpntr,*rpntr) 2) changes in the create_matrix_row(), AZ_transform(), and AZ_solve() parameters 3) adding 3 lines to input m and broadcast it. 4) storage allocation for val,rpntr,bpntr,indx,val,b and x 5) initializing rpntr[0], bpntr[0], indx[0] to 0 6) changing the right hand side and initial guess for VBR format 7) changing create_matrix_row() to call VBR_block instead of setting val[]. 8) adding the subroutine VBR_block()
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?