diff --git a/src/cell.h b/src/cell.h index e821d0438f96a7dbc20db6da78d00cf48c4c85cc..0ba63d1f037167e49130af64acc05ea1c879b95d 100644 --- a/src/cell.h +++ b/src/cell.h @@ -136,8 +136,8 @@ struct cell { /* Momentum of particles in cell. */ float mom[3], ang[3]; - /* Potential and kinetic energy of particles in this cell. */ - double epot, ekin; + /* Mass, potential, internal and kinetic energy of particles in this cell. */ + double mass, e_pot, e_int, e_kin; /* Number of particles updated in this cell. */ int updated; diff --git a/src/engine.c b/src/engine.c index dc6a9113ecbb74abc8048ffd653df428d160ccd3..4c323958c16abb084614122a99ef591f0473bce3 100644 --- a/src/engine.c +++ b/src/engine.c @@ -1617,7 +1617,7 @@ void engine_collect_kick(struct cell *c) { int updated = 0; float t_end_min = FLT_MAX, t_end_max = 0.0f; - double ekin = 0.0, epot = 0.0; + double e_kin = 0.0, e_int = 0.0, e_pot = 0.0; float mom[3] = {0.0f, 0.0f, 0.0f}, ang[3] = {0.0f, 0.0f, 0.0f}; struct cell *cp; @@ -1641,8 +1641,9 @@ void engine_collect_kick(struct cell *c) { t_end_min = fminf(t_end_min, cp->t_end_min); t_end_max = fmaxf(t_end_max, cp->t_end_max); updated += cp->updated; - ekin += cp->ekin; - epot += cp->epot; + e_kin += cp->e_kin; + e_int += cp->e_int; + e_pot += cp->e_pot; mom[0] += cp->mom[0]; mom[1] += cp->mom[1]; mom[2] += cp->mom[2]; @@ -1656,8 +1657,9 @@ void engine_collect_kick(struct cell *c) { c->t_end_min = t_end_min; c->t_end_max = t_end_max; c->updated = updated; - c->ekin = ekin; - c->epot = epot; + c->e_kin = e_kin; + c->e_int = e_int; + c->e_pot = e_pot; c->mom[0] = mom[0]; c->mom[1] = mom[1]; c->mom[2] = mom[2]; @@ -1752,7 +1754,7 @@ void engine_step(struct engine *e) { int k; int updates = 0; float t_end_min = FLT_MAX, t_end_max = 0.f; - double epot = 0.0, ekin = 0.0; + double e_pot = 0.0, e_int = 0.0, e_kin = 0.0; float mom[3] = {0.0, 0.0, 0.0}; float ang[3] = {0.0, 0.0, 0.0}; struct cell *c; @@ -1764,11 +1766,16 @@ void engine_step(struct engine *e) { for (k = 0; k < s->nr_cells; k++) if (s->cells[k].nodeID == e->nodeID) { c = &s->cells[k]; + + /* Recurse */ engine_collect_kick(c); + + /* And aggregate */ t_end_min = fminf(t_end_min, c->t_end_min); t_end_max = fmaxf(t_end_max, c->t_end_max); - ekin += c->ekin; - epot += c->epot; + e_kin += c->e_kin; + e_int += c->e_int; + e_pot += c->e_pot; updates += c->updated; mom[0] += c->mom[0]; mom[1] += c->mom[1]; @@ -1780,7 +1787,7 @@ void engine_step(struct engine *e) { /* Aggregate the data from the different nodes. */ #ifdef WITH_MPI - double in[3], out[3]; + double in[4], out[4]; out[0] = t_end_min; if (MPI_Allreduce(out, in, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD) != MPI_SUCCESS) @@ -1792,20 +1799,16 @@ void engine_step(struct engine *e) { error("Failed to aggregate t_end_max."); t_end_max = in[0]; out[0] = updates; - out[1] = ekin; - out[2] = epot; + out[1] = e_kin; + out[2] = e_int; + out[3] = e_pot; if (MPI_Allreduce(out, in, 3, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD) != MPI_SUCCESS) error("Failed to aggregate energies."); updates = in[0]; - ekin = in[1]; - epot = in[2]; -/* int nr_parts; -if ( MPI_Allreduce( &s->nr_parts , &nr_parts , 1 , MPI_INT , MPI_SUM , -MPI_COMM_WORLD ) != MPI_SUCCESS ) - error( "Failed to aggregate particle count." ); -if ( e->nodeID == 0 ) - message( "nr_parts=%i." , nr_parts ); */ + e_kin = in[1]; + e_int = in[2]; + e_pot = in[3]; #endif /* Move forward in time */ @@ -1837,11 +1840,18 @@ if ( e->nodeID == 0 ) TIMER_TOC2(timer_step); - /* Print some information to the screen */ if (e->nodeID == 0) { + + /* Print some information to the screen */ printf("%d %f %f %d %.3f\n", e->step, e->time, e->timeStep, updates, ((double)timers[timer_count - 1]) / CPU_TPS * 1000); fflush(stdout); + + /* Write some energy statistics */ + fprintf(e->file_stats, "%d %f %f %f %f %f %f %f %f %f %f\n", e->step, e_kin, + e_int, e_pot, e_kin + e_int + e_pot, mom[0], mom[1], mom[2], ang[0], + ang[1], ang[2]); + fflush(e->file_stats); } } @@ -2131,6 +2141,7 @@ void engine_init(struct engine *e, struct space *s, float dt, int nr_threads, e->timeStep = 0.; e->dt_min = dt_min; e->dt_max = dt_max; + e->file_stats = NULL; engine_rank = nodeID; /* Make the space link back to the engine. */ @@ -2150,6 +2161,14 @@ void engine_init(struct engine *e, struct space *s, float dt, int nr_threads, #endif } + /* Open some files */ + if (e->nodeID == 0) { + e->file_stats = fopen("energy.txt", "w"); + fprintf(e->file_stats, + "# Step E_kin E_int E_pot E_tot " + "p_x p_y p_z ang_x ang_y ang_z\n"); + } + /* Print policy */ engine_print_policy(e); diff --git a/src/engine.h b/src/engine.h index 4cc1d5079867a8e7493692e6610fc21156494e09..eafd6081aba8899559d99ea6fbf0eb6cfb7138a7 100644 --- a/src/engine.h +++ b/src/engine.h @@ -29,6 +29,7 @@ /* Some standard headers. */ #include <pthread.h> +#include <stdio.h> /* Includes. */ #include "lock.h" @@ -109,8 +110,8 @@ struct engine { /* Time step */ float timeStep; - /* The system energies from the previous step. */ - double ekin, epot; + /* File for statistics */ + FILE *file_stats; /* The current step number. */ int step, nullstep; diff --git a/src/hydro/Default/hydro.h b/src/hydro/Default/hydro.h index 412a4e4a96281f8c5bf3713b2482abc67ce10362..97357f42662e886d16e3f990883a061fdf118f1c 100644 --- a/src/hydro/Default/hydro.h +++ b/src/hydro/Default/hydro.h @@ -224,3 +224,14 @@ __attribute__((always_inline)) */ __attribute__((always_inline)) INLINE static void hydro_convert_quantities(struct part* p) {} + +/** + * @brief Returns the internal energy of a particle + * + * @param p The particle of interest + */ +__attribute__((always_inline)) + INLINE static float hydro_get_internal_energy(struct part* p) { + + return p->u; +} diff --git a/src/hydro/Gadget2/hydro.h b/src/hydro/Gadget2/hydro.h index b25879af4ccfa5ee4da890abb5e371e57ce84409..5194bccc6c3534c9ac896cf97e4cf503b6718273 100644 --- a/src/hydro/Gadget2/hydro.h +++ b/src/hydro/Gadget2/hydro.h @@ -238,3 +238,15 @@ __attribute__((always_inline)) p->entropy = (const_hydro_gamma - 1.f) * p->entropy * powf(p->rho, -(const_hydro_gamma - 1.f)); } + +/** + * @brief Returns the internal energy of a particle + * + * @param p The particle of interest + */ +__attribute__((always_inline)) + INLINE static float hydro_get_internal_energy(struct part* p) { + + return p->entropy * powf(p->rho, const_hydro_gamma - 1.f) * + (1.f / (const_hydro_gamma - 1.f)); +} diff --git a/src/hydro/Minimal/hydro.h b/src/hydro/Minimal/hydro.h index b73114b437713d8045492f6db30afa7dbf8f82a8..3585fc3c295be2d449adee5425d61c6024fa7caf 100644 --- a/src/hydro/Minimal/hydro.h +++ b/src/hydro/Minimal/hydro.h @@ -218,3 +218,18 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra( */ __attribute__((always_inline)) INLINE static void hydro_convert_quantities(struct part* p) {} + +/** + * @brief Returns the internal energy of a particle + * + * For implementations where the main thermodynamic variable + * is not internal energy, this function computes the internal + * energy from the thermodynamic variable. + * + * @param p The particle of interest + */ +__attribute__((always_inline)) + INLINE static float hydro_get_internal_energy(struct part* p) { + + return p->u; +} diff --git a/src/runner.c b/src/runner.c index bdf32f66ea4498ff4b94168f368d171c4dc41fc4..157616ad29c954bb7ebfd72acfea96454327e4ee 100644 --- a/src/runner.c +++ b/src/runner.c @@ -807,9 +807,10 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) { int updated = 0; float t_end_min = FLT_MAX, t_end_max = 0.f; - double ekin = 0.0, epot = 0.0; - float mom[3] = {0.0f, 0.0f, 0.0f}, ang[3] = {0.0f, 0.0f, 0.0f}; - float m, x[3], v_full[3]; + double e_kin = 0.0, e_int = 0.0, e_pot = 0.0, mass = 0.0; + float mom[3] = {0.0f, 0.0f, 0.0f}; + float ang[3] = {0.0f, 0.0f, 0.0f}; + float x[3], v_full[3]; struct part *restrict p, *restrict parts = c->parts; struct xpart *restrict xp, *restrict xparts = c->xparts; @@ -825,7 +826,7 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) { p = &parts[k]; xp = &xparts[k]; - m = p->mass; + const float m = p->mass; x[0] = p->x[0]; x[1] = p->x[1]; x[2] = p->x[2]; @@ -908,6 +909,9 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) { v_full[1] = xp->v_full[1]; v_full[2] = xp->v_full[2]; + /* Collect mass */ + mass += m; + /* Collect momentum */ mom[0] += m * v_full[0]; mom[1] += m * v_full[1]; @@ -919,9 +923,10 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) { ang[2] += m * (x[0] * v_full[1] - x[1] * v_full[0]); /* Collect total energy. */ - ekin += 0.5 * m * (v_full[0] * v_full[0] + v_full[1] * v_full[1] + - v_full[2] * v_full[2]); - epot += 0.f; // MATTHIEU + e_kin += 0.5 * m * (v_full[0] * v_full[0] + v_full[1] * v_full[1] + + v_full[2] * v_full[2]); + e_pot += 0.f; /* No gravitational potential thus far */ + e_int += hydro_get_internal_energy(p); /* Minimal time for next end of time-step */ t_end_min = fminf(p->t_end, t_end_min); @@ -940,11 +945,16 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) { for (int k = 0; k < 8; k++) if (c->progeny[k] != NULL) { struct cell *cp = c->progeny[k]; + + /* Recurse */ runner_dokick(r, cp, 0); + /* And aggregate */ updated += cp->updated; - ekin += cp->ekin; - epot += cp->epot; + e_kin += cp->e_kin; + e_int += cp->e_int; + e_pot += cp->e_pot; + mass += cp->mass; mom[0] += cp->mom[0]; mom[1] += cp->mom[1]; mom[2] += cp->mom[2]; @@ -958,8 +968,10 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) { /* Store the values. */ c->updated = updated; - c->ekin = ekin; - c->epot = epot; + c->e_kin = e_kin; + c->e_int = e_int; + c->e_pot = e_pot; + c->mass = mass; c->mom[0] = mom[0]; c->mom[1] = mom[1]; c->mom[2] = mom[2];