using System;
using System.Collections.Generic;
using Simanfor.Core.EngineModels;
namespace EngineTest
{
///
/// Todas las funciones y procedimientos son opcionales. Si se elimina cualquiera de ellas, se usará un
/// procedimiento o función por defecto que no modifica el estado del inventario.
///
public class Template : ModelBase
{
///
/// Procedimiento que permite la inicialización de variables de parcelas necesarias para la ejecución del modelo
///
///
public override void Initialize(Parcela plot)
{
plot.SI = Math.Exp(4.016+(Math.Log(plot.H_DOMINANTE.Value)-4.016)*Math.Pow(80/plot.EDAD.Value,-0.5031));
}
///
/// Procedimiento que permite la inicialización de variables de árbol necesarias para la ejecución del modelo
///
///
///
public override void InitializeTree(Parcela plot, PieMayor tree)
{
tree.BAL = 0;
foreach (PieMayor pm in plot.PiesMayores)
{
if (pm.DAP < tree.DAP)
{
tree.BAL += pm.SEC_NORMAL.Value / 10000;
}
}
if (!tree.ALTURA.HasValue)
{
tree.ALTURA = (13 + (32.3287 + 1.6688 * plot.H_DOMINANTE * 10 - 0.1279 * plot.D_CUADRATICO * 10) * Math.Exp(-11.4522 / Math.Sqrt(tree.DAP.Value * 10))) / 10;
}
double HLCW = tree.ALTURA.Value / (1 + Math.Exp((double)(-0.0041*tree.ALTURA.Value*10-0.0093*tree.BAL-0.0123*plot.A_BASIMETRICA )));
if (!tree.ALTURA_BC.HasValue)
{
tree.ALTURA_BC = HLCW / (1+Math.Exp((double)(0.0078*plot.A_BASIMETRICA - 0.5725*Math.Log(plot.A_BASIMETRICA.Value)*0.0082*tree.BAL)));
}
tree.CR = (tree.ALTURA.Value - tree.ALTURA_BC.Value) / tree.ALTURA.Value;
if (!tree.LCW.HasValue)
{
tree.LCW = (0.1826*tree.DAP.Value)*Math.Pow(tree.CR.Value, (0.1594+0.0014*(tree.ALTURA.Value - tree.ALTURA_BC.Value)));
}
}
///
/// Función que indica si el árbol sobrevive o no después de "years" años
///
///
///
///
/// Devuelve el porcentaje de árboles que sobreviven
public override double Survives(double years, Parcela plot, PieMayor tree)
{
return 1 / (1 + Math.Exp(2.0968 + (4.7358 * tree.DAP.Value / plot.D_CUADRATICO.Value) - 0.0012 * plot.SI.Value * plot.A_BASIMETRICA.Value));
}
///
/// Procedimiento que permite modificar las propiedades del árbol durante su crecimiento después de "years" años
///
///
///
///
///
public override void Grow(double years, Parcela plot, PieMayor oldTree, PieMayor newTree)
{
double DBHG5 = Math.Exp(0.2030 * Math.Log(oldTree.DAP.Value) + 0.4414 * Math.Log(oldTree.CR.Value + 0.2 / 1.2) + 0.8379 * Math.Log(plot.SI.Value) - 0.1295 * Math.Sqrt(plot.A_BASIMETRICA.Value) - 0.0007 * (oldTree.BAL.Value * oldTree.BAL.Value / Math.Log(oldTree.DAP.Value)));
newTree.DAP += DBHG5;
newTree.ALTURA += Math.Exp(4.1375+0.3762*Math.Log(DBHG5)-0.5260*Math.Log(oldTree.DAP.Value)+0.1727*Math.Log(oldTree.ALTURA.Value)+2.6468*oldTree.CR.Value);
}
///
/// Procedimiento que permite añadir nuevos árboles a una parcela después de "years" años
///
///
///
/// Área basimetrica a distribuir o 0 si no hay masa incorporada
public override double? AddTree(double years, Parcela plot)
{
double result = 1 / (1 + Math.Exp(12.3424 + 0.1108 * plot.A_BASIMETRICA.Value - 0.6154 * plot.D_CUADRATICO.Value));
if (result >= 0.38F)
{
return 6.7389 - 0.2235 * plot.D_CUADRATICO.Value;
}
return 0.0F;
}
///
/// Expresa como se ha de distribuir la masa incorporada entre los árboles existentes.
/// La implementación por defecto la distribuye de forma uniforme.
///
///
///
///
///
public override Distribution[] NewTreeDistribution(double years, Parcela plot, double AreaBasimetricaIncorporada)
{
Distribution[] distribution = new Distribution[3];
double percentAreaBasimetrica = AreaBasimetricaIncorporada/plot.A_BASIMETRICA.Value;
distribution[0] = new Distribution();
distribution[0].diametroMenor = 0.0;
distribution[0].diametroMayor = 12.5;
distribution[0].AreaBasimetricaToAdd = 0.0809 * AreaBasimetricaIncorporada;
distribution[1] = new Distribution();
distribution[1].diametroMenor = 12.5;
distribution[1].diametroMayor = 22.5;
distribution[1].AreaBasimetricaToAdd = 0.3263 * AreaBasimetricaIncorporada;
distribution[2] = new Distribution();
distribution[2].diametroMenor = 22.5;
distribution[2].diametroMayor = double.MaxValue;
distribution[2].AreaBasimetricaToAdd = 0.5828 * AreaBasimetricaIncorporada;
return distribution;
}
///
/// Procedimiento que realiza todos los precálculos para preparar el procesamiento de los árboles y parcelas.
///
///
///
///
public override void PreCalculation(double years, Parcela plot, PieMayor[] trees)
{
}
///
/// Procedimiento que realiza los cálculos sobre un árbol.
///
///
///
///
public override void ProcessTree(double years, Parcela plot, PieMayor tree)
{
double exp = 1 / 0.8533;
double DIB = Math.Pow((1 / 2.8708), exp) * Math.Pow(tree.DAP.Value*10, exp);
currentTree = tree;
tree.VCC = IntegralBySimpson(0, 1, 0.01, d_conCorteza); //Integración --> d_conCorteza sobre HR en los limites 0 -> 1
tree.VSC = IntegralBySimpson(0, 1, 0.01, d_sinCorteza); //Integración --> d_sinCorteza sobre HR en los limites 0 -> 1
currentTree = null;
}
private PieMayor currentTree;
private double d_conCorteza(double HR)
{
return (1 + 1.1034 * Math.Exp(-6.0879 * HR)) * Math.Pow(0.5656 * currentTree.DAP.Value * (1 - HR), 0.6330 - 1.7228 * (1 - HR));
}
private double d_sinCorteza(double HR)
{
return (1 + 2.4771 * Math.Exp(-5.0779 * HR)) * Math.Pow(0.2360 * currentTree.DAP.Value * (1 - HR), 0.4733 - 3.0371 * (1 - HR));
}
///
/// Procedimiento que realiza los cálculos sobre una parcela.
///
///
///
///
public override void ProcessPlot(double years, Parcela plot, PieMayor[] trees)
{
}
}
}