void stat_reset(void) /* Reset the statusline pointer and clear old messages if expired. */ { if (stat_ktl > 0 && --stat_ktl == 0) { statusrow= STATUSROW; need_help= 1; } if (need_help && statusrow < (24-2)) { if (statusrow > STATUSROW) stat_start(0); stat_start(0); putstr( "Type '+' or '-' to change, 'r' to read, '?' for more help, 'q' to exit"); } statusrow= STATUSROW; need_help= 0; }
/* * Fetch a file */ static int fetch(char *URL, const char *path) { struct url *url; struct url_stat us; struct stat sb, nsb; struct xferstat xs; FILE *f, *of; size_t size, readcnt, wr; off_t count; char flags[8]; const char *slash; char *tmppath; int r; unsigned timeout; char *ptr; f = of = NULL; tmppath = NULL; timeout = 0; *flags = 0; count = 0; /* set verbosity level */ if (v_level > 1) strcat(flags, "v"); if (v_level > 2) fetchDebug = 1; /* parse URL */ if ((url = fetchParseURL(URL)) == NULL) { warnx("%s: parse error", URL); goto failure; } /* if no scheme was specified, take a guess */ if (*url->scheme == 0) { if (*url->host == 0) strcpy(url->scheme, SCHEME_FILE); else if (strncasecmp(url->host, "ftp.", 4) == 0) strcpy(url->scheme, SCHEME_FTP); else if (strncasecmp(url->host, "www.", 4) == 0) strcpy(url->scheme, SCHEME_HTTP); } /* common flags */ switch (family) { case PF_INET: strcat(flags, "4"); break; case PF_INET6: strcat(flags, "6"); break; } /* FTP specific flags */ if (strcmp(url->scheme, SCHEME_FTP) == 0) { if (p_flag) strcat(flags, "p"); if (d_flag) strcat(flags, "d"); if (U_flag) strcat(flags, "l"); timeout = T_secs ? T_secs : ftp_timeout; } /* HTTP specific flags */ if (strcmp(url->scheme, SCHEME_HTTP) == 0 || strcmp(url->scheme, SCHEME_HTTPS) == 0) { if (d_flag) strcat(flags, "d"); if (A_flag) strcat(flags, "A"); timeout = T_secs ? T_secs : http_timeout; if (i_flag) { if (stat(i_filename, &sb)) { warn("%s: stat()", i_filename); goto failure; } url->ims_time = sb.st_mtime; strcat(flags, "i"); } } /* set the protocol timeout. */ fetchTimeout = timeout; /* just print size */ if (s_flag) { if (timeout) alarm(timeout); r = fetchStat(url, &us, flags); if (timeout) alarm(0); if (sigalrm || sigint) goto signal; if (r == -1) { warnx("%s", fetchLastErrString); goto failure; } if (us.size == -1) printf("Unknown\n"); else printf("%jd\n", (intmax_t)us.size); goto success; } /* * If the -r flag was specified, we have to compare the local * and remote files, so we should really do a fetchStat() * first, but I know of at least one HTTP server that only * sends the content size in response to GET requests, and * leaves it out of replies to HEAD requests. Also, in the * (frequent) case that the local and remote files match but * the local file is truncated, we have sufficient information * before the compare to issue a correct request. Therefore, * we always issue a GET request as if we were sure the local * file was a truncated copy of the remote file; we can drop * the connection later if we change our minds. */ sb.st_size = -1; if (!o_stdout) { r = stat(path, &sb); if (r == 0 && r_flag && S_ISREG(sb.st_mode)) { url->offset = sb.st_size; } else if (r == -1 || !S_ISREG(sb.st_mode)) { /* * Whatever value sb.st_size has now is either * wrong (if stat(2) failed) or irrelevant (if the * path does not refer to a regular file) */ sb.st_size = -1; } if (r == -1 && errno != ENOENT) { warnx("%s: stat()", path); goto failure; } } /* start the transfer */ if (timeout) alarm(timeout); f = fetchXGet(url, &us, flags); if (timeout) alarm(0); if (sigalrm || sigint) goto signal; if (f == NULL) { warnx("%s: %s", URL, fetchLastErrString); if (i_flag && strcmp(url->scheme, SCHEME_HTTP) == 0 && fetchLastErrCode == FETCH_OK && strcmp(fetchLastErrString, "Not Modified") == 0) { /* HTTP Not Modified Response, return OK. */ r = 0; goto done; } else goto failure; } if (sigint) goto signal; /* check that size is as expected */ if (S_size) { if (us.size == -1) { warnx("%s: size unknown", URL); } else if (us.size != S_size) { warnx("%s: size mismatch: expected %jd, actual %jd", URL, (intmax_t)S_size, (intmax_t)us.size); goto failure; } } /* symlink instead of copy */ if (l_flag && strcmp(url->scheme, "file") == 0 && !o_stdout) { if (symlink(url->doc, path) == -1) { warn("%s: symlink()", path); goto failure; } goto success; } if (us.size == -1 && !o_stdout && v_level > 0) warnx("%s: size of remote file is not known", URL); if (v_level > 1) { if (sb.st_size != -1) fprintf(stderr, "local size / mtime: %jd / %ld\n", (intmax_t)sb.st_size, (long)sb.st_mtime); if (us.size != -1) fprintf(stderr, "remote size / mtime: %jd / %ld\n", (intmax_t)us.size, (long)us.mtime); } /* open output file */ if (o_stdout) { /* output to stdout */ of = stdout; } else if (r_flag && sb.st_size != -1) { /* resume mode, local file exists */ if (!F_flag && us.mtime && sb.st_mtime != us.mtime) { /* no match! have to refetch */ fclose(f); /* if precious, warn the user and give up */ if (R_flag) { warnx("%s: local modification time " "does not match remote", path); goto failure_keep; } } else if (us.size != -1) { if (us.size == sb.st_size) /* nothing to do */ goto success; if (sb.st_size > us.size) { /* local file too long! */ warnx("%s: local file (%jd bytes) is longer " "than remote file (%jd bytes)", path, (intmax_t)sb.st_size, (intmax_t)us.size); goto failure; } /* we got it, open local file */ if ((of = fopen(path, "a")) == NULL) { warn("%s: fopen()", path); goto failure; } /* check that it didn't move under our feet */ if (fstat(fileno(of), &nsb) == -1) { /* can't happen! */ warn("%s: fstat()", path); goto failure; } if (nsb.st_dev != sb.st_dev || nsb.st_ino != nsb.st_ino || nsb.st_size != sb.st_size) { warnx("%s: file has changed", URL); fclose(of); of = NULL; sb = nsb; } } } else if (m_flag && sb.st_size != -1) { /* mirror mode, local file exists */ if (sb.st_size == us.size && sb.st_mtime == us.mtime) goto success; } if (of == NULL) { /* * We don't yet have an output file; either this is a * vanilla run with no special flags, or the local and * remote files didn't match. */ if (url->offset > 0) { /* * We tried to restart a transfer, but for * some reason gave up - so we have to restart * from scratch if we want the whole file */ url->offset = 0; if ((f = fetchXGet(url, &us, flags)) == NULL) { warnx("%s: %s", URL, fetchLastErrString); goto failure; } if (sigint) goto signal; } /* construct a temporary file name */ if (sb.st_size != -1 && S_ISREG(sb.st_mode)) { if ((slash = strrchr(path, '/')) == NULL) slash = path; else ++slash; asprintf(&tmppath, "%.*s.fetch.XXXXXX.%s", (int)(slash - path), path, slash); if (tmppath != NULL) { if (mkstemps(tmppath, strlen(slash)+1) == -1) { warn("%s: mkstemps()", path); goto failure; } of = fopen(tmppath, "w"); chown(tmppath, sb.st_uid, sb.st_gid); chmod(tmppath, sb.st_mode & ALLPERMS); } } if (of == NULL) if ((of = fopen(path, "w")) == NULL) { warn("%s: fopen()", path); goto failure; } } count = url->offset; /* start the counter */ stat_start(&xs, path, us.size, count); sigalrm = siginfo = sigint = 0; /* suck in the data */ signal(SIGINFO, sig_handler); while (!sigint) { if (us.size != -1 && us.size - count < B_size && us.size - count >= 0) size = us.size - count; else size = B_size; if (siginfo) { stat_end(&xs); siginfo = 0; } if (size == 0) break; if ((readcnt = fread(buf, 1, size, f)) < size) { if (ferror(f) && errno == EINTR && !sigint) clearerr(f); else if (readcnt == 0) break; } stat_update(&xs, count += readcnt); for (ptr = buf; readcnt > 0; ptr += wr, readcnt -= wr) if ((wr = fwrite(ptr, 1, readcnt, of)) < readcnt) { if (ferror(of) && errno == EINTR && !sigint) clearerr(of); else break; } if (readcnt != 0) break; } if (!sigalrm) sigalrm = ferror(f) && errno == ETIMEDOUT; signal(SIGINFO, SIG_DFL); stat_end(&xs); /* * If the transfer timed out or was interrupted, we still want to * set the mtime in case the file is not removed (-r or -R) and * the user later restarts the transfer. */ signal: /* set mtime of local file */ if (!n_flag && us.mtime && !o_stdout && of != NULL && (stat(path, &sb) != -1) && sb.st_mode & S_IFREG) { struct timeval tv[2]; fflush(of); tv[0].tv_sec = (long)(us.atime ? us.atime : us.mtime); tv[1].tv_sec = (long)us.mtime; tv[0].tv_usec = tv[1].tv_usec = 0; if (utimes(tmppath ? tmppath : path, tv)) warn("%s: utimes()", tmppath ? tmppath : path); } /* timed out or interrupted? */ if (sigalrm) warnx("transfer timed out"); if (sigint) { warnx("transfer interrupted"); goto failure; } /* timeout / interrupt before connection completley established? */ if (f == NULL) goto failure; if (!sigalrm) { /* check the status of our files */ if (ferror(f)) warn("%s", URL); if (ferror(of)) warn("%s", path); if (ferror(f) || ferror(of)) goto failure; } /* did the transfer complete normally? */ if (us.size != -1 && count < us.size) { warnx("%s appears to be truncated: %jd/%jd bytes", path, (intmax_t)count, (intmax_t)us.size); goto failure_keep; } /* * If the transfer timed out and we didn't know how much to * expect, assume the worst (i.e. we didn't get all of it) */ if (sigalrm && us.size == -1) { warnx("%s may be truncated", path); goto failure_keep; } success: r = 0; if (tmppath != NULL && rename(tmppath, path) == -1) { warn("%s: rename()", path); goto failure_keep; } goto done; failure: if (of && of != stdout && !R_flag && !r_flag) if (stat(path, &sb) != -1 && (sb.st_mode & S_IFREG)) unlink(tmppath ? tmppath : path); if (R_flag && tmppath != NULL && sb.st_size == -1) rename(tmppath, path); /* ignore errors here */ failure_keep: r = -1; goto done; done: if (f) fclose(f); if (of && of != stdout) fclose(of); if (url) fetchFreeURL(url); if (tmppath != NULL) free(tmppath); return (r); }
void* non_adaptive_fmm_periodic_ws2(GenericFmmThreadArg *arg) { FmmvHandle *FMMV = arg->fh; int thread = arg->thread; Box *box, *box1, *box2; int level; int i, j, k, jj; void (*GEN_M)(FmmvHandle *FMMV, Box *box) = FMMV->gen_M; void (*EVAL_L)(FmmvHandle *FMMV, Box *box) = FMMV->eval_L; void (*EVAL_DIRECT)(FmmvHandle *FMMV, Box *target, Box *source) = FMMV->eval_direct; void (*EVAL_DIRECT_periodic)(FmmvHandle *FMMV, Box *target, Box *source, _FLOAT_ dx, _FLOAT_ dy #if (FMM_DIM>=3) , _FLOAT_ dz #endif ) = FMMV->eval_direct_periodic; switch(thread) { case (FARFIELD_THREAD): stat_start(FMMV, STAT_FARFIELD); break; case (NEARFIELD_THREAD): stat_start(FMMV, STAT_NEARFIELD); break; default: break; } if ((thread==STANDARD_THREAD)||(thread==FARFIELD_THREAD)) { /*** Upward Pass ***/ /* Form multipole expansions at finest level */ stat_start(FMMV, STAT_GEN_M); for (box=FMMV->firstSourceBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextSourceBox) { GEN_M(FMMV, box); } stat_stop(FMMV, STAT_GEN_M); /* Form multipole expansions at coarser levels by merging */ stat_start(FMMV, STAT_M2M); init_M2M(FMMV, -1); for (level=FMMV->maxLevel-1; level>=0; level--) {/* note: now compute M up to level 0 */ for (box=FMMV->firstSourceBoxOfLevel[level]; box!=0; box=box->nextSourceBox) { init_M2M(FMMV, level); M2M(FMMV, box); } } finish_M2M(FMMV); stat_stop(FMMV, STAT_M2M); /*** Downward Pass ***/ stat_start(FMMV, STAT_M2L); init_M2L(FMMV, -1); /******************************************************************/ FMMV->firstSourceBoxOfLevel[0]->L = (_FLOAT_ *) FMMV_MALLOC(FMMV, FMM_SIZE_OF_L(FMMV->pL)*sizeof(_FLOAT_)); #ifdef USE_PTHREADS if (thread==FARFIELD_THREAD) { pthread_mutex_lock(&(FMMV->firstSourceBoxOfLevel[0]->mutex)); } #endif periodic_lattice_M2L(FMMV, FMMV->firstSourceBoxOfLevel[0]->M, FMMV->firstSourceBoxOfLevel[0]->L); #ifdef USE_PTHREADS if (thread==FARFIELD_THREAD) { pthread_mutex_unlock(&(FMMV->firstSourceBoxOfLevel[0]->mutex)); } #endif FREE_M(FMMV, FMMV->firstSourceBoxOfLevel[0]->M); /******************************************************************/ if (FMMV->reducedScheme) { /* we need an artificial parent for root */ Box parentOfRoot; box = FMMV->firstSourceBoxOfLevel[0]; parentOfRoot.level = -1; box->whichChild=0; box->parent=&parentOfRoot; for (i=0; i<FMM_CHILDS_PER_BOX; i++) { parentOfRoot.child[i] = box; } for (i=0; i<26; i++) { parentOfRoot.neighbor[i] = &parentOfRoot; } for (i=0; i<6; i++) { parentOfRoot.X[i] = 0; parentOfRoot.X2[i] = 0; } init_M2L(FMMV, 1); M2L_ws2_reduced(FMMV, &parentOfRoot); box = FMMV->firstSourceBoxOfLevel[0]; for (i=0; i<FMM_CHILDS_PER_BOX; i++) { if (box->child[i]) { FREE_M(FMMV, box->child[i]->M); } } for (level=2; level<=FMMV->maxLevel; level++) { /* Convert multipole to exponential expansions and shift exponential expansions */ init_M2L(FMMV, level); for (box=FMMV->firstSourceBoxOfLevel[level-2]; box!=0; box=box->nextSourceBox) { M2L_ws2_reduced(FMMV, box); for (i=0; i<FMM_CHILDS_PER_BOX; i++) { if (box->child[i]) { for (j=0; j<FMM_CHILDS_PER_BOX; j++) { if (box->child[i]->child[j]) { FREE_M(FMMV, box->child[i]->child[j]->M); } } } } } } } else { for (level=1; level<=FMMV->maxLevel; level++) { /* Convert multipole to exponential expansions and shift exponential expansions */ init_M2L(FMMV, level); for (box=FMMV->firstSourceBoxOfLevel[level-1]; box!=0; box=box->nextSourceBox) { M2L_ws2(FMMV, box); for (i=0; i<FMM_CHILDS_PER_BOX; i++) { if (box->child[i]) FREE_M(FMMV, box->child[i]->M); } } } } finish_M2L(FMMV); stat_stop(FMMV, STAT_M2L); /* Shift local expansions from each parent to each of its children */ stat_start(FMMV, STAT_L2L); init_L2L(FMMV, -1); for (level=1; level<=FMMV->maxLevel; level++) { init_L2L(FMMV, level-1); for (box=FMMV->firstTargetBoxOfLevel[level-1]; box!=0; box=box->nextTargetBox) { L2L(FMMV, box); FREE_L(FMMV, box->L); } } finish_L2L(FMMV); stat_stop(FMMV, STAT_L2L); /*** Evaluation of Potentials ***/ stat_start(FMMV, STAT_EVAL_L); if (thread==STANDARD_THREAD) { for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextTargetBox) { /* Evaluate local expansions at finest level */ EVAL_L(FMMV, box); FREE_L(FMMV, box->L); } } /* if (thread==STANDARD_THREAD) */ #ifdef USE_PTHREADS else { /* if (thread==FARFIELD_THREAD) */ for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextTargetBox) { /* Evaluate local expansions at finest level */ pthread_mutex_lock(&(box->mutex)); pthread_mutex_lock(&(box->parent->mutex)); EVAL_L(FMMV, box); pthread_mutex_unlock(&(box->mutex)); pthread_mutex_unlock(&(box->parent->mutex)); FREE_L(FMMV, box->L); } } /* if (thread==FARFIELD_THREAD) */ #endif stat_stop(FMMV, STAT_EVAL_L); } /* if ((thread==STANDARD_THREAD)||(thread==FARFIELD_THREAD)) */ if (thread==STANDARD_THREAD) { stat_start(FMMV, STAT_LIST1); if (FMMV->maxLevel==0) { int dx, dy; #if (FMM_DIM>=3) int dz; #endif box=FMMV->firstTargetBoxOfLevel[0]; EVAL_DIRECT(FMMV, box, box); for (dx=-2; dx<=+2; dx++) { for (dy=-2; dy<=+2; dy++) { #if (FMM_DIM>=3) for (dz=-2; dz<=+2; dz++) { #endif if (!((dx==0)&&(dy==0) #if (FMM_DIM>=3) &&(dz==0) #endif )) { EVAL_DIRECT_periodic(FMMV, box, box, dx, dy #if (FMM_DIM>=3) , dz #endif ); } #if (FMM_DIM>=3) } #endif }} } else { for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel-1]; box!=0; box=box->nextTargetBox) { EVAL_DIRECT(FMMV, box, box); } for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextTargetBox) { for (i=0; i<FMM_CHILDS_PER_BOX-1; i++) { box1 = box->parent->neighbor[k=theseParentNeighbors[box->whichChild][i]]; if (isSource(box1)) { /*&& (box1->firstParticle < box->firstParticle) */ jj=((box->parent->atBoundary) & (boundarysData[k])); EVAL_DIRECT_periodic(FMMV, box, box1, pS[jj].dx, pS[jj].dy #if (FMM_DIM>=3) , pS[jj].dz #endif ); } } for (i=0; i<N_OTHER_NEIGHBORS; i++) { box1 = box->parent->neighbor[k=otherParentNeighborsChilds[box->whichChild][i][0]]; if (isSource(box1)) { jj=((box->parent->atBoundary) & (boundarysData[k])); for (j=2; j<otherParentNeighborsChilds[box->whichChild][i][1]+2; j++) { box2 = box1->child[otherParentNeighborsChilds[box->whichChild][i][j]]; EVAL_DIRECT_periodic(FMMV, box, box2, pS[jj].dx, pS[jj].dy #if (FMM_DIM>=3) , pS[jj].dz #endif ); } } } } } stat_stop(FMMV, STAT_LIST1); } /* if (thread==STANDARD_THREAD) */ #ifdef USE_PTHREADS if (thread==NEARFIELD_THREAD) { stat_start(FMMV, STAT_LIST1); if (FMMV->maxLevel==0) { int dx, dy; #if (FMM_DIM>=3) int dz; #endif box=FMMV->firstTargetBoxOfLevel[0]; pthread_mutex_lock(&(box->mutex)); EVAL_DIRECT(FMMV, box, box); for (dx=-2; dx<=+2; dx++) { for (dy=-2; dy<=+2; dy++) { #if (FMM_DIM>=3) for (dz=-2; dz<=+2; dz++) { #endif if (!((dx==0)&&(dy==0) #if (FMM_DIM>=3) &&(dz==0) #endif )) { EVAL_DIRECT_periodic(FMMV, box, box, dx, dy #if (FMM_DIM>=3) , dz #endif ); } #if (FMM_DIM>=3) } #endif }} pthread_mutex_unlock(&(box->mutex)); } else { for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel-1]; box!=0; box=box->nextTargetBox) { pthread_mutex_lock(&(box->mutex)); EVAL_DIRECT(FMMV, box, box); pthread_mutex_unlock(&(box->mutex)); } for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextTargetBox) { pthread_mutex_lock(&(box->mutex)); if (FMMV->targets) { /* no lock for source boxes */ for (i=0; i<FMM_CHILDS_PER_BOX-1; i++) { box1 = box->parent->neighbor[k=theseParentNeighbors[box->whichChild][i]]; if (isSource(box1)) { /*&& (box1->firstParticle < box->firstParticle) */ jj=((box->parent->atBoundary) & (boundarysData[k])); EVAL_DIRECT_periodic(FMMV, box, box1, pS[jj].dx, pS[jj].dy #if (FMM_DIM>=3) , pS[jj].dz #endif ); } } for (i=0; i<N_OTHER_NEIGHBORS; i++) { box1 = box->parent->neighbor[k=otherParentNeighborsChilds[box->whichChild][i][0]]; if (isSource(box1)) { /* && (box1->firstParticle < box->firstParticle)) { */ jj=((box->parent->atBoundary) & (boundarysData[k])); for (j=2; j<otherParentNeighborsChilds[box->whichChild][i][1]+2; j++) { box2 = box1->child[otherParentNeighborsChilds[box->whichChild][i][j]]; if(box2) { EVAL_DIRECT_periodic(FMMV, box, box2, pS[jj].dx, pS[jj].dy #if (FMM_DIM>=3) , pS[jj].dz #endif ); } } } } } else { for (i=0; i<FMM_CHILDS_PER_BOX-1; i++) { box1 = box->parent->neighbor[k=theseParentNeighbors[box->whichChild][i]]; if (isSource(box1)) { /*&& (box1->firstParticle < box->firstParticle) */ jj=((box->parent->atBoundary) & (boundarysData[k])); pthread_mutex_lock(&(box1->mutex)); EVAL_DIRECT_periodic(FMMV, box, box1, pS[jj].dx, pS[jj].dy #if (FMM_DIM>=3) , pS[jj].dz #endif ); pthread_mutex_unlock(&(box1->mutex)); } } for (i=0; i<N_OTHER_NEIGHBORS; i++) { box1 = box->parent->neighbor[k=otherParentNeighborsChilds[box->whichChild][i][0]]; if (isSource(box1)) { /* && (box1->firstParticle < box->firstParticle)) { */ jj=((box->parent->atBoundary) & (boundarysData[k])); for (j=2; j<otherParentNeighborsChilds[box->whichChild][i][1]+2; j++) { box2 = box1->child[otherParentNeighborsChilds[box->whichChild][i][j]]; if(box2) { pthread_mutex_lock(&(box2->mutex)); EVAL_DIRECT_periodic(FMMV, box, box2, pS[jj].dx, pS[jj].dy #if (FMM_DIM>=3) , pS[jj].dz #endif ); pthread_mutex_unlock(&(box2->mutex)); } } } } } pthread_mutex_unlock(&(box->mutex)); } } stat_stop(FMMV, STAT_LIST1); } /* if (thread==NEARFIELD_THREAD) */ #endif switch(thread) { case (FARFIELD_THREAD): stat_stop(FMMV, STAT_FARFIELD); break; case (NEARFIELD_THREAD): stat_stop(FMMV, STAT_NEARFIELD); break; default: break; } return 0; }
void* non_adaptive_fmm_ws2(GenericFmmThreadArg *arg) { FmmvHandle *FMMV = arg->fh; int thread = arg->thread; Box *box, *box1, *box2; int level; int i, j; void (*GEN_M)(FmmvHandle *FMMV, Box *box) = FMMV->gen_M; void (*EVAL_L)(FmmvHandle *FMMV, Box *box) = FMMV->eval_L; void (*EVAL_DIRECT)(FmmvHandle *FMMV, Box *target, Box *source) = FMMV->eval_direct; switch(thread) { case (FARFIELD_THREAD): stat_start(FMMV, STAT_FARFIELD); break; case (NEARFIELD_THREAD): stat_start(FMMV, STAT_NEARFIELD); break; default: break; } if ((thread==STANDARD_THREAD)||(thread==FARFIELD_THREAD)) { /*** Upward Pass ***/ /* Form multipole expansions at finest level */ stat_start(FMMV, STAT_GEN_M); if (FMMV->maxLevel>1) { for (box=FMMV->firstSourceBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextSourceBox) { GEN_M(FMMV, box); } } stat_stop(FMMV, STAT_GEN_M); /* Form multipole expansions at coarser levels by merging */ stat_start(FMMV, STAT_M2M); init_M2M(FMMV, -1); for (level=FMMV->maxLevel-1; level>=2; level--) { init_M2M(FMMV, level); for (box=FMMV->firstSourceBoxOfLevel[level]; box!=0; box=box->nextSourceBox) { M2M(FMMV, box); } } finish_M2M(FMMV); stat_stop(FMMV, STAT_M2M); /*** Downward Pass ***/ stat_start(FMMV, STAT_M2L); init_M2L(FMMV, -1); if (FMMV->reducedScheme) { for (level=2; level<=FMMV->maxLevel; level++) { init_M2L(FMMV, level); /* Convert multipole to exponential expansions and shift exponential expansions */ for (box=FMMV->firstSourceBoxOfLevel[level-2]; box!=0; box=box->nextSourceBox) { M2L_ws2_reduced(FMMV, box); for (i=0; i<FMM_CHILDS_PER_BOX; i++) { if (box->child[i]) { for (j=0; j<FMM_CHILDS_PER_BOX; j++) { if (box->child[i]->child[j]) { FREE_M(FMMV, box->child[i]->child[j]->M); } } } } } } } else { for (level=2; level<=FMMV->maxLevel; level++) { init_M2L(FMMV, level); /* Convert multipole to exponential expansions and shift exponential expansions */ for (box=FMMV->firstSourceBoxOfLevel[level-1]; box!=0; box=box->nextSourceBox) { M2L_ws2(FMMV, box); for (i=0; i<FMM_CHILDS_PER_BOX; i++) { if (box->child[i]) FREE_M(FMMV, box->child[i]->M); } } } } finish_M2L(FMMV); stat_stop(FMMV, STAT_M2L); /* Shift local expansions from each parent to each of its children */ stat_start(FMMV, STAT_L2L); init_L2L(FMMV, -1); for (level=2; level<=FMMV->maxLevel; level++) { init_L2L(FMMV, level-1); for (box=FMMV->firstTargetBoxOfLevel[level-1]; box!=0; box=box->nextTargetBox) { L2L(FMMV, box); FREE_L(FMMV, box->L); } } finish_L2L(FMMV); stat_stop(FMMV, STAT_L2L); /*** Evaluation of Potentials ***/ stat_start(FMMV, STAT_EVAL_L); if (thread==STANDARD_THREAD) { if (FMMV->maxLevel>1) { for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextTargetBox) { /* Evaluate local expansions at finest level */ EVAL_L(FMMV, box); FREE_L(FMMV, box->L); } } } /* if (thread==STANDARD_THREAD) */ #ifdef USE_PTHREADS else { /* if (thread==FARFIELD_THREAD) */ if (FMMV->maxLevel>1) { for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextTargetBox) { /* Evaluate local expansions at finest level */ pthread_mutex_lock(&(box->parent->mutex)); pthread_mutex_lock(&(box->mutex)); EVAL_L(FMMV, box); pthread_mutex_unlock(&(box->mutex)); pthread_mutex_unlock(&(box->parent->mutex)); FREE_L(FMMV, box->L); } } } /* if (thread==FARFIELD_THREAD) */ #endif stat_stop(FMMV, STAT_EVAL_L); } /* if ((thread==STANDARD_THREAD)||(thread==FARFIELD_THREAD)) */ if (thread==STANDARD_THREAD) { stat_start(FMMV, STAT_LIST1); if (FMMV->maxLevel<=1) { box=FMMV->firstTargetBoxOfLevel[0]; EVAL_DIRECT(FMMV, box, box); } else { for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel-1]; box!=0; box=box->nextTargetBox) { EVAL_DIRECT(FMMV, box, box); } for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextTargetBox) { for (i=0; i<FMM_CHILDS_PER_BOX-1; i++) { box1 = box->parent->neighbor[theseParentNeighbors[box->whichChild][i]]; EVAL_DIRECT(FMMV, box, box1); } for (i=0; i<N_OTHER_NEIGHBORS; i++) { box1 = box->parent->neighbor[otherParentNeighborsChilds[box->whichChild][i][0]]; if (isSource(box1)) { for (j=2; j<otherParentNeighborsChilds[box->whichChild][i][1]+2; j++) { box2 = box1->child[otherParentNeighborsChilds[box->whichChild][i][j]]; EVAL_DIRECT(FMMV, box, box2); } } } } } stat_stop(FMMV, STAT_LIST1); } /* if (thread==STANDARD_THREAD) */ #ifdef USE_PTHREADS if (thread==NEARFIELD_THREAD) { stat_start(FMMV, STAT_LIST1); if (FMMV->maxLevel<=1) { box=FMMV->firstTargetBoxOfLevel[0]; EVAL_DIRECT(FMMV, box, box); } else { for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel-1]; box!=0; box=box->nextTargetBox) { pthread_mutex_lock(&(box->mutex)); EVAL_DIRECT(FMMV, box, box); pthread_mutex_unlock(&(box->mutex)); } for (box=FMMV->firstTargetBoxOfLevel[FMMV->maxLevel]; box!=0; box=box->nextTargetBox) { pthread_mutex_lock(&(box->mutex)); if (FMMV->targets) { /* no lock for source boxes */ for (i=0; i<FMM_CHILDS_PER_BOX-1; i++) { box1 = box->parent->neighbor[theseParentNeighbors[box->whichChild][i]]; if (box1) { EVAL_DIRECT(FMMV, box, box1); } } for (i=0; i<N_OTHER_NEIGHBORS; i++) { box1 = box->parent->neighbor[otherParentNeighborsChilds[box->whichChild][i][0]]; if (isSource(box1)) { for (j=2; j<otherParentNeighborsChilds[box->whichChild][i][1]+2; j++) { box2 = box1->child[otherParentNeighborsChilds[box->whichChild][i][j]]; if (box2) { EVAL_DIRECT(FMMV, box, box2); } } } } } else { for (i=0; i<FMM_CHILDS_PER_BOX-1; i++) { box1 = box->parent->neighbor[theseParentNeighbors[box->whichChild][i]]; if (box1) { pthread_mutex_lock(&(box1->mutex)); EVAL_DIRECT(FMMV, box, box1); pthread_mutex_unlock(&(box1->mutex)); } } for (i=0; i<N_OTHER_NEIGHBORS; i++) { box1 = box->parent->neighbor[otherParentNeighborsChilds[box->whichChild][i][0]]; if (isSource(box1)) { for (j=2; j<otherParentNeighborsChilds[box->whichChild][i][1]+2; j++) { box2 = box1->child[otherParentNeighborsChilds[box->whichChild][i][j]]; if (box2) { pthread_mutex_lock(&(box2->mutex)); EVAL_DIRECT(FMMV, box, box2); pthread_mutex_unlock(&(box2->mutex)); } } } } } pthread_mutex_unlock(&(box->mutex)); } } stat_stop(FMMV, STAT_LIST1); } /* if (thread==NEARFIELD_THREAD) */ #endif switch(thread) { case (FARFIELD_THREAD): stat_stop(FMMV, STAT_FARFIELD); break; case (NEARFIELD_THREAD): stat_stop(FMMV, STAT_NEARFIELD); break; default: break; } return 0; }
/***** INITIALIZE ********************************************************/ char* fmmv_initialize(FmmvHandle **fh, struct FmmvOptions *options, struct FmmvStatistics *statistics) { int err; struct FmmvOptions _options; FmmvHandle *FMMV = *fh; if (!options) { _options = fmmvGetDefaultOptions(); options = &_options; } FMMV->statistics.PAPIeventSet = options->PAPIeventSet; stat_init(FMMV); stat_start(FMMV, STAT_TOTAL); stat_start(FMMV, STAT_INITIALIZE); if (!FMMV) goto _err; /* TODO: check options */ FMMV->beta = options->beta; FMMV->pM = options->pM; FMMV->pL = options->pL; FMMV->s_eps = options->s; FMMV->ws = options->ws; FMMV->splitThreshold = options->splitThreshold; FMMV->splitTargetThreshold = options->splitTargetThreshold; FMMV->maxLevel = options->levels; FMMV->directEvalThreshold = options->directEvalThreshold; FMMV->periodicBoundaryConditions = options->periodicBoundaryConditions; FMMV->extrinsicCorrection = options->extrinsicCorrection; FMMV->scale = (_FLOAT_) options->scale; FMMV->useHilbertOrder = options->useHilbertOrder; FMMV->directEvalAccuracy = options->directEvalAccuracy; FMMV->useFarfieldNearfieldThreads = options->useFarfieldNearfieldThreads; FMMV->reducedScheme = options->reducedScheme; FMMV->lambda = 0; /* TODO: handle addtitional options */ /* if (options->x) { // TODO: no global variables!!! for (i=0; i<FMMV->s_eps; i++) { user_defined_x[i] = (_FLOAT_) options->x[i]; user_defined_w[i] = (_FLOAT_) options->w[i]; user_defined_M[i] = (_FLOAT_) options->M[i]; } FMMV->lambda = user_defined_x; FMMV->w = user_defined_w; FMMV->M = user_defined_M; } */ /* TODO: search for best values: */ if (FMMV->splitThreshold==-1) FMMV->splitThreshold = 200; /* TODO: find precision-, dipole_grad-, etc.- dependent better value */ if (FMMV->splitTargetThreshold==-1) FMMV->splitTargetThreshold = 200; /* TODO: find precision-, dipole_grad-, etc.- dependent better value */ if (FMMV->splitThreshold==0) FMMV->splitTargetThreshold = 0; /* non adaptive FMM! */ #if (FMM_PRECISION==0) if (FMMV->maxLevel==-1) FMMV->maxLevel = 22; #elif (FMM_PRECISION==1) if (FMMV->maxLevel==-1) FMMV->maxLevel = 51; #endif if (FMMV->directEvalThreshold==-1) FMMV->directEvalThreshold = 200; /* TODO: find precision-, dipole_grad-, etc.- dependent better value */ FMMV->allocatedMemory = 0; FMMV->maxAllocatedMemory = 0; FMMV->noOfDirectInteractions = 0; init_all(FMMV); stat_start(FMMV, STAT_BUILD_TREE); FMMV->perm = (int *) FMMV_MALLOC(FMMV, FMMV->NParticles*sizeof(int)); if (FMMV->perm==0) goto _err; if (FMMV->targets) { FMMV->permTargets = (int *) FMMV_MALLOC(FMMV, FMMV->NTargets*sizeof(int)); if (FMMV->permTargets==0) goto _err; err = buildTree_ST(FMMV); if (err) goto _err; } else { FMMV->permTargets = FMMV->perm; err = buildTree(FMMV); if (err) goto _err; } stat_stop(FMMV, STAT_BUILD_TREE); if (FMMV->targets) { FMMV->maxTargetLevel = FMMV->maxLevel; for (; FMMV->firstSourceBoxOfLevel[FMMV->maxLevel] == 0; FMMV->maxLevel--) ; for (; FMMV->firstTargetBoxOfLevel[FMMV->maxTargetLevel] == 0; FMMV->maxTargetLevel--) ; genTreeStatistics_ST(FMMV); } else { for (; FMMV->firstSourceBoxOfLevel[FMMV->maxLevel] == 0; FMMV->maxLevel--) ; genTreeStatistics(FMMV); FMMV->statistics.noOfTargets = -1; FMMV->statistics.noOfTargetLevels = -1; FMMV->statistics.noOfTargetBoxes = -1; FMMV->statistics.noOfTargetLeafBoxes = -1; FMMV->statistics.averageNoOfTargetsPerLeafBox = -1; } ida_allocate(FMMV); copy_particles(FMMV); stat_stop(FMMV, STAT_INITIALIZE); if (statistics) { *statistics = FMMV->statistics; statistics->maxAllocatedMemory = FMMV->maxAllocatedMemory; statistics->noOfDirectInteractions = FMMV->noOfDirectInteractions; statistics->PAPIeventSet = FMMV->statistics.PAPIeventSet; } *fh = (void*) FMMV; return 0; _err: return errbuf; }
/***** EVALUATE ********************************************************/ char* fmmv_evaluate(FmmvHandle *FMMV, struct FmmvStatistics *statistics) { GenericFmmThreadArg STANDARD_THREAD, FARFIELD_THREAD, NEARFIELD_THREAD; #ifdef USE_PTHREADS pthread_t nearfield_thread; #endif int err; stat_start(FMMV, STAT_EVALUATE); FMMV->noOfStoredXin = 0; FMMV->maxNoOfStoredXin = 0; STANDARD_THREAD.fh = FMMV; FARFIELD_THREAD.fh = FMMV; NEARFIELD_THREAD.fh = FMMV; STANDARD_THREAD.thread = 0; FARFIELD_THREAD.thread = 1; NEARFIELD_THREAD.thread = 2; copy_charges(FMMV); zero_pot(FMMV); if (FMMV->useFarfieldNearfieldThreads) { #ifdef USE_PTHREADS if (FMMV->useFarfieldNearfieldThreads<0) { /* test mode */ #endif if (FMMV->periodicBoundaryConditions) { if (FMMV->splitThreshold == 0) { if (FMMV->ws == 1) { non_adaptive_fmm_periodic(&FARFIELD_THREAD); non_adaptive_fmm_periodic(&NEARFIELD_THREAD); } else { /* FMMV->ws == 2 */ non_adaptive_fmm_periodic_ws2(&FARFIELD_THREAD); non_adaptive_fmm_periodic_ws2(&NEARFIELD_THREAD); } } else { assert(0); /* adaptive_fmm_periodic - not yet implemented... */ } } else { if (FMMV->splitThreshold == 0) { if (FMMV->ws == 1) { non_adaptive_fmm(&FARFIELD_THREAD); non_adaptive_fmm(&NEARFIELD_THREAD); } else { /* FMMV->ws == 2 */ non_adaptive_fmm_ws2(&FARFIELD_THREAD); non_adaptive_fmm_ws2(&NEARFIELD_THREAD); } } else { if (FMMV->ws == 1) { if (FMMV->targets) { adaptive_fmm_ST(&FARFIELD_THREAD); adaptive_fmm_ST(&NEARFIELD_THREAD); } else { adaptive_fmm(&FARFIELD_THREAD); adaptive_fmm(&NEARFIELD_THREAD); } } else { /* FMMV->ws == 2 */ assert(0); /*adaptive_fmm_ws2 not yet implemented */ } } } #ifdef USE_PTHREADS } else { if (FMMV->periodicBoundaryConditions) { if (FMMV->splitThreshold == 0) { if (FMMV->ws == 1) { /* TODO error handling ... */ err = pthread_create(&nearfield_thread, 0, (void* (*)(void *)) non_adaptive_fmm_periodic, (void*) &NEARFIELD_THREAD); non_adaptive_fmm_periodic(&FARFIELD_THREAD); } else { /* FMMV->ws == 2 */ /* TODO error handling ... */ err = pthread_create(&nearfield_thread, 0, (void* (*)(void *)) non_adaptive_fmm_periodic_ws2, (void*) &NEARFIELD_THREAD); non_adaptive_fmm_periodic_ws2(&FARFIELD_THREAD); } } else { assert(0); /* adaptive_fmm_periodic - not yet implemented... */ } } else { if (FMMV->splitThreshold == 0) { if (FMMV->ws == 1) { err = pthread_create(&nearfield_thread, 0, (void* (*)(void *)) non_adaptive_fmm, (void*) &NEARFIELD_THREAD); non_adaptive_fmm(&FARFIELD_THREAD); } else { /* FMMV->ws == 2 */ err = pthread_create(&nearfield_thread, 0, (void* (*)(void *)) non_adaptive_fmm_ws2, (void*) &NEARFIELD_THREAD); non_adaptive_fmm_ws2(&FARFIELD_THREAD); } } else { if (FMMV->ws == 1) { if (FMMV->targets) { err = pthread_create(&nearfield_thread, 0, (void* (*)(void *)) adaptive_fmm_ST, (void*) &NEARFIELD_THREAD); adaptive_fmm_ST(&FARFIELD_THREAD); } else { err = pthread_create(&nearfield_thread, 0, (void* (*)(void *)) adaptive_fmm, (void*) &NEARFIELD_THREAD); adaptive_fmm(&FARFIELD_THREAD); } } else { /* FMMV->ws == 2 */ assert(0); /* adaptive_fmm_ws2 not yet implemented */ } } } pthread_join(nearfield_thread, 0); } #endif } else { if (FMMV->periodicBoundaryConditions) { if (FMMV->splitThreshold == 0) { if (FMMV->ws == 1) { non_adaptive_fmm_periodic(&STANDARD_THREAD); } else { /* FMMV->ws == 2 */ non_adaptive_fmm_periodic_ws2(&STANDARD_THREAD); } } else { assert(0); /* adaptive_fmm_periodic - not yet implemented... */ } } else { if (FMMV->splitThreshold == 0) { if (FMMV->ws == 1) { non_adaptive_fmm(&STANDARD_THREAD); } else { /* FMMV->ws == 2 */ non_adaptive_fmm_ws2(&STANDARD_THREAD); } } else { if (FMMV->ws == 1) { if (FMMV->targets) { adaptive_fmm_ST(&STANDARD_THREAD); } else { adaptive_fmm(&STANDARD_THREAD); } } else { /* FMMV->ws == 2 */ assert(0); /* adaptive_fmm_ws2 not yet implemented */ } } } } if (FMMV->periodicBoundaryConditions && FMMV->extrinsicCorrection) { FMMV->extrinsic_correction(FMMV); } backcopy_pot(FMMV); if (FMMV->targets==0) { FMMV->noOfDirectInteractions *= 2; } stat_stop(FMMV, STAT_EVALUATE); if (statistics) { *statistics = FMMV->statistics; statistics->maxNoOfStoredXin = FMMV->maxNoOfStoredXin; statistics->maxAllocatedMemory = FMMV->maxAllocatedMemory; statistics->noOfDirectInteractions = FMMV->noOfDirectInteractions; statistics->PAPIeventSet = FMMV->statistics.PAPIeventSet; } return 0; /* //TODO: error handling _err: return errbuf; */ }