1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
| #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#include <stdbool.h>
static int nbDl ;
/*! \brief Computes coordinates of point number 'i'
The points are computed on a cylinder defined by 'radius' and 'height'. The number of points is given by nbDl.
\a i should be in [0, nbDl[.
\param i the number of the point (input)
\param coord the coordinates x y z of this point (output)
*/
void computeCoord(int i, double *coord) {
const double radius=0.5 ;
const double height=1. ;
static double angleStep=0. ;
static double zStep=0. ;
double theta ;
if (i<0 || i>=nbDl) {
printf("Incorrect unknown number %d, should be in [0, %d[\n", i, nbDl) ;
exit (-1);
}
if (angleStep==0.) {
zStep=height/(double)nbDl ;
angleStep=sqrt(zStep*2.*M_PI/radius) ;
}
theta=(double)i * angleStep ;
coord[0]=radius * sin(theta) ;
coord[1]=radius * cos(theta) ;
coord[2]=(double)i*zStep ;
return ;
}
void computeKernel(double r, double *kernel) {
*kernel=exp(-r*r)/(r+0.1) ;
}
void computeDistance(double *coord1, double *coord2, double *r) {
double v[3] ;
v[0]=coord1[0]-coord2[0] ;
v[1]=coord1[1]-coord2[1] ;
v[2]=coord1[2]-coord2[2] ;
*r=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]) ;
return ;
}
/*! \brief Computes a block of matrix
We compute the block defined by [rowMin, rowMax] x [colMin, colMax] where index should be in [0, nbDl[.
The output is written in block, an allocated array of sufficient size. The output is a fortran-style, column wise block.
\param rowMin beginning row index
\param rowMax ending row index
\param colMin beginning col index
\param colMax ending col index
\param block
*/
void computeMatrixBlock(int rowMin, int rowMax, int colMin, int colMax, double *block) {
double coord1[3], coord2[3], r, kernel ;
int i, j, pos ;
pos=0 ;
for (j=colMin ; j<=colMax ; j++) {
computeCoord(j, &(coord2[0])) ;
for (i=rowMin ; i<=rowMax ; i++) {
computeCoord(i, &(coord1[0])) ;
computeDistance(&(coord1[0]), &(coord2[0]), &r) ;
computeKernel(r, &(block[pos])) ;
pos++ ;
}
}
return ;
}
void computeRhs(double *rhs) {
double coord[3] ;
int i ;
for (i=0 ; i<nbDl ; i++) {
computeCoord(i, &(coord[0])) ;
rhs[i]=cos(coord[0]+coord[1]+coord[2]) ;
}
return ;
}
void loadFile(char *name, void **p) {
int fd, ierr, header[5] ;
ssize_t res ;
size_t s ;
*p=NULL ;
fd=open(name, O_RDONLY) ;
if(fd==-1) {
printf(" %s not found\n", name) ;
return ;
}
res=read(fd, header, sizeof(int)*5) ;
s=(size_t)header[1]*header[2]*header[3] ;
*p=(void*)malloc(s) ;
res=read(fd, *p, s) ;
if(res!=sizeof(double)*nbDl) exit(-1) ;
ierr=close(fd) ;
if(ierr==-1) exit(errno) ;
return ;
}
void computeRelativeError(double *sol, double *ref, double *eps) {
int i ;
double normRef, normDelta ;
normDelta=0. ;
normRef=0. ;
for (i=0 ; i<nbDl ; i++) {
normDelta += (sol[i]-ref[i])*(sol[i]-ref[i]) ;
normRef += ref[i]*ref[i] ;
}
*eps = sqrt(normDelta/normRef) ;
return ;
}
bool compareSolutions(double *rhs,double threshold) {
char fileName[100] ;
double *rhsRef, eps ;
/* Comparing with MPF solution if available */
sprintf(fileName, "ref_MPF_%d", nbDl) ;
/* Allocates and loads the right hand side */
loadFile(fileName, (void**)&rhsRef) ;
/* Compute relative error */
if (rhsRef) {
computeRelativeError(rhs, rhsRef, &eps) ;
free(rhsRef) ;
if (eps<=threshold) {
return true;
}
else {
return false;
}
}
return false ;
}
extern void solver(int, char**, int, double**, void (*)(int, int, int, int, double*) ) ;
int main(int argc, char **argv) {
int ierr ;
double *rhs ;
struct itimerval tv ;
double t1, t2 ;
double threshold=1e-14;
bool status;
/* Set the number of unknowns */
if (argc > 1)
nbDl=atoi(argv[1]) ;
else
nbDl=60000 ;
/* Allocates and computes the right hand side */
rhs=(double*)calloc(nbDl, sizeof(double)) ;
computeRhs(rhs) ;
/* Init timers */
tv.it_interval.tv_sec = 86400000 ;
tv.it_interval.tv_usec = 0;
tv.it_value.tv_sec = 86400000 ;
tv.it_value.tv_usec = 0;
ierr=setitimer(ITIMER_REAL, &tv, NULL) ;
/* Solves the system by calling the participant's routine */
ierr=getitimer( ITIMER_REAL, &tv ) ;
t1 = -( (double )(tv.it_value.tv_sec)+((double )(tv.it_value.tv_usec))*1.e-6 ) ;
solver(argc, argv, nbDl, &rhs, computeMatrixBlock) ;
ierr=getitimer( ITIMER_REAL, &tv ) ;
t2 = -( (double )(tv.it_value.tv_sec)+((double )(tv.it_value.tv_usec))*1.e-6 ) ;
/* Compare the result to a reference result (if available) */
status=compareSolutions(rhs,threshold);
if(status)
printf("OK %.4f\n", t2-t1);
else
printf("KO\n");
free(rhs) ;
return 0 ;
} |
Partager