summaryrefslogtreecommitdiff
path: root/lib/net_fracture.c
blob: 65ede9b33b39180f1c45d7f7d2a7f6eaa8a5c251 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

#include "fracture.h"

uint_t get_next_broken(net_t *net, double *currents, double cutoff) {
  uint_t max_pos = UINT_MAX;
  long double max_val = 0;

  for (uint_t i = 0; i < net->graph->ne; i++) {
    long double current = fabs(currents[i]);
    bool broken = net->fuses[i];

    if (!broken && current > cutoff) {
      long double val = current / net->thres[i];

      if (val > max_val) {
        max_val = val;
        max_pos = i;
      }
    }
  }

  if (max_pos == UINT_MAX) {
    printf("GET_NEXT_BROKEN: currents is zero or NaN, no max_val found\n");
    exit(EXIT_FAILURE);
  }

  return max_pos;
}

data_t *net_fracture(net_t *net, cholmod_common *c, double cutoff) {
  data_t *data = data_create(net->graph->ne);

  uint_t n = 0;
  while (true) {
    n++;
    double *voltages = net_voltages(net, c);
    double *currents = net_currents(net, voltages, c);

    double conductivity = net_conductivity(net, voltages);

    if (conductivity < cutoff) {
      free(voltages);
      free(currents);
      break;
    }

    uint_t last_broke = get_next_broken(net, currents, cutoff);

    long double sim_current;

    if (net->voltage_bound) {
      sim_current = conductivity;
    } else {
      sim_current = 1;
    }

    data_update(data, last_broke, fabsl(sim_current * (net->thres)[last_broke] /
                                        ((long double)currents[last_broke])),
                conductivity);

    free(voltages);
    free(currents);

    break_edge(net, last_broke, c);
  }

  return data;
}