Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
iwr
dune-vtk
Commits
c66bd4cd
Commit
c66bd4cd
authored
Jul 06, 2020
by
Praetorius, Simon
Browse files
rename read method due to missunderstanding
parent
178a7777
Changes
12
Hide whitespace changes
Inline
Side-by-side
dune/vtk/filereader.hh
View file @
c66bd4cd
...
...
@@ -21,15 +21,15 @@ namespace Dune
struct
Accessor
:
public
Implementation
{
template
<
class
...
Args
>
static
std
::
unique_ptr
<
Grid
>
rea
d
Imp
(
Args
&&
...
args
)
static
std
::
unique_ptr
<
Grid
>
c
rea
teGridFromFile
Imp
l
(
Args
&&
...
args
)
{
return
Implementation
::
rea
d
Impl
(
std
::
forward
<
Args
>
(
args
)...);
return
Implementation
::
c
rea
teGridFromFile
Impl
(
std
::
forward
<
Args
>
(
args
)...);
}
template
<
class
...
Args
>
static
void
read
FactoryImpl
(
Args
&&
...
args
)
static
void
fill
FactoryImpl
(
Args
&&
...
args
)
{
return
Implementation
::
read
FactoryImpl
(
std
::
forward
<
Args
>
(
args
)...);
return
Implementation
::
fill
FactoryImpl
(
std
::
forward
<
Args
>
(
args
)...);
}
};
...
...
@@ -37,34 +37,38 @@ namespace Dune
/// Reads the grid from a file with filename and returns a unique_ptr to the created grid.
/// Redirects to concrete implementation of derivated class.
template
<
class
...
Args
>
static
std
::
unique_ptr
<
Grid
>
rea
d
(
const
std
::
string
&
filename
,
Args
&&
...
args
)
static
std
::
unique_ptr
<
Grid
>
c
rea
teGridFromFile
(
const
std
::
string
&
filename
,
Args
&&
...
args
)
{
return
Accessor
::
rea
d
Impl
(
filename
,
std
::
forward
<
Args
>
(
args
)...);
return
Accessor
::
c
rea
teGridFromFile
Impl
(
filename
,
std
::
forward
<
Args
>
(
args
)...);
}
/// Reads the grid from a file with filename into a grid-factory.
/// Redirects to concrete implementation of derivated class.
template
<
class
...
Args
>
static
void
read
(
GridFactory
<
Grid
>
&
factory
,
const
std
::
string
&
filename
,
Args
&&
...
args
)
static
void
fillFactory
(
GridFactory
<
Grid
>
&
factory
,
const
std
::
string
&
filename
,
Args
&&
...
args
)
{
Accessor
::
read
FactoryImpl
(
factory
,
filename
,
std
::
forward
<
Args
>
(
args
)...);
Accessor
::
fill
FactoryImpl
(
factory
,
filename
,
std
::
forward
<
Args
>
(
args
)...);
}
protected:
// default implementations
// Default implementation, redirects to factory
read
implementation.
// Default implementation, redirects to f
illF
actory implementation.
template
<
class
...
Args
>
static
std
::
unique_ptr
<
Grid
>
readImpl
(
const
std
::
string
&
filename
,
Args
&&
...
args
)
static
std
::
unique_ptr
<
Grid
>
createGridFromFileImpl
(
const
std
::
string
&
filename
,
Args
&&
...
args
)
{
GridFactory
<
Grid
>
factory
;
read
(
factory
,
filename
,
std
::
forward
<
Args
>
(
args
)...);
fillFactory
(
factory
,
filename
,
std
::
forward
<
Args
>
(
args
)...);
return
std
::
unique_ptr
<
Grid
>
{
factory
.
createGrid
()
};
}
// Default implementation for reading into grid-factory: produces a runtime-error.
template
<
class
...
Args
>
static
void
readFactoryImpl
(
GridFactory
<
Grid
>
&
/*factory*/
,
const
std
::
string
&
/*filename*/
,
static
void
fillFactoryImpl
(
GridFactory
<
Grid
>
&
/*factory*/
,
const
std
::
string
&
/*filename*/
,
Args
&&
...
/*args*/
)
{
DUNE_THROW
(
NotImplemented
,
...
...
dune/vtk/gridcreatorinterface.hh
View file @
c66bd4cd
...
...
@@ -18,7 +18,7 @@ namespace Dune
* Construct a grid from data read from VTK files.
*
* \tparam GridType Model of Dune::Grid
* \tparam GlobalCoordType Type of the global coordinates.
* \tparam GlobalCoordType Type of the global coordinates.
* \tparam DerivedType Implementation of a concrete GridCreator.
**/
template
<
class
GridType
,
class
DerivedType
>
...
...
@@ -56,6 +56,12 @@ namespace Dune
asDerived
().
insertPiecesImpl
(
pieces
);
}
/// Construct the actual grid using the GridFactory
std
::
unique_ptr
<
Grid
>
createGrid
()
const
{
return
factory_
->
createGrid
();
}
/// Return the associated GridFactory
GridFactory
<
Grid
>&
factory
()
{
...
...
dune/vtk/gridcreators/lagrangegridcreator.hh
View file @
c66bd4cd
...
...
@@ -131,7 +131,8 @@ namespace Dune
// try to create element with parametrization
if
constexpr
(
Std
::
is_detected_v
<
HasParametrizedElements
,
GridFactory
<
GridType
>>
)
{
try
{
factory
().
insertElement
(
type
,
element
,
localParametrization
(
parametrization_
.
size
()
-
1
));
factory
().
insertElement
(
type
,
element
,
localParametrization
(
parametrization_
.
size
()
-
1
));
}
catch
(
Dune
::
GridError
const
&
/* notImplemented */
)
{
factory
().
insertElement
(
type
,
element
);
}
...
...
@@ -232,9 +233,21 @@ namespace Dune
return
LocalFunction
{
gridCreator
};
}
friend
LocalFunction
localFunction
(
LagrangeGridCreator
const
&
gridCreator
)
{
return
LocalFunction
{
gridCreator
};
}
friend
LocalFunction
localFunction
(
LagrangeGridCreator
&&
gridCreator
)
{
DUNE_THROW
(
Dune
::
Exception
,
"Cannot pass temporary LagrangeGridCreator to localFunction(). Pass an lvalue-reference instead."
);
return
LocalFunction
{
gridCreator
};
}
struct
EntitySet
{
using
Grid
=
GridType
;
using
GlobalCoordinate
=
typename
Self
::
GlobalCoordinate
;
};
/// Dummy function returning a placeholder entityset
...
...
@@ -334,10 +347,12 @@ namespace Dune
using
LocalParametrization
=
typename
LagrangeGridCreator
::
LocalParametrization
;
public:
explicit
LocalFunction
(
LagrangeGridCreator
&
gridCreator
)
explicit
LocalFunction
(
LagrangeGridCreator
const
&
gridCreator
)
:
gridCreator_
(
&
gridCreator
)
{}
explicit
LocalFunction
(
LagrangeGridCreator
&&
gridCreator
)
=
delete
;
/// Collect a local parametrization on the element
void
bind
(
LocalContext
const
&
element
)
{
...
...
dune/vtk/gridcreators/parallelgridcreator.hh
View file @
c66bd4cd
...
...
@@ -42,7 +42,7 @@ namespace Dune
{
if
(
int
(
pieces
.
size
())
==
this
->
comm
().
size
())
{
VtkReader
<
Grid
,
Self
>
pieceReader
(
this
->
factory
());
pieceReader
.
read
FromFile
(
pieces
[
this
->
comm
().
rank
()],
true
);
pieceReader
.
read
(
pieces
[
this
->
comm
().
rank
()],
true
);
}
}
};
...
...
dune/vtk/gridcreators/serialgridcreator.hh
View file @
c66bd4cd
...
...
@@ -53,8 +53,8 @@ namespace Dune
if
(
this
->
comm
().
rank
()
==
0
)
{
VtkReader
<
Grid
,
Self
>
pieceReader
(
*
this
);
for
(
std
::
string
const
&
piece
:
pieces
)
{
pieceReader
.
read
FromFile
(
piece
,
false
);
pieceReader
.
createGrid
(
false
);
pieceReader
.
read
(
piece
,
false
);
pieceReader
.
fillGridCreator
(
false
);
}
DiscontinuousGridCreator
<
Grid
>
creator
(
this
->
factory
());
...
...
dune/vtk/vtkreader.hh
View file @
c66bd4cd
...
...
@@ -61,18 +61,18 @@ namespace Dune
:
creator_
(
std
::
move
(
creator
))
{}
/// Read the grid from file with `filename` into the Grid
Factory \ref fac
tor
y_
/// Read the grid from file with `filename` into the Grid
Crea
tor
/**
* \param filename The name of the input file
* \param
c
reat
e
If `false`, only fill internal data structures, if `true`,
also create
the
g
rid. [true]
* \param
fillC
reat
or
If `false`, only fill internal data structures, if `true`,
pass the internal data to
the
G
rid
Creator
. [true]
**/
void
read
FromFile
(
std
::
string
const
&
filename
,
bool
c
reat
e
=
true
);
void
read
(
std
::
string
const
&
filename
,
bool
fillC
reat
or
=
true
);
/// Implementation of \ref FileReader interface
static
void
read
FactoryImpl
(
GridFactory
<
Grid
>&
factory
,
std
::
string
const
&
filename
)
static
void
fill
FactoryImpl
(
GridFactory
<
Grid
>&
factory
,
std
::
string
const
&
filename
)
{
VtkReader
reader
{
factory
};
reader
.
read
FromFile
(
filename
);
reader
.
read
(
filename
);
}
/// Obtains the creator of the grid
...
...
@@ -81,6 +81,12 @@ namespace Dune
return
*
creator_
;
}
/// Construct the actual grid using the GridCreator
std
::
unique_ptr
<
Grid
>
createGrid
()
const
{
return
creator_
->
createGrid
();
}
/// Advanced read methods
/// @{
...
...
@@ -98,9 +104,9 @@ namespace Dune
**/
void
readParallelFileFromStream
(
std
::
ifstream
&
input
,
int
rank
,
int
size
,
bool
create
=
true
);
///
Construct a grid using
the GridCreator
// NOTE: requires the internal data structures to be filled by an aforgoing call to read
FromFile
void
createGrid
(
bool
insertPieces
=
true
);
///
Insert all internal data to
the GridCreator
// NOTE: requires the internal data structures to be filled by an aforgoing call to read
()
void
fillGridCreator
(
bool
insertPieces
=
true
);
/// @}
...
...
dune/vtk/vtkreader.impl.hh
View file @
c66bd4cd
...
...
@@ -16,7 +16,7 @@
namespace
Dune
{
template
<
class
Grid
,
class
Creator
>
void
VtkReader
<
Grid
,
Creator
>::
read
FromFile
(
std
::
string
const
&
filename
,
bool
c
reat
e
)
void
VtkReader
<
Grid
,
Creator
>::
read
(
std
::
string
const
&
filename
,
bool
fillC
reat
or
)
{
// check whether file exists!
if
(
!
filesystem
::
exists
(
filename
))
...
...
@@ -27,10 +27,10 @@ void VtkReader<Grid,Creator>::readFromFile (std::string const& filename, bool cr
std
::
string
ext
=
filesystem
::
path
(
filename
).
extension
().
string
();
if
(
ext
==
".vtu"
)
{
readSerialFileFromStream
(
input
,
c
reat
e
);
readSerialFileFromStream
(
input
,
fillC
reat
or
);
pieces_
.
push_back
(
filename
);
}
else
if
(
ext
==
".pvtu"
)
{
readParallelFileFromStream
(
input
,
comm
().
rank
(),
comm
().
size
(),
c
reat
e
);
readParallelFileFromStream
(
input
,
comm
().
rank
(),
comm
().
size
(),
fillC
reat
or
);
}
else
{
DUNE_THROW
(
IOError
,
"File has unknown file-extension '"
<<
ext
<<
"'. Allowed are only '.vtu' and '.pvtu'."
);
}
...
...
@@ -38,7 +38,7 @@ void VtkReader<Grid,Creator>::readFromFile (std::string const& filename, bool cr
template
<
class
Grid
,
class
Creator
>
void
VtkReader
<
Grid
,
Creator
>::
readSerialFileFromStream
(
std
::
ifstream
&
input
,
bool
c
reat
e
)
void
VtkReader
<
Grid
,
Creator
>::
readSerialFileFromStream
(
std
::
ifstream
&
input
,
bool
fillC
reat
or
)
{
clear
();
std
::
string
compressor
=
""
;
...
...
@@ -225,13 +225,13 @@ void VtkReader<Grid,Creator>::readSerialFileFromStream (std::ifstream& input, bo
if
(
section
!=
NO_SECTION
)
DUNE_THROW
(
IOError
,
"VTK-File is incomplete. It must end with </VTKFile>!"
);
if
(
c
reat
e
)
createGrid
();
if
(
fillC
reat
or
)
fillGridCreator
();
}
template
<
class
Grid
,
class
Creator
>
void
VtkReader
<
Grid
,
Creator
>::
readParallelFileFromStream
(
std
::
ifstream
&
input
,
int
commRank
,
int
commSize
,
bool
c
reat
e
)
void
VtkReader
<
Grid
,
Creator
>::
readParallelFileFromStream
(
std
::
ifstream
&
input
,
int
commRank
,
int
commSize
,
bool
fillC
reat
or
)
{
clear
();
...
...
@@ -276,8 +276,8 @@ void VtkReader<Grid,Creator>::readParallelFileFromStream (std::ifstream& input,
if
(
section
!=
NO_SECTION
)
DUNE_THROW
(
IOError
,
"VTK-File is incomplete. It must end with </VTKFile>!"
);
if
(
c
reat
e
)
createGrid
();
if
(
fillC
reat
or
)
fillGridCreator
();
}
...
...
@@ -543,7 +543,7 @@ void VtkReader<Grid,Creator>::readAppended (std::ifstream& input, std::vector<T>
template
<
class
Grid
,
class
Creator
>
void
VtkReader
<
Grid
,
Creator
>::
createGrid
(
bool
insertPieces
)
void
VtkReader
<
Grid
,
Creator
>::
fillGridCreator
(
bool
insertPieces
)
{
assert
(
vec_points
.
size
()
==
numberOfPoints_
);
assert
(
vec_types
.
size
()
==
numberOfCells_
);
...
...
src/lagrangereader.cc
View file @
c66bd4cd
...
...
@@ -51,7 +51,7 @@ int main(int argc, char** argv)
{
// Test using the (static) file-reader interface
std
::
cout
<<
"Test 1..."
<<
std
::
endl
;
auto
gridPtr
=
VtkReader
<
GridType
,
GridCreator
>::
rea
d
(
GRID_PATH
"/"
+
filename
+
".vtu"
);
auto
gridPtr
=
VtkReader
<
GridType
,
GridCreator
>::
c
rea
teGridFromFile
(
GRID_PATH
"/"
+
filename
+
".vtu"
);
auto
&
grid
=
*
gridPtr
;
grid
.
globalRefine
(
2
);
...
...
@@ -63,7 +63,7 @@ int main(int argc, char** argv)
std
::
cout
<<
"Test 2..."
<<
std
::
endl
;
GridFactory
<
GridType
>
factory
;
VtkReader
<
GridType
,
GridCreator
>
reader
(
factory
);
reader
.
read
FromFile
(
GRID_PATH
"/"
+
filename
+
".vtu"
);
reader
.
read
(
GRID_PATH
"/"
+
filename
+
".vtu"
);
auto
gridPtr
=
factory
.
createGrid
();
auto
&
grid
=
*
gridPtr
;
...
...
@@ -80,7 +80,7 @@ int main(int argc, char** argv)
GridFactory
<
GridType
>
factory
;
GridCreator
creator
(
factory
);
VtkReader
<
GridType
,
GridCreator
>
reader
(
creator
);
reader
.
read
FromFile
(
GRID_PATH
"/"
+
filename
+
".vtu"
);
reader
.
read
(
GRID_PATH
"/"
+
filename
+
".vtu"
);
auto
gridPtr
=
factory
.
createGrid
();
auto
&
grid
=
*
gridPtr
;
...
...
src/test/mixed_element_test.cc
View file @
c66bd4cd
...
...
@@ -82,7 +82,7 @@ template <class Grid, class Test>
void
reader_test
(
Test
&
test
)
{
for
(
auto
const
&
test_case
:
test_cases
)
{
auto
grid
=
VtkReader
<
Grid
>::
rea
d
(
"mixed_element_test_"
+
std
::
get
<
0
>
(
test_case
)
+
".vtu"
);
auto
grid
=
VtkReader
<
Grid
>::
c
rea
teGridFromFile
(
"mixed_element_test_"
+
std
::
get
<
0
>
(
test_case
)
+
".vtu"
);
VtkUnstructuredGridWriter
<
typename
Grid
::
LeafGridView
>
vtkWriter
(
grid
->
leafGridView
(),
std
::
get
<
1
>
(
test_case
),
std
::
get
<
2
>
(
test_case
));
vtkWriter
.
write
(
"mixed_element_test_"
+
std
::
get
<
0
>
(
test_case
)
+
"_2.vtu"
);
...
...
src/test/parallel_reader_writer_test.cc
View file @
c66bd4cd
...
...
@@ -119,7 +119,7 @@ void reader_writer_test(MPIHelper& mpi, TestSuite& test, std::string const& test
// Step 2: read the grid from file1 and write it back to file2
{
GridFactory
<
Grid
>
factory
;
VtkReader
<
Grid
,
Creator
>
reader
{
factory
};
reader
.
read
FromFile
(
base_name
+
ext
);
reader
.
read
(
base_name
+
ext
);
std
::
unique_ptr
<
Grid
>
grid
{
Hybrid
::
ifElse
(
HasParallelGridFactory
<
Grid
>
{},
[
&
](
auto
id
)
{
return
id
(
factory
).
createGrid
(
std
::
true_type
{});
},
...
...
@@ -135,7 +135,7 @@ void reader_writer_test(MPIHelper& mpi, TestSuite& test, std::string const& test
// Step 3: read the (parallel) file1 to get the piece filenames
{
GridFactory
<
Grid
>
factory
;
VtkReader
<
Grid
,
Creator
>
reader
{
factory
};
reader
.
read
FromFile
(
base_name
+
"_1"
+
ext
);
reader
.
read
(
base_name
+
"_1"
+
ext
);
std
::
unique_ptr
<
Grid
>
grid
{
Hybrid
::
ifElse
(
HasParallelGridFactory
<
Grid
>
{},
[
&
](
auto
id
)
{
return
id
(
factory
).
createGrid
(
std
::
true_type
{});
},
...
...
@@ -152,7 +152,7 @@ void reader_writer_test(MPIHelper& mpi, TestSuite& test, std::string const& test
// Step 4: read the (parallel) file2 to get the piece filenames
{
GridFactory
<
Grid
>
factory
;
VtkReader
<
Grid
,
Creator
>
reader
{
factory
};
reader
.
read
FromFile
(
base_name
+
"_2"
+
ext
,
false
);
reader
.
read
(
base_name
+
"_2"
+
ext
,
false
);
pieces2
=
reader
.
pieces
();
}
...
...
src/test/reader_writer_test.cc
View file @
c66bd4cd
...
...
@@ -105,7 +105,7 @@ void reader_test (MPIHelper& mpi, Test& test)
{
GridFactory
<
Grid
>
factory
;
VtkReader
<
Grid
>
reader
{
factory
};
reader
.
read
FromFile
(
"reader_writer_test_"
+
std
::
get
<
0
>
(
test_case
)
+
ext
);
reader
.
read
(
"reader_writer_test_"
+
std
::
get
<
0
>
(
test_case
)
+
ext
);
std
::
unique_ptr
<
Grid
>
grid
{
factory
.
createGrid
()};
pieces1
=
reader
.
pieces
();
...
...
@@ -118,7 +118,7 @@ void reader_test (MPIHelper& mpi, Test& test)
{
GridFactory
<
Grid
>
factory2
;
VtkReader
<
Grid
>
reader2
{
factory2
};
reader2
.
read
FromFile
(
"reader_writer_test_"
+
std
::
get
<
0
>
(
test_case
)
+
"_2"
+
ext
,
false
);
reader2
.
read
(
"reader_writer_test_"
+
std
::
get
<
0
>
(
test_case
)
+
"_2"
+
ext
,
false
);
pieces2
=
reader2
.
pieces
();
}
...
...
src/vtkreader.cc
View file @
c66bd4cd
...
...
@@ -51,7 +51,7 @@ int main(int argc, char** argv)
{
std
::
cout
<<
"read 'test_ascii_float32.vtu'..."
<<
std
::
endl
;
auto
gridPtr
=
VtkReader
<
GridType
>::
rea
d
(
"test_ascii_float32.vtu"
);
auto
gridPtr
=
VtkReader
<
GridType
>::
c
rea
teGridFromFile
(
"test_ascii_float32.vtu"
);
auto
&
grid
=
*
gridPtr
;
VtkUnstructuredGridWriter
<
GridView
>
vtkWriter
(
grid
.
leafGridView
(),
Vtk
::
ASCII
);
...
...
@@ -60,7 +60,7 @@ int main(int argc, char** argv)
{
std
::
cout
<<
"read 'test_binary_float32.vtu'..."
<<
std
::
endl
;
auto
gridPtr
=
VtkReader
<
GridType
>::
rea
d
(
"test_binary_float32.vtu"
);
auto
gridPtr
=
VtkReader
<
GridType
>::
c
rea
teGridFromFile
(
"test_binary_float32.vtu"
);
auto
&
grid
=
*
gridPtr
;
VtkUnstructuredGridWriter
<
GridView
>
vtkWriter
(
grid
.
leafGridView
(),
Vtk
::
ASCII
);
...
...
@@ -69,7 +69,7 @@ int main(int argc, char** argv)
{
std
::
cout
<<
"read 'test_compressed_float64.vtu'..."
<<
std
::
endl
;
auto
gridPtr
=
VtkReader
<
GridType
>::
rea
d
(
"test_compressed_float64.vtu"
);
auto
gridPtr
=
VtkReader
<
GridType
>::
c
rea
teGridFromFile
(
"test_compressed_float64.vtu"
);
auto
&
grid
=
*
gridPtr
;
VtkUnstructuredGridWriter
<
GridView
>
vtkWriter
(
grid
.
leafGridView
(),
Vtk
::
ASCII
,
Vtk
::
FLOAT64
);
...
...
@@ -78,7 +78,7 @@ int main(int argc, char** argv)
{
std
::
cout
<<
"read 'test_ascii_float32.vtu'..."
<<
std
::
endl
;
auto
gridPtr
=
VtkReader
<
GridType
,
DiscontinuousGridCreator
<
GridType
>>::
rea
d
(
"test_ascii_float32.vtu"
);
auto
gridPtr
=
VtkReader
<
GridType
,
DiscontinuousGridCreator
<
GridType
>>::
c
rea
teGridFromFile
(
"test_ascii_float32.vtu"
);
auto
&
grid
=
*
gridPtr
;
VtkUnstructuredGridWriter
<
GridView
>
vtkWriter
(
grid
.
leafGridView
(),
Vtk
::
ASCII
);
...
...
@@ -90,7 +90,7 @@ int main(int argc, char** argv)
using
GridView3d
=
typename
GridType3d
::
LeafGridView
;
std
::
cout
<<
"read 'paraview_3d.vtu'..."
<<
std
::
endl
;
auto
gridPtr
=
VtkReader
<
GridType3d
>::
rea
d
(
"paraview_3d.vtu"
);
auto
gridPtr
=
VtkReader
<
GridType3d
>::
c
rea
teGridFromFile
(
"paraview_3d.vtu"
);
auto
&
grid
=
*
gridPtr
;
VtkUnstructuredGridWriter
<
GridView3d
>
vtkWriter
(
grid
.
leafGridView
(),
Vtk
::
ASCII
,
Vtk
::
FLOAT64
);
...
...
@@ -102,7 +102,7 @@ int main(int argc, char** argv)
using
GridType2d
=
UGGrid
<
2
>
;
using
GridView2d
=
typename
GridType2d
::
LeafGridView
;
std
::
cout
<<
"read 'paraview_2d.vtu'..."
<<
std
::
endl
;
auto
gridPtr
=
VtkReader
<
GridType2d
>::
rea
d
(
"paraview_2d.vtu"
);
auto
gridPtr
=
VtkReader
<
GridType2d
>::
c
rea
teGridFromFile
(
"paraview_2d.vtu"
);
auto
&
grid
=
*
gridPtr
;
VtkUnstructuredGridWriter
<
GridView2d
>
vtkWriter
(
grid
.
leafGridView
(),
Vtk
::
ASCII
,
Vtk
::
FLOAT64
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment