From a43b645ccfbfb633c6544f45ada02292a7cc8d8c Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Mon, 2 Mar 2020 16:07:05 +1100 Subject: [PATCH 01/51] Corrected some typos and added a PhysicalBasesTests.jl --- src/Arrays/Tables.jl | 6 +- src/FESpaces/CLagrangianFESpaces.jl | 4 +- src/FESpaces/ConformingFESpaces.jl | 3 +- src/FESpaces/CurlConformingFESpaces.jl | 2 +- src/FESpaces/DiscontinuousFESpaces.jl | 2 +- src/FESpaces/DivConformingFESpaces.jl | 2 +- src/FESpaces/FESpaces.jl | 2 +- src/FESpaces/UnconstrainedFESpaces.jl | 30 ++++----- src/ReferenceFEs/LagrangianDofBases.jl | 4 +- test/FESpacesTests/FESpaceFactoriesTests.jl | 12 ++-- test/FESpacesTests/PhysicalBasesTests.jl | 67 +++++++++++++++++++ .../UnconstrainedFESpacesTests.jl | 2 +- 12 files changed, 100 insertions(+), 36 deletions(-) create mode 100644 test/FESpacesTests/PhysicalBasesTests.jl diff --git a/src/Arrays/Tables.jl b/src/Arrays/Tables.jl index 1f18fb42e..52e2a5cf5 100644 --- a/src/Arrays/Tables.jl +++ b/src/Arrays/Tables.jl @@ -6,7 +6,7 @@ ptrs::Vector{P} end -Type representing a list of lists (i.e., a table) in +Type representing a list of lists (i.e., a table) in compressed format. """ struct Table{T,P} <: AbstractVector{Vector{T}} @@ -337,7 +337,7 @@ end """ collect1d(a) -Equivalent to +Equivalent to [a[i] for in 1:length(a)] """ @@ -437,5 +437,3 @@ function from_dict(::Type{Table{T,P}}, dict::Dict{Symbol,Any}) where {T,P} ptrs::Vector{P} = dict[:ptrs] Table(data,ptrs) end - - diff --git a/src/FESpaces/CLagrangianFESpaces.jl b/src/FESpaces/CLagrangianFESpaces.jl index ddc8187a5..0a58c000d 100644 --- a/src/FESpaces/CLagrangianFESpaces.jl +++ b/src/FESpaces/CLagrangianFESpaces.jl @@ -9,7 +9,7 @@ end """ struct CLagrangianFESpace{S} <: SingleFieldFESpace - space::UnsconstrainedFESpace + space::UnconstrainedFESpace grid::Grid dof_to_node::Vector{Int} dof_to_comp::Vector{Int8} @@ -114,7 +114,7 @@ function _generate_clargangian_fespace(T,grid) dirichlet_cells = Int[] ntags = 0 - space = UnsconstrainedFESpace( + space = UnconstrainedFESpace( nfree, ndirichlet, cell_dofs, diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index 0f0e28fd4..f711bcdcb 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -69,7 +69,7 @@ function GradConformingFESpace( cell_shapefuns, cell_dof_basis = compute_cell_space(reffes, cell_to_ctype, cell_map) - UnsconstrainedFESpace( + UnconstrainedFESpace( nfree, ndirichlet, cell_dofs, @@ -526,4 +526,3 @@ end ### getindex!(cache,a,cell) ###end ### - diff --git a/src/FESpaces/CurlConformingFESpaces.jl b/src/FESpaces/CurlConformingFESpaces.jl index d1461a1c2..ac03902a2 100644 --- a/src/FESpaces/CurlConformingFESpaces.jl +++ b/src/FESpaces/CurlConformingFESpaces.jl @@ -26,7 +26,7 @@ function CurlConformingFESpace( cell_shapefuns, cell_dof_basis = _compute_hcurl_cell_space(reffes, cell_to_ctype, cell_map) - UnsconstrainedFESpace( + UnconstrainedFESpace( nfree, ndirichlet, cell_dofs, diff --git a/src/FESpaces/DiscontinuousFESpaces.jl b/src/FESpaces/DiscontinuousFESpaces.jl index 15677f5af..4778de575 100644 --- a/src/FESpaces/DiscontinuousFESpaces.jl +++ b/src/FESpaces/DiscontinuousFESpaces.jl @@ -16,7 +16,7 @@ function DiscontinuousFESpace(reffes::Vector{<:ReferenceFE}, trian::Triangulatio cell_shapefuns, cell_dof_basis = compute_cell_space(reffes, cell_to_ctype, cell_map) - UnsconstrainedFESpace( + UnconstrainedFESpace( nfree, ndirichlet, cell_dofs, diff --git a/src/FESpaces/DivConformingFESpaces.jl b/src/FESpaces/DivConformingFESpaces.jl index e93351c2a..18a20dc54 100644 --- a/src/FESpaces/DivConformingFESpaces.jl +++ b/src/FESpaces/DivConformingFESpaces.jl @@ -25,7 +25,7 @@ function DivConformingFESpace( cell_shapefuns, cell_dof_basis = _compute_hdiv_cell_space(reffes, cell_to_ctype, cell_map) - UnsconstrainedFESpace( + UnconstrainedFESpace( nfree, ndirichlet, cell_dofs, diff --git a/src/FESpaces/FESpaces.jl b/src/FESpaces/FESpaces.jl index 1a8f2a459..530e35cbf 100644 --- a/src/FESpaces/FESpaces.jl +++ b/src/FESpaces/FESpaces.jl @@ -123,7 +123,7 @@ export get_cell_dof_basis export SingleFieldFEFunction -export UnsconstrainedFESpace +export UnconstrainedFESpace export GradConformingFESpace export DiscontinuousFESpace diff --git a/src/FESpaces/UnconstrainedFESpaces.jl b/src/FESpaces/UnconstrainedFESpaces.jl index 5a40e124e..213a16140 100644 --- a/src/FESpaces/UnconstrainedFESpaces.jl +++ b/src/FESpaces/UnconstrainedFESpaces.jl @@ -3,7 +3,7 @@ Generic implementation of an unconstrained single-field FE space Private fields and type parameters """ -struct UnsconstrainedFESpace{A,B,C} <: SingleFieldFESpace +struct UnconstrainedFESpace{A,B,C} <: SingleFieldFESpace nfree::Int ndirichlet::Int cell_dofs::A @@ -15,7 +15,7 @@ struct UnsconstrainedFESpace{A,B,C} <: SingleFieldFESpace @doc """ """ - function UnsconstrainedFESpace( + function UnconstrainedFESpace( nfree::Int, ndirichlet::Int, cell_dofs::AbstractArray, @@ -46,53 +46,53 @@ end # FESpace interface -constraint_style(::Type{<:UnsconstrainedFESpace}) = Val{false}() +constraint_style(::Type{<:UnconstrainedFESpace}) = Val{false}() -function num_free_dofs(f::UnsconstrainedFESpace) +function num_free_dofs(f::UnconstrainedFESpace) f.nfree end -function get_cell_basis(f::UnsconstrainedFESpace) +function get_cell_basis(f::UnconstrainedFESpace) f.cell_basis end -function zero_free_values(::Type{T},f::UnsconstrainedFESpace) where T +function zero_free_values(::Type{T},f::UnconstrainedFESpace) where T zeros(T,num_free_dofs(f)) end # SingleFieldFESpace interface -function get_cell_dofs(f::UnsconstrainedFESpace) +function get_cell_dofs(f::UnconstrainedFESpace) f.cell_dofs end -function get_cell_dof_basis(f::UnsconstrainedFESpace) +function get_cell_dof_basis(f::UnconstrainedFESpace) f.cell_dof_basis end -function num_dirichlet_dofs(f::UnsconstrainedFESpace) +function num_dirichlet_dofs(f::UnconstrainedFESpace) f.ndirichlet end -function num_dirichlet_tags(f::UnsconstrainedFESpace) +function num_dirichlet_tags(f::UnconstrainedFESpace) f.ntags end -function zero_dirichlet_values(f::UnsconstrainedFESpace) +function zero_dirichlet_values(f::UnconstrainedFESpace) T = Float64 # TODO zeros(T,num_dirichlet_dofs(f)) end -function get_dirichlet_dof_tag(f::UnsconstrainedFESpace) +function get_dirichlet_dof_tag(f::UnconstrainedFESpace) f.dirichlet_dof_tag end -function scatter_free_and_dirichlet_values(f::UnsconstrainedFESpace,free_values,dirichlet_values) +function scatter_free_and_dirichlet_values(f::UnconstrainedFESpace,free_values,dirichlet_values) cell_dofs = get_cell_dofs(f) LocalToGlobalPosNegArray(cell_dofs,free_values,dirichlet_values) end -function gather_free_and_dirichlet_values(f::UnsconstrainedFESpace,cell_vals) +function gather_free_and_dirichlet_values(f::UnconstrainedFESpace,cell_vals) cell_dofs = get_cell_dofs(f) cache_vals = array_cache(cell_vals) @@ -113,7 +113,7 @@ function gather_free_and_dirichlet_values(f::UnsconstrainedFESpace,cell_vals) (free_vals, dirichlet_vals) end -function gather_dirichlet_values(f::UnsconstrainedFESpace,cell_vals) +function gather_dirichlet_values(f::UnconstrainedFESpace,cell_vals) cell_dofs = get_cell_dofs(f) cache_vals = array_cache(cell_vals) diff --git a/src/ReferenceFEs/LagrangianDofBases.jl b/src/ReferenceFEs/LagrangianDofBases.jl index ba9598acc..50e254942 100644 --- a/src/ReferenceFEs/LagrangianDofBases.jl +++ b/src/ReferenceFEs/LagrangianDofBases.jl @@ -36,6 +36,8 @@ function LagrangianDofBasis(::Type{T},nodes::Vector{<:Point}) where T LagrangianDofBasis(nodes,r...) end +get_nodes(b::LagrangianDofBasis) = b.nodes + function _generate_dof_layout_node_major(::Type{<:Real},nnodes::Integer) ndofs = nnodes dof_to_comp = ones(Int,ndofs) @@ -127,5 +129,3 @@ function _evaluate_lagr_dof!(c::AbstractMatrix,node_pdof_comp_to_val,node_and_co end r end - - diff --git a/test/FESpacesTests/FESpaceFactoriesTests.jl b/test/FESpacesTests/FESpaceFactoriesTests.jl index f0d6431ce..1677afbd5 100644 --- a/test/FESpacesTests/FESpaceFactoriesTests.jl +++ b/test/FESpacesTests/FESpaceFactoriesTests.jl @@ -19,7 +19,7 @@ V = FESpace( order=order, conformity=:L2) -@test isa(V,UnsconstrainedFESpace) +@test isa(V,UnconstrainedFESpace) V = FESpace( model=model, @@ -28,7 +28,7 @@ V = FESpace( order=order, conformity=:H1) -@test isa(V,UnsconstrainedFESpace) +@test isa(V,UnconstrainedFESpace) V = FESpace( model=model, @@ -38,7 +38,7 @@ V = FESpace( order=order, dirichlet_tags="boundary") -@test isa(V,UnsconstrainedFESpace) +@test isa(V,UnconstrainedFESpace) D = num_point_dims(model) @@ -51,7 +51,7 @@ V = FESpace( dirichlet_tags="boundary", dirichlet_masks=(true,false)) -@test isa(V,UnsconstrainedFESpace) +@test isa(V,UnconstrainedFESpace) V = FESpace( model=model, @@ -62,7 +62,7 @@ V = FESpace( dirichlet_tags=[1,2], dirichlet_masks=[(true,false),(false,true)]) -@test isa(V,UnsconstrainedFESpace) +@test isa(V,UnconstrainedFESpace) V = FESpace( model=model, @@ -71,7 +71,7 @@ V = FESpace( order=order, conformity=:L2) -@test isa(V,UnsconstrainedFESpace) +@test isa(V,UnconstrainedFESpace) V = FESpace( model=model, diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl new file mode 100644 index 000000000..f4fa7c20f --- /dev/null +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -0,0 +1,67 @@ +using Gridap +using Gridap.ReferenceFEs +using Gridap.Geometry +using Gridap.Arrays +using Gridap.Fields +using Gridap.FESpaces +using Gridap.Polynomials + +# Start with a PhysicalSpaceCellBasis + +domain = (0,1) +partition = (2) +model = CartesianDiscreteModel(domain,partition) +order = 1 + +trian = get_triangulation(model) +polytopes = get_polytopes(model) +T = Float64 + +# In fact, Lagrangian not needed, minor thing +reffes = [LagrangianRefFE(T,p,order) for p in polytopes] + +dof_basis = map(get_dof_basis,reffes) + +cell_to_ctype = get_cell_type(grid_topology) + +cell_dof_basis = CompressedArray(dof_basis,cell_to_ctype) + +grid = get_grid(model) + +cell_map = get_cell_map(grid) + +prebasis = map(get_prebasis,reffes) + +grid_topology = get_grid_topology(model) + +cell_to_ctype = get_cell_type(grid_topology) + +refprebasis = CompressedArray(prebasis,cell_to_ctype) + +cell_prebasis = attachmap(refprebasis,cell_map) + +# Now for each cell in the mesh we do + +cell = 1 + +ns = get_nodes(cell_dof_basis[cell]) + +pns = evaluate(cell_map[cell],ns) + +p_changeofbasis = evaluate(cell_prebasis[cell],pns) + +# So if we want to evaluate the basis or its gradient in a set of points, we can +# do the same as `BasisFromChangeOfBasis` but the difference being that the computation +# of the change matrix is a cell_array. + +# I think we should create a new `CellBasis` struct that at the get_index level +# performs all these computations, makes use of cache arrays, and provides a +# basis. Before doing this, I want to discuss with Francesc what can we use +# of the pre-existing arrays, etc. + + +grad_cpb = gradient(cell_prebasis) + +evaluate(grad_cpb[cell],pns) + +gradient(refprebasis) diff --git a/test/FESpacesTests/UnconstrainedFESpacesTests.jl b/test/FESpacesTests/UnconstrainedFESpacesTests.jl index a5d41133b..a29d3ee6c 100644 --- a/test/FESpacesTests/UnconstrainedFESpacesTests.jl +++ b/test/FESpacesTests/UnconstrainedFESpacesTests.jl @@ -1,4 +1,4 @@ -module UnsconstrainedFESpacesTests +module UnconstrainedFESpacesTests using Test using Gridap.Arrays From a826fc8c4f3cc70cf5956431a1c6b6413adbbdc4 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Tue, 3 Mar 2020 10:58:41 +1100 Subject: [PATCH 02/51] Problem with zero() --- src/Arrays/Apply.jl | 3 +- src/Inference/Inference.jl | 6 +-- test/FESpacesTests/PhysicalBasesTests.jl | 62 +++++++++++++++++++++++- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/Arrays/Apply.jl b/src/Arrays/Apply.jl index bf26d9803..8c2150d72 100644 --- a/src/Arrays/Apply.jl +++ b/src/Arrays/Apply.jl @@ -118,7 +118,7 @@ end """ apply_all(f::Tuple,a::AbstractArray...) -> Tuple -Numerically equivalent to +Numerically equivalent to tuple( ( apply(fi, a...) for fi in f)... ) @@ -352,4 +352,3 @@ Base.IndexStyle(::Type{<:ArrayWithCounter{T,N,A}}) where {T,A,N} = IndexStyle(A) function reset_counter!(a::ArrayWithCounter) a.counter[:] .= 0 end - diff --git a/src/Inference/Inference.jl b/src/Inference/Inference.jl index d15766312..b4358c32b 100644 --- a/src/Inference/Inference.jl +++ b/src/Inference/Inference.jl @@ -31,8 +31,8 @@ The underlying implementation uses the function [`testargs`](@ref) to generate some test values in order to call the function and determine the returned type. This mechanism does not use `Base._return_type`. One of the advantages is that the given function `f` is called, and thus, meaningful error messages -will be displayed if there is any error in `f`. - +will be displayed if there is any error in `f`. + """ function return_type(f::Function,Ts...) args = testargs(f,Ts...) @@ -114,7 +114,7 @@ Returns an arbitrary instance of type `T`. It defaults to `zero(T)` for non-array types and to an empty array for array types. This function is used to compute the default test arguments in [`testargs`](@ref). -It can be overloaded for new types `T` if `zero(T)` does not makes sense. +It can be overloaded for new types `T` if `zero(T)` does not makes sense. """ function testvalue end diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index f4fa7c20f..982cf3039 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -22,6 +22,7 @@ reffes = [LagrangianRefFE(T,p,order) for p in polytopes] dof_basis = map(get_dof_basis,reffes) +grid_topology = get_grid_topology(model) cell_to_ctype = get_cell_type(grid_topology) cell_dof_basis = CompressedArray(dof_basis,cell_to_ctype) @@ -32,7 +33,6 @@ cell_map = get_cell_map(grid) prebasis = map(get_prebasis,reffes) -grid_topology = get_grid_topology(model) cell_to_ctype = get_cell_type(grid_topology) @@ -40,7 +40,65 @@ refprebasis = CompressedArray(prebasis,cell_to_ctype) cell_prebasis = attachmap(refprebasis,cell_map) -# Now for each cell in the mesh we do +cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) + +cell_matrix_inv = apply(inv,cell_matrix) + +isa(cell_prebasis,CellBasis) + +change_basis(cell_prebasis[1],cell_matrix_inv[1]) + +cell_shapefuns = apply(change_basis,cell_prebasis,cell_matrix_inv) + +a = (cell_prebasis,cell_matrix_inv) + +import Base.zero +fi[1] + +typeof(a) +sizeof(a) +zero(a) + +fi = testitems(a...) +zero(fi[1]) +zero(fi[2]) + + +gradient(cell_shapefuns) + +# Whereas for the standard approach... +gradient(cell_prebasis) + + +shapefuns = map(get_shapefuns,reffes) +refshapefuns = CompressedArray(shapefuns,cell_to_ctype) +cell_shapefuns = attachmap(refshapefuns,cell_map) +gradient(cell_shapefuns) + + + + + + + + + + + + + + + + + + + + + + + +# cell_shapefuns = attachmap(cell_shapefuns,cell_map) +isa(cell_shapefuns,CellBasis) cell = 1 From beb79d5c959746e212a7ed103eb9cd3b5fab7e68 Mon Sep 17 00:00:00 2001 From: Francesc Verdugo Date: Tue, 3 Mar 2020 09:32:33 +0100 Subject: [PATCH 03/51] Minor to use `change_basis` function as a kernel --- src/Polynomials/ChangeBasis.jl | 4 ++++ src/Polynomials/Polynomials.jl | 1 + 2 files changed, 5 insertions(+) diff --git a/src/Polynomials/ChangeBasis.jl b/src/Polynomials/ChangeBasis.jl index ab87e9f93..1177ffa0b 100644 --- a/src/Polynomials/ChangeBasis.jl +++ b/src/Polynomials/ChangeBasis.jl @@ -30,6 +30,10 @@ function change_basis(basis,changeofbasis::AbstractMatrix) BasisFromChangeOfBasis(basis,changeofbasis) end +function kernel_return_type(::typeof(change_basis),prebasis,matrix_inv) + typeof(change_basis(prebasis,matrix_inv)) +end + struct BasisFromChangeOfBasis{B,M} <: Field basis::B change::M diff --git a/src/Polynomials/Polynomials.jl b/src/Polynomials/Polynomials.jl index 8ec871c0b..3fed6e78c 100644 --- a/src/Polynomials/Polynomials.jl +++ b/src/Polynomials/Polynomials.jl @@ -21,6 +21,7 @@ import Gridap.Fields: evaluate_gradient! import Gridap.Fields: gradient_cache import Gridap.Fields: evaluate_hessian! import Gridap.Fields: hessian_cache +import Gridap.Arrays: kernel_return_type export MonomialBasis export QGradMonomialBasis From 21b5025b7baa51a6213dc66b7dcd4aa134e4a477 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Tue, 3 Mar 2020 20:12:46 +1100 Subject: [PATCH 04/51] Typo labeing -> labeling + added a new function for computation FE space in physical space --- src/FESpaces/ConformingFESpaces.jl | 24 ++++++++--------- src/FESpaces/CurlConformingFESpaces.jl | 6 ++--- src/FESpaces/DivConformingFESpaces.jl | 6 ++--- test/FESpacesTests/ConformingFESpacesTests.jl | 8 +++--- test/FESpacesTests/PhysicalBasesTests.jl | 27 ++++++++++++------- 5 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index f711bcdcb..b9601b046 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -7,10 +7,10 @@ function GradConformingFESpace( dirichlet_tags, dirichlet_components=nothing) - face_labeing = get_face_labeling(model) + face_labeling = get_face_labeling(model) GradConformingFESpace( - reffes,model,face_labeing,dirichlet_tags,dirichlet_components) + reffes,model,face_labeling,dirichlet_tags,dirichlet_components) end @@ -21,9 +21,9 @@ function GradConformingFESpace( dirichlet_tags, dirichlet_components=nothing) where T - face_labeing = get_face_labeling(model) + face_labeling = get_face_labeling(model) - GradConformingFESpace(T,model,order,face_labeing,dirichlet_tags,dirichlet_components) + GradConformingFESpace(T,model,order,face_labeling,dirichlet_tags,dirichlet_components) end @@ -31,7 +31,7 @@ function GradConformingFESpace( ::Type{T}, model::DiscreteModel, order::Integer, - face_labeing::FaceLabeling, + face_labeling::FaceLabeling, dirichlet_tags, dirichlet_components=nothing) where T @@ -41,7 +41,7 @@ function GradConformingFESpace( reffes = [ LagrangianRefFE(T,p,order) for p in polytopes ] GradConformingFESpace( - reffes,model,face_labeing,dirichlet_tags,dirichlet_components) + reffes,model,face_labeling,dirichlet_tags,dirichlet_components) end @@ -50,7 +50,7 @@ end function GradConformingFESpace( reffes::Vector{<:LagrangianRefFE}, model::DiscreteModel, - face_labeing::FaceLabeling, + face_labeling::FaceLabeling, dirichlet_tags, dirichlet_components=nothing) @@ -59,7 +59,7 @@ function GradConformingFESpace( _dirichlet_components = _convert_dirichlet_components(dirichlet_tags,dirichlet_components) cell_dofs, nfree, ndirichlet, dirichlet_dof_tag, dirichlet_cells = compute_conforming_cell_dofs( - reffes,grid_topology,face_labeing,dirichlet_tags,_dirichlet_components) + reffes,grid_topology,face_labeling,dirichlet_tags,_dirichlet_components) ntags = length(dirichlet_tags) @@ -100,13 +100,13 @@ end compute_conforming_cell_dofs( reffes, grid_topology, - face_labeing, + face_labeling, dirichlet_tags) compute_conforming_cell_dofs( reffes, grid_topology, - face_labeing, + face_labeling, dirichlet_tags, dirichlet_components) @@ -121,7 +121,7 @@ If `dirichlet_components` is given, then `get_dof_to_comp` has to be defined for the reference elements in `reffes`. """ function compute_conforming_cell_dofs( - reffes,grid_topology,face_labeing,dirichlet_tags,dirichlet_components=nothing) + reffes,grid_topology,face_labeling,dirichlet_tags,dirichlet_components=nothing) D = num_cell_dims(grid_topology) n_faces = num_faces(grid_topology) @@ -140,7 +140,7 @@ function compute_conforming_cell_dofs( d_to_offset, d_to_ctype_to_ldface_to_own_ldofs) - d_to_dface_to_tag = [ get_face_tag_index(face_labeing,dirichlet_tags,d) for d in 0:D] + d_to_dface_to_tag = [ get_face_tag_index(face_labeling,dirichlet_tags,d) for d in 0:D] cell_to_faces = Table(get_cell_faces(grid_topology)) nfree, ndiri, diri_dof_tag = _split_face_own_dofs_into_free_and_dirichlet!( diff --git a/src/FESpaces/CurlConformingFESpaces.jl b/src/FESpaces/CurlConformingFESpaces.jl index ac03902a2..817ba7c69 100644 --- a/src/FESpaces/CurlConformingFESpaces.jl +++ b/src/FESpaces/CurlConformingFESpaces.jl @@ -4,19 +4,19 @@ CurlConformingFESpace( reffes::Vector{<:ReferenceFE}, model::DiscreteModel, - face_labeing::FaceLabeling, + face_labeling::FaceLabeling, dirichlet_tags) """ function CurlConformingFESpace( reffes::Vector{<:ReferenceFE}, model::DiscreteModel, - face_labeing::FaceLabeling, + face_labeling::FaceLabeling, dirichlet_tags) grid_topology = get_grid_topology(model) cell_dofs, nfree, ndirichlet, dirichlet_dof_tag, dirichlet_cells = compute_conforming_cell_dofs( - reffes,grid_topology,face_labeing,dirichlet_tags) + reffes,grid_topology,face_labeling,dirichlet_tags) ntags = length(dirichlet_tags) diff --git a/src/FESpaces/DivConformingFESpaces.jl b/src/FESpaces/DivConformingFESpaces.jl index 18a20dc54..62009f8f4 100644 --- a/src/FESpaces/DivConformingFESpaces.jl +++ b/src/FESpaces/DivConformingFESpaces.jl @@ -3,19 +3,19 @@ DivConformingFESpace( reffes::Vector{<:ReferenceFE}, model::DiscreteModel, - face_labeing::FaceLabeling, + face_labeling::FaceLabeling, dirichlet_tags) """ function DivConformingFESpace( reffes::Vector{<:ReferenceFE}, model::DiscreteModel, - face_labeing::FaceLabeling, + face_labeling::FaceLabeling, dirichlet_tags) grid_topology = get_grid_topology(model) cell_dofs, nfree, ndirichlet, dirichlet_dof_tag, dirichlet_cells = compute_conforming_cell_dofs( - reffes,grid_topology,face_labeing,dirichlet_tags) + reffes,grid_topology,face_labeling,dirichlet_tags) ntags = length(dirichlet_tags) diff --git a/test/FESpacesTests/ConformingFESpacesTests.jl b/test/FESpacesTests/ConformingFESpacesTests.jl index 0858e38fe..c39da7b30 100644 --- a/test/FESpacesTests/ConformingFESpacesTests.jl +++ b/test/FESpacesTests/ConformingFESpacesTests.jl @@ -18,11 +18,11 @@ grid_topology = get_grid_topology(model) polytopes = get_polytopes(grid_topology) reffes = [LagrangianRefFE(Float64,p,order) for p in polytopes] -face_labeing = get_face_labeling(model) +face_labeling = get_face_labeling(model) dirichlet_tags = ["tag_1","tag_6"] cell_dofs, nfree, ndiri, dirichlet_dof_tag, dirichlet_cells = compute_conforming_cell_dofs( - reffes, grid_topology, face_labeing, dirichlet_tags) + reffes, grid_topology, face_labeling, dirichlet_tags) r = [ [-1,1,4,5,14,15,16,17,35],[1,2,5,6,18,19,17,20,36],[2,3,6,7,21,22,20,23,37], @@ -40,7 +40,7 @@ reffes = [LagrangianRefFE(VectorValue{2,Float64},p,order) for p in polytopes] dirichlet_components = [(true,true), (false,true)] cell_dofs, nfree, ndiri, dirichlet_dof_tag, dirichlet_cells = compute_conforming_cell_dofs( - reffes, grid_topology, face_labeing, dirichlet_tags, dirichlet_components) + reffes, grid_topology, face_labeling, dirichlet_tags, dirichlet_components) r = [ [-1,1,7,9,-2,2,8,10],[1,3,9,11,2,4,10,12],[3,5,11,13,4,6,12,14], @@ -59,7 +59,7 @@ reffes = [LagrangianRefFE(VectorValue{2,Float64},p,order) for p in polytopes] dirichlet_components = [(true,true), (false,true)] cell_dofs, nfree, ndiri, dirichlet_dof_tag, dirichlet_cells = compute_conforming_cell_dofs( - reffes, grid_topology, face_labeing, dirichlet_tags, dirichlet_components) + reffes, grid_topology, face_labeling, dirichlet_tags, dirichlet_components) V = GradConformingFESpace(reffes,model,dirichlet_tags) test_single_field_fe_space(V) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 982cf3039..dcb215db5 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -23,6 +23,7 @@ reffes = [LagrangianRefFE(T,p,order) for p in polytopes] dof_basis = map(get_dof_basis,reffes) grid_topology = get_grid_topology(model) + cell_to_ctype = get_cell_type(grid_topology) cell_dof_basis = CompressedArray(dof_basis,cell_to_ctype) @@ -49,22 +50,28 @@ isa(cell_prebasis,CellBasis) change_basis(cell_prebasis[1],cell_matrix_inv[1]) cell_shapefuns = apply(change_basis,cell_prebasis,cell_matrix_inv) +gradient(cell_shapefuns) -a = (cell_prebasis,cell_matrix_inv) +function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) -import Base.zero -fi[1] + dof_basis = map(get_dof_basis,reffes) + cell_dof_basis = CompressedArray(dof_basis,cell_to_ctype) -typeof(a) -sizeof(a) -zero(a) + prebasis = map(get_prebasis,reffes) + refprebasis = CompressedArray(prebasis,cell_to_ctype) + cell_prebasis = attachmap(refprebasis,cell_map) -fi = testitems(a...) -zero(fi[1]) -zero(fi[2]) + cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) + cell_matrix_inv = apply(inv,cell_matrix) + cell_shapefuns = apply(change_basis,cell_prebasis,cell_matrix_inv) + # shapefuns = map(get_shapefuns,reffes) + # refshapefuns = CompressedArray(shapefuns,cell_to_ctype) + # cell_shapefuns = attachmap(cell_shapefuns,cell_map) + + (cell_shapefuns, cell_dof_basis) +end -gradient(cell_shapefuns) # Whereas for the standard approach... gradient(cell_prebasis) From 152df55e4ee378827d053e11d315eff4e2f2dee2 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Wed, 4 Mar 2020 16:58:54 +1100 Subject: [PATCH 05/51] Added a new method for physical FE spaces --- test/FESpacesTests/PhysicalBasesTests.jl | 90 ++++++++---------------- 1 file changed, 28 insertions(+), 62 deletions(-) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index dcb215db5..05569274c 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -14,6 +14,10 @@ model = CartesianDiscreteModel(domain,partition) order = 1 trian = get_triangulation(model) + +quad = CellQuadrature(trian,order*2) +q = get_coordinates(quad) + polytopes = get_polytopes(model) T = Float64 @@ -34,7 +38,6 @@ cell_map = get_cell_map(grid) prebasis = map(get_prebasis,reffes) - cell_to_ctype = get_cell_type(grid_topology) refprebasis = CompressedArray(prebasis,cell_to_ctype) @@ -48,9 +51,31 @@ cell_matrix_inv = apply(inv,cell_matrix) isa(cell_prebasis,CellBasis) change_basis(cell_prebasis[1],cell_matrix_inv[1]) +## -cell_shapefuns = apply(change_basis,cell_prebasis,cell_matrix_inv) -gradient(cell_shapefuns) +evaluate(cell_prebasis,q) +g_cpb = gradient(cell_prebasis) +evaluate(g_cpb,q) + +shapefuns = map(get_shapefuns,reffes) +refshapefuns = CompressedArray(shapefuns,cell_to_ctype) +cell_shapefuns = attachmap(refshapefuns,cell_map) +g_csf = gradient(cell_shapefuns) +evaluate(g_csf,q) +@which evaluate(g_csf,q) +@which Gridap.Fields.apply(g_csf,q) +@which Gridap.Arrays._fill_to_compressed(g_csf,q) +Gridap.Arrays._fill_to_compressed(g_csf,q) +f = Gridap.Arrays._fill_to_compressed(g_csf,q) +Gridap.Arrays._apply_compressed(g_csf,f...) + +cell_physshapefuns = apply(change_basis,cell_prebasis,cell_matrix_inv) +# I don't think I need this step, just to check whether it solved the problem below +cell_physshapefuns = attachmap(cell_physshapefuns,cell_map) +g_cpsf = gradient(cell_physshapefuns) +# evaluate(g_cpsf,q) + +## function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) @@ -71,62 +96,3 @@ function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) (cell_shapefuns, cell_dof_basis) end - - -# Whereas for the standard approach... -gradient(cell_prebasis) - - -shapefuns = map(get_shapefuns,reffes) -refshapefuns = CompressedArray(shapefuns,cell_to_ctype) -cell_shapefuns = attachmap(refshapefuns,cell_map) -gradient(cell_shapefuns) - - - - - - - - - - - - - - - - - - - - - - - -# cell_shapefuns = attachmap(cell_shapefuns,cell_map) -isa(cell_shapefuns,CellBasis) - -cell = 1 - -ns = get_nodes(cell_dof_basis[cell]) - -pns = evaluate(cell_map[cell],ns) - -p_changeofbasis = evaluate(cell_prebasis[cell],pns) - -# So if we want to evaluate the basis or its gradient in a set of points, we can -# do the same as `BasisFromChangeOfBasis` but the difference being that the computation -# of the change matrix is a cell_array. - -# I think we should create a new `CellBasis` struct that at the get_index level -# performs all these computations, makes use of cache arrays, and provides a -# basis. Before doing this, I want to discuss with Francesc what can we use -# of the pre-existing arrays, etc. - - -grad_cpb = gradient(cell_prebasis) - -evaluate(grad_cpb[cell],pns) - -gradient(refprebasis) From 5d1764c4f69a5285f01335ec014b1fa4678e9b4b Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 5 Mar 2020 06:16:18 +1100 Subject: [PATCH 06/51] Current version --- test/FESpacesTests/PhysicalBasesTests.jl | 46 ++++++++++++++++++------ 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 05569274c..fb30e69bd 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -55,26 +55,52 @@ change_basis(cell_prebasis[1],cell_matrix_inv[1]) evaluate(cell_prebasis,q) g_cpb = gradient(cell_prebasis) -evaluate(g_cpb,q) +# Juno.@enter gradient(cell_prebasis) +# Juno.@enter evaluate(g_cpb,q) shapefuns = map(get_shapefuns,reffes) refshapefuns = CompressedArray(shapefuns,cell_to_ctype) cell_shapefuns = attachmap(refshapefuns,cell_map) g_csf = gradient(cell_shapefuns) -evaluate(g_csf,q) -@which evaluate(g_csf,q) -@which Gridap.Fields.apply(g_csf,q) -@which Gridap.Arrays._fill_to_compressed(g_csf,q) -Gridap.Arrays._fill_to_compressed(g_csf,q) -f = Gridap.Arrays._fill_to_compressed(g_csf,q) -Gridap.Arrays._apply_compressed(g_csf,f...) +# Juno.@enter gradient(cell_shapefuns) +# Juno.@enter evaluate(g_csf,q) +typeof(g_csf) +# Juno.@enter evaluate(g_csf,q) cell_physshapefuns = apply(change_basis,cell_prebasis,cell_matrix_inv) # I don't think I need this step, just to check whether it solved the problem below cell_physshapefuns = attachmap(cell_physshapefuns,cell_map) g_cpsf = gradient(cell_physshapefuns) -# evaluate(g_cpsf,q) - +# Juno.@enter evaluate(g_cpsf,q) +evaluate(g_cpsf,q) + +# # # k = g_cpsf.g.value +# # # f = g_cpsf.f +# # # g = apply(k,f...) +# # # h = testitem(g) +# # # b = h.field +# # # x = testitems(q...) +# # # Gridap.Polynomials.gradient_cache(b,x) +# # +# # bs1 = g_csf +# # +# # k1 = bs1.g.value +# # f1 = bs1.f +# # g1 = apply(k1,f1...) +# # h1 = testitem(g1) +# # b1 = h1.field +# # x1 = testitems(q...) +# # Gridap.Polynomials.gradient_cache(b1,x1) +# +# bs2 = g_cpsf +# +# k2 = bs2.g.value +# f2 = bs2.f +# g2 = apply(k2,f2...) +# h2 = testitem(g2) +# b2 = h2.field +# x2 = testitems(q...) +# Gridap.Polynomials.gradient_cache(b2,x2) ## function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) From 015ee825c7731a5bc635f28a8a3aa546620db262 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 6 Mar 2020 14:00:06 +1100 Subject: [PATCH 07/51] Now new method working in test --- test/FESpacesTests/PhysicalBasesTests.jl | 118 ++++++++--------------- 1 file changed, 42 insertions(+), 76 deletions(-) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index fb30e69bd..8e91f1cde 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -14,111 +14,77 @@ model = CartesianDiscreteModel(domain,partition) order = 1 trian = get_triangulation(model) - quad = CellQuadrature(trian,order*2) q = get_coordinates(quad) polytopes = get_polytopes(model) T = Float64 - # In fact, Lagrangian not needed, minor thing reffes = [LagrangianRefFE(T,p,order) for p in polytopes] - -dof_basis = map(get_dof_basis,reffes) - -grid_topology = get_grid_topology(model) - -cell_to_ctype = get_cell_type(grid_topology) - -cell_dof_basis = CompressedArray(dof_basis,cell_to_ctype) +cell_to_ctype = get_cell_type(model) grid = get_grid(model) - cell_map = get_cell_map(grid) -prebasis = map(get_prebasis,reffes) - -cell_to_ctype = get_cell_type(grid_topology) - -refprebasis = CompressedArray(prebasis,cell_to_ctype) - -cell_prebasis = attachmap(refprebasis,cell_map) - -cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) +newsfs, x = compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) +r11 = evaluate(newsfs,q) +r22 = evaluate(gradient(newsfs),q) -cell_matrix_inv = apply(inv,cell_matrix) +# If I want new evaluation... +function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) + cell_prebasis_x = evaluate_field_array(cell_prebasis,x) + apply(mul,cell_prebasis_x,cell_prebasis,cell_matrix_inv) +end +function apply_gradient(k::typeof(change_basis),cell_prebasis,cell_matrix_inv) + cell_prebasis_grad = gradient(cell_prebasis) + apply(change_basis,cell_prebasis_grad,cell_matrix_inv) +end +# Optimisation : evaluate_field_array for AbstractArray with FieldLike +# Define a new kernel that better treats the inverse +struct InvKernel <: Kernel end +function kernel_cache(k::InvKernel,mat) +end +function apply_kernel!(cache,k::InvKernel,mat) +end +function kernel_cache(k::InvKernel,mat) +CachedArray(copy(mat)) +end +function apply_kernel!(cache,k::InvKernel,mat) + setsize!(cache,size(mat)) + m = cache.array + fill!(m,zero(m)) + for i:size(m,1); m[i] = 1; end + ldiv!(mat,m) + m +end +k = InvKernel() isa(cell_prebasis,CellBasis) change_basis(cell_prebasis[1],cell_matrix_inv[1]) ## -evaluate(cell_prebasis,q) -g_cpb = gradient(cell_prebasis) # Juno.@enter gradient(cell_prebasis) # Juno.@enter evaluate(g_cpb,q) -shapefuns = map(get_shapefuns,reffes) -refshapefuns = CompressedArray(shapefuns,cell_to_ctype) -cell_shapefuns = attachmap(refshapefuns,cell_map) -g_csf = gradient(cell_shapefuns) -# Juno.@enter gradient(cell_shapefuns) -# Juno.@enter evaluate(g_csf,q) -typeof(g_csf) -# Juno.@enter evaluate(g_csf,q) - -cell_physshapefuns = apply(change_basis,cell_prebasis,cell_matrix_inv) -# I don't think I need this step, just to check whether it solved the problem below -cell_physshapefuns = attachmap(cell_physshapefuns,cell_map) -g_cpsf = gradient(cell_physshapefuns) -# Juno.@enter evaluate(g_cpsf,q) -evaluate(g_cpsf,q) - -# # # k = g_cpsf.g.value -# # # f = g_cpsf.f -# # # g = apply(k,f...) -# # # h = testitem(g) -# # # b = h.field -# # # x = testitems(q...) -# # # Gridap.Polynomials.gradient_cache(b,x) -# # -# # bs1 = g_csf -# # -# # k1 = bs1.g.value -# # f1 = bs1.f -# # g1 = apply(k1,f1...) -# # h1 = testitem(g1) -# # b1 = h1.field -# # x1 = testitems(q...) -# # Gridap.Polynomials.gradient_cache(b1,x1) -# -# bs2 = g_cpsf -# -# k2 = bs2.g.value -# f2 = bs2.f -# g2 = apply(k2,f2...) -# h2 = testitem(g2) -# b2 = h2.field -# x2 = testitems(q...) -# Gridap.Polynomials.gradient_cache(b2,x2) -## - function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) + # Create new dof_basis with nodes in the physical space + ctype_to_refnodes= map(get_node_coordinates,reffes) + cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) + cell_physnodes = evaluate(cell_map,cell_to_refnodes) + dof_basis = map(get_dof_basis,reffes) - cell_dof_basis = CompressedArray(dof_basis,cell_to_ctype) + # Not efficient, create a Kernel + cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) prebasis = map(get_prebasis,reffes) - refprebasis = CompressedArray(prebasis,cell_to_ctype) - cell_prebasis = attachmap(refprebasis,cell_map) + cell_prebasis = CompressedArray(prebasis,cell_to_ctype) cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) cell_matrix_inv = apply(inv,cell_matrix) - cell_shapefuns = apply(change_basis,cell_prebasis,cell_matrix_inv) - - # shapefuns = map(get_shapefuns,reffes) - # refshapefuns = CompressedArray(shapefuns,cell_to_ctype) - # cell_shapefuns = attachmap(cell_shapefuns,cell_map) + cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) + cell_shapefuns = compose(cell_shapefuns_phys,cell_map) (cell_shapefuns, cell_dof_basis) end From 7f9ab1f1fea223924a95bd755c2d9017ec76d9fd Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 6 Mar 2020 14:00:30 +1100 Subject: [PATCH 08/51] Further modifications --- test/FESpacesTests/PhysicalBasesTests.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 8e91f1cde..2e2135ccc 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -26,10 +26,14 @@ cell_to_ctype = get_cell_type(model) grid = get_grid(model) cell_map = get_cell_map(grid) +# Test against the ref approach... + newsfs, x = compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) r11 = evaluate(newsfs,q) r22 = evaluate(gradient(newsfs),q) + +## # If I want new evaluation... function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) cell_prebasis_x = evaluate_field_array(cell_prebasis,x) @@ -39,6 +43,7 @@ function apply_gradient(k::typeof(change_basis),cell_prebasis,cell_matrix_inv) cell_prebasis_grad = gradient(cell_prebasis) apply(change_basis,cell_prebasis_grad,cell_matrix_inv) end +## # Optimisation : evaluate_field_array for AbstractArray with FieldLike # Define a new kernel that better treats the inverse struct InvKernel <: Kernel end From ca1cae0d69d344b6db4f02bb6ce81432679c903c Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 6 Mar 2020 14:26:47 +1100 Subject: [PATCH 09/51] Added method to FESpaces --- src/FESpaces/ConformingFESpaces.jl | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index b9601b046..22356f8dd 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -96,6 +96,37 @@ function compute_cell_space(reffes, cell_to_ctype, cell_map) (cell_shapefuns, cell_dof_basis) end +""" +It creates the cell-wise DOF basis and shape functions, when the DOFs +are evaluated at the physical space. The DOFs (moments) for the prebasis +are assumed to be computable at a reference FE space. +""" +# E.g., if one has to implement $\int_F q ϕ_h(x)$ for $q \in P(F)$, we can +# assume that it can be written as $\sum_{x_{gp} \in Q}_{\hat{F}} +# \hat{q}(\tilde{x}_{gp}) ϕ(x_{gp})$ for $\hat{q} \in P(\hat{F})$. +function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) + + # Create new dof_basis with nodes in the physical space + ctype_to_refnodes= map(get_node_coordinates,reffes) + cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) + cell_physnodes = evaluate(cell_map,cell_to_refnodes) + + dof_basis = map(get_dof_basis,reffes) + # Not efficient, create a Kernel + cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) + + prebasis = map(get_prebasis,reffes) + cell_prebasis = CompressedArray(prebasis,cell_to_ctype) + + cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) + cell_matrix_inv = apply(inv,cell_matrix) + cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) + cell_shapefuns = compose(cell_shapefuns_phys,cell_map) + + (cell_shapefuns, cell_dof_basis) +end + + """ compute_conforming_cell_dofs( reffes, From adf80fd14c308a7f28982d53e26fa74819a1d44c Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 6 Mar 2020 16:19:22 +1100 Subject: [PATCH 10/51] GenericNodalRefFE -> GenericNodalCartesianRefFE --- docs/src/ReferenceFEs.md | 4 +-- src/ReferenceFEs/NodalReferenceFEs.jl | 35 +++++++++---------- src/ReferenceFEs/ReferenceFEs.jl | 2 +- test/FESpacesTests/PhysicalBasesTests.jl | 15 +++++--- .../NodalReferenceFEsTests.jl | 2 +- 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/docs/src/ReferenceFEs.md b/docs/src/ReferenceFEs.md index 86f9102b2..33a85105f 100644 --- a/docs/src/ReferenceFEs.md +++ b/docs/src/ReferenceFEs.md @@ -162,10 +162,10 @@ get_face_own_nodes_permutations(reffe::NodalReferenceFE,d::Integer) get_face_nodes(reffe::NodalReferenceFE,d::Integer) ``` -### GenericNodalRefFE +### GenericNodalCartesianRefFE ```@docs -GenericNodalRefFE +GenericNodalCartesianRefFE ``` ### Lagrangian reference elements diff --git a/src/ReferenceFEs/NodalReferenceFEs.jl b/src/ReferenceFEs/NodalReferenceFEs.jl index 9357a1b5d..7223baca7 100644 --- a/src/ReferenceFEs/NodalReferenceFEs.jl +++ b/src/ReferenceFEs/NodalReferenceFEs.jl @@ -76,7 +76,7 @@ function test_nodal_reference_fe(reffe::NodalReferenceFE) @test isa(get_face_nodes(reffe),Vector{Vector{Int}}) end -# Dafault API +# Default API """ num_nodes(reffe::NodalReferenceFE) @@ -149,7 +149,7 @@ end # Generic implementation """ - struct GenericNodalRefFE{D,T,V} <: NodalReferenceFE{D} + struct GenericNodalCartesianRefFE{D,T,V} <: NodalReferenceFE{D} reffe::GenericRefFE{D} node_coordinates::Vector{Point{D,T}} node_and_comp_to_dof::Vector{V} @@ -158,7 +158,7 @@ end face_nodes::Vector{Vector{Int}} end """ -struct GenericNodalRefFE{D,T,V} <: NodalReferenceFE{D} +struct GenericNodalCartesianRefFE{D,T,V} <: NodalReferenceFE{D} reffe::GenericRefFE{D} node_coordinates::Vector{Point{D,T}} node_and_comp_to_dof::Vector{V} @@ -169,31 +169,30 @@ end # NodalReffe -get_node_coordinates(reffe::GenericNodalRefFE) = reffe.node_coordinates +get_node_coordinates(reffe::GenericNodalCartesianRefFE) = reffe.node_coordinates -get_node_and_comp_to_dof(reffe::GenericNodalRefFE) = reffe.node_and_comp_to_dof +get_node_and_comp_to_dof(reffe::GenericNodalCartesianRefFE) = reffe.node_and_comp_to_dof -get_face_own_nodes(reffe::GenericNodalRefFE) = reffe.face_own_nodes +get_face_own_nodes(reffe::GenericNodalCartesianRefFE) = reffe.face_own_nodes -get_face_own_nodes_permutations(reffe::GenericNodalRefFE) = reffe.face_own_nodes_permutations +get_face_own_nodes_permutations(reffe::GenericNodalCartesianRefFE) = reffe.face_own_nodes_permutations -get_face_nodes(reffe::GenericNodalRefFE) = reffe.face_nodes +get_face_nodes(reffe::GenericNodalCartesianRefFE) = reffe.face_nodes -# Reffe +# Reffe -num_dofs(reffe::GenericNodalRefFE) = reffe.reffe.ndofs +num_dofs(reffe::GenericNodalCartesianRefFE) = reffe.reffe.ndofs -get_polytope(reffe::GenericNodalRefFE) = reffe.reffe.polytope +get_polytope(reffe::GenericNodalCartesianRefFE) = reffe.reffe.polytope -get_prebasis(reffe::GenericNodalRefFE) = reffe.reffe.prebasis +get_prebasis(reffe::GenericNodalCartesianRefFE) = reffe.reffe.prebasis -get_dof_basis(reffe::GenericNodalRefFE) = reffe.reffe.dofs +get_dof_basis(reffe::GenericNodalCartesianRefFE) = reffe.reffe.dofs -get_face_own_dofs(reffe::GenericNodalRefFE) = reffe.reffe.face_own_dofs +get_face_own_dofs(reffe::GenericNodalCartesianRefFE) = reffe.reffe.face_own_dofs -get_face_own_dofs_permutations(reffe::GenericNodalRefFE) = reffe.reffe.face_own_dofs_permutations +get_face_own_dofs_permutations(reffe::GenericNodalCartesianRefFE) = reffe.reffe.face_own_dofs_permutations -get_face_dofs(reffe::GenericNodalRefFE) = reffe.reffe.face_own_dofs - -get_shapefuns(reffe::GenericNodalRefFE) = reffe.reffe.shapefuns +get_face_dofs(reffe::GenericNodalCartesianRefFE) = reffe.reffe.face_own_dofs +get_shapefuns(reffe::GenericNodalCartesianRefFE) = reffe.reffe.shapefuns diff --git a/src/ReferenceFEs/ReferenceFEs.jl b/src/ReferenceFEs/ReferenceFEs.jl index 07d46ae68..a6bb5a0e4 100644 --- a/src/ReferenceFEs/ReferenceFEs.jl +++ b/src/ReferenceFEs/ReferenceFEs.jl @@ -102,7 +102,7 @@ export test_reference_fe export num_dofs export NodalReferenceFE -export GenericNodalRefFE +export GenericNodalCartesianRefFE export get_face_own_nodes export get_face_nodes export get_face_own_nodes_permutations diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 2e2135ccc..43d6725e1 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -5,6 +5,7 @@ using Gridap.Arrays using Gridap.Fields using Gridap.FESpaces using Gridap.Polynomials +using Test # Start with a PhysicalSpaceCellBasis @@ -28,11 +29,15 @@ cell_map = get_cell_map(grid) # Test against the ref approach... -newsfs, x = compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) -r11 = evaluate(newsfs,q) -r22 = evaluate(gradient(newsfs),q) - - +sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) +psfs, x = Gridap.FESpaces.compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) +r, x = evaluate(sfs,q) +rg, x = evaluate(gradient(sfs),q) +rp, x = evaluate(psfs,q) +rgp, x = evaluate(gradient(psfs),q) +@test r == rp +@test collect(rg) == collect(rgp) +@test rg == rgp ## # If I want new evaluation... function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) diff --git a/test/ReferenceFEsTests/NodalReferenceFEsTests.jl b/test/ReferenceFEsTests/NodalReferenceFEsTests.jl index 2b40f8562..68e6057cb 100644 --- a/test/ReferenceFEsTests/NodalReferenceFEsTests.jl +++ b/test/ReferenceFEsTests/NodalReferenceFEsTests.jl @@ -32,7 +32,7 @@ face_own_nodes = face_own_dofs face_own_nodes_permutations = face_own_dofs_permutations face_nodes = face_dofs -reffe = GenericNodalRefFE( +reffe = GenericNodalCartesianRefFE( reffe, node_coordinates, node_and_comp_to_dof, From 878287d979c8934a16d7bce4ba571d0e383ccacd Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Sat, 7 Mar 2020 09:48:39 +1100 Subject: [PATCH 11/51] get_nodes from dofbasis et al --- src/FESpaces/ConformingFESpaces.jl | 3 +- src/ReferenceFEs/NodalReferenceFEs.jl | 1 - src/ReferenceFEs/RaviartThomasRefFEs.jl | 11 ++++ src/ReferenceFEs/ReferenceFEs.jl | 1 + test/FESpacesTests/PhysicalBasesTests.jl | 71 ++++++++++++++++++++---- 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index 22356f8dd..f97a68947 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -107,7 +107,8 @@ are assumed to be computable at a reference FE space. function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) # Create new dof_basis with nodes in the physical space - ctype_to_refnodes= map(get_node_coordinates,reffes) + dof_bases = map(get_dof_basis,reffes) + ctype_to_refnodes = map(get_node_coordinates,dof_bases) cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) cell_physnodes = evaluate(cell_map,cell_to_refnodes) diff --git a/src/ReferenceFEs/NodalReferenceFEs.jl b/src/ReferenceFEs/NodalReferenceFEs.jl index 7223baca7..9109b8b7f 100644 --- a/src/ReferenceFEs/NodalReferenceFEs.jl +++ b/src/ReferenceFEs/NodalReferenceFEs.jl @@ -147,7 +147,6 @@ function get_face_nodes(reffe::NodalReferenceFE,d::Integer) end # Generic implementation - """ struct GenericNodalCartesianRefFE{D,T,V} <: NodalReferenceFE{D} reffe::GenericRefFE{D} diff --git a/src/ReferenceFEs/RaviartThomasRefFEs.jl b/src/ReferenceFEs/RaviartThomasRefFEs.jl index db4c4f9ba..7cfe181bd 100644 --- a/src/ReferenceFEs/RaviartThomasRefFEs.jl +++ b/src/ReferenceFEs/RaviartThomasRefFEs.jl @@ -176,6 +176,12 @@ struct MomentBasedDofBasis{P,V} <: Dof face_moments::Vector{Array{V}} face_nodes::Vector{UnitRange{Int}} + function MomentBasedDofBasis(nodes,f_moments,f_nodes) + P = eltype(nodes) + V = eltype(eltype(f_moments)) + new{P,V}(nodes,f_moments,f_nodes) + end + function MomentBasedDofBasis(f_nodes,f_moments) P = eltype(eltype(f_nodes)) V = eltype(eltype(f_moments)) @@ -197,6 +203,11 @@ struct MomentBasedDofBasis{P,V} <: Dof end end +putaspasa() = "Hola" +get_nodes(b::MomentBasedDofBasis) = b.nodes +get_face_moments(b::MomentBasedDofBasis) = b.face_moments +get_face_nodes_dofs(b::MomentBasedDofBasis) = b.face_nodes + function num_dofs(b::MomentBasedDofBasis) n = 0 for m in b.face_moments diff --git a/src/ReferenceFEs/ReferenceFEs.jl b/src/ReferenceFEs/ReferenceFEs.jl index a6bb5a0e4..1e7737a01 100644 --- a/src/ReferenceFEs/ReferenceFEs.jl +++ b/src/ReferenceFEs/ReferenceFEs.jl @@ -80,6 +80,7 @@ export TET_AXIS export INVALID_PERM export Dof +export get_nodes export evaluate_dof! export evaluate_dof export dof_cache diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 43d6725e1..19a28b1d5 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -9,19 +9,19 @@ using Test # Start with a PhysicalSpaceCellBasis -domain = (0,1) -partition = (2) +# domain = (0,1) +# partition = (3,) +domain = (0,1,0,1) +partition = (1,1) model = CartesianDiscreteModel(domain,partition) order = 1 +# order = 2 trian = get_triangulation(model) -quad = CellQuadrature(trian,order*2) +quad = CellQuadrature(trian,order) q = get_coordinates(quad) polytopes = get_polytopes(model) -T = Float64 -# In fact, Lagrangian not needed, minor thing -reffes = [LagrangianRefFE(T,p,order) for p in polytopes] cell_to_ctype = get_cell_type(model) grid = get_grid(model) @@ -29,15 +29,56 @@ cell_map = get_cell_map(grid) # Test against the ref approach... -sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) +# T = VectorValue{2,Float64} +T = Float64 + +# In fact, Lagrangian not needed, minor thing +# reffes = [LagrangianRefFE(T,p,order) for p in polytopes] +reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] + + +cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) +cell_physnodes = evaluate(cell_map,cell_to_refnodes) + +dof_bases = map(get_dof_basis,reffes) +# Not efficient, create a Kernel +# Here I have the problem !!! +# cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) +# cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) +ctype_to_refnodes = map(Gridap.ReferenceFEs.get_nodes,dof_bases) +ctype_to_face_moments = map(Gridap.ReferenceFEs.get_face_moments,dof_bases) +ctype_to_face_nodes_dofs = map(Gridap.ReferenceFEs.get_face_nodes_dofs,dof_bases) +cell_dof_basis = apply( (n,m,nd) -> Gridap.ReferenceFEs.MomentBasedDofBasis(n,m,nd), + ctype_to_refnodes, ctype_to_face_moments, ctype_to_face_nodes_dofs) + +prebasis = map(get_prebasis,reffes) +cell_prebasis = CompressedArray(prebasis,cell_to_ctype) + +# Juno.@enter evaluate_dof_array(cell_dof_basis,cell_prebasis) +cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) +cell_matrix_inv = apply(inv,cell_matrix) +cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) +cell_shapefuns = compose(cell_shapefuns_phys,cell_map) + +(cell_shapefuns, cell_dof_basis) + +evaluate(cell_shapefuns,q) +evaluate(gradient(cell_shapefuns),q) + + psfs, x = Gridap.FESpaces.compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) +sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) + +q +evaluate(sfs[1],q[1]) r, x = evaluate(sfs,q) rg, x = evaluate(gradient(sfs),q) rp, x = evaluate(psfs,q) rgp, x = evaluate(gradient(psfs),q) -@test r == rp -@test collect(rg) == collect(rgp) -@test rg == rgp +@test r ≈ rp +@test rg ≈ rgp + + ## # If I want new evaluation... function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) @@ -98,3 +139,13 @@ function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) (cell_shapefuns, cell_dof_basis) end + + +a1 = Gridap.Arrays.Fill(1.0,3) +b1 = Gridap.Arrays.Fill(1.0,3) +c1 = Gridap.Arrays.Fill(1.0,3) +f(a,b,c) = a+b+c +p1 = Gridap.Arrays.pair_arrays(a1,b1) +p2 = Gridap.Arrays.pair_arrays(p1,c1) + +apply(f,a1,b1,c1) From 7210eecbfafe4351d60fab4a365c5125dc8f3e2d Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Sat, 7 Mar 2020 16:27:35 +1100 Subject: [PATCH 12/51] Now everything works for physical space defined Lagrangian and RT reference FEs --- src/FESpaces/ConformingFESpaces.jl | 33 ++++++++- src/ReferenceFEs/RaviartThomasRefFEs.jl | 1 - test/FESpacesTests/PhysicalBasesTests.jl | 94 +++++++++++------------- 3 files changed, 71 insertions(+), 57 deletions(-) diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index f97a68947..111f77b89 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -104,11 +104,37 @@ are assumed to be computable at a reference FE space. # E.g., if one has to implement $\int_F q ϕ_h(x)$ for $q \in P(F)$, we can # assume that it can be written as $\sum_{x_{gp} \in Q}_{\hat{F}} # \hat{q}(\tilde{x}_{gp}) ϕ(x_{gp})$ for $\hat{q} \in P(\hat{F})$. -function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) +function compute_cell_space_physical_space_moment(reffes, cell_to_ctype, cell_map) - # Create new dof_basis with nodes in the physical space dof_bases = map(get_dof_basis,reffes) - ctype_to_refnodes = map(get_node_coordinates,dof_bases) + + ctype_to_refnodes = map(get_nodes,dof_bases) + cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) + cell_physnodes = evaluate(cell_map,cell_to_refnodes) + + # Not efficient, create a Kernel + ct_face_moments = map(ReferenceFEs.get_face_moments,dof_bases) + c_face_moments = CompressedArray(ct_face_moments,cell_to_ctype) + ct_face_nodes_dofs = map(ReferenceFEs.get_face_nodes_dofs,dof_bases) + c_face_nodes_dofs = CompressedArray(ct_face_nodes_dofs,cell_to_ctype) + cell_dof_basis = apply( (n,m,nd) -> ReferenceFEs.MomentBasedDofBasis(n,m,nd), + cell_physnodes, c_face_moments, c_face_nodes_dofs) + + prebasis = map(get_prebasis,reffes) + cell_prebasis = CompressedArray(prebasis,cell_to_ctype) + + cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) + cell_matrix_inv = apply(inv,cell_matrix) + cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) + cell_shapefuns = compose(cell_shapefuns_phys,cell_map) + + (cell_shapefuns, cell_dof_basis) +end + +function compute_cell_space_physical_space_lagrangian(reffes, cell_to_ctype, cell_map) + + # Create new dof_basis with nodes in the physical space + ctype_to_refnodes= map(get_node_coordinates,reffes) cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) cell_physnodes = evaluate(cell_map,cell_to_refnodes) @@ -127,7 +153,6 @@ function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) (cell_shapefuns, cell_dof_basis) end - """ compute_conforming_cell_dofs( reffes, diff --git a/src/ReferenceFEs/RaviartThomasRefFEs.jl b/src/ReferenceFEs/RaviartThomasRefFEs.jl index 7cfe181bd..8e06ff5a0 100644 --- a/src/ReferenceFEs/RaviartThomasRefFEs.jl +++ b/src/ReferenceFEs/RaviartThomasRefFEs.jl @@ -203,7 +203,6 @@ struct MomentBasedDofBasis{P,V} <: Dof end end -putaspasa() = "Hola" get_nodes(b::MomentBasedDofBasis) = b.nodes get_face_moments(b::MomentBasedDofBasis) = b.face_moments get_face_nodes_dofs(b::MomentBasedDofBasis) = b.face_nodes diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 19a28b1d5..1522fe2b3 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -12,7 +12,7 @@ using Test # domain = (0,1) # partition = (3,) domain = (0,1,0,1) -partition = (1,1) +partition = (2,2) model = CartesianDiscreteModel(domain,partition) order = 1 # order = 2 @@ -32,52 +32,64 @@ cell_map = get_cell_map(grid) # T = VectorValue{2,Float64} T = Float64 -# In fact, Lagrangian not needed, minor thing -# reffes = [LagrangianRefFE(T,p,order) for p in polytopes] +reffes = [LagrangianRefFE(T,p,order) for p in polytopes] + +psfs, x = Gridap.FESpaces.compute_cell_space_physical_space_lagrangian(reffes, cell_to_ctype, cell_map) +sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) + +r = evaluate(sfs,q) +rg = evaluate(gradient(sfs),q) +rp = evaluate(psfs,q) +rgp = evaluate(gradient(psfs),q) + +@test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) +@test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) + +## reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] +psfs, dofp = Gridap.FESpaces.compute_cell_space_physical_space_moment(reffes, cell_to_ctype, cell_map) +sfs, dof = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) + +r = evaluate(sfs,q) +rg = evaluate(gradient(sfs),q) +rp = evaluate(psfs,q) +rgp = evaluate(gradient(psfs),q) +@test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) +@test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) + +dofp[2] +dof +q[1] +r[1] +rp[1] + +## +dof_bases = map(get_dof_basis,reffes) + +ctype_to_refnodes = map(get_nodes,dof_bases) cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) cell_physnodes = evaluate(cell_map,cell_to_refnodes) -dof_bases = map(get_dof_basis,reffes) # Not efficient, create a Kernel -# Here I have the problem !!! -# cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) -# cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) -ctype_to_refnodes = map(Gridap.ReferenceFEs.get_nodes,dof_bases) -ctype_to_face_moments = map(Gridap.ReferenceFEs.get_face_moments,dof_bases) -ctype_to_face_nodes_dofs = map(Gridap.ReferenceFEs.get_face_nodes_dofs,dof_bases) -cell_dof_basis = apply( (n,m,nd) -> Gridap.ReferenceFEs.MomentBasedDofBasis(n,m,nd), - ctype_to_refnodes, ctype_to_face_moments, ctype_to_face_nodes_dofs) +ct_face_moments = map(ReferenceFEs.get_face_moments,dof_bases) +c_face_moments = CompressedArray(ct_face_moments,cell_to_ctype) +ct_face_nodes_dofs = map(ReferenceFEs.get_face_nodes_dofs,dof_bases) +c_face_nodes_dofs = CompressedArray(ct_face_nodes_dofs,cell_to_ctype) +cell_dof_basis = apply( (n,m,nd) -> ReferenceFEs.MomentBasedDofBasis(n,m,nd), + cell_physnodes, c_face_moments, c_face_nodes_dofs) prebasis = map(get_prebasis,reffes) cell_prebasis = CompressedArray(prebasis,cell_to_ctype) -# Juno.@enter evaluate_dof_array(cell_dof_basis,cell_prebasis) cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) cell_matrix_inv = apply(inv,cell_matrix) cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) cell_shapefuns = compose(cell_shapefuns_phys,cell_map) (cell_shapefuns, cell_dof_basis) - -evaluate(cell_shapefuns,q) -evaluate(gradient(cell_shapefuns),q) - - -psfs, x = Gridap.FESpaces.compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) -sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) - -q -evaluate(sfs[1],q[1]) -r, x = evaluate(sfs,q) -rg, x = evaluate(gradient(sfs),q) -rp, x = evaluate(psfs,q) -rgp, x = evaluate(gradient(psfs),q) -@test r ≈ rp -@test rg ≈ rgp - +## ## # If I want new evaluation... @@ -118,28 +130,6 @@ change_basis(cell_prebasis[1],cell_matrix_inv[1]) # Juno.@enter gradient(cell_prebasis) # Juno.@enter evaluate(g_cpb,q) -function compute_cell_space_physical_space(reffes, cell_to_ctype, cell_map) - - # Create new dof_basis with nodes in the physical space - ctype_to_refnodes= map(get_node_coordinates,reffes) - cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) - cell_physnodes = evaluate(cell_map,cell_to_refnodes) - - dof_basis = map(get_dof_basis,reffes) - # Not efficient, create a Kernel - cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) - - prebasis = map(get_prebasis,reffes) - cell_prebasis = CompressedArray(prebasis,cell_to_ctype) - - cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) - cell_matrix_inv = apply(inv,cell_matrix) - cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) - cell_shapefuns = compose(cell_shapefuns_phys,cell_map) - - (cell_shapefuns, cell_dof_basis) -end - a1 = Gridap.Arrays.Fill(1.0,3) b1 = Gridap.Arrays.Fill(1.0,3) From bc2cec45b7a3321948cc7b822ef8118f06ff3dc2 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Sat, 7 Mar 2020 17:47:36 +1100 Subject: [PATCH 13/51] Better internal structure methods --- src/FESpaces/ConformingFESpaces.jl | 96 ++++++++++++++++++------ src/ReferenceFEs/ReferenceFEs.jl | 9 ++- test/FESpacesTests/PhysicalBasesTests.jl | 31 ++++---- 3 files changed, 92 insertions(+), 44 deletions(-) diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index 111f77b89..5be5cc8d5 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -104,55 +104,101 @@ are assumed to be computable at a reference FE space. # E.g., if one has to implement $\int_F q ϕ_h(x)$ for $q \in P(F)$, we can # assume that it can be written as $\sum_{x_{gp} \in Q}_{\hat{F}} # \hat{q}(\tilde{x}_{gp}) ϕ(x_{gp})$ for $\hat{q} \in P(\hat{F})$. -function compute_cell_space_physical_space_moment(reffes, cell_to_ctype, cell_map) +# function compute_cell_space_physical_space_moment(reffes, cell_to_ctype, cell_map) +# +# dof_bases = map(get_dof_basis,reffes) +# +# ctype_to_refnodes = map(get_nodes,dof_bases) +# cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) +# cell_physnodes = evaluate(cell_map,cell_to_refnodes) +# +# # Not efficient, create a Kernel +# ct_face_moments = map(ReferenceFEs.get_face_moments,dof_bases) +# c_face_moments = CompressedArray(ct_face_moments,cell_to_ctype) +# ct_face_nodes_dofs = map(ReferenceFEs.get_face_nodes_dofs,dof_bases) +# c_face_nodes_dofs = CompressedArray(ct_face_nodes_dofs,cell_to_ctype) +# cell_dof_basis = apply( (n,m,nd) -> ReferenceFEs.MomentBasedDofBasis(n,m,nd), +# cell_physnodes, c_face_moments, c_face_nodes_dofs) +# +# prebasis = map(get_prebasis,reffes) +# cell_prebasis = CompressedArray(prebasis,cell_to_ctype) +# +# cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) +# cell_matrix_inv = apply(inv,cell_matrix) +# cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) +# cell_shapefuns = compose(cell_shapefuns_phys,cell_map) +# +# (cell_shapefuns, cell_dof_basis) +# end + +function compute_cell_space_physical(reffes, cell_to_ctype, cell_map) dof_bases = map(get_dof_basis,reffes) - ctype_to_refnodes = map(get_nodes,dof_bases) - cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) - cell_physnodes = evaluate(cell_map,cell_to_refnodes) - - # Not efficient, create a Kernel - ct_face_moments = map(ReferenceFEs.get_face_moments,dof_bases) - c_face_moments = CompressedArray(ct_face_moments,cell_to_ctype) - ct_face_nodes_dofs = map(ReferenceFEs.get_face_nodes_dofs,dof_bases) - c_face_nodes_dofs = CompressedArray(ct_face_nodes_dofs,cell_to_ctype) - cell_dof_basis = apply( (n,m,nd) -> ReferenceFEs.MomentBasedDofBasis(n,m,nd), - cell_physnodes, c_face_moments, c_face_nodes_dofs) + cell_dof_basis = _cell_dof_basis_physical_space(dof_bases,cell_to_ctype,cell_map) prebasis = map(get_prebasis,reffes) cell_prebasis = CompressedArray(prebasis,cell_to_ctype) - cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) - cell_matrix_inv = apply(inv,cell_matrix) - cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) - cell_shapefuns = compose(cell_shapefuns_phys,cell_map) + cell_shapefuns = _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) (cell_shapefuns, cell_dof_basis) end -function compute_cell_space_physical_space_lagrangian(reffes, cell_to_ctype, cell_map) +function _cell_dof_basis_physical_space(dof_bases,cell_to_ctype,cell_map) + @notimplemented +end +function _cell_dof_basis_physical_space( + dof_bases::Vector{MomentBasedDofBasis{T,V}}, + cell_to_ctype,cell_map) where {T,V} - # Create new dof_basis with nodes in the physical space - ctype_to_refnodes= map(get_node_coordinates,reffes) + ctype_to_refnodes = map(get_nodes,dof_bases) cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) cell_physnodes = evaluate(cell_map,cell_to_refnodes) - dof_basis = map(get_dof_basis,reffes) # Not efficient, create a Kernel - cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) + ct_face_moments = map(get_face_moments,dof_bases) + c_face_moments = CompressedArray(ct_face_moments,cell_to_ctype) + ct_face_nodes_dofs = map(get_face_nodes_dofs,dof_bases) + c_face_nodes_dofs = CompressedArray(ct_face_nodes_dofs,cell_to_ctype) + cell_dof_basis = apply( (n,m,nd) -> MomentBasedDofBasis(n,m,nd), + cell_physnodes, c_face_moments, c_face_nodes_dofs) +end - prebasis = map(get_prebasis,reffes) - cell_prebasis = CompressedArray(prebasis,cell_to_ctype) +function _cell_dof_basis_physical_space( + dof_bases::Vector{LagrangianDofBasis{T,V}}, + cell_to_ctype,cell_map) where {T,V} + # Create new dof_basis with nodes in the physical space + # ctype_to_refnodes= map(get_node_coordinates,reffes) + ctype_to_refnodes= map(get_nodes,dof_bases) + cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) + cell_physnodes = evaluate(cell_map,cell_to_refnodes) + cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) +end + +function _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) cell_matrix_inv = apply(inv,cell_matrix) cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) cell_shapefuns = compose(cell_shapefuns_phys,cell_map) - - (cell_shapefuns, cell_dof_basis) end +# function compute_cell_space_physical_space_lagrangian(reffes, cell_to_ctype, cell_map) +# +# +# dof_basis = map(get_dof_basis,reffes) +# # Not efficient, create a Kernel +# cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) +# +# prebasis = map(get_prebasis,reffes) +# cell_prebasis = CompressedArray(prebasis,cell_to_ctype) +# +# cell_shapefuns = _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) +# +# (cell_shapefuns, cell_dof_basis) +# end + """ compute_conforming_cell_dofs( reffes, diff --git a/src/ReferenceFEs/ReferenceFEs.jl b/src/ReferenceFEs/ReferenceFEs.jl index 1e7737a01..0d35c7a0a 100644 --- a/src/ReferenceFEs/ReferenceFEs.jl +++ b/src/ReferenceFEs/ReferenceFEs.jl @@ -81,6 +81,9 @@ export INVALID_PERM export Dof export get_nodes +export get_face_moments +export get_face_nodes_dofs +export get_nodes export evaluate_dof! export evaluate_dof export dof_cache @@ -104,8 +107,6 @@ export num_dofs export NodalReferenceFE export GenericNodalCartesianRefFE -export get_face_own_nodes -export get_face_nodes export get_face_own_nodes_permutations export get_own_nodes_permutations export get_node_coordinates @@ -130,6 +131,10 @@ export is_Q export is_P export is_S +export MomentBasedDofBasis +export get_face_own_nodes +export get_face_nodes + export VERTEX1 export SEG2 export TRI3 diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 1522fe2b3..dc585e66b 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -14,7 +14,7 @@ using Test domain = (0,1,0,1) partition = (2,2) model = CartesianDiscreteModel(domain,partition) -order = 1 +order = 2 # order = 2 trian = get_triangulation(model) @@ -34,7 +34,7 @@ T = Float64 reffes = [LagrangianRefFE(T,p,order) for p in polytopes] -psfs, x = Gridap.FESpaces.compute_cell_space_physical_space_lagrangian(reffes, cell_to_ctype, cell_map) +psfs, x = Gridap.FESpaces.shapefuns_dofs_physical_space(reffes, cell_to_ctype, cell_map) sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) r = evaluate(sfs,q) @@ -59,17 +59,20 @@ rgp = evaluate(gradient(psfs),q) @test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) @test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) -dofp[2] -dof -q[1] -r[1] -rp[1] - ## + dof_bases = map(get_dof_basis,reffes) +Gridap.FESpaces.prueba(dof_bases) + ctype_to_refnodes = map(get_nodes,dof_bases) cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) + +typeof(dof_bases) <: Vector{<:Gridap.ReferenceFEs.MomentBasedDofBasis} + + +function cell_dof + cell_physnodes = evaluate(cell_map,cell_to_refnodes) # Not efficient, create a Kernel @@ -78,18 +81,12 @@ c_face_moments = CompressedArray(ct_face_moments,cell_to_ctype) ct_face_nodes_dofs = map(ReferenceFEs.get_face_nodes_dofs,dof_bases) c_face_nodes_dofs = CompressedArray(ct_face_nodes_dofs,cell_to_ctype) cell_dof_basis = apply( (n,m,nd) -> ReferenceFEs.MomentBasedDofBasis(n,m,nd), - cell_physnodes, c_face_moments, c_face_nodes_dofs) +cell_physnodes, c_face_moments, c_face_nodes_dofs) + + -prebasis = map(get_prebasis,reffes) -cell_prebasis = CompressedArray(prebasis,cell_to_ctype) -cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) -cell_matrix_inv = apply(inv,cell_matrix) -cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) -cell_shapefuns = compose(cell_shapefuns_phys,cell_map) -(cell_shapefuns, cell_dof_basis) -## ## # If I want new evaluation... From 1c5f94163a27557ce892fdbad98180e357d9cba1 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Sat, 7 Mar 2020 17:47:57 +1100 Subject: [PATCH 14/51] Test improvements --- test/FESpacesTests/PhysicalBasesTests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index dc585e66b..5d17eee33 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -34,7 +34,7 @@ T = Float64 reffes = [LagrangianRefFE(T,p,order) for p in polytopes] -psfs, x = Gridap.FESpaces.shapefuns_dofs_physical_space(reffes, cell_to_ctype, cell_map) +psfs, x = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) r = evaluate(sfs,q) @@ -48,7 +48,7 @@ rgp = evaluate(gradient(psfs),q) ## reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] -psfs, dofp = Gridap.FESpaces.compute_cell_space_physical_space_moment(reffes, cell_to_ctype, cell_map) +psfs, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) sfs, dof = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) r = evaluate(sfs,q) From 78d783a0242bb9f8f42a17e32bec1a20b075f217 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Sat, 7 Mar 2020 18:24:27 +1100 Subject: [PATCH 15/51] Machinery for creating Grand and Curl conforming FE spaces with DOFs defined in the physical space... NOT WORKING YET --- src/FESpaces/ConformingFESpaces.jl | 67 +++++-------------- src/FESpaces/DivConformingFESpaces.jl | 13 +++- src/FESpaces/FESpaceFactories.jl | 9 ++- .../DivConformingFESpacesTests.jl | 3 +- test/FESpacesTests/PhysicalBasesTests.jl | 2 + 5 files changed, 37 insertions(+), 57 deletions(-) diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index 5be5cc8d5..1f150ffa1 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -5,12 +5,13 @@ function GradConformingFESpace( reffes::Vector{<:ReferenceFE}, model::DiscreteModel, dirichlet_tags, - dirichlet_components=nothing) + dirichlet_components=nothing, + is_ref=true) face_labeling = get_face_labeling(model) GradConformingFESpace( - reffes,model,face_labeling,dirichlet_tags,dirichlet_components) + reffes,model,face_labeling,dirichlet_tags,dirichlet_components,is_ref) end @@ -19,11 +20,12 @@ function GradConformingFESpace( model::DiscreteModel, order::Integer, dirichlet_tags, - dirichlet_components=nothing) where T + dirichlet_components=nothing, + is_ref=true) where T face_labeling = get_face_labeling(model) - GradConformingFESpace(T,model,order,face_labeling,dirichlet_tags,dirichlet_components) + GradConformingFESpace(T,model,order,face_labeling,dirichlet_tags,dirichlet_components,is_ref) end @@ -33,7 +35,8 @@ function GradConformingFESpace( order::Integer, face_labeling::FaceLabeling, dirichlet_tags, - dirichlet_components=nothing) where T + dirichlet_components=nothing, + is_ref=true) where T grid_topology = get_grid_topology(model) polytopes = get_polytopes(grid_topology) @@ -41,7 +44,7 @@ function GradConformingFESpace( reffes = [ LagrangianRefFE(T,p,order) for p in polytopes ] GradConformingFESpace( - reffes,model,face_labeling,dirichlet_tags,dirichlet_components) + reffes,model,face_labeling,dirichlet_tags,dirichlet_components,is_ref) end @@ -52,7 +55,8 @@ function GradConformingFESpace( model::DiscreteModel, face_labeling::FaceLabeling, dirichlet_tags, - dirichlet_components=nothing) + dirichlet_components=nothing, + is_ref=true) grid_topology = get_grid_topology(model) @@ -67,7 +71,11 @@ function GradConformingFESpace( cell_to_ctype = get_cell_type(grid_topology) cell_map = get_cell_map(grid) - cell_shapefuns, cell_dof_basis = compute_cell_space(reffes, cell_to_ctype, cell_map) + if is_ref + cell_shapefuns, cell_dof_basis = compute_cell_space(reffes, cell_to_ctype, cell_map) + else + cell_shapefuns, cell_dof_basis = compute_cell_space_physical(reffes, cell_to_ctype, cell_map) + end UnconstrainedFESpace( nfree, @@ -104,33 +112,6 @@ are assumed to be computable at a reference FE space. # E.g., if one has to implement $\int_F q ϕ_h(x)$ for $q \in P(F)$, we can # assume that it can be written as $\sum_{x_{gp} \in Q}_{\hat{F}} # \hat{q}(\tilde{x}_{gp}) ϕ(x_{gp})$ for $\hat{q} \in P(\hat{F})$. -# function compute_cell_space_physical_space_moment(reffes, cell_to_ctype, cell_map) -# -# dof_bases = map(get_dof_basis,reffes) -# -# ctype_to_refnodes = map(get_nodes,dof_bases) -# cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) -# cell_physnodes = evaluate(cell_map,cell_to_refnodes) -# -# # Not efficient, create a Kernel -# ct_face_moments = map(ReferenceFEs.get_face_moments,dof_bases) -# c_face_moments = CompressedArray(ct_face_moments,cell_to_ctype) -# ct_face_nodes_dofs = map(ReferenceFEs.get_face_nodes_dofs,dof_bases) -# c_face_nodes_dofs = CompressedArray(ct_face_nodes_dofs,cell_to_ctype) -# cell_dof_basis = apply( (n,m,nd) -> ReferenceFEs.MomentBasedDofBasis(n,m,nd), -# cell_physnodes, c_face_moments, c_face_nodes_dofs) -# -# prebasis = map(get_prebasis,reffes) -# cell_prebasis = CompressedArray(prebasis,cell_to_ctype) -# -# cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) -# cell_matrix_inv = apply(inv,cell_matrix) -# cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) -# cell_shapefuns = compose(cell_shapefuns_phys,cell_map) -# -# (cell_shapefuns, cell_dof_basis) -# end - function compute_cell_space_physical(reffes, cell_to_ctype, cell_map) dof_bases = map(get_dof_basis,reffes) @@ -148,6 +129,7 @@ end function _cell_dof_basis_physical_space(dof_bases,cell_to_ctype,cell_map) @notimplemented end + function _cell_dof_basis_physical_space( dof_bases::Vector{MomentBasedDofBasis{T,V}}, cell_to_ctype,cell_map) where {T,V} @@ -184,21 +166,6 @@ function _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_ cell_shapefuns = compose(cell_shapefuns_phys,cell_map) end -# function compute_cell_space_physical_space_lagrangian(reffes, cell_to_ctype, cell_map) -# -# -# dof_basis = map(get_dof_basis,reffes) -# # Not efficient, create a Kernel -# cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) -# -# prebasis = map(get_prebasis,reffes) -# cell_prebasis = CompressedArray(prebasis,cell_to_ctype) -# -# cell_shapefuns = _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) -# -# (cell_shapefuns, cell_dof_basis) -# end - """ compute_conforming_cell_dofs( reffes, diff --git a/src/FESpaces/DivConformingFESpaces.jl b/src/FESpaces/DivConformingFESpaces.jl index 62009f8f4..8517cdcdd 100644 --- a/src/FESpaces/DivConformingFESpaces.jl +++ b/src/FESpaces/DivConformingFESpaces.jl @@ -10,7 +10,8 @@ function DivConformingFESpace( reffes::Vector{<:ReferenceFE}, model::DiscreteModel, face_labeling::FaceLabeling, - dirichlet_tags) + dirichlet_tags, + is_ref) grid_topology = get_grid_topology(model) @@ -23,7 +24,13 @@ function DivConformingFESpace( cell_to_ctype = get_cell_type(grid_topology) cell_map = get_cell_map(grid) - cell_shapefuns, cell_dof_basis = _compute_hdiv_cell_space(reffes, cell_to_ctype, cell_map) + # cell_shapefuns, cell_dof_basis = _compute_hdiv_cell_space(reffes, cell_to_ctype, cell_map) + if is_ref + cell_shapefuns, cell_dof_basis = compute_cell_space(reffes,cell_to_ctype,cell_map) + else + cell_shapefuns, cell_dof_basis = compute_cell_space_physical(reffes,cell_to_ctype,cell_map) + end + UnconstrainedFESpace( nfree, @@ -40,5 +47,5 @@ end function _compute_hdiv_cell_space(reffes, cell_to_ctype, cell_map) #TODO: fine for structured hex meshes, but not otherwise - compute_cell_space(reffes,cell_to_ctype,cell_map) + # compute_cell_space(reffes,cell_to_ctype,cell_map) end diff --git a/src/FESpaces/FESpaceFactories.jl b/src/FESpaces/FESpaceFactories.jl index 73c3fdc87..75cd6b021 100644 --- a/src/FESpaces/FESpaceFactories.jl +++ b/src/FESpaces/FESpaceFactories.jl @@ -57,6 +57,9 @@ function _setup_hdiv_space(kwargs) conformity = _get_kwarg(:conformity,kwargs,true) diritags = _get_kwarg(:dirichlet_tags,kwargs,Int[]) order = _get_kwarg(:order,kwargs,nothing) + dofspace = _get_kwarg(:dof_space,kwargs,:reference) + ( dofspace == :reference ? true : false ) + Tf = _get_kwarg(:valuetype,kwargs,VectorValue{1,Float64}) T = eltype(Tf) @@ -68,7 +71,7 @@ function _setup_hdiv_space(kwargs) reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] if conformity in [true, :default, :HDiv, :Hdiv] - V = DivConformingFESpace(reffes,model,labels,diritags) + V = DivConformingFESpace(reffes,model,labels,diritags,(dofspace==:reference)) else s = "Conformity $conformity not implemented for $reffe reference FE on polytopes $(polytopes...)" @unreachable s @@ -141,9 +144,9 @@ function _setup_lagrange_spaces(kwargs) elseif conformity in [true, :default, :H1, :C0] if labels == nothing - return GradConformingFESpace(_reffes,model,diritags,dirimasks) + return GradConformingFESpace(_reffes,model,diritags,dirimasks,(dofspace==:reference)) else - return GradConformingFESpace(_reffes,model,labels,diritags,dirimasks) + return GradConformingFESpace(_reffes,model,labels,diritags,dirimasks,(dofspace==:reference)) end else diff --git a/test/FESpacesTests/DivConformingFESpacesTests.jl b/test/FESpacesTests/DivConformingFESpacesTests.jl index 34a9fe2bb..bb9d4d379 100644 --- a/test/FESpacesTests/DivConformingFESpacesTests.jl +++ b/test/FESpacesTests/DivConformingFESpacesTests.jl @@ -20,7 +20,8 @@ V = TestFESpace( conformity = :Hdiv, order = order, model = model, - dirichlet_tags = [1,6]) + dirichlet_tags = [1,6] + dof_space = :reference) test_single_field_fe_space(V) U = TrialFESpace(V,u) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 5d17eee33..3321d5536 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -8,6 +8,8 @@ using Gridap.Polynomials using Test # Start with a PhysicalSpaceCellBasis +a = 1 +b = ( a == 1 ) # domain = (0,1) # partition = (3,) From 0fd0aeaba79111081b8105ca33c9945a08c77a3c Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Mon, 9 Mar 2020 17:36:57 +1100 Subject: [PATCH 16/51] Added methods for interpolation in the physical space --- src/FESpaces/SingleFieldFESpaces.jl | 34 +++++++++++++++++-- src/Fields/Fields.jl | 4 +++ src/Fields/FunctionFields.jl | 21 ++++++++++++ src/Inference/Inference.jl | 1 + .../DivConformingFESpacesTests.jl | 3 +- test/FieldsTests/FunctionFieldsTests.jl | 28 +++++++++++++++ 6 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 src/Fields/FunctionFields.jl create mode 100644 test/FieldsTests/FunctionFieldsTests.jl diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index 935a0cd3b..ff903612f 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -159,7 +159,6 @@ end function _compute_cell_vals(f,cell_field) cell_dof_basis = get_cell_dof_basis(f) - cell_dofs = get_cell_dofs(f) cell_vals = evaluate_dof_array(cell_dof_basis,get_array(cell_field)) cell_vals end @@ -171,6 +170,7 @@ even in the case that the given cell field does not fulfill them) function interpolate(fs::SingleFieldFESpace,object) cell_map = get_cell_map(fs) cell_field = convert_to_cell_field(object,cell_map) + # Here we have a problem because the nodes are in the physical space!!! free_values = compute_free_values(fs,cell_field) FEFunction(fs,free_values) end @@ -196,6 +196,37 @@ function interpolate_dirichlet(fs::SingleFieldFESpace,object) FEFunction(fs,free_values, dirichlet_values) end +function interpolate_physical(fs::SingleFieldFESpace,object) + field = function_field(object) + cell_dof_basis = get_cell_dof_basis(fs) + cell_field = Fill(field,length(get_cell_map(fs))) + # + cell_vals = apply(cell_dof_basis,cell_field) + free_values = gather_free_values(fs,cell_vals) + FEFunction(fs,free_values) +end + +function interpolate_dirichlet_physical(fs::SingleFieldFESpace,object) + field = function_field(object) + cell_dof_basis = get_cell_dof_basis(fs) + cell_field = Fill(field,length(get_cell_map(fs))) + cell_vals = apply(cell_dof_basis,cell_field) + dirichlet_values = gather_dirichlet_values(fs,cell_vals) + free_values = zero_free_values(fs) + FEFunction(fs,free_values, dirichlet_values) +end + +function interpolate_everywhere_physical(fs::SingleFieldFESpace,object) + field = function_field(object) + cell_dof_basis = get_cell_dof_basis(fs) + cell_field = Fill(field,length(get_cell_map(fs))) + cell_vals = apply(cell_dof_basis,cell_field) + fv, dv = gather_free_and_dirichlet_values(fs,cell_vals) + FEFunction(fs,fv,dv) +end + + + """ """ function compute_dirichlet_values_for_tags(f::SingleFieldFESpace,tag_to_object) @@ -231,4 +262,3 @@ end function _convert_to_collectable(object::Number,ntags) _convert_to_collectable(fill(object,ntags),ntags) end - diff --git a/src/Fields/Fields.jl b/src/Fields/Fields.jl index f65e4ab19..4a756b8ab 100644 --- a/src/Fields/Fields.jl +++ b/src/Fields/Fields.jl @@ -69,6 +69,8 @@ export AffineMap export field_operation export field_array_operation +export function_field + import Gridap.Arrays: kernel_cache import Gridap.Arrays: apply_kernel! import Gridap.Arrays: kernel_return_type @@ -85,6 +87,8 @@ include("FieldInterface.jl") include("MockFields.jl") +include("FunctionFields.jl") + include("ConstantFields.jl") include("Homothecies.jl") diff --git a/src/Fields/FunctionFields.jl b/src/Fields/FunctionFields.jl new file mode 100644 index 000000000..b61df5033 --- /dev/null +++ b/src/Fields/FunctionFields.jl @@ -0,0 +1,21 @@ +struct FunctionField{F} + f::F +end + +function_field(f::Function) = FunctionField(f) + +function field_cache(f::FunctionField,x) + nx = length(x) + Te = eltype(x) + c = zeros(return_type(f.f,Te),nx) + CachedArray(c) +end + +function evaluate_field!(c,f::FunctionField,x) + nx = length(x) + setsize!(c,(nx,)) + for i in eachindex(x) + c[i] = f.f(x[i]) + end + c +end diff --git a/src/Inference/Inference.jl b/src/Inference/Inference.jl index b4358c32b..f01589d6b 100644 --- a/src/Inference/Inference.jl +++ b/src/Inference/Inference.jl @@ -119,6 +119,7 @@ It can be overloaded for new types `T` if `zero(T)` does not makes sense. function testvalue end testvalue(::Type{T}) where T = zero(T) +testvalue(v) = testvalue(typeof(v)) function testvalue(::Type{T}) where T<:AbstractArray{E,N} where {E,N} similar(T,fill(0,N)...) diff --git a/test/FESpacesTests/DivConformingFESpacesTests.jl b/test/FESpacesTests/DivConformingFESpacesTests.jl index bb9d4d379..34a9fe2bb 100644 --- a/test/FESpacesTests/DivConformingFESpacesTests.jl +++ b/test/FESpacesTests/DivConformingFESpacesTests.jl @@ -20,8 +20,7 @@ V = TestFESpace( conformity = :Hdiv, order = order, model = model, - dirichlet_tags = [1,6] - dof_space = :reference) + dirichlet_tags = [1,6]) test_single_field_fe_space(V) U = TrialFESpace(V,u) diff --git a/test/FieldsTests/FunctionFieldsTests.jl b/test/FieldsTests/FunctionFieldsTests.jl new file mode 100644 index 000000000..a69f4a2ab --- /dev/null +++ b/test/FieldsTests/FunctionFieldsTests.jl @@ -0,0 +1,28 @@ +using Gridap +using Gridap.Inference +using Gridap.Fields +using Test + +# In this file, I want to create a FunctionField. +# The idea is to create a function that takes points +# and returns a Field value (scalar, vector, tensor). +# Next, make this function cell-wise, and consider it +# as a CellField structure. + +u(x) = x + +p1 = Point(1,2) +p2 = Point(2,1) +p3 = Point(4,3) +p4 = Point(6,1) +x = [p1,p2,p3,p4] + +# First, I want to do some research, in order to infer +# what type of thing it returns... Without more info, +# e.g., space-dim, etc, that is not possible. I would +# need to know the type of point, e.g. Point{D,Float64}. + +f = FunctionField(u) +test_field(f,x,x) + +Fill(f,4) From 160c05ade8dbdfc3bc08830d9dda6ee09e9fb779 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Mon, 9 Mar 2020 17:55:44 +1100 Subject: [PATCH 17/51] Added tests --- src/FESpaces/SingleFieldFESpaces.jl | 21 ++-- test/FESpacesTests/PhysicalBasesTests.jl | 126 +++++++++-------------- 2 files changed, 56 insertions(+), 91 deletions(-) diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index ff903612f..d037b42d5 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -197,36 +197,31 @@ function interpolate_dirichlet(fs::SingleFieldFESpace,object) end function interpolate_physical(fs::SingleFieldFESpace,object) - field = function_field(object) - cell_dof_basis = get_cell_dof_basis(fs) - cell_field = Fill(field,length(get_cell_map(fs))) - # - cell_vals = apply(cell_dof_basis,cell_field) + cell_vals = _physical_cell_vals(fs,object) free_values = gather_free_values(fs,cell_vals) FEFunction(fs,free_values) end function interpolate_dirichlet_physical(fs::SingleFieldFESpace,object) - field = function_field(object) - cell_dof_basis = get_cell_dof_basis(fs) - cell_field = Fill(field,length(get_cell_map(fs))) - cell_vals = apply(cell_dof_basis,cell_field) + cell_vals = _physical_cell_vals(fs,object) dirichlet_values = gather_dirichlet_values(fs,cell_vals) free_values = zero_free_values(fs) FEFunction(fs,free_values, dirichlet_values) end function interpolate_everywhere_physical(fs::SingleFieldFESpace,object) + cell_vals = _physical_cell_vals(fs,object) + fv, dv = gather_free_and_dirichlet_values(fs,cell_vals) + FEFunction(fs,fv,dv) +end + +function _physical_cell_vals(fs::SingleFieldFESpace,object) field = function_field(object) cell_dof_basis = get_cell_dof_basis(fs) cell_field = Fill(field,length(get_cell_map(fs))) cell_vals = apply(cell_dof_basis,cell_field) - fv, dv = gather_free_and_dirichlet_values(fs,cell_vals) - FEFunction(fs,fv,dv) end - - """ """ function compute_dirichlet_values_for_tags(f::SingleFieldFESpace,tag_to_object) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 3321d5536..b110d7617 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -1,3 +1,5 @@ +module PhysicalBasesTests + using Gridap using Gridap.ReferenceFEs using Gridap.Geometry @@ -44,10 +46,20 @@ rg = evaluate(gradient(sfs),q) rp = evaluate(psfs,q) rgp = evaluate(gradient(psfs),q) +func(x) = x +evaluate(func,q) +import Gridap.Fields: evaluate +evaluate(f::Function,x) = apply(f,x) + +cell_field = convert_to_cell_field(func,cell_map) + +isa(cell_field,CellField) + @test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) @test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) -## +# Now RT elements + reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] psfs, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) @@ -61,80 +73,38 @@ rgp = evaluate(gradient(psfs),q) @test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) @test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) -## - -dof_bases = map(get_dof_basis,reffes) - -Gridap.FESpaces.prueba(dof_bases) - -ctype_to_refnodes = map(get_nodes,dof_bases) -cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) - -typeof(dof_bases) <: Vector{<:Gridap.ReferenceFEs.MomentBasedDofBasis} - - -function cell_dof - -cell_physnodes = evaluate(cell_map,cell_to_refnodes) - -# Not efficient, create a Kernel -ct_face_moments = map(ReferenceFEs.get_face_moments,dof_bases) -c_face_moments = CompressedArray(ct_face_moments,cell_to_ctype) -ct_face_nodes_dofs = map(ReferenceFEs.get_face_nodes_dofs,dof_bases) -c_face_nodes_dofs = CompressedArray(ct_face_nodes_dofs,cell_to_ctype) -cell_dof_basis = apply( (n,m,nd) -> ReferenceFEs.MomentBasedDofBasis(n,m,nd), -cell_physnodes, c_face_moments, c_face_nodes_dofs) - - - - - - -## -# If I want new evaluation... -function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) - cell_prebasis_x = evaluate_field_array(cell_prebasis,x) - apply(mul,cell_prebasis_x,cell_prebasis,cell_matrix_inv) -end -function apply_gradient(k::typeof(change_basis),cell_prebasis,cell_matrix_inv) - cell_prebasis_grad = gradient(cell_prebasis) - apply(change_basis,cell_prebasis_grad,cell_matrix_inv) -end -## -# Optimisation : evaluate_field_array for AbstractArray with FieldLike -# Define a new kernel that better treats the inverse -struct InvKernel <: Kernel end -function kernel_cache(k::InvKernel,mat) -end -function apply_kernel!(cache,k::InvKernel,mat) -end -function kernel_cache(k::InvKernel,mat) -CachedArray(copy(mat)) -end -function apply_kernel!(cache,k::InvKernel,mat) - setsize!(cache,size(mat)) - m = cache.array - fill!(m,zero(m)) - for i:size(m,1); m[i] = 1; end - ldiv!(mat,m) - m -end -k = InvKernel() - -isa(cell_prebasis,CellBasis) - -change_basis(cell_prebasis[1],cell_matrix_inv[1]) -## - -# Juno.@enter gradient(cell_prebasis) -# Juno.@enter evaluate(g_cpb,q) - - -a1 = Gridap.Arrays.Fill(1.0,3) -b1 = Gridap.Arrays.Fill(1.0,3) -c1 = Gridap.Arrays.Fill(1.0,3) -f(a,b,c) = a+b+c -p1 = Gridap.Arrays.pair_arrays(a1,b1) -p2 = Gridap.Arrays.pair_arrays(p1,c1) - -apply(f,a1,b1,c1) +end #module + +# # If I want new evaluation... +# function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) +# cell_prebasis_x = evaluate_field_array(cell_prebasis,x) +# apply(mul,cell_prebasis_x,cell_prebasis,cell_matrix_inv) +# end +# function apply_gradient(k::typeof(change_basis),cell_prebasis,cell_matrix_inv) +# cell_prebasis_grad = gradient(cell_prebasis) +# apply(change_basis,cell_prebasis_grad,cell_matrix_inv) +# end +# ## +# # Optimisation : evaluate_field_array for AbstractArray with FieldLike +# # Define a new kernel that better treats the inverse +# struct InvKernel <: Kernel end +# function kernel_cache(k::InvKernel,mat) +# end +# function apply_kernel!(cache,k::InvKernel,mat) +# end +# function kernel_cache(k::InvKernel,mat) +# CachedArray(copy(mat)) +# end +# function apply_kernel!(cache,k::InvKernel,mat) +# setsize!(cache,size(mat)) +# m = cache.array +# fill!(m,zero(m)) +# for i:size(m,1); m[i] = 1; end +# ldiv!(mat,m) +# m +# end +# k = InvKernel() +# +# isa(cell_prebasis,CellBasis) +# +# change_basis(cell_prebasis[1],cell_matrix_inv[1]) From 5d6df6e0fd581fc0132c1278297f90af5fe56733 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Mon, 9 Mar 2020 18:09:44 +1100 Subject: [PATCH 18/51] Bug in FE factories --- src/FESpaces/FESpaceFactories.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FESpaces/FESpaceFactories.jl b/src/FESpaces/FESpaceFactories.jl index 75cd6b021..ef0b4e2aa 100644 --- a/src/FESpaces/FESpaceFactories.jl +++ b/src/FESpaces/FESpaceFactories.jl @@ -88,6 +88,7 @@ function _setup_hcurl_space(kwargs) conformity = _get_kwarg(:conformity,kwargs,true) diritags = _get_kwarg(:dirichlet_tags,kwargs,Int[]) order = _get_kwarg(:order,kwargs,nothing) + dofspace = _get_kwarg(:dof_space,kwargs,:reference) Tf = _get_kwarg(:valuetype,kwargs,VectorValue{1,Float64}) T = eltype(Tf) @@ -116,6 +117,7 @@ function _setup_lagrange_spaces(kwargs) conformity = _get_kwarg(:conformity,kwargs,true) diritags = _get_kwarg(:dirichlet_tags,kwargs,Int[]) dirimasks = _get_kwarg(:dirichlet_masks,kwargs,nothing) + dofspace = _get_kwarg(:dof_space,kwargs,:reference) order = _get_kwarg(:order,kwargs) polytopes = get_polytopes(model) From ddd4c1dc4ce922d832c07f8db58a9bc2d5fbdaa5 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Mon, 9 Mar 2020 22:27:24 +1100 Subject: [PATCH 19/51] Typos --- test/FESpacesTests/FESpaceFactoriesTests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/FESpacesTests/FESpaceFactoriesTests.jl b/test/FESpacesTests/FESpaceFactoriesTests.jl index d4a2d015d..3fd2f4ff1 100644 --- a/test/FESpacesTests/FESpaceFactoriesTests.jl +++ b/test/FESpacesTests/FESpaceFactoriesTests.jl @@ -28,7 +28,7 @@ V = FESpace( order=order, conformity=:L2) -@test isa(V,UnsconstrainedFESpace) +@test isa(V,UnconstrainedFESpace) V = FESpace( model=model, @@ -84,7 +84,7 @@ V = FESpace( #uh = FEFunction(V,rand(num_free_dofs(V))) #writevtk(get_triangulation(model),"trian",nsubcells=20,cellfields=["uh"=>uh]) -@test isa(V,UnsconstrainedFESpace) +@test isa(V,UnconstrainedFESpace) V = FESpace( model=model, From 51eda45e59d541ec889d97cff8108f32aed990ac Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Mon, 9 Mar 2020 22:29:59 +1100 Subject: [PATCH 20/51] curl in physical --- src/FESpaces/FESpaceFactories.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FESpaces/FESpaceFactories.jl b/src/FESpaces/FESpaceFactories.jl index 8abc3dc8c..311e12e2a 100644 --- a/src/FESpaces/FESpaceFactories.jl +++ b/src/FESpaces/FESpaceFactories.jl @@ -108,7 +108,7 @@ function _setup_hcurl_space(kwargs) reffes = [NedelecRefFE(T,p,order) for p in polytopes] if conformity in [true, :default, :HCurl, :Hcurl] - V = CurlConformingFESpace(reffes,model,labels,diritags) + V = CurlConformingFESpace(reffes,model,labels,diritags,(dofspace==:reference)) else s = "Conformity $conformity not implemented for $reffe reference FE on polytopes $(polytopes...)" @unreachable s From 9ba259d6a399dbe2c53ef4569686e69d0ae95de9 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 12 Mar 2020 17:04:59 +1100 Subject: [PATCH 21/51] CellDofBasis and Traits for CellFieldLike --- src/FESpaces/CellDofs.jl | 17 +++++++++++++++++ src/FESpaces/FESpaces.jl | 7 +++++++ src/Geometry/CellFields.jl | 9 ++++++++- src/Geometry/Geometry.jl | 1 + 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/FESpaces/CellDofs.jl diff --git a/src/FESpaces/CellDofs.jl b/src/FESpaces/CellDofs.jl new file mode 100644 index 000000000..90251a3da --- /dev/null +++ b/src/FESpaces/CellDofs.jl @@ -0,0 +1,17 @@ +""" + abstract type CellDofBasis end + +Abstract type that represents a cell array of `Dof`. The main motivation for +its definition is to provide a trait that informs whether the `Dof` entries are +defined for functions in the reference or physical space +""" +abstract type CellDofBasis end + +# RefTrait{::Type{<:CellDofBasis}} = Val{true}() + +struct GenericCellDofBasis{R} <: CellDofBasis + ref_trait::Val{R} + array::AbstractArray{<:Dof} +end + +RefTrait(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() diff --git a/src/FESpaces/FESpaces.jl b/src/FESpaces/FESpaces.jl index 4f1483947..2f37192e7 100644 --- a/src/FESpaces/FESpaces.jl +++ b/src/FESpaces/FESpaces.jl @@ -25,6 +25,7 @@ using Gridap.TensorValues using Gridap.Geometry: CellFieldLike using Gridap.Geometry: UnimplementedField using Gridap.Geometry: test_cell_field_like + using Gridap.Arrays: _split using Gridap.Arrays: Reindexed using Gridap.Arrays: IdentityVector @@ -41,6 +42,7 @@ import Gridap.Geometry: get_cell_map import Gridap.Geometry: get_cell_shapefuns import Gridap.Geometry: get_reffes import Gridap.Geometry: get_cell_type +import Gridap.Geometry: RefTrait import Gridap.Helpers: operate import Gridap.Geometry: similar_object import Gridap.Geometry: jump @@ -146,6 +148,9 @@ export is_trial export is_test export attach_dirichlet_bcs +export CellDofBasis +export GenericCellDofBasis + export FECellBasisStyle export is_a_fe_cell_basis @@ -205,6 +210,8 @@ export update_state_variables! include("CellBases.jl") +include("CellDofs.jl") + include("Law.jl") include("FEFunctions.jl") diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 726038fce..0721523b0 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -18,6 +18,14 @@ function get_cell_map(cf::CellFieldLike) @abstractmethod end +""" +This trait returns `Val{true}()` when the `CellFieldLike` is defined in a +reference finite element space, and `Val{false}()` when it is defined in the +physical space +""" +RefTrait(::Type{<:CellFieldLike}) = Val{true}() +RefTrait(a) = RefTrait(typeof(a)) + """ similar_object(cf::CellFieldLike,array::AbstractArray) """ @@ -280,4 +288,3 @@ function operate(op,object,cf2::SkeletonCellField) cf1 = convert_to_cell_field(object,cm) operate(op,cf1,cf2) end - diff --git a/src/Geometry/Geometry.jl b/src/Geometry/Geometry.jl index 81aa25629..2ae859c17 100644 --- a/src/Geometry/Geometry.jl +++ b/src/Geometry/Geometry.jl @@ -88,6 +88,7 @@ import Gridap.Arrays: apply_kernel! export CellField export GenericCellField export SkeletonCellField +export RefTrait export similar_object export test_cell_field export convert_to_cell_field From 5a1fcfd08772def0ac8c10c0f9f74caee402c1e7 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 12 Mar 2020 18:39:55 +1100 Subject: [PATCH 22/51] Added CellDofBasis to FE spaces constructors --- src/FESpaces/CellDofs.jl | 5 +++-- src/FESpaces/ConformingFESpaces.jl | 3 +++ src/FESpaces/CurlConformingFESpaces.jl | 9 +++++++-- test/FESpacesTests/PhysicalBasesTests.jl | 13 ++++++++++--- test/GeometryTests/CellFieldsTests.jl | 3 +++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/FESpaces/CellDofs.jl b/src/FESpaces/CellDofs.jl index 90251a3da..24d3b9c49 100644 --- a/src/FESpaces/CellDofs.jl +++ b/src/FESpaces/CellDofs.jl @@ -7,11 +7,12 @@ defined for functions in the reference or physical space """ abstract type CellDofBasis end -# RefTrait{::Type{<:CellDofBasis}} = Val{true}() - struct GenericCellDofBasis{R} <: CellDofBasis ref_trait::Val{R} array::AbstractArray{<:Dof} + + GenericCellDofBasis(R,array) = new{R}(Val{R}(),array) + end RefTrait(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index 1f150ffa1..120adc722 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -96,6 +96,7 @@ function compute_cell_space(reffes, cell_to_ctype, cell_map) dof_basis = map(get_dof_basis,reffes) cell_dof_basis = CompressedArray(dof_basis,cell_to_ctype) + cell_dof_basis = GenericCellDofBasis(true,cell_dof_basis) shapefuns = map(get_shapefuns,reffes) refshapefuns = CompressedArray(shapefuns,cell_to_ctype) @@ -117,6 +118,7 @@ function compute_cell_space_physical(reffes, cell_to_ctype, cell_map) dof_bases = map(get_dof_basis,reffes) cell_dof_basis = _cell_dof_basis_physical_space(dof_bases,cell_to_ctype,cell_map) + cell_dof_basis = GenericCellDofBasis(false,cell_dof_basis) prebasis = map(get_prebasis,reffes) cell_prebasis = CompressedArray(prebasis,cell_to_ctype) @@ -157,6 +159,7 @@ function _cell_dof_basis_physical_space( cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) cell_physnodes = evaluate(cell_map,cell_to_refnodes) cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) + cell_dof_basis = GenericCellDofBasis(false,cell_dof_basis) end function _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) diff --git a/src/FESpaces/CurlConformingFESpaces.jl b/src/FESpaces/CurlConformingFESpaces.jl index 817ba7c69..c4c68be3b 100644 --- a/src/FESpaces/CurlConformingFESpaces.jl +++ b/src/FESpaces/CurlConformingFESpaces.jl @@ -24,7 +24,12 @@ function CurlConformingFESpace( cell_to_ctype = get_cell_type(grid_topology) cell_map = get_cell_map(grid) - cell_shapefuns, cell_dof_basis = _compute_hcurl_cell_space(reffes, cell_to_ctype, cell_map) + # cell_shapefuns, cell_dof_basis = _compute_hcurl_cell_space(reffes, cell_to_ctype, cell_map) + if is_ref + cell_shapefuns, cell_dof_basis = compute_cell_space(reffes,cell_to_ctype,cell_map) + else + cell_shapefuns, cell_dof_basis = compute_cell_space_physical(reffes,cell_to_ctype,cell_map) + end UnconstrainedFESpace( nfree, @@ -41,5 +46,5 @@ end function _compute_hcurl_cell_space(reffes, cell_to_ctype, cell_map) #TODO: fine for structured hex meshes, but not otherwise - compute_cell_space(reffes,cell_to_ctype,cell_map) + # compute_cell_space(reffes,cell_to_ctype,cell_map) end diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index b110d7617..1e5eaa011 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -1,4 +1,4 @@ -module PhysicalBasesTests +# module PhysicalBasesTests using Gridap using Gridap.ReferenceFEs @@ -47,7 +47,7 @@ rp = evaluate(psfs,q) rgp = evaluate(gradient(psfs),q) func(x) = x -evaluate(func,q) +# evaluate(func,q) import Gridap.Fields: evaluate evaluate(f::Function,x) = apply(f,x) @@ -65,6 +65,13 @@ reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] psfs, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) sfs, dof = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) +GenericCellDofBasis(true,dof) + +isa(dof,AbstractArray{<:Dof}) + +methods(RefTrait) + + r = evaluate(sfs,q) rg = evaluate(gradient(sfs),q) rp = evaluate(psfs,q) @@ -73,7 +80,7 @@ rgp = evaluate(gradient(psfs),q) @test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) @test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) -end #module +# end #module # # If I want new evaluation... # function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) diff --git a/test/GeometryTests/CellFieldsTests.jl b/test/GeometryTests/CellFieldsTests.jl index 72a83b16a..940571ed9 100644 --- a/test/GeometryTests/CellFieldsTests.jl +++ b/test/GeometryTests/CellFieldsTests.jl @@ -29,6 +29,9 @@ r = [[0.0], [2.0], [0.0], [2.0]] g = Vector{VectorValue{2,Float64}}[[(1, 0)], [(1, 0)], [(1, 0)], [(1, 0)]] test_cell_field(cf1,q,r,grad=g) +isa(cf1,Gridap.Geometry.CellFieldLike) +@test RefTrait(cf1) == Val{true}() + cf2 = cf1 + 4 r2 = map( (i) -> i.+4, r) test_cell_field(cf2,q,r2) From 2f53775a2e009994e4ad6cfb80802e4cac884593 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 12 Mar 2020 18:56:49 +1100 Subject: [PATCH 23/51] Fixing bugs --- src/FESpaces/CellDofs.jl | 2 ++ src/FESpaces/SingleFieldFESpaces.jl | 2 +- src/FESpaces/UnconstrainedFESpaces.jl | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/FESpaces/CellDofs.jl b/src/FESpaces/CellDofs.jl index 24d3b9c49..c3bc48faa 100644 --- a/src/FESpaces/CellDofs.jl +++ b/src/FESpaces/CellDofs.jl @@ -16,3 +16,5 @@ struct GenericCellDofBasis{R} <: CellDofBasis end RefTrait(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() + +get_array(a::GenericCellDofBasis) = a.array diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index d037b42d5..dfd81b4a4 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -159,7 +159,7 @@ end function _compute_cell_vals(f,cell_field) cell_dof_basis = get_cell_dof_basis(f) - cell_vals = evaluate_dof_array(cell_dof_basis,get_array(cell_field)) + cell_vals = evaluate_dof_array(get_array(cell_dof_basis),get_array(cell_field)) cell_vals end diff --git a/src/FESpaces/UnconstrainedFESpaces.jl b/src/FESpaces/UnconstrainedFESpaces.jl index 213a16140..045029190 100644 --- a/src/FESpaces/UnconstrainedFESpaces.jl +++ b/src/FESpaces/UnconstrainedFESpaces.jl @@ -20,7 +20,7 @@ struct UnconstrainedFESpace{A,B,C} <: SingleFieldFESpace ndirichlet::Int, cell_dofs::AbstractArray, cell_shapefuns::AbstractArray, - cell_dof_basis::AbstractArray, + cell_dof_basis::CellDofBasis, cell_map::AbstractArray, dirichlet_dof_tag::Vector{Int8}, dirichlet_cells::Vector{Int}, From f7421a86875fc617d18d0e84b99439298aee9cbc Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 12 Mar 2020 20:45:24 +1100 Subject: [PATCH 24/51] fixing extended fe space --- src/FESpaces/ExtendedFESpaces.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FESpaces/ExtendedFESpaces.jl b/src/FESpaces/ExtendedFESpaces.jl index a5217a2ba..fb4d34a02 100644 --- a/src/FESpaces/ExtendedFESpaces.jl +++ b/src/FESpaces/ExtendedFESpaces.jl @@ -160,6 +160,7 @@ end function get_cell_dof_basis(f::ExtendedFESpace) cell_to_val = get_cell_dof_basis(f.space) + cell_to_val = cell_to_val.array D = num_dims(f.trian) T = Float64 # TODO @@ -223,4 +224,3 @@ function TrialFESpace(f::ExtendedFESpace) U = TrialFESpace(f.space) ExtendedFESpace(U,f.trian) end - From 213cccdaa0d02e30fcf69c0bea1267dbaa0e8f81 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 13 Mar 2020 13:50:24 +1100 Subject: [PATCH 25/51] Adding methods, traits, fixing bugs --- docs/src/ReferenceFEs.md | 4 +-- src/FESpaces/CellDofs.jl | 37 ++++++++++++++++++++++++ src/FESpaces/ConformingFESpaces.jl | 3 +- src/FESpaces/SingleFieldFESpaces.jl | 2 +- src/ReferenceFEs/Dofs.jl | 7 +++-- src/ReferenceFEs/ReferenceFEs.jl | 2 +- test/FESpacesTests/PhysicalBasesTests.jl | 1 + 7 files changed, 47 insertions(+), 9 deletions(-) diff --git a/docs/src/ReferenceFEs.md b/docs/src/ReferenceFEs.md index 33a85105f..46afc51b1 100644 --- a/docs/src/ReferenceFEs.md +++ b/docs/src/ReferenceFEs.md @@ -83,7 +83,7 @@ evaluate_dof(dof,field) evaluate(dof::Dof,field) ``` -### Working with arrays of DOFs + ## Reference Finite Elements diff --git a/src/FESpaces/CellDofs.jl b/src/FESpaces/CellDofs.jl index c3bc48faa..f3667b646 100644 --- a/src/FESpaces/CellDofs.jl +++ b/src/FESpaces/CellDofs.jl @@ -18,3 +18,40 @@ end RefTrait(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() get_array(a::GenericCellDofBasis) = a.array + +""" + evaluate(dof_array::CellDofBasis,field_array::AbstractArray) + +Evaluates the `CellDofBasis` for the `Field` objects +at the array `field` element by element. + +The result is numerically equivalent to + + map(evaluate_dof, dof_array.array, field_array) + +but it is described with a more memory-friendly lazy type. +""" +function evaluate(cell_dofs::CellDofBasis,cell_field) #::CellFieldLike) + _evaluate_cell_dofs(cell_dofs,cell_field,RefTrait(cell_dofs)) +end + +function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{true}) + evaluate_dof_array(get_array(cell_dofs),get_array(_to_ref_space(cell_field)),ref_trait) +end + +function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{false}) + evaluate_dof_array(get_array(cell_dofs),get_array(_to_physical_space(cell_field)),ref_trait) +end + +function evaluate_dof_array(dof_array::AbstractArray,field_array::AbstractArray,::Val{true}) + k = DofEval() + apply(k,dof,field) +end + +function evaluate_dof_array(dof_array::AbstractArray,field_array::AbstractArray,::Val{false}) + apply(dof_array,field_array) +end + +_to_ref_space(a) = a + +_to_physical_space(a) = a diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index 120adc722..f7a8075cf 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -159,11 +159,10 @@ function _cell_dof_basis_physical_space( cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) cell_physnodes = evaluate(cell_map,cell_to_refnodes) cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) - cell_dof_basis = GenericCellDofBasis(false,cell_dof_basis) end function _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) - cell_matrix = evaluate_dof_array(cell_dof_basis,cell_prebasis) + cell_matrix = evaluate(cell_dof_basis,cell_prebasis) cell_matrix_inv = apply(inv,cell_matrix) cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) cell_shapefuns = compose(cell_shapefuns_phys,cell_map) diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index dfd81b4a4..7aff6d281 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -159,7 +159,7 @@ end function _compute_cell_vals(f,cell_field) cell_dof_basis = get_cell_dof_basis(f) - cell_vals = evaluate_dof_array(get_array(cell_dof_basis),get_array(cell_field)) + cell_vals = evaluate(cell_dof_basis,get_array(cell_field)) cell_vals end diff --git a/src/ReferenceFEs/Dofs.jl b/src/ReferenceFEs/Dofs.jl index 41e27f5f3..76884e343 100644 --- a/src/ReferenceFEs/Dofs.jl +++ b/src/ReferenceFEs/Dofs.jl @@ -129,12 +129,12 @@ The result is numerically equivalent to but it is described with a more memory-friendly lazy type. """ -function evaluate_dof_array(dof::AbstractArray,field::AbstractArray) +function evaluate_dof_array(dof::AbstractArray,field::AbstractArray,::Val{true}) k = DofEval() apply(k,dof,field) end -function evaluate_dof_array(dof::AbstractArray{<:Dof},field::AbstractArray) +function evaluate_dof_array(dof::AbstractArray{<:Dof},field::AbstractArray,::Val{false}) apply(dof,field) end @@ -143,6 +143,8 @@ end Equivalent to `evaluate_dof_array(dof,field)` """ +# @santiagobadia : I have put the trait for the moment, not sure it is needed... +# If we keep it, I have to change the documentation function evaluate(dof::AbstractArray{<:Dof},field::AbstractArray) evaluate_dof_array(dof,field) end @@ -160,4 +162,3 @@ end function kernel_return_type(k::DofEval,dof,field) dof_return_type(dof,field) end - diff --git a/src/ReferenceFEs/ReferenceFEs.jl b/src/ReferenceFEs/ReferenceFEs.jl index 0d35c7a0a..d2f22b93d 100644 --- a/src/ReferenceFEs/ReferenceFEs.jl +++ b/src/ReferenceFEs/ReferenceFEs.jl @@ -89,7 +89,7 @@ export evaluate_dof export dof_cache export dof_return_type export test_dof -export evaluate_dof_array +# export evaluate_dof_array export ReferenceFE export GenericRefFE diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 1e5eaa011..b53160a85 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -38,6 +38,7 @@ T = Float64 reffes = [LagrangianRefFE(T,p,order) for p in polytopes] +# Juno.@enter Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) psfs, x = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) From cdeb6bfc5c56a24349ff1dd922661656a493e23f Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 13 Mar 2020 15:16:25 +1100 Subject: [PATCH 26/51] Now working interpolation --- src/FESpaces/{CellDofs.jl => CellDofBases.jl} | 17 +++---- src/FESpaces/FESpaces.jl | 4 +- src/FESpaces/FESpacesInterfaces.jl | 1 - src/FESpaces/SingleFieldFESpaces.jl | 46 +++++++++++++------ src/Geometry/CellFields.jl | 4 +- test/FESpacesTests/PhysicalBasesTests.jl | 7 --- 6 files changed, 45 insertions(+), 34 deletions(-) rename src/FESpaces/{CellDofs.jl => CellDofBases.jl} (80%) diff --git a/src/FESpaces/CellDofs.jl b/src/FESpaces/CellDofBases.jl similarity index 80% rename from src/FESpaces/CellDofs.jl rename to src/FESpaces/CellDofBases.jl index f3667b646..93b35e460 100644 --- a/src/FESpaces/CellDofs.jl +++ b/src/FESpaces/CellDofBases.jl @@ -16,6 +16,7 @@ struct GenericCellDofBasis{R} <: CellDofBasis end RefTrait(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() +RefTrait(a::GenericCellDofBasis) = RefTrait(typeof(a)) get_array(a::GenericCellDofBasis) = a.array @@ -43,14 +44,14 @@ function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{false}) evaluate_dof_array(get_array(cell_dofs),get_array(_to_physical_space(cell_field)),ref_trait) end -function evaluate_dof_array(dof_array::AbstractArray,field_array::AbstractArray,::Val{true}) - k = DofEval() - apply(k,dof,field) -end - -function evaluate_dof_array(dof_array::AbstractArray,field_array::AbstractArray,::Val{false}) - apply(dof_array,field_array) -end +# function evaluate_dof_array(dof_array::AbstractArray,field_array::AbstractArray,::Val{true}) +# k = DofEval() +# apply(k,dof_array,field) +# end +# +# function evaluate_dof_array(dof_array::AbstractArray,field_array::AbstractArray,::Val{false}) +# apply(dof_array,field_array) +# end _to_ref_space(a) = a diff --git a/src/FESpaces/FESpaces.jl b/src/FESpaces/FESpaces.jl index 2f37192e7..8943e1523 100644 --- a/src/FESpaces/FESpaces.jl +++ b/src/FESpaces/FESpaces.jl @@ -22,6 +22,8 @@ using Gridap.Algebra using Gridap.Polynomials using Gridap.TensorValues +using Gridap.ReferenceFEs: evaluate_dof_array + using Gridap.Geometry: CellFieldLike using Gridap.Geometry: UnimplementedField using Gridap.Geometry: test_cell_field_like @@ -210,7 +212,7 @@ export update_state_variables! include("CellBases.jl") -include("CellDofs.jl") +include("CellDofBases.jl") include("Law.jl") diff --git a/src/FESpaces/FESpacesInterfaces.jl b/src/FESpaces/FESpacesInterfaces.jl index 7f44bc8f6..68fad9a7e 100644 --- a/src/FESpaces/FESpacesInterfaces.jl +++ b/src/FESpaces/FESpacesInterfaces.jl @@ -268,4 +268,3 @@ end a = apply_kernel!(cmat,k.kmat,mat,cellid) (a,vec) end - diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index 7aff6d281..881a3bda9 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -168,27 +168,54 @@ The resulting FE function is in the space (in particular it fulfills Dirichlet B even in the case that the given cell field does not fulfill them) """ function interpolate(fs::SingleFieldFESpace,object) + cdb = get_cell_dof_basis(fs) + _interpolate(fs,object,RefTrait(cdb)) +end + +function _interpolate(fs,object,::Val{true}) + cell_dofs = get_cell_dofs cell_map = get_cell_map(fs) cell_field = convert_to_cell_field(object,cell_map) - # Here we have a problem because the nodes are in the physical space!!! free_values = compute_free_values(fs,cell_field) FEFunction(fs,free_values) end +function _interpolate(fs,object,::Val{false}) + cell_vals = _physical_cell_vals(fs,object) + free_values = gather_free_values(fs,cell_vals) + FEFunction(fs,free_values) +end + """ like interpolate, but also compute new degrees of freedom for the dirichlet component. The resulting FEFunction does not necessary belongs to the underlying space """ function interpolate_everywhere(fs::SingleFieldFESpace,object) + cdb = get_cell_dof_basis(fs) + _interpolate_everywhere(fs,object,RefTrait(cdb)) +end + +function _interpolate_everywhere(fs,object,::Val{true}) cell_map = get_cell_map(fs) cell_field = convert_to_cell_field(object,cell_map) free_values, dirichlet_values = compute_free_and_dirichlet_values(fs,cell_field) FEFunction(fs,free_values, dirichlet_values) end +function _interpolate_everywhere(fs,object,::Val{false}) + cell_vals = _physical_cell_vals(fs,object) + fv, dv = gather_free_and_dirichlet_values(fs,cell_vals) + FEFunction(fs,fv,dv) +end + """ """ function interpolate_dirichlet(fs::SingleFieldFESpace,object) + cdb = get_cell_dof_basis(fs) + _interpolate_dirichlet(fs,object,RefTrait(cdb)) +end + +function _interpolate_dirichlet(fs,object,::Val{true}) cell_map = get_cell_map(fs) cell_field = convert_to_cell_field(object,cell_map) dirichlet_values = compute_dirichlet_values(fs,cell_field) @@ -196,30 +223,18 @@ function interpolate_dirichlet(fs::SingleFieldFESpace,object) FEFunction(fs,free_values, dirichlet_values) end -function interpolate_physical(fs::SingleFieldFESpace,object) - cell_vals = _physical_cell_vals(fs,object) - free_values = gather_free_values(fs,cell_vals) - FEFunction(fs,free_values) -end - -function interpolate_dirichlet_physical(fs::SingleFieldFESpace,object) +function _interpolate_dirichlet(fs,object,::Val{false}) cell_vals = _physical_cell_vals(fs,object) dirichlet_values = gather_dirichlet_values(fs,cell_vals) free_values = zero_free_values(fs) FEFunction(fs,free_values, dirichlet_values) end -function interpolate_everywhere_physical(fs::SingleFieldFESpace,object) - cell_vals = _physical_cell_vals(fs,object) - fv, dv = gather_free_and_dirichlet_values(fs,cell_vals) - FEFunction(fs,fv,dv) -end - function _physical_cell_vals(fs::SingleFieldFESpace,object) field = function_field(object) cell_dof_basis = get_cell_dof_basis(fs) cell_field = Fill(field,length(get_cell_map(fs))) - cell_vals = apply(cell_dof_basis,cell_field) + cell_vals = apply(cell_dof_basis.array,cell_field) end """ @@ -254,6 +269,7 @@ function _convert_to_collectable(object::Function,ntags) _convert_to_collectable(fill(object,ntags),ntags) end + function _convert_to_collectable(object::Number,ntags) _convert_to_collectable(fill(object,ntags),ntags) end diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 0721523b0..d6bafc43d 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -23,8 +23,8 @@ This trait returns `Val{true}()` when the `CellFieldLike` is defined in a reference finite element space, and `Val{false}()` when it is defined in the physical space """ -RefTrait(::Type{<:CellFieldLike}) = Val{true}() -RefTrait(a) = RefTrait(typeof(a)) +# RefTrait(::Type{<:CellFieldLike}) = Val{true}() +# RefTrait(a) = RefTrait(typeof(a)) """ similar_object(cf::CellFieldLike,array::AbstractArray) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index b53160a85..b764cf13e 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -66,13 +66,6 @@ reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] psfs, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) sfs, dof = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) -GenericCellDofBasis(true,dof) - -isa(dof,AbstractArray{<:Dof}) - -methods(RefTrait) - - r = evaluate(sfs,q) rg = evaluate(gradient(sfs),q) rp = evaluate(psfs,q) From 8e15408ee9347159a57010efea05fc6327d00665 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 13 Mar 2020 21:53:24 +1100 Subject: [PATCH 27/51] minor --- src/FESpaces/CellDofBases.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index 93b35e460..6ec7f1b04 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -53,6 +53,8 @@ end # apply(dof_array,field_array) # end + +# @santiagobadia : To create trait for CellBasis and CellField and implement these methods _to_ref_space(a) = a _to_physical_space(a) = a From ec1453b4f19f01929fd3aa307fd72fbf56695f8c Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Wed, 18 Mar 2020 10:15:10 +1100 Subject: [PATCH 28/51] Adding Trails to CellBasis and CellFields --- src/FESpaces/CellBases.jl | 23 ++++++++++++++++++++--- src/FESpaces/UnconstrainedFESpaces.jl | 2 +- src/Geometry/CellFields.jl | 12 +++++++++++- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index d1bcb86b0..560d054cf 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -191,17 +191,29 @@ end """ """ -struct GenericCellBasis{T} <: CellBasis +struct GenericCellBasis{T,R} <: CellBasis trial_style::Val{T} array cell_map + ref_trait::Val{R} end """ """ function GenericCellBasis(array::AbstractArray,cell_map::AbstractArray) trial_style = Val{false}() - GenericCellBasis(trial_style,array,cell_map) + ref_trait = Val{true}() + GenericCellBasis(trial_style,array,cell_map,ref_trait) +end + +function GenericCellBasis(trial_style::Val{T},array::AbstractArray,cell_map::AbstractArray) where T + ref_trait = Val{true}() + GenericCellBasis(trial_style,array,cell_map,ref_trait) +end + +function GenericCellBasis(array::AbstractArray,cell_map::AbstractArray,ref_trait::Val{R}) where R + trial_style = Val{false}() + GenericCellBasis(trial_style,array,cell_map,ref_trait) end get_array(a::GenericCellBasis) = a.array @@ -212,6 +224,12 @@ function TrialStyle(::Type{<:GenericCellBasis{T}}) where T Val{T}() end +function RefTrait(::Type{<:GenericCellBasis{T,R}}) where {T,R} + Val{R}() +end + +RefTrait(a::GenericCellBasis) = RefTrait(typeof(a)) + # CellMatrixField """ @@ -635,4 +653,3 @@ end add_to_array!(vecd,vec) (mat, vecd) end - diff --git a/src/FESpaces/UnconstrainedFESpaces.jl b/src/FESpaces/UnconstrainedFESpaces.jl index 045029190..271292a8e 100644 --- a/src/FESpaces/UnconstrainedFESpaces.jl +++ b/src/FESpaces/UnconstrainedFESpaces.jl @@ -26,7 +26,7 @@ struct UnconstrainedFESpace{A,B,C} <: SingleFieldFESpace dirichlet_cells::Vector{Int}, ntags) where T - cell_basis = GenericCellBasis(cell_shapefuns,cell_map) + cell_basis = GenericCellBasis(cell_shapefuns,cell_map,RefTrait(cell_dof_basis)) A = typeof(cell_dofs) B = typeof(cell_basis) diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index d6bafc43d..c0a90dcf7 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -189,9 +189,14 @@ end cell_map::AbstractArray end """ -struct GenericCellField <: CellField +struct GenericCellField{R} <: CellField array::AbstractArray cell_map::AbstractArray + ref_trait::Val{R} +end + +function GenericCellField(array::AbstractArray,cell_map::AbstractArray) + GenericCellField(array,cell_map,Val{true}) end function get_array(cf::GenericCellField) @@ -202,6 +207,11 @@ function get_cell_map(cf::GenericCellField) cf.cell_map end +function RefTrait(::Type{<:GenericCellField{R}}) where {R} + Val{R}() +end + +RefTrait(a::GenericCellField) = RefTrait(typeof(a)) # Skeleton related From f748683518243b558af30dd8494294b9200ec15d Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 19 Mar 2020 10:16:37 +1100 Subject: [PATCH 29/51] Fixing typos, misc changes --- docs/src/TensorValues.md | 2 +- src/FESpaces/CLagrangianFESpaces.jl | 5 ++-- src/FESpaces/CellBases.jl | 20 +++++++++++++ src/FESpaces/ConformingFESpaces.jl | 2 +- src/FESpaces/FESpaceFactories.jl | 12 +++++--- src/Fields/DiffOperators.jl | 2 +- src/Fields/FieldOperations.jl | 2 +- src/Fields/Fields.jl | 2 +- src/Geometry/CellFields.jl | 2 +- src/TensorValues/Operations.jl | 4 +-- src/TensorValues/TensorValues.jl | 2 +- test/FESpacesTests/PhysicalBasesTests.jl | 34 ++++++++++++++++------- test/FieldsTests/DiffOperatorsTests.jl | 2 +- test/TensorValuesTests/OperationsTests.jl | 2 +- 14 files changed, 65 insertions(+), 28 deletions(-) diff --git a/docs/src/TensorValues.md b/docs/src/TensorValues.md index e47f09c4e..80e7678df 100644 --- a/docs/src/TensorValues.md +++ b/docs/src/TensorValues.md @@ -34,6 +34,6 @@ n_components inner outer meas -symmetic_part +symmetric_part ``` diff --git a/src/FESpaces/CLagrangianFESpaces.jl b/src/FESpaces/CLagrangianFESpaces.jl index 0a58c000d..810c0e4b5 100644 --- a/src/FESpaces/CLagrangianFESpaces.jl +++ b/src/FESpaces/CLagrangianFESpaces.jl @@ -19,7 +19,7 @@ struct CLagrangianFESpace{S} <: SingleFieldFESpace CLagrangianFESpace(::Type{T},grid::Grid) where T """ function CLagrangianFESpace(::Type{T},grid::Grid) where T - space, dof_to_node, dof_to_comp, node_and_comp_to_dof = _generate_clargangian_fespace(T,grid) + space, dof_to_node, dof_to_comp, node_and_comp_to_dof = _generate_clagrangian_fespace(T,grid) S = eltype(node_and_comp_to_dof) new{S}(space,grid,dof_to_node,dof_to_comp,node_and_comp_to_dof) end @@ -81,7 +81,7 @@ end # Helpers -function _generate_clargangian_fespace(T,grid) +function _generate_clagrangian_fespace(T,grid) grid_reffes = get_reffes(grid) function fun(reffe) @@ -235,4 +235,3 @@ function _fill_cell_dofs_clagrangian_fespace!( end end - diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index 560d054cf..e6307aa74 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -16,6 +16,8 @@ end TrialStyle(cb) = TrialStyle(typeof(cb)) +RefTrait(::CellBasis) = @notimplemented + """ """ is_trial(cb) = is_trial(typeof(cb)) @@ -230,6 +232,24 @@ end RefTrait(a::GenericCellBasis) = RefTrait(typeof(a)) +function evaluate(cf::GenericCellBasis,x) + ref_trait = RefTrait(cf) + _evaluate(cf,x,ref_trait) +end + +function _evaluate(cf,x,::Val{true}) where R + a = get_array(cf) + evaluate_field_array(a,x) +end + +function _evaluate(cf,x,::Val{false}) where R + # @santiagobadia : How to implement it more efficiently? + cm = get_cell_map(cf) + _x = evaluate(cm,x) + a = get_array(cf) + evaluate_field_array(a,_x) +end + # CellMatrixField """ diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index f7a8075cf..c73fe3bc2 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -158,7 +158,7 @@ function _cell_dof_basis_physical_space( ctype_to_refnodes= map(get_nodes,dof_bases) cell_to_refnodes = CompressedArray(ctype_to_refnodes,cell_to_ctype) cell_physnodes = evaluate(cell_map,cell_to_refnodes) - cell_dof_basis = apply( nodes -> LagrangianDofBasis(Float64,nodes), cell_physnodes ) + cell_dof_basis = apply( nodes -> LagrangianDofBasis(V,nodes), cell_physnodes ) end function _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) diff --git a/src/FESpaces/FESpaceFactories.jl b/src/FESpaces/FESpaceFactories.jl index 311e12e2a..4360fb796 100644 --- a/src/FESpaces/FESpaceFactories.jl +++ b/src/FESpaces/FESpaceFactories.jl @@ -3,7 +3,8 @@ """ function FESpace(;kwargs...) - constraint = _get_kwarg(:constraint,kwargs,nothing) + # constraint = _get_kwarg(:constraint,kwargs,nothing) + constraint = nothing reffe = _get_kwarg(:reffe,kwargs) @notimplementedif !isa(reffe,Symbol) "For the moment, reffe can only be a symbol" @@ -41,7 +42,8 @@ function FESpace(;kwargs...) @unreachable "Unknown constraint value $constraint" end - restricted_at = _get_kwarg(:restricted_at,kwargs,nothing) + # restricted_at = _get_kwarg(:restricted_at,kwargs,nothing) + restricted_at = nothing if restricted_at == nothing return _fespace else @@ -124,9 +126,11 @@ function _setup_lagrange_spaces(kwargs) order = _get_kwarg(:order,kwargs) T = _get_kwarg(:valuetype,kwargs,nothing) diritags = _get_kwarg(:dirichlet_tags,kwargs,Int[]) - dirimasks = _get_kwarg(:dirichlet_masks,kwargs,nothing) + # dirimasks = _get_kwarg(:dirichlet_masks,kwargs,nothing) + dirimasks = nothing dofspace = _get_kwarg(:dof_space,kwargs,:reference) - labels = _get_kwarg(:labels,kwargs,nothing) + # labels = _get_kwarg(:labels,kwargs,nothing) + labels = nothing model = _get_kwarg(:model,kwargs,nothing) if T == nothing diff --git a/src/Fields/DiffOperators.jl b/src/Fields/DiffOperators.jl index 8f499d945..d39582f8f 100644 --- a/src/Fields/DiffOperators.jl +++ b/src/Fields/DiffOperators.jl @@ -9,7 +9,7 @@ function symmetric_gradient end """ symmetric_gradient(f) """ -symmetric_gradient(f) = symmetic_part(gradient(f)) +symmetric_gradient(f) = symmetric_part(gradient(f)) """ const ε = symmetric_gradient diff --git a/src/Fields/FieldOperations.jl b/src/Fields/FieldOperations.jl index 67420ec92..5e35ce939 100644 --- a/src/Fields/FieldOperations.jl +++ b/src/Fields/FieldOperations.jl @@ -40,7 +40,7 @@ end # Unary operations on fields and arrays of fields -for op in (:+,:-,:tr, :transpose, :adjoint, :symmetic_part) +for op in (:+,:-,:tr, :transpose, :adjoint, :symmetric_part) @eval begin function ($op)(f::Field) diff --git a/src/Fields/Fields.jl b/src/Fields/Fields.jl index 4a756b8ab..ce2116f95 100644 --- a/src/Fields/Fields.jl +++ b/src/Fields/Fields.jl @@ -76,7 +76,7 @@ import Gridap.Arrays: apply_kernel! import Gridap.Arrays: kernel_return_type import Gridap.TensorValues: outer import Gridap.TensorValues: inner -import Gridap.TensorValues: symmetic_part +import Gridap.TensorValues: symmetric_part import Base: +, - , * import LinearAlgebra: cross import LinearAlgebra: tr diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index c0a90dcf7..b32c73ae8 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -196,7 +196,7 @@ struct GenericCellField{R} <: CellField end function GenericCellField(array::AbstractArray,cell_map::AbstractArray) - GenericCellField(array,cell_map,Val{true}) + GenericCellField(array,cell_map,Val{true}()) end function get_array(cf::GenericCellField) diff --git a/src/TensorValues/Operations.jl b/src/TensorValues/Operations.jl index 485efde75..6c7a3c799 100644 --- a/src/TensorValues/Operations.jl +++ b/src/TensorValues/Operations.jl @@ -209,7 +209,7 @@ end """ """ -@generated function symmetic_part(v::TensorValue{D}) where D +@generated function symmetric_part(v::TensorValue{D}) where D str = "(" for j in 1:D for i in 1:D @@ -222,7 +222,7 @@ end # Define new operations for Gridap types -for op in (:symmetic_part,) +for op in (:symmetric_part,) @eval begin function ($op)(a::GridapType) operate($op,a) diff --git a/src/TensorValues/TensorValues.jl b/src/TensorValues/TensorValues.jl index 2cac90dc3..eec716873 100644 --- a/src/TensorValues/TensorValues.jl +++ b/src/TensorValues/TensorValues.jl @@ -41,7 +41,7 @@ export VectorValue export inner, outer, meas #export det, inv, tr, dot, norm export mutable -export symmetic_part +export symmetric_part export n_components export change_eltype export diagonal_tensor diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index b764cf13e..4b99c8649 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -18,7 +18,7 @@ b = ( a == 1 ) domain = (0,1,0,1) partition = (2,2) model = CartesianDiscreteModel(domain,partition) -order = 2 +order = 1 # order = 2 trian = get_triangulation(model) @@ -33,34 +33,48 @@ cell_map = get_cell_map(grid) # Test against the ref approach... -# T = VectorValue{2,Float64} T = Float64 - reffes = [LagrangianRefFE(T,p,order) for p in polytopes] -# Juno.@enter Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) psfs, x = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) +# T = VectorValue{2,Float64} +# reffes = [LagrangianRefFE(T,p,order) for p in polytopes] + r = evaluate(sfs,q) rg = evaluate(gradient(sfs),q) rp = evaluate(psfs,q) rgp = evaluate(gradient(psfs),q) -func(x) = x -# evaluate(func,q) -import Gridap.Fields: evaluate -evaluate(f::Function,x) = apply(f,x) +@test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) +@test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) -cell_field = convert_to_cell_field(func,cell_map) +T = VectorValue{2,Float64} +reffes = [LagrangianRefFE(T,p,order) for p in polytopes] -isa(cell_field,CellField) +psfs, x = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) +sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) + +r = evaluate(sfs,q) +rg = evaluate(gradient(sfs),q) +rp = evaluate(psfs,q) +rgp = evaluate(gradient(psfs),q) @test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) @test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) +func(x) = x +# # evaluate(func,q) +# import Gridap.Fields: evaluate +# evaluate(f::Function,x) = apply(f,x) + +cell_field = convert_to_cell_field(func,cell_map) +isa(cell_field,CellField) + # Now RT elements +T = Float64 reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] psfs, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) diff --git a/test/FieldsTests/DiffOperatorsTests.jl b/test/FieldsTests/DiffOperatorsTests.jl index 2402aacaa..76d86ae5d 100644 --- a/test/FieldsTests/DiffOperatorsTests.jl +++ b/test/FieldsTests/DiffOperatorsTests.jl @@ -34,7 +34,7 @@ for f in (_f,_af) @test outer(f,∇) == transpose(∇(f)) - @test ε(f) == symmetic_part(gradient(f)) + @test ε(f) == symmetric_part(gradient(f)) @test Δ(f) == ∇*∇(f) diff --git a/test/TensorValuesTests/OperationsTests.jl b/test/TensorValuesTests/OperationsTests.jl index d4b81578f..4ac20a2f0 100644 --- a/test/TensorValuesTests/OperationsTests.jl +++ b/test/TensorValuesTests/OperationsTests.jl @@ -251,7 +251,7 @@ t = TensorValue(1,2,3,4,5,6,7,8,9) @test tr(t) == 15 @test tr(t) == 15 -@test symmetic_part(t) == TensorValue(1.0, 3.0, 5.0, 3.0, 5.0, 7.0, 5.0, 7.0, 9.0) +@test symmetric_part(t) == TensorValue(1.0, 3.0, 5.0, 3.0, 5.0, 7.0, 5.0, 7.0, 9.0) a = TensorValue(1,2,3,4) b = a' From 5055e2a958493309fd864609a1df87a6220e95b4 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 19 Mar 2020 17:12:49 +1100 Subject: [PATCH 30/51] Fixing typos, e.g., extended fe spaces --- src/FESpaces/CellDofBases.jl | 10 ---------- src/FESpaces/ExtendedFESpaces.jl | 18 +++++++++++------- src/FESpaces/FESpaceFactories.jl | 16 ++++++++-------- src/FESpaces/SingleFieldFESpaces.jl | 13 ++++++------- test/FESpacesTests/ExtendedFESpacesTests.jl | 5 +++-- 5 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index 6ec7f1b04..a60606cbe 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -44,16 +44,6 @@ function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{false}) evaluate_dof_array(get_array(cell_dofs),get_array(_to_physical_space(cell_field)),ref_trait) end -# function evaluate_dof_array(dof_array::AbstractArray,field_array::AbstractArray,::Val{true}) -# k = DofEval() -# apply(k,dof_array,field) -# end -# -# function evaluate_dof_array(dof_array::AbstractArray,field_array::AbstractArray,::Val{false}) -# apply(dof_array,field_array) -# end - - # @santiagobadia : To create trait for CellBasis and CellField and implement these methods _to_ref_space(a) = a diff --git a/src/FESpaces/ExtendedFESpaces.jl b/src/FESpaces/ExtendedFESpaces.jl index fb4d34a02..083f5caaf 100644 --- a/src/FESpaces/ExtendedFESpaces.jl +++ b/src/FESpaces/ExtendedFESpaces.jl @@ -160,18 +160,22 @@ end function get_cell_dof_basis(f::ExtendedFESpace) cell_to_val = get_cell_dof_basis(f.space) - cell_to_val = cell_to_val.array + ref_trait = RefTrait(cell_to_val) + cell_to_val = cell_to_val.array D = num_dims(f.trian) T = Float64 # TODO void_to_val = Fill(LagrangianDofBasis(T,Point{D,T}[]),length(f.trian.void_to_oldcell)) - ExtendedVector( - void_to_val, - cell_to_val, - f.trian.oldcell_to_cell, - f.trian.void_to_oldcell, - f.trian.cell_to_oldcell) + eb = ExtendedVector( + void_to_val, + cell_to_val, + f.trian.oldcell_to_cell, + f.trian.void_to_oldcell, + f.trian.cell_to_oldcell) + + _bool(::Val{R}) where R = R + cell_dof_basis = GenericCellDofBasis(_bool(ref_trait),eb) end diff --git a/src/FESpaces/FESpaceFactories.jl b/src/FESpaces/FESpaceFactories.jl index 4360fb796..0953ac34c 100644 --- a/src/FESpaces/FESpaceFactories.jl +++ b/src/FESpaces/FESpaceFactories.jl @@ -3,8 +3,8 @@ """ function FESpace(;kwargs...) - # constraint = _get_kwarg(:constraint,kwargs,nothing) - constraint = nothing + constraint = _get_kwarg(:constraint,kwargs,nothing) + # constraint = nothing reffe = _get_kwarg(:reffe,kwargs) @notimplementedif !isa(reffe,Symbol) "For the moment, reffe can only be a symbol" @@ -42,8 +42,8 @@ function FESpace(;kwargs...) @unreachable "Unknown constraint value $constraint" end - # restricted_at = _get_kwarg(:restricted_at,kwargs,nothing) - restricted_at = nothing + restricted_at = _get_kwarg(:restricted_at,kwargs,nothing) + # restricted_at = nothing if restricted_at == nothing return _fespace else @@ -126,11 +126,11 @@ function _setup_lagrange_spaces(kwargs) order = _get_kwarg(:order,kwargs) T = _get_kwarg(:valuetype,kwargs,nothing) diritags = _get_kwarg(:dirichlet_tags,kwargs,Int[]) - # dirimasks = _get_kwarg(:dirichlet_masks,kwargs,nothing) - dirimasks = nothing + dirimasks = _get_kwarg(:dirichlet_masks,kwargs,nothing) + # dirimasks = nothing dofspace = _get_kwarg(:dof_space,kwargs,:reference) - # labels = _get_kwarg(:labels,kwargs,nothing) - labels = nothing + labels = _get_kwarg(:labels,kwargs,nothing) + # labels = nothing model = _get_kwarg(:model,kwargs,nothing) if T == nothing diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index 881a3bda9..c6ca5b4f4 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -212,22 +212,20 @@ end """ function interpolate_dirichlet(fs::SingleFieldFESpace,object) cdb = get_cell_dof_basis(fs) - _interpolate_dirichlet(fs,object,RefTrait(cdb)) + dirichlet_values = _interpolate_dirichlet(fs,object,RefTrait(cdb)) + free_values = zero_free_values(fs) + FEFunction(fs,free_values, dirichlet_values) end function _interpolate_dirichlet(fs,object,::Val{true}) cell_map = get_cell_map(fs) cell_field = convert_to_cell_field(object,cell_map) dirichlet_values = compute_dirichlet_values(fs,cell_field) - free_values = zero_free_values(fs) - FEFunction(fs,free_values, dirichlet_values) end function _interpolate_dirichlet(fs,object,::Val{false}) cell_vals = _physical_cell_vals(fs,object) dirichlet_values = gather_dirichlet_values(fs,cell_vals) - free_values = zero_free_values(fs) - FEFunction(fs,free_values, dirichlet_values) end function _physical_cell_vals(fs::SingleFieldFESpace,object) @@ -241,12 +239,13 @@ end """ function compute_dirichlet_values_for_tags(f::SingleFieldFESpace,tag_to_object) dirichlet_dof_to_tag = get_dirichlet_dof_tag(f) + cdb = get_cell_dof_basis(f) + ref_trait = RefTrait(cdb) cell_map = get_cell_map(f) dirichlet_values = zero_dirichlet_values(f) _tag_to_object = _convert_to_collectable(tag_to_object,num_dirichlet_tags(f)) for (tag, object) in enumerate(_tag_to_object) - cell_field = convert_to_cell_field(object,cell_map) - dv = compute_dirichlet_values(f,cell_field) + dv = _interpolate_dirichlet(f,object,ref_trait) _fill_dirichlet_values_for_tag!(dirichlet_values,dv,tag,dirichlet_dof_to_tag) end dirichlet_values diff --git a/test/FESpacesTests/ExtendedFESpacesTests.jl b/test/FESpacesTests/ExtendedFESpacesTests.jl index 22796a241..c0ee6c6ca 100644 --- a/test/FESpacesTests/ExtendedFESpacesTests.jl +++ b/test/FESpacesTests/ExtendedFESpacesTests.jl @@ -1,4 +1,4 @@ -module ExtendedFESpacesTests +# module ExtendedFESpacesTests using Test using Gridap.Arrays @@ -67,6 +67,7 @@ u(x) = x[1]+x[2] uh = interpolate(U,u) + uh_in = restrict(uh,trian_in) t_in = AffineFETerm( (u,v) -> v*u, (v) -> v*4, trian_in, quad_in) @@ -89,4 +90,4 @@ collect(evaluate(uh,q)) #writevtk(trian,"trian",cellfields=["uh"=>uh]) #writevtk(trian_in,"trian_in",cellfields=["uh"=>uh_in]) -end # module +# end # module From 09a9cb4d897f9d3250ceea47b2e8043356d54ff0 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 19 Mar 2020 19:07:06 +1100 Subject: [PATCH 31/51] Added tests, fixing typos --- src/ReferenceFEs/Dofs.jl | 4 ++-- test/FESpacesTests/PhysicalBasesTests.jl | 7 ++----- test/FESpacesTests/runtests.jl | 6 ++++++ test/FieldsTests/FunctionFieldsTests.jl | 11 ----------- test/ReferenceFEsTests/MockDofsTests.jl | 2 +- 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/ReferenceFEs/Dofs.jl b/src/ReferenceFEs/Dofs.jl index 76884e343..ad5b9330d 100644 --- a/src/ReferenceFEs/Dofs.jl +++ b/src/ReferenceFEs/Dofs.jl @@ -145,8 +145,8 @@ Equivalent to `evaluate_dof_array(dof,field)` """ # @santiagobadia : I have put the trait for the moment, not sure it is needed... # If we keep it, I have to change the documentation -function evaluate(dof::AbstractArray{<:Dof},field::AbstractArray) - evaluate_dof_array(dof,field) +function evaluate(dof::AbstractArray{<:Dof},field::AbstractArray,reft::Val{R}) where R + evaluate_dof_array(dof,field,reft) end struct DofEval <: Kernel end diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 4b99c8649..9200ea950 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -1,4 +1,4 @@ -# module PhysicalBasesTests +module PhysicalBasesTests using Gridap using Gridap.ReferenceFEs @@ -65,9 +65,6 @@ rgp = evaluate(gradient(psfs),q) @test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) func(x) = x -# # evaluate(func,q) -# import Gridap.Fields: evaluate -# evaluate(f::Function,x) = apply(f,x) cell_field = convert_to_cell_field(func,cell_map) isa(cell_field,CellField) @@ -88,7 +85,7 @@ rgp = evaluate(gradient(psfs),q) @test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) @test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) -# end #module +end #module # # If I want new evaluation... # function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) diff --git a/test/FESpacesTests/runtests.jl b/test/FESpacesTests/runtests.jl index a18bdf3ec..f718a0c76 100644 --- a/test/FESpacesTests/runtests.jl +++ b/test/FESpacesTests/runtests.jl @@ -52,6 +52,12 @@ using Test @testset "ExtendedFESpaces" begin include("ExtendedFESpacesTests.jl") end +@testset "ExtendedFESpaces" begin include("ExtendedFESpacesTests.jl") end + +@testset "PhysicalBasesTests" begin include("PhysicalBasesTests.jl") end + +@testset "PhysicalFESpaces" begin include("PhysicalFESpacesTests.jl") end + @testset "FESpaceFactories" begin include("FESpaceFactoriesTests.jl") end @testset "StateLaws" begin include("StateLawsTests.jl") end diff --git a/test/FieldsTests/FunctionFieldsTests.jl b/test/FieldsTests/FunctionFieldsTests.jl index a69f4a2ab..811595143 100644 --- a/test/FieldsTests/FunctionFieldsTests.jl +++ b/test/FieldsTests/FunctionFieldsTests.jl @@ -3,12 +3,6 @@ using Gridap.Inference using Gridap.Fields using Test -# In this file, I want to create a FunctionField. -# The idea is to create a function that takes points -# and returns a Field value (scalar, vector, tensor). -# Next, make this function cell-wise, and consider it -# as a CellField structure. - u(x) = x p1 = Point(1,2) @@ -17,11 +11,6 @@ p3 = Point(4,3) p4 = Point(6,1) x = [p1,p2,p3,p4] -# First, I want to do some research, in order to infer -# what type of thing it returns... Without more info, -# e.g., space-dim, etc, that is not possible. I would -# need to know the type of point, e.g. Point{D,Float64}. - f = FunctionField(u) test_field(f,x,x) diff --git a/test/ReferenceFEsTests/MockDofsTests.jl b/test/ReferenceFEsTests/MockDofsTests.jl index a9f594088..67617cd8a 100644 --- a/test/ReferenceFEsTests/MockDofsTests.jl +++ b/test/ReferenceFEsTests/MockDofsTests.jl @@ -24,7 +24,7 @@ af = fill(f,l) ax = fill(x,l) afx = evaluate(af,ax) -abf = evaluate(ab,af) +abf = evaluate(ab,af,Val{true}()) @test abf == afx end # module From a7c3a381ae249fd38510e124ae6e0c967545fee0 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 19 Mar 2020 21:45:33 +1100 Subject: [PATCH 32/51] Added tests, fixes --- test/FESpacesTests/PhysicalFESpacesTests.jl | 119 ++++++++++++++++++++ test/GeometryTests/CellFieldsTests.jl | 2 +- 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 test/FESpacesTests/PhysicalFESpacesTests.jl diff --git a/test/FESpacesTests/PhysicalFESpacesTests.jl b/test/FESpacesTests/PhysicalFESpacesTests.jl new file mode 100644 index 000000000..33f37d5b4 --- /dev/null +++ b/test/FESpacesTests/PhysicalFESpacesTests.jl @@ -0,0 +1,119 @@ +module PhysicalFESpacesTests + +using Gridap +using Gridap.ReferenceFEs +using Gridap.Geometry +using Gridap.Arrays +using Gridap.Fields +using Gridap.FESpaces +using Gridap.Polynomials +using Test + +# domain = (0,1) +# partition = (3,) +domain = (0,1,0,1) +partition = (2,2) +model = CartesianDiscreteModel(domain,partition) +order = 1 + +trian = get_triangulation(model) +quad = CellQuadrature(trian,order) + +u(x) = x[1] +T = Float64 + +u(x) = VectorValue(x[1],x[2]) +T = VectorValue{2,Float64} + +# Juno.@run TestFESpace( reffe = :Lagrangian, conformity = :H1, valuetype=T, order = order, model = model, dirichlet_tags = [1,6], dof_space = :physical) +# Juno.@enter TestFESpace( reffe = :Lagrangian, conformity = :H1, valuetype=T, order = order, model = model, dirichlet_tags = [1,6], dof_space = :physical) +# Juno.@enter TestFESpace( reffe = :Lagrangian, conformity = :H1, valuetype=T, order = order, model = model, dirichlet_tags = [1,6]) + +Vp = TestFESpace( + reffe = :Lagrangian, + conformity = :H1, + valuetype=T, + order = order, + model = model, + dirichlet_tags = [1,6], + dof_space = :physical) + +V = TestFESpace( + reffe = :Lagrangian, + conformity = :H1, + valuetype=VectorValue{2,Float64}, + order = order, + model = model, + dirichlet_tags = [1,6]) + +# Vp = TestFESpace( +# reffe = :RaviartThomas, +# conformity = :Hdiv, +# order = order, +# model = model, +# dirichlet_tags = [1,6], +# dof_space = :physical) +# +# V = TestFESpace( +# reffe = :RaviartThomas, +# conformity = :Hdiv, +# order = order, +# model = model, +# dirichlet_tags = [1,6]) +# test_single_field_fe_space(V) + +Up = TrialFESpace(Vp,u) +U = TrialFESpace(V,u) + +# FEM = Gridap.FESpaces +# Juno.@enter TrialFESpace(Vp,u) +# dirichlet_values = FEM.compute_dirichlet_values_for_tags(V,u) + +q = get_coordinates(quad) +r = evaluate(U.cell_basis,q) +rp = evaluate(Up.cell_basis,q) + +@test all(collect(r) .≈ collect(rp)) + +@test Gridap.FESpaces.RefTrait(Up.space.cell_dof_basis) == Val{false}() +@test Gridap.FESpaces.RefTrait(U.space.cell_dof_basis) == Val{true}() + +@test Gridap.FESpaces.RefTrait(Up.space.cell_basis) == Val{false}() +@test Gridap.FESpaces.RefTrait(U.space.cell_basis) == Val{true}() + +@test Gridap.FESpaces.RefTrait(Vp.cell_basis) == Val{false}() +@test Gridap.FESpaces.RefTrait(V.cell_basis) == Val{true}() + +uhf = Gridap.FESpaces.interpolate(Up,u) +uhd = Gridap.FESpaces.interpolate_dirichlet(Up,u) +uhdf = Gridap.FESpaces.interpolate_everywhere(Up,u) +uhf.dirichlet_values +uhdf.dirichlet_values +uhd.dirichlet_values + + +uhf_r = Gridap.FESpaces.interpolate(U,u) +uhd_r= Gridap.FESpaces.interpolate_dirichlet(U,u) +uhdf_r = Gridap.FESpaces.interpolate_everywhere(U,u) +uhd_r.dirichlet_values + + +@test uhf.free_values == uhf_r.free_values +@test uhf.dirichlet_values == uhf_r.dirichlet_values +@test uhd.dirichlet_values == uhd_r.dirichlet_values +@test uhdf.free_values == uhdf_r.free_values +@test uhdf.dirichlet_values == uhdf_r.dirichlet_values + +@test uhf.free_values == uhdf.free_values +@test uhf.dirichlet_values == uhd.dirichlet_values +@test uhdf.free_values == uhf.free_values +@test uhdf.dirichlet_values == uhd.dirichlet_values +@test uhdf.dirichlet_values == uhdf_r.dirichlet_values + +e = u - uhf + +el2 = sqrt(sum(integrate(inner(e,e),trian,quad))) + +@test el2 < 1.0e-10 + +end #module diff --git a/test/GeometryTests/CellFieldsTests.jl b/test/GeometryTests/CellFieldsTests.jl index 940571ed9..64b33ba86 100644 --- a/test/GeometryTests/CellFieldsTests.jl +++ b/test/GeometryTests/CellFieldsTests.jl @@ -29,7 +29,7 @@ r = [[0.0], [2.0], [0.0], [2.0]] g = Vector{VectorValue{2,Float64}}[[(1, 0)], [(1, 0)], [(1, 0)], [(1, 0)]] test_cell_field(cf1,q,r,grad=g) -isa(cf1,Gridap.Geometry.CellFieldLike) +isa(cf1,Geometry.CellFieldLike) @test RefTrait(cf1) == Val{true}() cf2 = cf1 + 4 From cbcdabdcf653aa1b6f417dc4a0d90e6a4efc689a Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 19 Mar 2020 21:55:43 +1100 Subject: [PATCH 33/51] Added poisson test in physical space --- test/GridapTests/PhysicalPoissonTests.jl | 111 +++++++++++++++++++++++ test/GridapTests/runtests.jl | 2 + 2 files changed, 113 insertions(+) create mode 100644 test/GridapTests/PhysicalPoissonTests.jl diff --git a/test/GridapTests/PhysicalPoissonTests.jl b/test/GridapTests/PhysicalPoissonTests.jl new file mode 100644 index 000000000..87dad1763 --- /dev/null +++ b/test/GridapTests/PhysicalPoissonTests.jl @@ -0,0 +1,111 @@ +module PhysicalPoissonTests + +using Test +using Gridap +import Gridap: ∇ + +domain = (0,1,0,1) +partition = (4,4) +model = CartesianDiscreteModel(domain,partition) +order = 2 + +const h = (domain[2]-domain[1]) / partition[1] +const γ = 10 + +labels = get_face_labeling(model) +add_tag_from_tags!(labels,"dirichlet",[1,2,5]) +add_tag_from_tags!(labels,"neumann",[7,8]) +add_tag_from_tags!(labels,"nitsche",6) + +trian = get_triangulation(model) +degree = order +quad = CellQuadrature(trian,degree) + +ntrian = BoundaryTriangulation(model,labels,"neumann") +ndegree = order +nquad = CellQuadrature(ntrian,ndegree) +const nn = get_normal_vector(ntrian) + +dtrian = BoundaryTriangulation(model,labels,"nitsche") +ddegree = order +dquad = CellQuadrature(dtrian,ddegree) +const dn = get_normal_vector(dtrian) + +u_scal(x) = x[1]^2 + x[2] +∇u_scal(x) = VectorValue( 2*x[1], one(x[2]) ) +Δu_scal(x) = 2 +f_scal(x) = - Δu_scal(x) +∇(::typeof(u_scal)) = ∇u_scal + +scalar_data = Dict{Symbol,Any}() +scalar_data[:valuetype] = Float64 +scalar_data[:u] = u_scal +scalar_data[:f] = f_scal + +u_vec(x) = VectorValue( x[1]^2 + x[2], 4*x[1] - x[2]^2 ) +∇u_vec(x) = TensorValue( 2*x[1], one(x[2]), 4*one(x[1]), - 2*x[2] ) +Δu_vec(x) = VectorValue( 2, -2 ) +f_vec(x) = - Δu_vec(x) +∇(::typeof(u_vec)) = ∇u_vec + +vector_data = Dict{Symbol,Any}() +vector_data[:valuetype] = VectorValue{2,Float64} +vector_data[:u] = u_vec +vector_data[:f] = f_vec + +for data in [ vector_data, scalar_data ] + + T = data[:valuetype] + u = data[:u] + f = data[:f] + + V = TestFESpace( + model=model, + order=order, + reffe=:Lagrangian, + labels=labels, + valuetype=T, + dirichlet_tags="dirichlet", + dof_space = :physical) + # dirichlet_tags="dirichlet") + # Juno.@enter TestFESpace( model=model, order=order, reffe=:Lagrangian, labels=labels, valuetype=T, dirichlet_tags="dirichlet", dof_space = :physical) + + U = TrialFESpace(V,u) + + uh = interpolate(U,u) + + a(u,v) = inner(∇(v),∇(u)) + l(v) = v*f + t_Ω = AffineFETerm(a,l,trian,quad) + + uh_Γn = restrict(uh,ntrian) + uh_Γd = restrict(uh,dtrian) + + l_Γn(v) = v*(nn*∇(uh_Γn)) + t_Γn = FESource(l_Γn,ntrian,nquad) + + a_Γd(u,v) = (γ/h)*v*u - v*(dn*∇(u)) - (dn*∇(v))*u + l_Γd(v) = (γ/h)*v*uh_Γd - (dn*∇(v))*u + t_Γd = AffineFETerm(a_Γd,l_Γd,dtrian,dquad) + + op = AffineFEOperator(U,V,t_Ω,t_Γn,t_Γd) + + uh = solve(op) + + e = u - uh + + l2(u) = inner(u,u) + sh1(u) = a(u,u) + h1(u) = sh1(u) + l2(u) + + el2 = sqrt(sum( integrate(l2(e),trian,quad) )) + eh1 = sqrt(sum( integrate(h1(e),trian,quad) )) + ul2 = sqrt(sum( integrate(l2(uh),trian,quad) )) + uh1 = sqrt(sum( integrate(h1(uh),trian,quad) )) + + @test el2/ul2 < 1.e-8 + @test eh1/uh1 < 1.e-7 + +end + +end # module diff --git a/test/GridapTests/runtests.jl b/test/GridapTests/runtests.jl index 034e3fca0..de727d223 100644 --- a/test/GridapTests/runtests.jl +++ b/test/GridapTests/runtests.jl @@ -18,4 +18,6 @@ using Test @testset "SurfaceCoupling" begin include("SurfaceCouplingTests.jl") end +@testset "PhysicalPoisson" begin include("PhysicalPoissonTests.jl") end + end # module From 19313fa5b7987afbc9e380f2f9e2ec885bafdf8e Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Thu, 19 Mar 2020 22:24:03 +1100 Subject: [PATCH 34/51] Fixing Hcurl, order in RT --- src/FESpaces/CellDofBases.jl | 2 +- src/FESpaces/CurlConformingFESpaces.jl | 3 ++- test/FESpacesTests/CurlConformingFESpacesTests.jl | 4 ++-- test/FESpacesTests/PhysicalBasesTests.jl | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index a60606cbe..d4dc0e33b 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -44,7 +44,7 @@ function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{false}) evaluate_dof_array(get_array(cell_dofs),get_array(_to_physical_space(cell_field)),ref_trait) end -# @santiagobadia : To create trait for CellBasis and CellField and implement these methods +# @santiagobadia : To be implemented _to_ref_space(a) = a _to_physical_space(a) = a diff --git a/src/FESpaces/CurlConformingFESpaces.jl b/src/FESpaces/CurlConformingFESpaces.jl index c4c68be3b..167ac0b07 100644 --- a/src/FESpaces/CurlConformingFESpaces.jl +++ b/src/FESpaces/CurlConformingFESpaces.jl @@ -11,7 +11,8 @@ function CurlConformingFESpace( reffes::Vector{<:ReferenceFE}, model::DiscreteModel, face_labeling::FaceLabeling, - dirichlet_tags) + dirichlet_tags, + is_ref) grid_topology = get_grid_topology(model) diff --git a/test/FESpacesTests/CurlConformingFESpacesTests.jl b/test/FESpacesTests/CurlConformingFESpacesTests.jl index 9b451018e..9a7891d6a 100644 --- a/test/FESpacesTests/CurlConformingFESpacesTests.jl +++ b/test/FESpacesTests/CurlConformingFESpacesTests.jl @@ -1,4 +1,4 @@ -module CurlConformingFESpacesTests +# module CurlConformingFESpacesTests ## using Test using Gridap @@ -45,4 +45,4 @@ el2 = sqrt(sum(integrate(inner(e,e),trian,quad))) ## -end # module +# end # module diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 9200ea950..f47737594 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -72,6 +72,7 @@ isa(cell_field,CellField) # Now RT elements T = Float64 +order = 0 reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] psfs, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) @@ -82,7 +83,7 @@ rg = evaluate(gradient(sfs),q) rp = evaluate(psfs,q) rgp = evaluate(gradient(psfs),q) -@test all([ r[i] ≈ rp[i] for i in 1:length(rg) ]) +@test all([ r[i] ≈ rp[i] for i in 1:length(rp) ]) @test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) end #module From 4306a8fed367f3e764a834e5b0ec98a96040eab8 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 08:21:35 +1100 Subject: [PATCH 35/51] Renamed RefTrat -> RefStyle --- src/FESpaces/CellBases.jl | 8 ++++---- src/FESpaces/CellDofBases.jl | 6 +++--- src/FESpaces/ExtendedFESpaces.jl | 2 +- src/FESpaces/FESpaces.jl | 2 +- src/FESpaces/SingleFieldFESpaces.jl | 8 ++++---- src/FESpaces/UnconstrainedFESpaces.jl | 2 +- src/Geometry/CellFields.jl | 8 ++++---- src/Geometry/Geometry.jl | 2 +- test/FESpacesTests/PhysicalFESpacesTests.jl | 12 ++++++------ test/GeometryTests/CellFieldsTests.jl | 2 +- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index f59f5a9b3..3b504c36f 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -16,7 +16,7 @@ end TrialStyle(cb) = TrialStyle(typeof(cb)) -RefTrait(::CellBasis) = @notimplemented +RefStyle(::CellBasis) = @notimplemented """ """ @@ -226,14 +226,14 @@ function TrialStyle(::Type{<:GenericCellBasis{T}}) where T Val{T}() end -function RefTrait(::Type{<:GenericCellBasis{T,R}}) where {T,R} +function RefStyle(::Type{<:GenericCellBasis{T,R}}) where {T,R} Val{R}() end -RefTrait(a::GenericCellBasis) = RefTrait(typeof(a)) +RefStyle(a::GenericCellBasis) = RefStyle(typeof(a)) function evaluate(cf::GenericCellBasis,x) - ref_trait = RefTrait(cf) + ref_trait = RefStyle(cf) _evaluate(cf,x,ref_trait) end diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index d4dc0e33b..d3098e9c8 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -15,8 +15,8 @@ struct GenericCellDofBasis{R} <: CellDofBasis end -RefTrait(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() -RefTrait(a::GenericCellDofBasis) = RefTrait(typeof(a)) +RefStyle(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() +RefStyle(a::GenericCellDofBasis) = RefStyle(typeof(a)) get_array(a::GenericCellDofBasis) = a.array @@ -33,7 +33,7 @@ The result is numerically equivalent to but it is described with a more memory-friendly lazy type. """ function evaluate(cell_dofs::CellDofBasis,cell_field) #::CellFieldLike) - _evaluate_cell_dofs(cell_dofs,cell_field,RefTrait(cell_dofs)) + _evaluate_cell_dofs(cell_dofs,cell_field,RefStyle(cell_dofs)) end function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{true}) diff --git a/src/FESpaces/ExtendedFESpaces.jl b/src/FESpaces/ExtendedFESpaces.jl index b0e892278..266f71cc5 100644 --- a/src/FESpaces/ExtendedFESpaces.jl +++ b/src/FESpaces/ExtendedFESpaces.jl @@ -186,7 +186,7 @@ end function get_cell_dof_basis(f::ExtendedFESpace) cell_to_val = get_cell_dof_basis(f.space) - ref_trait = RefTrait(cell_to_val) + ref_trait = RefStyle(cell_to_val) cell_to_val = cell_to_val.array D = num_dims(f.trian) diff --git a/src/FESpaces/FESpaces.jl b/src/FESpaces/FESpaces.jl index 8943e1523..830d13f02 100644 --- a/src/FESpaces/FESpaces.jl +++ b/src/FESpaces/FESpaces.jl @@ -44,7 +44,7 @@ import Gridap.Geometry: get_cell_map import Gridap.Geometry: get_cell_shapefuns import Gridap.Geometry: get_reffes import Gridap.Geometry: get_cell_type -import Gridap.Geometry: RefTrait +import Gridap.Geometry: RefStyle import Gridap.Helpers: operate import Gridap.Geometry: similar_object import Gridap.Geometry: jump diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index c6ca5b4f4..5f1770b1b 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -169,7 +169,7 @@ even in the case that the given cell field does not fulfill them) """ function interpolate(fs::SingleFieldFESpace,object) cdb = get_cell_dof_basis(fs) - _interpolate(fs,object,RefTrait(cdb)) + _interpolate(fs,object,RefStyle(cdb)) end function _interpolate(fs,object,::Val{true}) @@ -192,7 +192,7 @@ The resulting FEFunction does not necessary belongs to the underlying space """ function interpolate_everywhere(fs::SingleFieldFESpace,object) cdb = get_cell_dof_basis(fs) - _interpolate_everywhere(fs,object,RefTrait(cdb)) + _interpolate_everywhere(fs,object,RefStyle(cdb)) end function _interpolate_everywhere(fs,object,::Val{true}) @@ -212,7 +212,7 @@ end """ function interpolate_dirichlet(fs::SingleFieldFESpace,object) cdb = get_cell_dof_basis(fs) - dirichlet_values = _interpolate_dirichlet(fs,object,RefTrait(cdb)) + dirichlet_values = _interpolate_dirichlet(fs,object,RefStyle(cdb)) free_values = zero_free_values(fs) FEFunction(fs,free_values, dirichlet_values) end @@ -240,7 +240,7 @@ end function compute_dirichlet_values_for_tags(f::SingleFieldFESpace,tag_to_object) dirichlet_dof_to_tag = get_dirichlet_dof_tag(f) cdb = get_cell_dof_basis(f) - ref_trait = RefTrait(cdb) + ref_trait = RefStyle(cdb) cell_map = get_cell_map(f) dirichlet_values = zero_dirichlet_values(f) _tag_to_object = _convert_to_collectable(tag_to_object,num_dirichlet_tags(f)) diff --git a/src/FESpaces/UnconstrainedFESpaces.jl b/src/FESpaces/UnconstrainedFESpaces.jl index 271292a8e..049d493aa 100644 --- a/src/FESpaces/UnconstrainedFESpaces.jl +++ b/src/FESpaces/UnconstrainedFESpaces.jl @@ -26,7 +26,7 @@ struct UnconstrainedFESpace{A,B,C} <: SingleFieldFESpace dirichlet_cells::Vector{Int}, ntags) where T - cell_basis = GenericCellBasis(cell_shapefuns,cell_map,RefTrait(cell_dof_basis)) + cell_basis = GenericCellBasis(cell_shapefuns,cell_map,RefStyle(cell_dof_basis)) A = typeof(cell_dofs) B = typeof(cell_basis) diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 23bddb898..2a89c282a 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -23,8 +23,8 @@ This trait returns `Val{true}()` when the `CellFieldLike` is defined in a reference finite element space, and `Val{false}()` when it is defined in the physical space """ -# RefTrait(::Type{<:CellFieldLike}) = Val{true}() -# RefTrait(a) = RefTrait(typeof(a)) +# RefStyle(::Type{<:CellFieldLike}) = Val{true}() +# RefStyle(a) = RefStyle(typeof(a)) """ similar_object(cf::CellFieldLike,array::AbstractArray) @@ -207,11 +207,11 @@ function get_cell_map(cf::GenericCellField) cf.cell_map end -function RefTrait(::Type{<:GenericCellField{R}}) where {R} +function RefStyle(::Type{<:GenericCellField{R}}) where {R} Val{R}() end -RefTrait(a::GenericCellField) = RefTrait(typeof(a)) +RefStyle(a::GenericCellField) = RefStyle(typeof(a)) # Skeleton related diff --git a/src/Geometry/Geometry.jl b/src/Geometry/Geometry.jl index 01623a398..90ebbf34d 100644 --- a/src/Geometry/Geometry.jl +++ b/src/Geometry/Geometry.jl @@ -88,7 +88,7 @@ import Gridap.Arrays: apply_kernel! export CellField export GenericCellField export SkeletonCellField -export RefTrait +export RefStyle export similar_object export test_cell_field export convert_to_cell_field diff --git a/test/FESpacesTests/PhysicalFESpacesTests.jl b/test/FESpacesTests/PhysicalFESpacesTests.jl index 33f37d5b4..a60813282 100644 --- a/test/FESpacesTests/PhysicalFESpacesTests.jl +++ b/test/FESpacesTests/PhysicalFESpacesTests.jl @@ -75,14 +75,14 @@ rp = evaluate(Up.cell_basis,q) @test all(collect(r) .≈ collect(rp)) -@test Gridap.FESpaces.RefTrait(Up.space.cell_dof_basis) == Val{false}() -@test Gridap.FESpaces.RefTrait(U.space.cell_dof_basis) == Val{true}() +@test Gridap.FESpaces.RefStyle(Up.space.cell_dof_basis) == Val{false}() +@test Gridap.FESpaces.RefStyle(U.space.cell_dof_basis) == Val{true}() -@test Gridap.FESpaces.RefTrait(Up.space.cell_basis) == Val{false}() -@test Gridap.FESpaces.RefTrait(U.space.cell_basis) == Val{true}() +@test Gridap.FESpaces.RefStyle(Up.space.cell_basis) == Val{false}() +@test Gridap.FESpaces.RefStyle(U.space.cell_basis) == Val{true}() -@test Gridap.FESpaces.RefTrait(Vp.cell_basis) == Val{false}() -@test Gridap.FESpaces.RefTrait(V.cell_basis) == Val{true}() +@test Gridap.FESpaces.RefStyle(Vp.cell_basis) == Val{false}() +@test Gridap.FESpaces.RefStyle(V.cell_basis) == Val{true}() uhf = Gridap.FESpaces.interpolate(Up,u) uhd = Gridap.FESpaces.interpolate_dirichlet(Up,u) diff --git a/test/GeometryTests/CellFieldsTests.jl b/test/GeometryTests/CellFieldsTests.jl index 46802da23..7304a0d7a 100644 --- a/test/GeometryTests/CellFieldsTests.jl +++ b/test/GeometryTests/CellFieldsTests.jl @@ -30,7 +30,7 @@ g = Vector{VectorValue{2,Float64}}[[(1, 0)], [(1, 0)], [(1, 0)], [(1, 0)]] test_cell_field(cf1,q,r,grad=g) isa(cf1,Geometry.CellFieldLike) -@test RefTrait(cf1) == Val{true}() +@test RefStyle(cf1) == Val{true}() cf2 = cf1 + 4 r2 = map( (i) -> i.+4, r) From 5fff1f684248bb1849361beaefc75ecd7bb73053 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 08:28:07 +1100 Subject: [PATCH 36/51] Moving RefStyle to CellFieldLike --- src/FESpaces/CellBases.jl | 2 +- src/Geometry/CellFields.jl | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index 3b504c36f..6969d1488 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -16,7 +16,7 @@ end TrialStyle(cb) = TrialStyle(typeof(cb)) -RefStyle(::CellBasis) = @notimplemented +# RefStyle(::Type{<:CellBasis}) = @notimplemented """ """ diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 2a89c282a..77273d480 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -23,8 +23,8 @@ This trait returns `Val{true}()` when the `CellFieldLike` is defined in a reference finite element space, and `Val{false}()` when it is defined in the physical space """ -# RefStyle(::Type{<:CellFieldLike}) = Val{true}() -# RefStyle(a) = RefStyle(typeof(a)) +RefStyle(::Type{<:CellFieldLike}) = @notimplemented +RefStyle(::T) where T<:CellFieldLike = RefStyle(T) """ similar_object(cf::CellFieldLike,array::AbstractArray) @@ -71,6 +71,7 @@ function test_cell_field_like(cf::CellFieldLike,x::AbstractArray,b::AbstractArra g = evaluate(gradient(cf),x) test_array(g,grad,pred) end + RefStyle(cf) end """ From 86077f0a79eb40aad54fc9637ad0792fc6b4457a Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 08:31:00 +1100 Subject: [PATCH 37/51] Moving RefStyle to CellFieldLike 2 --- src/FESpaces/CellBases.jl | 2 -- src/FESpaces/CellDofBases.jl | 3 +-- src/Geometry/CellFields.jl | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index 6969d1488..5b7183c28 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -230,8 +230,6 @@ function RefStyle(::Type{<:GenericCellBasis{T,R}}) where {T,R} Val{R}() end -RefStyle(a::GenericCellBasis) = RefStyle(typeof(a)) - function evaluate(cf::GenericCellBasis,x) ref_trait = RefStyle(cf) _evaluate(cf,x,ref_trait) diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index d3098e9c8..7d5520884 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -16,7 +16,6 @@ struct GenericCellDofBasis{R} <: CellDofBasis end RefStyle(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() -RefStyle(a::GenericCellDofBasis) = RefStyle(typeof(a)) get_array(a::GenericCellDofBasis) = a.array @@ -44,7 +43,7 @@ function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{false}) evaluate_dof_array(get_array(cell_dofs),get_array(_to_physical_space(cell_field)),ref_trait) end -# @santiagobadia : To be implemented +# @santiagobadia : To be implemented _to_ref_space(a) = a _to_physical_space(a) = a diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 77273d480..271c187d4 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -212,8 +212,6 @@ function RefStyle(::Type{<:GenericCellField{R}}) where {R} Val{R}() end -RefStyle(a::GenericCellField) = RefStyle(typeof(a)) - # Skeleton related """ From 67ae319398f1faeca90812b708ed8222668596ce Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 09:15:49 +1100 Subject: [PATCH 38/51] More on the same REfStyle move --- src/FESpaces/CellDofBases.jl | 3 +++ test/FESpacesTests/PhysicalBasesTests.jl | 1 + 2 files changed, 4 insertions(+) diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index 7d5520884..76d3a8ccb 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -7,6 +7,9 @@ defined for functions in the reference or physical space """ abstract type CellDofBasis end +RefStyle(::Type{<:CellDofBasis}) = @notimplemented +RefStyle(::T) where T <: CellDofBasis = RefStyle(T) + struct GenericCellDofBasis{R} <: CellDofBasis ref_trait::Val{R} array::AbstractArray{<:Dof} diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index f47737594..5e9a4f9f3 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -7,6 +7,7 @@ using Gridap.Arrays using Gridap.Fields using Gridap.FESpaces using Gridap.Polynomials +using Gridap.Integration using Test # Start with a PhysicalSpaceCellBasis From 9acce8f0704b93e095d461576778077fdc974ca3 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 09:49:42 +1100 Subject: [PATCH 39/51] Removed inner constructor --- src/FESpaces/CellBases.jl | 1 - src/FESpaces/CellDofBases.jl | 2 +- src/FESpaces/ConformingFESpaces.jl | 4 ++-- src/Geometry/CellFields.jl | 4 ++++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index 5b7183c28..b1f57c9ef 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -241,7 +241,6 @@ function _evaluate(cf,x,::Val{true}) where R end function _evaluate(cf,x,::Val{false}) where R - # @santiagobadia : How to implement it more efficiently? cm = get_cell_map(cf) _x = evaluate(cm,x) a = get_array(cf) diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index 76d3a8ccb..b688c6990 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -14,7 +14,7 @@ struct GenericCellDofBasis{R} <: CellDofBasis ref_trait::Val{R} array::AbstractArray{<:Dof} - GenericCellDofBasis(R,array) = new{R}(Val{R}(),array) + # GenericCellDofBasis(R,array) = new{R}(Val{R}(),array) end diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index c73fe3bc2..d2a9f5e80 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -96,7 +96,7 @@ function compute_cell_space(reffes, cell_to_ctype, cell_map) dof_basis = map(get_dof_basis,reffes) cell_dof_basis = CompressedArray(dof_basis,cell_to_ctype) - cell_dof_basis = GenericCellDofBasis(true,cell_dof_basis) + cell_dof_basis = GenericCellDofBasis(Val{true}(),cell_dof_basis) shapefuns = map(get_shapefuns,reffes) refshapefuns = CompressedArray(shapefuns,cell_to_ctype) @@ -118,7 +118,7 @@ function compute_cell_space_physical(reffes, cell_to_ctype, cell_map) dof_bases = map(get_dof_basis,reffes) cell_dof_basis = _cell_dof_basis_physical_space(dof_bases,cell_to_ctype,cell_map) - cell_dof_basis = GenericCellDofBasis(false,cell_dof_basis) + cell_dof_basis = GenericCellDofBasis(Val{false}(),cell_dof_basis) prebasis = map(get_prebasis,reffes) cell_prebasis = CompressedArray(prebasis,cell_to_ctype) diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 271c187d4..0d650f6ee 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -26,6 +26,10 @@ physical space RefStyle(::Type{<:CellFieldLike}) = @notimplemented RefStyle(::T) where T<:CellFieldLike = RefStyle(T) +is_in_ref_space(::Type{T}) where T <:CellFieldLike = get_val_parameter(RefStyle(T)) +is_in_ref_space(::T) where T <:CellFieldLike = is_in_ref_space(T) +is_in_physical_space(a) = !is_in_ref_space(a) + """ similar_object(cf::CellFieldLike,array::AbstractArray) """ From 380c71676038f437810ba670debc743512363232 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 10:03:04 +1100 Subject: [PATCH 40/51] Improving CellDofBasis --- src/FESpaces/CellDofBases.jl | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index b688c6990..b9f23a6da 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -7,15 +7,28 @@ defined for functions in the reference or physical space """ abstract type CellDofBasis end -RefStyle(::Type{<:CellDofBasis}) = @notimplemented +RefStyle(::Type{<:CellDofBasis}) = @abstractmethod +get_array(::CellDofBasis) = @abstractmethod +evaluate(cell_dofs::CellDofBasis,cell_field::CellFieldLike) = @abstractmethod + RefStyle(::T) where T <: CellDofBasis = RefStyle(T) +is_in_ref_space(::Type{T}) where T <:CellDofBasis = get_val_parameter(RefStyle(T)) +is_in_ref_space(::T) where T <:CellDofBasis = is_in_ref_space(T) +# is_in_physical_space(a) = !is_in_ref_space(a) # @santiagobadia : not needed, already in CellFieldLike + +function test_cell_dof_basis(cf::CellDofBasis,f::CellFieldLike) + ar = get_array(cf) + @test isa(ar,AbstractArray) + a = evaluate(cf,f) + @test isa(RefStyle(cf),Bool) +end + +""" +""" struct GenericCellDofBasis{R} <: CellDofBasis ref_trait::Val{R} array::AbstractArray{<:Dof} - - # GenericCellDofBasis(R,array) = new{R}(Val{R}(),array) - end RefStyle(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() From 2b69c8006c191f60d82be13eb8fd71e1aa73c733 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 10:09:37 +1100 Subject: [PATCH 41/51] Added to_ref_space and to_physical_space methods for CellFieldLike --- src/Geometry/CellFields.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 0d650f6ee..5a5240a98 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -30,6 +30,19 @@ is_in_ref_space(::Type{T}) where T <:CellFieldLike = get_val_parameter(RefStyle( is_in_ref_space(::T) where T <:CellFieldLike = is_in_ref_space(T) is_in_physical_space(a) = !is_in_ref_space(a) +to_ref_space(a::CellFieldLike) = _to_ref_space(a,RefTrait(a)) +_to_ref_space(a,::Val{true}) = a +function _to_ref_space(a,::Val{false}) + cell_map = get_cell_map(a) + array = compose( get_array(a), cell_map ) + similar_object(a,array) # This creates a CellFieldLike from `array` using the metadata in `a`. +end + +to_physical_space(a::CellFieldLike) = _to_physical_space(a,RefTrait(a)) +_to_physical_space(a,::Val{true}) = @abstractmethod +_to_physical_space(a,::Val{false}) = a + + """ similar_object(cf::CellFieldLike,array::AbstractArray) """ From bcec8422600f0212111a81a363baff16b3d087c4 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 10:18:25 +1100 Subject: [PATCH 42/51] Some minor changes --- src/FESpaces/CellDofBases.jl | 2 +- src/FESpaces/ExtendedFESpaces.jl | 5 ++--- src/Geometry/Geometry.jl | 4 ++++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index b9f23a6da..f1dab709e 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -47,7 +47,7 @@ The result is numerically equivalent to but it is described with a more memory-friendly lazy type. """ -function evaluate(cell_dofs::CellDofBasis,cell_field) #::CellFieldLike) +function evaluate(cell_dofs::CellDofBasis,cell_field::CellFieldLike) _evaluate_cell_dofs(cell_dofs,cell_field,RefStyle(cell_dofs)) end diff --git a/src/FESpaces/ExtendedFESpaces.jl b/src/FESpaces/ExtendedFESpaces.jl index 266f71cc5..7dadd26c3 100644 --- a/src/FESpaces/ExtendedFESpaces.jl +++ b/src/FESpaces/ExtendedFESpaces.jl @@ -187,7 +187,7 @@ function get_cell_dof_basis(f::ExtendedFESpace) cell_to_val = get_cell_dof_basis(f.space) ref_trait = RefStyle(cell_to_val) - cell_to_val = cell_to_val.array + cell_to_val = get_array(cell_to_val) D = num_dims(f.trian) T = Float64 # TODO @@ -200,8 +200,7 @@ function get_cell_dof_basis(f::ExtendedFESpace) f.trian.void_to_oldcell, f.trian.cell_to_oldcell) - _bool(::Val{R}) where R = R - cell_dof_basis = GenericCellDofBasis(_bool(ref_trait),eb) + cell_dof_basis = GenericCellDofBasis(get_val_parameter(ref_trait),eb) end diff --git a/src/Geometry/Geometry.jl b/src/Geometry/Geometry.jl index 90ebbf34d..9d27fc1f5 100644 --- a/src/Geometry/Geometry.jl +++ b/src/Geometry/Geometry.jl @@ -92,6 +92,10 @@ export RefStyle export similar_object export test_cell_field export convert_to_cell_field +export to_ref_space +export to_physical_space +export is_in_physical_space +export is_in_ref_space export GridTopology export num_cells From 47dde1225d86311f4c3ed805efd31c481def136c Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 16:18:51 +1100 Subject: [PATCH 43/51] Moving methods to CellFieldLike, intensive cleaning up, etc --- src/FESpaces/CellBases.jl | 32 ++++++++++----------- src/FESpaces/CellDofBases.jl | 28 +++++++----------- src/FESpaces/ConformingFESpaces.jl | 8 +++++- src/FESpaces/SingleFieldFESpaces.jl | 2 +- src/FESpaces/UnconstrainedFESpaces.jl | 4 +-- src/Geometry/CellFields.jl | 20 +++++++++++-- test/FESpacesTests/PhysicalBasesTests.jl | 24 ++++++++++++++-- test/FESpacesTests/PhysicalFESpacesTests.jl | 4 +-- 8 files changed, 76 insertions(+), 46 deletions(-) diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index b1f57c9ef..cc6ff0d26 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -230,22 +230,22 @@ function RefStyle(::Type{<:GenericCellBasis{T,R}}) where {T,R} Val{R}() end -function evaluate(cf::GenericCellBasis,x) - ref_trait = RefStyle(cf) - _evaluate(cf,x,ref_trait) -end - -function _evaluate(cf,x,::Val{true}) where R - a = get_array(cf) - evaluate_field_array(a,x) -end - -function _evaluate(cf,x,::Val{false}) where R - cm = get_cell_map(cf) - _x = evaluate(cm,x) - a = get_array(cf) - evaluate_field_array(a,_x) -end +# function evaluate(cf::GenericCellBasis,x) +# ref_trait = RefStyle(cf) +# _evaluate(cf,x,ref_trait) +# end + +# function _evaluate(cf,x,::Val{true}) where R +# a = get_array(cf) +# evaluate_field_array(a,x) +# end +# +# function _evaluate(cf,x,::Val{false}) where R +# cm = get_cell_map(cf) +# _x = evaluate(cm,x) +# a = get_array(cf) +# evaluate_field_array(a,_x) +# end # CellMatrixField diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index f1dab709e..21821b618 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -9,7 +9,6 @@ abstract type CellDofBasis end RefStyle(::Type{<:CellDofBasis}) = @abstractmethod get_array(::CellDofBasis) = @abstractmethod -evaluate(cell_dofs::CellDofBasis,cell_field::CellFieldLike) = @abstractmethod RefStyle(::T) where T <: CellDofBasis = RefStyle(T) @@ -24,17 +23,6 @@ function test_cell_dof_basis(cf::CellDofBasis,f::CellFieldLike) @test isa(RefStyle(cf),Bool) end -""" -""" -struct GenericCellDofBasis{R} <: CellDofBasis - ref_trait::Val{R} - array::AbstractArray{<:Dof} -end - -RefStyle(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() - -get_array(a::GenericCellDofBasis) = a.array - """ evaluate(dof_array::CellDofBasis,field_array::AbstractArray) @@ -52,14 +40,20 @@ function evaluate(cell_dofs::CellDofBasis,cell_field::CellFieldLike) end function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{true}) - evaluate_dof_array(get_array(cell_dofs),get_array(_to_ref_space(cell_field)),ref_trait) + evaluate_dof_array(get_array(cell_dofs),get_array(to_ref_space(cell_field)),ref_trait) end function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{false}) - evaluate_dof_array(get_array(cell_dofs),get_array(_to_physical_space(cell_field)),ref_trait) + evaluate_dof_array(get_array(cell_dofs),get_array(to_physical_space(cell_field)),ref_trait) +end + +""" +""" +struct GenericCellDofBasis{R} <: CellDofBasis + ref_trait::Val{R} + array::AbstractArray{<:Dof} end -# @santiagobadia : To be implemented -_to_ref_space(a) = a +RefStyle(::Type{<:GenericCellDofBasis{R}}) where R = Val{R}() -_to_physical_space(a) = a +get_array(a::GenericCellDofBasis) = a.array diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index d2a9f5e80..428354916 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -101,6 +101,7 @@ function compute_cell_space(reffes, cell_to_ctype, cell_map) shapefuns = map(get_shapefuns,reffes) refshapefuns = CompressedArray(shapefuns,cell_to_ctype) cell_shapefuns = attachmap(refshapefuns,cell_map) + cell_shapefuns = GenericCellBasis(Val{false}(),cell_shapefuns,cell_map,Val{true}()) (cell_shapefuns, cell_dof_basis) end @@ -122,6 +123,8 @@ function compute_cell_space_physical(reffes, cell_to_ctype, cell_map) prebasis = map(get_prebasis,reffes) cell_prebasis = CompressedArray(prebasis,cell_to_ctype) + cell_prebasis = GenericCellBasis(Val{false}(),cell_prebasis,cell_map,Val{false}()) + # @santiagobadia : Think about last argument cell_shapefuns = _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) @@ -164,8 +167,11 @@ end function _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) cell_matrix = evaluate(cell_dof_basis,cell_prebasis) cell_matrix_inv = apply(inv,cell_matrix) - cell_shapefuns_phys = apply(change_basis,cell_prebasis,cell_matrix_inv) + cell_shapefuns_phys = apply(change_basis,get_array(cell_prebasis),cell_matrix_inv) cell_shapefuns = compose(cell_shapefuns_phys,cell_map) + # @santiagobadia : twice cell_map + GenericCellBasis(Val{false}(),cell_shapefuns,cell_map,Val{false}()) + # @santiagobadia : better implementation in the future... end """ diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index 5f1770b1b..3be6058e3 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -159,7 +159,7 @@ end function _compute_cell_vals(f,cell_field) cell_dof_basis = get_cell_dof_basis(f) - cell_vals = evaluate(cell_dof_basis,get_array(cell_field)) + cell_vals = evaluate(cell_dof_basis,cell_field) cell_vals end diff --git a/src/FESpaces/UnconstrainedFESpaces.jl b/src/FESpaces/UnconstrainedFESpaces.jl index 049d493aa..8cdf8b046 100644 --- a/src/FESpaces/UnconstrainedFESpaces.jl +++ b/src/FESpaces/UnconstrainedFESpaces.jl @@ -19,15 +19,13 @@ struct UnconstrainedFESpace{A,B,C} <: SingleFieldFESpace nfree::Int, ndirichlet::Int, cell_dofs::AbstractArray, - cell_shapefuns::AbstractArray, + cell_basis::CellBasis, cell_dof_basis::CellDofBasis, cell_map::AbstractArray, dirichlet_dof_tag::Vector{Int8}, dirichlet_cells::Vector{Int}, ntags) where T - cell_basis = GenericCellBasis(cell_shapefuns,cell_map,RefStyle(cell_dof_basis)) - A = typeof(cell_dofs) B = typeof(cell_basis) C = typeof(cell_dof_basis) diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 5a5240a98..f6d0aa12c 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -30,7 +30,7 @@ is_in_ref_space(::Type{T}) where T <:CellFieldLike = get_val_parameter(RefStyle( is_in_ref_space(::T) where T <:CellFieldLike = is_in_ref_space(T) is_in_physical_space(a) = !is_in_ref_space(a) -to_ref_space(a::CellFieldLike) = _to_ref_space(a,RefTrait(a)) +to_ref_space(a::CellFieldLike) = _to_ref_space(a,RefStyle(a)) _to_ref_space(a,::Val{true}) = a function _to_ref_space(a,::Val{false}) cell_map = get_cell_map(a) @@ -38,10 +38,24 @@ function _to_ref_space(a,::Val{false}) similar_object(a,array) # This creates a CellFieldLike from `array` using the metadata in `a`. end -to_physical_space(a::CellFieldLike) = _to_physical_space(a,RefTrait(a)) -_to_physical_space(a,::Val{true}) = @abstractmethod +to_physical_space(a::CellFieldLike) = _to_physical_space(a,RefStyle(a)) +_to_physical_space(a,::Val{true}) = @notimplemented _to_physical_space(a,::Val{false}) = a +function evaluate(cf::CellFieldLike,x::AbstractArray) + _evaluate(cf,x,RefStyle(cf)) +end + +function _evaluate(cf::CellFieldLike,x::AbstractArray,::Val{true}) + evaluate_field_array(get_array(cf),x) +end + +function _evaluate(cf::CellFieldLike,x::AbstractArray,::Val{false}) + cm = get_cell_map(cf) + _x = evaluate(cm,x) + evaluate_field_array(get_array(cf),x) +end + """ similar_object(cf::CellFieldLike,array::AbstractArray) diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 5e9a4f9f3..54be50566 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -1,4 +1,4 @@ -module PhysicalBasesTests +# module PhysicalBasesTests using Gridap using Gridap.ReferenceFEs @@ -37,6 +37,23 @@ cell_map = get_cell_map(grid) T = Float64 reffes = [LagrangianRefFE(T,p,order) for p in polytopes] +dof_bases = map(get_dof_basis,reffes) + +FEM = Gridap.FESpaces +cell_dof_basis = FEM._cell_dof_basis_physical_space(dof_bases,cell_to_ctype,cell_map) +cell_dof_basis = GenericCellDofBasis(Val{false}(),cell_dof_basis) + +prebasis = map(get_prebasis,reffes) +cell_prebasis = CompressedArray(prebasis,cell_to_ctype) +cell_prebasis_new = GenericCellBasis(Val{false}(),cell_prebasis,cell_map,Val{false}()) + +typeof(cell_prebasis) +isa(cell_prebasis,CellBasis) + +# cell_matrix = evaluate(cell_dof_basis,cell_prebasis) + +# cell_shapefuns = _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) + psfs, x = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) sfs, x = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) @@ -76,7 +93,8 @@ T = Float64 order = 0 reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] -psfs, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) +psfs_, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) +psfs = get_array(psfs_) sfs, dof = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) r = evaluate(sfs,q) @@ -87,7 +105,7 @@ rgp = evaluate(gradient(psfs),q) @test all([ r[i] ≈ rp[i] for i in 1:length(rp) ]) @test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) -end #module +# end #module # # If I want new evaluation... # function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) diff --git a/test/FESpacesTests/PhysicalFESpacesTests.jl b/test/FESpacesTests/PhysicalFESpacesTests.jl index a60813282..e7b2e3271 100644 --- a/test/FESpacesTests/PhysicalFESpacesTests.jl +++ b/test/FESpacesTests/PhysicalFESpacesTests.jl @@ -1,4 +1,4 @@ -module PhysicalFESpacesTests +# module PhysicalFESpacesTests using Gridap using Gridap.ReferenceFEs @@ -116,4 +116,4 @@ el2 = sqrt(sum(integrate(inner(e,e),trian,quad))) @test el2 < 1.0e-10 -end #module +# end #module From 1e677db02620f123092c24aa83ea76c01898639e Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 16:25:11 +1100 Subject: [PATCH 44/51] Cleaning up --- src/FESpaces/CellBases.jl | 43 ++++++++---------------------------- src/FESpaces/CellDofBases.jl | 1 - src/Geometry/CellFields.jl | 5 +++-- 3 files changed, 12 insertions(+), 37 deletions(-) diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index cc6ff0d26..6a6985a86 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -16,8 +16,6 @@ end TrialStyle(cb) = TrialStyle(typeof(cb)) -# RefStyle(::Type{<:CellBasis}) = @notimplemented - """ """ is_trial(cb) = is_trial(typeof(cb)) @@ -202,21 +200,21 @@ end """ """ -function GenericCellBasis(array::AbstractArray,cell_map::AbstractArray) - trial_style = Val{false}() - ref_trait = Val{true}() - GenericCellBasis(trial_style,array,cell_map,ref_trait) -end +# function GenericCellBasis(array::AbstractArray,cell_map::AbstractArray) +# trial_style = Val{false}() +# ref_trait = Val{true}() +# GenericCellBasis(trial_style,array,cell_map,ref_trait) +# end function GenericCellBasis(trial_style::Val{T},array::AbstractArray,cell_map::AbstractArray) where T ref_trait = Val{true}() GenericCellBasis(trial_style,array,cell_map,ref_trait) end -function GenericCellBasis(array::AbstractArray,cell_map::AbstractArray,ref_trait::Val{R}) where R - trial_style = Val{false}() - GenericCellBasis(trial_style,array,cell_map,ref_trait) -end +# function GenericCellBasis(array::AbstractArray,cell_map::AbstractArray,ref_trait::Val{R}) where R +# trial_style = Val{false}() +# GenericCellBasis(trial_style,array,cell_map,ref_trait) +# end get_array(a::GenericCellBasis) = a.array @@ -226,29 +224,6 @@ function TrialStyle(::Type{<:GenericCellBasis{T}}) where T Val{T}() end -function RefStyle(::Type{<:GenericCellBasis{T,R}}) where {T,R} - Val{R}() -end - -# function evaluate(cf::GenericCellBasis,x) -# ref_trait = RefStyle(cf) -# _evaluate(cf,x,ref_trait) -# end - -# function _evaluate(cf,x,::Val{true}) where R -# a = get_array(cf) -# evaluate_field_array(a,x) -# end -# -# function _evaluate(cf,x,::Val{false}) where R -# cm = get_cell_map(cf) -# _x = evaluate(cm,x) -# a = get_array(cf) -# evaluate_field_array(a,_x) -# end - -# CellMatrixField - """ """ abstract type CellMatrixField <: CellFieldLike end diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index 21821b618..e9bd6991a 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -14,7 +14,6 @@ RefStyle(::T) where T <: CellDofBasis = RefStyle(T) is_in_ref_space(::Type{T}) where T <:CellDofBasis = get_val_parameter(RefStyle(T)) is_in_ref_space(::T) where T <:CellDofBasis = is_in_ref_space(T) -# is_in_physical_space(a) = !is_in_ref_space(a) # @santiagobadia : not needed, already in CellFieldLike function test_cell_dof_basis(cf::CellDofBasis,f::CellFieldLike) ar = get_array(cf) diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index f6d0aa12c..262b4b175 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -35,13 +35,14 @@ _to_ref_space(a,::Val{true}) = a function _to_ref_space(a,::Val{false}) cell_map = get_cell_map(a) array = compose( get_array(a), cell_map ) - similar_object(a,array) # This creates a CellFieldLike from `array` using the metadata in `a`. + similar_object(a,array) end to_physical_space(a::CellFieldLike) = _to_physical_space(a,RefStyle(a)) -_to_physical_space(a,::Val{true}) = @notimplemented +_to_physical_space(a,::Val{true}) = @notimplemented # and probably not doable in some cases _to_physical_space(a,::Val{false}) = a +# Assumption : x ALWAIS defined in the reference space function evaluate(cf::CellFieldLike,x::AbstractArray) _evaluate(cf,x,RefStyle(cf)) end From 593246ec229310e5ce11d6b0822a242cf6c59fc0 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 21:24:20 +1100 Subject: [PATCH 45/51] Adding RefStyle to more CellFieldLike subtypes --- src/FESpaces/CellBases.jl | 17 +++++++++++++++++ src/FESpaces/CellDofBases.jl | 4 ++-- src/FESpaces/ExtendedFESpaces.jl | 2 +- src/FESpaces/SingleFieldFEFunctions.jl | 1 + src/Geometry/CellFields.jl | 3 ++- src/MultiField/MultiField.jl | 1 + src/MultiField/MultiFieldCellBases.jl | 5 ++--- .../CurlConformingFESpacesTests.jl | 7 +++---- test/FESpacesTests/PhysicalFESpacesTests.jl | 4 ++++ test/FESpacesTests/runtests.jl | 2 -- 10 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index 6a6985a86..2055125a2 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -41,6 +41,16 @@ end # Define how the metadata is preserved +function change_ref_style(cf::CellBasis) + ref_sty = RefStyle(cf) + new_sty = !get_value_type(ref_sty) + new_sty = Val{new_sty}() + trial_style = TrialStyle(cf) + ar = get_array(cf) + cm = get_cell_map(cf) + GenericCellBasis(trial_style,ar,cm,new_sty) +end + function similar_object(cf::CellBasis,array::AbstractArray) cm = get_cell_map(cf) trial_style = TrialStyle(cf) @@ -224,6 +234,10 @@ function TrialStyle(::Type{<:GenericCellBasis{T}}) where T Val{T}() end +function RefStyle(::Type{<:GenericCellBasis{T,R}}) where {T,R} + Val{R}() +end + """ """ abstract type CellMatrixField <: CellFieldLike end @@ -294,6 +308,9 @@ function operate(op,a,b::CellMatrixField) operate(op,_a,b) end +RefStyle(::CellMatrixField) = Val{true}() +# @santiagobadia : @fverdugo can you check what we need here??? + # Concrete CellMatrixField """ diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index e9bd6991a..5d8ff229c 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -39,11 +39,11 @@ function evaluate(cell_dofs::CellDofBasis,cell_field::CellFieldLike) end function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{true}) - evaluate_dof_array(get_array(cell_dofs),get_array(to_ref_space(cell_field)),ref_trait) + evaluate_dof_array(get_array(cell_dofs),get_array(to_ref_space(cell_field)),RefStyle(cell_dofs)) end function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{false}) - evaluate_dof_array(get_array(cell_dofs),get_array(to_physical_space(cell_field)),ref_trait) + evaluate_dof_array(get_array(cell_dofs),get_array(to_physical_space(cell_field)),RefStyle(cell_dofs)) end """ diff --git a/src/FESpaces/ExtendedFESpaces.jl b/src/FESpaces/ExtendedFESpaces.jl index 7dadd26c3..3666fca6f 100644 --- a/src/FESpaces/ExtendedFESpaces.jl +++ b/src/FESpaces/ExtendedFESpaces.jl @@ -200,7 +200,7 @@ function get_cell_dof_basis(f::ExtendedFESpace) f.trian.void_to_oldcell, f.trian.cell_to_oldcell) - cell_dof_basis = GenericCellDofBasis(get_val_parameter(ref_trait),eb) + cell_dof_basis = GenericCellDofBasis(ref_trait,eb) end diff --git a/src/FESpaces/SingleFieldFEFunctions.jl b/src/FESpaces/SingleFieldFEFunctions.jl index 51b413a77..7a969239b 100644 --- a/src/FESpaces/SingleFieldFEFunctions.jl +++ b/src/FESpaces/SingleFieldFEFunctions.jl @@ -33,3 +33,4 @@ get_cell_map(f::SingleFieldFEFunction) = get_cell_map(f.fe_space) get_cell_values(f::SingleFieldFEFunction) = f.cell_vals +RefStyle(f::SingleFieldFEFunction) = RefStyle(get_cell_dof_basis(f.fe_space)) diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 262b4b175..7f1e9e9a5 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -35,7 +35,8 @@ _to_ref_space(a,::Val{true}) = a function _to_ref_space(a,::Val{false}) cell_map = get_cell_map(a) array = compose( get_array(a), cell_map ) - similar_object(a,array) + no = similar_object(a,array) + change_ref_style(no) end to_physical_space(a::CellFieldLike) = _to_physical_space(a,RefStyle(a)) diff --git a/src/MultiField/MultiField.jl b/src/MultiField/MultiField.jl index 8eada98ef..7d9d844bb 100644 --- a/src/MultiField/MultiField.jl +++ b/src/MultiField/MultiField.jl @@ -41,6 +41,7 @@ import Gridap.Geometry: restrict import Gridap.Fields: integrate import Gridap.Fields: evaluate import Gridap.FESpaces: TrialStyle +import Gridap.FESpaces: RefStyle import Gridap.FESpaces: FECellBasisStyle import Gridap.FESpaces: FEFunctionStyle import Gridap.FESpaces: num_free_dofs diff --git a/src/MultiField/MultiFieldCellBases.jl b/src/MultiField/MultiFieldCellBases.jl index e8dcac096..eb37a7c2e 100644 --- a/src/MultiField/MultiFieldCellBases.jl +++ b/src/MultiField/MultiFieldCellBases.jl @@ -16,6 +16,8 @@ get_cell_map(cb::CellBasisWithFieldID) = get_cell_map(cb.cell_basis) TrialStyle(::Type{CellBasisWithFieldID{S}}) where S = Val{S}() +RefStyle(cb::CellBasisWithFieldID) = RefStyle(cb.cell_basis) + function similar_object(cb::CellBasisWithFieldID,array::AbstractArray) cell_basis = similar_object(cb.cell_basis,array) field_id = cb.field_id @@ -224,6 +226,3 @@ end end vec end - - - diff --git a/test/FESpacesTests/CurlConformingFESpacesTests.jl b/test/FESpacesTests/CurlConformingFESpacesTests.jl index 9a7891d6a..9a976f248 100644 --- a/test/FESpacesTests/CurlConformingFESpacesTests.jl +++ b/test/FESpacesTests/CurlConformingFESpacesTests.jl @@ -1,5 +1,5 @@ -# module CurlConformingFESpacesTests -## +module CurlConformingFESpacesTests + using Test using Gridap using LinearAlgebra @@ -43,6 +43,5 @@ el2 = sqrt(sum(integrate(inner(e,e),trian,quad))) # writevtk(trian,"trian",nsubcells=10,cellfields=["uh"=>uh]) -## -# end # module +end # module diff --git a/test/FESpacesTests/PhysicalFESpacesTests.jl b/test/FESpacesTests/PhysicalFESpacesTests.jl index e7b2e3271..c90378f80 100644 --- a/test/FESpacesTests/PhysicalFESpacesTests.jl +++ b/test/FESpacesTests/PhysicalFESpacesTests.jl @@ -46,6 +46,8 @@ V = TestFESpace( model = model, dirichlet_tags = [1,6]) + V.cell_basis.ref_trait + # Vp = TestFESpace( # reffe = :RaviartThomas, # conformity = :Hdiv, @@ -64,6 +66,8 @@ V = TestFESpace( Up = TrialFESpace(Vp,u) U = TrialFESpace(V,u) +U.cell_basis.ref_trait +U.space.cell_basis.ref_trait # FEM = Gridap.FESpaces # Juno.@enter TrialFESpace(Vp,u) diff --git a/test/FESpacesTests/runtests.jl b/test/FESpacesTests/runtests.jl index 9229bd087..9687dc0e2 100644 --- a/test/FESpacesTests/runtests.jl +++ b/test/FESpacesTests/runtests.jl @@ -52,8 +52,6 @@ using Test @testset "ExtendedFESpaces" begin include("ExtendedFESpacesTests.jl") end -@testset "ExtendedFESpaces" begin include("ExtendedFESpacesTests.jl") end - @testset "PhysicalBasesTests" begin include("PhysicalBasesTests.jl") end @testset "PhysicalFESpaces" begin include("PhysicalFESpacesTests.jl") end From 11f55986c81376870b4a801395b2daa9a58aa601 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 21:31:42 +1100 Subject: [PATCH 46/51] Eliminating trait from evaluate_dof_array --- src/ReferenceFEs/Dofs.jl | 15 +++++++++------ test/ReferenceFEsTests/MockDofsTests.jl | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ReferenceFEs/Dofs.jl b/src/ReferenceFEs/Dofs.jl index ad5b9330d..48f5c0e46 100644 --- a/src/ReferenceFEs/Dofs.jl +++ b/src/ReferenceFEs/Dofs.jl @@ -129,14 +129,14 @@ The result is numerically equivalent to but it is described with a more memory-friendly lazy type. """ -function evaluate_dof_array(dof::AbstractArray,field::AbstractArray,::Val{true}) +function evaluate_dof_array(dof::AbstractArray,field::AbstractArray) k = DofEval() apply(k,dof,field) end -function evaluate_dof_array(dof::AbstractArray{<:Dof},field::AbstractArray,::Val{false}) - apply(dof,field) -end +# function evaluate_dof_array(dof::AbstractArray{<:Dof},field::AbstractArray) +# apply(dof,field) +# end """ evaluate(dof::AbstractArray{<:Dof},field::AbstractArray) @@ -145,9 +145,12 @@ Equivalent to `evaluate_dof_array(dof,field)` """ # @santiagobadia : I have put the trait for the moment, not sure it is needed... # If we keep it, I have to change the documentation -function evaluate(dof::AbstractArray{<:Dof},field::AbstractArray,reft::Val{R}) where R - evaluate_dof_array(dof,field,reft) +function evaluate(dof::AbstractArray{<:Dof},field::AbstractArray) + evaluate_dof_array(dof,field) end +# function evaluate(dof::AbstractArray{<:Dof},field::AbstractArray,reft::Val{R}) where R +# evaluate_dof_array(dof,field,reft) +# end struct DofEval <: Kernel end diff --git a/test/ReferenceFEsTests/MockDofsTests.jl b/test/ReferenceFEsTests/MockDofsTests.jl index 67617cd8a..a9f594088 100644 --- a/test/ReferenceFEsTests/MockDofsTests.jl +++ b/test/ReferenceFEsTests/MockDofsTests.jl @@ -24,7 +24,7 @@ af = fill(f,l) ax = fill(x,l) afx = evaluate(af,ax) -abf = evaluate(ab,af,Val{true}()) +abf = evaluate(ab,af) @test abf == afx end # module From 08fb421bd770668a5e227ef6247252a0ce31795f Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Fri, 20 Mar 2020 23:15:01 +1100 Subject: [PATCH 47/51] No RefStyle in Interpolate --- src/FESpaces/CellBases.jl | 11 --- src/FESpaces/CellDofBases.jl | 4 +- src/FESpaces/SingleFieldFESpaces.jl | 120 ++++++++--------------- src/Geometry/CellFields.jl | 15 +++ src/Geometry/Geometry.jl | 1 + src/ReferenceFEs/Dofs.jl | 5 - test/FESpacesTests/PhysicalBasesTests.jl | 4 +- 7 files changed, 62 insertions(+), 98 deletions(-) diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index 2055125a2..6aac9268c 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -210,22 +210,11 @@ end """ """ -# function GenericCellBasis(array::AbstractArray,cell_map::AbstractArray) -# trial_style = Val{false}() -# ref_trait = Val{true}() -# GenericCellBasis(trial_style,array,cell_map,ref_trait) -# end - function GenericCellBasis(trial_style::Val{T},array::AbstractArray,cell_map::AbstractArray) where T ref_trait = Val{true}() GenericCellBasis(trial_style,array,cell_map,ref_trait) end -# function GenericCellBasis(array::AbstractArray,cell_map::AbstractArray,ref_trait::Val{R}) where R -# trial_style = Val{false}() -# GenericCellBasis(trial_style,array,cell_map,ref_trait) -# end - get_array(a::GenericCellBasis) = a.array get_cell_map(a::GenericCellBasis) = a.cell_map diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index 5d8ff229c..590431da8 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -39,11 +39,11 @@ function evaluate(cell_dofs::CellDofBasis,cell_field::CellFieldLike) end function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{true}) - evaluate_dof_array(get_array(cell_dofs),get_array(to_ref_space(cell_field)),RefStyle(cell_dofs)) + evaluate_dof_array(get_array(cell_dofs),get_array(to_ref_space(cell_field))) end function _evaluate_cell_dofs(cell_dofs,cell_field,ref_trait::Val{false}) - evaluate_dof_array(get_array(cell_dofs),get_array(to_physical_space(cell_field)),RefStyle(cell_dofs)) + evaluate_dof_array(get_array(cell_dofs),get_array(to_physical_space(cell_field))) end """ diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index 3be6058e3..b05109608 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -134,56 +134,50 @@ function gather_free_values(f::SingleFieldFESpace,cell_vals) free_values, _ = gather_free_and_dirichlet_values(f,cell_vals) free_values end - -""" -cell_field defined in the reference space with derivatives in the physical one -""" -function compute_free_and_dirichlet_values(f::SingleFieldFESpace, cell_field::CellField) - cell_vals = _compute_cell_vals(f, cell_field) - gather_free_and_dirichlet_values(f,cell_vals) -end - -""" -""" -function compute_dirichlet_values(f::SingleFieldFESpace,cell_field::CellField) - cell_vals = _compute_cell_vals(f, cell_field) - gather_dirichlet_values(f,cell_vals) -end - -""" -""" -function compute_free_values(f::SingleFieldFESpace,cell_field::CellField) - cell_vals = _compute_cell_vals(f, cell_field) - gather_free_values(f,cell_vals) -end - -function _compute_cell_vals(f,cell_field) - cell_dof_basis = get_cell_dof_basis(f) - cell_vals = evaluate(cell_dof_basis,cell_field) - cell_vals -end +# +# """ +# cell_field defined in the reference space with derivatives in the physical one +# """ +# function compute_free_and_dirichlet_values(f::SingleFieldFESpace, cell_field::CellField) +# cell_vals = _compute_cell_vals(f, cell_field) +# gather_free_and_dirichlet_values(f,cell_vals) +# end +# +# """ +# """ +# function compute_dirichlet_values(f::SingleFieldFESpace,cell_field::CellField) +# cell_vals = _compute_cell_vals(f, cell_field) +# gather_dirichlet_values(f,cell_vals) +# end +# +# """ +# """ +# function compute_free_values(f::SingleFieldFESpace,cell_field::CellField) +# cell_vals = _compute_cell_vals(f, cell_field) +# gather_free_values(f,cell_vals) +# end +# +# function _compute_cell_vals(f,cell_field) +# cell_dof_basis = get_cell_dof_basis(f) +# cell_vals = evaluate(cell_dof_basis,cell_field) +# cell_vals +# end """ The resulting FE function is in the space (in particular it fulfills Dirichlet BCs even in the case that the given cell field does not fulfill them) """ function interpolate(fs::SingleFieldFESpace,object) - cdb = get_cell_dof_basis(fs) - _interpolate(fs,object,RefStyle(cdb)) -end - -function _interpolate(fs,object,::Val{true}) - cell_dofs = get_cell_dofs - cell_map = get_cell_map(fs) - cell_field = convert_to_cell_field(object,cell_map) - free_values = compute_free_values(fs,cell_field) + cell_vals = _cell_vals(fs,object) + free_values = gather_free_values(fs,cell_vals) FEFunction(fs,free_values) end -function _interpolate(fs,object,::Val{false}) - cell_vals = _physical_cell_vals(fs,object) - free_values = gather_free_values(fs,cell_vals) - FEFunction(fs,free_values) +function _cell_vals(fs::SingleFieldFESpace,object) + cdb = get_cell_dof_basis(fs) + cm = get_cell_map(fs) + cf = cell_field_from_function(object,cm,RefStyle(cdb)) + cell_vals = evaluate(cdb,cf) end """ @@ -191,61 +185,31 @@ like interpolate, but also compute new degrees of freedom for the dirichlet comp The resulting FEFunction does not necessary belongs to the underlying space """ function interpolate_everywhere(fs::SingleFieldFESpace,object) - cdb = get_cell_dof_basis(fs) - _interpolate_everywhere(fs,object,RefStyle(cdb)) -end - -function _interpolate_everywhere(fs,object,::Val{true}) - cell_map = get_cell_map(fs) - cell_field = convert_to_cell_field(object,cell_map) - free_values, dirichlet_values = compute_free_and_dirichlet_values(fs,cell_field) - FEFunction(fs,free_values, dirichlet_values) -end - -function _interpolate_everywhere(fs,object,::Val{false}) - cell_vals = _physical_cell_vals(fs,object) - fv, dv = gather_free_and_dirichlet_values(fs,cell_vals) - FEFunction(fs,fv,dv) + cell_vals = _cell_vals(fs,object) + free_values, dirichlet_values = gather_free_and_dirichlet_values(fs,cell_vals) + FEFunction(fs,free_values,dirichlet_values) end """ """ function interpolate_dirichlet(fs::SingleFieldFESpace,object) - cdb = get_cell_dof_basis(fs) - dirichlet_values = _interpolate_dirichlet(fs,object,RefStyle(cdb)) + cell_vals = _cell_vals(fs,object) + dirichlet_values = gather_dirichlet_values(fs,cell_vals) free_values = zero_free_values(fs) FEFunction(fs,free_values, dirichlet_values) end -function _interpolate_dirichlet(fs,object,::Val{true}) - cell_map = get_cell_map(fs) - cell_field = convert_to_cell_field(object,cell_map) - dirichlet_values = compute_dirichlet_values(fs,cell_field) -end - -function _interpolate_dirichlet(fs,object,::Val{false}) - cell_vals = _physical_cell_vals(fs,object) - dirichlet_values = gather_dirichlet_values(fs,cell_vals) -end - -function _physical_cell_vals(fs::SingleFieldFESpace,object) - field = function_field(object) - cell_dof_basis = get_cell_dof_basis(fs) - cell_field = Fill(field,length(get_cell_map(fs))) - cell_vals = apply(cell_dof_basis.array,cell_field) -end - """ """ function compute_dirichlet_values_for_tags(f::SingleFieldFESpace,tag_to_object) dirichlet_dof_to_tag = get_dirichlet_dof_tag(f) cdb = get_cell_dof_basis(f) - ref_trait = RefStyle(cdb) cell_map = get_cell_map(f) dirichlet_values = zero_dirichlet_values(f) _tag_to_object = _convert_to_collectable(tag_to_object,num_dirichlet_tags(f)) for (tag, object) in enumerate(_tag_to_object) - dv = _interpolate_dirichlet(f,object,ref_trait) + cell_vals = _cell_vals(f,object) + dv = gather_dirichlet_values(f,cell_vals) _fill_dirichlet_values_for_tag!(dirichlet_values,dv,tag,dirichlet_dof_to_tag) end dirichlet_values diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 7f1e9e9a5..5e1d627c7 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -233,6 +233,10 @@ function GenericCellField(array::AbstractArray,cell_map::AbstractArray) GenericCellField(array,cell_map,Val{true}()) end +# function GenericCellField(array::AbstractArray,cell_map::AbstractArray,ref_style) +# GenericCellField(array,cell_map,ref_style) +# end + function get_array(cf::GenericCellField) cf.array end @@ -245,6 +249,17 @@ function RefStyle(::Type{<:GenericCellField{R}}) where {R} Val{R}() end +function cell_field_from_function(fun,cell_map,::Val{true}) + # GenericCellField(cell_field,cell_map,Val{true}()) + cell_field = convert_to_cell_field(fun,cell_map) +end + +function cell_field_from_function(fun,cell_map,::Val{false}) + field = function_field(fun) + cell_field = Fill(field,length(cell_map)) + GenericCellField(cell_field,cell_map,Val{false}()) +end + # Skeleton related """ diff --git a/src/Geometry/Geometry.jl b/src/Geometry/Geometry.jl index 9d27fc1f5..7d20d75b5 100644 --- a/src/Geometry/Geometry.jl +++ b/src/Geometry/Geometry.jl @@ -96,6 +96,7 @@ export to_ref_space export to_physical_space export is_in_physical_space export is_in_ref_space +export cell_field_from_function export GridTopology export num_cells diff --git a/src/ReferenceFEs/Dofs.jl b/src/ReferenceFEs/Dofs.jl index 48f5c0e46..8ba80b843 100644 --- a/src/ReferenceFEs/Dofs.jl +++ b/src/ReferenceFEs/Dofs.jl @@ -143,14 +143,9 @@ end Equivalent to `evaluate_dof_array(dof,field)` """ -# @santiagobadia : I have put the trait for the moment, not sure it is needed... -# If we keep it, I have to change the documentation function evaluate(dof::AbstractArray{<:Dof},field::AbstractArray) evaluate_dof_array(dof,field) end -# function evaluate(dof::AbstractArray{<:Dof},field::AbstractArray,reft::Val{R}) where R -# evaluate_dof_array(dof,field,reft) -# end struct DofEval <: Kernel end diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 54be50566..4224a5e12 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -1,4 +1,4 @@ -# module PhysicalBasesTests +module PhysicalBasesTests using Gridap using Gridap.ReferenceFEs @@ -105,7 +105,7 @@ rgp = evaluate(gradient(psfs),q) @test all([ r[i] ≈ rp[i] for i in 1:length(rp) ]) @test all([ rg[i] ≈ rgp[i] for i in 1:length(rg) ]) -# end #module +end #module # # If I want new evaluation... # function kernel_evaluate(k::typeof{change_basis},x,cell_prebasis,cell_matrix_inv) From 5e2885d527573f91e7e50224c56646d862bd5040 Mon Sep 17 00:00:00 2001 From: Francesc Verdugo Date: Fri, 20 Mar 2020 15:10:18 +0100 Subject: [PATCH 48/51] Reactivating some docs --- docs/src/ReferenceFEs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/ReferenceFEs.md b/docs/src/ReferenceFEs.md index 46afc51b1..33a85105f 100644 --- a/docs/src/ReferenceFEs.md +++ b/docs/src/ReferenceFEs.md @@ -83,7 +83,7 @@ evaluate_dof(dof,field) evaluate(dof::Dof,field) ``` - +``` ## Reference Finite Elements From 685a4fb50e4c4e58e20a56ed860dfbfae317a96b Mon Sep 17 00:00:00 2001 From: Francesc Verdugo Date: Fri, 20 Mar 2020 18:33:05 +0100 Subject: [PATCH 49/51] Misc changes to make phys ref spaces work (single field) --- src/FESpaces/CellBases.jl | 52 +++++---- src/FESpaces/CellDofBases.jl | 9 +- src/FESpaces/ConformingFESpaces.jl | 13 ++- src/FESpaces/ExtendedFESpaces.jl | 2 +- src/FESpaces/FESpaces.jl | 2 + src/FESpaces/SingleFieldFEFunctions.jl | 10 +- src/FESpaces/SingleFieldFESpaces.jl | 30 +----- src/FESpaces/TrialFESpaces.jl | 2 +- src/Fields/FunctionFields.jl | 6 +- src/Geometry/CellFields.jl | 114 ++++++++++++-------- src/Geometry/CellQuadratures.jl | 3 +- src/Geometry/Geometry.jl | 1 + src/Geometry/Triangulations.jl | 3 +- src/ReferenceFEs/Dofs.jl | 6 +- src/Visualization/Vtk.jl | 4 +- test/FESpacesTests/CellBasesTests.jl | 4 +- test/FESpacesTests/CellDofBasesTests.jl | 52 +++++++++ test/FESpacesTests/PhysicalBasesTests.jl | 3 +- test/FESpacesTests/PhysicalFESpacesTests.jl | 11 +- test/FESpacesTests/runtests.jl | 2 + 20 files changed, 201 insertions(+), 128 deletions(-) create mode 100644 test/FESpacesTests/CellDofBasesTests.jl diff --git a/src/FESpaces/CellBases.jl b/src/FESpaces/CellBases.jl index 6aac9268c..7bdf2937f 100644 --- a/src/FESpaces/CellBases.jl +++ b/src/FESpaces/CellBases.jl @@ -43,8 +43,8 @@ end function change_ref_style(cf::CellBasis) ref_sty = RefStyle(cf) - new_sty = !get_value_type(ref_sty) - new_sty = Val{new_sty}() + bool = !get_val_parameter(ref_sty) + new_sty = Val{bool}() trial_style = TrialStyle(cf) ar = get_array(cf) cm = get_cell_map(cf) @@ -54,7 +54,7 @@ end function similar_object(cf::CellBasis,array::AbstractArray) cm = get_cell_map(cf) trial_style = TrialStyle(cf) - GenericCellBasis(trial_style,array,cm) + GenericCellBasis(trial_style,array,cm,RefStyle(cf)) end function similar_object(a::CellBasis,b::CellField,v::AbstractArray) @@ -83,7 +83,8 @@ end function _similar_cell_basis_test_trial(v,a,b) cm = get_cell_map(a) - GenericCellMatrixField(v,cm) + @assert is_in_ref_space(a) == is_in_ref_space(b) + GenericCellMatrixField(v,cm,RefStyle(a)) end # Operations @@ -124,13 +125,13 @@ end function operate(op,cf1::CellBasis,object) cm = get_cell_map(cf1) - cf2 = convert_to_cell_field(object,cm) + cf2 = convert_to_cell_field(object,cm,RefStyle(cf1)) operate(op,cf1,cf2) end function operate(op,object,cf2::CellBasis) cm = get_cell_map(cf2) - cf1 = convert_to_cell_field(object,cm) + cf1 = convert_to_cell_field(object,cm,RefStyle(cf2)) operate(op,cf1,cf2) end @@ -208,8 +209,6 @@ struct GenericCellBasis{T,R} <: CellBasis ref_trait::Val{R} end -""" -""" function GenericCellBasis(trial_style::Val{T},array::AbstractArray,cell_map::AbstractArray) where T ref_trait = Val{true}() GenericCellBasis(trial_style,array,cell_map,ref_trait) @@ -239,9 +238,18 @@ end # Define how the metadata is preserved +function change_ref_style(cf::CellMatrixField) + ref_sty = RefStyle(cf) + bool = !get_val_parameter(ref_sty) + new_sty = Val{bool}() + ar = get_array(cf) + cm = get_cell_map(cf) + GenericCellMatrixField(ar,cm,new_sty) +end + function similar_object(cf::CellMatrixField,a::AbstractArray) cm = get_cell_map(cf) - GenericCellMatrixField(a,cm) + GenericCellMatrixField(a,cm,RefStyle(cf)) end function similar_object(a::CellMatrixField,b::CellField,v::AbstractArray) @@ -287,28 +295,29 @@ end function operate(op,a::CellMatrixField,b) cm = get_cell_map(a) - _b = convert_to_cell_field(b,cm) + _b = convert_to_cell_field(b,cm,RefStyle(a)) operate(op,a,_b) end function operate(op,a,b::CellMatrixField) cm = get_cell_map(b) - _a = convert_to_cell_field(a,cm) + _a = convert_to_cell_field(a,cm,RefStyle(b)) operate(op,_a,b) end -RefStyle(::CellMatrixField) = Val{true}() -# @santiagobadia : @fverdugo can you check what we need here??? # Concrete CellMatrixField """ """ -struct GenericCellMatrixField{A,B} <: CellMatrixField +struct GenericCellMatrixField{A,B,R} <: CellMatrixField array::A cell_map::B + ref_style::Val{R} end +RefStyle(::Type{GenericCellMatrixField{A,B,R}}) where {A,B,R} = Val{R}() + get_array(a::GenericCellMatrixField) = a.array get_cell_map(a::GenericCellMatrixField) = a.cell_map @@ -316,7 +325,8 @@ get_cell_map(a::GenericCellMatrixField) = a.cell_map # Restrictions function restrict(cf::CellBasis,trian::Triangulation) - a = get_array(cf) + _cf = to_ref_space(cf) + a = get_array(_cf) r = restrict(a,trian) trial_style = TrialStyle(cf) _restrict_cell_basis(trial_style,r,trian) @@ -414,13 +424,13 @@ end function operate(op,cf1::SkeletonCellBasis,object) cm = get_cell_map(cf1) - cf2 = convert_to_cell_field(object,cm) + cf2 = convert_to_cell_field(object,cm,RefStyle(cf1.left)) operate(op,cf1,cf2) end function operate(op,object,cf2::SkeletonCellBasis) cm = get_cell_map(cf2) - cf1 = convert_to_cell_field(object,cm) + cf1 = convert_to_cell_field(object,cm,RefStyle(cf2.left)) operate(op,cf1,cf2) end @@ -466,13 +476,13 @@ end function operate(op,cf1::ReducedSkeletonCellBasis,object) cm = get_cell_map(cf1) - cf2 = convert_to_cell_field(object,cm) + cf2 = convert_to_cell_field(object,cm,RefStyle(cf1.left)) operate(op,cf1,cf2) end function operate(op,object,cf2::ReducedSkeletonCellBasis) cm = get_cell_map(cf2) - cf1 = convert_to_cell_field(object,cm) + cf1 = convert_to_cell_field(object,cm,RefStyle(cf2.left)) operate(op,cf1,cf2) end @@ -549,13 +559,13 @@ end function operate(op,object,cf2::SkeletonCellMatrixField) cm = get_cell_map(cf2) - cf1 = convert_to_cell_field(object,cm) + cf1 = convert_to_cell_field(object,cm,RefStyle(cf2.ll)) operate(op,cf1,cf2) end function operate(op,cf1::SkeletonCellMatrixField,object) cm = get_cell_map(cf1) - cf2 = convert_to_cell_field(object,cm) + cf2 = convert_to_cell_field(object,cm,RefStyle(cf1.ll)) operate(op,cf1,cf2) end diff --git a/src/FESpaces/CellDofBases.jl b/src/FESpaces/CellDofBases.jl index 590431da8..9a4118f98 100644 --- a/src/FESpaces/CellDofBases.jl +++ b/src/FESpaces/CellDofBases.jl @@ -10,16 +10,13 @@ abstract type CellDofBasis end RefStyle(::Type{<:CellDofBasis}) = @abstractmethod get_array(::CellDofBasis) = @abstractmethod -RefStyle(::T) where T <: CellDofBasis = RefStyle(T) - -is_in_ref_space(::Type{T}) where T <:CellDofBasis = get_val_parameter(RefStyle(T)) -is_in_ref_space(::T) where T <:CellDofBasis = is_in_ref_space(T) - function test_cell_dof_basis(cf::CellDofBasis,f::CellFieldLike) ar = get_array(cf) @test isa(ar,AbstractArray) a = evaluate(cf,f) - @test isa(RefStyle(cf),Bool) + _ = collect(a) + rs = RefStyle(cf) + @test isa(get_val_parameter(rs),Bool) end """ diff --git a/src/FESpaces/ConformingFESpaces.jl b/src/FESpaces/ConformingFESpaces.jl index 428354916..3b2434cdd 100644 --- a/src/FESpaces/ConformingFESpaces.jl +++ b/src/FESpaces/ConformingFESpaces.jl @@ -111,21 +111,20 @@ It creates the cell-wise DOF basis and shape functions, when the DOFs are evaluated at the physical space. The DOFs (moments) for the prebasis are assumed to be computable at a reference FE space. """ +function compute_cell_space_physical(reffes, cell_to_ctype, cell_map) # E.g., if one has to implement $\int_F q ϕ_h(x)$ for $q \in P(F)$, we can # assume that it can be written as $\sum_{x_{gp} \in Q}_{\hat{F}} # \hat{q}(\tilde{x}_{gp}) ϕ(x_{gp})$ for $\hat{q} \in P(\hat{F})$. -function compute_cell_space_physical(reffes, cell_to_ctype, cell_map) dof_bases = map(get_dof_basis,reffes) cell_dof_basis = _cell_dof_basis_physical_space(dof_bases,cell_to_ctype,cell_map) - cell_dof_basis = GenericCellDofBasis(Val{false}(),cell_dof_basis) + ref_style = Val{false}() + cell_dof_basis = GenericCellDofBasis(ref_style,cell_dof_basis) prebasis = map(get_prebasis,reffes) cell_prebasis = CompressedArray(prebasis,cell_to_ctype) cell_prebasis = GenericCellBasis(Val{false}(),cell_prebasis,cell_map,Val{false}()) - # @santiagobadia : Think about last argument - cell_shapefuns = _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_map) (cell_shapefuns, cell_dof_basis) @@ -168,9 +167,9 @@ function _cell_shape_functions_physical_space(cell_prebasis,cell_dof_basis,cell_ cell_matrix = evaluate(cell_dof_basis,cell_prebasis) cell_matrix_inv = apply(inv,cell_matrix) cell_shapefuns_phys = apply(change_basis,get_array(cell_prebasis),cell_matrix_inv) - cell_shapefuns = compose(cell_shapefuns_phys,cell_map) - # @santiagobadia : twice cell_map - GenericCellBasis(Val{false}(),cell_shapefuns,cell_map,Val{false}()) + ref_style = Val{false}() + trial_style = Val{false}() + GenericCellBasis(trial_style,cell_shapefuns_phys,cell_map,ref_style) # @santiagobadia : better implementation in the future... end diff --git a/src/FESpaces/ExtendedFESpaces.jl b/src/FESpaces/ExtendedFESpaces.jl index 3666fca6f..29b6583a4 100644 --- a/src/FESpaces/ExtendedFESpaces.jl +++ b/src/FESpaces/ExtendedFESpaces.jl @@ -180,7 +180,7 @@ function get_cell_basis(f::ExtendedFESpace) cm = get_cell_map(f.trian.oldtrian) trial_style = TrialStyle(cell_basis) - GenericCellBasis(trial_style,array,cm) + GenericCellBasis(trial_style,array,cm,RefStyle(cell_basis)) end function get_cell_dof_basis(f::ExtendedFESpace) diff --git a/src/FESpaces/FESpaces.jl b/src/FESpaces/FESpaces.jl index 830d13f02..1579bc414 100644 --- a/src/FESpaces/FESpaces.jl +++ b/src/FESpaces/FESpaces.jl @@ -45,6 +45,7 @@ import Gridap.Geometry: get_cell_shapefuns import Gridap.Geometry: get_reffes import Gridap.Geometry: get_cell_type import Gridap.Geometry: RefStyle +import Gridap.Geometry: change_ref_style import Gridap.Helpers: operate import Gridap.Geometry: similar_object import Gridap.Geometry: jump @@ -152,6 +153,7 @@ export attach_dirichlet_bcs export CellDofBasis export GenericCellDofBasis +export test_cell_dof_basis export FECellBasisStyle export is_a_fe_cell_basis diff --git a/src/FESpaces/SingleFieldFEFunctions.jl b/src/FESpaces/SingleFieldFEFunctions.jl index 7a969239b..669e5ee1f 100644 --- a/src/FESpaces/SingleFieldFEFunctions.jl +++ b/src/FESpaces/SingleFieldFEFunctions.jl @@ -1,12 +1,13 @@ """ """ -struct SingleFieldFEFunction <: CellField +struct SingleFieldFEFunction{R} <: CellField array cell_vals free_values dirichlet_values fe_space + ref_style::Val{R} @doc """ """ function SingleFieldFEFunction( @@ -15,7 +16,10 @@ struct SingleFieldFEFunction <: CellField free_values::AbstractVector, dirichlet_values::AbstractVector, fe_space::SingleFieldFESpace) - new(array,cell_vals,free_values,dirichlet_values,fe_space) + + ref_style = RefStyle(get_cell_dof_basis(fe_space)) + R = get_val_parameter(ref_style) + new{R}(array,cell_vals,free_values,dirichlet_values,fe_space,ref_style) end end @@ -33,4 +37,4 @@ get_cell_map(f::SingleFieldFEFunction) = get_cell_map(f.fe_space) get_cell_values(f::SingleFieldFEFunction) = f.cell_vals -RefStyle(f::SingleFieldFEFunction) = RefStyle(get_cell_dof_basis(f.fe_space)) +RefStyle(::Type{SingleFieldFEFunction{R}}) where R = Val{R}() diff --git a/src/FESpaces/SingleFieldFESpaces.jl b/src/FESpaces/SingleFieldFESpaces.jl index b05109608..d9380e8eb 100644 --- a/src/FESpaces/SingleFieldFESpaces.jl +++ b/src/FESpaces/SingleFieldFESpaces.jl @@ -134,34 +134,6 @@ function gather_free_values(f::SingleFieldFESpace,cell_vals) free_values, _ = gather_free_and_dirichlet_values(f,cell_vals) free_values end -# -# """ -# cell_field defined in the reference space with derivatives in the physical one -# """ -# function compute_free_and_dirichlet_values(f::SingleFieldFESpace, cell_field::CellField) -# cell_vals = _compute_cell_vals(f, cell_field) -# gather_free_and_dirichlet_values(f,cell_vals) -# end -# -# """ -# """ -# function compute_dirichlet_values(f::SingleFieldFESpace,cell_field::CellField) -# cell_vals = _compute_cell_vals(f, cell_field) -# gather_dirichlet_values(f,cell_vals) -# end -# -# """ -# """ -# function compute_free_values(f::SingleFieldFESpace,cell_field::CellField) -# cell_vals = _compute_cell_vals(f, cell_field) -# gather_free_values(f,cell_vals) -# end -# -# function _compute_cell_vals(f,cell_field) -# cell_dof_basis = get_cell_dof_basis(f) -# cell_vals = evaluate(cell_dof_basis,cell_field) -# cell_vals -# end """ The resulting FE function is in the space (in particular it fulfills Dirichlet BCs @@ -176,7 +148,7 @@ end function _cell_vals(fs::SingleFieldFESpace,object) cdb = get_cell_dof_basis(fs) cm = get_cell_map(fs) - cf = cell_field_from_function(object,cm,RefStyle(cdb)) + cf = convert_to_cell_field(object,cm,RefStyle(cdb)) cell_vals = evaluate(cdb,cf) end diff --git a/src/FESpaces/TrialFESpaces.jl b/src/FESpaces/TrialFESpaces.jl index 6d93703a9..59bdb1ffa 100644 --- a/src/FESpaces/TrialFESpaces.jl +++ b/src/FESpaces/TrialFESpaces.jl @@ -31,7 +31,7 @@ function _prepare_trial_cell_basis(space) a = get_array(cb) cm = get_cell_map(cb) trial_style = Val{true}() - cell_basis = GenericCellBasis(trial_style,a,cm) + cell_basis = GenericCellBasis(trial_style,a,cm,RefStyle(cb)) end # Genuine functions diff --git a/src/Fields/FunctionFields.jl b/src/Fields/FunctionFields.jl index b61df5033..bb324c94e 100644 --- a/src/Fields/FunctionFields.jl +++ b/src/Fields/FunctionFields.jl @@ -1,4 +1,4 @@ -struct FunctionField{F} +struct FunctionField{F} <: Field f::F end @@ -19,3 +19,7 @@ function evaluate_field!(c,f::FunctionField,x) end c end + +function field_gradient(f::FunctionField) + FunctionField(gradient(f.f)) +end diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 5e1d627c7..33aeca01e 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -24,11 +24,13 @@ reference finite element space, and `Val{false}()` when it is defined in the physical space """ RefStyle(::Type{<:CellFieldLike}) = @notimplemented -RefStyle(::T) where T<:CellFieldLike = RefStyle(T) -is_in_ref_space(::Type{T}) where T <:CellFieldLike = get_val_parameter(RefStyle(T)) -is_in_ref_space(::T) where T <:CellFieldLike = is_in_ref_space(T) -is_in_physical_space(a) = !is_in_ref_space(a) +# We use duck typing here for all types marked with the RefStyle +RefStyle(::T) where T = RefStyle(T) +is_in_ref_space(::Type{T}) where T = get_val_parameter(RefStyle(T)) +is_in_ref_space(::T) where T = is_in_ref_space(T) +is_in_physical_space(::Type{T}) where T = !is_in_ref_space(T) +is_in_physical_space(a::T) where T = !is_in_ref_space(T) to_ref_space(a::CellFieldLike) = _to_ref_space(a,RefStyle(a)) _to_ref_space(a,::Val{true}) = a @@ -44,6 +46,10 @@ _to_physical_space(a,::Val{true}) = @notimplemented # and probably not doable in _to_physical_space(a,::Val{false}) = a # Assumption : x ALWAIS defined in the reference space +# In the future we can also add the RefStyle to x +""" + evaluate(cf::CellFieldLike,x) +""" function evaluate(cf::CellFieldLike,x::AbstractArray) _evaluate(cf,x,RefStyle(cf)) end @@ -55,10 +61,9 @@ end function _evaluate(cf::CellFieldLike,x::AbstractArray,::Val{false}) cm = get_cell_map(cf) _x = evaluate(cm,x) - evaluate_field_array(get_array(cf),x) + evaluate_field_array(get_array(cf),_x) end - """ similar_object(cf::CellFieldLike,array::AbstractArray) """ @@ -73,6 +78,15 @@ function similar_object(cf1::CellFieldLike,cf2::CellFieldLike,array::AbstractArr @abstractmethod end +""" + change_ref_style(cf::CellFieldLike) + +Return an object with the same array and metadata as in `cf`, except for `RefStyle` which is changed. +""" +function change_ref_style(cf::CellFieldLike) + @abstractmethod +end + """ gradient(cf::CellFieldLike) """ @@ -104,15 +118,12 @@ function test_cell_field_like(cf::CellFieldLike,x::AbstractArray,b::AbstractArra g = evaluate(gradient(cf),x) test_array(g,grad,pred) end - RefStyle(cf) -end - -""" - evaluate(cf::CellFieldLike,x) -""" -function evaluate(cf::CellFieldLike,x) - a = get_array(cf) - evaluate_field_array(a,x) + rs = RefStyle(cf) + @test isa(get_val_parameter(rs),Bool) + _cf = change_ref_style(cf) + @test get_array(_cf) === get_array(cf) + @test is_in_ref_space(cf) == !is_in_ref_space(_cf) + @test is_in_physical_space(cf) == !is_in_physical_space(_cf) end """ @@ -139,12 +150,22 @@ end function similar_object(cf::CellField,array::AbstractArray) cm = get_cell_map(cf) - GenericCellField(array,cm) + GenericCellField(array,cm,RefStyle(cf)) end function similar_object(cf1::CellField,cf2::CellField,array::AbstractArray) cm = get_cell_map(cf1) - GenericCellField(array,cm) + @assert is_in_ref_space(cf1) == is_in_ref_space(cf2) + GenericCellField(array,cm,RefStyle(cf1)) +end + +function change_ref_style(cf::CellField) + ref_sty = RefStyle(cf) + bool = !get_val_parameter(ref_sty) + new_sty = Val{bool}() + ar = get_array(cf) + cm = get_cell_map(cf) + GenericCellField(ar,cm,new_sty) end # Diff operations @@ -181,46 +202,64 @@ end function operate(op,cf1::CellField,object) cm = get_cell_map(cf1) - cf2 = convert_to_cell_field(object,cm) + cf2 = convert_to_cell_field(object,cm,RefStyle(cf1)) operate(op,cf1,cf2) end function operate(op,object,cf2::CellField) cm = get_cell_map(cf2) - cf1 = convert_to_cell_field(object,cm) + cf1 = convert_to_cell_field(object,cm,RefStyle(cf2)) operate(op,cf1,cf2) end # Conversions +function convert_to_cell_field(object,cell_map) + ref_style = Val{true}() + convert_to_cell_field(object,cell_map,ref_style) +end + """ - convert_to_cell_field(object::CellField,cell_map) + convert_to_cell_field(object,cell_map,ref_style) """ -function convert_to_cell_field(object::CellField,cell_map) +function convert_to_cell_field(object::CellField,cell_map,ref_style::Val) + @assert RefStyle(object) == ref_style object end -function convert_to_cell_field(object::AbstractArray,cell_map) +function convert_to_cell_field(object::CellField,cell_map) + ref_style = RefStyle(object) + convert_to_cell_field(object,cell_map,ref_style) +end + +function convert_to_cell_field(object::AbstractArray,cell_map,ref_style::Val) @assert length(object) == length(cell_map) - GenericCellField(object,cell_map) + GenericCellField(object,cell_map,ref_style) end -function convert_to_cell_field(object::Function,cell_map) +function convert_to_cell_field(object::Function,cell_map,ref_style::Val{true}) b = compose(object,cell_map) - GenericCellField(b,cell_map) + GenericCellField(b,cell_map,Val{true}()) +end + +function convert_to_cell_field(fun::Function,cell_map,ref_style::Val{false}) + field = function_field(fun) + cell_field = Fill(field,length(cell_map)) + GenericCellField(cell_field,cell_map,Val{false}()) end -function convert_to_cell_field(object::Number,cell_map) +function convert_to_cell_field(object::Number,cell_map,ref_style::Val) a = Fill(object,length(cell_map)) - GenericCellField(a,cell_map) + GenericCellField(a,cell_map,ref_style) end # Concrete implementation """ - struct GenericCellField <: CellField +struct GenericCellField{R} <: CellField array::AbstractArray cell_map::AbstractArray + ref_trait::Val{R} end """ struct GenericCellField{R} <: CellField @@ -233,10 +272,6 @@ function GenericCellField(array::AbstractArray,cell_map::AbstractArray) GenericCellField(array,cell_map,Val{true}()) end -# function GenericCellField(array::AbstractArray,cell_map::AbstractArray,ref_style) -# GenericCellField(array,cell_map,ref_style) -# end - function get_array(cf::GenericCellField) cf.array end @@ -249,17 +284,6 @@ function RefStyle(::Type{<:GenericCellField{R}}) where {R} Val{R}() end -function cell_field_from_function(fun,cell_map,::Val{true}) - # GenericCellField(cell_field,cell_map,Val{true}()) - cell_field = convert_to_cell_field(fun,cell_map) -end - -function cell_field_from_function(fun,cell_map,::Val{false}) - field = function_field(fun) - cell_field = Fill(field,length(cell_map)) - GenericCellField(cell_field,cell_map,Val{false}()) -end - # Skeleton related """ @@ -346,12 +370,12 @@ end function operate(op,cf1::SkeletonCellField,object) cm = get_cell_map(cf1) - cf2 = convert_to_cell_field(object,cm) + cf2 = convert_to_cell_field(object,cm,RefStyle(cf1.left)) operate(op,cf1,cf2) end function operate(op,object,cf2::SkeletonCellField) cm = get_cell_map(cf2) - cf1 = convert_to_cell_field(object,cm) + cf1 = convert_to_cell_field(object,cm,RefStyle(cf2.left)) operate(op,cf1,cf2) end diff --git a/src/Geometry/CellQuadratures.jl b/src/Geometry/CellQuadratures.jl index 4435ec260..907d6be20 100644 --- a/src/Geometry/CellQuadratures.jl +++ b/src/Geometry/CellQuadratures.jl @@ -101,7 +101,8 @@ function integrate(cell_field,trian::Triangulation,quad::CellQuadrature) q = get_coordinates(quad) w = get_weights(quad) j = gradient(cell_map) - f = convert_to_cell_field(cell_field,cell_map) + _f = CellField(cell_field,trian) + f = to_ref_space(_f) @assert length(f) == length(cell_map) "Are you using the right triangulation to integrate?" @assert length(f) == length(w) "Are you using the right quadrature to integrate?" integrate(get_array(f),q,w,j) diff --git a/src/Geometry/Geometry.jl b/src/Geometry/Geometry.jl index 7d20d75b5..859d152ce 100644 --- a/src/Geometry/Geometry.jl +++ b/src/Geometry/Geometry.jl @@ -90,6 +90,7 @@ export GenericCellField export SkeletonCellField export RefStyle export similar_object +export change_ref_style export test_cell_field export convert_to_cell_field export to_ref_space diff --git a/src/Geometry/Triangulations.jl b/src/Geometry/Triangulations.jl index 78f63f354..fe5ff704f 100644 --- a/src/Geometry/Triangulations.jl +++ b/src/Geometry/Triangulations.jl @@ -233,7 +233,8 @@ end restrict(cf::CellField,trian::Triangulation) """ function restrict(cf::CellField,trian::Triangulation) - a = get_array(cf) + _cf = to_ref_space(cf) + a = get_array(_cf) r = restrict(a,trian) _restrict_cell_field(r,trian) end diff --git a/src/ReferenceFEs/Dofs.jl b/src/ReferenceFEs/Dofs.jl index 8ba80b843..92001e1c8 100644 --- a/src/ReferenceFEs/Dofs.jl +++ b/src/ReferenceFEs/Dofs.jl @@ -134,9 +134,9 @@ function evaluate_dof_array(dof::AbstractArray,field::AbstractArray) apply(k,dof,field) end -# function evaluate_dof_array(dof::AbstractArray{<:Dof},field::AbstractArray) -# apply(dof,field) -# end +function evaluate_dof_array(dof::AbstractArray{<:Dof},field::AbstractArray) + apply(dof,field) +end """ evaluate(dof::AbstractArray{<:Dof},field::AbstractArray) diff --git a/src/Visualization/Vtk.jl b/src/Visualization/Vtk.jl index a843ffd54..9c44391a6 100644 --- a/src/Visualization/Vtk.jl +++ b/src/Visualization/Vtk.jl @@ -399,8 +399,8 @@ end function _prepare_pdata(trian,cellfields,samplingpoints) pdata = Dict() for (k,v) in cellfields - _v = convert_to_cell_field(v,get_cell_map(trian)) - pdata[k], = _prepare_node_to_coords(evaluate_field_array(get_array(_v),samplingpoints)) + _v = CellField(v,trian) + pdata[k], = _prepare_node_to_coords(evaluate(_v,samplingpoints)) end pdata end diff --git a/test/FESpacesTests/CellBasesTests.jl b/test/FESpacesTests/CellBasesTests.jl index dbb96e652..580305622 100644 --- a/test/FESpacesTests/CellBasesTests.jl +++ b/test/FESpacesTests/CellBasesTests.jl @@ -43,8 +43,8 @@ f(x) = sin(4*pi*(x[1]-x[2]^2))+1 uh = interpolate_everywhere(V0,f) uhx = collect(evaluate(uh,q)) -v = GenericCellBasis(Val{false}(),get_array(cell_basis),get_cell_map(cell_basis)) -u = GenericCellBasis(Val{true}(),get_array(cell_basis),get_cell_map(cell_basis)) +v = GenericCellBasis(Val{false}(),get_array(cell_basis),get_cell_map(cell_basis),Val{true}()) +u = GenericCellBasis(Val{true}(),get_array(cell_basis),get_cell_map(cell_basis),Val{true}()) dv = v du = u diff --git a/test/FESpacesTests/CellDofBasesTests.jl b/test/FESpacesTests/CellDofBasesTests.jl new file mode 100644 index 000000000..44cb8976d --- /dev/null +++ b/test/FESpacesTests/CellDofBasesTests.jl @@ -0,0 +1,52 @@ +module CellDofBasesTests + +using Test +using Gridap.Geometry +using Gridap.FESpaces +using Gridap.Fields + +domain =(0,1,0,1) +partition = (3,3) +model = CartesianDiscreteModel(domain,partition) + +order = 1 + +V = TestFESpace( + reffe = :Lagrangian, + conformity = :H1, + valuetype=Float64, + order = order, + model = model, + dirichlet_tags = [1,6], + dof_space = :physical) + +cell_dof_basis = get_cell_dof_basis(V) +@test is_in_physical_space(cell_dof_basis) + +cell_basis = get_cell_basis(V) +@test is_in_physical_space(cell_basis) + +test_cell_dof_basis(cell_dof_basis,cell_basis) + +# TODO not working: it should be the cell-wise identity... +#display(evaluate(cell_dof_basis,cell_basis)) + +V = TestFESpace( + reffe = :Lagrangian, + conformity = :H1, + valuetype=Float64, + order = order, + model = model, + dirichlet_tags = [1,6]) + +cell_dof_basis = get_cell_dof_basis(V) +@test is_in_ref_space(cell_dof_basis) + +cell_basis = get_cell_basis(V) +@test is_in_ref_space(cell_basis) + +test_cell_dof_basis(cell_dof_basis,cell_basis) + +#display(evaluate(cell_dof_basis,cell_basis)) + +end # module diff --git a/test/FESpacesTests/PhysicalBasesTests.jl b/test/FESpacesTests/PhysicalBasesTests.jl index 4224a5e12..2ce8ecc47 100644 --- a/test/FESpacesTests/PhysicalBasesTests.jl +++ b/test/FESpacesTests/PhysicalBasesTests.jl @@ -93,8 +93,7 @@ T = Float64 order = 0 reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] -psfs_, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) -psfs = get_array(psfs_) +psfs, dofp = Gridap.FESpaces.compute_cell_space_physical(reffes, cell_to_ctype, cell_map) sfs, dof = Gridap.FESpaces.compute_cell_space(reffes, cell_to_ctype, cell_map) r = evaluate(sfs,q) diff --git a/test/FESpacesTests/PhysicalFESpacesTests.jl b/test/FESpacesTests/PhysicalFESpacesTests.jl index c90378f80..647026504 100644 --- a/test/FESpacesTests/PhysicalFESpacesTests.jl +++ b/test/FESpacesTests/PhysicalFESpacesTests.jl @@ -1,4 +1,4 @@ -# module PhysicalFESpacesTests +module PhysicalFESpacesTests using Gridap using Gridap.ReferenceFEs @@ -95,7 +95,6 @@ uhf.dirichlet_values uhdf.dirichlet_values uhd.dirichlet_values - uhf_r = Gridap.FESpaces.interpolate(U,u) uhd_r= Gridap.FESpaces.interpolate_dirichlet(U,u) uhdf_r = Gridap.FESpaces.interpolate_everywhere(U,u) @@ -114,10 +113,16 @@ uhd_r.dirichlet_values @test uhdf.dirichlet_values == uhd.dirichlet_values @test uhdf.dirichlet_values == uhdf_r.dirichlet_values +e = u - uhf_r + +el2 = sqrt(sum(integrate(inner(e,e),trian,quad))) + +@test el2 < 1.0e-10 + e = u - uhf el2 = sqrt(sum(integrate(inner(e,e),trian,quad))) @test el2 < 1.0e-10 -# end #module +end #module diff --git a/test/FESpacesTests/runtests.jl b/test/FESpacesTests/runtests.jl index 9687dc0e2..57a94e48f 100644 --- a/test/FESpacesTests/runtests.jl +++ b/test/FESpacesTests/runtests.jl @@ -4,6 +4,8 @@ using Test @testset "CellBases" begin include("CellBasesTests.jl") end +@testset "CellDofBases" begin include("CellDofBasesTests.jl") end + @testset "Law" begin include("LawTests.jl") end @testset "FEFunctions" begin include("FEFunctionsTests.jl") end From 1cfe779f07fedad395f7ccfcf96295cedf5f2dd4 Mon Sep 17 00:00:00 2001 From: Francesc Verdugo Date: Fri, 20 Mar 2020 18:53:41 +0100 Subject: [PATCH 50/51] physical fe spaces also for multi-field --- src/MultiField/MultiFieldCellBases.jl | 31 ++++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/MultiField/MultiFieldCellBases.jl b/src/MultiField/MultiFieldCellBases.jl index eb37a7c2e..8f5bd7b67 100644 --- a/src/MultiField/MultiFieldCellBases.jl +++ b/src/MultiField/MultiFieldCellBases.jl @@ -1,12 +1,15 @@ -struct CellBasisWithFieldID{S} <: CellBasis +struct CellBasisWithFieldID{S,R} <: CellBasis trial_style::Val{S} cell_basis::CellBasis field_id::Int + ref_style::Val{R} function CellBasisWithFieldID(cell_basis::CellBasis,field_id::Integer) trial_style = TrialStyle(cell_basis) S = get_val_parameter(trial_style) - new{S}(trial_style,cell_basis,field_id) + ref_style = RefStyle(cell_basis) + R = get_val_parameter(ref_style) + new{S,R}(trial_style,cell_basis,field_id,ref_style) end end @@ -14,9 +17,9 @@ get_array(cb::CellBasisWithFieldID) = get_array(cb.cell_basis) get_cell_map(cb::CellBasisWithFieldID) = get_cell_map(cb.cell_basis) -TrialStyle(::Type{CellBasisWithFieldID{S}}) where S = Val{S}() +TrialStyle(::Type{CellBasisWithFieldID{S,R}}) where {S,R} = Val{S}() -RefStyle(cb::CellBasisWithFieldID) = RefStyle(cb.cell_basis) +RefStyle(::Type{CellBasisWithFieldID{S,R}}) where {S,R} = Val{R}() function similar_object(cb::CellBasisWithFieldID,array::AbstractArray) cell_basis = similar_object(cb.cell_basis,array) @@ -47,7 +50,8 @@ function _similar_cell_basis_with_field_id_test_trial(v,a,b) field_id_rows = a.field_id field_id_cols = b.field_id cell_matrix_field = similar_object(a.cell_basis,b.cell_basis,v) - CellMatrixFieldWithFieldIds(cell_matrix_field,field_id_rows,field_id_cols) + @assert is_in_ref_space(a) == is_in_ref_space(b) + CellMatrixFieldWithFieldIds(cell_matrix_field,field_id_rows,field_id_cols,RefStyle(a)) end function operate(op,a::CellBasisWithFieldID,b::CellBasisWithFieldID) @@ -78,12 +82,15 @@ function _operate_cell_basis_with_field_id(op,a,b,atrial,btrial) _operate_cell_basis(op,a,b,TrialStyle(a),TrialStyle(b)) end -struct CellMatrixFieldWithFieldIds <: CellMatrixField +struct CellMatrixFieldWithFieldIds{R} <: CellMatrixField cell_matrix_field::CellMatrixField field_id_rows::Int field_id_cols::Int + ref_style::Val{R} end +RefStyle(::Type{CellMatrixFieldWithFieldIds{R}}) where R = Val{R}() + get_array(a::CellMatrixFieldWithFieldIds) = get_array(a.cell_matrix_field) get_cell_map(a::CellMatrixFieldWithFieldIds) = get_cell_map(a.cell_matrix_field) @@ -96,7 +103,7 @@ function similar_object(cf::CellMatrixFieldWithFieldIds,a::AbstractArray) cell_matrix_field = similar_object(cf.cell_matrix_field,a) field_id_rows = cf.field_id_rows field_id_cols = cf.field_id_cols - CellMatrixFieldWithFieldIds(cell_matrix_field,field_id_rows,field_id_cols) + CellMatrixFieldWithFieldIds(cell_matrix_field,field_id_rows,field_id_cols,RefStyle(cf)) end function similar_object(a::CellMatrixFieldWithFieldIds,b::CellMatrixFieldWithFieldIds,v::AbstractArray) @@ -173,24 +180,28 @@ function integrate(cb::BlockTracker,trian::Triangulation,quad::CellQuadrature) MultiFieldCellArray(blocks,block_ids) end -struct MultiCellBasis{S} <: GridapType +struct MultiCellBasis{S,R} <: GridapType blocks::Vector{CellBasisWithFieldID{S}} function MultiCellBasis(blocks::Vector{<:CellBasis}) cb = first(blocks) S = is_trial(cb) + R = is_in_ref_space(cb) new_blocks = CellBasisWithFieldID{S}[] for (field_id, cell_basis) in enumerate(blocks) @assert is_trial(cell_basis) == S "All the provided bases need to be either test or trial" + @assert is_in_ref_space(cell_basis) == R block = CellBasisWithFieldID(cell_basis,field_id) push!(new_blocks,block) end - new{S}(new_blocks) + new{S,R}(new_blocks) end end FECellBasisStyle(::Type{<:MultiCellBasis}) = Val{true}() -TrialStyle(::Type{MultiCellBasis{S}}) where S = Val{S}() +TrialStyle(::Type{MultiCellBasis{S,R}}) where {S,R} = Val{S}() + +RefStyle(::Type{MultiCellBasis{S,R}}) where {S,R} = Val{R}() num_fields(m::MultiCellBasis) = length(m.blocks) From f87a95177940450a3021ecdf2f73454833c37433 Mon Sep 17 00:00:00 2001 From: Santiago Badia Date: Sat, 21 Mar 2020 19:09:11 +1100 Subject: [PATCH 51/51] Corrected DG space w/ physical, multifield tests --- src/FESpaces/DiscontinuousFESpaces.jl | 8 +- src/FESpaces/FESpaceFactories.jl | 16 +- src/Geometry/CellFields.jl | 1 + src/MultiField/MultiFieldCellBases.jl | 4 +- src/MultiField/MultiFieldFESpaces.jl | 12 +- test/FESpacesTests/ExtendedFESpacesTests.jl | 4 +- test/GridapTests/StokesTaylorHoodTests.jl | 139 +++++++++--------- .../MultiFieldCellBasesTests.jl | 8 + .../MultiFieldFESpacesTests.jl | 97 ++++++------ 9 files changed, 160 insertions(+), 129 deletions(-) diff --git a/src/FESpaces/DiscontinuousFESpaces.jl b/src/FESpaces/DiscontinuousFESpaces.jl index 4778de575..d0c2565f1 100644 --- a/src/FESpaces/DiscontinuousFESpaces.jl +++ b/src/FESpaces/DiscontinuousFESpaces.jl @@ -2,7 +2,7 @@ """ DiscontinuousFESpace(reffes::Vector{<:ReferenceFE}, trian::Triangulation) """ -function DiscontinuousFESpace(reffes::Vector{<:ReferenceFE}, trian::Triangulation) +function DiscontinuousFESpace(reffes::Vector{<:ReferenceFE}, trian::Triangulation, is_ref=true) cell_to_ctype = get_cell_type(trian) cell_map = get_cell_map(trian) @@ -14,7 +14,11 @@ function DiscontinuousFESpace(reffes::Vector{<:ReferenceFE}, trian::Triangulatio dirichlet_cells = Int[] ntags = 0 - cell_shapefuns, cell_dof_basis = compute_cell_space(reffes, cell_to_ctype, cell_map) + if is_ref + cell_shapefuns, cell_dof_basis = compute_cell_space(reffes, cell_to_ctype, cell_map) + else + cell_shapefuns, cell_dof_basis = compute_cell_space_physical(reffes, cell_to_ctype, cell_map) + end UnconstrainedFESpace( nfree, diff --git a/src/FESpaces/FESpaceFactories.jl b/src/FESpaces/FESpaceFactories.jl index 969d25740..1d4a91cc8 100644 --- a/src/FESpaces/FESpaceFactories.jl +++ b/src/FESpaces/FESpaceFactories.jl @@ -94,6 +94,8 @@ function _setup_hdiv_space(kwargs) dofspace = _get_kwarg(:dof_space,kwargs,:reference) ( dofspace == :reference ? true : false ) + is_ref = (dofspace==:reference) + Tf = _get_kwarg(:valuetype,kwargs,VectorValue{1,Float64}) T = eltype(Tf) @@ -105,7 +107,7 @@ function _setup_hdiv_space(kwargs) reffes = [RaviartThomasRefFE(T,p,order) for p in polytopes] if conformity in [true, :default, :HDiv, :Hdiv] - V = DivConformingFESpace(reffes,model,labels,diritags,(dofspace==:reference)) + V = DivConformingFESpace(reffes,model,labels,diritags,is_ref) else s = "Conformity $conformity not implemented for $reffe reference FE on polytopes $(polytopes...)" @unreachable s @@ -126,6 +128,8 @@ function _setup_hcurl_space(kwargs) Tf = _get_kwarg(:valuetype,kwargs,VectorValue{1,Float64}) T = eltype(Tf) + is_ref = dofspace==:reference + if order == nothing @unreachable "order is a mandatory keyword argument in FESpace constructor for Nedelec reference FEs" end @@ -134,7 +138,7 @@ function _setup_hcurl_space(kwargs) reffes = [NedelecRefFE(T,p,order) for p in polytopes] if conformity in [true, :default, :HCurl, :Hcurl] - V = CurlConformingFESpace(reffes,model,labels,diritags,(dofspace==:reference)) + V = CurlConformingFESpace(reffes,model,labels,diritags,is_ref) else s = "Conformity $conformity not implemented for $reffe reference FE on polytopes $(polytopes...)" @unreachable s @@ -157,6 +161,8 @@ function _setup_lagrange_spaces(kwargs) # labels = nothing model = _get_kwarg(:model,kwargs,nothing) + is_ref = (dofspace==:reference) + if T == nothing @unreachable "valuetype is a mandatory keyword argument in FESpace constructor for Lagrangian reference FEs" end @@ -196,7 +202,7 @@ function _setup_lagrange_spaces(kwargs) end end - return DiscontinuousFESpace(_reffes,trian) + return DiscontinuousFESpace(_reffes,trian,is_ref) elseif conformity in [true, :default, :H1, :C0] @@ -215,9 +221,9 @@ function _setup_lagrange_spaces(kwargs) _reffes = [LagrangianRefFE(T,p,order) for p in polytopes] end if labels == nothing - return GradConformingFESpace(_reffes,model,diritags,dirimasks,(dofspace==:reference)) + return GradConformingFESpace(_reffes,model,diritags,dirimasks,is_ref) else - return GradConformingFESpace(_reffes,model,labels,diritags,dirimasks,(dofspace==:reference)) + return GradConformingFESpace(_reffes,model,labels,diritags,dirimasks,is_ref) end else diff --git a/src/Geometry/CellFields.jl b/src/Geometry/CellFields.jl index 33aeca01e..dee177ac3 100644 --- a/src/Geometry/CellFields.jl +++ b/src/Geometry/CellFields.jl @@ -26,6 +26,7 @@ physical space RefStyle(::Type{<:CellFieldLike}) = @notimplemented # We use duck typing here for all types marked with the RefStyle +# @santiagobadia : That is dangerous, it creates overflows if called with RefStyle(::T) where T = RefStyle(T) is_in_ref_space(::Type{T}) where T = get_val_parameter(RefStyle(T)) is_in_ref_space(::T) where T = is_in_ref_space(T) diff --git a/src/MultiField/MultiFieldCellBases.jl b/src/MultiField/MultiFieldCellBases.jl index 8f5bd7b67..d1b9ca326 100644 --- a/src/MultiField/MultiFieldCellBases.jl +++ b/src/MultiField/MultiFieldCellBases.jl @@ -188,8 +188,8 @@ struct MultiCellBasis{S,R} <: GridapType R = is_in_ref_space(cb) new_blocks = CellBasisWithFieldID{S}[] for (field_id, cell_basis) in enumerate(blocks) - @assert is_trial(cell_basis) == S "All the provided bases need to be either test or trial" - @assert is_in_ref_space(cell_basis) == R + @assert is_trial(cell_basis) == S "All the provided bases must be of the same type (trial or test)" + @assert is_in_ref_space(cell_basis) == R "All the provided bases must be defined in the same space (reference or physical)" block = CellBasisWithFieldID(cell_basis,field_id) push!(new_blocks,block) end diff --git a/src/MultiField/MultiFieldFESpaces.jl b/src/MultiField/MultiFieldFESpaces.jl index daa4879c7..2f8dbb639 100644 --- a/src/MultiField/MultiFieldFESpaces.jl +++ b/src/MultiField/MultiFieldFESpaces.jl @@ -1,7 +1,7 @@ abstract type MultiFieldStyle end -struct ConsequtiveMultiFieldStyle <: MultiFieldStyle end +struct ConsecutiveMultiFieldStyle <: MultiFieldStyle end struct StridedMultiFieldStyle <: MultiFieldStyle end @@ -30,7 +30,7 @@ end MultiFieldFESpace(spaces::Vector{<:SingleFieldFESpace}) """ function MultiFieldFESpace(spaces::Vector{<:SingleFieldFESpace}) - MultiFieldFESpace(spaces,ConsequtiveMultiFieldStyle()) + MultiFieldFESpace(spaces,ConsecutiveMultiFieldStyle()) end MultiFieldStyle(::Type{MultiFieldFESpace{S,B}}) where {S,B} = S() @@ -129,7 +129,7 @@ function _restrict_to_field(f,::MultiFieldStyle,free_values,field) @notimplemented end -function _restrict_to_field(f,::ConsequtiveMultiFieldStyle,free_values,field) +function _restrict_to_field(f,::ConsecutiveMultiFieldStyle,free_values,field) offsets = compute_field_offsets(f) U = f.spaces pini = offsets[field] + 1 @@ -146,7 +146,7 @@ function _get_cell_dofs(f,::MultiFieldStyle) end -function _get_cell_dofs(f,::ConsequtiveMultiFieldStyle) +function _get_cell_dofs(f,::ConsecutiveMultiFieldStyle) offsets = compute_field_offsets(f) spaces = f.spaces function fun(i,space) @@ -171,13 +171,13 @@ function _sum_if_first_positive(a,b) end end -# API for the ConsequtiveMultiFieldStyle +# API for the ConsecutiveMultiFieldStyle """ compute_field_offsets(f::MultiFieldFESpace) """ function compute_field_offsets(f::MultiFieldFESpace) - @assert MultiFieldStyle(f) == ConsequtiveMultiFieldStyle() + @assert MultiFieldStyle(f) == ConsecutiveMultiFieldStyle() U = f.spaces n = length(U) offsets = zeros(Int,n) diff --git a/test/FESpacesTests/ExtendedFESpacesTests.jl b/test/FESpacesTests/ExtendedFESpacesTests.jl index a7dfc1afe..ccabd1ba1 100644 --- a/test/FESpacesTests/ExtendedFESpacesTests.jl +++ b/test/FESpacesTests/ExtendedFESpacesTests.jl @@ -1,4 +1,4 @@ -# module ExtendedFESpacesTests +module ExtendedFESpacesTests using Test using Gridap.Arrays @@ -120,4 +120,4 @@ V = TestFESpace(triangulation=trian,valuetype=Float64,reffe=:Lagrangian,order=2, #writevtk(trian,"trian",cellfields=["uh"=>uh]) #writevtk(trian_in,"trian_in",cellfields=["uh"=>uh_in]) -# end # module +end # module diff --git a/test/GridapTests/StokesTaylorHoodTests.jl b/test/GridapTests/StokesTaylorHoodTests.jl index db1935a23..13fde5591 100644 --- a/test/GridapTests/StokesTaylorHoodTests.jl +++ b/test/GridapTests/StokesTaylorHoodTests.jl @@ -29,73 +29,80 @@ add_tag_from_tags!(labels,"neumann",[6,7,8]) order = 2 -V = TestFESpace( - model=model, - order=order, - reffe=:Lagrangian, - labels=labels, - valuetype=VectorValue{2,Float64}, - dirichlet_tags="dirichlet", - conformity=:H1) - -Q = TestFESpace( - model=model, - order=order-1, - reffe=:Lagrangian, - valuetype=Float64, - conformity=:H1) - -U = TrialFESpace(V,u) -P = TrialFESpace(Q) - -Y = MultiFieldFESpace([V,Q]) -X = MultiFieldFESpace([U,P]) - -trian = get_triangulation(model) -degree = order -quad = CellQuadrature(trian,degree) - -btrian = BoundaryTriangulation(model,labels,"neumann") -bdegree = order -bquad = CellQuadrature(btrian,bdegree) -const n = get_normal_vector(btrian) - -function a(x,y) - u,p = x - v,q = y - inner(∇(v),∇(u)) - (∇*v)*p + q*(∇*u) +ref_style = [:reference,:physical] + +for ref_st in ref_style + V = TestFESpace( + model=model, + order=order, + reffe=:Lagrangian, + labels=labels, + valuetype=VectorValue{2,Float64}, + dirichlet_tags="dirichlet", + dof_space=ref_st, + conformity=:H1) + + Q = TestFESpace( + model=model, + order=order-1, + reffe=:Lagrangian, + valuetype=Float64, + dof_space=ref_st, + conformity=:H1) + + U = TrialFESpace(V,u) + P = TrialFESpace(Q) + + Y = MultiFieldFESpace([V,Q]) + X = MultiFieldFESpace([U,P]) + + trian = get_triangulation(model) + degree = order + quad = CellQuadrature(trian,degree) + + btrian = BoundaryTriangulation(model,labels,"neumann") + bdegree = order + bquad = CellQuadrature(btrian,bdegree) + n = get_normal_vector(btrian) + + function a(x,y) + u,p = x + v,q = y + inner(∇(v),∇(u)) - (∇*v)*p + q*(∇*u) + end + + function l(y) + v,q = y + v*f + q*g + end + + function l_Γb(y) + v,q = y + v*(n*∇u) - (n*v)*p + end + + t_Ω = AffineFETerm(a,l,trian,quad) + t_Γb = FESource(l_Γb,btrian,bquad) + + op = AffineFEOperator(X,Y,t_Ω,t_Γb) + + uh, ph = solve(op) + + eu = u - uh + ep = p - ph + + l2(v) = v*v + h1(v) = v*v + inner(∇(v),∇(v)) + + eu_l2 = sqrt(sum(integrate(l2(eu),trian,quad))) + eu_h1 = sqrt(sum(integrate(h1(eu),trian,quad))) + ep_l2 = sqrt(sum(integrate(l2(ep),trian,quad))) + + tol = 1.0e-9 + @test eu_l2 < tol + @test eu_h1 < tol + @test ep_l2 < tol end -function l(y) - v,q = y - v*f + q*g -end - -function l_Γb(y) - v,q = y - v*(n*∇u) - (n*v)*p -end - -t_Ω = AffineFETerm(a,l,trian,quad) -t_Γb = FESource(l_Γb,btrian,bquad) - -op = AffineFEOperator(X,Y,t_Ω,t_Γb) - -uh, ph = solve(op) - -eu = u - uh -ep = p - ph - -l2(v) = v*v -h1(v) = v*v + inner(∇(v),∇(v)) - -eu_l2 = sqrt(sum(integrate(l2(eu),trian,quad))) -eu_h1 = sqrt(sum(integrate(h1(eu),trian,quad))) -ep_l2 = sqrt(sum(integrate(l2(ep),trian,quad))) - -tol = 1.0e-9 -@test eu_l2 < tol -@test eu_h1 < tol -@test ep_l2 < tol end # module diff --git a/test/MultiFieldTests/MultiFieldCellBasesTests.jl b/test/MultiFieldTests/MultiFieldCellBasesTests.jl index 94b29f062..7aad5392d 100644 --- a/test/MultiFieldTests/MultiFieldCellBasesTests.jl +++ b/test/MultiFieldTests/MultiFieldCellBasesTests.jl @@ -22,12 +22,14 @@ quad = CellQuadrature(trian,degree) q = get_coordinates(quad) V = TestFESpace(model=model,reffe=:Lagrangian,order=order,conformity=:H1,valuetype=Float64) +Vp = TestFESpace(model=model,reffe=:Lagrangian,order=order,conformity=:H1,valuetype=Float64,dof_space=:physical) U = TrialFESpace(V) cell_basis_v = get_cell_basis(V) field_id_v = 3 v = CellBasisWithFieldID(cell_basis_v,field_id_v) vq = collect(evaluate(v,q)) +@test is_in_ref_space(v) field_id_a = 2 a = CellBasisWithFieldID(cell_basis_v,field_id_a) @@ -42,6 +44,12 @@ field_id_b = 5 b = CellBasisWithFieldID(cell_basis_u,field_id_b) bq = collect(evaluate(b,q)) +cell_basis_vp = get_cell_basis(Vp) +field_id_vp = 6 +vp = CellBasisWithFieldID(cell_basis_vp,field_id_vp) +vpq = collect(evaluate(vp,q)) +@test !is_in_ref_space(vp) + r = 2*v test_cell_basis(r,q,2*vq) @test isa(r,CellBasisWithFieldID) diff --git a/test/MultiFieldTests/MultiFieldFESpacesTests.jl b/test/MultiFieldTests/MultiFieldFESpacesTests.jl index f2edd5f79..3a37ab2e2 100644 --- a/test/MultiFieldTests/MultiFieldFESpacesTests.jl +++ b/test/MultiFieldTests/MultiFieldFESpacesTests.jl @@ -10,7 +10,7 @@ using Test using Gridap.MultiField using Gridap.MultiField: MultiFieldFESpace using Gridap.MultiField: MultiFieldCellArray -using Gridap.MultiField: ConsequtiveMultiFieldStyle +using Gridap.MultiField: ConsecutiveMultiFieldStyle order = 2 @@ -22,64 +22,69 @@ trian = get_triangulation(model) degree = order quad = CellQuadrature(trian,degree) -V = TestFESpace(model=model,order=order,reffe=:Lagrangian,conformity=:H1,valuetype=Float64) -Q = TestFESpace(model=model,order=order-1,reffe=:Lagrangian,conformity=:L2,valuetype=Float64) +ref_style = [:reference,:physical] -U = TrialFESpace(V) -P = TrialFESpace(Q) +for ref_st in ref_style + + V = TestFESpace(model=model,order=order,reffe=:Lagrangian,conformity=:H1,valuetype=Float64,dof_space=ref_st) + Q = TestFESpace(model=model,order=order-1,reffe=:Lagrangian,conformity=:L2,valuetype=Float64,dof_space=ref_st) -multi_field_style = ConsequtiveMultiFieldStyle() + U = TrialFESpace(V) + P = TrialFESpace(Q) -Y = MultiFieldFESpace([V,Q],multi_field_style) -X = MultiFieldFESpace([U,P],multi_field_style) + multi_field_style = ConsecutiveMultiFieldStyle() -@test num_free_dofs(X) == num_free_dofs(U) + num_free_dofs(P) -@test num_free_dofs(X) == num_free_dofs(Y) + Y = MultiFieldFESpace([V,Q],multi_field_style) + X = MultiFieldFESpace([U,P],multi_field_style) -free_values = rand(num_free_dofs(X)) -xh = FEFunction(X,free_values) -test_fe_function(xh) -@test is_a_fe_function(xh) -uh, ph = xh -@test is_a_fe_function(uh) -@test is_a_fe_function(ph) + @test num_free_dofs(X) == num_free_dofs(U) + num_free_dofs(P) + @test num_free_dofs(X) == num_free_dofs(Y) -dy = get_cell_basis(Y) -@test is_test(dy) -@test is_a_fe_cell_basis(dy) -dv, dq = dy -@test is_a_fe_cell_basis(dv) -@test is_a_fe_cell_basis(dq) + free_values = rand(num_free_dofs(X)) + xh = FEFunction(X,free_values) + test_fe_function(xh) + @test is_a_fe_function(xh) + uh, ph = xh + @test is_a_fe_function(uh) + @test is_a_fe_function(ph) -dx = get_cell_basis(X) -@test is_a_fe_cell_basis(dx) -@test is_trial(dx) -du, dp = dx -@test is_a_fe_cell_basis(du) -@test is_a_fe_cell_basis(dp) + dy = get_cell_basis(Y) + @test is_test(dy) + @test is_a_fe_cell_basis(dy) + dv, dq = dy + @test is_a_fe_cell_basis(dv) + @test is_a_fe_cell_basis(dq) -cellmat = integrate(dv*du,trian,quad) -cellvec = integrate(dv*2,trian,quad) -cellids = get_cell_id(trian) -cellmatvec = pair_arrays(cellmat,cellvec) + dx = get_cell_basis(X) + @test is_a_fe_cell_basis(dx) + @test is_trial(dx) + du, dp = dx + @test is_a_fe_cell_basis(du) + @test is_a_fe_cell_basis(dp) -matvecdata = (cellmatvec,cellids,cellids) -matdata = (cellmat,cellids,cellids) -vecdata = (cellvec,cellids) + cellmat = integrate(dv*du,trian,quad) + cellvec = integrate(dv*2,trian,quad) + cellids = get_cell_id(trian) + cellmatvec = pair_arrays(cellmat,cellvec) -test_fe_space(V,matvecdata,matdata,vecdata) -test_fe_space(U,matvecdata,matdata,vecdata) + matvecdata = (cellmatvec,cellids,cellids) + matdata = (cellmat,cellids,cellids) + vecdata = (cellvec,cellids) -#using Gridap.Visualization -#writevtk(trian,"trian";nsubcells=30,cellfields=["uh" => uh, "ph"=> ph]) + test_fe_space(V,matvecdata,matdata,vecdata) + test_fe_space(U,matvecdata,matdata,vecdata) -cell_dofs = get_cell_dofs(X) -@test isa(cell_dofs,MultiFieldCellArray) + #using Gridap.Visualization + #writevtk(trian,"trian";nsubcells=30,cellfields=["uh" => uh, "ph"=> ph]) -cellids = [3,5,2] + cell_dofs = get_cell_dofs(X) + @test isa(cell_dofs,MultiFieldCellArray) -cell_dofs_new = reindex(cell_dofs,cellids) -@test isa(cell_dofs_new,MultiFieldCellArray) -@test cell_dofs_new.block_ids == cell_dofs.block_ids + cellids = [3,5,2] + + cell_dofs_new = reindex(cell_dofs,cellids) + @test isa(cell_dofs_new,MultiFieldCellArray) + @test cell_dofs_new.block_ids == cell_dofs.block_ids +end end # module