Thursday, June 20, 2024

The 3 Types of Woodstock Yield Tables (plus one)

Introduction

Currently, I'm working on a strategic planning model for a research forest in the U.S. Forests held by land-grant universities is subject to scrutiny from many interested parties: faculty, students, neighboring landowners, etc. In this case, we need to recognize ongoing research projects, recreational use, biodiversity, fire resilience and other metrics. Representing these metrics in the model required the use of all Woodstock yield types, so I thought this would be a good opportunity to review them with you.

Three Types of Yield Tables

Anyone who has taken Remsoft’s Modeling Fundamentals course was taught the three types of yield tables: age-dependent, time-dependent and complex. Let’s review each one.

Age-Dependent Yields

Yield tables that represent the development of stands over time are usually age-dependent. For a given age, the yield table shows things like product volume, diameter, dominant height, basal area, and other stand parameters. The yield table header starts with *Y followed by the development type mask.

*Y ? ? ? ? ? ? ? ? EX ? 00 00 ? ? ? ? 010111 010111  
_AGE yiTPA  yiBA yiBAO yxTHT yxQMD yxSDI yxCCF   yiTCF
   6   374   135    23    57   8.1   268   192   3.075
   7   359   153    26    67   8.8   295   209   3.995
   8   345   171    30    73   9.5   320   226   4.936
   9   332   189    34    80  10.2   343   241   5.899
  10   319   205    38    87  10.8   364   255   6.843

Of course, this assumes that you are practicing even-aged management, and that you know the age of your stands fairly precisely. Otherwise, you should be using a time-dependent yield table.

Time-Dependent Yields

Yield tables that represent values that depend on planning periods rather than age are time-dependent. Prices and costs that are expected to change over time (in real terms) are associated with particular planning periods, and the yield header starts with *YT followed by the development type mask.

*YT ? ? ? ? ? ? ? ? ? ? ? ? ? ? CA ? ? ?
y$CC 1 327
y$UI 1 377
y$UG 1 377
y$UV 1 285
y$OR 1 388

*YT ? ? ? ? ? ? ? ? ? ? ? ? ? ? GR ? ? ?
y$CC 1 189
y$UI 1 280
y$UG 1 222
y$UV 1 195
y$OR 1 388

Complex Yields

A complex yield table is really just a way to created new yield components based on previously-defined yield components. For example, you can sum individual product volumes to produce a total volume coefficient. Complex yield headers start with *YC.

Woodstock provides a number of built-in functions to make complex yields easier to define and to speed up processing. For example, I can define a complex yield coefficient that sums all volume coefficients (MBF/ac) that occur in the same period. I can also define cost coefficients that occur in the same period that depend on harvest volume ($/MBF). If I use this method to trigger total costs, I can reduce the matrix generation time. In theory, I should also be able to define a harvest cost coefficient by multiplying product harvest volume by logging cost.

*YC ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
yiDF _SUM(yiDF0,yiDF4,yiDF8,yiDF2,yiDF3)
ycCC _MULTIPLY(yiMBF,y$CC)
ycSW _MULTIPLY(yhMBF,y$CC)
ycSC _MULTIPLY(yhMBF,y$T2)

Since most people define costs and prices as time-dependent yields, the example above may or may not work. If you define stumpage prices as time-dependent, but they are static (no price appreciation), the syntax above works fine. But if you have price appreciation, Woodstock will throw the following error:

Error: 386, line number(2539), in file C:\Work\Model.yld 
       yrPLP _MULTIPLY(yplp,yplp$)
Incorrect use of internal functions. You cannot mix Age-dependent and Time-dependent yield curves. 

There is a work-around if you're willing to use older code:

*YC .MASK()
yrPWD yPWD * y$PWD

If you have a lot of yield tables to process, the interpreted code is much slower than the functions like _MULTIPLY( ) that are implemented using dynamic link libraries (DLLs). But that may be better than rethinking your entire model.

Sequence-Dependent Yields?

I know we are becoming an endangered species, but those of us old enough to have used FORPLAN may remember that yields could be one of age-, time- or sequence-dependent. By sequence-dependent, we mean that a yield is triggered after some other event. For example, suppose that I want to model siltation and have it triggered for a few periods after a harvest operation. The siltation does not depend on the age of the trees harvested, and while the amount of silt produced may change with time, it is not associated with any particular planning period either. It is truly sequence-dependent.

Woodstock doesn’t explicitly offer sequence-dependent yields and you may think you are out of luck modeling something like siltation. However, you can incorporate yield tables within prescriptions in the REGIMES section. For example, in the research forest model, we have a group selection prescription that consists of periodic harvests. We also have a yield table that shows changes in the presence of pollinator insects following harvest that we link directly in the prescription table.

*PRESCRIPTION rxUG01 Start removals in period 1
*OPERABLE .MASK(_TH1(F),_TH4(UGRP),_TH17(U01)) _AGE >= 1
  _RXPERIOD _ACTION _ENTRY  yxPOL
      0       aGS  _INITIAL   4.0    
      1        -       -      3.5     
      2        -       -      2.5 
      3        -       -      1.0
      4       aGS      -      4.0  
      5        -       -      3.5
     ...

I have defined the prescription rxUG01. The action aGS (group selection harvest), boosts pollinator levels to 4.0 (on a scale of 0 to 5). One period (5 years) later, pollinator levels drop to 3.5. As the canopy closes on the group selection harvest area, pollinators drop more quickly. However, following another harvest, pollinator levels are boosted once again. While you could probably construct age- or time-dependent yields to represent these, they would quickly become unwieldy if the return period between harvests is not constant (say 15 years, then 10 years and then 20 years).

If the yield table containing yxPOL is present in the YIELDS section within a time-dependent yield table, it will also be treated as time-dependent in REGIMES. That means it will be subject to the same rules for other time-dependent yields, including the restriction on mixing types using yield functions. I don’t know how yield tables in the REGIMES section are represented in the Woodstock code (as age- or time-dependent) if the yield component is not present in the YIELDS section.

Confused by Regimes and Sequence-Dependent Yields? Contact Me!

If you are interested in modeling innovative silviculture or other uncommon formulations, give me a shout! I have lots of experience modeling different types of silviculture from around the world and I'm sure I can help you devise an efficient formulation.

Why are MIP models difficult to solve (or not)?

Introduction I recently joined a conversation about why a mixed-integer programming (MIP) problem is so much harder to solve than a regular ...