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) { } } }