double ic_energy(double x, double y, scalar& dx, scalar& dy) { return calc_energy(RHO_EXT, RHO_EXT*V1_EXT, RHO_EXT*V2_EXT, P_EXT); }
int main(int argc, char* argv[]) { /*! * \page Vector_5_md_vl_sym_crs Vector 5 molecular dynamic with symmetric Verlet list crossing scheme * * ## Simulation ## {#md_e5_sym_sim_crs} * * The simulation is equal to the simulation explained in the example molecular dynamic * * \see \ref md_e5_sym * * The difference is that we create a symmetric Verlet-list for crossing scheme instead of a normal one * \snippet Vector/5_molecular_dynamic_sym_crs/main.cpp sim verlet * * The rest of the code remain unchanged * * \snippet Vector/5_molecular_dynamic_sym_crs/main.cpp simulation * */ //! \cond [simulation] \endcond double dt = 0.00025; double sigma = 0.1; double r_cut = 3.0*sigma; double r_gskin = 1.3*r_cut; double sigma12 = pow(sigma,12); double sigma6 = pow(sigma,6); openfpm::vector<double> x; openfpm::vector<openfpm::vector<double>> y; openfpm_init(&argc,&argv); Vcluster & v_cl = create_vcluster(); // we will use it do place particles on a 10x10x10 Grid like size_t sz[3] = {10,10,10}; // domain Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0}); // Boundary conditions size_t bc[3]={PERIODIC,PERIODIC,PERIODIC}; // ghost, big enough to contain the interaction radius Ghost<3,float> ghost(r_gskin); ghost.setLow(0,0.0); ghost.setLow(1,0.0); ghost.setLow(2,0.0); vector_dist<3,double, aggregate<double[3],double[3]> > vd(0,box,bc,ghost,BIND_DEC_TO_GHOST); size_t k = 0; size_t start = vd.accum(); auto it = vd.getGridIterator(sz); while (it.isNext()) { vd.add(); auto key = it.get(); vd.getLastPos()[0] = key.get(0) * it.getSpacing(0); vd.getLastPos()[1] = key.get(1) * it.getSpacing(1); vd.getLastPos()[2] = key.get(2) * it.getSpacing(2); vd.template getLastProp<velocity>()[0] = 0.0; vd.template getLastProp<velocity>()[1] = 0.0; vd.template getLastProp<velocity>()[2] = 0.0; vd.template getLastProp<force>()[0] = 0.0; vd.template getLastProp<force>()[1] = 0.0; vd.template getLastProp<force>()[2] = 0.0; k++; ++it; } vd.map(); vd.ghost_get<>(); timer tsim; tsim.start(); //! \cond [sim verlet] \endcond // Get the Cell list structure auto NN = vd.getVerletCrs(r_gskin);; //! \cond [sim verlet] \endcond // calculate forces calc_forces(vd,NN,sigma12,sigma6,r_cut); unsigned long int f = 0; int cnt = 0; double max_disp = 0.0; // MD time stepping for (size_t i = 0; i < 10000 ; i++) { // Get the iterator auto it3 = vd.getDomainIterator(); double max_displ = 0.0; // integrate velicity and space based on the calculated forces (Step1) while (it3.isNext()) { auto p = it3.get(); // here we calculate v(tn + 0.5) vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0]; vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1]; vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2]; Point<3,double> disp({vd.template getProp<velocity>(p)[0]*dt,vd.template getProp<velocity>(p)[1]*dt,vd.template getProp<velocity>(p)[2]*dt}); // here we calculate x(tn + 1) vd.getPos(p)[0] += disp.get(0); vd.getPos(p)[1] += disp.get(1); vd.getPos(p)[2] += disp.get(2); if (disp.norm() > max_displ) max_displ = disp.norm(); ++it3; } if (max_disp < max_displ) max_disp = max_displ; // Because we moved the particles in space we have to map them and re-sync the ghost if (cnt % 10 == 0) { vd.map(); vd.template ghost_get<>(); // Get the Cell list structure vd.updateVerlet(NN,r_gskin,VL_CRS_SYMMETRIC); } else { vd.template ghost_get<>(SKIP_LABELLING); } cnt++; // calculate forces or a(tn + 1) Step 2 calc_forces(vd,NN,sigma12,sigma6,r_cut); // Integrate the velocity Step 3 auto it4 = vd.getDomainIterator(); while (it4.isNext()) { auto p = it4.get(); // here we calculate v(tn + 1) vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0]; vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1]; vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2]; ++it4; } // After every iteration collect some statistic about the confoguration if (i % 100 == 0) { // We write the particle position for visualization (Without ghost) vd.deleteGhost(); vd.write("particles_",f); // we resync the ghost vd.ghost_get<>(); // We calculate the energy double energy = calc_energy(vd,NN,sigma12,sigma6,r_cut); auto & vcl = create_vcluster(); vcl.sum(energy); vcl.max(max_disp); vcl.execute(); // we save the energy calculated at time step i c contain the time-step y contain the energy x.add(i); y.add({energy}); // We also print on terminal the value of the energy // only one processor (master) write on terminal if (vcl.getProcessUnitID() == 0) std::cout << "Energy: " << energy << " " << max_disp << " " << std::endl; max_disp = 0.0; f++; } } tsim.stop(); std::cout << "Time: " << tsim.getwct() << std::endl; //! \cond [simulation] \endcond // Google charts options, it store the options to draw the X Y graph GCoptions options; // Title of the graph options.title = std::string("Energy with time"); // Y axis name options.yAxis = std::string("Energy"); // X axis name options.xAxis = std::string("iteration"); // width of the line options.lineWidth = 1.0; // Object that draw the X Y graph GoogleChart cg; // Add the graph // The graph that it produce is in svg format that can be opened on browser cg.AddLinesGraph(x,y,options); // Write into html format cg.write("gc_plot2_out.html"); //! \cond [google chart] \endcond /*! * \page Vector_5_md_vl_sym_crs Vector 5 molecular dynamic with symmetric Verlet list crossing scheme * * ## Finalize ## {#finalize_v_e5_md_sym_crs} * * At the very end of the program we have always to de-initialize the library * * \snippet Vector/5_molecular_dynamic_sym_crs/main.cpp finalize * */ //! \cond [finalize] \endcond openfpm_finalize(); //! \cond [finalize] \endcond /*! * \page Vector_5_md_vl_sym_crs Vector 5 molecular dynamic with symmetric Verlet list crossing scheme * * ## Full code ## {#full_code_v_e5_md_sym_crs} * * \include Vector/5_molecular_dynamic_sym_crs/main.cpp * */ }
// Equation parameters. const double P_EXT = 2.5; // Exterior pressure (dimensionless). const double RHO_EXT = 1.0; // Inlet density (dimensionless). const double V1_EXT = 1.25; // Inlet x-velocity (dimensionless). const double V2_EXT = 0.0; // Inlet y-velocity (dimensionless). const double KAPPA = 1.4; // Kappa. // Numerical flux. // For numerical fluxes, please see hermes2d/src/numerical_flux.h NumericalFlux num_flux(KAPPA); // Utility functions for the Euler equations. #include "../euler-util.cpp" // Calculated exterior energy. double ENERGY_EXT = calc_energy(RHO_EXT, RHO_EXT*V1_EXT, RHO_EXT*V2_EXT, P_EXT); // Diffusion parameter (diffusivity). const double EPSILON = 0.01; // Boundary (initial) value of the concentration. const double CONCENTRATION_EXT = 1.0; // Boundary markers. const int BDY_INLET = 1; const int BDY_OUTLET = 2; const int BDY_SOLID_WALL_BOTTOM = 3; const int BDY_SOLID_WALL_TOP = 4; // Constant initial state (matching the supersonic inlet state). double ic_density(double x, double y, scalar& dx, scalar& dy)
void FoldingEngine<SEQ>:: stochastic_fold(const std::string& name, const SEQ& seq, uint num_samples, const std::vector<float>& gamma, uint max_clusters, std::ostream& out, const std::string& p_outname, float th) { std::vector<BPvecPtr> bpv; stochastic_fold(seq, num_samples, bpv); if (max_clusters>=2) { // calculate the distance matrix typedef boost::multi_array<double, 2> DMatrix; DMatrix dmatrix(boost::extents[bpv.size()][bpv.size()]); for (uint i=0; i!=bpv.size(); ++i) for (uint j=i; j!=bpv.size(); ++j) dmatrix[i][j]=dmatrix[j][i]=hamming_distance(*bpv[i], *bpv[j]); // hierarchical clustering by DIANA HCLUST::Diana<DMatrix> diana(dmatrix); diana.build(max_clusters); uint opt_n = diana.optimal_size(); std::vector<uint> res; std::vector<uint> num; diana.get_clusters(opt_n, res, num); // sort by size of clusters std::vector<uint> s(num.size(), 0); std::vector<uint> idx(num.size()); for (uint i=0; i!=num.size(); ++i) { idx[i]=i; if (i!=0) s[i]=s[i-1]+num[i-1]; } std::sort(idx.begin(), idx.end(), cmp_by_size(num)); // centroid estimation for each cluster for (uint i=0; i!=idx.size(); ++i) { std::vector<BPvecPtr> v(num[idx[i]]); for (uint j=0; j!=v.size(); ++j) v[j] = bpv[res[s[idx[i]]+j]]; CountBP< std::vector<BPvecPtr> > count_bp(v, seq.size()); inside_traverse(0, seq.size()-1, count_bp); char buf[100]; sprintf(buf, "%3.1f%%", static_cast<float>(num[idx[i]])/bpv.size()*100); out << ">" << name << " (" << i+1 << " of " << num.size() << ", size=" << buf << ")" << std::endl << get_seq(seq) << std::endl; std::vector<float>::const_iterator g; for (g=gamma.begin(); g!=gamma.end(); ++g) { std::string paren(seq.size(), '.'); Centroid::execute(count_bp.table, paren, *g); out << paren << " (g=" << *g << ",th=" << (1.0/(1.0+*g)); #ifdef HAVE_LIBRNA out << ",e=" << calc_energy(seq, paren); #endif out << ")" << std::endl; } if (!p_outname.empty()) { char buf[1024]; snprintf(buf, sizeof(buf), "%s-%d", p_outname.c_str(), i); count_bp.table.save(buf, get_seq(seq), th); } } } else { CountBP< std::vector<BPvecPtr> > count_bp(bpv, seq.size()); inside_traverse(0, seq.size()-1, count_bp); std::string paren(seq.size(), '.'); std::vector<float>::const_iterator g; out << ">" << name << std::endl << get_seq(seq) << std::endl; for (g=gamma.begin(); g!=gamma.end(); ++g) { std::fill(paren.begin(), paren.end(), '.'); Centroid::execute(count_bp.table, paren, *g); out << paren << " (g=" << *g << ",th=" << (1.0/(1.0+*g)); #ifdef HAVE_LIBRNA out << ",e=" << calc_energy(seq, paren); #endif out << ")" << std::endl; } if (!p_outname.empty()) { char buf[1024]; snprintf(buf, sizeof(buf), "%s-1", p_outname.c_str()); count_bp.table.save(buf, get_seq(seq), th); } } }
static int av_is_beat(struct bd_instance_t* sh_, double* samples, int len, double thr_) { struct bd_avinstance_t* sh = (struct bd_avinstance_t*) sh_; int i; int raw_max = min(sh->raw_size - sh->raw_len, len); int block_size = sh->block_size; int num_blocks; double* buf = sh->hist_buf; int diff; double energy = 0; double var = 0; double local_energy; double thr; // printf("len = %i\n", len); // printf("raw_len = %i\n", sh->raw_len); // printf("raw_max = %i\n", raw_max); memcpy(sh->raw_buf + sh->raw_len, samples, raw_max*sizeof(double)); sh->raw_len += raw_max; num_blocks = min(sh->hist_buf_size, sh->raw_len / block_size); diff = max(0, (sh->buf_len + num_blocks) - sh->hist_buf_size); diff = min(diff, sh->buf_len); memmove(buf, buf+diff, (sh->buf_len-diff) * sizeof(double)); sh->buf_len -= diff; for (i = 0; i < num_blocks; ++i) { double e = calc_energy(sh->raw_buf + i*block_size, sh->raw_buf + (i+1)*block_size) / block_size; buf[sh->buf_len + i] = e; } sh->raw_len -= num_blocks*block_size; sh->buf_len += num_blocks; memmove(sh->raw_buf, sh->raw_buf+num_blocks*block_size, sh->raw_len * sizeof(double)); // printf("num_blocks: %i\n", num_blocks); // printf("buffer length: %i\n", sh->buf_len); if (sh->buf_len < 0.5*sh->hist_buf_size) return 0; for (i = 0; i < sh->buf_len; ++i) { energy += buf[i]; } energy /= ((double) sh->buf_len); local_energy = buf[sh->buf_len - 1]; for (i = 0; i < sh->buf_len; ++i) { double v = (buf[i] - energy); var += v*v; } var /= ((double) sh->buf_len); thr = thr_ + 1.5 - 20*var; if (thr < 1) thr = 1; /*printf("var = %f\n", var); printf("thr = %f\n", thr); printf("ding = %f\n", local_energy / energy);*/ if (local_energy / energy > thr) return 1; else return 0; }
int main(int argc, char* argv[]) { /*! * * \page Vector_4_comp_reo Vector 4 computational reordering and cache friendliness * * ## Initialization ## * * The initialization is the same as the molecular dynamic example. The differences are in the * parameters. We will use a bigger system, with more particles. The delta time for integration * is chosen in order to keep the system stable. * * \see \ref e3_md_init * * \snippet Vector/4_reorder/main_comp_ord.cpp vect create * */ //! \cond [vect create] \endcond double dt = 0.0001; float r_cut = 0.03; double sigma = r_cut/3.0; double sigma12 = pow(sigma,12); double sigma6 = pow(sigma,6); openfpm::vector<double> x; openfpm::vector<openfpm::vector<double>> y; openfpm_init(&argc,&argv); Vcluster & v_cl = create_vcluster(); // we will use it do place particles on a 40x40x40 Grid like size_t sz[3] = {40,40,40}; // domain Box<3,float> box({0.0,0.0,0.0}, {1.0,1.0,1.0}); // Boundary conditions size_t bc[3]= {PERIODIC,PERIODIC,PERIODIC}; // ghost, big enough to contain the interaction radius Ghost<3,float> ghost(r_cut); vector_dist<3,double, aggregate<double[3],double[3]> > vd(0,box,bc,ghost); //! \cond [vect create] \endcond /*! * \page Vector_4_comp_reo Vector 4 computational reordering and cache friendliness * * ## Particles on a grid like position ## * * Here we place the particles on a grid like manner * * \see \ref e3_md_gl * * \snippet Vector/4_reorder/main_comp_ord.cpp vect grid * */ //! \cond [vect grid] \endcond auto it = vd.getGridIterator(sz); while (it.isNext()) { vd.add(); auto key = it.get(); vd.getLastPos()[0] = key.get(0) * it.getSpacing(0); vd.getLastPos()[1] = key.get(1) * it.getSpacing(1); vd.getLastPos()[2] = key.get(2) * it.getSpacing(2); vd.template getLastProp<velocity>()[0] = 0.0; vd.template getLastProp<velocity>()[1] = 0.0; vd.template getLastProp<velocity>()[2] = 0.0; vd.template getLastProp<force>()[0] = 0.0; vd.template getLastProp<force>()[1] = 0.0; vd.template getLastProp<force>()[2] = 0.0; ++it; } //! \cond [vect grid] \endcond /*! * * \page Vector_4_comp_reo Vector 4 computational reordering and cache friendliness * * ## Molecular dynamic steps ## * * Here we do 30000 MD steps using verlet integrator the cycle is the same as the * molecular dynamic example. with the following changes. * * ### Cell lists ### * * Instead of getting the normal cell list we get an hilbert curve cell-list. Such cell list has a * function called **getIterator** used inside the function **calc_forces** and **calc_energy** * that iterate across all the particles but in a smart-way. In practice * given an r-cut a cell-list is constructed with the provided spacing. Suppose to have a cell-list * \f$ m \times n \f$, an hilbert curve \f$ 2^k \times 2^k \f$ is contructed with \f$ k = ceil(log_2(max(m,n))) \f$. * Cell-lists are explored according to this Hilbert curve, If a cell does not exist is simply skipped. * * * \verbatim +------+------+------+------+ Example of Hilbert curve running on a 3 x 3 Cell | | | | | An hilbert curve of k = ceil(log_2(3)) = 4 | X+---->X | X +---> X | | ^ | + | ^ | + | ***|******|******|****---|--+ ******* * + | v | + * v | * * * 7 | 8+---->9 * X | * * = Domain * ^ | | * + | * * *--|-----------------*---|--+ ******* * + | | * v | * 4<----+5 | 6<---+ X | * | ^ | + * | *---------|-------|--*------+ * | + | v * | * 1+---->2 | 3+---> X | * | | * | **********************------+ this mean that we will iterate the following cells 1,2,5,4,7,8,9,6,3 Suppose now that the particles are ordered like described Particles id Cell 0 1 1 7 2 8 3 1 4 9 5 9 6 6 7 7 8 3 9 2 10 4 11 3 The iterator of the cell-list will explore the particles in the following way Cell 1 2 5 4 7 8 9 6 3 | | | | | | | | | | 0,3,9,,10,1,7,2,4,5,6,8 * \endverbatim * * We cannot explain here what is a cache, but in practice is a fast memory in the CPU able * to store chunks of memory. The cache in general is much smaller than RAM, but the big advantage * is its speed. Retrieve data from the cache is much faster than RAM. Unfortunately the factors * that determine what is on cache and what is not are multiples: Type of cache, algorithm ... . * Qualitatively all caches will tend to load chunks of data that you read multiple-time, or chunks * of data that probably you will read based on pattern analysis. A small example is a linear memory copy where * you read consecutively memory and you write on consecutive memory. * Modern CPU recognize such pattern and decide to load on cache the consecutive memory before * you actually require it. * * * Iterating the vector in the way described above has the advantage that when we do computation on particles * and its neighborhood with the sequence described above it will happen that: * * * If to process a particle A we read some neighborhood particles to process the next particle A+1 * we will probably read most of the previous particles. * * * In order to show in practice what happen we first show the graph when we do not reorder * * \htmlinclude Vector/4_reorder/no_reorder.html * * The measure has oscillation but we see an asymptotic behavior from 0.04 in the initial condition to * 0.124 . Below we show what happen when we use iterator from the Cell list hilbert * * \htmlinclude Vector/4_reorder/comp_reord.html * * In cases where particles does not move or move very slowly consider to use data-reordering, because it can * give **8-10% speedup** * * \see \ref e4_reo * * ## Timers ## * * In order to collect the time of the force calculation we insert two timers around the function * calc_force. The overall performance is instead calculated with another timer around the time stepping * * \snippet Vector/4_reorder/main_data_ord.cpp timer start * \snippet Vector/4_reorder/main_data_ord.cpp timer stop * * \see \ref e3_md_vi * * */ //! \cond [md steps] \endcond // Get the Cell list structure auto NN = vd.getCellList_hilb(r_cut); // calculate forces calc_forces(vd,NN,sigma12,sigma6); unsigned long int f = 0; timer time2; time2.start(); #ifndef TEST_RUN size_t Nstep = 30000; #else size_t Nstep = 300; #endif // MD time stepping for (size_t i = 0; i < Nstep ; i++) { // Get the iterator auto it3 = vd.getDomainIterator(); // integrate velicity and space based on the calculated forces (Step1) while (it3.isNext()) { auto p = it3.get(); // here we calculate v(tn + 0.5) vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0]; vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1]; vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2]; // here we calculate x(tn + 1) vd.getPos(p)[0] += vd.template getProp<velocity>(p)[0]*dt; vd.getPos(p)[1] += vd.template getProp<velocity>(p)[1]*dt; vd.getPos(p)[2] += vd.template getProp<velocity>(p)[2]*dt; ++it3; } // Because we mooved the particles in space we have to map them and re-sync the ghost vd.map(); vd.template ghost_get<>(); timer time; if (i % 10 == 0) time.start(); // calculate forces or a(tn + 1) Step 2 calc_forces(vd,NN,sigma12,sigma6); if (i % 10 == 0) { time.stop(); x.add(i); y.add({time.getwct()}); } // Integrate the velocity Step 3 auto it4 = vd.getDomainIterator(); while (it4.isNext()) { auto p = it4.get(); // here we calculate v(tn + 1) vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0]; vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1]; vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2]; ++it4; } // After every iteration collect some statistic about the confoguration if (i % 100 == 0) { // We write the particle position for visualization (Without ghost) vd.deleteGhost(); vd.write("particles_",f); // we resync the ghost vd.ghost_get<>(); // We calculate the energy double energy = calc_energy(vd,NN,sigma12,sigma6); auto & vcl = create_vcluster(); vcl.sum(energy); vcl.execute(); // We also print on terminal the value of the energy // only one processor (master) write on terminal if (vcl.getProcessUnitID() == 0) std::cout << std::endl << "Energy: " << energy << std::endl; f++; } } time2.stop(); std::cout << "Performance: " << time2.getwct() << std::endl; //! \cond [md steps] \endcond /*! * \page Vector_4_comp_reo Vector 4 computational reordering and cache friendliness * * ## Plotting graphs ## * * After we terminate the MD steps our vector x contains at which iteration we benchmark the force * calculation time, while y contains the measured time at that time-step. We can produce a graph X Y * * \note The graph produced is an svg graph that can be view with a browser. From the browser we can * also easily save the graph into pure svg format * * \snippet Vector/4_reorder/main_comp_ord.cpp google chart * */ //! \cond [google chart] \endcond // Google charts options, it store the options to draw the X Y graph GCoptions options; // Title of the graph options.title = std::string("Force calculation time"); // Y axis name options.yAxis = std::string("Time"); // X axis name options.xAxis = std::string("iteration"); // width of the line options.lineWidth = 1.0; // Object that draw the X Y graph GoogleChart cg; // Add the graph // The graph that it produce is in svg format that can be opened on browser cg.AddLinesGraph(x,y,options); // Write into html format cg.write("gc_plot2_out.html"); //! \cond [google chart] \endcond /*! * * \page Vector_4_comp_reo Vector 4 computational reordering and cache friendliness * * ## Finalize ## * * At the very end of the program we have always to de-initialize the library * * \snippet Vector/4_reorder/main_comp_ord.cpp finalize * */ //! \cond [finalize] \endcond openfpm_finalize(); //! \cond [finalize] \endcond /*! * * \page Vector_4_comp_reo Vector 4 computational reordering and cache friendliness * * # Full code # * * \include Vector/4_reorder/main_comp_ord.cpp * */ }
int main(int argc, char **argv) { int i, j; int atoms; float **atom_positions; float *energies; float maxenergy; /* * Initialisierung der Atome */ /* Vereinfachung: normalerweise von Benutzer z.B. durch Eingabedatei übergebbar */ atoms = 10; /* * Allokierung des nötigen Speichers */ /* Allokierung des 2-Dimensionalen atom_positions Arrays */ /* Allokierung einer Liste von float Pointern (erste Dimension) */ atom_positions = malloc(atoms * sizeof(float *)); if (atom_positions == NULL) { fprintf(stderr, "out of memory\n"); return -1; } /* Allokierung der 3 Spalten für die Positionsangaben (zweite Dimension) */ for (i = 0; i < atoms; i++) { atom_positions[i] = malloc(3 * sizeof(float)); if (atom_positions[i] == NULL) { fprintf(stderr, "out of memory\n"); return -1; } } /* Allokierung und Initialisierung der Energie-Liste */ energies = malloc(atoms * sizeof(float)); if (energies == NULL) { fprintf(stderr, "out of memory\n"); return -1; } for (i = 0; i < atoms; i++) { energies[i] = 0.0f; } /* Einlesen der Atompositionen */ /* Vereinfachung: normalerweise von Benutzer z.B. durch Eingabedatei übergebbar */ for (i = 0; i < atoms; i++) { for (j = 0; j < 3; j++) { atom_positions[i][j] = (i + 1) * (j + 1); } } /* * Berechnung */ /* Bewege jedes Atom in eine der 3 Raumrichtungen und berechne die Energie */ for (i = 0; i < atoms; i++) { /* Verschiebe Atom und bestimme jeweils die Energie * Speicher die maximale Energie */ /* init maxenergy */ maxenergy = 0; for (j = 0; j < 3; j++) { /* verschieben */ atom_positions[i][j] += 1 * i; /* Energie berechnen */ maxenergy = calc_energy(atoms, atom_positions); if (energies[i] < maxenergy) { energies[i] = maxenergy; } /* zurücksetzen */ atom_positions[i][j] -= 1 * i; } printf("Energie für Atom %d: %f \n", i + 1, energies[i]); } maxenergy = 0; for (i = 0; i < atoms; i++) { if (energies[i] > maxenergy) { maxenergy = energies[i]; } } printf("Maximalenergie: %f \n", maxenergy); /* Allokationen freigeben */ free(energies); for (i = 0; i < atoms; i++) { free(atom_positions[i]); } free(atom_positions); return 0; }