1ded9b81dSJeremy L Thompson // Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC. 2ded9b81dSJeremy L Thompson // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. 3ded9b81dSJeremy L Thompson // All Rights reserved. See files LICENSE and NOTICE for details. 4ded9b81dSJeremy L Thompson // 5ded9b81dSJeremy L Thompson // This file is part of CEED, a collection of benchmarks, miniapps, software 6ded9b81dSJeremy L Thompson // libraries and APIs for efficient high-order finite element and spectral 7ded9b81dSJeremy L Thompson // element discretizations for exascale applications. For more information and 8ded9b81dSJeremy L Thompson // source code availability see http://github.com/ceed. 9ded9b81dSJeremy L Thompson // 10ded9b81dSJeremy L Thompson // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11ded9b81dSJeremy L Thompson // a collaborative effort of two U.S. Department of Energy organizations (Office 12ded9b81dSJeremy L Thompson // of Science and the National Nuclear Security Administration) responsible for 13ded9b81dSJeremy L Thompson // the planning and preparation of a capable exascale ecosystem, including 14ded9b81dSJeremy L Thompson // software, applications, hardware, advanced system engineering and early 15ded9b81dSJeremy L Thompson // testbed platforms, in support of the nation's exascale computing imperative. 16ded9b81dSJeremy L Thompson 17ded9b81dSJeremy L Thompson use libceed::{prelude::*, Ceed}; 18ded9b81dSJeremy L Thompson 19ded9b81dSJeremy L Thompson // ---------------------------------------------------------------------------- 20ded9b81dSJeremy L Thompson // Determine problem size in each dimension from size and dimenison 21ded9b81dSJeremy L Thompson // ---------------------------------------------------------------------------- 22ded9b81dSJeremy L Thompson pub fn cartesian_mesh_size(dim: usize, solution_degree: usize, problem_size: i64) -> [usize; 3] { 23ded9b81dSJeremy L Thompson // Use the approximate formula: 24ded9b81dSJeremy L Thompson // prob_size ~ num_elem * degree^dim 25ded9b81dSJeremy L Thompson let mut num_elem = problem_size / solution_degree.pow(dim as u32) as i64; 26ded9b81dSJeremy L Thompson let mut s = 0; // find s: num_elem / 2 < 2^s <= num_elem 27ded9b81dSJeremy L Thompson while num_elem > 1 { 28ded9b81dSJeremy L Thompson num_elem /= 2; 29ded9b81dSJeremy L Thompson s += 1; 30ded9b81dSJeremy L Thompson } 31ded9b81dSJeremy L Thompson 32ded9b81dSJeremy L Thompson // Size per dimension 33ded9b81dSJeremy L Thompson let mut r = s % dim; 34ded9b81dSJeremy L Thompson let mut num_xyz = [0; 3]; 35ded9b81dSJeremy L Thompson for d in 0..dim { 36ded9b81dSJeremy L Thompson let mut sd = s / dim; 37ded9b81dSJeremy L Thompson if r > 0 { 38ded9b81dSJeremy L Thompson sd += 1; 39ded9b81dSJeremy L Thompson r -= 1; 40ded9b81dSJeremy L Thompson } 41ded9b81dSJeremy L Thompson num_xyz[d] = 1 << sd; 42ded9b81dSJeremy L Thompson } 43ded9b81dSJeremy L Thompson num_xyz 44ded9b81dSJeremy L Thompson } 45ded9b81dSJeremy L Thompson 46ded9b81dSJeremy L Thompson // ---------------------------------------------------------------------------- 47ded9b81dSJeremy L Thompson // Build element restriction objects for the mesh 48ded9b81dSJeremy L Thompson // ---------------------------------------------------------------------------- 49ded9b81dSJeremy L Thompson pub fn build_cartesian_restriction( 50ded9b81dSJeremy L Thompson ceed: &Ceed, 51ded9b81dSJeremy L Thompson dim: usize, 52ded9b81dSJeremy L Thompson num_xyz: [usize; 3], 53ded9b81dSJeremy L Thompson degree: usize, 54ded9b81dSJeremy L Thompson num_comp: usize, 55ded9b81dSJeremy L Thompson num_qpts: usize, 5689d15d5fSJeremy L Thompson ) -> libceed::Result<(ElemRestriction, ElemRestriction)> { 57ded9b81dSJeremy L Thompson let p = degree + 1; 58ded9b81dSJeremy L Thompson let num_nodes = p.pow(dim as u32); // number of nodes per element 59ded9b81dSJeremy L Thompson let elem_qpts = num_qpts.pow(dim as u32); // number of quadrature pts per element 60ded9b81dSJeremy L Thompson 61ded9b81dSJeremy L Thompson // Problem dimensions 62ded9b81dSJeremy L Thompson let mut num_d = [0; 3]; 63ded9b81dSJeremy L Thompson let mut num_elem = 1; 64ded9b81dSJeremy L Thompson let mut scalar_size = 1; 65ded9b81dSJeremy L Thompson for d in 0..dim { 66ded9b81dSJeremy L Thompson num_elem *= num_xyz[d]; 67ded9b81dSJeremy L Thompson num_d[d] = num_xyz[d] * (p - 1) + 1; 68ded9b81dSJeremy L Thompson scalar_size *= num_d[d]; 69ded9b81dSJeremy L Thompson } 70ded9b81dSJeremy L Thompson 71ded9b81dSJeremy L Thompson // elem: 0 1 n-1 72ded9b81dSJeremy L Thompson // |---*-...-*---|---*-...-*---|- ... -|--...--| 73ded9b81dSJeremy L Thompson // nodes: 0 1 p-1 p p+1 2*p n*p 74ded9b81dSJeremy L Thompson let mut elem_nodes = vec![0; num_elem * num_nodes]; 75ded9b81dSJeremy L Thompson for e in 0..num_elem { 76ded9b81dSJeremy L Thompson let mut e_xyz = [1; 3]; 77ded9b81dSJeremy L Thompson let mut re = e; 78ded9b81dSJeremy L Thompson for d in 0..dim { 79ded9b81dSJeremy L Thompson e_xyz[d] = re % num_xyz[d]; 80ded9b81dSJeremy L Thompson re /= num_xyz[d]; 81ded9b81dSJeremy L Thompson } 82ded9b81dSJeremy L Thompson let loc_offset = e * num_nodes; 83ded9b81dSJeremy L Thompson for loc_nodes in 0..num_nodes { 84ded9b81dSJeremy L Thompson let mut global_nodes = 0; 85ded9b81dSJeremy L Thompson let mut global_nodes_stride = 1; 86ded9b81dSJeremy L Thompson let mut r_nodes = loc_nodes; 87ded9b81dSJeremy L Thompson for d in 0..dim { 88ded9b81dSJeremy L Thompson global_nodes += (e_xyz[d] * (p - 1) + r_nodes % p) * global_nodes_stride; 89ded9b81dSJeremy L Thompson global_nodes_stride *= num_d[d]; 90ded9b81dSJeremy L Thompson r_nodes /= p; 91ded9b81dSJeremy L Thompson } 92ded9b81dSJeremy L Thompson elem_nodes[loc_offset + loc_nodes] = global_nodes as i32; 93ded9b81dSJeremy L Thompson } 94ded9b81dSJeremy L Thompson } 95ded9b81dSJeremy L Thompson 96ded9b81dSJeremy L Thompson // Mesh/solution data restriction 97ded9b81dSJeremy L Thompson let restr = ceed.elem_restriction( 98ded9b81dSJeremy L Thompson num_elem, 99ded9b81dSJeremy L Thompson num_nodes, 100ded9b81dSJeremy L Thompson num_comp, 101ded9b81dSJeremy L Thompson scalar_size, 102ded9b81dSJeremy L Thompson num_comp * scalar_size, 103ded9b81dSJeremy L Thompson MemType::Host, 104ded9b81dSJeremy L Thompson &elem_nodes, 105e15f9bd0SJeremy L Thompson )?; 106ded9b81dSJeremy L Thompson 107ded9b81dSJeremy L Thompson // Quadratue data restriction 108ded9b81dSJeremy L Thompson let restr_qdata = ceed.strided_elem_restriction( 109ded9b81dSJeremy L Thompson num_elem, 110ded9b81dSJeremy L Thompson elem_qpts, 111ded9b81dSJeremy L Thompson num_comp, 112ded9b81dSJeremy L Thompson num_comp * elem_qpts * num_elem, 113ded9b81dSJeremy L Thompson CEED_STRIDES_BACKEND, 114e15f9bd0SJeremy L Thompson )?; 115e15f9bd0SJeremy L Thompson Ok((restr, restr_qdata)) 116ded9b81dSJeremy L Thompson } 117ded9b81dSJeremy L Thompson 118ded9b81dSJeremy L Thompson // ---------------------------------------------------------------------------- 119ded9b81dSJeremy L Thompson // Set mesh coordinates 120ded9b81dSJeremy L Thompson // ---------------------------------------------------------------------------- 121ded9b81dSJeremy L Thompson pub fn cartesian_mesh_coords( 122ded9b81dSJeremy L Thompson ceed: &Ceed, 123ded9b81dSJeremy L Thompson dim: usize, 124ded9b81dSJeremy L Thompson num_xyz: [usize; 3], 125ded9b81dSJeremy L Thompson mesh_degree: usize, 126ded9b81dSJeremy L Thompson mesh_size: usize, 12789d15d5fSJeremy L Thompson ) -> libceed::Result<Vector> { 128ded9b81dSJeremy L Thompson let p = mesh_degree + 1; 129ded9b81dSJeremy L Thompson let mut num_d = [0; 3]; 130ded9b81dSJeremy L Thompson let mut scalar_size = 1; 131ded9b81dSJeremy L Thompson for d in 0..dim { 132ded9b81dSJeremy L Thompson num_d[d] = num_xyz[d] * (p - 1) + 1; 133ded9b81dSJeremy L Thompson scalar_size *= num_d[d]; 134ded9b81dSJeremy L Thompson } 135ded9b81dSJeremy L Thompson 136ded9b81dSJeremy L Thompson // Lobatto points 137*51d03428SJeremy L Thompson let lobatto_basis = ceed.basis_tensor_H1_Lagrange(1, 1, 2, p, QuadMode::GaussLobatto)?; 138e15f9bd0SJeremy L Thompson let nodes_corners = ceed.vector_from_slice(&[0.0, 1.0])?; 139e15f9bd0SJeremy L Thompson let mut nodes_full = ceed.vector(p)?; 140ded9b81dSJeremy L Thompson lobatto_basis.apply( 141ded9b81dSJeremy L Thompson 1, 142ded9b81dSJeremy L Thompson TransposeMode::NoTranspose, 143ded9b81dSJeremy L Thompson EvalMode::Interp, 144ded9b81dSJeremy L Thompson &nodes_corners, 145ded9b81dSJeremy L Thompson &mut nodes_full, 146e15f9bd0SJeremy L Thompson )?; 147ded9b81dSJeremy L Thompson 148ded9b81dSJeremy L Thompson // Coordinates for mesh 149e15f9bd0SJeremy L Thompson let mut mesh_coords = ceed.vector(mesh_size)?; 150ded9b81dSJeremy L Thompson { 151e78171edSJeremy L Thompson let mut coords = mesh_coords.view_mut()?; 152e78171edSJeremy L Thompson let nodes = nodes_full.view()?; 153ded9b81dSJeremy L Thompson for gs_nodes in 0..scalar_size { 154ded9b81dSJeremy L Thompson let mut r_nodes = gs_nodes; 155ded9b81dSJeremy L Thompson for d in 0..dim { 156ded9b81dSJeremy L Thompson let d_1d = r_nodes % num_d[d]; 157ded9b81dSJeremy L Thompson coords[gs_nodes + scalar_size * d] = 15880a9ef05SNatalie Beams ((d_1d / (p - 1)) as Scalar + nodes[d_1d % (p - 1)]) / num_xyz[d] as Scalar; 159ded9b81dSJeremy L Thompson r_nodes /= num_d[d]; 160ded9b81dSJeremy L Thompson } 161ded9b81dSJeremy L Thompson } 162ded9b81dSJeremy L Thompson } 163e15f9bd0SJeremy L Thompson Ok(mesh_coords) 164ded9b81dSJeremy L Thompson } 165ded9b81dSJeremy L Thompson 166ded9b81dSJeremy L Thompson // ---------------------------------------------------------------------------- 167