/// <summary> /// Reads type-specific residue constants from ini-file and places them in c. constants; /// </summary> /// <param name="surfom_type">The surfom_type.</param> /// <param name="i">The i.</param> /// <param name="pot_decomp_rate">The pot_decomp_rate.</param> private void ReadTypeSpecificConstants(string surfom_type, int i, out double pot_decomp_rate) { ResidueType thistype = ResidueTypes.GetResidueType(surfom_type); if (thistype == null) { throw new ApsimXException(this, "Cannot find residue type description for '" + surfom_type + "'"); } C_fract[i] = MathUtilities.Bound(thistype.fraction_C, 0.0, 1.0); po4ppm[i] = MathUtilities.Bound(thistype.po4ppm, 0.0, 1000.0); nh4ppm[i] = MathUtilities.Bound(thistype.nh4ppm, 0.0, 2000.0); no3ppm[i] = MathUtilities.Bound(thistype.no3ppm, 0.0, 1000.0); specific_area[i] = MathUtilities.Bound(thistype.specific_area, 0.0, 0.01); cf_contrib[i] = Math.Max(Math.Min(thistype.cf_contrib, 1), 0); pot_decomp_rate = MathUtilities.Bound(thistype.pot_decomp_rate, 0.0, 1.0); if (thistype.fr_c.Length != thistype.fr_n.Length || thistype.fr_n.Length != thistype.fr_p.Length) { throw new ApsimXException(this, "Error reading in fr_c/n/p values, inconsistent array lengths"); } for (int j = 0; j < thistype.fr_c.Length; j++) { frPoolC[j, i] = thistype.fr_c[j]; frPoolN[j, i] = thistype.fr_n[j]; frPoolP[j, i] = thistype.fr_p[j]; } }
/// <summary>Looks at a residue type and copies properties from the base type if one was specified.</summary> /// <param name="residueType">The residue to examine and change</param> private ResidueType FillDerived(ResidueType residueType) { ResidueType baseType = null; if (residueType.derived_from != null) { baseType = ResidueType.Find(type => StringUtilities.StringsAreEqual(type.fom_type, residueType.derived_from)); if (baseType != null) { baseType = FillDerived(baseType); // Make sure the base residue type has itself been filled } } if (baseType != null) { residueType = (ResidueType)ReflectionUtilities.Clone(residueType); if (residueType.fraction_C == 0) { residueType.fraction_C = baseType.fraction_C; } if (residueType.po4ppm == 0) { residueType.po4ppm = baseType.po4ppm; } if (residueType.nh4ppm == 0) { residueType.nh4ppm = baseType.nh4ppm; } if (residueType.no3ppm == 0) { residueType.no3ppm = baseType.no3ppm; } if (residueType.specific_area == 0) { residueType.specific_area = baseType.specific_area; } if (residueType.pot_decomp_rate == 0) { residueType.pot_decomp_rate = baseType.pot_decomp_rate; } if (residueType.cf_contrib == 0) { residueType.cf_contrib = baseType.cf_contrib; } if (residueType.fr_c == null) { residueType.fr_c = (double[])baseType.fr_c.Clone(); } if (residueType.fr_n == null) { residueType.fr_n = (double[])baseType.fr_n.Clone(); } if (residueType.fr_p == null) { residueType.fr_p = (double[])baseType.fr_p.Clone(); } } return(residueType); }
/// <summary>Gets a specific residue type. Throws if not found.</summary> /// <param name="name">The name of the residue type to find</param> public ResidueType GetResidueType(string name) { if (ResidueType != null) { ResidueType residueType = ResidueType.Find(type => StringUtilities.StringsAreEqual(type.fom_type, name)); if (residueType != null) { return(FillDerived(residueType)); } } throw new Exception($"Could not find residue type '{name}'"); }
/// <summary>Gets a specific residue type. Throws if not found.</summary> /// <param name="name">The name of the residue type to find</param> public ResidueType GetResidueType(string name) { if (Types != null) { ResidueType residueType = Types.Find(type => StringUtilities.StringsAreEqual(type.fom_type, name)); if (residueType != null) { FillDerived(residueType); return(residueType); } } throw new Exception("Could not find residue type " + name); }