Creates a dictionary of indices and values for each parameter in a parameter array to be evaluated later. WARNING: It is not possible to initialize multidimensional array parameters e.g. dimension(-3:1, 4, 3:5) at this point. This is because in Fortran initialization through ar
(v, g_params, params, dimspec=None)
| 2998 | |
| 2999 | |
| 3000 | def param_eval(v, g_params, params, dimspec=None): |
| 3001 | """ |
| 3002 | Creates a dictionary of indices and values for each parameter in a |
| 3003 | parameter array to be evaluated later. |
| 3004 | |
| 3005 | WARNING: It is not possible to initialize multidimensional array |
| 3006 | parameters e.g. dimension(-3:1, 4, 3:5) at this point. This is because in |
| 3007 | Fortran initialization through array constructor requires the RESHAPE |
| 3008 | intrinsic function. Since the right-hand side of the parameter declaration |
| 3009 | is not executed in f2py, but rather at the compiled c/fortran extension, |
| 3010 | later, it is not possible to execute a reshape of a parameter array. |
| 3011 | One issue remains: if the user wants to access the array parameter from |
| 3012 | python, we should either |
| 3013 | 1) allow them to access the parameter array using python standard indexing |
| 3014 | (which is often incompatible with the original fortran indexing) |
| 3015 | 2) allow the parameter array to be accessed in python as a dictionary with |
| 3016 | fortran indices as keys |
| 3017 | We are choosing 2 for now. |
| 3018 | """ |
| 3019 | if dimspec is None: |
| 3020 | try: |
| 3021 | p = eval(v, g_params, params) |
| 3022 | except Exception as msg: |
| 3023 | p = v |
| 3024 | outmess(f'param_eval: got "{msg}" on {v!r}\n') |
| 3025 | return p |
| 3026 | |
| 3027 | # This is an array parameter. |
| 3028 | # First, we parse the dimension information |
| 3029 | if len(dimspec) < 2 or dimspec[::len(dimspec)-1] != "()": |
| 3030 | raise ValueError(f'param_eval: dimension {dimspec} can\'t be parsed') |
| 3031 | dimrange = dimspec[1:-1].split(',') |
| 3032 | if len(dimrange) == 1: |
| 3033 | # e.g. dimension(2) or dimension(-1:1) |
| 3034 | dimrange = dimrange[0].split(':') |
| 3035 | # now, dimrange is a list of 1 or 2 elements |
| 3036 | if len(dimrange) == 1: |
| 3037 | bound = param_parse(dimrange[0], params) |
| 3038 | dimrange = range(1, int(bound)+1) |
| 3039 | else: |
| 3040 | lbound = param_parse(dimrange[0], params) |
| 3041 | ubound = param_parse(dimrange[1], params) |
| 3042 | dimrange = range(int(lbound), int(ubound)+1) |
| 3043 | else: |
| 3044 | raise ValueError(f'param_eval: multidimensional array parameters ' |
| 3045 | '{dimspec} not supported') |
| 3046 | |
| 3047 | # Parse parameter value |
| 3048 | v = (v[2:-2] if v.startswith('(/') else v).split(',') |
| 3049 | v_eval = [] |
| 3050 | for item in v: |
| 3051 | try: |
| 3052 | item = eval(item, g_params, params) |
| 3053 | except Exception as msg: |
| 3054 | outmess(f'param_eval: got "{msg}" on {item!r}\n') |
| 3055 | v_eval.append(item) |
| 3056 | |
| 3057 | p = dict(zip(dimrange, v_eval)) |
no test coverage detected