Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Scientific Software
Takin
mag-core
Commits
67e00e03
Commit
67e00e03
authored
Dec 16, 2019
by
Tobias WEBER
Browse files
continued with moldyn tool
parent
d8a461cd
Changes
3
Hide whitespace changes
Inline
Side-by-side
tools/moldyn/moldyn-loader.h
View file @
67e00e03
...
...
@@ -150,6 +150,15 @@ class MolDyn
}
/**
* get atom coordinates for a specific frame
*/
const
t_vec
&
GetAtomCoords
(
std
::
size_t
idxType
,
std
::
size_t
idxSubType
,
std
::
size_t
iFrameIdx
)
const
{
return
GetFrame
(
iFrameIdx
).
GetAtomCoords
(
idxType
,
idxSubType
);
}
/**
* get atom coordinates for all frames
*/
...
...
tools/moldyn/moldyn.cpp
View file @
67e00e03
...
...
@@ -29,6 +29,9 @@ constexpr t_real g_eps = 1e-6;
constexpr
int
g_prec
=
6
;
#define PROG_NAME "Molecular Dynamics Tool"
// ----------------------------------------------------------------------------
/**
...
...
@@ -83,7 +86,7 @@ class MolDynFileDlg : public QFileDialog
MolDynDlg
::
MolDynDlg
(
QWidget
*
pParent
)
:
QMainWindow
{
pParent
},
m_sett
{
new
QSettings
{
"tobis_stuff"
,
"moldyn"
}}
{
setWindowTitle
(
"Molecular Dynamics"
);
setWindowTitle
(
PROG_NAME
);
this
->
setObjectName
(
"moldyn"
);
m_status
=
new
QStatusBar
(
this
);
...
...
@@ -102,6 +105,7 @@ MolDynDlg::MolDynDlg(QWidget* pParent) : QMainWindow{pParent},
m_menu
=
new
QMenuBar
(
this
);
m_menu
->
setNativeMenuBar
(
m_sett
?
m_sett
->
value
(
"native_gui"
,
false
).
toBool
()
:
false
);
// File
auto
menuFile
=
new
QMenu
(
"File"
,
m_menu
);
...
...
@@ -125,25 +129,62 @@ MolDynDlg::MolDynDlg(QWidget* pParent) : QMainWindow{pParent},
// Edit
auto
menuEdit
=
new
QMenu
(
"Edit"
,
m_menu
);
auto
acSelectAll
=
new
QAction
(
"Select All"
,
menuEdit
);
auto
acSelectNone
=
new
QAction
(
"Select None"
,
menuEdit
);
menuEdit
->
addAction
(
acSelectAll
);
menuEdit
->
addAction
(
acSelectNone
);
connect
(
acSelectAll
,
&
QAction
::
triggered
,
this
,
&
MolDynDlg
::
SelectAll
);
connect
(
acSelectNone
,
&
QAction
::
triggered
,
this
,
&
MolDynDlg
::
SelectNone
);
// Calculate
auto
menuCalc
=
new
QMenu
(
"Calculate"
,
m_menu
);
auto
acCalcDist
=
new
QAction
(
"Distance Between Selected Atoms"
,
menuEdit
);
auto
acCalcDist
=
new
QAction
(
"Distance Between Selected Atoms..."
,
menuEdit
);
auto
acCalcPos
=
new
QAction
(
"Positions Of Selected Atoms..."
,
menuEdit
);
auto
acCalcDeltaDist
=
new
QAction
(
"Distances to Initial Position of Selected Atoms..."
,
menuEdit
);
menuCalc
->
addAction
(
acCalcDist
);
menuCalc
->
addAction
(
acCalcPos
);
menuCalc
->
addAction
(
acCalcDeltaDist
);
connect
(
acCalcDist
,
&
QAction
::
triggered
,
this
,
&
MolDynDlg
::
CalculateDistanceBetweenAtoms
);
connect
(
acCalcPos
,
&
QAction
::
triggered
,
this
,
&
MolDynDlg
::
CalculatePositionsOfAtoms
);
connect
(
acCalcDeltaDist
,
&
QAction
::
triggered
,
this
,
&
MolDynDlg
::
CalculateDeltaDistancesOfAtoms
);
// Help
auto
menuHelp
=
new
QMenu
(
"Help"
,
m_menu
);
auto
acHelpInfo
=
new
QAction
(
"Infos..."
,
menuHelp
);
menuHelp
->
addAction
(
acHelpInfo
);
connect
(
acHelpInfo
,
&
QAction
::
triggered
,
this
,
[
this
]()
{
QString
strHelp
;
strHelp
=
QString
{
PROG_NAME
}
+
", part of the Takin 2 package.
\n
"
;
strHelp
+=
"Written by Tobias Weber <tweber@ill.fr>
\n
in December 2019.
\n\n
"
;
strHelp
+=
"This program is free software: you can redistribute it and/or modify "
"it under the terms of the GNU General Public License as published by "
"the Free Software Foundation, version 3 of the License.
\n\n
"
"This program is distributed in the hope that it will be useful, "
"but WITHOUT ANY WARRANTY; without even the implied warranty of "
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
"GNU General Public License for more details.
\n\n
"
"You should have received a copy of the GNU General Public License "
"along with this program. If not, see <http://www.gnu.org/licenses/>."
;
QMessageBox
::
information
(
this
,
PROG_NAME
,
strHelp
);
});
m_menu
->
addMenu
(
menuFile
);
m_menu
->
addMenu
(
menuEdit
);
m_menu
->
addMenu
(
menuCalc
);
m_menu
->
addMenu
(
menuHelp
);
this
->
setMenuBar
(
m_menu
);
}
...
...
@@ -282,57 +323,278 @@ void MolDynDlg::Change3DItem(std::size_t obj, const t_vec *vec, const t_vec *col
*/
void
MolDynDlg
::
CalculateDistanceBetweenAtoms
()
{
std
::
vector
<
std
::
tuple
<
std
::
size_t
,
std
::
size_t
>>
objs
;
for
(
const
auto
&
obj
:
m_sphereHandles
)
try
{
// continue if object isn't selected
if
(
!
m_plot
->
GetImpl
()
->
GetObjectHighlight
(
obj
))
continue
;
// get selected atoms
std
::
vector
<
std
::
tuple
<
std
::
size_t
,
std
::
size_t
>>
objs
;
for
(
const
auto
&
obj
:
m_sphereHandles
)
{
// continue if object isn't selected
if
(
!
m_plot
->
GetImpl
()
->
GetObjectHighlight
(
obj
))
continue
;
// get indices for selected atoms
const
auto
[
bOk
,
atomTypeIdx
,
atomSubTypeIdx
,
sphereIdx
]
=
GetAtomIndexFromHandle
(
obj
);
if
(
!
bOk
)
{
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Atom handle not found, data is corrupted."
);
return
;
}
objs
.
push_back
(
std
::
make_tuple
(
atomTypeIdx
,
atomSubTypeIdx
));
}
// get indices for selected atoms
const
auto
[
bOk
,
atomTypeIdx
,
atomSubTypeIdx
,
sphereIdx
]
=
GetAtomIndexFromHandle
(
obj
);
if
(
!
bOk
)
if
(
objs
.
size
()
<=
1
)
{
QMessageBox
::
critical
(
this
,
"Molecular Dynamics"
,
"A
tom ha
ndle not found, data is corrup
ted."
);
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"At least two a
tom
s
ha
ve to be selec
ted."
);
return
;
}
objs
.
push_back
(
std
::
make_tuple
(
atomTypeIdx
,
atomSubTypeIdx
));
}
if
(
objs
.
size
()
<=
1
)
// create file
QString
dirLast
=
m_sett
->
value
(
"dir"
,
""
).
toString
();
QString
filename
=
QFileDialog
::
getSaveFileName
(
this
,
"Save File"
,
dirLast
,
"Data File (*.dat)"
);
if
(
filename
==
""
)
return
;
std
::
ofstream
ofstr
(
filename
.
toStdString
());
if
(
!
ofstr
)
{
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Cannot open file."
);
return
;
}
ofstr
.
precision
(
g_prec
);
m_sett
->
setValue
(
"dir"
,
QFileInfo
(
filename
).
path
());
// get coordinates of first atom
auto
[
firstObjTypeIdx
,
firstObjSubTypeIdx
]
=
objs
[
0
];
auto
firstObjCoords
=
m_mol
.
GetAtomCoords
(
firstObjTypeIdx
,
firstObjSubTypeIdx
);
ofstr
<<
"# Column 1: Frame
\n
"
;
ofstr
<<
"# Columns 2, 3, ...: Distances to first atom (A)
\n
"
;
// progress dialog
std
::
shared_ptr
<
QProgressDialog
>
dlgProgress
=
std
::
make_shared
<
QProgressDialog
>
(
"Calculating..."
,
"Cancel"
,
1
,
objs
.
size
(),
this
);
dlgProgress
->
setWindowModality
(
Qt
::
WindowModal
);
// get distances to other selected atoms
for
(
std
::
size_t
objIdx
=
1
;
objIdx
<
objs
.
size
();
++
objIdx
)
{
auto
[
objTypeIdx
,
objSubTypeIdx
]
=
objs
[
objIdx
];
const
auto
objCoords
=
m_mol
.
GetAtomCoords
(
objTypeIdx
,
objSubTypeIdx
);
for
(
std
::
size_t
frameidx
=
0
;
frameidx
<
m_mol
.
GetFrameCount
();
++
frameidx
)
{
t_real
dist
=
m
::
get_dist_uc
(
m_crystA
,
firstObjCoords
[
frameidx
],
objCoords
[
frameidx
]);
ofstr
<<
std
::
left
<<
std
::
setw
(
g_prec
*
1.5
)
<<
frameidx
<<
" "
<<
std
::
left
<<
std
::
setw
(
g_prec
*
1.5
)
<<
dist
<<
"
\n
"
;
}
dlgProgress
->
setValue
(
objIdx
+
1
);
if
(
dlgProgress
->
wasCanceled
())
{
ofstr
<<
"
\n
# WARNING: Calculation aborted by user.
\n
"
;
break
;
}
}
}
catch
(
const
std
::
exception
&
ex
)
{
QMessageBox
::
critical
(
this
,
"Molecular Dynamics"
,
"At least two atoms have to be selected."
);
return
;
QMessageBox
::
critical
(
this
,
PROG_NAME
,
ex
.
what
());
}
}
/**
* calculate positions of selected atoms
*/
void
MolDynDlg
::
CalculatePositionsOfAtoms
()
{
try
{
// get selected atoms
std
::
vector
<
std
::
tuple
<
std
::
size_t
,
std
::
size_t
>>
objs
;
for
(
const
auto
&
obj
:
m_sphereHandles
)
{
// continue if object isn't selected
if
(
!
m_plot
->
GetImpl
()
->
GetObjectHighlight
(
obj
))
continue
;
// get indices for selected atoms
const
auto
[
bOk
,
atomTypeIdx
,
atomSubTypeIdx
,
sphereIdx
]
=
GetAtomIndexFromHandle
(
obj
);
if
(
!
bOk
)
{
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Atom handle not found, data is corrupted."
);
return
;
}
objs
.
push_back
(
std
::
make_tuple
(
atomTypeIdx
,
atomSubTypeIdx
));
}
if
(
objs
.
size
()
<=
0
)
{
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"At least one atom has to be selected."
);
return
;
}
// create file
QString
dirLast
=
m_sett
->
value
(
"dir"
,
""
).
toString
();
QString
filename
=
QFileDialog
::
getSaveFileName
(
this
,
"Save File"
,
dirLast
,
"Data File (*.dat)"
);
if
(
filename
==
""
)
return
;
std
::
ofstream
ofstr
(
filename
.
toStdString
());
if
(
!
ofstr
)
{
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Cannot open file."
);
return
;
}
ofstr
.
precision
(
g_prec
);
m_sett
->
setValue
(
"dir"
,
QFileInfo
(
filename
).
path
());
// get coordinates of first atom
auto
[
firstObjTypeIdx
,
firstObjSubTypeIdx
]
=
objs
[
0
];
auto
firstObjCoords
=
m_mol
.
GetAtomCoords
(
firstObjTypeIdx
,
firstObjSubTypeIdx
);
ofstr
<<
"# Column 1: Frame
\n
"
;
ofstr
<<
"# Columns 2, 3, 4: x, y, z position of atom (A)
\n
"
;
// progress dialog
std
::
shared_ptr
<
QProgressDialog
>
dlgProgress
=
std
::
make_shared
<
QProgressDialog
>
(
"Calculating..."
,
"Cancel"
,
0
,
m_mol
.
GetFrameCount
(),
this
);
dlgProgress
->
setWindowModality
(
Qt
::
WindowModal
);
std
::
vector
<
t_vec
>
firstObjCoordsCryst
;
firstObjCoordsCryst
.
reserve
(
m_mol
.
GetFrameCount
());
// iterate all selected atoms
for
(
std
::
size_t
frameidx
=
0
;
frameidx
<
m_mol
.
GetFrameCount
();
++
frameidx
)
{
ofstr
<<
std
::
left
<<
std
::
setw
(
g_prec
*
1.5
)
<<
frameidx
<<
" "
;
for
(
std
::
size_t
frameidx
=
0
;
frameidx
<
m_mol
.
GetFrameCount
();
++
frameidx
)
firstObjCoordsCryst
.
push_back
(
m_crystA
*
firstObjCoords
[
frameidx
]);
for
(
std
::
size_t
objIdx
=
0
;
objIdx
<
objs
.
size
();
++
objIdx
)
{
auto
[
objTypeIdx
,
objSubTypeIdx
]
=
objs
[
objIdx
];
const
t_vec
&
coords
=
m_mol
.
GetAtomCoords
(
objTypeIdx
,
objSubTypeIdx
,
frameidx
);
ofstr
<<
std
::
left
<<
std
::
setw
(
g_prec
*
1.5
)
<<
coords
[
0
]
<<
" "
<<
std
::
left
<<
std
::
setw
(
g_prec
*
1.5
)
<<
coords
[
1
]
<<
" "
<<
std
::
left
<<
std
::
setw
(
g_prec
*
1.5
)
<<
coords
[
2
]
<<
" "
;
}
ofstr
<<
"
\n
"
;
// get distances to other selected atoms
for
(
std
::
size_t
objIdx
=
1
;
objIdx
<
objs
.
size
();
++
objIdx
)
dlgProgress
->
setValue
(
frameidx
+
1
);
if
(
dlgProgress
->
wasCanceled
())
{
ofstr
<<
"
\n
# WARNING: Calculation aborted by user.
\n
"
;
break
;
}
}
}
catch
(
const
std
::
exception
&
ex
)
{
auto
[
objTypeIdx
,
objSubTypeIdx
]
=
objs
[
objIdx
];
const
auto
objCoords
=
m_mol
.
GetAtomCoords
(
objTypeIdx
,
objSubTypeIdx
);
QMessageBox
::
critical
(
this
,
PROG_NAME
,
ex
.
what
());
}
}
/**
* calculate distance to initial positions of selected atoms
*/
void
MolDynDlg
::
CalculateDeltaDistancesOfAtoms
()
{
try
{
// get selected atoms
std
::
vector
<
std
::
tuple
<
std
::
size_t
,
std
::
size_t
>>
objs
;
for
(
const
auto
&
obj
:
m_sphereHandles
)
{
// continue if object isn't selected
if
(
!
m_plot
->
GetImpl
()
->
GetObjectHighlight
(
obj
))
continue
;
// get indices for selected atoms
const
auto
[
bOk
,
atomTypeIdx
,
atomSubTypeIdx
,
sphereIdx
]
=
GetAtomIndexFromHandle
(
obj
);
if
(
!
bOk
)
{
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Atom handle not found, data is corrupted."
);
return
;
}
objs
.
push_back
(
std
::
make_tuple
(
atomTypeIdx
,
atomSubTypeIdx
));
}
if
(
objs
.
size
()
<=
0
)
{
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"At least one atom has to be selected."
);
return
;
}
// create file
QString
dirLast
=
m_sett
->
value
(
"dir"
,
""
).
toString
();
QString
filename
=
QFileDialog
::
getSaveFileName
(
this
,
"Save File"
,
dirLast
,
"Data File (*.dat)"
);
if
(
filename
==
""
)
return
;
std
::
ofstream
ofstr
(
filename
.
toStdString
());
if
(
!
ofstr
)
{
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Cannot open file."
);
return
;
}
ofstr
.
precision
(
g_prec
);
m_sett
->
setValue
(
"dir"
,
QFileInfo
(
filename
).
path
());
ofstr
<<
"# Column 1: Frame
\n
"
;
ofstr
<<
"# Column 2, 3, ...: Distance delta (A)
\n
"
;
// progress dialog
std
::
shared_ptr
<
QProgressDialog
>
dlgProgress
=
std
::
make_shared
<
QProgressDialog
>
(
"Calculating..."
,
"Cancel"
,
0
,
m_mol
.
GetFrameCount
(),
this
);
dlgProgress
->
setWindowModality
(
Qt
::
WindowModal
);
// iterate all selected atoms
for
(
std
::
size_t
frameidx
=
0
;
frameidx
<
m_mol
.
GetFrameCount
();
++
frameidx
)
{
t_real
dist
=
m
::
get_dist_uc
(
m_crystA
,
firstObjCoordsCryst
[
frameidx
],
objCoords
[
frameidx
]);
ofstr
<<
std
::
left
<<
std
::
setw
(
g_prec
*
1.5
)
<<
frameidx
<<
" "
;
for
(
std
::
size_t
objIdx
=
0
;
objIdx
<
objs
.
size
();
++
objIdx
)
{
auto
[
objTypeIdx
,
objSubTypeIdx
]
=
objs
[
objIdx
];
const
t_vec
&
coords
=
m_mol
.
GetAtomCoords
(
objTypeIdx
,
objSubTypeIdx
,
frameidx
);
const
t_vec
&
coordsInitial
=
m_mol
.
GetAtomCoords
(
objTypeIdx
,
objSubTypeIdx
,
0
);
t_real
dist
=
m
::
get_dist_uc
(
m_crystA
,
coords
,
coordsInitial
);
// TODO: plot/save/...
std
::
cout
<<
dist
<<
std
::
endl
;
ofstr
<<
std
::
left
<<
std
::
setw
(
g_prec
*
1.5
)
<<
dist
<<
" "
;
}
ofstr
<<
"
\n
"
;
dlgProgress
->
setValue
(
frameidx
+
1
);
if
(
dlgProgress
->
wasCanceled
())
{
ofstr
<<
"
\n
# WARNING: Calculation aborted by user.
\n
"
;
break
;
}
}
}
catch
(
const
std
::
exception
&
ex
)
{
QMessageBox
::
critical
(
this
,
PROG_NAME
,
ex
.
what
());
}
}
// ----------------------------------------------------------------------------
...
...
@@ -392,7 +654,7 @@ void MolDynDlg::Load()
{
// only show error if not explicitely cancelled
if
(
!
bCancelled
)
QMessageBox
::
critical
(
this
,
"Molecular Dynamics"
,
"Error loading file."
);
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Error loading file."
);
return
;
}
...
...
@@ -416,7 +678,7 @@ void MolDynDlg::Load()
if
(
!
ok
)
{
m_crystB
=
m
::
unit
<
t_mat
>
();
QMessageBox
::
critical
(
this
,
"Molecular Dynamics"
,
"Error: Cannot invert A matrix."
);
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Error: Cannot invert A matrix."
);
}
m_crystB
/=
t_real_gl
(
2
)
*
m
::
pi
<
t_real_gl
>
;
...
...
@@ -458,7 +720,7 @@ void MolDynDlg::Load()
}
catch
(
const
std
::
exception
&
ex
)
{
QMessageBox
::
critical
(
this
,
"Molecular Dynamics"
,
ex
.
what
());
QMessageBox
::
critical
(
this
,
PROG_NAME
,
ex
.
what
());
}
m_plot
->
update
();
...
...
@@ -491,7 +753,7 @@ void MolDynDlg::SaveAs()
if
(
!
m_mol
.
SaveFile
(
filename
.
toStdString
()))
{
QMessageBox
::
critical
(
this
,
"Molecular Dynamics"
,
"Error saving file."
);
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Error saving file."
);
}
...
...
@@ -499,7 +761,7 @@ void MolDynDlg::SaveAs()
}
catch
(
const
std
::
exception
&
ex
)
{
QMessageBox
::
critical
(
this
,
"Molecular Dynamics"
,
ex
.
what
());
QMessageBox
::
critical
(
this
,
PROG_NAME
,
ex
.
what
());
}
}
// ----------------------------------------------------------------------------
...
...
@@ -591,6 +853,20 @@ void MolDynDlg::PlotMouseClick(bool left, bool mid, bool right)
// ----------------------------------------------------------------------------
/**
* select all atoms
*/
void
MolDynDlg
::
SelectAll
()
{
if
(
!
m_plot
)
return
;
for
(
auto
handle
:
m_sphereHandles
)
m_plot
->
GetImpl
()
->
SetObjectHighlight
(
handle
,
1
);
m_plot
->
update
();
}
/**
* unselect all atoms
*/
...
...
@@ -683,13 +959,13 @@ void MolDynDlg::DeleteAtomUnderCursor()
const
auto
[
bOk
,
atomTypeIdx
,
atomSubTypeIdx
,
sphereIdx
]
=
GetAtomIndexFromHandle
(
m_curPickedObj
);
if
(
!
bOk
)
{
QMessageBox
::
critical
(
this
,
"Molecular Dynamics"
,
"Atom handle not found, data is corrupted."
);
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Atom handle not found, data is corrupted."
);
return
;
}
if
(
m_mol
.
GetAtomName
(
atomTypeIdx
)
!=
atomLabel
)
{
QMessageBox
::
critical
(
this
,
"Molecular Dynamics"
,
"Mismatch in atom type, data is corrupted."
);
QMessageBox
::
critical
(
this
,
PROG_NAME
,
"Mismatch in atom type, data is corrupted."
);
return
;
}
...
...
tools/moldyn/moldyn.h
View file @
67e00e03
...
...
@@ -53,10 +53,15 @@ protected:
void
AfterGLInitialisation
();
void
SliderValueChanged
(
int
val
);
void
SelectAll
();
void
SelectNone
();
std
::
tuple
<
bool
,
std
::
size_t
,
std
::
size_t
,
std
::
size_t
>
GetAtomIndexFromHandle
(
std
::
size_t
handle
)
const
;
void
CalculateDistanceBetweenAtoms
();
void
CalculatePositionsOfAtoms
();
void
CalculateDeltaDistancesOfAtoms
();
void
DeleteAtomUnderCursor
();
void
DeleteAllAtomsOfSameType
();
...
...
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