#![doc(html_logo_url = "https://gitlab.onelab.info/gmsh/gmsh/raw/master/utils/icons/gmsh.svg")]
#![deny(missing_docs)]
extern crate gmsh_sys;
use std::os::raw::{c_int, c_char, c_void};
pub mod err;
#[doc(inline)]
pub use err::{GmshError, GmshResult};
pub mod fltk;
pub mod interface;
use std::ffi::{CStr, CString};
use interface::get_cstring;
pub mod model;
#[doc(inline)]
pub use model::{GeoModel, OccModel};
struct FieldTag(i64);
struct ViewTag(i64);
pub struct Gmsh {
}
impl Gmsh {
pub fn initialize() -> GmshResult<Self> {
unsafe {
let mut ierr: c_int = 0;
let gmsh_name = CString::new("gmsh").unwrap();
let name_arg = gmsh_name.into_raw();
gmsh_sys::gmshInitialize(
1 as c_int,
[name_arg].as_mut_ptr(),
0,
&mut ierr,
);
let _ = CString::from_raw(name_arg);
if ierr == 0 {
let mut gmsh = Self {};
gmsh.set_number_option("General.Terminal", 1.)?;
Ok(gmsh)
} else {
Err(GmshError::Initialization)
}
}
}
pub fn create_native_model(&self, name: &'static str) -> GmshResult<GeoModel> {
GeoModel::create(self, name)
}
pub fn create_occ_model(&self, name: &'static str) -> GmshResult<OccModel> {
OccModel::create(self, name)
}
pub fn get_number_option(&self, name: &str) -> GmshResult<f64> {
let c_name = get_cstring(name)?;
let mut value: f64 = 0.;
let mut ierr: c_int = 0;
unsafe {
gmsh_sys::gmshOptionGetNumber(c_name.as_ptr(), &mut value, &mut ierr);
}
check_option_error!(ierr, value)
}
pub fn set_number_option(&mut self, name: &str, value: f64) -> GmshResult<()> {
let c_name = get_cstring(name)?;
let mut ierr: c_int = 0;
unsafe {
gmsh_sys::gmshOptionSetNumber(c_name.as_ptr(), value, &mut ierr);
}
check_option_error!(ierr, ())
}
pub fn get_string_option(&self, name: &str) -> GmshResult<String> {
let c_name = get_cstring(name)?;
let mut ierr: c_int = 0;
let mut api_val: *mut c_char = &mut 0;
unsafe {
gmsh_sys::gmshOptionGetString(c_name.as_ptr(), &mut api_val, &mut ierr);
let str_val = CStr::from_ptr(api_val as *const c_char).to_str();
let ret_val = match str_val {
Ok(val) => check_option_error!(ierr, val.to_string()),
Err(_) => Err(GmshError::CInterface),
};
if *api_val != 0 {
gmsh_sys::gmshFree(api_val as *mut c_void);
}
ret_val
}
}
pub fn set_string_option(&mut self, name: &str, value: &str) -> GmshResult<()> {
let c_name = get_cstring(name)?;
let c_value = get_cstring(value)?;
let mut ierr: c_int = 0;
unsafe {
gmsh_sys::gmshOptionSetString(c_name.as_ptr(), c_value.as_ptr(), &mut ierr);
}
check_option_error!(ierr, ())
}
}
impl Drop for Gmsh {
fn drop(&mut self) {
unsafe {
let mut ierr: c_int = 0;
gmsh_sys::gmshFinalize(&mut ierr);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::model::*;
#[test]
pub fn multiple_models() -> GmshResult<()> {
let gmsh = Gmsh::initialize()?;
let mut occ_geom = gmsh.create_occ_model("box")?;
let p1 = occ_geom.add_point(0., 0., 0.)?;
let mut native_geom = gmsh.create_native_model("bella")?;
let p2 = native_geom.add_point(1., 1., 1.)?;
let mut another_native_geom = gmsh.create_native_model("plane")?;
let p3 = another_native_geom.add_point(2., 2., 2.)?;
assert!((p1 == p2) && (p1 == p3));
Ok(())
}
#[test]
pub fn catch_unknown_options() -> GmshResult<()> {
let mut gmsh = Gmsh::initialize()?;
let geom = gmsh.create_occ_model("model")?;
let bad_opt = "Bad.Option";
let get_num_err = gmsh.get_number_option(bad_opt);
let get_str_err = gmsh.get_string_option(bad_opt);
let set_num_err = gmsh.set_number_option(bad_opt, 1.);
let set_str_err = gmsh.set_string_option(bad_opt, "Garbo");
macro_rules! is_unknown_err {
($err:ident) => {
match $err {
Err(GmshError::UnknownOption) => (),
_ => panic!(),
}
};
}
is_unknown_err!(get_num_err);
is_unknown_err!(get_str_err);
is_unknown_err!(set_num_err);
is_unknown_err!(set_str_err);
Ok(())
}
#[test]
pub fn set_and_return_opts() -> GmshResult<()> {
let mut gmsh = Gmsh::initialize()?;
let geom = gmsh.create_occ_model("model")?;
let opt = "Solver.Name0";
let str_val = "TEST_NAME_1";
gmsh.set_string_option(opt, str_val)?;
assert!(str_val == gmsh.get_string_option(opt)?);
gmsh.set_number_option("General.Axes", 5.)?;
assert!(5. == gmsh.get_number_option("General.Axes")?);
Ok(())
}
}