gridap / GridapP4est.jl

MIT License
10 stars 1 forks source link

Add support for adaptive mesh refinement with hanging-nodes to Gridap.jl (serial runs) #21

Closed amartinhuertas closed 1 year ago

amartinhuertas commented 2 years ago

Potential tasks (to be filled as we go):

CONCERNS

TO-DO DONE

cc @santiagobadia @fverdugo

I create this issue as requested by @principejavier. The issue develops a bit further the project abstract available at

https://github.com/gridap/GSoC/blob/main/2022/ideas-list.md#add-support-for-adaptive-mesh-refinement-with-hanging-nodes-to-gridapjl

with additional remarks/code/details.

principejavier commented 2 years ago

Thanks @amartinhuertas! I finally had time to start with this. So far I only completed Step0 and I got a fair first understanding of Gridap.Geometry. Everything seems to work, see the pictures without and with constrains:

non_conforming

constrained

amartinhuertas commented 1 year ago

Hi @principejavier ! Which is the status of this development?

principejavier commented 1 year ago

Hi @amartinhuertas I was at step 1 when shifted focus to other issues. I expect to have some time for this at the end of the month.

amartinhuertas commented 1 year ago

Ok. Thanks for the update. I may have some time the following two weeks to contribute to this dev. I am just asking so that we do not overlap work. My goal would be ideally to come up with the linear constraints built for the serial case + 2D, and be able to solve a 2D Poisson problem with a non-conforming mesh top-bottom.

amartinhuertas commented 1 year ago

cc @JordiManyer ... highly related to his current work.

JordiManyer commented 1 year ago

I have time to put into this PR, although I don't really have experience with the low-level P4est api. But I'm glad to take any work off your hands if you need me to.

principejavier commented 1 year ago

Here is the code for Step 0

module poisson

using FillArrays
using Gridap
using Gridap.Arrays
using Gridap.FESpaces
import Gridap: ∇

# Define manufactured functions
u(x) = x[1] # + x[2]
∇u(x) = VectorValue(1,1)
∇(::typeof(u)) = ∇u
f(x) = 0.0

function setup_model()
#
#  7---8---9------11
#  | 3 | 4 |       |
#  4---5---6   5   |
#  | 1 | 2 |       |
#  1---2---3------10
#
    ptr  = [ 1, 5, 9, 13, 17, 21 ]
    data = [ 1,2,4,5, 2,3,5,6, 4,5,7,8, 5,6,8,9, 3,10,9,11 ]
    cell_vertex_lids = Gridap.Arrays.Table(data,ptr)
    node_coordinates = Vector{Point{2,Float64}}(undef,11)
    for j in 1:3
        for i in 1:3
            node_coordinates[3*(j-1)+i]=Point{2,Float64}((i-1)/2.0,(j-1)/2.0)
        end
    end
    node_coordinates[10]=Point{2,Float64}(2.0,0.0)
    node_coordinates[11]=Point{2,Float64}(2.0,1.0)

    polytope=QUAD
    scalar_reffe=Gridap.ReferenceFEs.ReferenceFE(polytope,Gridap.ReferenceFEs.lagrangian,Float64,1)
    cell_types=collect(Fill(1,length(cell_vertex_lids)))
    cell_reffes=[scalar_reffe]
    grid = Gridap.Geometry.UnstructuredGrid(node_coordinates,
                                            cell_vertex_lids,
                                            cell_reffes,
                                            cell_types,
                                            Gridap.Geometry.NonOriented())
    Gridap.Geometry.UnstructuredDiscreteModel(grid)
end

function run()

# Construct the discrete model
model=setup_model()
labels = get_face_labeling(model)
labels.d_to_dface_to_entity[1]=[1,0,0,1,0,0,1,0,0,1,1]
labels.d_to_dface_to_entity[2]=[0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1] # this is not needed...
add_tag!(labels,"dirichlet",[1])

# Construct the FEspace
order = 1
reffe = ReferenceFE(lagrangian,Float64,order)
V0 = TestFESpace(model,reffe,conformity=:H1,dirichlet_tags="dirichlet")
U = TrialFESpace(V0,u)

sDOF_to_dof = [4]
sDOF_to_dofs = Table([[2,6]])
sDOF_to_coeffs = Table([[0.5,0.5]])
Vc = FESpaceWithLinearConstraints(
  sDOF_to_dof,
  sDOF_to_dofs,
  sDOF_to_coeffs,
  V0)
Uc = TrialFESpace(Vc,u)

# Define integration mesh and quadrature
degree = 2
Ω = Triangulation(model)
dΩ = Measure(Ω,degree)

a(u,v) = ∫( ∇(v)⊙∇(u) )*dΩ
b(v) = ∫(v*f)*dΩ

# op = AffineFEOperator(a,b,U,V0)
op = AffineFEOperator(a,b,Uc,Vc)
uh = solve(op)

# Define exact solution and error
e = u - uh

# Compute errors
el2 = sqrt(sum( ∫( e*e )*dΩ ))
eh1 = sqrt(sum( ∫( e*e + ∇(e)⋅∇(e) )*dΩ ))

# tol=1e-8
# @assert el2 < tol
# @assert eh1 < tol

# Write the numerical solution, the manufactured solution, and the error
# in a vtu file
#writevtk(trian,"results",nref=1,cellfields=["uh"=>uh,"u"=>u,"e"=>e])
writevtk(Ω,"results",cellfields=["uh"=>uh,"u"=>u,"e"=>e])

end

end
amartinhuertas commented 1 year ago

For the records, and to help understanding the p4est_lnodes_t data structure, let me post below, assuming that we run the sample snippet program (in its current status: https://github.com/gridap/P4est_wrapper.jl/blob/a0b27a292f4684ccd485661b7ac05d9bccac2e32/test/example_lnodes.jl) in a single MPI task:

  1. A picture of the element_nodes member variable, along with the values of other relevant member variables.
  2. The output that the program generates on screen.

IMG20230117145021

cell=1 faces=Int32[0, 1, 2, 3]
lface=0 gface=0
lface=1 gface=1
lface=2 gface=2
lface=3 gface=3
cell=1 vertices=Int32[4, 5, 6, 7]
cell=1 does not have hanging faces
cell=2 faces=Int32[1, 8, 9, 10]
lface=1 gface=1
lface=8 gface=8
lface=9 gface=9
lface=10 gface=10
cell=2 vertices=Int32[5, 11, 7, 16]
cell=2 has hanging faces
cell=2 lface=1 is NOT hanging
cell=2 lface=2 is hanging from half=0
cell=2 lface=3 is NOT hanging
cell=2 lface=4 is NOT hanging
cell=3 faces=Int32[12, 13, 3, 14]
lface=12 gface=12
lface=13 gface=13
lface=3 gface=3
lface=14 gface=14
cell=3 vertices=Int32[6, 7, 15, 16]
cell=3 has hanging faces
cell=3 lface=1 is NOT hanging
cell=3 lface=2 is NOT hanging
cell=3 lface=3 is NOT hanging
cell=3 lface=4 is hanging from half=0
cell=4 faces=Int32[13, 8, 10, 14]
lface=13 gface=13
lface=8 gface=8
lface=10 gface=10
lface=14 gface=14
cell=4 vertices=Int32[7, 11, 15, 16]
cell=4 has hanging faces
cell=4 lface=1 is NOT hanging
cell=4 lface=2 is hanging from half=1
cell=4 lface=3 is NOT hanging
cell=4 lface=4 is hanging from half=1
cell=5 faces=Int32[8, 17, 18, 19]
lface=8 gface=8
lface=17 gface=17
lface=18 gface=18
lface=19 gface=19
cell=5 vertices=Int32[11, 20, 16, 21]
cell=5 does not have hanging faces
cell=6 faces=Int32[22, 23, 14, 24]
lface=22 gface=22
lface=23 gface=23
lface=14 gface=14
lface=24 gface=24
cell=6 vertices=Int32[15, 16, 25, 26]
cell=6 does not have hanging faces
cell=7 faces=Int32[23, 27, 19, 28]
lface=23 gface=23
lface=27 gface=27
lface=19 gface=19
lface=28 gface=28
cell=7 vertices=Int32[16, 21, 26, 29]
cell=7 does not have hanging faces
amartinhuertas commented 1 year ago

The same as in https://github.com/gridap/GridapP4est.jl/issues/21#issuecomment-1384819749 but with an updated version of the test driver that just prints additional output on screen (https://github.com/gridap/P4est_wrapper.jl/blob/568fc013a991bde9f619886474cc35e5ae2f26ea/test/example_lnodes.jl) run on two MPI tasks: EDIT: (1) the upper left corner in the 4th cell in P0 should be labeled as 15 not 16; (2) the upper right corner of the 4th cell in P0 is labeled as 16.

IMG20230117181715

[1,0]<stdout>:num_local_nodes=17
[1,0]<stdout>:owned_count=17
[1,0]<stdout>:num_nonlocal_nodes=0
[1,0]<stdout>:nonlocal_nodes=Int64[]
[1,0]<stdout>:global_owned_count=Int32[17, 13]
[1,0]<stdout>:global_offset=0
[1,0]<stdout>:num_nonlocal_nodes=0
[1,0]<stdout>:nonlocal_nodes=Int64[]
[1,0]<stdout>:cell=1 faces=Int32[0, 1, 2, 3]
[1,0]<stdout>:lface=0 gface=0
[1,0]<stdout>:lface=1 gface=1
[1,0]<stdout>:lface=2 gface=2
[1,0]<stdout>:lface=3 gface=3
[1,0]<stdout>:cell=1 vertices=Int32[4, 5, 6, 7]
[1,0]<stdout>:cell=1 does not have hanging faces
[1,0]<stdout>:cell=2 faces=Int32[1, 8, 9, 10]
[1,0]<stdout>:lface=1 gface=1
[1,0]<stdout>:lface=8 gface=8
[1,0]<stdout>:lface=9 gface=9
[1,0]<stdout>:lface=10 gface=10
[1,0]<stdout>:cell=2 vertices=Int32[5, 11, 7, 16]
[1,0]<stdout>:cell=2 has hanging faces
[1,0]<stdout>:cell=2 lface=1 is NOT hanging
[1,0]<stdout>:cell=2 lface=2 is hanging from half=0
[1,0]<stdout>:cell=2 lface=3 is NOT hanging
[1,0]<stdout>:cell=2 lface=4 is NOT hanging
[1,0]<stdout>:cell=3 faces=Int32[12, 13, 3, 14]
[1,0]<stdout>:lface=12 gface=12
[1,0]<stdout>:lface=13 gface=13
[1,0]<stdout>:lface=3 gface=3
[1,0]<stdout>:lface=14 gface=14
[1,0]<stdout>:cell=3 vertices=Int32[6, 7, 15, 16]
[1,0]<stdout>:cell=3 has hanging faces
[1,0]<stdout>:cell=3 lface=1 is NOT hanging
[1,0]<stdout>:cell=3 lface=2 is NOT hanging
[1,0]<stdout>:cell=3 lface=3 is NOT hanging
[1,0]<stdout>:cell=3 lface=4 is hanging from half=0
[1,0]<stdout>:cell=4 faces=Int32[13, 8, 10, 14]
[1,0]<stdout>:lface=13 gface=13
[1,0]<stdout>:lface=8 gface=8
[1,0]<stdout>:lface=10 gface=10
[1,0]<stdout>:lface=14 gface=14
[1,0]<stdout>:cell=4 vertices=Int32[7, 11, 15, 16]
[1,0]<stdout>:cell=4 has hanging faces
[1,0]<stdout>:cell=4 lface=1 is NOT hanging
[1,0]<stdout>:cell=4 lface=2 is hanging from half=1
[1,0]<stdout>:cell=4 lface=3 is NOT hanging
[1,0]<stdout>:cell=4 lface=4 is hanging from half=1

[1,1]<stdout>:num_local_nodes=18
[1,1]<stdout>:owned_count=13
[1,1]<stdout>:num_nonlocal_nodes=5
[1,1]<stdout>:nonlocal_nodes=[8, 11, 14, 15, 16]
[1,1]<stdout>:global_owned_count=Int32[17, 13]
[1,1]<stdout>:global_offset=17
[1,1]<stdout>:num_nonlocal_nodes=5
[1,1]<stdout>:nonlocal_nodes=[8, 11, 14, 15, 16]
[1,1]<stdout>:cell=1 faces=Int32[13, 0, 1, 2]
[1,1]<stdout>:lface=13 gface=30
[1,1]<stdout>:lface=0 gface=17
[1,1]<stdout>:lface=1 gface=18
[1,1]<stdout>:lface=2 gface=19
[1,1]<stdout>:cell=1 vertices=Int32[14, 3, 17, 4]
[1,1]<stdout>:cell=1 does not have hanging faces
[1,1]<stdout>:cell=2 faces=Int32[5, 6, 15, 7]
[1,1]<stdout>:lface=5 gface=22
[1,1]<stdout>:lface=6 gface=23
[1,1]<stdout>:lface=15 gface=32
[1,1]<stdout>:lface=7 gface=24
[1,1]<stdout>:cell=2 vertices=Int32[16, 17, 8, 9]
[1,1]<stdout>:cell=2 does not have hanging faces
[1,1]<stdout>:cell=3 faces=Int32[6, 10, 2, 11]
[1,1]<stdout>:lface=6 gface=23
[1,1]<stdout>:lface=10 gface=27
[1,1]<stdout>:lface=2 gface=19
[1,1]<stdout>:lface=11 gface=28
[1,1]<stdout>:cell=3 vertices=Int32[17, 4, 9, 12]
[1,1]<stdout>:cell=3 does not have hanging faces
principejavier commented 1 year ago

Note that the p4est does not generate an ID for hanging nodes but it fills the cell with the constraining one (that is not already in the cell), e.g upper right corner of cell 3 in https://github.com/gridap/GridapP4est.jl/issues/21#issuecomment-1384819749 is printed as 16.

Therefore replacing the function setup_model in the code of Step 0 above will not be immediate, we need to generate a new numbering (adding IDs to hanging nodes) to create the space V0. One option would be to just using a counter starting at num_local_nodes. In the parallel case it would require a reduction to generate global IDs.

amartinhuertas commented 1 year ago

Note that the p4est does not generate an ID for hanging nodes but it fills the cell with the constraining one (that is not already in the cell), e.g upper right corner of cell 3 in https://github.com/gridap/GridapP4est.jl/issues/21#issuecomment-1384819749 is printed as 16. Therefore replacing the function setup_model in the code of Step 0 above will not be immediate, we need to generate a new numbering (adding IDs to hanging nodes) to create the space V0.

Yes, I also noted that. Unfortunately, we cannot run the current algorithm for conforming meshes verbatim to generate the model produced by setup_model() in step 0 (e.g., for faces, this would imply gluing together the hanging faces and their owner face, which i think does not make much sense). As you say, it seems we need an ad-hoc numbering of vertices, edges, and faces algorithm for non-conforming meshes.

In 2D, the logic behind the definition of p4est_lnodes_t seems to be:

[UPDATE]: the logic behind p4est_lnodes is to provide, for a given cell, all the dofs ids which are ultimately touched when assembling the cell + the constraints on its hanging dofs.

amartinhuertas commented 1 year ago

Just documenting in this post (to not forget) an scenario we will have to deal with correctly when working with 3D non-conforming meshes:

IMG20230118114403

amartinhuertas commented 1 year ago

For the records, below you can find the output of https://github.com/gridap/P4est_wrapper.jl/blob/51530b6d8a88b2a6b14228eeffcd910b652a19a6/test/example_lnodes_3d.jl (i.e., p8est_lnodes_t for degree=-3) along with an illustration that covers all possible cases:

IMG20230121215116

cell=1 faces=Int32[0, 1, 2, 3, 4, 5]
lface=0 gface=0
lface=1 gface=1
lface=2 gface=2
lface=3 gface=3
lface=4 gface=4
lface=5 gface=5
cell=1 edges=Int32[6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
cell=1 corners=Int32[18, 19, 20, 21, 22, 23, 24, 25]
cell=1 does not have hanging faces
cell=2 faces=Int32[1, 26, 27, 28, 29, 30]
lface=1 gface=1
lface=26 gface=26
lface=27 gface=27
lface=28 gface=28
lface=29 gface=29
lface=30 gface=30
cell=2 edges=Int32[31, 32, 33, 34, 11, 35, 13, 36, 15, 37, 17, 38]
cell=2 corners=Int32[19, 39, 21, 40, 23, 41, 25, 42]
cell=2 has hanging faces
hanging_face=Int32[0, -1, -1, -1, -1, -1]
hanging_edge=Int32[-1, -1, -1, -1, 0, -1, 4, -1, 0, -1, 4, -1]
cell=3 faces=Int32[26, 43, 44, 45, 46, 47]
lface=26 gface=26
lface=43 gface=43
lface=44 gface=44
lface=45 gface=45
lface=46 gface=46
lface=47 gface=47
cell=3 edges=Int32[48, 49, 50, 51, 35, 52, 36, 53, 37, 54, 38, 55]
cell=3 corners=Int32[39, 56, 40, 57, 41, 58, 42, 59]
cell=3 does not have hanging faces
cell=4 faces=Int32[1, 60, 28, 61, 62, 63]
lface=1 gface=1
lface=60 gface=60
lface=28 gface=28
lface=61 gface=61
lface=62 gface=62
lface=63 gface=63
cell=4 edges=Int32[32, 64, 34, 89, 11, 65, 13, 66, 15, 38, 17, 72]
cell=4 corners=Int32[19, 40, 21, 73, 23, 42, 25, 91]
cell=4 has hanging faces
hanging_face=Int32[1, -1, -1, 0, -1, -1]
hanging_edge=Int32[-1, 0, -1, 4, 3, -1, 4, -1, 4, -1, 0, 4]
cell=5 faces=Int32[60, 67, 45, 61, 68, 69]
lface=60 gface=60
lface=67 gface=67
lface=45 gface=45
lface=61 gface=61
lface=68 gface=68
lface=69 gface=69
cell=5 edges=Int32[49, 64, 51, 89, 65, 70, 66, 71, 38, 55, 17, 72]
cell=5 corners=Int32[40, 57, 21, 73, 42, 59, 25, 91]
cell=5 has hanging faces
hanging_face=Int32[-1, -1, -1, 1, -1, -1]
hanging_edge=Int32[-1, 1, -1, 4, -1, -1, -1, -1, -1, -1, 4, 2]
cell=6 faces=Int32[1, 74, 75, 76, 30, 77]
lface=1 gface=1
lface=74 gface=74
lface=75 gface=75
lface=76 gface=76
lface=30 gface=30
lface=77 gface=77
cell=6 edges=Int32[33, 34, 78, 89, 11, 36, 13, 84, 15, 79, 17, 80]
cell=6 corners=Int32[19, 41, 21, 42, 23, 87, 25, 91]
cell=6 has hanging faces
hanging_face=Int32[2, -1, -1, -1, -1, 0]
hanging_edge=Int32[-1, -1, 0, 4, 4, -1, 0, 4, 3, -1, 4, -1]
cell=7 faces=Int32[74, 81, 82, 83, 47, 77]
lface=74 gface=74
lface=81 gface=81
lface=82 gface=82
lface=83 gface=83
lface=47 gface=47
lface=77 gface=77
cell=7 edges=Int32[50, 51, 78, 89, 36, 53, 13, 84, 79, 85, 80, 86]
cell=7 corners=Int32[41, 58, 42, 59, 23, 87, 25, 91]
cell=7 has hanging faces
hanging_face=Int32[-1, -1, -1, -1, -1, 1]
hanging_edge=Int32[-1, -1, 1, 4, -1, -1, 4, 2, -1, -1, -1, -1]
cell=8 faces=Int32[1, 88, 76, 61, 63, 77]
lface=1 gface=1
lface=88 gface=88
lface=76 gface=76
lface=61 gface=61
lface=63 gface=63
lface=77 gface=77
cell=8 edges=Int32[34, 64, 78, 89, 11, 66, 13, 84, 15, 80, 17, 72]
cell=8 corners=Int32[19, 42, 21, 73, 23, 87, 25, 91]
cell=8 has hanging faces
hanging_face=Int32[3, -1, -1, 2, -1, 2]
hanging_edge=Int32[-1, 4, 4, 2, 4, -1, 1, 4, 4, -1, 1, 4]
cell=9 faces=Int32[88, 90, 83, 61, 69, 77]
lface=88 gface=88
lface=90 gface=90
lface=83 gface=83
lface=61 gface=61
lface=69 gface=69
lface=77 gface=77
cell=9 edges=Int32[51, 64, 78, 89, 66, 71, 13, 84, 80, 86, 17, 72]
cell=9 corners=Int32[42, 59, 21, 73, 23, 87, 25, 91]
cell=9 has hanging faces
hanging_face=Int32[-1, -1, -1, 3, -1, 3]
hanging_edge=Int32[-1, 4, 4, 3, -1, -1, 4, 3, -1, -1, 4, 3]
cell=10 faces=Int32[92, 93, 3, 94, 95, 96]
lface=92 gface=92
lface=93 gface=93
lface=3 gface=3
lface=94 gface=94
lface=95 gface=95
lface=96 gface=96
cell=10 edges=Int32[7, 97, 9, 98, 99, 100, 101, 102, 16, 17, 103, 104]
cell=10 corners=Int32[20, 21, 105, 106, 24, 25, 107, 108]
cell=10 does not have hanging faces
cell=11 faces=Int32[93, 109, 61, 110, 111, 112]
lface=93 gface=93
lface=109 gface=109
lface=61 gface=61
lface=110 gface=110
lface=111 gface=111
lface=112 gface=112
cell=11 edges=Int32[64, 113, 89, 114, 100, 115, 102, 116, 17, 72, 104, 117]
cell=11 corners=Int32[21, 73, 106, 118, 25, 91, 108, 119]
cell=11 does not have hanging faces
cell=12 faces=Int32[120, 121, 122, 123, 5, 124]
lface=120 gface=120
lface=121 gface=121
lface=122 gface=122
lface=123 gface=123
lface=5 gface=5
lface=124 gface=124
cell=12 edges=Int32[8, 9, 125, 126, 12, 13, 127, 128, 129, 130, 131, 132]
cell=12 corners=Int32[22, 23, 24, 25, 133, 134, 135, 136]
cell=12 does not have hanging faces
cell=13 faces=Int32[121, 137, 138, 139, 77, 140]
lface=121 gface=121
lface=137 gface=137
lface=138 gface=138
lface=139 gface=139
lface=77 gface=77
lface=140 gface=140
cell=13 edges=Int32[78, 89, 141, 142, 13, 84, 128, 143, 130, 144, 132, 145]
cell=13 corners=Int32[23, 87, 25, 91, 134, 146, 136, 147]
cell=13 does not have hanging faces
cell=14 faces=Int32[148, 149, 123, 150, 96, 151]
lface=148 gface=148
lface=149 gface=149
lface=123 gface=123
lface=150 gface=150
lface=96 gface=96
lface=151 gface=151
cell=14 edges=Int32[9, 98, 126, 152, 101, 102, 153, 154, 131, 132, 155, 156]
cell=14 corners=Int32[24, 25, 107, 108, 135, 136, 157, 158]
cell=14 does not have hanging faces
cell=15 faces=Int32[149, 159, 139, 160, 112, 161]
lface=149 gface=149
lface=159 gface=159
lface=139 gface=139
lface=160 gface=160
lface=112 gface=112
lface=161 gface=161
cell=15 edges=Int32[89, 114, 142, 162, 102, 116, 154, 163, 132, 145, 156, 164]
cell=15 corners=Int32[25, 91, 108, 119, 136, 147, 158, 165]
cell=15 does not have hanging faces
amartinhuertas commented 1 year ago

@principejavier ... please note:

  1. The following commit on GridapP4est.jl, p4est-migration-exploring-non-conformity branch. https://github.com/gridap/GridapP4est.jl/commit/7d7fc38eca3549fe46466a992a7e8499a8499734
  2. I have updated the issue description (https://github.com/gridap/GridapP4est.jl/issues/21#issue-1333404245) such that that I have added some additional tasks that I believe have to be completed after the work in 1.

I dont have much time the following weeks to continue with this dev (teaching starts). Can you please take the lead? We can have a meeting if you like, I can also help you out, but not too much time to write code.

principejavier commented 1 year ago

After https://github.com/gridap/GridapP4est.jl/commit/e21df63f15b18e65d95141941161929ba23bb457 the code is working in 2D producing a DistributedDiscreteModel as in the uniform case, including geometric IDs. I need to change the focus (to produce some results with GridapMHD.jl) but I will continue with this development as much as I can.

amartinhuertas commented 1 year ago

After https://github.com/gridap/GridapP4est.jl/commit/e21df63f15b18e65d95141941161929ba23bb457 the code is working in 2D producing a DistributedDiscreteModel as in the uniform case, including geometric IDs. I need to change the focus (to produce some results with GridapMHD.jl) but I will continue with this development as much as I can.

FYI ... I could work on this the past couple of days. I have now to leave it here for this week. I moved part of the code to src and implemented the generation of symbolic constraints dependencies (the coefficient values are still missing).

On a separate note, I do believe that the function generate_cell_vertices_and_faces should return dimension-indexed arrays (i.e., 1 for corners, 2 for edges, etc.), instead of separated arrays for vertices, and faces, etc. This would avoid code replication in the generation of symbolic constraint dependencies.

amartinhuertas commented 1 year ago

@principejavier ... FYI, this week, I could work a day on this. I just pushed into the branch. The current code (https://github.com/gridap/GridapP4est.jl/blob/61b08ac74e8e560a762532ef8a1d896a02ca3d70/test/non_conforming_octrees_wip.jl) already automates the generation of constraints and reproduces https://github.com/gridap/GridapP4est.jl/issues/21#issuecomment-1384635611.

Thanks to @JordiManyer that helped us via this Gridap PR to provide some missing functionality needed to build the constraints (https://github.com/gridap/Gridap.jl/pull/886).

Immediate lines of action:

amartinhuertas commented 1 year ago

for the records ... I have already completed the following in 2D:

Immediate lines of action: test with finer meshes/non-oriented meshes. support for order>1 elements (currently only works for order=1 elements) clean/abstract software.

I am going to start next with the 3D case. To this end, I will need at some point an extension of

Thanks to @JordiManyer that helped us via this Gridap PR to provide some missing functionality needed to build the constraints (https://github.com/gridap/Gridap.jl/pull/886).

to the 3D case. No hurries. There is still a lot of work in the geometric/topological part before starting with the construction of the hanging node constraints.

amartinhuertas commented 1 year ago

I am going to start next with the 3D case.

For the records, I have now a preliminary implementation of 3D AMR with forest-of-octrees that works for scalar Lagrangian FEs and arbitrary order. See https://github.com/gridap/GridapP4est.jl/blob/a65eb67e165e1489cef922dafa797bd29d196277/test/NonConformingOctreeDistributedDiscreteModelsTests.jl! Thanks to @JordiManyer that helped us to extending the functionality required to compute the constraints in 3D!

amartinhuertas commented 1 year ago

Closing this issue. At present, the code works in 2D/3D and in parallel with non-conforming meshes. all tasks except facet integration have been completed. See https://github.com/gridap/GridapP4est.jl/issues/35 for a more up-to-date list of pending tasks.