Package sfc :: Package codegeneration :: Module formargumentcg
[hide private]
[frames] | no frames]

Source Code for Module sfc.codegeneration.formargumentcg

  1   
  2  from ufl.common import component_to_index, product 
  3  from ufl.permutation import compute_indices 
  4   
  5  """ 
  6  FIXME: 
  7   
  8  Get information: 
  9   
 10  - List of required elements with number of derivatives needed 
 11   
 12  - Element representation for all required elements 
 13   
 14  - Element representation for all required SUBelements 
 15   
 16  - Mappings from elements to unique subelements 
 17   
 18   
 19  Without derivatives: 
 20   
 21  - Generate array members for precompute struct 
 22   
 23  - Fill array members of precompute struct 
 24   
 25  - Use precomputed basis functions in argument loops 
 26   
 27  - Use linear combinations of dofs and basis functions for coefficients 
 28   
 29   
 30  With derivatives: 
 31   
 32  - Generate array members for local gradients for precompute struct 
 33   
 34  - Fill array members of precompute struct with local gradients 
 35   
 36  - Use precomputed basis function gradients with applied geometry mapping in argument loops 
 37   
 38  - Use linear combinations of dofs and mapped basis function gradients for coefficients 
 39   
 40  """ 
 41   
 42  import ufl 
 43  from uflacs.codeutils.target_formatter import analyse_terminalish 
 44  from uflacs.codeutils.format_code_structure import (format_code_structure, 
 45                                                      ArrayDecl, ArrayAccess) 
 46   
47 -def Assignment(lhs, rhs): # TODO: Implement in uflacs
48 return (lhs, " = ", rhs, ";") 49
50 -class FormArgumentCG(object):
51 - def __init__(self, farep, on_facet):
52 self.farep = farep 53 self.geomrep = farep.geomrep 54 self.on_facet = on_facet
55
56 - def precompute(self, terminalish, required):
57 self.pcelm = [] 58 59 fr = self.farep.formrep 60 61 # Figure out how many derivatives we need for which element 62 todo = set() 63 for o in terminalish: 64 t, ngrads, r = analyse_terminalish(o) 65 66 if isinstance(t, ufl.Argument): 67 count = t.count() 68 elif isinstance(t, ufl.Coefficient): 69 count = t.count() + fr.rank 70 else: 71 count = None 72 73 if count is not None: 74 elm = fr.formdata.elements[count] 75 todo.add((elm, ngrads, r)) 76 77 #prefix_template = "pc[%(iq)s]." 78 #phi_template = "%(diff)sphi%(elmnum)d[%(idof)s][%(icomp)s]" 79 80 # Loop over element representations and emit precomputation code 81 for elm, ngrads, r in todo: 82 assert not r # FIXME 83 assert not ngrads # FIXME 84 er = fr.element_reps[elm] 85 86 # Handle both mixed and simple elements same way, 87 # keeps it generic for now, some optimizations lost 88 89 #name = "d%d_phi%d" % (0, 0,) # FIXME: Need unique element count here 90 91 name = "phi%d" % (0,) # FIXME: Need unique element count here 92 shape = (er.local_dimension, er.value_size) 93 decl = ArrayDecl("double", name, shape) 94 data = decl, er, ngrads, r 95 self.pcelm.append(data)
96
97 - def _scratch(self):
98 if 0: 99 if isinstance(elm, ufl.MixedElement): 100 assert False # FIXME: Support arbitrary mixed elements 101 # Check for unique subelements of er and add to todo: 102 for ser in er.sub_elements: # TODO 103 #name = "d%d_phi%d" % (0, 0,) # FIXME: Need unique element count here 104 name = "phi%d" % (0,) # FIXME: Need unique element count here 105 shape = (er.local_dimension, er.value_size) # FIXME: symmetries? other? 106 decl = ArrayDecl("double", name, shape) 107 data = decl, ser, ngrads, r 108 self.pcelm.append(data) 109 else: 110 #name = "d%d_phi%d" % (0, 0,) # FIXME: Need unique element count here 111 name = "phi%d" % (0,) # FIXME: Need unique element count here 112 shape = (er.local_dimension, er.value_size) 113 decl = ArrayDecl("double", name, shape) 114 data = decl, er, ngrads, r 115 self.pcelm.append(data)
116
117 - def precomp_assignments(self):
118 prefix = self.iq_prefix() 119 code = [] 120 for data in self.pcelm: 121 decl, er, ngrads, r = data 122 for i in range(er.local_dimension): 123 for j in range(er.value_size): # FIXME: symmetries? other? 124 if ngrads == 0: 125 lhscode = (prefix, ArrayAccess(decl, (i,j))) 126 rhscode = "FIXME" #er.basis_function(...) 127 code.append(format_code_structure(Assignment(lhscode, rhscode))) 128 else: 129 assert False # FIXME 130 lhscode = (prefix, ArrayAccess(decl, (i,j))) 131 rhscode = "FIXME" #er.basis_function_derivative(...) 132 code.append(format_code_structure(Assignment(lhscode, rhscode))) 133 return code
134
135 - def precomp_declarations(self):
136 code = [] 137 for data in self.pcelm: 138 decl, er, ngrads, r = data 139 code.append(format_code_structure(decl)) 140 return code
141
143 code = [] 144 return code
145
146 - def generate_coefficient_declarations(self, coefficient, num_derivatives, restricted):
147 code = [''] 148 basename = "w%d" % coefficient.count() 149 150 shape = coefficient.shape() 151 symmetry = coefficient.element().symmetry() 152 size = product(shape) 153 nsd = self.geomrep.sfc_cell.nsd 154 155 #er = self.FIXME 156 157 restriction = None # FIXME 158 159 if num_derivatives == 0: 160 all_derivatives = [()] 161 else: 162 assert num_derivatives == 1 # FIXME 163 all_derivatives = [(d,) for d in range(nsd)] # FIXME: Permutations of (d,)*num_der.. 164 165 for derivatives in all_derivatives: 166 dstr = self.derivative_prefix(derivatives) 167 cstr = "[%d]" % (size,) if size > 1 else "" 168 decl = "double %s;" % (dstr + basename + cstr) 169 code += [decl] 170 171 # Iterate over components and flattened indices 172 assert not symmetry # FIXME 173 #comp2index, components = build_component_numbering(shape, symmetry) 174 #for index, component in components: 175 for component in compute_indices(shape): 176 compindex = component_to_index(component, shape) 177 178 terms = [] 179 nbf = 1 # er.nbf # FIXME 180 for dofindex in range(nbf): 181 dofname = self.gen_coefficient_dof_name(coefficient, dofindex, restriction) 182 doffunc = "1.0/*FIXME*/" # er.N_dof_code[dofindex][compindex] # "pc[iq]." # FIXME: Add to element ref 183 if doffunc not in ("0", "0.0"): 184 terms.append("%s * %s" % (dofname, doffunc)) 185 assert terms 186 expr = " + ".join(terms) 187 188 name = self.gen_coefficient_name(coefficient, derivatives, component, restriction) 189 assign = "%s = %s;" % (name, expr) 190 code += [assign] 191 192 return code
193
194 - def generate_argument_declarations(self, argument, num_derivatives, restricted):
195 code = [] 196 basename = "v%d" % argument.count() 197 198 shape = argument.shape() 199 symmetry = argument.element().symmetry() 200 size = product(shape) 201 nsd = self.geomrep.sfc_cell.nsd 202 203 restriction = None # FIXME 204 205 if num_derivatives == 0: 206 all_derivatives = [()] 207 else: 208 assert num_derivatives == 1 # FIXME 209 all_derivatives = [(d,) for d in range(nsd)] # FIXME: Permutations of (d,)*num_der.. 210 211 for derivatives in all_derivatives: 212 dstr = self.derivative_prefix(derivatives) 213 cstr = "[%d]" % (size,) if size > 1 else "" 214 decl = "double %s;" % (dstr + basename + cstr) 215 code += [decl] 216 217 # Iterate over components and flattened indices 218 assert not symmetry # FIXME 219 #comp2index, components = build_component_numbering(shape, symmetry) 220 #for index, component in components: 221 for component in compute_indices(shape): 222 index = component_to_index(component, shape) 223 224 name = self.gen_argument_name(argument, derivatives, component, restriction) 225 dstr = self.derivative_prefix(derivatives) 226 assert not restriction 227 # FIXME: If derivatives, apply geometry mapping! 228 element_id, element_index = 0, index # FIXME 229 expr = self.iq_prefix() + dstr + "phi%d[%d]" % (element_id, element_index) 230 #expr = "0.0" # FIXME 231 232 assign = "%s = %s;" % (name, expr) 233 code += [assign] 234 code += [''] 235 return code
236
237 - def gen_coefficient_dof_name(self, o, index, restriction):
238 assert not restriction # FIXME: How does this map into w array? 239 code = "w[%d][%d]" % (o.count(), index) 240 return code
241
242 - def gen_constant_coefficient_name(self, o, component, restriction):
243 assert not restriction # FIXME: How does this map into w array? 244 assert not o.element().symmetry() # FIXME: Ignoring symmetries here! 245 index = component_to_index(component, o.shape()) 246 code = self.gen_coefficient_dof_name(o, index, restriction) 247 return code
248
249 - def iq_prefix(self):
250 if self.on_facet: 251 prefix = "pc[facet][iq]." 252 else: 253 prefix = "pc[iq]." 254 return prefix
255
256 - def derivative_prefix(self, derivatives):
257 if derivatives: 258 dstr = "d%s_" % ("".join(map(str,sorted(derivatives))),) 259 else: 260 dstr = "" 261 return dstr
262
263 - def component_prefix(self, shape, component):
264 if shape: 265 index = component_to_index(component, shape) 266 cstr = "[%d]" % index 267 else: 268 cstr = "" 269 return cstr
270
271 - def component_decl(self, shape):
272 if shape: 273 size = product(shape) # FIXME symmetry 274 cstr = "[%d]" % size 275 else: 276 cstr = "" 277 return cstr
278
279 - def gen_form_argument_decl_name(self, basename, o, derivatives, restriction):
280 assert not restriction # FIXME 281 dstr = self.derivative_prefix(derivatives) 282 cstr = self.component_decl(o.shape()) 283 code = dstr + basename + str(o.count()) + cstr 284 return code
285
286 - def gen_coefficient_decl(self, o, derivatives, restriction):
287 return self.gen_form_argument_decl("w", o, derivatives, restriction)
288
289 - def gen_argument_decl(self, o, derivatives, restriction):
290 return self.gen_form_argument_decl("v", o, derivatives, restriction)
291
292 - def gen_form_argument_name(self, basename, o, derivatives, component, restriction):
293 assert not restriction # FIXME 294 dstr = self.derivative_prefix(derivatives) 295 cstr = self.component_prefix(o.shape(), component) 296 code = dstr + basename + str(o.count()) + cstr 297 return code
298
299 - def gen_coefficient_name(self, o, derivatives, component, restriction):
300 return self.gen_form_argument_name("w", o, derivatives, component, restriction)
301
302 - def gen_argument_name(self, o, derivatives, component, restriction):
303 return self.gen_form_argument_name("v", o, derivatives, component, restriction)
304