From e7fdcaf093dfe80fd8ba5da2b942298dbba42ad6 Mon Sep 17 00:00:00 2001 From: Daniel Bergman Date: Mon, 17 Feb 2025 22:04:36 -0500 Subject: [PATCH 1/2] refactor how intracellular updates are handled - first do all pre updates, then all updates, then all post updates - this ensures that any changes manifested in updates/post-updates are not immediately visible to the pre-updates of other cells - with the more verbose logic controlling intracellular updates, make a separate function to handle it - in that function, encode directly dependence on `diffusion_dt` rather than the argument `diffusion_dt_` - `initialzed` used to determine when to call `intracellular` rather than passed in - if after first looping over all cells, none were found to require intracellular updates, then return early --- core/PhysiCell_cell_container.cpp | 62 ++++++++++++++++++++++--------- core/PhysiCell_cell_container.h | 4 +- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/core/PhysiCell_cell_container.cpp b/core/PhysiCell_cell_container.cpp index 0c5850b1d..2bce73287 100644 --- a/core/PhysiCell_cell_container.cpp +++ b/core/PhysiCell_cell_container.cpp @@ -140,24 +140,8 @@ void Cell_Container::update_all_cells(double t, double phenotype_dt_ , double me static double mechanics_dt_tolerance = 0.001 * mechanics_dt_; // intracellular update. called for every diffusion_dt, but actually depends on the intracellular_dt of each cell (as it can be noisy) - - #pragma omp parallel for - for( int i=0; i < (*all_cells).size(); i++ ) - { - if( (*all_cells)[i]->is_out_of_domain == false && initialzed ) { - - if( (*all_cells)[i]->phenotype.intracellular != NULL && (*all_cells)[i]->phenotype.intracellular->need_update()) - { - if ((*all_cells)[i]->functions.pre_update_intracellular != NULL) - (*all_cells)[i]->functions.pre_update_intracellular( (*all_cells)[i], (*all_cells)[i]->phenotype , diffusion_dt_ ); - - (*all_cells)[i]->phenotype.intracellular->update( (*all_cells)[i], (*all_cells)[i]->phenotype , diffusion_dt_ ); - - if ((*all_cells)[i]->functions.post_update_intracellular != NULL) - (*all_cells)[i]->functions.post_update_intracellular( (*all_cells)[i], (*all_cells)[i]->phenotype , diffusion_dt_ ); - } - } - } + if (initialzed) + { update_all_cells_intracellular(); } if( time_since_last_cycle > phenotype_dt_ - 0.5 * diffusion_dt_ || !initialzed ) { @@ -318,6 +302,48 @@ void Cell_Container::update_all_cells(double t, double phenotype_dt_ , double me return; } +void Cell_Container::update_all_cells_intracellular( void ) +{ + bool anything_to_update = false; + std::vector ready_to_update_intracellular = std::vector( (*all_cells).size(), false ); + #pragma omp parallel for + for( int i=0; i < (*all_cells).size(); i++ ) + { + if( (*all_cells)[i]->is_out_of_domain == false ) { + if( (*all_cells)[i]->phenotype.intracellular != NULL && (*all_cells)[i]->phenotype.intracellular->need_update()) + { + ready_to_update_intracellular[i] = true; + anything_to_update = true; + if ((*all_cells)[i]->functions.pre_update_intracellular != NULL) + { + (*all_cells)[i]->functions.pre_update_intracellular((*all_cells)[i], (*all_cells)[i]->phenotype, diffusion_dt); + } + } + } + } + + if (!anything_to_update) + { return; } + + #pragma omp parallel for + for ( int i=0; i < (*all_cells).size(); i++ ) + { + if (ready_to_update_intracellular[i]) + { + (*all_cells)[i]->phenotype.intracellular->update((*all_cells)[i], (*all_cells)[i]->phenotype, diffusion_dt); + } + } + + #pragma omp parallel for + for ( int i=0; i < (*all_cells).size(); i++ ) + { + if (ready_to_update_intracellular[i] && (*all_cells)[i]->functions.post_update_intracellular != NULL) + { + (*all_cells)[i]->functions.post_update_intracellular((*all_cells)[i], (*all_cells)[i]->phenotype, diffusion_dt); + } + } +} + void Cell_Container::register_agent( Cell* agent ) { agent_grid[agent->get_current_mechanics_voxel_index()].push_back(agent); diff --git a/core/PhysiCell_cell_container.h b/core/PhysiCell_cell_container.h index f0b2cb9ee..5d1ff34ce 100644 --- a/core/PhysiCell_cell_container.h +++ b/core/PhysiCell_cell_container.h @@ -104,7 +104,9 @@ class Cell_Container : public BioFVM::Agent_Container void update_all_cells(double t); void update_all_cells(double t, double dt); void update_all_cells(double t, double phenotype_dt, double mechanics_dt); - void update_all_cells(double t, double phenotype_dt, double mechanics_dt, double diffusion_dt ); + void update_all_cells(double t, double phenotype_dt, double mechanics_dt, double diffusion_dt ); + + void update_all_cells_intracellular( void ); void register_agent( Cell* agent ); void add_agent_to_outer_voxel(Cell* agent); From 7af2a17343e1597a87d538dfe10ca2b7156b242a Mon Sep 17 00:00:00 2001 From: Daniel Bergman Date: Fri, 4 Apr 2025 11:36:34 -0400 Subject: [PATCH 2/2] reduction to safely set bool in OpenMP loop --- core/PhysiCell_cell_container.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/PhysiCell_cell_container.cpp b/core/PhysiCell_cell_container.cpp index 2bce73287..d36e57047 100644 --- a/core/PhysiCell_cell_container.cpp +++ b/core/PhysiCell_cell_container.cpp @@ -304,16 +304,17 @@ void Cell_Container::update_all_cells(double t, double phenotype_dt_ , double me void Cell_Container::update_all_cells_intracellular( void ) { - bool anything_to_update = false; + bool anything_to_update = false; // Use a simple boolean for reduction std::vector ready_to_update_intracellular = std::vector( (*all_cells).size(), false ); - #pragma omp parallel for + + #pragma omp parallel for reduction(||:anything_to_update) for( int i=0; i < (*all_cells).size(); i++ ) { if( (*all_cells)[i]->is_out_of_domain == false ) { if( (*all_cells)[i]->phenotype.intracellular != NULL && (*all_cells)[i]->phenotype.intracellular->need_update()) { ready_to_update_intracellular[i] = true; - anything_to_update = true; + anything_to_update = true; // Set to true if any cell needs an update if ((*all_cells)[i]->functions.pre_update_intracellular != NULL) { (*all_cells)[i]->functions.pre_update_intracellular((*all_cells)[i], (*all_cells)[i]->phenotype, diffusion_dt); @@ -324,7 +325,7 @@ void Cell_Container::update_all_cells_intracellular( void ) if (!anything_to_update) { return; } - + #pragma omp parallel for for ( int i=0; i < (*all_cells).size(); i++ ) {