How do I set metadata of an existing Measure instance?
91
views
0
I want to be able to set metadata, specifically the quadrature degree, of an already existing Measure instance.
Based on what I read from
I tried
but unfortunately, Measure.__call__, actually returns a new instance, and does not modify the caller in place as I had expected from reading the doc.
I also tried
which throws the error
So how can I do this? Essentially I am looking for setter method for Measure.metadata. I've read the whole doc and tried digging around with dx.__dict__ or dx._asdict(). I haven't looked at the source code of Measure yet.
I'm using FEniCS 2017.2.0.
Edit: AllAnswered isn't indenting the outputs that I tried to indent, so feel free to suggest a way to format the output from
Based on what I read from
help(fenics.Measure)
,Help on class Measure in module ufl.measure:
class Measure(builtins.object)
 Methods defined here:

 __add__(self, other)
 Add two measures (self+other).

 Creates an intermediate object used for the notation

 expr * (dx(1) + dx(2)) := expr * dx(1) + expr * dx(2)

 __call__(self, subdomain_id=None, metadata=None, domain=None, subdomain_data=None, degree=None, scheme=None, rule=None)
 Reconfigure measure with new domain specification or metadata.

I tried
import fenics
dx = fenics.Measure("dx")
dx8 = fenics.Measure("dx", metadata={"quadrature_degree": 8})
dx(metadata={"quadrature_degree": 8})
assert(dx.metadata() == dx8.metadata())
but unfortunately, Measure.__call__, actually returns a new instance, and does not modify the caller in place as I had expected from reading the doc.
I also tried
dx.metadata()["quadrature_degree"] = 8
which throws the error
This is a frozen unique empty dictionary object, inserting values is an error.
So how can I do this? Essentially I am looking for setter method for Measure.metadata. I've read the whole doc and tried digging around with dx.__dict__ or dx._asdict(). I haven't looked at the source code of Measure yet.
I'm using FEniCS 2017.2.0.
Edit: AllAnswered isn't indenting the outputs that I tried to indent, so feel free to suggest a way to format the output from
help
and the error.
Community: FEniCS Project
You could always do
I did some tinkering and found that the "reconstruct" method seems to be a reliable way to set specific attributes (without altering others on a seeminglyrandom basis, the way __call__ does). It still technically creates a new instance, but you may or may not find the below test code useful:
dx._metadata = dx(metadata={"quadrature_degree": 8}).metadata()
but I don't think that's considered best practice...I did some tinkering and found that the "reconstruct" method seems to be a reliable way to set specific attributes (without altering others on a seeminglyrandom basis, the way __call__ does). It still technically creates a new instance, but you may or may not find the below test code useful:
from dolfin import *
# This adds to and/or overwrites specific attributes of the an
# existing metadata dictionary.
def addMeta(m1,m2):
import ufl.utils.dicts
if(not isinstance(m1,ufl.utils.dicts.EmptyDictType)):
return m1.update(m2)
return m2
print(repr(dx)+'\n')
dx = dx.reconstruct(metadata=addMeta(dx.metadata(),{"a":"b"}))
print(repr(dx)+'\n')
dx = dx.reconstruct(subdomain_id=0)
print(repr(dx)+'\n')
dx = dx.reconstruct(subdomain_data
=MeshFunction("size_t",UnitSquareMesh(10,10),2))
print(repr(dx)+'\n')
dx = dx.reconstruct(metadata=addMeta(dx.metadata(),{"quadrate_degree":8}))
print(repr(dx)+'\n')
dx = dx.reconstruct(metadata=addMeta(dx.metadata(),
{"quadrate_degree":7, "c":"d"}))
print(repr(dx)+'\n')
written
11 weeks ago by
David Kamensky
Unfortunately creating a new instance doesn't solve my current problem; but thanks for pointing out the difference between __call__ and reconstruct. I'm sure I would have been perplexed by this at some point.
written
10 weeks ago by
Alexander G. Zimmerman
1 Answer
2
As David suggested in the comments, the following runs without error:
Given how metadata is "hidden" without an obvious setter, I'm assuming we aren't supposed to do this. That being said, I haven't actually tested if this has any adverse effects when performing quadrature.
import fenics
dx = fenics.Measure("dx")
dx8 = fenics.Measure("dx", metadata={"quadrature_degree": 8})
dx._metadata = dx8.metadata()
assert(dx.metadata() == dx8.metadata())
Given how metadata is "hidden" without an obvious setter, I'm assuming we aren't supposed to do this. That being said, I haven't actually tested if this has any adverse effects when performing quadrature.
Please login to add an answer/comment or follow this question.
but this throws the error "AttributeError: 'Measure' object attribute 'metadata' is readonly".
so perhaps FEniCS purposefully does not allow me to do this.