forked from lijiext/lammps
remove source files from lib/pace;
add lib/pace/Install.py to automatically download the source files from github/ICAMS/lammps-user-pace; add lib/pace/CMakeLists.txt to build libpace.a add lib/pace/README update src/USER-PACE/Install.sh
This commit is contained in:
parent
6a99f5b5c5
commit
3de3302767
|
@ -0,0 +1,19 @@
|
||||||
|
cmake_minimum_required(VERSION 3.7) # CMake version check
|
||||||
|
project(aceevaluator)
|
||||||
|
set(CMAKE_CXX_STANDARD 11) # Enable c++11 standard
|
||||||
|
|
||||||
|
|
||||||
|
set(PACE_EVALUATOR_PATH ${CMAKE_CURRENT_LIST_DIR}/src/USER-PACE)
|
||||||
|
# message("CMakeLists.txt DEBUG: PACE_EVALUATOR_PATH=${PACE_EVALUATOR_PATH}")
|
||||||
|
set(PACE_EVALUATOR_SRC_PATH ${PACE_EVALUATOR_PATH})
|
||||||
|
|
||||||
|
FILE(GLOB PACE_EVALUATOR_SOURCE_FILES ${PACE_EVALUATOR_SRC_PATH}/*.cpp)
|
||||||
|
list(FILTER PACE_EVALUATOR_SOURCE_FILES EXCLUDE REGEX ".*pair_pace.*")
|
||||||
|
set(PACE_EVALUATOR_INCLUDE_DIR ${PACE_EVALUATOR_SRC_PATH})
|
||||||
|
|
||||||
|
|
||||||
|
##### aceevaluator #####
|
||||||
|
add_library(aceevaluator ${PACE_EVALUATOR_SOURCE_FILES})
|
||||||
|
target_include_directories(aceevaluator PUBLIC ${PACE_EVALUATOR_INCLUDE_DIR})
|
||||||
|
target_compile_options(aceevaluator PRIVATE -O3)
|
||||||
|
set_target_properties(aceevaluator PROPERTIES OUTPUT_NAME pace${LAMMPS_MACHINE})
|
|
@ -1 +1,111 @@
|
||||||
# TODO
|
# TODO#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Install.py tool to download, compile, and setup the pace library
|
||||||
|
used to automate the steps described in the README file in this dir
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys, os, subprocess, shutil
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
|
sys.path.append('..')
|
||||||
|
from install_helpers import fullpath, geturl, checkmd5sum
|
||||||
|
|
||||||
|
parser = ArgumentParser(prog='Install.py',
|
||||||
|
description="LAMMPS library build wrapper script")
|
||||||
|
|
||||||
|
# settings
|
||||||
|
|
||||||
|
thisdir = fullpath('.')
|
||||||
|
version = "v.2021.2.3"
|
||||||
|
|
||||||
|
# known checksums for different PACE versions. used to validate the download.
|
||||||
|
checksums = { \
|
||||||
|
'v.2021.2.3' : '9ebb087cba7e4ca041fde52f7e9e640c', \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# help message
|
||||||
|
|
||||||
|
HELP = """
|
||||||
|
Syntax from src dir: make lib-pace args="-b"
|
||||||
|
or: make lib-pace args="-b -v version"
|
||||||
|
Syntax from lib dir: python Install.py -b
|
||||||
|
or: python Install.py -b -v version
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
make lib-pace args="-b" # install default version of PACE lib
|
||||||
|
make lib-pace args="-b -v version" # install specified version of PACE lib
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
pgroup = parser.add_mutually_exclusive_group()
|
||||||
|
pgroup.add_argument("-b", "--build", action="store_true",
|
||||||
|
help="download and build base PACE library")
|
||||||
|
parser.add_argument("-v", "--version", default=version, choices=checksums.keys(),
|
||||||
|
help="set version of PACE library to download and build (default: %s)" % version)
|
||||||
|
parser.add_argument("-vv", "--verbose", action="store_true",
|
||||||
|
help="be more verbose about is happening while this script runs")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# print help message and exit, if neither build nor path options are given
|
||||||
|
if not args.build:
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(HELP)
|
||||||
|
|
||||||
|
buildflag = args.build
|
||||||
|
|
||||||
|
verboseflag = args.verbose
|
||||||
|
version = args.version
|
||||||
|
|
||||||
|
|
||||||
|
archive_extension = "tar.gz"
|
||||||
|
url = "https://github.com/ICAMS/lammps-user-pace/archive/refs/tags/%s.%s" % (version, archive_extension)
|
||||||
|
unarchived_folder_name = "lammps-user-pace-%s"%(version)
|
||||||
|
|
||||||
|
# download PACE tarball, unpack, build PACE
|
||||||
|
if buildflag:
|
||||||
|
|
||||||
|
# download entire tarball
|
||||||
|
|
||||||
|
print("Downloading pace tarball ...")
|
||||||
|
archive_filename = "%s.%s" % (version, archive_extension)
|
||||||
|
download_filename = "%s/%s" % (thisdir, archive_filename)
|
||||||
|
print("Downloading from ",url," to ",download_filename, end=" ")
|
||||||
|
geturl(url, download_filename)
|
||||||
|
print(" done")
|
||||||
|
|
||||||
|
# verify downloaded archive integrity via md5 checksum, if known.
|
||||||
|
if version in checksums:
|
||||||
|
if not checkmd5sum(checksums[version], archive_filename):
|
||||||
|
sys.exit("Checksum for pace library does not match")
|
||||||
|
|
||||||
|
print("Unpacking pace tarball ...")
|
||||||
|
src_folder = thisdir+"/src"
|
||||||
|
cmd = 'cd "%s"; rm -rf "%s"; tar -xvf %s; mv %s %s' % (thisdir, src_folder, archive_filename, unarchived_folder_name, src_folder)
|
||||||
|
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
|
||||||
|
|
||||||
|
# configure
|
||||||
|
|
||||||
|
build_folder = "%s/build"%(thisdir)
|
||||||
|
print("Configuring libpace ...")
|
||||||
|
cmd = 'cd %s && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release' % (thisdir)
|
||||||
|
txt = subprocess.check_output(cmd,stderr=subprocess.STDOUT,shell=True)
|
||||||
|
if verboseflag: print(txt.decode("UTF-8"))
|
||||||
|
|
||||||
|
# build
|
||||||
|
print("Building libpace ...")
|
||||||
|
cmd = 'cd "%s" && make -j2 && cp libpace.a %s/' % (build_folder, thisdir)
|
||||||
|
txt = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
|
||||||
|
if verboseflag:
|
||||||
|
print(txt.decode("UTF-8"))
|
||||||
|
|
||||||
|
# remove source files
|
||||||
|
|
||||||
|
print("Removing pace build files and archive ...")
|
||||||
|
cmd = 'rm %s; rm -rf %s' % (download_filename, build_folder)
|
||||||
|
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
|
674
lib/pace/LICENSE
674
lib/pace/LICENSE
|
@ -1,674 +0,0 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
|
||||||
or can get the source code. And you must show them these terms so they
|
|
||||||
know their rights.
|
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
|
||||||
that there is no warranty for this free software. For both users' and
|
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
|
||||||
changed, so that their problems will not be attributed erroneously to
|
|
||||||
authors of previous versions.
|
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the special requirements of the GNU Affero General Public License,
|
|
||||||
section 13, concerning interaction through a network will apply to the
|
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
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, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
|
||||||
notice like this when it starts in an interactive mode:
|
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author>
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
|
||||||
<https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
This directory contains files required to use the USER-PACE package.
|
||||||
|
|
||||||
|
You can type "make lib-pace" from the src directory to see help on
|
||||||
|
how to download and build this library via make commands, or you can
|
||||||
|
do the same thing by typing "python Install.py" from within this
|
||||||
|
directory.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,184 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Lysogorskiy Yury on 28.04.2020.
|
|
||||||
|
|
||||||
#include "ace_abstract_basis.h"
|
|
||||||
|
|
||||||
////embedding function
|
|
||||||
////case nemb = 1 only implementation
|
|
||||||
////F = sign(x)*( ( 1 - exp(-(w*x)^3) )*abs(x)^m + ((1/w)^(m-1))*exp(-(w*x)^3)*abs(x) )
|
|
||||||
//// !! no prefactor wpre
|
|
||||||
void Fexp(DOUBLE_TYPE x, DOUBLE_TYPE m, DOUBLE_TYPE &F, DOUBLE_TYPE &DF) {
|
|
||||||
DOUBLE_TYPE w = 1.e6;
|
|
||||||
DOUBLE_TYPE eps = 1e-10;
|
|
||||||
|
|
||||||
DOUBLE_TYPE lambda = pow(1.0 / w, m - 1.0);
|
|
||||||
if (abs(x) > eps) {
|
|
||||||
DOUBLE_TYPE g;
|
|
||||||
DOUBLE_TYPE a = abs(x);
|
|
||||||
DOUBLE_TYPE am = pow(a, m);
|
|
||||||
DOUBLE_TYPE w3x3 = pow(w * a, 3);
|
|
||||||
DOUBLE_TYPE sign_factor = (signbit(x) ? -1 : 1);
|
|
||||||
if (w3x3 > 30.0)
|
|
||||||
g = 0.0;
|
|
||||||
else
|
|
||||||
g = exp(-w3x3);
|
|
||||||
|
|
||||||
DOUBLE_TYPE omg = 1.0 - g;
|
|
||||||
F = sign_factor * (omg * am + lambda * g * a);
|
|
||||||
DOUBLE_TYPE dg = -3.0 * w * w * w * a * a * g;
|
|
||||||
DF = m * pow(a, m - 1.0) * omg - am * dg + lambda * dg * a + lambda * g;
|
|
||||||
} else {
|
|
||||||
F = lambda * x;
|
|
||||||
DF = lambda;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Scaled-shifted embedding function
|
|
||||||
//F = sign(x)*( ( 1 - exp(-(w*x)^3) )*abs(x)^m + ((1/w)^(m-1))*exp(-(w*x)^3)*abs(x) )
|
|
||||||
// !! no prefactor wpre
|
|
||||||
void FexpShiftedScaled(DOUBLE_TYPE rho, DOUBLE_TYPE mexp, DOUBLE_TYPE &F, DOUBLE_TYPE &DF) {
|
|
||||||
DOUBLE_TYPE eps = 1e-10;
|
|
||||||
DOUBLE_TYPE a, xoff, yoff, nx, exprho;
|
|
||||||
|
|
||||||
if (abs(mexp - 1.0) < eps) {
|
|
||||||
F = rho;
|
|
||||||
DF = 1;
|
|
||||||
} else {
|
|
||||||
a = abs(rho);
|
|
||||||
exprho = exp(-a);
|
|
||||||
nx = 1. / mexp;
|
|
||||||
xoff = pow(nx, (nx / (1.0 - nx))) * exprho;
|
|
||||||
yoff = pow(nx, (1 / (1.0 - nx))) * exprho;
|
|
||||||
DOUBLE_TYPE sign_factor = (signbit(rho) ? -1 : 1);
|
|
||||||
F = sign_factor * (pow(xoff + a, mexp) - yoff);
|
|
||||||
DF = yoff + mexp * (-xoff + 1.0) * pow(xoff + a, mexp - 1.);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEAbstractBasisSet::inner_cutoff(DOUBLE_TYPE rho_core, DOUBLE_TYPE rho_cut, DOUBLE_TYPE drho_cut,
|
|
||||||
DOUBLE_TYPE &fcut, DOUBLE_TYPE &dfcut) {
|
|
||||||
|
|
||||||
DOUBLE_TYPE rho_low = rho_cut - drho_cut;
|
|
||||||
if (rho_core >= rho_cut) {
|
|
||||||
fcut = 0;
|
|
||||||
dfcut = 0;
|
|
||||||
} else if (rho_core <= rho_low) {
|
|
||||||
fcut = 1;
|
|
||||||
dfcut = 0;
|
|
||||||
} else {
|
|
||||||
fcut = 0.5 * (1 + cos(M_PI * (rho_core - rho_low) / drho_cut));
|
|
||||||
dfcut = -0.5 * sin(M_PI * (rho_core - rho_low) / drho_cut) * M_PI / drho_cut;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEAbstractBasisSet::FS_values_and_derivatives(Array1D<DOUBLE_TYPE> &rhos, DOUBLE_TYPE &value,
|
|
||||||
Array1D<DOUBLE_TYPE> &derivatives, DENSITY_TYPE ndensity) {
|
|
||||||
DOUBLE_TYPE F, DF = 0, wpre, mexp;
|
|
||||||
for (int p = 0; p < ndensity; p++) {
|
|
||||||
wpre = FS_parameters.at(p * ndensity + 0);
|
|
||||||
mexp = FS_parameters.at(p * ndensity + 1);
|
|
||||||
if (this->npoti == "FinnisSinclair")
|
|
||||||
Fexp(rhos(p), mexp, F, DF);
|
|
||||||
else if (this->npoti == "FinnisSinclairShiftedScaled")
|
|
||||||
FexpShiftedScaled(rhos(p), mexp, F, DF);
|
|
||||||
value += F * wpre; // * weight (wpre)
|
|
||||||
derivatives(p) = DF * wpre;// * weight (wpre)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEAbstractBasisSet::_clean() {
|
|
||||||
|
|
||||||
delete[] elements_name;
|
|
||||||
elements_name = nullptr;
|
|
||||||
delete radial_functions;
|
|
||||||
radial_functions = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ACEAbstractBasisSet::ACEAbstractBasisSet(const ACEAbstractBasisSet &other) {
|
|
||||||
ACEAbstractBasisSet::_copy_scalar_memory(other);
|
|
||||||
ACEAbstractBasisSet::_copy_dynamic_memory(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
ACEAbstractBasisSet &ACEAbstractBasisSet::operator=(const ACEAbstractBasisSet &other) {
|
|
||||||
if (this != &other) {
|
|
||||||
// deallocate old memory
|
|
||||||
ACEAbstractBasisSet::_clean();
|
|
||||||
//copy scalar values
|
|
||||||
ACEAbstractBasisSet::_copy_scalar_memory(other);
|
|
||||||
//copy dynamic memory
|
|
||||||
ACEAbstractBasisSet::_copy_dynamic_memory(other);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ACEAbstractBasisSet::~ACEAbstractBasisSet() {
|
|
||||||
ACEAbstractBasisSet::_clean();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEAbstractBasisSet::_copy_scalar_memory(const ACEAbstractBasisSet &src) {
|
|
||||||
deltaSplineBins = src.deltaSplineBins;
|
|
||||||
FS_parameters = src.FS_parameters;
|
|
||||||
npoti = src.npoti;
|
|
||||||
|
|
||||||
nelements = src.nelements;
|
|
||||||
rankmax = src.rankmax;
|
|
||||||
ndensitymax = src.ndensitymax;
|
|
||||||
nradbase = src.nradbase;
|
|
||||||
lmax = src.lmax;
|
|
||||||
nradmax = src.nradmax;
|
|
||||||
cutoffmax = src.cutoffmax;
|
|
||||||
|
|
||||||
spherical_harmonics = src.spherical_harmonics;
|
|
||||||
|
|
||||||
rho_core_cutoffs = src.rho_core_cutoffs;
|
|
||||||
drho_core_cutoffs = src.drho_core_cutoffs;
|
|
||||||
|
|
||||||
|
|
||||||
E0vals = src.E0vals;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEAbstractBasisSet::_copy_dynamic_memory(const ACEAbstractBasisSet &src) {//allocate new memory
|
|
||||||
if (src.elements_name == nullptr)
|
|
||||||
throw runtime_error("Could not copy ACEAbstractBasisSet::elements_name - array not initialized");
|
|
||||||
elements_name = new string[nelements];
|
|
||||||
//copy
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
elements_name[mu] = src.elements_name[mu];
|
|
||||||
}
|
|
||||||
radial_functions = src.radial_functions->clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
SPECIES_TYPE ACEAbstractBasisSet::get_species_index_by_name(const string &elemname) {
|
|
||||||
for (SPECIES_TYPE t = 0; t < nelements; t++) {
|
|
||||||
if (this->elements_name[t] == elemname)
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
|
@ -1,169 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Created by Lysogorskiy Yury on 28.04.2020.
|
|
||||||
|
|
||||||
#ifndef ACE_EVALUATOR_ACE_ABSTRACT_BASIS_H
|
|
||||||
#define ACE_EVALUATOR_ACE_ABSTRACT_BASIS_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "ace_c_basisfunction.h"
|
|
||||||
#include "ace_contigous_array.h"
|
|
||||||
#include "ace_radial.h"
|
|
||||||
#include "ace_spherical_cart.h"
|
|
||||||
#include "ace_types.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract basis set class
|
|
||||||
*/
|
|
||||||
class ACEAbstractBasisSet {
|
|
||||||
public:
|
|
||||||
SPECIES_TYPE nelements = 0; ///< number of elements in basis set
|
|
||||||
RANK_TYPE rankmax = 0; ///< maximum value of rank
|
|
||||||
DENSITY_TYPE ndensitymax = 0; ///< maximum number of densities \f$ \rho^{(p)} \f$
|
|
||||||
NS_TYPE nradbase = 0; ///< maximum number of radial \f$\textbf{basis}\f$ function \f$ g_{k}(r) \f$
|
|
||||||
LS_TYPE lmax = 0; ///< \f$ l_\textrm{max} \f$ - maximum value of orbital moment \f$ l \f$
|
|
||||||
NS_TYPE nradmax = 0; ///< maximum number \f$ n \f$ of radial function \f$ R_{nl}(r) \f$
|
|
||||||
DOUBLE_TYPE cutoffmax = 0; ///< maximum value of cutoff distance among all species in basis set
|
|
||||||
DOUBLE_TYPE deltaSplineBins = 0; ///< Spline interpolation density
|
|
||||||
|
|
||||||
string npoti = "FinnisSinclair"; ///< FS and embedding function combination
|
|
||||||
|
|
||||||
string *elements_name = nullptr; ///< Array of elements name for mapping from index (0..nelements-1) to element symbol (string)
|
|
||||||
|
|
||||||
AbstractRadialBasis *radial_functions = nullptr; ///< object to work with radial functions
|
|
||||||
ACECartesianSphericalHarmonics spherical_harmonics; ///< object to work with spherical harmonics in Cartesian representation
|
|
||||||
|
|
||||||
|
|
||||||
Array1D<DOUBLE_TYPE> rho_core_cutoffs; ///< energy-based inner cut-off
|
|
||||||
Array1D<DOUBLE_TYPE> drho_core_cutoffs; ///< decay of energy-based inner cut-off
|
|
||||||
|
|
||||||
vector<DOUBLE_TYPE> FS_parameters; ///< parameters for cluster functional, see Eq.(3) in implementation notes or Eq.(53) in <A HREF="https://journals.aps.org/prb/abstract/10.1103/PhysRevB.99.014104"> PRB 99, 014104 (2019) </A>
|
|
||||||
|
|
||||||
// E0 values
|
|
||||||
Array1D<DOUBLE_TYPE> E0vals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default empty constructor
|
|
||||||
*/
|
|
||||||
ACEAbstractBasisSet() = default;
|
|
||||||
|
|
||||||
// copy constructor, operator= and destructor (see. Rule of Three)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor (see. Rule of Three)
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
ACEAbstractBasisSet(const ACEAbstractBasisSet &other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* operator= (see. Rule of Three)
|
|
||||||
* @param other
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ACEAbstractBasisSet &operator=(const ACEAbstractBasisSet &other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virtual destructor (see. Rule of Three)
|
|
||||||
*/
|
|
||||||
virtual ~ACEAbstractBasisSet();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computing cluster functional \f$ F(\rho_i^{(1)}, \dots, \rho_i^{(P)}) \f$
|
|
||||||
* and its derivatives \f$ (\partial F/\partial\rho_i^{(1)}, \dots, \partial F/\partial \rho_i^{(P)} ) \f$
|
|
||||||
* @param rhos array with densities \f$ \rho^{(p)} \f$
|
|
||||||
* @param value (out) return value of cluster functional
|
|
||||||
* @param derivatives (out) array of derivatives \f$ (\partial F/\partial\rho_i^{(1)}, \dots, \partial F/\partial \rho_i^{(P)} ) \f$
|
|
||||||
* @param ndensity number \f$ P \f$ of densities to use
|
|
||||||
*/
|
|
||||||
void FS_values_and_derivatives(Array1D<DOUBLE_TYPE> &rhos, DOUBLE_TYPE &value, Array1D<DOUBLE_TYPE> &derivatives,
|
|
||||||
DENSITY_TYPE ndensity);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computing hard core pairwise repulsive potential \f$ f_{cut}(\rho_i^{(\textrm{core})})\f$ and its derivative,
|
|
||||||
* see Eq.(29) of implementation notes
|
|
||||||
* @param rho_core value of \f$ \rho_i^{(\textrm{core})} \f$
|
|
||||||
* @param rho_cut \f$ \rho_{cut}^{\mu_i} \f$ value
|
|
||||||
* @param drho_cut \f$ \Delta_{cut}^{\mu_i} \f$ value
|
|
||||||
* @param fcut (out) return inner cutoff function
|
|
||||||
* @param dfcut (out) return derivative of inner cutoff function
|
|
||||||
*/
|
|
||||||
static void inner_cutoff(DOUBLE_TYPE rho_core, DOUBLE_TYPE rho_cut, DOUBLE_TYPE drho_cut, DOUBLE_TYPE &fcut,
|
|
||||||
DOUBLE_TYPE &dfcut);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual method to save potential to file
|
|
||||||
* @param filename file name
|
|
||||||
*/
|
|
||||||
virtual void save(const string &filename) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual method to load potential from file
|
|
||||||
* @param filename file name
|
|
||||||
*/
|
|
||||||
virtual void load(const string filename) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the species index by its element name
|
|
||||||
* @param elemname element name
|
|
||||||
* @return species index
|
|
||||||
*/
|
|
||||||
SPECIES_TYPE get_species_index_by_name(const string &elemname);
|
|
||||||
|
|
||||||
|
|
||||||
// routines for copying and cleaning dynamic memory of the class (see. Rule of Three)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Routine for clean the dynamically allocated memory\n
|
|
||||||
* IMPORTANT! It must be idempotent for safety.
|
|
||||||
*/
|
|
||||||
virtual void _clean();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy dynamic memory from src. Must be override and extended in derived classes!
|
|
||||||
* @param src source object to copy from
|
|
||||||
*/
|
|
||||||
virtual void _copy_dynamic_memory(const ACEAbstractBasisSet &src);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy scalar values from src. Must be override and extended in derived classes!
|
|
||||||
* @param src source object to copy from
|
|
||||||
*/
|
|
||||||
virtual void _copy_scalar_memory(const ACEAbstractBasisSet &src);
|
|
||||||
};
|
|
||||||
|
|
||||||
void Fexp(DOUBLE_TYPE rho, DOUBLE_TYPE mexp, DOUBLE_TYPE &F, DOUBLE_TYPE &DF);
|
|
||||||
|
|
||||||
void FexpShiftedScaled(DOUBLE_TYPE rho, DOUBLE_TYPE mexp, DOUBLE_TYPE &F, DOUBLE_TYPE &DF);
|
|
||||||
|
|
||||||
#endif //ACE_EVALUATOR_ACE_ABSTRACT_BASIS_H
|
|
|
@ -1,579 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 11.01.20.
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ACE_ARRAY2DLM_H
|
|
||||||
#define ACE_ARRAY2DLM_H
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "ace_arraynd.h"
|
|
||||||
#include "ace_contigous_array.h"
|
|
||||||
#include "ace_types.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contiguous array to organize values by \f$ (l,m) \f$ indiced (orbital moment and its projection).
|
|
||||||
* Only \f$ l_\textrm{max}\f$ should be provided, \f$ m = -l, \dots,l \f$
|
|
||||||
* for \f$ l = 0, \dots, l_\textrm{max}\f$
|
|
||||||
* @tparam T type of values to store
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
class Array2DLM : public ContiguousArrayND<T> {
|
|
||||||
using ContiguousArrayND<T>::array_name;
|
|
||||||
using ContiguousArrayND<T>::data;
|
|
||||||
using ContiguousArrayND<T>::size;
|
|
||||||
|
|
||||||
LS_TYPE lmax = 0; ///< orbital dimension \f$ l_{max} \f$
|
|
||||||
|
|
||||||
bool is_proxy = false; ///< flag to show, if object is owning the memory or just represent it (proxying)dimensions
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Default empty constructor
|
|
||||||
*/
|
|
||||||
Array2DLM() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parametrized constructor
|
|
||||||
* @param lmax maximum value of \f$ l \f$
|
|
||||||
* @param array_name name of the array
|
|
||||||
*/
|
|
||||||
explicit Array2DLM(LS_TYPE lmax, string array_name = "Array2DLM") {
|
|
||||||
init(lmax, array_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor to create slices-proxy array, i.e. to provide access to the memory, but not to own it.
|
|
||||||
* @param lmax maximum value of \f$ l \f$
|
|
||||||
* @param data_ptr pointer to original data
|
|
||||||
* @param array_name name of the array
|
|
||||||
*/
|
|
||||||
Array2DLM(LS_TYPE lmax, T *data_ptr, string array_name = "Array2DLM") {
|
|
||||||
this->lmax = lmax;
|
|
||||||
this->size = (lmax + 1) * (lmax + 1);
|
|
||||||
this->data = data_ptr;
|
|
||||||
this->array_name = array_name;
|
|
||||||
is_proxy = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
~Array2DLM() {
|
|
||||||
if (!is_proxy) {
|
|
||||||
if (data != nullptr) delete[] data;
|
|
||||||
}
|
|
||||||
data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize array, allocate memory
|
|
||||||
* @param lmax maximum value of l
|
|
||||||
* @param array_name name of the array
|
|
||||||
*/
|
|
||||||
void init(LS_TYPE lmax, string array_name = "Array2DLM") {
|
|
||||||
if (is_proxy) {
|
|
||||||
char s[1024];
|
|
||||||
sprintf(s, "Could not re-initialize proxy-array %s\n", this->array_name.c_str());
|
|
||||||
throw logic_error(s);
|
|
||||||
}
|
|
||||||
this->lmax = lmax;
|
|
||||||
this->array_name = array_name;
|
|
||||||
//for m = -l .. l
|
|
||||||
if (size != (lmax + 1) * (lmax + 1)) {
|
|
||||||
size = (lmax + 1) * (lmax + 1);
|
|
||||||
if (data) delete[] data;
|
|
||||||
data = new T[size]{};
|
|
||||||
memset(data, 0.0, size * sizeof(T));
|
|
||||||
} else {
|
|
||||||
memset(data, 0, size * sizeof(T));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
/**
|
|
||||||
* Check if indices (l,m) are within array
|
|
||||||
*/
|
|
||||||
void check_indices(LS_TYPE l, MS_TYPE m) const {
|
|
||||||
|
|
||||||
if ((l < 0) | (l > lmax)) {
|
|
||||||
fprintf(stderr, "%s: Index l = %d out of range (0, %d)\n", array_name.c_str(), l, lmax);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m < -l) | (m > l)) {
|
|
||||||
fprintf(stderr, "%s: Index m = %d out of range (%d, %d)\n", array_name.c_str(), m, -l, l);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
size_t ii = l * (l + 1) + m;
|
|
||||||
if (ii >= size) {
|
|
||||||
fprintf(stderr, "%s: index = %ld out of range %ld\n", array_name.c_str(), ii, size);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessing the array value by index (l,m) for reading
|
|
||||||
* @param l
|
|
||||||
* @param m
|
|
||||||
* @return array value
|
|
||||||
*/
|
|
||||||
inline const T &operator()(LS_TYPE l, MS_TYPE m) const {
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
check_indices(l, m);
|
|
||||||
#endif
|
|
||||||
//l^2 + l + m
|
|
||||||
return data[l * (l + 1) + m];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessing the array value by index (l,m) for writing
|
|
||||||
* @param l
|
|
||||||
* @param m
|
|
||||||
* @return array value
|
|
||||||
*/
|
|
||||||
inline T &operator()(LS_TYPE l, MS_TYPE m) {
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
check_indices(l, m);
|
|
||||||
#endif
|
|
||||||
//l^2 + l + m
|
|
||||||
return data[l * (l + 1) + m];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert array to STL vector<vector<T>> container
|
|
||||||
* @return vector<vector<T>> container
|
|
||||||
*/
|
|
||||||
vector<vector<T>> to_vector() const {
|
|
||||||
vector<vector<T>> res;
|
|
||||||
res.resize(lmax + 1);
|
|
||||||
|
|
||||||
for (int i = 0; i < lmax + 1; i++) {
|
|
||||||
res[i].resize(i + 1);
|
|
||||||
for (int j = 0; j < i + 1; j++) {
|
|
||||||
res[i][j] = operator()(i, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contiguous array to organize values by \f$ (i_0, l , m) \f$ indices.
|
|
||||||
* Only \f$ d_{0}, l_\textrm{max}\f$ should be provided: \f$ m = -l, \dots,l \f$
|
|
||||||
* for \f$ l = 0, \dots, l_\textrm{max}\f$
|
|
||||||
* @tparam T type of values to store
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
class Array3DLM : public ContiguousArrayND<T> {
|
|
||||||
using ContiguousArrayND<T>::array_name;
|
|
||||||
using ContiguousArrayND<T>::data;
|
|
||||||
using ContiguousArrayND<T>::size;
|
|
||||||
|
|
||||||
LS_TYPE lmax = 0; ///< orbital dimension \f$ l_{max} \f$
|
|
||||||
|
|
||||||
|
|
||||||
size_t dim[1] = {0}; ///< linear dimension \f$ d_{0} \f$
|
|
||||||
|
|
||||||
size_t s[1] = {0}; ///< strides for linear dimensions
|
|
||||||
|
|
||||||
Array1D<Array2DLM<T> *> _proxy_slices; ///< slices representation
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Default empty constructor
|
|
||||||
*/
|
|
||||||
Array3DLM() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parametrized constructor
|
|
||||||
* @param array_name name of the array
|
|
||||||
*/
|
|
||||||
Array3DLM(string array_name) {
|
|
||||||
this->array_name = array_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parametrized constructor
|
|
||||||
* @param d0 maximum value of \f$ i_0 \f$
|
|
||||||
* @param lmax maximum value of \f$ l \f$
|
|
||||||
* @param array_name name of the array
|
|
||||||
*/
|
|
||||||
explicit Array3DLM(size_t d0, LS_TYPE lmax, string array_name = "Array3DLM") {
|
|
||||||
init(d0, lmax, array_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize array and its slices
|
|
||||||
* @param d0 maximum value of \f$ i_0 \f$
|
|
||||||
* @param lmax maximum value of \f$ l \f$
|
|
||||||
* @param array_name name of the array
|
|
||||||
*/
|
|
||||||
void init(size_t d0, LS_TYPE lmax, string array_name = "Array3DLM") {
|
|
||||||
this->array_name = array_name;
|
|
||||||
this->lmax = lmax;
|
|
||||||
dim[0] = d0;
|
|
||||||
s[0] = lmax * lmax;
|
|
||||||
if (size != s[0] * dim[0]) {
|
|
||||||
size = s[0] * dim[0];
|
|
||||||
if (data) delete[] data;
|
|
||||||
data = new T[size]{};
|
|
||||||
memset(data, 0, size * sizeof(T));
|
|
||||||
} else {
|
|
||||||
memset(data, 0, size * sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
_proxy_slices.set_array_name(array_name + "_proxy");
|
|
||||||
//arrange proxy-slices
|
|
||||||
_clear_proxies();
|
|
||||||
_proxy_slices.resize(dim[0]);
|
|
||||||
for (size_t i0 = 0; i0 < dim[0]; ++i0) {
|
|
||||||
_proxy_slices(i0) = new Array2DLM<T>(this->lmax, &this->data[i0 * s[0]],
|
|
||||||
array_name + "_slice");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release pointers to slices
|
|
||||||
*/
|
|
||||||
void _clear_proxies() {
|
|
||||||
for (size_t i0 = 0; i0 < _proxy_slices.get_dim(0); ++i0) {
|
|
||||||
delete _proxy_slices(i0);
|
|
||||||
_proxy_slices(i0) = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor, clear proxies
|
|
||||||
*/
|
|
||||||
~Array3DLM() {
|
|
||||||
_clear_proxies();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resize array to new dimensions
|
|
||||||
* @param d0
|
|
||||||
* @param lmax
|
|
||||||
*/
|
|
||||||
void resize(size_t d0, LS_TYPE lmax) {
|
|
||||||
_clear_proxies();
|
|
||||||
init(d0, lmax, this->array_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get array dimensions
|
|
||||||
* @param d dimension index
|
|
||||||
* @return dimension along axis 'd'
|
|
||||||
*/
|
|
||||||
size_t get_dim(int d) const {
|
|
||||||
return dim[d];
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
/**
|
|
||||||
* Check if indices (i0, l,m) are within array
|
|
||||||
*/
|
|
||||||
void check_indices(size_t i0, LS_TYPE l, MS_TYPE m) const {
|
|
||||||
if ((l < 0) | (l > lmax)) {
|
|
||||||
fprintf(stderr, "%s: Index l = %d out of range (0, %d)\n", array_name.c_str(), l, lmax);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m < -l) | (m > l)) {
|
|
||||||
fprintf(stderr, "%s: Index m = %d out of range (%d, %d)\n", array_name.c_str(), m, -l, l);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((i0 < 0) | (i0 >= dim[0])) {
|
|
||||||
fprintf(stderr, "%s: index i0 = %ld out of range (0, %ld)\n", array_name.c_str(), i0, dim[0] - 1);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ii = i0 * s[0] + l * (l + 1) + m;
|
|
||||||
if (ii >= size) {
|
|
||||||
fprintf(stderr, "%s: index = %ld out of range %ld\n", array_name.c_str(), ii, size);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessing the array value by index (i0,l,m) for reading
|
|
||||||
* @param i0
|
|
||||||
* @param l
|
|
||||||
* @param m
|
|
||||||
* @return array value
|
|
||||||
*/
|
|
||||||
inline const T &operator()(size_t i0, LS_TYPE l, MS_TYPE m) const {
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
check_indices(i0, l, m);
|
|
||||||
#endif
|
|
||||||
return data[i0 * s[0] + l * (l + 1) + m];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessing the array value by index (i0,l,m) for writing
|
|
||||||
* @param i0
|
|
||||||
* @param l
|
|
||||||
* @param m
|
|
||||||
* @return array value
|
|
||||||
*/
|
|
||||||
inline T &operator()(size_t i0, LS_TYPE l, MS_TYPE m) {
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
check_indices(i0, l, m);
|
|
||||||
#endif
|
|
||||||
return data[i0 * s[0] + l * (l + 1) + m];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return proxy Array2DLM pointing to i0, l=0, m=0 to read
|
|
||||||
* @param i0
|
|
||||||
* @return proxy Array2DLM pointing to i0, l=0, m=0
|
|
||||||
*/
|
|
||||||
inline const Array2DLM<T> &operator()(size_t i0) const {
|
|
||||||
return *_proxy_slices(i0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return proxy Array2DLM pointing to i0, l=0, m=0 to write
|
|
||||||
* @param i0
|
|
||||||
* @return proxy Array2DLM pointing to i0, l=0, m=0
|
|
||||||
*/
|
|
||||||
inline Array2DLM<T> &operator()(size_t i0) {
|
|
||||||
return *_proxy_slices(i0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contiguous array to organize values by \f$ (i_0, i_1, l , m) \f$ indices.
|
|
||||||
* Only \f$ d_{0}, d_{1}, l_\textrm{max}\f$ should be provided: \f$ m = -l, \dots,l \f$
|
|
||||||
* for \f$ l = 0, \dots, l_\textrm{max}\f$
|
|
||||||
* @tparam T type of values to store
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
class Array4DLM : public ContiguousArrayND<T> {
|
|
||||||
using ContiguousArrayND<T>::array_name;
|
|
||||||
using ContiguousArrayND<T>::data;
|
|
||||||
using ContiguousArrayND<T>::size;
|
|
||||||
|
|
||||||
LS_TYPE lmax = 0; ///< orbital dimension \f$ l_{max} \f$
|
|
||||||
size_t dim[2] = {0, 0}; ///< linear dimension \f$ d_{0}, d_{1} \f$
|
|
||||||
size_t s[2] = {0, 0}; ///< strides for linear dimensions
|
|
||||||
|
|
||||||
Array2D<Array2DLM<T> *> _proxy_slices; ///< slices representation
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Default empty constructor
|
|
||||||
*/
|
|
||||||
Array4DLM() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parametrized constructor
|
|
||||||
* @param array_name name of the array
|
|
||||||
*/
|
|
||||||
Array4DLM(string array_name) {
|
|
||||||
this->array_name = array_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parametrized constructor
|
|
||||||
* @param d0 maximum value of \f$ i_0 \f$
|
|
||||||
* @param d1 maximum value of \f$ i_1 \f$
|
|
||||||
* @param lmax maximum value of \f$ l \f$
|
|
||||||
* @param array_name name of the array
|
|
||||||
*/
|
|
||||||
explicit Array4DLM(size_t d0, size_t d1, LS_TYPE lmax, string array_name = "Array4DLM") {
|
|
||||||
init(d0, d1, lmax, array_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize array, reallocate memory and its slices
|
|
||||||
* @param d0 maximum value of \f$ i_0 \f$
|
|
||||||
* @param d1 maximum value of \f$ i_1 \f$
|
|
||||||
* @param lmax maximum value of \f$ l \f$
|
|
||||||
* @param array_name name of the array
|
|
||||||
*/
|
|
||||||
void init(size_t d0, size_t d1, LS_TYPE lmax, string array_name = "Array4DLM") {
|
|
||||||
this->array_name = array_name;
|
|
||||||
this->lmax = lmax;
|
|
||||||
dim[1] = d1;
|
|
||||||
dim[0] = d0;
|
|
||||||
s[1] = lmax * lmax;
|
|
||||||
s[0] = s[1] * dim[1];
|
|
||||||
if (size != s[0] * dim[0]) {
|
|
||||||
size = s[0] * dim[0];
|
|
||||||
if (data) delete[] data;
|
|
||||||
data = new T[size]{};
|
|
||||||
memset(data, 0, size * sizeof(T));
|
|
||||||
} else {
|
|
||||||
memset(data, 0, size * sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
_proxy_slices.set_array_name(array_name + "_proxy");
|
|
||||||
//release old memory if there is any
|
|
||||||
_clear_proxies();
|
|
||||||
//arrange proxy-slices
|
|
||||||
_proxy_slices.resize(dim[0], dim[1]);
|
|
||||||
for (size_t i0 = 0; i0 < dim[0]; ++i0)
|
|
||||||
for (size_t i1 = 0; i1 < dim[1]; ++i1) {
|
|
||||||
_proxy_slices(i0, i1) = new Array2DLM<T>(this->lmax, &this->data[i0 * s[0] + i1 * s[1]],
|
|
||||||
array_name + "_slice");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release pointers to slices
|
|
||||||
*/
|
|
||||||
void _clear_proxies() {
|
|
||||||
|
|
||||||
for (size_t i0 = 0; i0 < _proxy_slices.get_dim(0); ++i0)
|
|
||||||
for (size_t i1 = 0; i1 < _proxy_slices.get_dim(1); ++i1) {
|
|
||||||
delete _proxy_slices(i0, i1);
|
|
||||||
_proxy_slices(i0, i1) = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor, clear proxies
|
|
||||||
*/
|
|
||||||
~Array4DLM() {
|
|
||||||
_clear_proxies();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deallocate memory, reallocate with the new dimensions
|
|
||||||
* @param d0
|
|
||||||
* @param lmax
|
|
||||||
*/
|
|
||||||
void resize(size_t d0, size_t d1, LS_TYPE lmax) {
|
|
||||||
_clear_proxies();
|
|
||||||
init(d0, d1, lmax, this->array_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get array dimensions
|
|
||||||
* @param d dimension index
|
|
||||||
* @return dimension along axis 'd'
|
|
||||||
*/
|
|
||||||
size_t get_dim(int d) const {
|
|
||||||
return dim[d];
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
/**
|
|
||||||
* Check if indices (i0, l,m) are within array
|
|
||||||
*/
|
|
||||||
void check_indices(size_t i0, size_t i1, LS_TYPE l, MS_TYPE m) const {
|
|
||||||
if ((l < 0) | (l > lmax)) {
|
|
||||||
fprintf(stderr, "%s: Index l = %d out of range (0, %d)\n", array_name.c_str(), l, lmax);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m < -l) | (m > l)) {
|
|
||||||
fprintf(stderr, "%s: Index m = %d out of range (%d, %d)\n", array_name.c_str(), m, -l, l);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((i0 < 0) | (i0 >= dim[0])) {
|
|
||||||
fprintf(stderr, "%s: index i0 = %ld out of range (0, %ld)\n", array_name.c_str(), i0, dim[0] - 1);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ((i1 < 0) | (i1 >= dim[1])) {
|
|
||||||
fprintf(stderr, "%s: index i1 = %ld out of range (0, %ld)\n", array_name.c_str(), i1, dim[1] - 1);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ii = i0 * s[0] + i1 * s[1] + l * (l + 1) + m;
|
|
||||||
if (ii >= size) {
|
|
||||||
fprintf(stderr, "%s: index = %ld out of range %ld\n", array_name.c_str(), ii, size);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessing the array value by index (i0,l,m) for reading
|
|
||||||
* @param i0
|
|
||||||
* @param i1
|
|
||||||
* @param l
|
|
||||||
* @param m
|
|
||||||
* @return array value
|
|
||||||
*/
|
|
||||||
inline const T &operator()(size_t i0, size_t i1, LS_TYPE l, MS_TYPE m) const {
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
check_indices(i0, i1, l, m);
|
|
||||||
#endif
|
|
||||||
return data[i0 * s[0] + i1 * s[1] + l * (l + 1) + m];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessing the array value by index (i0,l,m) for writing
|
|
||||||
* @param i0
|
|
||||||
* @param i1
|
|
||||||
* @param l
|
|
||||||
* @param m
|
|
||||||
* @return array value
|
|
||||||
*/
|
|
||||||
inline T &operator()(size_t i0, size_t i1, LS_TYPE l, MS_TYPE m) {
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
check_indices(i0, i1, l, m);
|
|
||||||
#endif
|
|
||||||
return data[i0 * s[0] + i1 * s[1] + l * (l + 1) + m];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return proxy Array2DLM pointing to i0, i1, l=0, m=0 to read
|
|
||||||
* @param i0
|
|
||||||
* @param i1
|
|
||||||
* @return proxy Array2DLM pointing to i0, l=0, m=0
|
|
||||||
*/
|
|
||||||
inline const Array2DLM<T> &operator()(size_t i0, size_t i1) const {
|
|
||||||
return *_proxy_slices(i0, i1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return proxy Array2DLM pointing to i0, i1, l=0, m=0 to write
|
|
||||||
* @param i0
|
|
||||||
* @param i1
|
|
||||||
* @return proxy Array2DLM pointing to i0, l=0, m=0
|
|
||||||
*/
|
|
||||||
inline Array2DLM<T> &operator()(size_t i0, size_t i1) {
|
|
||||||
return *_proxy_slices(i0, i1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //ACE_ARRAY2DLM_H
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,980 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 1.04.20.
|
|
||||||
|
|
||||||
#include "ace_c_basis.h"
|
|
||||||
#include "ships_radial.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
ACECTildeBasisSet::ACECTildeBasisSet(string filename) {
|
|
||||||
load(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
ACECTildeBasisSet::ACECTildeBasisSet(const ACECTildeBasisSet &other) {
|
|
||||||
ACECTildeBasisSet::_copy_scalar_memory(other);
|
|
||||||
ACECTildeBasisSet::_copy_dynamic_memory(other);
|
|
||||||
pack_flatten_basis();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ACECTildeBasisSet &ACECTildeBasisSet::operator=(const ACECTildeBasisSet &other) {
|
|
||||||
if (this != &other) {
|
|
||||||
_clean();
|
|
||||||
_copy_scalar_memory(other);
|
|
||||||
_copy_dynamic_memory(other);
|
|
||||||
pack_flatten_basis();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ACECTildeBasisSet::~ACECTildeBasisSet() {
|
|
||||||
ACECTildeBasisSet::_clean();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::_clean() {
|
|
||||||
// call parent method
|
|
||||||
ACEFlattenBasisSet::_clean();
|
|
||||||
_clean_contiguous_arrays();
|
|
||||||
_clean_basis_arrays();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::_copy_scalar_memory(const ACECTildeBasisSet &src) {
|
|
||||||
ACEFlattenBasisSet::_copy_scalar_memory(src);
|
|
||||||
num_ctilde_max = src.num_ctilde_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::_copy_dynamic_memory(const ACECTildeBasisSet &src) {//allocate new memory
|
|
||||||
ACEFlattenBasisSet::_copy_dynamic_memory(src);
|
|
||||||
|
|
||||||
if (src.basis_rank1 == nullptr)
|
|
||||||
throw runtime_error("Could not copy ACECTildeBasisSet::basis_rank1 - array not initialized");
|
|
||||||
if (src.basis == nullptr) throw runtime_error("Could not copy ACECTildeBasisSet::basis - array not initialized");
|
|
||||||
|
|
||||||
|
|
||||||
basis_rank1 = new ACECTildeBasisFunction *[src.nelements];
|
|
||||||
basis = new ACECTildeBasisFunction *[src.nelements];
|
|
||||||
|
|
||||||
//copy basis arrays
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < src.nelements; ++mu) {
|
|
||||||
basis_rank1[mu] = new ACECTildeBasisFunction[src.total_basis_size_rank1[mu]];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < src.total_basis_size_rank1[mu]; i++) {
|
|
||||||
basis_rank1[mu][i] = src.basis_rank1[mu][i];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
basis[mu] = new ACECTildeBasisFunction[src.total_basis_size[mu]];
|
|
||||||
for (size_t i = 0; i < src.total_basis_size[mu]; i++) {
|
|
||||||
basis[mu][i] = src.basis[mu][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//DON"T COPY CONTIGUOUS ARRAY, REBUILD THEM
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::_clean_contiguous_arrays() {
|
|
||||||
ACEFlattenBasisSet::_clean_contiguous_arrays();
|
|
||||||
|
|
||||||
delete[] full_c_tildes_rank1;
|
|
||||||
full_c_tildes_rank1 = nullptr;
|
|
||||||
|
|
||||||
delete[] full_c_tildes;
|
|
||||||
full_c_tildes = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//re-pack the constituent dynamic arrays of all basis functions in contiguous arrays
|
|
||||||
void ACECTildeBasisSet::pack_flatten_basis() {
|
|
||||||
compute_array_sizes(basis_rank1, basis);
|
|
||||||
|
|
||||||
//1. clean contiguous arrays
|
|
||||||
_clean_contiguous_arrays();
|
|
||||||
//2. allocate contiguous arrays
|
|
||||||
delete[] full_ns_rank1;
|
|
||||||
full_ns_rank1 = new NS_TYPE[rank_array_total_size_rank1];
|
|
||||||
delete[] full_ls_rank1;
|
|
||||||
full_ls_rank1 = new NS_TYPE[rank_array_total_size_rank1];
|
|
||||||
delete[] full_mus_rank1;
|
|
||||||
full_mus_rank1 = new SPECIES_TYPE[rank_array_total_size_rank1];
|
|
||||||
delete[] full_ms_rank1;
|
|
||||||
full_ms_rank1 = new MS_TYPE[rank_array_total_size_rank1];
|
|
||||||
|
|
||||||
delete[] full_c_tildes_rank1;
|
|
||||||
full_c_tildes_rank1 = new DOUBLE_TYPE[coeff_array_total_size_rank1];
|
|
||||||
|
|
||||||
|
|
||||||
delete[] full_ns;
|
|
||||||
full_ns = new NS_TYPE[rank_array_total_size];
|
|
||||||
delete[] full_ls;
|
|
||||||
full_ls = new LS_TYPE[rank_array_total_size];
|
|
||||||
delete[] full_mus;
|
|
||||||
full_mus = new SPECIES_TYPE[rank_array_total_size];
|
|
||||||
delete[] full_ms;
|
|
||||||
full_ms = new MS_TYPE[ms_array_total_size];
|
|
||||||
|
|
||||||
delete[] full_c_tildes;
|
|
||||||
full_c_tildes = new DOUBLE_TYPE[coeff_array_total_size];
|
|
||||||
|
|
||||||
|
|
||||||
//3. copy the values from private C_tilde_B_basis_function arrays to new contigous space
|
|
||||||
//4. clean private memory
|
|
||||||
//5. reassign private array pointers
|
|
||||||
|
|
||||||
//r = 0, rank = 1
|
|
||||||
size_t rank_array_ind_rank1 = 0;
|
|
||||||
size_t coeff_array_ind_rank1 = 0;
|
|
||||||
size_t ms_array_ind_rank1 = 0;
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
for (int func_ind_r1 = 0; func_ind_r1 < total_basis_size_rank1[mu]; ++func_ind_r1) {
|
|
||||||
ACECTildeBasisFunction &func = basis_rank1[mu][func_ind_r1];
|
|
||||||
|
|
||||||
//copy values ns from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
full_ns_rank1[rank_array_ind_rank1] = func.ns[0];
|
|
||||||
|
|
||||||
//copy values ls from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
full_ls_rank1[rank_array_ind_rank1] = func.ls[0];
|
|
||||||
|
|
||||||
//copy values mus from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
full_mus_rank1[rank_array_ind_rank1] = func.mus[0];
|
|
||||||
|
|
||||||
//copy values ctildes from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
memcpy(&full_c_tildes_rank1[coeff_array_ind_rank1], func.ctildes,
|
|
||||||
func.ndensity * sizeof(DOUBLE_TYPE));
|
|
||||||
|
|
||||||
|
|
||||||
//copy values mus from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
memcpy(&full_ms_rank1[ms_array_ind_rank1], func.ms_combs,
|
|
||||||
func.num_ms_combs *
|
|
||||||
func.rank * sizeof(MS_TYPE));
|
|
||||||
|
|
||||||
//release memory of each ACECTildeBasisFunction if it is not proxy
|
|
||||||
func._clean();
|
|
||||||
|
|
||||||
func.mus = &full_mus_rank1[rank_array_ind_rank1];
|
|
||||||
func.ns = &full_ns_rank1[rank_array_ind_rank1];
|
|
||||||
func.ls = &full_ls_rank1[rank_array_ind_rank1];
|
|
||||||
func.ms_combs = &full_ms_rank1[ms_array_ind_rank1];
|
|
||||||
func.ctildes = &full_c_tildes_rank1[coeff_array_ind_rank1];
|
|
||||||
func.is_proxy = true;
|
|
||||||
|
|
||||||
rank_array_ind_rank1 += func.rank;
|
|
||||||
ms_array_ind_rank1 += func.rank *
|
|
||||||
func.num_ms_combs;
|
|
||||||
coeff_array_ind_rank1 += func.num_ms_combs * func.ndensity;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//rank>1, r>0
|
|
||||||
size_t rank_array_ind = 0;
|
|
||||||
size_t coeff_array_ind = 0;
|
|
||||||
size_t ms_array_ind = 0;
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
for (int func_ind = 0; func_ind < total_basis_size[mu]; ++func_ind) {
|
|
||||||
ACECTildeBasisFunction &func = basis[mu][func_ind];
|
|
||||||
|
|
||||||
//copy values mus from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
memcpy(&full_mus[rank_array_ind], func.mus,
|
|
||||||
func.rank * sizeof(SPECIES_TYPE));
|
|
||||||
|
|
||||||
//copy values ns from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
memcpy(&full_ns[rank_array_ind], func.ns,
|
|
||||||
func.rank * sizeof(NS_TYPE));
|
|
||||||
//copy values ls from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
memcpy(&full_ls[rank_array_ind], func.ls,
|
|
||||||
func.rank * sizeof(LS_TYPE));
|
|
||||||
//copy values mus from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
memcpy(&full_ms[ms_array_ind], func.ms_combs,
|
|
||||||
func.num_ms_combs *
|
|
||||||
func.rank * sizeof(MS_TYPE));
|
|
||||||
|
|
||||||
//copy values ctildes from c_tilde_basis_function private memory to contigous memory part
|
|
||||||
memcpy(&full_c_tildes[coeff_array_ind], func.ctildes,
|
|
||||||
func.num_ms_combs * func.ndensity * sizeof(DOUBLE_TYPE));
|
|
||||||
|
|
||||||
|
|
||||||
//release memory of each ACECTildeBasisFunction if it is not proxy
|
|
||||||
func._clean();
|
|
||||||
|
|
||||||
func.ns = &full_ns[rank_array_ind];
|
|
||||||
func.ls = &full_ls[rank_array_ind];
|
|
||||||
func.mus = &full_mus[rank_array_ind];
|
|
||||||
func.ctildes = &full_c_tildes[coeff_array_ind];
|
|
||||||
func.ms_combs = &full_ms[ms_array_ind];
|
|
||||||
func.is_proxy = true;
|
|
||||||
|
|
||||||
rank_array_ind += func.rank;
|
|
||||||
ms_array_ind += func.rank *
|
|
||||||
func.num_ms_combs;
|
|
||||||
coeff_array_ind += func.num_ms_combs * func.ndensity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fwrite_c_tilde_b_basis_func(FILE *fptr, ACECTildeBasisFunction &func) {
|
|
||||||
RANK_TYPE r;
|
|
||||||
fprintf(fptr, "ctilde_basis_func: ");
|
|
||||||
fprintf(fptr, "rank=%d ndens=%d mu0=%d ", func.rank, func.ndensity, func.mu0);
|
|
||||||
|
|
||||||
fprintf(fptr, "mu=(");
|
|
||||||
for (r = 0; r < func.rank; ++r)
|
|
||||||
fprintf(fptr, " %d ", func.mus[r]);
|
|
||||||
fprintf(fptr, ")\n");
|
|
||||||
|
|
||||||
fprintf(fptr, "n=(");
|
|
||||||
for (r = 0; r < func.rank; ++r)
|
|
||||||
fprintf(fptr, " %d ", func.ns[r]);
|
|
||||||
fprintf(fptr, ")\n");
|
|
||||||
|
|
||||||
fprintf(fptr, "l=(");
|
|
||||||
for (r = 0; r < func.rank; ++r)
|
|
||||||
fprintf(fptr, " %d ", func.ls[r]);
|
|
||||||
fprintf(fptr, ")\n");
|
|
||||||
|
|
||||||
fprintf(fptr, "num_ms=%d\n", func.num_ms_combs);
|
|
||||||
|
|
||||||
for (int m_ind = 0; m_ind < func.num_ms_combs; m_ind++) {
|
|
||||||
fprintf(fptr, "<");
|
|
||||||
for (r = 0; r < func.rank; ++r)
|
|
||||||
fprintf(fptr, " %d ", func.ms_combs[m_ind * func.rank + r]);
|
|
||||||
fprintf(fptr, ">: ");
|
|
||||||
for (DENSITY_TYPE p = 0; p < func.ndensity; p++)
|
|
||||||
fprintf(fptr, " %.18f ", func.ctildes[m_ind * func.ndensity + p]);
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::save(const string &filename) {
|
|
||||||
FILE *fptr;
|
|
||||||
fptr = fopen(filename.c_str(), "w");
|
|
||||||
|
|
||||||
fprintf(fptr, "nelements=%d\n", nelements);
|
|
||||||
|
|
||||||
//elements mapping
|
|
||||||
fprintf(fptr, "elements:");
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu)
|
|
||||||
fprintf(fptr, " %s", elements_name[mu].c_str());
|
|
||||||
fprintf(fptr, "\n\n");
|
|
||||||
|
|
||||||
fprintf(fptr, "lmax=%d\n\n", lmax);
|
|
||||||
|
|
||||||
fprintf(fptr, "embedding-function: %s\n", npoti.c_str());
|
|
||||||
|
|
||||||
fprintf(fptr, "%ld FS parameters: ", FS_parameters.size());
|
|
||||||
for (int i = 0; i < FS_parameters.size(); ++i) {
|
|
||||||
fprintf(fptr, " %f", FS_parameters.at(i));
|
|
||||||
}
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
//hard-core energy cutoff repulsion
|
|
||||||
fprintf(fptr, "core energy-cutoff parameters: ");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
fprintf(fptr, "%.18f %.18f\n", rho_core_cutoffs(mu_i), drho_core_cutoffs(mu_i));
|
|
||||||
|
|
||||||
// save E0 values
|
|
||||||
fprintf(fptr, "E0:");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
fprintf(fptr, " %.18f", E0vals(mu_i));
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(fptr, "radbasename=%s\n", radial_functions->radbasename.c_str());
|
|
||||||
fprintf(fptr, "nradbase=%d\n", nradbase);
|
|
||||||
fprintf(fptr, "nradmax=%d\n", nradmax);
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(fptr, "cutoffmax=%f\n", cutoffmax);
|
|
||||||
|
|
||||||
fprintf(fptr, "deltaSplineBins=%f\n", deltaSplineBins);
|
|
||||||
|
|
||||||
//hard-core repulsion
|
|
||||||
fprintf(fptr, "core repulsion parameters: ");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j)
|
|
||||||
fprintf(fptr, "%.18f %.18f\n", radial_functions->prehc(mu_i, mu_j), radial_functions->lambdahc(mu_j, mu_j));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: radial functions
|
|
||||||
//radparameter
|
|
||||||
fprintf(fptr, "radparameter=");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j)
|
|
||||||
fprintf(fptr, " %.18f", radial_functions->lambda(mu_i, mu_j));
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
fprintf(fptr, "cutoff=");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j)
|
|
||||||
fprintf(fptr, " %.18f", radial_functions->cut(mu_i, mu_j));
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
fprintf(fptr, "dcut=");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j)
|
|
||||||
fprintf(fptr, " %.18f", radial_functions->dcut(mu_i, mu_j));
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
fprintf(fptr, "crad=");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j) {
|
|
||||||
for (NS_TYPE k = 0; k < nradbase; k++) {
|
|
||||||
for (NS_TYPE n = 0; n < nradmax; n++) {
|
|
||||||
for (LS_TYPE l = 0; l <= lmax; l++) {
|
|
||||||
fprintf(fptr, " %.18f", radial_functions->crad(mu_i, mu_j, n, l, k));
|
|
||||||
}
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
fprintf(fptr, "rankmax=%d\n", rankmax);
|
|
||||||
fprintf(fptr, "ndensitymax=%d\n", ndensitymax);
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
//num_c_tilde_max
|
|
||||||
fprintf(fptr, "num_c_tilde_max=%d\n", num_ctilde_max);
|
|
||||||
fprintf(fptr, "num_ms_combinations_max=%d\n", num_ms_combinations_max);
|
|
||||||
|
|
||||||
|
|
||||||
//write total_basis_size and total_basis_size_rank1
|
|
||||||
fprintf(fptr, "total_basis_size_rank1: ");
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
fprintf(fptr, "%d ", total_basis_size_rank1[mu]);
|
|
||||||
}
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; mu++)
|
|
||||||
for (SHORT_INT_TYPE func_ind = 0; func_ind < total_basis_size_rank1[mu]; ++func_ind)
|
|
||||||
fwrite_c_tilde_b_basis_func(fptr, basis_rank1[mu][func_ind]);
|
|
||||||
|
|
||||||
fprintf(fptr, "total_basis_size: ");
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
fprintf(fptr, "%d ", total_basis_size[mu]);
|
|
||||||
}
|
|
||||||
fprintf(fptr, "\n");
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; mu++)
|
|
||||||
for (SHORT_INT_TYPE func_ind = 0; func_ind < total_basis_size[mu]; ++func_ind)
|
|
||||||
fwrite_c_tilde_b_basis_func(fptr, basis[mu][func_ind]);
|
|
||||||
|
|
||||||
|
|
||||||
fclose(fptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fread_c_tilde_b_basis_func(FILE *fptr, ACECTildeBasisFunction &func) {
|
|
||||||
RANK_TYPE r;
|
|
||||||
int res;
|
|
||||||
char buf[3][128];
|
|
||||||
|
|
||||||
res = fscanf(fptr, " ctilde_basis_func: ");
|
|
||||||
|
|
||||||
res = fscanf(fptr, "rank=%s ndens=%s mu0=%s ", buf[0], buf[1], buf[2]);
|
|
||||||
if (res != 3)
|
|
||||||
throw invalid_argument("Could not read C-tilde basis function");
|
|
||||||
|
|
||||||
func.rank = (RANK_TYPE) stol(buf[0]);
|
|
||||||
func.ndensity = (DENSITY_TYPE) stol(buf[1]);
|
|
||||||
func.mu0 = (SPECIES_TYPE) stol(buf[2]);
|
|
||||||
|
|
||||||
func.mus = new SPECIES_TYPE[func.rank];
|
|
||||||
func.ns = new NS_TYPE[func.rank];
|
|
||||||
func.ls = new LS_TYPE[func.rank];
|
|
||||||
|
|
||||||
res = fscanf(fptr, " mu=(");
|
|
||||||
for (r = 0; r < func.rank; ++r) {
|
|
||||||
res = fscanf(fptr, "%s", buf[0]);
|
|
||||||
if (res != 1)
|
|
||||||
throw invalid_argument("Could not read C-tilde basis function");
|
|
||||||
func.mus[r] = (SPECIES_TYPE) stol(buf[0]);
|
|
||||||
}
|
|
||||||
res = fscanf(fptr, " )"); // ")"
|
|
||||||
|
|
||||||
res = fscanf(fptr, " n=("); // "n="
|
|
||||||
for (r = 0; r < func.rank; ++r) {
|
|
||||||
res = fscanf(fptr, "%s", buf[0]);
|
|
||||||
if (res != 1)
|
|
||||||
throw invalid_argument("Could not read C-tilde basis function");
|
|
||||||
|
|
||||||
func.ns[r] = (NS_TYPE) stol(buf[0]);
|
|
||||||
}
|
|
||||||
res = fscanf(fptr, " )");
|
|
||||||
|
|
||||||
res = fscanf(fptr, " l=(");
|
|
||||||
for (r = 0; r < func.rank; ++r) {
|
|
||||||
res = fscanf(fptr, "%s", buf[0]);
|
|
||||||
if (res != 1)
|
|
||||||
throw invalid_argument("Could not read C-tilde basis function");
|
|
||||||
func.ls[r] = (NS_TYPE) stol(buf[0]);
|
|
||||||
}
|
|
||||||
res = fscanf(fptr, " )");
|
|
||||||
|
|
||||||
res = fscanf(fptr, " num_ms=%s\n", buf[0]);
|
|
||||||
if (res != 1)
|
|
||||||
throw invalid_argument("Could not read C-tilde basis function");
|
|
||||||
|
|
||||||
func.num_ms_combs = (SHORT_INT_TYPE) stoi(buf[0]);
|
|
||||||
|
|
||||||
func.ms_combs = new MS_TYPE[func.rank * func.num_ms_combs];
|
|
||||||
func.ctildes = new DOUBLE_TYPE[func.ndensity * func.num_ms_combs];
|
|
||||||
|
|
||||||
for (int m_ind = 0; m_ind < func.num_ms_combs; m_ind++) {
|
|
||||||
res = fscanf(fptr, " <");
|
|
||||||
for (r = 0; r < func.rank; ++r) {
|
|
||||||
res = fscanf(fptr, "%s", buf[0]);
|
|
||||||
if (res != 1)
|
|
||||||
throw invalid_argument("Could not read C-tilde basis function");
|
|
||||||
func.ms_combs[m_ind * func.rank + r] = stoi(buf[0]);
|
|
||||||
}
|
|
||||||
res = fscanf(fptr, " >:");
|
|
||||||
for (DENSITY_TYPE p = 0; p < func.ndensity; p++) {
|
|
||||||
res = fscanf(fptr, "%s", buf[0]);
|
|
||||||
if (res != 1)
|
|
||||||
throw invalid_argument("Could not read C-tilde basis function");
|
|
||||||
func.ctildes[m_ind * func.ndensity + p] = stod(buf[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string
|
|
||||||
format_error_message(const char *buffer, const string &filename, const string &var_name, const string &expected) {
|
|
||||||
string err_message = "File '" + filename + "': couldn't read '" + var_name + "'";
|
|
||||||
if (buffer)
|
|
||||||
err_message = err_message + ", read:'" + buffer + "'";
|
|
||||||
if (!expected.empty())
|
|
||||||
err_message = err_message + ". Expected format: '" + expected + "'";
|
|
||||||
return err_message;
|
|
||||||
}
|
|
||||||
|
|
||||||
void throw_error(const string &filename, const string &var_name, const string expected = "") {
|
|
||||||
throw invalid_argument(format_error_message(nullptr, filename, var_name, expected));
|
|
||||||
}
|
|
||||||
|
|
||||||
DOUBLE_TYPE stod_err(const char *buffer, const string &filename, const string &var_name, const string expected = "") {
|
|
||||||
try {
|
|
||||||
return stod(buffer);
|
|
||||||
} catch (invalid_argument &exc) {
|
|
||||||
throw invalid_argument(format_error_message(buffer, filename, var_name, expected).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int stoi_err(const char *buffer, const string &filename, const string &var_name, const string expected = "") {
|
|
||||||
try {
|
|
||||||
return stoi(buffer);
|
|
||||||
} catch (invalid_argument &exc) {
|
|
||||||
throw invalid_argument(format_error_message(buffer, filename, var_name, expected).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long int stol_err(const char *buffer, const string &filename, const string &var_name, const string expected = "") {
|
|
||||||
try {
|
|
||||||
return stol(buffer);
|
|
||||||
} catch (invalid_argument &exc) {
|
|
||||||
throw invalid_argument(format_error_message(buffer, filename, var_name, expected).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::load(const string filename) {
|
|
||||||
int res;
|
|
||||||
char buffer[1024], buffer2[1024];
|
|
||||||
string radbasename = "ChebExpCos";
|
|
||||||
|
|
||||||
FILE *fptr;
|
|
||||||
fptr = fopen(filename.c_str(), "r");
|
|
||||||
if (fptr == NULL)
|
|
||||||
throw invalid_argument("Could not open file " + filename);
|
|
||||||
|
|
||||||
//read number of elements
|
|
||||||
res = fscanf(fptr, " nelements=");
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "nelements", "nelements=[number]");
|
|
||||||
nelements = stoi_err(buffer, filename, "nelements", "nelements=[number]");
|
|
||||||
|
|
||||||
//elements mapping
|
|
||||||
elements_name = new string[nelements];
|
|
||||||
res = fscanf(fptr, " elements:");
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "elements", "elements: Ele1 Ele2 ...");
|
|
||||||
elements_name[mu] = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load angular basis - only need spherical harmonics parameter
|
|
||||||
res = fscanf(fptr, " lmax=%s\n", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "lmax", "lmax=[number]");
|
|
||||||
lmax = stoi_err(buffer, filename, "lmax", "lmax=[number]");
|
|
||||||
spherical_harmonics.init(lmax);
|
|
||||||
|
|
||||||
|
|
||||||
// reading "embedding-function:"
|
|
||||||
bool is_embedding_function_specified = false;
|
|
||||||
res = fscanf(fptr, " embedding-function: %s", buffer);
|
|
||||||
if (res == 0) {
|
|
||||||
//throw_error(filename, "E0", " E0: E0-species1 E0-species2 ...");
|
|
||||||
this->npoti = "FinnisSinclair"; // default values
|
|
||||||
//printf("Warning! No embedding-function is specified, embedding-function: FinnisSinclair would be assumed\n");
|
|
||||||
is_embedding_function_specified = false;
|
|
||||||
} else {
|
|
||||||
this->npoti = buffer;
|
|
||||||
is_embedding_function_specified = true;
|
|
||||||
}
|
|
||||||
int parameters_size;
|
|
||||||
res = fscanf(fptr, "%s FS parameters:", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "FS parameters size", "[number] FS parameters: par1 par2 ...");
|
|
||||||
parameters_size = stoi_err(buffer, filename, "FS parameters size", "[number] FS parameters");
|
|
||||||
FS_parameters.resize(parameters_size);
|
|
||||||
for (int i = 0; i < FS_parameters.size(); ++i) {
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "FS parameter", "[number] FS parameters: [par1] [par2] ...");
|
|
||||||
FS_parameters[i] = stod_err(buffer, filename, "FS parameter", "[number] FS parameters: [par1] [par2] ...");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_embedding_function_specified) {
|
|
||||||
// assuming non-linear potential, and embedding function type is important
|
|
||||||
for (int j = 1; j < parameters_size; j += 2)
|
|
||||||
if (FS_parameters[j] != 1.0) { //if not ensure linearity of embedding function parameters
|
|
||||||
printf("ERROR! Your potential is non-linear\n");
|
|
||||||
printf("Please specify 'embedding-function: FinnisSinclair' or 'embedding-function: FinnisSinclairShiftedScaled' before 'FS parameters size' line\n");
|
|
||||||
throw_error(filename, "embedding-function", "FinnisSinclair or FinnisSinclairShiftedScaled");
|
|
||||||
}
|
|
||||||
printf("Notice! No embedding-function is specified, but potential has linear embedding, default embedding-function: FinnisSinclair would be assumed\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//hard-core energy cutoff repulsion
|
|
||||||
res = fscanf(fptr, " core energy-cutoff parameters:");
|
|
||||||
if (res != 0)
|
|
||||||
throw_error(filename, "core energy-cutoff parameters", "core energy-cutoff parameters: [par1] [par2]");
|
|
||||||
|
|
||||||
rho_core_cutoffs.init(nelements, "rho_core_cutoffs");
|
|
||||||
drho_core_cutoffs.init(nelements, "drho_core_cutoffs");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i) {
|
|
||||||
res = fscanf(fptr, "%s %s", buffer, buffer2);
|
|
||||||
if (res != 2)
|
|
||||||
throw_error(filename, "core energy-cutoff parameters",
|
|
||||||
"core energy-cutoff parameters: [rho_core_cut] [drho_core_cutoff] ...");
|
|
||||||
rho_core_cutoffs(mu_i) = stod_err(buffer, filename, "rho core cutoff",
|
|
||||||
"core energy-cutoff parameters: [rho_core_cut] [drho_core_cutoff] ...");
|
|
||||||
drho_core_cutoffs(mu_i) = stod_err(buffer2, filename, "drho_core_cutoff",
|
|
||||||
"core energy-cutoff parameters: [rho_core_cut] [drho_core_cutoff] ...");
|
|
||||||
}
|
|
||||||
|
|
||||||
// atom energy shift E0 (energy of isolated atom)
|
|
||||||
E0vals.init(nelements);
|
|
||||||
|
|
||||||
// reading "E0:"
|
|
||||||
res = fscanf(fptr, " E0: %s", buffer);
|
|
||||||
if (res == 0) {
|
|
||||||
//throw_error(filename, "E0", " E0: E0-species1 E0-species2 ...");
|
|
||||||
E0vals.fill(0.0);
|
|
||||||
} else {
|
|
||||||
double E0 = atof(buffer);
|
|
||||||
E0vals(0) = E0;
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu_i = 1; mu_i < nelements; ++mu_i) {
|
|
||||||
res = fscanf(fptr, " %lf", &E0);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "E0", " couldn't read one of the E0 values");
|
|
||||||
E0vals(mu_i) = E0;
|
|
||||||
}
|
|
||||||
res = fscanf(fptr, "\n");
|
|
||||||
if (res != 0)
|
|
||||||
printf("file %s : format seems broken near E0; trying to continue...\n", filename.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// check which radial basis we need to load
|
|
||||||
res = fscanf(fptr, " radbasename=%s\n", buffer);
|
|
||||||
if (res != 1) {
|
|
||||||
throw_error(filename, "radbasename", "rabbasename=ChebExpCos|ChebPow|ACE.jl.Basic");
|
|
||||||
} else {
|
|
||||||
radbasename = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// printf("radbasename = `%s`\n", radbasename.c_str());
|
|
||||||
if (radbasename == "ChebExpCos" | radbasename == "ChebPow") {
|
|
||||||
_load_radial_ACERadial(fptr, filename, radbasename);
|
|
||||||
} else if (radbasename == "ACE.jl.Basic") {
|
|
||||||
_load_radial_SHIPsBasic(fptr, filename, radbasename);
|
|
||||||
} else {
|
|
||||||
throw invalid_argument(
|
|
||||||
("File '" + filename + "': I don't know how to read radbasename = " + radbasename).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
res = fscanf(fptr, " rankmax=");
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "rankmax", "rankmax=[number]");
|
|
||||||
rankmax = stoi_err(buffer, filename, "rankmax", "rankmax=[number]");
|
|
||||||
|
|
||||||
res = fscanf(fptr, " ndensitymax=");
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "ndensitymax", "ndensitymax=[number]");
|
|
||||||
ndensitymax = stoi_err(buffer, filename, "ndensitymax", "ndensitymax=[number]");
|
|
||||||
|
|
||||||
// read the list of correlations to be put into the basis
|
|
||||||
//num_c_tilde_max
|
|
||||||
res = fscanf(fptr, " num_c_tilde_max=");
|
|
||||||
res = fscanf(fptr, "%s\n", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "num_c_tilde_max", "num_c_tilde_max=[number]");
|
|
||||||
num_ctilde_max = stol_err(buffer, filename, "num_c_tilde_max", "num_c_tilde_max=[number]");
|
|
||||||
|
|
||||||
res = fscanf(fptr, " num_ms_combinations_max=");
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "num_ms_combinations_max", "num_ms_combinations_max=[number]");
|
|
||||||
// throw invalid_argument(("File '" + filename + "': couldn't read num_ms_combinations_max").c_str());
|
|
||||||
num_ms_combinations_max = stol_err(buffer, filename, "num_ms_combinations_max", "num_ms_combinations_max=[number]");
|
|
||||||
|
|
||||||
//read total_basis_size_rank1
|
|
||||||
total_basis_size_rank1 = new SHORT_INT_TYPE[nelements];
|
|
||||||
basis_rank1 = new ACECTildeBasisFunction *[nelements];
|
|
||||||
res = fscanf(fptr, " total_basis_size_rank1: ");
|
|
||||||
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "total_basis_size_rank1", "total_basis_size_rank1: [size_ele1] [size_ele2] ...");
|
|
||||||
// throw invalid_argument(("File '" + filename + "': couldn't read total_basis_size_rank1").c_str());
|
|
||||||
total_basis_size_rank1[mu] = stoi_err(buffer, filename, "total_basis_size_rank1",
|
|
||||||
"total_basis_size_rank1: [size_ele1] [size_ele2] ...");
|
|
||||||
basis_rank1[mu] = new ACECTildeBasisFunction[total_basis_size_rank1[mu]];
|
|
||||||
}
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; mu++)
|
|
||||||
for (SHORT_INT_TYPE func_ind = 0; func_ind < total_basis_size_rank1[mu]; ++func_ind) {
|
|
||||||
fread_c_tilde_b_basis_func(fptr, basis_rank1[mu][func_ind]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//read total_basis_size
|
|
||||||
res = fscanf(fptr, " total_basis_size: ");
|
|
||||||
total_basis_size = new SHORT_INT_TYPE[nelements];
|
|
||||||
basis = new ACECTildeBasisFunction *[nelements];
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "total_basis_size", "total_basis_size: [size_ele1] [size_ele2] ...");
|
|
||||||
total_basis_size[mu] = stoi_err(buffer, filename, "total_basis_size",
|
|
||||||
"total_basis_size: [size_ele1] [size_ele2] ...");
|
|
||||||
basis[mu] = new ACECTildeBasisFunction[total_basis_size[mu]];
|
|
||||||
}
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; mu++)
|
|
||||||
for (SHORT_INT_TYPE func_ind = 0; func_ind < total_basis_size[mu]; ++func_ind) {
|
|
||||||
fread_c_tilde_b_basis_func(fptr, basis[mu][func_ind]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fptr);
|
|
||||||
|
|
||||||
// radial_functions->radbasename = radbasename;
|
|
||||||
radial_functions->setuplookupRadspline();
|
|
||||||
pack_flatten_basis();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::compute_array_sizes(ACECTildeBasisFunction **basis_rank1, ACECTildeBasisFunction **basis) {
|
|
||||||
//compute arrays sizes
|
|
||||||
rank_array_total_size_rank1 = 0;
|
|
||||||
//ms_array_total_size_rank1 = rank_array_total_size_rank1;
|
|
||||||
coeff_array_total_size_rank1 = 0;
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
if (total_basis_size_rank1[mu] > 0) {
|
|
||||||
rank_array_total_size_rank1 += total_basis_size_rank1[mu];
|
|
||||||
|
|
||||||
ACEAbstractBasisFunction &func = basis_rank1[mu][0];//TODO: get total density instead of density from first function
|
|
||||||
coeff_array_total_size_rank1 += total_basis_size_rank1[mu] * func.ndensity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rank_array_total_size = 0;
|
|
||||||
coeff_array_total_size = 0;
|
|
||||||
|
|
||||||
ms_array_total_size = 0;
|
|
||||||
max_dB_array_size = 0;
|
|
||||||
|
|
||||||
|
|
||||||
max_B_array_size = 0;
|
|
||||||
|
|
||||||
size_t cur_ms_size = 0;
|
|
||||||
size_t cur_ms_rank_size = 0;
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
|
|
||||||
cur_ms_size = 0;
|
|
||||||
cur_ms_rank_size = 0;
|
|
||||||
for (int func_ind = 0; func_ind < total_basis_size[mu]; ++func_ind) {
|
|
||||||
auto &func = basis[mu][func_ind];
|
|
||||||
rank_array_total_size += func.rank;
|
|
||||||
ms_array_total_size += func.rank * func.num_ms_combs;
|
|
||||||
coeff_array_total_size += func.ndensity * func.num_ms_combs;
|
|
||||||
|
|
||||||
cur_ms_size += func.num_ms_combs;
|
|
||||||
cur_ms_rank_size += func.rank * func.num_ms_combs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cur_ms_size > max_B_array_size)
|
|
||||||
max_B_array_size = cur_ms_size;
|
|
||||||
|
|
||||||
if (cur_ms_rank_size > max_dB_array_size)
|
|
||||||
max_dB_array_size = cur_ms_rank_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::_clean_basis_arrays() {
|
|
||||||
if (basis_rank1 != nullptr)
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
delete[] basis_rank1[mu];
|
|
||||||
basis_rank1[mu] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (basis != nullptr)
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
delete[] basis[mu];
|
|
||||||
basis[mu] = nullptr;
|
|
||||||
}
|
|
||||||
delete[] basis;
|
|
||||||
basis = nullptr;
|
|
||||||
|
|
||||||
delete[] basis_rank1;
|
|
||||||
basis_rank1 = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//pack into 1D array with all basis functions
|
|
||||||
void ACECTildeBasisSet::flatten_basis(C_tilde_full_basis_vector2d &mu0_ctilde_basis_vector) {
|
|
||||||
|
|
||||||
_clean_basis_arrays();
|
|
||||||
basis_rank1 = new ACECTildeBasisFunction *[nelements];
|
|
||||||
basis = new ACECTildeBasisFunction *[nelements];
|
|
||||||
|
|
||||||
delete[] total_basis_size_rank1;
|
|
||||||
delete[] total_basis_size;
|
|
||||||
total_basis_size_rank1 = new SHORT_INT_TYPE[nelements];
|
|
||||||
total_basis_size = new SHORT_INT_TYPE[nelements];
|
|
||||||
|
|
||||||
|
|
||||||
size_t tot_size_rank1 = 0;
|
|
||||||
size_t tot_size = 0;
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < this->nelements; ++mu) {
|
|
||||||
tot_size = 0;
|
|
||||||
tot_size_rank1 = 0;
|
|
||||||
|
|
||||||
for (auto &func: mu0_ctilde_basis_vector[mu]) {
|
|
||||||
if (func.rank == 1) tot_size_rank1 += 1;
|
|
||||||
else tot_size += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
total_basis_size_rank1[mu] = tot_size_rank1;
|
|
||||||
basis_rank1[mu] = new ACECTildeBasisFunction[tot_size_rank1];
|
|
||||||
|
|
||||||
total_basis_size[mu] = tot_size;
|
|
||||||
basis[mu] = new ACECTildeBasisFunction[tot_size];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < this->nelements; ++mu) {
|
|
||||||
size_t ind_rank1 = 0;
|
|
||||||
size_t ind = 0;
|
|
||||||
|
|
||||||
for (auto &func: mu0_ctilde_basis_vector[mu]) {
|
|
||||||
if (func.rank == 1) { //r=0, rank=1
|
|
||||||
basis_rank1[mu][ind_rank1] = func;
|
|
||||||
ind_rank1 += 1;
|
|
||||||
} else { //r>0, rank>1
|
|
||||||
basis[mu][ind] = func;
|
|
||||||
ind += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::_load_radial_ACERadial(FILE *fptr,
|
|
||||||
const string filename,
|
|
||||||
const string radbasename) {
|
|
||||||
int res;
|
|
||||||
char buffer[1024], buffer2[1024];
|
|
||||||
|
|
||||||
res = fscanf(fptr, " nradbase=");
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "nradbase", "nradbase=[number]");
|
|
||||||
// throw invalid_argument(("File '" + filename + "': couldn't read nradbase").c_str());
|
|
||||||
nradbase = stoi_err(buffer, filename, "nradbase", "nradbase=[number]");
|
|
||||||
|
|
||||||
res = fscanf(fptr, " nradmax=");
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "nradmax", "nradmax=[number]");
|
|
||||||
nradmax = stoi_err(buffer, filename, "nradmax", "nradmax=[number]");
|
|
||||||
|
|
||||||
res = fscanf(fptr, " cutoffmax=");
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "cutoffmax", "cutoffmax=[number]");
|
|
||||||
cutoffmax = stod_err(buffer, filename, "cutoffmax", "cutoffmax=[number]");
|
|
||||||
|
|
||||||
|
|
||||||
res = fscanf(fptr, " deltaSplineBins=");
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "deltaSplineBins", "deltaSplineBins=[spline density, Angstroms]");
|
|
||||||
// throw invalid_argument(("File '" + filename + "': couldn't read ntot").c_str());
|
|
||||||
deltaSplineBins = stod_err(buffer, filename, "deltaSplineBins", "deltaSplineBins=[spline density, Angstroms]");
|
|
||||||
|
|
||||||
|
|
||||||
if (radial_functions == nullptr)
|
|
||||||
radial_functions = new ACERadialFunctions(nradbase, lmax, nradmax,
|
|
||||||
deltaSplineBins,
|
|
||||||
nelements,
|
|
||||||
cutoffmax, radbasename);
|
|
||||||
else
|
|
||||||
radial_functions->init(nradbase, lmax, nradmax,
|
|
||||||
deltaSplineBins,
|
|
||||||
nelements,
|
|
||||||
cutoffmax, radbasename);
|
|
||||||
|
|
||||||
|
|
||||||
//hard-core repulsion
|
|
||||||
res = fscanf(fptr, " core repulsion parameters:");
|
|
||||||
if (res != 0)
|
|
||||||
throw_error(filename, "core repulsion parameters", "core repulsion parameters: [prehc lambdahc] ...");
|
|
||||||
// throw invalid_argument(("File '" + filename + "': couldn't read core repulsion parameters").c_str());
|
|
||||||
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j) {
|
|
||||||
res = fscanf(fptr, "%s %s", buffer, buffer2);
|
|
||||||
if (res != 2)
|
|
||||||
throw_error(filename, "core repulsion parameters", "core repulsion parameters: [prehc lambdahc] ...");
|
|
||||||
radial_functions->prehc(mu_i, mu_j) = stod_err(buffer, filename, "core repulsion parameters",
|
|
||||||
"core repulsion parameters: [prehc lambdahc] ...");
|
|
||||||
radial_functions->lambdahc(mu_i, mu_j) = stod_err(buffer2, filename, "core repulsion parameters",
|
|
||||||
"core repulsion parameters: [prehc lambdahc] ...");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//read radial functions parameter
|
|
||||||
res = fscanf(fptr, " radparameter=");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j) {
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "radparameter", "radparameter=[param_ele1] [param_ele2]");
|
|
||||||
radial_functions->lambda(mu_i, mu_j) = stod_err(buffer, filename, "radparameter",
|
|
||||||
"radparameter=[param_ele1] [param_ele2]");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
res = fscanf(fptr, " cutoff=");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j) {
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "cutoff", "cutoff=[param_ele1] [param_ele2]");
|
|
||||||
radial_functions->cut(mu_i, mu_j) = stod_err(buffer, filename, "cutoff",
|
|
||||||
"cutoff=[param_ele1] [param_ele2]");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
res = fscanf(fptr, " dcut=");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j) {
|
|
||||||
res = fscanf(fptr, " %s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "dcut", "dcut=[param_ele1] [param_ele2]");
|
|
||||||
radial_functions->dcut(mu_i, mu_j) = stod_err(buffer, filename, "dcut", "dcut=[param_ele1] [param_ele2]");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
res = fscanf(fptr, " crad=");
|
|
||||||
for (SPECIES_TYPE mu_i = 0; mu_i < nelements; ++mu_i)
|
|
||||||
for (SPECIES_TYPE mu_j = 0; mu_j < nelements; ++mu_j)
|
|
||||||
for (NS_TYPE k = 0; k < nradbase; k++)
|
|
||||||
for (NS_TYPE n = 0; n < nradmax; n++)
|
|
||||||
for (LS_TYPE l = 0; l <= lmax; l++) {
|
|
||||||
res = fscanf(fptr, "%s", buffer);
|
|
||||||
if (res != 1)
|
|
||||||
throw_error(filename, "crad", "crad=[crad_]...[crad_knl]: nradbase*nrad*(l+1) times");
|
|
||||||
radial_functions->crad(mu_i, mu_j, n, l, k) = stod_err(buffer, filename, "crad",
|
|
||||||
"crad=[crad_]...[crad_knl]: nradbase*nrad*(l+1) times");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeBasisSet::_load_radial_SHIPsBasic(FILE *fptr,
|
|
||||||
const string filename,
|
|
||||||
const string radbasename) {
|
|
||||||
// create a radial basis object, and read it from the file pointer
|
|
||||||
SHIPsRadialFunctions *ships_radial_functions = new SHIPsRadialFunctions();
|
|
||||||
ships_radial_functions->fread(fptr);
|
|
||||||
|
|
||||||
//mimic ships_radial_functions to ACERadialFunctions
|
|
||||||
ships_radial_functions->nradial = ships_radial_functions->get_maxn();
|
|
||||||
ships_radial_functions->nradbase = ships_radial_functions->get_maxn();
|
|
||||||
|
|
||||||
nradbase = ships_radial_functions->get_maxn();
|
|
||||||
nradmax = ships_radial_functions->get_maxn();
|
|
||||||
cutoffmax = ships_radial_functions->get_rcut();
|
|
||||||
deltaSplineBins = 0.001;
|
|
||||||
|
|
||||||
ships_radial_functions->init(nradbase, lmax, nradmax,
|
|
||||||
deltaSplineBins,
|
|
||||||
nelements,
|
|
||||||
cutoffmax, radbasename);
|
|
||||||
|
|
||||||
|
|
||||||
if (radial_functions) delete radial_functions;
|
|
||||||
radial_functions = ships_radial_functions;
|
|
||||||
radial_functions->prehc.fill(0);
|
|
||||||
radial_functions->lambdahc.fill(1);
|
|
||||||
radial_functions->lambda.fill(0);
|
|
||||||
|
|
||||||
|
|
||||||
radial_functions->cut.fill(ships_radial_functions->get_rcut());
|
|
||||||
radial_functions->dcut.fill(0);
|
|
||||||
|
|
||||||
radial_functions->crad.fill(0);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,155 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 1.04.20.
|
|
||||||
|
|
||||||
#ifndef ACE_C_BASIS_H
|
|
||||||
#define ACE_C_BASIS_H
|
|
||||||
|
|
||||||
#include "ace_flatten_basis.h"
|
|
||||||
|
|
||||||
typedef vector<vector<ACECTildeBasisFunction>> C_tilde_full_basis_vector2d;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ACE basis set of C-tilde basis functions
|
|
||||||
*/
|
|
||||||
class ACECTildeBasisSet : public ACEFlattenBasisSet {
|
|
||||||
public:
|
|
||||||
|
|
||||||
ACECTildeBasisFunction **basis_rank1 = nullptr; ///< two-dimensional array of first-rank basis function with indices: [species index][func index]
|
|
||||||
ACECTildeBasisFunction **basis = nullptr; ///< two-dimensional array of higher rank basis function with indices: [species index][func index]
|
|
||||||
|
|
||||||
DOUBLE_TYPE *full_c_tildes_rank1 = nullptr; ///< C_tilde coefficients contiguous package, size: coeff_array_total_size_rank1
|
|
||||||
DOUBLE_TYPE *full_c_tildes = nullptr; ///< C_tilde coefficients contiguous package, size: coeff_array_total_size
|
|
||||||
|
|
||||||
//TODO: remove?
|
|
||||||
SHORT_INT_TYPE num_ctilde_max = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor
|
|
||||||
*/
|
|
||||||
ACECTildeBasisSet() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor from .ace file
|
|
||||||
*/
|
|
||||||
ACECTildeBasisSet(const string filename);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor (see. Rule of Three)
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
ACECTildeBasisSet(const ACECTildeBasisSet &other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* operator= (see. Rule of Three)
|
|
||||||
* @param other
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ACECTildeBasisSet &operator=(const ACECTildeBasisSet &other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor (see. Rule of Three)
|
|
||||||
*/
|
|
||||||
~ACECTildeBasisSet() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleaning dynamic memory of the class (see. Rule of Three)
|
|
||||||
*/
|
|
||||||
void _clean() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copying and cleaning dynamic memory of the class (see. Rule of Three)
|
|
||||||
* @param src
|
|
||||||
*/
|
|
||||||
void _copy_dynamic_memory(const ACECTildeBasisSet &src);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copying scalar variables
|
|
||||||
* @param src
|
|
||||||
*/
|
|
||||||
void _copy_scalar_memory(const ACECTildeBasisSet &src);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean contiguous arrays (full_c_tildes_rank1, full_c_tildes) and those of base class
|
|
||||||
*/
|
|
||||||
void _clean_contiguous_arrays() override ;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save potential to .ace file
|
|
||||||
* @param filename .ace file name
|
|
||||||
*/
|
|
||||||
void save(const string &filename) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load potential from .ace
|
|
||||||
* @param filename .ace file name
|
|
||||||
*/
|
|
||||||
void load(const string filename) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the ACE type radial basis
|
|
||||||
*/
|
|
||||||
void _load_radial_ACERadial(FILE *fptr,
|
|
||||||
const string filename,
|
|
||||||
const string radbasename);
|
|
||||||
|
|
||||||
void _load_radial_SHIPsBasic(FILE * fptr,
|
|
||||||
const string filename,
|
|
||||||
const string radbasename );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-pack the constituent dynamic arrays of all basis functions in contiguous arrays
|
|
||||||
*/
|
|
||||||
void pack_flatten_basis() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes flatten array sizes
|
|
||||||
* @param basis_rank1 two-dimensional array of first-rank ACECTildeBasisFunctions
|
|
||||||
* @param basis two-dimensional array of higher-rank ACECTildeBasisFunctions
|
|
||||||
*/
|
|
||||||
void compute_array_sizes(ACECTildeBasisFunction** basis_rank1, ACECTildeBasisFunction** basis);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean basis arrays 'basis_rank1' and 'basis'
|
|
||||||
*/
|
|
||||||
void _clean_basis_arrays();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pack two-dimensional vector of ACECTildeBasisFunction into 1D dynami array with all basis functions
|
|
||||||
* @param mu0_ctilde_basis_vector vector<vector<ACECTildeBasisFunction>>
|
|
||||||
*/
|
|
||||||
void flatten_basis(C_tilde_full_basis_vector2d& mu0_ctilde_basis_vector);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Empty stub implementation
|
|
||||||
*/
|
|
||||||
void flatten_basis() override{};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //ACE_C_BASIS_H
|
|
|
@ -1,251 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 26.02.20.
|
|
||||||
|
|
||||||
#ifndef ACE_C_BASISFUNCTION_H
|
|
||||||
#define ACE_C_BASISFUNCTION_H
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "ace_types.h"
|
|
||||||
|
|
||||||
//macros for copying the member-array from "other" object for C-tilde and B-basis
|
|
||||||
#define basis_mem_copy(other, array, size, type) if(other.array) { \
|
|
||||||
if(!is_proxy) delete[] array;\
|
|
||||||
array = new type[(size)];\
|
|
||||||
is_proxy = false;\
|
|
||||||
memcpy(array, other.array, (size) * sizeof(type));\
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract basis function, that stores general quantities
|
|
||||||
*/
|
|
||||||
struct ACEAbstractBasisFunction {
|
|
||||||
/**
|
|
||||||
* flattened array of computed combinations of (m1, m2, ..., m_rank)
|
|
||||||
* which have non-zero general Clebsch-Gordan coefficient:
|
|
||||||
* \f$ \mathbf{m}_1, \dots, \mathbf{m}_\mathrm{num ms combs}\f$ =
|
|
||||||
* \f$ (m_1, m_2, \dots, m_{rank})_1, \dots, (m_1, m_2, \dots, m_{rank})_{\mathrm{num ms combs}} \f$,
|
|
||||||
* size = num_ms_combs * rank,
|
|
||||||
* effective shape: [num_ms_combs][rank]
|
|
||||||
*/
|
|
||||||
MS_TYPE *ms_combs = nullptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* species types of neighbours atoms \f$ \mathbf{\mu} = (\mu_1, \mu_2, \dots, \mu_{rank}) \f$,
|
|
||||||
* should be lexicographically sorted,
|
|
||||||
* size = rank,
|
|
||||||
* effective shape: [rank]
|
|
||||||
*/
|
|
||||||
SPECIES_TYPE *mus = nullptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* indices for radial part \f$ \mathbf{n} = (n_1, n_2, \dots, n_{rank}) \f$,
|
|
||||||
* should be lexicographically sorted,
|
|
||||||
* size = rank,
|
|
||||||
* effective shape: [rank]
|
|
||||||
*/
|
|
||||||
NS_TYPE *ns = nullptr;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* indices for radial part \f$ \mathbf{l} = (l_1, l_2, \dots, l_{rank}) \f$,
|
|
||||||
* should be lexicographically sorted,
|
|
||||||
* size = rank,
|
|
||||||
* effective shape: [rank]
|
|
||||||
*/
|
|
||||||
LS_TYPE *ls = nullptr;
|
|
||||||
|
|
||||||
SHORT_INT_TYPE num_ms_combs = 0; ///< number of different ms-combinations
|
|
||||||
|
|
||||||
RANK_TYPE rank = 0; ///< number of atomic base functions "A"s in basis function product B
|
|
||||||
|
|
||||||
DENSITY_TYPE ndensity = 0; ///< number of densities
|
|
||||||
|
|
||||||
SPECIES_TYPE mu0 = 0; ///< species type of central atom
|
|
||||||
|
|
||||||
/**
|
|
||||||
* whether ms array contains only "non-negative" ms-combinations.
|
|
||||||
* positive ms-combination is when the first non-zero m is positive (0 1 -1)
|
|
||||||
* negative ms-combination is when the first non-zero m is negative (0 -1 1)
|
|
||||||
*/
|
|
||||||
bool is_half_ms_basis = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* flag, whether object is "owner" (i.e. responsible for memory cleaning) of
|
|
||||||
* the ms, ns, ls, mus and other dynamically allocated arrases or just a proxy for them
|
|
||||||
*/
|
|
||||||
bool is_proxy = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copying static and dynamic memory variables from another ACEAbstractBasisFunction.
|
|
||||||
* Always copy the dynamic memory, even if the source is a proxy object
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
virtual void _copy_from(const ACEAbstractBasisFunction &other) {
|
|
||||||
rank = other.rank;
|
|
||||||
ndensity = other.ndensity;
|
|
||||||
mu0 = other.mu0;
|
|
||||||
num_ms_combs = other.num_ms_combs;
|
|
||||||
is_half_ms_basis = other.is_half_ms_basis;
|
|
||||||
is_proxy = false;
|
|
||||||
|
|
||||||
basis_mem_copy(other, mus, rank, SPECIES_TYPE)
|
|
||||||
basis_mem_copy(other, ns, rank, NS_TYPE)
|
|
||||||
basis_mem_copy(other, ls, rank, LS_TYPE)
|
|
||||||
basis_mem_copy(other, ms_combs, num_ms_combs * rank, MS_TYPE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean the dynamically allocated memory if object is responsible for it
|
|
||||||
*/
|
|
||||||
virtual void _clean() {
|
|
||||||
//release memory if the structure is not proxy
|
|
||||||
if (!is_proxy) {
|
|
||||||
delete[] mus;
|
|
||||||
delete[] ns;
|
|
||||||
delete[] ls;
|
|
||||||
delete[] ms_combs;
|
|
||||||
}
|
|
||||||
|
|
||||||
mus = nullptr;
|
|
||||||
ns = nullptr;
|
|
||||||
ls = nullptr;
|
|
||||||
ms_combs = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Representation of C-tilde basis function, i.e. the function that is summed up over a group of B-functions
|
|
||||||
* that differs only by intermediate coupling orbital moment \f$ L \f$ and coefficients.
|
|
||||||
*/
|
|
||||||
struct ACECTildeBasisFunction : public ACEAbstractBasisFunction {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* c_tilde coefficients for all densities,
|
|
||||||
* size = num_ms_combs*ndensity,
|
|
||||||
* effective shape [num_ms_combs][ndensity]
|
|
||||||
*/
|
|
||||||
DOUBLE_TYPE *ctildes = nullptr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Default constructor
|
|
||||||
*/
|
|
||||||
ACECTildeBasisFunction() = default;
|
|
||||||
|
|
||||||
// Because the ACECTildeBasisFunction contains dynamically allocated arrays, the Rule of Three should be
|
|
||||||
// fulfilled, i.e. copy constructor (copy the dynamic arrays), operator= (release previous arrays and
|
|
||||||
// copy the new dynamic arrays) and destructor (release all dynamically allocated memory)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor, to fulfill the Rule of Three.
|
|
||||||
* Always copy the dynamic memory, even if the source is a proxy object.
|
|
||||||
*/
|
|
||||||
ACECTildeBasisFunction(const ACECTildeBasisFunction &other) {
|
|
||||||
_copy_from(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* operator=, to fulfill the Rule of Three.
|
|
||||||
* Always copy the dynamic memory, even if the source is a proxy object
|
|
||||||
*/
|
|
||||||
ACECTildeBasisFunction &operator=(const ACECTildeBasisFunction &other) {
|
|
||||||
_clean();
|
|
||||||
_copy_from(other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
~ACECTildeBasisFunction() {
|
|
||||||
_clean();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy from another object, always copy the memory, even if the source is a proxy object
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
void _copy_from(const ACECTildeBasisFunction &other) {
|
|
||||||
ACEAbstractBasisFunction::_copy_from(other);
|
|
||||||
is_proxy = false;
|
|
||||||
basis_mem_copy(other, ctildes, num_ms_combs * ndensity, DOUBLE_TYPE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean the dynamically allocated memory if object is responsible for it
|
|
||||||
*/
|
|
||||||
void _clean() override {
|
|
||||||
ACEAbstractBasisFunction::_clean();
|
|
||||||
//release memory if the structure is not proxy
|
|
||||||
if (!is_proxy) {
|
|
||||||
delete[] ctildes;
|
|
||||||
}
|
|
||||||
ctildes = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print the information about basis function to cout, in order to ease the output redirection.
|
|
||||||
*/
|
|
||||||
void print() const {
|
|
||||||
using namespace std;
|
|
||||||
cout << "ACECTildeBasisFunction: ndensity= " << (int) this->ndensity << ", mu0 = " << (int) this->mu0 << " ";
|
|
||||||
cout << " mus=(";
|
|
||||||
for (RANK_TYPE r = 0; r < this->rank; r++)
|
|
||||||
cout << (int) this->mus[r] << " ";
|
|
||||||
cout << "), ns=(";
|
|
||||||
for (RANK_TYPE r = 0; r < this->rank; r++)
|
|
||||||
cout << this->ns[r] << " ";
|
|
||||||
cout << "), ls=(";
|
|
||||||
for (RANK_TYPE r = 0; r < this->rank; r++)
|
|
||||||
cout << this->ls[r] << " ";
|
|
||||||
|
|
||||||
cout << "), " << this->num_ms_combs << " m_s combinations: {" << endl;
|
|
||||||
|
|
||||||
for (int i = 0; i < this->num_ms_combs; i++) {
|
|
||||||
cout << "\t< ";
|
|
||||||
for (RANK_TYPE r = 0; r < this->rank; r++)
|
|
||||||
cout << this->ms_combs[i * this->rank + r] << " ";
|
|
||||||
cout << " >: c_tilde=";
|
|
||||||
for (DENSITY_TYPE p = 0; p < this->ndensity; ++p)
|
|
||||||
cout << " " << this->ctildes[i * this->ndensity + p] << " ";
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
if (this->is_proxy)
|
|
||||||
cout << "proxy ";
|
|
||||||
if (this->is_half_ms_basis)
|
|
||||||
cout << "half_ms_basis";
|
|
||||||
cout << "}" << endl;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //ACE_C_BASISFUNCTION_H
|
|
|
@ -1,266 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 26.02.20.
|
|
||||||
|
|
||||||
#ifndef ACE_COMPLEX_H
|
|
||||||
#define ACE_COMPLEX_H
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
A custom data structure for complex numbers and overloaded operations with them.
|
|
||||||
*/
|
|
||||||
struct ACEComplex {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
Double, real part of the complex number
|
|
||||||
*/
|
|
||||||
DOUBLE_TYPE real;
|
|
||||||
/**
|
|
||||||
Double, imaginary part of the complex number
|
|
||||||
*/
|
|
||||||
DOUBLE_TYPE img;
|
|
||||||
|
|
||||||
ACEComplex &operator=(const ACEComplex &rhs) = default;
|
|
||||||
|
|
||||||
ACEComplex &operator=(const DOUBLE_TYPE &rhs) {
|
|
||||||
this->real = rhs;
|
|
||||||
this->img = 0.;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Overloading of arithmetical operator += ACEComplex
|
|
||||||
*/
|
|
||||||
ACEComplex &operator+=(const ACEComplex &rhs) {
|
|
||||||
this->real += rhs.real;
|
|
||||||
this->img += rhs.img;
|
|
||||||
return *this; // return the result by reference
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Overloading of arithmetical operator += DOUBLE_TYPE
|
|
||||||
*/
|
|
||||||
ACEComplex &operator+=(const DOUBLE_TYPE &rhs) {
|
|
||||||
this->real += rhs;
|
|
||||||
return *this; // return the result by reference
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Overloading of arithmetical operator *= DOUBLE_TYPE
|
|
||||||
*/
|
|
||||||
ACEComplex &operator*=(const DOUBLE_TYPE &rhs) {
|
|
||||||
this->real *= rhs;
|
|
||||||
this->img *= rhs;
|
|
||||||
return *this; // return the result by reference
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Overloading of arithmetical operator *= ACEComplex
|
|
||||||
*/
|
|
||||||
ACEComplex &operator*=(const ACEComplex &rhs) {
|
|
||||||
DOUBLE_TYPE old_real = this->real;
|
|
||||||
this->real = old_real * rhs.real - this->img * rhs.img;
|
|
||||||
this->img = old_real * rhs.img + this->img * rhs.real;
|
|
||||||
return *this; // return the result by reference
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Overloading of arithmetical operator * ACEComplex
|
|
||||||
*/
|
|
||||||
ACEComplex operator*(const ACEComplex &cm2) const {
|
|
||||||
ACEComplex res{real * cm2.real - img * cm2.img,
|
|
||||||
real * cm2.img + img * cm2.real};
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return complex conjugated copy of itself
|
|
||||||
*/
|
|
||||||
ACEComplex conjugated() const {
|
|
||||||
ACEComplex res{real, -img};
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Complex conjugate itself inplace
|
|
||||||
*/
|
|
||||||
void conjugate() {
|
|
||||||
img = -img;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Multiplication by ACEComplex and return real-part only
|
|
||||||
*/
|
|
||||||
DOUBLE_TYPE real_part_product(const ACEComplex &cm2) const {
|
|
||||||
return real * cm2.real - img * cm2.img;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Multiplication by DOUBLE_TYPE and return real-part only
|
|
||||||
*/
|
|
||||||
DOUBLE_TYPE real_part_product(const DOUBLE_TYPE &cm2) const {
|
|
||||||
return real * cm2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator * by DOUBLE_TYPE
|
|
||||||
*/
|
|
||||||
ACEComplex operator*(const DOUBLE_TYPE &cm2) const {
|
|
||||||
ACEComplex res{real * cm2,
|
|
||||||
img * cm2};
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator + ACEComplex
|
|
||||||
*/
|
|
||||||
ACEComplex operator+(const ACEComplex &cm2) const {
|
|
||||||
ACEComplex res{real + cm2.real,
|
|
||||||
img + cm2.img};
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator + with DOUBLE_TYPE
|
|
||||||
*/
|
|
||||||
ACEComplex operator+(const DOUBLE_TYPE &cm2) const {
|
|
||||||
ACEComplex res{real + cm2, img};
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator == ACEComplex
|
|
||||||
*/
|
|
||||||
bool operator==(const ACEComplex &c2) const {
|
|
||||||
return (real == c2.real) && (img == c2.img);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator == DOUBLE_TYPE
|
|
||||||
*/
|
|
||||||
bool operator==(const DOUBLE_TYPE &d2) const {
|
|
||||||
return (real == d2) && (img == 0.);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator != ACEComplex
|
|
||||||
*/
|
|
||||||
bool operator!=(const ACEComplex &c2) const {
|
|
||||||
return (real != c2.real) || (img != c2.img);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator != DOUBLE_TYPE
|
|
||||||
*/
|
|
||||||
bool operator!=(const DOUBLE_TYPE &d2) const {
|
|
||||||
return (real != d2) || (img != 0.);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* double * complex for commutativity with complex * double
|
|
||||||
*/
|
|
||||||
inline ACEComplex operator*(const DOUBLE_TYPE &real, const ACEComplex &cm) {
|
|
||||||
return cm * real;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* double + complex for commutativity with complex + double
|
|
||||||
*/
|
|
||||||
inline ACEComplex operator+(const DOUBLE_TYPE &real, const ACEComplex &cm) {
|
|
||||||
return cm + real;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
A structure to store the derivative of \f$ Y_{lm} \f$
|
|
||||||
*/
|
|
||||||
struct ACEDYcomponent {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
complex, contains the three components of derivative of Ylm,
|
|
||||||
\f$ \frac{dY_{lm}}{dx}, \frac{dY_{lm}}{dy} and \frac{dY_{lm}}{dz}\f$
|
|
||||||
*/
|
|
||||||
ACEComplex a[3];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator*= DOUBLE_TYPE
|
|
||||||
*/
|
|
||||||
ACEDYcomponent &operator*=(const DOUBLE_TYPE &rhs) {
|
|
||||||
this->a[0] *= rhs;
|
|
||||||
this->a[1] *= rhs;
|
|
||||||
this->a[2] *= rhs;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator * ACEComplex
|
|
||||||
*/
|
|
||||||
ACEDYcomponent operator*(const ACEComplex &rhs) const {
|
|
||||||
ACEDYcomponent res;
|
|
||||||
res.a[0] = this->a[0] * rhs;
|
|
||||||
res.a[1] = this->a[1] * rhs;
|
|
||||||
res.a[2] = this->a[2] * rhs;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overloading of arithmetical operator * DOUBLE_TYPE
|
|
||||||
*/
|
|
||||||
ACEDYcomponent operator*(const DOUBLE_TYPE &rhs) const {
|
|
||||||
ACEDYcomponent res;
|
|
||||||
res.a[0] = this->a[0] * rhs;
|
|
||||||
res.a[1] = this->a[1] * rhs;
|
|
||||||
res.a[2] = this->a[2] * rhs;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return conjugated copy of itself
|
|
||||||
*/
|
|
||||||
ACEDYcomponent conjugated() const {
|
|
||||||
ACEDYcomponent res;
|
|
||||||
res.a[0] = this->a[0].conjugated();
|
|
||||||
res.a[1] = this->a[1].conjugated();
|
|
||||||
res.a[2] = this->a[2].conjugated();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Conjugated itself in-place
|
|
||||||
*/
|
|
||||||
void conjugate() {
|
|
||||||
this->a[0].conjugate();
|
|
||||||
this->a[1].conjugate();
|
|
||||||
this->a[2].conjugate();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //ACE_COMPLEX_H
|
|
|
@ -1,249 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 11.01.20.
|
|
||||||
#ifndef ACE_CONTIGUOUSARRAYND_H
|
|
||||||
#define ACE_CONTIGUOUSARRAYND_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "ace_types.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common predecessor class to represent multidimensional array of type T
|
|
||||||
* and store it in memory contiguous form
|
|
||||||
*
|
|
||||||
* @tparam T data type
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
class ContiguousArrayND {
|
|
||||||
protected:
|
|
||||||
T *data = nullptr; ///< pointer to contiguous data
|
|
||||||
size_t size = 0; ///< total array size
|
|
||||||
string array_name = "Array"; ///<array name
|
|
||||||
bool is_proxy_ = false; ///< array is proxy (wrapper) and not owner of the memory
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default empty constructor
|
|
||||||
*/
|
|
||||||
ContiguousArrayND() = default;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor with array name
|
|
||||||
* @param array_name name of array (for error logging)
|
|
||||||
*/
|
|
||||||
ContiguousArrayND(string array_name) : array_name(array_name) {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor
|
|
||||||
* @param other other ContiguousArrayND
|
|
||||||
*/
|
|
||||||
ContiguousArrayND(const ContiguousArrayND &other) : array_name(other.array_name), size(other.size), is_proxy_(other.is_proxy_) {
|
|
||||||
#ifdef MULTIARRAY_LIFE_CYCLE
|
|
||||||
cout<<array_name<<"::copy constructor"<<endl;
|
|
||||||
#endif
|
|
||||||
if(!is_proxy_) { //if not the proxy, then copy the values
|
|
||||||
if (size > 0) {
|
|
||||||
data = new T[size];
|
|
||||||
for (size_t ind = 0; ind < size; ind++)
|
|
||||||
data[ind] = other.data[ind];
|
|
||||||
}
|
|
||||||
} else { //is proxy, then copy the pointer
|
|
||||||
data = other.data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overload operator=
|
|
||||||
* @param other another ContiguousArrayND
|
|
||||||
* @return itself
|
|
||||||
*/
|
|
||||||
|
|
||||||
ContiguousArrayND &operator=(const ContiguousArrayND &other) {
|
|
||||||
#ifdef MULTIARRAY_LIFE_CYCLE
|
|
||||||
cout<<array_name<<"::operator="<<endl;
|
|
||||||
#endif
|
|
||||||
if (this != &other) {
|
|
||||||
array_name = other.array_name;
|
|
||||||
size = other.size;
|
|
||||||
is_proxy_ = other.is_proxy_;
|
|
||||||
if(!is_proxy_) { //if not the proxy, then copy the values
|
|
||||||
if (size > 0) {
|
|
||||||
|
|
||||||
if(data!=nullptr) delete[] data;
|
|
||||||
data = new T[size];
|
|
||||||
|
|
||||||
for (size_t ind = 0; ind < size; ind++)
|
|
||||||
data[ind] = other.data[ind];
|
|
||||||
}
|
|
||||||
} else { //is proxy, then copy the pointer
|
|
||||||
data = other.data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: make destructor virtual, check the destructors in inherited classes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
~ContiguousArrayND() {
|
|
||||||
#ifdef MULTIARRAY_LIFE_CYCLE
|
|
||||||
cout<<array_name<<"::~destructor"<<endl;
|
|
||||||
#endif
|
|
||||||
if(! is_proxy_) {
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set array name
|
|
||||||
* @param name array name
|
|
||||||
*/
|
|
||||||
void set_array_name(const string &name) {
|
|
||||||
this->array_name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get total number of elements in array (its size)
|
|
||||||
* @return array size
|
|
||||||
*/
|
|
||||||
size_t get_size() const {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fill array with value
|
|
||||||
* @param value value to fill
|
|
||||||
*/
|
|
||||||
void fill(T value) {
|
|
||||||
for (size_t ind = 0; ind < size; ind++)
|
|
||||||
data[ind] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get array data at absolute index ind for reading
|
|
||||||
* @param ind absolute index
|
|
||||||
* @return array value
|
|
||||||
*/
|
|
||||||
inline const T &get_data(size_t ind) const {
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
if ((ind < 0) | (ind >= size)) {
|
|
||||||
printf("%s: get_data ind=%d out of range (0, %d)\n", array_name, ind, size);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return data[ind];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get array data at absolute index ind for writing
|
|
||||||
* @param ind absolute index
|
|
||||||
* @return array value
|
|
||||||
*/
|
|
||||||
inline T &get_data(size_t ind) {
|
|
||||||
#ifdef MULTIARRAY_INDICES_CHECK
|
|
||||||
if ((ind < 0) | (ind >= size)) {
|
|
||||||
printf("%s: get_data ind=%ld out of range (0, %ld)\n", array_name.c_str(), ind, size);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return data[ind];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get array data pointer
|
|
||||||
* @return data array pointer
|
|
||||||
*/
|
|
||||||
inline T* get_data() const {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overload comparison operator==
|
|
||||||
* Compare the total size and array values elementwise.
|
|
||||||
*
|
|
||||||
* @param other another array
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool operator==(const ContiguousArrayND &other) const {
|
|
||||||
if (this->size != other.size)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < this->size; ++i)
|
|
||||||
if (this->data[i] != other.data[i])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert to flatten vector<T> container
|
|
||||||
* @return vector container
|
|
||||||
*/
|
|
||||||
vector<T> to_flatten_vector() const {
|
|
||||||
vector<T> res;
|
|
||||||
|
|
||||||
res.resize(size);
|
|
||||||
size_t vec_ind = 0;
|
|
||||||
|
|
||||||
for (int vec_ind = 0; vec_ind < size; vec_ind++)
|
|
||||||
res.at(vec_ind) = data[vec_ind];
|
|
||||||
|
|
||||||
return res;
|
|
||||||
} // end to_flatten_vector()
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set values from flatten vector<T> container
|
|
||||||
* @param vec container
|
|
||||||
*/
|
|
||||||
void set_flatten_vector(const vector<T> &vec) {
|
|
||||||
if (vec.size() != size)
|
|
||||||
throw std::invalid_argument("Flatten vector size is not consistent with expected size");
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
|
||||||
data[i] = vec[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_proxy(){
|
|
||||||
return is_proxy_;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //ACE_CONTIGUOUSARRAYND_H
|
|
|
@ -1,660 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 31.01.20.
|
|
||||||
|
|
||||||
#include "ace_evaluator.h"
|
|
||||||
|
|
||||||
#include "ace_abstract_basis.h"
|
|
||||||
#include "ace_types.h"
|
|
||||||
|
|
||||||
void ACEEvaluator::init(ACEAbstractBasisSet *basis_set) {
|
|
||||||
A.init(basis_set->nelements, basis_set->nradmax + 1, basis_set->lmax + 1, "A");
|
|
||||||
A_rank1.init(basis_set->nelements, basis_set->nradbase, "A_rank1");
|
|
||||||
|
|
||||||
rhos.init(basis_set->ndensitymax + 1, "rhos"); // +1 density for core repulsion
|
|
||||||
dF_drho.init(basis_set->ndensitymax + 1, "dF_drho"); // +1 density for core repulsion
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEEvaluator::init_timers() {
|
|
||||||
loop_over_neighbour_timer.init();
|
|
||||||
forces_calc_loop_timer.init();
|
|
||||||
forces_calc_neighbour_timer.init();
|
|
||||||
energy_calc_timer.init();
|
|
||||||
per_atom_calc_timer.init();
|
|
||||||
total_time_calc_timer.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
//================================================================================================================
|
|
||||||
|
|
||||||
void ACECTildeEvaluator::set_basis(ACECTildeBasisSet &bas) {
|
|
||||||
basis_set = &bas;
|
|
||||||
init(basis_set);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeEvaluator::init(ACECTildeBasisSet *basis_set) {
|
|
||||||
|
|
||||||
ACEEvaluator::init(basis_set);
|
|
||||||
|
|
||||||
|
|
||||||
weights.init(basis_set->nelements, basis_set->nradmax + 1, basis_set->lmax + 1,
|
|
||||||
"weights");
|
|
||||||
|
|
||||||
weights_rank1.init(basis_set->nelements, basis_set->nradbase, "weights_rank1");
|
|
||||||
|
|
||||||
|
|
||||||
DG_cache.init(1, basis_set->nradbase, "DG_cache");
|
|
||||||
DG_cache.fill(0);
|
|
||||||
|
|
||||||
R_cache.init(1, basis_set->nradmax, basis_set->lmax + 1, "R_cache");
|
|
||||||
R_cache.fill(0);
|
|
||||||
|
|
||||||
DR_cache.init(1, basis_set->nradmax, basis_set->lmax + 1, "DR_cache");
|
|
||||||
DR_cache.fill(0);
|
|
||||||
|
|
||||||
Y_cache.init(1, basis_set->lmax + 1, "Y_cache");
|
|
||||||
Y_cache.fill({0, 0});
|
|
||||||
|
|
||||||
DY_cache.init(1, basis_set->lmax + 1, "dY_dense_cache");
|
|
||||||
DY_cache.fill({0.});
|
|
||||||
|
|
||||||
//hard-core repulsion
|
|
||||||
DCR_cache.init(1, "DCR_cache");
|
|
||||||
DCR_cache.fill(0);
|
|
||||||
dB_flatten.init(basis_set->max_dB_array_size, "dB_flatten");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECTildeEvaluator::resize_neighbours_cache(int max_jnum) {
|
|
||||||
if(basis_set== nullptr) {
|
|
||||||
throw std::invalid_argument("ACECTildeEvaluator: basis set is not assigned");
|
|
||||||
}
|
|
||||||
if (R_cache.get_dim(0) < max_jnum) {
|
|
||||||
|
|
||||||
//TODO: implement grow
|
|
||||||
R_cache.resize(max_jnum, basis_set->nradmax, basis_set->lmax + 1);
|
|
||||||
R_cache.fill(0);
|
|
||||||
|
|
||||||
DR_cache.resize(max_jnum, basis_set->nradmax, basis_set->lmax + 1);
|
|
||||||
DR_cache.fill(0);
|
|
||||||
|
|
||||||
DG_cache.resize(max_jnum, basis_set->nradbase);
|
|
||||||
DG_cache.fill(0);
|
|
||||||
|
|
||||||
Y_cache.resize(max_jnum, basis_set->lmax + 1);
|
|
||||||
Y_cache.fill({0, 0});
|
|
||||||
|
|
||||||
DY_cache.resize(max_jnum, basis_set->lmax + 1);
|
|
||||||
DY_cache.fill({0});
|
|
||||||
|
|
||||||
//hard-core repulsion
|
|
||||||
DCR_cache.init(max_jnum, "DCR_cache");
|
|
||||||
DCR_cache.fill(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// double** r - atomic coordinates of atom I
|
|
||||||
// int* types - atomic types if atom I
|
|
||||||
// int **firstneigh - ptr to 1st J int value of each I atom. Usage: jlist = firstneigh[i];
|
|
||||||
// Usage: j = jlist_of_i[jj];
|
|
||||||
// jnum - number of J neighbors for each I atom. jnum = numneigh[i];
|
|
||||||
|
|
||||||
void
|
|
||||||
ACECTildeEvaluator::compute_atom(int i, DOUBLE_TYPE **x, const SPECIES_TYPE *type, const int jnum, const int *jlist) {
|
|
||||||
if(basis_set== nullptr) {
|
|
||||||
throw std::invalid_argument("ACECTildeEvaluator: basis set is not assigned");
|
|
||||||
}
|
|
||||||
per_atom_calc_timer.start();
|
|
||||||
#ifdef PRINT_MAIN_STEPS
|
|
||||||
printf("\n ATOM: ind = %d r_norm=(%f, %f, %f)\n",i, x[i][0], x[i][1], x[i][2]);
|
|
||||||
#endif
|
|
||||||
DOUBLE_TYPE evdwl = 0, evdwl_cut = 0, rho_core = 0;
|
|
||||||
DOUBLE_TYPE r_norm;
|
|
||||||
DOUBLE_TYPE xn, yn, zn, r_xyz;
|
|
||||||
DOUBLE_TYPE R, GR, DGR, R_over_r, DR, DCR;
|
|
||||||
DOUBLE_TYPE *r_hat;
|
|
||||||
|
|
||||||
SPECIES_TYPE mu_j;
|
|
||||||
RANK_TYPE r, rank, t;
|
|
||||||
NS_TYPE n;
|
|
||||||
LS_TYPE l;
|
|
||||||
MS_TYPE m, m_t;
|
|
||||||
|
|
||||||
SPECIES_TYPE *mus;
|
|
||||||
NS_TYPE *ns;
|
|
||||||
LS_TYPE *ls;
|
|
||||||
MS_TYPE *ms;
|
|
||||||
|
|
||||||
int j, jj, func_ind, ms_ind;
|
|
||||||
SHORT_INT_TYPE factor;
|
|
||||||
|
|
||||||
ACEComplex Y{0}, Y_DR{0.};
|
|
||||||
ACEComplex B{0.};
|
|
||||||
ACEComplex dB{0};
|
|
||||||
ACEComplex A_cache[basis_set->rankmax];
|
|
||||||
|
|
||||||
dB_flatten.fill({0.});
|
|
||||||
|
|
||||||
ACEDYcomponent grad_phi_nlm{0}, DY{0.};
|
|
||||||
|
|
||||||
//size is +1 of max to avoid out-of-boundary array access in double-triangular scheme
|
|
||||||
ACEComplex A_forward_prod[basis_set->rankmax + 1];
|
|
||||||
ACEComplex A_backward_prod[basis_set->rankmax + 1];
|
|
||||||
|
|
||||||
DOUBLE_TYPE inv_r_norm;
|
|
||||||
DOUBLE_TYPE r_norms[jnum];
|
|
||||||
DOUBLE_TYPE inv_r_norms[jnum];
|
|
||||||
DOUBLE_TYPE rhats[jnum][3];//normalized vector
|
|
||||||
SPECIES_TYPE elements[jnum];
|
|
||||||
const DOUBLE_TYPE xtmp = x[i][0];
|
|
||||||
const DOUBLE_TYPE ytmp = x[i][1];
|
|
||||||
const DOUBLE_TYPE ztmp = x[i][2];
|
|
||||||
DOUBLE_TYPE f_ji[3];
|
|
||||||
|
|
||||||
bool is_element_mapping = element_type_mapping.get_size() > 0;
|
|
||||||
SPECIES_TYPE mu_i;
|
|
||||||
if (is_element_mapping)
|
|
||||||
mu_i = element_type_mapping(type[i]);
|
|
||||||
else
|
|
||||||
mu_i = type[i];
|
|
||||||
|
|
||||||
const SHORT_INT_TYPE total_basis_size_rank1 = basis_set->total_basis_size_rank1[mu_i];
|
|
||||||
const SHORT_INT_TYPE total_basis_size = basis_set->total_basis_size[mu_i];
|
|
||||||
|
|
||||||
ACECTildeBasisFunction *basis_rank1 = basis_set->basis_rank1[mu_i];
|
|
||||||
ACECTildeBasisFunction *basis = basis_set->basis[mu_i];
|
|
||||||
|
|
||||||
DOUBLE_TYPE rho_cut, drho_cut, fcut, dfcut;
|
|
||||||
DOUBLE_TYPE dF_drho_core;
|
|
||||||
|
|
||||||
//TODO: lmax -> lmaxi (get per-species type)
|
|
||||||
const LS_TYPE lmaxi = basis_set->lmax;
|
|
||||||
|
|
||||||
//TODO: nradmax -> nradiali (get per-species type)
|
|
||||||
const NS_TYPE nradiali = basis_set->nradmax;
|
|
||||||
|
|
||||||
//TODO: nradbase -> nradbasei (get per-species type)
|
|
||||||
const NS_TYPE nradbasei = basis_set->nradbase;
|
|
||||||
|
|
||||||
//TODO: get per-species type number of densities
|
|
||||||
const DENSITY_TYPE ndensity= basis_set->ndensitymax;
|
|
||||||
|
|
||||||
neighbours_forces.resize(jnum, 3);
|
|
||||||
neighbours_forces.fill(0);
|
|
||||||
|
|
||||||
//TODO: shift nullifications to place where arrays are used
|
|
||||||
weights.fill({0});
|
|
||||||
weights_rank1.fill(0);
|
|
||||||
A.fill({0});
|
|
||||||
A_rank1.fill(0);
|
|
||||||
rhos.fill(0);
|
|
||||||
dF_drho.fill(0);
|
|
||||||
|
|
||||||
#ifdef EXTRA_C_PROJECTIONS
|
|
||||||
basis_projections_rank1.init(total_basis_size_rank1, ndensity, "c_projections_rank1");
|
|
||||||
basis_projections.init(total_basis_size, ndensity, "c_projections");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//proxy references to spherical harmonics and radial functions arrays
|
|
||||||
const Array2DLM<ACEComplex> &ylm = basis_set->spherical_harmonics.ylm;
|
|
||||||
const Array2DLM<ACEDYcomponent> &dylm = basis_set->spherical_harmonics.dylm;
|
|
||||||
|
|
||||||
const Array2D<DOUBLE_TYPE> &fr = basis_set->radial_functions->fr;
|
|
||||||
const Array2D<DOUBLE_TYPE> &dfr = basis_set->radial_functions->dfr;
|
|
||||||
|
|
||||||
const Array1D<DOUBLE_TYPE> &gr = basis_set->radial_functions->gr;
|
|
||||||
const Array1D<DOUBLE_TYPE> &dgr = basis_set->radial_functions->dgr;
|
|
||||||
|
|
||||||
loop_over_neighbour_timer.start();
|
|
||||||
|
|
||||||
int jj_actual = 0;
|
|
||||||
SPECIES_TYPE type_j = 0;
|
|
||||||
int neighbour_index_mapping[jnum]; // jj_actual -> jj
|
|
||||||
//loop over neighbours, compute distance, consider only atoms within with r<cutoff(mu_i, mu_j)
|
|
||||||
for (jj = 0; jj < jnum; ++jj) {
|
|
||||||
|
|
||||||
j = jlist[jj];
|
|
||||||
xn = x[j][0] - xtmp;
|
|
||||||
yn = x[j][1] - ytmp;
|
|
||||||
zn = x[j][2] - ztmp;
|
|
||||||
type_j = type[j];
|
|
||||||
if (is_element_mapping)
|
|
||||||
mu_j = element_type_mapping(type_j);
|
|
||||||
else
|
|
||||||
mu_j = type_j;
|
|
||||||
|
|
||||||
DOUBLE_TYPE current_cutoff = basis_set->radial_functions->cut(mu_i, mu_j);
|
|
||||||
r_xyz = sqrt(xn * xn + yn * yn + zn * zn);
|
|
||||||
|
|
||||||
if (r_xyz >= current_cutoff)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
inv_r_norm = 1 / r_xyz;
|
|
||||||
|
|
||||||
r_norms[jj_actual] = r_xyz;
|
|
||||||
inv_r_norms[jj_actual] = inv_r_norm;
|
|
||||||
rhats[jj_actual][0] = xn * inv_r_norm;
|
|
||||||
rhats[jj_actual][1] = yn * inv_r_norm;
|
|
||||||
rhats[jj_actual][2] = zn * inv_r_norm;
|
|
||||||
elements[jj_actual] = mu_j;
|
|
||||||
neighbour_index_mapping[jj_actual] = jj;
|
|
||||||
jj_actual++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int jnum_actual = jj_actual;
|
|
||||||
|
|
||||||
//ALGORITHM 1: Atomic base A
|
|
||||||
for (jj = 0; jj < jnum_actual; ++jj) {
|
|
||||||
r_norm = r_norms[jj];
|
|
||||||
mu_j = elements[jj];
|
|
||||||
r_hat = rhats[jj];
|
|
||||||
|
|
||||||
//proxies
|
|
||||||
Array2DLM<ACEComplex> &Y_jj = Y_cache(jj);
|
|
||||||
Array2DLM<ACEDYcomponent> &DY_jj = DY_cache(jj);
|
|
||||||
|
|
||||||
|
|
||||||
basis_set->radial_functions->evaluate(r_norm, basis_set->nradbase, nradiali, mu_i, mu_j);
|
|
||||||
basis_set->spherical_harmonics.compute_ylm(r_hat[0], r_hat[1], r_hat[2], lmaxi);
|
|
||||||
//loop for computing A's
|
|
||||||
//rank = 1
|
|
||||||
for (n = 0; n < basis_set->nradbase; n++) {
|
|
||||||
GR = gr(n);
|
|
||||||
#ifdef DEBUG_ENERGY_CALCULATIONS
|
|
||||||
printf("-neigh atom %d\n", jj);
|
|
||||||
printf("gr(n=%d)(r=%f) = %f\n", n, r_norm, gr(n));
|
|
||||||
printf("dgr(n=%d)(r=%f) = %f\n", n, r_norm, dgr(n));
|
|
||||||
#endif
|
|
||||||
DG_cache(jj, n) = dgr(n);
|
|
||||||
A_rank1(mu_j, n) += GR * Y00;
|
|
||||||
}
|
|
||||||
//loop for computing A's
|
|
||||||
// for rank > 1
|
|
||||||
for (n = 0; n < nradiali; n++) {
|
|
||||||
auto &A_lm = A(mu_j, n);
|
|
||||||
for (l = 0; l <= lmaxi; l++) {
|
|
||||||
R = fr(n, l);
|
|
||||||
#ifdef DEBUG_ENERGY_CALCULATIONS
|
|
||||||
printf("R(nl=%d,%d)(r=%f)=%f\n", n + 1, l, r_norm, R);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DR_cache(jj, n, l) = dfr(n, l);
|
|
||||||
R_cache(jj, n, l) = R;
|
|
||||||
|
|
||||||
for (m = 0; m <= l; m++) {
|
|
||||||
Y = ylm(l, m);
|
|
||||||
#ifdef DEBUG_ENERGY_CALCULATIONS
|
|
||||||
printf("Y(lm=%d,%d)=(%f, %f)\n", l, m, Y.real, Y.img);
|
|
||||||
#endif
|
|
||||||
A_lm(l, m) += R * Y; //accumulation sum over neighbours
|
|
||||||
Y_jj(l, m) = Y;
|
|
||||||
DY_jj(l, m) = dylm(l, m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//hard-core repulsion
|
|
||||||
rho_core += basis_set->radial_functions->cr;
|
|
||||||
DCR_cache(jj) = basis_set->radial_functions->dcr;
|
|
||||||
|
|
||||||
} //end loop over neighbours
|
|
||||||
|
|
||||||
//complex conjugate A's (for NEGATIVE (-m) terms)
|
|
||||||
// for rank > 1
|
|
||||||
for (mu_j = 0; mu_j < basis_set->nelements; mu_j++) {
|
|
||||||
for (n = 0; n < nradiali; n++) {
|
|
||||||
auto &A_lm = A(mu_j, n);
|
|
||||||
for (l = 0; l <= lmaxi; l++) {
|
|
||||||
//fill in -m part in the outer loop using the same m <-> -m symmetry as for Ylm
|
|
||||||
for (m = 1; m <= l; m++) {
|
|
||||||
factor = m % 2 == 0 ? 1 : -1;
|
|
||||||
A_lm(l, -m) = A_lm(l, m).conjugated() * factor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} //now A's are constructed
|
|
||||||
loop_over_neighbour_timer.stop();
|
|
||||||
|
|
||||||
// ==================== ENERGY ====================
|
|
||||||
|
|
||||||
energy_calc_timer.start();
|
|
||||||
#ifdef EXTRA_C_PROJECTIONS
|
|
||||||
basis_projections_rank1.fill(0);
|
|
||||||
basis_projections.fill(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//ALGORITHM 2: Basis functions B with iterative product and density rho(p) calculation
|
|
||||||
//rank=1
|
|
||||||
for (int func_rank1_ind = 0; func_rank1_ind < total_basis_size_rank1; ++func_rank1_ind) {
|
|
||||||
ACECTildeBasisFunction *func = &basis_rank1[func_rank1_ind];
|
|
||||||
// ndensity = func->ndensity;
|
|
||||||
#ifdef PRINT_LOOPS_INDICES
|
|
||||||
printf("Num density = %d r = 0\n",(int) ndensity );
|
|
||||||
print_C_tilde_B_basis_function(*func);
|
|
||||||
#endif
|
|
||||||
double A_cur = A_rank1(func->mus[0], func->ns[0] - 1);
|
|
||||||
#ifdef DEBUG_ENERGY_CALCULATIONS
|
|
||||||
printf("A_r=1(x=%d, n=%d)=(%f)\n", func->mus[0], func->ns[0], A_cur);
|
|
||||||
printf(" coeff[0] = %f\n", func->ctildes[0]);
|
|
||||||
#endif
|
|
||||||
for (DENSITY_TYPE p = 0; p < ndensity; ++p) {
|
|
||||||
//for rank=1 (r=0) only 1 ms-combination exists (ms_ind=0), so index of func.ctildes is 0..ndensity-1
|
|
||||||
rhos(p) += func->ctildes[p] * A_cur;
|
|
||||||
#ifdef EXTRA_C_PROJECTIONS
|
|
||||||
//aggregate C-projections separately
|
|
||||||
basis_projections_rank1(func_rank1_ind, p)+= func->ctildes[p] * A_cur;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} // end loop for rank=1
|
|
||||||
|
|
||||||
//rank>1
|
|
||||||
int func_ms_ind = 0;
|
|
||||||
int func_ms_t_ind = 0;// index for dB
|
|
||||||
|
|
||||||
for (func_ind = 0; func_ind < total_basis_size; ++func_ind) {
|
|
||||||
ACECTildeBasisFunction *func = &basis[func_ind];
|
|
||||||
//TODO: check if func->ctildes are zero, then skip
|
|
||||||
// ndensity = func->ndensity;
|
|
||||||
rank = func->rank;
|
|
||||||
r = rank - 1;
|
|
||||||
#ifdef PRINT_LOOPS_INDICES
|
|
||||||
printf("Num density = %d r = %d\n",(int) ndensity, (int)r );
|
|
||||||
print_C_tilde_B_basis_function(*func);
|
|
||||||
#endif
|
|
||||||
mus = func->mus;
|
|
||||||
ns = func->ns;
|
|
||||||
ls = func->ls;
|
|
||||||
|
|
||||||
//loop over {ms} combinations in sum
|
|
||||||
for (ms_ind = 0; ms_ind < func->num_ms_combs; ++ms_ind, ++func_ms_ind) {
|
|
||||||
ms = &func->ms_combs[ms_ind * rank]; // current ms-combination (of length = rank)
|
|
||||||
|
|
||||||
//loop over m, collect B = product of A with given ms
|
|
||||||
A_forward_prod[0] = 1;
|
|
||||||
A_backward_prod[r] = 1;
|
|
||||||
|
|
||||||
//fill forward A-product triangle
|
|
||||||
for (t = 0; t < rank; t++) {
|
|
||||||
//TODO: optimize ns[t]-1 -> ns[t] during functions construction
|
|
||||||
A_cache[t] = A(mus[t], ns[t] - 1, ls[t], ms[t]);
|
|
||||||
#ifdef DEBUG_ENERGY_CALCULATIONS
|
|
||||||
printf("A(x=%d, n=%d, l=%d, m=%d)=(%f,%f)\n", mus[t], ns[t], ls[t], ms[t], A_cache[t].real,
|
|
||||||
A_cache[t].img);
|
|
||||||
#endif
|
|
||||||
A_forward_prod[t + 1] = A_forward_prod[t] * A_cache[t];
|
|
||||||
}
|
|
||||||
|
|
||||||
B = A_forward_prod[t];
|
|
||||||
|
|
||||||
#ifdef DEBUG_FORCES_CALCULATIONS
|
|
||||||
printf("B = (%f, %f)\n", (B).real, (B).img);
|
|
||||||
#endif
|
|
||||||
//fill backward A-product triangle
|
|
||||||
for (t = r; t >= 1; t--) {
|
|
||||||
A_backward_prod[t - 1] =
|
|
||||||
A_backward_prod[t] * A_cache[t];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (t = 0; t < rank; ++t, ++func_ms_t_ind) {
|
|
||||||
dB = A_forward_prod[t] * A_backward_prod[t]; //dB - product of all A's except t-th
|
|
||||||
dB_flatten(func_ms_t_ind) = dB;
|
|
||||||
#ifdef DEBUG_FORCES_CALCULATIONS
|
|
||||||
m_t = ms[t];
|
|
||||||
printf("dB(n,l,m)(%d,%d,%d) = (%f, %f)\n", ns[t], ls[t], m_t, (dB).real, (dB).img);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
for (DENSITY_TYPE p = 0; p < ndensity; ++p) {
|
|
||||||
//real-part only multiplication
|
|
||||||
rhos(p) += B.real_part_product(func->ctildes[ms_ind * ndensity + p]);
|
|
||||||
|
|
||||||
#ifdef EXTRA_C_PROJECTIONS
|
|
||||||
//aggregate C-projections separately
|
|
||||||
basis_projections(func_ind, p)+=B.real_part_product(func->ctildes[ms_ind * ndensity + p]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PRINT_INTERMEDIATE_VALUES
|
|
||||||
printf("rhos(%d) += %f\n", p, B.real_part_product(func->ctildes[ms_ind * ndensity + p]));
|
|
||||||
printf("Rho[i = %d][p = %d] = %f\n", i , p , rhos(p));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}//end of loop over {ms} combinations in sum
|
|
||||||
}// end loop for rank>1
|
|
||||||
|
|
||||||
#ifdef DEBUG_FORCES_CALCULATIONS
|
|
||||||
printf("rhos = ");
|
|
||||||
for(DENSITY_TYPE p =0; p<ndensity; ++p) printf(" %.20f ",rhos(p));
|
|
||||||
printf("\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// energy cutoff
|
|
||||||
rho_cut = basis_set->rho_core_cutoffs(mu_i);
|
|
||||||
drho_cut = basis_set->drho_core_cutoffs(mu_i);
|
|
||||||
|
|
||||||
basis_set->inner_cutoff(rho_core, rho_cut, drho_cut, fcut, dfcut);
|
|
||||||
basis_set->FS_values_and_derivatives(rhos, evdwl, dF_drho, ndensity);
|
|
||||||
|
|
||||||
dF_drho_core = evdwl * dfcut + 1;
|
|
||||||
for (DENSITY_TYPE p = 0; p < ndensity; ++p)
|
|
||||||
dF_drho(p) *= fcut;
|
|
||||||
evdwl_cut = evdwl * fcut + rho_core;
|
|
||||||
|
|
||||||
// E0 shift
|
|
||||||
evdwl_cut += basis_set->E0vals(mu_i);
|
|
||||||
|
|
||||||
#ifdef DEBUG_FORCES_CALCULATIONS
|
|
||||||
printf("dFrhos = ");
|
|
||||||
for(DENSITY_TYPE p =0; p<ndensity; ++p) printf(" %f ",dF_drho(p));
|
|
||||||
printf("\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//ALGORITHM 3: Weights and theta calculation
|
|
||||||
// rank = 1
|
|
||||||
for (int f_ind = 0; f_ind < total_basis_size_rank1; ++f_ind) {
|
|
||||||
ACECTildeBasisFunction *func = &basis_rank1[f_ind];
|
|
||||||
// ndensity = func->ndensity;
|
|
||||||
for (DENSITY_TYPE p = 0; p < ndensity; ++p) {
|
|
||||||
//for rank=1 (r=0) only 1 ms-combination exists (ms_ind=0), so index of func.ctildes is 0..ndensity-1
|
|
||||||
weights_rank1(func->mus[0], func->ns[0] - 1) += dF_drho(p) * func->ctildes[p];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rank>1
|
|
||||||
func_ms_ind = 0;
|
|
||||||
func_ms_t_ind = 0;// index for dB
|
|
||||||
DOUBLE_TYPE theta = 0;
|
|
||||||
for (func_ind = 0; func_ind < total_basis_size; ++func_ind) {
|
|
||||||
ACECTildeBasisFunction *func = &basis[func_ind];
|
|
||||||
// ndensity = func->ndensity;
|
|
||||||
rank = func->rank;
|
|
||||||
mus = func->mus;
|
|
||||||
ns = func->ns;
|
|
||||||
ls = func->ls;
|
|
||||||
for (ms_ind = 0; ms_ind < func->num_ms_combs; ++ms_ind, ++func_ms_ind) {
|
|
||||||
ms = &func->ms_combs[ms_ind * rank];
|
|
||||||
theta = 0;
|
|
||||||
for (DENSITY_TYPE p = 0; p < ndensity; ++p) {
|
|
||||||
theta += dF_drho(p) * func->ctildes[ms_ind * ndensity + p];
|
|
||||||
#ifdef DEBUG_FORCES_CALCULATIONS
|
|
||||||
printf("(p=%d) theta += dF_drho[p] * func.ctildes[ms_ind * ndensity + p] = %f * %f = %f\n",p, dF_drho(p), func->ctildes[ms_ind * ndensity + p],dF_drho(p)*func->ctildes[ms_ind * ndensity + p]);
|
|
||||||
printf("theta=%f\n",theta);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
theta *= 0.5; // 0.5 factor due to possible double counting ???
|
|
||||||
for (t = 0; t < rank; ++t, ++func_ms_t_ind) {
|
|
||||||
m_t = ms[t];
|
|
||||||
factor = (m_t % 2 == 0 ? 1 : -1);
|
|
||||||
dB = dB_flatten(func_ms_t_ind);
|
|
||||||
weights(mus[t], ns[t] - 1, ls[t], m_t) += theta * dB; //Theta_array(func_ms_ind);
|
|
||||||
// update -m_t (that could also be positive), because the basis is half_basis
|
|
||||||
weights(mus[t], ns[t] - 1, ls[t], -m_t) +=
|
|
||||||
theta * (dB).conjugated() * factor;// Theta_array(func_ms_ind);
|
|
||||||
#ifdef DEBUG_FORCES_CALCULATIONS
|
|
||||||
printf("dB(n,l,m)(%d,%d,%d) = (%f, %f)\n", ns[t], ls[t], m_t, (dB).real, (dB).img);
|
|
||||||
printf("theta = %f\n",theta);
|
|
||||||
printf("weights(n,l,m)(%d,%d,%d) += (%f, %f)\n", ns[t], ls[t], m_t, (theta * dB * 0.5).real,
|
|
||||||
(theta * dB * 0.5).img);
|
|
||||||
printf("weights(n,l,-m)(%d,%d,%d) += (%f, %f)\n", ns[t], ls[t], -m_t,
|
|
||||||
( theta * (dB).conjugated() * factor * 0.5).real,
|
|
||||||
( theta * (dB).conjugated() * factor * 0.5).img);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
energy_calc_timer.stop();
|
|
||||||
|
|
||||||
// ==================== FORCES ====================
|
|
||||||
#ifdef PRINT_MAIN_STEPS
|
|
||||||
printf("\nFORCE CALCULATION\n");
|
|
||||||
printf("loop over neighbours\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
forces_calc_loop_timer.start();
|
|
||||||
// loop over neighbour atoms for force calculations
|
|
||||||
for (jj = 0; jj < jnum_actual; ++jj) {
|
|
||||||
mu_j = elements[jj];
|
|
||||||
r_hat = rhats[jj];
|
|
||||||
inv_r_norm = inv_r_norms[jj];
|
|
||||||
|
|
||||||
Array2DLM<ACEComplex> &Y_cache_jj = Y_cache(jj);
|
|
||||||
Array2DLM<ACEDYcomponent> &DY_cache_jj = DY_cache(jj);
|
|
||||||
|
|
||||||
#ifdef PRINT_LOOPS_INDICES
|
|
||||||
printf("\nneighbour atom #%d\n", jj);
|
|
||||||
printf("rhat = (%f, %f, %f)\n", r_hat[0], r_hat[1], r_hat[2]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
forces_calc_neighbour_timer.start();
|
|
||||||
|
|
||||||
f_ji[0] = f_ji[1] = f_ji[2] = 0;
|
|
||||||
|
|
||||||
//for rank = 1
|
|
||||||
for (n = 0; n < nradbasei; ++n) {
|
|
||||||
if (weights_rank1(mu_j, n) == 0)
|
|
||||||
continue;
|
|
||||||
auto &DG = DG_cache(jj, n);
|
|
||||||
DGR = DG * Y00;
|
|
||||||
DGR *= weights_rank1(mu_j, n);
|
|
||||||
#ifdef DEBUG_FORCES_CALCULATIONS
|
|
||||||
printf("r=1: (n,l,m)=(%d, 0, 0)\n",n+1);
|
|
||||||
printf("\tGR(n=%d, r=%f)=%f\n",n+1,r_norm, gr(n));
|
|
||||||
printf("\tDGR(n=%d, r=%f)=%f\n",n+1,r_norm, dgr(n));
|
|
||||||
printf("\tdF+=(%f, %f, %f)\n",DGR * r_hat[0], DGR * r_hat[1], DGR * r_hat[2]);
|
|
||||||
#endif
|
|
||||||
f_ji[0] += DGR * r_hat[0];
|
|
||||||
f_ji[1] += DGR * r_hat[1];
|
|
||||||
f_ji[2] += DGR * r_hat[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
//for rank > 1
|
|
||||||
for (n = 0; n < nradiali; n++) {
|
|
||||||
for (l = 0; l <= lmaxi; l++) {
|
|
||||||
R_over_r = R_cache(jj, n, l) * inv_r_norm;
|
|
||||||
DR = DR_cache(jj, n, l);
|
|
||||||
|
|
||||||
// for m>=0
|
|
||||||
for (m = 0; m <= l; m++) {
|
|
||||||
ACEComplex w = weights(mu_j, n, l, m);
|
|
||||||
if (w == 0)
|
|
||||||
continue;
|
|
||||||
//counting for -m cases if m>0
|
|
||||||
if (m > 0) w *= 2;
|
|
||||||
|
|
||||||
DY = DY_cache_jj(l, m);
|
|
||||||
Y_DR = Y_cache_jj(l, m) * DR;
|
|
||||||
|
|
||||||
grad_phi_nlm.a[0] = Y_DR * r_hat[0] + DY.a[0] * R_over_r;
|
|
||||||
grad_phi_nlm.a[1] = Y_DR * r_hat[1] + DY.a[1] * R_over_r;
|
|
||||||
grad_phi_nlm.a[2] = Y_DR * r_hat[2] + DY.a[2] * R_over_r;
|
|
||||||
#ifdef DEBUG_FORCES_CALCULATIONS
|
|
||||||
printf("d_phi(n=%d, l=%d, m=%d) = ((%f,%f), (%f,%f), (%f,%f))\n",n+1,l,m,
|
|
||||||
grad_phi_nlm.a[0].real, grad_phi_nlm.a[0].img,
|
|
||||||
grad_phi_nlm.a[1].real, grad_phi_nlm.a[1].img,
|
|
||||||
grad_phi_nlm.a[2].real, grad_phi_nlm.a[2].img);
|
|
||||||
|
|
||||||
printf("weights(n,l,m)(%d,%d,%d) = (%f,%f)\n", n+1, l, m,w.real, w.img);
|
|
||||||
//if (m>0) w*=2;
|
|
||||||
printf("dF(n,l,m)(%d, %d, %d) += (%f, %f, %f)\n", n + 1, l, m,
|
|
||||||
w.real_part_product(grad_phi_nlm.a[0]),
|
|
||||||
w.real_part_product(grad_phi_nlm.a[1]),
|
|
||||||
w.real_part_product(grad_phi_nlm.a[2])
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
// real-part multiplication only
|
|
||||||
f_ji[0] += w.real_part_product(grad_phi_nlm.a[0]);
|
|
||||||
f_ji[1] += w.real_part_product(grad_phi_nlm.a[1]);
|
|
||||||
f_ji[2] += w.real_part_product(grad_phi_nlm.a[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef PRINT_INTERMEDIATE_VALUES
|
|
||||||
printf("f_ji(jj=%d, i=%d)=(%f, %f, %f)\n", jj, i,
|
|
||||||
f_ji[0], f_ji[1], f_ji[2]
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//hard-core repulsion
|
|
||||||
DCR = DCR_cache(jj);
|
|
||||||
#ifdef DEBUG_FORCES_CALCULATIONS
|
|
||||||
printf("DCR = %f\n",DCR);
|
|
||||||
#endif
|
|
||||||
f_ji[0] += dF_drho_core * DCR * r_hat[0];
|
|
||||||
f_ji[1] += dF_drho_core * DCR * r_hat[1];
|
|
||||||
f_ji[2] += dF_drho_core * DCR * r_hat[2];
|
|
||||||
#ifdef PRINT_INTERMEDIATE_VALUES
|
|
||||||
printf("with core-repulsion\n");
|
|
||||||
printf("f_ji(jj=%d, i=%d)=(%f, %f, %f)\n", jj, i,
|
|
||||||
f_ji[0], f_ji[1], f_ji[2]
|
|
||||||
);
|
|
||||||
printf("neighbour_index_mapping[jj=%d]=%d\n",jj,neighbour_index_mapping[jj]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
neighbours_forces(neighbour_index_mapping[jj], 0) = f_ji[0];
|
|
||||||
neighbours_forces(neighbour_index_mapping[jj], 1) = f_ji[1];
|
|
||||||
neighbours_forces(neighbour_index_mapping[jj], 2) = f_ji[2];
|
|
||||||
|
|
||||||
forces_calc_neighbour_timer.stop();
|
|
||||||
}// end loop over neighbour atoms for forces
|
|
||||||
|
|
||||||
forces_calc_loop_timer.stop();
|
|
||||||
|
|
||||||
//now, energies and forces are ready
|
|
||||||
//energies(i) = evdwl + rho_core;
|
|
||||||
e_atom = evdwl_cut;
|
|
||||||
|
|
||||||
#ifdef PRINT_INTERMEDIATE_VALUES
|
|
||||||
printf("energies(i) = FS(...rho_p_accum...) = %f\n", evdwl);
|
|
||||||
#endif
|
|
||||||
per_atom_calc_timer.stop();
|
|
||||||
}
|
|
|
@ -1,230 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 31.01.20.
|
|
||||||
|
|
||||||
#ifndef ACE_EVALUATOR_H
|
|
||||||
#define ACE_EVALUATOR_H
|
|
||||||
|
|
||||||
#include "ace_abstract_basis.h"
|
|
||||||
#include "ace_arraynd.h"
|
|
||||||
#include "ace_array2dlm.h"
|
|
||||||
#include "ace_c_basis.h"
|
|
||||||
#include "ace_complex.h"
|
|
||||||
#include "ace_timing.h"
|
|
||||||
#include "ace_types.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic evaluator class, that should accept the basis set and implement the "compute_atom" method using given basis set.
|
|
||||||
*/
|
|
||||||
class ACEEvaluator {
|
|
||||||
protected:
|
|
||||||
|
|
||||||
Array2D<DOUBLE_TYPE> A_rank1 = Array2D<DOUBLE_TYPE>("A_rank1"); ///< 2D-array for storing A's for rank=1, shape: A(mu_j,n)
|
|
||||||
Array4DLM<ACEComplex> A = Array4DLM<ACEComplex>("A"); ///< 4D array with (l,m) last indices for storing A's for rank>1: A(mu_j, n, l, m)
|
|
||||||
|
|
||||||
Array1D<DOUBLE_TYPE> rhos = Array1D<DOUBLE_TYPE>("rhos"); ///< densities \f$ \rho^{(p)} \f$(ndensity), p = 0 .. ndensity-1
|
|
||||||
Array1D<DOUBLE_TYPE> dF_drho = Array1D<DOUBLE_TYPE>("dF_drho"); ///< derivatives of cluster functional wrt. densities, index = 0 .. ndensity-1
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize internal arrays according to basis set sizes
|
|
||||||
* @param basis_set
|
|
||||||
*/
|
|
||||||
void init(ACEAbstractBasisSet *basis_set);
|
|
||||||
|
|
||||||
public:
|
|
||||||
// set of timers for code profiling
|
|
||||||
|
|
||||||
ACETimer loop_over_neighbour_timer; ///< timer for loop over neighbours when constructing A's for single central atom
|
|
||||||
ACETimer per_atom_calc_timer; ///< timer for single compute_atom call
|
|
||||||
|
|
||||||
|
|
||||||
ACETimer forces_calc_loop_timer; ///< timer for forces calculations for single central atom
|
|
||||||
ACETimer forces_calc_neighbour_timer; ///< timer for loop over neighbour atoms for force calculations
|
|
||||||
|
|
||||||
ACETimer energy_calc_timer; ///< timer for energy calculation
|
|
||||||
ACETimer total_time_calc_timer; ///< timer for total calculations of all atoms within given atomic environment system
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize all timers
|
|
||||||
*/
|
|
||||||
void init_timers();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mapping from external atoms types, i.e. LAMMPS, to internal SPECIES_TYPE, used in basis functions
|
|
||||||
*/
|
|
||||||
Array1D<int> element_type_mapping = Array1D<int>("element_type_mapping");
|
|
||||||
|
|
||||||
|
|
||||||
DOUBLE_TYPE e_atom = 0; ///< energy of current atom, including core-repulsion
|
|
||||||
|
|
||||||
/**
|
|
||||||
* temporary array for the pair forces between current atom_i and its neighbours atom_k
|
|
||||||
* neighbours_forces(k,3), k = 0..num_of_neighbours(atom_i)-1
|
|
||||||
*/
|
|
||||||
Array2D<DOUBLE_TYPE> neighbours_forces = Array2D<DOUBLE_TYPE>("neighbours_forces");
|
|
||||||
|
|
||||||
ACEEvaluator() = default;
|
|
||||||
|
|
||||||
virtual ~ACEEvaluator() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The key method to compute energy and forces for atom 'i'.
|
|
||||||
* Method will update the "e_atom" variable and "neighbours_forces(jj, alpha)" array
|
|
||||||
*
|
|
||||||
* @param i atom index
|
|
||||||
* @param x atomic positions array of the real and ghost atoms, shape: [atom_ind][3]
|
|
||||||
* @param type atomic types array of the real and ghost atoms, shape: [atom_ind]
|
|
||||||
* @param jnum number of neighbours of atom_i
|
|
||||||
* @param jlist array of neighbour indices, shape: [jnum]
|
|
||||||
*/
|
|
||||||
virtual void compute_atom(int i, DOUBLE_TYPE **x, const SPECIES_TYPE *type, const int jnum, const int *jlist) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resize all caches over neighbours atoms
|
|
||||||
* @param max_jnum maximum number of neighbours
|
|
||||||
*/
|
|
||||||
virtual void resize_neighbours_cache(int max_jnum) = 0;
|
|
||||||
|
|
||||||
#ifdef EXTRA_C_PROJECTIONS
|
|
||||||
/**
|
|
||||||
* 2D array to store projections of basis function for rank = 1, shape: [func_ind][ndensity]
|
|
||||||
*/
|
|
||||||
Array2D<DOUBLE_TYPE> basis_projections_rank1 = Array2D<DOUBLE_TYPE>("basis_projections_rank1");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2D array to store projections of basis function for rank > 1, shape: [func_ind][ndensity]
|
|
||||||
*/
|
|
||||||
Array2D<DOUBLE_TYPE> basis_projections = Array2D<DOUBLE_TYPE>("basis_projections");
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
//TODO: split into separate file
|
|
||||||
/**
|
|
||||||
* Evaluator for C-tilde basis set, that should accept the basis set and implement the "compute_atom" method using given basis set.
|
|
||||||
*/
|
|
||||||
class ACECTildeEvaluator : public ACEEvaluator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Weights \f$ \omega_{i \mu n 0 0} \f$ for rank = 1, see Eq.(10) from implementation notes,
|
|
||||||
* 'i' is fixed for the current atom, shape: [nelements][nradbase]
|
|
||||||
*/
|
|
||||||
Array2D<DOUBLE_TYPE> weights_rank1 = Array2D<DOUBLE_TYPE>("weights_rank1");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Weights \f$ \omega_{i \mu n l m} \f$ for rank > 1, see Eq.(10) from implementation notes,
|
|
||||||
* 'i' is fixed for the current atom, shape: [nelements][nradbase][l=0..lmax, m]
|
|
||||||
*/
|
|
||||||
Array4DLM<ACEComplex> weights = Array4DLM<ACEComplex>("weights");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cache for gradients of \f$ g(r)\f$: grad_phi(jj,n)=A2DLM(l,m)
|
|
||||||
* shape:[max_jnum][nradbase]
|
|
||||||
*/
|
|
||||||
Array2D<DOUBLE_TYPE> DG_cache = Array2D<DOUBLE_TYPE>("DG_cache");
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cache for \f$ R_{nl}(r)\f$
|
|
||||||
* shape:[max_jnum][nradbase][0..lmax]
|
|
||||||
*/
|
|
||||||
Array3D<DOUBLE_TYPE> R_cache = Array3D<DOUBLE_TYPE>("R_cache");
|
|
||||||
/**
|
|
||||||
* cache for derivatives of \f$ R_{nl}(r)\f$
|
|
||||||
* shape:[max_jnum][nradbase][0..lmax]
|
|
||||||
*/
|
|
||||||
Array3D<DOUBLE_TYPE> DR_cache = Array3D<DOUBLE_TYPE>("DR_cache");
|
|
||||||
/**
|
|
||||||
* cache for \f$ Y_{lm}(\hat{r})\f$
|
|
||||||
* shape:[max_jnum][0..lmax][m]
|
|
||||||
*/
|
|
||||||
Array3DLM<ACEComplex> Y_cache = Array3DLM<ACEComplex>("Y_cache");
|
|
||||||
/**
|
|
||||||
* cache for \f$ \nabla Y_{lm}(\hat{r})\f$
|
|
||||||
* shape:[max_jnum][0..lmax][m]
|
|
||||||
*/
|
|
||||||
Array3DLM<ACEDYcomponent> DY_cache = Array3DLM<ACEDYcomponent>("dY_dense_cache");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cache for derivatives of hard-core repulsion
|
|
||||||
* shape:[max_jnum]
|
|
||||||
*/
|
|
||||||
Array1D<DOUBLE_TYPE> DCR_cache = Array1D<DOUBLE_TYPE>("DCR_cache");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Partial derivatives \f$ dB_{i \mu n l m t}^{(r)} \f$ with sequential numbering over [func_ind][ms_ind][r],
|
|
||||||
* shape:[func_ms_r_ind]
|
|
||||||
*/
|
|
||||||
Array1D<ACEComplex> dB_flatten = Array1D<ACEComplex>("dB_flatten");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pointer to the ACEBasisSet object
|
|
||||||
*/
|
|
||||||
ACECTildeBasisSet *basis_set = nullptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize internal arrays according to basis set sizes
|
|
||||||
* @param basis_set
|
|
||||||
*/
|
|
||||||
void init(ACECTildeBasisSet *basis_set);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
ACECTildeEvaluator() = default;
|
|
||||||
|
|
||||||
explicit ACECTildeEvaluator(ACECTildeBasisSet &bas) {
|
|
||||||
set_basis(bas);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the basis function to the ACE evaluator
|
|
||||||
* @param bas
|
|
||||||
*/
|
|
||||||
void set_basis(ACECTildeBasisSet &bas);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The key method to compute energy and forces for atom 'i'.
|
|
||||||
* Method will update the "e_atom" variable and "neighbours_forces(jj, alpha)" array
|
|
||||||
*
|
|
||||||
* @param i atom index
|
|
||||||
* @param x atomic positions array of the real and ghost atoms, shape: [atom_ind][3]
|
|
||||||
* @param type atomic types array of the real and ghost atoms, shape: [atom_ind]
|
|
||||||
* @param jnum number of neighbours of atom_i
|
|
||||||
* @param jlist array of neighbour indices, shape: [jnum]
|
|
||||||
*/
|
|
||||||
void compute_atom(int i, DOUBLE_TYPE **x, const SPECIES_TYPE *type, const int jnum, const int *jlist) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resize all caches over neighbours atoms
|
|
||||||
* @param max_jnum maximum number of neighbours
|
|
||||||
*/
|
|
||||||
void resize_neighbours_cache(int max_jnum) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //ACE_EVALUATOR_H
|
|
|
@ -1,130 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Created by yury on 28.04.2020.
|
|
||||||
|
|
||||||
#include "ace_flatten_basis.h"
|
|
||||||
|
|
||||||
ACEFlattenBasisSet::ACEFlattenBasisSet(const ACEFlattenBasisSet &other) {
|
|
||||||
_copy_scalar_memory(other);
|
|
||||||
_copy_dynamic_memory(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
ACEFlattenBasisSet &ACEFlattenBasisSet::operator=(const ACEFlattenBasisSet &other) {
|
|
||||||
if (this != &other) {
|
|
||||||
_clean();
|
|
||||||
_copy_scalar_memory(other);
|
|
||||||
_copy_dynamic_memory(other);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ACEFlattenBasisSet::~ACEFlattenBasisSet() {
|
|
||||||
ACEFlattenBasisSet::_clean();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEFlattenBasisSet::_clean() {
|
|
||||||
//chained call of base class method
|
|
||||||
ACEAbstractBasisSet::_clean();
|
|
||||||
_clean_contiguous_arrays();
|
|
||||||
_clean_basissize_arrays();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEFlattenBasisSet::_clean_basissize_arrays() {
|
|
||||||
delete[] total_basis_size;
|
|
||||||
total_basis_size = nullptr;
|
|
||||||
|
|
||||||
delete[] total_basis_size_rank1;
|
|
||||||
total_basis_size_rank1 = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEFlattenBasisSet::_clean_contiguous_arrays() {
|
|
||||||
delete[] full_ns_rank1;
|
|
||||||
full_ns_rank1 = nullptr;
|
|
||||||
|
|
||||||
delete[] full_ls_rank1;
|
|
||||||
full_ls_rank1 = nullptr;
|
|
||||||
|
|
||||||
delete[] full_mus_rank1;
|
|
||||||
full_mus_rank1 = nullptr;
|
|
||||||
|
|
||||||
delete[] full_ms_rank1;
|
|
||||||
full_ms_rank1 = nullptr;
|
|
||||||
|
|
||||||
//////
|
|
||||||
|
|
||||||
delete[] full_ns;
|
|
||||||
full_ns = nullptr;
|
|
||||||
|
|
||||||
delete[] full_ls;
|
|
||||||
full_ls = nullptr;
|
|
||||||
|
|
||||||
delete[] full_mus;
|
|
||||||
full_mus = nullptr;
|
|
||||||
|
|
||||||
delete[] full_ms;
|
|
||||||
full_ms = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEFlattenBasisSet::_copy_scalar_memory(const ACEFlattenBasisSet &src) {
|
|
||||||
ACEAbstractBasisSet::_copy_scalar_memory(src);
|
|
||||||
|
|
||||||
rank_array_total_size_rank1 = src.rank_array_total_size_rank1;
|
|
||||||
coeff_array_total_size_rank1 = src.coeff_array_total_size_rank1;
|
|
||||||
rank_array_total_size = src.rank_array_total_size;
|
|
||||||
ms_array_total_size = src.ms_array_total_size;
|
|
||||||
coeff_array_total_size = src.coeff_array_total_size;
|
|
||||||
|
|
||||||
max_B_array_size = src.max_B_array_size;
|
|
||||||
max_dB_array_size = src.max_dB_array_size;
|
|
||||||
num_ms_combinations_max = src.num_ms_combinations_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACEFlattenBasisSet::_copy_dynamic_memory(const ACEFlattenBasisSet &src) { //allocate new memory
|
|
||||||
|
|
||||||
ACEAbstractBasisSet::_copy_dynamic_memory(src);
|
|
||||||
|
|
||||||
if (src.total_basis_size_rank1 == nullptr)
|
|
||||||
throw runtime_error("Could not copy ACEFlattenBasisSet::total_basis_size_rank1 - array not initialized");
|
|
||||||
if (src.total_basis_size == nullptr)
|
|
||||||
throw runtime_error("Could not copy ACEFlattenBasisSet::total_basis_size - array not initialized");
|
|
||||||
|
|
||||||
delete[] total_basis_size_rank1;
|
|
||||||
total_basis_size_rank1 = new SHORT_INT_TYPE[nelements];
|
|
||||||
delete[] total_basis_size;
|
|
||||||
total_basis_size = new SHORT_INT_TYPE[nelements];
|
|
||||||
|
|
||||||
//copy
|
|
||||||
for (SPECIES_TYPE mu = 0; mu < nelements; ++mu) {
|
|
||||||
total_basis_size_rank1[mu] = src.total_basis_size_rank1[mu];
|
|
||||||
total_basis_size[mu] = src.total_basis_size[mu];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,135 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Lysogroskiy Yury on 28.04.2020.
|
|
||||||
|
|
||||||
#ifndef ACE_EVALUATOR_ACE_FLATTEN_BASIS_H
|
|
||||||
#define ACE_EVALUATOR_ACE_FLATTEN_BASIS_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "ace_abstract_basis.h"
|
|
||||||
#include "ace_c_basisfunction.h"
|
|
||||||
#include "ace_radial.h"
|
|
||||||
#include "ace_spherical_cart.h"
|
|
||||||
#include "ace_types.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basis set with basis function attributes, i.e. \f$ \mathbf{n}, \mathbf{l}, \mathbf{m}\f$, etc.
|
|
||||||
* packed into contiguous arrays for the cache-friendly memory layout.
|
|
||||||
*/
|
|
||||||
class ACEFlattenBasisSet : public ACEAbstractBasisSet {
|
|
||||||
public:
|
|
||||||
//arrays and its sizes for rank = 1 basis functions for packed basis
|
|
||||||
|
|
||||||
size_t rank_array_total_size_rank1 = 0; ///< size for full_ns_rank1, full_ls_rank1, full_Xs_rank1
|
|
||||||
size_t coeff_array_total_size_rank1 = 0; ///< size for full coefficients array (depends on B or C-Tilde basis)
|
|
||||||
|
|
||||||
NS_TYPE *full_ns_rank1 = nullptr; ///< ns contiguous package [rank_array_total_size_rank1]
|
|
||||||
LS_TYPE *full_ls_rank1 = nullptr; ///< ls contiguous package [rank_array_total_size_rank1]
|
|
||||||
SPECIES_TYPE *full_mus_rank1 = nullptr; ///< mus contiguous package [rank_array_total_size_rank1]
|
|
||||||
MS_TYPE *full_ms_rank1 = nullptr; ///< m_s contiguous package[rank_array_total_size_rank1]
|
|
||||||
|
|
||||||
//arrays and its sizes for rank > 1 basis functions for packed basis
|
|
||||||
size_t rank_array_total_size = 0; ///< size for full_ns, full_ls, full_Xs
|
|
||||||
size_t ms_array_total_size = 0; ///< size for full_ms array
|
|
||||||
size_t coeff_array_total_size = 0;///< size for full coefficients arrays (depends on B- or C- basis)
|
|
||||||
|
|
||||||
NS_TYPE *full_ns = nullptr; ///< ns contiguous package [rank_array_total_size]
|
|
||||||
LS_TYPE *full_ls = nullptr; ///< ls contiguous package [rank_array_total_size]
|
|
||||||
SPECIES_TYPE *full_mus = nullptr; ///< mus contiguous package [rank_array_total_size]
|
|
||||||
MS_TYPE *full_ms = nullptr; ///< //m_s contiguous package [ms_array_total_size]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rearrange basis functions in contiguous memory to optimize cache access
|
|
||||||
*/
|
|
||||||
virtual void pack_flatten_basis() = 0;
|
|
||||||
|
|
||||||
virtual void flatten_basis() = 0;
|
|
||||||
|
|
||||||
//1D flat array basis representation: [mu]
|
|
||||||
SHORT_INT_TYPE *total_basis_size_rank1 = nullptr; ///< per-species type array of total_basis_rank1[mu] sizes
|
|
||||||
SHORT_INT_TYPE *total_basis_size = nullptr; ///< per-species type array of total_basis[mu] sizes
|
|
||||||
|
|
||||||
size_t max_B_array_size = 0; ///< maximum over elements array size for B[func_ind][ms_ind]
|
|
||||||
size_t max_dB_array_size = 0; ///< maximum over elements array size for dB[func_ind][ms_ind][r]
|
|
||||||
|
|
||||||
SHORT_INT_TYPE num_ms_combinations_max = 0; ///< maximum number of ms combinations among all basis functions
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor
|
|
||||||
*/
|
|
||||||
ACEFlattenBasisSet() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor (see Rule of Three)
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
ACEFlattenBasisSet(const ACEFlattenBasisSet &other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* operator= (see Rule of Three)
|
|
||||||
* @param other
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ACEFlattenBasisSet &operator=(const ACEFlattenBasisSet &other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor (see Rule of Three)
|
|
||||||
*/
|
|
||||||
~ACEFlattenBasisSet() override;
|
|
||||||
|
|
||||||
// routines for copying and cleaning dynamic memory of the class (see Rule of Three)
|
|
||||||
/**
|
|
||||||
* Cleaning dynamic memory of the class (see. Rule of Three),
|
|
||||||
* must be idempotent for safety
|
|
||||||
*/
|
|
||||||
void _clean() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copying scalar variables
|
|
||||||
* @param src
|
|
||||||
*/
|
|
||||||
void _copy_scalar_memory(const ACEFlattenBasisSet &src);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copying and cleaning dynamic memory of the class (see. Rule of Three)
|
|
||||||
* @param src
|
|
||||||
*/
|
|
||||||
void _copy_dynamic_memory(const ACEFlattenBasisSet &src);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean contiguous arrays
|
|
||||||
*/
|
|
||||||
virtual void _clean_contiguous_arrays();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release dynamic arrays with basis set sizes
|
|
||||||
*/
|
|
||||||
void _clean_basissize_arrays();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //ACE_EVALUATOR_ACE_FLATTEN_BASIS_H
|
|
|
@ -1,566 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <functional>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include "ace_radial.h"
|
|
||||||
|
|
||||||
const DOUBLE_TYPE pi = 3.14159265358979323846264338327950288419; // pi
|
|
||||||
|
|
||||||
ACERadialFunctions::ACERadialFunctions(NS_TYPE nradb, LS_TYPE lmax, NS_TYPE nradial, DOUBLE_TYPE deltaSplineBins,
|
|
||||||
SPECIES_TYPE nelements,
|
|
||||||
DOUBLE_TYPE cutoff, string radbasename) {
|
|
||||||
init(nradb, lmax, nradial, deltaSplineBins, nelements, cutoff, radbasename);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACERadialFunctions::init(NS_TYPE nradb, LS_TYPE lmax, NS_TYPE nradial, DOUBLE_TYPE deltaSplineBins,
|
|
||||||
SPECIES_TYPE nelements,
|
|
||||||
DOUBLE_TYPE cutoff, string radbasename) {
|
|
||||||
this->nradbase = nradb;
|
|
||||||
this->lmax = lmax;
|
|
||||||
this->nradial = nradial;
|
|
||||||
this->deltaSplineBins = deltaSplineBins;
|
|
||||||
this->nelements = nelements;
|
|
||||||
this->cutoff = cutoff;
|
|
||||||
this->radbasename = radbasename;
|
|
||||||
|
|
||||||
gr.init(nradbase, "gr");
|
|
||||||
dgr.init(nradbase, "dgr");
|
|
||||||
d2gr.init(nradbase, "d2gr");
|
|
||||||
|
|
||||||
|
|
||||||
fr.init(nradial, lmax + 1, "fr");
|
|
||||||
dfr.init(nradial, lmax + 1, "dfr");
|
|
||||||
d2fr.init(nradial, lmax + 1, "d2fr");
|
|
||||||
|
|
||||||
|
|
||||||
cheb.init(nradbase + 1, "cheb");
|
|
||||||
dcheb.init(nradbase + 1, "dcheb");
|
|
||||||
cheb2.init(nradbase + 1, "cheb2");
|
|
||||||
|
|
||||||
|
|
||||||
splines_gk.init(nelements, nelements, "splines_gk");
|
|
||||||
splines_rnl.init(nelements, nelements, "splines_rnl");
|
|
||||||
splines_hc.init(nelements, nelements, "splines_hc");
|
|
||||||
|
|
||||||
lambda.init(nelements, nelements, "lambda");
|
|
||||||
lambda.fill(1.);
|
|
||||||
|
|
||||||
cut.init(nelements, nelements, "cut");
|
|
||||||
cut.fill(1.);
|
|
||||||
|
|
||||||
dcut.init(nelements, nelements, "dcut");
|
|
||||||
dcut.fill(1.);
|
|
||||||
|
|
||||||
crad.init(nelements, nelements, nradial, (lmax + 1), nradbase, "crad");
|
|
||||||
crad.fill(0.);
|
|
||||||
|
|
||||||
//hard-core repulsion
|
|
||||||
prehc.init(nelements, nelements, "prehc");
|
|
||||||
prehc.fill(0.);
|
|
||||||
|
|
||||||
lambdahc.init(nelements, nelements, "lambdahc");
|
|
||||||
lambdahc.fill(1.);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Function that computes Chebyshev polynomials of first and second kind
|
|
||||||
to setup the radial functions and the derivatives
|
|
||||||
|
|
||||||
@param n, x
|
|
||||||
|
|
||||||
@returns cheb1, dcheb1
|
|
||||||
*/
|
|
||||||
void ACERadialFunctions::calcCheb(NS_TYPE n, DOUBLE_TYPE x) {
|
|
||||||
if (n < 0) {
|
|
||||||
char s[1024];
|
|
||||||
sprintf(s, "The order n of the polynomials should be positive %d\n", n);
|
|
||||||
throw std::invalid_argument(s);
|
|
||||||
}
|
|
||||||
DOUBLE_TYPE twox = 2.0 * x;
|
|
||||||
cheb(0) = 1.;
|
|
||||||
dcheb(0) = 0.;
|
|
||||||
cheb2(0) = 1.;
|
|
||||||
|
|
||||||
if (nradbase > 1) {
|
|
||||||
cheb(1) = x;
|
|
||||||
cheb2(1) = twox;
|
|
||||||
}
|
|
||||||
for (NS_TYPE m = 1; m <= n - 1; m++) {
|
|
||||||
cheb(m + 1) = twox * cheb(m) - cheb(m - 1);
|
|
||||||
cheb2(m + 1) = twox * cheb2(m) - cheb2(m - 1);
|
|
||||||
}
|
|
||||||
for (NS_TYPE m = 1; m <= n; m++) {
|
|
||||||
dcheb(m) = m * cheb2(m - 1);
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_RADIAL
|
|
||||||
for ( NS_TYPE m=0; m<=n; m++ ) {
|
|
||||||
printf(" m %d cheb %f dcheb %f \n", m, cheb(m), dcheb(m));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Function that computes radial basis.
|
|
||||||
|
|
||||||
@param lam, nradbase, cut, dcut, r
|
|
||||||
|
|
||||||
@returns gr, dgr
|
|
||||||
*/
|
|
||||||
void ACERadialFunctions::radbase(DOUBLE_TYPE lam, DOUBLE_TYPE cut, DOUBLE_TYPE dcut, DOUBLE_TYPE r) {
|
|
||||||
/*lam is given by the formula (24), that contains cut */
|
|
||||||
|
|
||||||
if (r < cut) {
|
|
||||||
if (radbasename == "ChebExpCos") {
|
|
||||||
chebExpCos(lam, cut, dcut, r);
|
|
||||||
} else if (radbasename == "ChebPow") {
|
|
||||||
chebPow(lam, cut, dcut, r);
|
|
||||||
} else if (radbasename == "ChebLinear") {
|
|
||||||
chebLinear(lam, cut, dcut, r);
|
|
||||||
} else {
|
|
||||||
throw invalid_argument("Unknown radial basis function name: " + radbasename);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gr.fill(0);
|
|
||||||
dgr.fill(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Radial function: ChebExpCos, cheb exp scaling including cos envelope
|
|
||||||
* @param lam function parameter
|
|
||||||
* @param cut cutoff distance
|
|
||||||
* @param r function input argument
|
|
||||||
* @return fills in gr and dgr arrays
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ACERadialFunctions::chebExpCos(DOUBLE_TYPE lam, DOUBLE_TYPE cut, DOUBLE_TYPE dcut, DOUBLE_TYPE r) {
|
|
||||||
DOUBLE_TYPE y2, y1, x, dx;
|
|
||||||
DOUBLE_TYPE env, denv, fcut, dfcut;
|
|
||||||
/* scaled distance x and derivative*/
|
|
||||||
y1 = exp(-lam * r / cut);
|
|
||||||
y2 = exp(-lam);
|
|
||||||
x = 1.0 - 2.0 * ((y1 - y2) / (1 - y2));
|
|
||||||
dx = 2 * (lam / cut) * (y1 / (1 - y2));
|
|
||||||
/* calculation of Chebyshev polynomials from the recursion */
|
|
||||||
calcCheb(nradbase - 1, x);
|
|
||||||
gr(0) = cheb(0);
|
|
||||||
dgr(0) = dcheb(0) * dx;
|
|
||||||
for (NS_TYPE n = 2; n <= nradbase; n++) {
|
|
||||||
gr(n - 1) = 0.5 - 0.5 * cheb(n - 1);
|
|
||||||
dgr(n - 1) = -0.5 * dcheb(n - 1) * dx;
|
|
||||||
}
|
|
||||||
env = 0.5 * (1.0 + cos(M_PI * r / cut));
|
|
||||||
denv = -0.5 * sin(M_PI * r / cut) * M_PI / cut;
|
|
||||||
for (NS_TYPE n = 0; n < nradbase; n++) {
|
|
||||||
dgr(n) = gr(n) * denv + dgr(n) * env;
|
|
||||||
gr(n) = gr(n) * env;
|
|
||||||
}
|
|
||||||
// for radtype = 3 a smooth cut is already included in the basis function
|
|
||||||
dx = cut - dcut;
|
|
||||||
if (r > dx) {
|
|
||||||
fcut = 0.5 * (1.0 + cos(M_PI * (r - dx) / dcut));
|
|
||||||
dfcut = -0.5 * sin(M_PI * (r - dx) / dcut) * M_PI / dcut;
|
|
||||||
for (NS_TYPE n = 0; n < nradbase; n++) {
|
|
||||||
dgr(n) = gr(n) * dfcut + dgr(n) * fcut;
|
|
||||||
gr(n) = gr(n) * fcut;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Radial function: ChebPow, Radial function: ChebPow
|
|
||||||
* - argument of Chebyshev polynomials
|
|
||||||
* x = 2.0*( 1.0 - (1.0 - r/rcut)^lam ) - 1.0
|
|
||||||
* - radial function
|
|
||||||
* gr(n) = ( 1.0 - Cheb(n) )/2.0, n = 1,...,nradbase
|
|
||||||
* - the function fulfills:
|
|
||||||
* gr(n) = 0 at rcut
|
|
||||||
* dgr(n) = 0 at rcut for lam >= 1
|
|
||||||
* second derivative zero at rcut for lam >= 2
|
|
||||||
* -> the radial function does not require a separate cutoff function
|
|
||||||
* - corresponds to radial basis radtype=5 in Fortran code
|
|
||||||
*
|
|
||||||
* @param lam function parameter
|
|
||||||
* @param cut cutoff distance
|
|
||||||
* @param r function input argument
|
|
||||||
* @return fills in gr and dgr arrays
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ACERadialFunctions::chebPow(DOUBLE_TYPE lam, DOUBLE_TYPE cut, DOUBLE_TYPE dcut, DOUBLE_TYPE r) {
|
|
||||||
DOUBLE_TYPE y, dy, x, dx;
|
|
||||||
/* scaled distance x and derivative*/
|
|
||||||
y = (1.0 - r / cut);
|
|
||||||
dy = pow(y, (lam - 1.0));
|
|
||||||
y = dy * y;
|
|
||||||
dy = -lam / cut * dy;
|
|
||||||
|
|
||||||
x = 2.0 * (1.0 - y) - 1.0;
|
|
||||||
dx = -2.0 * dy;
|
|
||||||
calcCheb(nradbase, x);
|
|
||||||
for (NS_TYPE n = 1; n <= nradbase; n++) {
|
|
||||||
gr(n - 1) = 0.5 - 0.5 * cheb(n);
|
|
||||||
dgr(n - 1) = -0.5 * dcheb(n) * dx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ACERadialFunctions::chebLinear(DOUBLE_TYPE lam, DOUBLE_TYPE cut, DOUBLE_TYPE dcut, DOUBLE_TYPE r) {
|
|
||||||
DOUBLE_TYPE x, dx;
|
|
||||||
/* scaled distance x and derivative*/
|
|
||||||
x = (1.0 - r / cut);
|
|
||||||
dx = -1 / cut;
|
|
||||||
calcCheb(nradbase, x);
|
|
||||||
for (NS_TYPE n = 1; n <= nradbase; n++) {
|
|
||||||
gr(n - 1) = 0.5 - 0.5 * cheb(n);
|
|
||||||
dgr(n - 1) = -0.5 * dcheb(n) * dx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Function that computes radial functions.
|
|
||||||
|
|
||||||
@param nradbase, nelements, elei, elej
|
|
||||||
|
|
||||||
@returns fr, dfr
|
|
||||||
*/
|
|
||||||
void ACERadialFunctions::radfunc(SPECIES_TYPE elei, SPECIES_TYPE elej) {
|
|
||||||
DOUBLE_TYPE frval, dfrval;
|
|
||||||
for (NS_TYPE n = 0; n < nradial; n++) {
|
|
||||||
for (LS_TYPE l = 0; l <= lmax; l++) {
|
|
||||||
frval = 0.0;
|
|
||||||
dfrval = 0.0;
|
|
||||||
for (NS_TYPE k = 0; k < nradbase; k++) {
|
|
||||||
frval += crad(elei, elej, n, l, k) * gr(k);
|
|
||||||
dfrval += crad(elei, elej, n, l, k) * dgr(k);
|
|
||||||
}
|
|
||||||
fr(n, l) = frval;
|
|
||||||
dfr(n, l) = dfrval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ACERadialFunctions::all_radfunc(SPECIES_TYPE mu_i, SPECIES_TYPE mu_j, DOUBLE_TYPE r) {
|
|
||||||
DOUBLE_TYPE lam = lambda(mu_i, mu_j);
|
|
||||||
DOUBLE_TYPE r_cut = cut(mu_i, mu_j);
|
|
||||||
DOUBLE_TYPE dr_cut = dcut(mu_i, mu_j);
|
|
||||||
// set up radial functions
|
|
||||||
radbase(lam, r_cut, dr_cut, r); //update gr, dgr
|
|
||||||
radfunc(mu_i, mu_j); // update fr(nr, l), dfr(nr, l)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ACERadialFunctions::setuplookupRadspline() {
|
|
||||||
using namespace std::placeholders;
|
|
||||||
DOUBLE_TYPE lam, r_cut, dr_cut;
|
|
||||||
DOUBLE_TYPE cr_c, dcr_c, pre, lamhc;
|
|
||||||
|
|
||||||
// at r = rcut + eps the function and its derivatives is zero
|
|
||||||
for (SPECIES_TYPE elei = 0; elei < nelements; elei++) {
|
|
||||||
for (SPECIES_TYPE elej = 0; elej < nelements; elej++) {
|
|
||||||
|
|
||||||
lam = lambda(elei, elej);
|
|
||||||
r_cut = cut(elei, elej);
|
|
||||||
dr_cut = dcut(elei, elej);
|
|
||||||
|
|
||||||
splines_gk(elei, elej).setupSplines(gr.get_size(),
|
|
||||||
std::bind(&ACERadialFunctions::radbase, this, lam, r_cut, dr_cut,
|
|
||||||
_1),//update gr, dgr
|
|
||||||
gr.get_data(),
|
|
||||||
dgr.get_data(), deltaSplineBins, cutoff);
|
|
||||||
|
|
||||||
splines_rnl(elei, elej).setupSplines(fr.get_size(),
|
|
||||||
std::bind(&ACERadialFunctions::all_radfunc, this, elei, elej,
|
|
||||||
_1), // update fr(nr, l), dfr(nr, l)
|
|
||||||
fr.get_data(),
|
|
||||||
dfr.get_data(), deltaSplineBins, cutoff);
|
|
||||||
|
|
||||||
|
|
||||||
pre = prehc(elei, elej);
|
|
||||||
lamhc = lambdahc(elei, elej);
|
|
||||||
// radcore(r, pre, lamhc, cutoff, cr_c, dcr_c);
|
|
||||||
splines_hc(elei, elej).setupSplines(1,
|
|
||||||
std::bind(&ACERadialFunctions::radcore, _1, pre, lamhc, cutoff,
|
|
||||||
std::ref(cr_c), std::ref(dcr_c)),
|
|
||||||
&cr_c,
|
|
||||||
&dcr_c, deltaSplineBins, cutoff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Function that gets radial function from look-up table using splines.
|
|
||||||
|
|
||||||
@param r, nradbase_c, nradial_c, lmax, mu_i, mu_j
|
|
||||||
|
|
||||||
@returns fr, dfr, gr, dgr, cr, dcr
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ACERadialFunctions::evaluate(DOUBLE_TYPE r, NS_TYPE nradbase_c, NS_TYPE nradial_c, SPECIES_TYPE mu_i,
|
|
||||||
SPECIES_TYPE mu_j, bool calc_second_derivatives) {
|
|
||||||
auto &spline_gk = splines_gk(mu_i, mu_j);
|
|
||||||
auto &spline_rnl = splines_rnl(mu_i, mu_j);
|
|
||||||
auto &spline_hc = splines_hc(mu_i, mu_j);
|
|
||||||
|
|
||||||
spline_gk.calcSplines(r, calc_second_derivatives); // populate splines_gk.values, splines_gk.derivatives;
|
|
||||||
for (NS_TYPE nr = 0; nr < nradbase_c; nr++) {
|
|
||||||
gr(nr) = spline_gk.values(nr);
|
|
||||||
dgr(nr) = spline_gk.derivatives(nr);
|
|
||||||
if (calc_second_derivatives)
|
|
||||||
d2gr(nr) = spline_gk.second_derivatives(nr);
|
|
||||||
}
|
|
||||||
|
|
||||||
spline_rnl.calcSplines(r, calc_second_derivatives);
|
|
||||||
for (size_t ind = 0; ind < fr.get_size(); ind++) {
|
|
||||||
fr.get_data(ind) = spline_rnl.values.get_data(ind);
|
|
||||||
dfr.get_data(ind) = spline_rnl.derivatives.get_data(ind);
|
|
||||||
if (calc_second_derivatives)
|
|
||||||
d2fr.get_data(ind) = spline_rnl.second_derivatives.get_data(ind);
|
|
||||||
}
|
|
||||||
|
|
||||||
spline_hc.calcSplines(r, calc_second_derivatives);
|
|
||||||
cr = spline_hc.values(0);
|
|
||||||
dcr = spline_hc.derivatives(0);
|
|
||||||
if (calc_second_derivatives)
|
|
||||||
d2cr = spline_hc.second_derivatives(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ACERadialFunctions::radcore(DOUBLE_TYPE r, DOUBLE_TYPE pre, DOUBLE_TYPE lambda, DOUBLE_TYPE cutoff, DOUBLE_TYPE &cr,
|
|
||||||
DOUBLE_TYPE &dcr) {
|
|
||||||
/* pseudocode for hard core repulsion
|
|
||||||
in:
|
|
||||||
r: distance
|
|
||||||
pre: prefactor: read from input, depends on pair of atoms mu_i mu_j
|
|
||||||
lambda: exponent: read from input, depends on pair of atoms mu_i mu_j
|
|
||||||
cutoff: cutoff distance: read from input, depends on pair of atoms mu_i mu_j
|
|
||||||
out:
|
|
||||||
cr: hard core repulsion
|
|
||||||
dcr: derivative of hard core repulsion
|
|
||||||
|
|
||||||
function
|
|
||||||
\$f f_{core} = pre \exp( - \lambda r^2 ) / r \$f
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
DOUBLE_TYPE r2, lr2, y, x0, env, denv;
|
|
||||||
|
|
||||||
// repulsion strictly positive and decaying
|
|
||||||
pre = abs(pre);
|
|
||||||
lambda = abs(lambda);
|
|
||||||
|
|
||||||
r2 = r * r;
|
|
||||||
lr2 = lambda * r2;
|
|
||||||
if (lr2 < 50.0) {
|
|
||||||
y = exp(-lr2);
|
|
||||||
cr = pre * y / r;
|
|
||||||
dcr = -pre * y * (2.0 * lr2 + 1.0) / r2;
|
|
||||||
|
|
||||||
x0 = r / cutoff;
|
|
||||||
env = 0.5 * (1.0 + cos(pi * x0));
|
|
||||||
denv = -0.5 * sin(pi * x0) * pi / cutoff;
|
|
||||||
dcr = cr * denv + dcr * env;
|
|
||||||
cr = cr * env;
|
|
||||||
} else {
|
|
||||||
cr = 0.0;
|
|
||||||
dcr = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ACERadialFunctions::evaluate_range(vector<DOUBLE_TYPE> r_vec, NS_TYPE nradbase_c, NS_TYPE nradial_c, SPECIES_TYPE mu_i,
|
|
||||||
SPECIES_TYPE mu_j) {
|
|
||||||
if (nradbase_c > nradbase)
|
|
||||||
throw invalid_argument("nradbase_c couldn't be larger than nradbase");
|
|
||||||
if (nradial_c > nradial)
|
|
||||||
throw invalid_argument("nradial_c couldn't be larger than nradial");
|
|
||||||
if (mu_i > nelements)
|
|
||||||
throw invalid_argument("mu_i couldn't be larger than nelements");
|
|
||||||
if (mu_j > nelements)
|
|
||||||
throw invalid_argument("mu_j couldn't be larger than nelements");
|
|
||||||
|
|
||||||
gr_vec.resize(r_vec.size(), nradbase_c);
|
|
||||||
dgr_vec.resize(r_vec.size(), nradbase_c);
|
|
||||||
d2gr_vec.resize(r_vec.size(), nradbase_c);
|
|
||||||
|
|
||||||
fr_vec.resize(r_vec.size(), fr.get_dim(0), fr.get_dim(1));
|
|
||||||
dfr_vec.resize(r_vec.size(), fr.get_dim(0), fr.get_dim(1));
|
|
||||||
d2fr_vec.resize(r_vec.size(), fr.get_dim(0), fr.get_dim(1));
|
|
||||||
|
|
||||||
for (size_t i = 0; i < r_vec.size(); i++) {
|
|
||||||
DOUBLE_TYPE r = r_vec[i];
|
|
||||||
this->evaluate(r, nradbase_c, nradial_c, mu_i, mu_j, true);
|
|
||||||
for (NS_TYPE nr = 0; nr < nradbase_c; nr++) {
|
|
||||||
gr_vec(i, nr) = gr(nr);
|
|
||||||
dgr_vec(i, nr) = dgr(nr);
|
|
||||||
d2gr_vec(i, nr) = d2gr(nr);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (NS_TYPE nr = 0; nr < nradial_c; nr++) {
|
|
||||||
for (LS_TYPE l = 0; l <= lmax; l++) {
|
|
||||||
fr_vec(i, nr, l) = fr(nr, l);
|
|
||||||
dfr_vec(i, nr, l) = dfr(nr, l);
|
|
||||||
d2fr_vec(i, nr, l) = d2fr(nr, l);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineInterpolator::setupSplines(int num_of_functions, RadialFunctions func,
|
|
||||||
DOUBLE_TYPE *values,
|
|
||||||
DOUBLE_TYPE *dvalues, DOUBLE_TYPE deltaSplineBins, DOUBLE_TYPE cutoff) {
|
|
||||||
|
|
||||||
this->deltaSplineBins = deltaSplineBins;
|
|
||||||
this->cutoff = cutoff;
|
|
||||||
this->ntot = static_cast<int>(cutoff / deltaSplineBins);
|
|
||||||
|
|
||||||
DOUBLE_TYPE r, c[4];
|
|
||||||
this->num_of_functions = num_of_functions;
|
|
||||||
this->values.resize(num_of_functions);
|
|
||||||
this->derivatives.resize(num_of_functions);
|
|
||||||
this->second_derivatives.resize(num_of_functions);
|
|
||||||
|
|
||||||
Array1D<DOUBLE_TYPE> f1g(num_of_functions);
|
|
||||||
Array1D<DOUBLE_TYPE> f1gd1(num_of_functions);
|
|
||||||
f1g.fill(0);
|
|
||||||
f1gd1.fill(0);
|
|
||||||
|
|
||||||
nlut = ntot;
|
|
||||||
DOUBLE_TYPE f0, f1, f0d1, f1d1;
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
// cutoff is global cutoff
|
|
||||||
rscalelookup = (DOUBLE_TYPE) nlut / cutoff;
|
|
||||||
invrscalelookup = 1.0 / rscalelookup;
|
|
||||||
|
|
||||||
lookupTable.init(ntot + 1, num_of_functions, 4);
|
|
||||||
if (values == nullptr & num_of_functions > 0)
|
|
||||||
throw invalid_argument("SplineInterpolator::setupSplines: values could not be null");
|
|
||||||
if (dvalues == nullptr & num_of_functions > 0)
|
|
||||||
throw invalid_argument("SplineInterpolator::setupSplines: dvalues could not be null");
|
|
||||||
|
|
||||||
for (int n = nlut; n >= 1; n--) {
|
|
||||||
r = invrscalelookup * DOUBLE_TYPE(n);
|
|
||||||
func(r); //populate values and dvalues arrays
|
|
||||||
for (int func_id = 0; func_id < num_of_functions; func_id++) {
|
|
||||||
f0 = values[func_id];
|
|
||||||
f1 = f1g(func_id);
|
|
||||||
f0d1 = dvalues[func_id] * invrscalelookup;
|
|
||||||
f1d1 = f1gd1(func_id);
|
|
||||||
// evaluate coefficients
|
|
||||||
c[0] = f0;
|
|
||||||
c[1] = f0d1;
|
|
||||||
c[2] = 3.0 * (f1 - f0) - f1d1 - 2.0 * f0d1;
|
|
||||||
c[3] = -2.0 * (f1 - f0) + f1d1 + f0d1;
|
|
||||||
// store coefficients
|
|
||||||
for (idx = 0; idx <= 3; idx++)
|
|
||||||
lookupTable(n, func_id, idx) = c[idx];
|
|
||||||
|
|
||||||
// evaluate function values and derivatives at current position
|
|
||||||
f1g(func_id) = c[0];
|
|
||||||
f1gd1(func_id) = c[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SplineInterpolator::calcSplines(DOUBLE_TYPE r, bool calc_second_derivatives) {
|
|
||||||
DOUBLE_TYPE wl, wl2, wl3, w2l1, w3l2, w4l2;
|
|
||||||
DOUBLE_TYPE c[4];
|
|
||||||
int func_id, idx;
|
|
||||||
DOUBLE_TYPE x = r * rscalelookup;
|
|
||||||
int nl = static_cast<int>(floor(x));
|
|
||||||
|
|
||||||
if (nl <= 0)
|
|
||||||
throw std::invalid_argument("Encountered very small distance. Stopping.");
|
|
||||||
|
|
||||||
if (nl < nlut) {
|
|
||||||
wl = x - DOUBLE_TYPE(nl);
|
|
||||||
wl2 = wl * wl;
|
|
||||||
wl3 = wl2 * wl;
|
|
||||||
w2l1 = 2.0 * wl;
|
|
||||||
w3l2 = 3.0 * wl2;
|
|
||||||
w4l2 = 6.0 * wl;
|
|
||||||
for (func_id = 0; func_id < num_of_functions; func_id++) {
|
|
||||||
for (idx = 0; idx <= 3; idx++) {
|
|
||||||
c[idx] = lookupTable(nl, func_id, idx);
|
|
||||||
}
|
|
||||||
values(func_id) = c[0] + c[1] * wl + c[2] * wl2 + c[3] * wl3;
|
|
||||||
derivatives(func_id) = (c[1] + c[2] * w2l1 + c[3] * w3l2) * rscalelookup;
|
|
||||||
if (calc_second_derivatives)
|
|
||||||
second_derivatives(func_id) = (c[2] + c[3] * w4l2) * rscalelookup * rscalelookup * 2;
|
|
||||||
}
|
|
||||||
} else { // fill with zeroes
|
|
||||||
values.fill(0);
|
|
||||||
derivatives.fill(0);
|
|
||||||
if (calc_second_derivatives)
|
|
||||||
second_derivatives.fill(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineInterpolator::calcSplines(DOUBLE_TYPE r, SHORT_INT_TYPE func_ind) {
|
|
||||||
DOUBLE_TYPE wl, wl2, wl3, w2l1, w3l2;
|
|
||||||
DOUBLE_TYPE c[4];
|
|
||||||
int idx;
|
|
||||||
DOUBLE_TYPE x = r * rscalelookup;
|
|
||||||
int nl = static_cast<int>(floor(x));
|
|
||||||
|
|
||||||
if (nl <= 0)
|
|
||||||
throw std::invalid_argument("Encountered very small distance. Stopping.");
|
|
||||||
|
|
||||||
if (nl < nlut) {
|
|
||||||
wl = x - DOUBLE_TYPE(nl);
|
|
||||||
wl2 = wl * wl;
|
|
||||||
wl3 = wl2 * wl;
|
|
||||||
w2l1 = 2.0 * wl;
|
|
||||||
w3l2 = 3.0 * wl2;
|
|
||||||
|
|
||||||
for (idx = 0; idx <= 3; idx++) {
|
|
||||||
c[idx] = lookupTable(nl, func_ind, idx);
|
|
||||||
}
|
|
||||||
values(func_ind) = c[0] + c[1] * wl + c[2] * wl2 + c[3] * wl3;
|
|
||||||
derivatives(func_ind) = (c[1] + c[2] * w2l1 + c[3] * w3l2) * rscalelookup;
|
|
||||||
|
|
||||||
} else { // fill with zeroes
|
|
||||||
values(func_ind) = 0;
|
|
||||||
derivatives(func_ind) = 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,324 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ACE_RADIAL_FUNCTIONS_H
|
|
||||||
#define ACE_RADIAL_FUNCTIONS_H
|
|
||||||
|
|
||||||
#include "ace_arraynd.h"
|
|
||||||
#include "ace_types.h"
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//typedef void (*RadialFunctions)(DOUBLE_TYPE x);
|
|
||||||
typedef std::function<void(DOUBLE_TYPE)> RadialFunctions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that implement spline interpolation and caching for radial functions
|
|
||||||
*/
|
|
||||||
class SplineInterpolator {
|
|
||||||
public:
|
|
||||||
DOUBLE_TYPE cutoff = 0; ///< cutoff
|
|
||||||
DOUBLE_TYPE deltaSplineBins = 0.001;
|
|
||||||
int ntot = 10000; ///< Number of bins for look-up tables.
|
|
||||||
int nlut = 10000; ///< number of nodes in look-up table
|
|
||||||
DOUBLE_TYPE invrscalelookup = 1; ///< inverse of conversion coefficient from distance to lookup table within cutoff range
|
|
||||||
DOUBLE_TYPE rscalelookup = 1; ///< conversion coefficient from distance to lookup table within cutoff range
|
|
||||||
int num_of_functions = 0;///< number of functions to spline-interpolation
|
|
||||||
|
|
||||||
Array1D<DOUBLE_TYPE> values;// = Array1D<DOUBLE_TYPE>("values"); ///< shape: [func_ind]
|
|
||||||
Array1D<DOUBLE_TYPE> derivatives;// = Array1D<DOUBLE_TYPE>("derivatives");///< shape: [func_ind]
|
|
||||||
Array1D<DOUBLE_TYPE> second_derivatives;// = Array1D<DOUBLE_TYPE>("second_derivatives");///< shape: [func_ind]
|
|
||||||
|
|
||||||
Array3D<DOUBLE_TYPE> lookupTable = Array3D<DOUBLE_TYPE>("lookupTable");///< shape: [ntot+1][func_ind][4]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup splines
|
|
||||||
*
|
|
||||||
* @param num_of_functions number of functions
|
|
||||||
* @param func subroutine, that update `values` and `dvalues` arrays
|
|
||||||
* @param values values
|
|
||||||
* @param dvalues derivatives
|
|
||||||
*/
|
|
||||||
void setupSplines(int num_of_functions, RadialFunctions func,
|
|
||||||
DOUBLE_TYPE *values,
|
|
||||||
DOUBLE_TYPE *dvalues, DOUBLE_TYPE deltaSplineBins, DOUBLE_TYPE cutoff);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populate `values` and `derivatives` arrays with a spline-interpolation for
|
|
||||||
* all functions
|
|
||||||
*
|
|
||||||
* @param r
|
|
||||||
*
|
|
||||||
* @return: populate 'values' and 'derivatives'
|
|
||||||
*/
|
|
||||||
void calcSplines(DOUBLE_TYPE r, bool calc_second_derivatives = false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populate `values` and `derivatives` arrays with a spline-interpolation for
|
|
||||||
* all functions
|
|
||||||
*
|
|
||||||
* @param r
|
|
||||||
*
|
|
||||||
* @return: populate 'values' and 'derivatives'
|
|
||||||
*/
|
|
||||||
void calcSplines(DOUBLE_TYPE r, SHORT_INT_TYPE func_ind);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface class for radial basis functions with rank=1 (g_k), R_nl (rank>1) and hard-core repulsion radial functions
|
|
||||||
*/
|
|
||||||
class AbstractRadialBasis {
|
|
||||||
public:
|
|
||||||
SPECIES_TYPE nelements = 0; ///< number of elements
|
|
||||||
Array2D<DOUBLE_TYPE> cut = Array2D<DOUBLE_TYPE>("cut"); ///< cutoffs, shape: [nelements][nelements]
|
|
||||||
Array2D<DOUBLE_TYPE> dcut = Array2D<DOUBLE_TYPE>("dcut"); ///< decay of cutoff, shape: [nelements][nelements]
|
|
||||||
DOUBLE_TYPE cutoff = 0; ///< cutoff
|
|
||||||
|
|
||||||
// int ntot = 10000; ///< Number of bins for look-up tables.
|
|
||||||
DOUBLE_TYPE deltaSplineBins;
|
|
||||||
LS_TYPE lmax = 0; ///< maximum value of `l`
|
|
||||||
NS_TYPE nradial = 0; ///< maximum number `n` of radial functions \f$ R_{nl}(r) \f$
|
|
||||||
NS_TYPE nradbase = 0; ///< number of radial basis functions \f$ g_k(r) \f$
|
|
||||||
|
|
||||||
// Arrays for look-up tables.
|
|
||||||
Array2D<SplineInterpolator> splines_gk; ///< array of spline interpolator to store g_k, shape: [nelements][nelements]
|
|
||||||
Array2D<SplineInterpolator> splines_rnl; ///< array of spline interpolator to store R_nl, shape: [nelements][nelements]
|
|
||||||
Array2D<SplineInterpolator> splines_hc; ///< array of spline interpolator to store R_nl shape: [nelements][nelements]
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
string radbasename = "ChebExpCos"; ///< type of radial basis functions \f$ g_{k}(r) \f$ (default="ChebExpCos")
|
|
||||||
|
|
||||||
/**
|
|
||||||
Arrays to store radial functions.
|
|
||||||
*/
|
|
||||||
Array1D<DOUBLE_TYPE> gr = Array1D<DOUBLE_TYPE>("gr"); ///< g_k(r) functions, shape: [nradbase]
|
|
||||||
Array1D<DOUBLE_TYPE> dgr = Array1D<DOUBLE_TYPE>("dgr"); ///< derivatives of g_k(r) functions, shape: [nradbase]
|
|
||||||
Array1D<DOUBLE_TYPE> d2gr = Array1D<DOUBLE_TYPE>("d2gr"); ///< derivatives of g_k(r) functions, shape: [nradbase]
|
|
||||||
|
|
||||||
Array2D<DOUBLE_TYPE> fr = Array2D<DOUBLE_TYPE>("fr"); ///< R_nl(r) functions, shape: [nradial][lmax+1]
|
|
||||||
Array2D<DOUBLE_TYPE> dfr = Array2D<DOUBLE_TYPE>(
|
|
||||||
"dfr"); ///< derivatives of R_nl(r) functions, shape: [nradial][lmax+1]
|
|
||||||
Array2D<DOUBLE_TYPE> d2fr = Array2D<DOUBLE_TYPE>(
|
|
||||||
"d2fr"); ///< derivatives of R_nl(r) functions, shape: [nradial][lmax+1]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DOUBLE_TYPE cr; ///< hard-core repulsion
|
|
||||||
DOUBLE_TYPE dcr; ///< derivative of hard-core repulsion
|
|
||||||
DOUBLE_TYPE d2cr; ///< derivative of hard-core repulsion
|
|
||||||
|
|
||||||
Array5D<DOUBLE_TYPE> crad = Array5D<DOUBLE_TYPE>(
|
|
||||||
"crad"); ///< expansion coefficients of radial functions into radial basis function, see Eq. (27) of PRB, shape: [nelements][nelements][lmax + 1][nradial][nradbase]
|
|
||||||
Array2D<DOUBLE_TYPE> lambda = Array2D<DOUBLE_TYPE>(
|
|
||||||
"lambda"); ///< distance scaling parameter Eq.(24) of PRB, shape: [nelements][nelements]
|
|
||||||
|
|
||||||
Array2D<DOUBLE_TYPE> prehc = Array2D<DOUBLE_TYPE>(
|
|
||||||
"prehc"); ///< hard-core repulsion coefficients (prefactor), shape: [nelements][nelements]
|
|
||||||
Array2D<DOUBLE_TYPE> lambdahc = Array2D<DOUBLE_TYPE>(
|
|
||||||
"lambdahc");; ///< hard-core repulsion coefficients (lambdahc), shape: [nelements][nelements]
|
|
||||||
|
|
||||||
virtual void
|
|
||||||
evaluate(DOUBLE_TYPE r, NS_TYPE nradbase_c, NS_TYPE nradial_c, SPECIES_TYPE mu_i, SPECIES_TYPE mu_j,
|
|
||||||
bool calc_second_derivatives = false) = 0;
|
|
||||||
|
|
||||||
virtual void
|
|
||||||
init(NS_TYPE nradb, LS_TYPE lmax, NS_TYPE nradial, DOUBLE_TYPE deltaSplineBins, SPECIES_TYPE nelements,
|
|
||||||
DOUBLE_TYPE cutoff,
|
|
||||||
string radbasename = "ChebExpCos") = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that sets up the look-up tables for spline-representation of radial functions.
|
|
||||||
*/
|
|
||||||
virtual void setuplookupRadspline() = 0;
|
|
||||||
|
|
||||||
virtual AbstractRadialBasis *clone() const = 0;
|
|
||||||
|
|
||||||
virtual ~AbstractRadialBasis() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Class to store radial functions and their associated functions. \n
|
|
||||||
*/
|
|
||||||
class ACERadialFunctions final : public AbstractRadialBasis {
|
|
||||||
public:
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
Arrays to store Chebyshev polynomials.
|
|
||||||
*/
|
|
||||||
Array1D<DOUBLE_TYPE> cheb = Array1D<DOUBLE_TYPE>(
|
|
||||||
"cheb"); ///< Chebyshev polynomials of the first kind, shape: [nradbase+1]
|
|
||||||
Array1D<DOUBLE_TYPE> dcheb = Array1D<DOUBLE_TYPE>(
|
|
||||||
"dcheb"); ///< derivatives Chebyshev polynomials of the first kind, shape: [nradbase+1]
|
|
||||||
Array1D<DOUBLE_TYPE> cheb2 = Array1D<DOUBLE_TYPE>(
|
|
||||||
"cheb2"); ///< Chebyshev polynomials of the second kind, shape: [nradbase+1]
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Array2D<DOUBLE_TYPE> gr_vec;
|
|
||||||
Array2D<DOUBLE_TYPE> dgr_vec;
|
|
||||||
Array2D<DOUBLE_TYPE> d2gr_vec;
|
|
||||||
|
|
||||||
Array3D<DOUBLE_TYPE> fr_vec;
|
|
||||||
Array3D<DOUBLE_TYPE> dfr_vec;
|
|
||||||
Array3D<DOUBLE_TYPE> d2fr_vec;
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* Default constructor
|
|
||||||
*/
|
|
||||||
ACERadialFunctions() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parametrized constructor
|
|
||||||
*
|
|
||||||
* @param nradb number of radial basis function \f$ g_k(r) \f$ - nradbase
|
|
||||||
* @param lmax maximum orbital moment - lmax
|
|
||||||
* @param nradial maximum n-index of radial functions \f$ R_{nl}(r) \f$ - nradial
|
|
||||||
* @param ntot Number of bins for spline look-up tables.
|
|
||||||
* @param nelements numer of elements
|
|
||||||
* @param cutoff cutoff
|
|
||||||
* @param radbasename type of radial basis function \f$ g_k(r) \f$ (default: "ChebExpCos")
|
|
||||||
*/
|
|
||||||
ACERadialFunctions(NS_TYPE nradb, LS_TYPE lmax, NS_TYPE nradial, DOUBLE_TYPE deltaSplineBins,
|
|
||||||
SPECIES_TYPE nelements,
|
|
||||||
DOUBLE_TYPE cutoff, string radbasename = "ChebExpCos");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize arrays for given parameters
|
|
||||||
*
|
|
||||||
* @param nradb number of radial basis function \f$ g_k(r) \f$ - nradbase
|
|
||||||
* @param lmax maximum orbital moment - lmax
|
|
||||||
* @param nradial maximum n-index of radial functions \f$ R_{nl}(r) \f$ - nradial
|
|
||||||
* @param ntot Number of bins for spline look-up tables.
|
|
||||||
* @param nelements numer of elements
|
|
||||||
* @param cutoff cutoff
|
|
||||||
* @param radbasename type of radial basis function \f$ g_k(r) \f$ (default: "ChebExpCos")
|
|
||||||
*/
|
|
||||||
void init(NS_TYPE nradb, LS_TYPE lmax, NS_TYPE nradial, DOUBLE_TYPE deltaSplineBins, SPECIES_TYPE nelements,
|
|
||||||
DOUBLE_TYPE cutoff,
|
|
||||||
string radbasename = "ChebExpCos") final;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
~ACERadialFunctions() final = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that computes Chebyshev polynomials of first and second kind
|
|
||||||
* to setup the radial functions and the derivatives
|
|
||||||
*
|
|
||||||
* @param n maximum polynom order
|
|
||||||
* @param x
|
|
||||||
*
|
|
||||||
* @returns fills cheb, dcheb and cheb2 arrays
|
|
||||||
*/
|
|
||||||
void calcCheb(NS_TYPE n, DOUBLE_TYPE x);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that computes radial basis functions \$f g_k(r) \$f, see Eq.(21) of PRB paper
|
|
||||||
* @param lam \$f \lambda \$f parameter, see eq. (24) of PRB paper
|
|
||||||
* @param cut cutoff
|
|
||||||
* @param dcut cutoff decay
|
|
||||||
* @param r distance
|
|
||||||
*
|
|
||||||
* @return function fills gr and dgr arrays
|
|
||||||
*/
|
|
||||||
void radbase(DOUBLE_TYPE lam, DOUBLE_TYPE cut, DOUBLE_TYPE dcut, DOUBLE_TYPE r);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that computes radial core repulsion \$f f_{core} = pre \exp( - \lambda r^2 ) / r \$f,
|
|
||||||
* and its derivative, see Eq.(27) of implementation notes.
|
|
||||||
*
|
|
||||||
* @param r distance
|
|
||||||
* @param pre prefactor: read from input, depends on pair of atoms mu_i mu_j
|
|
||||||
* @param lambda exponent: read from input, depends on pair of atoms mu_i mu_j
|
|
||||||
* @param cutoff cutoff distance: read from input, depends on pair of atoms mu_i mu_j
|
|
||||||
* @param cr (out) hard core repulsion
|
|
||||||
* @param dcr (out) derivative of hard core repulsion
|
|
||||||
*/
|
|
||||||
static void radcore(DOUBLE_TYPE r, DOUBLE_TYPE pre, DOUBLE_TYPE lambda, DOUBLE_TYPE cutoff, DOUBLE_TYPE &cr,
|
|
||||||
DOUBLE_TYPE &dcr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that sets up the look-up tables for spline-representation of radial functions.
|
|
||||||
*/
|
|
||||||
void setuplookupRadspline() final;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that computes radial functions \f$ R_{nl}(r)\f$ (see Eq. 27 from PRB paper)
|
|
||||||
* and its derivatives for all range of n,l,
|
|
||||||
* ONLY if radial basis functions (gr and dgr) are computed.
|
|
||||||
* @param elei first species type
|
|
||||||
* @param elej second species type
|
|
||||||
*
|
|
||||||
* @return fills in fr, dfr arrays
|
|
||||||
*/
|
|
||||||
void radfunc(SPECIES_TYPE elei, SPECIES_TYPE elej);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute all radial functions R_nl(r), radial basis functions g_k(r) and hard-core repulsion function hc(r)
|
|
||||||
*
|
|
||||||
* @param r distance
|
|
||||||
* @param nradbase_c
|
|
||||||
* @param nradial_c
|
|
||||||
* @param mu_i
|
|
||||||
* @param mu_j
|
|
||||||
*
|
|
||||||
* @return update gr(k), dgr(k), fr(n,l), dfr(n,l), cr, dcr
|
|
||||||
*/
|
|
||||||
void evaluate(DOUBLE_TYPE r, NS_TYPE nradbase_c, NS_TYPE nradial_c, SPECIES_TYPE mu_i, SPECIES_TYPE mu_j,
|
|
||||||
bool calc_second_derivatives = false) final;
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
evaluate_range(vector<DOUBLE_TYPE> r_vec, NS_TYPE nradbase_c, NS_TYPE nradial_c, SPECIES_TYPE mu_i,
|
|
||||||
SPECIES_TYPE mu_j);
|
|
||||||
|
|
||||||
void chebExpCos(DOUBLE_TYPE lam, DOUBLE_TYPE cut, DOUBLE_TYPE dcut, DOUBLE_TYPE r);
|
|
||||||
|
|
||||||
void chebPow(DOUBLE_TYPE lam, DOUBLE_TYPE cut, DOUBLE_TYPE dcut, DOUBLE_TYPE r);
|
|
||||||
|
|
||||||
void chebLinear(DOUBLE_TYPE lam, DOUBLE_TYPE cut, DOUBLE_TYPE dcut, DOUBLE_TYPE r);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup all radial functions for element pair mu_i-mu_j and distance r
|
|
||||||
* @param mu_i first specie type
|
|
||||||
* @param mu_j second specie type
|
|
||||||
* @param r distance
|
|
||||||
* @return update fr(nr, l), dfr(nr, l)
|
|
||||||
*/
|
|
||||||
void all_radfunc(SPECIES_TYPE mu_i, SPECIES_TYPE mu_j, DOUBLE_TYPE r);
|
|
||||||
|
|
||||||
ACERadialFunctions *clone() const override {
|
|
||||||
return new ACERadialFunctions(*this);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,247 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Created by Christoph Ortner on 20.12.2020
|
|
||||||
|
|
||||||
#ifndef ACE_RECURSIVE_H
|
|
||||||
#define ACE_RECURSIVE_H
|
|
||||||
|
|
||||||
#include "ace_abstract_basis.h"
|
|
||||||
#include "ace_arraynd.h"
|
|
||||||
#include "ace_array2dlm.h"
|
|
||||||
#include "ace_c_basis.h"
|
|
||||||
#include "ace_complex.h"
|
|
||||||
#include "ace_timing.h"
|
|
||||||
#include "ace_types.h"
|
|
||||||
#include "ace_evaluator.h"
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <utility>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
|
||||||
typedef pair<vector<int>, vector<int> > TPARTITION;
|
|
||||||
typedef list<TPARTITION> TPARTITIONS;
|
|
||||||
|
|
||||||
typedef map<vector<int>, int> TDAGMAP;
|
|
||||||
|
|
||||||
class ACEDAG {
|
|
||||||
|
|
||||||
TPARTITIONS find_2partitions(vector<int> v);
|
|
||||||
|
|
||||||
void insert_node(TDAGMAP &dagmap,
|
|
||||||
vector<int> node,
|
|
||||||
vector<DOUBLE_TYPE> c);
|
|
||||||
|
|
||||||
// the following fields are used only for *construction*, not evaluation
|
|
||||||
int dag_idx; // current index of dag node
|
|
||||||
Array2D<int> nodes_pre; //TODO: YL: better to use vector<>
|
|
||||||
Array2D<DOUBLE_TYPE> coeffs_pre; //TODO: YL: better to use vector<>
|
|
||||||
Array1D<bool> haschild; //TODO: YL: better to use vector<>
|
|
||||||
|
|
||||||
/* which heuristic to choose for DAG construction?
|
|
||||||
* 0 : the simple original heuristic
|
|
||||||
* 1 : prioritize 2-correlation nodes and build the rest from those
|
|
||||||
*/
|
|
||||||
int heuristic = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
ACEDAG() = default;
|
|
||||||
|
|
||||||
void init(Array2D<int> Aspec, Array2D<int> AAspec,
|
|
||||||
Array1D<int> orders, Array2D<DOUBLE_TYPE> coeffs,
|
|
||||||
int heuristic );
|
|
||||||
|
|
||||||
Array1D<ACEComplex> AAbuf;
|
|
||||||
Array1D<ACEComplex> w;
|
|
||||||
|
|
||||||
Array2D<int> Aspec;
|
|
||||||
|
|
||||||
// nodes in the graph
|
|
||||||
Array2D<int> nodes;
|
|
||||||
Array2D<DOUBLE_TYPE> coeffs;
|
|
||||||
|
|
||||||
// total number of nodes in the dag
|
|
||||||
int num_nodes;
|
|
||||||
// number of interior nodes (with children)
|
|
||||||
int num2_int;
|
|
||||||
// number of leaf nodes (nc = no child)
|
|
||||||
int num2_leaf;
|
|
||||||
|
|
||||||
|
|
||||||
// number of 1-particle basis functions
|
|
||||||
// (these will be stored in the first num1 entries of AAbuf)
|
|
||||||
int get_num1() { return Aspec.get_dim(0); };
|
|
||||||
// total number of n-correlation basis functions n > 1.
|
|
||||||
int get_num2() { return num_nodes - get_num1(); };
|
|
||||||
int get_num2_int() { return num2_int; }; // with children
|
|
||||||
int get_num2_leaf() { return num2_leaf; }; // without children
|
|
||||||
|
|
||||||
// debugging tool
|
|
||||||
void print();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursive Variant of the ACETildeEvaluator; should be 100% compatible
|
|
||||||
*/
|
|
||||||
class ACERecursiveEvaluator : public ACEEvaluator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Weights \f$ \omega_{i \mu n 0 0} \f$ for rank = 1, see Eq.(10) from implementation notes,
|
|
||||||
* 'i' is fixed for the current atom, shape: [nelements][nradbase]
|
|
||||||
*/
|
|
||||||
Array2D<DOUBLE_TYPE> weights_rank1 = Array2D<DOUBLE_TYPE>("weights_rank1");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Weights \f$ \omega_{i \mu n l m} \f$ for rank > 1, see Eq.(10) from implementation notes,
|
|
||||||
* 'i' is fixed for the current atom, shape: [nelements][nradbase][l=0..lmax, m]
|
|
||||||
*/
|
|
||||||
Array4DLM<ACEComplex> weights = Array4DLM<ACEComplex>("weights");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cache for gradients of \f$ g(r)\f$: grad_phi(jj,n)=A2DLM(l,m)
|
|
||||||
* shape:[max_jnum][nradbase]
|
|
||||||
*/
|
|
||||||
Array2D<DOUBLE_TYPE> DG_cache = Array2D<DOUBLE_TYPE>("DG_cache");
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cache for \f$ R_{nl}(r)\f$
|
|
||||||
* shape:[max_jnum][nradbase][0..lmax]
|
|
||||||
*/
|
|
||||||
Array3D<DOUBLE_TYPE> R_cache = Array3D<DOUBLE_TYPE>("R_cache");
|
|
||||||
/**
|
|
||||||
* cache for derivatives of \f$ R_{nl}(r)\f$
|
|
||||||
* shape:[max_jnum][nradbase][0..lmax]
|
|
||||||
*/
|
|
||||||
Array3D<DOUBLE_TYPE> DR_cache = Array3D<DOUBLE_TYPE>("DR_cache");
|
|
||||||
/**
|
|
||||||
* cache for \f$ Y_{lm}(\hat{r})\f$
|
|
||||||
* shape:[max_jnum][0..lmax][m]
|
|
||||||
*/
|
|
||||||
Array3DLM<ACEComplex> Y_cache = Array3DLM<ACEComplex>("Y_cache");
|
|
||||||
/**
|
|
||||||
* cache for \f$ \nabla Y_{lm}(\hat{r})\f$
|
|
||||||
* shape:[max_jnum][0..lmax][m]
|
|
||||||
*/
|
|
||||||
Array3DLM<ACEDYcomponent> DY_cache = Array3DLM<ACEDYcomponent>("dY_dense_cache");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cache for derivatives of hard-core repulsion
|
|
||||||
* shape:[max_jnum]
|
|
||||||
*/
|
|
||||||
Array1D<DOUBLE_TYPE> DCR_cache = Array1D<DOUBLE_TYPE>("DCR_cache");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Partial derivatives \f$ dB_{i \mu n l m t}^{(r)} \f$ with sequential numbering over [func_ind][ms_ind][r],
|
|
||||||
* shape:[func_ms_r_ind]
|
|
||||||
*/
|
|
||||||
Array1D<ACEComplex> dB_flatten = Array1D<ACEComplex>("dB_flatten");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pointer to the ACEBasisSet object
|
|
||||||
*/
|
|
||||||
ACECTildeBasisSet *basis_set = nullptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize internal arrays according to basis set sizes
|
|
||||||
* @param basis_set
|
|
||||||
*/
|
|
||||||
void init(ACECTildeBasisSet *basis_set, int heuristic);
|
|
||||||
|
|
||||||
/* convert the PACE to the ACE.jl format to prepare for DAG construction*/
|
|
||||||
Array2D<int> jl_Aspec;
|
|
||||||
Array2D<int> jl_AAspec;
|
|
||||||
Array1D<int> jl_AAspec_flat;
|
|
||||||
Array1D<int> jl_orders;
|
|
||||||
Array2D<DOUBLE_TYPE> jl_coeffs;
|
|
||||||
void acejlformat();
|
|
||||||
|
|
||||||
/* the main event : the computational graph */
|
|
||||||
ACEDAG dag;
|
|
||||||
|
|
||||||
bool recursive = true;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
ACERecursiveEvaluator() = default;
|
|
||||||
|
|
||||||
explicit ACERecursiveEvaluator(ACECTildeBasisSet &bas,
|
|
||||||
bool recursive = true) {
|
|
||||||
set_recursive(recursive);
|
|
||||||
set_basis(bas);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the basis function to the ACE evaluator
|
|
||||||
* @param bas
|
|
||||||
*/
|
|
||||||
void set_basis(ACECTildeBasisSet &bas, int heuristic = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The key method to compute energy and forces for atom 'i'.
|
|
||||||
* Method will update the "e_atom" variable and "neighbours_forces(jj, alpha)" array
|
|
||||||
*
|
|
||||||
* @param i atom index
|
|
||||||
* @param x atomic positions array of the real and ghost atoms, shape: [atom_ind][3]
|
|
||||||
* @param type atomic types array of the real and ghost atoms, shape: [atom_ind]
|
|
||||||
* @param jnum number of neighbours of atom_i
|
|
||||||
* @param jlist array of neighbour indices, shape: [jnum]
|
|
||||||
*/
|
|
||||||
void compute_atom(int i, DOUBLE_TYPE **x, const SPECIES_TYPE *type, const int jnum, const int *jlist) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resize all caches over neighbours atoms
|
|
||||||
* @param max_jnum maximum number of neighbours
|
|
||||||
*/
|
|
||||||
void resize_neighbours_cache(int max_jnum) override;
|
|
||||||
|
|
||||||
/******* public functions related to recursive evaluator ********/
|
|
||||||
|
|
||||||
// print out the DAG for visual inspection
|
|
||||||
void print_dag() {dag.print();}
|
|
||||||
|
|
||||||
// print out the jl format for visual inspection
|
|
||||||
// should be converted into a proper test
|
|
||||||
void test_acejlformat();
|
|
||||||
|
|
||||||
void set_recursive(bool tf) { recursive = tf; }
|
|
||||||
|
|
||||||
/********************************/
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //ACE_RECURSIVE_H
|
|
|
@ -1,221 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Ralf Drautz, Yury Lysogorskiy
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "ace_spherical_cart.h"
|
|
||||||
|
|
||||||
ACECartesianSphericalHarmonics::ACECartesianSphericalHarmonics(LS_TYPE lm) {
|
|
||||||
init(lm);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ACECartesianSphericalHarmonics::init(LS_TYPE lm) {
|
|
||||||
lmax = lm;
|
|
||||||
|
|
||||||
alm.init(lmax, "alm");
|
|
||||||
blm.init(lmax, "blm");
|
|
||||||
cl.init(lmax + 1);
|
|
||||||
dl.init(lmax + 1);
|
|
||||||
|
|
||||||
plm.init(lmax, "plm");
|
|
||||||
dplm.init(lmax, "dplm");
|
|
||||||
|
|
||||||
ylm.init(lmax, "ylm");
|
|
||||||
dylm.init(lmax, "dylm");
|
|
||||||
|
|
||||||
pre_compute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Destructor for ACECartesianSphericalHarmonics.
|
|
||||||
|
|
||||||
@param None
|
|
||||||
|
|
||||||
@returns None
|
|
||||||
*/
|
|
||||||
ACECartesianSphericalHarmonics::~ACECartesianSphericalHarmonics() {}
|
|
||||||
|
|
||||||
|
|
||||||
void ACECartesianSphericalHarmonics::pre_compute() {
|
|
||||||
|
|
||||||
DOUBLE_TYPE a, b;
|
|
||||||
DOUBLE_TYPE lsq, ld, l1, l2;
|
|
||||||
DOUBLE_TYPE msq;
|
|
||||||
|
|
||||||
for (LS_TYPE l = 1; l <= lmax; l++) {
|
|
||||||
lsq = l * l;
|
|
||||||
ld = 2 * l;
|
|
||||||
l1 = (4 * lsq - 1);
|
|
||||||
l2 = lsq - ld + 1;
|
|
||||||
for (MS_TYPE m = 0; m < l - 1; m++) {
|
|
||||||
msq = m * m;
|
|
||||||
a = sqrt((DOUBLE_TYPE(l1)) / (DOUBLE_TYPE(lsq - msq)));
|
|
||||||
b = -sqrt((DOUBLE_TYPE(l2 - msq)) / (DOUBLE_TYPE(4 * l2 - 1)));
|
|
||||||
alm(l, m) = a;
|
|
||||||
blm(l, m) = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (LS_TYPE l = 1; l <= lmax; l++) {
|
|
||||||
cl(l) = -sqrt(1.0 + 0.5 / (DOUBLE_TYPE(l)));
|
|
||||||
dl(l) = sqrt(DOUBLE_TYPE(2 * (l - 1) + 3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ACECartesianSphericalHarmonics::compute_barplm(DOUBLE_TYPE rz, LS_TYPE lmaxi) {
|
|
||||||
|
|
||||||
// requires -1 <= rz <= 1 , NO CHECKING IS PERFORMED !!!!!!!!!
|
|
||||||
// prefactors include 1/sqrt(2) factor compared to reference
|
|
||||||
DOUBLE_TYPE t;
|
|
||||||
|
|
||||||
// l=0, m=0
|
|
||||||
//plm(0, 0) = Y00/sq1o4pi; //= sq1o4pi;
|
|
||||||
plm(0, 0) = Y00; //= 1;
|
|
||||||
dplm(0, 0) = 0.0;
|
|
||||||
|
|
||||||
if (lmaxi > 0) {
|
|
||||||
|
|
||||||
// l=1, m=0
|
|
||||||
plm(1, 0) = Y00 * sq3 * rz;
|
|
||||||
dplm(1, 0) = Y00 * sq3;
|
|
||||||
|
|
||||||
// l=1, m=1
|
|
||||||
plm(1, 1) = -sq3o2 * Y00;
|
|
||||||
dplm(1, 1) = 0.0;
|
|
||||||
|
|
||||||
// loop l = 2, lmax
|
|
||||||
for (LS_TYPE l = 2; l <= lmaxi; l++) {
|
|
||||||
for (MS_TYPE m = 0; m < l - 1; m++) {
|
|
||||||
plm(l, m) = alm(l, m) * (rz * plm(l - 1, m) + blm(l, m) * plm(l - 2, m));
|
|
||||||
dplm(l, m) = alm(l, m) * (plm(l - 1, m) + rz * dplm(l - 1, m) + blm(l, m) * dplm(l - 2, m));
|
|
||||||
}
|
|
||||||
t = dl(l) * plm(l - 1, l - 1);
|
|
||||||
plm(l, l - 1) = t * rz;
|
|
||||||
dplm(l, l - 1) = t;
|
|
||||||
plm(l, l) = cl(l) * plm(l - 1, l - 1);
|
|
||||||
dplm(l, l) = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} //end compute_barplm
|
|
||||||
|
|
||||||
|
|
||||||
void ACECartesianSphericalHarmonics::compute_ylm(DOUBLE_TYPE rx, DOUBLE_TYPE ry, DOUBLE_TYPE rz, LS_TYPE lmaxi) {
|
|
||||||
|
|
||||||
// requires rx^2 + ry^2 + rz^2 = 1 , NO CHECKING IS PERFORMED !!!!!!!!!
|
|
||||||
|
|
||||||
DOUBLE_TYPE real;
|
|
||||||
DOUBLE_TYPE img;
|
|
||||||
MS_TYPE m;
|
|
||||||
ACEComplex phase;
|
|
||||||
ACEComplex phasem, mphasem1;
|
|
||||||
ACEComplex dyx, dyy, dyz;
|
|
||||||
ACEComplex rdy;
|
|
||||||
|
|
||||||
phase.real = rx;
|
|
||||||
phase.img = ry;
|
|
||||||
//compute barplm
|
|
||||||
compute_barplm(rz, lmaxi);
|
|
||||||
|
|
||||||
//m = 0
|
|
||||||
m = 0;
|
|
||||||
for (LS_TYPE l = 0; l <= lmaxi; l++) {
|
|
||||||
|
|
||||||
ylm(l, m).real = plm(l, m);
|
|
||||||
ylm(l, m).img = 0.0;
|
|
||||||
|
|
||||||
dyz.real = dplm(l, m);
|
|
||||||
rdy.real = dyz.real * rz;
|
|
||||||
|
|
||||||
dylm(l, m).a[0].real = -rdy.real * rx;
|
|
||||||
dylm(l, m).a[0].img = 0.0;
|
|
||||||
dylm(l, m).a[1].real = -rdy.real * ry;
|
|
||||||
dylm(l, m).a[1].img = 0.0;
|
|
||||||
dylm(l, m).a[2].real = dyz.real - rdy.real * rz;
|
|
||||||
dylm(l, m).a[2].img = 0;
|
|
||||||
}
|
|
||||||
//m = 0
|
|
||||||
m = 1;
|
|
||||||
for (LS_TYPE l = 1; l <= lmaxi; l++) {
|
|
||||||
|
|
||||||
ylm(l, m) = phase * plm(l, m);
|
|
||||||
|
|
||||||
// std::cout << "Re ylm(" << l << "," << m <<")= " << ylm(l, m).real << std::endl;
|
|
||||||
// std::cout << "Im ylm(" << l << "," << m <<")= " << ylm(l, m).img << std::endl;
|
|
||||||
|
|
||||||
dyx.real = plm(l, m);
|
|
||||||
dyx.img = 0.0;
|
|
||||||
dyy.real = 0.0;
|
|
||||||
dyy.img = plm(l, m);
|
|
||||||
dyz.real = phase.real * dplm(l, m);
|
|
||||||
dyz.img = phase.img * dplm(l, m);
|
|
||||||
|
|
||||||
rdy.real = rx * dyx.real + +rz * dyz.real;
|
|
||||||
rdy.img = ry * dyy.img + rz * dyz.img;
|
|
||||||
|
|
||||||
dylm(l, m).a[0].real = dyx.real - rdy.real * rx;
|
|
||||||
dylm(l, m).a[0].img = -rdy.img * rx;
|
|
||||||
dylm(l, m).a[1].real = -rdy.real * ry;
|
|
||||||
dylm(l, m).a[1].img = dyy.img - rdy.img * ry;
|
|
||||||
dylm(l, m).a[2].real = dyz.real - rdy.real * rz;
|
|
||||||
dylm(l, m).a[2].img = dyz.img - rdy.img * rz;
|
|
||||||
}
|
|
||||||
|
|
||||||
// m > 1
|
|
||||||
phasem = phase;
|
|
||||||
for (MS_TYPE m = 2; m <= lmaxi; m++) {
|
|
||||||
|
|
||||||
mphasem1.real = phasem.real * DOUBLE_TYPE(m);
|
|
||||||
mphasem1.img = phasem.img * DOUBLE_TYPE(m);
|
|
||||||
phasem = phasem * phase;
|
|
||||||
|
|
||||||
for (LS_TYPE l = m; l <= lmaxi; l++) {
|
|
||||||
|
|
||||||
ylm(l, m).real = phasem.real * plm(l, m);
|
|
||||||
ylm(l, m).img = phasem.img * plm(l, m);
|
|
||||||
|
|
||||||
dyx = mphasem1 * plm(l, m);
|
|
||||||
dyy.real = -dyx.img;
|
|
||||||
dyy.img = dyx.real;
|
|
||||||
dyz = phasem * dplm(l, m);
|
|
||||||
|
|
||||||
rdy.real = rx * dyx.real + ry * dyy.real + rz * dyz.real;
|
|
||||||
rdy.img = rx * dyx.img + ry * dyy.img + rz * dyz.img;
|
|
||||||
|
|
||||||
dylm(l, m).a[0].real = dyx.real - rdy.real * rx;
|
|
||||||
dylm(l, m).a[0].img = dyx.img - rdy.img * rx;
|
|
||||||
dylm(l, m).a[1].real = dyy.real - rdy.real * ry;
|
|
||||||
dylm(l, m).a[1].img = dyy.img - rdy.img * ry;
|
|
||||||
dylm(l, m).a[2].real = dyz.real - rdy.real * rz;
|
|
||||||
dylm(l, m).a[2].img = dyz.img - rdy.img * rz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Ralf Drautz, Yury Lysogorskiy
|
|
||||||
|
|
||||||
#ifndef ACE_SPHERICAL_CART_H
|
|
||||||
#define ACE_SPHERICAL_CART_H
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "ace_arraynd.h"
|
|
||||||
#include "ace_array2dlm.h"
|
|
||||||
#include "ace_complex.h"
|
|
||||||
#include "ace_types.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
const DOUBLE_TYPE sq1o4pi = 0.28209479177387814347; // sqrt(1/(4*pi))
|
|
||||||
const DOUBLE_TYPE sq4pi = 3.54490770181103176384; // sqrt(4*pi)
|
|
||||||
const DOUBLE_TYPE sq3 = 1.73205080756887719318;//sqrt(3), numpy
|
|
||||||
const DOUBLE_TYPE sq3o2 = 1.22474487139158894067;//sqrt(3/2), numpy
|
|
||||||
|
|
||||||
//definition of common factor for spherical harmonics = Y00
|
|
||||||
//const DOUBLE_TYPE Y00 = sq1o4pi;
|
|
||||||
const DOUBLE_TYPE Y00 = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Class to store spherical harmonics and their associated functions. \n
|
|
||||||
All the associated members such as \f$ P_{lm}, Y_{lm}\f$ etc are one dimensional arrays of length (L+1)*(L+2)/2. \n
|
|
||||||
The value that corresponds to a particular l, m configuration can be accessed through a \code ylm(l,m) \endcode \n
|
|
||||||
*/
|
|
||||||
class ACECartesianSphericalHarmonics {
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
int, the number of spherical harmonics to be found
|
|
||||||
*/
|
|
||||||
LS_TYPE lmax;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor
|
|
||||||
*/
|
|
||||||
ACECartesianSphericalHarmonics() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parametrized constructor. Dynamically initialises all the arrays.
|
|
||||||
* @param lmax maximum orbital moment
|
|
||||||
*/
|
|
||||||
explicit ACECartesianSphericalHarmonics(LS_TYPE lmax);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize internal arrays and precompute necessary coefficients
|
|
||||||
* @param lm maximum orbital moment
|
|
||||||
*/
|
|
||||||
void init(LS_TYPE lm);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
~ACECartesianSphericalHarmonics();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Precompute necessaary helper arrays Precomputes the value of \f$ a_{lm}, b_{lm}, c_l, d_l \f$
|
|
||||||
*/
|
|
||||||
void pre_compute();
|
|
||||||
|
|
||||||
/**
|
|
||||||
Function that computes \f$ \bar{P}_{lm} \f$ for the corresponding lmax value
|
|
||||||
Input is \f$ \hat{r}_z \f$ which is the $z$-component of the bond direction.
|
|
||||||
|
|
||||||
For each \f$ \hat{r}_z \f$, this computes the whole range of \f$ \bar{P}_{lm} \f$ values
|
|
||||||
and its derivatives upto the lmax specified, which is a member of the class.
|
|
||||||
|
|
||||||
@param rz, DOUBLE_TYPE
|
|
||||||
|
|
||||||
@returns None
|
|
||||||
*/
|
|
||||||
void compute_barplm(DOUBLE_TYPE rz, LS_TYPE lmaxi);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Function that computes \f$ Y_{lm} \f$ for the corresponding lmax value
|
|
||||||
Input is the bond-directon vector \f$ \hat{r}_x, \hat{r}_y, \hat{r}_z \f$
|
|
||||||
|
|
||||||
Each \f$ Y_{lm} \f$ value is a ACEComplex object with real and imaginary parts. This function also
|
|
||||||
finds the derivatives, which are stored in the Dycomponent class, with each component being a
|
|
||||||
ACEComplex object.
|
|
||||||
|
|
||||||
@param rx, DOUBLE_TYPE
|
|
||||||
@param ry, DOUBLE_TYPE
|
|
||||||
@param rz, DOUBLE_TYPE
|
|
||||||
@param lmaxi, int
|
|
||||||
*/
|
|
||||||
void compute_ylm(DOUBLE_TYPE rx, DOUBLE_TYPE ry, DOUBLE_TYPE rz, LS_TYPE lmaxi);
|
|
||||||
|
|
||||||
Array2DLM<DOUBLE_TYPE> alm;
|
|
||||||
Array2DLM<DOUBLE_TYPE> blm;
|
|
||||||
Array1D<DOUBLE_TYPE> cl;
|
|
||||||
Array1D<DOUBLE_TYPE> dl;
|
|
||||||
|
|
||||||
Array2DLM<DOUBLE_TYPE> plm;
|
|
||||||
Array2DLM<DOUBLE_TYPE> dplm;
|
|
||||||
|
|
||||||
Array2DLM<ACEComplex> ylm; ///< Values of all spherical harmonics after \code compute_ylm(rx,ry,rz, lmaxi) \endcode call
|
|
||||||
Array2DLM<ACEDYcomponent> dylm;///< Values of gradients of all spherical harmonics after \code compute_ylm(rx,ry,rz, lmaxi) \endcode call
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,126 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 19.02.20.
|
|
||||||
|
|
||||||
#ifndef ACE_TIMING_H
|
|
||||||
#define ACE_TIMING_H
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
using namespace std::chrono;
|
|
||||||
using Clock = std::chrono::high_resolution_clock;
|
|
||||||
using TimePoint = std::chrono::time_point<Clock>;
|
|
||||||
using Duration = Clock::duration;
|
|
||||||
|
|
||||||
//////////////////////////////////////////
|
|
||||||
#ifdef FINE_TIMING
|
|
||||||
/**
|
|
||||||
* Helper class for timing the code.
|
|
||||||
* The timer should be initialized to reset measured time and
|
|
||||||
* then call "start" and "stop" before and after measured code.
|
|
||||||
* The measured time is stored in "duration" variable
|
|
||||||
*/
|
|
||||||
struct ACETimer {
|
|
||||||
Duration duration; ///< measured duration
|
|
||||||
TimePoint start_moment; ///< start moment of current measurement
|
|
||||||
|
|
||||||
ACETimer() { init(); };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset timer
|
|
||||||
*/
|
|
||||||
void init() { duration = std::chrono::nanoseconds(0); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start timer
|
|
||||||
*/
|
|
||||||
void start() { start_moment = Clock::now(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop timer, update measured "duration"
|
|
||||||
*/
|
|
||||||
void stop() { duration += Clock::now() - start_moment; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get duration in microseconds
|
|
||||||
*/
|
|
||||||
long as_microseconds() { return std::chrono::duration_cast<std::chrono::microseconds>(duration).count(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get duration in nanoseconds
|
|
||||||
*/
|
|
||||||
long as_nanoseconds() { return std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count(); }
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#else // EMPTY Definitions
|
|
||||||
/**
|
|
||||||
* Helper class for timing the code.
|
|
||||||
* The timer should be initialized to reset measured time and
|
|
||||||
* then call "start" and "stop" before and after measured code.
|
|
||||||
* The measured time is stored in "duration" variable
|
|
||||||
*/
|
|
||||||
struct ACETimer {
|
|
||||||
Duration duration; ///< measured duration
|
|
||||||
TimePoint start_moment; ///< start moment of current measurement
|
|
||||||
|
|
||||||
ACETimer() {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset timer
|
|
||||||
*/
|
|
||||||
void init() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start timer
|
|
||||||
*/
|
|
||||||
void start() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop timer, update measured "duration"
|
|
||||||
*/
|
|
||||||
void stop() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get duration in microseconds
|
|
||||||
*/
|
|
||||||
long as_microseconds() {return 0; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get duration in nanoseconds
|
|
||||||
*/
|
|
||||||
long as_nanoseconds() {return 0; }
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
//////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
#endif //ACE_TIMING_H
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Yury Lysogorskiy on 20.01.20.
|
|
||||||
|
|
||||||
#ifndef ACE_TYPES_H
|
|
||||||
#define ACE_TYPES_H
|
|
||||||
|
|
||||||
typedef char RANK_TYPE;
|
|
||||||
typedef int SPECIES_TYPE;
|
|
||||||
typedef short int NS_TYPE;
|
|
||||||
typedef short int LS_TYPE;
|
|
||||||
|
|
||||||
typedef short int DENSITY_TYPE;
|
|
||||||
|
|
||||||
typedef short int MS_TYPE;
|
|
||||||
|
|
||||||
typedef short int SHORT_INT_TYPE;
|
|
||||||
typedef double DOUBLE_TYPE;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Created by Lysogorskiy Yury on 07.04.2020.
|
|
||||||
|
|
||||||
#ifndef ACE_VERSION_H
|
|
||||||
#define ACE_VERSION_H
|
|
||||||
|
|
||||||
#define VERSION_YEAR 2021
|
|
||||||
#define VERSION_MONTH 2
|
|
||||||
#define VERSION_DAY 3
|
|
||||||
|
|
||||||
#endif //ACE_VERSION_Hls
|
|
||||||
|
|
|
@ -1,388 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Created by Christoph Ortner on 03.06.2020
|
|
||||||
|
|
||||||
#include "ships_radial.h"
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <cmath>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void SHIPsRadPolyBasis::_init(DOUBLE_TYPE r0, int p, DOUBLE_TYPE rcut,
|
|
||||||
DOUBLE_TYPE xl, DOUBLE_TYPE xr,
|
|
||||||
int pl, int pr, size_t maxn) {
|
|
||||||
this->p = p;
|
|
||||||
this->r0 = r0;
|
|
||||||
this->rcut = rcut;
|
|
||||||
this->xl = xl;
|
|
||||||
this->xr = xr;
|
|
||||||
this->pl = pl;
|
|
||||||
this->pr = pr;
|
|
||||||
this->maxn = maxn;
|
|
||||||
this->A.resize(maxn);
|
|
||||||
this->B.resize(maxn);
|
|
||||||
this->C.resize(maxn);
|
|
||||||
this->P.resize(maxn);
|
|
||||||
this->dP_dr.resize(maxn);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHIPsRadPolyBasis::fread(FILE *fptr)
|
|
||||||
{
|
|
||||||
int res; //for fscanf result
|
|
||||||
int maxn, p, pl, pr, ntests;
|
|
||||||
double r0, xl, xr, a, b, c, rcut;
|
|
||||||
|
|
||||||
// transform parameters
|
|
||||||
res = fscanf(fptr, "transform parameters: p=%d r0=%lf\n", &p, &r0);
|
|
||||||
if (res != 2)
|
|
||||||
throw invalid_argument("Couldn't read line: transform parameters: p=%d r0=%lf");
|
|
||||||
// cutoff parameters
|
|
||||||
res = fscanf(fptr, "cutoff parameters: rcut=%lf xl=%lf xr=%lf pl=%d pr=%d\n",
|
|
||||||
&rcut, &xl, &xr, &pl, &pr);
|
|
||||||
if (res != 5)
|
|
||||||
throw invalid_argument("Couldn't read cutoff parameters: rcut=%lf xl=%lf xr=%lf pl=%d pr=%d");
|
|
||||||
// basis size
|
|
||||||
res = fscanf(fptr, "recursion coefficients: maxn = %d\n", &maxn);
|
|
||||||
if (res != 1)
|
|
||||||
throw invalid_argument("Couldn't read recursion coefficients: maxn = %d");
|
|
||||||
// initialize and allocate
|
|
||||||
this->_init(r0, p, rcut, xl, xr, pl, pr, maxn);
|
|
||||||
|
|
||||||
// read basis coefficients
|
|
||||||
for (int i = 0; i < maxn; i++) {
|
|
||||||
res = fscanf(fptr, " %lf %lf %lf\n", &a, &b, &c);
|
|
||||||
if (res != 3)
|
|
||||||
throw invalid_argument("Couldn't read line: A_n B_n C_n");
|
|
||||||
this->A(i) = DOUBLE_TYPE(a);
|
|
||||||
this->B(i) = DOUBLE_TYPE(b);
|
|
||||||
this->C(i) = DOUBLE_TYPE(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// // check there are no consistency tests (I don't have time to fix this now)
|
|
||||||
// res = fscanf(fptr, "tests: ntests = %d\n", &ntests);
|
|
||||||
// if (res != 1)
|
|
||||||
// throw invalid_argument("Couldn't read line: tests: ntests = %d");
|
|
||||||
// if (ntests != 0)
|
|
||||||
// throw invalid_argument("must have ntests = 0!");
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// run the consistency test this could be moved into a separate function
|
|
||||||
double r, Pn, dPn;
|
|
||||||
double err = 0.0;
|
|
||||||
|
|
||||||
res = fscanf(fptr, "tests: ntests = %d\n", &ntests);
|
|
||||||
if (res != 1)
|
|
||||||
throw invalid_argument("Couldn't read line: tests: ntests = %d");
|
|
||||||
for (size_t itest = 0; itest < ntests; itest++) {
|
|
||||||
// read an r argument
|
|
||||||
res = fscanf(fptr, " r=%lf\n", &r);
|
|
||||||
// printf("r = %lf \n", r);
|
|
||||||
if (res != 1)
|
|
||||||
throw invalid_argument("Couldn't read line: r=%lf");
|
|
||||||
// printf("test %d, r=%f, maxn=%d \n", itest, r, maxn);
|
|
||||||
// evaluate the basis
|
|
||||||
this->calcP(r, maxn, SPECIES_TYPE(0), SPECIES_TYPE(0));
|
|
||||||
// compare against the stored values
|
|
||||||
for (size_t n = 0; n < maxn; n++) {
|
|
||||||
res = fscanf(fptr, " %lf %lf\n", &Pn, &dPn);
|
|
||||||
if (res != 2)
|
|
||||||
throw invalid_argument("Couldn't read test value line: %lf %lf");
|
|
||||||
err = max(err, abs(Pn - this->P(n)) + abs(dPn - this->dP_dr(n)));
|
|
||||||
// printf(" %d %e %e \n", int(n),
|
|
||||||
// abs(Pn - this->P(n)),
|
|
||||||
// abs(dPn - this->dP_dr(n)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ntests > 0)
|
|
||||||
printf("Maximum Test error = %e\n", err);
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
size_t SHIPsRadPolyBasis::get_maxn()
|
|
||||||
{
|
|
||||||
return this->maxn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Julia code: ((1+r0)/(1+r))^p
|
|
||||||
void SHIPsRadPolyBasis::transform(const DOUBLE_TYPE r, DOUBLE_TYPE &x_out, DOUBLE_TYPE &dx_out) const {
|
|
||||||
x_out = pow((1 + r0) / (1 + r), p); // ==pow( (1 + r) / (1 + r0), -p );
|
|
||||||
dx_out = -p * pow((1 + r) / (1 + r0), -p - 1) / (1 + r0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHIPsRadPolyBasis::fcut(const DOUBLE_TYPE x, DOUBLE_TYPE &f_out, DOUBLE_TYPE &df_out) const {
|
|
||||||
if ( ((x < xl) && (pl > 0)) || ((x > xr) && (pr > 0)) ) {
|
|
||||||
f_out = 0.0;
|
|
||||||
df_out = 0.0;
|
|
||||||
} else {
|
|
||||||
f_out = pow(x - xl, pl) * pow(x - xr, pr);
|
|
||||||
df_out = pl * pow(x - xl, pl - 1) * pow(x - xr, pr) + pow(x - xl, pl) * pr * pow(x - xr, pr - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
|
||||||
Julia Code
|
|
||||||
P[1] = J.A[1] * _fcut_(J.pl, J.tl, J.pr, J.tr, t)
|
|
||||||
if length(J) == 1; return P; end
|
|
||||||
P[2] = (J.A[2] * t + J.B[2]) * P[1]
|
|
||||||
@inbounds for n = 3:length(J)
|
|
||||||
P[n] = (J.A[n] * t + J.B[n]) * P[n-1] + J.C[n] * P[n-2]
|
|
||||||
end
|
|
||||||
return P
|
|
||||||
------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
void SHIPsRadPolyBasis::calcP(DOUBLE_TYPE r, size_t maxn,
|
|
||||||
SPECIES_TYPE z1, SPECIES_TYPE z2) {
|
|
||||||
if (maxn > this->maxn)
|
|
||||||
throw invalid_argument("Given maxn couldn't be larger than global maxn");
|
|
||||||
|
|
||||||
if (maxn > P.get_size())
|
|
||||||
throw invalid_argument("Given maxn couldn't be larger than global length of P");
|
|
||||||
|
|
||||||
DOUBLE_TYPE x, dx_dr; // dx -> dx/dr
|
|
||||||
transform(r, x, dx_dr);
|
|
||||||
// printf("r = %f, x = %f, fcut = %f \n", r, x, fcut(x));
|
|
||||||
DOUBLE_TYPE f, df_dx;
|
|
||||||
fcut(x, f, df_dx); // df -> df/dx
|
|
||||||
|
|
||||||
//fill with zeros
|
|
||||||
P.fill(0);
|
|
||||||
dP_dr.fill(0);
|
|
||||||
|
|
||||||
P(0) = A(0) * f;
|
|
||||||
dP_dr(0) = A(0) * df_dx * dx_dr; // dP/dr; chain rule: df_cut/dr = df_cut/dx * dx/dr
|
|
||||||
if (maxn > 0) {
|
|
||||||
P(1) = (A(1) * x + B(1)) * P(0);
|
|
||||||
dP_dr(1) = A(1) * dx_dr * P(0) + (A(1) * x + B(1)) * dP_dr(0);
|
|
||||||
}
|
|
||||||
for (size_t n = 2; n < maxn; n++) {
|
|
||||||
P(n) = (A(n) * x + B(n)) * P(n - 1) + C(n) * P(n - 2);
|
|
||||||
dP_dr(n) = A(n) * dx_dr * P(n - 1) + (A(n) * x + B(n)) * dP_dr(n - 1) + C(n) * dP_dr(n - 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ====================================================================
|
|
||||||
|
|
||||||
|
|
||||||
bool SHIPsRadialFunctions::has_pair() {
|
|
||||||
return this->haspair;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHIPsRadialFunctions::load(string fname) {
|
|
||||||
FILE * fptr = fopen(fname.data(), "r");
|
|
||||||
size_t res = fscanf(fptr, "radbasename=ACE.jl.Basic\n");
|
|
||||||
if (res != 0)
|
|
||||||
throw("SHIPsRadialFunctions::load : couldnt read radbasename=ACE.jl.Basic");
|
|
||||||
this->fread(fptr);
|
|
||||||
fclose(fptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHIPsRadialFunctions::fread(FILE *fptr){
|
|
||||||
int res;
|
|
||||||
size_t maxn;
|
|
||||||
char hasE0, haspair;
|
|
||||||
DOUBLE_TYPE c;
|
|
||||||
|
|
||||||
// check whether we have a pair potential
|
|
||||||
res = fscanf(fptr, "haspair: %c\n", &haspair);
|
|
||||||
if (res != 1)
|
|
||||||
throw("SHIPsRadialFunctions::load : couldn't read haspair");
|
|
||||||
|
|
||||||
// read the radial basis
|
|
||||||
this->radbasis.fread(fptr);
|
|
||||||
|
|
||||||
// read the pair potential
|
|
||||||
if (haspair == 't') {
|
|
||||||
this->haspair=true;
|
|
||||||
fscanf(fptr, "begin repulsive potential\n");
|
|
||||||
fscanf(fptr, "begin polypairpot\n");
|
|
||||||
// read the basis parameters
|
|
||||||
pairbasis.fread(fptr);
|
|
||||||
maxn = pairbasis.get_maxn();
|
|
||||||
// read the coefficients
|
|
||||||
fscanf(fptr, "coefficients\n");
|
|
||||||
paircoeffs.resize(maxn);
|
|
||||||
for (size_t n = 0; n < maxn; n++) {
|
|
||||||
fscanf(fptr, "%lf\n", &c);
|
|
||||||
paircoeffs(n) = c;
|
|
||||||
}
|
|
||||||
fscanf(fptr, "end polypairpot\n");
|
|
||||||
// read the spline parameters
|
|
||||||
fscanf(fptr, "spline parameters\n");
|
|
||||||
fscanf(fptr, " e_0 + B exp(-A*(r/ri-1)) * (ri/r)\n");
|
|
||||||
fscanf(fptr, "ri=%lf\n", &(this->ri));
|
|
||||||
fscanf(fptr, "e0=%lf\n", &(this->e0));
|
|
||||||
fscanf(fptr, "A=%lf\n", &(this->A));
|
|
||||||
fscanf(fptr, "B=%lf\n", &(this->B));
|
|
||||||
fscanf(fptr, "end repulsive potential\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t SHIPsRadialFunctions::get_maxn()
|
|
||||||
{
|
|
||||||
return this->radbasis.get_maxn();
|
|
||||||
}
|
|
||||||
|
|
||||||
DOUBLE_TYPE SHIPsRadialFunctions::get_rcut()
|
|
||||||
{
|
|
||||||
return max(radbasis.rcut, pairbasis.rcut);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHIPsRadialFunctions::fill_gk(DOUBLE_TYPE r, NS_TYPE maxn, SPECIES_TYPE z1, SPECIES_TYPE z2) {
|
|
||||||
radbasis.calcP(r, maxn, z1, z2);
|
|
||||||
for (NS_TYPE n = 0; n < maxn; n++) {
|
|
||||||
gr(n) = radbasis.P(n);
|
|
||||||
dgr(n) = radbasis.dP_dr(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHIPsRadialFunctions::fill_Rnl(DOUBLE_TYPE r, NS_TYPE maxn, SPECIES_TYPE z1, SPECIES_TYPE z2) {
|
|
||||||
radbasis.calcP(r, maxn, z1, z2);
|
|
||||||
for (NS_TYPE n = 0; n < maxn; n++) {
|
|
||||||
for (LS_TYPE l = 0; l <= lmax; l++) {
|
|
||||||
fr(n, l) = radbasis.P(n);
|
|
||||||
dfr(n, l) = radbasis.dP_dr(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHIPsRadialFunctions::setuplookupRadspline() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHIPsRadialFunctions::init(NS_TYPE nradb, LS_TYPE lmax, NS_TYPE nradial, DOUBLE_TYPE deltaSplineBins,
|
|
||||||
SPECIES_TYPE nelements,
|
|
||||||
DOUBLE_TYPE cutoff, string radbasename) {
|
|
||||||
//mimic ACERadialFunctions::init
|
|
||||||
this->nradbase = nradb;
|
|
||||||
this->lmax = lmax;
|
|
||||||
this->nradial = nradial;
|
|
||||||
this->deltaSplineBins = deltaSplineBins;
|
|
||||||
this->nelements = nelements;
|
|
||||||
this->cutoff = cutoff;
|
|
||||||
this->radbasename = radbasename;
|
|
||||||
|
|
||||||
gr.init(nradbase, "gr");
|
|
||||||
dgr.init(nradbase, "dgr");
|
|
||||||
|
|
||||||
|
|
||||||
fr.init(nradial, lmax + 1, "fr");
|
|
||||||
dfr.init(nradial, lmax + 1, "dfr");
|
|
||||||
|
|
||||||
splines_gk.init(nelements, nelements, "splines_gk");
|
|
||||||
splines_rnl.init(nelements, nelements, "splines_rnl");
|
|
||||||
splines_hc.init(nelements, nelements, "splines_hc");
|
|
||||||
|
|
||||||
lambda.init(nelements, nelements, "lambda");
|
|
||||||
lambda.fill(1.);
|
|
||||||
|
|
||||||
cut.init(nelements, nelements, "cut");
|
|
||||||
cut.fill(1.);
|
|
||||||
|
|
||||||
dcut.init(nelements, nelements, "dcut");
|
|
||||||
dcut.fill(1.);
|
|
||||||
|
|
||||||
crad.init(nelements, nelements, (lmax + 1), nradial, nradbase, "crad");
|
|
||||||
crad.fill(0.);
|
|
||||||
|
|
||||||
//hard-core repulsion
|
|
||||||
prehc.init(nelements, nelements, "prehc");
|
|
||||||
prehc.fill(0.);
|
|
||||||
|
|
||||||
lambdahc.init(nelements, nelements, "lambdahc");
|
|
||||||
lambdahc.fill(1.);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHIPsRadialFunctions::evaluate(DOUBLE_TYPE r, NS_TYPE nradbase_c, NS_TYPE nradial_c, SPECIES_TYPE mu_i,
|
|
||||||
SPECIES_TYPE mu_j, bool calc_second_derivatives) {
|
|
||||||
if (calc_second_derivatives)
|
|
||||||
throw invalid_argument("SHIPsRadialFunctions has not `calc_second_derivatives` option");
|
|
||||||
|
|
||||||
radbasis.calcP(r, nradbase_c, mu_i, mu_j);
|
|
||||||
for (NS_TYPE nr = 0; nr < nradbase_c; nr++) {
|
|
||||||
gr(nr) = radbasis.P(nr);
|
|
||||||
dgr(nr) = radbasis.dP_dr(nr);
|
|
||||||
}
|
|
||||||
for (NS_TYPE nr = 0; nr < nradial_c; nr++) {
|
|
||||||
for (LS_TYPE l = 0; l <= this->lmax; l++) {
|
|
||||||
fr(nr, l) = radbasis.P(nr);
|
|
||||||
dfr(nr, l) = radbasis.dP_dr(nr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->has_pair())
|
|
||||||
this->evaluate_pair(r, mu_i, mu_j);
|
|
||||||
else {
|
|
||||||
cr = 0;
|
|
||||||
dcr = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHIPsRadialFunctions::evaluate_pair(DOUBLE_TYPE r,
|
|
||||||
SPECIES_TYPE mu_i,
|
|
||||||
SPECIES_TYPE mu_j,
|
|
||||||
bool calc_second_derivatives) {
|
|
||||||
// spline_hc.calcSplines(r);
|
|
||||||
// cr = spline_hc.values(0);
|
|
||||||
// dcr = spline_hc.derivatives(0);
|
|
||||||
|
|
||||||
// the outer polynomial potential
|
|
||||||
if (r > ri) {
|
|
||||||
pairbasis.calcP(r, pairbasis.get_maxn(), mu_i, mu_j);
|
|
||||||
cr = 0;
|
|
||||||
dcr = 0;
|
|
||||||
for (size_t n = 0; n < pairbasis.get_maxn(); n++) {
|
|
||||||
cr += paircoeffs(n) * pairbasis.P(n);
|
|
||||||
dcr += paircoeffs(n) * pairbasis.dP_dr(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // the repulsive core part
|
|
||||||
cr = e0 + B * exp(-A * (r/ri - 1)) * (ri/r);
|
|
||||||
dcr = B * exp( - A * (r/ri-1) ) * ri * ( - A / ri / r - 1/(r*r) );
|
|
||||||
}
|
|
||||||
// fix double-counting
|
|
||||||
cr *= 0.5;
|
|
||||||
dcr *= 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
/*
|
|
||||||
* Performant implementation of atomic cluster expansion and interface to LAMMPS
|
|
||||||
*
|
|
||||||
* Copyright 2021 (c) Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
|
||||||
* Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
|
||||||
* Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
|
||||||
*
|
|
||||||
* ^1: Ruhr-University Bochum, Bochum, Germany
|
|
||||||
* ^2: University of Cambridge, Cambridge, United Kingdom
|
|
||||||
* ^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
|
||||||
* ^4: University of British Columbia, Vancouver, BC, Canada
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the LICENSE file.
|
|
||||||
* This FILENAME 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, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Created by Christoph Ortner on 03.06.2020
|
|
||||||
|
|
||||||
#ifndef SHIPs_RADIAL_FUNCTIONS_H
|
|
||||||
#define SHIPs_RADIAL_FUNCTIONS_H
|
|
||||||
|
|
||||||
#include "ace_arraynd.h"
|
|
||||||
#include "ace_types.h"
|
|
||||||
#include "ace_radial.h"
|
|
||||||
|
|
||||||
class SHIPsRadPolyBasis {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// transform parameters
|
|
||||||
int p = 0;
|
|
||||||
DOUBLE_TYPE r0 = 0.0;
|
|
||||||
|
|
||||||
// cutoff parameters
|
|
||||||
DOUBLE_TYPE rcut = 0.0;
|
|
||||||
DOUBLE_TYPE xl = 0.0;
|
|
||||||
DOUBLE_TYPE xr = 0.0;
|
|
||||||
int pl = 0;
|
|
||||||
int pr = 0;
|
|
||||||
|
|
||||||
// basis size
|
|
||||||
size_t maxn = 0;
|
|
||||||
|
|
||||||
// recursion parameters
|
|
||||||
Array1D<DOUBLE_TYPE> A = Array1D<DOUBLE_TYPE>("SHIPs radial basis: A");
|
|
||||||
Array1D<DOUBLE_TYPE> B = Array1D<DOUBLE_TYPE>("SHIPs radial basis: B");
|
|
||||||
Array1D<DOUBLE_TYPE> C = Array1D<DOUBLE_TYPE>("SHIPs radial basis: C");
|
|
||||||
|
|
||||||
// temporary storage for evaluating the basis
|
|
||||||
Array1D<DOUBLE_TYPE> P = Array1D<DOUBLE_TYPE>("SHIPs radial basis: P");
|
|
||||||
Array1D<DOUBLE_TYPE> dP_dr = Array1D<DOUBLE_TYPE>("SHIPs radial basis: dP");
|
|
||||||
|
|
||||||
//////////////////////////////////
|
|
||||||
|
|
||||||
SHIPsRadPolyBasis() = default;
|
|
||||||
|
|
||||||
~SHIPsRadPolyBasis() = default;
|
|
||||||
|
|
||||||
// distance transform
|
|
||||||
void transform(const DOUBLE_TYPE r, DOUBLE_TYPE &x_out, DOUBLE_TYPE &dx_out) const;
|
|
||||||
|
|
||||||
// cutoff function
|
|
||||||
void fcut(const DOUBLE_TYPE x, DOUBLE_TYPE &f_out, DOUBLE_TYPE &df_out) const;
|
|
||||||
|
|
||||||
void fread(FILE *fptr);
|
|
||||||
|
|
||||||
void _init(DOUBLE_TYPE r0, int p, DOUBLE_TYPE rcut,
|
|
||||||
DOUBLE_TYPE xl, DOUBLE_TYPE xr,
|
|
||||||
int pl, int pr, size_t maxn);
|
|
||||||
|
|
||||||
void calcP(DOUBLE_TYPE r, size_t maxn, SPECIES_TYPE z1, SPECIES_TYPE z2);
|
|
||||||
|
|
||||||
size_t get_maxn();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SHIPsRadialFunctions : public AbstractRadialBasis {
|
|
||||||
public:
|
|
||||||
|
|
||||||
// radial basis
|
|
||||||
SHIPsRadPolyBasis radbasis;
|
|
||||||
|
|
||||||
// pair potential basis
|
|
||||||
bool haspair = false;
|
|
||||||
SHIPsRadPolyBasis pairbasis;
|
|
||||||
|
|
||||||
// pair potential coefficients
|
|
||||||
Array1D<DOUBLE_TYPE> paircoeffs = Array1D<DOUBLE_TYPE>("SHIPs pairpot coeffs: paircoeffs");
|
|
||||||
|
|
||||||
// spline parameters for repulsive core
|
|
||||||
DOUBLE_TYPE ri = 0.0;
|
|
||||||
DOUBLE_TYPE e0 = 0.0;
|
|
||||||
DOUBLE_TYPE A = 0.0;
|
|
||||||
DOUBLE_TYPE B = 0.0;
|
|
||||||
|
|
||||||
//////////////////////////////////
|
|
||||||
|
|
||||||
SHIPsRadialFunctions() = default;
|
|
||||||
|
|
||||||
~SHIPsRadialFunctions() override = default;
|
|
||||||
|
|
||||||
|
|
||||||
void fread(FILE *fptr);
|
|
||||||
|
|
||||||
void load(string fname);
|
|
||||||
|
|
||||||
size_t get_maxn();
|
|
||||||
DOUBLE_TYPE get_rcut();
|
|
||||||
|
|
||||||
bool has_pair();
|
|
||||||
|
|
||||||
void init(NS_TYPE nradb, LS_TYPE lmax, NS_TYPE nradial, DOUBLE_TYPE deltaSplineBins, SPECIES_TYPE nelements,
|
|
||||||
DOUBLE_TYPE cutoff,
|
|
||||||
string radbasename) override;
|
|
||||||
|
|
||||||
void
|
|
||||||
evaluate(DOUBLE_TYPE r, NS_TYPE nradbase_c, NS_TYPE nradial_c, SPECIES_TYPE mu_i, SPECIES_TYPE mu_j,
|
|
||||||
bool calc_second_derivatives = false) override;
|
|
||||||
|
|
||||||
void
|
|
||||||
evaluate_pair(DOUBLE_TYPE r, SPECIES_TYPE mu_i, SPECIES_TYPE mu_j,
|
|
||||||
bool calc_second_derivatives = false);
|
|
||||||
|
|
||||||
void setuplookupRadspline() override;
|
|
||||||
|
|
||||||
SHIPsRadialFunctions *clone() const override {
|
|
||||||
return new SHIPsRadialFunctions(*this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method, that populate `fr` and `dfr` 2D-arrays (n,l) with P(n), dP_dr for given coordinate r
|
|
||||||
* @param r
|
|
||||||
* @param maxn
|
|
||||||
* @param z1
|
|
||||||
* @param z2
|
|
||||||
*/
|
|
||||||
void fill_Rnl(DOUBLE_TYPE r, NS_TYPE maxn, SPECIES_TYPE z1, SPECIES_TYPE z2);
|
|
||||||
|
|
||||||
void fill_gk(DOUBLE_TYPE r, NS_TYPE maxn, SPECIES_TYPE z1, SPECIES_TYPE z2);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,68 +1,64 @@
|
||||||
# Install.sh file that integrates the settings from the lib folder into the conventional build process (make build?)
|
# Install/unInstall package files in LAMMPS
|
||||||
|
# mode = 0/1/2 for uninstall/install/update
|
||||||
|
|
||||||
# COPIED FROM src/KIM/Install.sh:
|
mode=$1
|
||||||
|
|
||||||
# # Install/unInstall package files in LAMMPS
|
# enforce using portable C locale
|
||||||
# # mode = 0/1/2 for uninstall/install/update
|
LC_ALL=C
|
||||||
|
export LC_ALL
|
||||||
|
|
||||||
# mode=$1
|
# arg1 = file, arg2 = file it depends on
|
||||||
|
|
||||||
# # enforce using portable C locale
|
action () {
|
||||||
# LC_ALL=C
|
if (test $mode = 0) then
|
||||||
# export LC_ALL
|
rm -f ../$1
|
||||||
|
elif (! cmp -s $1 ../$1) then
|
||||||
|
if (test -z "$2" || test -e ../$2) then
|
||||||
|
cp $1 ..
|
||||||
|
if (test $mode = 2) then
|
||||||
|
echo " updating src/$1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
elif (test -n "$2") then
|
||||||
|
if (test ! -e ../$2) then
|
||||||
|
rm -f ../$1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# # arg1 = file, arg2 = file it depends on
|
# all package files with no dependencies
|
||||||
|
|
||||||
# action () {
|
for file in *.cpp *.h; do
|
||||||
# if (test $mode = 0) then
|
test -f ${file} && action $file
|
||||||
# rm -f ../$1
|
done
|
||||||
# elif (! cmp -s $1 ../$1) then
|
|
||||||
# if (test -z "$2" || test -e ../$2) then
|
|
||||||
# cp $1 ..
|
|
||||||
# if (test $mode = 2) then
|
|
||||||
# echo " updating src/$1"
|
|
||||||
# fi
|
|
||||||
# fi
|
|
||||||
# elif (test -n "$2") then
|
|
||||||
# if (test ! -e ../$2) then
|
|
||||||
# rm -f ../$1
|
|
||||||
# fi
|
|
||||||
# fi
|
|
||||||
# }
|
|
||||||
|
|
||||||
# # all package files with no dependencies
|
# edit 2 Makefile.package files to include/exclude package info
|
||||||
|
|
||||||
# for file in *.cpp *.h; do
|
if (test $1 = 1) then
|
||||||
# test -f ${file} && action $file
|
|
||||||
# done
|
|
||||||
|
|
||||||
# # edit 2 Makefile.package files to include/exclude package info
|
if (test -e ../Makefile.package) then
|
||||||
|
sed -i -e 's/[^ \t]*pace[^ \t]* //' ../Makefile.package
|
||||||
|
sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(pace_SYSINC) |' ../Makefile.package
|
||||||
|
sed -i -e 's|^PKG_SYSLIB =[ \t]*|&$(pace_SYSLIB) |' ../Makefile.package
|
||||||
|
sed -i -e 's|^PKG_SYSPATH =[ \t]*|&$(pace_SYSPATH) |' ../Makefile.package
|
||||||
|
fi
|
||||||
|
|
||||||
# if (test $1 = 1) then
|
if (test -e ../Makefile.package.settings) then
|
||||||
|
sed -i -e '/^include.*pace.*$/d' ../Makefile.package.settings
|
||||||
|
# multiline form needed for BSD sed on Macs
|
||||||
|
sed -i -e '4 i \
|
||||||
|
include ..\/..\/lib\/pace\/Makefile.lammps
|
||||||
|
' ../Makefile.package.settings
|
||||||
|
fi
|
||||||
|
|
||||||
# if (test -e ../Makefile.package) then
|
elif (test $1 = 0) then
|
||||||
# sed -i -e 's/[^ \t]*kim[^ \t]* //' ../Makefile.package
|
|
||||||
# sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(kim_SYSINC) |' ../Makefile.package
|
|
||||||
# sed -i -e 's|^PKG_SYSLIB =[ \t]*|&$(kim_SYSLIB) |' ../Makefile.package
|
|
||||||
# sed -i -e 's|^PKG_SYSPATH =[ \t]*|&$(kim_SYSPATH) |' ../Makefile.package
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# if (test -e ../Makefile.package.settings) then
|
if (test -e ../Makefile.package) then
|
||||||
# sed -i -e '/^include.*kim.*$/d' ../Makefile.package.settings
|
sed -i -e 's/[^ \t]*pace[^ \t]* //' ../Makefile.package
|
||||||
# # multiline form needed for BSD sed on Macs
|
fi
|
||||||
# sed -i -e '4 i \
|
|
||||||
# include ..\/..\/lib\/kim\/Makefile.lammps
|
|
||||||
# ' ../Makefile.package.settings
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# elif (test $1 = 0) then
|
if (test -e ../Makefile.package.settings) then
|
||||||
|
sed -i -e '/^include.*pace.*$/d' ../Makefile.package.settings
|
||||||
|
fi
|
||||||
|
|
||||||
# if (test -e ../Makefile.package) then
|
fi
|
||||||
# sed -i -e 's/[^ \t]*kim[^ \t]* //' ../Makefile.package
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# if (test -e ../Makefile.package.settings) then
|
|
||||||
# sed -i -e '/^include.*kim.*$/d' ../Makefile.package.settings
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# fi
|
|
||||||
|
|
Loading…
Reference in New Issue