Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

creating DG0 feilds computationally without floating point error. #4022

Open
karimnorouzi opened this issue Feb 10, 2025 · 13 comments
Open

creating DG0 feilds computationally without floating point error. #4022

karimnorouzi opened this issue Feb 10, 2025 · 13 comments

Comments

@karimnorouzi
Copy link

when we want to create a DG0 field like:

assemble(sum(Constant(v)/CellVolume(mesh)*dx(i+1) for i, v in enumerate(val)))

the floating point error sometimes creates large distortion.
as per recommandation from Colin Cotter:

"This could be fixed by adding floor/ceil to UFL (and then handling in the form compiler).
6:03
If you raise this as an issue in Firedrake then someone can give you advise on how to do it."

How to do this ?

thanks.

@dham
Copy link
Member

dham commented Feb 10, 2025

Can you not get what you want with conditional?

There's nothing wrong with adding floor and ceil to UFL other than it'll cause you a lot of legwork (the differentiation rules, for example). If you can get away with conditional then your life will be easier.

@karimnorouzi
Copy link
Author

karimnorouzi commented Feb 10, 2025

Is there a way to use something like this:

def Parameter(vals, FS):
    par = Function(FS)
    for j in range(len(vals)):
        par_loop(("{[i] : 0 <= i < f.dofs}", "f[i, 0] = {}".format(vals[j])),
             dx(j+1),
             {"f": (par, WRITE)})
    return par

mu = Parameter([ 1, 2] , fd.FunctionSpace(mesh, "DG", 0))

but correctly ? This obviously does not work for DG0

@pbrubeck
Copy link
Contributor

Could please you send an example where the round-off error is noticeable?
You should only get large round-off errors if the values you are prescribing are astronomically large:

mesh = UnitSquareMesh(1000, 2)
V = FunctionSpace(mesh, "DG", 0)
val = 2E10
c = assemble(val*TestFunction(V)/CellVolume(mesh)*dx)
max(abs(c.dat.data[:] - val))  # --> np.float64(3.814697265625e-06)

@pbrubeck
Copy link
Contributor

pbrubeck commented Feb 10, 2025

Here's how you assign int data on a subdomain:

from firedrake import *

def assign_subdomain(f, val, subdomain):
    mesh = f.function_space().mesh()
    f.assign(val, subset=mesh.cell_subset(subdomain))

mesh = UnitSquareMesh(1, 1)
q = Function(FunctionSpace(mesh, "DG", 0), dtype=int)
q.dat.data[1] = 1
rmesh = RelabeledMesh(mesh, (q,), (1,))
W = FunctionSpace(rmesh, "DG", 0)
w = Function(W, dtype=int)

assign_subdomain(w, 1E10, 1)

print(w.dat.data) # array([          0, 10000000000])

We should probably make this more user-friendly.

@pbrubeck
Copy link
Contributor

@ksagiyam could we allow subset to be an iterable of subdomain_ids? And internally construct the subset via mesh.cell_subset?

@karimnorouzi
Copy link
Author

karimnorouzi commented Feb 10, 2025

dtype = int does not work with VTKFile

But the solution is very good. I like it.

@karimnorouzi
Copy link
Author

karimnorouzi commented Feb 10, 2025

def assign_subdomain(f, vals, subdomains):

mesh = f.function_space().mesh()
for v, s in zip(vals, subdomains):
            f.assign(v, subset=mesh.cell_subset(s))

is this ok for multiple valsues and subdomains ?

@ksagiyam
Copy link
Contributor

@pbrubeck I think the potential problem is that, if we assign to a CG function with some cell subdomain IDs, what should happen at the subdomain interface is not clear. It is clear for DG functions.

@pbrubeck
Copy link
Contributor

pbrubeck commented Feb 10, 2025

Wouldn't the obvious operation assign dofs on the closure of each cell in the subdomain?

@ksagiyam
Copy link
Contributor

I think cg_assignee.assign(cg_assigner, subdomain) is well defined only when cg_assignee and cg_assigner have the same values at the subdomain interface, and we can not force users' code to satisfy this condition (unless we inspect data). Our current implementation might not be user friendly, but causes no ambiguity regarding this point.

@karimnorouzi
Copy link
Author

this is Ok for DG functions right ?
for CG functions this should not work as the other element sharing the interface can be affected ?

@pbrubeck
Copy link
Contributor

this is Ok for DG functions right ? for CG functions this should not work as the other element sharing the interface can be affected ?

Yes, for DG there's no confusion

@pbrubeck
Copy link
Contributor

pbrubeck commented Feb 10, 2025

@ksagiyam I think for CG we can agree on a well defined operation, by considering the subspace of basis functions supported on the closure of cells in the subdomain.

DirichletBC uses this subset mechanism for continuous Functions, except that subdomains are constructed as subsets of the facets (we even allow them to be taken from the interior). That is why the ordering of bcs gives different results: [DirichletBC(V, g1, sub1), DirichletBC(V, g2, sub2)] writes g2 on the intersection of sub1 and sub2, while the reversed order would write g1 instead. So we are already exposing similar ambiguities to the user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants