int main(int argc, char **argv){ uint32_t datarows, datacolumns; uint32_t i, j, k; int world_size, world_rank, rc; //Check input arguments if (argc != 2) { fprintf(stderr,"USAGE: %s <input_filename>\n", argv[0]); exit(1); } // Start MPI rc = MPI_Init(&argc,&argv); if (rc != MPI_SUCCESS) { printf ("Error starting MPI program. Terminating.\n"); MPI_Abort(MPI_COMM_WORLD, rc); } // Get world size (number of MPI processes) and world rank (# of this process) MPI_Comm_size(MPI_COMM_WORLD,&world_size); MPI_Comm_rank(MPI_COMM_WORLD,&world_rank); if (world_rank==0){ // Declare variables used only on the root node int buf[world_size-1], nextReady; MPI_Request reqs[world_size-1]; MPI_Status stats[world_size-1]; // Print format of output printf("Kv\tMbulk\tTliq\tTsatb\tTf\tTsat\tZrsat\tZrf\tFf\tSiO2\tZrbulk\tMZr\tTcryst\n"); // Import 2-d source data array as a flat double array. Format: // SiO2, TiO2, Al2O3, Fe2O3, Cr2O3, FeO, MnO, MgO, NiO, CoO, CaO, Na2O, K2O, P2O5, CO2, H2O, Zr, Kv; double** const data = csvparse(argv[1],',', &datarows, &datacolumns); // Listen for task requests from the worker nodes for (i=1; i<world_size; i++){ // *buf, count, datatype, dest, tag, comm, *request MPI_Irecv(&buf[i-1], 1, MPI_INT, i, 0, MPI_COMM_WORLD, &reqs[i-1]); } // Once any worker asks for a new task, send next task to that worker and keep listening for (i=0; i<datarows; i++){ MPI_Waitany(world_size-1, reqs, &nextReady, stats); // *buf, count, datatype, dest, tag, comm MPI_Send(data[i], 18, MPI_DOUBLE, nextReady+1, 1, MPI_COMM_WORLD); // *buf, count, datatype, source, tag, comm, *request MPI_Irecv(&buf[nextReady], 1, MPI_INT, nextReady+1, 0, MPI_COMM_WORLD, &reqs[nextReady]); } // Wait for all workers to complete, then send the stop signal MPI_Waitall(world_size-1, reqs, stats); double stop[18] = {-1}; for (i=1; i<world_size; i++){ MPI_Send(&stop, 18, MPI_DOUBLE, i, 1, MPI_COMM_WORLD); } } else { // Declare variables used only on the worker nodes MPI_Request sReq; MPI_Status sStat; double ic[18], Kd, iKd; FILE *fp; // char prefix[200], cmd_string[500]; char* prefix = malloc(500*sizeof(char)); char* cmd_string = malloc(1000*sizeof(char)); // Simulation parameters /**********************************************************/ // Version to run MELTS in (MELTS or pMELTS) const char version[]="pMELTS"; // Melts mode (isobaric, ptpath, etc) const char mode[]="isobaric"; // fO2 buffer to use (None, FMQ, etc.) const char fo2Buffer[]="FMQ"; // fO2 offset from buffer double fo2Delta=1; // Initial temperature (Celcius) double Ti=1700; //Initial Pressure (bar) double Pi=600; //Temperature step size in each simulation const int deltaT=-10; // Pressure step size; const int deltaP=0; // Stop simulations at a given percent melt const double minPercentMelt=10; // Variables that control size and location of the simulation /***********************************************************/ // Location of scratch directory (ideally local scratch for each node) // This location may vary on your system - contact your sysadmin if unsure // const char scratchdir[]="/scratch/gpfs/cbkeller/"; const char scratchdir[]="/scratch/"; // Variables that determine how much memory to allocate to imported results const int maxMinerals=100, maxSteps=1700/abs(deltaT), maxColumns=50; /***********************************************************/ // Malloc space for the imported melts array double **rawMatrix=mallocDoubleArray(maxMinerals*maxSteps,maxColumns); double ***melts=malloc(maxMinerals*sizeof(double**)); char **names=malloc(maxMinerals*sizeof(char*)); char ***elements=malloc(maxMinerals*sizeof(char**)); int *meltsrows=malloc(maxMinerals*sizeof(int)), *meltscolumns=malloc(maxMinerals*sizeof(int)); for (i=0; i<maxMinerals; i++){ names[i]=malloc(30*sizeof(char)); elements[i]=malloc(maxColumns*sizeof(char*)); for (k=0; k<maxColumns; k++){ elements[i][k]=malloc(30*sizeof(char)); } } int minerals; // Variables for finding saturation temperature int row, col, P, T, mass, SiO2, TiO2, Al2O3, Fe2O3, Cr2O3, FeO, MnO, MgO, NiO, CoO, CaO, Na2O, K2O, P2O5, CO2, H2O; int fspCaO, fspNa2O, fspK2O, oxideTiO2, oxideFe2O3, oxideFeO, oxideMnO; double M, Tf, Tsat, Tsatbulk, Ts, Tsmax, Zrf, Zrsat, MZr, MZrnow, Tcryst; double AnKd, AbKd, OrKd, IlmKd, MtKd; while (1) { // Ask root node for new task // *buf, count, datatype, dest, tag, comm, *request MPI_Isend(&world_rank, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &sReq); // *buf, count, datatype, source, tag, comm, *status MPI_Recv(&ic, 18, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, &sStat); // Exit loop if stop signal recieved if (ic[0]<0) break; //Configure working directory sprintf(prefix,"%sout%i_%.0f/", scratchdir, world_rank, ic[17]); sprintf(cmd_string,"mkdir -p %s", prefix); system(cmd_string); // //Set water // ic[15]=3.0; // //Set CO2 // ic[14]=0.1; //Run MELTS runmelts(prefix,ic,version,"isobaric",fo2Buffer,fo2Delta,"1\nsc.melts\n10\n1\n3\n1\nliquid\n1\n0.99\n1\n10\n0\n4\n0\n","","!",Ti,Pi,deltaT,deltaP,0.005); // If simulation failed, clean up scratch directory and move on to next simulation sprintf(cmd_string,"%sPhase_main_tbl.txt", prefix); if ((fp = fopen(cmd_string, "r")) == NULL) { fprintf(stderr, "%s : MELTS equilibration failed to produce output.\n", prefix); sprintf(cmd_string,"rm -r %s", prefix); system(cmd_string); continue; } // Import results, if they exist. Format: // Pressure Temperature mass S H V Cp viscosity SiO2 TiO2 Al2O3 Fe2O3 Cr2O3 FeO MnO MgO NiO CoO CaO Na2O K2O P2O5 H2O minerals=maxMinerals; importmelts(maxSteps, maxColumns, prefix, melts, rawMatrix, meltsrows, meltscolumns, names, elements, &minerals); if (minerals<1 | strcmp(names[0],"liquid_0")!=0) { fprintf(stderr, "%s : MELTS equilibration failed to calculate liquid composition.\n", prefix); sprintf(cmd_string,"rm -r %s", prefix); system(cmd_string); continue; } // Can delete temp files after we've read them sprintf(cmd_string,"rm -r %s", prefix); system(cmd_string); // Find the columns containing useful elements for(col=0; col<meltscolumns[0]; col++){ if (strcmp(elements[0][col], "Pressure")==0) P=col; else if (strcmp(elements[0][col], "Temperature")==0) T=col; else if (strcmp(elements[0][col], "mass")==0) mass=col; else if (strcmp(elements[0][col], "SiO2")==0) SiO2=col; else if (strcmp(elements[0][col], "TiO2")==0) TiO2=col; else if (strcmp(elements[0][col], "Al2O3")==0) Al2O3=col; else if (strcmp(elements[0][col], "Fe2O3")==0) Fe2O3=col; else if (strcmp(elements[0][col], "Cr2O3")==0) Cr2O3=col; else if (strcmp(elements[0][col], "FeO")==0) FeO=col; else if (strcmp(elements[0][col], "MnO")==0) MnO=col; else if (strcmp(elements[0][col], "MgO")==0) MgO=col; else if (strcmp(elements[0][col], "NiO")==0) NiO=col; else if (strcmp(elements[0][col], "CoO")==0) CoO=col; else if (strcmp(elements[0][col], "CaO")==0) CaO=col; else if (strcmp(elements[0][col], "Na2O")==0) Na2O=col; else if (strcmp(elements[0][col], "K2O")==0) K2O=col; else if (strcmp(elements[0][col], "P2O5")==0) P2O5=col; else if (strcmp(elements[0][col], "CO2")==0) CO2=col; else if (strcmp(elements[0][col], "H2O")==0) H2O=col; } // Find the columns containing useful elements for other minerals for (i=1; i<minerals; i++){ if (strncasecmp(names[i],"feldspar",8)==0){ for(col=0; col<meltscolumns[i]; col++){ if (strcmp(elements[i][col], "CaO")==0) fspCaO=col; else if (strcmp(elements[i][col], "Na2O")==0) fspNa2O=col; else if (strcmp(elements[i][col], "K2O")==0) fspK2O=col; } } else if (strncasecmp(names[i],"rhm_oxide",9)==0){ for(col=0; col<meltscolumns[i]; col++){ if (strcmp(elements[i][col], "TiO2")==0) oxideTiO2=col; else if (strcmp(elements[i][col], "Fe2O3")==0) oxideFe2O3=col; else if (strcmp(elements[i][col], "FeO")==0) oxideFeO=col; else if (strcmp(elements[i][col], "MnO")==0) oxideMnO=col; } } } // Initial saturation state M = meltsM(&melts[0][0][SiO2]); Zrf = ic[16]; // Zirconium content in melt Tf = melts[0][0][T]; // Current temperature Zrsat = tzircZr(M, Tf); // Zirconium required for saturation Tsatbulk = tzirc(M, Zrf); // Temperature required for saturation // Calculate saturation temperature and minimum necessary zirconium content Tsat=0; Tcryst=0; MZr=0; Tsmax = Tsatbulk; for(row=1; row<(meltsrows[0]-1); row++){ // Calculate bulk zircon partition coefficient at present step Kd = 0; for (i=1; i<minerals; i++){ // See what minerals might be crystallizing at this temperature // so we can find their GERM partition coefficients for (j=0; j<meltsrows[i]; j++){ if (fabs(melts[0][row][T]-melts[i][j][T]) < 0.01){ if (strncasecmp(names[i],"feldspar",8)==0){ AnKd = getGERMKd("AnKdorthite","Zr",melts[0][row][SiO2]); AbKd = getGERMKd("Albite","Zr",melts[0][row][SiO2]); OrKd = getGERMKd("Orthoclase","Zr",melts[0][row][SiO2]); if (isnan(AnKd)) AnKd=0; if (isnan(OrKd)) OrKd=0; if (isnan(AbKd)) AbKd = (AnKd + OrKd)/2; iKd = (220.1298+56.18)/56.18*melts[i][j][fspCaO]/100 * AnKd\ +(228.2335+30.99)/30.99*melts[i][j][fspNa2O]/100 * AbKd\ +(228.2335+47.1)/47.1*melts[i][j][fspK2O]/100 * OrKd; } else if (strncasecmp(names[i],"rhm_oxide",9)==0){ IlmKd = getGERMKd("Ilmenite","Zr",melts[0][row][SiO2]); MtKd = getGERMKd("Magnetite","Zr",melts[0][row][SiO2]); if (isnan(IlmKd)) IlmKd = 0; if (isnan(MtKd)) MtKd = 0; iKd = (melts[i][j][oxideTiO2]+melts[i][j][oxideMnO]+(melts[i][j][oxideTiO2]\ *(71.8444/79.8768)-melts[i][j][oxideMnO]*(71.8444/70.9374)))/100 * AnKd\ + (1 - (melts[i][j][oxideTiO2]+melts[i][j][oxideMnO]+(melts[i][j][oxideTiO2]\ *(71.8444/79.8768)-melts[i][j][oxideMnO]*(71.8444/70.9374)))/100) * MtKd; } else { iKd = getGERMKd(names[i],"Zr",melts[0][row][SiO2]); } if (isnan(iKd)){iKd = 0;} Kd += iKd * melts[i][j][mass]; } } } Kd = Kd / (100 - melts[0][row][mass]); //Calculate melt M and [Zr] M = meltsM(&melts[0][row][SiO2]); Zrf = ic[16]*100/(melts[0][row][mass] + Kd*(100-melts[0][row][mass])); // Zirconium content in melt Tf = melts[0][row][T]; // Current temperature Zrsat = tzircZr(M, Tf); // Zirconium required for saturation Ts = tzirc(M, Zrf); // Temperature required for saturation // Determine how much zircon is saturated if (Zrf>Zrsat){ MZrnow = melts[0][row][mass]/100*(Zrf-Zrsat); if (MZr < MZrnow){ Tcryst += (MZrnow - MZr)*melts[0][row][T]; MZr = MZrnow; } } // Keep track of maximum saturation temperature if (Ts > Tsmax){ Tsmax = Ts; } // Check if we've cooled below the saturation temperature yet if (Tsat==0 && Ts > melts[0][row][T]){ Tsat = Ts; } // Stop when we get to maximum SiO2 if (melts[0][row-1][SiO2]>(melts[0][row][SiO2])+0.01){ row--; break; } // Or when remaining melt falls below minimum percent if (melts[0][row][mass]<minPercentMelt){ row--; break; } } // If zircon never saturated, check what the best (highest) saturation temperature was if (Tsat==0 || MZr==0){ Tsat = Tsmax; Tcryst = NAN; } else { Tcryst = Tcryst / MZr; } // Get back bulk M M = meltsM(&melts[0][0][SiO2]); // Print results. Format: // Kv, Mbulk, Tliquidus, Tsatbulk, Tf, Tsat, Zrsat, Zrf, Ff, SiO2, Zrbulk, MZr, Tcryst printf("%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\n", ic[17], M, melts[0][0][T], Tsatbulk, Tf, Tsat, Zrsat, Zrf, melts[0][row][mass], melts[0][0][SiO2], ic[16], MZr, Tcryst); } } MPI_Finalize(); return 0; }
int main(int argc, char** argv) { memory = new (nothrow) Memory(100); //memory management structure if(argc<5) //not enough arguments printusage(argv[0]); if(argc>5) //debug level provided, parse debuglevel=atoi(argv[5]); if(debuglevel<0 || debuglevel>9) //debug level weird printusage(argv[0]); //choose method int method=-1; if(strncmp(argv[2], "gml", 3)==0) method=0; else if(strncmp(argv[2], "csv", 3)==0) method=1; Nodes* nodes=NULL; switch(method) { case 0: { nodes = gmlparse(argv[1]); //parse nodes as gml break; } case 1: { nodes = csvparse(argv[1]); break; } default: { printusage(argv[0]); } } if(nodes==NULL) { //something got wrong printf("E: Parsing failed. Exiting...\n"); delete memory; exit(1); } //for(int i=0; i<nodes->hashmap->max; i++) // printf("Bucket %d: %d items\n", i, nodes->hashmap->counts[i]); if(nodes->count<100) nodes->Print(); debug(2, "---------------------------------------"); //find root by name Node* root = nodes->Find(argv[4]); if(root==NULL) { printf("E: You must choose valid node id!\n"); delete memory; return 1; } //compute Dijkstra nodes->SPF(root, argv[3]); //delete memory structure (will free everything) delete memory; return 0; }