37 struct RINGMesh2CSMP {
45 static RINGMesh2CSMP tet_descriptor = { 4,
52 static RINGMesh2CSMP hex_descriptor = { 6,
54 { 0, 4, 5, 1, 2, 6, 7, 3 },
59 static RINGMesh2CSMP prism_descriptor = { 12,
66 static RINGMesh2CSMP pyramid_descriptor = { 18,
73 static RINGMesh2CSMP* cell_type_to_cell_descriptor[4] = { &tet_descriptor,
76 &pyramid_descriptor };
78 class CSMPIOHandler final:
public GeoModelIOHandler< 3 > {
85 void load(
const std::string& filename, GeoModel3D& geomodel )
final 89 throw RINGMeshException(
"I/O",
90 "Loading of a GeoModel from CSMP not implemented yet" );
92 void save(
const GeoModel3D& geomodel,
const std::string& filename )
final 94 initialize( geomodel );
96 std::string directory = GEO::FileSystem::dir_name( filename );
97 std::string file = GEO::FileSystem::base_name( filename );
99 std::ostringstream oss_ascii;
100 oss_ascii << directory <<
"/" << file <<
".asc";
101 std::ofstream ascii( oss_ascii.str().c_str() );
102 ascii.precision( 16 );
104 ascii << geomodel.name() <<
EOL;
105 ascii <<
"Model generated from RINGMesh" <<
EOL;
107 std::ostringstream oss_data;
108 oss_data << directory <<
"/" << file <<
".dat";
109 std::ofstream data( oss_data.str().c_str() );
110 data.precision( 16 );
112 std::ostringstream oss_regions;
113 oss_regions << directory <<
"/" << file <<
"-regions.txt";
114 std::ofstream regions( oss_regions.str().c_str() );
115 regions <<
"'" << oss_regions.str() <<
EOL;
116 regions <<
"no properties" <<
EOL;
118 const GeoModelMesh3D& mesh = geomodel.mesh;
119 const GeoModelMeshPolygons3D& polygons = mesh.polygons;
122 signed_index_t conversion_sign[3] = { 1, 1, -1 };
123 index_t conversion_axis[3] = { 0, 2, 1 };
124 data << mesh.vertices.nb() <<
" # PX, PY, PZ" <<
EOL;
125 for(
auto dim : range( 3 ) ) {
126 for(
auto v : range( mesh.vertices.nb() ) ) {
128 << conversion_sign[dim]
129 * mesh.vertices.vertex( v )[conversion_axis[dim]];
130 new_line( count, 5, data );
132 reset_line( count, data );
134 reset_line( count, data );
136 index_t nb_families = 0;
137 index_t nb_interfaces = geomodel.nb_geological_entities(
138 Interface3D::type_name_static() );
139 std::vector< index_t > nb_triangle_interface( nb_interfaces, 0 );
140 std::vector< index_t > nb_quad_interface( nb_interfaces, 0 );
141 for(
auto i : range( nb_interfaces ) ) {
142 const GeoModelGeologicalEntity3D& interf =
143 geomodel.geological_entity( Interface3D::type_name_static(), i );
144 for(
auto s : range( interf.nb_children() ) ) {
145 index_t s_id = interf.child_gmme( s ).index();
146 nb_triangle_interface[i] += polygons.nb_triangle( s_id );
147 nb_quad_interface[i] += polygons.nb_quad( s_id );
149 if( nb_triangle_interface[i] > 0 ) nb_families++;
150 if( nb_quad_interface[i] > 0 ) nb_families++;
152 for(
auto r : range( geomodel.nb_regions() ) ) {
153 if( mesh.cells.nb_tet( r ) > 0 ) nb_families++;
154 if( mesh.cells.nb_pyramid( r ) > 0 ) nb_families++;
155 if( mesh.cells.nb_prism( r ) > 0 ) nb_families++;
156 if( mesh.cells.nb_hex( r ) > 0 ) nb_families++;
158 if( geomodel.wells() ) nb_families += geomodel.wells()->nb_wells();
160 ascii << nb_families <<
" # Number of families" <<
EOL;
161 ascii <<
"# Object name" <<
TAB <<
"Entity type" <<
TAB <<
"Material-ID" 162 <<
TAB <<
"Number of entities" <<
EOL;
163 for(
const auto& region : geomodel.regions() ) {
164 regions << region.name() <<
EOL;
165 std::string entity_type[4] = {
"TETRA_4",
"HEXA_8",
"PENTA_6",
167 for(
auto type : range(
171 if( mesh.cells.nb_cells( region.index(), T ) > 0 ) {
172 ascii << region.name() <<
TAB << entity_type[type] <<
TAB 173 << 0 <<
TAB << mesh.cells.nb_cells( region.index(), T )
178 for(
auto i : range( nb_interfaces ) ) {
179 regions << interface_csmp_name( i, geomodel ) <<
EOL;
180 if( nb_triangle_interface[i] > 0 ) {
181 ascii << interface_csmp_name( i, geomodel ) <<
TAB <<
"TRI_3" 182 <<
TAB << 0 <<
TAB << nb_triangle_interface[i] <<
EOL;
184 if( nb_quad_interface[i] > 0 ) {
185 ascii << interface_csmp_name( i, geomodel ) <<
TAB <<
"QUAD_4" 186 <<
TAB << 0 <<
TAB << nb_quad_interface[i] <<
EOL;
189 if( geomodel.wells() ) {
190 for(
auto w : range( geomodel.wells()->nb_wells() ) ) {
191 const Well3D& well = geomodel.wells()->well( w );
192 regions << well.name() <<
EOL;
193 ascii << well.name() <<
TAB <<
"BAR_2" <<
TAB << 0 <<
TAB 194 << well.nb_edges() <<
EOL;
198 data <<
"# PBFLAGS" <<
EOL;
199 for(
auto p : range( mesh.vertices.nb() ) ) {
200 data <<
" " << std::setw( 3 ) << point_boundary( p );
201 new_line( count, 20, data );
203 reset_line( count, data );
205 data <<
"# PBVALS" <<
EOL;
206 for(
auto p : range( mesh.vertices.nb() ) ) {
208 data <<
" " << std::setw( 3 ) << 0;
209 new_line( count, 20, data );
211 reset_line( count, data );
213 index_t nb_total_entities = mesh.cells.nb_cells()
214 + polygons.nb_polygons() + mesh.wells.nb_edges();
215 data << nb_total_entities <<
" # PELEMENT" <<
EOL;
216 for(
auto r : range( geomodel.nb_regions() ) ) {
217 index_t entity_type[4] = { 4, 6, 12, 18 };
218 for(
auto type : range(
222 for(
auto el : range( mesh.cells.nb_cells( r, T ) ) ) {
224 data <<
" " << std::setw( 3 ) << entity_type[type];
225 new_line( count, 20, data );
229 for(
auto i : range( nb_interfaces ) ) {
230 for(
auto el : range( nb_triangle_interface[i] ) ) {
232 data <<
" " << std::setw( 3 ) << 8;
233 new_line( count, 20, data );
235 for(
auto el : range( nb_quad_interface[i] ) ) {
237 data <<
" " << std::setw( 3 ) << 14;
238 new_line( count, 20, data );
241 if( geomodel.wells() ) {
242 for(
auto w : range( geomodel.wells()->nb_wells() ) ) {
243 const Well3D& well = geomodel.wells()->well( w );
244 for(
auto e : range( well.nb_edges() ) ) {
246 data <<
" " << std::setw( 3 ) << 2;
247 new_line( count, 20, data );
251 reset_line( count, data );
254 <<
"# now the entities which make up each object are listed in sequence" 256 index_t cur_cell = 0;
257 for(
auto r : range( geomodel.nb_regions() ) ) {
258 const RINGMesh::GeoModelEntity3D& region = geomodel.region( r );
259 std::string entity_type[4] = {
"TETRA_4",
"HEXA_8",
"PENTA_6",
261 for(
auto type : range(
265 if( mesh.cells.nb_cells( r, T ) > 0 ) {
266 ascii << region.name() <<
" " << entity_type[type] <<
" " 267 << mesh.cells.nb_cells( r, T ) <<
EOL;
268 for(
auto el : range( mesh.cells.nb_cells( r, T ) ) ) {
270 ascii << cur_cell++ <<
" ";
271 new_line( count, 10, ascii );
273 reset_line( count, ascii );
277 for(
auto i : range( nb_interfaces ) ) {
278 if( nb_triangle_interface[i] > 0 ) {
279 ascii << interface_csmp_name( i, geomodel ) <<
" " <<
"TRI_3" 280 <<
" " << nb_triangle_interface[i] <<
EOL;
281 for(
auto el : range( nb_triangle_interface[i] ) ) {
283 ascii << cur_cell++ <<
" ";
284 new_line( count, 10, ascii );
286 reset_line( count, ascii );
288 if( nb_quad_interface[i] > 0 ) {
289 ascii << interface_csmp_name( i, geomodel ) <<
" " <<
"QUAD_4" 290 <<
" " << nb_quad_interface[i] <<
EOL;
291 for(
auto el : range( nb_quad_interface[i] ) ) {
293 ascii << cur_cell++ <<
" ";
294 new_line( count, 10, ascii );
296 reset_line( count, ascii );
299 if( geomodel.wells() ) {
300 for(
auto w : range( geomodel.wells()->nb_wells() ) ) {
301 const Well3D& well = geomodel.wells()->well( w );
302 ascii << well.name() <<
" " <<
"BAR_2" <<
" " << well.nb_edges()
304 for(
auto e : range( well.nb_edges() ) ) {
306 ascii << cur_cell++ <<
" ";
307 new_line( count, 10, ascii );
309 reset_line( count, ascii );
313 index_t nb_plist = 3 * polygons.nb_triangle() + 4 * polygons.nb_quad()
314 + 4 * mesh.cells.nb_tet() + 5 * mesh.cells.nb_pyramid()
315 + 6 * mesh.cells.nb_prism() + 8 * mesh.cells.nb_hex()
316 + 2 * mesh.wells.nb_edges();
317 data << nb_plist <<
" # PLIST" <<
EOL;
318 for(
auto r : range( geomodel.nb_regions() ) ) {
319 for(
auto type : range(
323 RINGMesh2CSMP& descriptor = *cell_type_to_cell_descriptor[type];
324 for(
auto el : range( mesh.cells.nb_cells( r, T ) ) ) {
325 index_t cell = mesh.cells.cell( r, el, T );
326 for(
auto p : range( descriptor.nb_vertices ) ) {
327 index_t csmp_p = descriptor.vertices[p];
328 index_t vertex_id = mesh.cells.vertex(
329 ElementLocalVertex( cell, csmp_p ) );
330 data <<
" " << std::setw( 7 ) << vertex_id;
331 new_line( count, 10, data );
336 for(
auto i : range( nb_interfaces ) ) {
337 const GeoModelGeologicalEntity3D& interf =
338 geomodel.geological_entity( Interface3D::type_name_static(), i );
339 for(
auto s : range( interf.nb_children() ) ) {
340 index_t s_id = interf.child_gmme( s ).index();
341 for(
auto el : range( polygons.nb_triangle( s_id ) ) ) {
342 index_t tri = polygons.triangle( s_id, el );
343 for(
auto p : range( polygons.nb_vertices( tri ) ) ) {
344 index_t vertex_id = polygons.vertex(
345 ElementLocalVertex( tri, p ) );
346 data <<
" " << std::setw( 7 ) << vertex_id;
347 new_line( count, 10, data );
350 for(
auto el : range( polygons.nb_quad( s_id ) ) ) {
351 index_t quad = polygons.quad( s_id, el );
352 for(
auto p : range( polygons.nb_vertices( quad ) ) ) {
353 index_t vertex_id = polygons.vertex(
354 ElementLocalVertex( quad, p ) );
355 data <<
" " << std::setw( 7 ) << vertex_id;
356 new_line( count, 10, data );
361 for(
auto w : range( mesh.wells.nb_wells() ) ) {
362 for(
auto e : range( mesh.wells.nb_edges( w ) ) ) {
363 for(
auto v : range( 2 ) ) {
364 index_t vertex_id = mesh.wells.vertex( w, e, v );
365 data <<
" " << std::setw( 7 ) << vertex_id;
366 new_line( count, 10, data );
370 reset_line( count, data );
372 index_t nb_polygons = 3 * polygons.nb_triangle() + 4 * polygons.nb_quad()
373 + 4 * mesh.cells.nb_tet() + 5 * mesh.cells.nb_pyramid()
374 + 5 * mesh.cells.nb_prism() + 6 * mesh.cells.nb_hex()
375 + 2 * mesh.wells.nb_edges();
376 data << nb_polygons <<
" # PFVERTS" <<
EOL;
377 for(
auto r : range( geomodel.nb_regions() ) ) {
378 for(
auto type : range(
382 RINGMesh2CSMP& descriptor = *cell_type_to_cell_descriptor[type];
383 for(
auto el : range( mesh.cells.nb_cells( r, T ) ) ) {
384 index_t cell = mesh.cells.cell( r, el );
385 for(
auto p : range( descriptor.nb_polygons ) ) {
386 index_t csmp_f = descriptor.polygon[p];
387 index_t adj = mesh.cells.adjacent( cell, csmp_f );
388 if( adj == GEO::NO_CELL ) {
389 data <<
" " << std::setw( 7 ) << -28;
391 data <<
" " << std::setw( 7 ) << adj;
393 new_line( count, 10, data );
398 for(
auto i : range( nb_interfaces ) ) {
399 const GeoModelGeologicalEntity3D& interf =
400 geomodel.geological_entity( Interface3D::type_name_static(), i );
401 for(
auto s : range( interf.nb_children() ) ) {
402 index_t s_id = interf.child_gmme( s ).index();
403 for(
auto el : range( polygons.nb_triangle( s_id ) ) ) {
404 index_t tri = polygons.triangle( s_id, el );
405 for(
auto e : range( polygons.nb_vertices( tri ) ) ) {
406 index_t adj = polygons.adjacent(
407 PolygonLocalEdge( tri, e ) );
408 if( adj == GEO::NO_FACET ) {
409 data <<
" " << std::setw( 7 ) << -28;
411 data <<
" " << std::setw( 7 ) << adj;
413 new_line( count, 10, data );
416 for(
auto el : range( polygons.nb_quad( s_id ) ) ) {
417 index_t quad = polygons.quad( s_id, el );
418 for(
auto e : range( polygons.nb_vertices( quad ) ) ) {
419 index_t adj = polygons.adjacent(
420 PolygonLocalEdge( quad, e ) );
421 if( adj == GEO::NO_FACET ) {
422 data <<
" " << std::setw( 7 ) << -28;
424 data <<
" " << std::setw( 7 ) << adj;
426 new_line( count, 10, data );
431 index_t edge_offset = polygons.nb() + mesh.cells.nb();
432 index_t cur_edge = 0;
433 for(
auto w : range( mesh.wells.nb_wells() ) ) {
434 data <<
" " << std::setw( 7 ) << -28;
435 new_line( count, 10, data );
436 if( mesh.wells.nb_edges( w ) > 1 ) {
437 data <<
" " << std::setw( 7 ) << edge_offset + cur_edge + 1;
439 new_line( count, 10, data );
440 for( index_t e = 1; e < mesh.wells.nb_edges( w ) - 1;
442 data <<
" " << std::setw( 7 ) << edge_offset + cur_edge - 1;
443 new_line( count, 10, data );
444 data <<
" " << std::setw( 7 ) << edge_offset + cur_edge + 1;
445 new_line( count, 10, data );
447 data <<
" " << std::setw( 7 ) << edge_offset + cur_edge - 1;
448 new_line( count, 10, data );
450 data <<
" " << std::setw( 7 ) << -28;
452 new_line( count, 10, data );
454 reset_line( count, data );
456 data << nb_total_entities <<
" # PMATERIAL" <<
EOL;
457 for(
auto i : range( nb_total_entities ) ) {
459 data <<
" " << std::setw( 3 ) << 0;
460 new_line( count, 20, data );
465 regions << std::flush;
471 index_t number_of_counts,
472 std::ofstream& out )
const 475 if( count == number_of_counts ) {
480 void reset_line( index_t& count, std::ofstream& out )
const 489 point_boundaries_.clear();
497 corner_boundary_flags_.clear();
498 edge_boundary_flags_.clear();
499 surface_boundary_flags_.clear();
501 void initialize(
const GeoModel3D& gm )
505 const GeoModel3D& geomodel = gm;
506 std::string cmsp_filename = GEO::CmdLine::get_arg(
"out:csmp" );
507 box_model_ = cmsp_filename !=
"";
509 GEO::LineInput parser( cmsp_filename );
511 throw RINGMeshException(
"I/O",
"Cannot open file: ",
516 while( !parser.eof() ) {
517 if( parser.nb_fields() == 0 )
continue;
518 if( parser.nb_fields() != 3 )
return;
519 std::string type = parser.field( 1 );
520 index_t interface_id = NO_ID;
521 if( type ==
"NAME" ) {
522 std::string name = parser.field( 2 );
523 GeologicalEntityType type = Interface3D::type_name_static();
524 for(
auto& cur_interface : geomodel.geol_entities( type ) ) {
525 if( cur_interface.name() == name ) {
526 interface_id = cur_interface.index();
530 }
else if( type ==
"ID" ) {
531 interface_id = parser.field_as_uint( 2 );
533 throw RINGMeshException(
"I/O",
"Unknown type: ", type );
536 std::string keyword = parser.field( 0 );
537 if( keyword ==
"BACK" ) {
538 back_ = interface_id;
539 }
else if( keyword ==
"TOP" ) {
541 }
else if( keyword ==
"FRONT" ) {
542 front_ = interface_id;
543 }
else if( keyword ==
"BOTTOM" ) {
544 bottom_ = interface_id;
545 }
else if( keyword ==
"LEFT" ) {
546 left_ = interface_id;
547 }
else if( keyword ==
"RIGHT" ) {
548 right_ = interface_id;
550 throw RINGMeshException(
"I/O",
"Unknown keyword: ",
557 if( back_ == NO_ID || top_ == NO_ID || front_ == NO_ID
558 || bottom_ == NO_ID || left_ == NO_ID || right_ == NO_ID ) {
559 throw RINGMeshException(
"I/O",
560 "Missing box shape information" );
563 surface_boundary_flags_[back_] = -7;
564 surface_boundary_flags_[top_] = -5;
565 surface_boundary_flags_[front_] = -6;
566 surface_boundary_flags_[bottom_] = -4;
567 surface_boundary_flags_[left_] = -2;
568 surface_boundary_flags_[right_] = -3;
570 std::set< index_t > back_bottom;
571 back_bottom.insert( back_ );
572 back_bottom.insert( bottom_ );
573 edge_boundary_flags_[back_bottom] = -16;
574 std::set< index_t > back_right;
575 back_right.insert( back_ );
576 back_right.insert( right_ );
577 edge_boundary_flags_[back_right] = -17;
578 std::set< index_t > back_top;
579 back_top.insert( back_ );
580 back_top.insert( top_ );
581 edge_boundary_flags_[back_top] = -18;
582 std::set< index_t > back_left;
583 back_left.insert( back_ );
584 back_left.insert( left_ );
585 edge_boundary_flags_[back_left] = -19;
586 std::set< index_t > right_bottom;
587 right_bottom.insert( right_ );
588 right_bottom.insert( bottom_ );
589 edge_boundary_flags_[right_bottom] = -20;
590 std::set< index_t > right_top;
591 right_top.insert( right_ );
592 right_top.insert( top_ );
593 edge_boundary_flags_[right_top] = -21;
594 std::set< index_t > left_top;
595 left_top.insert( left_ );
596 left_top.insert( top_ );
597 edge_boundary_flags_[left_top] = -22;
598 std::set< index_t > left_bottom;
599 left_bottom.insert( left_ );
600 left_bottom.insert( bottom_ );
601 edge_boundary_flags_[left_bottom] = -23;
602 std::set< index_t > front_bottom;
603 front_bottom.insert( front_ );
604 front_bottom.insert( bottom_ );
605 edge_boundary_flags_[front_bottom] = -24;
606 std::set< index_t > front_right;
607 front_right.insert( front_ );
608 front_right.insert( right_ );
609 edge_boundary_flags_[front_right] = -25;
610 std::set< index_t > front_top;
611 front_top.insert( front_ );
612 front_top.insert( top_ );
613 edge_boundary_flags_[front_top] = -26;
614 std::set< index_t > front_left;
615 front_left.insert( front_ );
616 front_left.insert( left_ );
617 edge_boundary_flags_[front_left] = -27;
619 std::set< index_t > back_top_left;
620 back_top_left.insert( back_ );
621 back_top_left.insert( top_ );
622 back_top_left.insert( left_ );
623 corner_boundary_flags_[back_top_left] = -13;
624 std::set< index_t > back_top_right;
625 back_top_right.insert( back_ );
626 back_top_right.insert( top_ );
627 back_top_right.insert( right_ );
628 corner_boundary_flags_[back_top_right] = -14;
629 std::set< index_t > back_bottom_left;
630 back_bottom_left.insert( back_ );
631 back_bottom_left.insert( bottom_ );
632 back_bottom_left.insert( left_ );
633 corner_boundary_flags_[back_bottom_left] = -8;
634 std::set< index_t > back_bottom_right;
635 back_bottom_right.insert( back_ );
636 back_bottom_right.insert( bottom_ );
637 back_bottom_right.insert( right_ );
638 corner_boundary_flags_[back_bottom_right] = -10;
639 std::set< index_t > front_top_left;
640 front_top_left.insert( front_ );
641 front_top_left.insert( top_ );
642 front_top_left.insert( left_ );
643 corner_boundary_flags_[front_top_left] = -15;
644 std::set< index_t > front_top_right;
645 front_top_right.insert( front_ );
646 front_top_right.insert( top_ );
647 front_top_right.insert( right_ );
648 corner_boundary_flags_[front_top_right] = -9;
649 std::set< index_t > front_bottom_left;
650 front_bottom_left.insert( front_ );
651 front_bottom_left.insert( bottom_ );
652 front_bottom_left.insert( left_ );
653 corner_boundary_flags_[front_bottom_left] = -12;
654 std::set< index_t > front_bottom_right;
655 front_bottom_right.insert( front_ );
656 front_bottom_right.insert( bottom_ );
657 front_bottom_right.insert( right_ );
658 corner_boundary_flags_[front_bottom_right] = -11;
661 point_boundaries_.resize( gm.mesh.vertices.nb() );
662 for(
const auto& surface : surface_range < 3 > ( gm ) ) {
663 index_t interface_id = surface.parent_gmge( 0 ).index();
665 gm.mesh.polygons.nb_polygons( surface.index() ) ) ) {
666 index_t p_id = gm.mesh.polygons.polygon( surface.index(), p );
667 for(
auto v : range( gm.mesh.polygons.nb_vertices( p_id ) ) ) {
668 index_t vertex_id = gm.mesh.polygons.vertex(
669 ElementLocalVertex( p_id, v ) );
670 point_boundaries_[vertex_id].insert( interface_id );
675 std::string interface_csmp_name(
677 const GeoModel3D& geomodel )
const 682 }
else if( i == top_ ) {
684 }
else if( i == front_ ) {
686 }
else if( i == bottom_ ) {
688 }
else if( i == left_ ) {
690 }
else if( i == right_ ) {
694 return geomodel.geological_entity( Interface3D::type_name_static(), i ).name();
696 signed_index_t point_boundary( index_t p )
const 699 const std::set< unsigned int >& boundaries = point_boundaries_[p];
701 if( boundaries.size() == 1 ) {
702 auto it = surface_boundary_flags_.find( *boundaries.begin() );
705 }
else if( boundaries.size() == 2 ) {
706 auto it = edge_boundary_flags_.find( boundaries );
709 }
else if( boundaries.size() == 3 ) {
710 auto it = corner_boundary_flags_.find( boundaries );
717 if( boundaries.empty() )
724 std::vector< std::set< index_t > > point_boundaries_;
734 std::map< std::set< index_t >, signed_index_t > corner_boundary_flags_;
735 std::map< std::set< index_t >, signed_index_t > edge_boundary_flags_;
736 std::map< index_t, signed_index_t > surface_boundary_flags_;
void ringmesh_unused(const T &)
auto to_underlying_type(Enum e) -> typename std::underlying_type< Enum >::type
#define ringmesh_assert(x)