Dear Peter,
sorry for the delay in responding.
On Fri, 22 Apr 2011 16:05:11 +0200, Peter17 <peter017(a)gmail.com> wrote:
Thank you very much for those informations. I think I
need a few more
details so I can make my code work. I have tried different
possibilities but I'm afraid I'm still thinking the wrong way, so,
there are things I still don't understand...
I have objects (material1, material2...) which contain the constants
(material1.C, material2.C, material1.mu, etc.) that I need to access
when calculating the fluxes. C is a 6x6 matrix.
1) Do I need to create a space-dependent function for each constant
(I'd like not to), or can I rely on Field() to make only "a reference
to the material object" be space-dependent?
i.e. Can I use this?
material_elements = {}
for key in materials.keys():
material_elements[key] = set(mesh_data.tag_to_elements[key])
def mat_val(x, el):
for key in materials.keys():
if el in material_elements[key]:
return key
raise ValueError, "Material not found for this element"
op = MyOperator(dim=dim,
mat_val = make_tdep_given(mat_val),
materials = materials,
...
)
And, then, materials[material].mu, materials[material].C
Or do I need a C_val, mu_val, etc.?
Here's a hack that might work for you. Create a scalar field with 1/0
flags for each of your different materials. You can then easily compute
whatever material properties are necessary, e.g.
From pymbolic.primitives import IfPositive
mat_prop = IfPositive(mat_flag, 15, 1) # this works like if-then-else
Alternately, you can also feed node coordinate data back into hedge and
compute your material properties based on that. See
hedge.data.CompiledExpressionData for an example of this.
2) I have packed this in a vector, so, I have:
def __init__(self,
dim,
mat_val,
materials,
...
):
self.mat_val = mat_val
...
# In rsh:
constants = self.mat_val
return compiled_op_template(q=q,constants=constants,**extra_kwargs)
# ^^^^^ Is this right? I am not touching extra_kwargs...
Only scalars, fields (i.e. vectors of nodal data), and object arrays of
them are allowed to be passed to compiled optemplates. So depending on
what mat_val is, that's either ok or not.
# In op_template:
q = make_vector_field('q', dim+self.dimF[dim])
constants = make_vector_field('constants', 1)
material = constants
# In the flux calculation, I try to access materials[material].mu but I get:
TypeError: unhashable type: 'numpy.ndarray'
Flux calculation is a bit special. Fluxes are expressed in terms of a
vector of input values that are allowed to be 'regular' hedge
expressions. Within the flux, however, they're only referred to by their
position (i.e. index) within the input vector. That's why all the flux
specifications create new "flux" placeholders. (If you're questioning
this design choice, note that they have to be different variables anyway
since you must choose between interior/exterior values.)
I assume your problem comes from trying to use 'regular' hedge
optemplate variables within your flux.
3) I have read
http://wiki.tiker.net/Hedge/HowTo/DealingwithOperators
but I don't understand when exactly I have to use Field() and when I
can pass the values in function calls...
What do you mean by 'function calls'? Note that hedge works by building
a symbolic operator first, then connecting it to a discretization, then
generating code for it. So within the creation of the abstract operator,
you may not use actual discretization vectors, only symbolic
names. These symbolic names ("Field", "make_vector_field" are then
filled with life by passing their values to the compiled optemplate.
Hope this helps,
Andreas