Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
elpa
elpa
Commits
6a4cc5fb
Commit
6a4cc5fb
authored
May 24, 2017
by
Andreas Marek
Browse files
C function for elpa_solve_tridi in new API
parent
15dffbd1
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
elpa/elpa_generic.h
View file @
6a4cc5fb
...
...
@@ -64,3 +64,13 @@
elpa_invert_trm_fc \
)(handle, a, error)
/**
* \todo document elpa_solve_tridi()
*/
#define elpa_solve_tridi(handle, d, e, q, error) _Generic((d), \
double*: \
elpa_solve_tridi_d, \
\
float*: \
elpa_solve_tridi_f \
)(handle, d, e, q, error)
src/elpa_api.F90
View file @
6a4cc5fb
...
...
@@ -349,6 +349,14 @@ module elpa_api
! Actual math routines
!> \brief abstract definition of interface to solve double real eigenvalue problem
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
!> blocksize, the number of eigenvectors
!> to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!> Parameters
!> \details
!> \param self class(elpa_t), the ELPA object
...
...
@@ -374,6 +382,14 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to solve single real eigenvalue problem
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
!> blocksize, the number of eigenvectors
!> to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!> Parameters
!> \details
!> \param self class(elpa_t), the ELPA object
...
...
@@ -399,6 +415,14 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to solve double complex eigenvalue problem
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
!> blocksize, the number of eigenvectors
!> to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!> Parameters
!> \details
!> \param self class(elpa_t), the ELPA object
...
...
@@ -425,6 +449,14 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to solve single complex eigenvalue problem
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
!> blocksize, the number of eigenvectors
!> to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!> Parameters
!> \details
!> \param self class(elpa_t), the ELPA object
...
...
@@ -662,6 +694,11 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to do a cholesky decomposition of a double real matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> Parameters
!> \param self class(elpa_t), the ELPA object
!> \param a double real matrix: the matrix to be decomposed
...
...
@@ -682,6 +719,11 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to do a cholesky decomposition of a single real matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> Parameters
!> \param self class(elpa_t), the ELPA object
!> \param a single real matrix: the matrix to be decomposed
...
...
@@ -702,6 +744,11 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to do a cholesky decomposition of a double complex matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> Parameters
!> \param self class(elpa_t), the ELPA object
!> \param a double complex matrix: the matrix to be decomposed
...
...
@@ -722,6 +769,11 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to do a cholesky decomposition of a single complex matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> Parameters
!> \param self class(elpa_t), the ELPA object
!> \param a single complex matrix: the matrix to be decomposed
...
...
@@ -742,6 +794,11 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to invert a triangular double real matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> Parameters
!> \param self class(elpa_t), the ELPA object
!> \param a double real matrix: the matrix to be inverted
...
...
@@ -763,6 +820,11 @@ module elpa_api
!> \brief abstract definition of interface to invert a triangular single real matrix
!> Parameters
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> \param self class(elpa_t), the ELPA object
!> \param a single real matrix: the matrix to be inverted
!> \param error integer, optional : error code, which can be queried with elpa_strerr
...
...
@@ -782,6 +844,11 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to invert a triangular double complex matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> Parameters
!> \param self class(elpa_t), the ELPA object
!> \param a double complex matrix: the matrix to be inverted
...
...
@@ -802,6 +869,11 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to invert a triangular single complex matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> Parameters
!> \param self class(elpa_t), the ELPA object
!> \param a single complex matrix: the matrix to be inverted
...
...
@@ -822,9 +894,15 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to solve the eigenvalue problem for a double-precision real valued tridiangular matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> Parameters
!> \param self class(elpa_t), the ELPA object
!> \param d double real 1d array: the diagonal elements of a matrix defined in setup
!> \param d double real 1d array: the diagonal elements of a matrix defined in setup, on output the eigenvalues
!> in ascending order
!> \param e double real 1d array: the subdiagonal elements of a matrix defined in setup
!> \param q double real matrix: on output contains the eigenvectors
!> \param error integer, optional : error code, which can be queried with elpa_strerr
...
...
@@ -845,9 +923,15 @@ module elpa_api
end
interface
!> \brief abstract definition of interface to solve the eigenvalue problem for a single-precision real valued tridiangular matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> Parameters
!> \param self class(elpa_t), the ELPA object
!> \param d single real 1d array: the diagonal elements of a matrix defined in setup
!> \param d single real 1d array: the diagonal elements of a matrix defined in setup, on output the eigenvalues
!> in ascending order
!> \param e single real 1d array: the subdiagonal elements of a matrix defined in setup
!> \param q single real matrix: on output contains the eigenvectors
!> \param error integer, optional : error code, which can be queried with elpa_strerr
...
...
src/elpa_impl.F90
View file @
6a4cc5fb
...
...
@@ -485,7 +485,8 @@ module elpa_impl
!> \brief elpa_solve_d: class method to solve the eigenvalue problem for double real matrices
!>
!> The dimensions of the matrix a (locally ditributed and global), the number of eigenvectors
!> The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
!> blocksize, the number of eigenvectors
!> to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
...
...
@@ -566,7 +567,8 @@ module elpa_impl
!> \brief elpa_solve_f: class method to solve the eigenvalue problem for float real matrices
!>
!> The dimensions of the matrix a (locally ditributed and global), the number of eigenvectors
!> The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
!> blocksize, the number of eigenvectors
!> to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
...
...
@@ -652,7 +654,8 @@ module elpa_impl
!> \brief elpa_solve_dc: class method to solve the eigenvalue problem for double complex matrices
!>
!> The dimensions of the matrix a (locally ditributed and global), the number of eigenvectors
!> The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
!> blocksize, the number of eigenvectors
!> to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
...
...
@@ -734,7 +737,8 @@ module elpa_impl
!> \brief elpa_solve_fc: class method to solve the eigenvalue problem for float complex matrices
!>
!> The dimensions of the matrix a (locally ditributed and global), the number of eigenvectors
!> The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
!> blocksize, the number of eigenvectors
!> to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
...
...
@@ -916,7 +920,7 @@ module elpa_impl
!> \param c matrix c
!> \param nrows_c number of rows of local (sub) matrix c
!> \param ncols_c number of columns of local (sub) matrix c
!> \param error optional argument, returns an error code
!> \param error optional argument, returns an error code
, which can be queried with elpa_strerr
subroutine
elpa_hermitian_multiply_f
(
self
,
uplo_a
,
uplo_c
,
na
,
ncb
,
a
,
nrows_a
,
ncols_a
,
b
,
nrows_b
,
ncols_b
,
&
c
,
nrows_c
,
ncols_c
,
error
)
use
iso_c_binding
...
...
@@ -983,7 +987,7 @@ module elpa_impl
!> \param c matrix c
!> \param nrows_c number of rows of local (sub) matrix c
!> \param ncols_c number of columns of local (sub) matrix c
!> \param error optional argument, returns an error code
!> \param error optional argument, returns an error code
, which can be queried with elpa_strerr
subroutine
elpa_hermitian_multiply_dc
(
self
,
uplo_a
,
uplo_c
,
na
,
ncb
,
a
,
nrows_a
,
ncols_a
,
b
,
nrows_b
,
ncols_b
,
&
c
,
nrows_c
,
ncols_c
,
error
)
use
iso_c_binding
...
...
@@ -1046,7 +1050,7 @@ module elpa_impl
!> \param c matrix c
!> \param nrows_c number of rows of local (sub) matrix c
!> \param ncols_c number of columns of local (sub) matrix c
!> \param error optional argument, returns an error code
!> \param error optional argument, returns an error code
, which can be queried with elpa_strerr
subroutine
elpa_hermitian_multiply_fc
(
self
,
uplo_a
,
uplo_c
,
na
,
ncb
,
a
,
nrows_a
,
ncols_a
,
b
,
nrows_b
,
ncols_b
,
&
c
,
nrows_c
,
ncols_c
,
error
)
use
iso_c_binding
...
...
@@ -1080,7 +1084,23 @@ module elpa_impl
#endif
end
subroutine
!> \brief elpa_choleksy_d: class method to do a cholesky factorization for a double real matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param a Distributed matrix for which eigenvalues are to be computed.
!> Distribution is like in Scalapack.
!> The full matrix must be set (not only one half like in scalapack).
!> Destroyed on exit (upper and lower half).
!>
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
subroutine
elpa_cholesky_d
(
self
,
a
,
error
)
use
iso_c_binding
use
elpa1_auxiliary_impl
...
...
@@ -1122,7 +1142,23 @@ module elpa_impl
call
elpa_cholesky_d
(
self
,
a
,
error
)
end
subroutine
!> \brief elpa_choleksy_f: class method to do a cholesky factorization for a float real matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param a Distributed matrix for which eigenvalues are to be computed.
!> Distribution is like in Scalapack.
!> The full matrix must be set (not only one half like in scalapack).
!> Destroyed on exit (upper and lower half).
!>
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
subroutine
elpa_cholesky_f
(
self
,
a
,
error
)
use
iso_c_binding
use
elpa1_auxiliary_impl
...
...
@@ -1169,7 +1205,23 @@ module elpa_impl
call
elpa_cholesky_f
(
self
,
a
,
error
)
end
subroutine
!> \brief elpa_choleksy_d: class method to do a cholesky factorization for a double complex matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param a Distributed matrix for which eigenvalues are to be computed.
!> Distribution is like in Scalapack.
!> The full matrix must be set (not only one half like in scalapack).
!> Destroyed on exit (upper and lower half).
!>
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
subroutine
elpa_cholesky_dc
(
self
,
a
,
error
)
use
iso_c_binding
use
elpa1_auxiliary_impl
...
...
@@ -1211,7 +1263,23 @@ module elpa_impl
call
elpa_cholesky_dc
(
self
,
a
,
error
)
end
subroutine
!> \brief elpa_choleksy_fc: class method to do a cholesky factorization for a float complex matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param a Distributed matrix for which eigenvalues are to be computed.
!> Distribution is like in Scalapack.
!> The full matrix must be set (not only one half like in scalapack).
!> Destroyed on exit (upper and lower half).
!>
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
subroutine
elpa_cholesky_fc
(
self
,
a
,
error
)
use
iso_c_binding
use
elpa1_auxiliary_impl
...
...
@@ -1257,7 +1325,23 @@ module elpa_impl
call
elpa_cholesky_fc
(
self
,
a
,
error
)
end
subroutine
!> \brief elpa_invert_trim_d: class method to invert a triangular double real matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param a Distributed matrix for which eigenvalues are to be computed.
!> Distribution is like in Scalapack.
!> The full matrix must be set (not only one half like in scalapack).
!> Destroyed on exit (upper and lower half).
!>
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
subroutine
elpa_invert_trm_d
(
self
,
a
,
error
)
use
iso_c_binding
use
elpa1_auxiliary_impl
...
...
@@ -1298,7 +1382,23 @@ module elpa_impl
call
elpa_invert_trm_d
(
self
,
a
,
error
)
end
subroutine
!> \brief elpa_invert_trim_f: class method to invert a triangular float real matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param a Distributed matrix for which eigenvalues are to be computed.
!> Distribution is like in Scalapack.
!> The full matrix must be set (not only one half like in scalapack).
!> Destroyed on exit (upper and lower half).
!>
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
subroutine
elpa_invert_trm_f
(
self
,
a
,
error
)
use
iso_c_binding
use
elpa1_auxiliary_impl
...
...
@@ -1344,7 +1444,23 @@ module elpa_impl
call
elpa_invert_trm_f
(
self
,
a
,
error
)
end
subroutine
!> \brief elpa_invert_trim_dc: class method to invert a triangular double complex matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param a Distributed matrix for which eigenvalues are to be computed.
!> Distribution is like in Scalapack.
!> The full matrix must be set (not only one half like in scalapack).
!> Destroyed on exit (upper and lower half).
!>
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
subroutine
elpa_invert_trm_dc
(
self
,
a
,
error
)
use
iso_c_binding
use
elpa1_auxiliary_impl
...
...
@@ -1386,7 +1502,23 @@ module elpa_impl
call
elpa_invert_trm_dc
(
self
,
a
,
error
)
end
subroutine
!> \brief elpa_invert_trim_fc: class method to invert a triangular float complex matrix
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param a Distributed matrix for which eigenvalues are to be computed.
!> Distribution is like in Scalapack.
!> The full matrix must be set (not only one half like in scalapack).
!> Destroyed on exit (upper and lower half).
!>
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
subroutine
elpa_invert_trm_fc
(
self
,
a
,
error
)
use
iso_c_binding
use
elpa1_auxiliary_impl
...
...
@@ -1433,6 +1565,22 @@ module elpa_impl
end
subroutine
!> \brief elpa_solve_tridi_d: class method to solve the eigenvalue problem for a double real tridiagonal matrix a
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param d array d on input diagonal elements of tridiagonal matrix, on
!> output the eigenvalues in ascending order
!> \param e array e on input subdiagonal elements of matrix, on exit destroyed
!> \param q matrix on exit : contains the eigenvectors
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
!> \todo e should have dimension (na - 1)
subroutine
elpa_solve_tridi_d
(
self
,
d
,
e
,
q
,
error
)
use
iso_c_binding
...
...
@@ -1463,6 +1611,40 @@ module elpa_impl
end
subroutine
!c> void elpa_solve_tridi_d(elpa_t handle, double *d, double *e, double *q, int *error);
subroutine
elpa_solve_tridi_d_c
(
handle
,
d_p
,
e_p
,
q_p
,
error
)
bind
(
C
,
name
=
"elpa_solve_tridi_d"
)
type
(
c_ptr
),
intent
(
in
),
value
::
handle
,
d_p
,
e_p
,
q_p
integer
(
kind
=
c_int
),
optional
,
intent
(
in
)
::
error
real
(
kind
=
c_double
),
pointer
::
d
(:),
e
(:),
q
(:,:)
type
(
elpa_impl_t
),
pointer
::
self
call
c_f_pointer
(
handle
,
self
)
call
c_f_pointer
(
d_p
,
d
,
[
self
%
na
])
call
c_f_pointer
(
e_p
,
e
,
[
self
%
na
])
call
c_f_pointer
(
q_p
,
q
,
[
self
%
local_nrows
,
self
%
local_ncols
])
call
elpa_solve_tridi_d
(
self
,
d
,
e
,
q
,
error
)
end
subroutine
!> \brief elpa_solve_tridi_f: class method to solve the eigenvalue problem for a float real tridiagonal matrix a
!>
!> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
!> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
!> with the class method "setup"
!>
!> It is possible to change the behaviour of the method by setting tunable parameters with the
!> class method "set"
!>
!> Parameters
!>
!> \param d array d on input diagonal elements of tridiagonal matrix, on
!> output the eigenvalues in ascending order
!> \param e array e on input subdiagonal elements of matrix, on exit destroyed
!> \param q matrix on exit : contains the eigenvectors
!> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
!> \todo e should have dimension (na - 1)
subroutine
elpa_solve_tridi_f
(
self
,
d
,
e
,
q
,
error
)
use
iso_c_binding
use
elpa1_auxiliary_impl
...
...
@@ -1497,6 +1679,24 @@ module elpa_impl
end
subroutine
!c> void elpa_solve_tridi_f(elpa_t handle, float *d, float *e, float *q, int *error);
subroutine
elpa_solve_tridi_f_c
(
handle
,
d_p
,
e_p
,
q_p
,
error
)
bind
(
C
,
name
=
"elpa_solve_tridi_f"
)
type
(
c_ptr
),
intent
(
in
),
value
::
handle
,
d_p
,
e_p
,
q_p
integer
(
kind
=
c_int
),
optional
,
intent
(
in
)
::
error
real
(
kind
=
c_float
),
pointer
::
d
(:),
e
(:),
q
(:,:)
type
(
elpa_impl_t
),
pointer
::
self
call
c_f_pointer
(
handle
,
self
)
call
c_f_pointer
(
d_p
,
d
,
[
self
%
na
])
call
c_f_pointer
(
e_p
,
e
,
[
self
%
na
])
call
c_f_pointer
(
q_p
,
q
,
[
self
%
local_nrows
,
self
%
local_ncols
])
call
elpa_solve_tridi_f
(
self
,
d
,
e
,
q
,
error
)
end
subroutine
subroutine
elpa_destroy
(
self
)
use
elpa_generated_fortran_interfaces
class
(
elpa_impl_t
)
::
self
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a 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