1*9ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
39df49d7eSJed Brown //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
59df49d7eSJed Brown //
63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed
79df49d7eSJed Brown
8a1cbad85SJed Brown // Fenced `rust` code blocks included from README.md are executed as part of doctests.
9a1cbad85SJed Brown #![doc = include_str!("../README.md")]
109df49d7eSJed Brown // -----------------------------------------------------------------------------
119df49d7eSJed Brown // Exceptions
129df49d7eSJed Brown // -----------------------------------------------------------------------------
139df49d7eSJed Brown #![allow(non_snake_case)]
149df49d7eSJed Brown
159df49d7eSJed Brown // -----------------------------------------------------------------------------
169df49d7eSJed Brown // Crate prelude
179df49d7eSJed Brown // -----------------------------------------------------------------------------
189df49d7eSJed Brown use crate::prelude::*;
199df49d7eSJed Brown use std::sync::Once;
209df49d7eSJed Brown
219df49d7eSJed Brown pub mod prelude {
22630ad4c9Sjeremylt pub(crate) use libceed_sys::bind_ceed;
239df49d7eSJed Brown pub(crate) use std::convert::TryFrom;
2408778c6fSJeremy L Thompson pub(crate) use std::ffi::{CStr, CString};
259df49d7eSJed Brown pub(crate) use std::fmt;
261142270cSJeremy L Thompson pub(crate) use std::marker::PhantomData;
279df49d7eSJed Brown }
289df49d7eSJed Brown
299df49d7eSJed Brown // -----------------------------------------------------------------------------
309df49d7eSJed Brown // Modules
319df49d7eSJed Brown // -----------------------------------------------------------------------------
329df49d7eSJed Brown pub mod basis;
339df49d7eSJed Brown pub mod elem_restriction;
349df49d7eSJed Brown pub mod operator;
359df49d7eSJed Brown pub mod qfunction;
369df49d7eSJed Brown pub mod vector;
379df49d7eSJed Brown
389df49d7eSJed Brown // -----------------------------------------------------------------------------
3980a9ef05SNatalie Beams // Typedef for scalar
4080a9ef05SNatalie Beams // -----------------------------------------------------------------------------
4180a9ef05SNatalie Beams pub type Scalar = bind_ceed::CeedScalar;
4280a9ef05SNatalie Beams
4380a9ef05SNatalie Beams // -----------------------------------------------------------------------------
449df49d7eSJed Brown // Constants for library
459df49d7eSJed Brown // -----------------------------------------------------------------------------
46257916f8SJed Brown const MAX_BUFFER_LENGTH: usize = 4096;
479df49d7eSJed Brown pub const MAX_QFUNCTION_FIELDS: usize = 16;
489df49d7eSJed Brown pub const CEED_STRIDES_BACKEND: [i32; 3] = [0; 3];
4980a9ef05SNatalie Beams pub const EPSILON: crate::Scalar = bind_ceed::CEED_EPSILON as crate::Scalar;
509df49d7eSJed Brown
519df49d7eSJed Brown // -----------------------------------------------------------------------------
529df49d7eSJed Brown // Enums for libCEED
539df49d7eSJed Brown // -----------------------------------------------------------------------------
549df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)]
559df49d7eSJed Brown /// Many Ceed interfaces take or return pointers to memory. This enum is used to
569df49d7eSJed Brown /// specify where the memory being provided or requested must reside.
579df49d7eSJed Brown pub enum MemType {
589df49d7eSJed Brown Host = bind_ceed::CeedMemType_CEED_MEM_HOST as isize,
599df49d7eSJed Brown Device = bind_ceed::CeedMemType_CEED_MEM_DEVICE as isize,
609df49d7eSJed Brown }
619df49d7eSJed Brown
629df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)]
639df49d7eSJed Brown // OwnPointer will not be used by user but is included for internal use
649df49d7eSJed Brown #[allow(dead_code)]
659df49d7eSJed Brown /// Conveys ownership status of arrays passed to Ceed interfaces.
669df49d7eSJed Brown pub(crate) enum CopyMode {
679df49d7eSJed Brown CopyValues = bind_ceed::CeedCopyMode_CEED_COPY_VALUES as isize,
689df49d7eSJed Brown UsePointer = bind_ceed::CeedCopyMode_CEED_USE_POINTER as isize,
699df49d7eSJed Brown OwnPointer = bind_ceed::CeedCopyMode_CEED_OWN_POINTER as isize,
709df49d7eSJed Brown }
719df49d7eSJed Brown
729df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)]
739df49d7eSJed Brown /// Denotes type of vector norm to be computed
749df49d7eSJed Brown pub enum NormType {
759df49d7eSJed Brown One = bind_ceed::CeedNormType_CEED_NORM_1 as isize,
769df49d7eSJed Brown Two = bind_ceed::CeedNormType_CEED_NORM_2 as isize,
779df49d7eSJed Brown Max = bind_ceed::CeedNormType_CEED_NORM_MAX as isize,
789df49d7eSJed Brown }
799df49d7eSJed Brown
809df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)]
819df49d7eSJed Brown /// Denotes whether a linear transformation or its transpose should be applied
829df49d7eSJed Brown pub enum TransposeMode {
839df49d7eSJed Brown NoTranspose = bind_ceed::CeedTransposeMode_CEED_NOTRANSPOSE as isize,
849df49d7eSJed Brown Transpose = bind_ceed::CeedTransposeMode_CEED_TRANSPOSE as isize,
859df49d7eSJed Brown }
869df49d7eSJed Brown
879df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)]
889df49d7eSJed Brown /// Type of quadrature; also used for location of nodes
899df49d7eSJed Brown pub enum QuadMode {
909df49d7eSJed Brown Gauss = bind_ceed::CeedQuadMode_CEED_GAUSS as isize,
919df49d7eSJed Brown GaussLobatto = bind_ceed::CeedQuadMode_CEED_GAUSS_LOBATTO as isize,
929df49d7eSJed Brown }
939df49d7eSJed Brown
949df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)]
959df49d7eSJed Brown /// Type of basis shape to create non-tensor H1 element basis
969df49d7eSJed Brown pub enum ElemTopology {
9750c301a5SRezgar Shakeri Line = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_LINE as isize,
9850c301a5SRezgar Shakeri Triangle = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_TRIANGLE as isize,
9950c301a5SRezgar Shakeri Quad = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_QUAD as isize,
10050c301a5SRezgar Shakeri Tet = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_TET as isize,
10150c301a5SRezgar Shakeri Pyramid = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_PYRAMID as isize,
10250c301a5SRezgar Shakeri Prism = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_PRISM as isize,
10350c301a5SRezgar Shakeri Hex = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_HEX as isize,
1049df49d7eSJed Brown }
1059df49d7eSJed Brown
106c68be7a2SJeremy L Thompson #[derive(Clone, Copy, Debug, PartialEq, Eq)]
1079df49d7eSJed Brown /// Basis evaluation mode
1089df49d7eSJed Brown pub enum EvalMode {
1099df49d7eSJed Brown None = bind_ceed::CeedEvalMode_CEED_EVAL_NONE as isize,
1109df49d7eSJed Brown Interp = bind_ceed::CeedEvalMode_CEED_EVAL_INTERP as isize,
1119df49d7eSJed Brown Grad = bind_ceed::CeedEvalMode_CEED_EVAL_GRAD as isize,
1129df49d7eSJed Brown Div = bind_ceed::CeedEvalMode_CEED_EVAL_DIV as isize,
1139df49d7eSJed Brown Curl = bind_ceed::CeedEvalMode_CEED_EVAL_CURL as isize,
1149df49d7eSJed Brown Weight = bind_ceed::CeedEvalMode_CEED_EVAL_WEIGHT as isize,
1159df49d7eSJed Brown }
116c68be7a2SJeremy L Thompson impl EvalMode {
from_u32(value: u32) -> EvalMode117c68be7a2SJeremy L Thompson pub(crate) fn from_u32(value: u32) -> EvalMode {
118c68be7a2SJeremy L Thompson match value {
119c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_NONE => EvalMode::None,
120c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_INTERP => EvalMode::Interp,
121c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_GRAD => EvalMode::Grad,
122c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_DIV => EvalMode::Div,
123c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_CURL => EvalMode::Curl,
124c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_WEIGHT => EvalMode::Weight,
125c68be7a2SJeremy L Thompson _ => panic!("Unknown value: {}", value),
126c68be7a2SJeremy L Thompson }
127c68be7a2SJeremy L Thompson }
128c68be7a2SJeremy L Thompson }
1299df49d7eSJed Brown
1309df49d7eSJed Brown // -----------------------------------------------------------------------------
1319df49d7eSJed Brown // Ceed error
1329df49d7eSJed Brown // -----------------------------------------------------------------------------
1332ba8e59cSJeremy L Thompson pub type Result<T> = std::result::Result<T, Error>;
1349df49d7eSJed Brown
1357ed177dbSJed Brown /// libCEED error messages - returning an Error without painc!ing indicates
1367ed177dbSJed Brown /// the function call failed but the data is not corrupted
1379df49d7eSJed Brown #[derive(Debug)]
1382ba8e59cSJeremy L Thompson pub struct Error {
1399df49d7eSJed Brown pub message: String,
1409df49d7eSJed Brown }
1419df49d7eSJed Brown
1422ba8e59cSJeremy L Thompson impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1439df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1449df49d7eSJed Brown write!(f, "{}", self.message)
1459df49d7eSJed Brown }
1469df49d7eSJed Brown }
1479df49d7eSJed Brown
1489df49d7eSJed Brown // -----------------------------------------------------------------------------
149eb07d68fSJeremy L Thompson // Internal crate contents
150eb07d68fSJeremy L Thompson // -----------------------------------------------------------------------------
151eb07d68fSJeremy L Thompson pub use crate::{
152eb07d68fSJeremy L Thompson basis::{Basis, BasisOpt},
153eb07d68fSJeremy L Thompson elem_restriction::{ElemRestriction, ElemRestrictionOpt},
154eb07d68fSJeremy L Thompson operator::{CompositeOperator, Operator, OperatorField},
155eb07d68fSJeremy L Thompson qfunction::{
156eb07d68fSJeremy L Thompson QFunction, QFunctionByName, QFunctionField, QFunctionInputs, QFunctionOpt, QFunctionOutputs,
157eb07d68fSJeremy L Thompson },
158eb07d68fSJeremy L Thompson vector::{Vector, VectorOpt, VectorSliceWrapper},
159eb07d68fSJeremy L Thompson };
160eb07d68fSJeremy L Thompson
161eb07d68fSJeremy L Thompson // -----------------------------------------------------------------------------
1621142270cSJeremy L Thompson // Internal error checker
1631142270cSJeremy L Thompson // -----------------------------------------------------------------------------
1641142270cSJeremy L Thompson #[doc(hidden)]
check_error<F>(ceed_ptr: F, ierr: i32) -> Result<i32> where F: FnOnce() -> bind_ceed::Ceed,16511544396SJeremy L Thompson pub(crate) fn check_error<F>(ceed_ptr: F, ierr: i32) -> Result<i32>
16611544396SJeremy L Thompson where
16711544396SJeremy L Thompson F: FnOnce() -> bind_ceed::Ceed,
16811544396SJeremy L Thompson {
1691142270cSJeremy L Thompson // Return early if code is clean
1701142270cSJeremy L Thompson if ierr == bind_ceed::CeedErrorType_CEED_ERROR_SUCCESS {
1711142270cSJeremy L Thompson return Ok(ierr);
1721142270cSJeremy L Thompson }
1731142270cSJeremy L Thompson // Retrieve error message
1741142270cSJeremy L Thompson let mut ptr: *const std::os::raw::c_char = std::ptr::null_mut();
1751142270cSJeremy L Thompson let c_str = unsafe {
17611544396SJeremy L Thompson bind_ceed::CeedGetErrorMessage(ceed_ptr(), &mut ptr);
1771142270cSJeremy L Thompson std::ffi::CStr::from_ptr(ptr)
1781142270cSJeremy L Thompson };
1791142270cSJeremy L Thompson let message = c_str.to_string_lossy().to_string();
1801142270cSJeremy L Thompson // Panic if negative code, otherwise return error
1811142270cSJeremy L Thompson if ierr < bind_ceed::CeedErrorType_CEED_ERROR_SUCCESS {
1821142270cSJeremy L Thompson panic!("{}", message);
1831142270cSJeremy L Thompson }
1842ba8e59cSJeremy L Thompson Err(Error { message })
1851142270cSJeremy L Thompson }
1861142270cSJeremy L Thompson
1871142270cSJeremy L Thompson // -----------------------------------------------------------------------------
1889df49d7eSJed Brown // Ceed error handler
1899df49d7eSJed Brown // -----------------------------------------------------------------------------
1902ba8e59cSJeremy L Thompson pub enum ErrorHandler {
1919df49d7eSJed Brown ErrorAbort,
1929df49d7eSJed Brown ErrorExit,
1939df49d7eSJed Brown ErrorReturn,
1949df49d7eSJed Brown ErrorStore,
1959df49d7eSJed Brown }
1969df49d7eSJed Brown
1979df49d7eSJed Brown // -----------------------------------------------------------------------------
1989df49d7eSJed Brown // Ceed context wrapper
1999df49d7eSJed Brown // -----------------------------------------------------------------------------
2009df49d7eSJed Brown /// A Ceed is a library context representing control of a logical hardware
2019df49d7eSJed Brown /// resource.
2029df49d7eSJed Brown #[derive(Debug)]
2039df49d7eSJed Brown pub struct Ceed {
2049df49d7eSJed Brown ptr: bind_ceed::Ceed,
2059df49d7eSJed Brown }
2069df49d7eSJed Brown
2079df49d7eSJed Brown // -----------------------------------------------------------------------------
2089df49d7eSJed Brown // Destructor
2099df49d7eSJed Brown // -----------------------------------------------------------------------------
2109df49d7eSJed Brown impl Drop for Ceed {
drop(&mut self)2119df49d7eSJed Brown fn drop(&mut self) {
2129df49d7eSJed Brown unsafe {
2139df49d7eSJed Brown bind_ceed::CeedDestroy(&mut self.ptr);
2149df49d7eSJed Brown }
2159df49d7eSJed Brown }
2169df49d7eSJed Brown }
2179df49d7eSJed Brown
2189df49d7eSJed Brown // -----------------------------------------------------------------------------
21959189cfaSJeremy L Thompson // Cloning
22059189cfaSJeremy L Thompson // -----------------------------------------------------------------------------
22159189cfaSJeremy L Thompson impl Clone for Ceed {
22259189cfaSJeremy L Thompson /// Perform a shallow clone of a Ceed context
22359189cfaSJeremy L Thompson ///
22459189cfaSJeremy L Thompson /// ```
22559189cfaSJeremy L Thompson /// let ceed = libceed::Ceed::init("/cpu/self/ref/serial");
22659189cfaSJeremy L Thompson /// let ceed_clone = ceed.clone();
22759189cfaSJeremy L Thompson ///
2287ed177dbSJed Brown /// println!(" original:{} \n clone:{}", ceed, ceed_clone);
22959189cfaSJeremy L Thompson /// ```
clone(&self) -> Self23059189cfaSJeremy L Thompson fn clone(&self) -> Self {
23159189cfaSJeremy L Thompson let mut ptr_clone = std::ptr::null_mut();
232656ef1e5SJeremy L Thompson self.check_error(unsafe { bind_ceed::CeedReferenceCopy(self.ptr, &mut ptr_clone) })
233656ef1e5SJeremy L Thompson .expect("failed to clone Ceed");
23459189cfaSJeremy L Thompson Self { ptr: ptr_clone }
23559189cfaSJeremy L Thompson }
23659189cfaSJeremy L Thompson }
23759189cfaSJeremy L Thompson
23859189cfaSJeremy L Thompson // -----------------------------------------------------------------------------
2399df49d7eSJed Brown // Display
2409df49d7eSJed Brown // -----------------------------------------------------------------------------
2419df49d7eSJed Brown impl fmt::Display for Ceed {
2429df49d7eSJed Brown /// View a Ceed
2439df49d7eSJed Brown ///
2449df49d7eSJed Brown /// ```
2459df49d7eSJed Brown /// let ceed = libceed::Ceed::init("/cpu/self/ref/serial");
2469df49d7eSJed Brown /// println!("{}", ceed);
2479df49d7eSJed Brown /// ```
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2489df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2499df49d7eSJed Brown let mut ptr = std::ptr::null_mut();
2509df49d7eSJed Brown let mut sizeloc = crate::MAX_BUFFER_LENGTH;
2519df49d7eSJed Brown let cstring = unsafe {
2529df49d7eSJed Brown let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc);
2539df49d7eSJed Brown bind_ceed::CeedView(self.ptr, file);
2549df49d7eSJed Brown bind_ceed::fclose(file);
2559df49d7eSJed Brown CString::from_raw(ptr)
2569df49d7eSJed Brown };
2579df49d7eSJed Brown cstring.to_string_lossy().fmt(f)
2589df49d7eSJed Brown }
2599df49d7eSJed Brown }
2609df49d7eSJed Brown
2619df49d7eSJed Brown static REGISTER: Once = Once::new();
2629df49d7eSJed Brown
2639df49d7eSJed Brown // -----------------------------------------------------------------------------
2649df49d7eSJed Brown // Object constructors
2659df49d7eSJed Brown // -----------------------------------------------------------------------------
2669df49d7eSJed Brown impl Ceed {
2677ed177dbSJed Brown #[cfg_attr(feature = "katexit", katexit::katexit)]
2689df49d7eSJed Brown /// Returns a Ceed context initialized with the specified resource
2699df49d7eSJed Brown ///
2709df49d7eSJed Brown /// # arguments
2719df49d7eSJed Brown ///
2729df49d7eSJed Brown /// * `resource` - Resource to use, e.g., "/cpu/self"
2739df49d7eSJed Brown ///
2749df49d7eSJed Brown /// ```
2759df49d7eSJed Brown /// let ceed = libceed::Ceed::init("/cpu/self/ref/serial");
2769df49d7eSJed Brown /// ```
init(resource: &str) -> Self2779df49d7eSJed Brown pub fn init(resource: &str) -> Self {
2782ba8e59cSJeremy L Thompson Ceed::init_with_error_handler(resource, ErrorHandler::ErrorStore)
2799df49d7eSJed Brown }
2809df49d7eSJed Brown
2819df49d7eSJed Brown /// Returns a Ceed context initialized with the specified resource
2829df49d7eSJed Brown ///
2839df49d7eSJed Brown /// # arguments
2849df49d7eSJed Brown ///
2859df49d7eSJed Brown /// * `resource` - Resource to use, e.g., "/cpu/self"
2869df49d7eSJed Brown ///
2879df49d7eSJed Brown /// ```
2889df49d7eSJed Brown /// let ceed = libceed::Ceed::init_with_error_handler(
2899df49d7eSJed Brown /// "/cpu/self/ref/serial",
2902ba8e59cSJeremy L Thompson /// libceed::ErrorHandler::ErrorAbort,
2919df49d7eSJed Brown /// );
2929df49d7eSJed Brown /// ```
init_with_error_handler(resource: &str, handler: ErrorHandler) -> Self2932ba8e59cSJeremy L Thompson pub fn init_with_error_handler(resource: &str, handler: ErrorHandler) -> Self {
2949df49d7eSJed Brown REGISTER.call_once(|| unsafe {
2959df49d7eSJed Brown bind_ceed::CeedRegisterAll();
2969df49d7eSJed Brown bind_ceed::CeedQFunctionRegisterAll();
2979df49d7eSJed Brown });
2989df49d7eSJed Brown
2999df49d7eSJed Brown // Convert to C string
3009df49d7eSJed Brown let c_resource = CString::new(resource).expect("CString::new failed");
3019df49d7eSJed Brown
3029df49d7eSJed Brown // Get error handler pointer
3039df49d7eSJed Brown let eh = match handler {
3042ba8e59cSJeremy L Thompson ErrorHandler::ErrorAbort => bind_ceed::CeedErrorAbort,
3052ba8e59cSJeremy L Thompson ErrorHandler::ErrorExit => bind_ceed::CeedErrorExit,
3062ba8e59cSJeremy L Thompson ErrorHandler::ErrorReturn => bind_ceed::CeedErrorReturn,
3072ba8e59cSJeremy L Thompson ErrorHandler::ErrorStore => bind_ceed::CeedErrorStore,
3089df49d7eSJed Brown };
3099df49d7eSJed Brown
3109df49d7eSJed Brown // Call to libCEED
3119df49d7eSJed Brown let mut ptr = std::ptr::null_mut();
312bf55b007SJeremy L Thompson let mut ierr = unsafe { bind_ceed::CeedInit(c_resource.as_ptr(), &mut ptr) };
3139df49d7eSJed Brown if ierr != 0 {
3149df49d7eSJed Brown panic!("Error initializing backend resource: {}", resource)
3159df49d7eSJed Brown }
3169df49d7eSJed Brown ierr = unsafe { bind_ceed::CeedSetErrorHandler(ptr, Some(eh)) };
3179df49d7eSJed Brown let ceed = Ceed { ptr };
3189df49d7eSJed Brown ceed.check_error(ierr).unwrap();
3199df49d7eSJed Brown ceed
3209df49d7eSJed Brown }
3219df49d7eSJed Brown
3229df49d7eSJed Brown /// Default initializer for testing
3239df49d7eSJed Brown #[doc(hidden)]
default_init() -> Self3249df49d7eSJed Brown pub fn default_init() -> Self {
3259df49d7eSJed Brown // Convert to C string
3269df49d7eSJed Brown let resource = "/cpu/self/ref/serial";
3279df49d7eSJed Brown crate::Ceed::init(resource)
3289df49d7eSJed Brown }
3299df49d7eSJed Brown
3309df49d7eSJed Brown /// Internal error checker
3319df49d7eSJed Brown #[doc(hidden)]
check_error(&self, ierr: i32) -> Result<i32>3329df49d7eSJed Brown fn check_error(&self, ierr: i32) -> Result<i32> {
3339df49d7eSJed Brown // Return early if code is clean
3349df49d7eSJed Brown if ierr == bind_ceed::CeedErrorType_CEED_ERROR_SUCCESS {
3359df49d7eSJed Brown return Ok(ierr);
3369df49d7eSJed Brown }
3379df49d7eSJed Brown // Retrieve error message
3389df49d7eSJed Brown let mut ptr: *const std::os::raw::c_char = std::ptr::null_mut();
3399df49d7eSJed Brown let c_str = unsafe {
3409df49d7eSJed Brown bind_ceed::CeedGetErrorMessage(self.ptr, &mut ptr);
3419df49d7eSJed Brown std::ffi::CStr::from_ptr(ptr)
3429df49d7eSJed Brown };
3439df49d7eSJed Brown let message = c_str.to_string_lossy().to_string();
3449df49d7eSJed Brown // Panic if negative code, otherwise return error
3459df49d7eSJed Brown if ierr < bind_ceed::CeedErrorType_CEED_ERROR_SUCCESS {
3469df49d7eSJed Brown panic!("{}", message);
3479df49d7eSJed Brown }
3482ba8e59cSJeremy L Thompson Err(Error { message })
3499df49d7eSJed Brown }
3509df49d7eSJed Brown
3519df49d7eSJed Brown /// Returns full resource name for a Ceed context
3529df49d7eSJed Brown ///
3539df49d7eSJed Brown /// ```
3549df49d7eSJed Brown /// let ceed = libceed::Ceed::init("/cpu/self/ref/serial");
3559df49d7eSJed Brown /// let resource = ceed.resource();
3569df49d7eSJed Brown ///
3579df49d7eSJed Brown /// assert_eq!(resource, "/cpu/self/ref/serial".to_string())
3589df49d7eSJed Brown /// ```
resource(&self) -> String3599df49d7eSJed Brown pub fn resource(&self) -> String {
3609df49d7eSJed Brown let mut ptr: *const std::os::raw::c_char = std::ptr::null_mut();
3619df49d7eSJed Brown let c_str = unsafe {
3629df49d7eSJed Brown bind_ceed::CeedGetResource(self.ptr, &mut ptr);
3639df49d7eSJed Brown std::ffi::CStr::from_ptr(ptr)
3649df49d7eSJed Brown };
3659df49d7eSJed Brown c_str.to_string_lossy().to_string()
3669df49d7eSJed Brown }
3679df49d7eSJed Brown
3687ed177dbSJed Brown /// Returns a Vector of the specified length (does not allocate memory)
3699df49d7eSJed Brown ///
3709df49d7eSJed Brown /// # arguments
3719df49d7eSJed Brown ///
3729df49d7eSJed Brown /// * `n` - Length of vector
3739df49d7eSJed Brown ///
3749df49d7eSJed Brown /// ```
3759df49d7eSJed Brown /// # use libceed::prelude::*;
3764d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
3779df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
378c68be7a2SJeremy L Thompson /// let vec = ceed.vector(10)?;
379c68be7a2SJeremy L Thompson /// # Ok(())
380c68be7a2SJeremy L Thompson /// # }
3819df49d7eSJed Brown /// ```
vector<'a>(&self, n: usize) -> Result<Vector<'a>>382594ef120SJeremy L Thompson pub fn vector<'a>(&self, n: usize) -> Result<Vector<'a>> {
3839df49d7eSJed Brown Vector::create(self, n)
3849df49d7eSJed Brown }
3859df49d7eSJed Brown
3869df49d7eSJed Brown /// Create a Vector initialized with the data (copied) from a slice
3879df49d7eSJed Brown ///
3889df49d7eSJed Brown /// # arguments
3899df49d7eSJed Brown ///
3909df49d7eSJed Brown /// * `slice` - Slice containing data
3919df49d7eSJed Brown ///
3929df49d7eSJed Brown /// ```
3939df49d7eSJed Brown /// # use libceed::prelude::*;
3944d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
3959df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
396c68be7a2SJeremy L Thompson /// let vec = ceed.vector_from_slice(&[1., 2., 3.])?;
3979df49d7eSJed Brown /// assert_eq!(vec.length(), 3);
398c68be7a2SJeremy L Thompson /// # Ok(())
399c68be7a2SJeremy L Thompson /// # }
4009df49d7eSJed Brown /// ```
vector_from_slice<'a>(&self, slice: &[crate::Scalar]) -> Result<Vector<'a>>401594ef120SJeremy L Thompson pub fn vector_from_slice<'a>(&self, slice: &[crate::Scalar]) -> Result<Vector<'a>> {
4029df49d7eSJed Brown Vector::from_slice(self, slice)
4039df49d7eSJed Brown }
4049df49d7eSJed Brown
4057ed177dbSJed Brown /// Returns an ElemRestriction, $\mathcal{E}$, which extracts the degrees of
4067ed177dbSJed Brown /// freedom for each element from the local vector into the element vector
4077ed177dbSJed Brown /// or assembles contributions from each element in the element vector to
4087ed177dbSJed Brown /// the local vector
4099df49d7eSJed Brown ///
4109df49d7eSJed Brown /// # arguments
4119df49d7eSJed Brown ///
4129df49d7eSJed Brown /// * `nelem` - Number of elements described in the offsets array
4139df49d7eSJed Brown /// * `elemsize` - Size (number of "nodes") per element
4149df49d7eSJed Brown /// * `ncomp` - Number of field components per interpolation node (1
4159df49d7eSJed Brown /// for scalar fields)
4169df49d7eSJed Brown /// * `compstride` - Stride between components for the same Lvector "node".
4179df49d7eSJed Brown /// Data for node `i`, component `j`, element `k` can be
4189df49d7eSJed Brown /// found in the Lvector at index
4199df49d7eSJed Brown /// `offsets[i + k*elemsize] + j*compstride`.
4209df49d7eSJed Brown /// * `lsize` - The size of the Lvector. This vector may be larger
4219df49d7eSJed Brown /// than the elements and fields given by this
4229df49d7eSJed Brown /// restriction.
4239df49d7eSJed Brown /// * `mtype` - Memory type of the offsets array, see CeedMemType
4249df49d7eSJed Brown /// * `offsets` - Array of shape `[nelem, elemsize]`. Row `i` holds the
4259df49d7eSJed Brown /// ordered list of the offsets (into the input CeedVector)
4269df49d7eSJed Brown /// for the unknowns corresponding to element `i`, where
4279df49d7eSJed Brown /// `0 <= i < nelem`. All offsets must be in the range
4289df49d7eSJed Brown /// `[0, lsize - 1]`.
4299df49d7eSJed Brown ///
4309df49d7eSJed Brown /// ```
431eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType};
4324d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
4339df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
4349df49d7eSJed Brown /// let nelem = 3;
4359df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
4369df49d7eSJed Brown /// for i in 0..nelem {
4379df49d7eSJed Brown /// ind[2 * i + 0] = i as i32;
4389df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32;
4399df49d7eSJed Brown /// }
440c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
441c68be7a2SJeremy L Thompson /// # Ok(())
442c68be7a2SJeremy L Thompson /// # }
4439df49d7eSJed Brown /// ```
44478c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)]
elem_restriction<'a>( &self, nelem: usize, elemsize: usize, ncomp: usize, compstride: usize, lsize: usize, mtype: MemType, offsets: &[i32], ) -> Result<ElemRestriction<'a>>445594ef120SJeremy L Thompson pub fn elem_restriction<'a>(
4469df49d7eSJed Brown &self,
4479df49d7eSJed Brown nelem: usize,
4489df49d7eSJed Brown elemsize: usize,
4499df49d7eSJed Brown ncomp: usize,
4509df49d7eSJed Brown compstride: usize,
4519df49d7eSJed Brown lsize: usize,
4529df49d7eSJed Brown mtype: MemType,
4539df49d7eSJed Brown offsets: &[i32],
454594ef120SJeremy L Thompson ) -> Result<ElemRestriction<'a>> {
4559df49d7eSJed Brown ElemRestriction::create(
4569df49d7eSJed Brown self, nelem, elemsize, ncomp, compstride, lsize, mtype, offsets,
457709403c1SSebastian Grimberg )
458709403c1SSebastian Grimberg }
459709403c1SSebastian Grimberg
460709403c1SSebastian Grimberg /// Returns an oriented ElemRestriction, $\mathcal{E}$, which extracts the
461709403c1SSebastian Grimberg /// degrees of freedom for each element from the local vector into the
462709403c1SSebastian Grimberg /// element vector or assembles contributions from each element in the
463709403c1SSebastian Grimberg /// element vector to the local vector
464709403c1SSebastian Grimberg ///
465709403c1SSebastian Grimberg /// # arguments
466709403c1SSebastian Grimberg ///
467709403c1SSebastian Grimberg /// * `nelem` - Number of elements described in the offsets array
468709403c1SSebastian Grimberg /// * `elemsize` - Size (number of "nodes") per element
469709403c1SSebastian Grimberg /// * `ncomp` - Number of field components per interpolation node (1
470709403c1SSebastian Grimberg /// for scalar fields)
471709403c1SSebastian Grimberg /// * `compstride` - Stride between components for the same Lvector "node".
472709403c1SSebastian Grimberg /// Data for node `i`, component `j`, element `k` can be
473709403c1SSebastian Grimberg /// found in the Lvector at index
474709403c1SSebastian Grimberg /// `offsets[i + k*elemsize] + j*compstride`.
475709403c1SSebastian Grimberg /// * `lsize` - The size of the Lvector. This vector may be larger
476709403c1SSebastian Grimberg /// than the elements and fields given by this
477709403c1SSebastian Grimberg /// restriction.
478709403c1SSebastian Grimberg /// * `mtype` - Memory type of the offsets array, see CeedMemType
479709403c1SSebastian Grimberg /// * `offsets` - Array of shape `[nelem, elemsize]`. Row `i` holds the
480709403c1SSebastian Grimberg /// ordered list of the offsets (into the input CeedVector)
481709403c1SSebastian Grimberg /// for the unknowns corresponding to element `i`, where
482709403c1SSebastian Grimberg /// `0 <= i < nelem`. All offsets must be in the range
483709403c1SSebastian Grimberg /// `[0, lsize - 1]`.
484709403c1SSebastian Grimberg /// * `orients` - Array of shape `[nelem, elemsize]`. Row `i` holds the
485709403c1SSebastian Grimberg /// ordered list of the orientations for the unknowns
486709403c1SSebastian Grimberg /// corresponding to element `i`, with bool `false` used
487709403c1SSebastian Grimberg /// for positively oriented and `true` to flip the
488709403c1SSebastian Grimberg /// orientation.
489709403c1SSebastian Grimberg ///
490709403c1SSebastian Grimberg /// ```
491eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType};
492709403c1SSebastian Grimberg /// # fn main() -> libceed::Result<()> {
493709403c1SSebastian Grimberg /// # let ceed = libceed::Ceed::default_init();
494709403c1SSebastian Grimberg /// let nelem = 3;
495709403c1SSebastian Grimberg /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
496709403c1SSebastian Grimberg /// let mut orients: Vec<bool> = vec![false; 2 * nelem];
497709403c1SSebastian Grimberg /// for i in 0..nelem {
498709403c1SSebastian Grimberg /// ind[2 * i + 0] = i as i32;
499709403c1SSebastian Grimberg /// ind[2 * i + 1] = (i + 1) as i32;
500709403c1SSebastian Grimberg /// orients[2 * i + 0] = (i % 2) > 0; // flip the dofs on element 1, 3, ...
501709403c1SSebastian Grimberg /// orients[2 * i + 1] = (i % 2) > 0;
502709403c1SSebastian Grimberg /// }
503709403c1SSebastian Grimberg /// let r =
504709403c1SSebastian Grimberg /// ceed.oriented_elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind, &orients)?;
505709403c1SSebastian Grimberg /// # Ok(())
506709403c1SSebastian Grimberg /// # }
507709403c1SSebastian Grimberg /// ```
50878c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)]
oriented_elem_restriction<'a>( &self, nelem: usize, elemsize: usize, ncomp: usize, compstride: usize, lsize: usize, mtype: MemType, offsets: &[i32], orients: &[bool], ) -> Result<ElemRestriction<'a>>509709403c1SSebastian Grimberg pub fn oriented_elem_restriction<'a>(
510709403c1SSebastian Grimberg &self,
511709403c1SSebastian Grimberg nelem: usize,
512709403c1SSebastian Grimberg elemsize: usize,
513709403c1SSebastian Grimberg ncomp: usize,
514709403c1SSebastian Grimberg compstride: usize,
515709403c1SSebastian Grimberg lsize: usize,
516709403c1SSebastian Grimberg mtype: MemType,
517709403c1SSebastian Grimberg offsets: &[i32],
518709403c1SSebastian Grimberg orients: &[bool],
519709403c1SSebastian Grimberg ) -> Result<ElemRestriction<'a>> {
520709403c1SSebastian Grimberg ElemRestriction::create_oriented(
521709403c1SSebastian Grimberg self, nelem, elemsize, ncomp, compstride, lsize, mtype, offsets, orients,
522709403c1SSebastian Grimberg )
523709403c1SSebastian Grimberg }
524709403c1SSebastian Grimberg
525709403c1SSebastian Grimberg /// Returns a curl-oriented ElemRestriction, $\mathcal{E}$, which extracts
526709403c1SSebastian Grimberg /// the degrees of freedom for each element from the local vector into
527709403c1SSebastian Grimberg /// the element vector or assembles contributions from each element in
528709403c1SSebastian Grimberg /// the element vector to the local vector
529709403c1SSebastian Grimberg ///
530709403c1SSebastian Grimberg /// # arguments
531709403c1SSebastian Grimberg ///
532709403c1SSebastian Grimberg /// * `nelem` - Number of elements described in the offsets array
533709403c1SSebastian Grimberg /// * `elemsize` - Size (number of "nodes") per element
534709403c1SSebastian Grimberg /// * `ncomp` - Number of field components per interpolation node (1
535709403c1SSebastian Grimberg /// for scalar fields)
536709403c1SSebastian Grimberg /// * `compstride` - Stride between components for the same Lvector "node".
537709403c1SSebastian Grimberg /// Data for node `i`, component `j`, element `k` can be
538709403c1SSebastian Grimberg /// found in the Lvector at index
539709403c1SSebastian Grimberg /// `offsets[i + k*elemsize] + j*compstride`.
540709403c1SSebastian Grimberg /// * `lsize` - The size of the Lvector. This vector may be larger
541709403c1SSebastian Grimberg /// than the elements and fields given by this
542709403c1SSebastian Grimberg /// restriction.
543709403c1SSebastian Grimberg /// * `mtype` - Memory type of the offsets array, see CeedMemType
544709403c1SSebastian Grimberg /// * `offsets` - Array of shape `[nelem, elemsize]`. Row `i` holds the
545709403c1SSebastian Grimberg /// ordered list of the offsets (into the input CeedVector)
546709403c1SSebastian Grimberg /// for the unknowns corresponding to element `i`, where
547709403c1SSebastian Grimberg /// `0 <= i < nelem`. All offsets must be in the range
548709403c1SSebastian Grimberg /// `[0, lsize - 1]`.
549709403c1SSebastian Grimberg /// * `curlorients` - Array of shape `[nelem, 3 * elemsize]`. Row `i` holds
550709403c1SSebastian Grimberg /// a row-major tridiagonal matrix (`curlorients[i, 0] =
551709403c1SSebastian Grimberg /// curlorients[i, 3 * elemsize - 1] = 0`, where
552709403c1SSebastian Grimberg /// `0 <= i < nelem`) which is applied to the element
553709403c1SSebastian Grimberg /// unknowns upon restriction.
554709403c1SSebastian Grimberg ///
555709403c1SSebastian Grimberg /// ```
556eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType};
557709403c1SSebastian Grimberg /// # fn main() -> libceed::Result<()> {
558709403c1SSebastian Grimberg /// # let ceed = libceed::Ceed::default_init();
559709403c1SSebastian Grimberg /// let nelem = 3;
560709403c1SSebastian Grimberg /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
561709403c1SSebastian Grimberg /// let mut curlorients: Vec<i8> = vec![0; 3 * 2 * nelem];
562709403c1SSebastian Grimberg /// for i in 0..nelem {
563709403c1SSebastian Grimberg /// ind[2 * i + 0] = i as i32;
564709403c1SSebastian Grimberg /// ind[2 * i + 1] = (i + 1) as i32;
565709403c1SSebastian Grimberg /// curlorients[3 * 2 * i] = 0 as i8;
566709403c1SSebastian Grimberg /// curlorients[3 * 2 * (i + 1) - 1] = 0 as i8;
567709403c1SSebastian Grimberg /// if (i % 2 > 0) {
568709403c1SSebastian Grimberg /// // T = [0 -1]
569709403c1SSebastian Grimberg /// // [-1 0]
570709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 1] = 0 as i8;
571709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 2] = -1 as i8;
572709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 3] = -1 as i8;
573709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 4] = 0 as i8;
574709403c1SSebastian Grimberg /// } else {
575709403c1SSebastian Grimberg /// // T = I
576709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 1] = 1 as i8;
577709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 2] = 0 as i8;
578709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 3] = 0 as i8;
579709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 4] = 1 as i8;
580709403c1SSebastian Grimberg /// }
581709403c1SSebastian Grimberg /// }
582709403c1SSebastian Grimberg /// let r = ceed.curl_oriented_elem_restriction(
583709403c1SSebastian Grimberg /// nelem,
584709403c1SSebastian Grimberg /// 2,
585709403c1SSebastian Grimberg /// 1,
586709403c1SSebastian Grimberg /// 1,
587709403c1SSebastian Grimberg /// nelem + 1,
588709403c1SSebastian Grimberg /// MemType::Host,
589709403c1SSebastian Grimberg /// &ind,
590709403c1SSebastian Grimberg /// &curlorients,
591709403c1SSebastian Grimberg /// )?;
592709403c1SSebastian Grimberg /// # Ok(())
593709403c1SSebastian Grimberg /// # }
594709403c1SSebastian Grimberg /// ```
59578c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)]
curl_oriented_elem_restriction<'a>( &self, nelem: usize, elemsize: usize, ncomp: usize, compstride: usize, lsize: usize, mtype: MemType, offsets: &[i32], curlorients: &[i8], ) -> Result<ElemRestriction<'a>>596709403c1SSebastian Grimberg pub fn curl_oriented_elem_restriction<'a>(
597709403c1SSebastian Grimberg &self,
598709403c1SSebastian Grimberg nelem: usize,
599709403c1SSebastian Grimberg elemsize: usize,
600709403c1SSebastian Grimberg ncomp: usize,
601709403c1SSebastian Grimberg compstride: usize,
602709403c1SSebastian Grimberg lsize: usize,
603709403c1SSebastian Grimberg mtype: MemType,
604709403c1SSebastian Grimberg offsets: &[i32],
605709403c1SSebastian Grimberg curlorients: &[i8],
606709403c1SSebastian Grimberg ) -> Result<ElemRestriction<'a>> {
607709403c1SSebastian Grimberg ElemRestriction::create_curl_oriented(
608709403c1SSebastian Grimberg self,
609709403c1SSebastian Grimberg nelem,
610709403c1SSebastian Grimberg elemsize,
611709403c1SSebastian Grimberg ncomp,
612709403c1SSebastian Grimberg compstride,
613709403c1SSebastian Grimberg lsize,
614709403c1SSebastian Grimberg mtype,
615709403c1SSebastian Grimberg offsets,
616709403c1SSebastian Grimberg curlorients,
6179df49d7eSJed Brown )
6189df49d7eSJed Brown }
6199df49d7eSJed Brown
6207ed177dbSJed Brown /// Returns an ElemRestriction, $\mathcal{E}$, from an local vector to
6217ed177dbSJed Brown /// an element vector where data can be indexed from the `strides` array
6229df49d7eSJed Brown ///
6239df49d7eSJed Brown /// # arguments
6249df49d7eSJed Brown ///
6259df49d7eSJed Brown /// * `nelem` - Number of elements described in the offsets array
6269df49d7eSJed Brown /// * `elemsize` - Size (number of "nodes") per element
6279df49d7eSJed Brown /// * `ncomp` - Number of field components per interpolation node (1
6289df49d7eSJed Brown /// for scalar fields)
6299df49d7eSJed Brown /// * `lsize` - The size of the Lvector. This vector may be larger
6309df49d7eSJed Brown /// than the elements and fields given by this restriction.
6319df49d7eSJed Brown /// * `strides` - Array for strides between `[nodes, components, elements]`.
6329df49d7eSJed Brown /// Data for node `i`, component `j`, element `k` can be
6339df49d7eSJed Brown /// found in the Lvector at index
6349df49d7eSJed Brown /// `i*strides[0] + j*strides[1] + k*strides[2]`.
6359df49d7eSJed Brown /// CEED_STRIDES_BACKEND may be used with vectors created
6369df49d7eSJed Brown /// by a Ceed backend.
6379df49d7eSJed Brown ///
6389df49d7eSJed Brown /// ```
6399df49d7eSJed Brown /// # use libceed::prelude::*;
6404d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
6419df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
6429df49d7eSJed Brown /// let nelem = 3;
6439df49d7eSJed Brown /// let strides: [i32; 3] = [1, 2, 2];
644c68be7a2SJeremy L Thompson /// let r = ceed.strided_elem_restriction(nelem, 2, 1, nelem * 2, strides)?;
645c68be7a2SJeremy L Thompson /// # Ok(())
646c68be7a2SJeremy L Thompson /// # }
6479df49d7eSJed Brown /// ```
strided_elem_restriction<'a>( &self, nelem: usize, elemsize: usize, ncomp: usize, lsize: usize, strides: [i32; 3], ) -> Result<ElemRestriction<'a>>648594ef120SJeremy L Thompson pub fn strided_elem_restriction<'a>(
6499df49d7eSJed Brown &self,
6509df49d7eSJed Brown nelem: usize,
6519df49d7eSJed Brown elemsize: usize,
6529df49d7eSJed Brown ncomp: usize,
6539df49d7eSJed Brown lsize: usize,
6549df49d7eSJed Brown strides: [i32; 3],
655594ef120SJeremy L Thompson ) -> Result<ElemRestriction<'a>> {
6569df49d7eSJed Brown ElemRestriction::create_strided(self, nelem, elemsize, ncomp, lsize, strides)
6579df49d7eSJed Brown }
6589df49d7eSJed Brown
6597ed177dbSJed Brown /// Returns an $H^1$ tensor-product Basis
6609df49d7eSJed Brown ///
6619df49d7eSJed Brown /// # arguments
6629df49d7eSJed Brown ///
6639df49d7eSJed Brown /// * `dim` - Topological dimension of element
6649df49d7eSJed Brown /// * `ncomp` - Number of field components (1 for scalar fields)
6659df49d7eSJed Brown /// * `P1d` - Number of Gauss-Lobatto nodes in one dimension. The
6669df49d7eSJed Brown /// polynomial degree of the resulting `Q_k` element is
6679df49d7eSJed Brown /// `k=P-1`.
6689df49d7eSJed Brown /// * `Q1d` - Number of quadrature points in one dimension
6699df49d7eSJed Brown /// * `interp1d` - Row-major `(Q1d * P1d)` matrix expressing the values of
6709df49d7eSJed Brown /// nodal basis functions at quadrature points
6719df49d7eSJed Brown /// * `grad1d` - Row-major `(Q1d * P1d)` matrix expressing derivatives of
6729df49d7eSJed Brown /// nodal basis functions at quadrature points
6739df49d7eSJed Brown /// * `qref1d` - Array of length `Q1d` holding the locations of quadrature
6749df49d7eSJed Brown /// points on the 1D reference element `[-1, 1]`
6759df49d7eSJed Brown /// * `qweight1d` - Array of length `Q1d` holding the quadrature weights on
6769df49d7eSJed Brown /// the reference element
6779df49d7eSJed Brown ///
6789df49d7eSJed Brown /// ```
6799df49d7eSJed Brown /// # use libceed::prelude::*;
6804d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
6819df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
6829df49d7eSJed Brown /// let interp1d = [ 0.62994317, 0.47255875, -0.14950343, 0.04700152,
6839df49d7eSJed Brown /// -0.07069480, 0.97297619, 0.13253993, -0.03482132,
6849df49d7eSJed Brown /// -0.03482132, 0.13253993, 0.97297619, -0.07069480,
6859df49d7eSJed Brown /// 0.04700152, -0.14950343, 0.47255875, 0.62994317];
6869df49d7eSJed Brown /// let grad1d = [-2.34183742, 2.78794489, -0.63510411, 0.18899664,
6879df49d7eSJed Brown /// -0.51670214, -0.48795249, 1.33790510, -0.33325047,
6889df49d7eSJed Brown // 0.33325047, -1.33790510, 0.48795249, 0.51670214,
6899df49d7eSJed Brown /// -0.18899664, 0.63510411, -2.78794489, 2.34183742];
6909df49d7eSJed Brown /// let qref1d = [-0.86113631, -0.33998104, 0.33998104, 0.86113631];
6919df49d7eSJed Brown /// let qweight1d = [ 0.34785485, 0.65214515, 0.65214515, 0.34785485];
6929df49d7eSJed Brown /// let b = ceed.
693c68be7a2SJeremy L Thompson /// basis_tensor_H1(2, 1, 4, 4, &interp1d, &grad1d, &qref1d, &qweight1d)?;
694c68be7a2SJeremy L Thompson /// # Ok(())
695c68be7a2SJeremy L Thompson /// # }
6969df49d7eSJed Brown /// ```
69778c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)]
basis_tensor_H1<'a>( &self, dim: usize, ncomp: usize, P1d: usize, Q1d: usize, interp1d: &[crate::Scalar], grad1d: &[crate::Scalar], qref1d: &[crate::Scalar], qweight1d: &[crate::Scalar], ) -> Result<Basis<'a>>698594ef120SJeremy L Thompson pub fn basis_tensor_H1<'a>(
6999df49d7eSJed Brown &self,
7009df49d7eSJed Brown dim: usize,
7019df49d7eSJed Brown ncomp: usize,
7029df49d7eSJed Brown P1d: usize,
7039df49d7eSJed Brown Q1d: usize,
70480a9ef05SNatalie Beams interp1d: &[crate::Scalar],
70580a9ef05SNatalie Beams grad1d: &[crate::Scalar],
70680a9ef05SNatalie Beams qref1d: &[crate::Scalar],
70780a9ef05SNatalie Beams qweight1d: &[crate::Scalar],
708594ef120SJeremy L Thompson ) -> Result<Basis<'a>> {
7099df49d7eSJed Brown Basis::create_tensor_H1(
7109df49d7eSJed Brown self, dim, ncomp, P1d, Q1d, interp1d, grad1d, qref1d, qweight1d,
7119df49d7eSJed Brown )
7129df49d7eSJed Brown }
7139df49d7eSJed Brown
7147ed177dbSJed Brown /// Returns an $H^1$ Lagrange tensor-product Basis
7159df49d7eSJed Brown ///
7169df49d7eSJed Brown /// # arguments
7179df49d7eSJed Brown ///
7189df49d7eSJed Brown /// * `dim` - Topological dimension of element
7199df49d7eSJed Brown /// * `ncomp` - Number of field components (1 for scalar fields)
7209df49d7eSJed Brown /// * `P` - Number of Gauss-Lobatto nodes in one dimension. The
7219df49d7eSJed Brown /// polynomial degree of the resulting `Q_k` element is `k=P-1`.
7229df49d7eSJed Brown /// * `Q` - Number of quadrature points in one dimension
7239df49d7eSJed Brown /// * `qmode` - Distribution of the `Q` quadrature points (affects order of
7249df49d7eSJed Brown /// accuracy for the quadrature)
7259df49d7eSJed Brown ///
7269df49d7eSJed Brown /// ```
727eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, QuadMode};
7284d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
7299df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
730c68be7a2SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(2, 1, 3, 4, QuadMode::Gauss)?;
731c68be7a2SJeremy L Thompson /// # Ok(())
732c68be7a2SJeremy L Thompson /// # }
7339df49d7eSJed Brown /// ```
basis_tensor_H1_Lagrange<'a>( &self, dim: usize, ncomp: usize, P: usize, Q: usize, qmode: QuadMode, ) -> Result<Basis<'a>>734594ef120SJeremy L Thompson pub fn basis_tensor_H1_Lagrange<'a>(
7359df49d7eSJed Brown &self,
7369df49d7eSJed Brown dim: usize,
7379df49d7eSJed Brown ncomp: usize,
7389df49d7eSJed Brown P: usize,
7399df49d7eSJed Brown Q: usize,
7409df49d7eSJed Brown qmode: QuadMode,
741594ef120SJeremy L Thompson ) -> Result<Basis<'a>> {
7429df49d7eSJed Brown Basis::create_tensor_H1_Lagrange(self, dim, ncomp, P, Q, qmode)
7439df49d7eSJed Brown }
7449df49d7eSJed Brown
7457ed177dbSJed Brown /// Returns an $H-1$ Basis
7469df49d7eSJed Brown ///
7479df49d7eSJed Brown /// # arguments
7489df49d7eSJed Brown ///
7499df49d7eSJed Brown /// * `topo` - Topology of element, e.g. hypercube, simplex, ect
7509df49d7eSJed Brown /// * `ncomp` - Number of field components (1 for scalar fields)
7519df49d7eSJed Brown /// * `nnodes` - Total number of nodes
7529df49d7eSJed Brown /// * `nqpts` - Total number of quadrature points
7539df49d7eSJed Brown /// * `interp` - Row-major `(nqpts * nnodes)` matrix expressing the values of
7549df49d7eSJed Brown /// nodal basis functions at quadrature points
75597c1c57aSSebastian Grimberg /// * `grad` - Row-major `(dim * nqpts * nnodes)` matrix expressing
7569df49d7eSJed Brown /// derivatives of nodal basis functions at quadrature points
7579df49d7eSJed Brown /// * `qref` - Array of length `nqpts` holding the locations of quadrature
7589df49d7eSJed Brown /// points on the reference element `[-1, 1]`
7599df49d7eSJed Brown /// * `qweight` - Array of length `nqpts` holding the quadrature weights on
7609df49d7eSJed Brown /// the reference element
7619df49d7eSJed Brown ///
7629df49d7eSJed Brown /// ```
763eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, ElemTopology};
7644d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
7659df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
7669df49d7eSJed Brown /// let interp = [
7679df49d7eSJed Brown /// 0.12000000,
7689df49d7eSJed Brown /// 0.48000000,
7699df49d7eSJed Brown /// -0.12000000,
7709df49d7eSJed Brown /// 0.48000000,
7719df49d7eSJed Brown /// 0.16000000,
7729df49d7eSJed Brown /// -0.12000000,
7739df49d7eSJed Brown /// -0.12000000,
7749df49d7eSJed Brown /// 0.48000000,
7759df49d7eSJed Brown /// 0.12000000,
7769df49d7eSJed Brown /// 0.16000000,
7779df49d7eSJed Brown /// 0.48000000,
7789df49d7eSJed Brown /// -0.12000000,
7799df49d7eSJed Brown /// -0.11111111,
7809df49d7eSJed Brown /// 0.44444444,
7819df49d7eSJed Brown /// -0.11111111,
7829df49d7eSJed Brown /// 0.44444444,
7839df49d7eSJed Brown /// 0.44444444,
7849df49d7eSJed Brown /// -0.11111111,
7859df49d7eSJed Brown /// -0.12000000,
7869df49d7eSJed Brown /// 0.16000000,
7879df49d7eSJed Brown /// -0.12000000,
7889df49d7eSJed Brown /// 0.48000000,
7899df49d7eSJed Brown /// 0.48000000,
7909df49d7eSJed Brown /// 0.12000000,
7919df49d7eSJed Brown /// ];
7929df49d7eSJed Brown /// let grad = [
7939df49d7eSJed Brown /// -1.40000000,
7949df49d7eSJed Brown /// 1.60000000,
7959df49d7eSJed Brown /// -0.20000000,
7969df49d7eSJed Brown /// -0.80000000,
7979df49d7eSJed Brown /// 0.80000000,
7989df49d7eSJed Brown /// 0.00000000,
7999df49d7eSJed Brown /// 0.20000000,
8009df49d7eSJed Brown /// -1.60000000,
8019df49d7eSJed Brown /// 1.40000000,
8029df49d7eSJed Brown /// -0.80000000,
8039df49d7eSJed Brown /// 0.80000000,
8049df49d7eSJed Brown /// 0.00000000,
8059df49d7eSJed Brown /// -0.33333333,
8069df49d7eSJed Brown /// 0.00000000,
8079df49d7eSJed Brown /// 0.33333333,
8089df49d7eSJed Brown /// -1.33333333,
8099df49d7eSJed Brown /// 1.33333333,
8109df49d7eSJed Brown /// 0.00000000,
8119df49d7eSJed Brown /// 0.20000000,
8129df49d7eSJed Brown /// 0.00000000,
8139df49d7eSJed Brown /// -0.20000000,
8149df49d7eSJed Brown /// -2.40000000,
8159df49d7eSJed Brown /// 2.40000000,
8169df49d7eSJed Brown /// 0.00000000,
8179df49d7eSJed Brown /// -1.40000000,
8189df49d7eSJed Brown /// -0.80000000,
8199df49d7eSJed Brown /// 0.00000000,
8209df49d7eSJed Brown /// 1.60000000,
8219df49d7eSJed Brown /// 0.80000000,
8229df49d7eSJed Brown /// -0.20000000,
8239df49d7eSJed Brown /// 0.20000000,
8249df49d7eSJed Brown /// -2.40000000,
8259df49d7eSJed Brown /// 0.00000000,
8269df49d7eSJed Brown /// 0.00000000,
8279df49d7eSJed Brown /// 2.40000000,
8289df49d7eSJed Brown /// -0.20000000,
8299df49d7eSJed Brown /// -0.33333333,
8309df49d7eSJed Brown /// -1.33333333,
8319df49d7eSJed Brown /// 0.00000000,
8329df49d7eSJed Brown /// 0.00000000,
8339df49d7eSJed Brown /// 1.33333333,
8349df49d7eSJed Brown /// 0.33333333,
8359df49d7eSJed Brown /// 0.20000000,
8369df49d7eSJed Brown /// -0.80000000,
8379df49d7eSJed Brown /// 0.00000000,
8389df49d7eSJed Brown /// -1.60000000,
8399df49d7eSJed Brown /// 0.80000000,
8409df49d7eSJed Brown /// 1.40000000,
8419df49d7eSJed Brown /// ];
8429df49d7eSJed Brown /// let qref = [
8439df49d7eSJed Brown /// 0.20000000, 0.60000000, 0.33333333, 0.20000000, 0.20000000, 0.20000000, 0.33333333,
8449df49d7eSJed Brown /// 0.60000000,
8459df49d7eSJed Brown /// ];
8469df49d7eSJed Brown /// let qweight = [0.26041667, 0.26041667, -0.28125000, 0.26041667];
847c68be7a2SJeremy L Thompson /// let b = ceed.basis_H1(
8489df49d7eSJed Brown /// ElemTopology::Triangle,
8499df49d7eSJed Brown /// 1,
8509df49d7eSJed Brown /// 6,
8519df49d7eSJed Brown /// 4,
8529df49d7eSJed Brown /// &interp,
8539df49d7eSJed Brown /// &grad,
8549df49d7eSJed Brown /// &qref,
8559df49d7eSJed Brown /// &qweight,
856c68be7a2SJeremy L Thompson /// )?;
857c68be7a2SJeremy L Thompson /// # Ok(())
858c68be7a2SJeremy L Thompson /// # }
8599df49d7eSJed Brown /// ```
86078c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)]
basis_H1<'a>( &self, topo: ElemTopology, ncomp: usize, nnodes: usize, nqpts: usize, interp: &[crate::Scalar], grad: &[crate::Scalar], qref: &[crate::Scalar], qweight: &[crate::Scalar], ) -> Result<Basis<'a>>861594ef120SJeremy L Thompson pub fn basis_H1<'a>(
8629df49d7eSJed Brown &self,
8639df49d7eSJed Brown topo: ElemTopology,
8649df49d7eSJed Brown ncomp: usize,
8659df49d7eSJed Brown nnodes: usize,
8669df49d7eSJed Brown nqpts: usize,
86780a9ef05SNatalie Beams interp: &[crate::Scalar],
86880a9ef05SNatalie Beams grad: &[crate::Scalar],
86980a9ef05SNatalie Beams qref: &[crate::Scalar],
87080a9ef05SNatalie Beams qweight: &[crate::Scalar],
871594ef120SJeremy L Thompson ) -> Result<Basis<'a>> {
8729df49d7eSJed Brown Basis::create_H1(
8739df49d7eSJed Brown self, topo, ncomp, nnodes, nqpts, interp, grad, qref, qweight,
8749df49d7eSJed Brown )
8759df49d7eSJed Brown }
8769df49d7eSJed Brown
87797c1c57aSSebastian Grimberg /// Returns an $H(div)$ Basis
87897c1c57aSSebastian Grimberg ///
87997c1c57aSSebastian Grimberg /// # arguments
88097c1c57aSSebastian Grimberg ///
88197c1c57aSSebastian Grimberg /// * `topo` - Topology of element, e.g. hypercube, simplex, ect
88297c1c57aSSebastian Grimberg /// * `ncomp` - Number of field components (1 for scalar fields)
88397c1c57aSSebastian Grimberg /// * `nnodes` - Total number of nodes
88497c1c57aSSebastian Grimberg /// * `nqpts` - Total number of quadrature points
88597c1c57aSSebastian Grimberg /// * `interp` - Row-major `(dim * nqpts * nnodes)` matrix expressing the
88697c1c57aSSebastian Grimberg /// values of basis functions at quadrature points
88797c1c57aSSebastian Grimberg /// * `div` - Row-major `(nqpts * nnodes)` matrix expressing the
88897c1c57aSSebastian Grimberg /// divergence of basis functions at quadrature points
88997c1c57aSSebastian Grimberg /// * `qref` - Array of length `nqpts` holding the locations of quadrature
89097c1c57aSSebastian Grimberg /// points on the reference element `[-1, 1]`
89197c1c57aSSebastian Grimberg /// * `qweight` - Array of length `nqpts` holding the quadrature weights on
89297c1c57aSSebastian Grimberg /// the reference element
89397c1c57aSSebastian Grimberg ///
89497c1c57aSSebastian Grimberg /// ```
895eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, ElemTopology};
89697c1c57aSSebastian Grimberg /// # fn main() -> libceed::Result<()> {
89797c1c57aSSebastian Grimberg /// # let ceed = libceed::Ceed::default_init();
89897c1c57aSSebastian Grimberg /// let interp = [
89997c1c57aSSebastian Grimberg /// 0.00000000,
90097c1c57aSSebastian Grimberg /// -1.57735027,
90197c1c57aSSebastian Grimberg /// 0.57735027,
90297c1c57aSSebastian Grimberg /// 0.00000000,
90397c1c57aSSebastian Grimberg /// 0.00000000,
90497c1c57aSSebastian Grimberg /// -1.57735027,
90597c1c57aSSebastian Grimberg /// 0.57735027,
90697c1c57aSSebastian Grimberg /// 0.00000000,
90797c1c57aSSebastian Grimberg /// 0.00000000,
90897c1c57aSSebastian Grimberg /// -1.57735027,
90997c1c57aSSebastian Grimberg /// 0.57735027,
91097c1c57aSSebastian Grimberg /// 0.00000000,
91197c1c57aSSebastian Grimberg /// 0.00000000,
91297c1c57aSSebastian Grimberg /// -0.42264973,
91397c1c57aSSebastian Grimberg /// -0.57735027,
91497c1c57aSSebastian Grimberg /// 0.00000000,
91597c1c57aSSebastian Grimberg /// 0.42264973,
91697c1c57aSSebastian Grimberg /// 0.00000000,
91797c1c57aSSebastian Grimberg /// 0.00000000,
91897c1c57aSSebastian Grimberg /// 0.57735027,
91997c1c57aSSebastian Grimberg /// 0.42264973,
92097c1c57aSSebastian Grimberg /// 0.00000000,
92197c1c57aSSebastian Grimberg /// 0.00000000,
92297c1c57aSSebastian Grimberg /// 0.57735027,
92397c1c57aSSebastian Grimberg /// 1.57735027,
92497c1c57aSSebastian Grimberg /// 0.00000000,
92597c1c57aSSebastian Grimberg /// 0.00000000,
92697c1c57aSSebastian Grimberg /// -0.57735027,
92797c1c57aSSebastian Grimberg /// 1.57735027,
92897c1c57aSSebastian Grimberg /// 0.00000000,
92997c1c57aSSebastian Grimberg /// 0.00000000,
93097c1c57aSSebastian Grimberg /// -0.57735027,
93197c1c57aSSebastian Grimberg /// ];
93297c1c57aSSebastian Grimberg /// let div = [
93397c1c57aSSebastian Grimberg /// -1.00000000,
93497c1c57aSSebastian Grimberg /// 1.00000000,
93597c1c57aSSebastian Grimberg /// -1.00000000,
93697c1c57aSSebastian Grimberg /// 1.00000000,
93797c1c57aSSebastian Grimberg /// -1.00000000,
93897c1c57aSSebastian Grimberg /// 1.00000000,
93997c1c57aSSebastian Grimberg /// -1.00000000,
94097c1c57aSSebastian Grimberg /// 1.00000000,
94197c1c57aSSebastian Grimberg /// -1.00000000,
94297c1c57aSSebastian Grimberg /// 1.00000000,
94397c1c57aSSebastian Grimberg /// -1.00000000,
94497c1c57aSSebastian Grimberg /// 1.00000000,
94597c1c57aSSebastian Grimberg /// -1.00000000,
94697c1c57aSSebastian Grimberg /// 1.00000000,
94797c1c57aSSebastian Grimberg /// -1.00000000,
94897c1c57aSSebastian Grimberg /// 1.00000000,
94997c1c57aSSebastian Grimberg /// ];
95097c1c57aSSebastian Grimberg /// let qref = [
95197c1c57aSSebastian Grimberg /// 0.57735026, 0.57735026, 0.57735026, 0.57735026, 0.57735026, 0.57735026, 0.57735026,
95297c1c57aSSebastian Grimberg /// 0.57735026,
95397c1c57aSSebastian Grimberg /// ];
95497c1c57aSSebastian Grimberg /// let qweight = [1.00000000, 1.00000000, 1.00000000, 1.00000000];
95597c1c57aSSebastian Grimberg /// let b = ceed.basis_Hdiv(ElemTopology::Quad, 1, 4, 4, &interp, &div, &qref, &qweight)?;
95697c1c57aSSebastian Grimberg /// # Ok(())
95797c1c57aSSebastian Grimberg /// # }
95897c1c57aSSebastian Grimberg /// ```
95978c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)]
basis_Hdiv<'a>( &self, topo: ElemTopology, ncomp: usize, nnodes: usize, nqpts: usize, interp: &[crate::Scalar], div: &[crate::Scalar], qref: &[crate::Scalar], qweight: &[crate::Scalar], ) -> Result<Basis<'a>>96097c1c57aSSebastian Grimberg pub fn basis_Hdiv<'a>(
96197c1c57aSSebastian Grimberg &self,
96297c1c57aSSebastian Grimberg topo: ElemTopology,
96397c1c57aSSebastian Grimberg ncomp: usize,
96497c1c57aSSebastian Grimberg nnodes: usize,
96597c1c57aSSebastian Grimberg nqpts: usize,
96697c1c57aSSebastian Grimberg interp: &[crate::Scalar],
96797c1c57aSSebastian Grimberg div: &[crate::Scalar],
96897c1c57aSSebastian Grimberg qref: &[crate::Scalar],
96997c1c57aSSebastian Grimberg qweight: &[crate::Scalar],
97097c1c57aSSebastian Grimberg ) -> Result<Basis<'a>> {
97197c1c57aSSebastian Grimberg Basis::create_Hdiv(self, topo, ncomp, nnodes, nqpts, interp, div, qref, qweight)
97297c1c57aSSebastian Grimberg }
97397c1c57aSSebastian Grimberg
97497c1c57aSSebastian Grimberg /// Returns an $H(curl)$ Basis
97597c1c57aSSebastian Grimberg ///
97697c1c57aSSebastian Grimberg /// # arguments
97797c1c57aSSebastian Grimberg ///
97897c1c57aSSebastian Grimberg /// * `topo` - Topology of element, e.g. hypercube, simplex, ect
97997c1c57aSSebastian Grimberg /// * `ncomp` - Number of field components (1 for scalar fields)
98097c1c57aSSebastian Grimberg /// * `nnodes` - Total number of nodes
98197c1c57aSSebastian Grimberg /// * `nqpts` - Total number of quadrature points
98297c1c57aSSebastian Grimberg /// * `interp` - Row-major `(dim * nqpts * nnodes)` matrix expressing the
98397c1c57aSSebastian Grimberg /// values of basis functions at quadrature points
98497c1c57aSSebastian Grimberg /// * `curl` - Row-major `(curl_comp * nqpts * nnodes)`, `curl_comp = 1 if
98597c1c57aSSebastian Grimberg /// dim < 3 else dim` matrix expressing the curl of basis
98697c1c57aSSebastian Grimberg /// functions at quadrature points
98797c1c57aSSebastian Grimberg /// * `qref` - Array of length `nqpts` holding the locations of quadrature
98897c1c57aSSebastian Grimberg /// points on the reference element `[-1, 1]`
98997c1c57aSSebastian Grimberg /// * `qweight` - Array of length `nqpts` holding the quadrature weights on
99097c1c57aSSebastian Grimberg /// the reference element
99197c1c57aSSebastian Grimberg ///
99297c1c57aSSebastian Grimberg /// ```
993eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, ElemTopology};
99497c1c57aSSebastian Grimberg /// # fn main() -> libceed::Result<()> {
99597c1c57aSSebastian Grimberg /// # let ceed = libceed::Ceed::default_init();
99697c1c57aSSebastian Grimberg /// let interp = [
99797c1c57aSSebastian Grimberg /// -0.20000000,
99897c1c57aSSebastian Grimberg /// 0.20000000,
99997c1c57aSSebastian Grimberg /// 0.80000000,
100097c1c57aSSebastian Grimberg /// -0.20000000,
100197c1c57aSSebastian Grimberg /// 0.20000000,
100297c1c57aSSebastian Grimberg /// 0.80000000,
100397c1c57aSSebastian Grimberg /// -0.33333333,
100497c1c57aSSebastian Grimberg /// 0.33333333,
100597c1c57aSSebastian Grimberg /// 0.66666667,
100697c1c57aSSebastian Grimberg /// -0.60000000,
100797c1c57aSSebastian Grimberg /// 0.60000000,
100897c1c57aSSebastian Grimberg /// 0.40000000,
100997c1c57aSSebastian Grimberg /// 0.20000000,
101097c1c57aSSebastian Grimberg /// 0.80000000,
101197c1c57aSSebastian Grimberg /// 0.20000000,
101297c1c57aSSebastian Grimberg /// 0.60000000,
101397c1c57aSSebastian Grimberg /// 0.40000000,
101497c1c57aSSebastian Grimberg /// 0.60000000,
101597c1c57aSSebastian Grimberg /// 0.33333333,
101697c1c57aSSebastian Grimberg /// 0.66666667,
101797c1c57aSSebastian Grimberg /// 0.33333333,
101897c1c57aSSebastian Grimberg /// 0.20000000,
101997c1c57aSSebastian Grimberg /// 0.80000000,
102097c1c57aSSebastian Grimberg /// 0.20000000,
102197c1c57aSSebastian Grimberg /// ];
102297c1c57aSSebastian Grimberg /// let curl = [
102397c1c57aSSebastian Grimberg /// 2.00000000,
102497c1c57aSSebastian Grimberg /// -2.00000000,
102597c1c57aSSebastian Grimberg /// -2.00000000,
102697c1c57aSSebastian Grimberg /// 2.00000000,
102797c1c57aSSebastian Grimberg /// -2.00000000,
102897c1c57aSSebastian Grimberg /// -2.00000000,
102997c1c57aSSebastian Grimberg /// 2.00000000,
103097c1c57aSSebastian Grimberg /// -2.00000000,
103197c1c57aSSebastian Grimberg /// -2.00000000,
103297c1c57aSSebastian Grimberg /// 2.00000000,
103397c1c57aSSebastian Grimberg /// -2.00000000,
103497c1c57aSSebastian Grimberg /// -2.00000000,
103597c1c57aSSebastian Grimberg /// ];
103697c1c57aSSebastian Grimberg /// let qref = [
103797c1c57aSSebastian Grimberg /// 0.20000000, 0.60000000, 0.33333333, 0.20000000, 0.20000000, 0.20000000, 0.33333333,
103897c1c57aSSebastian Grimberg /// 0.60000000,
103997c1c57aSSebastian Grimberg /// ];
104097c1c57aSSebastian Grimberg /// let qweight = [0.26041667, 0.26041667, -0.28125000, 0.26041667];
104197c1c57aSSebastian Grimberg /// let b = ceed.basis_Hcurl(
104297c1c57aSSebastian Grimberg /// ElemTopology::Triangle,
104397c1c57aSSebastian Grimberg /// 1,
104497c1c57aSSebastian Grimberg /// 3,
104597c1c57aSSebastian Grimberg /// 4,
104697c1c57aSSebastian Grimberg /// &interp,
104797c1c57aSSebastian Grimberg /// &curl,
104897c1c57aSSebastian Grimberg /// &qref,
104997c1c57aSSebastian Grimberg /// &qweight,
105097c1c57aSSebastian Grimberg /// )?;
105197c1c57aSSebastian Grimberg /// # Ok(())
105297c1c57aSSebastian Grimberg /// # }
105397c1c57aSSebastian Grimberg /// ```
105478c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)]
basis_Hcurl<'a>( &self, topo: ElemTopology, ncomp: usize, nnodes: usize, nqpts: usize, interp: &[crate::Scalar], curl: &[crate::Scalar], qref: &[crate::Scalar], qweight: &[crate::Scalar], ) -> Result<Basis<'a>>105597c1c57aSSebastian Grimberg pub fn basis_Hcurl<'a>(
105697c1c57aSSebastian Grimberg &self,
105797c1c57aSSebastian Grimberg topo: ElemTopology,
105897c1c57aSSebastian Grimberg ncomp: usize,
105997c1c57aSSebastian Grimberg nnodes: usize,
106097c1c57aSSebastian Grimberg nqpts: usize,
106197c1c57aSSebastian Grimberg interp: &[crate::Scalar],
106297c1c57aSSebastian Grimberg curl: &[crate::Scalar],
106397c1c57aSSebastian Grimberg qref: &[crate::Scalar],
106497c1c57aSSebastian Grimberg qweight: &[crate::Scalar],
106597c1c57aSSebastian Grimberg ) -> Result<Basis<'a>> {
106697c1c57aSSebastian Grimberg Basis::create_Hcurl(
106797c1c57aSSebastian Grimberg self, topo, ncomp, nnodes, nqpts, interp, curl, qref, qweight,
106897c1c57aSSebastian Grimberg )
106997c1c57aSSebastian Grimberg }
107097c1c57aSSebastian Grimberg
10717ed177dbSJed Brown /// Returns a QFunction for evaluating interior (volumetric) terms
10727ed177dbSJed Brown /// of a weak form corresponding to the $L^2$ inner product
10737ed177dbSJed Brown ///
10747ed177dbSJed Brown /// $$
10757ed177dbSJed Brown /// \langle v, F(u) \rangle = \int_\Omega v \cdot f_0 \left( u, \nabla u \right) + \left( \nabla v \right) : f_1 \left( u, \nabla u \right),
10767ed177dbSJed Brown /// $$
10777ed177dbSJed Brown ///
10787ed177dbSJed Brown /// where $v \cdot f_0$ represents contraction over fields and $\nabla v : f_1$
10797ed177dbSJed Brown /// represents contraction over both fields and spatial dimensions.
10809df49d7eSJed Brown ///
10819df49d7eSJed Brown /// # arguments
10829df49d7eSJed Brown ///
10839df49d7eSJed Brown /// * `vlength` - Vector length. Caller must ensure that number of
10849df49d7eSJed Brown /// quadrature points is a multiple of vlength.
10857ed177dbSJed Brown /// * `f` - Boxed closure to evaluate weak form at quadrature points.
10869df49d7eSJed Brown ///
10879df49d7eSJed Brown /// ```
1088eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, QFunctionInputs, QFunctionOutputs};
10894d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
10909df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
10919df49d7eSJed Brown /// let mut user_f = |[u, weights, ..]: QFunctionInputs, [v, ..]: QFunctionOutputs| {
10929df49d7eSJed Brown /// // Iterate over quadrature points
10939df49d7eSJed Brown /// v.iter_mut()
10949df49d7eSJed Brown /// .zip(u.iter().zip(weights.iter()))
10959df49d7eSJed Brown /// .for_each(|(v, (u, w))| *v = u * w);
10969df49d7eSJed Brown ///
10979df49d7eSJed Brown /// // Return clean error code
10989df49d7eSJed Brown /// 0
10999df49d7eSJed Brown /// };
11009df49d7eSJed Brown ///
1101c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior(1, Box::new(user_f))?;
1102c68be7a2SJeremy L Thompson /// # Ok(())
1103c68be7a2SJeremy L Thompson /// # }
11049df49d7eSJed Brown /// ```
q_function_interior<'a>( &self, vlength: usize, f: Box<qfunction::QFunctionUserClosure>, ) -> Result<QFunction<'a>>1105594ef120SJeremy L Thompson pub fn q_function_interior<'a>(
11069df49d7eSJed Brown &self,
11079df49d7eSJed Brown vlength: usize,
11089df49d7eSJed Brown f: Box<qfunction::QFunctionUserClosure>,
1109594ef120SJeremy L Thompson ) -> Result<QFunction<'a>> {
11109df49d7eSJed Brown QFunction::create(self, vlength, f)
11119df49d7eSJed Brown }
11129df49d7eSJed Brown
11137ed177dbSJed Brown /// Returns a QFunction for evaluating interior (volumetric) terms
11149df49d7eSJed Brown /// created by name
11159df49d7eSJed Brown ///
11167ed177dbSJed Brown /// # arguments
11177ed177dbSJed Brown ///
11187ed177dbSJed Brown /// * `name` - name of QFunction from libCEED gallery
11197ed177dbSJed Brown ///
11209df49d7eSJed Brown /// ```
11219df49d7eSJed Brown /// # use libceed::prelude::*;
11224d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
11239df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
1124c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?;
1125c68be7a2SJeremy L Thompson /// # Ok(())
1126c68be7a2SJeremy L Thompson /// # }
11279df49d7eSJed Brown /// ```
q_function_interior_by_name<'a>(&self, name: &str) -> Result<QFunctionByName<'a>>1128594ef120SJeremy L Thompson pub fn q_function_interior_by_name<'a>(&self, name: &str) -> Result<QFunctionByName<'a>> {
11299df49d7eSJed Brown QFunctionByName::create(self, name)
11309df49d7eSJed Brown }
11319df49d7eSJed Brown
11327ed177dbSJed Brown /// Returns an Operator and associate a QFunction. A Basis and
11337ed177dbSJed Brown /// ElemRestriction can be associated with QFunction fields via
11349df49d7eSJed Brown /// set_field().
11359df49d7eSJed Brown ///
11367ed177dbSJed Brown /// # arguments
11377ed177dbSJed Brown ///
11389df49d7eSJed Brown /// * `qf` - QFunction defining the action of the operator at quadrature
11399df49d7eSJed Brown /// points
11409df49d7eSJed Brown /// * `dqf` - QFunction defining the action of the Jacobian of the qf (or
11419df49d7eSJed Brown /// qfunction_none)
11429df49d7eSJed Brown /// * `dqfT` - QFunction defining the action of the transpose of the
11439df49d7eSJed Brown /// Jacobian of the qf (or qfunction_none)
11449df49d7eSJed Brown ///
11459df49d7eSJed Brown /// ```
1146eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, QFunctionOpt};
11474d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
11489df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
1149c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?;
1150c68be7a2SJeremy L Thompson /// let op = ceed.operator(&qf, QFunctionOpt::None, QFunctionOpt::None)?;
1151c68be7a2SJeremy L Thompson /// # Ok(())
1152c68be7a2SJeremy L Thompson /// # }
11539df49d7eSJed Brown /// ```
operator<'a, 'b>( &self, qf: impl Into<QFunctionOpt<'b>>, dqf: impl Into<QFunctionOpt<'b>>, dqfT: impl Into<QFunctionOpt<'b>>, ) -> Result<Operator<'a>>1154594ef120SJeremy L Thompson pub fn operator<'a, 'b>(
11559df49d7eSJed Brown &self,
11569df49d7eSJed Brown qf: impl Into<QFunctionOpt<'b>>,
11579df49d7eSJed Brown dqf: impl Into<QFunctionOpt<'b>>,
11589df49d7eSJed Brown dqfT: impl Into<QFunctionOpt<'b>>,
1159594ef120SJeremy L Thompson ) -> Result<Operator<'a>> {
11609df49d7eSJed Brown Operator::create(self, qf, dqf, dqfT)
11619df49d7eSJed Brown }
11629df49d7eSJed Brown
11639df49d7eSJed Brown /// Returns an Operator that composes the action of several Operators
11649df49d7eSJed Brown ///
11659df49d7eSJed Brown /// ```
11669df49d7eSJed Brown /// # use libceed::prelude::*;
11674d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> {
11689df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init();
1169c68be7a2SJeremy L Thompson /// let op = ceed.composite_operator()?;
1170c68be7a2SJeremy L Thompson /// # Ok(())
1171c68be7a2SJeremy L Thompson /// # }
11729df49d7eSJed Brown /// ```
composite_operator<'a>(&self) -> Result<CompositeOperator<'a>>1173594ef120SJeremy L Thompson pub fn composite_operator<'a>(&self) -> Result<CompositeOperator<'a>> {
11749df49d7eSJed Brown CompositeOperator::create(self)
11759df49d7eSJed Brown }
11769df49d7eSJed Brown }
11779df49d7eSJed Brown
11789df49d7eSJed Brown // -----------------------------------------------------------------------------
11799df49d7eSJed Brown // Tests
11809df49d7eSJed Brown // -----------------------------------------------------------------------------
11819df49d7eSJed Brown #[cfg(test)]
11829df49d7eSJed Brown mod tests {
11839df49d7eSJed Brown use super::*;
11849df49d7eSJed Brown
ceed_t501() -> Result<()>118589d15d5fSJeremy L Thompson fn ceed_t501() -> Result<()> {
11869df49d7eSJed Brown let resource = "/cpu/self/ref/blocked";
11879df49d7eSJed Brown let ceed = Ceed::init(resource);
11889df49d7eSJed Brown let nelem = 4;
11899df49d7eSJed Brown let p = 3;
11909df49d7eSJed Brown let q = 4;
11919df49d7eSJed Brown let ndofs = p * nelem - nelem + 1;
11929df49d7eSJed Brown
11939df49d7eSJed Brown // Vectors
11949df49d7eSJed Brown let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?;
11959df49d7eSJed Brown let mut qdata = ceed.vector(nelem * q)?;
11969df49d7eSJed Brown qdata.set_value(0.0)?;
11979df49d7eSJed Brown let mut u = ceed.vector(ndofs)?;
11989df49d7eSJed Brown u.set_value(1.0)?;
11999df49d7eSJed Brown let mut v = ceed.vector(ndofs)?;
12009df49d7eSJed Brown v.set_value(0.0)?;
12019df49d7eSJed Brown
12029df49d7eSJed Brown // Restrictions
12039df49d7eSJed Brown let mut indx: Vec<i32> = vec![0; 2 * nelem];
12049df49d7eSJed Brown for i in 0..nelem {
12051ce8139fSJeremy L Thompson for j in 0..2 {
12061ce8139fSJeremy L Thompson indx[2 * i + j] = (i + j) as i32;
12071ce8139fSJeremy L Thompson }
12089df49d7eSJed Brown }
12099df49d7eSJed Brown let rx = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &indx)?;
12109df49d7eSJed Brown let mut indu: Vec<i32> = vec![0; p * nelem];
12119df49d7eSJed Brown for i in 0..nelem {
12121ce8139fSJeremy L Thompson for j in 0..p {
12131ce8139fSJeremy L Thompson indu[p * i + j] = (i + j) as i32;
12149df49d7eSJed Brown }
12151ce8139fSJeremy L Thompson }
12161ce8139fSJeremy L Thompson let ru = ceed.elem_restriction(nelem, p, 1, 1, ndofs, MemType::Host, &indu)?;
12179df49d7eSJed Brown let strides: [i32; 3] = [1, q as i32, q as i32];
12189df49d7eSJed Brown let rq = ceed.strided_elem_restriction(nelem, q, 1, q * nelem, strides)?;
12199df49d7eSJed Brown
12209df49d7eSJed Brown // Bases
12219df49d7eSJed Brown let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?;
12229df49d7eSJed Brown let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?;
12239df49d7eSJed Brown
12249df49d7eSJed Brown // Build quadrature data
12259df49d7eSJed Brown let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?;
12269df49d7eSJed Brown ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)?
12279df49d7eSJed Brown .field("dx", &rx, &bx, VectorOpt::Active)?
12289df49d7eSJed Brown .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)?
1229356036faSJeremy L Thompson .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?
12309df49d7eSJed Brown .apply(&x, &mut qdata)?;
12319df49d7eSJed Brown
12329df49d7eSJed Brown // Mass operator
12339df49d7eSJed Brown let qf_mass = ceed.q_function_interior_by_name("MassApply")?;
12349df49d7eSJed Brown let op_mass = ceed
12359df49d7eSJed Brown .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)?
12369df49d7eSJed Brown .field("u", &ru, &bu, VectorOpt::Active)?
1237356036faSJeremy L Thompson .field("qdata", &rq, BasisOpt::None, &qdata)?
12386f97ff0aSJeremy L Thompson .field("v", &ru, &bu, VectorOpt::Active)?
12396f97ff0aSJeremy L Thompson .check()?;
12409df49d7eSJed Brown
12419df49d7eSJed Brown v.set_value(0.0)?;
12429df49d7eSJed Brown op_mass.apply(&u, &mut v)?;
12439df49d7eSJed Brown
12449df49d7eSJed Brown // Check
1245e78171edSJeremy L Thompson let sum: Scalar = v.view()?.iter().sum();
12461ce8139fSJeremy L Thompson let error: Scalar = (sum - 2.0).abs();
12479df49d7eSJed Brown assert!(
12484b61a5a0SRezgar Shakeri error < 50.0 * EPSILON,
12491ce8139fSJeremy L Thompson "Incorrect interval length computed. Expected: 2.0, Found: {}, Error: {:.12e}",
12501ce8139fSJeremy L Thompson sum,
12511ce8139fSJeremy L Thompson error
12529df49d7eSJed Brown );
125389d15d5fSJeremy L Thompson Ok(())
12549df49d7eSJed Brown }
12559df49d7eSJed Brown
12569df49d7eSJed Brown #[test]
test_ceed_t501()12579df49d7eSJed Brown fn test_ceed_t501() {
12589df49d7eSJed Brown assert!(ceed_t501().is_ok());
12599df49d7eSJed Brown }
12609df49d7eSJed Brown }
12619df49d7eSJed Brown
12629df49d7eSJed Brown // -----------------------------------------------------------------------------
1263