/******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk) * Matthieu Schaller (schaller@strw.leidenuniv.nl) * 2015 Peter W. Draper (p.w.draper@durham.ac.uk) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * ******************************************************************************/ /* Config parameters. */ #include /* This object's header. */ #include "engine.h" /* Local headers. */ #include "fof.h" /** * @brief Activate all the #gpart communications in preparation * fof a call to FOF. * * @param e The #engine to act on. */ void engine_activate_gpart_comms(struct engine *e) { #ifdef WITH_MPI const ticks tic = getticks(); struct scheduler *s = &e->sched; const int nr_tasks = s->nr_tasks; struct task *tasks = s->tasks; for (int k = 0; k < nr_tasks; ++k) { struct task *t = &tasks[k]; if ((t->type == task_type_send) && (t->subtype == task_subtype_gpart)) { scheduler_activate(s, t); } else if ((t->type == task_type_recv) && (t->subtype == task_subtype_gpart)) { scheduler_activate(s, t); } else { t->skip = 1; } } if (e->verbose) message("took %.3f %s.", clocks_from_ticks(getticks() - tic), clocks_getunit()); #else error("Calling an MPI function in non-MPI mode."); #endif } /** * @brief Activate all the FOF linking tasks. * * Marks all the other task types to be skipped. * * @param e The #engine to act on. */ void engine_activate_fof_tasks(struct engine *e) { const ticks tic = getticks(); struct scheduler *s = &e->sched; const int nr_tasks = s->nr_tasks; struct task *tasks = s->tasks; for (int k = 0; k < nr_tasks; k++) { struct task *t = &tasks[k]; if (t->type == task_type_fof_self || t->type == task_type_fof_pair) scheduler_activate(s, t); else t->skip = 1; } if (e->verbose) message("took %.3f %s.", clocks_from_ticks(getticks() - tic), clocks_getunit()); } /** * @brief Activate all the FOF attaching tasks. * * Marks all the other task types to be skipped. * * @param e The #engine to act on. */ void engine_activate_fof_attach_tasks(struct engine *e) { const ticks tic = getticks(); struct scheduler *s = &e->sched; const int nr_tasks = s->nr_tasks; struct task *tasks = s->tasks; for (int k = 0; k < nr_tasks; k++) { struct task *t = &tasks[k]; if (t->type == task_type_fof_attach_self || t->type == task_type_fof_attach_pair) scheduler_activate(s, t); else t->skip = 1; } if (e->verbose) message("took %.3f %s.", clocks_from_ticks(getticks() - tic), clocks_getunit()); } /** * @brief Run a FOF search. * * @param e the engine * @param dump_results Are we writing group catalogues to output files? * @param dump_debug_results Are we writing a txt-file debug catalogue * (including BH seed info)? * @param seed_black_holes Are we seeding black holes? * @param foreign_buffers_allocated Are the foreign buffers currently * allocated? */ void engine_fof(struct engine *e, const int dump_results, const int dump_debug_results, const int seed_black_holes, const int foreign_buffers_allocated) { #ifdef WITH_FOF const ticks tic = getticks(); /* Start by cleaning up the foreign buffers */ if (foreign_buffers_allocated) { #ifdef WITH_MPI space_free_foreign_parts(e->s, /*clear pointers=*/1); #endif } /* Initialise FOF parameters and allocate FOF arrays. */ fof_allocate(e->s, e->fof_properties); /* Make FOF tasks */ engine_make_fof_tasks(e); /* and activate them. */ engine_activate_fof_tasks(e); /* Print the number of active tasks ? */ if (e->verbose) engine_print_task_counts(e); /* Perform local FOF tasks for linkable particles. */ engine_launch(e, "fof"); /* Compute group sizes (only of local fragments with MPI) */ fof_compute_local_sizes(e->fof_properties, e->s); #ifdef WITH_MPI /* Allocate buffers to receive the gpart fof information */ engine_allocate_foreign_particles(e, /*fof=*/1); /* Compute the local<->foreign group links (nothing to do without MPI)*/ fof_search_foreign_cells(e->fof_properties, e->s); #endif /* Compute the attachable->linkable links */ fof_link_attachable_particles(e->fof_properties, e->s); #ifdef WITH_MPI /* Free the foreign particles */ space_free_foreign_parts(e->s, /*clear pointers=*/1); /* Make a list of purely local groups to speed up the attaching */ fof_build_list_of_purely_local_groups(e->fof_properties, e->s); #endif /* Finish the operations attaching the attachables to their groups */ fof_finalise_attachables(e->fof_properties, e->s); #ifdef WITH_MPI /* Link the foreign fragments and finalise global group list (nothing to do * without MPI) */ fof_link_foreign_fragments(e->fof_properties, e->s); #endif /* Compute group properties and act on the results * (seed BHs, dump catalogues..) */ fof_compute_group_props(e->fof_properties, e->black_holes_properties, e->physical_constants, e->cosmology, e->s, dump_results, dump_debug_results, seed_black_holes); /* Reset flag. */ e->run_fof = 0; /* Flag that a FOF has taken place */ e->step_props |= engine_step_prop_fof; /* ... and find the next FOF time */ if (seed_black_holes) engine_compute_next_fof_time(e); /* Restore the foreign buffers as they were*/ if (foreign_buffers_allocated) { #ifdef WITH_MPI engine_allocate_foreign_particles(e, /*fof=*/0); #endif } if (engine_rank == 0) message("Complete FOF search took: %.3f %s.", clocks_from_ticks(getticks() - tic), clocks_getunit()); #else error("SWIFT was not compiled with FOF enabled!"); #endif }