Subversion Repositories public iLand

Rev

Rev 1176 | Rev 1179 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1176 Rev 1178
Line 361... Line 361...
361
    // filling of the kernel.... use the treemig
361
    // filling of the kernel.... use the treemig
362
    QPoint center = QPoint(kernel_offset, kernel_offset);
362
    QPoint center = QPoint(kernel_offset, kernel_offset);
363
    const float *sk_end = kernel.end();
363
    const float *sk_end = kernel.end();
364
    for (float *p=kernel.begin(); p!=sk_end;++p) {
364
    for (float *p=kernel.begin(); p!=sk_end;++p) {
365
        double d = kernel.distance(center, kernel.indexOf(p));
365
        double d = kernel.distance(center, kernel.indexOf(p));
366
        *p = d<=max_dist?static_cast<float>(treemig(d)):0.f;
-
 
-
 
366
        if (d==0.)
-
 
367
            *p = treemig_centercell(sqrt(cell_size*cell_size/M_PI)); // r is the radius of a circle with the same area as a cell
-
 
368
        else
-
 
369
            *p = d<=max_dist?static_cast<float>(treemig(d)):0.f;
367
    }
370
    }
368
371
369
    // normalize
372
    // normalize
370
    float sum = kernel.sum();
373
    float sum = kernel.sum();
371
    if (sum==0. || occupation==0.)
374
    if (sum==0. || occupation==0.)
372
        throw IException("create seed kernel: sum of probabilities = 0!");
375
        throw IException("create seed kernel: sum of probabilities = 0!");
373
376
374
    // the sum of all kernel cells has to equal 1
377
    // the sum of all kernel cells has to equal 1
375
    kernel.multiply(1.f/sum);
-
 
-
 
378
    // kernel.multiply(1.f/sum);
-
 
379
376
    float fecundity_factor = static_cast<float>( max_seed / occupation);
380
    float fecundity_factor = static_cast<float>( max_seed / occupation);
377
    // probabilities are derived in multiplying by seed number, and dividing by occupancy criterion
381
    // probabilities are derived in multiplying by seed number, and dividing by occupancy criterion
378
    kernel.multiply( fecundity_factor );
382
    kernel.multiply( fecundity_factor );
379
    // all cells that get more seeds than the occupancy criterion are considered to have no seed limitation for regeneration
383
    // all cells that get more seeds than the occupancy criterion are considered to have no seed limitation for regeneration
380
    for (float *p=kernel.begin(); p!=sk_end;++p) {
384
    for (float *p=kernel.begin(); p!=sk_end;++p) {
381
        *p = qMin(*p, 1.f);
385
        *p = qMin(*p, 1.f);
382
    }
386
    }
383
    // set the parent cell to 1
387
    // set the parent cell to 1
384
    kernel.valueAtIndex(kernel_offset, kernel_offset)=1.f;
-
 
-
 
388
    //kernel.valueAtIndex(kernel_offset, kernel_offset)=1.f;
385
389
386
390
387
    // some final statistics....
391
    // some final statistics....
388
    if (logLevelInfo()) qDebug() << "kernel setup.Species:"<< mSpecies->id() << "kernel-size: " << kernel.sizeX() << "x" << kernel.sizeY() << "pixels, sum: " << kernel.sum();
392
    if (logLevelInfo()) qDebug() << "kernel setup.Species:"<< mSpecies->id() << "kernel-size: " << kernel.sizeX() << "x" << kernel.sizeY() << "pixels, sum: " << kernel.sum();
389
393
Line 408... Line 412...
408
        mLDDDistance.push_back(mLDDDistance.last() + (r_max-r_min)/static_cast<float>(mLDDRings));
412
        mLDDDistance.push_back(mLDDDistance.last() + (r_max-r_min)/static_cast<float>(mLDDRings));
409
        double r_out = mLDDDistance.last();
413
        double r_out = mLDDDistance.last();
410
        // calculate the value of the kernel for the middle of the ring
414
        // calculate the value of the kernel for the middle of the ring
411
        double ring_in = treemig(r_in); // kernel value at the inner border of the ring
415
        double ring_in = treemig(r_in); // kernel value at the inner border of the ring
412
        double ring_out = treemig(r_out); // kernel value at the outer border of the ring
416
        double ring_out = treemig(r_out); // kernel value at the outer border of the ring
413
        double ring_val = ring_in - ring_out; // this p should be distributed within the ring
-
 
-
 
417
        double ring_val = (ring_in + ring_out)/2.; // this is the average p
414
        ring_val *= mFecundityFactor; // include fecundity (along the lines of the kernel calculations)
418
        ring_val *= mFecundityFactor; // include fecundity (along the lines of the kernel calculations)
415
        // calculate the area of the ring
419
        // calculate the area of the ring
416
        double ring_area = (r_out*r_out - r_in*r_in)*M_PI; // in square meters
420
        double ring_area = (r_out*r_out - r_in*r_in)*M_PI; // in square meters
417
        double ring_px = ring_area / (mSeedMap.cellsize()*mSeedMap.cellsize()); // # of seed pixels on the ring
421
        double ring_px = ring_area / (mSeedMap.cellsize()*mSeedMap.cellsize()); // # of seed pixels on the ring
418
        double n_px = ring_val * ring_px / mLDDProbability;
422
        double n_px = ring_val * ring_px / mLDDProbability;
Line 433... Line 437...
433
        }
437
        }
434
*/
438
*/
435
439
436
/// the used kernel function
440
/// the used kernel function
437
/// see also Appendix B of iland paper II (note the different variable names)
441
/// see also Appendix B of iland paper II (note the different variable names)
-
 
442
/// the function returns the seed density at a point with distance 'distance'.
438
double SeedDispersal::treemig(const double &distance)
443
double SeedDispersal::treemig(const double &distance)
439
{
444
{
440
    double p1 = (1.-mTM_ks)*exp(-distance/mTM_as1)/mTM_as1;
445
    double p1 = (1.-mTM_ks)*exp(-distance/mTM_as1)/mTM_as1;
441
    double p2 = 0.;
446
    double p2 = 0.;
442
    if (mTM_as2>0.)
447
    if (mTM_as2>0.)
443
       p2 = mTM_ks*exp(-distance/mTM_as2)/mTM_as2;
448
       p2 = mTM_ks*exp(-distance/mTM_as2)/mTM_as2;
444
    return p1 + p2;
-
 
-
 
449
    double s = p1 + p2;
-
 
450
    // 's' is the density for radius 'distance' - not for specific point with that distance.
-
 
451
    // (i.e. the integral over the one-dimensional treemig function is 1, but if applied for 2d cells, the
-
 
452
    // sum would be much larger as all seeds arriving at 'distance' would be arriving somewhere at the circle with radius 'distance')
-
 
453
    // convert that to a density at a point, by dividing with the circumference at the circle with radius 'distance'
-
 
454
    s = s / (2.*std::max(distance, 0.01)*M_PI);
-
 
455
-
 
456
    return s;
-
 
457
}
-
 
458
-
 
459
double SeedDispersal::treemig_centercell(const double &max_distance)
-
 
460
{
-
 
461
    // use 100 steps and calculate dispersal kernel for consecutive rings
-
 
462
    double sum = 0.;
-
 
463
    for (int i=0;i<100;i++) {
-
 
464
        double r_in = i*max_distance/100.;
-
 
465
        double r_out = (i+1)*max_distance/100.;
-
 
466
        double ring_area = (r_out*r_out-r_in*r_in)*M_PI;
-
 
467
        // the value of each ring is: treemig(r) * area of the ring
-
 
468
        sum += treemig((r_out+r_in)/2.)*ring_area;
-
 
469
    }
-
 
470
    return sum;
445
}
471
}
446
472
447
/// calculate the distance where the probability falls below 'value'
473
/// calculate the distance where the probability falls below 'value'
448
double SeedDispersal::treemig_distanceTo(const double value)
474
double SeedDispersal::treemig_distanceTo(const double value)
449
{
475
{