Rev 1181 | Rev 1204 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1181 | Rev 1182 | ||
---|---|---|---|
Line 785... | Line 785... | ||
785 | }
|
785 | }
|
786 | *p=1.f; // mark as processed |
786 | *p=1.f; // mark as processed |
787 | } // *p==1 |
787 | } // *p==1 |
788 | } // for() |
788 | } // for() |
789 | }
|
789 | }
|
- | 790 | ||
- | 791 | // because C modulo operation gives negative numbers for negative values, here a fix
|
|
- | 792 | // that always returns positive numbers: http://www.lemoda.net/c/modulo-operator/
|
|
- | 793 | #define MOD(a,b) ((((a)%(b))+(b))%(b))
|
|
790 | 794 | ||
791 | void SeedDispersal::distributeSeeds(Grid<float> *seed_map) |
795 | void SeedDispersal::distributeSeeds(Grid<float> *seed_map) |
792 | {
|
796 | {
|
793 | Grid<float> &sourcemap = seed_map ? *seed_map : mSourceMap; // switch to extra seed map if provided |
797 | Grid<float> &sourcemap = seed_map ? *seed_map : mSourceMap; // switch to extra seed map if provided |
794 | Grid<float> &kernel = mKernelSeedYear; |
798 | Grid<float> &kernel = mKernelSeedYear; |
- | 799 | ||
- | 800 | // *** estimate seed production (based on leaf area) ***
|
|
795 | // calculate number of seeds; the source map holds now m2 leaf area on 20x20m pixels
|
801 | // calculate number of seeds; the source map holds now m2 leaf area on 20x20m pixels
|
796 | // after this step, each source cell has a value between 0 (no source) and 1 (fully covered cell)
|
802 | // after this step, each source cell has a value between 0 (no source) and 1 (fully covered cell)
|
797 | float fec = species()->fecundity_m2(); |
803 | float fec = species()->fecundity_m2(); |
798 | if (!species()->isSeedYear()) |
804 | if (!species()->isSeedYear()) |
799 | fec *= mNonSeedYearFraction; |
805 | fec *= mNonSeedYearFraction; |
Line 828... | Line 834... | ||
828 | // mSeedMap.initialize(0.f); // just for debugging...
|
834 | // mSeedMap.initialize(0.f); // just for debugging...
|
829 | 835 | ||
830 | int offset = kernel.sizeX() / 2; // offset is the index of the center pixel |
836 | int offset = kernel.sizeX() / 2; // offset is the index of the center pixel |
831 | // source mode
|
837 | // source mode
|
832 | 838 | ||
833 | - | ||
- | 839 | // *** seed distribution (Kernel + long distance dispersal) ***
|
|
- | 840 | if (GlobalSettings::instance()->model()->settings().torusMode==false) { |
|
- | 841 | // ** standard case (no torus) **
|
|
834 | for (float *src=sourcemap.begin(); src!=sourcemap.end(); ++src) { |
842 | for (float *src=sourcemap.begin(); src!=sourcemap.end(); ++src) { |
835 | if (*src>0.f) { |
843 | if (*src>0.f) { |
836 | QPoint sm=sourcemap.indexOf(src)-QPoint(offset, offset); |
844 | QPoint sm=sourcemap.indexOf(src)-QPoint(offset, offset); |
837 | int sx = sm.x(), sy=sm.y(); |
845 | int sx = sm.x(), sy=sm.y(); |
838 | for (int iy=0;iy<kernel.sizeY();++iy) { |
846 | for (int iy=0;iy<kernel.sizeY();++iy) { |
Line 866... | Line 874... | ||
866 | }
|
874 | }
|
867 | }
|
875 | }
|
868 | 876 | ||
869 | }
|
877 | }
|
870 | }
|
878 | }
|
- | 879 | } else { |
|
- | 880 | // **** seed distribution in torus mode ***
|
|
- | 881 | int seedmap_offset = sourcemap.indexAt(QPointF(0., 0.)).x(); // the seed maps have x extra rows/columns |
|
- | 882 | QPoint torus_pos;
|
|
- | 883 | int seedpx_per_ru = static_cast<int>((cRUSize/sourcemap.cellsize())); |
|
- | 884 | for (float *src=sourcemap.begin(); src!=sourcemap.end(); ++src) { |
|
- | 885 | if (*src>0.f) { |
|
- | 886 | QPoint sm=sourcemap.indexOf(src); |
|
- | 887 | // get the origin of the resource unit *on* the seedmap in *seedmap-coords*:
|
|
- | 888 | QPoint offset_ru( ((sm.x()-seedmap_offset) / seedpx_per_ru) * seedpx_per_ru + seedmap_offset, |
|
- | 889 | ((sm.y()-seedmap_offset) / seedpx_per_ru) * seedpx_per_ru + seedmap_offset); // coords RU origin |
|
- | 890 | ||
- | 891 | QPoint offset_in_ru((sm.x()-seedmap_offset) % seedpx_per_ru, (sm.y()-seedmap_offset) % seedpx_per_ru ); // offset of current point within the RU |
|
- | 892 | ||
- | 893 | //QPoint sm=sourcemap.indexOf(src)-QPoint(offset, offset);
|
|
- | 894 | for (int iy=0;iy<kernel.sizeY();++iy) { |
|
- | 895 | for (int ix=0;ix<kernel.sizeX();++ix) { |
|
- | 896 | torus_pos = offset_ru + QPoint(MOD((offset_in_ru.x() - offset + ix), seedpx_per_ru), MOD((offset_in_ru.y() - offset + iy), seedpx_per_ru)); |
|
- | 897 | ||
- | 898 | if (mSeedMap.isIndexValid(torus_pos)) |
|
- | 899 | mSeedMap.valueAtIndex(torus_pos)+= *src * kernel(ix, iy); |
|
- | 900 | }
|
|
- | 901 | }
|
|
- | 902 | // long distance dispersal
|
|
- | 903 | if (!mLDDDensity.isEmpty()) { |
|
- | 904 | ||
- | 905 | for (int r=0;r<mLDDDensity.size(); ++r) { |
|
- | 906 | float ldd_val = mLDDSeedlings / fec; // pixels will have this probability [note: fecundity will be multiplied below] |
|
- | 907 | int n; |
|
- | 908 | if (mLDDDensity[r]<1) |
|
- | 909 | n = drandom()<mLDDDensity[r] ? 1 : 0; |
|
- | 910 | else
|
|
- | 911 | n = round( mLDDDensity[r] ); // number of pixels to activate |
|
- | 912 | for (int i=0;i<n;++i) { |
|
- | 913 | // distance and direction:
|
|
- | 914 | double radius = nrandom(mLDDDistance[r], mLDDDistance[r+1]) / mSeedMap.cellsize(); // choose a random distance (in pixels) |
|
- | 915 | double phi = drandom()*2.*M_PI; // choose a random direction |
|
- | 916 | QPoint ldd( radius*cos(phi), + radius*sin(phi)); // destination (offset) |
|
- | 917 | torus_pos = offset_ru + QPoint(MOD((offset_in_ru.x()+ldd.x()),seedpx_per_ru), MOD((offset_in_ru.y()+ldd.y()),seedpx_per_ru) ); |
|
- | 918 | ||
- | 919 | if (mSeedMap.isIndexValid(torus_pos)) { |
|
- | 920 | float &val = mSeedMap.valueAtIndex(torus_pos); |
|
- | 921 | _debug_ldd++; |
|
- | 922 | val += ldd_val; |
|
- | 923 | }
|
|
- | 924 | }
|
|
- | 925 | }
|
|
- | 926 | }
|
|
- | 927 | ||
- | 928 | }
|
|
- | 929 | }
|
|
- | 930 | } // torus |
|
871 | 931 | ||
872 | 932 | ||
873 | 933 | ||
874 | // now the seed sources (0..1) are spatially distributed by the kernel (and LDD) without altering the magnitude;
|
934 | // now the seed sources (0..1) are spatially distributed by the kernel (and LDD) without altering the magnitude;
|
875 | // now we include the fecundity (=seedling potential per m2 crown area), and convert to the establishment probability p_seed.
|
935 | // now we include the fecundity (=seedling potential per m2 crown area), and convert to the establishment probability p_seed.
|