blob: a9a4feeb1a5ae5f17f2d0ae1b8ffc83de343e4b6 [file] [log] [blame]
//------------------------------------------------------------------------------------------------------------------------------
// Samuel Williams
// SWWilliams@lbl.gov
// Lawrence Berkeley National Lab
//------------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
//------------------------------------------------------------------------------------------------------------------------------
#ifdef OMP
#include <omp.h>
#endif
#ifdef __MPI
#include <mpi.h>
#endif
//------------------------------------------------------------------------------------------------------------------------------
#include "defines.h"
#include "box.h"
#include "mg.h"
#include "operators.h"
//------------------------------------------------------------------------------------------------------------------------------
void MGResetTimers(domain_type * domain);
int main(int argc, char **argv){
int MPI_Rank=0;
int MPI_Tasks=1;
int OMP_Threads = 1;
#ifdef OMP
#pragma omp parallel
{
#pragma omp master
{
OMP_Threads = omp_get_num_threads();
}
}
#endif
#ifdef __MPI
#warning Compiling for MPI...
int MPI_threadingModel = -1;
//int MPI_threadingModelRequested = MPI_THREAD_SINGLE;
//int MPI_threadingModelRequested = MPI_THREAD_SERIALIZED;
int MPI_threadingModelRequested = MPI_THREAD_FUNNELED;
//int MPI_threadingModelRequested = MPI_THREAD_MULTIPLE;
#ifdef __MPI_THREAD_MULTIPLE
MPI_threadingModelRequested = MPI_THREAD_MULTIPLE;
#endif
MPI_Init_thread(&argc, &argv, MPI_threadingModelRequested, &MPI_threadingModel);
MPI_Comm_size(MPI_COMM_WORLD, &MPI_Tasks);
MPI_Comm_rank(MPI_COMM_WORLD, &MPI_Rank);
if(MPI_threadingModel>MPI_threadingModelRequested)MPI_threadingModel=MPI_threadingModelRequested;
if(MPI_Rank==0){
if(MPI_threadingModelRequested == MPI_THREAD_MULTIPLE )printf("Requested MPI_THREAD_MULTIPLE, ");
else if(MPI_threadingModelRequested == MPI_THREAD_SINGLE )printf("Requested MPI_THREAD_SINGLE, ");
else if(MPI_threadingModelRequested == MPI_THREAD_FUNNELED )printf("Requested MPI_THREAD_FUNNELED, ");
else if(MPI_threadingModelRequested == MPI_THREAD_SERIALIZED)printf("Requested MPI_THREAD_SERIALIZED, ");
else if(MPI_threadingModelRequested == MPI_THREAD_MULTIPLE )printf("Requested MPI_THREAD_MULTIPLE, ");
else printf("Requested Unknown MPI Threading Model (%d), ",MPI_threadingModelRequested);
if(MPI_threadingModel == MPI_THREAD_MULTIPLE )printf("got MPI_THREAD_MULTIPLE\n");
else if(MPI_threadingModel == MPI_THREAD_SINGLE )printf("got MPI_THREAD_SINGLE\n");
else if(MPI_threadingModel == MPI_THREAD_FUNNELED )printf("got MPI_THREAD_FUNNELED\n");
else if(MPI_threadingModel == MPI_THREAD_SERIALIZED)printf("got MPI_THREAD_SERIALIZED\n");
else if(MPI_threadingModel == MPI_THREAD_MULTIPLE )printf("got MPI_THREAD_MULTIPLE\n");
else printf("got Unknown MPI Threading Model (%d)\n",MPI_threadingModel);
fflush(stdout); }
#ifdef __MPI_THREAD_MULTIPLE
if( (MPI_threadingModelRequested == MPI_THREAD_MULTIPLE) && (MPI_threadingModel != MPI_THREAD_MULTIPLE) ){MPI_Finalize();exit(0);}
#endif
#endif
int log2_subdomain_dim = 6;
int subdomains_per_rank_in_i=256 / (1<<log2_subdomain_dim);
int subdomains_per_rank_in_j=256 / (1<<log2_subdomain_dim);
int subdomains_per_rank_in_k=256 / (1<<log2_subdomain_dim);
int ranks_in_i=1;
int ranks_in_j=1;
int ranks_in_k=1;
if(argc==2){
log2_subdomain_dim=atoi(argv[1]);
subdomains_per_rank_in_i=256 / (1<<log2_subdomain_dim);
subdomains_per_rank_in_j=256 / (1<<log2_subdomain_dim);
subdomains_per_rank_in_k=256 / (1<<log2_subdomain_dim);
}else if(argc==5){
log2_subdomain_dim=atoi(argv[1]);
subdomains_per_rank_in_i=atoi(argv[2]);
subdomains_per_rank_in_j=atoi(argv[3]);
subdomains_per_rank_in_k=atoi(argv[4]);
}else if(argc==8){
log2_subdomain_dim=atoi(argv[1]);
subdomains_per_rank_in_i=atoi(argv[2]);
subdomains_per_rank_in_j=atoi(argv[3]);
subdomains_per_rank_in_k=atoi(argv[4]);
ranks_in_i=atoi(argv[5]);
ranks_in_j=atoi(argv[6]);
ranks_in_k=atoi(argv[7]);
}else if(argc!=1){
if(MPI_Rank==0){printf("usage: ./a.out [log2_subdomain_dim] [subdomains per rank in i,j,k] [ranks in i,j,k]\n");}
#ifdef __MPI
MPI_Finalize();
#endif
exit(0);
}
/*
if(log2_subdomain_dim>7){
if(MPI_Rank==0){printf("error, log2_subdomain_dim(%d)>7\n",log2_subdomain_dim);}
#ifdef __MPI
MPI_Finalize();
#endif
exit(0);
}
*/
if(ranks_in_i*ranks_in_j*ranks_in_k != MPI_Tasks){
if(MPI_Rank==0){printf("error, ranks_in_i*ranks_in_j*ranks_in_k(%d*%d*%d=%d) != MPI_Tasks(%d)\n",ranks_in_i,ranks_in_j,ranks_in_k,ranks_in_i*ranks_in_j*ranks_in_k,MPI_Tasks);}
#ifdef __MPI
MPI_Finalize();
#endif
exit(0);
}
if(MPI_Rank==0)printf("%d MPI Tasks of %d threads\n",MPI_Tasks,OMP_Threads);
int subdomain_dim_i=1<<log2_subdomain_dim;
int subdomain_dim_j=1<<log2_subdomain_dim;
int subdomain_dim_k=1<<log2_subdomain_dim;
// fine dim = 128 64 32 16 8 4
// levels = 6 5 4 3 2 1
//int log2_coarse_dim = 2; // i.e. coarsen to 4^3
int log2_coarse_dim = 1; // i.e. coarsen to 2^3
int levels_in_vcycle=1+log2_subdomain_dim-log2_coarse_dim; // ie 1+log2(fine grid size)-log2(bottom grid size)
if(MPI_Rank==0){printf("truncating the v-cycle at %d^3 subdomains\n",1<<log2_coarse_dim);fflush(stdout);}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int box;
domain_type domain;
int boundary_conditions[3] = {__BOUNDARY_PERIODIC,__BOUNDARY_PERIODIC,__BOUNDARY_PERIODIC}; // i-, j-, and k-directions
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
create_domain(&domain,
subdomain_dim_i,subdomain_dim_j,subdomain_dim_k,
subdomains_per_rank_in_i,subdomains_per_rank_in_j,subdomains_per_rank_in_k,
ranks_in_i,ranks_in_j,ranks_in_k,
MPI_Rank,
boundary_conditions,
__NumGrids,1,levels_in_vcycle);
double h0=1.0/((double)(domain.dim.i));
if(MPI_Rank==0){printf("initializing alpha, beta, RHS for the ``hard problem''...");fflush(stdout);}
double a=0.9; // i.e. good Helmholtz
double b=0.9;
initialize_problem(&domain,0,h0,a,b);
if(MPI_Rank==0){printf("done\n");fflush(stdout);}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MGBuild(&domain,a,b,h0); // restrictions, dominant eigenvalue, etc...
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int s,sMax=2;
#ifdef __MPI
sMax=4;
#endif
//Make initial an guess for u(=0)... Solve Lu=f to precision of 1e-10...print the benchmarking timing results...
MGResetTimers(&domain);for(s=0;s<sMax;s++){zero_grid(&domain,0,__u); MGSolve(&domain,__u,__f,a,b,1e-15);}print_timing(&domain);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// calculate error...
double h3 = h0*h0*h0;
add_grids(&domain,0,__temp,1.0,__u_exact,-1.0,__u); // __temp = __u_exact - __u
double max = norm(&domain,0,__temp); // max norm of error function
double error = sqrt( dot(&domain,0,__temp,__temp)*h3); // normalized L2 error ?
if(MPI_Rank==0){printf("Error test: h = %e, max = %e\n",h0,max);}
if(MPI_Rank==0){printf("Error test: h = %e, L2 = %e\n",h0,error);}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
destroy_domain(&domain);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#ifdef __MPI
MPI_Finalize();
#endif
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
return(0);
}