Digital Twins: Using Maths across Measurements

A presentation at Code.talks in October 2019 in Hamburg, Germany by David G. Simmons

Slide 1

Slide 1

Digital Twins: Using Maths across Measurements David G. Simmons Senior Developer Evangelist, InfluxData bit.ly/dgctalk </> code.talks InfluxData @davidgsIoT

Slide 2

Slide 2

Photo by William Daigneault on Unsplash It’s about Digital Twins But really it’s about maths </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 3

Slide 3

Photo by Martin Adams on Unsplash Gas is easy: How much gas is there? Ideal Gas Law PV=nRT </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 4

Slide 4

Photo by Zack Woolwine on Unsplash Heat Index: How hot does it feel Heat index is hard Steadman’s Equation: HI = 0.5 * {T + 61.0 + [(T-68.0)1.2] + (RH0.094)} Rothsfuz Regression: HI = -42.379 + 2.04901523T + 10.14333127RH - .22475541TRH - . 00683783TT - .05481717RHRH + . 00122874TTRH + . 00085282TRHRH - . 00000199TTRHRH </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 5

Slide 5

There are lots of others </> • Saturation Vapor Pressure • Vapor Pressure Deficit • Dew Point • Air Density </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 6

Slide 6

Let’s talk about Flux • Flux is a functional data scripting language that is written to be: • Useable • Readable • Composable • Testable • Contributable • Shareable • Javascript-esque • MIT License </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 7

Slide 7

Some Terminology </> • Bucket: Named data source with a retention policy • Pipe-forward operator: Used to chain operators together • Table: Data is returned in annotated CSVs, represented as tables • Group key: List of columns for which every row in the table has the same value </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 8

Slide 8

A Simple Flux Example from(bucket:”telegraf/autogen”) |> range(start: -1h) |> filter(fn: (r) => r.measurement == “cpu” AND r.field == “usage_system” AND r.cpu == “cpu_total”) |> yield() </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 9

Slide 9

Let’s do some Maths in Flux! • First, we build a tables: CO2Raw = from(bucket: “telegraf”) |> range(start: v.timeRangeStart) |> filter(fn: (r) => r._measurement == “k30_reader” and (r._field == “co2”)) |> aggregateWindow(every: 30s, fn: mean) |> filter(fn: (r) => exists r._value) |> keep(columns: [“_value”, “_time”]) |> yield(name: “Raw CO2”) </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 10

Slide 10

Here’s Your Table </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 11

Slide 11

Build some more Tables </> • Temperature • Pressure </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 12

Slide 12

There Can Be Only One* • Join 2 of the tables together: first_join = join(tables: {CO2meas: CO2Raw, Tmeas: Tmeas}, on: [“_time”]) • Make the big table: second_join = join(tables: {first_join: first_join, Pmeas: Pmeas}, on: [“_time”]) |>map(fn: (r) => ({_time: r._time, pressure: r._value, gas:r._value_CO2meas, temperature:r._value_Tmeas})) |> filter(fn: (r) => exists r.pressure) |> filter(fn: (r) => exists r.gas) |> filter(fn: (r) => exists r.temperature) |> environmental.idealGasLaw() |> yield(name: “Compensated”) * </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 13

Slide 13

Let’s see the Maths idealGasLaw = (tables=<-) => tables |> map(fn: (r) => ({_time: r._time, _value: r.gas * (((r.temperature + 273.15) * 1013.25) / (r.pressure * 298.15))})) </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 14

Slide 14

The End Result </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 15

Slide 15

Photo by Shahadat Shemul on Unsplash We can Hide Complex Maths • We can add more equations to our environmental package • Soon, we can share that package with other users </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 16

Slide 16

Steadman and Rothsfuz // The ‘simple’ Steadman Equation _steadman = (t,h) => (0.5 * (t + 61.0 + ((t - 68.0)1.2) + (h0.094))) // The more complex Rothsfuz Regression equation _rothfusz = (t,h) => -42.379 + 2.04901523t + 10.14333127h - .22475541th - .00683783tt - . 05481717hh + .00122874tth + .00085282thh - .00000199tthh // required adjustment #1 to the Rothsfuz Regression _roth_adjust1 = (t,h) => ((13.0-h)/4.0)*math.sqrt(x: ((17.0-math.abs(x: (t-95.0))/17.0))) // required adjustment #2 to the Rothsfuz Regression _roth_adjust2 = (t,h) => ((h-85.0 )/10.0) *((87.0-t)/5.0) </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 17

Slide 17

Heat Index is Hard // Calculate the heat index given a table with Columns: temperature and humidity heatIndex = (tables=<-) => tables |> map(fn: (r) => ({ r with _value: if (_steadman(t: r.temperature, h: r.humidity) + r.temperature)/ 2.0 < 80.0 then _steadman(t: r.temperature, h: r.humidity) else if ( r.humidty < 13.0 and r.temperature > 80.0) then _rothfusz(t: r.temperature, h: r.humidity) - _roth_adjust1(t: r.temperature, h: r.humidity) else if r.humidity > 85.0 and r.temperature >= 80.0 and r.temperature <= 87.0 then _rothfusz(t: r.temperature, h: r.humidity) + _roth_adjust2(t: r.temperature, h: r.humidity) else _rothfusz(t: r.temperature, h: r.humidity) })) </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 18

Slide 18

The End Result </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 19

Slide 19

Demo Time! </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 20

Slide 20

Photo by Franck V. on Unsplash “I hate this damned machine I wish that they would sell it. It never does what I want But only what I tell it.” –My Mom </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> </> @davidgsIoT

Slide 21

Slide 21

Resources • • • • Ideal Gas Law: • https://en.wikipedia.org/wiki/Ideal_gas_law Heat index: • https://www.weather.gov/media/ffc/ta_htindx.PDF /www.wpc.ncep.noaa.gov/html/ • https:/ heatindex_equation.shtml Flux: • https://v2.docs.influxdata.com/v2.0/query-data/ This talk: • bit.ly/dgctalk </> </></> </></> </> </></> </></> </> </></> </> </></> </></> </> </> </> </></> </> </> </> </> </></> </> </> </> </> </> </> </></> </> </> </> </> </> @davidgsIoT

Slide 22

Slide 22

THANK YOU @davidgsIoT