Skip to content

Commit 27097b4

Browse files
Return number of extinctions from condense.
Renable migrate code. Make makeId() work for some negative arguments. Code to run epochs of high and low migration.
1 parent 595f073 commit 27097b4

File tree

3 files changed

+96
-63
lines changed

3 files changed

+96
-63
lines changed

models/ecolab_model.cc

Lines changed: 62 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -200,16 +200,17 @@ void ModelData::condense(const array<bool>& mask, size_t mask_true) /* remove
200200
foodweb = interaction;
201201
}
202202

203-
void PanmicticModel::condense()
203+
unsigned PanmicticModel::condense()
204204
{
205205
auto mask=density != 0;
206206
size_t mask_true=sum(mask);
207-
if (mask.size()==mask_true) return; /* no change ! */
207+
if (mask.size()==mask_true) return 0; /* no change ! */
208208
ModelData::condense(mask,mask_true);
209209
EcolabPoint::condense(mask, mask_true);
210+
return mask.size()-mask_true;
210211
}
211212

212-
void SpatialModel::condense()
213+
unsigned SpatialModel::condense()
213214
{
214215
array<int> total_density(species.size());
215216
for (auto& i: *this) total_density+=i->as<EcolabCell>()->density; // TODO
@@ -221,9 +222,10 @@ void SpatialModel::condense()
221222
auto mask=total_density != 0;
222223

223224
size_t mask_true=sum(mask);
224-
if (mask.size()==mask_true) return; /* no change ! */
225+
if (mask.size()==mask_true) return 0; /* no change ! */
225226
ModelData::condense(mask,mask_true);
226227
for (auto& i: *this) i->as<EcolabCell>()->condense(mask, mask_true);
228+
return mask.size()-mask_true;
227229
}
228230

229231

@@ -633,59 +635,71 @@ void SpatialModel::generate(unsigned niter)
633635

634636
void SpatialModel::migrate()
635637
{
636-
// /* each cell gets a distinct random salt value */
637-
// forAll([=,this](EcolabCell& c) {c.salt=c.rand();});
638-
//
639-
// prepareNeighbours();
640-
//
641-
////#ifdef SYCL_LANGUAGE_VERSION
642-
//// using ArrayAlloc=graphcode::Allocator<int>;
643-
//// using Array=vector<int,ArrayAlloc>;
644-
//// using DeltaAlloc=graphcode::Allocator<Array>;
645-
//// Array init(species.size(),0,ArrayAlloc(syclQ(),sycl::usm::alloc::device));
646-
//// vector<Array,DeltaAlloc> delta(size(), init, DeltaAlloc(syclQ(),sycl::usm::alloc::device));
647-
////#else
648-
//// vector<array<int>> delta(size(), array<int>(species.size(),0));
649-
////#endif
650-
//
638+
/* each cell gets a distinct random salt value */
639+
hostForAll([=,this](EcolabCell& c) {c.salt=c.rand();});
640+
641+
prepareNeighbours();
642+
643+
//#ifdef SYCL_LANGUAGE_VERSION
644+
// using ArrayAlloc=graphcode::Allocator<int>;
645+
// using Array=vector<int,ArrayAlloc>;
646+
// using DeltaAlloc=graphcode::Allocator<Array>;
647+
// Array init(species.size(),0,ArrayAlloc(syclQ(),sycl::usm::alloc::device));
648+
// vector<Array,DeltaAlloc> delta(size(), init, DeltaAlloc(syclQ(),sycl::usm::alloc::device));
649+
//#else
650+
vector<array<int>> delta(size(), array<int>(species.size(),0));
651+
//#endif
652+
651653
// for (auto& c: *this)
652654
// c->as<EcolabCell>()->delta.resize(species.size());
653-
//
654-
// groupedForAll([=,this](EcolabCell& c) {
655-
// /* loop over neighbours */
656-
// for (auto& n: c)
657-
// {
658-
// auto& nbr=*n->as<EcolabCell>();
659-
// Float salt=c.id<nbr.id? c.salt: nbr.salt;
660-
// array_ns::groupAsg(species.size(), [&](size_t i) {
661-
// Float m=(tstep-last_mig_tstep) * migration[i] * (nbr.density[i] - c.density[i]);
662-
// c.delta[i]+=m + (m!=0.0)*(2*(m>0.0)-1) * salt;
663-
// });
664-
// }
665-
// });
666-
// last_mig_tstep=tstep;
667-
// syncThreads();
668-
// groupedForAll([=,this](EcolabCell& c) {
669-
// c.density+=c.delta;
670-
// });
655+
656+
hostForAll([&,this](EcolabCell& c) {
657+
/* loop over neighbours */
658+
for (auto& n: c)
659+
{
660+
auto& nbr=*n->as<EcolabCell>();
661+
Float salt=c.id<nbr.id? c.salt: nbr.salt;
662+
array<Float> m=(tstep-last_mig_tstep) * migration * (nbr.density - c.density);
663+
delta[c.idx()]+=m + array<Float>((m!=0.0)*(2*(m>0.0)-1)) * salt;
664+
}
665+
});
666+
667+
array<int> ssum(species.size(),0);
668+
hostForAll([&,this](EcolabCell& c) {
669+
c.density+=delta[c.idx()];
670+
#if !defined(NDEBUG)
671+
#pragma omp critical
672+
ssum+=delta[c.idx()];
673+
#endif
674+
});
675+
last_mig_tstep=tstep;
671676

672677
/* assertion testing that population numbers are conserved */
673678
#if !defined(NDEBUG) && !defined(SYCL_LANGUAGE_VERSION)
674-
array<int> ssum(species.size()), s(species.size());
675-
unsigned mig=0, i;
676-
for (ssum=0, i=0; i<size(); i++)
677-
{
678-
ssum+=delta[i];
679-
for (size_t j=0; j<delta[i].size(); j++)
680-
mig+=abs(delta[i][j]);
681-
}
682679
#ifdef MPI_SUPPORT
680+
array<int> s(species.size());
683681
MPI_Reduce(ssum.data(),s.data(),s.size(),MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);
684682
ssum=s;
685-
int m;
686-
MPI_Reduce(&mig,&m,1,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);
687-
mig=m;
688683
#endif
684+
if (sum(ssum==0)!=int(ssum.size()))
685+
{
686+
for (size_t i=0; i<ssum.size(); ++i)
687+
if (ssum[i])
688+
{
689+
cout<<"species "<<i<<":"<<endl;
690+
for (size_t idx=0; idx<size(); ++idx)
691+
if (delta[idx][i])
692+
{
693+
auto& c=*(*this)[idx]->as<EcolabCell>();
694+
cout<<" delta "<<c.id<<"="<<delta[idx][i]<<" n="<<c.density[i]<<endl;
695+
for (auto& n: c)
696+
{
697+
auto& nbr=*n->as<EcolabCell>();
698+
cout<<" nbr:"<<nbr.id<<"="<<nbr.density[i]<<endl;
699+
}
700+
}
701+
}
702+
}
689703
if (myid()==0) assert(sum(ssum==0)==int(ssum.size()));
690704
#endif
691705
}

models/ecolab_model.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ struct PanmicticModel: public ModelData, public EcolabPoint<AllocatorBase>, publ
9595
void seed(unsigned x) {rand.seed(x);}
9696
void generate(unsigned niter);
9797
void generate() {generate(1);}
98-
void condense();
98+
/// returns number of extinctions
99+
unsigned condense();
99100
void mutate();
100101
array<double> lifetimes();
101102
};
@@ -113,7 +114,8 @@ class SpatialModel: public ModelData, public EcolabGraph<EcolabCell>,
113114
CLASSDESC_ACCESS(SpatialModel);
114115
public:
115116
static constexpr size_t log2MaxNsp=10;
116-
size_t makeId(size_t x, size_t y) const {return x%numX + numX*(y%numY);}
117+
// function valid for x∈(-numX,∞], y∈(-numY,∞]
118+
size_t makeId(size_t x, size_t y) const {return (x+numX)%numX + numX*((y+numY)%numY);}
117119
void setGrid(size_t nx, size_t ny);
118120
EcolabCell& cell(size_t x, size_t y) {
119121
return *objects[makeId(x,y)];
@@ -126,7 +128,8 @@ class SpatialModel: public ModelData, public EcolabGraph<EcolabCell>,
126128
void seed(unsigned x) {forAll([=](EcolabCell& cell){cell.rand.seed(x);});}
127129
void generate(unsigned niter);
128130
void generate() {generate(1);}
129-
void condense();
131+
/// returns number of extinctions
132+
unsigned condense();
130133
void mutate();
131134
void migrate();
132135
};

models/spatial_ecolab.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
print(device())
88

99
# we want initialisation to be identical across all processes
10-
randomSeed(1)
10+
randomSeed(10)
1111

1212
# we want the array operations to have a different seed across processes
1313
array_urand.seed(10+myid())
@@ -28,14 +28,15 @@ def randomList(num, min, max):
2828

2929
ecolab.species(range(nsp))
3030

31-
numX=2
32-
numY=2
31+
numX=3
32+
numY=3
3333
ecolab.setGrid(numX,numY)
3434
ecolab.partitionObjects()
3535

3636
print("initialising density")
3737
for i in range(numX):
3838
for j in range(numY):
39+
#ecolab.cell(i,j).density([int(100*random()) for i in range(nsp)])
3940
ecolab.cell(i,j).density(nsp*[100])
4041
print("density initialised")
4142

@@ -46,20 +47,30 @@ def randomList(num, min, max):
4647
ecolab.interaction.val(randomList(len(ecolab.interaction.val), ecolab.odiag_min(), ecolab.odiag_max()))
4748

4849
ecolab.mutation(nsp*[ecolab.mut_max()])
49-
ecolab.migration(nsp*[1e-5])
50+
ecolab.migration(nsp*[1e-4])
5051

5152
from plot import plot
5253
from GUI import gui, statusBar, windows
5354

55+
epoch=2000000
56+
mut_factor=1000
5457

58+
extinctions=0
5559
def stepImpl():
5660
#ecolab.setDensitiesDevice()
5761
ecolab.generate(100)
5862
ecolab.mutate()
59-
# ecolab.migrate()
60-
# ecolab.condense()
63+
64+
epochTs=ecolab.tstep()%epoch
65+
if (epochTs==0):
66+
ecolab.migration([x*mut_factor for x in ecolab.migration()])
67+
if (epochTs==epoch//2):
68+
ecolab.migration([x/mut_factor for x in ecolab.migration()])
69+
70+
#ecolab.migrate()
71+
global extinctions
72+
extinctions+=ecolab.condense()
6173
#ecolab.syncThreads()
62-
print("tstep=",ecolab.tstep())
6374
#print(ecolab.nsp()())
6475
#ecolab.setDensitiesShared()
6576
#ecolab.gather()
@@ -73,15 +84,20 @@ def stepImpl():
7384
print(timeit('stepImpl()', globals=globals(), number=10))
7485

7586
def step():
76-
stepImpl()
87+
global extinctions
88+
extinctions=0
89+
for i in range(epoch//10000):
90+
stepImpl()
7791
if myid()==0:
7892
nsp=len(ecolab.species)
7993
statusBar.configure(text=f't={ecolab.tstep()} nsp:{nsp}')
80-
plot('No. species',ecolab.tstep(),nsp)
94+
plot('No. species',ecolab.tstep(),nsp,200*(ecolab.tstep()%epoch<0.5*epoch))
95+
#plot('No. species',ecolab.tstep(),nsp)
8196
plot('No. species by cell',ecolab.tstep(),ecolab.nsp()())
82-
for i in range(numX):
83-
for j in range(numY):
84-
plot(f'Density({i},{j})',ecolab.tstep(),ecolab.cell(i,j).density(), pens=ecolab.species())
97+
plot('Extinctions',ecolab.tstep(),extinctions)
98+
# for i in range(numX):
99+
# for j in range(numY):
100+
# plot(f'Density({i},{j})',ecolab.tstep(),ecolab.cell(i,j).density(), pens=ecolab.species())
85101

86102
gui(step)
87103

0 commit comments

Comments
 (0)