Subversion Repositories public iLand

Rev

Rev 1181 | Rev 1204 | Go to most recent revision | Show entire file | Ignore 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 804... Line 810...
804
        }
810
        }
805
    }
811
    }
806
812
807
    // sink mode
813
    // sink mode
808
814
809
//    // now look for each pixel in the targetmap and sum up seeds*kernel
-
 
810
//    int idx=0;
-
 
811
//    int offset = kernel.sizeX() / 2; // offset is the index of the center pixel
-
 
812
//    //const Grid<ResourceUnit*> &ru_map = GlobalSettings::instance()->model()->RUgrid();
-
 
813
//    DebugTimer tsink("seed_sink"); {
-
 
814
//    for (float *t=mSeedMap.begin(); t!=mSeedMap.end(); ++t, ++idx) {
-
 
815
//        // skip out-of-project areas
-
 
816
//        //if (!ru_map.constValueAtIndex(mSeedMap.index5(idx)))
-
 
817
//        //    continue;
-
 
818
//        // apply the kernel
-
 
819
//        QPoint sm=mSeedMap.indexOf(t)-QPoint(offset, offset);
-
 
820
//        for (int iy=0;iy<kernel.sizeY();++iy) {
-
 
821
//            for (int ix=0;ix<kernel.sizeX();++ix) {
-
 
822
//                if (sourcemap.isIndexValid(sm.x()+ix, sm.y()+iy))
-
 
823
//                    *t+=sourcemap(sm.x()+ix, sm.y()+iy) * kernel(ix, iy);
-
 
824
//            }
-
 
825
//        }
-
 
826
//    }
-
 
827
//    } // debugtimer
-
 
828
//    mSeedMap.initialize(0.f); // just for debugging...
-
 
-
 
815
    //    // now look for each pixel in the targetmap and sum up seeds*kernel
-
 
816
    //    int idx=0;
-
 
817
    //    int offset = kernel.sizeX() / 2; // offset is the index of the center pixel
-
 
818
    //    //const Grid<ResourceUnit*> &ru_map = GlobalSettings::instance()->model()->RUgrid();
-
 
819
    //    DebugTimer tsink("seed_sink"); {
-
 
820
    //    for (float *t=mSeedMap.begin(); t!=mSeedMap.end(); ++t, ++idx) {
-
 
821
    //        // skip out-of-project areas
-
 
822
    //        //if (!ru_map.constValueAtIndex(mSeedMap.index5(idx)))
-
 
823
    //        //    continue;
-
 
824
    //        // apply the kernel
-
 
825
    //        QPoint sm=mSeedMap.indexOf(t)-QPoint(offset, offset);
-
 
826
    //        for (int iy=0;iy<kernel.sizeY();++iy) {
-
 
827
    //            for (int ix=0;ix<kernel.sizeX();++ix) {
-
 
828
    //                if (sourcemap.isIndexValid(sm.x()+ix, sm.y()+iy))
-
 
829
    //                    *t+=sourcemap(sm.x()+ix, sm.y()+iy) * kernel(ix, iy);
-
 
830
    //            }
-
 
831
    //        }
-
 
832
    //    }
-
 
833
    //    } // debugtimer
-
 
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
-
 
839
    // *** seed distribution (Kernel + long distance dispersal) ***
-
 
840
    if (GlobalSettings::instance()->model()->settings().torusMode==false) {
-
 
841
        // ** standard case (no torus) **
-
 
842
        for (float *src=sourcemap.begin(); src!=sourcemap.end(); ++src) {
-
 
843
            if (*src>0.f) {
-
 
844
                QPoint sm=sourcemap.indexOf(src)-QPoint(offset, offset);
-
 
845
                int sx = sm.x(), sy=sm.y();
-
 
846
                for (int iy=0;iy<kernel.sizeY();++iy) {
-
 
847
                    for (int ix=0;ix<kernel.sizeX();++ix) {
-
 
848
                        if (mSeedMap.isIndexValid(sx+ix, sy+iy))
-
 
849
                            mSeedMap.valueAtIndex(sx+ix, sy+iy)+= *src * kernel(ix, iy);
-
 
850
                    }
-
 
851
                }
-
 
852
                // long distance dispersal
-
 
853
                if (!mLDDDensity.isEmpty()) {
-
 
854
                    QPoint pt=sourcemap.indexOf(src);
833
855
834
    for (float *src=sourcemap.begin(); src!=sourcemap.end(); ++src) {
-
 
835
        if (*src>0.f) {
-
 
836
            QPoint sm=sourcemap.indexOf(src)-QPoint(offset, offset);
-
 
837
            int sx = sm.x(), sy=sm.y();
-
 
838
            for (int iy=0;iy<kernel.sizeY();++iy) {
-
 
839
                for (int ix=0;ix<kernel.sizeX();++ix) {
-
 
840
                    if (mSeedMap.isIndexValid(sx+ix, sy+iy))
-
 
841
                        mSeedMap.valueAtIndex(sx+ix, sy+iy)+= *src * kernel(ix, iy);
-
 
-
 
856
                    for (int r=0;r<mLDDDensity.size(); ++r) {
-
 
857
                        float ldd_val = mLDDSeedlings / fec; // pixels will have this probability [note: fecundity will be multiplied below]
-
 
858
                        int n;
-
 
859
                        if (mLDDDensity[r]<1)
-
 
860
                            n = drandom()<mLDDDensity[r] ? 1 : 0;
-
 
861
                        else
-
 
862
                            n = round( mLDDDensity[r] ); // number of pixels to activate
-
 
863
                        for (int i=0;i<n;++i) {
-
 
864
                            // distance and direction:
-
 
865
                            double radius = nrandom(mLDDDistance[r], mLDDDistance[r+1]) / mSeedMap.cellsize(); // choose a random distance (in pixels)
-
 
866
                            double phi = drandom()*2.*M_PI; // choose a random direction
-
 
867
                            QPoint ldd(pt.x() + radius*cos(phi), pt.y() + radius*sin(phi));
-
 
868
                            if (mSeedMap.isIndexValid(ldd)) {
-
 
869
                                float &val = mSeedMap.valueAtIndex(ldd);
-
 
870
                                _debug_ldd++;
-
 
871
                                val += ldd_val;
-
 
872
                            }
-
 
873
                        }
-
 
874
                    }
842
                }
875
                }
-
 
876
843
            }
877
            }
844
            // long distance dispersal
-
 
845
            if (!mLDDDensity.isEmpty()) {
-
 
846
                QPoint pt=sourcemap.indexOf(src);
-
 
-
 
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) );
847
918
848
                for (int r=0;r<mLDDDensity.size(); ++r) {
-
 
849
                    float ldd_val = mLDDSeedlings / fec; // pixels will have this probability [note: fecundity will be multiplied below]
-
 
850
                    int n;
-
 
851
                    if (mLDDDensity[r]<1)
-
 
852
                        n = drandom()<mLDDDensity[r] ? 1 : 0;
-
 
853
                    else
-
 
854
                        n = round( mLDDDensity[r] ); // number of pixels to activate
-
 
855
                    for (int i=0;i<n;++i) {
-
 
856
                        // distance and direction:
-
 
857
                        double radius = nrandom(mLDDDistance[r], mLDDDistance[r+1]) / mSeedMap.cellsize(); // choose a random distance (in pixels)
-
 
858
                        double phi = drandom()*2.*M_PI; // choose a random direction
-
 
859
                        QPoint ldd(pt.x() + radius*cos(phi), pt.y() + radius*sin(phi));
-
 
860
                        if (mSeedMap.isIndexValid(ldd)) {
-
 
861
                            float &val = mSeedMap.valueAtIndex(ldd);
-
 
862
                            _debug_ldd++;
-
 
863
                            val += ldd_val;
-
 
-
 
919
                            if (mSeedMap.isIndexValid(torus_pos)) {
-
 
920
                                float &val = mSeedMap.valueAtIndex(torus_pos);
-
 
921
                                _debug_ldd++;
-
 
922
                                val += ldd_val;
-
 
923
                            }
864
                        }
924
                        }
865
                    }
925
                    }
866
                }
926
                }
-
 
927
867
            }
928
            }
868
-
 
869
        }
929
        }
870
    }
-
 
-
 
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.