/// <summary> /// Función que indica si el árbol sobrevive o no después de "years" años /// </summary> /// <returns>Devuelve el porcentaje de árboles que sobreviven (que luego multiplica por EXPAN) public override double Survives(double years, Parcela plot, PieMayor tree) { double prob = MyFunc.probabilidadSupervivenciaen10(plot.A_BASIMETRICA.Value, tree.BAL.Value / plot.A_BASIMETRICA.Value, plot.I_HART.Value / 100); double prob_years = Math.Pow(prob, years / 10);///el exponente years/10 es para interpolar a "years" años, ya que el modelo de supervivencia se construyó para un lapso de 10 años return(prob_years); }
/// <summary> /// Procedimiento que realiza los cálculos sobre un árbol. /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> public override void ProcessTree(double years, Parcela plot, PieMayor tree) { currentTree = tree; tree.VCC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_conCorteza); //Integración --> r2_conCorteza sobre HR en los limites 0 -> 1 tree.VSC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_sinCorteza); //Integración --> d_sinCorteza sobre HR en los limites 0 -> 1 currentTree = null; }
/// <summary> /// Función que indica si el árbol sobrevive o no después de "years" años /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> /// <returns>Devuelve el porcentaje de árboles que sobreviven</returns> public override double Survives(double years, Parcela plot, PieMayor tree) { double BA_Survives = 1 - (1 / (1 + Math.Exp(2.0968 + (4.7358 * tree.DAP.Value / plot.D_CUADRATICO.Value) - 0.0012 * plot.SI.Value * plot.A_BASIMETRICA.Value))); if (BA_Survives > 0) { return(BA_Survives); } return(0.0F); }
/// <summary> /// Procedimiento que permite modificar las propiedades del árbol durante su crecimiento después de "years" años /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="oldTree"></param> /// <param name="newTree"></param> public override void Grow(double years, Parcela plot, PieMayor oldTree, PieMayor newTree) { double DBHG5 = Math.Exp(-0.37110 + 0.2525 * Math.Log(oldTree.DAP.Value) + 0.7090 * Math.Log((oldTree.CR.Value + 0.2) / 1.2) + 0.9087 * Math.Log(plot.SI.Value) - 0.1545 * Math.Sqrt(plot.A_BASIMETRICA.Value) - 0.0004 * (oldTree.BAL.Value * oldTree.BAL.Value / Math.Log(oldTree.DAP.Value))); newTree.DAP += DBHG5 / 10; double HTG5 = (Math.Exp(3.1222 - 0.4939 * Math.Log(oldTree.DAP.Value) + 1.3763 * Math.Log(plot.SI.Value) - 0.0061 * oldTree.BAL.Value + 0.1876 * Math.Log(oldTree.CR.Value))) / 500; newTree.ALTURA += HTG5 / 100; }
/// <summary> /// Procedimiento que permite modificar las propiedades del árbol durante su crecimiento después de "years" años /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="oldTree"></param> /// <param name="newTree"></param> public override void Grow(double years, Parcela plot, PieMayor oldTree, PieMayor newTree) { double DBHG5 = Math.Exp(0.2030 * Math.Log(oldTree.DAP.Value * 10) + 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 * Math.Pow(oldTree.BAL.Value, 2) / Math.Log(oldTree.DAP.Value * 10)); newTree.DAP += DBHG5 / 10; /// HTG5=(1/100)*Exp(0.21603+0.40329*Log(DBHG5*10/2)-1.12721*Log(DBH*10) +1.18099*Log(HT*100) +3.01622*CR) double HTG5 = Math.Exp(0.21603 + 0.40329 * Math.Log(DBHG5 / 2) - 1.12721 * Math.Log(oldTree.DAP.Value * 10) + 1.18099 * Math.Log(oldTree.ALTURA.Value * 100) + 3.01622 * oldTree.CR.Value); newTree.ALTURA += HTG5 / 100; /// formula de la tesis--corregido error en base de datos newTree.ALTURA+=(Math.Exp(4.1375+0.3762*Math.Log(DBHG5*10/2)-0.5260*Math.Log(oldTree.DAP.Value*10)+0.1727*Math.Log(oldTree.ALTURA.Value*100)+2.6468* oldTree.CR.Value))/100; }
/// <summary> /// Procedimiento que permite modificar las propiedades del árbol durante su crecimiento después de "years" años /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="oldTree"></param> /// <param name="newTree"></param> public override void Grow(double years, Parcela plot, PieMayor oldTree, PieMayor newTree) { double STR = 0; // su valor debe ser 1 cuando la masa esta en el estrato 1 double DBHG5 = Math.Exp(0.8351 + 0.1273 * Math.Log(oldTree.DAP.Value) - 0.00006 * Math.Pow(oldTree.DAP.Value, 2) - 0.01216 * oldTree.BAL.Value - 0.00016 * plot.N_PIESHA.Value - 0.03386 * plot.H_DOMINANTE.Value + 0.04917 * plot.SI.Value - 0.1991 * STR); newTree.DAP += (DBHG5 - 1); // calculo de la altura en el estado 2 /// newTree.ALTURA+=HTG5/100; }
/// <summary> /// Procedimiento que realiza los cálculos sobre un árbol. /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> public override void ProcessTree(double years, Parcela plot, PieMayor tree) { // ecuacion Martinez Millán et al 1993 double ParA = 0.056395; double ParB = 1.94631; double ParC = 0.92797; tree.VCC = (ParA * Math.Pow(tree.DAP.Value, ParB) * Math.Pow(tree.ALTURA.Value, ParC)) / 1000; // currentTree = null; }
/// <summary> /// Procedimiento que realiza los cálculos sobre un árbol. /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> public override void ProcessTree(double years, Parcela plot, PieMayor tree) { double exp = 1 / 0.9718; double DIB = Math.Pow((1 / 1.3285), exp) * Math.Pow(tree.DAP.Value * 10, exp); currentTree = tree; tree.VCC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_conCorteza); //Integración --> d_conCorteza sobre HR en los limites 0 -> 1 tree.VSC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_sinCorteza); //Integración --> d_sinCorteza sobre HR en los limites 0 -> 1 currentTree = null; }
/// <summary> /// Procedimiento que permite la inicialización de variables de árbol necesarias para la ejecución del modelo /// </summary> /// <param name="plot"></param> /// <param name="tree"></param> public override void InitializeTree(Parcela plot, PieMayor tree) { if (!tree.ESTADO.HasValue || String.IsNullOrEmpty(tree.ESTADO.ToString())) { tree.BAL = 0; foreach (PieMayor pm in tree.Parcela.PiesMayores) { if (!pm.ESTADO.HasValue || String.IsNullOrEmpty(pm.ESTADO.ToString())) { if (pm.DAP > tree.DAP) { tree.BAL += pm.SEC_NORMAL.Value * pm.EXPAN.Value / 10000; } } } } if (!tree.ALTURA.HasValue) { tree.ALTURA = 1.3 + (3.099 - 0.00203 * plot.A_BASIMETRICA.Value + 1.02491 * plot.H_DOMINANTE.Value * Math.Exp(-8.5052 / tree.DAP.Value)); } // if (!tree.ALTURA_MAC.HasValue) // { // tree.ALTURA_MAC = tree.ALTURA.Value / (1 + Math.Exp((double)(-0.0012*tree.ALTURA.Value*10-0.0102*tree.BAL.Value-0.0168*plot.A_BASIMETRICA.Value ))); // } // if (!tree.ALTURA_BC.HasValue) // { // tree.ALTURA_BC = tree.ALTURA_MAC.Value / (1+Math.Exp((double)(1.2425*(plot.A_BASIMETRICA.Value/(tree.ALTURA.Value*10)) + 0.0047*(plot.A_BASIMETRICA.Value) - 0.5725*Math.Log(plot.A_BASIMETRICA.Value)-0.0082*tree.BAL.Value))); // } // tree.CR=1-tree.ALTURA_BC.Value/tree.ALTURA.Value; // if (!tree.LCW.HasValue) // { // tree.LCW=(1/10.0F)*(0.2518*tree.DAP.Value*10)*Math.Pow(tree.CR.Value,(0.2386+0.0046*(tree.ALTURA.Value-tree.ALTURA_BC.Value)*10)); // } tree.VCC = 0.000051 * Math.Pow(tree.DAP.Value, 1.86781) * Math.Pow(tree.ALTURA.Value, 0.989625); /// almacenamiento de variables de biomasa (eq. para Q. pyrenaica, Ruiz-Peinado et al 2011) if (tree.ESPECIE == 43) { /// Stem + Thick branches: Ws + Wb7 = 0.0261 · d2 · h tree.VAR_5 = 0.0261 * Math.Pow(tree.DAP.Value, 2) * tree.ALTURA.Value; /// Medium branches: Wb2–7 = –0.0260 · d2 + 0.536 · h + 0.00538 · d2 · h tree.VAR_2 = -0.0260 * Math.Pow(tree.DAP.Value, 2) + 0.536 * tree.ALTURA.Value + 0.00538 * Math.Pow(tree.DAP.Value, 2) * tree.ALTURA.Value; /// Thin branches: Wb2 = 0.898 · d – 0.445 · h tree.VAR_3 = 0.898 * tree.DAP.Value - 0.445 * tree.ALTURA.Value; /// Roots: Wr = 0.143 · d2 tree.VAR_4 = 0.143 * Math.Pow(tree.DAP.Value, 2); } }
/// <summary> /// Procedimiento que permite la inicialización de variables de parcelas necesarias para la ejecución del modelo /// Solo se ejecuta en el primer nodo. /// Variables que deben permanecer constantes como el índice de sitio deben calcularse sólo en este apartado del modelo /// </summary> /// <param name="plot"></param> public override void CalculateInitialInventory(Parcela plot) { IList <PieMayor> piesOrdenados = base.Sort(plot.PiesMayores, new PieMayorSortingCriteria.DescendingByField("DAP")); double bal = 0; double old_sec_normal = 100000; double old_bal = 0; //double sec_normal = tree.SEC_NORMAL; ///índice de sitio basado en la ecuación Ho-t para Pinus halepensis en el Valle del Ebro (GADA) (Rojo etal. 2017), edad de referencia 60 años plot.SI = MyFunc.Ecuacion_rojo_alboreca(plot.H_DOMINANTE.Value, plot.EDAD.Value, 60); foreach (PieMayor tree in piesOrdenados) { if (old_sec_normal > tree.SEC_NORMAL) { tree.BAL = bal; old_bal = bal; } else { tree.BAL = old_bal; } bal += tree.SEC_NORMAL.Value * tree.EXPAN.Value / 10000; old_sec_normal = tree.SEC_NORMAL.Value; if (!tree.ALTURA.HasValue) { tree.ALTURA = MyFunc.alturaDiametroGeneralizada(plot.H_DOMINANTE.Value, tree.DAP.Value, plot.D_DOMINANTE.Value);///altura-diámetro generalizada. Alturas en m y diámetros en cm ======= } if (!tree.ALTURA_BC.HasValue) { tree.ALTURA_BC = MyFunc.alturaInicioCopa(tree.ALTURA.Value, plot.I_HART.Value / 100, plot.SI.Value, (tree.BAL.Value / plot.A_BASIMETRICA.Value));///altura de la base de la copa (altura de inicio de copa viva). Alturas en m y diámetros en cm } tree.LCW = MyFunc.diametroCopa(tree.DAP.Value, tree.ALTURA.Value);///diámetro de copa (m) currentTree = tree; tree.VCC = Math.PI * 0.0001 * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_conCorteza); //Integración --> r2_conCorteza sobre HR en los limites 0 -> 1 // VCC en m³ currentTree = null; } }
/// <summary> /// Procedimiento que permite la inicialización de variables de parcelas necesarias para la ejecución del modelo /// Solo se ejecuta en el primer nodo. /// Variables que deben permanecer constantes como el índice de sitio deben calcularse solo en este apartado del modelo /// </summary> /// <param name="plot"></param> public override void CalculateInitialInventory(Parcela plot) { IList <PieMayor> piesOrdenados = base.Sort(plot.PiesMayores, new PieMayorSortingCriteria.DescendingByField("DAP")); double bal = 0; double old_sec_normal = 100000; double old_bal = 0; //double sec_normal = tree.SEC_NORMAL; foreach (PieMayor tree in piesOrdenados) { if (old_sec_normal > tree.SEC_NORMAL) { tree.BAL = bal; old_bal = bal; } else { tree.BAL = old_bal; } bal += tree.SEC_NORMAL.Value * tree.EXPAN.Value / 10000; old_sec_normal = tree.SEC_NORMAL.Value; if (!tree.ALTURA.HasValue || tree.ALTURA.Value == 0) { 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.0; } if (!tree.ALTURA_MAC.HasValue || tree.ALTURA_MAC.Value == 0) { tree.ALTURA_MAC = 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.Value == 0) { tree.ALTURA_BC = tree.ALTURA_MAC.Value / (1 + Math.Exp((double)(0.0078 * plot.A_BASIMETRICA - 0.5488 * Math.Log(plot.A_BASIMETRICA.Value) - 0.0085 * tree.BAL))); } tree.CR = 1 - tree.ALTURA_BC.Value / tree.ALTURA.Value; if (!tree.LCW.HasValue) { tree.LCW = (1 / 10.0F) * (0.1826 * tree.DAP.Value * 10) * Math.Pow(tree.CR.Value, (0.1594 + 0.0014 * (tree.ALTURA.Value - tree.ALTURA_BC.Value) * 10)); } // tree.VAR_1 = tree.COORD_X;//añadido para tener coordenadas // tree.VAR_2 = tree.COORD_Y;//añadido para tener coordenadas currentTree = tree; tree.VCC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_conCorteza); //Integración --> r2_conCorteza sobre HR en los limites 0 -> 1 tree.VSC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_sinCorteza); //Integración --> r2_sinCorteza sobre HR en los limites 0 -> 1 currentTree = null; } plot.SI = Math.Exp(4.016 + (Math.Log(plot.H_DOMINANTE.Value) - 4.016) * Math.Pow(80 / plot.EDAD.Value, -0.5031) ); }
/// <summary> /// Procedimiento que realiza los cálculos sobre un árbol. /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> public override void ProcessTree(double years, Parcela plot, PieMayor tree) { tree.ALTURA = 1.3 + (3.099 - 0.00203 * plot.A_BASIMETRICA.Value + 1.02491 * plot.H_DOMINANTE.Value * Math.Exp(-8.5052 / tree.DAP.Value)); //double DIB = Math.Pow((1/1.3285),exp)*Math.Pow(tree.DAP.Value*10,exp); tree.VCC = 0.000051 * Math.Pow(tree.DAP.Value, 1.86781) * Math.Pow(tree.ALTURA.Value, 0.989625); /// almacenamiento de variables de biomasa (eq. para Q. pyrenaica, Ruiz-Peinado et al 2011) if (tree.ESPECIE == 43) { /// Stem + Thick branches: Ws + Wb7 = 0.0261 · d2 · h tree.VAR_5 = 0.0261 * Math.Pow(tree.DAP.Value, 2) * tree.ALTURA.Value; /// Medium branches: Wb2–7 = –0.0260 · d2 + 0.536 · h + 0.00538 · d2 · h tree.VAR_2 = -0.0260 * Math.Pow(tree.DAP.Value, 2) + 0.536 * tree.ALTURA.Value + 0.00538 * Math.Pow(tree.DAP.Value, 2) * tree.ALTURA.Value; /// Thin branches: Wb2 = 0.898 · d – 0.445 · h tree.VAR_3 = 0.898 * tree.DAP.Value - 0.445 * tree.ALTURA.Value; /// Roots: Wr = 0.143 · d2 tree.VAR_4 = 0.143 * Math.Pow(tree.DAP.Value, 2); } }
/// <summary> /// Función que indica si el árbol sobrevive o no después de "years" años /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> /// <returns>Devuelve el porcentaje de árboles que sobreviven</returns> public override double Survives(double years, Parcela plot, PieMayor tree) { /// se calcula la desviacion estandar double sumOfDerivation = 0; double sumOfTrees = 0; double DMedioCuadrado = plot.D_MEDIO.Value * plot.D_MEDIO.Value; foreach (PieMayor pm in plot.PiesMayores) { sumOfDerivation += ((pm.DAP.Value) * (pm.DAP.Value) * (pm.EXPAN.Value)); sumOfTrees += pm.EXPAN.Value; } double sumOfDerivationAverage = sumOfDerivation / sumOfTrees; double StandardDeviation = Math.Sqrt(sumOfDerivationAverage - DMedioCuadrado); /// calculamos el coeficiente de variación -cvDAP- como el cociente entre la desviacion estandar y la media double cvDAP = (StandardDeviation / plot.D_MEDIO.Value); return(1 / (1 + Math.Exp(-6.8548 + (9.792 / tree.DAP.Value) + 0.121 * tree.BAL.Value * cvDAP + 0.037 * plot.SI.Value))); /// return 1; }
/// <summary> /// Procedimiento que permite la inicialización de variables de árbol necesarias para la ejecución del modelo /// </summary> /// <param name="plot"></param> /// <param name="tree"></param> public override void InitializeTree(Parcela plot, PieMayor tree) { if (!tree.ESTADO.HasValue || String.IsNullOrEmpty(tree.ESTADO.ToString())) { tree.BAL = 0; foreach (PieMayor pm in tree.Parcela.PiesMayores) { if (!pm.ESTADO.HasValue || String.IsNullOrEmpty(pm.ESTADO.ToString())) { if (pm.DAP > tree.DAP) { tree.BAL += pm.SEC_NORMAL.Value * pm.EXPAN.Value / 10000; } } } } if (!tree.ALTURA.HasValue) { tree.ALTURA = (13 + (27.0392 + 1.4853 * plot.H_DOMINANTE.Value * 10 - 0.1437 * plot.D_CUADRATICO.Value * 10) * Math.Exp(-8.0048 / Math.Sqrt(tree.DAP.Value * 10))) / 10; } if (!tree.ALTURA_MAC.HasValue) { tree.ALTURA_MAC = tree.ALTURA.Value / (1 + Math.Exp((double)(-0.0012 * tree.ALTURA.Value * 10 - 0.0102 * tree.BAL.Value - 0.0168 * plot.A_BASIMETRICA.Value))); } if (!tree.ALTURA_BC.HasValue) { tree.ALTURA_BC = tree.ALTURA_MAC.Value / (1 + Math.Exp((double)(1.2425 * (plot.A_BASIMETRICA.Value / tree.ALTURA.Value * 10) + 0.0047 * (plot.A_BASIMETRICA.Value) - 0.5725 * Math.Log(plot.A_BASIMETRICA.Value) - 0.0082 * tree.BAL.Value))); } tree.CR = (1 - tree.ALTURA_BC / tree.ALTURA); if (!tree.LCW.HasValue) { tree.LCW = (0.2518 * tree.DAP.Value) * Math.Pow(tree.CR.Value, (0.2386 + 0.0046 * (tree.ALTURA.Value - tree.ALTURA_BC.Value))); } currentTree = tree; tree.VCC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_conCorteza); //Integración --> r2_conCorteza sobre HR en los limites 0 -> 1 tree.VSC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_sinCorteza); //Integración --> d_sinCorteza sobre HR en los limites 0 -> 1 currentTree = null; }
/// <summary> /// Procedimiento que permite modificar las propiedades del árbol durante su crecimiento después de "years" años /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="oldTree"></param> /// <param name="newTree"></param> public override void Grow(double years, Parcela plot, PieMayor oldTree, PieMayor newTree) { // ecuacion Calama y Montero 2005 // Andalucia, Meseta central y Sistema Central(cat es 0) double DBHG5 = Math.Exp(2.2451 - 0.2615 * oldTree.DAP.Value - 0.0369 * oldTree.ALTURA.Value - 0.1368 * Math.Log(plot.N_PIESHA.Value) + 0.0448 * plot.SI.Value + 0.1984 * oldTree.DAP.Value / plot.D_CUADRATICO.Value) + 1; newTree.DAP = oldTree.DAP + DBHG5; double parA = 4.1437; double parB = -0.3935; double H_DOMINANTE_new = Math.Exp((double)parA + Math.Log(plot.H_DOMINANTE.Value) - parA / Math.Pow((100 / plot.EDAD.Value), parB)); // calculo de rango de diametros entre los percentiles 10 y 90 double P1090 = 10; double ALTURA_old = 1.3 + Math.Exp((double)(1.7306 + 0.0882 * plot.H_DOMINANTE.Value - 0.0062 * P1090 - 0.0936) + (-25.2776 + 1.6999 * Math.Log(plot.N_PIESHA.Value) + 4.743) / (oldTree.DAP.Value + 1)); double ALTURA_new = 1.3 + Math.Exp((double)(1.7306 + 0.0882 * H_DOMINANTE_new - 0.0062 * P1090 - 0.0936) + (-25.2776 + 1.6999 * Math.Log(plot.N_PIESHA.Value) + 4.743) / (newTree.DAP.Value + 1)); newTree.ALTURA = oldTree.ALTURA * ALTURA_new / ALTURA_old; }
/// <summary> /// Procedimiento que permite modificar las propiedades del árbol durante su crecimiento después de "years" años /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="oldTree"></param> /// <param name="newTree"></param> public override void Grow(double years, Parcela plot, PieMayor oldTree, PieMayor newTree) { // Para Cataluña (cat es 1) double DBHG5 = Math.Exp(2.2451 - 0.2615 * oldTree.DAP.Value - 0.0369 * oldTree.ALTURA.Value - 0.1368 * Math.Log(plot.N_PIESHA.Value) + 0.0448 * plot.SI.Value + 0.1984 * oldTree.DAP.Value / plot.D_CUADRATICO.Value - 0.5542 + 0.0277 * plot.SI.Value) + 1; newTree.DAP = oldTree.DAP + DBHG5; newTree.EDAD_BASE = Convert.ToInt32(years + oldTree.EDAD_BASE.Value); double parA = 4.1437; double parB = -0.3935; double logSI = Math.Log(plot.SI.Value); double potEDAD = Math.Pow(100 / (years + plot.EDAD.Value), parB); newTree.VAR_8 = plot.EDAD.Value; newTree.VAR_6 = logSI; newTree.VAR_5 = potEDAD; double H_DOMINANTE_new = Math.Exp(parA + (logSI - parA) / potEDAD); plot.VAR_7 = H_DOMINANTE_new; newTree.VAR_7 = H_DOMINANTE_new; // calculo de rango de diametros entre los percentiles 10 y 90 double P1090 = plot.VAR_10.Value - plot.VAR_9.Value; double ALTURA_old = 1.3 + Math.Exp(1.7306 + 0.0882 * plot.H_DOMINANTE.Value - 0.0062 * P1090 - 0.0936 + (-25.2776 + 1.6999 * Math.Log(plot.N_PIESHA.Value) + 4.743) / (oldTree.DAP.Value + 1)); newTree.VAR_9 = ALTURA_old; double ALTURA_new = 1.3 + Math.Exp(1.7306 + 0.0882 * H_DOMINANTE_new - 0.0062 * P1090 - 0.0936 + (-25.2776 + 1.6999 * Math.Log(plot.N_PIESHA.Value) + 4.743) / (newTree.DAP.Value + 1)); newTree.VAR_10 = ALTURA_new; newTree.ALTURA = oldTree.ALTURA * ALTURA_new / ALTURA_old; }
/// <summary> /// Procedimiento que permite la inicialización de variables de parcelas necesarias para la ejecución del modelo /// Solo se ejecuta en el primer nodo. /// Variables que deben permanecer constantes como el índice de sitio deben calcularse solo en este apartado del modelo /// </summary> /// <param name="plot"></param> public override void CalculateInitialInventory(Parcela plot) { foreach (PieMayor tree in plot.PiesMayores) { tree.BAL = 0; foreach (PieMayor pm in tree.Parcela.PiesMayores) { if (pm.DAP > tree.DAP) { tree.BAL += pm.SEC_NORMAL.Value * pm.EXPAN.Value / 10000; } } if (!tree.ALTURA.HasValue) { tree.ALTURA = (13 + (27.0392 + 1.4853 * plot.H_DOMINANTE.Value * 10 - 0.1437 * plot.D_CUADRATICO.Value * 10) * Math.Exp(-8.0048 / Math.Sqrt(tree.DAP.Value * 10))) / 10; } if (!tree.ALTURA_MAC.HasValue) { tree.ALTURA_MAC = tree.ALTURA.Value / (1 + Math.Exp((double)(-0.0012 * tree.ALTURA.Value * 10 - 0.0102 * tree.BAL.Value - 0.0168 * plot.A_BASIMETRICA.Value))); } if (!tree.ALTURA_BC.HasValue) { tree.ALTURA_BC = tree.ALTURA_MAC.Value / (1 + Math.Exp((double)(1.2425 * (plot.A_BASIMETRICA.Value / tree.ALTURA.Value * 10) + 0.0047 * (plot.A_BASIMETRICA.Value) - 0.5725 * Math.Log(plot.A_BASIMETRICA.Value) - 0.0082 * tree.BAL.Value))); } tree.CR = (1 - tree.ALTURA_BC / tree.ALTURA); if (!tree.LCW.HasValue) { tree.LCW = (0.2518 * tree.DAP.Value) * Math.Pow(tree.CR.Value, (0.2386 + 0.0046 * (tree.ALTURA.Value - tree.ALTURA_BC.Value))); } currentTree = tree; tree.VCC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_conCorteza); //Integración --> d_conCorteza sobre HR en los limites 0 -> 1 tree.VSC = Math.PI * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_sinCorteza); //Integración --> d_sinCorteza sobre HR en los limites 0 -> 1 currentTree = null; } plot.SI = (plot.H_DOMINANTE.Value * 0.8534446) / Math.Pow((1 - Math.Exp((double)(-0.270 * plot.EDAD.Value / 10))), 2.2779); }
/// <summary> /// Procedimiento que realiza los cálculos sobre un árbol. /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> public override void ProcessTree(double years, Parcela plot, PieMayor tree) { }
/// <summary> /// Función que indica si el árbol sobrevive o no después de "years" años /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> /// <returns>Devuelve el porcentaje de árboles que sobreviven</returns> public override double Survives(double years, Parcela plot, PieMayor tree) { return(1); }
/// <summary> /// Procedimiento que permite la inicialización de variables de árbol necesarias para la ejecución del modelo /// </summary> /// <param name="plot"></param> /// <param name="tree"></param> public override void InitializeTree(Parcela plot, PieMayor tree) { }
/// <summary> /// Procedimiento que permite modificar las propiedades del árbol durante su crecimiento después de "years" años (LAPSOS DE 5 AÑOS) /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="oldTree"></param> /// <param name="newTree"></param> public override void Grow(double years, Parcela plot, PieMayor oldTree, PieMayor newTree) { double id10 = MyFunc.incrementoDiametroConCortezaen10(oldTree.DAP.Value, plot.A_BASIMETRICA.Value, plot.SI.Value, oldTree.BAL.Value / plot.A_BASIMETRICA.Value); newTree.DAP = oldTree.DAP + id10 * (years / 10);///el factor years/10 es para interpolar a "years" años, ya que el modelo de incremento diametral se construyó para un lapso de 10 años }
/// <summary> /// Función que indica si el árbol sobrevive o no después de "years" años /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> /// <returns>Devuelve el porcentaje de árboles que sobreviven</returns> public override double Survives(double years, Parcela plot, PieMayor tree) { double p_mort = 1 / (1 + Math.Exp(1.3286 - 9.791 / tree.DAP.Value + 3.5383 * tree.ALTURA.Value / plot.H_DOMINANTE.Value)); return(1 - p_mort); }
/// <summary> /// Procedimiento que realiza los cálculos sobre un árbol. /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="tree"></param> public override void ProcessTree(double years, Parcela plot, PieMayor tree) { ///currentTree = tree; ///tree.VCC = Math.PI * 0.0001 * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_conCorteza); ///currentTree = null; }
/// <summary> /// Procedimiento que realiza los cálculos sobre una parcela. /// </summary> /// <param name="years"></param> /// <param name="plot"></param> /// <param name="trees"></param> public override void ProcessPlot(double years, Parcela plot, PieMayor[] trees) { ///recalcula la Ho para la nueva edad basándose en el índice de sitio if (plot.VAR_5.HasValue == false) { plot.VAR_5 = plot.EDAD.Value; } plot.VAR_5 += years; plot.H_DOMINANTE = MyFunc.Ecuacion_rojo_alboreca(plot.SI.Value, 60, plot.VAR_5.Value); ///recalcula IH plot.I_HART = 10000 / (plot.H_DOMINANTE.Value * Math.Sqrt(plot.N_PIESHA.Value)); IList <PieMayor> piesOrdenados = base.Sort(plot.PiesMayores, new PieMayorSortingCriteria.DescendingByField("DAP")); double bal = 0; double old_sec_normal = 100000; double old_bal = 0; foreach (PieMayor tree in piesOrdenados) { if (!tree.ESTADO.HasValue || String.IsNullOrEmpty(tree.ESTADO.ToString())) { if (old_sec_normal > tree.SEC_NORMAL) { tree.BAL = bal; old_bal = bal; } else { tree.BAL = old_bal; } bal += tree.SEC_NORMAL.Value * tree.EXPAN.Value / 10000; old_sec_normal = tree.SEC_NORMAL.Value; tree.ALTURA = MyFunc.alturaDiametroGeneralizada(plot.H_DOMINANTE.Value, tree.DAP.Value, plot.D_DOMINANTE.Value); tree.ALTURA_BC = MyFunc.alturaInicioCopa(tree.ALTURA.Value, plot.I_HART.Value / 100, plot.SI.Value, (tree.BAL.Value / plot.A_BASIMETRICA.Value)); tree.LCW = MyFunc.diametroCopa(tree.DAP.Value, tree.ALTURA.Value); } else { tree.BAL = 0; tree.CR = 0; tree.LCW = 0; tree.ALTURA_MAC = 0; tree.ALTURA_BC = 0; } } ///recalcula correctamente la altura media, diámetros de copa medios, FCC y VCC por hectárea double exp_temp = 0; double h_exp_temp = 0; double dcopa_exp_temp = 0; double dcopa2_exp_temp = 0; double vcc_exp_temp = 0; foreach (PieMayor tree in piesOrdenados) { if (!tree.ESTADO.HasValue || String.IsNullOrEmpty(tree.ESTADO.ToString())) { exp_temp = exp_temp + (tree.EXPAN.Value); h_exp_temp = h_exp_temp + (tree.ALTURA.Value * tree.EXPAN.Value); dcopa_exp_temp = dcopa_exp_temp + (tree.LCW.Value * tree.EXPAN.Value); dcopa2_exp_temp = dcopa2_exp_temp + (Math.Pow(tree.LCW.Value, 2) * tree.EXPAN.Value); currentTree = tree; tree.VCC = Math.PI * 0.0001 * tree.ALTURA.Value * IntegralBySimpson(0, 1, 0.01, r2_conCorteza); ///recalcula el vcc de cada árbol con la altura correcta currentTree = null; vcc_exp_temp = vcc_exp_temp + (tree.VCC.Value * tree.EXPAN.Value); } } ///double h_media_new = h_exp_temp / exp_temp; plot.H_MEDIA = h_exp_temp / exp_temp; plot.DM_COPA = dcopa_exp_temp / exp_temp; plot.DG_COPA = Math.Sqrt(dcopa2_exp_temp / exp_temp); plot.VCC = vcc_exp_temp; plot.FCC = 0.25 * Math.PI * dcopa2_exp_temp / 10000; }