This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Replace all node values of a subfunction above a certain value

+1 vote

Hi, i basically would like to replace all node values above a certain value with an another

I have this:

# z is a mixed function, i extract one subfunction
csub = z.sub(1, deepcopy=True) 
# the function is converted in an array
csub_array = csub.vector().array()

I would like to do somehting like this:

# Replace array value superior to c_max 
np.place(csub_array, csub_array>c_max , new_value)
#Re insert the array into the subfunction
assign(z.sub(1), csub_array.vector())

The assign function does not work (AttributeError: 'numpy.ndarray' object has no attribute 'vector').

Do you know the correct syntax, that keep the same 'mask' approach?
Regards,

asked Feb 28, 2017 by fussegli FEniCS Novice (700 points)

1 Answer

+1 vote
 
Best answer

Hi,

the mistake is in the last line of your code as you do not have to provide the 'csub_array.vector()' (in fact, csub_array is a numpy vector, which does not even have a 'vector()' attribute, that's why you get the error) but the manipulated 'csub' function instead.
To clarify things, consider the following minimal working example (made in version 2016.1.0):

from dolfin import *

mesh = UnitSquareMesh(5,5)

V  = FunctionSpace(mesh, "CG", 1)
W  = FunctionSpace(mesh, "CG", 1)          
M  = MixedFunctionSpace([V,W])

Phi = Function(M)
# Make a deepcopy of the subfunctions
phi, tau = Phi.split(deepcopy = True)

# Manipulate one of the subfunctions 
# of course you can also manipulate phi.vector().array() here
val = Expression('1-x[0]')
assign(phi,interpolate(val,V))

# Confirms that the manipulated phi is clearly not assigned to Phi.sub(0):
print 'Before assign', assemble(dot(Phi.sub(0)-phi,Phi.sub(0)-phi)*dx)

# Assign phi to Phi.sub(0):
assign(Phi.sub(0),phi)
print 'After assign', assemble(dot(Phi.sub(0)-phi,Phi.sub(0)-phi)*dx)
answered Feb 28, 2017 by jmmal FEniCS User (5,890 points)
selected Feb 28, 2017 by fussegli

Hi,
Thanks for the quick answer.
Unfortunately, in my case, i do not want to replace all the values of the subfunction. I would like to keep all the nodes values, except those above a certain values, and then replace only these ones with a constant value i know (thus apply a mask).

Then, this way does not suit well my case i think:

val = Expression('1-x[0]')
assign(phi,interpolate(val,V))

I am looking something close to this...

val (val>= value) = new value # That's the matlab syntax for an array
numpy.place(val , val >value, new_value) # That's the python syntax for an array

... but for a function, not an array.

So, to reformulate my question: how to apply a mask to a fenics function?

EDIT: ok, the solution was in front of me:)

#Extract subfunction
csub = z.sub(1, deepcopy=True)
# The function is converted in an array
csub_array = csub.vector().array()
# Apply a mask
numpy.place(csub_array, csub_array>c_max, new_value)
# Insert the new array in the fuction
csub.vector()[:] = csub_array   
# And assign it to the mixed function
assign(z.sub(1),csub)   

There you go ;) So I guess you managed? :)

Yes. It works very well now. Thanks!

...