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
|
||||
# # mode = 0/1/2 for uninstall/install/update
|
||||
# enforce using portable C locale
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
# mode=$1
|
||||
# arg1 = file, arg2 = file it depends on
|
||||
|
||||
# # enforce using portable C locale
|
||||
# LC_ALL=C
|
||||
# export LC_ALL
|
||||
action () {
|
||||
if (test $mode = 0) then
|
||||
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 () {
|
||||
# if (test $mode = 0) then
|
||||
# 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
|
||||
# }
|
||||
for file in *.cpp *.h; do
|
||||
test -f ${file} && action $file
|
||||
done
|
||||
|
||||
# # all package files with no dependencies
|
||||
# edit 2 Makefile.package files to include/exclude package info
|
||||
|
||||
# for file in *.cpp *.h; do
|
||||
# test -f ${file} && action $file
|
||||
# done
|
||||
if (test $1 = 1) then
|
||||
|
||||
# # 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
|
||||
# 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
|
||||
elif (test $1 = 0) then
|
||||
|
||||
# if (test -e ../Makefile.package.settings) then
|
||||
# sed -i -e '/^include.*kim.*$/d' ../Makefile.package.settings
|
||||
# # multiline form needed for BSD sed on Macs
|
||||
# sed -i -e '4 i \
|
||||
# include ..\/..\/lib\/kim\/Makefile.lammps
|
||||
# ' ../Makefile.package.settings
|
||||
# fi
|
||||
if (test -e ../Makefile.package) then
|
||||
sed -i -e 's/[^ \t]*pace[^ \t]* //' ../Makefile.package
|
||||
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
|
||||
# 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
|
||||
fi
|
||||
|
|
Loading…
Reference in New Issue