-
Notifications
You must be signed in to change notification settings - Fork 97
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
Generalization of FESpaceWithLastDofRemoved #396
Conversation
…fPotentiallyRemoved. FESpaceWithDofPotentiallyRemoved is though to be a future replacement for FESpaceWithLastDofRemoved, as it is based on the same concept, but it is more general as it lets the user to activate/deactivate whether to remove the dof at hand, and select the particular dof to be removed
…hLastDofRemoved, but on FESpaceWithDofPotentiallyRemoved,
…th_dof_potentially_removed
…th_dof_potentially_removed
fixed as an input argument (instead of being hard-coded to the last dof)
@@ -0,0 +1,185 @@ | |||
""" | |||
struct FESpaceWithDofPotentiallyRemoved{CS,RD} <: SingleFieldFESpace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FESpaceConstantFixed
or FESpaceWithConstantFixed
Note the difference between having the constants fixed and zero mean value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will use FESpaceWithConstantFixed
. The "potential" sense of the type is lost in the name, but we can leave with that.
Note the difference between having the constants fixed and zero mean value
Ok, good point. This space lets you fix the constant to an arbitrary value. The zero mean space fixes it to a particular value, i..e, the one which results in a zero mean function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This space lets you fix the constant to an arbitrary value.
FYI, the zero mean FE space currently assumes that the value is fixed exactly to 0 in the fixed dof of the FESpaceWithDofPotentiallyRemoved
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, the zero mean FE space currently assumes that the value is fixed exactly to 0 in the fixed dof of the FESpaceWithDofPotentiallyRemoved.
I do not see this statement. Doesn't it depend on the dirichlet values that come along with the trial FE space?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in faa32a3
function FESpaceWithDofPotentiallyRemoved(space::SingleFieldFESpace, | ||
remove_dof::Bool, | ||
dof_to_remove::Int=num_free_dofs(space)) | ||
s = "FESpaceWithDofPotentiallyRemoved can only be constructed from spaces without dirichlet dofs." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably do nothing in this case. It reminds me Balancing Neumann-Neumann local spaces. If the constant is already fixed, do nothing. Minor point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 0da971d.
dv .= view(_fv,f.dof_to_remove:f.dof_to_remove) | ||
(fv, dv) | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all these functions, we should decide which is the way to deal with the vector with one row eliminated in an efficient way. We could probably create a lazy vector doing this, using what we already have in Gridap. It is a quite obvious and would not involve any allocation instead of using views + vcat. Idem for the vector with only one touched value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another option is to implement a VectorWithIndexRemoved
in addition to the VectorWithIndexInserted
I commented above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will implement VectorWithIndexRemoved
and VectorWithIndexInserted
because it will be even more efficient than using lazy vectors, and can be useful for other scenarios as well. Besides, lazy vectors do not currently support write operations, broadcasted assignments, etc. Is there any fundamental reason behind this? or it is just because it is missing? I do not need it, anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in PR #401
r[j] = rj | ||
end | ||
r | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this? Couldn't we just change the data
vector in the Table
that represents the face dofs using a lazy vector that only touches one entry (to -1)? Probably create a method for adding these constraints in face_own_dofs
Table
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need this (or something in this direction) to be general. We cannot assume in general that we have a Table
for the face dofs. We could write (on top of this) a specialized version when we have a Table, but it seems premature optimization to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not have to be a table but just create a method that modifies the face_own_dofs
whatever it is. The idea is simple, only modify the plain global vector by touching one of, in the line of what you say above, e.g., VectorWithIndexChanged
(horrible name) with the global Ids that is being used in face_own_dofs
. This way, we do not need the code above, I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I worked on all the issues, except this one.
Just to double-check, you propose to remove the CellDofsWithDofFixed
data type, right?
Plus a possible alternative solution, that I do not enterily grasp. What I do not get is:
- "Probably create a method for adding these constraints in face_own_dofs Table."
- "It does not have to be a table but just create a method that modifies the face_own_dofs whatever it is."
face_own_dofs
is a Table returned by ReferenceFE
right? How is the link among this Table and get_cell_dofs()
such that we can achieve the desired effect?. I am sure that they key is here, and thus I am missing something important.
I have been exploring get_cell_dofs
references along the whole project, and there are a myriad of different data types that such method can return. Of course, all this data types can be conceptually seen as Vector{Vector{Int}}
. Besides, such methods, can be traversed in several ways, using a single loop, two nested loops, with and without caches, etc.
What it comes into my mind is to define a new Vector of vectors, which is built from another vector of vectors, and two indices, i
, j
, and a value v
, such that the new vector fulfills x[i][j]==v
. But this is in some sense what CellDofsWithDofFixed
is doing, so I expect to be missing something.
space::SingleFieldFESpace | ||
constraint_style::Val{CS} | ||
remove_dof::Val{RD} | ||
dof_to_remove::Int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use structs for these values, not true or false. Then, you don't need constraint_style
and remove_dof
, already in the param. You can create obvious getter for these. More readable code and more extensible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proposal (feedback welcomed):
abstract type ConstantStrategy end;
struct FixConstant <: ConstantStrategy end
struct DoNotFixConstant <: ConstantStrategy end
With constraint_style
I need help. May be @fverdugo can help here? What does True/False
mean for the constraint_style
of FE spaces? On the other hand, I guess this is a cross-cutting change, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With constraint_style I need help. May be @fverdugo can help here? What does True/False mean for the constraint_style of FE spaces? On the other hand, I guess this is a cross-cutting change, right?
constraint_style(V) == Val(false)
for un-constrained spaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done (partially) in 0da971d. In particular, I would prefer to transform constraint_style
into struct-like traits in a different PR. I expect that such implies a number of changes that deserve its separate PR.
_dv = similar(dv,eltype(dv),0) | ||
_fv = vcat(view(fv,1:f.dof_to_remove-1), | ||
dv, | ||
view(fv,f.dof_to_remove:length(fv))) # TODO lazy append |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try Gridap.Arrays.lazy_append
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other option is to implement a VectorWithIndexInserted
, or whatever name you like.
r[j] = rj | ||
end | ||
r | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need this (or something in this direction) to be general. We cannot assume in general that we have a Table
for the face dofs. We could write (on top of this) a specialized version when we have a Table, but it seems premature optimization to me.
|
||
function gather_free_and_dirichlet_values!( | ||
fv,dv,f::FESpaceWithDofPotentiallyRemoved{CS,true},cv) where {CS} | ||
_fv, _dv = gather_free_and_dirichlet_values(f.space,cv) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we reduce code duplication between gather_free_and_dirichlet_values
and gather_free_and_dirichlet_values!
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we reduce code duplication between gather_free_and_dirichlet_values and gather_free_and_dirichlet_values! ?
I guess the comment has become outdated after latest changes. Agreed? (See below)
function gather_free_and_dirichlet_values(
f::FESpaceWithConstantFixed{CS,FixConstant},cv) where {CS}
_fv, _dv = gather_free_and_dirichlet_values(f.space,cv)
@assert length(_dv) == 0
fv = VectorWithEntryRemoved(_fv,f.dof_to_fix)
dv = _fv[f.dof_to_fix:f.dof_to_fix]
(fv, dv)
end
function gather_free_and_dirichlet_values!(
fv,dv,f::FESpaceWithConstantFixed{CS,FixConstant},cv) where {CS}
_fv, _dv = gather_free_and_dirichlet_values(f.space,cv)
@assert length(_dv) == 0
fv .= VectorWithEntryRemoved(_fv,f.dof_to_fix)
dv[1] = _fv[f.dof_to_fix]
(fv, dv)
end
dv .= view(_fv,f.dof_to_remove:f.dof_to_remove) | ||
(fv, dv) | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another option is to implement a VectorWithIndexRemoved
in addition to the VectorWithIndexInserted
I commented above.
@@ -0,0 +1,185 @@ | |||
""" | |||
struct FESpaceWithDofPotentiallyRemoved{CS,RD} <: SingleFieldFESpace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This space lets you fix the constant to an arbitrary value.
FYI, the zero mean FE space currently assumes that the value is fixed exactly to 0 in the fixed dof of the FESpaceWithDofPotentiallyRemoved
.
…ith_dof_potentially_removed
Codecov Report
@@ Coverage Diff @@
## master #396 +/- ##
==========================================
- Coverage 87.49% 87.26% -0.24%
==========================================
Files 156 158 +2
Lines 11049 11092 +43
==========================================
+ Hits 9667 9679 +12
- Misses 1382 1413 +31
Continue to review full report at Codecov.
|
@amartinhuertas just a minor thing. Can you add a temporarily alias
and comment in NEWS.md, deprecated section, that " the name With this, the code is 100% backwards compatible and we can publish your changes via v0.14.1 ASAP so that you can use a registered Gridap version in GridapDistributed. We need to remember to delete the alias in 0.15. |
Sure! But take into account that it is not a single renaming. The interface of the constructor has changed. Do we still follow the deprecated path? |
Then, use Gridap.jl/src/FESpaces/SingleFieldFESpaces.jl Line 172 in 5faa6e0
|
I was not precise enough in my previous message, sorry about that. The new data type has introduced a lot of changes with respect to the previous data type. It has a a new template parameter! I can start using deprecate everywhere, but I have the impression that I am some how maintaining the previous data type alive. I am not sure it this is what we want. I guess that you want to avoid a new minor relese right? (0.15) |
the old type is a trivial particular case of the new one. We only need these temporary defs until 0.15: export FESpaceWithLastDofRemoved
const FESpaceWithLastDofRemoved{CS} = FESpaceWithConstantFixed{CS,FixConstant}
@deprecate FESpaceWithLastDofRemoved(space::SingleFieldFESpace) = FESpaceWithConstantFixed(space,true) this 3 lines allow us to publish 0.14.1 ASAP so that you can use it in GridapDistributed |
FYI, from the julia doc:
|
Ok, good call. I was expecting something more dirty to keep the old data type alive. New lesson learned! Done! |
I realized that this PR was already merged, perhaps accidentally? I will open a brand new one, I cannot re-open this one. |
…oved Fe space with dof potentially removed (pending changes from PR #396)
As agreed, this PR:
FESpaceWithLastDofRemoved
byFESpaceWithDofPotentiallyRemoved
, a more general version with two additional features:ZeroMeanFESpace
such that it now relies onFESpaceWithDofPotentiallyRemoved
.(not directly related to this PR, but FYI,
FESpaceWithDofPotentiallyRemoved
is already being succesfully used by the parallel distributed-memory version ofZeroMeanFESpace
; click here for more details).To simplify things, I think that two main concerns should be object to code review:
FESpaceWithDofPotentiallyRemoved
? (I used the one that we came up as a joke, but after thinking a bit, I have no better alternative).FESpaceWithLastDofRemoved
. In particular, here and here. Can we leave with that? If not, do you foresee any possible solution to avoid this?@amartinhuertas