https://mooseframework.inl.gov
Loading...
Searching...
No Matches
KokkosMesh.h
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#pragma once
11
12#include "KokkosTypes.h"
13
14#ifdef MOOSE_KOKKOS_SCOPE
15#include "KokkosUtils.h"
16#endif
17
20using ContiguousElementID = dof_id_type;
21using ContiguousNodeID = dof_id_type;
22
23class MooseMesh;
24
25namespace Moose::Kokkos
26{
27
34{
46 ContiguousSubdomainID subdomain = std::numeric_limits<ContiguousSubdomainID>::max();
47};
48
52class Mesh
53{
54public:
59 Mesh(MooseMesh & mesh) : _mesh(mesh) {}
64 const MooseMesh & getMesh() { return _mesh; }
68 [[nodiscard]] bool initialized() const { return _initialized; }
72 void update();
73
79
89
94 auto getNumSubdomains() const { return _maps->subdomain_id_mapping.size(); }
99 auto getNumLocalElementTypes() const { return _maps->elem_type_id_mapping.size(); }
104 const auto & getElementTypeMap() const { return _maps->elem_type_id_mapping; }
109 dof_id_type getNumLocalElements() const { return _num_local_elems; }
120 auto getNumSubdomainLocalElements(const SubdomainID subdomain) const
121 {
122 auto range = libmesh_map_find(_maps->subdomain_elem_id_ranges, subdomain);
123 return range.second - range.first;
124 }
129 auto getNumLocalNodes() const { return _num_local_nodes; }
134 const auto & getLocalNodes() const { return _maps->local_nodes; }
152 unsigned int getElementTypeID(const Elem * elem) const;
163 const auto & getGhostElemIdMapping() const { return _maps->ghost_elem_id_mapping; }
170 {
171 const auto & range = libmesh_map_find(_maps->subdomain_elem_id_ranges, subdomain);
172 return libMesh::make_range(range.first, range.second);
173 }
179 ContiguousNodeID getContiguousNodeID(const Node * node) const;
186 const auto & getSubdomainContiguousNodeIDs(const SubdomainID subdomain) const
187 {
188 return libmesh_map_find(_maps->subdomain_node_ids, subdomain);
189 }
196 const auto & getBoundaryContiguousNodeIDs(const BoundaryID boundary) const
197 {
198 return libmesh_map_find(_maps->boundary_node_ids, boundary);
199 }
200#ifdef MOOSE_KOKKOS_SCOPE
206 KOKKOS_FUNCTION const auto & getElementInfo(ContiguousElementID elem) const
207 {
208 KOKKOS_ASSERT(elem < _elem_info.size());
209
210 return _elem_info[elem];
211 }
218 KOKKOS_FUNCTION ContiguousElementID getNeighbor(ContiguousElementID elem, unsigned int side) const
219 {
220 return _elem_neighbor(side, elem);
221 }
228 KOKKOS_FUNCTION Real getSideArea(ContiguousElementID elem, unsigned int side) const
229 {
231 return _side_area(side, elem);
232 }
239 KOKKOS_FUNCTION Real3 getSideCentroid(ContiguousElementID elem, unsigned int side) const
240 {
242 return _side_centroid(side, elem);
243 }
250 KOKKOS_FUNCTION Real3 getSideNormal(ContiguousElementID elem, unsigned int side) const
251 {
253 return _side_normal(side, elem);
254 }
262 unsigned int side) const
263 {
265 return _elem_centroid_to_side_centroid(side, elem);
266 }
274 unsigned int side) const
275 {
278 }
287 unsigned int side) const
288 {
290 return _elem_centroid_to_neighbor_centroid(side, elem);
291 }
300 unsigned int side) const
301 {
304 }
310 KOKKOS_FUNCTION Real getElementVolume(ContiguousElementID elem) const
311 {
312 KOKKOS_ASSERT(_element_geometry_initialized);
313 KOKKOS_ASSERT(elem < _elem_volume.size());
314 return _elem_volume[elem];
315 }
321 KOKKOS_FUNCTION Real3 getElementCentroid(ContiguousElementID elem) const
322 {
323 KOKKOS_ASSERT(_element_geometry_initialized);
324 KOKKOS_ASSERT(elem < _elem_centroid.size());
325 return _elem_centroid[elem];
326 }
327
332
339
345 KOKKOS_FUNCTION unsigned int getNumSides(unsigned int elem_type) const
346 {
347 return _num_sides[elem_type];
348 }
354 KOKKOS_FUNCTION unsigned int getNumNodes(unsigned int elem_type) const
355 {
356 return _num_nodes[elem_type];
357 }
364 KOKKOS_FUNCTION unsigned int getNumNodes(unsigned int elem_type, unsigned int side) const
365 {
366 return _num_side_nodes[elem_type][side];
367 }
374 KOKKOS_FUNCTION dof_id_type getExtraElementID(ContiguousElementID elem, unsigned int index) const
375 {
376 KOKKOS_ASSERT(elem < _extra_elem_ids.n(0));
377 KOKKOS_ASSERT(index < _extra_elem_ids.n(1));
378
379 return _extra_elem_ids(elem, index);
380 }
386 KOKKOS_FUNCTION dof_id_type getStartingContiguousElementID(ContiguousSubdomainID subdomain) const
387 {
388 return _starting_elem_id[subdomain];
389 }
397 unsigned int node) const
398 {
399 return _nodes(node, elem);
400 }
409 unsigned int side,
410 unsigned int node) const
411 {
412 return _nodes(_local_side_node[info.type](node, side), info.id);
413 }
419 KOKKOS_FUNCTION Real3 getNodePoint(ContiguousNodeID node) const { return _points[node]; }
426 KOKKOS_FUNCTION bool isBoundaryNode(ContiguousNodeID node, ContiguousBoundaryID boundary) const;
433 KOKKOS_FUNCTION unsigned int getNumSideBoundaryIDs(ContiguousElementID elem,
434 unsigned int side) const
435 {
436 return _side_boundary_ids(side, elem).size();
437 }
446 unsigned int side,
447 unsigned int i) const
448 {
449 return _side_boundary_ids(side, elem)[i];
450 }
458 KOKKOS_FUNCTION bool
459 isSideOnBoundary(ContiguousElementID elem, unsigned int side, BoundaryID boundary) const;
460#endif
461
462private:
466 void initMap();
471
479 bool _initialized = false;
480
484 struct MeshMap
485 {
489 std::unordered_map<SubdomainID, ContiguousSubdomainID> subdomain_id_mapping;
493 std::unordered_map<BoundaryID, ContiguousBoundaryID> boundary_id_mapping;
497 std::map<std::pair<ElemType, unsigned int>, unsigned int> elem_type_id_mapping;
501 std::vector<Node *> local_nodes;
505 std::unordered_map<const Node *, ContiguousNodeID> ghost_node_id_mapping;
509 std::unordered_map<const Elem *, ContiguousElementID> ghost_elem_id_mapping;
513 std::unordered_map<SubdomainID, std::pair<ContiguousElementID, ContiguousElementID>>
519 std::unordered_map<SubdomainID, std::vector<ContiguousNodeID>> subdomain_node_ids;
524 std::unordered_map<BoundaryID, std::set<ContiguousNodeID>> boundary_node_ids;
525 };
529 std::shared_ptr<MeshMap> _maps;
530
542 dof_id_type _num_local_elems = 0;
546 dof_id_type _num_ghost_elems = 0;
550 dof_id_type _num_local_nodes = 0;
600
627};
628
629#ifdef MOOSE_KOKKOS_SCOPE
630KOKKOS_FUNCTION inline bool
632{
633 if (!_boundary_nodes[boundary].size())
634 return false;
635
636 auto begin = &_boundary_nodes[boundary].begin();
637 auto end = &_boundary_nodes[boundary].end();
638 auto target = Utils::find(node, begin, end);
639
640 return target != end;
641}
642
643KOKKOS_FUNCTION inline bool
644Mesh::isSideOnBoundary(ContiguousElementID elem, unsigned int side, BoundaryID boundary) const
645{
646 const auto boundaries = _side_boundary_ids(side, elem);
647
648 for (unsigned int i = 0; i < boundaries.size(); ++i)
649 if (boundaries[i] == boundary)
650 return true;
651
652 return false;
653}
654#endif
655
656inline dof_id_type
661
669{
670public:
679 MeshHolder(const MeshHolder & holder)
681 {
682 }
683
684#ifdef MOOSE_KOKKOS_SCOPE
690 KOKKOS_FUNCTION const Mesh & kokkosMesh() const
691 {
692 KOKKOS_IF_ON_HOST(
694 "kokkosMesh() was called too early. Kokkos mesh is available after problem "
695 "initialization. Override initialSetup() if you need to setup your object data "
696 "using the Kokkos mesh.");
697
698 return _mesh_host;)
699
700 return _mesh_device;
701 }
702#endif
703
704private:
713};
714
715} // namespace Moose::Kokkos
boundary_id_type BoundaryID
subdomain_id_type SubdomainID
BoundaryID ContiguousBoundaryID
Definition KokkosMesh.h:19
dof_id_type ContiguousElementID
Definition KokkosMesh.h:20
SubdomainID ContiguousSubdomainID
Definition KokkosMesh.h:18
dof_id_type ContiguousNodeID
Definition KokkosMesh.h:21
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
KOKKOS_FUNCTION index_type size() const
Get the total array size.
The Kokkos array class.
The Kokkos jagged array class.
KOKKOS_FUNCTION index_type size() const
Get the total data array size.
The Kokkos interface that holds the host reference of the Kokkos mesh and copies it to device during ...
Definition KokkosMesh.h:669
KOKKOS_FUNCTION const Mesh & kokkosMesh() const
Get the const reference of the Kokkos mesh.
Definition KokkosMesh.h:690
MeshHolder(const MeshHolder &holder)
Copy constructor.
Definition KokkosMesh.h:679
const Mesh & _mesh_host
Host reference of the Kokkos mesh.
Definition KokkosMesh.h:708
const Mesh _mesh_device
Device copy of the Kokkos mesh.
Definition KokkosMesh.h:712
MeshHolder(const Mesh &mesh)
Constructor.
Definition KokkosMesh.h:675
The Kokkos mesh object.
Definition KokkosMesh.h:53
const auto & getBoundaryContiguousNodeIDs(const BoundaryID boundary) const
Get the list of local contiguous node IDs for a boundary NOTE: This list excludes semi-local nodes.
Definition KokkosMesh.h:196
KOKKOS_FUNCTION Real3 getSideCentroid(ContiguousElementID elem, unsigned int side) const
Get the centroid of an element side.
Definition KokkosMesh.h:239
KOKKOS_FUNCTION dof_id_type getStartingContiguousElementID(ContiguousSubdomainID subdomain) const
Get the starting contiguous element ID of a subdomain.
Definition KokkosMesh.h:386
Array< ElementInfo > _elem_info
Element information.
Definition KokkosMesh.h:554
void initMap()
Initialize host maps.
Array2D< Real > _elem_centroid_to_side_centroid_distance
Element-centroid to side-centroid distances indexed by (side, contiguous element ID)
Definition KokkosMesh.h:622
ContiguousNodeID getContiguousNodeID(const Node *node) const
Get the contiguous node ID of a node.
Array< ContiguousElementID > _starting_elem_id
Starting contiguous element ID of each subdomain.
Definition KokkosMesh.h:562
void setNeedsElementSideGeometry()
Mark that element-side geometry data is needed; initElementSideGeometry() will be called on the next ...
Definition KokkosMesh.h:84
bool _needs_element_geometry
Whether initElementGeometry() should be called on the next update()
Definition KokkosMesh.h:604
Array2D< Real > _elem_centroid_to_neighbor_centroid_distance
Element-centroid to neighbor-centroid distances indexed by (side, contiguous element ID)
Definition KokkosMesh.h:626
KOKKOS_FUNCTION unsigned int getNumNodes(unsigned int elem_type, unsigned int side) const
Get the number of nodes on a side of an element type.
Definition KokkosMesh.h:364
JaggedArray< BoundaryID, 1, 2 > _side_boundary_ids
Boundary IDs of each local element side indexed by (side, contiguous element ID), each inner array so...
Definition KokkosMesh.h:599
KOKKOS_FUNCTION ContiguousNodeID getContiguousNodeID(ElementInfo info, unsigned int side, unsigned int node) const
Get the contiguous node ID for a side.
Definition KokkosMesh.h:408
KOKKOS_FUNCTION BoundaryID getSideBoundaryID(ContiguousElementID elem, unsigned int side, unsigned int i) const
Get a boundary ID of a local element side.
Definition KokkosMesh.h:445
auto getNumLocalNodes() const
Get the number of local nodes including semi-local nodes.
Definition KokkosMesh.h:129
Array< Array< ContiguousNodeID > > _boundary_nodes
Contiguous node IDs on each boundary.
Definition KokkosMesh.h:594
Array2D< ContiguousElementID > _elem_neighbor
Neighbor contiguous element IDs of each element.
Definition KokkosMesh.h:558
KOKKOS_FUNCTION dof_id_type getExtraElementID(ContiguousElementID elem, unsigned int index) const
Get the extra element ID of an element.
Definition KokkosMesh.h:374
Array< unsigned int > _num_sides
Number of sides of each element type.
Definition KokkosMesh.h:570
ContiguousBoundaryID getContiguousBoundaryID(const BoundaryID boundary) const
Get the contiguous boundary ID of a boundary.
dof_id_type _num_local_nodes
Number of local nodes including semi-local nodes.
Definition KokkosMesh.h:550
KOKKOS_FUNCTION unsigned int getNumSideBoundaryIDs(ContiguousElementID elem, unsigned int side) const
Get the number of boundary IDs of a local element side.
Definition KokkosMesh.h:433
const auto & getSubdomainContiguousNodeIDs(const SubdomainID subdomain) const
Get the list of local contiguous node IDs for a subdomain NOTE: This list excludes semi-local nodes.
Definition KokkosMesh.h:186
void setNeedsElementGeometry()
Mark that element geometry data is needed; initElementGeometry() will be called on the next update()
Definition KokkosMesh.h:78
Array2D< Real3 > _side_centroid
Cached side centroids indexed by (side, contiguous element ID)
Definition KokkosMesh.h:616
bool _element_geometry_initialized
Whether initElementGeometry() has been called and the element geometry cache is populated.
Definition KokkosMesh.h:602
auto getNumSubdomains() const
Get the number of subdomains.
Definition KokkosMesh.h:94
Array< Real3 > _points
Node coordinates.
Definition KokkosMesh.h:586
KOKKOS_FUNCTION unsigned int getNumNodes(unsigned int elem_type) const
Get the number of nodes of an element type.
Definition KokkosMesh.h:354
Array2D< Real3 > _elem_centroid_to_neighbor_centroid
Element-centroid to neighbor-centroid vectors indexed by (side, contiguous element ID)
Definition KokkosMesh.h:624
const auto & getElementTypeMap() const
Get the element type ID map.
Definition KokkosMesh.h:104
Array< Array< unsigned int > > _num_side_nodes
Number of nodes per side of each element side.
Definition KokkosMesh.h:578
Mesh(MooseMesh &mesh)
Constructor.
Definition KokkosMesh.h:59
KOKKOS_FUNCTION const auto & getElementInfo(ContiguousElementID elem) const
Get the element information object.
Definition KokkosMesh.h:206
Array2D< ContiguousNodeID > _nodes
Contiguous node IDs of each element.
Definition KokkosMesh.h:590
auto getNumLocalElementTypes() const
Get the number of local elements types.
Definition KokkosMesh.h:99
Array2D< Real > _side_area
Cached coordinate-weighted side areas indexed by (side, local contiguous element ID)
Definition KokkosMesh.h:614
Array2D< Real3 > _side_normal
Cached side normals indexed by (side, contiguous element ID)
Definition KokkosMesh.h:618
ContiguousElementID getContiguousElementID(const Elem *elem) const
Get the contiguous element ID of an element.
const MooseMesh & getMesh()
Get the underyling MOOSE mesh.
Definition KokkosMesh.h:64
bool _element_side_geometry_initialized
Whether initElementSideGeometry() has been called and the side geometry cache is populated.
Definition KokkosMesh.h:606
KOKKOS_FUNCTION Real3 getNodePoint(ContiguousNodeID node) const
Get the coordinate of a node.
Definition KokkosMesh.h:419
KOKKOS_FUNCTION unsigned int getNumSides(unsigned int elem_type) const
Get the number of sides of an element type.
Definition KokkosMesh.h:345
Array< unsigned int > _num_nodes
Number of nodes of each element type.
Definition KokkosMesh.h:574
KOKKOS_FUNCTION Real getElementCentroidToSideCentroidDistance(ContiguousElementID elem, unsigned int side) const
Get the element-centroid to side-centroid distance for an element side.
Definition KokkosMesh.h:273
std::shared_ptr< MeshMap > _maps
A shared pointer holding all the host maps to avoid deep copy.
Definition KokkosMesh.h:529
unsigned int _elem_id_integer
Element integer for Kokkos contiguous element ID.
Definition KokkosMesh.h:534
Array< Real > _elem_volume
Cached coordinate-weighted local element volumes indexed by contiguous element ID.
Definition KokkosMesh.h:610
dof_id_type getNumLocalElements() const
Get the number of local elements.
Definition KokkosMesh.h:109
KOKKOS_FUNCTION Real getElementCentroidToNeighborCentroidDistance(ContiguousElementID elem, unsigned int side) const
Get the element-centroid to neighbor-centroid distance for an element side with a neighbor.
Definition KokkosMesh.h:299
bool _initialized
Flag whether the mesh was initialized.
Definition KokkosMesh.h:479
MooseMesh & _mesh
Reference of the MOOSE mesh.
Definition KokkosMesh.h:475
Array2D< Real3 > _elem_centroid_to_side_centroid
Element-centroid to side-centroid vectors indexed by (side, contiguous element ID)
Definition KokkosMesh.h:620
dof_id_type _num_ghost_elems
Number of ghost (off-process neighbor) elements.
Definition KokkosMesh.h:546
void initElement()
Initialize device element data.
KOKKOS_FUNCTION Real getElementVolume(ContiguousElementID elem) const
Get the coordinate-weighted volume of a local element.
Definition KokkosMesh.h:310
Array2D< dof_id_type > _extra_elem_ids
Extra element IDs.
Definition KokkosMesh.h:566
auto getSubdomainContiguousElementIDRange(const SubdomainID subdomain) const
Get the range of contiguous element IDs for a subdomain.
Definition KokkosMesh.h:169
unsigned int _node_id_integer
Node integer for Kokkos contiguous node ID.
Definition KokkosMesh.h:538
KOKKOS_FUNCTION ContiguousElementID getNeighbor(ContiguousElementID elem, unsigned int side) const
Get the neighbor contiguous element ID.
Definition KokkosMesh.h:218
KOKKOS_FUNCTION bool isBoundaryNode(ContiguousNodeID node, ContiguousBoundaryID boundary) const
Get whether a node is on a boundary.
Definition KokkosMesh.h:631
dof_id_type getNumLocalAndPossiblyOneNeighborLayerGhostElements() const
Get the total number of elements, i.e.
Definition KokkosMesh.h:657
void initElementGeometry()
Allocate and populate local element centroids and coordinate-weighted volumes.
Array< Array2D< unsigned int > > _local_side_node
Map from local side node index to local element node index.
Definition KokkosMesh.h:582
Array< Real3 > _elem_centroid
Cached local element centroids indexed by contiguous element ID.
Definition KokkosMesh.h:612
auto getNumSubdomainLocalElements(const SubdomainID subdomain) const
Get the number of local elements in a MOOSE subdomain.
Definition KokkosMesh.h:120
const auto & getGhostElemIdMapping() const
Get the ghost element ID map (host-side only)
Definition KokkosMesh.h:163
KOKKOS_FUNCTION Real3 getElementCentroidToSideCentroidVector(ContiguousElementID elem, unsigned int side) const
Get the element-centroid to side-centroid vector for an element side.
Definition KokkosMesh.h:261
KOKKOS_FUNCTION Real3 getElementCentroid(ContiguousElementID elem) const
Get the centroid of a local element.
Definition KokkosMesh.h:321
ContiguousSubdomainID getContiguousSubdomainID(const SubdomainID subdomain) const
Get the contiguous subdomain ID of a MOOSE subdomain.
const auto & getLocalNodes() const
Get the list of local nodes including semi-local nodes.
Definition KokkosMesh.h:134
KOKKOS_FUNCTION Real getSideArea(ContiguousElementID elem, unsigned int side) const
Get the coordinate-weighted area of an element side.
Definition KokkosMesh.h:228
bool initialized() const
Get whether the mesh was initialized.
Definition KokkosMesh.h:68
void initElementSideGeometry()
Allocate and populate cached side geometry: side areas, centroids, normals, element-centroid to side-...
bool _needs_element_side_geometry
Whether initElementSideGeometry() should be called on the next update()
Definition KokkosMesh.h:608
dof_id_type _num_local_elems
Number of local elements.
Definition KokkosMesh.h:542
KOKKOS_FUNCTION bool isSideOnBoundary(ContiguousElementID elem, unsigned int side, BoundaryID boundary) const
Get whether a local element side belongs to a boundary.
Definition KokkosMesh.h:644
KOKKOS_FUNCTION ContiguousNodeID getContiguousNodeID(ContiguousElementID elem, unsigned int node) const
Get the contiguous node ID for an element.
Definition KokkosMesh.h:396
unsigned int getElementTypeID(const Elem *elem) const
Get the element type ID of an element.
KOKKOS_FUNCTION Real3 getElementCentroidToNeighborCentroidVector(ContiguousElementID elem, unsigned int side) const
Get the element-centroid to neighbor-centroid vector for an element side with a neighbor.
Definition KokkosMesh.h:286
KOKKOS_FUNCTION Real3 getSideNormal(ContiguousElementID elem, unsigned int side) const
Get the outward unit normal of an element side.
Definition KokkosMesh.h:250
void update()
Update the mesh.
static constexpr dof_id_type invalid_id
MeshBase & mesh
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition KokkosUtils.h:40
const unsigned int invalid_uint
IntRange< T > make_range(T beg, T end)
The Kokkos object that contains the information of an element The IDs used in Kokkos are different fr...
Definition KokkosMesh.h:34
unsigned int type
Element type ID.
Definition KokkosMesh.h:38
ContiguousSubdomainID subdomain
Contiguous subdomain ID.
Definition KokkosMesh.h:46
The wrapper of host maps.
Definition KokkosMesh.h:485
std::unordered_map< const Elem *, ContiguousElementID > ghost_elem_id_mapping
Map from off-process ghost Elem* to its contiguous element ID on this process.
Definition KokkosMesh.h:509
std::unordered_map< BoundaryID, std::set< ContiguousNodeID > > boundary_node_ids
List of the contiguous node IDs on each boundary NOTE: This list excludes semi-local nodes.
Definition KokkosMesh.h:524
std::unordered_map< SubdomainID, ContiguousSubdomainID > subdomain_id_mapping
Map from the MOOSE subdomain ID to the contiguous subdomain ID.
Definition KokkosMesh.h:489
std::unordered_map< SubdomainID, std::vector< ContiguousNodeID > > subdomain_node_ids
List of the contiguous node IDs in each subdomain NOTE: This list excludes semi-local nodes.
Definition KokkosMesh.h:519
std::vector< Node * > local_nodes
List of local nodes including semi-local nodes.
Definition KokkosMesh.h:501
std::unordered_map< const Node *, ContiguousNodeID > ghost_node_id_mapping
Map from off-process ghost node to the contiguous node ID.
Definition KokkosMesh.h:505
std::unordered_map< SubdomainID, std::pair< ContiguousElementID, ContiguousElementID > > subdomain_elem_id_ranges
Range of the contiguous element IDs in each subdomain.
Definition KokkosMesh.h:514
std::unordered_map< BoundaryID, ContiguousBoundaryID > boundary_id_mapping
Map from the MOOSE boundary ID to the contiguous boundary ID.
Definition KokkosMesh.h:493
std::map< std::pair< ElemType, unsigned int >, unsigned int > elem_type_id_mapping
Map from the MOOSE element type and p-refinement level to the element type ID.
Definition KokkosMesh.h:497