Exercises: Expression Builder Walkthrough
This walkthrough will use an Expression to calculate drill and blast fields.
Rapid Reserver Setup
For this model two blast properties were added to Rapid Reserver:
-
Initial State – Used to set the initial state of a blast.
-
Contour Percent – Used to calculate drilling for patterns that have areas for both production and contour drills.
In the Designer, values were populated on different blasts for testing and validation purposes:
APS – Settings
Tick on ‘Use Expression Builder’:
APS – Production Mode Features
For the walkthrough, tick on drilling, charging and the generic activity that occurs before drilling:
APS – Parcels
For this walkthrough, parcels have been setup as follows:
Activity |
Parcel |
Comment |
---|---|---|
PreDrilling |
PatternPrep |
Generic name to represent area required for pattern preparation. |
ProductionDrilling |
251, 165 |
Values represent the drill bit diameter used for production and contour drilling. |
ProductionCharging |
ANFO, Mix8020, Mix6040, Emulsion |
Different explosive types. |
Mining |
Variable |
These will be unique to each model and will not impact the expressions being created during the walkthough. |
APS – Fields
Additional fields are required to be added to hold final values as well as assisting in calculations. Having extra fields for temporary calculation steps will help in validating that Expressions are working as intended.
Note: Field collections not mentioned below, are not used in Expressions through the walkthrough.
BlastSolid
Add two new fields to hold the Blast Properties from Rapid Reserver:
PreDrilling
Add field to be used as Primary field for PreDrilling activity:
ProductionDrilling
For Production Drilling in addition to holes and meters, 2 temporary fields are going to be added to help with calculations, tempHoles251 & tempHoles165.
Why have tempHoles? This is to avoid recalculating the number of holes for charging requirements. If the initial state is drilled, then number of holes would be set to zero.
Why separate by parcel when the software already does this? Once again this was done to simplify the charging requirements as the diameter is required to calculate explosives tonnes.
ProductionCharging
For Production Charging in addition to design charge, 1 temporary field is added to simplify calculations.
Why have chargeLength? Having this field helps simplify the design charge calculation. This can be used to validate scenarios where the average pattern depth is less than the minimum charge length.
Primary Fields
Choose the appropriate field for each activity:
Map Data
Map the blast properties from the Rapid Reserver to the BlastSolid fields:
Database Inputs – Table Setup
To help create long lists of inputs it is recommended to use iteration lists. These will create multiple inputs for each item in the iteration list.
Row Type |
Indent |
Full Name |
Name |
Input Type |
Iteration List |
Comments |
---|---|---|---|---|---|---|
Title |
0 |
(Auto) |
BlastType |
N/A |
N/A |
|
Iter |
1 |
(Auto) |
N/A |
N/A |
BlastSolid.BlastType |
For each BlastType in the model, create rows for each child row. |
Value |
2 |
(Auto) |
Diameter |
Choice |
Parcels – ProductionDrilling |
Creates a dropdown option with drill diameters. This allows a diameter to be assigned to each pattern type. |
Value |
2 |
(Auto) |
Burden |
Double |
N/A |
|
Value |
2 |
(Auto) |
Spacing |
Double |
N/A |
|
Value |
2 |
(Auto) |
Subdrill |
Double |
N/A |
|
Value |
2 |
(Auto) |
Stemming |
Double |
N/A |
|
Title |
2 |
(Auto) |
ExplosivePercent |
N/A |
N/A |
|
Iter |
3 |
(Auto) |
N/A |
N/A |
Parcels – ProductionCharging |
For each ProductionCharging Parcel, create rows for each child row. |
Value |
4 |
(Auto) |
Percentage |
Double |
|
|
Title |
0 |
(Auto) |
Explosive Densities |
N/A |
N/A |
|
Iter |
1 |
(Auto) |
N/A |
N/A |
Parcels – ProductionCharging |
For each ProductionCharging Parcel, create rows for each child row. |
Value |
2 |
(Auto) |
Density |
Double |
N/A |
|
Note: Using BlastSolid.BlastType as an iteration list creates a relationship between the input field and database. This allows the software to automatically grab the correct input value from the table based on the blastType.
Database Inputs – Table
From the setup above, one can see how the iteration lists are being applied:
Expression Builder
The Expression builder is where mapped fields are combined with data inputs to calculate new database values.
PreDrilling
Only one field should be visible for an expression. If the field is not visible, check that is has been added as a field to PreDrilling and is not mapped under Map Data.
Even though PreDrilling uses area as the primary field, the model needs to consider the initial state of the pattern. This can be done using a simple if statement.
By Parcel |
Field Name / Parcel |
APS Expression |
What it means |
---|---|---|---|
No |
|
T("BlastSolid.initialState") == "Insitu" ? N("BlastSolid.surfaceArea") : 0 |
If the Initial State of the Blast Solid is Insitu, then set the value to the Blast Solid area, otherwise set to zero. |
|
|
|
If Initial State = Insitu, Then Surface Area, Else 0 |
Since PreDrilling only has one parcel type, there is no need to use ‘By Parcel’ option.
Once that Expression is complete, run one step forward to Expression Refined Database to validate results.
ProductionDrilling
ProductionDrilling has multiple parcels which will require the ‘By Parcel’ Option to be used.
By Parcel |
Field Name / Parcel |
APS Expression |
What it means |
---|---|---|---|
Yes |
tempHoles251 / 251 |
RT("BlastType/<BlastSolid.blastType>/Diameter") == Parcel ? N("BlastSolid.surfaceArea") / (RN("BlastType/<BlastSolid.blastType>/Burden") * RN("BlastType/<BlastSolid.blastType>/Spacing")) * (1 - N("BlastSolid.contourPct")) : 0 |
|
To make interpreting the above expression easier it has been separated in pieces and explained below.
Section |
What it means |
---|---|
RT("BlastType/<BlastSolid.blastType>/Diameter") |
Get the Diameter from the inputs table that matches the blast type for the record being evaluated. |
== Parcel |
Does the Diameter for the pattern match the parcel being evaluated. In this case the Parcel is 251. |
N("BlastSolid.surfaceArea") |
Get Blast Solid Surface Area from the main database. |
RN("BlastType/<BlastSolid.blastType>/Burden") |
Get the Burden from the inputs table that matches the blast type for the record being evaluated. |
RN("BlastType/<BlastSolid.blastType>/Spacing") |
Get the Spacing from the inputs table that matches the blast type for the record being evaluated. |
N("BlastSolid.contourPct")) |
Get Blast Solid Contour Percent from the main database. |
And when that all gets put together:
By Parcel |
Field Name / Parcel |
APS Expression |
What it means |
---|---|---|---|
Yes |
tempHoles251 / 251 |
RT("BlastType/<BlastSolid.blastType>/Diameter") == Parcel ?
|
If the pattern diameter equals 251 |
N("BlastSolid.surfaceArea") / (RN("BlastType/<BlastSolid.blastType>/Burden") * RN("BlastType/<BlastSolid.blastType>/Spacing")) * (1 - N("BlastSolid.contourPct")) :
|
Then calculate the number of holes and adjust by the contour percent
Number of Holes = Surface Area / (Burden * Spacing) |
||
0 |
Else zero
|
What about parcel 165 under TempHoles251? Since this field will only report 251 holes, parcel 165 can simply be hard coded to 0.
Looking at the expressions in basic text is not great, fortunately the Edit Expression window helps with this. Comments can also be added to the expressions to make them easier to read. Use /* to start a comment and */ to end it.
Repeating the same exercise for tempHoles165. Parcel 251 can be hard coded to 0.
For parcel 165, things may appear a bit more complicated, but this is just an extra check if a pattern contains contours.
By Parcel |
Field Name / Parcel |
APS Expression |
What it means |
---|---|---|---|
Yes |
tempHoles165 / 165 |
RT("BlastType/<BlastSolid.blastType>/Diameter") == Parcel ? |
If the pattern diameter equals 165
|
|
|
N("BlastSolid.surfaceArea") / (RN("BlastType/<BlastSolid.blastType>/Burden") * RN("BlastType/<BlastSolid.blastType>/Spacing")) :
|
If the diameters match, calculate number for 165 holes |
|
|
N("BlastSolid.contourPct") == 0 ? 0 : |
If pattern diameters don't match, check if pattern contains contour percent If contour percent is zero then set value to zero |
|
|
(N("BlastSolid.surfaceArea") / (RN("BlastType/Contour/Burden") * RN("BlastType/Contour/Spacing")) * N("BlastSolid.contourPct"))
|
If pattern contour percent exists, then calculate 165 holes usings contour pattern inputs |
The last two fields are much simpler as all the hard work has been done.
Since tempHoles are already split by diameters, there is no need to calculate holes by parcel. All that needs to be done is to check the initial status and add the temp holes together.
By Parcel |
Field Name / Parcel |
APS Expression |
What it means |
---|---|---|---|
No |
Holes |
T("BlastSolid.initialState") == "Blasted" || T("BlastSolid.initialState") == "Drilled" ? 0 :
|
If the initial state is Blasted or Drilled then set value to zero |
|
|
N("ProductionDrilling.tempHoles251",Parcel) + N("ProductionDrilling.tempHoles165",Parcel)
|
Else add the value from tempHoles from both fields where the parcels match. |
Remember that expressions are always evaluated at the parcel level, so using N("ProductionDrilling.tempHoles251",Parcel) will get the number of tempHoles251 which match the parcel being evaluated. When evaluating parcel 251, the expression above becomes tempHoles251 + 0. Similarly, when evaluating parcel 165, the expression above becomes 0 + tempHoles165.
The final drilling field to calculate is meters. In this walkthrough, it is assumed that all pattern types will use the same calculation for hole depth, so there is no need to calculate by parcel.
By Parcel |
Field Name / Parcel |
APS Expression |
What it means |
---|---|---|---|
No |
Meters |
N("ProductionDrilling.holes",Parcel) *
|
Get the number of holes for the associated parcel. |
|
|
(N("BlastSolid.volume") / N("BlastSolid.surfaceArea") + RN("BlastType/<BlastSolid.blastType>/Subdrill"))
|
Calculate average bench height and add subdrill for the blast type. |
Once all Expressions are complete and valid, run one step forward to Expression Refined Database to validate results.
ProductionCharging
The first field to calculate will be chargeLength. This field is not required, but it does simplify the subsequent expression. Also, if there were other checks for minimum hole depth or charge length, they could be done here.
No need to calculate by parcel since the charge length per hole is assumed to be the same regardless of the explosive type being used.
By Parcel |
Field Name / Parcel |
APS Expression |
What it means |
---|---|---|---|
No |
chargeLength |
T("BlastSolid.initialState") == "Blasted" ? 0 :
|
If the initial state is Blasted then set value to zero |
|
|
N("BlastSolid.volume") / N("BlastSolid.surfaceArea") + RN("BlastType/<BlastSolid.blastType>/Subdrill") - RN("BlastType/<BlastSolid.blastType>/Stemming")
|
Calculate average bench height and add subdrill and subtract stemming height. |
Charging quantity is essentially calculated in 3 sections:
-
Quantity for 251mm holes
-
Quantity for 165mm holes when the pattern in not a mix of production and contour
-
Quantity for 165mm holes when the pattern is a mix of production and contour
The expression for each will be the same, so only one will be looked at in detail.
In this expression the Parcel name is being added to the expression, this will update the input fields being referenced and remove the need to calculate by parcel.
By Parcel |
Field Name / Parcel |
APS Expression |
What it means |
---|---|---|---|
No |
designCharge |
N("ProductionDrilling.tempHoles251") * |
Get the number of 251 holes |
|
|
N("ProductionCharging.chargeLength",Parcel) * Pi * Math.Pow(.251/2,2) * |
Calculate the volume of explosive required |
|
|
RN("ExplosiveDensities/" + Parcel + "/Density") * |
Get the explosive density for the parcel being evaluated |
|
|
RN("BlastType/<BlastSolid.blastType>/ExplosivePercent/" + Parcel + "/Percentage") / 100 |
Get the explosive percentage for the blast type and parcel being evaluated |
Note: In the above expression, the ‘wildcard’ inputs were combined with the Parcel name formula to add more flexibility to the expression.
When all 3 hole types are calculated, the expression should look something like this:
Quick check in the Expression Refined Database: