int SolveStep::solve(double timestep, double time, std::string name, std::string method, std::string dimension) { /* Solves given system with given parametres using * given method * timestep: size of timestep * time: total simulation time * name: name of files where the position of the * particles are saved at some timesteps * method: verlet or RK4 * dimension: ly or AU * * Ditterent timers have not been used at the * same time.*/ clock_t start, finish; Distance d; //declaration and intialisation omp_set_num_threads(8); //parallelisation double limit = 60; //definition of bound system arma::Col<double> center(3), position(3); center.zeros(); double t = 0.; System newsystem = mysolarsystem_; int n = time/timestep; //file to store energy of the system std::ofstream energy("energy.m"); energy << "A = ["; //file to store energy of the bound system std::ofstream bound("BoundEnergy.m"); bound << "A = ["; //update the objects initial acceleration for (int i = 0 ; i < size() ; ++i) { Object &mainbody = newsystem.objectlist[i]; newsystem.acceleration(mainbody, i, 0.0,dimension); } // start = clock(); //start timer //start simulation for (int k = 0 ; k < n ; ++k) { t += timestep; //file to store position of particles name.append("t"); std::string filename = name; filename.append(".m"); std::ofstream fout(filename.c_str()); fout << "t = " << t << "\n A = ["; //variable needed for calculating intermediate steps double addtime = 0.0; //simulate all particles for one timestep #pragma omp parallel for private(i) for (int i = 0 ; i < size() ; ++i) { Object &mainbody = newsystem.objectlist[i]; System tempSystem = mysolarsystem_; double dt = timestep; int j = 0; double maxTimestep; //chose the smallest timestep if (mainbody.maxTimestep() < tempSystem.maxTimestep(i)) { maxTimestep = mainbody.maxTimestep(); } else { maxTimestep = tempSystem.maxTimestep(i); } //make sure to use small endough timesteps while(dt > maxTimestep) { dt = dt/2.0; j += 1; } //simulate timesteps for (int kk = 0 ; kk < std::pow(2,j); ++kk) { if (method == "rk4") { start = clock(); //start timer rk4Step(dt, i, mainbody, tempSystem, addtime, dimension); finish = clock(); //stop timer std::cout << "time one rk4 step: " << static_cast<double>(finish - start)/ static_cast<double>(CLOCKS_PER_SEC ) << " s" << std::endl; // mainbody.addToFile(name); addtime += dt; } else if(method == "verlet") { start = clock(); //start timer verlet(dt, i, mainbody, tempSystem, addtime, dimension); finish = clock(); //stop timer std::cout << "time one verlet step: " << static_cast<double>(finish - start)/ static_cast<double>(CLOCKS_PER_SEC ) << " s" << std::endl; // mainbody.addToFile(name); addtime += dt; } else { std::cout << "method must be 'verlet' or 'rk4'" << std::endl; } } mysolarsystem_ = newsystem; //save position to file for (int i = 0 ; i < size() ; ++i) { Object &mainbody = mysolarsystem_.objectlist[i]; position = mainbody.getPosition(); double dist = d.twoObjects(position,center) ; if(dist < limit) { fout << mainbody.getPosition()(0) << "\t\t" << mainbody.getPosition()(1) << "\t\t" << mainbody.getPosition()(2) << "\n"; } // else // { // mysolarsystem_.removeObject(i); // i-=1; // } } fout << "]; \n"; fout << "plot3(A(:,1), A(:,2),A(:,3), 'o')\n"; fout << "t = " << t ; fout.close(); } //write energy of the system to file bound << t << "\t\t" << mysolarsystem_.boundPotentialEnergy(limit) << "\t\t" << mysolarsystem_.boundKineticEnergi(limit) << "\n"; energy << t << "\t\t" << mysolarsystem_.potentialEnergy() << "\t\t" << mysolarsystem_.kineticEnergi() << "\n"; if (k % 100 == 0) { std::cout << t << std::endl; } } // finish = clock(); //stop timer // std::cout << "time: " << // static_cast<double>(finish - start)/ // static_cast<double>(CLOCKS_PER_SEC ) << " s" << std::endl; energy << "]; \n"; energy.close(); bound << "]; \n"; bound.close(); for (int i = 0 ; i < size() ; ++i) { Object &mainbody = mysolarsystem_.objectlist[i]; mysolarsystem_.acceleration(mainbody, i, 0.0,dimension); } //write final postition to file std::ofstream fout("end.m"); fout << "A = ["; for (int i = 0 ; i < size() ; ++i) { Object &mainbody = mysolarsystem_.objectlist[i]; fout << mainbody.getPosition()(0) << "\t\t" << mainbody.getPosition()(1) << "\t\t" << mainbody.getPosition()(2) << "\n"; } fout << "] \n"; fout.close(); return 0; }
/** * Name: main * * Description: * See usage statement (run program with '-h' flag). * * Parameters: * @param argc number of command line arguments * @param argv command line arguments */ int main( int argc, char **argv ) { CmdArgs cmd_args; // Command line arguments. int num_comps, num_dendrs; // Simulation parameters. int i, j, t_ms, step, dendrite; // Various indexing variables. struct timeval start, stop, diff; // Values used to measure time. double exec_time; // How long we take. // Accumulators used during dendrite simulation. // NOTE: We depend on the compiler to handle the use of double[] variables as // double*. double current, **dendr_volt; double res[COMPTIME], y[NUMVAR], y0[NUMVAR], dydt[NUMVAR], soma_params[3]; // Strings used to store filenames for the graph and data files. char time_str[14]; char graph_fname[ FNAME_LEN ]; char data_fname[ FNAME_LEN ]; FILE *data_file; // The output file where we store the soma potential values. FILE *graph_file; // File where graph will be saved. PlotInfo pinfo; // Info passed to the plotting functions. ////////////////////////////////////////////////////////////////////////////// // Parse command line arguments. ////////////////////////////////////////////////////////////////////////////// if (!parseArgs( &cmd_args, argc, argv )) { // Something was wrong. exit(1); } // Pull out the parameters so we don't need to type 'cmd_args.' all the time. num_dendrs = cmd_args.num_dendrs; num_comps = cmd_args.num_comps; printf( "Simulating %d dendrites with %d compartments per dendrite.\n", num_dendrs, num_comps ); ////////////////////////////////////////////////////////////////////////////// // Create files where results will be stored. ////////////////////////////////////////////////////////////////////////////// // Generate the graph and data file names. time_t t = time(NULL); struct tm *tmp = localtime( &t ); strftime( time_str, 14, "%m%d%y_%H%M%S", tmp ); // The resulting filenames will resemble // pWWdXXcYY_MoDaYe_HoMiSe.xxx // where 'WW' is the number of processes, 'XX' is the number of dendrites, // 'YY' the number of compartments, and 'MoDaYe...' the time at which this // simulation was run. sprintf( graph_fname, "graphs/p1d%dc%d_%s.png", num_dendrs, num_comps, time_str ); sprintf( data_fname, "data/p1d%dc%d_%s.dat", num_dendrs, num_comps, time_str ); // Verify that the graphs/ and data/ directories exist. Create them if they // don't. struct stat stat_buf; stat( "graphs", &stat_buf ); if ((!S_ISDIR(stat_buf.st_mode)) && (mkdir( "graphs", 0700 ) != 0)) { fprintf( stderr, "Could not create 'graphs' directory!\n" ); exit(1); } stat( "data", &stat_buf ); if ((!S_ISDIR(stat_buf.st_mode)) && (mkdir( "data", 0700 ) != 0)) { fprintf( stderr, "Could not create 'data' directory!\n" ); exit(1); } // Verify that we can open files where results will be stored. if ((data_file = fopen(data_fname, "wb")) == NULL) { fprintf(stderr, "Can't open %s file!\n", data_fname); exit(1); } else { printf( "\nData will be stored in %s\n", data_fname ); } if (ISDEF_PLOT_PNG && (graph_file = fopen(graph_fname, "wb")) == NULL) { fprintf(stderr, "Can't open %s file!\n", graph_fname); exit(1); } else { printf( "Graph will be stored in %s\n", graph_fname ); fclose(graph_file); } ////////////////////////////////////////////////////////////////////////////// // Initialize simulation parameters. ////////////////////////////////////////////////////////////////////////////// // The first compartment is a dummy and the last is connected to the soma. num_comps = num_comps + 2; // Initialize 'y' with precomputed values from the HH model. y[0] = VREST; y[1] = 0.037; y[2] = 0.0148; y[3] = 0.9959; // Setup parameters for the soma. soma_params[0] = 1.0 / (double) STEPS; // dt soma_params[1] = 0.0; // Direct current injection into soma is always zero. soma_params[2] = 0.0; // Dendritic current injected into soma. This is the // value that our simulation will update at each step. printf( "\nIntegration step dt = %f\n", soma_params[0]); // Start the clock. gettimeofday( &start, NULL ); // Initialize the potential of each dendrite compartment to the rest voltage. dendr_volt = (double**) malloc( num_dendrs * sizeof(double*) ); for (i = 0; i < num_dendrs; i++) { dendr_volt[i] = (double*) malloc( num_comps * sizeof(double) ); for (j = 0; j < num_comps; j++) { dendr_volt[i][j] = VREST; } } ////////////////////////////////////////////////////////////////////////////// // Main computation. ////////////////////////////////////////////////////////////////////////////// // Record the initial potential value in our results array. res[0] = y[0]; // Loop over milliseconds. for (t_ms = 1; t_ms < COMPTIME; t_ms++) { // Loop over integration time steps in each millisecond. for (step = 0; step < STEPS; step++) { soma_params[2] = 0.0; // Loop over all the dendrites. for (dendrite = 0; dendrite < num_dendrs; dendrite++) { // This will update Vm in all compartments and will give a new injected // current value from last compartment into the soma. current = dendriteStep( dendr_volt[ dendrite ], step + dendrite + 1, num_comps, soma_params[0], y[0] ); // Accumulate the current generated by the dendrite. soma_params[2] += current; } // Store previous HH model parameters. y0[0] = y[0]; y0[1] = y[1]; y0[2] = y[2]; y0[3] = y[3]; // This is the main HH computation. It updates the potential, Vm, of the // soma, injects current, and calculates action potential. Good stuff. soma(dydt, y, soma_params); rk4Step(y, y0, dydt, NUMVAR, soma_params, 1, soma); } // Record the membrane potential of the soma at this simulation step. // Let's show where we are in terms of computation. printf("\r%02d ms",t_ms); fflush(stdout); res[t_ms] = y[0]; } ////////////////////////////////////////////////////////////////////////////// // Report results of computation. ////////////////////////////////////////////////////////////////////////////// // Stop the clock, compute how long the program was running and report that // time. gettimeofday( &stop, NULL ); timersub( &stop, &start, &diff ); exec_time = (double) (diff.tv_sec) + (double) (diff.tv_usec) * 0.000001; printf("\n\nExecution time: %f seconds.\n", exec_time); // Record the parameters for this simulation as well as data for gnuplot. fprintf( data_file, "# Vm for HH model. " "Simulation time: %d ms, Integration step: %f ms, " "Compartments: %d, Dendrites: %d, Execution time: %f s, " "Slave processes: %d\n", COMPTIME, soma_params[0], num_comps - 2, num_dendrs, exec_time, 0 ); fprintf( data_file, "# X Y\n"); for (t_ms = 0; t_ms < COMPTIME; t_ms++) { fprintf(data_file, "%d %f\n", t_ms, res[t_ms]); } fflush(data_file); // Flush and close the data file so that gnuplot will fclose(data_file); // see it. ////////////////////////////////////////////////////////////////////////////// // Plot results if approriate macro was defined. ////////////////////////////////////////////////////////////////////////////// if (ISDEF_PLOT_PNG || ISDEF_PLOT_SCREEN) { pinfo.sim_time = COMPTIME; pinfo.int_step = soma_params[0]; pinfo.num_comps = num_comps - 2; pinfo.num_dendrs = num_dendrs; pinfo.exec_time = exec_time; pinfo.slaves = 0; } if (ISDEF_PLOT_PNG) { plotData( &pinfo, data_fname, graph_fname ); } if (ISDEF_PLOT_SCREEN) { plotData( &pinfo, data_fname, NULL ); } ////////////////////////////////////////////////////////////////////////////// // Free up allocated memory. ////////////////////////////////////////////////////////////////////////////// for(i = 0; i < num_dendrs; i++) { free(dendr_volt[i]); } free(dendr_volt); return 0; }