1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """Appends a userfcn to the list to be called for a case.
18 """
19
20 from sys import stderr
21
22 -def add_userfcn(ppc, stage, fcn, args=None, allow_multiple=False):
23 """Appends a userfcn to the list to be called for a case.
24
25 A userfcn is a callback function that can be called automatically by
26 PYPOWER at one of various stages in a simulation.
27
28 Currently there are 5 different callback stages defined. Each stage has
29 a name, and by convention, the name of a user-defined callback function
30 ends with the name of the stage. The following is a description of each
31 stage, when it is called and the input and output arguments which vary
32 depending on the stage. The reserves example (see L{runopf_w_res}) is used
33 to illustrate how these callback userfcns might be used.
34
35 1. C{'ext2int'}
36
37 Called from L{ext2int} immediately after the case is converted from
38 external to internal indexing. Inputs are a PYPOWER case dict (C{ppc}),
39 freshly converted to internal indexing and any (optional) C{args} value
40 supplied via L{add_userfcn}. Output is the (presumably updated) C{ppc}.
41 This is typically used to reorder any input arguments that may be needed
42 in internal ordering by the formulation stage.
43
44 E.g. C{ppc = userfcn_reserves_ext2int(ppc, args)}
45
46 2. C{'formulation'}
47
48 Called from L{opf} after the OPF Model (C{om}) object has been
49 initialized with the standard OPF formulation, but before calling the
50 solver. Inputs are the C{om} object and any (optional) C{args} supplied
51 via L{add_userfcn}. Output is the C{om} object. This is the ideal place
52 to add any additional vars, constraints or costs to the OPF formulation.
53
54 E.g. C{om = userfcn_reserves_formulation(om, args)}
55
56 3. C{'int2ext'}
57
58 Called from L{int2ext} immediately before the resulting case is converted
59 from internal back to external indexing. Inputs are the C{results} dict
60 and any (optional) C{args} supplied via C{add_userfcn}. Output is the
61 C{results} dict. This is typically used to convert any results to
62 external indexing and populate any corresponding fields in the
63 C{results} dict.
64
65 E.g. C{results = userfcn_reserves_int2ext(results, args)}
66
67 4. C{'printpf'}
68
69 Called from L{printpf} after the pretty-printing of the standard OPF
70 output. Inputs are the C{results} dict, the file descriptor to write to,
71 a PYPOWER options dict, and any (optional) C{args} supplied via
72 L{add_userfcn}. Output is the C{results} dict. This is typically used for
73 any additional pretty-printing of results.
74
75 E.g. C{results = userfcn_reserves_printpf(results, fd, ppopt, args)}
76
77 5. C{'savecase'}
78
79 Called from L{savecase} when saving a case dict to a Python file after
80 printing all of the other data to the file. Inputs are the case dict,
81 the file descriptor to write to, the variable prefix (typically 'ppc')
82 and any (optional) C{args} supplied via L{add_userfcn}. Output is the
83 case dict. This is typically used to write any non-standard case dict
84 fields to the case file.
85
86 E.g. C{ppc = userfcn_reserves_printpf(ppc, fd, prefix, args)}
87
88 @param ppc: the case dict
89 @param stage: the name of the stage at which this function should be
90 called: ext2int, formulation, int2ext, printpf
91 @param fcn: the name of the userfcn
92 @param args: (optional) the value to be passed as an argument to the
93 userfcn
94 @param allow_multiple: (optional) if True, allows the same function to
95 be added more than once.
96
97 @see: L{run_userfcn}, L{remove_userfcn}, L{toggle_reserves},
98 L{toggle_iflims}, L{runopf_w_res}.
99
100 @author: Ray Zimmerman (PSERC Cornell)
101 @author: Richard Lincoln
102 """
103 if args is None:
104 args = []
105
106 if stage not in ['ext2int', 'formulation', 'int2ext', 'printpf', 'savecase']:
107 stderr.write('add_userfcn : \'%s\' is not the name of a valid callback stage\n' % stage)
108
109 n = 0
110 if 'userfcn' in ppc:
111 if stage in ppc['userfcn']:
112 n = len(ppc['userfcn'][stage])
113 if not allow_multiple:
114 for k in range(n):
115 if ppc['userfcn'][stage][k]['fcn'] == fcn:
116 stderr.write('add_userfcn: the function \'%s\' has already been added\n' % fcn.func_name)
117 else:
118 ppc['userfcn'][stage] = []
119 else:
120 ppc['userfcn'] = {stage: []}
121
122 ppc['userfcn'][stage].append({'fcn': fcn})
123 if len(args) > 0:
124 ppc['userfcn'][stage][n]['args'] = args
125
126 return ppc
127