Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sour-kings-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@svenvw/fdm-calculator": patch
---

Fix calculation of crop residue biomass at nitrogen balance calculation
8 changes: 6 additions & 2 deletions fdm-calculator/src/balance/nitrogen/removal/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ describe("calculateNitrogenRemoval", () => {
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
m_cropresidue: true,
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
},
]
const harvests: FieldInput["harvests"] = [
Expand Down Expand Up @@ -45,9 +47,9 @@ describe("calculateNitrogenRemoval", () => {
cultivationDetailsMap,
)

expect(result.total.toNumber()).toBeCloseTo(-21.2) // -20 from harvest + -1.2 from residue
expect(result.total.toNumber()).toBeCloseTo(-23) // -20 from harvest + -3 from residue
expect(result.harvests.total.toNumber()).toBeCloseTo(-20)
expect(result.residues.total.toNumber()).toBeCloseTo(-1.2)
expect(result.residues.total.toNumber()).toBeCloseTo(-3)
})

it("should handle cases with no harvests or residues", () => {
Expand All @@ -56,6 +58,8 @@ describe("calculateNitrogenRemoval", () => {
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
m_cropresidue: false,
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
},
]
const harvests: FieldInput["harvests"] = []
Expand Down
37 changes: 22 additions & 15 deletions fdm-calculator/src/balance/nitrogen/removal/residue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ describe("calculateNitrogenRemovalByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
// b_lu_start: new Date(),
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: false, // No residue left
},
]
Expand All @@ -47,7 +48,8 @@ describe("calculateNitrogenRemovalByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
// b_lu_start: new Date(),
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: true,
},
]
Expand All @@ -74,16 +76,17 @@ describe("calculateNitrogenRemovalByResidue", () => {
cultivationDetailsMap,
)

expect(result.total.toNumber()).toBeCloseTo(-1.2) //Approximation due to floating point
expect(result.cultivations[0].value.toNumber()).toBeCloseTo(-1.2) //Approximation due to floating point
expect(result.total.toNumber()).toBeCloseTo(-3) //Approximation due to floating point
expect(result.cultivations[0].value.toNumber()).toBeCloseTo(-3) //Approximation due to floating point
})

it("should calculate nitrogen removal for multiple harvests, averaging yields", () => {
const cultivations: FieldInput["cultivations"] = [
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
// b_lu_start: new Date(),
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: true,
},
]
Expand All @@ -108,16 +111,17 @@ describe("calculateNitrogenRemovalByResidue", () => {
cultivationDetailsMap,
)

expect(result.total.toNumber()).toBeCloseTo(-1.2) //Approximation due to floating point
expect(result.cultivations[0].value.toNumber()).toBeCloseTo(-1.2) //Approximation due to floating point
expect(result.total.toNumber()).toBeCloseTo(-3) //Approximation due to floating point
expect(result.cultivations[0].value.toNumber()).toBeCloseTo(-3) //Approximation due to floating point
})

it("should handle missing harvest data using cultivation defaults", () => {
const cultivations: FieldInput["cultivations"] = [
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
// b_lu_start: new Date(),
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: true,
},
]
Expand All @@ -129,16 +133,17 @@ describe("calculateNitrogenRemovalByResidue", () => {
cultivationDetailsMap,
)

expect(result.total.toNumber()).toBeCloseTo(-1.2) //Approximation due to floating point
expect(result.cultivations[0].value.toNumber()).toBeCloseTo(-1.2) //Approximation due to floating point
expect(result.total.toNumber()).toBeCloseTo(-3) //Approximation due to floating point
expect(result.cultivations[0].value.toNumber()).toBeCloseTo(-3) //Approximation due to floating point
})

it("should handle missing cultivation details and throw an error", () => {
const cultivations: FieldInput["cultivations"] = [
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
// b_lu_start: new Date(),
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: true,
},
]
Expand All @@ -161,7 +166,8 @@ describe("calculateNitrogenRemovalByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
// b_lu_start: new Date(),
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: undefined, // Undefined residue handling
},
]
Expand All @@ -184,7 +190,8 @@ describe("calculateNitrogenRemovalByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
// b_lu_start: new Date(),
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: true,
},
]
Expand All @@ -206,7 +213,7 @@ describe("calculateNitrogenRemovalByResidue", () => {
cultivationDetailsMap,
)

expect(result.total.toNumber()).toBeCloseTo(-1.2) //Approximation due to floating point
expect(result.cultivations[0].value.toNumber()).toBeCloseTo(-1.2) //Approximation due to floating point
expect(result.total.toNumber()).toBeCloseTo(-3) //Approximation due to floating point
expect(result.cultivations[0].value.toNumber()).toBeCloseTo(-3) //Approximation due to floating point
})
})
1 change: 1 addition & 0 deletions fdm-calculator/src/balance/nitrogen/removal/residue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export function calculateNitrogenRemovalByResidue(

// Calculate the amount of Nitrogen removed by crop residues of this cultivation
const removal = b_lu_yield
.dividedBy(b_lu_hi)
.times(b_lu_hi_res)
.times(b_lu_n_residue)
.dividedBy(new Decimal(1000)) // Convert from g N / ha to kg N / ha
Expand Down
18 changes: 15 additions & 3 deletions fdm-calculator/src/balance/nitrogen/volatization/residues.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ describe("calculateNitrogenVolatizationViaAmmoniaByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: true,
},
]
Expand All @@ -50,7 +52,7 @@ describe("calculateNitrogenVolatizationViaAmmoniaByResidue", () => {
)

//Check for approximation due to floating point
expect(result.total.toNumber()).toBeCloseTo(-2.688, 2)
expect(result.total.toNumber()).toBeCloseTo(-6.72, 2)
expect(result.cultivations).toEqual([
{ id: "cultivation1", value: expect.any(Decimal) },
])
Expand All @@ -61,6 +63,8 @@ describe("calculateNitrogenVolatizationViaAmmoniaByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: true,
},
]
Expand Down Expand Up @@ -102,7 +106,7 @@ describe("calculateNitrogenVolatizationViaAmmoniaByResidue", () => {
)

//Check for approximation due to floating point
expect(result.total.toNumber()).toBeCloseTo(-2.688, 2)
expect(result.total.toNumber()).toBeCloseTo(-6.72, 2)
expect(result.cultivations).toEqual([
{ id: "cultivation1", value: expect.any(Decimal) },
])
Expand All @@ -113,6 +117,8 @@ describe("calculateNitrogenVolatizationViaAmmoniaByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: true,
},
]
Expand All @@ -135,6 +141,8 @@ describe("calculateNitrogenVolatizationViaAmmoniaByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: false,
},
]
Expand Down Expand Up @@ -170,6 +178,8 @@ describe("calculateNitrogenVolatizationViaAmmoniaByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: undefined, // Undefined residue handling
},
]
Expand Down Expand Up @@ -206,6 +216,8 @@ describe("calculateNitrogenVolatizationViaAmmoniaByResidue", () => {
{
b_lu: "cultivation1",
b_lu_catalogue: "catalogue1",
b_lu_start: new Date("2022-01-01"),
b_lu_end: new Date("2022-12-31"),
m_cropresidue: true,
},
]
Expand Down Expand Up @@ -241,7 +253,7 @@ describe("calculateNitrogenVolatizationViaAmmoniaByResidue", () => {
cultivationDetailsMap,
)

expect(result.total.toNumber()).toBeCloseTo(-2.688, 1)
expect(result.total.toNumber()).toBeCloseTo(-6.72, 1)
expect(result.cultivations).toEqual([
{ id: "cultivation1", value: expect.any(Decimal) },
])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export function calculateNitrogenVolatizationViaAmmoniaByResidue(

// Calculate the amount of Nitrogen volatilized by crop residues of this cultivation
const removal = b_lu_yield
.dividedBy(b_lu_hi)
.times(b_lu_hi_res)
.times(b_lu_n_residue)
.times(emissionFactor)
Expand Down