Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
f5ec3142
Commit
f5ec3142
authored
Mar 08, 2016
by
ChayaSt
Browse files
Merge branch 'master' of
https://github.com/pandegroup/openmm
into nbfix
parents
6b7ef87f
9b5b52f2
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
86 additions
and
45 deletions
+86
-45
platforms/cpu/src/CpuNeighborList.cpp
platforms/cpu/src/CpuNeighborList.cpp
+62
-22
platforms/cpu/tests/TestCpuNeighborList.cpp
platforms/cpu/tests/TestCpuNeighborList.cpp
+6
-6
platforms/cuda/src/CudaKernels.cpp
platforms/cuda/src/CudaKernels.cpp
+6
-5
platforms/opencl/src/OpenCLKernels.cpp
platforms/opencl/src/OpenCLKernels.cpp
+2
-2
plugins/amoeba/openmmapi/include/openmm/AmoebaMultipoleForce.h
...ns/amoeba/openmmapi/include/openmm/AmoebaMultipoleForce.h
+3
-3
plugins/amoeba/openmmapi/src/AmoebaMultipoleForce.cpp
plugins/amoeba/openmmapi/src/AmoebaMultipoleForce.cpp
+5
-5
wrappers/python/simtk/openmm/app/forcefield.py
wrappers/python/simtk/openmm/app/forcefield.py
+2
-2
No files found.
platforms/cpu/src/CpuNeighborList.cpp
View file @
f5ec3142
...
@@ -225,38 +225,78 @@ public:
...
@@ -225,38 +225,78 @@ public:
if
(
usePeriodic
)
if
(
usePeriodic
)
voxelIndex
.
y
=
(
y
<
0
?
y
+
ny
:
(
y
>=
ny
?
y
-
ny
:
y
));
voxelIndex
.
y
=
(
y
<
0
?
y
+
ny
:
(
y
>=
ny
?
y
-
ny
:
y
));
float
boxy
=
floor
((
float
)
y
/
ny
);
float
boxy
=
floor
((
float
)
y
/
ny
);
float
xoffset
=
(
float
)
(
usePeriodic
?
boxy
*
periodicBoxVectors
[
1
][
0
]
+
boxz
*
periodicBoxVectors
[
2
][
0
]
:
0
);
// Identify the range of atoms within this bin we need to search. When using periodic boundary
// Identify the range of atoms within this bin we need to search. When using periodic boundary
// conditions, there may be two separate ranges.
// conditions, there may be two separate ranges.
float
minx
=
centerPos
[
0
];
float
minx
=
centerPos
[
0
];
float
maxx
=
centerPos
[
0
];
float
maxx
=
centerPos
[
0
];
fvec4
offset
(
-
xoffset
,
-
yoffset
+
voxelSizeY
*
y
+
(
usePeriodic
?
0.0
f
:
miny
),
voxelSizeZ
*
z
+
(
usePeriodic
?
0.0
f
:
minz
),
0
);
if
(
usePeriodic
&&
triclinic
)
{
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
++
)
{
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
++
)
{
const
float
*
atomPos
=
&
sortedPositions
[
4
*
(
blockSize
*
blockIndex
+
k
)];
const
float
*
atomPos
=
&
sortedPositions
[
4
*
(
blockSize
*
blockIndex
+
k
)];
fvec4
posVec
(
atomPos
);
fvec4
delta1
(
0
,
voxelSizeY
*
voxelIndex
.
y
-
atomPos
[
1
],
voxelSizeZ
*
voxelIndex
.
z
-
atomPos
[
2
],
0
);
fvec4
delta1
=
offset
-
posVec
;
fvec4
delta2
=
delta1
+
fvec4
(
0
,
voxelSizeY
,
0
,
0
);
fvec4
delta2
=
delta1
+
fvec4
(
0
,
voxelSizeY
,
voxelSizeZ
,
0
);
fvec4
delta3
=
delta1
+
fvec4
(
0
,
0
,
voxelSizeZ
,
0
);
if
(
usePeriodic
)
{
fvec4
delta4
=
delta1
+
fvec4
(
0
,
voxelSizeY
,
voxelSizeZ
,
0
);
delta1
-=
round
(
delta1
*
invBoxSize
)
*
boxSize
;
delta1
-=
periodicBoxVec4
[
2
]
*
floorf
(
delta1
[
2
]
*
recipBoxSize
[
2
]
+
0.5
f
);
delta2
-=
round
(
delta2
*
invBoxSize
)
*
boxSize
;
delta1
-=
periodicBoxVec4
[
1
]
*
floorf
(
delta1
[
1
]
*
recipBoxSize
[
1
]
+
0.5
f
);
delta1
-=
periodicBoxVec4
[
0
]
*
floorf
(
delta1
[
0
]
*
recipBoxSize
[
0
]
+
0.5
f
);
delta2
-=
periodicBoxVec4
[
2
]
*
floorf
(
delta2
[
2
]
*
recipBoxSize
[
2
]
+
0.5
f
);
delta2
-=
periodicBoxVec4
[
1
]
*
floorf
(
delta2
[
1
]
*
recipBoxSize
[
1
]
+
0.5
f
);
delta2
-=
periodicBoxVec4
[
0
]
*
floorf
(
delta2
[
0
]
*
recipBoxSize
[
0
]
+
0.5
f
);
delta3
-=
periodicBoxVec4
[
2
]
*
floorf
(
delta3
[
2
]
*
recipBoxSize
[
2
]
+
0.5
f
);
delta3
-=
periodicBoxVec4
[
1
]
*
floorf
(
delta3
[
1
]
*
recipBoxSize
[
1
]
+
0.5
f
);
delta3
-=
periodicBoxVec4
[
0
]
*
floorf
(
delta3
[
0
]
*
recipBoxSize
[
0
]
+
0.5
f
);
delta4
-=
periodicBoxVec4
[
2
]
*
floorf
(
delta4
[
2
]
*
recipBoxSize
[
2
]
+
0.5
f
);
delta4
-=
periodicBoxVec4
[
1
]
*
floorf
(
delta4
[
1
]
*
recipBoxSize
[
1
]
+
0.5
f
);
delta4
-=
periodicBoxVec4
[
0
]
*
floorf
(
delta4
[
0
]
*
recipBoxSize
[
0
]
+
0.5
f
);
if
(
delta1
[
1
]
<
0
&&
delta1
[
1
]
+
voxelSizeY
>
0
)
delta1
=
fvec4
(
delta1
[
0
],
0
,
delta1
[
2
],
0
);
if
(
delta1
[
2
]
<
0
&&
delta1
[
2
]
+
voxelSizeZ
>
0
)
delta1
=
fvec4
(
delta1
[
0
],
delta1
[
1
],
0
,
0
);
if
(
delta3
[
1
]
<
0
&&
delta3
[
1
]
+
voxelSizeY
>
0
)
delta3
=
fvec4
(
delta3
[
0
],
0
,
delta3
[
2
],
0
);
if
(
delta2
[
2
]
<
0
&&
delta2
[
2
]
+
voxelSizeZ
>
0
)
delta2
=
fvec4
(
delta2
[
0
],
delta2
[
1
],
0
,
0
);
fvec4
delta
=
min
(
min
(
min
(
abs
(
delta1
),
abs
(
delta2
)),
abs
(
delta3
)),
abs
(
delta4
));
float
dy
=
(
voxelIndex
.
y
==
atomVoxelIndex
[
k
].
y
?
0.0
f
:
delta
[
1
]);
float
dz
=
(
voxelIndex
.
z
==
atomVoxelIndex
[
k
].
z
?
0.0
f
:
delta
[
2
]);
float
dist2
=
maxDistanceSquared
-
dy
*
dy
-
dz
*
dz
;
if
(
dist2
>
0
)
{
float
dist
=
sqrtf
(
dist2
);
minx
=
min
(
minx
,
atomPos
[
0
]
-
dist
-
max
(
max
(
max
(
delta1
[
0
],
delta2
[
0
]),
delta3
[
0
]),
delta4
[
0
]));
maxx
=
max
(
maxx
,
atomPos
[
0
]
+
dist
-
min
(
min
(
min
(
delta1
[
0
],
delta2
[
0
]),
delta3
[
0
]),
delta4
[
0
]));
}
}
}
fvec4
delta
=
min
(
abs
(
delta1
),
abs
(
delta2
));
}
float
dy
=
(
y
==
atomVoxelIndex
[
k
].
y
?
0.0
f
:
delta
[
1
]);
else
{
float
dz
=
(
z
==
atomVoxelIndex
[
k
].
z
?
0.0
f
:
delta
[
2
]);
float
xoffset
=
(
float
)
(
usePeriodic
?
boxy
*
periodicBoxVectors
[
1
][
0
]
+
boxz
*
periodicBoxVectors
[
2
][
0
]
:
0
);
float
dist2
=
maxDistanceSquared
-
dy
*
dy
-
dz
*
dz
;
fvec4
offset
(
-
xoffset
,
-
yoffset
+
voxelSizeY
*
y
+
(
usePeriodic
?
0.0
f
:
miny
),
voxelSizeZ
*
z
+
(
usePeriodic
?
0.0
f
:
minz
),
0
);
if
(
dist2
>
0
)
{
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
++
)
{
float
dist
=
sqrtf
(
dist2
);
const
float
*
atomPos
=
&
sortedPositions
[
4
*
(
blockSize
*
blockIndex
+
k
)];
minx
=
min
(
minx
,
atomPos
[
0
]
-
dist
-
xoffset
);
fvec4
posVec
(
atomPos
);
maxx
=
max
(
maxx
,
atomPos
[
0
]
+
dist
-
xoffset
);
fvec4
delta1
=
offset
-
posVec
;
fvec4
delta2
=
delta1
+
fvec4
(
0
,
voxelSizeY
,
voxelSizeZ
,
0
);
if
(
usePeriodic
)
{
delta1
-=
round
(
delta1
*
invBoxSize
)
*
boxSize
;
delta2
-=
round
(
delta2
*
invBoxSize
)
*
boxSize
;
}
fvec4
delta
=
min
(
abs
(
delta1
),
abs
(
delta2
));
float
dy
=
(
y
==
atomVoxelIndex
[
k
].
y
?
0.0
f
:
delta
[
1
]);
float
dz
=
(
z
==
atomVoxelIndex
[
k
].
z
?
0.0
f
:
delta
[
2
]);
float
dist2
=
maxDistanceSquared
-
dy
*
dy
-
dz
*
dz
;
if
(
dist2
>
0
)
{
float
dist
=
sqrtf
(
dist2
);
minx
=
min
(
minx
,
atomPos
[
0
]
-
dist
-
xoffset
);
maxx
=
max
(
maxx
,
atomPos
[
0
]
+
dist
-
xoffset
);
}
}
}
}
}
if
(
minx
==
maxx
)
if
(
minx
==
maxx
)
continue
;
continue
;
bool
needPeriodic
=
(
centerPos
[
1
]
-
blockWidth
[
1
]
<
maxDistance
||
centerPos
[
1
]
+
blockWidth
[
1
]
>
periodicBoxSize
[
1
]
-
maxDistance
||
bool
needPeriodic
=
usePeriodic
&&
(
centerPos
[
1
]
-
blockWidth
[
1
]
<
maxDistance
||
centerPos
[
1
]
+
blockWidth
[
1
]
>
periodicBoxSize
[
1
]
-
maxDistance
||
centerPos
[
2
]
-
blockWidth
[
2
]
<
maxDistance
||
centerPos
[
2
]
+
blockWidth
[
2
]
>
periodicBoxSize
[
2
]
-
maxDistance
||
centerPos
[
2
]
-
blockWidth
[
2
]
<
maxDistance
||
centerPos
[
2
]
+
blockWidth
[
2
]
>
periodicBoxSize
[
2
]
-
maxDistance
||
minx
<
0.0
f
||
maxx
>
periodicBoxVectors
[
0
][
0
]);
minx
<
0.0
f
||
maxx
>
periodicBoxVectors
[
0
][
0
]);
int
numRanges
;
int
numRanges
;
int
rangeStart
[
2
];
int
rangeStart
[
2
];
int
rangeEnd
[
2
];
int
rangeEnd
[
2
];
...
@@ -294,7 +334,7 @@ public:
...
@@ -294,7 +334,7 @@ public:
continue
;
continue
;
fvec4
atomPos
(
&
sortedPositions
[
4
*
sortedIndex
]);
fvec4
atomPos
(
&
sortedPositions
[
4
*
sortedIndex
]);
fvec4
delta
=
atomPos
-
c
enter
Pos
;
fvec4
delta
=
atomPos
-
blockC
enter
;
if
(
periodicRectangular
)
if
(
periodicRectangular
)
delta
-=
round
(
delta
*
invBoxSize
)
*
boxSize
;
delta
-=
round
(
delta
*
invBoxSize
)
*
boxSize
;
else
if
(
needPeriodic
)
{
else
if
(
needPeriodic
)
{
...
...
platforms/cpu/tests/TestCpuNeighborList.cpp
View file @
f5ec3142
...
@@ -53,14 +53,14 @@ void testNeighborList(bool periodic, bool triclinic) {
...
@@ -53,14 +53,14 @@ void testNeighborList(bool periodic, bool triclinic) {
const
float
cutoff
=
2.0
f
;
const
float
cutoff
=
2.0
f
;
RealVec
boxVectors
[
3
];
RealVec
boxVectors
[
3
];
if
(
triclinic
)
{
if
(
triclinic
)
{
boxVectors
[
0
]
=
RealVec
(
2
0
,
0
,
0
);
boxVectors
[
0
]
=
RealVec
(
1
0
,
0
,
0
);
boxVectors
[
1
]
=
RealVec
(
5
,
15
,
0
);
boxVectors
[
1
]
=
RealVec
(
4
,
9
,
0
);
boxVectors
[
2
]
=
RealVec
(
-
3
,
-
7
,
22
);
boxVectors
[
2
]
=
RealVec
(
-
3
,
-
3.5
,
11
);
}
}
else
{
else
{
boxVectors
[
0
]
=
RealVec
(
2
0
,
0
,
0
);
boxVectors
[
0
]
=
RealVec
(
1
0
,
0
,
0
);
boxVectors
[
1
]
=
RealVec
(
0
,
15
,
0
);
boxVectors
[
1
]
=
RealVec
(
0
,
9
,
0
);
boxVectors
[
2
]
=
RealVec
(
0
,
0
,
22
);
boxVectors
[
2
]
=
RealVec
(
0
,
0
,
11
);
}
}
const
float
boxSize
[
3
]
=
{(
float
)
boxVectors
[
0
][
0
],
(
float
)
boxVectors
[
1
][
1
],
(
float
)
boxVectors
[
2
][
2
]};
const
float
boxSize
[
3
]
=
{(
float
)
boxVectors
[
0
][
0
],
(
float
)
boxVectors
[
1
][
1
],
(
float
)
boxVectors
[
2
][
2
]};
const
int
blockSize
=
8
;
const
int
blockSize
=
8
;
...
...
platforms/cuda/src/CudaKernels.cpp
View file @
f5ec3142
...
@@ -1495,12 +1495,13 @@ public:
...
@@ -1495,12 +1495,13 @@ public:
addEnergyKernel
(
addEnergyKernel
),
pmeEnergyBuffer
(
pmeEnergyBuffer
),
forceGroup
(
forceGroup
)
{
addEnergyKernel
(
addEnergyKernel
),
pmeEnergyBuffer
(
pmeEnergyBuffer
),
forceGroup
(
forceGroup
)
{
}
}
double
computeForceAndEnergy
(
bool
includeForces
,
bool
includeEnergy
,
int
groups
)
{
double
computeForceAndEnergy
(
bool
includeForces
,
bool
includeEnergy
,
int
groups
)
{
if
((
groups
&
(
1
<<
forceGroup
))
!=
0
)
if
((
groups
&
(
1
<<
forceGroup
))
!=
0
)
{
cuStreamWaitEvent
(
cu
.
getCurrentStream
(),
event
,
0
);
cuStreamWaitEvent
(
cu
.
getCurrentStream
(),
event
,
0
);
if
(
includeEnergy
)
{
if
(
includeEnergy
)
{
int
bufferSize
=
pmeEnergyBuffer
.
getSize
();
int
bufferSize
=
pmeEnergyBuffer
.
getSize
();
void
*
args
[]
=
{
&
pmeEnergyBuffer
.
getDevicePointer
(),
&
cu
.
getEnergyBuffer
().
getDevicePointer
(),
&
bufferSize
};
void
*
args
[]
=
{
&
pmeEnergyBuffer
.
getDevicePointer
(),
&
cu
.
getEnergyBuffer
().
getDevicePointer
(),
&
bufferSize
};
cu
.
executeKernel
(
addEnergyKernel
,
args
,
bufferSize
);
cu
.
executeKernel
(
addEnergyKernel
,
args
,
bufferSize
);
}
}
}
return
0.0
;
return
0.0
;
}
}
...
...
platforms/opencl/src/OpenCLKernels.cpp
View file @
f5ec3142
...
@@ -1502,9 +1502,9 @@ public:
...
@@ -1502,9 +1502,9 @@ public:
events
[
0
]
=
event
;
events
[
0
]
=
event
;
event
=
cl
::
Event
();
event
=
cl
::
Event
();
cl
.
getQueue
().
enqueueWaitForEvents
(
events
);
cl
.
getQueue
().
enqueueWaitForEvents
(
events
);
if
(
includeEnergy
)
cl
.
executeKernel
(
addEnergyKernel
,
pmeEnergyBuffer
.
getSize
());
}
}
if (includeEnergy)
cl.executeKernel(addEnergyKernel, pmeEnergyBuffer.getSize());
return
0.0
;
return
0.0
;
}
}
private:
private:
...
...
plugins/amoeba/openmmapi/include/openmm/AmoebaMultipoleForce.h
View file @
f5ec3142
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
6
Stanford University and the Authors. *
* Authors: Mark Friedrichs, Peter Eastman *
* Authors: Mark Friedrichs, Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -87,7 +87,7 @@ public:
...
@@ -87,7 +87,7 @@ public:
* Extrapolated perturbation theory approximation. The dipoles are iterated a few times, and then an analytic
* Extrapolated perturbation theory approximation. The dipoles are iterated a few times, and then an analytic
* approximation is used to extrapolate to the fully converged values. Call setExtrapolationCoefficients()
* approximation is used to extrapolate to the fully converged values. Call setExtrapolationCoefficients()
* to set the coefficients used for the extrapolation. The default coefficients used in this release are
* to set the coefficients used for the extrapolation. The default coefficients used in this release are
* [
0
,
-
0.
3, 0, 1.3
], but be aware that those may change in a future release.
* [
-0.154
, 0.
017, 0.658, 0.474
], but be aware that those may change in a future release.
*/
*/
Extrapolated
=
2
Extrapolated
=
2
...
@@ -322,7 +322,7 @@ public:
...
@@ -322,7 +322,7 @@ public:
/**
/**
* Get the coefficients for the mu_0, mu_1, mu_2, ..., mu_n terms in the extrapolation
* Get the coefficients for the mu_0, mu_1, mu_2, ..., mu_n terms in the extrapolation
* algorithm for induced dipoles. In this release, the default values for the coefficients are
* algorithm for induced dipoles. In this release, the default values for the coefficients are
* [
0
,
-
0.
3, 0, 1.3
], but be aware that those may change in a future release.
* [
-0.154
, 0.
017, 0.658, 0.474
], but be aware that those may change in a future release.
*/
*/
const
std
::
vector
<
double
>&
getExtrapolationCoefficients
()
const
;
const
std
::
vector
<
double
>&
getExtrapolationCoefficients
()
const
;
...
...
plugins/amoeba/openmmapi/src/AmoebaMultipoleForce.cpp
View file @
f5ec3142
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
6
Stanford University and the Authors. *
* Authors: *
* Authors: *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -43,10 +43,10 @@ AmoebaMultipoleForce::AmoebaMultipoleForce() : nonbondedMethod(NoCutoff), polari
...
@@ -43,10 +43,10 @@ AmoebaMultipoleForce::AmoebaMultipoleForce() : nonbondedMethod(NoCutoff), polari
mutualInducedTargetEpsilon
(
1.0e-02
),
scalingDistanceCutoff
(
100.0
),
electricConstant
(
138.9354558456
),
aewald
(
0.0
)
{
mutualInducedTargetEpsilon
(
1.0e-02
),
scalingDistanceCutoff
(
100.0
),
electricConstant
(
138.9354558456
),
aewald
(
0.0
)
{
pmeGridDimension
.
resize
(
3
);
pmeGridDimension
.
resize
(
3
);
pmeGridDimension
[
0
]
=
pmeGridDimension
[
1
]
=
pmeGridDimension
[
2
];
pmeGridDimension
[
0
]
=
pmeGridDimension
[
1
]
=
pmeGridDimension
[
2
];
extrapolationCoefficients
.
push_back
(
0.
0
);
extrapolationCoefficients
.
push_back
(
-
0.
154
);
extrapolationCoefficients
.
push_back
(
-
0.
3
);
extrapolationCoefficients
.
push_back
(
0.
017
);
extrapolationCoefficients
.
push_back
(
0.
0
);
extrapolationCoefficients
.
push_back
(
0.
658
);
extrapolationCoefficients
.
push_back
(
1.3
);
extrapolationCoefficients
.
push_back
(
0.474
);
}
}
AmoebaMultipoleForce
::
NonbondedMethod
AmoebaMultipoleForce
::
getNonbondedMethod
()
const
{
AmoebaMultipoleForce
::
NonbondedMethod
AmoebaMultipoleForce
::
getNonbondedMethod
()
const
{
...
...
wrappers/python/simtk/openmm/app/forcefield.py
View file @
f5ec3142
...
@@ -856,13 +856,13 @@ class ForceField(object):
...
@@ -856,13 +856,13 @@ class ForceField(object):
uniquePropers
=
set
()
uniquePropers
=
set
()
for
angle
in
data
.
angles
:
for
angle
in
data
.
angles
:
for
atom
in
bondedToAtom
[
angle
[
0
]]:
for
atom
in
bondedToAtom
[
angle
[
0
]]:
if
atom
!=
angle
[
1
]
:
if
atom
not
in
angle
:
if
atom
<
angle
[
2
]:
if
atom
<
angle
[
2
]:
uniquePropers
.
add
((
atom
,
angle
[
0
],
angle
[
1
],
angle
[
2
]))
uniquePropers
.
add
((
atom
,
angle
[
0
],
angle
[
1
],
angle
[
2
]))
else
:
else
:
uniquePropers
.
add
((
angle
[
2
],
angle
[
1
],
angle
[
0
],
atom
))
uniquePropers
.
add
((
angle
[
2
],
angle
[
1
],
angle
[
0
],
atom
))
for
atom
in
bondedToAtom
[
angle
[
2
]]:
for
atom
in
bondedToAtom
[
angle
[
2
]]:
if
atom
!=
angle
[
1
]
:
if
atom
not
in
angle
:
if
atom
>
angle
[
0
]:
if
atom
>
angle
[
0
]:
uniquePropers
.
add
((
angle
[
0
],
angle
[
1
],
angle
[
2
],
atom
))
uniquePropers
.
add
((
angle
[
0
],
angle
[
1
],
angle
[
2
],
atom
))
else
:
else
:
...
...
Write
Preview
Markdown
is supported
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