The International Simutrans Forum

 

Author Topic: Industry consumption query  (Read 2302 times)

0 Members and 1 Guest are viewing this topic.

Offline jamespetts gb

  • Simutrans-Extended project coordinator
  • Devotee
  • *
  • Posts: 18745
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Industry consumption query
« on: January 18, 2014, 08:57:24 PM »
Probably a silly question, but it is not immediately obvious from reading the code: where can one find a variable/getter in the fabrik_t class representing the monthly maximum consumption of one particular type of input goods in any given industry?

Edit: My investigations into this have dug up some very weird behaviour, and I am not sure whether this is confined to Experimental or not: a market consumes fruit, vegetables, meat and fish in proportions 100%, 100%, 33%, 200%. It is connected to a single arable farm in a test game, which produces vegetables far faster than the market can consume them (I set up the test game to test the max_intransit_percentage adjustment feature that I am writing).

Production is nominally 16 units per month. The industry is not connected to electricity. When I run the game fast forwarded and it is connected to the arable farm, consumption of vegetables is 41/month (as shown on the "goods needed" graph). When run for a month without fast forwarding, consumption is only 20/month. A diary, meanwhile, with a nominal consumption of 800/month consumed exactly that in a very similar test when connected to two cattle farms with sufficient transport to meet its need more than sufficiently.

Also, I examined the code and deduced that this was the relevant code determining industry consumption rates:

Code: [Select]
if(  ausgang.empty()  ) {
            // consumer only ...
            if(  besch->is_electricity_producer()  ) {
                // power station => start with no production
                power = 0;
            }

            // finally consume stock
            for(  uint32 index = 0;  index < eingang.get_count();  index++  ) {
                if(!besch->get_lieferant(index))
                {
                    continue;
                }
                const uint32 vb = besch->get_lieferant(index)->get_verbrauch();
                const uint32 v = max(1,(menge*vb) >>;

                if(  (uint32)eingang[index].menge > v + 1  ) {
                    eingang[index].menge -= v;
                    eingang[index].book_stat(v, FAB_GOODS_CONSUMED);
                    currently_producing = true;
                    if(  besch->is_electricity_producer()  ) {
                        // power station => produce power
                        power += (uint32)( ((sint64)scaled_electric_amount * (sint64)(DEFAULT_PRODUCTION_FACTOR + prodfactor_pax + prodfactor_mail)) >> DEFAULT_PRODUCTION_FACTOR_BITS );
                    }
                    // to find out, if storage changed
                    delta_menge += v;
                }

In theory, therefore, the following code should produce the correct number:

Code: [Select]
const uint64 max_prod = (uint64)prodbase * (uint64)(get_prodfactor());
    const uint64 menge_prod = (max_prod >> (18-10+DEFAULT_PRODUCTION_FACTOR_BITS-fabrik_t::precision_bits)) * welt->ticks_per_world_month + (uint64)menge_remainder;
    const uint32 menge = (uint32)(menge_prod / (uint64)PRODUCTION_DELTA_T);
    const uint32 vb = besch->get_lieferant(index)->get_verbrauch();
    const uint32 v = max(1,(menge*vb) >>;
    const uint32 TEST = convert_goods(v);

("TEST" should be the same as shown in the "goods needed" graph). However, this produces the figure of 16, which is the same as would be produced by the much simpler:

Code: [Select]
(get_current_production() * besch->get_lieferant(index)->get_verbrauch()) >> 8;

This looks to me like a rounding error somewhere. Would changing "fabrik_t::precision_bits" to a higher number assist, or would doing so cause overflows somewhere?
« Last Edit: January 19, 2014, 02:28:24 PM by jamespetts »

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 9568
  • Languages: De,EN,JP
Re: Industry consumption query
« Reply #1 on: January 20, 2014, 04:06:44 PM »
Part of the problem is how often step() is called. When bits per month were introduced, I set this so the pa128 open pit mine did not overflow until setting of 23 (if memory serves me right, that was a little ago already).

Offline jamespetts gb

  • Simutrans-Extended project coordinator
  • Devotee
  • *
  • Posts: 18745
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Industry consumption query
« Reply #2 on: January 20, 2014, 08:00:32 PM »
Interesting - thank you. Does that mean that industries whose monthly production is less than 23 are likely to see this problem?

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 9568
  • Languages: De,EN,JP
Re: Industry consumption query
« Reply #3 on: January 20, 2014, 09:04:42 PM »
No, this would be an underflow. For this I tested until bit per month 16. But I only tested the standard paks, so a risk of underflow might still exist. Best to add some debug logging and see for yourself.

Although with bits per month = 20, you should only get productions which are divideable by four.