16cf3b68dSWill Paznerfunction get_cartesian_mesh_size(dim, order, prob_size) 26cf3b68dSWill Pazner dims = zeros(CeedInt, dim) 36cf3b68dSWill Pazner # Use the approximate formula: 46cf3b68dSWill Pazner # prob_size ~ num_elem * order^dim 56cf3b68dSWill Pazner num_elem = div(prob_size, order^dim) 66cf3b68dSWill Pazner s = 0 # find s: num_elem/2 < 2^s <= num_elem 76cf3b68dSWill Pazner while num_elem > 1 86cf3b68dSWill Pazner num_elem = div(num_elem, 2) 96cf3b68dSWill Pazner s += 1 106cf3b68dSWill Pazner end 116cf3b68dSWill Pazner r = s%dim 126cf3b68dSWill Pazner for d = 1:dim 136cf3b68dSWill Pazner sd = div(s, dim) 146cf3b68dSWill Pazner if r > 0 156cf3b68dSWill Pazner sd += 1 166cf3b68dSWill Pazner r -= 1 176cf3b68dSWill Pazner end 186cf3b68dSWill Pazner dims[d] = 2^sd 196cf3b68dSWill Pazner end 206cf3b68dSWill Pazner dims 216cf3b68dSWill Paznerend 226cf3b68dSWill Pazner 236cf3b68dSWill Paznerstruct FormRestrictionMode{T} end 24*edb2538eSJeremy L Thompsonconst RestrictionOnly = FormRestrictionMode{:rstr}() 25*edb2538eSJeremy L Thompsonconst StridedOnly = FormRestrictionMode{:rstr_i}() 266cf3b68dSWill Paznerconst RestrictionAndStrided = FormRestrictionMode{:both}() 276cf3b68dSWill Pazner 286cf3b68dSWill Paznerfunction build_cartesian_restriction( 296cf3b68dSWill Pazner c::Ceed, 306cf3b68dSWill Pazner dim, 316cf3b68dSWill Pazner nxyz, 326cf3b68dSWill Pazner order, 336cf3b68dSWill Pazner ncomp, 346cf3b68dSWill Pazner num_qpts; 356cf3b68dSWill Pazner mode::Mode=RestrictionOnly, 366cf3b68dSWill Pazner) where {Mode} 376cf3b68dSWill Pazner p::CeedInt = order 386cf3b68dSWill Pazner pp1::CeedInt = p + 1 396cf3b68dSWill Pazner nnodes::CeedInt = pp1^dim # number of scal. nodes per element 406cf3b68dSWill Pazner elem_qpts::CeedInt = num_qpts^dim # number of qpts per element 416cf3b68dSWill Pazner 426cf3b68dSWill Pazner nd = CeedInt.(p*nxyz .+ 1) 436cf3b68dSWill Pazner num_elem::CeedInt = prod(nxyz) 446cf3b68dSWill Pazner scalar_size::CeedInt = prod(nd) 456cf3b68dSWill Pazner size::CeedInt = scalar_size*ncomp 466cf3b68dSWill Pazner 47*edb2538eSJeremy L Thompson form_rstr = (Mode() != StridedOnly) 486cf3b68dSWill Pazner form_strided = (Mode() != RestrictionOnly) 496cf3b68dSWill Pazner 506cf3b68dSWill Pazner # elem: 0 1 n-1 516cf3b68dSWill Pazner # |---*-...-*---|---*-...-*---|- ... -|--...--| 526cf3b68dSWill Pazner # nnodes: 0 1 p-1 p p+1 2*p n*p 536cf3b68dSWill Pazner 54*edb2538eSJeremy L Thompson if form_rstr 556cf3b68dSWill Pazner el_nodes = zeros(CeedInt, num_elem*nnodes) 566cf3b68dSWill Pazner exyz = zeros(CeedInt, dim) 576cf3b68dSWill Pazner @inbounds @simd for e = 0:(num_elem-1) 586cf3b68dSWill Pazner re::CeedInt = e 596cf3b68dSWill Pazner for d::CeedInt = 1:dim 606cf3b68dSWill Pazner exyz[d] = re%nxyz[d] 616cf3b68dSWill Pazner re ÷= nxyz[d] 626cf3b68dSWill Pazner end 636cf3b68dSWill Pazner for lnodes::CeedInt = 0:(nnodes-1) 646cf3b68dSWill Pazner gnodes::CeedInt = 0 656cf3b68dSWill Pazner gnodes_stride::CeedInt = 1 666cf3b68dSWill Pazner rnodes::CeedInt = lnodes 676cf3b68dSWill Pazner for d::CeedInt = 1:dim 686cf3b68dSWill Pazner q = rnodes÷pp1 696cf3b68dSWill Pazner r = rnodes - pp1*q 706cf3b68dSWill Pazner gnodes::CeedInt += (exyz[d]*p + r)*gnodes_stride 716cf3b68dSWill Pazner gnodes_stride::CeedInt *= nd[d] 726cf3b68dSWill Pazner rnodes = q 736cf3b68dSWill Pazner end 746cf3b68dSWill Pazner el_nodes[e*nnodes+lnodes+1] = gnodes 756cf3b68dSWill Pazner end 766cf3b68dSWill Pazner end 776cf3b68dSWill Pazner end 786cf3b68dSWill Pazner 79*edb2538eSJeremy L Thompson rstr = 80*edb2538eSJeremy L Thompson form_rstr ? 816cf3b68dSWill Pazner create_elem_restriction( 826cf3b68dSWill Pazner c, 836cf3b68dSWill Pazner num_elem, 846cf3b68dSWill Pazner nnodes, 856cf3b68dSWill Pazner ncomp, 866cf3b68dSWill Pazner scalar_size, 876cf3b68dSWill Pazner ncomp*scalar_size, 886cf3b68dSWill Pazner el_nodes, 89cdf95791SWill Pazner ) : nothing 90*edb2538eSJeremy L Thompson rstr_i = 916cf3b68dSWill Pazner form_strided ? 926cf3b68dSWill Pazner create_elem_restriction_strided( 936cf3b68dSWill Pazner c, 946cf3b68dSWill Pazner num_elem, 956cf3b68dSWill Pazner elem_qpts, 966cf3b68dSWill Pazner ncomp, 976cf3b68dSWill Pazner ncomp*elem_qpts*num_elem, 986cf3b68dSWill Pazner STRIDES_BACKEND, 99cdf95791SWill Pazner ) : nothing 1006cf3b68dSWill Pazner 101*edb2538eSJeremy L Thompson return size, rstr, rstr_i 1026cf3b68dSWill Paznerend 1036cf3b68dSWill Pazner 1046cf3b68dSWill Paznerfunction set_cartesian_mesh_coords!(dim, nxyz, mesh_order, mesh_coords) 1056cf3b68dSWill Pazner p = mesh_order 1066cf3b68dSWill Pazner nd = p*nxyz .+ 1 1076cf3b68dSWill Pazner num_elem::CeedInt = prod(nxyz) 1086cf3b68dSWill Pazner scalar_size::CeedInt = prod(nd) 1096cf3b68dSWill Pazner 1106cf3b68dSWill Pazner # The H1 basis uses Lobatto quadrature points as nodes. 1116cf3b68dSWill Pazner nodes::Vector{CeedScalar} = lobatto_quadrature(p + 1) # nodes are in [-1,1] 1126cf3b68dSWill Pazner nodes = 0.5 .+ 0.5*nodes 1136cf3b68dSWill Pazner 1146cf3b68dSWill Pazner @witharray coords = mesh_coords begin 1156cf3b68dSWill Pazner @inbounds @simd for gsnodes = 0:scalar_size-1 1166cf3b68dSWill Pazner rnodes = gsnodes 1176cf3b68dSWill Pazner for d = 1:dim 1186cf3b68dSWill Pazner ndd = nd[d] 1196cf3b68dSWill Pazner q = rnodes÷ndd 1206cf3b68dSWill Pazner r = rnodes - ndd*q 1216cf3b68dSWill Pazner 1226cf3b68dSWill Pazner d1d = r 1236cf3b68dSWill Pazner coords[gsnodes+scalar_size*(d-1)+1] = ((d1d÷p) + nodes[d1d%p+1])/nxyz[d] 1246cf3b68dSWill Pazner rnodes = q 1256cf3b68dSWill Pazner end 1266cf3b68dSWill Pazner end 1276cf3b68dSWill Pazner end 1286cf3b68dSWill Paznerend 129