@@ -608,6 +608,7 @@ bool ConnectionPlot::redraw(int x0, int y0, int width, int height)
608608void SpatialModel::setGrid (size_t nx, size_t ny)
609609{
610610 numX=nx; numY=ny;
611+ objects.clear ();
611612 for (size_t i=0 ; i<numX; ++i)
612613 for (size_t j=0 ; j<numY; ++j)
613614 {
@@ -617,10 +618,14 @@ void SpatialModel::setGrid(size_t nx, size_t ny)
617618 c.rand .seed (o.id ());
618619 o.proc (o.id () % nprocs ()); // TODO can we get this to work without this.
619620 // wire up von Neumann neighborhood
620- o->neighbours .push_back (makeId (i-1 ,j));
621- o->neighbours .push_back (makeId (i+1 ,j));
622- o->neighbours .push_back (makeId (i,j-1 ));
623- o->neighbours .push_back (makeId (i,j+1 ));
621+ if (i>0 )
622+ o->neighbours .push_back (makeId (i-1 ,j));
623+ if (i<numX-1 )
624+ o->neighbours .push_back (makeId (i+1 ,j));
625+ if (j>0 )
626+ o->neighbours .push_back (makeId (i,j-1 ));
627+ if (j<numY-1 )
628+ o->neighbours .push_back (makeId (i,j+1 ));
624629 }
625630 rebuildPtrLists ();
626631}
@@ -641,64 +646,66 @@ unsigned SpatialModel::migrate()
641646
642647 prepareNeighbours ();
643648
644- // #ifdef SYCL_LANGUAGE_VERSION
645- // using ArrayAlloc=graphcode::Allocator<int>;
646- // using Array=vector<int,ArrayAlloc>;
647- // using DeltaAlloc=graphcode::Allocator<Array>;
648- // Array init(species.size(),0,ArrayAlloc(syclQ(),sycl::usm::alloc::device));
649- // vector<Array,DeltaAlloc> delta(size(), init, DeltaAlloc(syclQ(),sycl::usm::alloc::device));
650- // #else
651649 vector<array<int >> delta (size (), array<int >(species.size (),0 ));
652- // #endif
653-
654- // for (auto& c: *this)
655- // c->as<EcolabCell>()->delta.resize(species.size());
656650
657651 hostForAll ([&,this ](EcolabCell& c) {
658652 /* loop over neighbours */
659653 for (auto & n: c)
660654 {
661655 auto & nbr=*n->as <EcolabCell>();
662- Float salt=c.id <nbr.id ? c.salt : nbr.salt ;
656+ Float salt=c.idx () <nbr.idx () ? c.salt : nbr.salt ;
663657 array<Float> m=(tstep-last_mig_tstep) * migration * (nbr.density - c.density );
664- delta[c.idx ()]+=m+ array<Float>(( m!=0.0 )*( 2 *(m> 0.0 )- 1 )) * salt ;
658+ delta[c.idx ()]+=m*( 1 +salt*( m!=0.0 )) ;
665659 }
666660 });
667661
668662 array<int > ssum (species.size (),0 );
669663 size_t totalMigration=0 ;
670- hostForAll ([&,this ](EcolabCell& c) {
671- // adjust delta so that density remains +ve
672- array<int > adjust=delta[c.idx ()]+c.density ;
673- adjust*=-(adjust<0 );
674- if (sum (adjust)>0 )
675- {
676- // distribute adjust among neighbours
677- array<int > totalDiff (c.density .size (),0 );
678- for (auto & n: c)
679- {
680- auto & nbr=*n->as <EcolabCell>();
681- totalDiff+=nbr.density -c.density ;
682- }
683- // adjust adjust to be divisible by totalDiff
684- adjust-=adjust%totalDiff;
685- for (auto & n: c)
686- {
687- auto & nbr=*n->as <EcolabCell>();
688- delta[nbr.idx ()]+=((nbr.density -c.density )/totalDiff)*adjust;
689- }
690- delta[c.idx ()]-=adjust;
691- }
692664
693- c.density +=delta[c.idx ()];
694- totalMigration+=sum (abs (delta[c.idx ()]));
665+ vector<size_t > negativeDensityIdx;
666+ size_t numCells=size ();
667+ #ifdef _OPENMP
668+ #pragma omp parallel for reduction(+:totalMigration)
669+ #endif
670+ for (size_t i=0 ; i<numCells; ++i)
671+ {
672+ auto & c=*(*this )[i]->as <EcolabCell>();
673+ c.density +=delta[c.idx ()];
674+ totalMigration+=sum (abs (delta[i]));
675+ if (sum (c.density <0 ))
676+ #ifdef _OPENMP
677+ #pragma omp critical
678+ #endif
679+ negativeDensityIdx.push_back (c.idx ());
695680#if !defined(NDEBUG)
681+ #ifdef _OPENMP
696682#pragma omp critical
697- ssum+=delta[c.idx ()];
698683#endif
699- });
684+ ssum+=delta[c.idx ()];
685+ #endif
686+ }
700687 last_mig_tstep=tstep;
701688
689+ // if any density values are -ve, then adjust migration from neighbours.
690+ // loop run sequentially to resolve race condition
691+ for (auto i: negativeDensityIdx)
692+ {
693+ auto & c=*(*this )[i]->as <EcolabCell>();
694+ for (auto j=0 ; j<c.density .size (); ++j)
695+ while (c.density [j]<0 )
696+ {
697+ assert (c.size ()>0 );
698+ int adjust=-(c.density [j]+c.size ()-1 )/c.size ();
699+ for (auto & n: c)
700+ {
701+ auto & nbr=*n->as <EcolabCell>();
702+ auto nbrAdjust=std::min (nbr.density [j], adjust);
703+ c.density [j]+=nbrAdjust;
704+ nbr.density [j]-=nbrAdjust;
705+ }
706+ }
707+ }
708+
702709#ifdef MPI_SUPPORT
703710 if (myid ()==0 )
704711 MPI_Reduce (MPI_IN_PLACE, &totalMigration,1 ,MPI_UNSIGNED,MPI_SUM,0 ,MPI_COMM_WORLD);
@@ -734,7 +741,7 @@ unsigned SpatialModel::migrate()
734741 }
735742 if (myid ()==0 ) assert (sum (ssum==0 )==int (ssum.size ()));
736743#endif
737- return totalMigration;
744+ return totalMigration/ 2 ;
738745}
739746
740747void ModelData::makeConsistent (size_t nsp)
0 commit comments