1"""Implements core functionality."""
2from cython.operator cimport dereference as deref
3
4cimport numpy as np
5import numpy as np
6import ctypes
7
8from pymoab cimport moab
9from pymoab cimport eh
10
11from .tag cimport Tag, _tagArray
12from .rng cimport Range
13from .types import check_error, np_tag_type, validate_type, _convert_array, _eh_array, _eh_py_type
14from . import types
15from libcpp.vector cimport vector
16from libcpp.string cimport string as std_string
17from libc.stdlib cimport malloc
18
19from collections import Iterable
20
21cdef void* null = NULL
22
23cdef class Core(object):
24
25    def __cinit__(self):
26        """ Constructor """
27        self.inst = new moab.Core()
28
29    def __del__(self):
30        """ Destructor """
31        del self.inst
32
33    def impl_version(self):
34        """MOAB implementation number as a float."""
35        return self.inst.impl_version()
36
37    def load_file(self, str fname, file_set = None, exceptions = ()):
38        """
39        Load or import a file.
40
41        Load a MOAB-native file or import data from some other supported file format.
42
43        Example
44        -------
45        mb = pymoab.core.Core()
46        mb.load_file("/location/of/my_file.h5m")
47
48        OR
49
50        fs = mb.create_meshset()
51        mb = pymoab.core.Core()
52        mb.load_file("/location/of/my_file.h5m", fs)
53
54        Parameters
55        ----------
56        fname : string
57            The location of the file to read.
58        file_set : EntityHandle (default None)
59            If not None, this argument must be a valid
60            entity set handle. All entities read from the file will be added to
61            this set. File metadata will be added to tags on the set.
62        exceptions : tuple
63            A tuple containing any error types that should
64            be ignored. (see pymoab.types module for more info)
65
66        Returns
67        -------
68          None.
69
70        Raises
71        ------
72          MOAB ErrorCode
73              if a MOAB error occurs
74          ValueError
75              if a parameter is not of the correct type
76        """
77        cdef bytes cfname = fname.encode('UTF-8')
78        cdef eh.EntityHandle fset
79        cdef eh.EntityHandle* ptr
80        if file_set != None:
81            fset = file_set
82            ptr = &fset
83        else:
84            ptr = NULL
85        cdef const char * file_name = cfname
86        cdef moab.ErrorCode err = self.inst.load_file(file_name,ptr)
87        check_error(err, exceptions)
88
89    def write_file(self, str fname, output_sets = None, output_tags = None, exceptions = ()):
90        """
91        Write or export a file.
92
93        Write a MOAB-native file or export data to some other supported file format.
94
95        Example
96        -------
97        mb.write_file("new_file.h5m")
98
99        Parameters
100        ----------
101        fname : string
102            the location of the file to write
103        output_sets : EntityHandle or Range (default None)
104            If not None, this argument must be a valid EntitySet handle or
105            Range containing only EntitySets.
106            When specified, the method will write any entities from the given
107            meshsets.
108        output_tags : List of PyMOAB Tags (default None)
109            If not None, this argument must be a list of valid Tags.
110            When specified, the write_file will not write any of the tag's data
111            to the specified file. All tags handles will appear in the file, however.
112
113        exceptions : tuple (default is empty tuple)
114            tuple containing any error types that should
115            be ignored (see pymoab.types module for more info)
116
117        Returns
118        -------
119        None
120
121        Raises
122        ------
123        MOAB ErrorCode
124            if a MOAB error occurs
125        ValueError
126            if a parameter is not of the correct type
127        """
128        cdef bytes cfname = fname.encode('UTF-8')
129        cdef const char * file_name = cfname
130        cdef moab.ErrorCode err
131        cdef int num_tags = 0
132        cdef _tagArray ta = _tagArray()
133
134        if output_tags:
135            assert isinstance(output_tags, Iterable), "Non-iterable output_tags argument."
136            for tag in output_tags:
137                assert isinstance(tag, Tag), "Non-tag type passed in output_tags."
138            num_tags = len(output_tags)
139            ta = _tagArray(output_tags)
140        else:
141            ta.ptr = NULL
142
143        cdef Range r = Range()
144        cdef np.ndarray[np.uint64_t, ndim=1] arr
145        if output_sets:
146          arr = _eh_array(output_sets)
147          r = Range(arr)
148          if not r.all_of_type(types.MBENTITYSET):
149              raise IOError("Only EntitySets should be passed to write file.")
150        if output_sets or output_tags:
151            err = self.inst.write_file(
152                file_name, <const char*> 0, <const char*> 0, deref(r.inst), ta.ptr, num_tags)
153        else:
154          err = self.inst.write_file(file_name)
155
156        check_error(err, exceptions)
157
158    def create_meshset(self, unsigned int options = 0x02, exceptions = ()):
159        """
160        Create a new mesh set.
161
162        Create a new mesh set. Meshsets can store entities ordered or
163        unordered. A set can include entities at most once (MESHSET_SET) or more
164        than once (MESHSET_ORDERED). Meshsets can optionally track its members
165        using adjacencies (MESHSET_TRACK_OWNER); if set, entities are deleted
166        from tracking meshsets before being deleted. This adds data to mesh
167        entities, which can be more memory intensive.
168
169        Example
170        -------
171        # Create a standard meshset
172        mb = pymoab.core.Core()
173        new_meshset = mb.create_meshset()
174
175        # Create a meshset which tracks entities
176        mb = pymoab.core.Core()
177        new_meshset = mb.create_meshset(pymoab.types.MESHSET_TRACK_OWNER)
178
179        Parameters
180        ----------
181        options : MOAB EntitySet Property (default is MESHSET_SET)
182            settings for the Meshset being created
183        exceptions : tuple (default is empty tuple)
184            A tuple containing any error types that should
185            be ignored. (see pymoab.types module for more info)
186
187        Returns
188        -------
189        MOAB Meshset (EntityHandle)
190
191        Raises
192        ------
193        MOAB ErrorCode
194            if a MOAB error occurs
195        """
196        cdef eh.EntityHandle ms_handle = 0
197        cdef moab.EntitySetProperty es_property = <moab.EntitySetProperty> options
198        cdef moab.ErrorCode err = self.inst.create_meshset(es_property, ms_handle)
199        check_error(err, exceptions)
200        return _eh_py_type(ms_handle)
201
202    def add_entity(self, eh.EntityHandle ms_handle, entity, exceptions = ()):
203        """
204        Add an entity to the specified meshset.
205
206        If meshset has MESHSET_TRACK_OWNER option set, the entity adjacencies
207        are also added to the meshset.
208
209        Example
210        -------
211        vertices # a iterable of MOAB vertex handles
212        new_meshset = mb.create_meshset()
213        mb.add_entity(new_meshset, entity)
214
215        Parameters
216        ----------
217        ms_handle : EntityHandle
218            EntityHandle of the Meshset the entities will be added to
219        entity : EntityHandle
220        exceptions : tuple (default is empty tuple)
221            A tuple containing any error types that should
222            be ignored. (see pymoab.types module for more info)
223
224        Returns
225        -------
226        None
227
228        Raises
229        ------
230        MOAB ErrorCode
231            if a MOAB error occurs
232        """
233        cdef moab.ErrorCode err
234        cdef Range r = Range(entity)
235        err = self.inst.add_entities(ms_handle, deref(r.inst))
236        check_error(err, exceptions)
237
238    def add_entities(self, eh.EntityHandle ms_handle, entities, exceptions = ()):
239        """
240        Add entities to the specified meshset. Entities can be provided either
241        as a pymoab.rng.Range o bject or as an iterable of EntityHandles.
242
243        If meshset has MESHSET_TRACK_OWNER option set, adjacencies are also
244        added to the meshset.
245
246        Example
247        -------
248        vertices # a iterable of MOAB vertex handles
249        new_meshset = mb.create_meshset()
250        mb.add_entities(new_meshset, entities)
251
252        Parameters
253        ----------
254        ms_handle : EntityHandle
255            EntityHandle of the Meshset the entities will be added to
256        entities : Range or iterable of EntityHandles
257            Entities that to add to the Meshset
258        exceptions : tuple (default is empty tuple)
259            A tuple containing any error types that should
260            be ignored. (see pymoab.types module for more info)
261
262        Returns
263        -------
264        None
265
266        Raises
267        ------
268        MOAB ErrorCode
269            if a MOAB error occurs
270        ValueError
271            if an EntityHandle is not of the correct type
272        """
273        cdef moab.ErrorCode err
274        cdef Range r
275        cdef np.ndarray[np.uint64_t, ndim=1] arr
276        if isinstance(entities, Range):
277           r = entities
278           err = self.inst.add_entities(ms_handle, deref(r.inst))
279        else:
280           arr = _eh_array(entities)
281           err = self.inst.add_entities(ms_handle, <eh.EntityHandle*> arr.data, len(entities))
282        check_error(err, exceptions)
283
284    def remove_entity(self, eh.EntityHandle ms_handle, entity, exceptions = ()):
285        """
286        Remove an entity from the specified meshset.
287
288        If meshset has MESHSET_TRACK_OWNER option set, entity adjacencies
289        are updated.
290
291        Example
292        -------
293        new_meshset = mb.create_meshset()
294        mb.remove_entity(new_meshset, entity)
295
296        Parameters
297        ----------
298        ms_handle : EntityHandle
299            EntityHandle of the Meshset the entities will be added to
300        entity : EntityHandle
301        exceptions : tuple (default is empty tuple)
302            A tuple containing any error types that should
303            be ignored. (see pymoab.types module for more info)
304
305        Returns
306        -------
307        None
308
309        Raises
310        ------
311        MOAB ErrorCode
312            if a MOAB error occurs
313        """
314        cdef moab.ErrorCode err
315        cdef Range r = Range(entity)
316        err = self.inst.remove_entities(ms_handle, deref(r.inst))
317        check_error(err, exceptions)
318
319    def remove_entities(self, eh.EntityHandle ms_handle, entities, exceptions = ()):
320        """
321        Remove entities from the specified meshset. Entities can be provided either
322        as a pymoab.rng.Range object or as an iterable of EntityHandles.
323
324        If meshset has MESHSET_TRACK_OWNER option set, adjacencies in entities
325        in entities are updated.
326
327        Example
328        -------
329        vertices # an iterable of MOAB vertex handles
330        new_meshset = mb.create_meshset()
331        mb.add_entities(new_meshset, entities)
332        # keep only the first entity in this meshset
333        mb.remove_entities(new_meshset, entities[1:])
334
335        Parameters
336        ----------
337        ms_handle : EntityHandle
338            EntityHandle of the Meshset the entities will be removed from
339        entities : Range or iterable of EntityHandles
340            Entities to remove from the Meshset
341        exceptions : tuple (default is empty tuple)
342            A tuple containing any error types that should
343            be ignored. (see pymoab.types module for more info)
344
345        Returns
346        -------
347        None
348
349        Raises
350        ------
351        MOAB ErrorCode
352            if a MOAB error occurs
353        ValueError
354            if an EntityHandle is not of the correct type
355        """
356        cdef moab.ErrorCode err
357        cdef Range r
358        cdef np.ndarray[np.uint64_t, ndim=1] arr
359        if isinstance(entities, Range):
360            r = entities
361            err = self.inst.remove_entities(ms_handle, deref(r.inst))
362        else:
363            arr = _eh_array(entities)
364            err = self.inst.remove_entities(ms_handle, <eh.EntityHandle*> arr.data, len(entities))
365        check_error(err, exceptions)
366
367    def delete_entity(self, entity, exceptions = ()):
368        """
369        Delete an entity from the database.
370
371        If the entity is contained in any meshsets, it are removed
372        from those meshsets which were created with MESHSET_TRACK_OWNER option.
373
374        Example
375        -------
376        mb.delete_entity(entity)
377
378        Parameters
379        ----------
380        entity : EntityHandle
381        exceptions : tuple (default is empty tuple)
382            A tuple containing any error types that should
383            be ignored. (see pymoab.types module for more info)
384
385        Returns
386        -------
387        None
388
389        Raises
390        ------
391        MOAB ErrorCode
392            if a MOAB error occurs
393        ValueError
394            if an EntityHandle is not of the correct type
395        """
396        cdef moab.ErrorCode err
397        cdef Range r = Range(entity)
398        err = self.inst.delete_entities(deref(r.inst))
399        check_error(err, exceptions)
400
401    def delete_entities(self, entities, exceptions = ()):
402        """
403        Delete entities from the database.
404
405        If any of the entities are contained in any meshsets, they are removed
406        from those meshsets which were created with MESHSET_TRACK_OWNER option.
407
408        Example
409        -------
410        mb = pymoab.core.Core()
411        # generate mesh using other Core functions #
412        mb.delete_entities(entities)
413
414        Parameters
415        ----------
416        entities : Range or iterable of EntityHandles
417            Entities that to delete from the database
418        exceptions : tuple (default is empty tuple)
419            A tuple containing any error types that should
420            be ignored. (see pymoab.types module for more info)
421
422        Returns
423        -------
424        None
425
426        Raises
427        ------
428        MOAB ErrorCode
429            if a MOAB error occurs
430        ValueError
431            if an EntityHandle is not of the correct type
432        """
433        cdef moab.ErrorCode err
434        cdef Range r
435        cdef np.ndarray[np.uint64_t, ndim=1] arr
436        if isinstance(entities, Range):
437            r = entities
438            err = self.inst.delete_entities(deref(r.inst))
439        else:
440            arr = _eh_array(entities)
441            err = self.inst.delete_entities(<eh.EntityHandle*> arr.data, len(entities))
442        check_error(err, exceptions)
443
444    def create_vertices(self, coordinates, exceptions = ()):
445        """
446        Create vertices using the specified x,y,z coordinates.
447
448        Example
449        -------
450        mb = pymoab.core.Core()
451        #create two vertices
452        coords = np.array((0, 0, 0, 1, 1, 1),dtype='float64')
453        verts = mb.create_vertices(coords)
454
455        OR
456
457        mb = pymoab.core.Core()
458        #create two vertices
459        coords = [[0.0, 0.0, 0.0],[1.0, 1.0, 1.0]]
460        verts = mb.create_vertices(coords)
461
462        Parameters
463        ----------
464        coordinates : 1-D or 2-D iterable
465            Coordinates can be provided as either a 1-D iterable of 3*n floats
466            or as a 2-D array with dimensions (n,3) where n is the number of
467            vertices being created.
468        exceptions : tuple (default is empty tuple)
469            A tuple containing any error types that should
470            be ignored. (see pymoab.types module for more info)
471
472        Returns
473        -------
474        MOAB Range of EntityHandles for the vertices
475
476        Raises
477        ------
478        MOAB ErrorCode
479            if a MOAB error occurs
480        ValueError
481            if an EntityHandle is not of the correct type
482        """
483        cdef Range rng = Range()
484        cdef np.ndarray coords_as_arr = np.asarray(coordinates)
485        if coords_as_arr.ndim > 1:
486            assert coords_as_arr.ndim == 2
487            coords_as_arr = coords_as_arr.flatten()
488        cdef np.ndarray[np.float64_t, ndim=1] coords_arr = _convert_array(coords_as_arr, (float, np.float64), np.float64)
489        assert len(coords_arr)%3 == 0, "Incorrect number of coordinates provided."
490        cdef moab.ErrorCode err = self.inst.create_vertices(<double *> coords_arr.data,
491                                                            len(coords_arr)//3,
492                                                            deref(rng.inst))
493        check_error(err, exceptions)
494        return rng
495
496    def create_element(self, int entity_type, connectivity, exceptions = ()):
497        """
498        Create an elment of type, entity_type, using vertex EntityHandles in connectivity.
499
500        Example
501        -------
502        mb = core.Core()
503        # create some vertices
504        coords = np.array((0,0,0,1,0,0,1,1,1),dtype='float64')
505        verts = mb.create_vertices(coords)
506
507        # create the triangle in the database
508        tri_verts = np.array(((verts[0],verts[1],verts[2]),),dtype='uint64')
509        tris = mb.create_element(types.MBTRI,tri_verts)
510
511        OR
512
513        tri_verts = [verts[0],verts[1],verts[2]]
514        tris = mb.create_element(types.MBTRI,tri_verts)
515
516
517        Parameters
518        ----------
519        entity_type : MOAB EntityType (see pymoab.types module)
520            type of entity to create (MBTRI, MBQUAD, etc.)
521        coordinates : iterable of EntityHandles
522            1-D array-like iterable of vertex EntityHandles the element is to be
523            created from
524        exceptions : tuple (default is empty tuple)
525            A tuple containing any error types that should
526            be ignored. (see pymoab.types module for more info)
527
528        Returns
529        -------
530        EntityHandle of element created
531
532        Raises
533        ------
534        MOAB ErrorCode
535            if a MOAB error occurs
536        ValueError
537            if an EntityHandle is not of the correct type
538        """
539        cdef moab.EntityType typ = <moab.EntityType> entity_type
540        cdef eh.EntityHandle handle = 0
541        if isinstance(connectivity, Range):
542            connectivity = list(connectivity)
543        cdef np.ndarray[np.uint64_t, ndim=1] conn_arr = _eh_array(connectivity)
544        cdef int nnodes = len(connectivity)
545        cdef moab.ErrorCode err = self.inst.create_element(typ,
546            <eh.EntityHandle*> conn_arr.data, nnodes, handle)
547        check_error(err, exceptions)
548        return _eh_py_type(handle)
549
550    def create_elements(self, int entity_type, connectivity, exceptions = ()):
551        """
552        Create an elments of type, entity_type, using vertex EntityHandles in connectivity.
553
554        Example
555        -------
556        mb = core.Core()
557        # create some vertices for triangle 1
558        coords1 = np.array((0,0,0,1,0,0,1,1,1),dtype='float64')
559        verts1 = mb.create_vertices(coords)
560        # create some more vertices for triangle 2
561        coords2 = np.array((1,2,3,4,5,6,1,1,1),dtype='float64')
562        verts2 = mb.create_vertices(coords)
563
564        # create the triangles in the database
565        tri_verts = [[verts1[0],verts1[1],verts1[2]],[verts2[0],verts2[1],verts2[2]]
566        tris = mb.create_elements(types.MBTRI,tri_verts)
567
568        OR
569
570        tri_verts = [verts1,verts2]
571        tris = mb.create_elements(types.MBTRI,tri_verts)
572
573        Parameters
574        ----------
575        entity_type : MOAB EntityType (see pymoab.types module)
576            type of entity to create (MBTRI, MBQUAD, MBHEX, etc.)
577        coordinates : iterable of EntityHandles
578            2-D array-like iterable of vertex EntityHandles the elements are to
579            be created from. Each entry in the array should have an appropriate
580            length for the element type being created (e.g. for MBTRI each entry
581            has length 3).
582        exceptions : tuple (default is empty tuple)
583            A tuple containing any error types that should
584            be ignored. (see pymoab.types module for more info)
585
586        Returns
587        -------
588        EntityHandles of element created as a Range
589
590        Raises
591        ------
592        MOAB ErrorCode
593            if a MOAB error occurs
594        ValueError
595            if an EntityHandle is not of the correct type
596        """
597        cdef int i
598        cdef moab.ErrorCode err
599        cdef moab.EntityType typ = <moab.EntityType> entity_type
600        cdef np.ndarray connectivity_as_arr = np.asarray(connectivity)
601        assert connectivity_as_arr.ndim == 2 #required for now
602        cdef int nelems = connectivity_as_arr.shape[0]
603        cdef int nnodes = connectivity_as_arr.shape[1]
604        cdef np.ndarray[np.uint64_t, ndim=1] connectivity_i
605        cdef np.ndarray[np.uint64_t, ndim=1] handles = np.empty(nelems, 'uint64')
606        for i in range(nelems):
607            connectivity_i = _eh_array(connectivity[i])
608            err = self.inst.create_element(typ, <eh.EntityHandle*> connectivity_i.data,
609                                           nnodes, deref((<eh.EntityHandle*> handles.data)+i))
610            check_error(err, exceptions)
611        return Range(handles)
612
613    def tag_get_handle(self,
614                       name,
615                       size = None,
616                       tag_type = None,
617                       storage_type = None,
618                       create_if_missing = False,
619                       default_value = None,
620                       exceptions = ()):
621        """
622        Retrieve and/or create tag handles for storing data on mesh elements, vertices,
623        meshsets, etc.
624
625
626        Example - creating a new tag handle
627        -------
628        # new MOAB core instance
629        mb = core.Core()
630        #
631        tag_type = pymoab.types.MB_TYPE_INTEGER # define the tag's data type
632        tag_size = 1 # the tag size (1 integer value)
633        storage_type = pymoab.types.MB_TAG_DENSE # define the storage type
634        tag_handle = mb.tag_get_handle("NewDataTag",
635                                       tag_size,
636                                       tag_type,
637                                       storage_type,
638                                       create_if_missing = True)
639
640        Example - retrieving an existing tag handle
641        -------
642        # new MOAB core instance
643        mb = core.Core()
644        #
645        tag_type = pymoab.types.MB_TYPE_INTEGER # define the tag's data type
646        tag_size = 1 # the tag size (1 integer value)
647        tag_handle = mb.tag_get_handle("NewDataTag",
648                                       tag_size,
649                                       tag_type)
650
651        OR
652
653        # find the tag by name rather than using the full signature (less robust)
654        tag_handle = mb.tag_get_handle("NewDataTag")
655
656        Parameters
657        ----------
658        name : string
659            name of the tag
660        size : int
661            number of values the tag contains (or the number of characters in
662            the case of an opaque tag)
663        tag_type : MOAB DataType
664            indicates the data type of the tag (MB_TYPE_DOUBLE, MB_TYPE_INTEGER,
665            MB_TYPE_OPAQUE, etc.)
666        storage_type : MOAB tag storage type (MB_TAG_DENSE, MB_TAG_SPARSE, etc.)
667            in advanced use of the database, this flag controls how this tag's
668            data is stored in memory. The two most common storage types are
669
670            MB_TYPE_SPARSE -  sparse tags are stored as a list of (entity
671                handle, tag value) tuples, one list per sparse tag, sorted by
672                entity handle
673
674            MB_TYPE_DENSE - Dense tag values are stored in arrays which match
675                arrays of contiguous entity handles. Dense tags are more
676                efficient in both storage and memory if large numbers of
677                entities are assigned the same tag. Storage for a given dense
678                tag is not allocated until a tag value is set on an entity;
679                memory for a given dense tag is allocated for all entities in a
680                given sequence at the same time.  Sparse: Sparse tags are stored
681                as a list of (entity handle, tag value) tuples, one list per
682                sparse tag, sorted by entity handle.
683
684            MB_TYPE_BIT - Bit tags are stored similarly to dense tags, but with
685                special handling to allow allocation in bit-size amounts per
686                entity.
687        create_if_missing : bool (default False)
688            indicates to the database instance that the tag should be created if
689            it cannot be found (requires that all arguments are provided to
690            fully define the tag)
691        default_value : default tag value (default None)
692            valid_default value fo the tag based on the tag type and length
693            specified in previous arguments. If no default value is specified,
694            then the returned tag will have no default value in the MOAB
695            instance.
696        exceptions : tuple (default is empty tuple)
697            A tuple containing any error types that should
698            be ignored. (see pymoab.types module for more info)
699
700        Returns
701        -------
702        MOAB TagHandle
703
704        Raises
705        ------
706        MOAB ErrorCode
707            if a MOAB error occurs
708        """
709        cdef bytes cname = str(name).encode('UTF-8')
710        cdef const char* tag_name = cname
711        cdef Tag tag = Tag()
712        cdef moab.ErrorCode err
713        cdef moab.DataType tt
714        cdef int s
715        cdef np.ndarray default_val_arr
716        cdef const void* def_val_ptr = NULL
717        incomplete_tag_specification = False
718
719        # tag_type, size, and storage_type
720        # should either be all None
721        # or all non-None
722        all_none = all(v == None for v in [size, tag_type, storage_type])
723        all_non_none = all( v != None for v in [size, tag_type, storage_type])
724        if not (all_none or all_non_none):
725            raise ValueError("""
726            Partial tag specification supplied. Please only provide tag name for
727            a name-based tag retrieval or provide a tag name, size, type, and
728            storage type for a more detailed specification of the tag to
729            retrieve.
730            """)
731
732        # if a default value is provided, set ptr
733        if default_value is not None:
734            if tag_type is types.MB_TYPE_OPAQUE:
735                default_val_arr = np.asarray((default_value,), dtype='S'+str(size))
736            else:
737                default_val_arr = np.asarray(default_value, dtype=np.dtype(np_tag_type(tag_type)))
738            # validate default value data for tag type and length
739            default_val_arr = validate_type(tag_type,size,default_val_arr)
740            def_val_ptr = <const void*> default_val_arr.data
741
742        if tag_type is None and size is None and storage_type is None:
743            err = self.inst.tag_get_handle(tag_name, tag.inst)
744        else:
745            tt = tag_type
746            s = size
747            flags = storage_type|types.MB_TAG_CREAT if create_if_missing else storage_type
748            err = self.inst.tag_get_handle(tag_name, s, tt, tag.inst, flags, def_val_ptr, NULL)
749
750        check_error(err, exceptions)
751        return tag
752
753    def tag_set_data(self, Tag tag, entity_handles, data, exceptions = ()):
754        """
755        Set tag data for a set of MOAB entities. The data provided must be
756        compatible with the tag's data type and be of an appropriate shape and
757        size depending on the number of entity handles are provided.
758
759        This function will ensure that the data is of the correct type and
760        length based on the tag it is to be applied to. Data can be passed as a
761        1-D iterable of appropriate length or as 2-D iterable with entries for
762        each entity handle equal to the length of the tag.
763
764        Example
765        -------
766        # create moab core instance
767        mb = core.Core()
768        # create some vertices
769        coords = np.array((0,0,0,1,0,0,1,1,1),dtype='float64')
770        verts = mb.create_vertices(coords)
771        # create a new tag for data
772        tag_length = 2
773        tag_type = pymoab.types.MB_TYPE_DOUBLE
774        data_tag = mb.tag_get_handle("Data",
775                                     tag_length,
776                                     tag_type,
777                                     create_if_missing = True)
778        # some sample data
779        data = np.array([1.0,2.0,3.0,4.0,5.0,6.0], dtype = 'float')
780        #use this function to tag vertices with the data
781        mb.tag_set_data(data_tag, verts, data)
782
783        OR
784
785        # some sample data
786        data = np.array([[1.0,2.0],[3.0,4.0],[5.0,6.0]], dtype = 'float')
787        #use this function to tag vertices with the data
788        mb.tag_set_data(data_tag, verts, data)
789
790        OR
791
792        ### pass data as a an iterable object ###
793        # some sample data
794        data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
795        #use this function to tag vertices with the data
796        mb.tag_set_data(data_tag, verts, data)
797
798        OR
799
800        ### pass data as a nested iterable object ###
801        ### (can be convenient for vector tags) ###
802        # some sample data
803        data = [[1.0, 2.0],[3.0, 4.0],[4.0, 5.0]]
804        #use this function to tag vertices with the data
805        mb.tag_set_data(data_tag, verts, data)
806
807        OR
808
809        ### tag a single vertex ###
810        # get a single vertex
811        vertex_to_tag = verts[0]
812        data = [1.0, 2.0]
813        #use this function to tag vertices with the data
814        mb.tag_set_data(data_tag, vertex, data)
815
816        Parameters
817        ----------
818        tag : MOAB TagHandle
819            tag to which the data is applied
820        entity_handles : iterable of MOAB EntityHandle's or single EntityHandle
821            the EntityHandle(s) to tag the data on. This can be any iterable of
822            EntityHandles or a single EntityHandle.
823        exceptions : tuple (default is empty tuple)
824            A tuple containing any error types that should
825            be ignored. (see pymoab.types module for more info)
826        data : iterable of data to set for the tag
827            This is a 1-D or 2-D iterable of data values to set for the tag and
828            entities specified in the entity_handles parameter. If the data is
829            1-D then it must be of size len(entity_handles)*tag_length. If the
830            data is 2-D then it must be of size len(entity_handles) with each
831            second dimension entry having a length equal to the tag's
832            length. All entries in the data must be of the proper type for the
833            tag or be able to be converted to that type.
834        Returns
835        -------
836        None
837
838        Raises
839        ------
840        MOAB ErrorCode
841            if a MOAB error occurs
842        ValueError
843            if a data entry is not of the correct type or cannot be converted to
844            the correct type
845        """
846        cdef moab.ErrorCode err
847        cdef np.ndarray ehs
848        cdef moab.DataType tag_type = moab.MB_MAX_DATA_TYPE
849        # create a numpy array for the entity handles to be tagged
850        if isinstance(entity_handles, _eh_py_type):
851            ehs = _eh_array([entity_handles,])
852        else:
853            ehs = _eh_array(entity_handles)
854        err = self.inst.tag_get_data_type(tag.inst, tag_type);
855        check_error(err, ())
856        cdef int length = 0
857        err = self.inst.tag_get_length(tag.inst,length);
858        check_error(err,())
859        cdef np.ndarray data_arr = np.asarray(data)
860        # protect against shallow copy, delayed evaluation problem
861        data_arr = np.copy(data_arr)
862        #if the data array is not flat it must be dimension 2 and have
863        #as many entries as entity handles provided
864        if data_arr.ndim > 1:
865            assert data_arr.ndim == 2
866            assert data_arr.shape[0] == ehs.size
867            #each entry must be equal to the tag length as well
868            for entry in data_arr:
869                len(entry) == length
870            #if all of this is true, then flatten the array and continue
871            data_arr = data_arr.flatten()
872        error_str = "Incorrect data length"
873        if types.MB_TYPE_OPAQUE == tag_type:
874            assert data_arr.size == ehs.size, error_str
875        else:
876            assert data_arr.size == ehs.size*length, error_str
877        data_arr = validate_type(tag_type,length,data_arr)
878        err = self.inst.tag_set_data(tag.inst, <eh.EntityHandle*> ehs.data, ehs.size, <const void*> data_arr.data)
879        check_error(err, exceptions)
880
881    def tag_get_data(self, Tag tag, entity_handles, flat = False, exceptions = ()):
882        """
883        Retrieve tag data for a set of entities. Data will be returned as a 2-D
884        array with number of entries equal to the number of EntityHandles passed
885        to the function by default. Each entry in the array will be equal to the
886        tag's length. A flat array of data can also be returned if specified by
887        setting the 'flat' parameter to True.
888
889        Example
890        -------
891        mb = core.Core()
892        coords = np.array((0,0,0,1,0,0,1,1,1),dtype='float64')
893        verts = mb.create_vertices(coords)
894        # create a new tag for data
895        tag_length = 2
896        tag_type = pymoab.types.MB_TYPE_DOUBLE
897        data_tag = mb.tag_get_handle("Data",
898                                     tag_length,
899                                     tag_type,
900                                     create_if_missing = True)
901        # some sample data
902        data = np.array([1.0,2.0,3.0,4.0,5.0,6.0], dtype = 'float')
903        # use this function to tag vertices with the data
904        mb.tag_set_data(data_tag, verts, data)
905
906        # now retrieve this tag's data for the vertices from the instance
907        data = mb.tag_get_data(data_tag, verts) # returns 2-D array
908
909        OR
910
911        # now retrieve this tag's data for the vertices from the instance
912        # returns 1-D array of len(verts)*tag_length
913        data = mb.tag_get_data(data_tag, verts, flat=True)
914
915        Parameters
916        ----------
917        tag : MOAB TagHandle
918            the tag for which data is to be retrieved
919        entity_handles : iterable of MOAB EntityHandles or a single EntityHandle
920            the EntityHandle(s) to retrieve data for.
921        flat : bool (default is False)
922            Indicates the structure in which the data is returned. If False, the
923            array is returned as a 2-D numpy array of len(entity_handles) with
924            each second dimension entry equal to the length of the tag data. If
925            True, the data is returned as a 1-D numpy array of length
926            len(entity_handles)*tag_length.
927        exceptions : tuple (default is empty tuple)
928            A tuple containing any error types that should
929            be ignored. (see pymoab.types module for more info)
930
931        Returns
932        -------
933        Numpy array of data with dtype matching that of the tag's type
934
935        Raises
936        ------
937        MOAB ErrorCode
938            if a MOAB error occurs
939        ValueError
940            if an EntityHandle is not of the correct type
941        """
942        cdef moab.ErrorCode err
943        cdef np.ndarray ehs
944        cdef moab.DataType tag_type = moab.MB_MAX_DATA_TYPE
945        # create a numpy array for the entity handles to be tagged
946        if isinstance(entity_handles, _eh_py_type):
947            ehs = _eh_array([entity_handles,])
948        else:
949            ehs = _eh_array(entity_handles)
950        # get the tag type and length for validation
951        err = self.inst.tag_get_data_type(tag.inst, tag_type);
952        check_error(err,())
953        cdef int length = 0
954        err = self.inst.tag_get_length(tag.inst,length);
955        check_error(err,())
956        #create array to hold data
957        cdef np.ndarray data
958        if tag_type is types.MB_TYPE_OPAQUE:
959            data = np.empty((ehs.size,),dtype='S'+str(length))
960        else:
961            data = np.empty((length*ehs.size,), dtype=np.dtype(np_tag_type(tag_type)))
962        err = self.inst.tag_get_data(tag.inst, <eh.EntityHandle*> ehs.data, ehs.size, <void*> data.data)
963        check_error(err, exceptions)
964        # return data as user specifies
965        if tag_type is types.MB_TYPE_OPAQUE:
966            data = data.astype('str')
967        if flat:
968            return data
969        else:
970            entry_len = 1 if tag_type == types.MB_TYPE_OPAQUE else length
971            return data.reshape((ehs.size,entry_len))
972
973    def tag_delete_data(self, Tag tag, entity_handles, exceptions = ()):
974        """
975        Delete the data of a tag on a set of EntityHandle's. Only sparse tag
976        data are deleted with this method; dense tags are deleted by deleting
977        the tag itself using tag_delete.
978
979        Example
980        -------
981        # delete data associated with the iterable entities from the tag data_tag
982        data = mb.tag_delete_data(data_tag, entities)
983
984        Parameters
985        ----------
986        tag : MOAB TagHandle
987            the tag from which data is to be deleted
988        entity_handles : iterable of MOAB EntityHandles or a single EntityHandle
989            the EntityHandle(s) to delete data from. This can be any iterable of
990            EntityHandles or a single EntityHandle.
991
992        Returns
993        -------
994        None
995
996        Raises
997        ------
998        MOAB ErrorCode
999            if a MOAB error occurs
1000        ValueError
1001            if an EntityHandle is not of the correct type
1002        """
1003        cdef moab.ErrorCode err
1004        cdef np.ndarray ehs
1005        # create a numpy array for the entity handles to be tagged
1006        if isinstance(entity_handles, _eh_py_type):
1007            ehs = _eh_array([entity_handles,])
1008        else:
1009            ehs = _eh_array(entity_handles)
1010        # Delete the data
1011        err = self.inst.tag_delete_data(tag.inst, <eh.EntityHandle*> ehs.data, ehs.size)
1012        check_error(err, exceptions)
1013
1014    def tag_delete(self, Tag tag, exceptions = ()):
1015        """
1016        Removes the tag from the database and deletes all of its associated data.
1017
1018        Example
1019        -------
1020        # delete a tag that was previously created
1021        data = mb.tag_delete(data_tag)
1022
1023        Parameters
1024        ----------
1025        tag : MOAB TagHandle
1026            the tag from which data is to be deleted
1027
1028        Returns
1029        -------
1030        None
1031
1032        Raises
1033        ------
1034        MOAB ErrorCode
1035            if a MOAB error occurs
1036        """
1037        cdef moab.ErrorCode err
1038        # Delete the tag
1039        err = self.inst.tag_delete(tag.inst)
1040        check_error(err, exceptions)
1041
1042    def get_adjacencies(self, entity_handles, int to_dim, bint create_if_missing = False, int op_type = types.INTERSECT, exceptions = ()):
1043        """
1044        Get the adjacencies associated with a range of entities to entities of a specified dimension.
1045
1046        Example
1047        -------
1048        mb = core.Core()
1049        coords = np.array((0,0,0,1,0,0,1,1,1),dtype='float64')
1050        verts = mb.create_vertices(coords)
1051        #create elements
1052        verts = np.array(((verts[0],verts[1],verts[2]),),dtype='uint64')
1053        tris = mb.create_elements(types.MBTRI,verts)
1054        #get the adjacencies of the triangle of dim 1 (should return the vertices)
1055        adjacent_verts = mb.get_adjacencies(tris, 0, False)
1056        #now get the edges and ask MOAB to create them for us
1057        adjacent_edges = mb.get_adjacencies(tris, 1, True)
1058
1059        Parameters
1060        ----------
1061        entity_handles : iterable of MOAB EntityHandles or a single EntityHandle
1062            the EntityHandle(s) to get the adjacencies of. This can be any
1063            iterable of EntityHandles or a single EntityHandle.
1064        to_dim : integer
1065            value indicating the dimension of the entities to return
1066        create_if_missing : bool (default is false)
1067            this parameter indicates that any adjacencies that do not exist
1068            should be created. For instance, in the example above, the second
1069            call to get_adjacencies will create the edges of the triangle which
1070            did not previously exist in the mesh database.
1071        op_type : int (default is 0 or INTERSECT)
1072            this value indicates how overlapping adjacencies should be handled
1073            INTERSECT - will return the intersection of the adjacencies between mesh elements
1074            UNION - will return the union of all adjacencies for the elements provided to the function
1075        exceptions : tuple (default is empty tuple)
1076            A tuple containing any error types that should
1077            be ignored. (see pymoab.types module for more info)
1078
1079        Returns
1080        -------
1081        Range of MOAB EntityHAndles
1082
1083        Raises
1084        ------
1085        MOAB ErrorCode
1086            if a MOAB error occurs
1087        ValueError
1088            if an EntityHandle is not of the correct type
1089        """
1090        cdef moab.ErrorCode err
1091        cdef Range r
1092        cdef Range adj = Range()
1093        r = Range(entity_handles)
1094        err = self.inst.get_adjacencies(deref(r.inst), to_dim, create_if_missing, deref(adj.inst), op_type)
1095        check_error(err, exceptions)
1096        return adj
1097
1098    def type_from_handle(self, entity_handle):
1099        """
1100        Returns the type (MBVERTEX, MBQUAD, etc.) of an EntityHandle
1101
1102        Example
1103        -------
1104        mb = core.Core()
1105        coords = np.array((0,0,0,1,0,0,1,1,1),dtype='float64')
1106        verts = mb.create_vertices(coords)
1107        #create elements
1108        verts = np.array(((verts[0],verts[1],verts[2]),),dtype='uint64')
1109        tris = mb.create_elements(types.MBTRI,verts)
1110        entity_type = mb.type_from_handle(tris[0])
1111
1112        Parameters
1113        ----------
1114        entity_handle : a MOAB EntityHandle
1115
1116        Returns
1117        -------
1118        An integer representing the EntityType
1119
1120        Raises
1121        ------
1122        MOAB ErrorCode
1123            if a MOAB error occurs
1124        """
1125        cdef moab.EntityType t
1126        t = self.inst.type_from_handle(<unsigned long> entity_handle)
1127        return t
1128
1129    def get_child_meshsets(self, meshset_handle, num_hops = 1, exceptions = ()):
1130        """
1131        Retrieves the child meshsets from a parent meshset.
1132
1133        Example
1134        -------
1135        mb = core.Core()
1136        parent_set = mb.create_meshset()
1137        child_set = mb.create_meshset()
1138        mb.add_parent_meshset(child_set, parent_set)
1139        child_sets = mb.get_child_meshsets(parent_set)
1140
1141        Parameters
1142        ----------
1143        meshset_handle : MOAB EntityHandle
1144            handle of the parent meshset
1145        num_hops : integer (default is 1)
1146            the number of generations to traverse when collecting child
1147            meshsets.  If this value is zero, then the maximum number of
1148            generations will be traversed.
1149        exceptions : tuple (default is empty tuple)
1150            A tuple containing any error types that should
1151            be ignored. (see pymoab.types module for more info)
1152
1153        Returns
1154        -------
1155        Range of MOAB EntityHandles
1156
1157        Raises
1158        ------
1159        MOAB ErrorCode
1160            if a MOAB error occurs
1161        ValueError
1162            if the Meshset EntityHandle is not of the correct type
1163        """
1164        cdef moab.ErrorCode err
1165        cdef Range r = Range()
1166        err = self.inst.get_child_meshsets(<unsigned long> meshset_handle, deref(r.inst), num_hops)
1167        check_error(err, exceptions)
1168        return r
1169
1170    def get_parent_meshsets(self, meshset_handle, num_hops = 1, exceptions = ()):
1171        """
1172        Retrieves the parent meshsets from a child meshset.
1173
1174        Example
1175        -------
1176        mb = core.Core()
1177        parent_set = mb.create_meshset()
1178        child_set = mb.create_meshset()
1179        mb.add_parent_meshset(child_set, parent_set)
1180        parent_sets = mb.get_parent_meshsets(child_set)
1181
1182        Parameters
1183        ----------
1184        meshset_handle : MOAB EntityHandle
1185            handle of the child meshset
1186        num_hops : integer (default is 1)
1187            the number of generations to traverse when collecting
1188            meshsets.  If this value is zero, then the maximum number of
1189            generations will be traversed.
1190        exceptions : tuple (default is empty tuple)
1191            A tuple containing any error types that should
1192            be ignored. (see pymoab.types module for more info)
1193
1194        Returns
1195        -------
1196        Range of MOAB EntityHandles
1197
1198        Raises
1199        ------
1200        MOAB ErrorCode
1201            if a MOAB error occurs
1202        ValueError
1203            if the Meshset EntityHandle is not of the correct type
1204        """
1205        cdef moab.ErrorCode err
1206        cdef Range r = Range()
1207        err = self.inst.get_parent_meshsets(<unsigned long> meshset_handle, deref(r.inst), 0)
1208        check_error(err, exceptions)
1209        return r
1210
1211    def add_parent_meshset(self, child_meshset, parent_meshset, exceptions = ()):
1212        """
1213        Add a parent meshset to a meshset.
1214
1215        Example
1216        -------
1217        mb = core.Core()
1218        parent_set = mb.create_meshset()
1219        child_set = mb.create_meshset()
1220        mb.add_parent_meshset(child_set, parent_set)
1221
1222        Parameters
1223        ----------
1224        child_meshset : MOAB EntityHandle
1225            handle of the child meshset
1226        parent_meshset : MOAB EntityHandle
1227            handle of the parent meshset
1228        exceptions : tuple (default is empty tuple)
1229            A tuple containing any error types that should
1230            be ignored. (see pymoab.types module for more info)
1231
1232        Returns
1233        -------
1234        None
1235
1236        Raises
1237        ------
1238        MOAB ErrorCode
1239            if a MOAB error occurs
1240        ValueError
1241            if the Meshset EntityHandle is not of the correct type
1242        """
1243        cdef moab.ErrorCode err
1244        err = self.inst.add_parent_meshset(<unsigned long> child_meshset, <unsigned long> parent_meshset)
1245        check_error(err, exceptions)
1246
1247    def add_child_meshset(self, parent_meshset, child_meshset, exceptions = ()):
1248        """
1249        Add a child meshset to a meshset.
1250
1251        Example
1252        -------
1253        mb = core.Core()
1254        parent_set = mb.create_meshset()
1255        child_set = mb.create_meshset()
1256        mb.add_child_meshset(parent_set, child_set)
1257
1258        Parameters
1259        ----------
1260        parent_meshset : MOAB EntityHandle
1261            handle of the parent meshset
1262        child_meshset : MOAB EntityHandle
1263            handle of the child meshset
1264        exceptions : tuple (default is empty tuple)
1265            A tuple containing any error types that should
1266            be ignored. (see pymoab.types module for more info)
1267
1268        Returns
1269        -------
1270        None
1271
1272        Raises
1273        ------
1274        MOAB ErrorCode
1275            if a MOAB error occurs
1276        ValueError
1277            if the Meshset EntityHandle is not of the correct type
1278        """
1279        cdef moab.ErrorCode err
1280        err = self.inst.add_child_meshset(<unsigned long> parent_meshset, <unsigned long> child_meshset)
1281        check_error(err, exceptions)
1282
1283    def add_parent_child(self, parent_meshset, child_meshset, exceptions = ()):
1284        """
1285        Add a parent-child link between two meshsets.
1286
1287        Example
1288        -------
1289        mb = core.Core()
1290        parent_set = mb.create_meshset()
1291        child_set = mb.create_meshset()
1292        mb.add_parent_child(parent_set, child_set)
1293
1294        Parameters
1295        ----------
1296        parent_meshset : MOAB EntityHandle
1297            handle of the parent meshset
1298        child_meshset : MOAB EntityHandle
1299            handle of the child meshset
1300        exceptions : tuple (default is empty tuple)
1301            A tuple containing any error types that should
1302            be ignored. (see pymoab.types module for more info)
1303
1304        Returns
1305        -------
1306        None
1307
1308        Raises
1309        ------
1310        MOAB ErrorCode
1311            if a MOAB error occurs
1312        ValueError
1313            if the Meshset EntityHandle is not of the correct type
1314        """
1315        cdef moab.ErrorCode err
1316        err = self.inst.add_parent_child(<unsigned long> parent_meshset, <unsigned long> child_meshset)
1317        check_error(err, exceptions)
1318
1319    def get_root_set(self):
1320        """
1321        Return the entity meshset representing the whole mesh.
1322
1323        Returns
1324        -------
1325        MOAB EntityHandle
1326        """
1327        return _eh_py_type(0)
1328
1329    def get_connectivity(self, entity_handles, exceptions = ()):
1330        """
1331        Returns the vertex handles which make up the mesh entities passed in via
1332        the entity_handles argument.
1333
1334        Example
1335        -------
1336        # new PyMOAB instance
1337        mb = core.Core()
1338        #create some vertices
1339        coords = np.array((0,0,0,1,0,0,1,1,1),dtype='float64')
1340        verts = mb.create_vertices(coords)
1341        #create a triangle
1342        verts = np.array(((verts[0],verts[1],verts[2]),),dtype='uint64')
1343        tris = mb.create_elements(types.MBTRI,verts)
1344        # retrieve the vertex handles that make up the triangle
1345        conn = mb.get_connectivity(tris[0])
1346
1347
1348        Parameters
1349        ----------
1350        entity_handles : iterable of MOAB EntityHandles or a single EntityHandle
1351            to retrieve the vertex connectivity of. Note that these
1352            EntityHandles should represent mesh entities (MBEDGE,
1353            MBTRI, MBQUAD, etc.) rather than an EntitySet.
1354        exceptions : tuple (default is empty tuple)
1355            A tuple containing any error types that should
1356            be ignored. (see pymoab.types module for more info)
1357
1358        Returns
1359        -------
1360        Numpy array of vertex EntityHandles
1361
1362        Raises
1363        ------
1364        MOAB ErrorCode
1365            if a MOAB error occurs
1366        ValueError
1367            if an EntityHandle is not of the correct datatype
1368        """
1369        cdef moab.ErrorCode err
1370        cdef np.ndarray[eh.EntityHandle] ehs
1371        if isinstance(entity_handles, _eh_py_type):
1372            ehs = _eh_array([entity_handles,])
1373        else:
1374            ehs = _eh_array(entity_handles)
1375        cdef vector[eh.EntityHandle] ehs_out
1376        cdef eh.EntityHandle* eh_ptr
1377        cdef int num_ents = 0
1378        err = self.inst.get_connectivity(<eh.EntityHandle*> ehs.data, ehs.size, ehs_out)
1379        check_error(err, exceptions)
1380
1381        return np.asarray(ehs_out, dtype = np.uint64)
1382
1383    def get_coords(self, entities, exceptions = ()):
1384        """
1385        Returns the xyz coordinate information for a set of vertices.
1386
1387        Example
1388        -------
1389        mb = core.Core()
1390        verts # list of vertex EntityHandles
1391        ret_coords = mb.get_coords(verts)
1392
1393        Parameters
1394        ----------
1395        entities : iterable of MOAB EntityHandles or a single EntityHandle
1396            the EntityHandle(s) to get the adjacencies of. This can be any
1397            iterable of EntityHandles or a single EntityHandle.
1398        exceptions : tuple (default is empty tuple)
1399            A tuple containing any error types that should
1400            be ignored. (see pymoab.types module for more info)
1401
1402        Returns
1403        -------
1404        Returns coordinates as a 1-D Numpy array of xyz values
1405
1406        Raises
1407        ------
1408        MOAB ErrorCode
1409            if a MOAB error occurs
1410        ValueError
1411            if the Meshset EntityHandle is not of the correct type
1412        """
1413        cdef moab.ErrorCode err
1414        cdef Range r
1415        cdef np.ndarray[np.uint64_t, ndim=1] arr
1416        cdef np.ndarray coords
1417        if isinstance(entities, _eh_py_type):
1418            entities = Range(entities)
1419        if isinstance(entities, Range):
1420            r = entities
1421            coords = np.empty((3*r.size(),),dtype='float64')
1422            err = self.inst.get_coords(deref(r.inst), <double*> coords.data)
1423        else:
1424            arr = _eh_array(entities)
1425            coords = np.empty((3*len(arr),),dtype='float64')
1426            err = self.inst.get_coords(<eh.EntityHandle*> arr.data, len(entities), <double*> coords.data)
1427        check_error(err, exceptions)
1428        return coords
1429
1430    def set_coords(self, entities, np.ndarray coords, exceptions = ()):
1431        """
1432        Sets the xyz coordinate information for a set of vertices.
1433
1434        Example
1435        -------
1436        mb = core.Core()
1437        verts # list of vertex EntityHandles
1438        coords = np.array([[0,0,0],[1,0,0],[0,1,0],[1,1,0]])
1439        ret_coords = mb.set_coords(verts, coords)
1440
1441        Parameters
1442        ----------
1443        entities : iterable of MOAB EntityHandles or a single EntityHandle
1444            the EntityHandle(s) to get the adjacencies of. This can be any
1445            iterable of EntityHandles or a single EntityHandle.
1446        coords : coordinate positions (float)
1447            vertex coordinates to be set in Core object
1448        exceptions : tuple (default is empty tuple)
1449            A tuple containing any error types that should
1450            be ignored. (see pymoab.types module for more info)
1451
1452        Raises
1453        ------
1454        MOAB ErrorCode
1455            if a MOAB error occurs
1456        ValueError
1457            if the Meshset EntityHandle is not of the correct type
1458        """
1459        cdef moab.ErrorCode err
1460        cdef Range r
1461        cdef np.ndarray[np.uint64_t, ndim=1] arr
1462        if isinstance(entities, _eh_py_type):
1463            entities = Range(entities)
1464        if isinstance(entities, Range):
1465            r = entities
1466            if 3*r.size() != len(coords):
1467              check_error(moab.MB_INVALID_SIZE, exceptions)
1468            err = self.inst.set_coords(deref(r.inst), <const double*> coords.data)
1469        else:
1470            arr = _eh_array(entities)
1471            if 3*len(arr) != len(coords):
1472              check_error(moab.MB_INVALID_SIZE, exceptions)
1473            err = self.inst.set_coords(<eh.EntityHandle*> arr.data, len(entities), <const double*> coords.data)
1474        check_error(err, exceptions)
1475
1476    def get_entities_by_type(self, meshset, entity_type, bint recur = False, bint as_list = False, exceptions = ()):
1477        """
1478        Retrieves all entities of a given entity type in the database or meshset
1479
1480        Parameters
1481        ----------
1482        meshset     : MOAB EntityHandle
1483                      meshset whose entities are being queried
1484        entity_type : MOAB EntityType
1485                      type of the entities desired (MBVERTEX, MBTRI, etc.)
1486        recur       : bool (default is False)
1487                      if True, meshsets containing meshsets are queried recusively. The
1488                      contenst of these meshsets are returned, but not the meshsets
1489                      themselves.
1490        as_list        : return entities in a list (preserves ordering if necessary, but
1491                      consumes more memory)
1492        Returns
1493        -------
1494        MOAB Range of EntityHandles
1495
1496        Raises
1497        ------
1498        MOAB ErrorCode
1499            if a MOAB error occurs
1500        ValueError
1501            if the Meshset EntityHandle is not of the correct type or
1502            if the EntityType provided is not valid
1503        """
1504        cdef moab.ErrorCode err
1505        cdef Range entities = Range()
1506        cdef moab.EntityType typ = entity_type
1507        cdef vector[eh.EntityHandle] hvec
1508        if as_list:
1509            err = self.inst.get_entities_by_type(<unsigned long> meshset,
1510                                                 typ,
1511                                                 hvec,
1512                                                 recur)
1513            check_error(err, exceptions)
1514            return hvec
1515
1516        else:
1517            err = self.inst.get_entities_by_type(<unsigned long> meshset,
1518                                                 typ,
1519                                                 deref(entities.inst),
1520                                                 recur)
1521            check_error(err, exceptions)
1522            return entities
1523
1524    def get_entities_by_type_and_tag(self,
1525                                     meshset,
1526                                     entity_type,
1527                                     tags,
1528                                     values,
1529                                     int condition = types.INTERSECT,
1530                                     bint recur = False,
1531                                     exceptions = ()):
1532        """
1533        Retrieve entities of a given EntityType in the database which also have
1534        the provided tag and (optionally) the value specified.
1535
1536        Values are expected to be provided in one or two-dimensional arrays in
1537        which each entry in the highest array dimension represents the value (or
1538        set of values for a vector tag) to be matched for corresponding tag in
1539        the "tags" parameter. If an entry is filled with None values, then any
1540        entity with that tag will be returned.
1541
1542        NOTE: This function currently only works for a single tag and set of values.
1543
1544        Example
1545        -------
1546        mb = core.Core()
1547        rs = mb.get_root_set()
1548        entities = mb.get_entities_by_type(rs, types.MBVERTEX)
1549
1550        Parameters
1551        ----------
1552        meshset : MOAB EntityHandle (defualt is the database root set)
1553            meshset whose entities are being queried.
1554        entity_type : MOAB EntityType
1555            type of the entities desired (MBVERTEX, MBTRI, etc.)
1556        tags : iterable of MOAB TagHandles or single TagHandle
1557            an iterable of MOAB TagHandles. Only entities with these tags will
1558            be returned.
1559        values : iterable of tag values
1560            an iterable data structure of the tag values to be matched for
1561            entities returned by the call (see general description for details
1562            on the composition of this data structure)
1563        recur : bool (default is False)
1564            if True, meshsets containing meshsets are queried recusively. The
1565            contenst of these meshsets are returned, but not the meshsets
1566            themselves.
1567
1568        Returns
1569        -------
1570        MOAB Range of EntityHandles
1571
1572        Raises
1573        ------
1574        MOAB ErrorCode
1575            if a MOAB error occurs
1576        ValueError
1577            if the Meshset EntityHandle is not of the correct type or if the
1578            EntityType provided is not valid or if the tag data to be matched is
1579            not constructed properly
1580        """
1581        cdef np.ndarray vals = np.asarray(values, dtype='O')
1582        assert isinstance(tags, Tag) or len(tags) == 1 , "Only single-tag queries are currently supported."
1583        # overall dimension of the numpy array should be 2
1584        # one array for each tag passed to the function
1585        # assert vals.ndim == 2 (was for support of multiple tags)
1586        #ensure that the correct number of arrays exist
1587        cdef int num_tags
1588        cdef Tag single_tag
1589        if isinstance(tags, Tag):
1590            num_tags = 1
1591            single_tag = tags
1592        elif len(tags) == 1:
1593            num_tags = 1
1594            single_tag = tags[0]
1595        else:
1596            num_tags = len(tags)
1597        if 1 != num_tags:
1598            assert vals.ndim == 2
1599            assert num_tags == vals.shape[0]
1600        assert vals.ndim <= 2
1601        #allocate memory for an appropriately sized void** array
1602        cdef void** arr = <void**> malloc(num_tags*sizeof(void*))
1603        #some variables to help in setting up the void array
1604        cdef moab.ErrorCode err
1605        cdef moab.DataType this_tag_type = moab.MB_MAX_DATA_TYPE
1606        cdef int this_tag_length = 0
1607        cdef bytes val_str
1608        cdef np.ndarray this_data
1609
1610        # if this is a single tag and the values array is 1-D
1611        # then validate and call function
1612        if (num_tags == 1) and (vals.ndim == 1):
1613            this_data = self._validate_data_for_tag(single_tag,vals)
1614            arr[0] = <void*> this_data.data if this_data is not None else NULL
1615        elif vals.ndim == 2:
1616            # assign values to void** array
1617            for i in range(num_tags):
1618                this_data = self._validate_data_for_tag(tags[i],vals[i])
1619                #set the array value
1620                arr[i] = <void*> this_data.data if this_data is not None else NULL
1621
1622        #create tag array to pass to function
1623        cdef _tagArray ta = _tagArray(tags)
1624        #convert type to tag type
1625        cdef moab.EntityType typ = entity_type
1626        #a range to hold returned entities
1627        cdef Range ents = Range()
1628        #here goes nothing
1629        err = self.inst.get_entities_by_type_and_tag(<unsigned long> meshset,
1630                                                     typ,
1631                                                     ta.ptr,
1632                                                     <const void**> arr,
1633                                                     num_tags,
1634                                                     deref(ents.inst),
1635                                                     condition,
1636                                                     recur)
1637        check_error(err, exceptions)
1638        # return entities found in the MOAB function call
1639        return ents
1640
1641
1642    def get_entities_by_handle(self, meshset, bint recur = False, bint as_list = False, exceptions = ()):
1643        """
1644        Retrieves all entities in the given meshset.
1645
1646        Parameters
1647        ----------
1648        meshset : MOAB EntityHandle
1649            meshset whose entities are being queried
1650        recur : bool (default is False)
1651            if True, meshsets containing meshsets are queried recusively. The
1652            contenst of these meshsets are returned, but not the meshsets
1653            themselves.
1654        as_list        : return entities in a list (preserves ordering if necessary, but
1655                      consumes more memory)
1656        Returns
1657        -------
1658        MOAB Range of EntityHandles
1659
1660        Raises
1661        ------
1662        MOAB ErrorCode
1663            if a MOAB error occurs
1664        ValueError
1665            if the Meshset EntityHandle is not of the correct type or
1666            if the EntityType provided is not valid
1667        """
1668        cdef moab.ErrorCode err
1669        cdef Range ents = Range()
1670        cdef vector[eh.EntityHandle] hvec
1671        if as_list:
1672            err = self.inst.get_entities_by_handle(<unsigned long> meshset, hvec, recur)
1673            check_error(err, exceptions)
1674            return hvec
1675        else:
1676            err = self.inst.get_entities_by_handle(<unsigned long> meshset, deref(ents.inst), recur)
1677            check_error(err, exceptions)
1678            return ents
1679
1680    def get_entities_by_dimension(self, meshset, int dimension, bint recur = False, bint as_list = False, exceptions = ()):
1681        """
1682        Retrieves all entities of a given topological dimension in the database or meshset
1683
1684        Parameters
1685        ----------
1686        meshset   : MOAB EntityHandle
1687                    meshset whose entities are being queried
1688        dimension : integer
1689                    topological dimension of the entities desired
1690        recur     : bool (default is False)
1691                    if True, meshsets containing meshsets are queried recusively. The
1692                    contenst of these meshsets are returned, but not the meshsets
1693                    themselves.
1694        as_list   : return entities in a list (preserves ordering if necessary, but
1695                    consumes more memory)
1696        Returns
1697        -------
1698        MOAB Range of EntityHandles
1699
1700        Raises
1701        ------
1702        MOAB ErrorCode
1703            if a MOAB error occurs
1704        ValueError
1705            if the Meshset EntityHandle is not of the correct type or
1706            if the EntityType provided is not valid
1707        """
1708        cdef moab.ErrorCode err
1709        cdef Range ents = Range()
1710        cdef vector[eh.EntityHandle] hvec
1711        if as_list:
1712            err = self.inst.get_entities_by_dimension(<unsigned long> meshset, dimension, hvec, recur)
1713            check_error(err, exceptions)
1714            return hvec
1715        else:
1716            err = self.inst.get_entities_by_dimension(<unsigned long> meshset, dimension, deref(ents.inst), recur)
1717            check_error(err, exceptions)
1718            return ents
1719
1720    def delete_mesh(self):
1721        """Deletes all mesh entities from the database"""
1722        self.inst.delete_mesh()
1723
1724    def _validate_data_for_tag(self, Tag tag, data_arr):
1725        """Internal method for validating tag data."""
1726
1727        cdef moab.ErrorCode err
1728        cdef moab.DataType tag_type = moab.MB_MAX_DATA_TYPE
1729        cdef int tag_length = 0
1730        # make sure we're dealing with a 1-D array at this point
1731        assert data_arr.ndim == 1
1732        # if None is passed, set pointer to NULL and continue
1733        if data_arr[0] == None:
1734            return None
1735        else:
1736            # otherwise get the tag type
1737            err = self.inst.tag_get_data_type(tag.inst, tag_type)
1738            check_error(err)
1739            #and length
1740            err = self.inst.tag_get_length(tag.inst,tag_length);
1741            check_error(err)
1742            #check that the data_arr for this tag is the correct length
1743            if tag_type == moab.MB_TYPE_OPAQUE:
1744                #if this is an opaque tag, there should only be one
1745                #string entry in the array
1746                assert data_arr.size == 1
1747            else:
1748                assert data_arr.size == tag_length
1749        #validate the array type and convert the dtype if necessary
1750        data_arr = validate_type(tag_type, tag_length, data_arr)
1751        return data_arr
1752
1753    def tag_get_default_value(self, Tag tag, exceptions = () ):
1754        """
1755        Returns the default value for a tag as a 1-D numpy array
1756
1757        Parameters
1758        ----------
1759        tag : MOAB tag
1760
1761        Returns
1762        -------
1763        NumPy 1-D array
1764
1765        Raises
1766        ------
1767        MOAB ErrorCode
1768            if an internal MOAB error occurs
1769        """
1770        # get the tag type and length for validation
1771        cdef moab.DataType tag_type = moab.MB_MAX_DATA_TYPE
1772        err = self.inst.tag_get_data_type(tag.inst, tag_type);
1773        check_error(err,())
1774        cdef int length = 0
1775        err = self.inst.tag_get_length(tag.inst,length);
1776        check_error(err,())
1777        #create array to hold data
1778        cdef np.ndarray data
1779        if tag_type is types.MB_TYPE_OPAQUE:
1780            data = np.empty((1,),dtype='S'+str(length))
1781        else:
1782            data = np.empty((length,),dtype=np.dtype(np_tag_type(tag_type)))
1783        err = self.inst.tag_get_default_value(tag.inst, <void*> data.data)
1784        check_error(err, exceptions)
1785        return data
1786
1787    def tag_get_length(self, Tag tag, exceptions = () ):
1788        """
1789        Returns an integer representing the tag's length
1790
1791        Parameters
1792        ----------
1793        tag : MOAB tag
1794
1795        Returns
1796        -------
1797        int : the tag length
1798
1799        Raises
1800        ------
1801        MOAB ErrorCode
1802            if an internal MOAB error occurs
1803        """
1804        cdef int length = 0
1805        err = self.inst.tag_get_length(tag.inst, length)
1806        check_error(err, exceptions)
1807        return length
1808
1809    def tag_get_tags_on_entity(self, entity):
1810        """
1811        Retrieves all tags for a given EntityHandle
1812
1813        Parameters
1814        ----------
1815        entity : MOAB EntityHandle
1816
1817        Returns
1818        -------
1819        A list of tags on that entity
1820
1821        Raises
1822        ------
1823        MOAB ErrorCode
1824            if an internal MOAB error occurs
1825        """
1826        cdef vector[moab.TagInfo*] tags
1827        err = self.inst.tag_get_tags_on_entity(entity, tags)
1828        tag_list = []
1829        for tag in tags:
1830            t = Tag()
1831            t.inst = tag
1832            tag_list.append(t)
1833        return tag_list
1834