Subversion Repositories public iLand

Rev

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.