1#![doc(html_logo_url = "https://gitlab.onelab.info/gmsh/gmsh/raw/master/utils/icons/gmsh.svg")]
2#![deny(missing_docs)]
3extern crate gmsh_sys;
34
35use std::os::raw::{c_int, c_char, c_void};
36
37pub mod err;
38#[doc(inline)]
39pub use err::{GmshError, GmshResult};
40
41pub mod fltk;
42
43pub mod interface;
44use std::ffi::{CStr, CString};
45use interface::get_cstring;
46
47pub mod model;
48#[doc(inline)]
49pub use model::{GeoModel, OccModel};
50
51struct FieldTag(i64);
53
54struct ViewTag(i64);
56
57pub struct Gmsh {
59 }
61
62impl Gmsh {
85 pub fn initialize() -> GmshResult<Self> {
89 unsafe {
92 let mut ierr: c_int = 0;
93 let gmsh_name = CString::new("gmsh").unwrap();
94 let name_arg = gmsh_name.into_raw();
95 gmsh_sys::gmshInitialize(
96 1 as c_int,
98 [name_arg].as_mut_ptr(),
100 0,
102 &mut ierr,
104 );
105
106 let _ = CString::from_raw(name_arg);
108
109 if ierr == 0 {
110 let mut gmsh = Self {};
112 gmsh.set_number_option("General.Terminal", 1.)?;
113 Ok(gmsh)
115 } else {
116 Err(GmshError::Initialization)
117 }
118 }
119 }
120
121 pub fn create_native_model(&self, name: &'static str) -> GmshResult<GeoModel> {
123 GeoModel::create(self, name)
125 }
126
127 pub fn create_occ_model(&self, name: &'static str) -> GmshResult<OccModel> {
129 OccModel::create(self, name)
131 }
132
133 pub fn get_number_option(&self, name: &str) -> GmshResult<f64> {
135 let c_name = get_cstring(name)?;
136 let mut value: f64 = 0.;
137 let mut ierr: c_int = 0;
138 unsafe {
139 gmsh_sys::gmshOptionGetNumber(c_name.as_ptr(), &mut value, &mut ierr);
140 }
141 check_option_error!(ierr, value)
142 }
143
144 pub fn set_number_option(&mut self, name: &str, value: f64) -> GmshResult<()> {
146 let c_name = get_cstring(name)?;
147 let mut ierr: c_int = 0;
148 unsafe {
149 gmsh_sys::gmshOptionSetNumber(c_name.as_ptr(), value, &mut ierr);
150 }
151 check_option_error!(ierr, ())
152 }
153
154 pub fn get_string_option(&self, name: &str) -> GmshResult<String> {
156 let c_name = get_cstring(name)?;
157 let mut ierr: c_int = 0;
158 let mut api_val: *mut c_char = &mut 0;
159 unsafe {
160 gmsh_sys::gmshOptionGetString(c_name.as_ptr(), &mut api_val, &mut ierr);
161 let str_val = CStr::from_ptr(api_val as *const c_char).to_str();
163 let ret_val = match str_val {
164 Ok(val) => check_option_error!(ierr, val.to_string()),
166 Err(_) => Err(GmshError::CInterface),
167 };
168
169 if *api_val != 0 {
171 gmsh_sys::gmshFree(api_val as *mut c_void);
172 }
173
174 ret_val
175 }
176 }
177
178 pub fn set_string_option(&mut self, name: &str, value: &str) -> GmshResult<()> {
180 let c_name = get_cstring(name)?;
181 let c_value = get_cstring(value)?;
182 let mut ierr: c_int = 0;
183 unsafe {
184 gmsh_sys::gmshOptionSetString(c_name.as_ptr(), c_value.as_ptr(), &mut ierr);
185 }
186 check_option_error!(ierr, ())
187 }
188}
189
190impl Drop for Gmsh {
191 fn drop(&mut self) {
192 unsafe {
194 let mut ierr: c_int = 0;
196 gmsh_sys::gmshFinalize(&mut ierr);
197 }
198 }
199}
200
201#[cfg(test)]
203mod tests {
204
205 use super::*;
207 use crate::model::*;
208
209 #[test]
211 pub fn multiple_models() -> GmshResult<()> {
212 let gmsh = Gmsh::initialize()?;
213 let mut occ_geom = gmsh.create_occ_model("box")?;
214 let p1 = occ_geom.add_point(0., 0., 0.)?;
215
216 let mut native_geom = gmsh.create_native_model("bella")?;
217 let p2 = native_geom.add_point(1., 1., 1.)?;
218
219 let mut another_native_geom = gmsh.create_native_model("plane")?;
220 let p3 = another_native_geom.add_point(2., 2., 2.)?;
221
222 assert!((p1 == p2) && (p1 == p3));
223 Ok(())
224 }
225
226 #[test]
227 pub fn catch_unknown_options() -> GmshResult<()> {
228 let mut gmsh = Gmsh::initialize()?;
229 let geom = gmsh.create_occ_model("model")?;
230 let bad_opt = "Bad.Option";
231
232 let get_num_err = gmsh.get_number_option(bad_opt);
233 let get_str_err = gmsh.get_string_option(bad_opt);
234 let set_num_err = gmsh.set_number_option(bad_opt, 1.);
235 let set_str_err = gmsh.set_string_option(bad_opt, "Garbo");
236
237 macro_rules! is_unknown_err {
238 ($err:ident) => {
239 match $err {
240 Err(GmshError::UnknownOption) => (),
241 _ => panic!(),
242 }
243 };
244 }
245
246 is_unknown_err!(get_num_err);
247 is_unknown_err!(get_str_err);
248 is_unknown_err!(set_num_err);
249 is_unknown_err!(set_str_err);
250
251 Ok(())
252 }
253
254 #[test]
255 pub fn set_and_return_opts() -> GmshResult<()> {
256 let mut gmsh = Gmsh::initialize()?;
257 let geom = gmsh.create_occ_model("model")?;
258
259 let opt = "Solver.Name0";
260 let str_val = "TEST_NAME_1";
262 gmsh.set_string_option(opt, str_val)?;
263 assert!(str_val == gmsh.get_string_option(opt)?);
264
265 gmsh.set_number_option("General.Axes", 5.)?;
267 assert!(5. == gmsh.get_number_option("General.Axes")?);
268
269 Ok(())
270 }
271}